Mercurial > hg > qm-dsp
comparison dsp/transforms/FFT.cpp @ 211:a41bea655151 msvc
Rename FFT back again, now we have our own project
author | Chris Cannam |
---|---|
date | Mon, 05 Feb 2018 17:40:13 +0000 |
parents | |
children | 0307327a3869 |
comparison
equal
deleted
inserted
replaced
210:cf62f73766e9 | 211:a41bea655151 |
---|---|
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 */ | |
8 | |
9 #include "FFT.h" | |
10 | |
11 #include "maths/MathUtilities.h" | |
12 | |
13 #include "kiss_fft.h" | |
14 #include "kiss_fftr.h" | |
15 | |
16 #include <cmath> | |
17 | |
18 #include <iostream> | |
19 | |
20 #include <stdexcept> | |
21 | |
22 class FFT::D | |
23 { | |
24 public: | |
25 D(int n) : m_n(n) { | |
26 m_planf = kiss_fft_alloc(m_n, 0, NULL, NULL); | |
27 m_plani = kiss_fft_alloc(m_n, 1, NULL, NULL); | |
28 m_kin = new kiss_fft_cpx[m_n]; | |
29 m_kout = new kiss_fft_cpx[m_n]; | |
30 } | |
31 | |
32 ~D() { | |
33 kiss_fft_free(m_planf); | |
34 kiss_fft_free(m_plani); | |
35 delete[] m_kin; | |
36 delete[] m_kout; | |
37 } | |
38 | |
39 void process(bool inverse, | |
40 const double *ri, | |
41 const double *ii, | |
42 double *ro, | |
43 double *io) { | |
44 | |
45 for (int i = 0; i < m_n; ++i) { | |
46 m_kin[i].r = ri[i]; | |
47 m_kin[i].i = (ii ? ii[i] : 0.0); | |
48 } | |
49 | |
50 if (!inverse) { | |
51 | |
52 kiss_fft(m_planf, m_kin, m_kout); | |
53 | |
54 for (int i = 0; i < m_n; ++i) { | |
55 ro[i] = m_kout[i].r; | |
56 io[i] = m_kout[i].i; | |
57 } | |
58 | |
59 } else { | |
60 | |
61 kiss_fft(m_plani, m_kin, m_kout); | |
62 | |
63 double scale = 1.0 / m_n; | |
64 | |
65 for (int i = 0; i < m_n; ++i) { | |
66 ro[i] = m_kout[i].r * scale; | |
67 io[i] = m_kout[i].i * scale; | |
68 } | |
69 } | |
70 } | |
71 | |
72 private: | |
73 int m_n; | |
74 kiss_fft_cfg m_planf; | |
75 kiss_fft_cfg m_plani; | |
76 kiss_fft_cpx *m_kin; | |
77 kiss_fft_cpx *m_kout; | |
78 }; | |
79 | |
80 FFT::FFT(int n) : | |
81 m_d(new D(n)) | |
82 { | |
83 } | |
84 | |
85 FFT::~FFT() | |
86 { | |
87 delete m_d; | |
88 } | |
89 | |
90 void | |
91 FFT::process(bool inverse, | |
92 const double *p_lpRealIn, const double *p_lpImagIn, | |
93 double *p_lpRealOut, double *p_lpImagOut) | |
94 { | |
95 m_d->process(inverse, | |
96 p_lpRealIn, p_lpImagIn, | |
97 p_lpRealOut, p_lpImagOut); | |
98 } | |
99 | |
100 class FFTReal::D | |
101 { | |
102 public: | |
103 D(int n) : m_n(n) { | |
104 if (n % 2) { | |
105 throw std::invalid_argument | |
106 ("nsamples must be even in FFTReal constructor"); | |
107 } | |
108 m_planf = kiss_fftr_alloc(m_n, 0, NULL, NULL); | |
109 m_plani = kiss_fftr_alloc(m_n, 1, NULL, NULL); | |
110 m_c = new kiss_fft_cpx[m_n]; | |
111 } | |
112 | |
113 ~D() { | |
114 kiss_fftr_free(m_planf); | |
115 kiss_fftr_free(m_plani); | |
116 delete[] m_c; | |
117 } | |
118 | |
119 void forward(const double *ri, double *ro, double *io) { | |
120 | |
121 kiss_fftr(m_planf, ri, m_c); | |
122 | |
123 for (int i = 0; i <= m_n/2; ++i) { | |
124 ro[i] = m_c[i].r; | |
125 io[i] = m_c[i].i; | |
126 } | |
127 | |
128 for (int i = 0; i + 1 < m_n/2; ++i) { | |
129 ro[m_n - i - 1] = ro[i + 1]; | |
130 io[m_n - i - 1] = -io[i + 1]; | |
131 } | |
132 } | |
133 | |
134 void forwardMagnitude(const double *ri, double *mo) { | |
135 | |
136 double *io = new double[m_n]; | |
137 | |
138 forward(ri, mo, io); | |
139 | |
140 for (int i = 0; i < m_n; ++i) { | |
141 mo[i] = sqrt(mo[i] * mo[i] + io[i] * io[i]); | |
142 } | |
143 | |
144 delete[] io; | |
145 } | |
146 | |
147 void inverse(const double *ri, const double *ii, double *ro) { | |
148 | |
149 // kiss_fftr.h says | |
150 // "input freqdata has nfft/2+1 complex points" | |
151 | |
152 for (int i = 0; i < m_n/2 + 1; ++i) { | |
153 m_c[i].r = ri[i]; | |
154 m_c[i].i = ii[i]; | |
155 } | |
156 | |
157 kiss_fftri(m_plani, m_c, ro); | |
158 | |
159 double scale = 1.0 / m_n; | |
160 | |
161 for (int i = 0; i < m_n; ++i) { | |
162 ro[i] *= scale; | |
163 } | |
164 } | |
165 | |
166 private: | |
167 int m_n; | |
168 kiss_fftr_cfg m_planf; | |
169 kiss_fftr_cfg m_plani; | |
170 kiss_fft_cpx *m_c; | |
171 }; | |
172 | |
173 FFTReal::FFTReal(int n) : | |
174 m_d(new D(n)) | |
175 { | |
176 } | |
177 | |
178 FFTReal::~FFTReal() | |
179 { | |
180 delete m_d; | |
181 } | |
182 | |
183 void | |
184 FFTReal::forward(const double *ri, double *ro, double *io) | |
185 { | |
186 m_d->forward(ri, ro, io); | |
187 } | |
188 | |
189 void | |
190 FFTReal::forwardMagnitude(const double *ri, double *mo) | |
191 { | |
192 m_d->forwardMagnitude(ri, mo); | |
193 } | |
194 | |
195 void | |
196 FFTReal::inverse(const double *ri, const double *ii, double *ro) | |
197 { | |
198 m_d->inverse(ri, ii, ro); | |
199 } | |
200 | |
201 | |
202 |