dsPIC33FJ64GP802 (10) --- DSP 命令と DSP ライブラリ (8)

 「楽音」の「音名」でいうと「A」(880 Hz)と、「A#」(932.33 Hz) を中心周波数とする 1/12 オクターブ・バンド・フィルタふたつを IIRTransposed() 関数で実現し、内部で発生させたリニア周波数スイープのサイン波をフィルタリングした結果を下に示します。
 フィルタ係数は 12 kHz サンプリングで中央周波数 880 Hz と 932.33 Hz になる値を求めており、実際にはサンプリング周波数 48 kHz で動作させているので、中心周波数はそれぞれ 4 倍の、3.52 kHz と 3.729 Hz になっています。

続きを読む

dsPIC33FJ64GP802 (9) --- DSP 命令と DSP ライブラリ (7)

 IIRTransposed() での処理の様子と伝達関数の表現との対応を、2 次セクション 1 段の場合について下に示します。
 「標準型」の構成を「転置」、つまり信号の向きを反対に (出力を入力に、入力を出力に)、「分岐」を「加算」に、「加算」を「分岐」に置き換えて得られる構成です。 (最初はフィルタ係数の 0.5 倍スケーリングはない「基本型」を転置し、後からフィルタ係数のスケーリングにともなう変更を加えたものです)
 転置型では、まず伝達関数の分子側の計算を先に行い、伝達関数の分母側の計算を後に行います。

続きを読む

dsPIC33FJ64GP802 (8) --- DSP 命令と DSP ライブラリ (6)

 IIRCanonicStruct 構造体 (IIRTransposedStruct 構造体も同様) の「numSectionsLess1」 フィールドには、2 次セクションの段数を「S」としたとき、(S - 1) の値を設定します。 前回の 2 次セクション 1 段の場合には、(S - 1) = (1 - 1) = 0 を設定します。
 2 次セクションを 2 段とした場合の図を下に示します。 numSectionsLess1 は「1」となります。

続きを読む

dsPIC33FJ64GP802 (7) --- DSP 命令と DSP ライブラリ (5)

 DSP ライブラリのドキュメントでは、IIR (Infinite Impulse Response) フィルタ係数は「dsPIC Filter Design」(略称: dsPICFD) プログラム (有償) によって生成されたもの (あるいはそれに等価なもの) を使うように指示されていて、係数値の取るべき詳細な条件については明記されていません。
 IIR フィルタの構成については、色々なバリエーションがあり、その定義によっては符号が反対になったり、設計プログラムで求まった数値をスケーリングする必要があったりします。
 一方、FIR (Finite Impulse Response) フィルタのタップ係数はフィルタのインパルス応答そのものであり、意味が自明なので、他のフィルタ設計プログラムの出力の流用も容易です。

続きを読む

dsPIC33FJ64GP802 (6) --- DSP 命令と DSP ライブラリ (4)

 DSP ライブラリ中の (補間/間引き/格子型/適応型などを除く「普通」の) FIR 関係の関数には次の 3 つがあります。

void FIRStructInit (
  FIRStruct*  filter,
  int         numCoeffs,
  fractional* coeffsBase,
  int         coeffsPage,
  fractional* delayBase
);
void FIRDelayInit (
   FIRStruct* filter
);
fractional* FIR (
   int         numSamps,
   fractional* dstSamps,
   fractional* srcSamps,
   FIRStruct*  filter
);
続きを読む

dsPIC33FJ64GP802 (5) --- DSP 命令と DSP ライブラリ (3)

DSP ライブラリの FIR() 関数を使う前に、下のようなデータを用意しておく必要があります。

  • 入力データが格納された配列 (要素数 N)
  • 出力データを受け取るための配列 (要素数 N)
  • タップ係数の配列 (要素数 M,、X-データ・メモリあるいはプログラム・メモリ、アライメント制限あり)
  • 遅延要素の配列 (要素数 M、Y-データ・メモリ、アライメント制限あり)
  • FIRStruct

 DSP ライブラリのドキュメントによると、FIR フィルタのタップ長を M、入出力サンプル数を N とすると、FIR() 関数の実行に必要なサイクル数は、C 言語での関数呼び出し/リターンのオーバーヘッドを含めて、

(タップ係数が X-データ・メモリ上にある場合)
61 + N*(4 + M)


(タップ係数がプログラム・メモリ上にある場合)
68 + N*(9 + M)

となっています。

続きを読む

dsPIC33FJ64GP802 (4) --- DSP 命令と DSP ライブラリ (2)

 DSP ライブラリに含まれる関数をカテゴリ別に分類すると下のようになります。

  • ベクトル演算
  • 窓関数の初期化
  • 行列演算
  • フィルタ
  • FFT/DCT
  • PID 制御
  • 浮動小数点と固定小数点との相互変換
  • スタック・ガードの設定 (dsPIC33E のみ)

 これらのカテゴリ分けは、ライブラリのソース・ファイルの構成を反映しているだけで、ライブラリのオブジェクトおよびヘッダ・ファイル中ではすべての関数がフラットに定義されています。
 この中で、フィルタのカテゴリの中を見ると、

  • FIR() — FIR フィルタ
  • FIRDecimate() — FIR + ダウン・サンプル
  • FIRInterpolate() — アップ・サンプル + FIR
  • FIRLattice() — 格子型 FIR フィルタ
  • FIRLMS() — 適応 FIR フィルタ (最小二乗アルゴリズム)
  • IIRCanonic() — IIR フィルタ (標準型)
  • IIRTransposed() — IIR フィルタ (転置型)
  • IIRLattice() — 格子型 IIR フィルタ

などの関数が定義されています。
 残念ながら、現状では、C 言語で適当に書き散らかしたプログラムを C コンパイラがいい感じに DSP 命令を使ったオブジェクトに変換してくれるようにはなっていないので、DSP 命令を活かしたプログラムとするにはアセンブリ言語を使う必要があります。

続きを読む