Hi there. I’m trying to merge two Event Pattern streams, using the “structure” from one (e.g. four events with duration of 0.5) and merging the values from another Event Pattern stream (e.g. two events with duration 1, repeated as needed). (the idea of this time-based merging is similar to the way TidalCycles works with different time patterns, where one of them defines the time “structure”, but the others provide their values for the corresponding times that would match (e.g. if they were running in parallel).
Maybe there’s a built-in class or a Quark to help with this (please redirect me, if so!), but I’ve managed to mock up something hacky that seems to work, as a test. It returns the expected values when I call next
on it repeatedly (and also prints what I’d expect to see as the yielded values). But if I call nextN
or all
the events shown are wrong…I must be missing something fundamental with Routines and streams here…
Here’s my exploratory code that “kind of” works:
(
var pStructure = Pbind(\degree, Pseq([1, 2, 3, 4], 1), \dur, 0.5).asStream;
var pOther = Pbind(\instrument, Pseq([\a, \b], inf), \dur, 1).asStream;
r = Routine{ |ev|
var next;
var curTime = 0;
var otherNextTime = 0;
var otherEvent = pOther.next(ev);
// "otherEvent: %".format(otherEvent).postln;
otherNextTime = otherEvent.delta.value;
while {
next = pStructure.next(ev);
// "next: %".format(next).postln;
next.notNil;
} {
// "curTime: % otherNextTime: %".format(curTime, otherNextTime).postln;
while {
otherNextTime <= curTime;
} {
otherEvent = pOther.next(ev);
// "otherEvent: %".format(otherEvent).postln;
otherNextTime = otherNextTime + otherEvent.delta.value;
// "otherNextTime updated: %".format(otherNextTime).postln;
};
otherEvent.putAll(next).postln.yield;
curTime = curTime + next.delta.value;
// "curTime: %".format(curTime).postln;
}
};
r.nextN(10, ());
)
Prints:
( 'instrument': a, 'degree': 1, 'dur': 0.5 )
( 'instrument': a, 'degree': 2, 'dur': 0.5 )
( 'instrument': b, 'degree': 3, 'dur': 0.5 )
( 'instrument': b, 'degree': 4, 'dur': 0.5 )
-> [ ( 'instrument': a, 'degree': 2, 'dur': 0.5 ), ( 'instrument': a, 'degree': 2, 'dur': 0.5 ), ( 'instrument': b, 'degree': 4, 'dur': 0.5 ), ( 'instrument': b, 'degree': 4, 'dur': 0.5 ), nil, nil, nil, nil, nil, nil ]
The printed events from inside the Routine (or if you make four separate calls to next
) look correct (degree 1,2,3,4 and instrument a,a,b,b, with duration 0.5), but the array of events returned from nextN
(or all
) has degree 2,2,4,4 (albeit with correct instrument and duration).
Also, there’s likely a better way to do this…any suggestions are welcome. It’s almost like Pchain
-ing two Event patterns, except the way values are handled is different…it needs to be time-aware instead of just taking the next Event from each stream in sequence.
Thanks,
Glen.