編集:修正が見つかりました。g.gain.setValueAtTime(0,now);
アタックランプを下に設定するラインの前に、私は行方不明でした。それg.gain.value = 0;
を追加した後も冗長でした。
だから私は奇妙な問題を抱えています。背景を説明しましょう。ノートが作成され、使い捨ての方法で再生されるポリフォニック シンセサイザーを実装しています。キーがトリガーされるたびに、新しいオシレーターが作成されます。
最初にボリューム エンベロープをグローバルに実装しましたが、これにより、新しいノートがトリガーされたときに過去のノートのディケイ/リリースが台無しになることが判明しましたが、モノフォニックでは、アタック、ディケイ、およびリリース エンベロープはすべて期待どおりに機能しました。
そこで私の修正は、キーがトリガーされたときにオシレーターとエンベロープの両方をその場で作成することでした。ディケイとリリースの両方が以前と同じように機能し、ノート ボリュームが一意にエンベロープされるという利点がありますが、アタック エンベロープは直線的に上昇しません。代わりに、指定されたアタック時間だけ遅延し、一斉に発射します。
ゲインを直線的に変更するのではなく、アタックエンベロープが遅延して即座に作用する理由を誰かが理解できますか?
関連する関数は次のとおりです。
synth.prototype.playNote = function(i, freq) {
// create oscillator
var o = this.context.createOscillator();
o.frequency.value = freq * Math.pow( 2, this.osc[i].oct-4 );
o.type = this.osc[i].type; o.start( 0 );
// create envelope node and connect
var g = this.context.createGainNode(); g.gain.value = 0;
o.connect( g ); g.connect( this.master_gain );
// enveloping
now = this.context.currentTime;
// the line below delays for the attack time at 0 gain and
// shoots to volume 1 after (now + this.amp_env.attack) rather than curving linearly
g.gain.linearRampToValueAtTime(1, now + this.amp_env.attack );
g.gain.linearRampToValueAtTime(this.amp_env.decay, now + this.amp_env.attack + this.amp_env.decay + this.amp_env.release );
g.gain.linearRampToValueAtTime(0, now + this.amp_env.attack + this.amp_env.decay + this.amp_env.release );
// kill note after envelopes are done;
o.stop( now + this.amp_env.attack + this.amp_env.release + this.amp_env.release );
}