#include "fastfouriertransformer.h"
 #include "math.h"
 #define STIN  inline
 #define __STATIC
 #include "fftpack.c"
 
 __STATIC void drfti1(int n, float *wa, int *ifac);
 void __ogg_fdrffti(int n, float *wsave, int *ifac);
 void __ogg_fdcosqi(int n, float *wsave, int *ifac);
 
 STIN void dradf2(int ido,int l1,float *cc,float *ch,float *wa1);
 
 STIN void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
         float *wa2,float *wa3);
 
 STIN void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
         float *c2,float *ch,float *ch2,float *wa);
 
 STIN void drftf1(int n,float *c,float *ch,float *wa,int *ifac);
 void __ogg_fdrfftf(int n,float *r,float *wsave,int *ifac);
 STIN void dcsqf1(int n,float *x,float *w,float *xh,int *ifac);
 void __ogg_fdcosqf(int n,float *x,float *wsave,int *ifac);
 STIN void dradb2(int ido,int l1,float *cc,float *ch,float *wa1);
 STIN void dradb3(int ido,int l1,float *cc,float *ch,float *wa1,
                           float *wa2);
 STIN void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
         float *wa2,float *wa3);
 STIN void dradbg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
             float *c2,float *ch,float *ch2,float *wa);
 STIN void drftb1(int n, float *c, float *ch, float *wa, int *ifac);
 void __ogg_fdrfftb(int n, float *r, float *wsave, int *ifac);
 STIN void dcsqb1(int n,float *x,float *w,float *xh,int *ifac);
 void __ogg_fdcosqb(int n,float *x,float *wsave,int *ifac);
 FastFourierTransformer::FastFourierTransformer(QObject *parent) :
         QObject(parent),
         m_waveFloat(0),
         m_workingArray(0),
         m_ifac(0),
         m_last_n(-1)
 {
 }
 FastFourierTransformer::~FastFourierTransformer()
 {
     if (m_waveFloat != 0) {
         delete [] m_waveFloat;
     }
     if (m_workingArray != 0) {
        delete [] m_workingArray;
     }
     if (m_ifac != 0) {
         delete [] m_ifac;
     }
 }
 
 void FastFourierTransformer::reserve(int n)
 {
     Q_ASSERT(n>0);
     if (m_waveFloat != 0) {
         delete [] m_waveFloat;
     }
     if (m_workingArray != 0) {
        delete [] m_workingArray;
     }
     if (m_ifac != 0) {
         delete [] m_ifac;
     }
     m_workingArray = new float[2*n+15];
     m_waveFloat = new float[n];
     m_ifac = new int[n];
     __ogg_fdrffti(n, m_workingArray, m_ifac);
     m_last_n = n;
 }
 
 void FastFourierTransformer::calculateFFT(QList<qint16> wave)
 {
     const int n = wave.size();
     if (m_last_n != n) {
         reserve(n);
     }
     for (int i = 0; i < n; i++) {
         m_waveFloat[i] = (float) wave.at(i);
     }
     __ogg_fdrfftf(n, m_waveFloat, m_workingArray, m_ifac);
 }
 
 int FastFourierTransformer::getMaximumDensityIndex()
 {
     const int halfN = m_last_n / 2;
     float maxDensity = 0;
     int maxDensityIndex = 0;
     float densitySquared = 0.f;
     for (int k = 1; k < halfN; k++) {
         
         
         
         
         
         
         
         
         
         
         const float cosCoefficient = qAbs(m_waveFloat[2*k-1]);
         const float sinCoefficient = qAbs(m_waveFloat[2*k]);
         densitySquared = sinCoefficient*sinCoefficient + cosCoefficient*cosCoefficient;
         if (densitySquared > maxDensity) {
             maxDensity = densitySquared;
             maxDensityIndex = k;
         }
     }
     if (m_cutOffForDensitySquared < maxDensity) {
         return maxDensityIndex;
     }
     else {
         return -1;
     }
 }
 
 void FastFourierTransformer::setCutOffForDensity(float cutoff)
 {
     m_cutOffForDensitySquared = cutoff*cutoff;
 }