Chuck入門 #10 - SndBufでwavファイルを鳴らす

なんだか ChucK by Exampleというべき様相を呈している本入門記事ですが、ついに第10回を迎えることとなりました。私の興味や、思いつきの実験精神にしたがってソースコードを作成しているので、どうしてもヘンな(妙に突っ込んだ)例が多いため理解の妨げになっている可能性もあるかと思います。その点はご容赦ください。

いままではオシレータを使って音を出してきたわけですが、今回は wavファイルを鳴らしてみましょう。多分、aiffなんかもいけるんだと思いますが試してません。

今回の完成品はこちら。まずはソースコードをどうぞ

Hid hid;
HidMsg msg;
0 => int device;
if (hid.openMouse(device)==false) {
  <<< "cannot open mouse" >>>;
  me.exit();
}

SndBuf l1;
l1.read("フルパス/loop2.wav");
1 => l1.loop;

SndBuf l2;
l2.read("フルパス/loop4.wav");
1 => l2.loop;

1.0 => l1.gain;
0.0 => l2.gain;

l1 => dac;
l2 => dac;

while (true) {
  hid => now;
  while (hid.recv( msg )) {
    if (msg.isMouseMotion()) {
       msg.deltaX / 500.0 => float g;
       l1.gain() + g => float l1g;
       if (l1g >= 1.0) {
          1.0 => l1g;
       } else if (l1g <= 0.0) {
          0.0 => l1g;
       }
       l1g => l1.gain;
       1.0 - l1g => l2.gain;
    }
  }
}

今回のキモは、l1とl2という SndBufクラスのインスタンスです。ほかのコードは基本的に、2つの波形のミックス比率をマウスで操作する、というクロスフェーダーごっこのためのコードです。

上記の例を動かすためには、どこかで、所謂「ループ素材」を2種類用意してきて実行してみてください。もちろん、BPMも同じでへんな前後マージンがないものを用意しないといけませんが、うまくいけば、ビートミックス的な感じになってなかなか気持ちいいです。私はVengeanceの適当なループ素材を使ってやってみましたが、なかなかいい感じになりました。

さて、コードの説明。Hidうんぬんは前回説明しましたから思いっきり割愛します。SndBufに関するところのみに絞ります。

SndBuf l1;
l1.read("フルパス/loop2.wav");
1 => l1.loop;

はい。もう構文的には大丈夫ですよね。SndBufクラスのインスタンスを作成して、l1にその参照を代入しています(というとなんだかものものしいですが)。そして、そのインスタンスに対して 例では フルパス/loop2.wav を読み込ませています。

SndBufのloopというプロパティに1を格納すると、自動的にループ再生してくれます。今回のサンプルコードみたいな内容だと、1にするわけですが、ワンショットの効果音なんかの場合は適宜設定してください。

SndBufのl2については省略。

1.0 => l1.gain;
0.0 => l2.gain;

はい、SndBufはユニットジェネレータ(UGen)です。なので、gainプロパティを(オシレータなどと同じく)持っています。この例では、まずは l1というSndBufのゲインを1.0に、l2をゼロ(鳴っていない)状態にしています。

l1 => dac;
l2 => dac;

と、これで l1,l2のUGenから dacに接続し、ただちに再生が開始されます。ちなみに、ただちに再生を開始したくない場合はどうするか、というと再生ポジションのプロパティがありますので、そちらにサンプルの長さ+1 とかおかしな値を入れておけば再生されませんので、必要なときに 0 にすると鳴りはじめます。

while (true) {
  hid => now;
  while (hid.recv( msg )) {
    if (msg.isMouseMotion()) {
       msg.deltaX / 500.0 => float g;
       l1.gain() + g => float l1g;
       if (l1g >= 1.0) {
          1.0 => l1g;
       } else if (l1g <= 0.0) {
          0.0 => l1g;
       }
       l1g => l1.gain;
       1.0 - l1g => l2.gain;
    }
  }
}

これは、前回同様ですが、今回の処理では、マウスの移動量にしたがって、l1のゲインを動かし、l1+l2=1.0 となるように双方のゲインを設定しています。これで半々になったり、l2だけに鳴ったりしますね。そんな内容のコードです。

今回はこれにて終了です。SndBufでループ素材を鳴らして、それをLPFに通して・・・などということももちろん出来ますから、ループ素材とオシレータとフィルターですでに夢が広がりまくりですね!

ではまた次回!