ならば

音とかで遊んでいたログ

イベント

前に書いた時間の進め方

  • dur型 => now
  • time型 => now

の二通りで、どちらも直接的に時間を指定する方法だった。実はChucKにはもう一通り、

  • eventオブジェクト => now

という形の時間の進め方が用意されている。この式では指定したイベントの待ち行列に現在のshredを追加して、そのイベントが起きて順番が回ってくるまでshredの実行を停止させておく(時間は進ませる)。プログラムの流れは、

Event e;   // eventオブジェクトを作る

/* ... */

e => now;  // shredをeの待ち行列に追加して、待つ(時間を進める)
// 順番が来たらここより下のコードが実行される
/* 俺の時代がやってきた */

という感じ。イベントの起こし方には次の二種類がある。

  • signal():待ち行列の先頭にいるshredを実行
  • broadcast():待ち行列にいる全てのshredを並行実行。shredは待ち行列に並んでいる順にスケジューリングされる

イベントは複数のshredを同期させるのに使える。下のプログラムを実行すると、一秒ごとに50%の確率でドミソの中の(待ち行列の先頭にある)一音が聴こえるか、または三音同時に鳴るので和音が聴こえる。

JCRev r => dac;
.1 => r.mix;
Event event;

fun void note(Event e, float m)
{
    Wurley w => r;
    m => Std.mtof => w.freq;
    while(e => now) w.noteOn(.5); // 順番が来たら鍵盤を叩く
}

spork ~ note(event, 60);  // ド
spork ~ note(event, 64);  // ミ
spork ~ note(event, 67);  // ソ

while(second => now)
    maybe ? event.signal() : event.broadcast();

maybeは読む度に50%の確率で0か1を返す変な値。それとマニュアルには載ってない三項演算子が使えた。