I will sacrifice some heads of and attempt to summon the Oracle of Concurrency as so many others have done before me
In more seriousness, I’ll throw out a strawman to open discussion.
What’s the Problem?
A user trying to setup one or more loops synchronized to another ‘master’ loop may have difficulty achieving the desired results, particularly if the loops all have a similar duration. As the example here (and other anecdotal user testing) illustrates, the scheduling algorithm can lead to threads missing cues that they would have been ready to handle, depending on where the thread ends up in the scheduling roster.
In my opinion, users should be able to specify a loop to sync to, with a guarantee that the loop will start at each master loop’s cue.
What Does It Look Like?
One option could be adding a method option to live_loop
called (for example) master_loop
:
live_loop :bars do
4.times do
sleep 1
end
end
live_loop :four_on_floor, master_loop: :bars do
4.times do
sample: drum_hard_bass
sleep 1
end
end
The concept should be simple enough, I hope - loops tied to the “master” loop will be scheduled to start at the same time, with each new run dependent on the “master” loop. This would be analogous to hardware multi-track loopers where one track is recorded and the other tracks are automatically quantized and synchronized. There might be some other considerations for doing this in Sonic Pi. For example, the hardware loopers in sync mode will limit the length of all tracks to the length of the first loop. I guess in Sonic Pi the loop length could be more ambiguous like if a loop kicked off a long-running pad then you could have overlapping loops if the audio is still going from the previous run when the next run kicks off.
Finally, I understand that “master/slave” terminology isn’t always the best choice for various reasons, so perhaps another convention like “group” or “parent” or “timer_loop” would be more suitable in place.