一度、関数やスレッドを使用したとても高度なライブコーディングを行うと、おそらくスレッド内にある間違いを直すことが、とても簡単なことを理解できるでしょう。あなたはコードを起動してスレッドを再スタートさせることが容易にできるので、それは全然大したことではないのでしょう。しかし、スレッドを再スタートさせるときは、元々のスレッドとは調子がずれる事になります。
以前話した時に、新しいスレッドがin_thread
として作られると元のスレッドのすべてのセッティングが継続されることを学びました。これは現在の時間を含んでいます。つまり、スレッドが同時にスタートするときには常に他のスレッドと同期していることを意味しています。
しかし、1つのスレッドを起動したときは、それは独自の時間で再生されるので、他の現在実行中のスレッドと同期していることはほとんどありません。
Sonic Pi はcue
とsync
という関数を使ってこの問題の解決方法を提供します。
cue
はすべての他のスレッドに向けてビートメッセージを送ることができます。初期状態の他のスレッドでは、これらのビートのメッセージは関係付けられず、無視されます。しかし、sync
関数を使えば、あなたは簡単にこの関連付けを登録することができるのです。
sync
という機能は、一定の時間、実行中のスレッドを止めるsleep
という関数と非常に似ていることに気づくことが重要です。しかし、sleep
ではどのくらい休止させるかを決めることができましたが、sync
ではそれを決めることができず、sync
は長さに関わらず、次のcue
が出てくるまで待つのです。
それでは、もうちょっと詳しくみていきましょう。
in_thread do
loop do
cue :tick
sleep 1
end
end
in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end
ここではふたつのスレッドが使われています。ひとつは音はなりませんがメトロノームのような機能として :tick
を使って一秒ごとにビートの情報を送っています。2つ目のスレッドははtick
の情報と同期し、そのビートの情報を受け取った際に、 cue
のスレッドの時間に情報を引き継ぎ、起動を続けます。
この結果、:drum_heavy_kick
のサンプル音源は、厳密に同時のスタートでないふたつのスレッドであったとしても、他のスレッドに :tick
からの情報をきっちり受け取って正確にビートを刻んだ音が聞けるはずです。
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
このちょっとやっかいな sleep(0.3)
は一つ目のスレッドとはあまり関係のない2つ目のスレッドを作り出してしまいます。しかしながら、cue
やsync
を使えば、タイミングがずれてしまうようなアクシデントを回避してくれます。
cue
には:tick
以外のどんな好きな名前でも付けられます。その際には他のスレッドと動機させるために必ず正しい名前を使用する必要があります。もし違った場合、永遠に(もしくはストップボタンを押すまで)それはcue
の情報を待ち続けることになります。
それではcue
の名前付けを見てみましょう。
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
ここではメインのcue
でビートメッセージをランダムに:foo
と:bar
、:baz
に送るよう設定しています。それから3つのスレッドがそれぞれ独自に同期して、それぞれ設定されたサンプルの音を再生します。この関係付けられた結果から、cue
のスレッドによって、それぞれが同期しながら0.5秒刻みに`syncスレッドの音がランダムに再生され、そしてサンプルが再生されます。
逆にsync
スレッドを次のcue
まで居座り続けさせ待たせるように、
それらのスレッドに送るように設定しても、もちろんそれは動作します。