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 (
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.
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.
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
time_warp rt(-0.53) + num_beats_in_bar do
live_loop :main, sync: :start do
play :E6, release: 0.1
#...Cue all the other loops...