包絡 — ゆっくりの層
実際の音は、立ち上がって、減って、保たれて、消える。この音量の輪郭がエンベロープ(包絡)。代表的なのが ADSR で、Attack・Decay・Sustain・Release の4区間でできた折れ線。
ADSR は鍵を押している間(ゲート)と離した後で形が分かれる。押すと Attack で 0 から最大へ、Decay で持続レベル(Sustain)まで落ち、離鍵まで Sustain を保つ。鍵を離すと Release で 0 へ戻る。Attack・Decay・Release は時間、Sustain だけが音量で、他の三つと単位が違う。WebAudio では GainNode.gain に linearRampToValueAtTime / setTargetAtTime を時刻ごとに積んで、この折れ線をそのまま音量に重ねる。
時刻 e を入れると 0..1 の音量が返る。立ち上がりは直線、減衰は持続レベルへの直線、ゲート中は平ら、離鍵後は 0 への直線。区間の境目を if で分ける。
const adsr = (e, gateLen) => {
const attack = 36
const decay = 40
const sustain = 0.55
const release = 64
if (e < attack) return e / attack
if (e < attack + decay) return 1 - (1 - sustain) * ((e - attack) / decay)
if (e < gateLen) return sustain
const rel = e - gateLen
if (rel >= release) return 0
return sustain * (1 - rel / release)
}下は adsr を左から右へ並べて、折れ線そのものを描いた。attack で一気に上がり、decay で少し落ち、gateLen まで sustain の高さで平らに伸び、ゲートを過ぎると release で 0 へ戻る。四つの区間で傾きが切り替わる。
attack を大きくすると立ち上がりが鈍く、sustain を上げると平らな部分が高くなり、release を伸ばすと右の尾が長くなる。gateLen がゲートの長さで、ここを過ぎた所から離鍵の下りが始まる。
下は時刻 t を毎フレーム進め、その時点の adsr の値を右端に書き込んで左へ流している。波形が右から左へ流れ、右端の点が再生ヘッド。値が 0 に戻りきると次の音が鳴り、ゲートの長さを変えながら包絡を繰り返す。
右端のヘッドが上下しながら、過ぎた音量が左へ尾を引いて残る。ゲートが長い音ほど平らな部分が長く伸び、短い音は山だけで終わる。波形が速い振動だとすれば、包絡は遅い変化で、音はこの速い層と遅い層の二段でできている。