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