Hi there,
if you’re trying to synchronise Sonic Pi’s internal synths with an external sound source (either from another app on the same computer or from an external sound source) you need to be aware that Sonic Pi, by default adds 500ms of latency to all synth and MIDI events. This is likely what you’re hearing. Of course, this is in addition to the latency of your sound device which will vary depending on your hardware and settings.
This extra 500ms latency enables Sonic Pi to work correctly on very low powered machines. You can reduce it (this is essentially what use_real_time
does) but that’s not always advisable as it can cause Sonic Pi to “run out of time” much more easily. It’s also important to point out that use_real_time
only affects the current thread, so some threads can not have this latency applied and others have the default.
In your example the miditrig
live loop has no latency applied, but that isn’t affecting it as it’s not sending any sound events (play
/ synth
) or MIDI events midi
). So it’s not needed here.
When you receive the note_on
event, you rewind the clock 530ms and send an event. This obviously is physically impossible as you can’t actually go back in time. What it instead does is write an event into the Time State with an old time.
The main
live loop waits for the start
event. After it is written by the miditrig
live loop, it is immediately available - but time still hasn’t gone backwards as it can’t. However, the main
live loop has its clock set back in the past to match the time that the start
was sent which is in the past. This means that the main
live loop is now late as its clock points to a time that is behind the actual time in the real world.
The main
loop continues to spin round, attempting to catch up with the real time but still adding the 500ms of latency as it is not in real time mode. This is why you initially hear things late but then slowly catch up.
To fix this you ideally want to send an event from your external DAW before you want things to happen. This is similar to a band counting in. The leader of the band doesn’t just say “PLAY!”, they typically say, “Ready? 3, 2, 1, Play!”.
If you can send an event one bar ahead of time, then this will all be much easier.
Either way, you don’t actually need the miditrig
live loop unless you want to do multiple cues during a performance. This would suffice:
num_beats_in_bar = 4
sync "/midi:rptmidi_remote:0:1/note_on"
time_warp rt(-0.53) + num_beats_in_bar do
cue :start
end
live_loop :main, sync: :start do
play :E6, release: 0.1
#...Cue all the other loops...
sleep 4
end