ChucK入門 #3 - blackhole!
ChucK入門第三回です。ChucKのドキュメントの流れをパクっていますが気にしない。
blackholeの存在
SinOsc s1 => dac; SinOsc s2; 5 => s2.freq; while (true) { 20::ms => now; (s2.last() * 40) + 440 => s1.freq; }
このプログラムを実行しても「あれ?別にs1だけ鳴ってるのとかわらない」って感じがします。
やろうとしていることは、s2というオシレータによってs1の周波数をモジュレーションするという内容です。
LFOで、オシレータにピッチモジュレーションを掛けている、というほうが解りやすい人もいるんじゃないでしょうか。
これはなぜかというと、s2(ユニットジェネレータ)が何にも結線(=>, chucking)されていないため、last()が取得できない(時間の進行の中で、という注釈が付くかもしれませんが)ためです。
これを回避するために
s2 => blackhole;
を追加します。
blackholeは音を吸い込むブラックホール、ということでユニットジェネレータの出力を吸い込みます。ChucKによってコンパイルされる際にもblackholeに結ばれたユニットジェネータは時間軸に従って動作します。
プロパティの取得
説明が前後しましたが、s1.freq(); とか s1.freq()+1 => s1.freq;
のように関数呼び出しのように記述するとプロパティの取得になります。
時間に厳密なChucK
上記の例で、LFO扱いになっている s2 の周波数には 5Hz が設定されていますね。5Hzはつまり200msで1サイクルとなります。サイン波なので、ゼロポイントは、0ms時点、100ms時点、200ms…100msの整数倍となります。
上記のプログラムで
while (true) { 100::ms => now; . .
と、ポーリング間隔を変えてやるとs1の周波数は変化していないように聴こえます。これは、s2の値を取り出すのが100ms間隔なので、いつ取得してもゼロになるためです。
ChucKは時間に対して(結構)厳密な環境だ、ということが伺えますね。
コンソール出力
こんな感じで出力できます。
<<<"hogehoge">>>; <<<s1.freq()>>>;