# Using :sync with live\_loops

**URL:** <https://in-thread.sonic-pi.net/t/using-sync-with-live-loops/172>\
**Category:** \[P\] Patreon Support\
**Created:** [October 4, 2017, 1:34am UTC](https://in-thread.sonic-pi.net/t/using-sync-with-live-loops/172 "2017-10-04T01:34:02Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![samaaron](https://dub1.discourse-cdn.com/flex017/user_avatar/in-thread.sonic-pi.net/samaaron/32/7_2.png) [@samaaron](https://in-thread.sonic-pi.net/u/samaaron)\
**Post date:** [October 4, 2017, 9:45am UTC](https://in-thread.sonic-pi.net/t/using-sync-with-live-loops/172/2 "2017-10-04T09:45:41Z")

</div>

Hi @mrbombmusic, excellent question!

Sonic Pi is a multi-threaded system, just like a band. What does this mean? Well, just like a band has multiple members that are capable of doing things at the same time (one band member plays the guitar, another the drums, etc) threads are also capable of running at the same time. In Sonic Pi you can create threads in a variety of ways - `in_thread` being the basic way, `at` for scheduling a thread for the future and `live_loop` for creating a looping thread that you can live code.

In a real band, you often want to ensure each band member is playing to the same rhythm. This means that they’re all playing to the same tempo (at the same speed). However, this isn’t quite enough - you can totally imagine a band where the drummer is just slightly ahead of the guitarist - they’re both playing at the same speed, but the drums hit a bit too early _every_ time (we say that they drums are out of _phase_) . This can be fixed by ensuring that the drummer and the guitarist start at the same time. The band members need to have the same _tempo_ and _phase_.

Getting multiple threads playing to the same rhythm is essentially the same problem. Firstly you have to make sure they’re playing to the same tempo - this is actually the default in Sonic Pi - the BPM is set to 60 unless you change it (which incidentally you _can_ do on a per-thread basis for some really interesting a-rhythmic music). You also need to make sure that the `sleep` times are all similar (i.e. stick to whole numbers). However, getting them in phase is slightly more tricky. This isn’t a typical requirement of programming languages, so Sonic Pi has invented a few concepts to help out: `cue` and `sync`.

One way to imagine these two concepts is to think of a conductor and an orchestra. The violins may be waiting for their cue to start playing, and only when the conductor indicates to them do they start. In other words, the violins were `sync`ing on the conductor’s `cue`:

```ruby
in_thread, name: :violins do
  sync :start_violins
  # play violins
end

in_thread, name: :conductor do
   sleep 1
   cue :start_violins
   # continue conducting
end

```

In the example above we have two named threads: `:violins` and `:conductor`. The `:violins` thread immediately calls `sync` which means it blocks, waiting for a `:start_violins` cue message from another thread. If one doesn’t arrive, then the `:violins` thread blocks forever (until you hit the big app Stop button which kills all threads and resets the system). Luckily we do have another thread which is about to call `cue` with the right message (`:start_violins`) which does so after a second of waiting. After this second, the cue message is sent, the `:violins` thread is woken up, inherits the logical time of the cue thread (`:conductor`) and then continues. The two threads are now in sync and phase.

There are a few ways of working with `sync`. Firstly is to call it manually as above. If the `sync` is in the outer context (i.e. not within a `do/end` block) then it will block the main thread (each time you hit the Run button a main thread is created to run the code in the buffer). If the `sync` is within a thread then it will only block that thread. The third way is to use `live_loop`'s `sync:` opt. Let’s quickly explore when you’d use each one.

# Outer Context

```ruby
sync :foo
live_loop :bar do
  # do stuff
end 

live_loop :quux do
  # do other stuff
end

```

In this case, we block the main thread waiting for a `:foo` cue message. Once received we then redefine both `:bar` and `:quux` live loops (or start them if they’re not already running). This has the advantage of ensuring that both `:bar` and `:quux` are in phase with another thread. However, it has the disadvantage of slowing down when you can re-define the live loops. Essentially, you can only re-define the live loops as often as there are `:foo` cues. One solution to this is to delete the `sync` line after the live loops have started, but it’s often easy to forget to do this, and you can be left wondering why your live loops aren’t updating (which has happened to me many times)

# Inner Context

If you wish to have different live loops synced with different threads, and also for the requirement to sync one thread not affect the update rate of others (as happened above) then the solution is to place the sync _within_ the live loops:

```ruby
live_loop :bar do
  sync :foo
  sample :bd_haus
  sleep 0.5
end 

live_loop :quux do
  sync :foo2
  play :e1
  sleep 1
end

```

Now both live loops get updated immediately on run. However, their rates are now limited to the rate of the incoming `:cue` messages. If the `:foo` cue only comes in every 4 seconds, then the `:bar` live loops won’t loop around every 0.5s, instead it will be every 4s as it has to wait for incoming cue messages which are slowing it down.

So, how do we allow live loops to be instantly updated (i.e. not block the main thread), loop at the correct rate (i.e. not have to wait for external syncs) yet also start in phase? For this we need the `sync:` opt.

# Live Loop :sync

To solve this problem I created the `:sync` opt for live loop. Let’s look at it in action:

```ruby
live_loop :bar, sync: :foo do
  sample :bd_haus
  sleep 0.5
end 

live_loop :quux, sync: :foo2 do
  play :e1
  sleep 1
end

```

Now, there’s no `sync` in the main thread blocking things, there’s no `sync` inside the live loops slowing them down. Instead it’s sneakily placed itself inside the opts of `live_loop`. In this position, the sync will only block the live loop from starting. If the live loop isn’t already running, then the first thing it will do is wait for a corresponding cue message. Once one has arrived, the live\_loop starts running and never again waits for another cue message. This allows you to sync up the thread on start, but not have to worry about things blocking or slowing down again.

Hope that this helps 🙂

---

_[View the full topic](https://in-thread.sonic-pi.net/t/using-sync-with-live-loops/172)._
