スレッドの同期

一度、関数やスレッドを使用したとても高度なライブコーディングを行うと、あるスレッドが止まってしまうような間違いがとても容易に発生することを理解するでしょう。Runボタンを押してスレッドを再スタートさせることは容易にできるので、それは全然大した問題ではないのでしょう。しかし、スレッドを再スタートさせるときは、元々のスレッドと時間がずれることになります。

時間の継承

以前話した時に、新しいスレッドがin_threadとして作られると元のスレッドのすべての設定が継承されることを学びました。これは現在の時間を含んでいます。つまり、スレッドが同時にスタートするときには常に他のスレッドと同期していることを意味しています。

しかし、あるスレッドを独自のタイミングで起動したときは、現在実行中の他のスレッドと同期していることはほとんどないでしょう。

CueとSync

Sonic Pi はcuesyncという関数を使ってこの問題の解決方法を提供します。

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

ここでは2つのスレッドが使われています。1つは、音は鳴りませんがメトロノームのような機能として1秒ごとに:tickというビートメッセージを送っています。2つ目のスレッドは、tickというビートメッセージと同期し、その際にcueのスレッドの時間の情報を継承して実行を続けます。

この結果、:drum_heavy_kickのサンプルは、たとえ同時に実行されていない2つのスレッドであったとしても、他のスレッドが: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)は、1つめのスレッドとは時間がずれた2つめのスレッドを作り出してしまいます。しかしながら、cuesyncを使えば、タイミングがずれてしまうようなアクシデントを回避してくれます。

Cueの名前

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つのスレッドがそれぞれ独自に同期して、それぞれ異なるサンプルの音を再生します。実際には、syncスレッドとして用意した3つのスレッドのいずれかがcueスレッドとランダムに同期し、0.5秒毎にサンプル音の再生を聴くことができるでしょう。

逆にsyncスレッドを単に次のcueまで待たせるようにしても、もちろんそれは動作します。