ChucK入門 #8 - ADSRエンベロープを使う

前回、音を鳴らすときに減衰を行うためにエンベロープ用のオシレータを準備していましたね。ですが、シンセなどでおなじみのADSR式エンベロープのUGenが ChucK にはすでに準備されているのです。こっちを使いましょう。

書き換えると、発音部分はこのようになります

fun void buzz( float hz )
{
  SinOsc s => ADSR env => dac;
  hz * 2 => s.freq;
  0.5 => s.gain;

  env.set( 0.05::second, 0::second, 1, 0.3::second);
  
  env.keyOn();
  0.1::second => now;
  env.keyOff();
  
  while (true) {
    if (env.state() == 4) {
      break;
    }
    1::ms => now;
  }
}

まず、実際に音を出す SinOsc s はそのままです。ただ、これを dacに通す前に、ADSRというUGenを間に挟んで出すようになっています。ADSRは振幅(音量)に対するエンベロープとして作用し、入力の信号にエンベロープに基づいた音量操作を行い、出力に通します。

s.gainに0.5を入れてますが…これは 1.0を入れてみて実験するとわかります。いま和音で鳴らしてますから gain 1.0の音が4つは鳴ってしまうわけで、dacに入った瞬間恐ろしい歪みが出ます。まあ数字はいろいろ試してみるってアプローチで適当に楽しみましょう。

  env.set( 0.05::second, 0::second, 1, 0.3::second);

ADSRエンベロープのパラメータをセットしています。

  • 第一引数は Attackタイム。詳細はWikipedia
  • 第二引数は Decayタイム。詳細はWikipedぐふ
  • 第三引数は Sustainレベル。詳細は・・・というのは不親切ですが、Sustainだけは「レベル」です。注意。
  • 第四引数は Releaseタイム。詳s(ry

恐ろしくシンプルにいうと、まず発音開始とともに、Attackタイムをかけてピークに達します。で、Decayタイムかけて、Sustainレベルに向けて減衰します。発音を止める(厳密には正しくなくて、キーを離すと、みたいな意味ですね。発音やめちゃうと出ない..)とReleaseタイムかけてゼロに向かって減衰する、そんな仕掛けがADSRエンベロープです。

で、

  env.keyOn();
  0.1::second => now;
  env.keyOff();

当たり前といえば当たり前ですが、SinOscは鳴りっぱなしなので、ADSRのほうに「はい、スタート」「はい、リリース開始」を教えてあげないといけません。そこで使うのが keyOn や keyOff です。間にはいっている待ち時間はアタックタイム分待っているわけです。(これがない/短いと音がならない、極端に小さいレベルの音が一瞬だけ聴こえる、とか)

  while (true) {
    if (env.state() == 4) {
      break;
    }
    1::ms => now;
  }

これは、キモは env.state() == 4 のところで、4は"リリース時間も終了しました"を示しています。詳しくはドキュメント参照、で、エンベロープのどの処理中かが取り出せるようになっているんですね。

はい、というわけで ADSRによるアンプのエンベロープが出来るようになりました。