FPGA 版 FM 音源 (28) -- 49 kHz → 44.1 kHz サンプリング・レート・コンバータ (1)

YMF262 (OPL3) などの、マスタークロックに NTSC 色副搬送波周波数 (の 4 倍) の 14.31818 MHz を使う FM 音源チップ (以降「14 MHz 系 OPL3」と略記) では出力サンプリング周波数はマスタークロックの 1/288 の

14.31813 [MHz] / 288 = 49.7159 [kHz]

になっています。
一方、44.1 kHz 系のディジタル・オーディオ用クロック

33.8688 [MHz] = 768 × 44.1 [kHz]

をマスタークロックとして使う YMF715 (OPL3-SA)、YMF289 (OPL3-L)、YMF278 (OPL4) など (以降「33 MHz 系 OPL3」と略記) では、出力サンプリング周波数はマスタークロックの 1/684 の

33.8688 [MHz] / 684 = 49.5158 [kHz]

となっています。
さらに、 YMF289 (OPL3-L)、YMF278 (OPL4) などでは、44.1 kHz サンプリングのシリアル DAC に出力するディジタル・インターフェースも備えています。
そのために、線形補間による 49.5158 kHz から 44.1 kHz へのサンプリング・レート・コンバータ (SRC) が含まれています。
これまで、漠然と SRC 回路はかなり複雑なのではないかと思っていましたが、検討してみると、それほど複雑でもないことが分かりました。
まず、サンプリング周波数の比は、

49.5158 [kHz] = 33.8688 [MHz] / 684
        = 33.8688 [MHz] / (22 × 32 × 19)


44.1 [kHz] = 33.8688 [MHz] / 768
        = 33.8688 [MHz] / (28 × 3)


49.5158 [kHz] : 44.1 [kHz] = 64 : 57

となり、「64」と「57」という、むやみに大きくはない数の比になっています。
サンプリング周波数変換を形式的に書くと、下の図のようになります。

fs = 49.5158 kHz の入力サンプルの隣接サンプル間に 56 個の「ゼロ」を補って 57 倍のレートの 2.8224 MHzにアップ・サンプリングし、そのサンプリング・レートで動作する LPF によってエイリアスを除去し、1/64 にダウン・サンプリング (デシメート) して 44.1 kHz サンプリングの信号にします。
この LPF が FIR (有限インパルス応答) であれば、2.8224 MHz レートでの信号を記憶しておく必要はなく、ダウン・サンプリングのタイミングで必要とされる計算だけを行えばすみます。
「線形補間」であれば、fs = 49.5158 kHz のサンプル 2 つと、線形補間フィルタ係数 2 つとの間の乗算 2 回と加算 1 回で fs = 44.1 kHz でのサンプルひとつが求まります。
この処理のブロック・ダイアグラムを下に示します。
OPL3 では出力を A,B,C,D の 4 つのチャネルに出力可能ですが、下の図はその 1 チャネル分だけを示しています。

破線より下の部分は 64fs のシリアル DAC とのインターフェース回路で、実際のチップでは 48fs に対する回路となっていますが、それは後で示します。
48fs に対する回路では SRC クロック部分が少し分かりにくくなります。
右上の破線で囲った部分が線形補間のための積和演算のブロックで、44.1 kHz のレートで演算を行います。
33.8688 MHz マスタークロックで数えると 44.1 kHz は 768 クロック分となりますから、乗算に「並列乗算器」を使う必要もなく、「シフト・アンド・アッド」の繰り返し演算による普通の乗算器で十分に実現することができます。
線形補間の係数発生回路は、2.8224 MHz のレートで、(以降の計算で使われるか否かに関わらず) 常に係数を発生させます。
その 2 つの係数は、下に示すような 57 個のシーケンスの繰り返しとなります。
新しい方のサンプルに対する係数 coef0 は、

0.0 = 0/57, 1/57, 2/57, ... , 55/57, 56/57

となり、49.5158 kHz レートでの次のサンプルの到着でアキュムレータをリセットし、2.8224 MHz クロックごとに 1/57 を足しこんで行くことで実現できます。
古い方のサンプルに対する係数 coef1 は、

1.0 = 57/57, 56/57, 55/57, ... , 2/57, 1/57

となり、49.5158 kHz レートでの次のサンプルの到着でアキュムレータに 1.0 をセットし、2.8224 MHz クロックごとに 1/57 を引いて行くことで実現できます。
あるいは、

coef1 = 1.0 - coef0
coef0 = 1.0 - coef1

の関係から、coef0、coef1 のどちらか一方だけを発生させ、もう一方は 1.0 から引くことでも求められます。
実際のチップのように、シリアル DAC インターフェースとして、 48 clk/frame にするには次のような構成で実現できます。

48fs クロックを得るために、この構成では 57 倍アップ・サンプリングと 1/64 ダウン・サンプリングとで共通の 2.8224 MHz クロックを使うのではなく、途中で分岐したクロックを使う形になります。