Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
FFT.cpp
- Committer:
- rik
- Date:
- 2017-03-29
- Revision:
- 1:099f1a4c5fc8
- Parent:
- 0:8c128e047ec9
File content as of revision 1:099f1a4c5fc8:
#include "FFT.h"
// Calculates and subtracts the signal mean
void subMean(float* data, int datalength){
float mean = 0;
float total = 0;
for (int i = 0; i < datalength; i++)
total += data[i]/datalength;
for (int i = 0; i < datalength; i++)
data[i] = data[i] - mean;
}
void reverseCooleyTukeyRadix2(float* data, complex_num* dataout, int datalength){
complex_num fftbuffer[256];
complex_num twiddlebuffer;
complex_num minusone;
minusone.real = -1;
minusone.imaginary = 0;
// copy iput to output first
for (int i = 0; i < datalength; i++){
dataout[i].real = data[i];
dataout[i].imaginary = 0;
}
for (int stage = 8; stage > -1; stage--){
unsigned int step = 1<<(stage+1);
for (unsigned int i = 0; i < 512; i = i+step){ // Crack it up in parts, i.e. for stage0 -> 512, stage1 -> 256 , 2>128, 3>64, 4>32, 5>16, 6>8, 7>4, 8>2, 9>1 --> 1024/2^stage OR IN STEPS: stage0 -> 2, stage1 -> 4, 2>8, 3>16, 4,32, 5>64, ......... 9>512 --> 1024 - 1024/2^stage+1
// Buffer the first 'half' of the thing, which is the first half step
for (unsigned int k = 0; k < step / 2; k++){
fftbuffer[k].real = dataout[i+k].real;
fftbuffer[k].imaginary = dataout[i+k].imaginary;
}
// Apply twiddle factors to the seconds half (half step) depending on stage and numbering
for (unsigned int k = 0; k < step / 2; k++){
// Read in the correct twiddle factor
// Twiddle factor is recalculated with k*(1024 / 2^stage+1) which can be recalculated to 1<<
twiddlebuffer.imaginary = twiddleLookupTable_Imaginary[k * (1<<(9-stage))];
twiddlebuffer.real = twiddleLookupTable_Real[k * (1 << (9 - stage))];
dataout[i + k + step / 2] = complex_multiply(dataout[i + k + step / 2], twiddlebuffer);
}
// Recalculate the first half by addition of the first and recalculated half
for (unsigned int k = 0; k < step / 2; k++)
dataout[i + k] = complex_add(dataout[i+k], dataout[i+k+step/2]);
// Multiply the second half with minus 1
for (unsigned int k = 0; k < step / 2; k++)
dataout[i + step / 2 + k] = complex_multiply(dataout[i + step/2+k], minusone);
// Add the buffered old values, with the new second half values
for (unsigned int k = 0; k < step / 2; k++)
dataout[i + step / 2 + k] = complex_add(dataout[i + step/2 + k], fftbuffer[k]);
}
}
}
void cooleyTukeyBack (float* dataout, complex_num* datain, int datalength){
complex_num fftbuffer[256];
complex_num twiddlebuffer;
complex_num minusone;
minusone.real = -1;
minusone.imaginary = 0;
for (int stage = 0; stage < 9; stage++){
unsigned int step = 1<<(stage+1);
for (unsigned int i = 0; i < 512; i = i+step){ // Crack it up in parts, i.e. for stage0 -> 512, stage1 -> 256 , 2>128, 3>64, 4>32, 5>16, 6>8, 7>4, 8>2, 9>1 --> 1024/2^stage OR IN STEPS: stage0 -> 2, stage1 -> 4, 2>8, 3>16, 4,32, 5>64, ......... 9>512 --> 1024 - 1024/2^stage+1
// Buffer the first 'half' of the thing, which is the first half step
for (unsigned int k = 0; k < step / 2; k++){
fftbuffer[k].real = datain[i+k].real;
fftbuffer[k].imaginary = datain[i+k].imaginary;
}
// Apply twiddle factors to the seconds half (half step) depending on stage and numbering
for (unsigned int k = 0; k < step / 2; k++){
// Read in the correct twiddle factor
// Twiddle factor is recalculated with N-k*(1024 / 2^stage+1) which can be recalculated to 1<<
twiddlebuffer.imaginary = twiddleLookupTable_Imaginary[512-(k * (1<<(9-stage)))];
twiddlebuffer.real = twiddleLookupTable_Real[512-(k * (1 << (9 - stage)))];
datain[i + k + step / 2] = complex_multiply(datain[i + k + step / 2], twiddlebuffer);
}
// Recalculate the first half by addition of the first and recalculated half
for (unsigned int k = 0; k < step / 2; k++)
datain[i + k] = complex_add(datain[i+k], datain[i+k+step/2]);
// Multiply the second half with minus 1
for (unsigned int k = 0; k < step / 2; k++)
datain[i + step / 2 + k] = complex_multiply(datain[i + step/2+k], minusone);
// Add the buffered old values, with the new second half values
for (unsigned int k = 0; k < step / 2; k++)
datain[i + step / 2 + k] = complex_add(datain[i + step/2 + k], fftbuffer[k]);
}
}
//first convert complex data back to magnitude data then divide by 1/N
for (int i = 0; i < 512; i++)
dataout[i] = (complex_magnitude(datain[i])/512);
}
void equalizer(complex_num* data){
}
void performEqualizer(float* datain, float* dataout, complex_num* freqdata, int datalength){
if (datalength == 512){
// - Calculating and substracting the mean -
subMean(datain, datalength);
// - Applying a hanning window - N multiplications
applyHanningTable(datain, datalength);
// It then applies a radix-2 Cooley Tukey FFT to create a fourier transform
reverseCooleyTukeyRadix2(datain, freqdata, datalength);
// It gets equalized
equalizer(freqdata);
// back to time domain
cooleyTukeyBack(dataout, freqdata, datalength);
}
}