FPGA 版 FM 音源 (39) -- YMF297 (OPN3/OPL3) 測定 (4)

YMF297 を OPL3 モードで動作させると、1 オーディオ・フレームあたりのビット・クロック数が 68 に変化するので、DAC 出力のサンプリング周波数を 48 kHz に保つためには、YMF297 に供給するマスタークロック自体の周波数を変化させなければなりません。
その値は、
48 [kHz] × 68 × 5 = 16.32 [MHz]
となります。
2014 年 7 月 24 日付けの記事 (→こちら) で示した Nucleo F401RE 用の構成では、システム PLL の分周比 N = (5 × 61) = 305 を N = (5 × 68) = 340 に変更するだけで、必要な 16.32 MHz を発生させることができます。
このとき、CPU クロックおよびバス・クロックの周波数は 65.28 MHz になります。
YMF297 の OPL3 モードでは LR クロックのデューティーは 50 % ぴったりになりますから、OPNA モードの場合と違って、BU9480F を使った場合でも歪み率は悪化しません。
OPNA モードの場合と同じ 750 Hz 正弦波出力を WaveSpectra で測定した結果を下に示します。

OPNA モードの場合は 4 パラレル・キャリア、OPL3 モードの場合は 2 パラレル・キャリアという違いにより、OPL3 モードでは録音ゲインを上げている以外の条件は、OPNA/OPL3 両者ともほぼ同一です。
歪み率は約 0.05 % で、正弦波自体の歪み率とほぼ同一で、悪化はしていません。
YMF297 の OPL3 モードでも「ビット・パーフェクト」なデータがキャプチャできるようになったので、「本家 OPL3」の YMF262 の測定の時から気になっていたことを確かめてみました。
それは、

  • オペレータが「有効」で、
  • 出力は正負に振れる波形で、
  • エンベロープが十分に減衰して振幅がほぼゼロになるべき状態で、
  • 出力値は「0」と「-1」の間を振動し、いつまでもゼロには収束しない

現象です。
波形をキャプチャしたものを下に示します。

減衰波形で振幅が減少していき、最後に 0 と -1 の間を振動する形となっていますが、それ以降、いくら時間が経過しても完全な「ゼロ」には収束しません。
これは、おそらく、波形の「負」の表現に「1 の補数」を使用していて、「ゼロ」の表現に「+0」(プラス・ゼロ) と「-0」(マイナス・ゼロ) との 2 種類があるためだと思われます。
OPN と OPM では 2 の補数表現を使っていると思われ、最終的にはゼロに収束します。
0x0000 が「+0」、0xFFFF が「-0」で、2 の補数表示として見れば 0 と -1 ですが、1 の補数では、どちらも「ゼロ」ということになります。
FM オペレータでは、LFO による AM やエンベロープの振幅と波形テーブル出力との間で「乗算」が必要ですが、実際には「log magnitude」として扱って、対数ドメインでの「加算」で処理していると思われます。
AM やキー・スケーリング、エンベロープ等の計算では「log magnitude」値のみが使われますが、波形テーブルの参照の時点で、これに「符号」が付け加わります。
本当に「ゼロ」の真数に対しては、対数はマイナス無限大となり表現できないので、十分に小さいが真にゼロではない数で代用します。
OPL3 の場合は -96 dB がその値となります。 計算の途中で -96 dB より小さい振幅になっても、-96 dB に置き換えます。
一方、対数-リニア値変換テーブルのリニア値出力の有効ビット幅は 11 ビットであり、-96 dB では変換回路で 15 ビット右シフトされ、結果としてゼロ (0x0000) に「アンダーフロー」します。
波形出力としては、この結果に符号を作用させ、「負」の場合には 1 の補数 (各ビットごとの反転) を取って0xFFFF になります。
リニアの絶対値としては「ゼロ」になっており、これ以上減衰することはありません。 
2 の補数表現にすれば、マイナス・ゼロも 0x0000 になって「無音」になりますが、1 の補数表現では振幅 0.5 の振動が残ります。
2 の補数を計算するには、1 の補数を取ったあとに +1 する必要があるので、この加算器の部分をケチったのかも知れません。
1 オペレータあたり 1 LSB(p-p) の振動ですから大したことはありませんが、全 36 オペレータが並列にキャリアとして作用すると無視できない値になります。
36 パラレル・キャリア出力の場合の波形を下に示します。

DC オフセットとして
-0.5 [LSB] × 36 = -18 [LSB]
になっているのが波形から読み取れます。
理論的なピーク・ツー・ピーク値は 36 LSB となります。
実際の音としてはあまり問題がなくても、「ビット・パーフェクト」にオペレータ出力をキャプチャし 1 ビット単位の値を追求する場合には、目的のオペレータ以外のオペレータ群からこのような「ノイズ」が出てくるのは邪魔になります。
観測対象外のオペレータからの寄与を停止するには、次のような方法があります。

  1. CHL/CHR ビットを 0 にしてオーディオ出力値の計算から除外する
  2. FNUMBER を 0 にして「発振」を停止させる
  3. WS (Wave Select) に正方向にしか振れない波形の値を設定する (WS=1,2,3,5)

1. は、出力値の計算から除外する方法で、当然そのキャリア・オペレータからの寄与はなくなります。
2. は、フェーズ・アキュムレータの増分 (位相増加分) をゼロにして、発振波形ではなく DC レベルのみを出力させる方法で、一定レベルを維持するので、DC オフセット分以外の寄与はなくなります。
3. は、正負に振れない波形を選択するもので符号は常に正となりますから、オペレータ出力が十分に減衰していれば、その値は 0x0000 のままで変化しなくなります。
1. の CHL/CHR ビットの操作による方法の結果を下に示します。

全 18 チャネル分の操作を同時に行うことは不可能なので、18 チャネルを順次オフにしています。
徐々に DC オフセット (の絶対値) および振幅が減少し、最終的に全オペレータの寄与がなくなり、値がゼロになっていることが分かります。