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

- 2011-08-02

という疑問を持つ方が多くおられるようなので、 何かしら役に立てればと思い以下にメモしていきます。 といってもわたしもヘルプを読み読み勉強しつつなのですべてを鵜呑みにしないように!

 

sclangでコードが評価されるタイミングがよく分からないと思いますが、基本的には選択してenterキーを押したときです(うーん奇妙ですね)

それ以外だとstartup.rtfに書いておくとSuperColliderAppの立ち上げ時に評価されるとか、OSCResponderやMIDIInとかにハンドラを用意しておいた時とかでしょうか..。

 

ではどうやってスケジューリングを書くのかと。

 

sclangにはスレッドとして機能するRoutineやTaskなどのクラスが用意されています。こうしたクラスにループのスケジュールを書いて”play”でインスタンス化してあげれば 周期的に評価されます。 *周期的に評価するにはdo()やloop()等のリピーターが必要です。 また全体がオブジェクトということで変数に割り当てて管理出来るのも特徴です。

まずはRoutineを使ってみます。( r =Routine({ "hello routine".yield; 1.yield; 20.yield; }); )

r.next; 一度しか評価されませんでしたか、もう一度r.next;を選んでenterで実行してください。5回繰り返します。

----実行結果---- hello routine 1 20 nil nil

 

.yieldイールド(プログラミング的にはイールド文といってなんか渋い文らしい)をつけると、オブジェクト内で値がどこまで再生されたか保持しておく事ができます。.nextや.resetなどで次の値を呼んだり初期化したり出来ます。値が空になるとnilを返します。

 

Routine内にyieldの値を埋め込むこともできますが、ややこしいので今度はPatternクラスを使ってみましょう。リストを順番に呼び出すPseqクラスを使いましょう。

p=Pseq([ "hello pattern", 1, 20 ]).asStream;

p.next ----実行結果---- hello pattern 1 20 nil nil

.asStreamというのがめんどくさいですね。Patternオブジェクトに直接.nextとはできないのです。一度Streamオブジェクトにしないと呼び出せないようです。Streamは先ほどあった.yieldと同じ"オブジェクトがどこまで再生したかを保持しておく"という機能を持っています。(RoutineもStreamクラスの派生なのです)

 

さて、Streamを使ってのシーケンスはできました。

 

これを自動化するには.nextや.resetなどを定期的に呼べばいいのではないでしょうか。

スパコには便利なplayというメソッドがあります。

 

Streamを"play"でインスタンス化します。その際、ファンクションに.do()とかloop()とかをつかいます。次のループに入るまでの待ち時間を入れます。.waitを使います。これを入れないと最悪SuperColliderAppがハングします。今度はTaskクラスを使ってみましょう。

( a = Task.new({ loop({ "ok, that was it".postln; 1.0.wait; }) }); )

a.play; a.stop; TaskはRoutineとほぼ書式は同じです。違うのはstopで止めた後、startで再開出来るという便利なところです。ただ注意があってクロックとの関係がどうにかこうにかなので心して使えと書いてありましたが詳しくはヘルプの最後の方をみてください。

 

RoutineからPatternを呼ぶこともできます。

( p=Pseq([ "hello routine", 1, 20 ],inf).asStream; r = Routine({ loop{ p.next.postln; 1.0.wait; } }).play; )

r.stop; *実はRoutineはもっと簡単に書けます。

FunctionクラスにはforkというメソッドがあってこれをつけとくだけでRoutineとしてTempoClockで再生されます。

( fork { inf.do({arg i; i.postln; 1.0.wait; }) } ) そのかわりforkはたとえ変数を割り当ててもプロセスをstopで止めることはできません。コマンド+.で止めましょう。 あと.waitなどの時間を与えないと実行時ハングすると思います、必ず入れましょう。

 

さてこのようにスケージューリングは書くことがきました。

 

しかし実際シンセにさまざまな値を渡しつつ、いくつものパターンを同時に作りたいとなった時、もっとたくさんのパターンを簡潔に書きたくなるでしょう。

 

PではじまるPatternクラス郡にいろいろな機能を持ったクラスがあります。

 

つづく..