Teensy4はデシメーションの必要がないくらい処理性能が高いが,ESP32-S3はTeensy4に比べて非力なので,デシメーションが必要となるケースが多いかもしれない.
ライブラリには Decimation FIR filter が用意されているので試してみた.デシメーションフィルタは普通のFIRフィルタに比べ,同じタップ数でもダウンサンプル比をNとすれば,ポリフェーズ分解によってフィルタ処理自体も理想的には1/Nになる.またサンプリング周波数も以降は1/Nとなるのであとの処理も軽くなる.
以下のコードを実行させて,ダウンサンプル比4のデシメーションフィルタと通常のFIRフィルタの処理時間と入出力信号を確認した.タップ数はいずれも1024.
#include <esp_dsp.h> #define BLOCK_SAMPLES 64 #define Ndec 1024 fir_f32_t fir_dec; float coeffs_fir_dec[Ndec]; float z_fir_dec[Ndec]; void setup(void) { Serial.begin(115200); delay(50); digitalWrite(48, LOW); pinMode(48, OUTPUT); digitalWrite(48, LOW); float si[BLOCK_SAMPLES]; // Input signal float so[BLOCK_SAMPLES]; // Output of FIR float sod[BLOCK_SAMPLES]; // Output of Decimation FIR // 入力信号(SIN波) for(int i; i<BLOCK_SAMPLES; i++){ si[i] = sin(2.0f*2.0f*M_PI*(float)i/BLOCK_SAMPLES); } // FIR 係数(入力を2倍にするフィルタ) dsps_d_gen_f32(coeffs_fir_dec, Ndec, 0); coeffs_fir_dec[0] =2.0f; // fir_dec をデシメーションフィルタとして初期化 //(ダウンサンプル比4) dsps_fird_init_f32(&fir_dec, coeffs_fir_dec, z_fir_dec, Ndec, 4, 0); digitalWrite(48, HIGH); dsps_fird_f32(&fir_dec, si, sod, BLOCK_SAMPLES); digitalWrite(48, LOW); // fir_dec を通常のFIRフィルタとして初期化 dsps_fir_init_f32(&fir_dec, coeffs_fir_dec, z_fir_dec, Ndec); digitalWrite(48, HIGH); dsps_fir_f32(&fir_dec, si, so, BLOCK_SAMPLES); digitalWrite(48, LOW); for(int i; i<BLOCK_SAMPLES; i++){ Serial.printf("%f %f %f;\n",si[i], so[i], sod[i] ); } } void loop(void) { }
実行時間は下図のとおり,デシメーションフィルタは通常のフィルタに比べおよそ1/3の処理時間になった.1/4でないのはオーバーヘッドなどを考えれば当然かと思うが,デシメーションFIRフィルタによってダウンサンプルを同時に行えば,処理時間をかなり減らすことができそう.もちろん信号帯域は狭くなるが.

入出力信号は下図のようになった.サンプル数が64 から1/4 の16に減少しているのがわかる(17個目以降はゴミ).フィルタ処理としては通常のFIRと同じ処理が行われている(2倍).
