How to invert FFT in Arduino

I am trying to filter some data based on the following code using Arduino FFT library for FFT (Fast Fourier Transform)

/*
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]);
   }    
  }
}

      

After applying the filter:

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

      

Then I need to invert the FFT data fft_log_out[]

.

I've searched for the inverse FFT function (specifically at http://wiki.openmusiclabs.com/wiki/FFTFunctions ) but can't find it anywhere.

So how can I get a reverse FFT in Arduino?

+3


source to share


1 answer


The inverse FFT can be obtained using the forward transform:

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.

      

Note, however, that your filtering code has several problems.

First, the results of the forward FFT are complex numbers that provide information about magnitude and phase. The use fft_mag_log

only accepts a value that by itself is insufficient to restore the original signal. Thus, you have to use the full FFT pin left in the array fft_input

as input to your filtering code.



Second, the FFT of real data leads to a spectrum with Hermitian symmetry. To get a reliable filtered result, you must maintain this symmetry. Thus, you should not completely zero out the values ​​in the upper half of the spectrum:

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;
  }
}

      

Third, filtering will be applied to each block of data independently of each other, always assuming previous inputs were zeros. This usually leads to rupture at block boundaries. To avoid this, you should use the overlap-add method .

+3


source







All Articles