前回投稿でさらっとスルーしていました「"fork"を使ってファンクションを評価したときにTempoClockで再生される」 と書きましたが、スケジューリングで大事なクロックと"play"について少し解説します。
スパコには”play”といういろいろなオブジェクトと合わせて使うと、プロセスを再生できる便利なメソッドがあります。
前回使用したのはRoutineとTaskですね、これはStreamオブジェクトに対しての”play”でした。forkもファンクションに対して使っていますがRouineの省略表記なので、Streamとして再生しています。
そのほかのplayにはたとえばFunction.play ( {}.play )、SynthDef.playなどがあります。これはシンセを生成して、サーバにノードを一つ作る(シンセを鳴らす)までやってくれます。x = { SinOsc.ar(1200,0,0.3) }.play;
x.free;
( x = SynthDef("test-dayo",{ var trig,src; trig = Impulse.kr(MouseX.kr(0.5, 20, 1)); src = SinOsc.ar(Sweep.kr(trig, 700) + 500, 0, 0.2); Out.ar(0,src); }).play )
x.free ノードを生成したので.freeです。
他にも様々なクラスに対して"play"が用意されていますが、基本的に何かのプロセスの再生をするという意味です。
さてStreamとしてスケジュールを再生した時に大切なのがクロック(Clock)です。その名の通り時計です。SuperColliderAppではいくつかの種類のクロックを利用しています。
SystemClock:システムクロック。
AppClock:アプリケーションクロック。 TempoClock:テンポクロック。
主にこの3つです。それぞれSuperColliderAppが立ち上がった時からカウントアップしています。
特徴ですがSystemClockがAppClockよりも正確だそうです。TempoClockはSystemClockと似ていますが、時間を秒やテンポ(bps,bpm)で管理出来ます。(じゃあAppClockいらないじゃん、て感じですが必要な場面もあります) 通常何も引数を加えないplayで再生されたものはTempoClockで再生されます。
通常意識しなくていいのですがスパコでは”play”すれば大体TempoClockで時間を刻みます。 TempoClock自体もオブジェクトなのでいくつでも任意に作る事ができます。
t = TempoClock(1); // create a TempoClock tに割り当てたTempoClockでRoutineを再生してみましょう
( p=Pseq([ "hello routine", 1, 20 ],inf).asStream; r = Routine({ loop{ p.next.postln; 1.0.wait; } }).play(t); ) ここでtのテンポをかえてみます、メソッドは.tempoです。(単位はbeat par a second、一秒簡のビートの数です)
t.tempo = 2 二倍の速さで再生されましたか。loopの中に書いた1.0.waitもTempoClockにい依存していることが分かります。 因にTempoClockのデフォルトのテンポは1、BPMで60になっています。
TempoClockは自分で生成しなくてもSuperColliderApp立ち上げ時にグローバルに一つ立ち上がっていますので”play”するだけで再生されます。デフォルトのクロックのテンポを操作する場合はTempoクラスを使います。
Tempo.tempo = 2; //tempoの単位はbps
Tempo.bpm = 140; //bpm
*AppClockが必要なときですが、ヘルプにあるように他のクロックではCococa primitiveが呼び出せないとあります。 Cococa primitiveはCococaを使ったクラスなので、たとえばGUIクラスのスケジューリングにはAppClockで再生する必要があるということです。
よくあるのが音のシーケンスに合わせてボタンを点滅させたい時。MIDI経由でフィジカルコントローラの値をGUIのスライダに反映させたい時など、GUIのスケジュールをAppClockで再生する必要がありまます。 その時どうしてもTempoClockやSystemClockで再生中にAppClockでGUI動かしたいときが出てくると思います。そういった場合はファンクションにdeferをつけるとそのブロック内だけAppClockで再生されます。
defer{ //GUIの更新とか }