如何在Arduino中反转FFT

时间:2015-05-30 09:27:04

标签: arduino fft ifft

我正在尝试使用Arduino FFT library进行FFT(快速傅里叶变换),根据以下代码过滤一些数据

/*
fft_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fft library.
it takes in data on ADC0 (Analog0) and processes them
with the fft. the data is sent out over the serial
port at 115.2kb.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft

#include <FFT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int

      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
     // Serial.print(millis());
     // Serial.print("input ");
     // Serial.print(i);
    //  Serial.print(" = ");
      Serial.println(k);
      fft_input[i+1] = 0; // set odd bins to 0
      delay(0.1);
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft
    sei();
    Serial.println("start");

   for (byte i = 0; i < FFT_N/2; i++) {
     if(i<10 || i>20)
     {
       fft_log_out[i] = 0;
     }

     Serial.println(fft_log_out[i]);
   }    
  }
}

应用这样的过滤器后:

if(i<10 || i>20)
     {
       fft_log_out[i] = 0;
     }

然后我需要反转FFT数据fft_log_out[]

我寻找逆FFT函数(特别是http://wiki.openmusiclabs.com/wiki/FFTFunctions),但无法在任何地方找到它。

那么如何在Arduino中获得逆FFT?

1 个答案:

答案 0 :(得分:3)

可以通过使用正向变换获得逆FFT:

for (int i = 0 ; i < 512 ; i += 2) {
  fft_input[i] =  (fft_input[i] >> 8);
  fft_input[i+1] = -(fft_input[i+1] >> 8);
}
fft_reorder();
fft_run();
// For complex data, you would then need to negate the imaginary part
// but we can skip this step since you have real data.

但请注意,您的过滤代码存在一些问题。

首先,正向FFT的结果是带有幅度和相位信息的复数。使用fft_mag_log只取大小,仅靠恢复原始信号是不够的。因此,您应该使用fft_input数组中剩余的完整FFT输出作为过滤代码的输入。

其次,实值数据的FFT导致具有厄米对称性的谱。要获得真正有价值的滤波输出,必须保持对称性。 因此,您不应该将频谱上半部分的值完全归零:

for (byte i = 0; i < FFT_N; i+=2) {
  if (! ((i>=20 && i<=40) || (i>=FFT_N-40 && i<=FFT_N-20)))
  {
    fft_input[i] = 0;
    fft_input[i+1] = 0;
  }
}

第三,过滤将彼此独立地应用于每个数据块,总是假设先前的输入为零。这通常导致块边界处的不连续性。为避免这种情况,您应该考虑使用overlap-add method