ChucK入門 #9 - マウス入力を扱う〜XYフィルター編

今回は趣向を変えてユーザーからの入力を扱ってみましょう。まずはマウス入力を使ってみましょう。

ついでに、マウスといえば、ということで、フィルターを作ってみましょう。
いきなりですがソースコードとその解説をしていきます。

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

Hid は Human Interface Deviceの略、でしょうか。まず Hidのインスタンスを生成して、次に後ほど使うことになる HidMsgのインスタンスも生成しております(実際に使うのは後なので宣言位置としてはイマイチですね)。

hid.openMouse によってマウスが使えるかどうかを確認しています。使えない場合は exitする。終了はこう書くわけですね > me.exit();

このあたりはイディオムということで深く考えなくても使える/理解できる範囲です。

SawOsc s => LPF lpf => dac;

0.5 => s.gain;
0.5 => lpf.gain;
1000.0 => float hz;
1.0 => float q;

lpf.set(hz, q);

はい、ノコギリ波オシレータを LPF に通してDAC出力しています。
LPFはローパスフィルターで、指定された周波数から下を通します。上もストンと切れているというよりは減衰していきます。シンセで御馴染みの概念です。パラメータは、今回はカットオフ周波数とQ(まあ、今はレゾナンスと同じってことにしてもとりあえず平気でしょう)。

LPFはUGen(ユニット・ジェネレータ)なので、gainがあります。レゾナンスによって出力がクリップするほど増大してノイズになるので、こんな数字にしていますが、それでも割れるのは割れるので、リミッターなどを後段に通せばいいのかもしれません。

で、次。

while (true) {
  hid => now;
  while (hid.recv( msg )) {
    if (msg.isMouseMotion()) {
      hz + (msg.deltaX * 3.0) => hz;
      if (hz < 50.0) {
        50.0 => hz;
      }
      
      q + (msg.deltaY / 50.0) => q;
      if (q < 0.6) {
        0.6 => q;
      }
      
      lpf.set(hz,q);
      <<< "" + hz + "," + q >>>;
    }
  }
}

今回は「マウスを使うには」なので重要な部分を。

まず

hid => now;

これによって hidからのイベントを待つ、ことになります。入力があるまでは動かないわけですね。

  while (hid.recv( msg )) {

hidから取り出せるイベントがある場合は・・・、という処理ループになっています。これで、取り出されたイベントの情報は msg (冒頭で宣言していましたね) に格納されます。

    if (msg.isMouseMotion()) {

HidMsgはマウス専用の型というわけではないので、ここでは「マウスの動きに関するイベントかどうか」を判断しています。

      hz + (msg.deltaX * 3.0) => hz;
      if (hz < 50.0) {
        50.0 => hz;
      }
      
      q + (msg.deltaY / 50.0) => q;
      if (q < 0.6) {
        0.6 => q;
      }
      
      lpf.set(hz,q);

注目すべきは msg.deltaX, deltaY です。つまり、マウスイベントではどうやら「絶対座標」は取れないようなのです*1

なのでマウスの動きを、カットオフとQに反映させてやります。下限値だけ決めていますが、このへんは各自の好みです。適当に遊んでみてくださいね。やりすぎるとエラいことになりますが。

ちなみに、LPFのsetは2つのパラメータを同時にセットできる便利なメソッドですが、バラバラに設定することもできます。

最終的なコードは以下の通り。このプログラムを走らせるとマウスの動きに応じて音が変化します。わうーわうーって喋っているような感覚、するでしょうか。面白いですね!!マウス入力を使って面白いシンセが作れそうな気がしてきました。

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

SawOsc s => LPF lpf => dac;

0.5 => s.gain;
0.5 => lpf.gain;
1000.0 => float hz;
1.0 => float q;

lpf.set(hz, q);

while (true) {
  hid => now;
  while (hid.recv( msg )) {
    if (msg.isMouseMotion()) {
      hz + (msg.deltaX * 3.0) => hz;
      if (hz < 50.0) {
        50.0 => hz;
      }
      
      q + (msg.deltaY / 50.0) => q;
      if (q < 0.6) {
        0.6 => q;
      }
      
      lpf.set(hz,q);
      <<< "" + hz + "," + q >>>;
    }
  }
}

*1:間違っていたら誰か教えていただきたいですー