Mercurial > hg > qm-dsp
comparison dsp/transforms/FFT.cpp @ 64:6cb2b3cd5356
* 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 | cannam |
---|---|
date | Wed, 13 May 2009 09:19:12 +0000 |
parents | 7fe29d8a7eaf |
children | d1d65fff5356 |
comparison
equal
deleted
inserted
replaced
63:0dcbce5d7dce | 64:6cb2b3cd5356 |
---|---|
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 } |