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

4 月 16 日付けの記事の構成をソフトウェアで実現した C プログラムの断片を下に示します。

  #define N1 57
  #define N2 64

  int32_t z[2] = {0, 0};
  int32_t acc[2] = {0, 0};
  int32_t new_sample;
  int32_t sum;
  int     i,  k;
 
  k = 0;
  while (1) {
    new_sample = calc_sample();      
    for (i = 0; i < N1; i++) {
      if (N2 <= (++k)) { // time to output
        k = 0;
        sum = (acc[0] + acc[1]); // add NEW and OLD
        sum >>= 6; // scaling
        output_sample(sum);	  
      } // if (N2 <= (++k)) { ...
      if ((N1 - 1) == i) { // data load timing
        acc[1] = (acc[0] + z[0]); // (N1 * OLD)
        acc[0] = 0;               // start from ZERO
        z[1]   = z[0]; // now NEW becomes OLD
        z[0]   = new_sample; // new sample arrival
      } else { // normal accumulation
        acc[1] -= z[1]; // decrement OLD samples
        acc[0] += z[0]; // increment NEW samples
      } // if ((N1 - 1) == i) {} else { ...
    } // for (i = 0; ...
  } // while (1) { ...

calc_sample() 関数の実行により 49.5158 kHz サンプリングでの新しいサンプルが得られるものとし、output_sample() 関数の実行により 44.1 kHz サンプリングでのサンプル出力が行われるものとします。
入力サンプルとして 16 ビット・フルスケール (-32767 〜 32767) の約 1 kHz の正弦波を発生させ、上のプログラムの実行で得られた出力サンプルとを合わせて一枚の図にプロットしたものを下に示します。

青いトレースが 49.5158 kHz サンプリングの入力サンプルで、赤いトレースが 44.1 kHz サンプリングの出力サンプルです。
横軸は「サンプル・インデクス」で並べてありますから、サンプリング周波数変換により、見かけ上、正弦波の周波数が変わっているように見えています。
出力サンプルの振幅も約 1 dB 減少しており、正確な値で言えば、

32767 * (57 / 64 ) = 29183.1

となり、±30000 を切る振幅となっています。
入力サンプルとして使用している 49.5158 kHz のレートで発生させた約 1 kHz のフルスケール正弦波を wave ファイル化し、WaveSpectra で観察したスクリーン・ショットを下に示します。

後で示す出力サンプルとのレベル比較のため、FFT の窓関数として「フラット・トップ窓」を使用しています。
フルスケール正弦波ということで、ピーク・レベル表示が 0 dB になるように表示のオフセットを調節してあります。
高調波のレベルはいずれも -100 dB 以下となっています。
上に示した、直線補間によるサンプリング周波数変換プログラムの出力サンプルを wave ファイル化し、WaveSpectra で観察したスクリーン・ショットを下に示します。

正弦波のピーク・レベルが約 1 dB 低下していることが分かります。
窓関数をフラット・トップではない他の窓に変えると、窓関数の影響で、たとえば -1.5 dB のような、より大きなレベル低下が表示されます。
約 1 kHz の正弦波の線スペクトラムの周りに見られるサイドローブは、フラット・トップ窓の特性によるもので、そこにスペクトル成分があるわけではなく、見かけ上のものです。
厳密なフィルタではなく、線形補間を使用しているために抑圧しきれないエイリアス成分が、周波数約 4 kHz 以上、レベル約 -70 dB 以下の部分に林立している線スペクトラムとなって見えています。