Oh, good tip. That makes it easy, then:
(
~alignPattern = { |pattern, cycle = 48|
Prout { |inval|
var clock = thisThread.clock,
phaseNow = ((clock.beats - clock.baseBarBeat) % cycle),
stream = pattern.asStream,
remaining = stream.fastForward(phaseNow, 0.001, inval);
// stream is now ready for the first event after 'phaseNow'
// but there is probably some time remaining; so, rest
inval = Event.silent(remaining).yield;
// return value (next inval) may be given back to the caller
stream.embedInStream(inval)
}
};
)
// test it
(
p = ~alignPattern.(
Pbind(
\dur, 1,
\a, Pn(Pseries(0, 1, 4), 1),
\beats, Pfunc { thisThread.beats },
\beatInBar, Pfunc { thisThread.clock.beatInBar }
).trace,
4
);
)
// you can do this many times
// and the relationship between \beats and \a
// will be consistent
q = p.play;
// e.g. one run
-> an EventStreamPlayer
( 'beats': 618.162651085, 'a': 0, 'dur': 1, 'beatInBar': 2.162651085 )
( 'beats': 618.162651085, 'a': 1, 'dur': 1, 'beatInBar': 2.162651085 )
( 'beats': 618.162651085, 'a': 2, 'dur': 1, 'beatInBar': 2.162651085 )
( 'beats': 619.0, 'a': 3, 'dur': 1, 'beatInBar': 3.0 )
// another
-> an EventStreamPlayer
( 'beats': 620.873896849, 'a': 0, 'dur': 1, 'beatInBar': 0.87389684900006 )
( 'beats': 621.0, 'a': 1, 'dur': 1, 'beatInBar': 1.0 )
( 'beats': 622.0, 'a': 2, 'dur': 1, 'beatInBar': 2.0 )
( 'beats': 623.0, 'a': 3, 'dur': 1, 'beatInBar': 3.0 )