comparison dsp/transforms/FFT.cpp @ 289:befe5aa6b450

* Refactor FFT a little bit so as to separate construction and processing rather than have a single static method -- will make it easier to use a different implementation * pull in KissFFT implementation (not hooked up yet)
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 13 May 2009 09:19:12 +0000
parents 9c403afdd9e9
children d1d65fff5356
comparison
equal deleted inserted replaced
288:86c70067c723 289:befe5aa6b450
13 13
14 #include <cmath> 14 #include <cmath>
15 15
16 #include <iostream> 16 #include <iostream>
17 17
18 ////////////////////////////////////////////////////////////////////// 18 #define USE_BUILTIN_FFT 1
19 // Construction/Destruction
20 //////////////////////////////////////////////////////////////////////
21 19
22 FFT::FFT() 20 #ifdef USE_BUILTIN_FFT
21
22 FFT::FFT(unsigned int n) :
23 m_n(n),
24 m_private(0)
23 { 25 {
24 26 if( !MathUtilities::isPowerOfTwo(m_n) )
27 {
28 std::cerr << "ERROR: FFT: Non-power-of-two FFT size "
29 << m_n << " not supported in this implementation"
30 << std::endl;
31 return;
32 }
25 } 33 }
26 34
27 FFT::~FFT() 35 FFT::~FFT()
28 { 36 {
29 37
30 } 38 }
31 39
32 void FFT::process(unsigned int p_nSamples, bool p_bInverseTransform, 40 FFTReal::FFTReal(unsigned int n) :
33 const double *p_lpRealIn, const double *p_lpImagIn, 41 m_n(n),
34 double *p_lpRealOut, double *p_lpImagOut) 42 m_private(0)
35 { 43 {
44 m_private = new FFT(m_n);
45 }
36 46
47 FFTReal::~FFTReal()
48 {
49 delete (FFT *)m_private;
50 }
51
52 void
53 FFTReal::process(bool inverse,
54 const double *realIn,
55 double *realOut, double *imagOut)
56 {
57 ((FFT *)m_private)->process(inverse, realIn, 0, realOut, imagOut);
58 }
59
60 static unsigned int numberOfBitsNeeded(unsigned int p_nSamples)
61 {
62 int i;
63
64 if( p_nSamples < 2 )
65 {
66 return 0;
67 }
68
69 for ( i=0; ; i++ )
70 {
71 if( p_nSamples & (1 << i) ) return i;
72 }
73 }
74
75 static unsigned int reverseBits(unsigned int p_nIndex, unsigned int p_nBits)
76 {
77 unsigned int i, rev;
78
79 for(i=rev=0; i < p_nBits; i++)
80 {
81 rev = (rev << 1) | (p_nIndex & 1);
82 p_nIndex >>= 1;
83 }
84
85 return rev;
86 }
87
88 void
89 FFT::process(bool p_bInverseTransform,
90 const double *p_lpRealIn, const double *p_lpImagIn,
91 double *p_lpRealOut, double *p_lpImagOut)
92 {
37 if(!p_lpRealIn || !p_lpRealOut || !p_lpImagOut) return; 93 if(!p_lpRealIn || !p_lpRealOut || !p_lpImagOut) return;
38
39 94
40 unsigned int NumBits; 95 unsigned int NumBits;
41 unsigned int i, j, k, n; 96 unsigned int i, j, k, n;
42 unsigned int BlockSize, BlockEnd; 97 unsigned int BlockSize, BlockEnd;
43 98
44 double angle_numerator = 2.0 * M_PI; 99 double angle_numerator = 2.0 * M_PI;
45 double tr, ti; 100 double tr, ti;
46 101
47 if( !MathUtilities::isPowerOfTwo(p_nSamples) ) 102 if( !MathUtilities::isPowerOfTwo(m_n) )
48 { 103 {
49 std::cerr << "ERROR: FFT::process: Non-power-of-two FFT size " 104 std::cerr << "ERROR: FFT::process: Non-power-of-two FFT size "
50 << p_nSamples << " not supported in this implementation" 105 << m_n << " not supported in this implementation"
51 << std::endl; 106 << std::endl;
52 return; 107 return;
53 } 108 }
54 109
55 if( p_bInverseTransform ) angle_numerator = -angle_numerator; 110 if( p_bInverseTransform ) angle_numerator = -angle_numerator;
56 111
57 NumBits = numberOfBitsNeeded ( p_nSamples ); 112 NumBits = numberOfBitsNeeded ( m_n );
58 113
59 114
60 for( i=0; i < p_nSamples; i++ ) 115 for( i=0; i < m_n; i++ )
61 { 116 {
62 j = reverseBits ( i, NumBits ); 117 j = reverseBits ( i, NumBits );
63 p_lpRealOut[j] = p_lpRealIn[i]; 118 p_lpRealOut[j] = p_lpRealIn[i];
64 p_lpImagOut[j] = (p_lpImagIn == 0) ? 0.0 : p_lpImagIn[i]; 119 p_lpImagOut[j] = (p_lpImagIn == 0) ? 0.0 : p_lpImagIn[i];
65 } 120 }
66 121
67 122
68 BlockEnd = 1; 123 BlockEnd = 1;
69 for( BlockSize = 2; BlockSize <= p_nSamples; BlockSize <<= 1 ) 124 for( BlockSize = 2; BlockSize <= m_n; BlockSize <<= 1 )
70 { 125 {
71 double delta_angle = angle_numerator / (double)BlockSize; 126 double delta_angle = angle_numerator / (double)BlockSize;
72 double sm2 = -sin ( -2 * delta_angle ); 127 double sm2 = -sin ( -2 * delta_angle );
73 double sm1 = -sin ( -delta_angle ); 128 double sm1 = -sin ( -delta_angle );
74 double cm2 = cos ( -2 * delta_angle ); 129 double cm2 = cos ( -2 * delta_angle );
75 double cm1 = cos ( -delta_angle ); 130 double cm1 = cos ( -delta_angle );
76 double w = 2 * cm1; 131 double w = 2 * cm1;
77 double ar[3], ai[3]; 132 double ar[3], ai[3];
78 133
79 for( i=0; i < p_nSamples; i += BlockSize ) 134 for( i=0; i < m_n; i += BlockSize )
80 { 135 {
81 136
82 ar[2] = cm2; 137 ar[2] = cm2;
83 ar[1] = cm1; 138 ar[1] = cm1;
84 139
114 } 169 }
115 170
116 171
117 if( p_bInverseTransform ) 172 if( p_bInverseTransform )
118 { 173 {
119 double denom = (double)p_nSamples; 174 double denom = (double)m_n;
120 175
121 for ( i=0; i < p_nSamples; i++ ) 176 for ( i=0; i < m_n; i++ )
122 { 177 {
123 p_lpRealOut[i] /= denom; 178 p_lpRealOut[i] /= denom;
124 p_lpImagOut[i] /= denom; 179 p_lpImagOut[i] /= denom;
125 } 180 }
126 } 181 }
127 } 182 }
128 183
129 unsigned int FFT::numberOfBitsNeeded(unsigned int p_nSamples) 184 #else
130 {
131 int i;
132 185
133 if( p_nSamples < 2 ) 186 #include "kissfft/kiss_fft.h"
134 { 187 #include "kissfft/kiss_fftr.h"
135 return 0;
136 }
137 188
138 for ( i=0; ; i++ ) 189 #endif
139 {
140 if( p_nSamples & (1 << i) ) return i;
141 }
142 }
143
144 unsigned int FFT::reverseBits(unsigned int p_nIndex, unsigned int p_nBits)
145 {
146 unsigned int i, rev;
147
148 for(i=rev=0; i < p_nBits; i++)
149 {
150 rev = (rev << 1) | (p_nIndex & 1);
151 p_nIndex >>= 1;
152 }
153
154 return rev;
155 }