i got rid of PSPdiv and was trying something like this with PtimeClutch and the L-System from the other thread. Dictionary inside Pattern - #20 by jamshark70
maybe better to post it there…
(
~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, 10);
// 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);
~absDict = ();
~patDict = ();
~putL = { |key, array|
~absDict.put(key, array);
~patDict.put(key, Pseq(array, 1));
};
// or, wipe out the whole system and start again with 'arrays'
~resetL = { |arrays|
~absDict.clear;
~patDict.clear;
arrays.do { |array, i|
~putL.(i, array);
};
};
~resetL.(~absArray);
)
// test SynthDef
(
SynthDef(\testMono, {
var trig = \trig.tr(1);
var gainEnv = EnvGen.ar(Env.perc(0.01,0.4), trig);
var sig = SinOscFB.ar(\freq.kr(150), 0.6);
sig = sig * gainEnv * \amp.kr(0.25);
Out.ar(\out.kr(0), sig);
}).add;
)
// Pattern Setup
(
~index = Pn(Pseq([0,1], inf)).asStream.trace(prefix: "measure index: ");
Pdef(\durs, Pn(Pbind(
\dur, Pdict(~patDict, Pfin(1, PL(\index))).timeClutch
), inf));
// bass
~numberOfHits_bass = 4;
~div_bass = 12;
// sine
~numberOfHits_sine = 3;
~div_sine = 6;
Pdef(\bassData,
Pbind(
\midinote, 60,
\dur, Pkey(\dur) / ~div_bass * Pbjorklund2(~numberOfHits_bass, ~div_bass),
);
);
Pdef(\sineData,
Pbind(
\midinote, 71,
\dur, Pkey(\dur) / ~div_sine * Pbjorklund2(~numberOfHits_sine, ~div_sine),
);
);
Pdef(\bassMono,
Ppar({|i|
var pat = Pmono(\testMono,
\out, i,
);
if(i == 0, {pat.trace(\dur, prefix: "\tbass dur: ")}, {pat});
} !2) <> Pdef(\bassData)
);
Pdef(\sineMono,
Ppar({|i|
var pat = Pmono(\testMono,
\out, i,
);
if(i == 0, {pat.trace(\dur, prefix: "\t\tsine dur: ")}, {pat});
pat; // comment out this line to trace sine durs
} !2) <> Pdef(\sineData)
);
)
// play Pattern
Pdef(\player, Ppar([Pdef(\bassMono), Pdef(\sineMono)], inf) <> Pdef(\durs)).play(quant:1);
Pdef(\player).stop;
// change index
~index = Pn(Pseq([2], inf)).asStream.trace(prefix: "measure index: ");
// 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);
)
unfortunately the system is running asynchronous after a while and when updating the ~index
there is some discontinuity between the phrase durations from the L-System and the durations from the Pbjorklund2s immediately.
i think the sum of the hits from the Pbjorklund2 should equal the size of the first item in the ~patDict
. to have them synchronized. for example with [ 2.125, 1.875 ] at index 1 of the ~patDict
.
(
var durs = [ 2.125, 1.875 ];
var numberOfHits_bass = 4;
var div_bass = 12;
x = durs[0] / div_bass * Pbjorklund2(numberOfHits_bass, div_bass).asStream;
y = x.nextN(numberOfHits_bass);
)
[ 0.53125, 0.53125, 0.53125, 0.53125 ].sum;
-> 2.125 // equals first item in the ~patDict
1.) is there a way to have the setup 100% synced for n chained Patterns with their own sequences on a note level to the master L-System pulse which only advances on phrase durations. I think its even more difficult when ~numberOfHits_instrument
is a Pattern.
2.) and when updating the ~index
manually at a random time or updating the ~absArray
it will wait until every duration from the chained patterns at the former index from the ~patDict
has been passed.
thanks