FPGA 版 FM 音源 (44) -- YMF297 (OPN3/OPL3) 測定 (9) -- トレモロ

今回は OPL3 のオペレータ出力レベルを LFO振幅変調する機能の話です。
シンセ的には LFO による「音量変化」は「トレモロ」(tremolo)と呼ばれていますが、OPL3 関係のドキュメントでは一貫して技術寄りの用語として AM (amplitude modulation) を使っています。
これは、「キャリア」となるオペレータに対する AM はトレモロの効果ですが、「モジュレータ」となるオペレータに対する AM は「音色変化」となる「グロウル」(growl) の効果を与えるので、一概にトレモロとは呼べないためと思われます。
音源パラメタを

WS = 6 (方形波)
FNUM = 0 
TL = 0 (減衰なし)
AM = 1 (トレモロ ON)
DAM = 0 (トレモロ「弱」、1 dB)

という設定で 48 kHz の SPDIF 出力を経由して波形をチャプチャし、波形編集ソフトで見たものを下に示します。

F-Number をゼロとしているので、フェーズ・アキュムレータはキーオンでリセットされた後は変化せず、波形出力部は DC (直流) の値として方形波の正側の振幅値 4084 を出し続け、AM による振幅変化がそのまま表れてきます。
見ているのは時間波形なので、ソフト上でサンプル単位で幅や振幅を読み取ることができ、下の図のようになります。

振幅変化は 7 つの階段で構成され、トップの階段の幅が 1984 サンプル、ボトムの階段の幅が 1216 サンプル、中間の 5 つの階段の幅はどれも等しく 1024 サンプルとなっています。
1 周期では、

1984 + (2 × 5 × 1024) + 1216 = 13440

となります。 したがって、AM LFO の周波数は、

48000 [Hz] / 13440 = 3.57 [Hz]

となります。
これを OPL4 (YMF278B) でのサンプリング周波数 49.516 kHz での値に換算すると、3.68 Hz となり、OPL4 (YMF278B) アプリケーション・マニュアルの記述 3.7 Hz と一致します。
振幅方向の値は、波形出力部の最小ステップ幅の 8 倍の間隔で出力されています。
以前「勝手」に定義した lb (log binary) 値、つまり減衰量を 2 を底とする対数で固定小数点表現したもので表すと、lb 値の小数部のビット位置を b-1、b-2, ... として、

b-3 : -0.75 dB
b-4 : -0.375 dB
b-5 : -0.1875 dB

の 3 ビットのみが、b[-3:-5] = 0 〜 6 の範囲で変化しています。
トレモロの深さは、トップとボトムの階段の振幅値から、

20 × log10(4084/3588) = 1.125 [dB]

となり、OPL4 (YMF278B) アプリケーション・マニュアルの記述 1 dB とほぼ一致します。
音源パラメタを

DAM = 1 (トレモロ「強」、4.8 dB)

という設定に変えたチャプチャ結果を下に示します。

波形が見やすいように縦軸のスケールを調整してあるので、DAM = 0 の場合と同じスケールではありません。
三角波が直線的ではなく曲がっているのは、「対数ドメイン」でリニアな三角波による変調がかかっているので、「真数ドメイン」のリニア値ではエクスポネンシャルな変化をしているためです。 DAM = 0 の場合には変化幅が小さく、曲がりが良く見えていませんでした。
トップとボトムの階段を除く中間部の階段は 25 段あります。
階段の幅を求めた結果を下に示します。

トップの階段の幅は 448 サンプル、ボトムの階段の幅は 192 サンプル、中間の 25 段の階段の幅はどれも同一で 256 サンプルとなっています。
1 周期では、

448 + (2 × 25 × 256) + 192 = 13440

となります。 当然ですが、DAM = 0 の場合と同じ結果です。

b-1 : -3 dB
b-2 : -1.5 dB
b-3 : -0.75 dB
b-4 : -0.375 dB
b-5 : -0.1875 dB

の 5 ビットのみが、b[-1:-5] = 0 〜 26 の範囲で変化しています。
トレモロの深さは、トップとボトムの階段の振幅値から、

20 × log10(4084/2326) = 4.890 [dB]

となり、OPL4 (YMF278B) アプリケーション・マニュアルの記述 4.8 dB とほぼ一致します。
DAM = 0 と DAM = 1 での階段の幅、

1984, 1216, 1024, 448, 256, 192

の最大公約数は 64 となりますから、サンプリング周波数 fs を 64 分周した fs/64 をクロックとした回路で AM LFO を実現できることになります。
カウント 0 からカウント 105 までを繰り返し往復する、周期 210 の 7 ビットのアップダウン・カウンタで実現できることが分かりました。
まず、DAM = 0 の場合を下に示します。

トップの階段は 1984 サンプル幅で、fs/64 クロックでは 1984/64 = 31 クロック幅となります。 31 = 15 + 1 + 15 ですから、カウント・ゼロを中央に置き、

15, 14, ... , 2, 1, 0, 1, 2, ... , 14, 15

と配置すれば、カウンタの b[6:4] = 0 を維持したまま 31 クロック幅におさまります。
ボトムの階段は 1216 サンプル幅で、fs/64 クロックでは 1216/64 = 19 クロック幅となります。 19 = 9 + 1 + 9 ですから、カウント 105 を中央に置き、

96, 97, ... , 103, 104, 105, 104, 103, ... , 97, 96

と配置すれば、カウンタの b[6:4] = 6 を維持したまま 19 クロック幅におさまります。
中間部の 1024 クロック幅についても、1024/64 = 16 ですから、16 クロックごとに b4 以上がインクリメント/デクリメントされ、うまく当てはまります。
結局、DAM = 0 ではカウンタ b[6:0] の上位 3 ビット b[6:4] を AM LFO 出力として取り出すことになります。
次に、DAM = 1 の場合を下に示します。

トップの階段は 448 サンプル幅で、fs/64 クロックでは 448/64 = 7 クロック幅となります。 7 = 3 + 1 + 3 ですから、カウント・ゼロを中央に置き、

3, 2, 1, 0, 1, 2, 3

と配置すれば、カウンタの b[6:2] = 0 を維持したまま 7 クロック幅におさまります。
ボトムの階段は 192 サンプル幅で、fs/64 クロックでは 192/64 = 3 クロック幅となります。 3 = 1 + 1 + 1 ですから、カウント 105 を中央に置き、

104, 105, 104

と配置すれば、カウンタの b[6:2] = 26 を維持したまま 3 クロック幅におさまります。
中間部の 256 クロック幅についても、256/64 = 4 ですから、4 クロックごとに b2 以上がインクリメント/デクリメントされ、うまく当てはまります。
結局、DAM = 1 ではカウンタ b[6:0] の上位 5 ビット b[6:2] を AM LFO 出力として取り出すことになります。
この考え方で書いたプログラムによる出力を下に示します。

青い線が DAM = 0 の場合、赤い線が DAM = 1 の場合です。 同じスケールでプロットしているので、DAM の違いによる減衰量の違いが良く分かります。
実チップのキャプチャ結果と一致しています。