hey,
im using this function for creating fractals from an initial rhythm pattern:
(
var 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;
};
var 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;
//pot_ioi = 1;
while { ioi.maxItem > pot_ioi } {
var intermediate_result = [];
index_max = ioi.findAll([ioi.maxItem]).choose;
intermediate_result = 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();
};
// return the complete list of increasements
result;
};
var getAbstractions = { |durations|
var low_abs, high_abs, abstractions = [];
durations.debug("rhythm");
//add abstractions with lower density to the array of abstractions
low_abs = low_dens.(durations);
low_abs.do{|el, elindex|
abstractions = abstractions.add(el);
};
//add the initial rhythm pattern to the array of abstractions
abstractions = abstractions.add(durations);
//add abstractions with higher density to the array of abstractions
high_abs = high_dens.(durations);
high_abs.do{|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(durations).debug("rhythm index");
abstractions.debug("abstractions");
};
var convertToBinary = { |arrays|
arrays.collect { |row|
var max;
row = row.integrate;
max = row.maxItem;
Array.fill(max, 0).putEach(row % max, 1)
};
};
~getAbs = { |durations|
var arrays = getAbstractions.(durations);
var binary = convertToBinary.(arrays);
var patterns = arrays.collect { |array|
Pseq(array, 1);
};
(arrays: arrays, binary: binary, patterns: patterns);
};
)
There is one issue i would like to fix and it has something to do with the high_dens
function:
when you pass in an array which includes 1 as the smallest integer value it works nicely:
~getAbs.([3, 1, 2, 2])[\arrays];
but when you pass in an array which does not include 1 as the smallest value you dont get the full set of abstractions:
~getAbs.([3, 3, 2])[\arrays];
is it enough to just exchange pot_ioi = ioi_sort.minItem;
with pot_ioi = 1;
in the high_dens
function? and do you have any other suggestions in terms of coding style for this function? thanks.