comparison dsp/transforms/FFT.cpp @ 114:f6ccde089491 pvoc

Tidy real-to-complex FFT -- forward and inverse have different arguments, so make them separate functions; document
author Chris Cannam
date Wed, 02 Oct 2013 15:04:38 +0100
parents e5907ae6de17
children 6ec45e85ed81
comparison
equal deleted inserted replaced
113:3cb359d043f0 114:f6ccde089491
13 13
14 #include <cmath> 14 #include <cmath>
15 15
16 #include <iostream> 16 #include <iostream>
17 17
18 FFT::FFT(unsigned int n) : 18 FFT::FFT(int n) :
19 m_n(n), 19 m_n(n)
20 m_private(0)
21 { 20 {
22 if( !MathUtilities::isPowerOfTwo(m_n) ) 21 if( !MathUtilities::isPowerOfTwo(m_n) )
23 { 22 {
24 std::cerr << "ERROR: FFT: Non-power-of-two FFT size " 23 std::cerr << "ERROR: FFT: Non-power-of-two FFT size "
25 << m_n << " not supported in this implementation" 24 << m_n << " not supported in this implementation"
31 FFT::~FFT() 30 FFT::~FFT()
32 { 31 {
33 32
34 } 33 }
35 34
36 FFTReal::FFTReal(unsigned int n) : 35 FFTReal::FFTReal(int n) :
37 m_n(n), 36 m_n(n),
38 m_private(0) 37 m_fft(new FFT(n)),
39 { 38 m_r(new double[n]),
40 m_private = new FFT(m_n); 39 m_i(new double[n]),
40 m_discard(new double[n])
41 {
42 for (int i = 0; i < n; ++i) {
43 m_r[i] = 0;
44 m_i[i] = 0;
45 m_discard[i] = 0;
46 }
41 } 47 }
42 48
43 FFTReal::~FFTReal() 49 FFTReal::~FFTReal()
44 { 50 {
45 delete (FFT *)m_private; 51 delete m_fft;
52 delete[] m_discard;
53 delete[] m_r;
54 delete[] m_i;
46 } 55 }
47 56
48 void 57 void
49 FFTReal::process(bool inverse, 58 FFTReal::forward(const double *realIn,
50 const double *realIn,
51 double *realOut, double *imagOut) 59 double *realOut, double *imagOut)
52 { 60 {
53 ((FFT *)m_private)->process(inverse, realIn, 0, realOut, imagOut); 61 m_fft->process(false, realIn, 0, realOut, imagOut);
54 } 62 }
55 63
56 static unsigned int numberOfBitsNeeded(unsigned int p_nSamples) 64 void
65 FFTReal::inverse(const double *realIn, const double *imagIn,
66 double *realOut)
67 {
68 for (int i = 0; i < m_n/2 + 1; ++i) {
69 m_r[i] = realIn[i];
70 m_i[i] = imagIn[i];
71 if (i > 0 && i < m_n/2) {
72 m_r[m_n - i] = realIn[i];
73 m_i[m_n - i] = -imagIn[i];
74 }
75 }
76 m_fft->process(true, m_r, m_i, realOut, m_discard);
77 }
78
79 static int numberOfBitsNeeded(int p_nSamples)
57 { 80 {
58 int i; 81 int i;
59 82
60 if( p_nSamples < 2 ) 83 if( p_nSamples < 2 )
61 { 84 {
66 { 89 {
67 if( p_nSamples & (1 << i) ) return i; 90 if( p_nSamples & (1 << i) ) return i;
68 } 91 }
69 } 92 }
70 93
71 static unsigned int reverseBits(unsigned int p_nIndex, unsigned int p_nBits) 94 static int reverseBits(int p_nIndex, int p_nBits)
72 { 95 {
73 unsigned int i, rev; 96 int i, rev;
74 97
75 for(i=rev=0; i < p_nBits; i++) 98 for(i=rev=0; i < p_nBits; i++)
76 { 99 {
77 rev = (rev << 1) | (p_nIndex & 1); 100 rev = (rev << 1) | (p_nIndex & 1);
78 p_nIndex >>= 1; 101 p_nIndex >>= 1;
88 { 111 {
89 if (!p_lpRealIn || !p_lpRealOut || !p_lpImagOut) return; 112 if (!p_lpRealIn || !p_lpRealOut || !p_lpImagOut) return;
90 113
91 // std::cerr << "FFT::process(" << m_n << "," << p_bInverseTransform << ")" << std::endl; 114 // std::cerr << "FFT::process(" << m_n << "," << p_bInverseTransform << ")" << std::endl;
92 115
93 unsigned int NumBits; 116 int NumBits;
94 unsigned int i, j, k, n; 117 int i, j, k, n;
95 unsigned int BlockSize, BlockEnd; 118 int BlockSize, BlockEnd;
96 119
97 double angle_numerator = 2.0 * M_PI; 120 double angle_numerator = 2.0 * M_PI;
98 double tr, ti; 121 double tr, ti;
99 122
100 if( !MathUtilities::isPowerOfTwo(m_n) ) 123 if( !MathUtilities::isPowerOfTwo(m_n) )
106 } 129 }
107 130
108 if( p_bInverseTransform ) angle_numerator = -angle_numerator; 131 if( p_bInverseTransform ) angle_numerator = -angle_numerator;
109 132
110 NumBits = numberOfBitsNeeded ( m_n ); 133 NumBits = numberOfBitsNeeded ( m_n );
134
111 135
112 136
113 for( i=0; i < m_n; i++ ) 137 for( i=0; i < m_n; i++ )
114 { 138 {
115 j = reverseBits ( i, NumBits ); 139 j = reverseBits ( i, NumBits );