ESP32-S3 AF信号処理ボード(デシメーションフィルタ)

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倍).