c@225
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
c@225
|
2
|
c@225
|
3 /*
|
c@225
|
4 QM DSP Library
|
c@225
|
5
|
c@225
|
6 Centre for Digital Music, Queen Mary, University of London.
|
c@225
|
7 This file is based on Don Cross's public domain FFT implementation.
|
c@225
|
8 */
|
c@225
|
9
|
c@225
|
10 #include "FFT.h"
|
c@225
|
11 #include <cmath>
|
c@225
|
12
|
c@225
|
13 //////////////////////////////////////////////////////////////////////
|
c@225
|
14 // Construction/Destruction
|
c@225
|
15 //////////////////////////////////////////////////////////////////////
|
c@225
|
16
|
c@225
|
17 FFT::FFT()
|
c@225
|
18 {
|
c@225
|
19
|
c@225
|
20 }
|
c@225
|
21
|
c@225
|
22 FFT::~FFT()
|
c@225
|
23 {
|
c@225
|
24
|
c@225
|
25 }
|
c@225
|
26
|
c@225
|
27 void FFT::process(unsigned int p_nSamples, bool p_bInverseTransform, double *p_lpRealIn, double *p_lpImagIn, double *p_lpRealOut, double *p_lpImagOut)
|
c@225
|
28 {
|
c@225
|
29
|
c@225
|
30 if(!p_lpRealIn || !p_lpRealOut || !p_lpImagOut) return;
|
c@225
|
31
|
c@225
|
32
|
c@225
|
33 unsigned int NumBits;
|
c@225
|
34 unsigned int i, j, k, n;
|
c@225
|
35 unsigned int BlockSize, BlockEnd;
|
c@225
|
36
|
c@225
|
37 double angle_numerator = 2.0 * M_PI;
|
c@225
|
38 double tr, ti;
|
c@225
|
39
|
c@225
|
40 if( !isPowerOfTwo(p_nSamples) )
|
c@225
|
41 {
|
c@225
|
42 return;
|
c@225
|
43 }
|
c@225
|
44
|
c@225
|
45 if( p_bInverseTransform ) angle_numerator = -angle_numerator;
|
c@225
|
46
|
c@225
|
47 NumBits = numberOfBitsNeeded ( p_nSamples );
|
c@225
|
48
|
c@225
|
49
|
c@225
|
50 for( i=0; i < p_nSamples; i++ )
|
c@225
|
51 {
|
c@225
|
52 j = reverseBits ( i, NumBits );
|
c@225
|
53 p_lpRealOut[j] = p_lpRealIn[i];
|
c@225
|
54 p_lpImagOut[j] = (p_lpImagIn == 0) ? 0.0 : p_lpImagIn[i];
|
c@225
|
55 }
|
c@225
|
56
|
c@225
|
57
|
c@225
|
58 BlockEnd = 1;
|
c@225
|
59 for( BlockSize = 2; BlockSize <= p_nSamples; BlockSize <<= 1 )
|
c@225
|
60 {
|
c@225
|
61 double delta_angle = angle_numerator / (double)BlockSize;
|
c@225
|
62 double sm2 = -sin ( -2 * delta_angle );
|
c@225
|
63 double sm1 = -sin ( -delta_angle );
|
c@225
|
64 double cm2 = cos ( -2 * delta_angle );
|
c@225
|
65 double cm1 = cos ( -delta_angle );
|
c@225
|
66 double w = 2 * cm1;
|
c@225
|
67 double ar[3], ai[3];
|
c@225
|
68
|
c@225
|
69 for( i=0; i < p_nSamples; i += BlockSize )
|
c@225
|
70 {
|
c@225
|
71
|
c@225
|
72 ar[2] = cm2;
|
c@225
|
73 ar[1] = cm1;
|
c@225
|
74
|
c@225
|
75 ai[2] = sm2;
|
c@225
|
76 ai[1] = sm1;
|
c@225
|
77
|
c@225
|
78 for ( j=i, n=0; n < BlockEnd; j++, n++ )
|
c@225
|
79 {
|
c@225
|
80
|
c@225
|
81 ar[0] = w*ar[1] - ar[2];
|
c@225
|
82 ar[2] = ar[1];
|
c@225
|
83 ar[1] = ar[0];
|
c@225
|
84
|
c@225
|
85 ai[0] = w*ai[1] - ai[2];
|
c@225
|
86 ai[2] = ai[1];
|
c@225
|
87 ai[1] = ai[0];
|
c@225
|
88
|
c@225
|
89 k = j + BlockEnd;
|
c@225
|
90 tr = ar[0]*p_lpRealOut[k] - ai[0]*p_lpImagOut[k];
|
c@225
|
91 ti = ar[0]*p_lpImagOut[k] + ai[0]*p_lpRealOut[k];
|
c@225
|
92
|
c@225
|
93 p_lpRealOut[k] = p_lpRealOut[j] - tr;
|
c@225
|
94 p_lpImagOut[k] = p_lpImagOut[j] - ti;
|
c@225
|
95
|
c@225
|
96 p_lpRealOut[j] += tr;
|
c@225
|
97 p_lpImagOut[j] += ti;
|
c@225
|
98
|
c@225
|
99 }
|
c@225
|
100 }
|
c@225
|
101
|
c@225
|
102 BlockEnd = BlockSize;
|
c@225
|
103
|
c@225
|
104 }
|
c@225
|
105
|
c@225
|
106
|
c@225
|
107 if( p_bInverseTransform )
|
c@225
|
108 {
|
c@225
|
109 double denom = (double)p_nSamples;
|
c@225
|
110
|
c@225
|
111 for ( i=0; i < p_nSamples; i++ )
|
c@225
|
112 {
|
c@225
|
113 p_lpRealOut[i] /= denom;
|
c@225
|
114 p_lpImagOut[i] /= denom;
|
c@225
|
115 }
|
c@225
|
116 }
|
c@225
|
117 }
|
c@225
|
118
|
c@225
|
119 bool FFT::isPowerOfTwo(unsigned int p_nX)
|
c@225
|
120 {
|
c@225
|
121 if( p_nX < 2 ) return false;
|
c@225
|
122
|
c@225
|
123 if( p_nX & (p_nX-1) ) return false;
|
c@225
|
124
|
c@225
|
125 return true;
|
c@225
|
126 }
|
c@225
|
127
|
c@225
|
128 unsigned int FFT::numberOfBitsNeeded(unsigned int p_nSamples)
|
c@225
|
129 {
|
c@225
|
130 int i;
|
c@225
|
131
|
c@225
|
132 if( p_nSamples < 2 )
|
c@225
|
133 {
|
c@225
|
134 return 0;
|
c@225
|
135 }
|
c@225
|
136
|
c@225
|
137 for ( i=0; ; i++ )
|
c@225
|
138 {
|
c@225
|
139 if( p_nSamples & (1 << i) ) return i;
|
c@225
|
140 }
|
c@225
|
141 }
|
c@225
|
142
|
c@225
|
143 unsigned int FFT::reverseBits(unsigned int p_nIndex, unsigned int p_nBits)
|
c@225
|
144 {
|
c@225
|
145 unsigned int i, rev;
|
c@225
|
146
|
c@225
|
147 for(i=rev=0; i < p_nBits; i++)
|
c@225
|
148 {
|
c@225
|
149 rev = (rev << 1) | (p_nIndex & 1);
|
c@225
|
150 p_nIndex >>= 1;
|
c@225
|
151 }
|
c@225
|
152
|
c@225
|
153 return rev;
|
c@225
|
154 }
|