MeeGo 1.2 Harmattan Developer Documentation Develop for the Nokia N9

fastfouriertransformer.cpp Example File

demos/mobile/guitartuner/src/fastfouriertransformer.cpp
 /****************************************************************************
 **
 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 ** All rights reserved.
 ** Contact: Nokia Corporation (qt-info@nokia.com)
 **
 ** This file is part of the QtDeclarative module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:BSD$
 ** You may use this file under the terms of the BSD license as follows:
 **
 ** "Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are
 ** met:
 **   * Redistributions of source code must retain the above copyright
 **     notice, this list of conditions and the following disclaimer.
 **   * Redistributions in binary form must reproduce the above copyright
 **     notice, this list of conditions and the following disclaimer in
 **     the documentation and/or other materials provided with the
 **     distribution.
 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
 **     the names of its contributors may be used to endorse or promote
 **     products derived from this software without specific prior written
 **     permission.
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/

 #include "fastfouriertransformer.h"
 #include "math.h"

 #define STIN  inline
 #define __STATIC

 #include "fftpack.c"

 // called by __ogg_fdrffti
 __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);
 // called by drftf1
 STIN void dradf2(int ido,int l1,float *cc,float *ch,float *wa1);
 // called by drftf1
 STIN void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
         float *wa2,float *wa3);
 // called by drftf1
 STIN void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
         float *c2,float *ch,float *ch2,float *wa);
 // called by drftf1
 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;
     }
 }

 /**
   * Prepares the arrays to be of length n.
   */
 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;
 }

 /**
   * Calculates the Fast Fourier Transformation (FFT).
   */
 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);

 }

 /**
   * Returns the index which corresponds to the maximum density
   * of the FFT.
   */
 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++) {
         // Here, we calculate the frequency k/N.
         // k=1, the wave oscillation time is N, and the frequency
         //      is 1/sample.
         // k=2, the wave oscillation time is N/2, and the frequency
         //      is 2/sample.
         // k=3, the wave oscillation time is N/3, and the frequency
         //      is 3/sample.
         // Note, that the documentation is for Fortran, so indexes in the
         // documentation does not match.
         // The sine and cosine coefficients are obtained thus as follows:
         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;
     }
 }

 /**
   * Sets the cutoff density.
   */
 void FastFourierTransformer::setCutOffForDensity(float cutoff)
 {
     m_cutOffForDensitySquared = cutoff*cutoff;
 }