Web Audio API の中にオートメーション関数と呼ばれるものがあります。これは例えば GainNode の増幅率や OscillatorNode の周波数等、AudioParam 型で定義されている様々なパラメータに対して直線や曲線等色々なカーブを駆使して変化させる事ができる、というものです。
setValueAtTime()
linearRampToValueAtTime()
exponentialRanpToValueAtTime()
setTargetAtTime()
setVlueCurveAtTime()
など。詳しくは Web Audio API のスペックを見ていただくとして、まあ名前だけでもなんとなく色々な事ができそうである事がわかるかと思います。ところがこれ、実際にこれらを使って実際にシンセアプリを作ろうとした時にどうもいまいち使いづらいんですよね。問題的は大きく分けて 2 つ。ただしその内の 1 つは今までの API の改訂で解決されていると言っても良いです。
元々の API の設計思想としては、このオートメーション関数はまず基本的にシンセのエンベロープ曲線を作るためのものだと考えられます。いわゆる ADSR カーブですね。私もこの仕様を最初に見た時にはこれで別に問題ないんじゃないかな、と思っていました。不都合な点は実際にこれを使ってみないとわかりにくいです。
第一の問題
このオートメーション関数は AudioParam 型のバラメータにくっ付いています。つまり、VCA に相当する GainNode の増幅率を指定する入力や オシレータの周波数を決める入力等、ノードの入力部にくっ付いています。普通の信号の接続についてはノード間の connect() 関数で行われますが、オートメーション関数はノード内部の話になります。
単に音量変化だけを付けるのならこれでも良いのですが、ちょっと複雑な構成のシンセなら、オートメーション関数で作られるエンベロープ曲線を使って音量の操作だけではなくフィルターのカットオフを変化させたり、オシレーターのピッチを変化させたりしたいところです。そうなると、複雑なオートメーション関数の設定を各入力パラメータにそれぞれ個別に設定してゆく事が必要になります。同じようにモジュレーション源である LFO ならオシレーターノードの周波数を下げて connect() によるノード間接続するだけで済むのに、これは不便です。複雑な構成のシンセなんかで、複数のエンベロープジェネレータを持って任意の対象にモジュレーションをかけるモジュレーションマトリクスなんかを装備しているシンセなんかになるとかなり無理があります。
まあ、この問題は後に ConstantSourceNode という定数値を出力するノードが追加された事でエンベロープ曲線も connect() による接続で複数個所に分配する事が可能になり、一応の解決を見たのですが。つまり ConstantSourceNode の役割はオートメーション関数の出力をノードの出力に変換する、という点に意義があります。
第二の問題
もう一つの問題はリトリガーの処理です。典型的なエンベロープ曲線というのは