SuperColliderのエンベロープ、式の評価順、マウスとキーボードの入力、arとkrについてです。
エンベロープ Env, EnvGen
Env
でエンベロープを作れます。
test
でエンベロープを音としてテストできます。また plot
でデフォルトのエンベロープをグラフにします。
Env().test.plot;
デフォルトから変えます。
Env( [0, 1, 0], [0.1, 0.5], [2, \sine] ).test.plot;
Env(レベル, 時間, カーブ)
となっています。カーブの種類については Env
のヘルプにまとまっています。引数がややこしいですが以下のような意味です。
Env( [点0, 点1, 点2, ...], [点0から点1へ至る時間, 点1から点2へ至る時間, ...] [点0と点1を結ぶ線の種類, 点1と点2を結ぶ線の種類, ...] );
作ったエンベロープをUGenに適用するには EnvGen
に入れて引数として渡してやります。
{ var freq = 40; var pitchShift = 1000; var detune = 6; var env = Env( [0, 1, 0], [0.1, 1.5], [2, \sine] ); var envGen = EnvGen.ar(env, doneAction: 2); var osc = Array.fill(4, { |index| Pulse.ar( freq + (detune * index) + (pitchShift * envGen), 0.5 * envGen, 0.2 * envGen)}); [osc, osc] }.play;
doneAction: 2
と指定することでエンベロープが終わると同時にシンセをfreeします。この指定がないと演奏を終えたシンセのリソースがサーバ側で確保されたままになりCPUやメモリを圧迫してしまいます。シンセに関するサーバの状態は s.plotTree
かCtrl+Alt+TでNode Treeを表示して確認することができます。 2
以外の値についてはヘルプのUGen done-actionsで確認できます。
この他のエンベロープはヘルプのBrowserからUGens > Envelopesとたどればいくつか見つかります。
式の評価とメソッドの中置
sclangでは常に前から順番に計算が行われます。 *
や /
などを使う時は注意してください。
(1 + 2 * 3).postln; // 9 (1 + (2 * 3)).postln; // 7
Array
に対しても直接、演算子がつかえます。
([1, 2, 3] + 4).postln; // [ 5, 6, 7 ] ([-1, 0, 1] > 0).postln; // [ false, false, true ]
引数を2つとるメソッドは中置できます。
(768 gcd: 1024).postln; // 256 gcd(768, 1024).postln; // 256
SynthDef
の内部などサーバ側で評価される式は常に浮動小数点数で計算が行われます。 >
や <
など普段はBooleanを扱う演算は false
のとき 0.0
, true
のとき 1.0
を返すようになります。
マウスとキーボードからの入力
MouseXとMouseYでポインタの位置を使えます。MouseButtonは左クリック(ボタン1)のみに反応しました。以下の例はマウスクリックで音が鳴り、ポインタの位置で音が変化します。
{ var freq = MouseX.kr(100, 800, 1); var osc = PMOsc.ar( freq, freq, MouseY.kr(0.01, 100, 1), 0, MouseButton.kr(0, 1, 0)); [osc, osc] }.play;
KeyStateでキーボードの入力を受け取ります。keycodeの値は環境によって変わるようです。以下の例は私が試した環境ではスペースキーに反応しました。
{ SinOsc.ar(KeyState.kr(65, 100, 200), 0, 1) }.play;
arとkr
arはaudio rateの略でサンプリングレートの解像度で計算することを意味します。krはcontrol rateの意でサンプリングレートの1/64の解像度で計算を行うそうです。
音を計算する時はサンプリング周波数の解像度で計算する必要があるのでarを使います。krは解像度が低くなりますがヘルプの例では変調などに使われています。
以下の例で違いを確認できます。
{ [ SinOsc.ar(Pulse.ar(Pulse.ar(0.5, 0.5, 200), 0.5, 400), 0.5, 0.3), SinOsc.ar(Pulse.kr(Pulse.kr(0.5, 0.5, 200), 0.5, 400), 0.5, 0.3) ] }.play;