FFT on arbitrary data source

Status
Not open for further replies.

mdion

Member
I'd like to take advantage of the speed of the FFT functionality of the audio library, but with data I "manually" input. By "manually" I mean I already have a 1024 data point buffer, and I don't know where to put it, so to speak.

I see in the Audio Library examples, an AudioConnection object is used to route data into the AudioAnalyzeFFT1024 object. Then I assume the FFT is scheduled to occur somewhere in the background? I've looked through some of the source code, but I'm unable to find where methods like "arm_cfft_radix4_q15" are. Should I just use the "copy_to_fft_buffer" method? When is "AudioAnalyzeFFT1024::update(void)" called?
 
To do an FFT using the arm_math library, you need to first initialize an fft instance ("fft_inst") to hold all of the twiddle factors and data structures. Once it is initialized, then you can call the FFT routine itself. Your Arduino/Teensy code would look something like this:

Code:
#include <arm_math.h>
#define N_FFT 256
arm_cfft_radix4_instance_f32 fft_inst;
uint8_t ifftFlag = 0; // 0 is FFT, 1 is IFFT
uint8_t doBitReverse = 1;
void setup() {

    arm_cfft_radix4_init_f32(&fft_inst, N_FFT, ifftFlag, doBitReverse); //init FFT

}


//allocate arrays to hold your data and your fft results
int buffer_mydata[N_FFT];      //this is where you'd normally accumulate your data for the FFT
int buffer_complex[N_FFT*2]; //then you'll copy it here in complex form to do the FFT

//here's your arduino loop function
void loop() {

   //gather your (real) time-domain data here...I'm showing analogRead() just as one
   //way that someone might get some data samples that they want to analyze
   for (int i=0; i<N_FFT; i++) {
       buffer_mydata[i]= analogRead(A0); //get a value
       delay(5);  //wait 5 msec to get a sample rate of ~200 Hz
   }

   //after you've gotten your vector of data, now you need to put it into 
   //complex-valued form, as that is what the FFT routines expect
   for (int i=0; i <= N_FFT; i++) {
       buffer_complex[2*i] = buffer_mydata[i]; //real part
       buffer_complex[2*i+1] = 0;   //imaginary part
   }


  //now you can call your fft
  arm_cfft_radix4_f32(&fft_inst, buffer_complex); //output is in buffer_complex

  //finally, print your results
  for (int i=0; i <= N_FFT; i++) {
      Serial.print(i); Serial.print(" "); //fft bin number
      Serial.print(buffer_complex[2*i];  Serial.print(" "); //real part
      Serial.print(buffer_complex[2*i+1];  Serial.println(); //imaginary part
   }

}

Note all of the extra work needed to put your vector of samples into complex-valued form. You probably also want to apply a windowing function to your data, but the code above might already have too many complications for new eyes.

Chip
 
Last edited:
Yes, simplest to just use the arm math library directly.

On the audio library question, there's a requirement to have at least one object with "update responsibility". All the input and output objects, except USB, implement update responsibility. The non-hardware object which merely process data can't cause the library to actually update. If you don't have at least one with update responsibility, the whole thing just sits there and never actually runs.
 
Status
Not open for further replies.
Back
Top