Skip to content

Instantly share code, notes, and snippets.

@chadochan
Created January 29, 2019 10:54
Show Gist options
  • Save chadochan/b42fb823ebb866b4126a0c604ea55121 to your computer and use it in GitHub Desktop.
Save chadochan/b42fb823ebb866b4126a0c604ea55121 to your computer and use it in GitHub Desktop.
EdgeList class takes two rhythm arrays (each comprised of 0 and 1 values) and makes a composite array.
/*
EdgeList takes two rhythm arrays and makes a composite array, returning a 3D array with the unit duration, the composite array,
and the IOI times between events in the composite (in seconds). Can be used as an edge list for a graph.
The array arguments should be comprised of 0 and 1 values, and must each contain at least one value.
*/
EdgeList {
var array1, array2, object;
*new { |array1, array2, object = 1| // possible to pass in any object, but just use 1 if you want a normal rhythmic array..
var composite_array, composite_size, ioiarray_ints, ioiarray_times, lastelement;
var unit_duration;
var divisor;
if(array1.size < 1 or: { array2.size < 1 },
{ "Both arrays must hold at least one value".warn;
^this;
}
);
/*
calculate the correct size for the composite_array:
as the given arrays may have multiple periods, i.e., 3 'bars' of 5, as in Nbit(5, 3),
use gcd to find the number of common periods. Thus, the base unit duration returned below will
be the base unit for 0/1 to 1/1, regardless of the number of periods in the constituent Nbit arrays..
*/
divisor = gcd(array1.size, array2.size);
composite_size = (array1.size*array2.size)/divisor;
// create new list of the required size to hold the composite; fill it with zeros:
composite_array = List.fill(composite_size, {0});
// add the elements from the given arrays to their correct positions in the new composite array:
array1.do { |item, i|
if (item == 1) { composite_array[i*((array2.size)/divisor)] = object };
};
array2.do { |item, i|
if (item == 1) { composite_array[i*((array1.size)/divisor)] = object };
};
/*
calculate the base unit duration for the graph, again using the divisor
to take into account multiple beat lengths in the given Nbit arrays
(Nbits must have the same number of beats for this to be accurate)
*/
unit_duration = (1 / (composite_array.size/divisor)).round(0.000001);
postln("*****************");
postln("Minimum base unit duration for this graph is: " ++ unit_duration);
/*
find the addresses containing 1, then find the 'wraparound' interval
between the last value and the first
*/
ioiarray_ints = composite_array.indicesOfEqual(object);
lastelement = (ioiarray_ints.first - ioiarray_ints.last)%(composite_array.size);
// calcuate differences between values in adjacent addresses, i.e., the distances between '1' slots
ioiarray_ints = ioiarray_ints.differentiate;
/*
add the 'wraparound' interval to the end of ioiarray and replace the first element with the offset
(if 0, then the first address is a '1')
*/
ioiarray_ints.remove(ioiarray_ints[0]);
ioiarray_ints.add(lastelement);
postln("Node IOI integers: " ++ ioiarray_ints);
// scale integer IOIs by the unit_duration, print result
ioiarray_times = ioiarray_ints.collect({ |item, i| (item * unit_duration).round(0.000001) });
postln("Node IOIs: " ++ ioiarray_times);
/*
add a tailing 0 to serve as a final 'ghost node' with
a duration of 0, allowing antipenultimate nodes or earlier to connect through to the end of the graph period
*/
ioiarray_times.add(0);
^[unit_duration, ioiarray_times, composite_array]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment