hey, thanks for your further ideas at least for the initial L-System which is created by ~getDur
inside ~getAbs
you already creating streams. is this kind of redundant then, when combined with ~resetL
?
(
~rewriteWord = {|word, rules, iter=6|
iter.do{
word = Array.newFrom(word)
.collect{|c| rules[c.asSymbol]}
.join;
};
word
};
~getDur = {|word, durDict|
// streams are created inside this function
// so every time we call ~getDur, streams are resetted
var streams = durDict.collect{|seq| Pseq(seq,inf).asStream};
Array.newFrom(word).collect{|c| streams[c.asSymbol].next }
};
// function for cropping L-System
~sumUpTo = {|array, total|
var sum = 0, i = 0, result = Array.new;
while { i < array.size and: { sum < total } } {
sum = sum + array[i];
if(sum > total) {
result = result.add(array[i] - (sum - total));
} {
result = result.add(array[i]);
};
i = i + 1;
};
result
};
// creating abstractions with lesser density: reduce the density by joining two values
~low_dens = {|array|
var ioi, min_index, neighbor_index, result = [];
ioi = array.copy();
while {ioi.size() > 1} {
// in every step, we will reduce ioi until it has size 1
var intermediate_result = [];
min_index = ioi.minIndex;
// if first element is minimum element, the neighor can only be to the right
if (min_index == 0) {
neighbor_index = 1;
} {
// else if last element is minimum element, the neighbor can only be to the left
if (min_index == (ioi.size - 1)) {
neighbor_index = (ioi.size - 2);
} {
// else we're in the middle, so use the neighbor which is smallest (arbitrary choice)
var dir = 1;
if (ioi[min_index - 1] < ioi[min_index + 1]) {
dir = -1;
};
neighbor_index = min_index + dir;
};
};
// swap neighbor and min_index so that neighbor is always bigger than min_index
// - this makes copying easier in the next step
if (neighbor_index < min_index) {
var tmp = min_index;
min_index = neighbor_index;
neighbor_index = tmp;
};
// make a new list consisting of everything before min_index, sum of min el and its neighbor, everything after neighbor
intermediate_result = ioi.copyRange(0, min_index-1) ++ (ioi[min_index] + ioi[neighbor_index]) ++ ioi.copyRange(neighbor_index+1, (ioi.size-1));
if (intermediate_result.size >= ioi.size) {
"ERROR!".postln;
};
// add it to the list of results
result = result.add(intermediate_result);
// and update our starting point with the reduced list
ioi = intermediate_result.copy();
};
// return the complete list of reductions
result;
};
// creating abstractions with higher density by replacing a value with:
// a smaller potential IOI value and the difference between it and the value being replaced
~high_dens = {|array|
var ioi, ioi_sort, pot_ioi, index_max, result = [];
ioi = array.copy();
ioi_sort = ioi.as(Set).as(Array).sort;
pot_ioi = ioi_sort.minItem;
while { ioi.maxItem > pot_ioi } {
var intermediate_result = [];
index_max = ioi.findAll([ioi.maxItem]).choose;
intermediate_result = intermediate_result.add(ioi);
intermediate_result = intermediate_result.insert(index_max+1, [ioi[index_max] - pot_ioi, pot_ioi]).flat;
intermediate_result.removeAt(index_max);
// add it to the list of results
result = result.add(intermediate_result);
// and update our starting point with the reduced list
ioi = intermediate_result.copy();
};
result;
};
~getAbs = {|rules, durations|
var axiom, lsys, low_abs, high_abs, abstractions = [];
// axiom
axiom = "A";
// rewrite iteration
axiom = ~rewriteWord.(axiom, rules, 6);
// get durations
lsys = ~getDur.(axiom, durations);
//crop initial L-System to a specific length
lsys = ~sumUpTo.(lsys, 4);
lsys.debug("L-System");
//add abstractions with lower density to the array of abstractions
low_abs = ~low_dens.(lsys);
low_abs.do({
arg el, elindex;
abstractions = abstractions.add(el);
});
//add the initial L-System to the array of abstractions
abstractions = abstractions.add(lsys);
//add abstractions with higher density to the array of abstractions
high_abs = ~high_dens.(lsys);
high_abs.do({
arg el, elindex;
abstractions = abstractions.add(el);
});
//order array of abstractions by size: low -> high
abstractions = abstractions.sort({|a, b| a.size < b.size});
abstractions.indexOf(lsys).debug("L-System index");
abstractions.debug("abstractions");
};
// define rules
~rules = (A:"AB", B:"A");
// define durations for each symbol
~durations = (A: [0.25, 0.5], B: [0.5, 0.125]);
~absArray = ~getAbs.(~rules, ~durations);
)
in the end im trying to use the L-System abstractions as a Pulse inside PSPdiv and not sure right now if Data Sharing with Pbindef(\measure)
from @PitchTrebler or your appraoch works best here. but this is already working correctly i think:
(
Pdef(\kick,
Pbind(
[...]
)
);
Pdef(\sd,
Pbind(
[...]
)
);
Pdef(\hh,
Pbind(
[...]
)
);
)
(
~index = Pn(Pseq([3,5,7], inf)).asStream.trace(prefix: "measure index: ");
~pulse = Pdict(~patDict, Pfin(1, PL(\index))).trace;
~div_kick = 4;
~div_sd = 3;
~div_hh = 5;
~divBase_kick = 1;
~divBase_sd = 2;
~divBase_hh = 1;
~divType = \seq;
Pdef(\rhythms,
PSPdiv(
PL(\pulse),
[Pdef(\kick), Pdef(\sd), Pdef(\hh)],
[PL(\div_kick), PL(\div_sd), PL(\div_hh)],
[PL(\divBase_sd), PL(\divBase_sd), PL(\divBase_hh)],
PL(\divType),
),
).play(t, quant:1);
)
// update ~absArray on the fly:
(
~rules = (A:"AB", B:"AC", C:"BA");
~durations = (A: [0.25, 0.5], B: [0.5, 0.125], C: [0.333, 0.167]);
~absArray = ~getAbs.(~rules, ~durations);
~resetL.(~absArray);
)