Eens je het live coderen voldoende onder de knie hebt met een aantal functies en threads tezelfdertijd, dan heb je misschien opgemerkt dat het niet moeilijk is om een fout te maken in één van de threads die dodelijk kan zijn. Niet heel erg, want je kan makkelijk de thread terug herstarten door op afspelen te klikken. Maar als je de thread herstart is deze uit de maat met de originele threads.
Zoals we eerder hebben besproken, erven nieuwe threads gemaakt met in_thread
alle instellingen van de bovenliggende thread. Dus ook de huidige tijd. Dit betekent dat de threads altijd synchroon met elkaar zijn als zij tegelijkertijd zijn gestart.
Wanneer je een thread op zich start, begint het met zijn eigen klok die waarschijnlijk niet in sync is met een van de andere actieve threads.
Sonic Pi biedt een oplossing voor dit probleem met de functies ‘cue’ en ‘sync’.
‘cue’ laat ons toe, hartslag-berichten te sturen aan alle andere threads. Standaard zijn de andere threads niet geïnteresseerd in deze, en negeren deze hartslag-berichten. Je kan hun aandacht wel vragen met de functie ‘sync’.
Het belangrijkst om weten is dat ‘sync’ vergelijkbaar is met sleep
in die zin dat het de huidige thread stopt voor een periode van tijd om om actief te zijn. Met sleep
geef je echter aan hoe lang je wilt wachten terwijl je met ‘sync’ niet weet hoe lang je zal wachten - als ‘sync’ op de volgende ‘cue’ van een andere thread wacht die lang of kort kan wegblijven.
Laten we dit in detail bekijken:
in_thread do
loop do
cue :tick
sleep 1
end
end
in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end
Hier hebben we twee threads - één gedraagt zich als metronoom, zonder geluid te maken en zend elke maat enkel :tick
hartslag-berichten uit. De tweede thread synchroniseerd op tick
berichten en wanneer deze er één ontvangt, erft hij de cue
tijd thread en blijft lopen.
Als gevolg zullen wij de ‘: drum_heavy_kick’ sample horen, precies op het moment dat de andere thread het :tick
bericht uitzend, zelfs als de twee threads niet met de uitvoering ervan op hetzelfde moment beginnen:
in_thread do
loop do
cue :tick
sleep 1
end
end
sleep(0.3)
in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end
Die ondeugende sleep
aanroep zou doorgaans de tweede thread uit fase laten lopen met de éérste. Als we echter cue
en sync
gebruiken, synchroniseren we automatisch alle lopende threads die toevallige verschuivingen in timing omzeilen.
Je mag eender welke naam gebruiken voor jouw cue
berichten, niet enkel :tick
. Je hoeft er alleen voor de zorgen dat alle threads op de correcte naam sync
-en, anders gaan ze voor eeuwig wachten (of tot je op de stopknopstop klikt tenminste).
Laten we met en paar cue
namen spelen:
in_thread do
loop do
cue [:foo, :bar, :baz].choose
sleep 0.5
end
end
in_thread do
loop do
sync :foo
sample :elec_beep
end
end
in_thread do
loop do
sync :bar
sample :elec_flip
end
end
in_thread do
loop do
sync :baz
sample :elec_blup
end
end
Hier hebben we een hoofd cue
loop die random de heartbeat namen :foo
, :bar
or :baz
uitzend. We hebben ook drie loop threads die elk onafhankelijk op één van die namen synct en daarbij een verschillende sample afspeeld. Het netto effect is dat we elke 0.5 beat een klank horen als wordt elk van deze 0.5 sync
threads random ge-synct wordt met de cue
thread en zijn sample speelt.
Dit werkt natuurlijk ook als jen de threads omgekeerd ordend omdat desync
threads gewoon op de volgende cue
zitten wachten.