dsPIC33FJ64GP802 (11) --- DSP 命令と DSP ライブラリ (9)
IIRCanonic() 関数と IIRTransposed() 関数を使ったプログラムの断片を下に示します。 フィルタ係数の配列の詳細は 2018 年 10 月 10 日付けの記事 (→こちら) に記載しています。
WaveSpectra による特性測定のために使ったプログラムでは、ふたつの 1/12 オクターブバンド・フィルタの両方とも IIRTransposed() で実現していますが、以下に示すプログラムでは 880 Hz は IIRCanonic()、932.33 Hz は IIRTransposed() を使っています。
#include <xc.h> #include <stdint.h> #include <dsp.h> . . . . . . <中略> . . . . . . #define N_sample (4) #define N_sect (3) . . . . . . <中略> . . . . . . // delay element in Y-DATA memory // for IIRCanonic() fractional _YBSS(2) d_880[2*N_sect]; // for IIRTransposed() fractional _YBSS(2) d1_932[N_sect]; fractional _YBSS(2) d2_932[N_sect]; . . . . . . <中略> . . . . . . // 1/12 octave band filter coeffs for IIRCanonic() // center freq. = 880 Hz @ fs = 12 kHz fractional _XDATA(2) IIRC_coef_880[] = { // 内容は 2018 年 10 年 10 日付けの記事に記載 }; // fractional IIRC_coef_880[]] // 1/12 octave band filter coeffs for IIRTransposed() // center freq. = 932.328 Hz (A#) @ fs = 12 kHz // exported from Filter component of PSoC Creator fractional _XDATA(2) IIRT_coef_932[] = { // 内容は 2018 年 10 年 10 日付けの記事に記載 }; // fractional IIRT_coef_932[]] . . . . . . <中略> . . . . . . IIRCanonicStruct IIRC_prof_880; IIRTransposedStruct IIRT_prof_932; fractional src_data[N_sample]; fractional dstL_data[N_sample]; fractional dstR_data[N_sample]; . . . . . . <中略> . . . . . . int main(int argc, char** argv) { . . . . . . <中略> . . . . . . // initialize IIRCanonic profile for f0 = 880 Hz IIRC_prof_880.numSectionsLess1 = N_sect-1; IIRC_prof_880.coeffsBase = &IIRC_coef_880[0]; IIRC_prof_880.coeffsPage = COEFFS_IN_DATA; IIRC_prof_880.delayBase = &d_880[0]; // pick up scaling factors IIRC_prof_880.initialGain = IIRC_coef_880[5*N_sect]; IIRC_prof_880.finalShift = IIRC_coef_880[5*N_sect+1]; // initialize IIRTransposed profile for f0 = 932.33 Hz IIRT_prof_932.numSectionsLess1 = N_sect-1; IIRT_prof_932.coeffsBase = &IIRT_coef_932[0]; IIRT_prof_932.coeffsPage = COEFFS_IN_DATA; IIRT_prof_932.delayBase1 = &d1_932[0]; IIRT_prof_932.delayBase2 = &d2_932[0]; IIRT_prof_932.finalShift = 0; // zero-clear delay element IIRCanonicInit(&IIRC_prof_880); IIRTransposedInit(&IIRT_prof_932); . . . . . . <中略> . . . . . . while (1) { // infinite loop . . . . . . <中略> . . . . . . IIRCanonic(N_sample, // numSamps &dstL_data[0], // output samples (L-ch) &src_data[0], // input samples (sweep sine) &IIRC_prof_880 // filter profile (880 Hz) ); IIRTransposed(N_sample, // numSamps &dstR_data[0], // output samples (R-ch) &src_data[0], // input samples (sweep sine) &IIRT_prof_932 // filter profile (932 Hz) ); . . . . . . <中略> . . . . . . } // while (1) { } // int main()
IIRCanonic() のスケーリング係数「initialGain」と「finalShift」の値はフィルタ係数の配列の末尾に格納しておき、IIRCanonicStruct 構造体の初期化の際に配列から拾い上げて対応するフィールドに設定しています。
フィルタの入出力ベクトルのサイズ (N_sample) は 、内蔵ステレオ・オーディオ DAC の FIFO サイズ (4 ワード) に合わせて (N_sample = 4) と選んでいます。
上のプログラムの断片では省略していますが、DAC の FIFO が「空」であることを確認すると、4 ワード分のデータを連続して書き込んでいます。