Thoughts on sync patterns

Most live loops I see in other people’s code are like…

live_loop :foo, sync: :bar do
  #play and sleep here
end

while early on I adopted this one as my goto. The point being that I don’t have to get the amount of sleeping right in the play-and-sleep bit, which is handy for live coding when I can’t add up. Never played enough darts.

live_loop :foo do
  sync :bar
  in_thread do
    #play and sleep here
  end
end

Are there any other useful pattern you folks have always appearing in your code?

AKA just this week I’ve seen lots of useful ideas that have really advanced my thinking, and I’m after more :grinning_face_with_smiling_eyes:

Not quite sure what you mean when you say you “don’t have to get the amount of sleeping right in the play-and-sleep bit”. Can you elaborate?

Sure, in the first one I’d want to get the length of the loop to be e.g. one bar, or 4 bars or whatever. It’s set running on the first cue and then runs in tempo. If I edit it and get the length wrong - you know, lots of individual sleeps that should add up to say 4 beats, but make it 5, then it’ll get out of sync with other loops.

With the 2nd one, the live loop is triggered on each cue, whatever happens in the in_thread bit. So if ends up 5 beats long then I might get a bit of duplication, but at least it starts right each time.

Does that make sense?

EDIT btw I’m not promoting this as something people should adopot, just my foible :smiley:

1 Like

Yeah it does, thanks :slightly_smiling_face:

The pattern in your code snippet in the first post certainly allows the code to re-sync every time around the loop. This is useful - For specific use cases :slight_smile: - For example - if you always want the second loop to wait for the first one before cycling around, it’s great. Where it might not be as useful is where having the second loop wait for the first one every time around would introduce an undesirable pause :slight_smile:

2 Likes

Yes, agreed. I mean, horses for course definitely.

I do use both I just find the 2nd one handy. And I also use it for some nice effects, like letting an arpeggio over-run the bar a little to get an overlay/echo effect.

1 Like

(Btw, when using the ‘sync-first-time’ approach with live_loop :blah, sync: :foo … - if you type code that causes it to become un-synchronised, one solution is to enter sync :foo on a line just inside the live_loop, run it, comment it out when it has re-synced, and run again. (This can be a little tricky to time right, depending on the time span of the loop, but it can work)).

1 Like

Yes I get you.

I’ve used sync :bogusname to halt a runaway loop, but yours is better as it keeps the sound going

Hey @soxsa,

it’s cool that you’ve found and have highlighted these two different approaches to syncing - thanks for this.

I should just add that both styles (sync: as an opt to live_loop and sync as a separate function call within a live_loop) are both different and useful in their own right - although their behaviour does cross over quite a bit which is why it’s possible people might think they do the same thing.

As @ethancrawford points out, calling sync as a separate function will always cause the thread to block on an incoming event. However, calling sync: as an opt to live_loop will just cause the live_loop's thread to block once - before it starts looping the actual content of the live loop.

So to say it a different way, in case some reading this found the paragraph above a bit too full of annoying technical words, consider the following:

live_loop :foo do
  sync :flibble
  # do something
end

This will cause the :foo live loop to spin round every time a :flibble event is triggered (which is likely to be from a live_loop called :flibble spinning round).

However, the following code will cause the :foo live loop to spin round no faster than incoming :flibble events but possibly slower depending on whether :flibble events come in faster than every 8 seconds

live_loop :foo do
  sync :flibble
  # do something
  sleep 8
end

Whereas the following will only wait for one :flibble event and then just let the loop spin around as it likes without bothering it again:

live_loop :foo, sync: :flibble do
  # do something
  sleep 8
end

Note that only the first example doesn’t need a call to sleep as the sync actually can be considered a special kind of sleep - one that doesn’t yet know how long to sleep for :slight_smile:

1 Like

I don’t know about other people you see learning SPi @samaaron, but for me understanding these two modes was something of an epiphany and unlocked a whole load of possibilites. As I say I see your second pattern a lot more live_loop :foo, sync: :flibble do so I’m hoping you’ll keep the first pattern.