Live loops Sync questions :-)

It is, but it works.

You can also use

4.times do
sync :clock
end

I think it is worth reading Sam Aaron’s comments in a previous thread
My solution would be to delay the start of the :metronome loop to give the other loops a chance to start and to be waiting for their initial sync, which ONLY applies the first time round (set in the define line of the live loop). Subsequently none of the loops need a sync, apart from the one with the 7 beat pattern. This needs to be delayed on each pass to the start of the next bar.
So applying this to your original code I get this. (Note ALL loops which are an exact number of bars can be synced directly to metronome. You done really need the loops for 8 beats, but you do ned the loop for 1_bar so that you can restart the 7 beat loop correctly.

Your code modified is below

use_bpm 120
beats_per_bar = 4

############################### TOOLS ###############################
live_loop :metronome,delay: 0.01 do #delay start of this by 0.01 to allow other loops to be ready
  use_synth :beep
  play :a4, release: 0.5
  sleep 1
end

live_loop :_1_bar,sync: :metronome do
  use_synth :beep
  play :as5, release: 0.5
  sleep beats_per_bar
  # the cue is sent ONLY NOW /:( so sad no ? NOT ANY MORE!!!
end

live_loop :_4_bars,sync: :metronome do #not required here
  sleep beats_per_bar*4
end

live_loop :_8_bars,sync: :metronome do #you don't really need this loop here
  sleep beats_per_bar*8
end

live_loop :_16_bars,sync: :metronome do #not used here
  sleep beats_per_bar*16
end

############################### live_l_o(U)pssssssssss ###############################

# this loop will start once _4_bars has finished once and become free as as bird no synchronicity
live_loop :loop_sans_sync, sync: :metronome do #:_4_bars
  sample :drum_cymbal_hard
  sleep 4
end

live_loop :loop_8_beats,sync: :metronome do # sync to :metronome not :_1_bar
  # après la durée de la boucle _1_bar 4 beats
  #sync :_1_bar
  use_synth :sine
  riff_8_notes = (ring :c3, :d3, :e3, :f3, :g3, :a3, :b3, :c4)
  # this pattern last 8 beats
  play_pattern_timed riff_8_notes, 1
  # oh it's strange i "miss" the cue "/live_loop/_1_bar" why have i wait the next one ?????
  #
end

live_loop :loop_7_beats do
  #  _1_bar last 4 beats
  sync :_1_bar #this loop needs to wait EVERY time for the start of the bar
  use_synth :pretty_bell
  riff_7_notes = (ring :c6, :d6, :e6, :f6, :g6, :a6, :b6)
  # this pattern last 7 beats
  play_pattern_timed riff_7_notes, 1
end

To summarise.
You need to delay the start of the main metronome to give other time to be ready to receive sync cues.

All loops that last a whole number of bars can be synced to :metronome

You only need a 1_bar loop if (as in this case) you have a loop which is NOT an integral number of bars. In this case it needs to be delayed until the start of the next bar. Here the sync appears INSIDE the loop and applies on each pass.

1 Like

It’s lovely to see such a great discussion about this. However, please could I ask that you refrain from using negative and potentially confrontational language in post titles such as “X sucks” instead preferring constructive language.

1 Like

@samaaron i change the subject you’re right !
it was with a smiley :slight_smile:

Thanks :slight_smile:

I totally didn’t take any offence. I just think it’s inportant to keep the right cultural tone :slight_smile:

2 Likes

my english is not perfect as it is not my natural language, i’m a “frog” so i thought the term was not so violent.

may i add just a piece of advice for your health during your set live coding, mind your back !
cheers

1 Like

Hi again,

as the issue of syncing live_loops quite constantly pops up (e. g. in my courses) I made a little sketch, trying to visualise the logic behind it. I am aware of the fact that technical accuracy is not always on good terms with easy-to-understand-clarity; the sketch tries to tackle practical problems of what you can experience while syncing live loops. Anyhow, please let me know if I did missunderstand anything, if I can be technical more precise without making it more complicated or if the sketch could be improved otherwise:

(If this is to small to read please let me know, I’ll upload a A4 PDF and link it here.)

@nlb: Yes, it’s a typo. Fixed that. Thanks for the hint!

8 Likes

@robin.newman, the delay: 0.01 is a nifty trick: Somehow like a conductor raised its stick (allthough timewise just the opposite happens) and everybody knows, now a downstroke will follow and then I will have to start playing my instrument :wink:

good idea but isn’t there a typo sync: :red no ?

Exactly Martin. Trying to sync without the delay is like the conductor giving his/her initial downbeat without any warning whilst the players (the other live loops are still getting their instruments ready, so they miss the first bar and start at a later bar start from the conductor. With the delay the subsidiary live loops all start and wait the “conductor’s” cue which comes a little (0.01 beats) later.

1 Like

There is one (more theoretical) question concerning the technical background, which I would like to be ansered for myself. Is this the correct description in plain words:

A synced live_loop can’t just start together meaning at the same time with the cueing loop. The synced live loop notices the ‘first’ cue (which concerning the runtime of the whole script for it happened to be in the past) and then starts with the next cue. So syncing needs kind of to be announced to actually i. e. audibly to happen.

Yes I think this is a fair statement that you make Martin.
Sam stated this when Ethan raised the sync issue on the Sonic Pi github site.

In v3 I made this deterministic which also meant deciding on a repeatable set of semantics. This in turn means that each cue is totally ordered across all runs and all syncs are also ordered. In v3 syncs will only catch cues after them. Which means that for threads syncing and queueing on the same logical time, their thread ID will determine whether they are before or after.

In other words for a sync to work you should make sure that the cue is sent AFTER the sync is waiting for it. For two live_loops starting at the same time, delay the one you wish to sync to slightly and they will then start together. (The second one waits for the first to send a cue as it starts).

1 Like

Hi,

I hope any conductor is reading your post… The conductor is the metronome and as a metronome he has to be on the beat and not 0.01 seconde after…

The conductor is of course raising its stick before the beat and not after.

And computers are used because they are kown to be very accurate. so a metronome indicates the correct beat and musicians can rely on it.

According to me there is no valable explanation of this bug, it’s not a feature it’s a sad bug and i understand why you met lot of people not understanding this. It’s not logical as a musical point of view.

So this how it works but it’s a bit sad…
So the code below may help people to clear their mind

# a signal is sent every 1 beat
live_loop :metronome do
  sleep 1
end


# this loop last 4 beats.
# metronome are accurate and that's why we can rely on them
live_loop :drums, sync: :metronome do
  
  sample :drum_bass_hard
  sleep 0.5
  sample :drum_bass_soft, compress: 0, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
  sample :drum_snare_hard, compress: 1, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 1
  
  sample :drum_bass_hard
  sleep 0.5
  sample :drum_bass_soft, compress: 0, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
  sample :drum_snare_hard, compress: 1, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
  sample :drum_snare_hard, compress: 1, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
  
end

# this loop last 15 x 0.5 = 7.5 + 0.49 = 7.99 beats ! ! ! 

live_loop :hithats do
  sync :drums
  15.times do
    sample :drum_cymbal_pedal, pan: [-0.8,0.8,-0.1,0.1].ring.tick
    sleep 0.5
  end
  sample :drum_cymbal_open
  # sleep 0.50 will NOT WORK it's a bug not a feature :(
  # musicians are not accurate and it saves us :-)
  sleep 0.49
end

best regards.

Hi @nlb,

try this:

live_loop :metronome do
  sleep 1
end

live_loop :drums, sync: :metronome do
  sample :drum_bass_hard
  sleep 0.5
  sample :drum_bass_soft, compress: 0, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
  sample :drum_snare_hard, compress: 1, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 1
  sample :drum_bass_hard
  sleep 0.5
  sample :drum_bass_soft, compress: 0, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
  sample :drum_snare_hard, compress: 1, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
  sample :drum_snare_hard, compress: 1, pan: [-1,1,-0.8,0.8].ring.tick
  sleep 0.5
end

live_loop :hithats, sync: :drums do
  15.times do
    sample :drum_cymbal_pedal, pan: [-0.8,0.8,-0.1,0.1].ring.tick
    sleep 0.5
  end
  sample :drum_cymbal_open
  sleep 0.5
end

Two more thoughts on this:

You are right, it is not the easiest feature to understand in Sonic Pi.

And in defendance of the conductor-metaphor: Have you ever joined a rehearsal of a Jazz band? There will most surely be someone who counts something like that (in the case of a four-four time): “One… two, you know, what to do!” and then everybody is going to start.

Before you can sync to a metronome someone has to make sure that you listen to it at all.

3 Likes

thanks for your help @Martin
indeed your code is working but still don’t understand why mine is not working. i think i’m dumb :slight_smile:

Hi @nlb,

no, if I may say so, you are not dumb at all. This thread did also help me to bring some more clarity. I have these questions during the course I give (and these are probable to pop up at any time) and now I am sure to be able to answer it.

See my grafic, which tries to explain exactly this point (as did the last part of Sam’s explanation). It is all about the fact, that your :hihats will try to sync every time the loop runs. This is a bit like, as if this loop was a musician, who after every bar needs a new start (“one… two… you know, what to do…”) In my example, it does sync one time and then goes on with its own timing. So it is actually listening to sync just once (and remember: the time rule says: a sync can only be recognised if it has happened in the past).

Hope that helps.

3 Likes

I think you misunderstand how this works. It is EXACTLY what a conductor does. When you press RUN all the live loops start and await a sync pulse from the metronome (the conductor). At the same time the “conductor” starts waiting for 0.01 seconds to give the other loops a chance to be ready (equivalent to him/her raising the stick and checking that all the instruments (other live_loops) are ready and waiting for a cue to sync on. THEN the conductor (the metronome) starts giving the first downbeat and all the other loops start exactly in step with the metronome.
There is nothing magical about the 0.01 it could be 1 in which case there would be a slightly longer pause while the “orchestra” gets ready. However, when they start to play they would all be in perfect sync with each other and the conductor, when metronome starts after the 1 beat deal.

If the conductor started without raising his/her stick to warn the other members of the orchestra then chaos could ensue. I have played in several orchestras and this is how it works!

2 Likes

hello everybody,
ok ok maybe sometimes “i’m lost in translation” or miss something : i’m going to read slower your correct post and start again. :smile:

thanks for your help and sorry to waste your time !

No time wasted. This is an important topic. I hope that this thread will help users to get syncing right.

2 Likes

A question while revisiting my own grafic: In the last note shouldn’t it be: “BLUE starts from here, and will listen for the next run of RED” instead of “… every new run …”? Because that is exactly the reason for the gap: With sync :red in the loop’s body BLUE does need a new sync for each run and will only pick up the sync when it is 1. not running and 2. the sync is not in the past. And if this is not correct is there anyone who can put this into plain English which is technically acurat? I’d be very grateful!