新版FM音源プログラム (10)

FM 音源の「オペレータ」のフェーズ・ジェネレータ部、EG 部を除く、波形生成部分の計算量を見積もる作業をしています。
以下のような、波形テーブルのサイズの違う 3 種類のプロトタイプのプログラムを作ってみました。

  • 8 K (8 × 1024 = 8192) エントリのテーブル (16 K バイト)
  • 4 K (4 × 1024 = 4096) エントリのテーブル (8 K バイト)
  • 256 (1024 / 4 = 256) エントリのテーブル (512 バイト)

当然、テーブル・サイズの大きい方が処理時間が短く、同時発音数を多くできます。
オペレータ間の相互変調はなし、すべてのオペレータでフィードバック用の LPF 処理をすると言う条件で、STM32F4-Discovery (168 MHz Cortex-M4F) で実行させて、サンプリング周波数 48 kHz でのオペレータ数の限界を探ってみると、

テーブル・
エントリ数
オペレータ数 clk/OP
8 K 108 32
4 K 93 37
256 79 44

となりました。
OPL3 では 1 周期 1024 ポイントのサイン波テーブルを使用しますが、波形の対称性から、その 1/4 の 256 エントリまでテーブル・サイズの削減ができます。 ただし、WS (Wave Select) などの処理も含めると、プログラム上の処理が多くなり、処理時間がかかることになります。
以下に示すように、1 波形 1024 エントリのテーブルを、8 つ全ての WS に対して独立に持ち、全エントリ数 8192 となる方式では、テーブル・サイズは最大となりますが、処理時間は最小になります。
















両者の中間的なテーブル・サイズ、処理時間を持つ方法として、下に示すような 4 K エントリのウェーブ・テーブルを使用し、WS の値に応じてテーブルの「途中」からアクセスする方式を考えました。

テーブルの各エントリは、サイン・マグニチュード方式で値を書き込んでおきます。 つまり、1 ビットの符号ビット + 12 ビット・リニアの絶対値で値を示します。
たとえば、WS = 0 および WS = 2 では、テーブルの 0 〜 1023 までをアクセスし、WS = 2 の場合には「符号ビット」を落として、波形として正の値だけをとるようにします。
WS = 1 では、テーブルは 512 〜 1535 までをアクセスし、さらに符号ビットを落として扱います。
4K エントリのテーブルを stab_4K[] 配列として表現し、テーブル・インデクス (0 〜 1023) を変数 i で表現すると、WS = 1 に対しては、

   stab_4K[0x200 + i]

でアクセスすることになります。
同様にして、WS = 4 と WS = 5 では、

   stab_4K[0x800 + i]

でアクセスし、WS = 7 に対しては、

   stab_4K[0xC00 + i]

でアクセスします。
WS = 3 に対しては、(0x1FF & i) をテーブル・インデクスとして、0 〜 511 の範囲を 2 回アクセスします。

   stab_4K[0x600 + (0x1FF & i)]

WS = 6 に対しては、10 ビットのインデクスの MSB のみを (0x200 & i) で取り出し、インデクスとしては、0、512 の 2 値のみにします。

   stab_4K[0x100 + (0x200 & i)]

実効インデクスとしては 256 および 768 となり、これは stab_4K[] 配列の最初のサイン波の正側、負側のピークの位置に相当します。
4 K エントリ方式では、1 オペレータあたりの実行クロック数は 8 K エントリ方式と比べて 5 クロック多く、256 エントリ方式と比べて 9 クロック少なくなっています。
8 K エントリ方式ではテーブル・サイズが 16 K バイトになるので、フラッシュ・サイズが 32 K バイトの Cortex-M0 マイコンなどでは使用が難しいのですが、4 K エントリ方式ではテーブル・サイズが 8 K バイトになるので、実現の可能性は大きくなります。