FIRフィルタを固定小数点化してみる
「FIRのフレーム処理」 では、FIRフィルタのフレーム化(実装)を紹介しましたが、今回は組み込み向けの話しをしたいと思います。
信号処理の組み込みと言えば、まずはDSP*1を思いつきますが、 RISC CPUによるSIMD*2やVLIW*3のように、並列処理により信号処理が高速に行われる時代になりました。
そしてDSPにも高速なFPU*4を持ったものや、SIMDやVILWが使われる時代で、ハイスペックなDSPが登場し再度注目を集めていると思います。
固定小数点DSP
ハイスペックなDSPならば開発は楽ですが、製品の価格競争を考えると、
組み込みの分野では固定小数点DSPという選択肢がまだ残っているのが現状だと思います。特に音の分野では低遅延が求められると、処理の順番(依存関係)を解消するのが難しく、並列処理をしたくてもアルゴリズム的に限界があります。また、音声のデータに関しても16bitのリニアPCMとして固定小数点で扱う場合が多いです。
組み込み向けのリファレンスコード(デジタル信号処理向けのリファレンスコード)
信号処理の組み込み分野では、デバイスに搭載されるプロセッサーのインストラクションアーキテクチャに適したソフトウェアが求められ、CPUのリソースとソフトウェアの品質のトレードオフになります。そして固定小数点DSPの場合、固定小数点化したリファレンスコードを作成し評価した後、リファレンスコードと同等な性能を維持するようにポーティングを進める方法が多く、特に固定小数点ではリファレンスに対しBitExactが一つの手法になっています。
basic_op (固定小数点DSP向けの命令関数)
basic_opと聞いてピンとくる方には説明は不要ですが、 固定小数点DSPへの組み込みを目的としたリファレンスコードでは、DSPの命令に対応した演算がC言語の関数の形で用意されている場合が多いです。代表的なものでは、ETSI*5という団体で用意されているbasic_opです。これは3GPPのWebサイトなどから入手可能です(3GPP)。
また、WindowsやLinuxでbasic_opを利用して固定小数点のソースコードを書くことにより、PCで評価が可能になります。そして、一番ありがたいことは、DSPメーカがbasic_opをIntrinsic(組み込み関数)としてサポートしていることです(サポートしている場合が多いです)。例えば、定番だったTI社(Texas Instruments)の、C55xシリーズでは、CCS*6で「gsm.h」としてサポートされインクルードすることで、PCで開発したbasic_opのコードがそのままポーティングできます。
FIRフィルタの固定小数点化
今回は、basic_opを使用して、FIRフィルタを固定小数点化してみました。具体的には畳み込みの部分になります。 浮動小数点のソースコードはこちら( 「FIRのフレーム処理」)。
サンプルコード【C言語】
#define FIR_TAP 15 // 目的に合わせて調整する (今回は15で試してみます)
#include "typedef.h" // basic_op固定小数点用ヘッダファイル #include "basic_op.h" // basic_op固定小数点用ヘッダファイル // FIRフィルタ固定小数点化(フレーム処理) void fir_frame_int16(Word16* coef, Word16 *mem, int n, Word16 *in, Word16 *out) { int flen; Word32 L_sum; Word16 *buff; Word16 *p_coef; Word16 *p_buff; // buff update memcpy(mem, &mem[n], sizeof(short)*(FIR_TAP - 1)); memcpy(&mem[FIR_TAP - 1], in, sizeof(short)*n); // convolution buff = &mem[FIR_TAP - 1]; while (n--) { L_sum = 0; p_coef = coef; p_buff = buff++; flen = FIR_TAP; while (flen--) { // sum += *p_coef++ * *p_buff--; L_sum = L_mac(L_sum, *p_coef++, *p_buff--); // 固定小数点化(basic_op) } *out++ = round(L_sum); // 固定小数点化(basic_op) } }
フィルタ係数はこちら FIRフィルタを作って周波数特性を検証