SuperColliderのシーケンスとかスケジューリングてどうなってるの2 [SuperCollider3]

- 2011-08-04

前回投稿でさらっとスルーしていました「"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の更新とか }