RSS Twitter Facebook

2020/06/29 (2020年06月 のアーカイブ)

Web Audio API での ADSR カーブ


Web Audio API でシンセを作る場合、元々 API の思想としてはエンベロープ曲線、いわゆる ADSR のカーブを生成するには各種の オートメーション関数 を使う事が想定されています。つまり、GainNode の gain パラメータに対して

setValueAtTime()
linearRampToValueAtTime()
exponentialRampToValueAtTime()
setTargetAtTime()

等の関数でパラメータを時間と共に変化させるという機能を使用します。しかし実際にそれなりに実用的なシンセを作ろうとするとこれではうまく行かない、あるいはとても面倒くさい、という事が起こります。それが「リトリガーへの対応」です。

ADSR は鍵盤を押した時、離した時のタイミングを基に下の図のような音量変化の曲線を作ります。各部の曲線は基本的に setTargetAtTime() による目標値に漸近する指数曲線 :

\(v(t) = V_1 + (V_0 - V_1)\, e^{-\left(\frac{t - T_0}{\tau}\right)}\)

で作れます。

問題は 2 回連続で鍵盤を素早く弾いた時です。1 回目の打鍵の曲線がまだ収束していない時に 2 回目の曲線が始まり、単に同じ曲線を繋げると不連続点ができてしまいます。この不連続点はノイズとして聞こえますので、対処が必要です。

でどうするかですけど、色々な考え方はあると思いますが、典型的なアナログシンセではどうなるかと言うと、次の図です。現在の値から ADSR 曲線が始まり、その分、2 つ目のピークになる点も少しだけ前倒しされます。ちなみに良くない例でありがちなのはアタック時のピークの時刻、つまり decay の始まる時刻を維持するために上りのカーブの傾きを変えてしまう事ですね。アタックのニュアンスが変わってしまいます。

ところがこれをオートメーション関数で実現しようとすると厄介な事になります。各部の曲線を指定するのはターゲットとなる値と発動する時刻がパラメータとして必要なので、2 回目の打鍵におけるアタック、ディケイ曲線を指定するにはリリース曲線の途中にある値を取得し、そこから 2 個目のピークになる時刻を計算する必要が出てきます。

何故こんな面倒な事になるかというと、Web Audio API のオートメーション機能はすべて時刻ベースのイベントで発動するのに対し、アナログシンセの ADSR では attack の次に decay が発動するタイミングというのは時刻で決まっているわけではなくてサンプル毎に現在の値を計算してゆく中で決まったピーク値になったら発動するものだからです。

という事で、これを根本的に解決するにはこのオートメーション関数のアプローチではちょっと筋が悪いのではないかと思うわけです。。。つまりどうするのが良いか。。。は次回に続く...

Web Audio API での ADSR カーブ (その2)

Posted by g200kg : 2020/06/29 07:14:26