FM音源プログラム (1) -- EG (1)

唐突ですが、ここで話題をFM音源プログラムの EG (Envelope Generator) の話に変えます。

アナログ EG


アナログシンセの EG (ADSR方式) の概念図を左に示します。
一次 RC 回路でコンデンサに充放電してエンベロープ波形を得ています。 図では「コントロール・ロジック」と書いてあるブロックは、実際はコンパレータ + SR-FF 程度の回路です。
電源電圧を V_{\rm cc}エンベロープの上端の電圧を V_{\rm top}、サステイン電圧を V_{\rm sus} 、また、アタックタイム、ディケイタイム、リリースタイムをそれぞれ、 T_a,\, T_d,\, T_r とすると、ADR 各フェーズでの電圧は、各フェーズの始めからの経過時間を t として、数式では、

  • アタック -- V_{\rm cc} \cdot \left ( 1 - \exp(-t / T_a) \right )
  • ディケイ -- (V_{\rm top} - V_{\rm sus}) \cdot \exp(-t / T_d) + V_{\rm sus}
  • リリース -- V_{\rm sus} \cdot \exp(-t / T_r)

となります。 ただし、サステイン・レベルに到達する前にリリース・フェーズに突入した場合は、その時点での電圧からグラウンドに向かって減衰していきます。
減衰音系の楽器では、音が自然に減衰していくメカニズムがエネルギーの散逸だけによるものならば、ディケイ/リリースで指数関数で減衰していくのは理にかなっています。
単位時間あたり一定の割合でエネルギーが失われることを数式で表現すると指数関数になるからです。
一方、アタックでは、エネルギーが加えられて発音を開始するメカニズムは楽器ごとに異なるので、共通の原理といったものは存在しません。
それでも、1-\exp(-t/T_a) のように、始めは急速に立ち上がるけれど、ピークに近づくにしたがってゆっくりになるものや、 S 字カーブ状に、始めゆっくり、中間速く、最後にまたゆっくりという変化は自然なものと言えます。
それに対し、\exp(t/T_a) のように、始めはゆっくりでも、ピークに近づくにしたがって、どんどん速く変化するようなカーブは不自然です。
持続音系の楽器では、演奏者の意思で音量を維持しているわけですから、EG による音量変化は近似にすぎません。

FM音源の EG 波形

OPL3 系のFM音源チップのボードは持っているのですが、ISA バスのカードであるため、現在、音を出せる状況にないので、MA-2 シミュレータのオーディオ出力を録音して、波形エディタで観察しました。
その結果、エンベロープは約 1 ms ステップで変化している、つまり、サンプリング周波数は約 1 kHz ということが分かりました。 これを受けて、私のFM音源プログラムでも、エンベロープは 1 ms ごとに計算しています。

また、アタックは直線的に変化しています。 これはハードウェアのFM音源チップでもそうなのかどうかは分かりません。
ディケイ/リリースは指数関数的です。 ただし、ディケイはアナログシンセのようにサステイン・レベルへ減衰していくのではなく、常にゼロに向かって減衰していって、サステイン・レベルを横切った時点でサステインへ移行するようになっています。

lb 値

FM音源のオペレータの出力振幅に関しては、出力最大=減衰なしで、それ以下の値は減衰させて作るという考えになっています。
FM音源チップの音色データの「トータルレベル」(TL) や「サステインレベル」(SL) がこのような減衰値を指定する数値で、振幅のリニア値ではなく、2 を底とする対数で表現する方法になっています。
そこで、勝手に、この方式によるデータ表現を「lb」または「lB」と表記して、「エルビー」と読むことにしました。
 その定義は、

2 を底とする対数をとって、符号を反対にしたもの
x をリニアな数値とすると、-\log_2(x) で表現される

です。
自然対数を「ln()」と表記するように、2 を底とする対数を「lb()」と表記することがあります。 「lb」 という表記は、それに従ったものですが、符号が逆になっています。
また、
\qquad \log_2 (x) = \log_{10}(x) / \log_{10}(2)
\qquad 20 \cdot \log_{10}(x) = 20 \cdot \log_{10}(2) \cdot \log_2(x)=6.02 \cdot \log_2(x)
ですから、lb 値に -6 をかければ減衰量を「dB」(デシベル) に変換できます。 「lB」 という表記は 「dB」 をまねたものです。
lb で表現されている数値 y の整数部を s、小数部を f として、元のリニアな表現 x にもどすには、
\qquad x = 2^{-y} = 2^{-s} \cdot 2^{-f}
を計算します。
s は整数ですから、2^{-s} はビットシフトで実現できます。 つまり、本当に計算する必要があるのは小数部 f に対する 2^{-f} だけです。
FM音源プログラムでは、小数部を 6 ビットとして、64 エントリのテーブルを使って小数部の lb - リニア変換を行っています。