digital audio mod11 / Mbed 2 deprecated equalizerseperate

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

}