Update copyright headers
[qt:qt.git] / demos / mobile / guitartuner / src / fastfouriertransformer.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of The Qt Company Ltd nor the names of its
21 **     contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #include "fastfouriertransformer.h"
42 #include "math.h"
43
44 #define STIN  inline
45 #define __STATIC
46
47 #include "fftpack.c"
48
49 // called by __ogg_fdrffti
50 __STATIC void drfti1(int n, float *wa, int *ifac);
51 void __ogg_fdrffti(int n, float *wsave, int *ifac);
52 void __ogg_fdcosqi(int n, float *wsave, int *ifac);
53 // called by drftf1
54 STIN void dradf2(int ido,int l1,float *cc,float *ch,float *wa1);
55 // called by drftf1
56 STIN void dradf4(int ido,int l1,float *cc,float *ch,float *wa1,
57         float *wa2,float *wa3);
58 // called by drftf1
59 STIN void dradfg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
60         float *c2,float *ch,float *ch2,float *wa);
61 // called by drftf1
62 STIN void drftf1(int n,float *c,float *ch,float *wa,int *ifac);
63 void __ogg_fdrfftf(int n,float *r,float *wsave,int *ifac);
64 STIN void dcsqf1(int n,float *x,float *w,float *xh,int *ifac);
65 void __ogg_fdcosqf(int n,float *x,float *wsave,int *ifac);
66 STIN void dradb2(int ido,int l1,float *cc,float *ch,float *wa1);
67 STIN void dradb3(int ido,int l1,float *cc,float *ch,float *wa1,
68                           float *wa2);
69 STIN void dradb4(int ido,int l1,float *cc,float *ch,float *wa1,
70         float *wa2,float *wa3);
71 STIN void dradbg(int ido,int ip,int l1,int idl1,float *cc,float *c1,
72             float *c2,float *ch,float *ch2,float *wa);
73 STIN void drftb1(int n, float *c, float *ch, float *wa, int *ifac);
74 void __ogg_fdrfftb(int n, float *r, float *wsave, int *ifac);
75 STIN void dcsqb1(int n,float *x,float *w,float *xh,int *ifac);
76 void __ogg_fdcosqb(int n,float *x,float *wsave,int *ifac);
77
78 FastFourierTransformer::FastFourierTransformer(QObject *parent) :
79         QObject(parent),
80         m_waveFloat(0),
81         m_workingArray(0),
82         m_ifac(0),
83         m_last_n(-1)
84 {
85 }
86
87 FastFourierTransformer::~FastFourierTransformer()
88 {
89     if (m_waveFloat != 0) {
90         delete [] m_waveFloat;
91     }
92     if (m_workingArray != 0) {
93        delete [] m_workingArray;
94     }
95     if (m_ifac != 0) {
96         delete [] m_ifac;
97     }
98 }
99
100 /**
101   * Prepares the arrays to be of length n.
102   */
103 void FastFourierTransformer::reserve(int n)
104 {
105     Q_ASSERT(n>0);
106     if (m_waveFloat != 0) {
107         delete [] m_waveFloat;
108     }
109     if (m_workingArray != 0) {
110        delete [] m_workingArray;
111     }
112     if (m_ifac != 0) {
113         delete [] m_ifac;
114     }
115     m_workingArray = new float[2*n+15];
116     m_waveFloat = new float[n];
117     m_ifac = new int[n];
118     __ogg_fdrffti(n, m_workingArray, m_ifac);
119     m_last_n = n;
120 }
121
122 /**
123   * Calculates the Fast Fourier Transformation (FFT).
124   */
125 void FastFourierTransformer::calculateFFT(QList<qint16> wave)
126 {
127     const int n = wave.size();
128     if (m_last_n != n) {
129         reserve(n);
130     }
131     for (int i = 0; i < n; i++) {
132         m_waveFloat[i] = (float) wave.at(i);
133     }
134
135     __ogg_fdrfftf(n, m_waveFloat, m_workingArray, m_ifac);
136
137 }
138
139 /**
140   * Returns the index which corresponds to the maximum density
141   * of the FFT.
142   */
143 int FastFourierTransformer::getMaximumDensityIndex()
144 {
145     const int halfN = m_last_n / 2;
146     float maxDensity = 0;
147     int maxDensityIndex = 0;
148     float densitySquared = 0.f;
149     for (int k = 1; k < halfN; k++) {
150         // Here, we calculate the frequency k/N.
151         // k=1, the wave oscillation time is N, and the frequency
152         //      is 1/sample.
153         // k=2, the wave oscillation time is N/2, and the frequency
154         //      is 2/sample.
155         // k=3, the wave oscillation time is N/3, and the frequency
156         //      is 3/sample.
157         // Note, that the documentation is for Fortran, so indexes in the
158         // documentation does not match.
159         // The sine and cosine coefficients are obtained thus as follows:
160         const float cosCoefficient = qAbs(m_waveFloat[2*k-1]);
161         const float sinCoefficient = qAbs(m_waveFloat[2*k]);
162
163         densitySquared = sinCoefficient*sinCoefficient + cosCoefficient*cosCoefficient;
164         if (densitySquared > maxDensity) {
165             maxDensity = densitySquared;
166             maxDensityIndex = k;
167         }
168     }
169
170     if (m_cutOffForDensitySquared < maxDensity) {
171         return maxDensityIndex;
172     }
173     else {
174         return -1;
175     }
176 }
177
178 /**
179   * Sets the cutoff density.
180   */
181 void FastFourierTransformer::setCutOffForDensity(float cutoff)
182 {
183     m_cutOffForDensitySquared = cutoff*cutoff;
184 }