Chris@29
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@29
|
2
|
Chris@29
|
3 /*
|
Chris@29
|
4 bqfft
|
Chris@29
|
5
|
Chris@29
|
6 A small library wrapping various FFT implementations for some
|
Chris@29
|
7 common audio processing use cases.
|
Chris@29
|
8
|
Chris@29
|
9 Copyright 2007-2015 Particular Programs Ltd.
|
Chris@29
|
10
|
Chris@29
|
11 Permission is hereby granted, free of charge, to any person
|
Chris@29
|
12 obtaining a copy of this software and associated documentation
|
Chris@29
|
13 files (the "Software"), to deal in the Software without
|
Chris@29
|
14 restriction, including without limitation the rights to use, copy,
|
Chris@29
|
15 modify, merge, publish, distribute, sublicense, and/or sell copies
|
Chris@29
|
16 of the Software, and to permit persons to whom the Software is
|
Chris@29
|
17 furnished to do so, subject to the following conditions:
|
Chris@29
|
18
|
Chris@29
|
19 The above copyright notice and this permission notice shall be
|
Chris@29
|
20 included in all copies or substantial portions of the Software.
|
Chris@29
|
21
|
Chris@29
|
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
Chris@29
|
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@29
|
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
Chris@29
|
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
Chris@29
|
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
Chris@29
|
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
Chris@29
|
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@29
|
29
|
Chris@29
|
30 Except as contained in this notice, the names of Chris Cannam and
|
Chris@29
|
31 Particular Programs Ltd shall not be used in advertising or
|
Chris@29
|
32 otherwise to promote the sale, use or other dealings in this
|
Chris@29
|
33 Software without prior written authorization.
|
Chris@29
|
34 */
|
Chris@29
|
35
|
Chris@29
|
36 #include "bqfft/FFT.h"
|
Chris@29
|
37
|
Chris@29
|
38 //#include "system/Thread.h"
|
Chris@29
|
39
|
Chris@29
|
40 #include <bqvec/Allocators.h>
|
Chris@29
|
41 #include <bqvec/VectorOps.h>
|
Chris@29
|
42 #include <bqvec/VectorOpsComplex.h>
|
Chris@29
|
43
|
Chris@29
|
44 //#define FFT_MEASUREMENT 1
|
Chris@29
|
45
|
Chris@29
|
46 #ifdef FFT_MEASUREMENT
|
Chris@29
|
47 #include <sstream>
|
Chris@29
|
48 #endif
|
Chris@29
|
49
|
Chris@29
|
50 #ifdef HAVE_IPP
|
Chris@29
|
51 #include <ipps.h>
|
Chris@29
|
52 #endif
|
Chris@29
|
53
|
Chris@29
|
54 #ifdef HAVE_FFTW3
|
Chris@29
|
55 #include <fftw3.h>
|
Chris@29
|
56 #endif
|
Chris@29
|
57
|
Chris@29
|
58 #ifdef HAVE_VDSP
|
Chris@29
|
59 #include <Accelerate/Accelerate.h>
|
Chris@29
|
60 #endif
|
Chris@29
|
61
|
Chris@29
|
62 #ifdef HAVE_MEDIALIB
|
Chris@29
|
63 #include <mlib_signal.h>
|
Chris@29
|
64 #endif
|
Chris@29
|
65
|
Chris@29
|
66 #ifdef HAVE_OPENMAX
|
Chris@29
|
67 #include <omxSP.h>
|
Chris@29
|
68 #endif
|
Chris@29
|
69
|
Chris@29
|
70 #ifdef HAVE_SFFT
|
Chris@29
|
71 extern "C" {
|
Chris@29
|
72 #include <sfft.h>
|
Chris@29
|
73 }
|
Chris@29
|
74 #endif
|
Chris@29
|
75
|
Chris@29
|
76 #ifdef HAVE_KISSFFT
|
Chris@29
|
77 #include "kissfft/kiss_fftr.h"
|
Chris@29
|
78 #endif
|
Chris@29
|
79
|
Chris@29
|
80 #ifndef HAVE_IPP
|
Chris@29
|
81 #ifndef HAVE_FFTW3
|
Chris@29
|
82 #ifndef HAVE_KISSFFT
|
Chris@29
|
83 #ifndef USE_BUILTIN_FFT
|
Chris@29
|
84 #ifndef HAVE_VDSP
|
Chris@29
|
85 #ifndef HAVE_MEDIALIB
|
Chris@29
|
86 #ifndef HAVE_OPENMAX
|
Chris@29
|
87 #ifndef HAVE_SFFT
|
Chris@29
|
88 #error No FFT implementation selected!
|
Chris@29
|
89 #endif
|
Chris@29
|
90 #endif
|
Chris@29
|
91 #endif
|
Chris@29
|
92 #endif
|
Chris@29
|
93 #endif
|
Chris@29
|
94 #endif
|
Chris@29
|
95 #endif
|
Chris@29
|
96 #endif
|
Chris@29
|
97
|
Chris@29
|
98 #include <cmath>
|
Chris@29
|
99 #include <iostream>
|
Chris@29
|
100 #include <map>
|
Chris@29
|
101 #include <cstdio>
|
Chris@29
|
102 #include <cstdlib>
|
Chris@29
|
103 #include <vector>
|
Chris@29
|
104
|
Chris@29
|
105 #ifdef FFT_MEASUREMENT
|
Chris@29
|
106 #ifndef _WIN32
|
Chris@29
|
107 #include <unistd.h>
|
Chris@29
|
108 #endif
|
Chris@29
|
109 #endif
|
Chris@29
|
110
|
Chris@29
|
111 namespace breakfastquay {
|
Chris@29
|
112
|
Chris@29
|
113 class FFTImpl
|
Chris@29
|
114 {
|
Chris@29
|
115 public:
|
Chris@29
|
116 virtual ~FFTImpl() { }
|
Chris@29
|
117
|
Chris@29
|
118 virtual FFT::Precisions getSupportedPrecisions() const = 0;
|
Chris@29
|
119
|
Chris@29
|
120 virtual void initFloat() = 0;
|
Chris@29
|
121 virtual void initDouble() = 0;
|
Chris@29
|
122
|
Chris@29
|
123 virtual void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) = 0;
|
Chris@29
|
124 virtual void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) = 0;
|
Chris@29
|
125 virtual void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) = 0;
|
Chris@29
|
126 virtual void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) = 0;
|
Chris@29
|
127
|
Chris@29
|
128 virtual void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) = 0;
|
Chris@29
|
129 virtual void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) = 0;
|
Chris@29
|
130 virtual void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) = 0;
|
Chris@29
|
131 virtual void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) = 0;
|
Chris@29
|
132
|
Chris@29
|
133 virtual void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) = 0;
|
Chris@29
|
134 virtual void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) = 0;
|
Chris@29
|
135 virtual void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) = 0;
|
Chris@29
|
136 virtual void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) = 0;
|
Chris@29
|
137
|
Chris@29
|
138 virtual void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) = 0;
|
Chris@29
|
139 virtual void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) = 0;
|
Chris@29
|
140 virtual void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) = 0;
|
Chris@29
|
141 virtual void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) = 0;
|
Chris@29
|
142 };
|
Chris@29
|
143
|
Chris@29
|
144 namespace FFTs {
|
Chris@29
|
145
|
Chris@29
|
146 #ifdef HAVE_IPP
|
Chris@29
|
147
|
Chris@29
|
148 class D_IPP : public FFTImpl
|
Chris@29
|
149 {
|
Chris@29
|
150 public:
|
Chris@29
|
151 D_IPP(int size) :
|
Chris@29
|
152 m_size(size), m_fspec(0), m_dspec(0)
|
Chris@29
|
153 {
|
Chris@29
|
154 for (int i = 0; ; ++i) {
|
Chris@29
|
155 if (m_size & (1 << i)) {
|
Chris@29
|
156 m_order = i;
|
Chris@29
|
157 break;
|
Chris@29
|
158 }
|
Chris@29
|
159 }
|
Chris@29
|
160 }
|
Chris@29
|
161
|
Chris@29
|
162 ~D_IPP() {
|
Chris@29
|
163 if (m_fspec) {
|
Chris@29
|
164 ippsFFTFree_R_32f(m_fspec);
|
Chris@29
|
165 ippsFree(m_fbuf);
|
Chris@29
|
166 ippsFree(m_fpacked);
|
Chris@29
|
167 ippsFree(m_fspare);
|
Chris@29
|
168 }
|
Chris@29
|
169 if (m_dspec) {
|
Chris@29
|
170 ippsFFTFree_R_64f(m_dspec);
|
Chris@29
|
171 ippsFree(m_dbuf);
|
Chris@29
|
172 ippsFree(m_dpacked);
|
Chris@29
|
173 ippsFree(m_dspare);
|
Chris@29
|
174 }
|
Chris@29
|
175 }
|
Chris@29
|
176
|
Chris@29
|
177 FFT::Precisions
|
Chris@29
|
178 getSupportedPrecisions() const {
|
Chris@29
|
179 return FFT::SinglePrecision | FFT::DoublePrecision;
|
Chris@29
|
180 }
|
Chris@29
|
181
|
Chris@29
|
182 //!!! rv check
|
Chris@29
|
183
|
Chris@29
|
184 void initFloat() {
|
Chris@29
|
185 if (m_fspec) return;
|
Chris@29
|
186 int specSize, specBufferSize, bufferSize;
|
Chris@29
|
187 ippsFFTGetSize_R_32f(m_order, IPP_FFT_NODIV_BY_ANY, ippAlgHintFast,
|
Chris@29
|
188 &specSize, &specBufferSize, &bufferSize);
|
Chris@29
|
189 m_fbuf = ippsMalloc_8u(bufferSize);
|
Chris@29
|
190 m_fpacked = ippsMalloc_32f(m_size + 2);
|
Chris@29
|
191 m_fspare = ippsMalloc_32f(m_size / 2 + 1);
|
Chris@29
|
192 ippsFFTInitAlloc_R_32f(&m_fspec, m_order, IPP_FFT_NODIV_BY_ANY,
|
Chris@29
|
193 ippAlgHintFast);
|
Chris@29
|
194 }
|
Chris@29
|
195
|
Chris@29
|
196 void initDouble() {
|
Chris@29
|
197 if (m_dspec) return;
|
Chris@29
|
198 int specSize, specBufferSize, bufferSize;
|
Chris@29
|
199 ippsFFTGetSize_R_64f(m_order, IPP_FFT_NODIV_BY_ANY, ippAlgHintFast,
|
Chris@29
|
200 &specSize, &specBufferSize, &bufferSize);
|
Chris@29
|
201 m_dbuf = ippsMalloc_8u(bufferSize);
|
Chris@29
|
202 m_dpacked = ippsMalloc_64f(m_size + 2);
|
Chris@29
|
203 m_dspare = ippsMalloc_64f(m_size / 2 + 1);
|
Chris@29
|
204 ippsFFTInitAlloc_R_64f(&m_dspec, m_order, IPP_FFT_NODIV_BY_ANY,
|
Chris@29
|
205 ippAlgHintFast);
|
Chris@29
|
206 }
|
Chris@29
|
207
|
Chris@29
|
208 void packFloat(const float *BQ_R__ re, const float *BQ_R__ im) {
|
Chris@29
|
209 int index = 0;
|
Chris@29
|
210 const int hs = m_size/2;
|
Chris@29
|
211 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
212 m_fpacked[index++] = re[i];
|
Chris@29
|
213 index++;
|
Chris@29
|
214 }
|
Chris@29
|
215 index = 0;
|
Chris@29
|
216 if (im) {
|
Chris@29
|
217 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
218 index++;
|
Chris@29
|
219 m_fpacked[index++] = im[i];
|
Chris@29
|
220 }
|
Chris@29
|
221 } else {
|
Chris@29
|
222 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
223 index++;
|
Chris@29
|
224 m_fpacked[index++] = 0.f;
|
Chris@29
|
225 }
|
Chris@29
|
226 }
|
Chris@29
|
227 }
|
Chris@29
|
228
|
Chris@29
|
229 void packDouble(const double *BQ_R__ re, const double *BQ_R__ im) {
|
Chris@29
|
230 int index = 0;
|
Chris@29
|
231 const int hs = m_size/2;
|
Chris@29
|
232 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
233 m_dpacked[index++] = re[i];
|
Chris@29
|
234 index++;
|
Chris@29
|
235 }
|
Chris@29
|
236 index = 0;
|
Chris@29
|
237 if (im) {
|
Chris@29
|
238 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
239 index++;
|
Chris@29
|
240 m_dpacked[index++] = im[i];
|
Chris@29
|
241 }
|
Chris@29
|
242 } else {
|
Chris@29
|
243 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
244 index++;
|
Chris@29
|
245 m_dpacked[index++] = 0.0;
|
Chris@29
|
246 }
|
Chris@29
|
247 }
|
Chris@29
|
248 }
|
Chris@29
|
249
|
Chris@29
|
250 void unpackFloat(float *re, float *BQ_R__ im) { // re may be equal to m_fpacked
|
Chris@29
|
251 int index = 0;
|
Chris@29
|
252 const int hs = m_size/2;
|
Chris@29
|
253 if (im) {
|
Chris@29
|
254 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
255 index++;
|
Chris@29
|
256 im[i] = m_fpacked[index++];
|
Chris@29
|
257 }
|
Chris@29
|
258 }
|
Chris@29
|
259 index = 0;
|
Chris@29
|
260 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
261 re[i] = m_fpacked[index++];
|
Chris@29
|
262 index++;
|
Chris@29
|
263 }
|
Chris@29
|
264 }
|
Chris@29
|
265
|
Chris@29
|
266 void unpackDouble(double *re, double *BQ_R__ im) { // re may be equal to m_dpacked
|
Chris@29
|
267 int index = 0;
|
Chris@29
|
268 const int hs = m_size/2;
|
Chris@29
|
269 if (im) {
|
Chris@29
|
270 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
271 index++;
|
Chris@29
|
272 im[i] = m_dpacked[index++];
|
Chris@29
|
273 }
|
Chris@29
|
274 }
|
Chris@29
|
275 index = 0;
|
Chris@29
|
276 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
277 re[i] = m_dpacked[index++];
|
Chris@29
|
278 index++;
|
Chris@29
|
279 }
|
Chris@29
|
280 }
|
Chris@29
|
281
|
Chris@29
|
282 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
283 if (!m_dspec) initDouble();
|
Chris@29
|
284 ippsFFTFwd_RToCCS_64f(realIn, m_dpacked, m_dspec, m_dbuf);
|
Chris@29
|
285 unpackDouble(realOut, imagOut);
|
Chris@29
|
286 }
|
Chris@29
|
287
|
Chris@29
|
288 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
289 if (!m_dspec) initDouble();
|
Chris@29
|
290 ippsFFTFwd_RToCCS_64f(realIn, complexOut, m_dspec, m_dbuf);
|
Chris@29
|
291 }
|
Chris@29
|
292
|
Chris@29
|
293 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
294 if (!m_dspec) initDouble();
|
Chris@29
|
295 ippsFFTFwd_RToCCS_64f(realIn, m_dpacked, m_dspec, m_dbuf);
|
Chris@29
|
296 unpackDouble(m_dpacked, m_dspare);
|
Chris@29
|
297 ippsCartToPolar_64f(m_dpacked, m_dspare, magOut, phaseOut, m_size/2+1);
|
Chris@29
|
298 }
|
Chris@29
|
299
|
Chris@29
|
300 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
301 if (!m_dspec) initDouble();
|
Chris@29
|
302 ippsFFTFwd_RToCCS_64f(realIn, m_dpacked, m_dspec, m_dbuf);
|
Chris@29
|
303 unpackDouble(m_dpacked, m_dspare);
|
Chris@29
|
304 ippsMagnitude_64f(m_dpacked, m_dspare, magOut, m_size/2+1);
|
Chris@29
|
305 }
|
Chris@29
|
306
|
Chris@29
|
307 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
308 if (!m_fspec) initFloat();
|
Chris@29
|
309 ippsFFTFwd_RToCCS_32f(realIn, m_fpacked, m_fspec, m_fbuf);
|
Chris@29
|
310 unpackFloat(realOut, imagOut);
|
Chris@29
|
311 }
|
Chris@29
|
312
|
Chris@29
|
313 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
314 if (!m_fspec) initFloat();
|
Chris@29
|
315 ippsFFTFwd_RToCCS_32f(realIn, complexOut, m_fspec, m_fbuf);
|
Chris@29
|
316 }
|
Chris@29
|
317
|
Chris@29
|
318 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
319 if (!m_fspec) initFloat();
|
Chris@29
|
320 ippsFFTFwd_RToCCS_32f(realIn, m_fpacked, m_fspec, m_fbuf);
|
Chris@29
|
321 unpackFloat(m_fpacked, m_fspare);
|
Chris@29
|
322 ippsCartToPolar_32f(m_fpacked, m_fspare, magOut, phaseOut, m_size/2+1);
|
Chris@29
|
323 }
|
Chris@29
|
324
|
Chris@29
|
325 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
326 if (!m_fspec) initFloat();
|
Chris@29
|
327 ippsFFTFwd_RToCCS_32f(realIn, m_fpacked, m_fspec, m_fbuf);
|
Chris@29
|
328 unpackFloat(m_fpacked, m_fspare);
|
Chris@29
|
329 ippsMagnitude_32f(m_fpacked, m_fspare, magOut, m_size/2+1);
|
Chris@29
|
330 }
|
Chris@29
|
331
|
Chris@29
|
332 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
333 if (!m_dspec) initDouble();
|
Chris@29
|
334 packDouble(realIn, imagIn);
|
Chris@29
|
335 ippsFFTInv_CCSToR_64f(m_dpacked, realOut, m_dspec, m_dbuf);
|
Chris@29
|
336 }
|
Chris@29
|
337
|
Chris@29
|
338 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
339 if (!m_dspec) initDouble();
|
Chris@29
|
340 ippsFFTInv_CCSToR_64f(complexIn, realOut, m_dspec, m_dbuf);
|
Chris@29
|
341 }
|
Chris@29
|
342
|
Chris@29
|
343 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
344 if (!m_dspec) initDouble();
|
Chris@29
|
345 ippsPolarToCart_64f(magIn, phaseIn, realOut, m_dspare, m_size/2+1);
|
Chris@29
|
346 packDouble(realOut, m_dspare); // to m_dpacked
|
Chris@29
|
347 ippsFFTInv_CCSToR_64f(m_dpacked, realOut, m_dspec, m_dbuf);
|
Chris@29
|
348 }
|
Chris@29
|
349
|
Chris@29
|
350 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
351 if (!m_dspec) initDouble();
|
Chris@29
|
352 const int hs1 = m_size/2 + 1;
|
Chris@29
|
353 ippsCopy_64f(magIn, m_dspare, hs1);
|
Chris@29
|
354 ippsAddC_64f_I(0.000001, m_dspare, hs1);
|
Chris@29
|
355 ippsLn_64f_I(m_dspare, hs1);
|
Chris@29
|
356 packDouble(m_dspare, 0);
|
Chris@29
|
357 ippsFFTInv_CCSToR_64f(m_dpacked, cepOut, m_dspec, m_dbuf);
|
Chris@29
|
358 }
|
Chris@29
|
359
|
Chris@29
|
360 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
361 if (!m_fspec) initFloat();
|
Chris@29
|
362 packFloat(realIn, imagIn);
|
Chris@29
|
363 ippsFFTInv_CCSToR_32f(m_fpacked, realOut, m_fspec, m_fbuf);
|
Chris@29
|
364 }
|
Chris@29
|
365
|
Chris@29
|
366 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
367 if (!m_fspec) initFloat();
|
Chris@29
|
368 ippsFFTInv_CCSToR_32f(complexIn, realOut, m_fspec, m_fbuf);
|
Chris@29
|
369 }
|
Chris@29
|
370
|
Chris@29
|
371 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
372 if (!m_fspec) initFloat();
|
Chris@29
|
373 ippsPolarToCart_32f(magIn, phaseIn, realOut, m_fspare, m_size/2+1);
|
Chris@29
|
374 packFloat(realOut, m_fspare); // to m_fpacked
|
Chris@29
|
375 ippsFFTInv_CCSToR_32f(m_fpacked, realOut, m_fspec, m_fbuf);
|
Chris@29
|
376 }
|
Chris@29
|
377
|
Chris@29
|
378 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
379 if (!m_fspec) initFloat();
|
Chris@29
|
380 const int hs1 = m_size/2 + 1;
|
Chris@29
|
381 ippsCopy_32f(magIn, m_fspare, hs1);
|
Chris@29
|
382 ippsAddC_32f_I(0.000001f, m_fspare, hs1);
|
Chris@29
|
383 ippsLn_32f_I(m_fspare, hs1);
|
Chris@29
|
384 packFloat(m_fspare, 0);
|
Chris@29
|
385 ippsFFTInv_CCSToR_32f(m_fpacked, cepOut, m_fspec, m_fbuf);
|
Chris@29
|
386 }
|
Chris@29
|
387
|
Chris@29
|
388 private:
|
Chris@29
|
389 const int m_size;
|
Chris@29
|
390 int m_order;
|
Chris@29
|
391 IppsFFTSpec_R_32f *m_fspec;
|
Chris@29
|
392 IppsFFTSpec_R_64f *m_dspec;
|
Chris@29
|
393 Ipp8u *m_fbuf;
|
Chris@29
|
394 Ipp8u *m_dbuf;
|
Chris@29
|
395 float *m_fpacked;
|
Chris@29
|
396 float *m_fspare;
|
Chris@29
|
397 double *m_dpacked;
|
Chris@29
|
398 double *m_dspare;
|
Chris@29
|
399 };
|
Chris@29
|
400
|
Chris@29
|
401 #endif /* HAVE_IPP */
|
Chris@29
|
402
|
Chris@29
|
403 #ifdef HAVE_VDSP
|
Chris@29
|
404
|
Chris@29
|
405 class D_VDSP : public FFTImpl
|
Chris@29
|
406 {
|
Chris@29
|
407 public:
|
Chris@29
|
408 D_VDSP(int size) :
|
Chris@29
|
409 m_size(size), m_fspec(0), m_dspec(0),
|
Chris@29
|
410 m_fpacked(0), m_fspare(0),
|
Chris@29
|
411 m_dpacked(0), m_dspare(0)
|
Chris@29
|
412 {
|
Chris@29
|
413 for (int i = 0; ; ++i) {
|
Chris@29
|
414 if (m_size & (1 << i)) {
|
Chris@29
|
415 m_order = i;
|
Chris@29
|
416 break;
|
Chris@29
|
417 }
|
Chris@29
|
418 }
|
Chris@29
|
419 }
|
Chris@29
|
420
|
Chris@29
|
421 ~D_VDSP() {
|
Chris@29
|
422 if (m_fspec) {
|
Chris@29
|
423 vDSP_destroy_fftsetup(m_fspec);
|
Chris@29
|
424 deallocate(m_fspare);
|
Chris@29
|
425 deallocate(m_fspare2);
|
Chris@29
|
426 deallocate(m_fbuf->realp);
|
Chris@29
|
427 deallocate(m_fbuf->imagp);
|
Chris@29
|
428 delete m_fbuf;
|
Chris@29
|
429 deallocate(m_fpacked->realp);
|
Chris@29
|
430 deallocate(m_fpacked->imagp);
|
Chris@29
|
431 delete m_fpacked;
|
Chris@29
|
432 }
|
Chris@29
|
433 if (m_dspec) {
|
Chris@29
|
434 vDSP_destroy_fftsetupD(m_dspec);
|
Chris@29
|
435 deallocate(m_dspare);
|
Chris@29
|
436 deallocate(m_dspare2);
|
Chris@29
|
437 deallocate(m_dbuf->realp);
|
Chris@29
|
438 deallocate(m_dbuf->imagp);
|
Chris@29
|
439 delete m_dbuf;
|
Chris@29
|
440 deallocate(m_dpacked->realp);
|
Chris@29
|
441 deallocate(m_dpacked->imagp);
|
Chris@29
|
442 delete m_dpacked;
|
Chris@29
|
443 }
|
Chris@29
|
444 }
|
Chris@29
|
445
|
Chris@29
|
446 FFT::Precisions
|
Chris@29
|
447 getSupportedPrecisions() const {
|
Chris@29
|
448 return FFT::SinglePrecision | FFT::DoublePrecision;
|
Chris@29
|
449 }
|
Chris@29
|
450
|
Chris@29
|
451 //!!! rv check
|
Chris@29
|
452
|
Chris@29
|
453 void initFloat() {
|
Chris@29
|
454 if (m_fspec) return;
|
Chris@29
|
455 m_fspec = vDSP_create_fftsetup(m_order, FFT_RADIX2);
|
Chris@29
|
456 m_fbuf = new DSPSplitComplex;
|
Chris@29
|
457 //!!! "If possible, tempBuffer->realp and tempBuffer->imagp should be 32-byte aligned for best performance."
|
Chris@29
|
458 m_fbuf->realp = allocate<float>(m_size);
|
Chris@29
|
459 m_fbuf->imagp = allocate<float>(m_size);
|
Chris@29
|
460 m_fpacked = new DSPSplitComplex;
|
Chris@29
|
461 m_fpacked->realp = allocate<float>(m_size / 2 + 1);
|
Chris@29
|
462 m_fpacked->imagp = allocate<float>(m_size / 2 + 1);
|
Chris@29
|
463 m_fspare = allocate<float>(m_size + 2);
|
Chris@29
|
464 m_fspare2 = allocate<float>(m_size + 2);
|
Chris@29
|
465 }
|
Chris@29
|
466
|
Chris@29
|
467 void initDouble() {
|
Chris@29
|
468 if (m_dspec) return;
|
Chris@29
|
469 m_dspec = vDSP_create_fftsetupD(m_order, FFT_RADIX2);
|
Chris@29
|
470 m_dbuf = new DSPDoubleSplitComplex;
|
Chris@29
|
471 //!!! "If possible, tempBuffer->realp and tempBuffer->imagp should be 32-byte aligned for best performance."
|
Chris@29
|
472 m_dbuf->realp = allocate<double>(m_size);
|
Chris@29
|
473 m_dbuf->imagp = allocate<double>(m_size);
|
Chris@29
|
474 m_dpacked = new DSPDoubleSplitComplex;
|
Chris@29
|
475 m_dpacked->realp = allocate<double>(m_size / 2 + 1);
|
Chris@29
|
476 m_dpacked->imagp = allocate<double>(m_size / 2 + 1);
|
Chris@29
|
477 m_dspare = allocate<double>(m_size + 2);
|
Chris@29
|
478 m_dspare2 = allocate<double>(m_size + 2);
|
Chris@29
|
479 }
|
Chris@29
|
480
|
Chris@29
|
481 void packReal(const float *BQ_R__ const re) {
|
Chris@29
|
482 // Pack input for forward transform
|
Chris@29
|
483 vDSP_ctoz((DSPComplex *)re, 2, m_fpacked, 1, m_size/2);
|
Chris@29
|
484 }
|
Chris@29
|
485 void packComplex(const float *BQ_R__ const re, const float *BQ_R__ const im) {
|
Chris@29
|
486 // Pack input for inverse transform
|
Chris@29
|
487 if (re) v_copy(m_fpacked->realp, re, m_size/2 + 1);
|
Chris@29
|
488 else v_zero(m_fpacked->realp, m_size/2 + 1);
|
Chris@29
|
489 if (im) v_copy(m_fpacked->imagp, im, m_size/2 + 1);
|
Chris@29
|
490 else v_zero(m_fpacked->imagp, m_size/2 + 1);
|
Chris@29
|
491 fnyq();
|
Chris@29
|
492 }
|
Chris@29
|
493
|
Chris@29
|
494 void unpackReal(float *BQ_R__ const re) {
|
Chris@29
|
495 // Unpack output for inverse transform
|
Chris@29
|
496 vDSP_ztoc(m_fpacked, 1, (DSPComplex *)re, 2, m_size/2);
|
Chris@29
|
497 }
|
Chris@29
|
498 void unpackComplex(float *BQ_R__ const re, float *BQ_R__ const im) {
|
Chris@29
|
499 // Unpack output for forward transform
|
Chris@29
|
500 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
501 float two = 2.f;
|
Chris@29
|
502 vDSP_vsdiv(m_fpacked->realp, 1, &two, re, 1, m_size/2 + 1);
|
Chris@29
|
503 vDSP_vsdiv(m_fpacked->imagp, 1, &two, im, 1, m_size/2 + 1);
|
Chris@29
|
504 }
|
Chris@29
|
505 void unpackComplex(float *BQ_R__ const cplx) {
|
Chris@29
|
506 // Unpack output for forward transform
|
Chris@29
|
507 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
508 const int hs1 = m_size/2 + 1;
|
Chris@29
|
509 for (int i = 0; i < hs1; ++i) {
|
Chris@29
|
510 cplx[i*2] = m_fpacked->realp[i] / 2.f;
|
Chris@29
|
511 cplx[i*2+1] = m_fpacked->imagp[i] / 2.f;
|
Chris@29
|
512 }
|
Chris@29
|
513 }
|
Chris@29
|
514
|
Chris@29
|
515 void packReal(const double *BQ_R__ const re) {
|
Chris@29
|
516 // Pack input for forward transform
|
Chris@29
|
517 vDSP_ctozD((DSPDoubleComplex *)re, 2, m_dpacked, 1, m_size/2);
|
Chris@29
|
518 }
|
Chris@29
|
519 void packComplex(const double *BQ_R__ const re, const double *BQ_R__ const im) {
|
Chris@29
|
520 // Pack input for inverse transform
|
Chris@29
|
521 if (re) v_copy(m_dpacked->realp, re, m_size/2 + 1);
|
Chris@29
|
522 else v_zero(m_dpacked->realp, m_size/2 + 1);
|
Chris@29
|
523 if (im) v_copy(m_dpacked->imagp, im, m_size/2 + 1);
|
Chris@29
|
524 else v_zero(m_dpacked->imagp, m_size/2 + 1);
|
Chris@29
|
525 dnyq();
|
Chris@29
|
526 }
|
Chris@29
|
527
|
Chris@29
|
528 void unpackReal(double *BQ_R__ const re) {
|
Chris@29
|
529 // Unpack output for inverse transform
|
Chris@29
|
530 vDSP_ztocD(m_dpacked, 1, (DSPDoubleComplex *)re, 2, m_size/2);
|
Chris@29
|
531 }
|
Chris@29
|
532 void unpackComplex(double *BQ_R__ const re, double *BQ_R__ const im) {
|
Chris@29
|
533 // Unpack output for forward transform
|
Chris@29
|
534 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
535 double two = 2.0;
|
Chris@29
|
536 vDSP_vsdivD(m_dpacked->realp, 1, &two, re, 1, m_size/2 + 1);
|
Chris@29
|
537 vDSP_vsdivD(m_dpacked->imagp, 1, &two, im, 1, m_size/2 + 1);
|
Chris@29
|
538 }
|
Chris@29
|
539 void unpackComplex(double *BQ_R__ const cplx) {
|
Chris@29
|
540 // Unpack output for forward transform
|
Chris@29
|
541 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
542 const int hs1 = m_size/2 + 1;
|
Chris@29
|
543 for (int i = 0; i < hs1; ++i) {
|
Chris@29
|
544 cplx[i*2] = m_dpacked->realp[i] / 2.0;
|
Chris@29
|
545 cplx[i*2+1] = m_dpacked->imagp[i] / 2.0;
|
Chris@29
|
546 }
|
Chris@29
|
547 }
|
Chris@29
|
548
|
Chris@29
|
549 void fdenyq() {
|
Chris@29
|
550 // for fft result in packed form, unpack the DC and Nyquist bins
|
Chris@29
|
551 const int hs = m_size/2;
|
Chris@29
|
552 m_fpacked->realp[hs] = m_fpacked->imagp[0];
|
Chris@29
|
553 m_fpacked->imagp[hs] = 0.f;
|
Chris@29
|
554 m_fpacked->imagp[0] = 0.f;
|
Chris@29
|
555 }
|
Chris@29
|
556 void ddenyq() {
|
Chris@29
|
557 // for fft result in packed form, unpack the DC and Nyquist bins
|
Chris@29
|
558 const int hs = m_size/2;
|
Chris@29
|
559 m_dpacked->realp[hs] = m_dpacked->imagp[0];
|
Chris@29
|
560 m_dpacked->imagp[hs] = 0.;
|
Chris@29
|
561 m_dpacked->imagp[0] = 0.;
|
Chris@29
|
562 }
|
Chris@29
|
563
|
Chris@29
|
564 void fnyq() {
|
Chris@29
|
565 // for ifft input in packed form, pack the DC and Nyquist bins
|
Chris@29
|
566 const int hs = m_size/2;
|
Chris@29
|
567 m_fpacked->imagp[0] = m_fpacked->realp[hs];
|
Chris@29
|
568 m_fpacked->realp[hs] = 0.f;
|
Chris@29
|
569 m_fpacked->imagp[hs] = 0.f;
|
Chris@29
|
570 }
|
Chris@29
|
571 void dnyq() {
|
Chris@29
|
572 // for ifft input in packed form, pack the DC and Nyquist bins
|
Chris@29
|
573 const int hs = m_size/2;
|
Chris@29
|
574 m_dpacked->imagp[0] = m_dpacked->realp[hs];
|
Chris@29
|
575 m_dpacked->realp[hs] = 0.;
|
Chris@29
|
576 m_dpacked->imagp[hs] = 0.;
|
Chris@29
|
577 }
|
Chris@29
|
578
|
Chris@29
|
579 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
580 if (!m_dspec) initDouble();
|
Chris@29
|
581 packReal(realIn);
|
Chris@29
|
582 vDSP_fft_zriptD(m_dspec, m_dpacked, 1, m_dbuf, m_order, FFT_FORWARD);
|
Chris@29
|
583 ddenyq();
|
Chris@29
|
584 unpackComplex(realOut, imagOut);
|
Chris@29
|
585 }
|
Chris@29
|
586
|
Chris@29
|
587 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
588 if (!m_dspec) initDouble();
|
Chris@29
|
589 packReal(realIn);
|
Chris@29
|
590 vDSP_fft_zriptD(m_dspec, m_dpacked, 1, m_dbuf, m_order, FFT_FORWARD);
|
Chris@29
|
591 ddenyq();
|
Chris@29
|
592 unpackComplex(complexOut);
|
Chris@29
|
593 }
|
Chris@29
|
594
|
Chris@29
|
595 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
596 if (!m_dspec) initDouble();
|
Chris@29
|
597 const int hs1 = m_size/2+1;
|
Chris@29
|
598 packReal(realIn);
|
Chris@29
|
599 vDSP_fft_zriptD(m_dspec, m_dpacked, 1, m_dbuf, m_order, FFT_FORWARD);
|
Chris@29
|
600 ddenyq();
|
Chris@29
|
601 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
602 for (int i = 0; i < hs1; ++i) m_dpacked->realp[i] /= 2.0;
|
Chris@29
|
603 for (int i = 0; i < hs1; ++i) m_dpacked->imagp[i] /= 2.0;
|
Chris@29
|
604 v_cartesian_to_polar(magOut, phaseOut,
|
Chris@29
|
605 m_dpacked->realp, m_dpacked->imagp, hs1);
|
Chris@29
|
606 }
|
Chris@29
|
607
|
Chris@29
|
608 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
609 if (!m_dspec) initDouble();
|
Chris@29
|
610 packReal(realIn);
|
Chris@29
|
611 vDSP_fft_zriptD(m_dspec, m_dpacked, 1, m_dbuf, m_order, FFT_FORWARD);
|
Chris@29
|
612 ddenyq();
|
Chris@29
|
613 const int hs1 = m_size/2+1;
|
Chris@29
|
614 vDSP_zvmagsD(m_dpacked, 1, m_dspare, 1, hs1);
|
Chris@29
|
615 vvsqrt(m_dspare2, m_dspare, &hs1);
|
Chris@29
|
616 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
617 double two = 2.0;
|
Chris@29
|
618 vDSP_vsdivD(m_dspare2, 1, &two, magOut, 1, hs1);
|
Chris@29
|
619 }
|
Chris@29
|
620
|
Chris@29
|
621 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
622 if (!m_fspec) initFloat();
|
Chris@29
|
623 packReal(realIn);
|
Chris@29
|
624 vDSP_fft_zript(m_fspec, m_fpacked, 1, m_fbuf, m_order, FFT_FORWARD);
|
Chris@29
|
625 fdenyq();
|
Chris@29
|
626 unpackComplex(realOut, imagOut);
|
Chris@29
|
627 }
|
Chris@29
|
628
|
Chris@29
|
629 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
630 if (!m_fspec) initFloat();
|
Chris@29
|
631 packReal(realIn);
|
Chris@29
|
632 vDSP_fft_zript(m_fspec, m_fpacked, 1, m_fbuf, m_order, FFT_FORWARD);
|
Chris@29
|
633 fdenyq();
|
Chris@29
|
634 unpackComplex(complexOut);
|
Chris@29
|
635 }
|
Chris@29
|
636
|
Chris@29
|
637 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
638 if (!m_fspec) initFloat();
|
Chris@29
|
639 const int hs1 = m_size/2+1;
|
Chris@29
|
640 packReal(realIn);
|
Chris@29
|
641 vDSP_fft_zript(m_fspec, m_fpacked, 1, m_fbuf, m_order, FFT_FORWARD);
|
Chris@29
|
642 fdenyq();
|
Chris@29
|
643 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
644 for (int i = 0; i < hs1; ++i) m_fpacked->realp[i] /= 2.f;
|
Chris@29
|
645 for (int i = 0; i < hs1; ++i) m_fpacked->imagp[i] /= 2.f;
|
Chris@29
|
646 v_cartesian_to_polar(magOut, phaseOut,
|
Chris@29
|
647 m_fpacked->realp, m_fpacked->imagp, hs1);
|
Chris@29
|
648 }
|
Chris@29
|
649
|
Chris@29
|
650 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
651 if (!m_fspec) initFloat();
|
Chris@29
|
652 packReal(realIn);
|
Chris@29
|
653 vDSP_fft_zript(m_fspec, m_fpacked, 1, m_fbuf, m_order, FFT_FORWARD);
|
Chris@29
|
654 fdenyq();
|
Chris@29
|
655 const int hs1 = m_size/2 + 1;
|
Chris@29
|
656 vDSP_zvmags(m_fpacked, 1, m_fspare, 1, hs1);
|
Chris@29
|
657 vvsqrtf(m_fspare2, m_fspare, &hs1);
|
Chris@29
|
658 // vDSP forward FFTs are scaled 2x (for some reason)
|
Chris@29
|
659 float two = 2.f;
|
Chris@29
|
660 vDSP_vsdiv(m_fspare2, 1, &two, magOut, 1, hs1);
|
Chris@29
|
661 }
|
Chris@29
|
662
|
Chris@29
|
663 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
664 if (!m_dspec) initDouble();
|
Chris@29
|
665 packComplex(realIn, imagIn);
|
Chris@29
|
666 vDSP_fft_zriptD(m_dspec, m_dpacked, 1, m_dbuf, m_order, FFT_INVERSE);
|
Chris@29
|
667 unpackReal(realOut);
|
Chris@29
|
668 }
|
Chris@29
|
669
|
Chris@29
|
670 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
671 if (!m_dspec) initDouble();
|
Chris@29
|
672 double *d[2] = { m_dpacked->realp, m_dpacked->imagp };
|
Chris@29
|
673 v_deinterleave(d, complexIn, 2, m_size/2 + 1);
|
Chris@29
|
674 vDSP_fft_zriptD(m_dspec, m_dpacked, 1, m_dbuf, m_order, FFT_INVERSE);
|
Chris@29
|
675 unpackReal(realOut);
|
Chris@29
|
676 }
|
Chris@29
|
677
|
Chris@29
|
678 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
679 if (!m_dspec) initDouble();
|
Chris@29
|
680 const int hs1 = m_size/2+1;
|
Chris@29
|
681 vvsincos(m_dpacked->imagp, m_dpacked->realp, phaseIn, &hs1);
|
Chris@29
|
682 double *const rp = m_dpacked->realp;
|
Chris@29
|
683 double *const ip = m_dpacked->imagp;
|
Chris@29
|
684 for (int i = 0; i < hs1; ++i) rp[i] *= magIn[i];
|
Chris@29
|
685 for (int i = 0; i < hs1; ++i) ip[i] *= magIn[i];
|
Chris@29
|
686 dnyq();
|
Chris@29
|
687 vDSP_fft_zriptD(m_dspec, m_dpacked, 1, m_dbuf, m_order, FFT_INVERSE);
|
Chris@29
|
688 unpackReal(realOut);
|
Chris@29
|
689 }
|
Chris@29
|
690
|
Chris@29
|
691 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
692 if (!m_dspec) initDouble();
|
Chris@29
|
693 const int hs1 = m_size/2 + 1;
|
Chris@29
|
694 v_copy(m_dspare, magIn, hs1);
|
Chris@29
|
695 for (int i = 0; i < hs1; ++i) m_dspare[i] += 0.000001;
|
Chris@29
|
696 vvlog(m_dspare2, m_dspare, &hs1);
|
Chris@29
|
697 inverse(m_dspare2, 0, cepOut);
|
Chris@29
|
698 }
|
Chris@29
|
699
|
Chris@29
|
700 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
701 if (!m_fspec) initFloat();
|
Chris@29
|
702 packComplex(realIn, imagIn);
|
Chris@29
|
703 vDSP_fft_zript(m_fspec, m_fpacked, 1, m_fbuf, m_order, FFT_INVERSE);
|
Chris@29
|
704 unpackReal(realOut);
|
Chris@29
|
705 }
|
Chris@29
|
706
|
Chris@29
|
707 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
708 if (!m_fspec) initFloat();
|
Chris@29
|
709 float *f[2] = { m_fpacked->realp, m_fpacked->imagp };
|
Chris@29
|
710 v_deinterleave(f, complexIn, 2, m_size/2 + 1);
|
Chris@29
|
711 vDSP_fft_zript(m_fspec, m_fpacked, 1, m_fbuf, m_order, FFT_INVERSE);
|
Chris@29
|
712 unpackReal(realOut);
|
Chris@29
|
713 }
|
Chris@29
|
714
|
Chris@29
|
715 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
716 if (!m_fspec) initFloat();
|
Chris@29
|
717
|
Chris@29
|
718 const int hs1 = m_size/2+1;
|
Chris@29
|
719 vvsincosf(m_fpacked->imagp, m_fpacked->realp, phaseIn, &hs1);
|
Chris@29
|
720 float *const rp = m_fpacked->realp;
|
Chris@29
|
721 float *const ip = m_fpacked->imagp;
|
Chris@29
|
722 for (int i = 0; i < hs1; ++i) rp[i] *= magIn[i];
|
Chris@29
|
723 for (int i = 0; i < hs1; ++i) ip[i] *= magIn[i];
|
Chris@29
|
724 fnyq();
|
Chris@29
|
725 vDSP_fft_zript(m_fspec, m_fpacked, 1, m_fbuf, m_order, FFT_INVERSE);
|
Chris@29
|
726 unpackReal(realOut);
|
Chris@29
|
727 }
|
Chris@29
|
728
|
Chris@29
|
729 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
730 if (!m_fspec) initFloat();
|
Chris@29
|
731 const int hs1 = m_size/2 + 1;
|
Chris@29
|
732 v_copy(m_fspare, magIn, hs1);
|
Chris@29
|
733 for (int i = 0; i < hs1; ++i) m_fspare[i] += 0.000001f;
|
Chris@29
|
734 vvlogf(m_fspare2, m_fspare, &hs1);
|
Chris@29
|
735 inverse(m_fspare2, 0, cepOut);
|
Chris@29
|
736 }
|
Chris@29
|
737
|
Chris@29
|
738 private:
|
Chris@29
|
739 const int m_size;
|
Chris@29
|
740 int m_order;
|
Chris@29
|
741 FFTSetup m_fspec;
|
Chris@29
|
742 FFTSetupD m_dspec;
|
Chris@29
|
743 DSPSplitComplex *m_fbuf;
|
Chris@29
|
744 DSPDoubleSplitComplex *m_dbuf;
|
Chris@29
|
745 DSPSplitComplex *m_fpacked;
|
Chris@29
|
746 float *m_fspare;
|
Chris@29
|
747 float *m_fspare2;
|
Chris@29
|
748 DSPDoubleSplitComplex *m_dpacked;
|
Chris@29
|
749 double *m_dspare;
|
Chris@29
|
750 double *m_dspare2;
|
Chris@29
|
751 };
|
Chris@29
|
752
|
Chris@29
|
753 #endif /* HAVE_VDSP */
|
Chris@29
|
754
|
Chris@29
|
755 #ifdef HAVE_MEDIALIB
|
Chris@29
|
756
|
Chris@29
|
757 class D_MEDIALIB : public FFTImpl
|
Chris@29
|
758 {
|
Chris@29
|
759 public:
|
Chris@29
|
760 D_MEDIALIB(int size) :
|
Chris@29
|
761 m_size(size),
|
Chris@29
|
762 m_dpacked(0), m_fpacked(0)
|
Chris@29
|
763 {
|
Chris@29
|
764 for (int i = 0; ; ++i) {
|
Chris@29
|
765 if (m_size & (1 << i)) {
|
Chris@29
|
766 m_order = i;
|
Chris@29
|
767 break;
|
Chris@29
|
768 }
|
Chris@29
|
769 }
|
Chris@29
|
770 }
|
Chris@29
|
771
|
Chris@29
|
772 ~D_MEDIALIB() {
|
Chris@29
|
773 if (m_dpacked) {
|
Chris@29
|
774 deallocate(m_dpacked);
|
Chris@29
|
775 }
|
Chris@29
|
776 if (m_fpacked) {
|
Chris@29
|
777 deallocate(m_fpacked);
|
Chris@29
|
778 }
|
Chris@29
|
779 }
|
Chris@29
|
780
|
Chris@29
|
781 FFT::Precisions
|
Chris@29
|
782 getSupportedPrecisions() const {
|
Chris@29
|
783 return FFT::SinglePrecision | FFT::DoublePrecision;
|
Chris@29
|
784 }
|
Chris@29
|
785
|
Chris@29
|
786 //!!! rv check
|
Chris@29
|
787
|
Chris@29
|
788 void initFloat() {
|
Chris@29
|
789 m_fpacked = allocate<float>(m_size*2);
|
Chris@29
|
790 }
|
Chris@29
|
791
|
Chris@29
|
792 void initDouble() {
|
Chris@29
|
793 m_dpacked = allocate<double>(m_size*2);
|
Chris@29
|
794 }
|
Chris@29
|
795
|
Chris@29
|
796 void packFloatConjugates() {
|
Chris@29
|
797 const int hs = m_size / 2;
|
Chris@29
|
798 for (int i = 1; i <= hs; ++i) {
|
Chris@29
|
799 m_fpacked[(m_size-i)*2] = m_fpacked[2*i];
|
Chris@29
|
800 m_fpacked[(m_size-i)*2 + 1] = -m_fpacked[2*i + 1];
|
Chris@29
|
801 }
|
Chris@29
|
802 }
|
Chris@29
|
803
|
Chris@29
|
804 void packDoubleConjugates() {
|
Chris@29
|
805 const int hs = m_size / 2;
|
Chris@29
|
806 for (int i = 1; i <= hs; ++i) {
|
Chris@29
|
807 m_dpacked[(m_size-i)*2] = m_dpacked[2*i];
|
Chris@29
|
808 m_dpacked[(m_size-i)*2 + 1] = -m_dpacked[2*i + 1];
|
Chris@29
|
809 }
|
Chris@29
|
810 }
|
Chris@29
|
811
|
Chris@29
|
812 void packFloat(const float *BQ_R__ re, const float *BQ_R__ im) {
|
Chris@29
|
813 int index = 0;
|
Chris@29
|
814 const int hs = m_size/2;
|
Chris@29
|
815 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
816 m_fpacked[index++] = re[i];
|
Chris@29
|
817 index++;
|
Chris@29
|
818 }
|
Chris@29
|
819 index = 0;
|
Chris@29
|
820 if (im) {
|
Chris@29
|
821 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
822 index++;
|
Chris@29
|
823 m_fpacked[index++] = im[i];
|
Chris@29
|
824 }
|
Chris@29
|
825 } else {
|
Chris@29
|
826 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
827 index++;
|
Chris@29
|
828 m_fpacked[index++] = 0.f;
|
Chris@29
|
829 }
|
Chris@29
|
830 }
|
Chris@29
|
831 packFloatConjugates();
|
Chris@29
|
832 }
|
Chris@29
|
833
|
Chris@29
|
834 void packDouble(const double *BQ_R__ re, const double *BQ_R__ im) {
|
Chris@29
|
835 int index = 0;
|
Chris@29
|
836 const int hs = m_size/2;
|
Chris@29
|
837 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
838 m_dpacked[index++] = re[i];
|
Chris@29
|
839 index++;
|
Chris@29
|
840 }
|
Chris@29
|
841 index = 0;
|
Chris@29
|
842 if (im) {
|
Chris@29
|
843 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
844 index++;
|
Chris@29
|
845 m_dpacked[index++] = im[i];
|
Chris@29
|
846 }
|
Chris@29
|
847 } else {
|
Chris@29
|
848 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
849 index++;
|
Chris@29
|
850 m_dpacked[index++] = 0.0;
|
Chris@29
|
851 }
|
Chris@29
|
852 }
|
Chris@29
|
853 packDoubleConjugates();
|
Chris@29
|
854 }
|
Chris@29
|
855
|
Chris@29
|
856 void unpackFloat(float *re, float *BQ_R__ im) { // re may be equal to m_fpacked
|
Chris@29
|
857 int index = 0;
|
Chris@29
|
858 const int hs = m_size/2;
|
Chris@29
|
859 if (im) {
|
Chris@29
|
860 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
861 index++;
|
Chris@29
|
862 im[i] = m_fpacked[index++];
|
Chris@29
|
863 }
|
Chris@29
|
864 }
|
Chris@29
|
865 index = 0;
|
Chris@29
|
866 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
867 re[i] = m_fpacked[index++];
|
Chris@29
|
868 index++;
|
Chris@29
|
869 }
|
Chris@29
|
870 }
|
Chris@29
|
871
|
Chris@29
|
872 void unpackDouble(double *re, double *BQ_R__ im) { // re may be equal to m_dpacked
|
Chris@29
|
873 int index = 0;
|
Chris@29
|
874 const int hs = m_size/2;
|
Chris@29
|
875 if (im) {
|
Chris@29
|
876 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
877 index++;
|
Chris@29
|
878 im[i] = m_dpacked[index++];
|
Chris@29
|
879 }
|
Chris@29
|
880 }
|
Chris@29
|
881 index = 0;
|
Chris@29
|
882 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
883 re[i] = m_dpacked[index++];
|
Chris@29
|
884 index++;
|
Chris@29
|
885 }
|
Chris@29
|
886 }
|
Chris@29
|
887
|
Chris@29
|
888 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
889 if (!m_dpacked) initDouble();
|
Chris@29
|
890 mlib_SignalFFT_1_D64C_D64(m_dpacked, realIn, m_order);
|
Chris@29
|
891 unpackDouble(realOut, imagOut);
|
Chris@29
|
892 }
|
Chris@29
|
893
|
Chris@29
|
894 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
895 if (!m_dpacked) initDouble();
|
Chris@29
|
896 // mlib FFT gives the whole redundant complex result
|
Chris@29
|
897 mlib_SignalFFT_1_D64C_D64(m_dpacked, realIn, m_order);
|
Chris@29
|
898 v_copy(complexOut, m_dpacked, m_size + 2);
|
Chris@29
|
899 }
|
Chris@29
|
900
|
Chris@29
|
901 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
902 if (!m_dpacked) initDouble();
|
Chris@29
|
903 mlib_SignalFFT_1_D64C_D64(m_dpacked, realIn, m_order);
|
Chris@29
|
904 const int hs = m_size/2;
|
Chris@29
|
905 int index = 0;
|
Chris@29
|
906 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
907 int reali = index;
|
Chris@29
|
908 ++index;
|
Chris@29
|
909 magOut[i] = sqrt(m_dpacked[reali] * m_dpacked[reali] +
|
Chris@29
|
910 m_dpacked[index] * m_dpacked[index]);
|
Chris@29
|
911 phaseOut[i] = atan2(m_dpacked[index], m_dpacked[reali]) ;
|
Chris@29
|
912 ++index;
|
Chris@29
|
913 }
|
Chris@29
|
914 }
|
Chris@29
|
915
|
Chris@29
|
916 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
917 if (!m_dpacked) initDouble();
|
Chris@29
|
918 mlib_SignalFFT_1_D64C_D64(m_dpacked, realIn, m_order);
|
Chris@29
|
919 const int hs = m_size/2;
|
Chris@29
|
920 int index = 0;
|
Chris@29
|
921 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
922 int reali = index;
|
Chris@29
|
923 ++index;
|
Chris@29
|
924 magOut[i] = sqrt(m_dpacked[reali] * m_dpacked[reali] +
|
Chris@29
|
925 m_dpacked[index] * m_dpacked[index]);
|
Chris@29
|
926 ++index;
|
Chris@29
|
927 }
|
Chris@29
|
928 }
|
Chris@29
|
929
|
Chris@29
|
930 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
931 if (!m_fpacked) initFloat();
|
Chris@29
|
932 mlib_SignalFFT_1_F32C_F32(m_fpacked, realIn, m_order);
|
Chris@29
|
933 unpackFloat(realOut, imagOut);
|
Chris@29
|
934 }
|
Chris@29
|
935
|
Chris@29
|
936 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
937 if (!m_fpacked) initFloat();
|
Chris@29
|
938 // mlib FFT gives the whole redundant complex result
|
Chris@29
|
939 mlib_SignalFFT_1_F32C_F32(m_fpacked, realIn, m_order);
|
Chris@29
|
940 v_copy(complexOut, m_fpacked, m_size + 2);
|
Chris@29
|
941 }
|
Chris@29
|
942
|
Chris@29
|
943 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
944 if (!m_fpacked) initFloat();
|
Chris@29
|
945 mlib_SignalFFT_1_F32C_F32(m_fpacked, realIn, m_order);
|
Chris@29
|
946 const int hs = m_size/2;
|
Chris@29
|
947 int index = 0;
|
Chris@29
|
948 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
949 int reali = index;
|
Chris@29
|
950 ++index;
|
Chris@29
|
951 magOut[i] = sqrtf(m_fpacked[reali] * m_fpacked[reali] +
|
Chris@29
|
952 m_fpacked[index] * m_fpacked[index]);
|
Chris@29
|
953 phaseOut[i] = atan2f(m_fpacked[index], m_fpacked[reali]);
|
Chris@29
|
954 ++index;
|
Chris@29
|
955 }
|
Chris@29
|
956 }
|
Chris@29
|
957
|
Chris@29
|
958 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
959 if (!m_fpacked) initFloat();
|
Chris@29
|
960 mlib_SignalFFT_1_F32C_F32(m_fpacked, realIn, m_order);
|
Chris@29
|
961 const int hs = m_size/2;
|
Chris@29
|
962 int index = 0;
|
Chris@29
|
963 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
964 int reali = index;
|
Chris@29
|
965 ++index;
|
Chris@29
|
966 magOut[i] = sqrtf(m_fpacked[reali] * m_fpacked[reali] +
|
Chris@29
|
967 m_fpacked[index] * m_fpacked[index]);
|
Chris@29
|
968 ++index;
|
Chris@29
|
969 }
|
Chris@29
|
970 }
|
Chris@29
|
971
|
Chris@29
|
972 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
973 if (!m_dpacked) initDouble();
|
Chris@29
|
974 packDouble(realIn, imagIn);
|
Chris@29
|
975 mlib_SignalIFFT_2_D64_D64C(realOut, m_dpacked, m_order);
|
Chris@29
|
976 }
|
Chris@29
|
977
|
Chris@29
|
978 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
979 if (!m_dpacked) initDouble();
|
Chris@29
|
980 v_copy(m_dpacked, complexIn, m_size + 2);
|
Chris@29
|
981 packDoubleConjugates();
|
Chris@29
|
982 mlib_SignalIFFT_2_D64_D64C(realOut, m_dpacked, m_order);
|
Chris@29
|
983 }
|
Chris@29
|
984
|
Chris@29
|
985 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
986 if (!m_dpacked) initDouble();
|
Chris@29
|
987 const int hs = m_size/2;
|
Chris@29
|
988 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
989 double real = magIn[i] * cos(phaseIn[i]);
|
Chris@29
|
990 double imag = magIn[i] * sin(phaseIn[i]);
|
Chris@29
|
991 m_dpacked[i*2] = real;
|
Chris@29
|
992 m_dpacked[i*2 + 1] = imag;
|
Chris@29
|
993 }
|
Chris@29
|
994 packDoubleConjugates();
|
Chris@29
|
995 mlib_SignalIFFT_2_D64_D64C(realOut, m_dpacked, m_order);
|
Chris@29
|
996 }
|
Chris@29
|
997
|
Chris@29
|
998 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
999 if (!m_dpacked) initDouble();
|
Chris@29
|
1000 const int hs = m_size/2;
|
Chris@29
|
1001 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1002 m_dpacked[i*2] = log(magIn[i] + 0.000001);
|
Chris@29
|
1003 m_dpacked[i*2 + 1] = 0.0;
|
Chris@29
|
1004 }
|
Chris@29
|
1005 packDoubleConjugates();
|
Chris@29
|
1006 mlib_SignalIFFT_2_D64_D64C(cepOut, m_dpacked, m_order);
|
Chris@29
|
1007 }
|
Chris@29
|
1008
|
Chris@29
|
1009 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
1010 if (!m_fpacked) initFloat();
|
Chris@29
|
1011 packFloat(realIn, imagIn);
|
Chris@29
|
1012 mlib_SignalIFFT_2_F32_F32C(realOut, m_fpacked, m_order);
|
Chris@29
|
1013 }
|
Chris@29
|
1014
|
Chris@29
|
1015 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
1016 if (!m_fpacked) initFloat();
|
Chris@29
|
1017 v_convert(m_fpacked, complexIn, m_size + 2);
|
Chris@29
|
1018 packFloatConjugates();
|
Chris@29
|
1019 mlib_SignalIFFT_2_F32_F32C(realOut, m_fpacked, m_order);
|
Chris@29
|
1020 }
|
Chris@29
|
1021
|
Chris@29
|
1022 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
1023 if (!m_fpacked) initFloat();
|
Chris@29
|
1024 const int hs = m_size/2;
|
Chris@29
|
1025 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1026 double real = magIn[i] * cos(phaseIn[i]);
|
Chris@29
|
1027 double imag = magIn[i] * sin(phaseIn[i]);
|
Chris@29
|
1028 m_fpacked[i*2] = real;
|
Chris@29
|
1029 m_fpacked[i*2 + 1] = imag;
|
Chris@29
|
1030 }
|
Chris@29
|
1031 packFloatConjugates();
|
Chris@29
|
1032 mlib_SignalIFFT_2_F32_F32C(realOut, m_fpacked, m_order);
|
Chris@29
|
1033 }
|
Chris@29
|
1034
|
Chris@29
|
1035 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
1036 if (!m_fpacked) initFloat();
|
Chris@29
|
1037 const int hs = m_size/2;
|
Chris@29
|
1038 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1039 m_fpacked[i*2] = logf(magIn[i] + 0.000001);
|
Chris@29
|
1040 m_fpacked[i*2 + 1] = 0.f;
|
Chris@29
|
1041 }
|
Chris@29
|
1042 packFloatConjugates();
|
Chris@29
|
1043 mlib_SignalIFFT_2_F32_F32C(cepOut, m_fpacked, m_order);
|
Chris@29
|
1044 }
|
Chris@29
|
1045
|
Chris@29
|
1046 private:
|
Chris@29
|
1047 const int m_size;
|
Chris@29
|
1048 int m_order;
|
Chris@29
|
1049 double *m_dpacked;
|
Chris@29
|
1050 float *m_fpacked;
|
Chris@29
|
1051 };
|
Chris@29
|
1052
|
Chris@29
|
1053 #endif /* HAVE_MEDIALIB */
|
Chris@29
|
1054
|
Chris@29
|
1055 #ifdef HAVE_OPENMAX
|
Chris@29
|
1056
|
Chris@29
|
1057 class D_OPENMAX : public FFTImpl
|
Chris@29
|
1058 {
|
Chris@29
|
1059 // Convert a signed 32-bit integer to a float in the range [-1,1)
|
Chris@29
|
1060 static inline float i2f(OMX_S32 i)
|
Chris@29
|
1061 {
|
Chris@29
|
1062 return float(i) / float(OMX_MAX_S32);
|
Chris@29
|
1063 }
|
Chris@29
|
1064
|
Chris@29
|
1065 // Convert a signed 32-bit integer to a double in the range [-1,1)
|
Chris@29
|
1066 static inline double i2d(OMX_S32 i)
|
Chris@29
|
1067 {
|
Chris@29
|
1068 return double(i) / double(OMX_MAX_S32);
|
Chris@29
|
1069 }
|
Chris@29
|
1070
|
Chris@29
|
1071 // Convert a float in the range [-1,1) to a signed 32-bit integer
|
Chris@29
|
1072 static inline OMX_S32 f2i(float f)
|
Chris@29
|
1073 {
|
Chris@29
|
1074 return OMX_S32(f * OMX_MAX_S32);
|
Chris@29
|
1075 }
|
Chris@29
|
1076
|
Chris@29
|
1077 // Convert a double in the range [-1,1) to a signed 32-bit integer
|
Chris@29
|
1078 static inline OMX_S32 d2i(double d)
|
Chris@29
|
1079 {
|
Chris@29
|
1080 return OMX_S32(d * OMX_MAX_S32);
|
Chris@29
|
1081 }
|
Chris@29
|
1082
|
Chris@29
|
1083 public:
|
Chris@29
|
1084 D_OPENMAX(int size) :
|
Chris@29
|
1085 m_size(size),
|
Chris@29
|
1086 m_packed(0)
|
Chris@29
|
1087 {
|
Chris@29
|
1088 for (int i = 0; ; ++i) {
|
Chris@29
|
1089 if (m_size & (1 << i)) {
|
Chris@29
|
1090 m_order = i;
|
Chris@29
|
1091 break;
|
Chris@29
|
1092 }
|
Chris@29
|
1093 }
|
Chris@29
|
1094 }
|
Chris@29
|
1095
|
Chris@29
|
1096 ~D_OPENMAX() {
|
Chris@29
|
1097 if (m_packed) {
|
Chris@29
|
1098 deallocate(m_packed);
|
Chris@29
|
1099 deallocate(m_buf);
|
Chris@29
|
1100 deallocate(m_fbuf);
|
Chris@29
|
1101 deallocate(m_spec);
|
Chris@29
|
1102 }
|
Chris@29
|
1103 }
|
Chris@29
|
1104
|
Chris@29
|
1105 FFT::Precisions
|
Chris@29
|
1106 getSupportedPrecisions() const {
|
Chris@29
|
1107 return FFT::SinglePrecision;
|
Chris@29
|
1108 }
|
Chris@29
|
1109
|
Chris@29
|
1110 //!!! rv check
|
Chris@29
|
1111
|
Chris@29
|
1112 // The OpenMAX implementation uses a fixed-point representation in
|
Chris@29
|
1113 // 32-bit signed integers, with a downward scaling factor (0-32
|
Chris@29
|
1114 // bits) supplied as an argument to the FFT function.
|
Chris@29
|
1115
|
Chris@29
|
1116 void initFloat() {
|
Chris@29
|
1117 initDouble();
|
Chris@29
|
1118 }
|
Chris@29
|
1119
|
Chris@29
|
1120 void initDouble() {
|
Chris@29
|
1121 if (!m_packed) {
|
Chris@29
|
1122 m_buf = allocate<OMX_S32>(m_size);
|
Chris@29
|
1123 m_packed = allocate<OMX_S32>(m_size*2 + 2);
|
Chris@29
|
1124 m_fbuf = allocate<float>(m_size*2 + 2);
|
Chris@29
|
1125 OMX_INT sz = 0;
|
Chris@29
|
1126 omxSP_FFTGetBufSize_R_S32(m_order, &sz);
|
Chris@29
|
1127 m_spec = (OMXFFTSpec_R_S32 *)allocate<char>(sz);
|
Chris@29
|
1128 omxSP_FFTInit_R_S32(m_spec, m_order);
|
Chris@29
|
1129 }
|
Chris@29
|
1130 }
|
Chris@29
|
1131
|
Chris@29
|
1132 void packFloat(const float *BQ_R__ re) {
|
Chris@29
|
1133 // prepare fixed point input for forward transform
|
Chris@29
|
1134 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
1135 m_buf[i] = f2i(re[i]);
|
Chris@29
|
1136 }
|
Chris@29
|
1137 }
|
Chris@29
|
1138
|
Chris@29
|
1139 void packDouble(const double *BQ_R__ re) {
|
Chris@29
|
1140 // prepare fixed point input for forward transform
|
Chris@29
|
1141 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
1142 m_buf[i] = d2i(re[i]);
|
Chris@29
|
1143 }
|
Chris@29
|
1144 }
|
Chris@29
|
1145
|
Chris@29
|
1146 void unpackFloat(float *BQ_R__ re, float *BQ_R__ im) {
|
Chris@29
|
1147 // convert fixed point output for forward transform
|
Chris@29
|
1148 int index = 0;
|
Chris@29
|
1149 const int hs = m_size/2;
|
Chris@29
|
1150 if (im) {
|
Chris@29
|
1151 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1152 index++;
|
Chris@29
|
1153 im[i] = i2f(m_packed[index++]);
|
Chris@29
|
1154 }
|
Chris@29
|
1155 v_scale(im, m_size, hs + 1);
|
Chris@29
|
1156 }
|
Chris@29
|
1157 index = 0;
|
Chris@29
|
1158 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1159 re[i] = i2f(m_packed[index++]);
|
Chris@29
|
1160 index++;
|
Chris@29
|
1161 }
|
Chris@29
|
1162 v_scale(re, m_size, hs + 1);
|
Chris@29
|
1163 }
|
Chris@29
|
1164
|
Chris@29
|
1165 void unpackDouble(double *BQ_R__ re, double *BQ_R__ im) {
|
Chris@29
|
1166 // convert fixed point output for forward transform
|
Chris@29
|
1167 int index = 0;
|
Chris@29
|
1168 const int hs = m_size/2;
|
Chris@29
|
1169 if (im) {
|
Chris@29
|
1170 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1171 index++;
|
Chris@29
|
1172 im[i] = i2d(m_packed[index++]);
|
Chris@29
|
1173 }
|
Chris@29
|
1174 v_scale(im, m_size, hs + 1);
|
Chris@29
|
1175 }
|
Chris@29
|
1176 index = 0;
|
Chris@29
|
1177 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1178 re[i] = i2d(m_packed[index++]);
|
Chris@29
|
1179 index++;
|
Chris@29
|
1180 }
|
Chris@29
|
1181 v_scale(re, m_size, hs + 1);
|
Chris@29
|
1182 }
|
Chris@29
|
1183
|
Chris@29
|
1184 void unpackFloatInterleaved(float *BQ_R__ cplx) {
|
Chris@29
|
1185 // convert fixed point output for forward transform
|
Chris@29
|
1186 for (int i = 0; i < m_size + 2; ++i) {
|
Chris@29
|
1187 cplx[i] = i2f(m_packed[i]);
|
Chris@29
|
1188 }
|
Chris@29
|
1189 v_scale(cplx, m_size, m_size + 2);
|
Chris@29
|
1190 }
|
Chris@29
|
1191
|
Chris@29
|
1192 void unpackDoubleInterleaved(double *BQ_R__ cplx) {
|
Chris@29
|
1193 // convert fixed point output for forward transform
|
Chris@29
|
1194 for (int i = 0; i < m_size + 2; ++i) {
|
Chris@29
|
1195 cplx[i] = i2d(m_packed[i]);
|
Chris@29
|
1196 }
|
Chris@29
|
1197 v_scale(cplx, m_size, m_size + 2);
|
Chris@29
|
1198 }
|
Chris@29
|
1199
|
Chris@29
|
1200 void packFloat(const float *BQ_R__ re, const float *BQ_R__ im) {
|
Chris@29
|
1201 // prepare fixed point input for inverse transform
|
Chris@29
|
1202 int index = 0;
|
Chris@29
|
1203 const int hs = m_size/2;
|
Chris@29
|
1204 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1205 m_packed[index++] = f2i(re[i]);
|
Chris@29
|
1206 index++;
|
Chris@29
|
1207 }
|
Chris@29
|
1208 index = 0;
|
Chris@29
|
1209 if (im) {
|
Chris@29
|
1210 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1211 index++;
|
Chris@29
|
1212 m_packed[index++] = f2i(im[i]);
|
Chris@29
|
1213 }
|
Chris@29
|
1214 } else {
|
Chris@29
|
1215 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1216 index++;
|
Chris@29
|
1217 m_packed[index++] = 0;
|
Chris@29
|
1218 }
|
Chris@29
|
1219 }
|
Chris@29
|
1220 }
|
Chris@29
|
1221
|
Chris@29
|
1222 void packDouble(const double *BQ_R__ re, const double *BQ_R__ im) {
|
Chris@29
|
1223 // prepare fixed point input for inverse transform
|
Chris@29
|
1224 int index = 0;
|
Chris@29
|
1225 const int hs = m_size/2;
|
Chris@29
|
1226 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1227 m_packed[index++] = d2i(re[i]);
|
Chris@29
|
1228 index++;
|
Chris@29
|
1229 }
|
Chris@29
|
1230 index = 0;
|
Chris@29
|
1231 if (im) {
|
Chris@29
|
1232 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1233 index++;
|
Chris@29
|
1234 m_packed[index++] = d2i(im[i]);
|
Chris@29
|
1235 }
|
Chris@29
|
1236 } else {
|
Chris@29
|
1237 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1238 index++;
|
Chris@29
|
1239 m_packed[index++] = 0;
|
Chris@29
|
1240 }
|
Chris@29
|
1241 }
|
Chris@29
|
1242 }
|
Chris@29
|
1243
|
Chris@29
|
1244 void convertFloat(const float *BQ_R__ f) {
|
Chris@29
|
1245 // convert interleaved input for inverse interleaved transform
|
Chris@29
|
1246 const int n = m_size + 2;
|
Chris@29
|
1247 for (int i = 0; i < n; ++i) {
|
Chris@29
|
1248 m_packed[i] = f2i(f[i]);
|
Chris@29
|
1249 }
|
Chris@29
|
1250 }
|
Chris@29
|
1251
|
Chris@29
|
1252 void convertDouble(const double *BQ_R__ d) {
|
Chris@29
|
1253 // convert interleaved input for inverse interleaved transform
|
Chris@29
|
1254 const int n = m_size + 2;
|
Chris@29
|
1255 for (int i = 0; i < n; ++i) {
|
Chris@29
|
1256 m_packed[i] = d2i(d[i]);
|
Chris@29
|
1257 }
|
Chris@29
|
1258 }
|
Chris@29
|
1259
|
Chris@29
|
1260 void unpackFloat(float *BQ_R__ re) {
|
Chris@29
|
1261 // convert fixed point output for inverse transform
|
Chris@29
|
1262 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
1263 re[i] = i2f(m_buf[i]) * m_size;
|
Chris@29
|
1264 }
|
Chris@29
|
1265 }
|
Chris@29
|
1266
|
Chris@29
|
1267 void unpackDouble(double *BQ_R__ re) {
|
Chris@29
|
1268 // convert fixed point output for inverse transform
|
Chris@29
|
1269 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
1270 re[i] = i2d(m_buf[i]) * m_size;
|
Chris@29
|
1271 }
|
Chris@29
|
1272 }
|
Chris@29
|
1273
|
Chris@29
|
1274 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
1275 if (!m_packed) initDouble();
|
Chris@29
|
1276 packDouble(realIn);
|
Chris@29
|
1277 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1278 unpackDouble(realOut, imagOut);
|
Chris@29
|
1279 }
|
Chris@29
|
1280
|
Chris@29
|
1281 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
1282 if (!m_packed) initDouble();
|
Chris@29
|
1283 packDouble(realIn);
|
Chris@29
|
1284 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1285 unpackDoubleInterleaved(complexOut);
|
Chris@29
|
1286 }
|
Chris@29
|
1287
|
Chris@29
|
1288 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
1289 if (!m_packed) initDouble();
|
Chris@29
|
1290 packDouble(realIn);
|
Chris@29
|
1291 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1292 unpackDouble(magOut, phaseOut); // temporarily
|
Chris@29
|
1293 // at this point we actually have real/imag in the mag/phase arrays
|
Chris@29
|
1294 const int hs = m_size/2;
|
Chris@29
|
1295 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1296 double real = magOut[i];
|
Chris@29
|
1297 double imag = phaseOut[i];
|
Chris@29
|
1298 c_magphase(magOut + i, phaseOut + i, real, imag);
|
Chris@29
|
1299 }
|
Chris@29
|
1300 }
|
Chris@29
|
1301
|
Chris@29
|
1302 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
1303 if (!m_packed) initDouble();
|
Chris@29
|
1304 packDouble(realIn);
|
Chris@29
|
1305 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1306 const int hs = m_size/2;
|
Chris@29
|
1307 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1308 int reali = i * 2;
|
Chris@29
|
1309 int imagi = reali + 1;
|
Chris@29
|
1310 double real = i2d(m_packed[reali]) * m_size;
|
Chris@29
|
1311 double imag = i2d(m_packed[imagi]) * m_size;
|
Chris@29
|
1312 magOut[i] = sqrt(real * real + imag * imag);
|
Chris@29
|
1313 }
|
Chris@29
|
1314 }
|
Chris@29
|
1315
|
Chris@29
|
1316 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
1317 if (!m_packed) initFloat();
|
Chris@29
|
1318 packFloat(realIn);
|
Chris@29
|
1319 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1320 unpackFloat(realOut, imagOut);
|
Chris@29
|
1321 }
|
Chris@29
|
1322
|
Chris@29
|
1323 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
1324 if (!m_packed) initFloat();
|
Chris@29
|
1325 packFloat(realIn);
|
Chris@29
|
1326 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1327 unpackFloatInterleaved(complexOut);
|
Chris@29
|
1328 }
|
Chris@29
|
1329
|
Chris@29
|
1330 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
1331 if (!m_packed) initFloat();
|
Chris@29
|
1332
|
Chris@29
|
1333 packFloat(realIn);
|
Chris@29
|
1334 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1335 unpackFloat(magOut, phaseOut); // temporarily
|
Chris@29
|
1336 // at this point we actually have real/imag in the mag/phase arrays
|
Chris@29
|
1337 const int hs = m_size/2;
|
Chris@29
|
1338 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1339 float real = magOut[i];
|
Chris@29
|
1340 float imag = phaseOut[i];
|
Chris@29
|
1341 c_magphase(magOut + i, phaseOut + i, real, imag);
|
Chris@29
|
1342 }
|
Chris@29
|
1343 }
|
Chris@29
|
1344
|
Chris@29
|
1345 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
1346 if (!m_packed) initFloat();
|
Chris@29
|
1347 packFloat(realIn);
|
Chris@29
|
1348 omxSP_FFTFwd_RToCCS_S32_Sfs(m_buf, m_packed, m_spec, m_order);
|
Chris@29
|
1349 const int hs = m_size/2;
|
Chris@29
|
1350 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1351 int reali = i * 2;
|
Chris@29
|
1352 int imagi = reali + 1;
|
Chris@29
|
1353 float real = i2f(m_packed[reali]) * m_size;
|
Chris@29
|
1354 float imag = i2f(m_packed[imagi]) * m_size;
|
Chris@29
|
1355 magOut[i] = sqrtf(real * real + imag * imag);
|
Chris@29
|
1356 }
|
Chris@29
|
1357 }
|
Chris@29
|
1358
|
Chris@29
|
1359 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
1360 if (!m_packed) initDouble();
|
Chris@29
|
1361 packDouble(realIn, imagIn);
|
Chris@29
|
1362 omxSP_FFTInv_CCSToR_S32_Sfs(m_packed, m_buf, m_spec, 0);
|
Chris@29
|
1363 unpackDouble(realOut);
|
Chris@29
|
1364 }
|
Chris@29
|
1365
|
Chris@29
|
1366 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
1367 if (!m_packed) initDouble();
|
Chris@29
|
1368 convertDouble(complexIn);
|
Chris@29
|
1369 omxSP_FFTInv_CCSToR_S32_Sfs(m_packed, m_buf, m_spec, 0);
|
Chris@29
|
1370 unpackDouble(realOut);
|
Chris@29
|
1371 }
|
Chris@29
|
1372
|
Chris@29
|
1373 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
1374 if (!m_packed) initDouble();
|
Chris@29
|
1375 int index = 0;
|
Chris@29
|
1376 const int hs = m_size/2;
|
Chris@29
|
1377 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1378 double real, imag;
|
Chris@29
|
1379 c_phasor(&real, &imag, phaseIn[i]);
|
Chris@29
|
1380 m_fbuf[index++] = float(real);
|
Chris@29
|
1381 m_fbuf[index++] = float(imag);
|
Chris@29
|
1382 }
|
Chris@29
|
1383 convertFloat(m_fbuf);
|
Chris@29
|
1384 omxSP_FFTInv_CCSToR_S32_Sfs(m_packed, m_buf, m_spec, 0);
|
Chris@29
|
1385 unpackDouble(realOut);
|
Chris@29
|
1386 }
|
Chris@29
|
1387
|
Chris@29
|
1388 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
1389 if (!m_packed) initDouble();
|
Chris@29
|
1390 //!!! implement
|
Chris@29
|
1391 #warning OpenMAX implementation lacks cepstral transforms
|
Chris@29
|
1392 }
|
Chris@29
|
1393
|
Chris@29
|
1394 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
1395 if (!m_packed) initFloat();
|
Chris@29
|
1396 packFloat(realIn, imagIn);
|
Chris@29
|
1397 omxSP_FFTInv_CCSToR_S32_Sfs(m_packed, m_buf, m_spec, 0);
|
Chris@29
|
1398 unpackFloat(realOut);
|
Chris@29
|
1399 }
|
Chris@29
|
1400
|
Chris@29
|
1401 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
1402 if (!m_packed) initFloat();
|
Chris@29
|
1403 convertFloat(complexIn);
|
Chris@29
|
1404 omxSP_FFTInv_CCSToR_S32_Sfs(m_packed, m_buf, m_spec, 0);
|
Chris@29
|
1405 unpackFloat(realOut);
|
Chris@29
|
1406 }
|
Chris@29
|
1407
|
Chris@29
|
1408 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
1409 if (!m_packed) initFloat();
|
Chris@29
|
1410 const int hs = m_size/2;
|
Chris@29
|
1411 v_polar_to_cartesian_interleaved(m_fbuf, magIn, phaseIn, hs+1);
|
Chris@29
|
1412 convertFloat(m_fbuf);
|
Chris@29
|
1413 omxSP_FFTInv_CCSToR_S32_Sfs(m_packed, m_buf, m_spec, 0);
|
Chris@29
|
1414 unpackFloat(realOut);
|
Chris@29
|
1415 }
|
Chris@29
|
1416
|
Chris@29
|
1417 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
1418 if (!m_packed) initFloat();
|
Chris@29
|
1419 //!!! implement
|
Chris@29
|
1420 #warning OpenMAX implementation lacks cepstral transforms
|
Chris@29
|
1421 }
|
Chris@29
|
1422
|
Chris@29
|
1423 private:
|
Chris@29
|
1424 const int m_size;
|
Chris@29
|
1425 int m_order;
|
Chris@29
|
1426 OMX_S32 *m_packed;
|
Chris@29
|
1427 OMX_S32 *m_buf;
|
Chris@29
|
1428 float *m_fbuf;
|
Chris@29
|
1429 OMXFFTSpec_R_S32 *m_spec;
|
Chris@29
|
1430
|
Chris@29
|
1431 };
|
Chris@29
|
1432
|
Chris@29
|
1433 #endif /* HAVE_OPENMAX */
|
Chris@29
|
1434
|
Chris@29
|
1435 #ifdef HAVE_FFTW3
|
Chris@29
|
1436
|
Chris@29
|
1437 /*
|
Chris@29
|
1438 Define FFTW_DOUBLE_ONLY to make all uses of FFTW functions be
|
Chris@29
|
1439 double-precision (so "float" FFTs are calculated by casting to
|
Chris@29
|
1440 doubles and using the double-precision FFTW function).
|
Chris@29
|
1441
|
Chris@29
|
1442 Define FFTW_SINGLE_ONLY to make all uses of FFTW functions be
|
Chris@29
|
1443 single-precision (so "double" FFTs are calculated by casting to
|
Chris@29
|
1444 floats and using the single-precision FFTW function).
|
Chris@29
|
1445
|
Chris@29
|
1446 Neither of these flags is desirable for either performance or
|
Chris@29
|
1447 precision. The main reason to define either flag is to avoid linking
|
Chris@29
|
1448 against both fftw3 and fftw3f libraries.
|
Chris@29
|
1449 */
|
Chris@29
|
1450
|
Chris@29
|
1451 //#define FFTW_DOUBLE_ONLY 1
|
Chris@29
|
1452 //#define FFTW_SINGLE_ONLY 1
|
Chris@29
|
1453
|
Chris@29
|
1454 #if defined(FFTW_DOUBLE_ONLY) && defined(FFTW_SINGLE_ONLY)
|
Chris@29
|
1455 // Can't meaningfully define both
|
Chris@29
|
1456 #error Can only define one of FFTW_DOUBLE_ONLY and FFTW_SINGLE_ONLY
|
Chris@29
|
1457 #endif
|
Chris@29
|
1458
|
Chris@29
|
1459 #if defined(FFTW_FLOAT_ONLY)
|
Chris@29
|
1460 #warning FFTW_FLOAT_ONLY is deprecated, use FFTW_SINGLE_ONLY instead
|
Chris@29
|
1461 #define FFTW_SINGLE_ONLY 1
|
Chris@29
|
1462 #endif
|
Chris@29
|
1463
|
Chris@29
|
1464 #ifdef FFTW_DOUBLE_ONLY
|
Chris@29
|
1465 #define fft_float_type double
|
Chris@29
|
1466 #define fftwf_complex fftw_complex
|
Chris@29
|
1467 #define fftwf_plan fftw_plan
|
Chris@29
|
1468 #define fftwf_plan_dft_r2c_1d fftw_plan_dft_r2c_1d
|
Chris@29
|
1469 #define fftwf_plan_dft_c2r_1d fftw_plan_dft_c2r_1d
|
Chris@29
|
1470 #define fftwf_destroy_plan fftw_destroy_plan
|
Chris@29
|
1471 #define fftwf_malloc fftw_malloc
|
Chris@29
|
1472 #define fftwf_free fftw_free
|
Chris@29
|
1473 #define fftwf_execute fftw_execute
|
Chris@29
|
1474 #define atan2f atan2
|
Chris@29
|
1475 #define sqrtf sqrt
|
Chris@29
|
1476 #define cosf cos
|
Chris@29
|
1477 #define sinf sin
|
Chris@29
|
1478 #else
|
Chris@29
|
1479 #define fft_float_type float
|
Chris@29
|
1480 #endif /* FFTW_DOUBLE_ONLY */
|
Chris@29
|
1481
|
Chris@29
|
1482 #ifdef FFTW_SINGLE_ONLY
|
Chris@29
|
1483 #define fft_double_type float
|
Chris@29
|
1484 #define fftw_complex fftwf_complex
|
Chris@29
|
1485 #define fftw_plan fftwf_plan
|
Chris@29
|
1486 #define fftw_plan_dft_r2c_1d fftwf_plan_dft_r2c_1d
|
Chris@29
|
1487 #define fftw_plan_dft_c2r_1d fftwf_plan_dft_c2r_1d
|
Chris@29
|
1488 #define fftw_destroy_plan fftwf_destroy_plan
|
Chris@29
|
1489 #define fftw_malloc fftwf_malloc
|
Chris@29
|
1490 #define fftw_free fftwf_free
|
Chris@29
|
1491 #define fftw_execute fftwf_execute
|
Chris@29
|
1492 #define atan2 atan2f
|
Chris@29
|
1493 #define sqrt sqrtf
|
Chris@29
|
1494 #define cos cosf
|
Chris@29
|
1495 #define sin sinf
|
Chris@29
|
1496 #else
|
Chris@29
|
1497 #define fft_double_type double
|
Chris@29
|
1498 #endif /* FFTW_SINGLE_ONLY */
|
Chris@29
|
1499
|
Chris@29
|
1500 class D_FFTW : public FFTImpl
|
Chris@29
|
1501 {
|
Chris@29
|
1502 public:
|
Chris@29
|
1503 D_FFTW(int size) :
|
Chris@29
|
1504 m_fplanf(0), m_dplanf(0), m_size(size)
|
Chris@29
|
1505 {
|
Chris@29
|
1506 initMutex();
|
Chris@29
|
1507 }
|
Chris@29
|
1508
|
Chris@29
|
1509 ~D_FFTW() {
|
Chris@29
|
1510 if (m_fplanf) {
|
Chris@29
|
1511 lock();
|
Chris@29
|
1512 bool save = false;
|
Chris@29
|
1513 if (m_extantf > 0 && --m_extantf == 0) save = true;
|
Chris@29
|
1514 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1515 if (save) saveWisdom('f');
|
Chris@29
|
1516 #endif
|
Chris@29
|
1517 fftwf_destroy_plan(m_fplanf);
|
Chris@29
|
1518 fftwf_destroy_plan(m_fplani);
|
Chris@29
|
1519 fftwf_free(m_fbuf);
|
Chris@29
|
1520 fftwf_free(m_fpacked);
|
Chris@29
|
1521 unlock();
|
Chris@29
|
1522 }
|
Chris@29
|
1523 if (m_dplanf) {
|
Chris@29
|
1524 lock();
|
Chris@29
|
1525 bool save = false;
|
Chris@29
|
1526 if (m_extantd > 0 && --m_extantd == 0) save = true;
|
Chris@29
|
1527 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1528 if (save) saveWisdom('d');
|
Chris@29
|
1529 #endif
|
Chris@29
|
1530 fftw_destroy_plan(m_dplanf);
|
Chris@29
|
1531 fftw_destroy_plan(m_dplani);
|
Chris@29
|
1532 fftw_free(m_dbuf);
|
Chris@29
|
1533 fftw_free(m_dpacked);
|
Chris@29
|
1534 unlock();
|
Chris@29
|
1535 }
|
Chris@29
|
1536 destroyMutex();
|
Chris@29
|
1537 }
|
Chris@29
|
1538
|
Chris@29
|
1539 FFT::Precisions
|
Chris@29
|
1540 getSupportedPrecisions() const {
|
Chris@29
|
1541 #ifdef FFTW_SINGLE_ONLY
|
Chris@29
|
1542 return FFT::SinglePrecision;
|
Chris@29
|
1543 #else
|
Chris@29
|
1544 #ifdef FFTW_DOUBLE_ONLY
|
Chris@29
|
1545 return FFT::DoublePrecision;
|
Chris@29
|
1546 #else
|
Chris@29
|
1547 return FFT::SinglePrecision | FFT::DoublePrecision;
|
Chris@29
|
1548 #endif
|
Chris@29
|
1549 #endif
|
Chris@29
|
1550 }
|
Chris@29
|
1551
|
Chris@29
|
1552 void initFloat() {
|
Chris@29
|
1553 if (m_fplanf) return;
|
Chris@29
|
1554 bool load = false;
|
Chris@29
|
1555 lock();
|
Chris@29
|
1556 if (m_extantf++ == 0) load = true;
|
Chris@29
|
1557 #ifdef FFTW_DOUBLE_ONLY
|
Chris@29
|
1558 if (load) loadWisdom('d');
|
Chris@29
|
1559 #else
|
Chris@29
|
1560 if (load) loadWisdom('f');
|
Chris@29
|
1561 #endif
|
Chris@29
|
1562 m_fbuf = (fft_float_type *)fftw_malloc(m_size * sizeof(fft_float_type));
|
Chris@29
|
1563 m_fpacked = (fftwf_complex *)fftw_malloc
|
Chris@29
|
1564 ((m_size/2 + 1) * sizeof(fftwf_complex));
|
Chris@29
|
1565 m_fplanf = fftwf_plan_dft_r2c_1d
|
Chris@29
|
1566 (m_size, m_fbuf, m_fpacked, FFTW_MEASURE);
|
Chris@29
|
1567 m_fplani = fftwf_plan_dft_c2r_1d
|
Chris@29
|
1568 (m_size, m_fpacked, m_fbuf, FFTW_MEASURE);
|
Chris@29
|
1569 unlock();
|
Chris@29
|
1570 }
|
Chris@29
|
1571
|
Chris@29
|
1572 void initDouble() {
|
Chris@29
|
1573 if (m_dplanf) return;
|
Chris@29
|
1574 bool load = false;
|
Chris@29
|
1575 lock();
|
Chris@29
|
1576 if (m_extantd++ == 0) load = true;
|
Chris@29
|
1577 #ifdef FFTW_SINGLE_ONLY
|
Chris@29
|
1578 if (load) loadWisdom('f');
|
Chris@29
|
1579 #else
|
Chris@29
|
1580 if (load) loadWisdom('d');
|
Chris@29
|
1581 #endif
|
Chris@29
|
1582 m_dbuf = (fft_double_type *)fftw_malloc(m_size * sizeof(fft_double_type));
|
Chris@29
|
1583 m_dpacked = (fftw_complex *)fftw_malloc
|
Chris@29
|
1584 ((m_size/2 + 1) * sizeof(fftw_complex));
|
Chris@29
|
1585 m_dplanf = fftw_plan_dft_r2c_1d
|
Chris@29
|
1586 (m_size, m_dbuf, m_dpacked, FFTW_MEASURE);
|
Chris@29
|
1587 m_dplani = fftw_plan_dft_c2r_1d
|
Chris@29
|
1588 (m_size, m_dpacked, m_dbuf, FFTW_MEASURE);
|
Chris@29
|
1589 unlock();
|
Chris@29
|
1590 }
|
Chris@29
|
1591
|
Chris@29
|
1592 void loadWisdom(char type) { wisdom(false, type); }
|
Chris@29
|
1593 void saveWisdom(char type) { wisdom(true, type); }
|
Chris@29
|
1594
|
Chris@29
|
1595 void wisdom(bool save, char type) {
|
Chris@29
|
1596
|
Chris@29
|
1597 #ifdef FFTW_DOUBLE_ONLY
|
Chris@29
|
1598 if (type == 'f') return;
|
Chris@29
|
1599 #endif
|
Chris@29
|
1600 #ifdef FFTW_SINGLE_ONLY
|
Chris@29
|
1601 if (type == 'd') return;
|
Chris@29
|
1602 #endif
|
Chris@29
|
1603
|
Chris@29
|
1604 const char *home = getenv("HOME");
|
Chris@29
|
1605 if (!home) return;
|
Chris@29
|
1606
|
Chris@29
|
1607 char fn[256];
|
Chris@29
|
1608 snprintf(fn, 256, "%s/%s.%c", home, ".turbot.wisdom", type);
|
Chris@29
|
1609
|
Chris@29
|
1610 FILE *f = fopen(fn, save ? "wb" : "rb");
|
Chris@29
|
1611 if (!f) return;
|
Chris@29
|
1612
|
Chris@29
|
1613 if (save) {
|
Chris@29
|
1614 switch (type) {
|
Chris@29
|
1615 #ifdef FFTW_DOUBLE_ONLY
|
Chris@29
|
1616 case 'f': break;
|
Chris@29
|
1617 #else
|
Chris@29
|
1618 case 'f': fftwf_export_wisdom_to_file(f); break;
|
Chris@29
|
1619 #endif
|
Chris@29
|
1620 #ifdef FFTW_SINGLE_ONLY
|
Chris@29
|
1621 case 'd': break;
|
Chris@29
|
1622 #else
|
Chris@29
|
1623 case 'd': fftw_export_wisdom_to_file(f); break;
|
Chris@29
|
1624 #endif
|
Chris@29
|
1625 default: break;
|
Chris@29
|
1626 }
|
Chris@29
|
1627 } else {
|
Chris@29
|
1628 switch (type) {
|
Chris@29
|
1629 #ifdef FFTW_DOUBLE_ONLY
|
Chris@29
|
1630 case 'f': break;
|
Chris@29
|
1631 #else
|
Chris@29
|
1632 case 'f': fftwf_import_wisdom_from_file(f); break;
|
Chris@29
|
1633 #endif
|
Chris@29
|
1634 #ifdef FFTW_SINGLE_ONLY
|
Chris@29
|
1635 case 'd': break;
|
Chris@29
|
1636 #else
|
Chris@29
|
1637 case 'd': fftw_import_wisdom_from_file(f); break;
|
Chris@29
|
1638 #endif
|
Chris@29
|
1639 default: break;
|
Chris@29
|
1640 }
|
Chris@29
|
1641 }
|
Chris@29
|
1642
|
Chris@29
|
1643 fclose(f);
|
Chris@29
|
1644 }
|
Chris@29
|
1645
|
Chris@29
|
1646 void packFloat(const float *BQ_R__ re, const float *BQ_R__ im) {
|
Chris@29
|
1647 const int hs = m_size/2;
|
Chris@29
|
1648 fftwf_complex *const BQ_R__ fpacked = m_fpacked;
|
Chris@29
|
1649 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1650 fpacked[i][0] = re[i];
|
Chris@29
|
1651 }
|
Chris@29
|
1652 if (im) {
|
Chris@29
|
1653 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1654 fpacked[i][1] = im[i];
|
Chris@29
|
1655 }
|
Chris@29
|
1656 } else {
|
Chris@29
|
1657 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1658 fpacked[i][1] = 0.f;
|
Chris@29
|
1659 }
|
Chris@29
|
1660 }
|
Chris@29
|
1661 }
|
Chris@29
|
1662
|
Chris@29
|
1663 void packDouble(const double *BQ_R__ re, const double *BQ_R__ im) {
|
Chris@29
|
1664 const int hs = m_size/2;
|
Chris@29
|
1665 fftw_complex *const BQ_R__ dpacked = m_dpacked;
|
Chris@29
|
1666 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1667 dpacked[i][0] = re[i];
|
Chris@29
|
1668 }
|
Chris@29
|
1669 if (im) {
|
Chris@29
|
1670 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1671 dpacked[i][1] = im[i];
|
Chris@29
|
1672 }
|
Chris@29
|
1673 } else {
|
Chris@29
|
1674 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1675 dpacked[i][1] = 0.0;
|
Chris@29
|
1676 }
|
Chris@29
|
1677 }
|
Chris@29
|
1678 }
|
Chris@29
|
1679
|
Chris@29
|
1680 void unpackFloat(float *BQ_R__ re, float *BQ_R__ im) {
|
Chris@29
|
1681 const int hs = m_size/2;
|
Chris@29
|
1682 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1683 re[i] = m_fpacked[i][0];
|
Chris@29
|
1684 }
|
Chris@29
|
1685 if (im) {
|
Chris@29
|
1686 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1687 im[i] = m_fpacked[i][1];
|
Chris@29
|
1688 }
|
Chris@29
|
1689 }
|
Chris@29
|
1690 }
|
Chris@29
|
1691
|
Chris@29
|
1692 void unpackDouble(double *BQ_R__ re, double *BQ_R__ im) {
|
Chris@29
|
1693 const int hs = m_size/2;
|
Chris@29
|
1694 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1695 re[i] = m_dpacked[i][0];
|
Chris@29
|
1696 }
|
Chris@29
|
1697 if (im) {
|
Chris@29
|
1698 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1699 im[i] = m_dpacked[i][1];
|
Chris@29
|
1700 }
|
Chris@29
|
1701 }
|
Chris@29
|
1702 }
|
Chris@29
|
1703
|
Chris@29
|
1704 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
1705 if (!m_dplanf) initDouble();
|
Chris@29
|
1706 const int sz = m_size;
|
Chris@29
|
1707 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1708 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1709 if (realIn != dbuf)
|
Chris@29
|
1710 #endif
|
Chris@29
|
1711 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1712 dbuf[i] = realIn[i];
|
Chris@29
|
1713 }
|
Chris@29
|
1714 fftw_execute(m_dplanf);
|
Chris@29
|
1715 unpackDouble(realOut, imagOut);
|
Chris@29
|
1716 }
|
Chris@29
|
1717
|
Chris@29
|
1718 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
1719 if (!m_dplanf) initDouble();
|
Chris@29
|
1720 const int sz = m_size;
|
Chris@29
|
1721 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1722 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1723 if (realIn != dbuf)
|
Chris@29
|
1724 #endif
|
Chris@29
|
1725 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1726 dbuf[i] = realIn[i];
|
Chris@29
|
1727 }
|
Chris@29
|
1728 fftw_execute(m_dplanf);
|
Chris@29
|
1729 v_convert(complexOut, (fft_double_type *)m_dpacked, sz + 2);
|
Chris@29
|
1730 }
|
Chris@29
|
1731
|
Chris@29
|
1732 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
1733 if (!m_dplanf) initDouble();
|
Chris@29
|
1734 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1735 const int sz = m_size;
|
Chris@29
|
1736 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1737 if (realIn != dbuf)
|
Chris@29
|
1738 #endif
|
Chris@29
|
1739 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1740 dbuf[i] = realIn[i];
|
Chris@29
|
1741 }
|
Chris@29
|
1742 fftw_execute(m_dplanf);
|
Chris@29
|
1743 v_cartesian_interleaved_to_polar(magOut, phaseOut,
|
Chris@29
|
1744 (double *)m_dpacked, m_size/2+1);
|
Chris@29
|
1745 }
|
Chris@29
|
1746
|
Chris@29
|
1747 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
1748 if (!m_dplanf) initDouble();
|
Chris@29
|
1749 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1750 const int sz = m_size;
|
Chris@29
|
1751 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1752 if (realIn != m_dbuf)
|
Chris@29
|
1753 #endif
|
Chris@29
|
1754 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1755 dbuf[i] = realIn[i];
|
Chris@29
|
1756 }
|
Chris@29
|
1757 fftw_execute(m_dplanf);
|
Chris@29
|
1758 const int hs = m_size/2;
|
Chris@29
|
1759 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1760 magOut[i] = sqrt(m_dpacked[i][0] * m_dpacked[i][0] +
|
Chris@29
|
1761 m_dpacked[i][1] * m_dpacked[i][1]);
|
Chris@29
|
1762 }
|
Chris@29
|
1763 }
|
Chris@29
|
1764
|
Chris@29
|
1765 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
1766 if (!m_fplanf) initFloat();
|
Chris@29
|
1767 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1768 const int sz = m_size;
|
Chris@29
|
1769 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1770 if (realIn != fbuf)
|
Chris@29
|
1771 #endif
|
Chris@29
|
1772 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1773 fbuf[i] = realIn[i];
|
Chris@29
|
1774 }
|
Chris@29
|
1775 fftwf_execute(m_fplanf);
|
Chris@29
|
1776 unpackFloat(realOut, imagOut);
|
Chris@29
|
1777 }
|
Chris@29
|
1778
|
Chris@29
|
1779 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
1780 if (!m_fplanf) initFloat();
|
Chris@29
|
1781 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1782 const int sz = m_size;
|
Chris@29
|
1783 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1784 if (realIn != fbuf)
|
Chris@29
|
1785 #endif
|
Chris@29
|
1786 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1787 fbuf[i] = realIn[i];
|
Chris@29
|
1788 }
|
Chris@29
|
1789 fftwf_execute(m_fplanf);
|
Chris@29
|
1790 v_convert(complexOut, (fft_float_type *)m_fpacked, sz + 2);
|
Chris@29
|
1791 }
|
Chris@29
|
1792
|
Chris@29
|
1793 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
1794 if (!m_fplanf) initFloat();
|
Chris@29
|
1795 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1796 const int sz = m_size;
|
Chris@29
|
1797 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1798 if (realIn != fbuf)
|
Chris@29
|
1799 #endif
|
Chris@29
|
1800 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1801 fbuf[i] = realIn[i];
|
Chris@29
|
1802 }
|
Chris@29
|
1803 fftwf_execute(m_fplanf);
|
Chris@29
|
1804 v_cartesian_interleaved_to_polar(magOut, phaseOut,
|
Chris@29
|
1805 (float *)m_fpacked, m_size/2+1);
|
Chris@29
|
1806 }
|
Chris@29
|
1807
|
Chris@29
|
1808 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
1809 if (!m_fplanf) initFloat();
|
Chris@29
|
1810 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1811 const int sz = m_size;
|
Chris@29
|
1812 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1813 if (realIn != fbuf)
|
Chris@29
|
1814 #endif
|
Chris@29
|
1815 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1816 fbuf[i] = realIn[i];
|
Chris@29
|
1817 }
|
Chris@29
|
1818 fftwf_execute(m_fplanf);
|
Chris@29
|
1819 const int hs = m_size/2;
|
Chris@29
|
1820 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1821 magOut[i] = sqrtf(m_fpacked[i][0] * m_fpacked[i][0] +
|
Chris@29
|
1822 m_fpacked[i][1] * m_fpacked[i][1]);
|
Chris@29
|
1823 }
|
Chris@29
|
1824 }
|
Chris@29
|
1825
|
Chris@29
|
1826 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
1827 if (!m_dplanf) initDouble();
|
Chris@29
|
1828 packDouble(realIn, imagIn);
|
Chris@29
|
1829 fftw_execute(m_dplani);
|
Chris@29
|
1830 const int sz = m_size;
|
Chris@29
|
1831 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1832 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1833 if (realOut != dbuf)
|
Chris@29
|
1834 #endif
|
Chris@29
|
1835 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1836 realOut[i] = dbuf[i];
|
Chris@29
|
1837 }
|
Chris@29
|
1838 }
|
Chris@29
|
1839
|
Chris@29
|
1840 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
1841 if (!m_dplanf) initDouble();
|
Chris@29
|
1842 v_convert((double *)m_dpacked, complexIn, m_size + 2);
|
Chris@29
|
1843 fftw_execute(m_dplani);
|
Chris@29
|
1844 const int sz = m_size;
|
Chris@29
|
1845 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1846 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1847 if (realOut != dbuf)
|
Chris@29
|
1848 #endif
|
Chris@29
|
1849 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1850 realOut[i] = dbuf[i];
|
Chris@29
|
1851 }
|
Chris@29
|
1852 }
|
Chris@29
|
1853
|
Chris@29
|
1854 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
1855 if (!m_dplanf) initDouble();
|
Chris@29
|
1856 const int hs = m_size/2;
|
Chris@29
|
1857 fftw_complex *const BQ_R__ dpacked = m_dpacked;
|
Chris@29
|
1858 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1859 dpacked[i][0] = magIn[i] * cos(phaseIn[i]);
|
Chris@29
|
1860 }
|
Chris@29
|
1861 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1862 dpacked[i][1] = magIn[i] * sin(phaseIn[i]);
|
Chris@29
|
1863 }
|
Chris@29
|
1864 fftw_execute(m_dplani);
|
Chris@29
|
1865 const int sz = m_size;
|
Chris@29
|
1866 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1867 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1868 if (realOut != dbuf)
|
Chris@29
|
1869 #endif
|
Chris@29
|
1870 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1871 realOut[i] = dbuf[i];
|
Chris@29
|
1872 }
|
Chris@29
|
1873 }
|
Chris@29
|
1874
|
Chris@29
|
1875 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
1876 if (!m_dplanf) initDouble();
|
Chris@29
|
1877 fft_double_type *const BQ_R__ dbuf = m_dbuf;
|
Chris@29
|
1878 fftw_complex *const BQ_R__ dpacked = m_dpacked;
|
Chris@29
|
1879 const int hs = m_size/2;
|
Chris@29
|
1880 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1881 dpacked[i][0] = log(magIn[i] + 0.000001);
|
Chris@29
|
1882 }
|
Chris@29
|
1883 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1884 dpacked[i][1] = 0.0;
|
Chris@29
|
1885 }
|
Chris@29
|
1886 fftw_execute(m_dplani);
|
Chris@29
|
1887 const int sz = m_size;
|
Chris@29
|
1888 #ifndef FFTW_SINGLE_ONLY
|
Chris@29
|
1889 if (cepOut != dbuf)
|
Chris@29
|
1890 #endif
|
Chris@29
|
1891 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1892 cepOut[i] = dbuf[i];
|
Chris@29
|
1893 }
|
Chris@29
|
1894 }
|
Chris@29
|
1895
|
Chris@29
|
1896 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
1897 if (!m_fplanf) initFloat();
|
Chris@29
|
1898 packFloat(realIn, imagIn);
|
Chris@29
|
1899 fftwf_execute(m_fplani);
|
Chris@29
|
1900 const int sz = m_size;
|
Chris@29
|
1901 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1902 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1903 if (realOut != fbuf)
|
Chris@29
|
1904 #endif
|
Chris@29
|
1905 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1906 realOut[i] = fbuf[i];
|
Chris@29
|
1907 }
|
Chris@29
|
1908 }
|
Chris@29
|
1909
|
Chris@29
|
1910 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
1911 if (!m_fplanf) initFloat();
|
Chris@29
|
1912 v_copy((float *)m_fpacked, complexIn, m_size + 2);
|
Chris@29
|
1913 fftwf_execute(m_fplani);
|
Chris@29
|
1914 const int sz = m_size;
|
Chris@29
|
1915 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1916 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1917 if (realOut != fbuf)
|
Chris@29
|
1918 #endif
|
Chris@29
|
1919 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1920 realOut[i] = fbuf[i];
|
Chris@29
|
1921 }
|
Chris@29
|
1922 }
|
Chris@29
|
1923
|
Chris@29
|
1924 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
1925 if (!m_fplanf) initFloat();
|
Chris@29
|
1926 const int hs = m_size/2;
|
Chris@29
|
1927 fftwf_complex *const BQ_R__ fpacked = m_fpacked;
|
Chris@29
|
1928 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1929 fpacked[i][0] = magIn[i] * cosf(phaseIn[i]);
|
Chris@29
|
1930 }
|
Chris@29
|
1931 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1932 fpacked[i][1] = magIn[i] * sinf(phaseIn[i]);
|
Chris@29
|
1933 }
|
Chris@29
|
1934 fftwf_execute(m_fplani);
|
Chris@29
|
1935 const int sz = m_size;
|
Chris@29
|
1936 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1937 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1938 if (realOut != fbuf)
|
Chris@29
|
1939 #endif
|
Chris@29
|
1940 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1941 realOut[i] = fbuf[i];
|
Chris@29
|
1942 }
|
Chris@29
|
1943 }
|
Chris@29
|
1944
|
Chris@29
|
1945 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
1946 if (!m_fplanf) initFloat();
|
Chris@29
|
1947 const int hs = m_size/2;
|
Chris@29
|
1948 fftwf_complex *const BQ_R__ fpacked = m_fpacked;
|
Chris@29
|
1949 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1950 fpacked[i][0] = logf(magIn[i] + 0.000001f);
|
Chris@29
|
1951 }
|
Chris@29
|
1952 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
1953 fpacked[i][1] = 0.f;
|
Chris@29
|
1954 }
|
Chris@29
|
1955 fftwf_execute(m_fplani);
|
Chris@29
|
1956 const int sz = m_size;
|
Chris@29
|
1957 fft_float_type *const BQ_R__ fbuf = m_fbuf;
|
Chris@29
|
1958 #ifndef FFTW_DOUBLE_ONLY
|
Chris@29
|
1959 if (cepOut != fbuf)
|
Chris@29
|
1960 #endif
|
Chris@29
|
1961 for (int i = 0; i < sz; ++i) {
|
Chris@29
|
1962 cepOut[i] = fbuf[i];
|
Chris@29
|
1963 }
|
Chris@29
|
1964 }
|
Chris@29
|
1965
|
Chris@29
|
1966 private:
|
Chris@29
|
1967 fftwf_plan m_fplanf;
|
Chris@29
|
1968 fftwf_plan m_fplani;
|
Chris@29
|
1969 #ifdef FFTW_DOUBLE_ONLY
|
Chris@29
|
1970 double *m_fbuf;
|
Chris@29
|
1971 #else
|
Chris@29
|
1972 float *m_fbuf;
|
Chris@29
|
1973 #endif
|
Chris@29
|
1974 fftwf_complex *m_fpacked;
|
Chris@29
|
1975 fftw_plan m_dplanf;
|
Chris@29
|
1976 fftw_plan m_dplani;
|
Chris@29
|
1977 #ifdef FFTW_SINGLE_ONLY
|
Chris@29
|
1978 float *m_dbuf;
|
Chris@29
|
1979 #else
|
Chris@29
|
1980 double *m_dbuf;
|
Chris@29
|
1981 #endif
|
Chris@29
|
1982 fftw_complex *m_dpacked;
|
Chris@29
|
1983 const int m_size;
|
Chris@29
|
1984 static int m_extantf;
|
Chris@29
|
1985 static int m_extantd;
|
Chris@29
|
1986 #ifdef NO_THREADING
|
Chris@29
|
1987 void initMutex() {}
|
Chris@29
|
1988 void destroyMutex() {}
|
Chris@29
|
1989 void lock() {}
|
Chris@29
|
1990 void unlock() {}
|
Chris@29
|
1991 #else
|
Chris@29
|
1992 #ifdef _WIN32
|
Chris@29
|
1993 static HANDLE m_commonMutex;
|
Chris@29
|
1994 void initMutex() { m_commonMutex = CreateMutex(NULL, FALSE, NULL); }
|
Chris@29
|
1995 void destroyMutex() { CloseHandle(m_commonMutex); }
|
Chris@29
|
1996 void lock() { WaitForSingleObject(m_commonMutex, INFINITE); }
|
Chris@29
|
1997 void unlock() { ReleaseMutex(m_commonMutex); }
|
Chris@29
|
1998 #else
|
Chris@29
|
1999 static pthread_mutex_t m_commonMutex;
|
Chris@29
|
2000 void initMutex() { pthread_mutex_init(&m_commonMutex, 0); }
|
Chris@29
|
2001 void destroyMutex() { pthread_mutex_destroy(&m_commonMutex); }
|
Chris@29
|
2002 void lock() { pthread_mutex_lock(&m_commonMutex); }
|
Chris@29
|
2003 void unlock() { pthread_mutex_unlock(&m_commonMutex); }
|
Chris@29
|
2004 #endif
|
Chris@29
|
2005 #endif
|
Chris@29
|
2006 };
|
Chris@29
|
2007
|
Chris@29
|
2008 int
|
Chris@29
|
2009 D_FFTW::m_extantf = 0;
|
Chris@29
|
2010
|
Chris@29
|
2011 int
|
Chris@29
|
2012 D_FFTW::m_extantd = 0;
|
Chris@29
|
2013
|
Chris@29
|
2014 #ifndef NO_THREADING
|
Chris@29
|
2015 #ifdef _WIN32
|
Chris@29
|
2016 HANDLE D_FFTW::m_commonMutex;
|
Chris@29
|
2017 #else
|
Chris@29
|
2018 pthread_mutex_t D_FFTW::m_commonMutex;
|
Chris@29
|
2019 #endif
|
Chris@29
|
2020 #endif
|
Chris@29
|
2021
|
Chris@29
|
2022 #endif /* HAVE_FFTW3 */
|
Chris@29
|
2023
|
Chris@29
|
2024 #ifdef HAVE_SFFT
|
Chris@29
|
2025
|
Chris@29
|
2026 /*
|
Chris@29
|
2027 Define SFFT_DOUBLE_ONLY to make all uses of SFFT functions be
|
Chris@29
|
2028 double-precision (so "float" FFTs are calculated by casting to
|
Chris@29
|
2029 doubles and using the double-precision SFFT function).
|
Chris@29
|
2030
|
Chris@29
|
2031 Define SFFT_SINGLE_ONLY to make all uses of SFFT functions be
|
Chris@29
|
2032 single-precision (so "double" FFTs are calculated by casting to
|
Chris@29
|
2033 floats and using the single-precision SFFT function).
|
Chris@29
|
2034
|
Chris@29
|
2035 Neither of these flags is desirable for either performance or
|
Chris@29
|
2036 precision.
|
Chris@29
|
2037 */
|
Chris@29
|
2038
|
Chris@29
|
2039 //#define SFFT_DOUBLE_ONLY 1
|
Chris@29
|
2040 //#define SFFT_SINGLE_ONLY 1
|
Chris@29
|
2041
|
Chris@29
|
2042 #if defined(SFFT_DOUBLE_ONLY) && defined(SFFT_SINGLE_ONLY)
|
Chris@29
|
2043 // Can't meaningfully define both
|
Chris@29
|
2044 #error Can only define one of SFFT_DOUBLE_ONLY and SFFT_SINGLE_ONLY
|
Chris@29
|
2045 #endif
|
Chris@29
|
2046
|
Chris@29
|
2047 #ifdef SFFT_DOUBLE_ONLY
|
Chris@29
|
2048 #define fft_float_type double
|
Chris@29
|
2049 #define FLAG_SFFT_FLOAT SFFT_DOUBLE
|
Chris@29
|
2050 #define atan2f atan2
|
Chris@29
|
2051 #define sqrtf sqrt
|
Chris@29
|
2052 #define cosf cos
|
Chris@29
|
2053 #define sinf sin
|
Chris@29
|
2054 #define logf log
|
Chris@29
|
2055 #else
|
Chris@29
|
2056 #define FLAG_SFFT_FLOAT SFFT_FLOAT
|
Chris@29
|
2057 #define fft_float_type float
|
Chris@29
|
2058 #endif /* SFFT_DOUBLE_ONLY */
|
Chris@29
|
2059
|
Chris@29
|
2060 #ifdef SFFT_SINGLE_ONLY
|
Chris@29
|
2061 #define fft_double_type float
|
Chris@29
|
2062 #define FLAG_SFFT_DOUBLE SFFT_FLOAT
|
Chris@29
|
2063 #define atan2 atan2f
|
Chris@29
|
2064 #define sqrt sqrtf
|
Chris@29
|
2065 #define cos cosf
|
Chris@29
|
2066 #define sin sinf
|
Chris@29
|
2067 #define log logf
|
Chris@29
|
2068 #else
|
Chris@29
|
2069 #define FLAG_SFFT_DOUBLE SFFT_DOUBLE
|
Chris@29
|
2070 #define fft_double_type double
|
Chris@29
|
2071 #endif /* SFFT_SINGLE_ONLY */
|
Chris@29
|
2072
|
Chris@29
|
2073 class D_SFFT : public FFTImpl
|
Chris@29
|
2074 {
|
Chris@29
|
2075 public:
|
Chris@29
|
2076 D_SFFT(int size) :
|
Chris@29
|
2077 m_fplanf(0), m_fplani(0), m_dplanf(0), m_dplani(0), m_size(size)
|
Chris@29
|
2078 {
|
Chris@29
|
2079 }
|
Chris@29
|
2080
|
Chris@29
|
2081 ~D_SFFT() {
|
Chris@29
|
2082 if (m_fplanf) {
|
Chris@29
|
2083 sfft_free(m_fplanf);
|
Chris@29
|
2084 sfft_free(m_fplani);
|
Chris@29
|
2085 deallocate(m_fbuf);
|
Chris@29
|
2086 deallocate(m_fresult);
|
Chris@29
|
2087 }
|
Chris@29
|
2088 if (m_dplanf) {
|
Chris@29
|
2089 sfft_free(m_dplanf);
|
Chris@29
|
2090 sfft_free(m_dplani);
|
Chris@29
|
2091 deallocate(m_dbuf);
|
Chris@29
|
2092 deallocate(m_dresult);
|
Chris@29
|
2093 }
|
Chris@29
|
2094 }
|
Chris@29
|
2095
|
Chris@29
|
2096 FFT::Precisions
|
Chris@29
|
2097 getSupportedPrecisions() const {
|
Chris@29
|
2098 #ifdef SFFT_SINGLE_ONLY
|
Chris@29
|
2099 return FFT::SinglePrecision;
|
Chris@29
|
2100 #else
|
Chris@29
|
2101 #ifdef SFFT_DOUBLE_ONLY
|
Chris@29
|
2102 return FFT::DoublePrecision;
|
Chris@29
|
2103 #else
|
Chris@29
|
2104 return FFT::SinglePrecision | FFT::DoublePrecision;
|
Chris@29
|
2105 #endif
|
Chris@29
|
2106 #endif
|
Chris@29
|
2107 }
|
Chris@29
|
2108
|
Chris@29
|
2109 void initFloat() {
|
Chris@29
|
2110 if (m_fplanf) return;
|
Chris@29
|
2111 m_fbuf = allocate<fft_float_type>(2 * m_size);
|
Chris@29
|
2112 m_fresult = allocate<fft_float_type>(2 * m_size);
|
Chris@29
|
2113 m_fplanf = sfft_init(m_size, SFFT_FORWARD | FLAG_SFFT_FLOAT);
|
Chris@29
|
2114 m_fplani = sfft_init(m_size, SFFT_BACKWARD | FLAG_SFFT_FLOAT);
|
Chris@29
|
2115 if (!m_fplanf || !m_fplani) {
|
Chris@29
|
2116 if (!m_fplanf) {
|
Chris@29
|
2117 std::cerr << "D_SFFT: Failed to construct forward float transform for size " << m_size << " (check SFFT library's target configuration)" << std::endl;
|
Chris@29
|
2118 } else {
|
Chris@29
|
2119 std::cerr << "D_SFFT: Failed to construct inverse float transform for size " << m_size << " (check SFFT library's target configuration)" << std::endl;
|
Chris@29
|
2120 }
|
Chris@29
|
2121 #ifndef NO_EXCEPTIONS
|
Chris@29
|
2122 throw FFT::InternalError;
|
Chris@29
|
2123 #else
|
Chris@29
|
2124 abort();
|
Chris@29
|
2125 #endif
|
Chris@29
|
2126 }
|
Chris@29
|
2127 }
|
Chris@29
|
2128
|
Chris@29
|
2129 void initDouble() {
|
Chris@29
|
2130 if (m_dplanf) return;
|
Chris@29
|
2131 m_dbuf = allocate<fft_double_type>(2 * m_size);
|
Chris@29
|
2132 m_dresult = allocate<fft_double_type>(2 * m_size);
|
Chris@29
|
2133 m_dplanf = sfft_init(m_size, SFFT_FORWARD | FLAG_SFFT_DOUBLE);
|
Chris@29
|
2134 m_dplani = sfft_init(m_size, SFFT_BACKWARD | FLAG_SFFT_DOUBLE);
|
Chris@29
|
2135 if (!m_dplanf || !m_dplani) {
|
Chris@29
|
2136 if (!m_dplanf) {
|
Chris@29
|
2137 std::cerr << "D_SFFT: Failed to construct forward double transform for size " << m_size << " (check SFFT library's target configuration)" << std::endl;
|
Chris@29
|
2138 } else {
|
Chris@29
|
2139 std::cerr << "D_SFFT: Failed to construct inverse double transform for size " << m_size << " (check SFFT library's target configuration)" << std::endl;
|
Chris@29
|
2140 }
|
Chris@29
|
2141 #ifndef NO_EXCEPTIONS
|
Chris@29
|
2142 throw FFT::InternalError;
|
Chris@29
|
2143 #else
|
Chris@29
|
2144 abort();
|
Chris@29
|
2145 #endif
|
Chris@29
|
2146 }
|
Chris@29
|
2147 }
|
Chris@29
|
2148
|
Chris@29
|
2149 void packFloat(const float *BQ_R__ re, const float *BQ_R__ im, fft_float_type *target, int n) {
|
Chris@29
|
2150 for (int i = 0; i < n; ++i) target[i*2] = re[i];
|
Chris@29
|
2151 if (im) {
|
Chris@29
|
2152 for (int i = 0; i < n; ++i) target[i*2+1] = im[i];
|
Chris@29
|
2153 } else {
|
Chris@29
|
2154 for (int i = 0; i < n; ++i) target[i*2+1] = 0.f;
|
Chris@29
|
2155 }
|
Chris@29
|
2156 }
|
Chris@29
|
2157
|
Chris@29
|
2158 void packDouble(const double *BQ_R__ re, const double *BQ_R__ im, fft_double_type *target, int n) {
|
Chris@29
|
2159 for (int i = 0; i < n; ++i) target[i*2] = re[i];
|
Chris@29
|
2160 if (im) {
|
Chris@29
|
2161 for (int i = 0; i < n; ++i) target[i*2+1] = im[i];
|
Chris@29
|
2162 } else {
|
Chris@29
|
2163 for (int i = 0; i < n; ++i) target[i*2+1] = 0.0;
|
Chris@29
|
2164 }
|
Chris@29
|
2165 }
|
Chris@29
|
2166
|
Chris@29
|
2167 void unpackFloat(const fft_float_type *source, float *BQ_R__ re, float *BQ_R__ im, int n) {
|
Chris@29
|
2168 for (int i = 0; i < n; ++i) re[i] = source[i*2];
|
Chris@29
|
2169 if (im) {
|
Chris@29
|
2170 for (int i = 0; i < n; ++i) im[i] = source[i*2+1];
|
Chris@29
|
2171 }
|
Chris@29
|
2172 }
|
Chris@29
|
2173
|
Chris@29
|
2174 void unpackDouble(const fft_double_type *source, double *BQ_R__ re, double *BQ_R__ im, int n) {
|
Chris@29
|
2175 for (int i = 0; i < n; ++i) re[i] = source[i*2];
|
Chris@29
|
2176 if (im) {
|
Chris@29
|
2177 for (int i = 0; i < n; ++i) im[i] = source[i*2+1];
|
Chris@29
|
2178 }
|
Chris@29
|
2179 }
|
Chris@29
|
2180
|
Chris@29
|
2181 template<typename T>
|
Chris@29
|
2182 void mirror(T *BQ_R__ cplx, int n) {
|
Chris@29
|
2183 for (int i = 1; i <= n/2; ++i) {
|
Chris@29
|
2184 int j = n-i;
|
Chris@29
|
2185 cplx[j*2] = cplx[i*2];
|
Chris@29
|
2186 cplx[j*2+1] = -cplx[i*2+1];
|
Chris@29
|
2187 }
|
Chris@29
|
2188 }
|
Chris@29
|
2189
|
Chris@29
|
2190 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
2191 if (!m_dplanf) initDouble();
|
Chris@29
|
2192 packDouble(realIn, 0, m_dbuf, m_size);
|
Chris@29
|
2193 sfft_execute(m_dplanf, m_dbuf, m_dresult);
|
Chris@29
|
2194 unpackDouble(m_dresult, realOut, imagOut, m_size/2+1);
|
Chris@29
|
2195 }
|
Chris@29
|
2196
|
Chris@29
|
2197 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
2198 if (!m_dplanf) initDouble();
|
Chris@29
|
2199 packDouble(realIn, 0, m_dbuf, m_size);
|
Chris@29
|
2200 sfft_execute(m_dplanf, m_dbuf, m_dresult);
|
Chris@29
|
2201 v_convert(complexOut, m_dresult, m_size+2); // i.e. m_size/2+1 complex
|
Chris@29
|
2202 }
|
Chris@29
|
2203
|
Chris@29
|
2204 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
2205 if (!m_dplanf) initDouble();
|
Chris@29
|
2206 packDouble(realIn, 0, m_dbuf, m_size);
|
Chris@29
|
2207 sfft_execute(m_dplanf, m_dbuf, m_dresult);
|
Chris@29
|
2208 v_cartesian_interleaved_to_polar(magOut, phaseOut,
|
Chris@29
|
2209 m_dresult, m_size/2+1);
|
Chris@29
|
2210 }
|
Chris@29
|
2211
|
Chris@29
|
2212 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
2213 if (!m_dplanf) initDouble();
|
Chris@29
|
2214 packDouble(realIn, 0, m_dbuf, m_size);
|
Chris@29
|
2215 sfft_execute(m_dplanf, m_dbuf, m_dresult);
|
Chris@29
|
2216 const int hs = m_size/2;
|
Chris@29
|
2217 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2218 magOut[i] = sqrt(m_dresult[i*2] * m_dresult[i*2] +
|
Chris@29
|
2219 m_dresult[i*2+1] * m_dresult[i*2+1]);
|
Chris@29
|
2220 }
|
Chris@29
|
2221 }
|
Chris@29
|
2222
|
Chris@29
|
2223 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
2224 if (!m_fplanf) initFloat();
|
Chris@29
|
2225 packFloat(realIn, 0, m_fbuf, m_size);
|
Chris@29
|
2226 sfft_execute(m_fplanf, m_fbuf, m_fresult);
|
Chris@29
|
2227 unpackFloat(m_fresult, realOut, imagOut, m_size/2+1);
|
Chris@29
|
2228 }
|
Chris@29
|
2229
|
Chris@29
|
2230 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
2231 if (!m_fplanf) initFloat();
|
Chris@29
|
2232 packFloat(realIn, 0, m_fbuf, m_size);
|
Chris@29
|
2233 sfft_execute(m_fplanf, m_fbuf, m_fresult);
|
Chris@29
|
2234 v_convert(complexOut, m_fresult, m_size+2); // i.e. m_size/2+1 complex
|
Chris@29
|
2235 }
|
Chris@29
|
2236
|
Chris@29
|
2237 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
2238 if (!m_fplanf) initFloat();
|
Chris@29
|
2239 packFloat(realIn, 0, m_fbuf, m_size);
|
Chris@29
|
2240 sfft_execute(m_fplanf, m_fbuf, m_fresult);
|
Chris@29
|
2241 v_cartesian_interleaved_to_polar(magOut, phaseOut,
|
Chris@29
|
2242 m_fresult, m_size/2+1);
|
Chris@29
|
2243 }
|
Chris@29
|
2244
|
Chris@29
|
2245 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
2246 if (!m_fplanf) initFloat();
|
Chris@29
|
2247 packFloat(realIn, 0, m_fbuf, m_size);
|
Chris@29
|
2248 sfft_execute(m_fplanf, m_fbuf, m_fresult);
|
Chris@29
|
2249 const int hs = m_size/2;
|
Chris@29
|
2250 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2251 magOut[i] = sqrtf(m_fresult[i*2] * m_fresult[i*2] +
|
Chris@29
|
2252 m_fresult[i*2+1] * m_fresult[i*2+1]);
|
Chris@29
|
2253 }
|
Chris@29
|
2254 }
|
Chris@29
|
2255
|
Chris@29
|
2256 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
2257 if (!m_dplanf) initDouble();
|
Chris@29
|
2258 packDouble(realIn, imagIn, m_dbuf, m_size/2+1);
|
Chris@29
|
2259 mirror(m_dbuf, m_size);
|
Chris@29
|
2260 sfft_execute(m_dplani, m_dbuf, m_dresult);
|
Chris@29
|
2261 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2262 realOut[i] = m_dresult[i*2];
|
Chris@29
|
2263 }
|
Chris@29
|
2264 }
|
Chris@29
|
2265
|
Chris@29
|
2266 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
2267 if (!m_dplanf) initDouble();
|
Chris@29
|
2268 v_convert((double *)m_dbuf, complexIn, m_size + 2);
|
Chris@29
|
2269 mirror(m_dbuf, m_size);
|
Chris@29
|
2270 sfft_execute(m_dplani, m_dbuf, m_dresult);
|
Chris@29
|
2271 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2272 realOut[i] = m_dresult[i*2];
|
Chris@29
|
2273 }
|
Chris@29
|
2274 }
|
Chris@29
|
2275
|
Chris@29
|
2276 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
2277 if (!m_dplanf) initDouble();
|
Chris@29
|
2278 const int hs = m_size/2;
|
Chris@29
|
2279 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2280 m_dbuf[i*2] = magIn[i] * cos(phaseIn[i]);
|
Chris@29
|
2281 m_dbuf[i*2+1] = magIn[i] * sin(phaseIn[i]);
|
Chris@29
|
2282 }
|
Chris@29
|
2283 mirror(m_dbuf, m_size);
|
Chris@29
|
2284 sfft_execute(m_dplani, m_dbuf, m_dresult);
|
Chris@29
|
2285 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2286 realOut[i] = m_dresult[i*2];
|
Chris@29
|
2287 }
|
Chris@29
|
2288 }
|
Chris@29
|
2289
|
Chris@29
|
2290 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
2291 if (!m_dplanf) initDouble();
|
Chris@29
|
2292 const int hs = m_size/2;
|
Chris@29
|
2293 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2294 m_dbuf[i*2] = log(magIn[i] + 0.000001);
|
Chris@29
|
2295 m_dbuf[i*2+1] = 0.0;
|
Chris@29
|
2296 }
|
Chris@29
|
2297 mirror(m_dbuf, m_size);
|
Chris@29
|
2298 sfft_execute(m_dplani, m_dbuf, m_dresult);
|
Chris@29
|
2299 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2300 cepOut[i] = m_dresult[i*2];
|
Chris@29
|
2301 }
|
Chris@29
|
2302 }
|
Chris@29
|
2303
|
Chris@29
|
2304 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
2305 if (!m_fplanf) initFloat();
|
Chris@29
|
2306 packFloat(realIn, imagIn, m_fbuf, m_size/2+1);
|
Chris@29
|
2307 mirror(m_fbuf, m_size);
|
Chris@29
|
2308 sfft_execute(m_fplani, m_fbuf, m_fresult);
|
Chris@29
|
2309 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2310 realOut[i] = m_fresult[i*2];
|
Chris@29
|
2311 }
|
Chris@29
|
2312 }
|
Chris@29
|
2313
|
Chris@29
|
2314 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
2315 if (!m_fplanf) initFloat();
|
Chris@29
|
2316 v_convert((float *)m_fbuf, complexIn, m_size + 2);
|
Chris@29
|
2317 mirror(m_fbuf, m_size);
|
Chris@29
|
2318 sfft_execute(m_fplani, m_fbuf, m_fresult);
|
Chris@29
|
2319 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2320 realOut[i] = m_fresult[i*2];
|
Chris@29
|
2321 }
|
Chris@29
|
2322 }
|
Chris@29
|
2323
|
Chris@29
|
2324 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
2325 if (!m_fplanf) initFloat();
|
Chris@29
|
2326 const int hs = m_size/2;
|
Chris@29
|
2327 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2328 m_fbuf[i*2] = magIn[i] * cosf(phaseIn[i]);
|
Chris@29
|
2329 m_fbuf[i*2+1] = magIn[i] * sinf(phaseIn[i]);
|
Chris@29
|
2330 }
|
Chris@29
|
2331 mirror(m_fbuf, m_size);
|
Chris@29
|
2332 sfft_execute(m_fplani, m_fbuf, m_fresult);
|
Chris@29
|
2333 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2334 realOut[i] = m_fresult[i*2];
|
Chris@29
|
2335 }
|
Chris@29
|
2336 }
|
Chris@29
|
2337
|
Chris@29
|
2338 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
2339 if (!m_fplanf) initFloat();
|
Chris@29
|
2340 const int hs = m_size/2;
|
Chris@29
|
2341 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2342 m_fbuf[i*2] = logf(magIn[i] + 0.00001);
|
Chris@29
|
2343 m_fbuf[i*2+1] = 0.0f;
|
Chris@29
|
2344 }
|
Chris@29
|
2345 sfft_execute(m_fplani, m_fbuf, m_fresult);
|
Chris@29
|
2346 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2347 cepOut[i] = m_fresult[i*2];
|
Chris@29
|
2348 }
|
Chris@29
|
2349 }
|
Chris@29
|
2350
|
Chris@29
|
2351 private:
|
Chris@29
|
2352 sfft_plan_t *m_fplanf;
|
Chris@29
|
2353 sfft_plan_t *m_fplani;
|
Chris@29
|
2354 fft_float_type *m_fbuf;
|
Chris@29
|
2355 fft_float_type *m_fresult;
|
Chris@29
|
2356
|
Chris@29
|
2357 sfft_plan_t *m_dplanf;
|
Chris@29
|
2358 sfft_plan_t *m_dplani;
|
Chris@29
|
2359 fft_double_type *m_dbuf;
|
Chris@29
|
2360 fft_double_type *m_dresult;
|
Chris@29
|
2361
|
Chris@29
|
2362 const int m_size;
|
Chris@29
|
2363 };
|
Chris@29
|
2364
|
Chris@29
|
2365 #endif /* HAVE_SFFT */
|
Chris@29
|
2366
|
Chris@29
|
2367 #ifdef HAVE_KISSFFT
|
Chris@29
|
2368
|
Chris@29
|
2369 class D_KISSFFT : public FFTImpl
|
Chris@29
|
2370 {
|
Chris@29
|
2371 public:
|
Chris@29
|
2372 D_KISSFFT(int size) :
|
Chris@29
|
2373 m_size(size),
|
Chris@29
|
2374 m_fplanf(0),
|
Chris@29
|
2375 m_fplani(0)
|
Chris@29
|
2376 {
|
Chris@29
|
2377 #ifdef FIXED_POINT
|
Chris@29
|
2378 #error KISSFFT is not configured for float values
|
Chris@29
|
2379 #endif
|
Chris@29
|
2380 if (sizeof(kiss_fft_scalar) != sizeof(float)) {
|
Chris@29
|
2381 std::cerr << "ERROR: KISSFFT is not configured for float values"
|
Chris@29
|
2382 << std::endl;
|
Chris@29
|
2383 }
|
Chris@29
|
2384
|
Chris@29
|
2385 m_fbuf = new kiss_fft_scalar[m_size + 2];
|
Chris@29
|
2386 m_fpacked = new kiss_fft_cpx[m_size + 2];
|
Chris@29
|
2387 m_fplanf = kiss_fftr_alloc(m_size, 0, NULL, NULL);
|
Chris@29
|
2388 m_fplani = kiss_fftr_alloc(m_size, 1, NULL, NULL);
|
Chris@29
|
2389 }
|
Chris@29
|
2390
|
Chris@29
|
2391 ~D_KISSFFT() {
|
Chris@29
|
2392 kiss_fftr_free(m_fplanf);
|
Chris@29
|
2393 kiss_fftr_free(m_fplani);
|
Chris@29
|
2394 kiss_fft_cleanup();
|
Chris@29
|
2395
|
Chris@29
|
2396 delete[] m_fbuf;
|
Chris@29
|
2397 delete[] m_fpacked;
|
Chris@29
|
2398 }
|
Chris@29
|
2399
|
Chris@29
|
2400 FFT::Precisions
|
Chris@29
|
2401 getSupportedPrecisions() const {
|
Chris@29
|
2402 return FFT::SinglePrecision;
|
Chris@29
|
2403 }
|
Chris@29
|
2404
|
Chris@29
|
2405 void initFloat() { }
|
Chris@29
|
2406 void initDouble() { }
|
Chris@29
|
2407
|
Chris@29
|
2408 void packFloat(const float *BQ_R__ re, const float *BQ_R__ im) {
|
Chris@29
|
2409 const int hs = m_size/2;
|
Chris@29
|
2410 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2411 m_fpacked[i].r = re[i];
|
Chris@29
|
2412 }
|
Chris@29
|
2413 if (im) {
|
Chris@29
|
2414 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2415 m_fpacked[i].i = im[i];
|
Chris@29
|
2416 }
|
Chris@29
|
2417 } else {
|
Chris@29
|
2418 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2419 m_fpacked[i].i = 0.f;
|
Chris@29
|
2420 }
|
Chris@29
|
2421 }
|
Chris@29
|
2422 }
|
Chris@29
|
2423
|
Chris@29
|
2424 void unpackFloat(float *BQ_R__ re, float *BQ_R__ im) {
|
Chris@29
|
2425 const int hs = m_size/2;
|
Chris@29
|
2426 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2427 re[i] = m_fpacked[i].r;
|
Chris@29
|
2428 }
|
Chris@29
|
2429 if (im) {
|
Chris@29
|
2430 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2431 im[i] = m_fpacked[i].i;
|
Chris@29
|
2432 }
|
Chris@29
|
2433 }
|
Chris@29
|
2434 }
|
Chris@29
|
2435
|
Chris@29
|
2436 void packDouble(const double *BQ_R__ re, const double *BQ_R__ im) {
|
Chris@29
|
2437 const int hs = m_size/2;
|
Chris@29
|
2438 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2439 m_fpacked[i].r = float(re[i]);
|
Chris@29
|
2440 }
|
Chris@29
|
2441 if (im) {
|
Chris@29
|
2442 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2443 m_fpacked[i].i = float(im[i]);
|
Chris@29
|
2444 }
|
Chris@29
|
2445 } else {
|
Chris@29
|
2446 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2447 m_fpacked[i].i = 0.f;
|
Chris@29
|
2448 }
|
Chris@29
|
2449 }
|
Chris@29
|
2450 }
|
Chris@29
|
2451
|
Chris@29
|
2452 void unpackDouble(double *BQ_R__ re, double *BQ_R__ im) {
|
Chris@29
|
2453 const int hs = m_size/2;
|
Chris@29
|
2454 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2455 re[i] = double(m_fpacked[i].r);
|
Chris@29
|
2456 }
|
Chris@29
|
2457 if (im) {
|
Chris@29
|
2458 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2459 im[i] = double(m_fpacked[i].i);
|
Chris@29
|
2460 }
|
Chris@29
|
2461 }
|
Chris@29
|
2462 }
|
Chris@29
|
2463
|
Chris@29
|
2464 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
2465
|
Chris@29
|
2466 v_convert(m_fbuf, realIn, m_size);
|
Chris@29
|
2467 kiss_fftr(m_fplanf, m_fbuf, m_fpacked);
|
Chris@29
|
2468 unpackDouble(realOut, imagOut);
|
Chris@29
|
2469 }
|
Chris@29
|
2470
|
Chris@29
|
2471 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
2472
|
Chris@29
|
2473 v_convert(m_fbuf, realIn, m_size);
|
Chris@29
|
2474 kiss_fftr(m_fplanf, m_fbuf, m_fpacked);
|
Chris@29
|
2475 v_convert(complexOut, (float *)m_fpacked, m_size + 2);
|
Chris@29
|
2476 }
|
Chris@29
|
2477
|
Chris@29
|
2478 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
2479
|
Chris@29
|
2480 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2481 m_fbuf[i] = float(realIn[i]);
|
Chris@29
|
2482 }
|
Chris@29
|
2483
|
Chris@29
|
2484 kiss_fftr(m_fplanf, m_fbuf, m_fpacked);
|
Chris@29
|
2485
|
Chris@29
|
2486 const int hs = m_size/2;
|
Chris@29
|
2487
|
Chris@29
|
2488 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2489 magOut[i] = sqrt(double(m_fpacked[i].r) * double(m_fpacked[i].r) +
|
Chris@29
|
2490 double(m_fpacked[i].i) * double(m_fpacked[i].i));
|
Chris@29
|
2491 }
|
Chris@29
|
2492
|
Chris@29
|
2493 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2494 phaseOut[i] = atan2(double(m_fpacked[i].i), double(m_fpacked[i].r));
|
Chris@29
|
2495 }
|
Chris@29
|
2496 }
|
Chris@29
|
2497
|
Chris@29
|
2498 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
2499
|
Chris@29
|
2500 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2501 m_fbuf[i] = float(realIn[i]);
|
Chris@29
|
2502 }
|
Chris@29
|
2503
|
Chris@29
|
2504 kiss_fftr(m_fplanf, m_fbuf, m_fpacked);
|
Chris@29
|
2505
|
Chris@29
|
2506 const int hs = m_size/2;
|
Chris@29
|
2507
|
Chris@29
|
2508 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2509 magOut[i] = sqrt(double(m_fpacked[i].r) * double(m_fpacked[i].r) +
|
Chris@29
|
2510 double(m_fpacked[i].i) * double(m_fpacked[i].i));
|
Chris@29
|
2511 }
|
Chris@29
|
2512 }
|
Chris@29
|
2513
|
Chris@29
|
2514 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
2515
|
Chris@29
|
2516 kiss_fftr(m_fplanf, realIn, m_fpacked);
|
Chris@29
|
2517 unpackFloat(realOut, imagOut);
|
Chris@29
|
2518 }
|
Chris@29
|
2519
|
Chris@29
|
2520 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
2521
|
Chris@29
|
2522 kiss_fftr(m_fplanf, realIn, (kiss_fft_cpx *)complexOut);
|
Chris@29
|
2523 }
|
Chris@29
|
2524
|
Chris@29
|
2525 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
2526
|
Chris@29
|
2527 kiss_fftr(m_fplanf, realIn, m_fpacked);
|
Chris@29
|
2528
|
Chris@29
|
2529 const int hs = m_size/2;
|
Chris@29
|
2530
|
Chris@29
|
2531 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2532 magOut[i] = sqrtf(m_fpacked[i].r * m_fpacked[i].r +
|
Chris@29
|
2533 m_fpacked[i].i * m_fpacked[i].i);
|
Chris@29
|
2534 }
|
Chris@29
|
2535
|
Chris@29
|
2536 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2537 phaseOut[i] = atan2f(m_fpacked[i].i, m_fpacked[i].r);
|
Chris@29
|
2538 }
|
Chris@29
|
2539 }
|
Chris@29
|
2540
|
Chris@29
|
2541 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
2542
|
Chris@29
|
2543 kiss_fftr(m_fplanf, realIn, m_fpacked);
|
Chris@29
|
2544
|
Chris@29
|
2545 const int hs = m_size/2;
|
Chris@29
|
2546
|
Chris@29
|
2547 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2548 magOut[i] = sqrtf(m_fpacked[i].r * m_fpacked[i].r +
|
Chris@29
|
2549 m_fpacked[i].i * m_fpacked[i].i);
|
Chris@29
|
2550 }
|
Chris@29
|
2551 }
|
Chris@29
|
2552
|
Chris@29
|
2553 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
2554
|
Chris@29
|
2555 packDouble(realIn, imagIn);
|
Chris@29
|
2556
|
Chris@29
|
2557 kiss_fftri(m_fplani, m_fpacked, m_fbuf);
|
Chris@29
|
2558
|
Chris@29
|
2559 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2560 realOut[i] = m_fbuf[i];
|
Chris@29
|
2561 }
|
Chris@29
|
2562 }
|
Chris@29
|
2563
|
Chris@29
|
2564 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
2565
|
Chris@29
|
2566 v_convert((float *)m_fpacked, complexIn, m_size + 2);
|
Chris@29
|
2567
|
Chris@29
|
2568 kiss_fftri(m_fplani, m_fpacked, m_fbuf);
|
Chris@29
|
2569
|
Chris@29
|
2570 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2571 realOut[i] = m_fbuf[i];
|
Chris@29
|
2572 }
|
Chris@29
|
2573 }
|
Chris@29
|
2574
|
Chris@29
|
2575 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
2576
|
Chris@29
|
2577 const int hs = m_size/2;
|
Chris@29
|
2578
|
Chris@29
|
2579 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2580 m_fpacked[i].r = float(magIn[i] * cos(phaseIn[i]));
|
Chris@29
|
2581 m_fpacked[i].i = float(magIn[i] * sin(phaseIn[i]));
|
Chris@29
|
2582 }
|
Chris@29
|
2583
|
Chris@29
|
2584 kiss_fftri(m_fplani, m_fpacked, m_fbuf);
|
Chris@29
|
2585
|
Chris@29
|
2586 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2587 realOut[i] = m_fbuf[i];
|
Chris@29
|
2588 }
|
Chris@29
|
2589 }
|
Chris@29
|
2590
|
Chris@29
|
2591 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
2592
|
Chris@29
|
2593 const int hs = m_size/2;
|
Chris@29
|
2594
|
Chris@29
|
2595 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2596 m_fpacked[i].r = float(log(magIn[i] + 0.000001));
|
Chris@29
|
2597 m_fpacked[i].i = 0.0f;
|
Chris@29
|
2598 }
|
Chris@29
|
2599
|
Chris@29
|
2600 kiss_fftri(m_fplani, m_fpacked, m_fbuf);
|
Chris@29
|
2601
|
Chris@29
|
2602 for (int i = 0; i < m_size; ++i) {
|
Chris@29
|
2603 cepOut[i] = m_fbuf[i];
|
Chris@29
|
2604 }
|
Chris@29
|
2605 }
|
Chris@29
|
2606
|
Chris@29
|
2607 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
2608
|
Chris@29
|
2609 packFloat(realIn, imagIn);
|
Chris@29
|
2610 kiss_fftri(m_fplani, m_fpacked, realOut);
|
Chris@29
|
2611 }
|
Chris@29
|
2612
|
Chris@29
|
2613 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
2614
|
Chris@29
|
2615 v_copy((float *)m_fpacked, complexIn, m_size + 2);
|
Chris@29
|
2616 kiss_fftri(m_fplani, m_fpacked, realOut);
|
Chris@29
|
2617 }
|
Chris@29
|
2618
|
Chris@29
|
2619 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
2620
|
Chris@29
|
2621 const int hs = m_size/2;
|
Chris@29
|
2622
|
Chris@29
|
2623 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2624 m_fpacked[i].r = magIn[i] * cosf(phaseIn[i]);
|
Chris@29
|
2625 m_fpacked[i].i = magIn[i] * sinf(phaseIn[i]);
|
Chris@29
|
2626 }
|
Chris@29
|
2627
|
Chris@29
|
2628 kiss_fftri(m_fplani, m_fpacked, realOut);
|
Chris@29
|
2629 }
|
Chris@29
|
2630
|
Chris@29
|
2631 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
2632
|
Chris@29
|
2633 const int hs = m_size/2;
|
Chris@29
|
2634
|
Chris@29
|
2635 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2636 m_fpacked[i].r = logf(magIn[i] + 0.000001f);
|
Chris@29
|
2637 m_fpacked[i].i = 0.0f;
|
Chris@29
|
2638 }
|
Chris@29
|
2639
|
Chris@29
|
2640 kiss_fftri(m_fplani, m_fpacked, cepOut);
|
Chris@29
|
2641 }
|
Chris@29
|
2642
|
Chris@29
|
2643 private:
|
Chris@29
|
2644 const int m_size;
|
Chris@29
|
2645 kiss_fftr_cfg m_fplanf;
|
Chris@29
|
2646 kiss_fftr_cfg m_fplani;
|
Chris@29
|
2647 kiss_fft_scalar *m_fbuf;
|
Chris@29
|
2648 kiss_fft_cpx *m_fpacked;
|
Chris@29
|
2649 };
|
Chris@29
|
2650
|
Chris@29
|
2651 #endif /* HAVE_KISSFFT */
|
Chris@29
|
2652
|
Chris@29
|
2653 #ifdef USE_BUILTIN_FFT
|
Chris@29
|
2654
|
Chris@29
|
2655 class D_Cross : public FFTImpl
|
Chris@29
|
2656 {
|
Chris@29
|
2657 public:
|
Chris@29
|
2658 D_Cross(int size) : m_size(size), m_table(0) {
|
Chris@29
|
2659
|
Chris@29
|
2660 m_a = new double[size];
|
Chris@29
|
2661 m_b = new double[size];
|
Chris@29
|
2662 m_c = new double[size];
|
Chris@29
|
2663 m_d = new double[size];
|
Chris@29
|
2664
|
Chris@29
|
2665 m_table = new int[m_size];
|
Chris@29
|
2666
|
Chris@29
|
2667 int bits;
|
Chris@29
|
2668 int i, j, k, m;
|
Chris@29
|
2669
|
Chris@29
|
2670 for (i = 0; ; ++i) {
|
Chris@29
|
2671 if (m_size & (1 << i)) {
|
Chris@29
|
2672 bits = i;
|
Chris@29
|
2673 break;
|
Chris@29
|
2674 }
|
Chris@29
|
2675 }
|
Chris@29
|
2676
|
Chris@29
|
2677 for (i = 0; i < m_size; ++i) {
|
Chris@29
|
2678
|
Chris@29
|
2679 m = i;
|
Chris@29
|
2680
|
Chris@29
|
2681 for (j = k = 0; j < bits; ++j) {
|
Chris@29
|
2682 k = (k << 1) | (m & 1);
|
Chris@29
|
2683 m >>= 1;
|
Chris@29
|
2684 }
|
Chris@29
|
2685
|
Chris@29
|
2686 m_table[i] = k;
|
Chris@29
|
2687 }
|
Chris@29
|
2688 }
|
Chris@29
|
2689
|
Chris@29
|
2690 ~D_Cross() {
|
Chris@29
|
2691 delete[] m_table;
|
Chris@29
|
2692 delete[] m_a;
|
Chris@29
|
2693 delete[] m_b;
|
Chris@29
|
2694 delete[] m_c;
|
Chris@29
|
2695 delete[] m_d;
|
Chris@29
|
2696 }
|
Chris@29
|
2697
|
Chris@29
|
2698 FFT::Precisions
|
Chris@29
|
2699 getSupportedPrecisions() const {
|
Chris@29
|
2700 return FFT::DoublePrecision;
|
Chris@29
|
2701 }
|
Chris@29
|
2702
|
Chris@29
|
2703 void initFloat() { }
|
Chris@29
|
2704 void initDouble() { }
|
Chris@29
|
2705
|
Chris@29
|
2706 void forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut) {
|
Chris@29
|
2707 basefft(false, realIn, 0, m_c, m_d);
|
Chris@29
|
2708 const int hs = m_size/2;
|
Chris@29
|
2709 for (int i = 0; i <= hs; ++i) realOut[i] = m_c[i];
|
Chris@29
|
2710 if (imagOut) {
|
Chris@29
|
2711 for (int i = 0; i <= hs; ++i) imagOut[i] = m_d[i];
|
Chris@29
|
2712 }
|
Chris@29
|
2713 }
|
Chris@29
|
2714
|
Chris@29
|
2715 void forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut) {
|
Chris@29
|
2716 basefft(false, realIn, 0, m_c, m_d);
|
Chris@29
|
2717 const int hs = m_size/2;
|
Chris@29
|
2718 for (int i = 0; i <= hs; ++i) complexOut[i*2] = m_c[i];
|
Chris@29
|
2719 for (int i = 0; i <= hs; ++i) complexOut[i*2+1] = m_d[i];
|
Chris@29
|
2720 }
|
Chris@29
|
2721
|
Chris@29
|
2722 void forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut) {
|
Chris@29
|
2723 basefft(false, realIn, 0, m_c, m_d);
|
Chris@29
|
2724 const int hs = m_size/2;
|
Chris@29
|
2725 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2726 magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]);
|
Chris@29
|
2727 phaseOut[i] = atan2(m_d[i], m_c[i]) ;
|
Chris@29
|
2728 }
|
Chris@29
|
2729 }
|
Chris@29
|
2730
|
Chris@29
|
2731 void forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut) {
|
Chris@29
|
2732 basefft(false, realIn, 0, m_c, m_d);
|
Chris@29
|
2733 const int hs = m_size/2;
|
Chris@29
|
2734 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2735 magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]);
|
Chris@29
|
2736 }
|
Chris@29
|
2737 }
|
Chris@29
|
2738
|
Chris@29
|
2739 void forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut) {
|
Chris@29
|
2740 for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i];
|
Chris@29
|
2741 basefft(false, m_a, 0, m_c, m_d);
|
Chris@29
|
2742 const int hs = m_size/2;
|
Chris@29
|
2743 for (int i = 0; i <= hs; ++i) realOut[i] = m_c[i];
|
Chris@29
|
2744 if (imagOut) {
|
Chris@29
|
2745 for (int i = 0; i <= hs; ++i) imagOut[i] = m_d[i];
|
Chris@29
|
2746 }
|
Chris@29
|
2747 }
|
Chris@29
|
2748
|
Chris@29
|
2749 void forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut) {
|
Chris@29
|
2750 for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i];
|
Chris@29
|
2751 basefft(false, m_a, 0, m_c, m_d);
|
Chris@29
|
2752 const int hs = m_size/2;
|
Chris@29
|
2753 for (int i = 0; i <= hs; ++i) complexOut[i*2] = m_c[i];
|
Chris@29
|
2754 for (int i = 0; i <= hs; ++i) complexOut[i*2+1] = m_d[i];
|
Chris@29
|
2755 }
|
Chris@29
|
2756
|
Chris@29
|
2757 void forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut) {
|
Chris@29
|
2758 for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i];
|
Chris@29
|
2759 basefft(false, m_a, 0, m_c, m_d);
|
Chris@29
|
2760 const int hs = m_size/2;
|
Chris@29
|
2761 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2762 magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]);
|
Chris@29
|
2763 phaseOut[i] = atan2(m_d[i], m_c[i]) ;
|
Chris@29
|
2764 }
|
Chris@29
|
2765 }
|
Chris@29
|
2766
|
Chris@29
|
2767 void forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut) {
|
Chris@29
|
2768 for (int i = 0; i < m_size; ++i) m_a[i] = realIn[i];
|
Chris@29
|
2769 basefft(false, m_a, 0, m_c, m_d);
|
Chris@29
|
2770 const int hs = m_size/2;
|
Chris@29
|
2771 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2772 magOut[i] = sqrt(m_c[i] * m_c[i] + m_d[i] * m_d[i]);
|
Chris@29
|
2773 }
|
Chris@29
|
2774 }
|
Chris@29
|
2775
|
Chris@29
|
2776 void inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut) {
|
Chris@29
|
2777 const int hs = m_size/2;
|
Chris@29
|
2778 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2779 double real = realIn[i];
|
Chris@29
|
2780 double imag = imagIn[i];
|
Chris@29
|
2781 m_a[i] = real;
|
Chris@29
|
2782 m_b[i] = imag;
|
Chris@29
|
2783 if (i > 0) {
|
Chris@29
|
2784 m_a[m_size-i] = real;
|
Chris@29
|
2785 m_b[m_size-i] = -imag;
|
Chris@29
|
2786 }
|
Chris@29
|
2787 }
|
Chris@29
|
2788 basefft(true, m_a, m_b, realOut, m_d);
|
Chris@29
|
2789 }
|
Chris@29
|
2790
|
Chris@29
|
2791 void inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut) {
|
Chris@29
|
2792 const int hs = m_size/2;
|
Chris@29
|
2793 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2794 double real = complexIn[i*2];
|
Chris@29
|
2795 double imag = complexIn[i*2+1];
|
Chris@29
|
2796 m_a[i] = real;
|
Chris@29
|
2797 m_b[i] = imag;
|
Chris@29
|
2798 if (i > 0) {
|
Chris@29
|
2799 m_a[m_size-i] = real;
|
Chris@29
|
2800 m_b[m_size-i] = -imag;
|
Chris@29
|
2801 }
|
Chris@29
|
2802 }
|
Chris@29
|
2803 basefft(true, m_a, m_b, realOut, m_d);
|
Chris@29
|
2804 }
|
Chris@29
|
2805
|
Chris@29
|
2806 void inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut) {
|
Chris@29
|
2807 const int hs = m_size/2;
|
Chris@29
|
2808 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2809 double real = magIn[i] * cos(phaseIn[i]);
|
Chris@29
|
2810 double imag = magIn[i] * sin(phaseIn[i]);
|
Chris@29
|
2811 m_a[i] = real;
|
Chris@29
|
2812 m_b[i] = imag;
|
Chris@29
|
2813 if (i > 0) {
|
Chris@29
|
2814 m_a[m_size-i] = real;
|
Chris@29
|
2815 m_b[m_size-i] = -imag;
|
Chris@29
|
2816 }
|
Chris@29
|
2817 }
|
Chris@29
|
2818 basefft(true, m_a, m_b, realOut, m_d);
|
Chris@29
|
2819 }
|
Chris@29
|
2820
|
Chris@29
|
2821 void inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut) {
|
Chris@29
|
2822 const int hs = m_size/2;
|
Chris@29
|
2823 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2824 double real = log(magIn[i] + 0.000001);
|
Chris@29
|
2825 m_a[i] = real;
|
Chris@29
|
2826 m_b[i] = 0.0;
|
Chris@29
|
2827 if (i > 0) {
|
Chris@29
|
2828 m_a[m_size-i] = real;
|
Chris@29
|
2829 m_b[m_size-i] = 0.0;
|
Chris@29
|
2830 }
|
Chris@29
|
2831 }
|
Chris@29
|
2832 basefft(true, m_a, m_b, cepOut, m_d);
|
Chris@29
|
2833 }
|
Chris@29
|
2834
|
Chris@29
|
2835 void inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut) {
|
Chris@29
|
2836 const int hs = m_size/2;
|
Chris@29
|
2837 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2838 float real = realIn[i];
|
Chris@29
|
2839 float imag = imagIn[i];
|
Chris@29
|
2840 m_a[i] = real;
|
Chris@29
|
2841 m_b[i] = imag;
|
Chris@29
|
2842 if (i > 0) {
|
Chris@29
|
2843 m_a[m_size-i] = real;
|
Chris@29
|
2844 m_b[m_size-i] = -imag;
|
Chris@29
|
2845 }
|
Chris@29
|
2846 }
|
Chris@29
|
2847 basefft(true, m_a, m_b, m_c, m_d);
|
Chris@29
|
2848 for (int i = 0; i < m_size; ++i) realOut[i] = m_c[i];
|
Chris@29
|
2849 }
|
Chris@29
|
2850
|
Chris@29
|
2851 void inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut) {
|
Chris@29
|
2852 const int hs = m_size/2;
|
Chris@29
|
2853 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2854 float real = complexIn[i*2];
|
Chris@29
|
2855 float imag = complexIn[i*2+1];
|
Chris@29
|
2856 m_a[i] = real;
|
Chris@29
|
2857 m_b[i] = imag;
|
Chris@29
|
2858 if (i > 0) {
|
Chris@29
|
2859 m_a[m_size-i] = real;
|
Chris@29
|
2860 m_b[m_size-i] = -imag;
|
Chris@29
|
2861 }
|
Chris@29
|
2862 }
|
Chris@29
|
2863 basefft(true, m_a, m_b, m_c, m_d);
|
Chris@29
|
2864 for (int i = 0; i < m_size; ++i) realOut[i] = m_c[i];
|
Chris@29
|
2865 }
|
Chris@29
|
2866
|
Chris@29
|
2867 void inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut) {
|
Chris@29
|
2868 const int hs = m_size/2;
|
Chris@29
|
2869 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2870 float real = magIn[i] * cosf(phaseIn[i]);
|
Chris@29
|
2871 float imag = magIn[i] * sinf(phaseIn[i]);
|
Chris@29
|
2872 m_a[i] = real;
|
Chris@29
|
2873 m_b[i] = imag;
|
Chris@29
|
2874 if (i > 0) {
|
Chris@29
|
2875 m_a[m_size-i] = real;
|
Chris@29
|
2876 m_b[m_size-i] = -imag;
|
Chris@29
|
2877 }
|
Chris@29
|
2878 }
|
Chris@29
|
2879 basefft(true, m_a, m_b, m_c, m_d);
|
Chris@29
|
2880 for (int i = 0; i < m_size; ++i) realOut[i] = m_c[i];
|
Chris@29
|
2881 }
|
Chris@29
|
2882
|
Chris@29
|
2883 void inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut) {
|
Chris@29
|
2884 const int hs = m_size/2;
|
Chris@29
|
2885 for (int i = 0; i <= hs; ++i) {
|
Chris@29
|
2886 float real = logf(magIn[i] + 0.000001);
|
Chris@29
|
2887 m_a[i] = real;
|
Chris@29
|
2888 m_b[i] = 0.0;
|
Chris@29
|
2889 if (i > 0) {
|
Chris@29
|
2890 m_a[m_size-i] = real;
|
Chris@29
|
2891 m_b[m_size-i] = 0.0;
|
Chris@29
|
2892 }
|
Chris@29
|
2893 }
|
Chris@29
|
2894 basefft(true, m_a, m_b, m_c, m_d);
|
Chris@29
|
2895 for (int i = 0; i < m_size; ++i) cepOut[i] = m_c[i];
|
Chris@29
|
2896 }
|
Chris@29
|
2897
|
Chris@29
|
2898 private:
|
Chris@29
|
2899 const int m_size;
|
Chris@29
|
2900 int *m_table;
|
Chris@29
|
2901 double *m_a;
|
Chris@29
|
2902 double *m_b;
|
Chris@29
|
2903 double *m_c;
|
Chris@29
|
2904 double *m_d;
|
Chris@29
|
2905 void basefft(bool inverse, const double *BQ_R__ ri, const double *BQ_R__ ii, double *BQ_R__ ro, double *BQ_R__ io);
|
Chris@29
|
2906 };
|
Chris@29
|
2907
|
Chris@29
|
2908 void
|
Chris@29
|
2909 D_Cross::basefft(bool inverse, const double *BQ_R__ ri, const double *BQ_R__ ii, double *BQ_R__ ro, double *BQ_R__ io)
|
Chris@29
|
2910 {
|
Chris@29
|
2911 if (!ri || !ro || !io) return;
|
Chris@29
|
2912
|
Chris@29
|
2913 int i, j, k, m;
|
Chris@29
|
2914 int blockSize, blockEnd;
|
Chris@29
|
2915
|
Chris@29
|
2916 double tr, ti;
|
Chris@29
|
2917
|
Chris@29
|
2918 double angle = 2.0 * M_PI;
|
Chris@29
|
2919 if (inverse) angle = -angle;
|
Chris@29
|
2920
|
Chris@29
|
2921 const int n = m_size;
|
Chris@29
|
2922
|
Chris@29
|
2923 if (ii) {
|
Chris@29
|
2924 for (i = 0; i < n; ++i) {
|
Chris@29
|
2925 ro[m_table[i]] = ri[i];
|
Chris@29
|
2926 }
|
Chris@29
|
2927 for (i = 0; i < n; ++i) {
|
Chris@29
|
2928 io[m_table[i]] = ii[i];
|
Chris@29
|
2929 }
|
Chris@29
|
2930 } else {
|
Chris@29
|
2931 for (i = 0; i < n; ++i) {
|
Chris@29
|
2932 ro[m_table[i]] = ri[i];
|
Chris@29
|
2933 }
|
Chris@29
|
2934 for (i = 0; i < n; ++i) {
|
Chris@29
|
2935 io[m_table[i]] = 0.0;
|
Chris@29
|
2936 }
|
Chris@29
|
2937 }
|
Chris@29
|
2938
|
Chris@29
|
2939 blockEnd = 1;
|
Chris@29
|
2940
|
Chris@29
|
2941 for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
|
Chris@29
|
2942
|
Chris@29
|
2943 double delta = angle / (double)blockSize;
|
Chris@29
|
2944 double sm2 = -sin(-2 * delta);
|
Chris@29
|
2945 double sm1 = -sin(-delta);
|
Chris@29
|
2946 double cm2 = cos(-2 * delta);
|
Chris@29
|
2947 double cm1 = cos(-delta);
|
Chris@29
|
2948 double w = 2 * cm1;
|
Chris@29
|
2949 double ar[3], ai[3];
|
Chris@29
|
2950
|
Chris@29
|
2951 for (i = 0; i < n; i += blockSize) {
|
Chris@29
|
2952
|
Chris@29
|
2953 ar[2] = cm2;
|
Chris@29
|
2954 ar[1] = cm1;
|
Chris@29
|
2955
|
Chris@29
|
2956 ai[2] = sm2;
|
Chris@29
|
2957 ai[1] = sm1;
|
Chris@29
|
2958
|
Chris@29
|
2959 for (j = i, m = 0; m < blockEnd; j++, m++) {
|
Chris@29
|
2960
|
Chris@29
|
2961 ar[0] = w * ar[1] - ar[2];
|
Chris@29
|
2962 ar[2] = ar[1];
|
Chris@29
|
2963 ar[1] = ar[0];
|
Chris@29
|
2964
|
Chris@29
|
2965 ai[0] = w * ai[1] - ai[2];
|
Chris@29
|
2966 ai[2] = ai[1];
|
Chris@29
|
2967 ai[1] = ai[0];
|
Chris@29
|
2968
|
Chris@29
|
2969 k = j + blockEnd;
|
Chris@29
|
2970 tr = ar[0] * ro[k] - ai[0] * io[k];
|
Chris@29
|
2971 ti = ar[0] * io[k] + ai[0] * ro[k];
|
Chris@29
|
2972
|
Chris@29
|
2973 ro[k] = ro[j] - tr;
|
Chris@29
|
2974 io[k] = io[j] - ti;
|
Chris@29
|
2975
|
Chris@29
|
2976 ro[j] += tr;
|
Chris@29
|
2977 io[j] += ti;
|
Chris@29
|
2978 }
|
Chris@29
|
2979 }
|
Chris@29
|
2980
|
Chris@29
|
2981 blockEnd = blockSize;
|
Chris@29
|
2982 }
|
Chris@29
|
2983
|
Chris@29
|
2984 /* fftw doesn't rescale, so nor will we
|
Chris@29
|
2985
|
Chris@29
|
2986 if (inverse) {
|
Chris@29
|
2987
|
Chris@29
|
2988 double denom = (double)n;
|
Chris@29
|
2989
|
Chris@29
|
2990 for (i = 0; i < n; i++) {
|
Chris@29
|
2991 ro[i] /= denom;
|
Chris@29
|
2992 io[i] /= denom;
|
Chris@29
|
2993 }
|
Chris@29
|
2994 }
|
Chris@29
|
2995 */
|
Chris@29
|
2996 }
|
Chris@29
|
2997
|
Chris@29
|
2998 #endif /* USE_BUILTIN_FFT */
|
Chris@29
|
2999
|
Chris@29
|
3000 } /* end namespace FFTs */
|
Chris@29
|
3001
|
Chris@29
|
3002 std::string
|
Chris@29
|
3003 FFT::m_implementation;
|
Chris@29
|
3004
|
Chris@29
|
3005 std::set<std::string>
|
Chris@29
|
3006 FFT::getImplementations()
|
Chris@29
|
3007 {
|
Chris@29
|
3008 std::set<std::string> impls;
|
Chris@29
|
3009 #ifdef HAVE_IPP
|
Chris@29
|
3010 impls.insert("ipp");
|
Chris@29
|
3011 #endif
|
Chris@29
|
3012 #ifdef HAVE_FFTW3
|
Chris@29
|
3013 impls.insert("fftw");
|
Chris@29
|
3014 #endif
|
Chris@29
|
3015 #ifdef HAVE_KISSFFT
|
Chris@29
|
3016 impls.insert("kissfft");
|
Chris@29
|
3017 #endif
|
Chris@29
|
3018 #ifdef HAVE_VDSP
|
Chris@29
|
3019 impls.insert("vdsp");
|
Chris@29
|
3020 #endif
|
Chris@29
|
3021 #ifdef HAVE_MEDIALIB
|
Chris@29
|
3022 impls.insert("medialib");
|
Chris@29
|
3023 #endif
|
Chris@29
|
3024 #ifdef HAVE_OPENMAX
|
Chris@29
|
3025 impls.insert("openmax");
|
Chris@29
|
3026 #endif
|
Chris@29
|
3027 #ifdef HAVE_SFFT
|
Chris@29
|
3028 impls.insert("sfft");
|
Chris@29
|
3029 #endif
|
Chris@29
|
3030 #ifdef USE_BUILTIN_FFT
|
Chris@29
|
3031 impls.insert("cross");
|
Chris@29
|
3032 #endif
|
Chris@29
|
3033 return impls;
|
Chris@29
|
3034 }
|
Chris@29
|
3035
|
Chris@29
|
3036 void
|
Chris@29
|
3037 FFT::pickDefaultImplementation()
|
Chris@29
|
3038 {
|
Chris@29
|
3039 if (m_implementation != "") return;
|
Chris@29
|
3040
|
Chris@29
|
3041 std::set<std::string> impls = getImplementations();
|
Chris@29
|
3042
|
Chris@29
|
3043 std::string best = "cross";
|
Chris@29
|
3044 if (impls.find("kissfft") != impls.end()) best = "kissfft";
|
Chris@29
|
3045 if (impls.find("medialib") != impls.end()) best = "medialib";
|
Chris@29
|
3046 if (impls.find("openmax") != impls.end()) best = "openmax";
|
Chris@29
|
3047 if (impls.find("sfft") != impls.end()) best = "sfft";
|
Chris@29
|
3048 if (impls.find("fftw") != impls.end()) best = "fftw";
|
Chris@29
|
3049 if (impls.find("vdsp") != impls.end()) best = "vdsp";
|
Chris@29
|
3050 if (impls.find("ipp") != impls.end()) best = "ipp";
|
Chris@29
|
3051
|
Chris@29
|
3052 m_implementation = best;
|
Chris@29
|
3053 }
|
Chris@29
|
3054
|
Chris@29
|
3055 std::string
|
Chris@29
|
3056 FFT::getDefaultImplementation()
|
Chris@29
|
3057 {
|
Chris@29
|
3058 return m_implementation;
|
Chris@29
|
3059 }
|
Chris@29
|
3060
|
Chris@29
|
3061 void
|
Chris@29
|
3062 FFT::setDefaultImplementation(std::string i)
|
Chris@29
|
3063 {
|
Chris@29
|
3064 m_implementation = i;
|
Chris@29
|
3065 }
|
Chris@29
|
3066
|
Chris@29
|
3067 FFT::FFT(int size, int debugLevel) :
|
Chris@29
|
3068 d(0)
|
Chris@29
|
3069 {
|
Chris@29
|
3070 if ((size < 2) ||
|
Chris@29
|
3071 (size & (size-1))) {
|
Chris@29
|
3072 std::cerr << "FFT::FFT(" << size << "): power-of-two sizes only supported, minimum size 2" << std::endl;
|
Chris@29
|
3073 #ifndef NO_EXCEPTIONS
|
Chris@29
|
3074 throw InvalidSize;
|
Chris@29
|
3075 #else
|
Chris@29
|
3076 abort();
|
Chris@29
|
3077 #endif
|
Chris@29
|
3078 }
|
Chris@29
|
3079
|
Chris@29
|
3080 if (m_implementation == "") pickDefaultImplementation();
|
Chris@29
|
3081 std::string impl = m_implementation;
|
Chris@29
|
3082
|
Chris@29
|
3083 if (debugLevel > 0) {
|
Chris@29
|
3084 std::cerr << "FFT::FFT(" << size << "): using implementation: "
|
Chris@29
|
3085 << impl << std::endl;
|
Chris@29
|
3086 }
|
Chris@29
|
3087
|
Chris@29
|
3088 if (impl == "ipp") {
|
Chris@29
|
3089 #ifdef HAVE_IPP
|
Chris@29
|
3090 d = new FFTs::D_IPP(size);
|
Chris@29
|
3091 #endif
|
Chris@29
|
3092 } else if (impl == "fftw") {
|
Chris@29
|
3093 #ifdef HAVE_FFTW3
|
Chris@29
|
3094 d = new FFTs::D_FFTW(size);
|
Chris@29
|
3095 #endif
|
Chris@29
|
3096 } else if (impl == "kissfft") {
|
Chris@29
|
3097 #ifdef HAVE_KISSFFT
|
Chris@29
|
3098 d = new FFTs::D_KISSFFT(size);
|
Chris@29
|
3099 #endif
|
Chris@29
|
3100 } else if (impl == "vdsp") {
|
Chris@29
|
3101 #ifdef HAVE_VDSP
|
Chris@29
|
3102 d = new FFTs::D_VDSP(size);
|
Chris@29
|
3103 #endif
|
Chris@29
|
3104 } else if (impl == "medialib") {
|
Chris@29
|
3105 #ifdef HAVE_MEDIALIB
|
Chris@29
|
3106 d = new FFTs::D_MEDIALIB(size);
|
Chris@29
|
3107 #endif
|
Chris@29
|
3108 } else if (impl == "openmax") {
|
Chris@29
|
3109 #ifdef HAVE_OPENMAX
|
Chris@29
|
3110 d = new FFTs::D_OPENMAX(size);
|
Chris@29
|
3111 #endif
|
Chris@29
|
3112 } else if (impl == "sfft") {
|
Chris@29
|
3113 #ifdef HAVE_SFFT
|
Chris@29
|
3114 d = new FFTs::D_SFFT(size);
|
Chris@29
|
3115 #endif
|
Chris@29
|
3116 } else if (impl == "cross") {
|
Chris@29
|
3117 #ifdef USE_BUILTIN_FFT
|
Chris@29
|
3118 d = new FFTs::D_Cross(size);
|
Chris@29
|
3119 #endif
|
Chris@29
|
3120 }
|
Chris@29
|
3121
|
Chris@29
|
3122 if (!d) {
|
Chris@29
|
3123 std::cerr << "FFT::FFT(" << size << "): ERROR: implementation "
|
Chris@29
|
3124 << impl << " is not compiled in" << std::endl;
|
Chris@29
|
3125 #ifndef NO_EXCEPTIONS
|
Chris@29
|
3126 throw InvalidImplementation;
|
Chris@29
|
3127 #else
|
Chris@29
|
3128 abort();
|
Chris@29
|
3129 #endif
|
Chris@29
|
3130 }
|
Chris@29
|
3131 }
|
Chris@29
|
3132
|
Chris@29
|
3133 FFT::~FFT()
|
Chris@29
|
3134 {
|
Chris@29
|
3135 delete d;
|
Chris@29
|
3136 }
|
Chris@29
|
3137
|
Chris@29
|
3138 #ifndef NO_EXCEPTIONS
|
Chris@29
|
3139 #define CHECK_NOT_NULL(x) \
|
Chris@29
|
3140 if (!(x)) { \
|
Chris@29
|
3141 std::cerr << "FFT: ERROR: Null argument " #x << std::endl; \
|
Chris@29
|
3142 throw NullArgument; \
|
Chris@29
|
3143 }
|
Chris@29
|
3144 #else
|
Chris@29
|
3145 #define CHECK_NOT_NULL(x) \
|
Chris@29
|
3146 if (!(x)) { \
|
Chris@29
|
3147 std::cerr << "FFT: ERROR: Null argument " #x << std::endl; \
|
Chris@29
|
3148 std::cerr << "FFT: Would be throwing NullArgument here, if exceptions were not disabled" << std::endl; \
|
Chris@29
|
3149 return; \
|
Chris@29
|
3150 }
|
Chris@29
|
3151 #endif
|
Chris@29
|
3152
|
Chris@29
|
3153 void
|
Chris@29
|
3154 FFT::forward(const double *BQ_R__ realIn, double *BQ_R__ realOut, double *BQ_R__ imagOut)
|
Chris@29
|
3155 {
|
Chris@29
|
3156 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3157 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3158 CHECK_NOT_NULL(imagOut);
|
Chris@29
|
3159 d->forward(realIn, realOut, imagOut);
|
Chris@29
|
3160 }
|
Chris@29
|
3161
|
Chris@29
|
3162 void
|
Chris@29
|
3163 FFT::forwardInterleaved(const double *BQ_R__ realIn, double *BQ_R__ complexOut)
|
Chris@29
|
3164 {
|
Chris@29
|
3165 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3166 CHECK_NOT_NULL(complexOut);
|
Chris@29
|
3167 d->forwardInterleaved(realIn, complexOut);
|
Chris@29
|
3168 }
|
Chris@29
|
3169
|
Chris@29
|
3170 void
|
Chris@29
|
3171 FFT::forwardPolar(const double *BQ_R__ realIn, double *BQ_R__ magOut, double *BQ_R__ phaseOut)
|
Chris@29
|
3172 {
|
Chris@29
|
3173 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3174 CHECK_NOT_NULL(magOut);
|
Chris@29
|
3175 CHECK_NOT_NULL(phaseOut);
|
Chris@29
|
3176 d->forwardPolar(realIn, magOut, phaseOut);
|
Chris@29
|
3177 }
|
Chris@29
|
3178
|
Chris@29
|
3179 void
|
Chris@29
|
3180 FFT::forwardMagnitude(const double *BQ_R__ realIn, double *BQ_R__ magOut)
|
Chris@29
|
3181 {
|
Chris@29
|
3182 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3183 CHECK_NOT_NULL(magOut);
|
Chris@29
|
3184 d->forwardMagnitude(realIn, magOut);
|
Chris@29
|
3185 }
|
Chris@29
|
3186
|
Chris@29
|
3187 void
|
Chris@29
|
3188 FFT::forward(const float *BQ_R__ realIn, float *BQ_R__ realOut, float *BQ_R__ imagOut)
|
Chris@29
|
3189 {
|
Chris@29
|
3190 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3191 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3192 CHECK_NOT_NULL(imagOut);
|
Chris@29
|
3193 d->forward(realIn, realOut, imagOut);
|
Chris@29
|
3194 }
|
Chris@29
|
3195
|
Chris@29
|
3196 void
|
Chris@29
|
3197 FFT::forwardInterleaved(const float *BQ_R__ realIn, float *BQ_R__ complexOut)
|
Chris@29
|
3198 {
|
Chris@29
|
3199 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3200 CHECK_NOT_NULL(complexOut);
|
Chris@29
|
3201 d->forwardInterleaved(realIn, complexOut);
|
Chris@29
|
3202 }
|
Chris@29
|
3203
|
Chris@29
|
3204 void
|
Chris@29
|
3205 FFT::forwardPolar(const float *BQ_R__ realIn, float *BQ_R__ magOut, float *BQ_R__ phaseOut)
|
Chris@29
|
3206 {
|
Chris@29
|
3207 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3208 CHECK_NOT_NULL(magOut);
|
Chris@29
|
3209 CHECK_NOT_NULL(phaseOut);
|
Chris@29
|
3210 d->forwardPolar(realIn, magOut, phaseOut);
|
Chris@29
|
3211 }
|
Chris@29
|
3212
|
Chris@29
|
3213 void
|
Chris@29
|
3214 FFT::forwardMagnitude(const float *BQ_R__ realIn, float *BQ_R__ magOut)
|
Chris@29
|
3215 {
|
Chris@29
|
3216 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3217 CHECK_NOT_NULL(magOut);
|
Chris@29
|
3218 d->forwardMagnitude(realIn, magOut);
|
Chris@29
|
3219 }
|
Chris@29
|
3220
|
Chris@29
|
3221 void
|
Chris@29
|
3222 FFT::inverse(const double *BQ_R__ realIn, const double *BQ_R__ imagIn, double *BQ_R__ realOut)
|
Chris@29
|
3223 {
|
Chris@29
|
3224 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3225 CHECK_NOT_NULL(imagIn);
|
Chris@29
|
3226 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3227 d->inverse(realIn, imagIn, realOut);
|
Chris@29
|
3228 }
|
Chris@29
|
3229
|
Chris@29
|
3230 void
|
Chris@29
|
3231 FFT::inverseInterleaved(const double *BQ_R__ complexIn, double *BQ_R__ realOut)
|
Chris@29
|
3232 {
|
Chris@29
|
3233 CHECK_NOT_NULL(complexIn);
|
Chris@29
|
3234 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3235 d->inverseInterleaved(complexIn, realOut);
|
Chris@29
|
3236 }
|
Chris@29
|
3237
|
Chris@29
|
3238 void
|
Chris@29
|
3239 FFT::inversePolar(const double *BQ_R__ magIn, const double *BQ_R__ phaseIn, double *BQ_R__ realOut)
|
Chris@29
|
3240 {
|
Chris@29
|
3241 CHECK_NOT_NULL(magIn);
|
Chris@29
|
3242 CHECK_NOT_NULL(phaseIn);
|
Chris@29
|
3243 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3244 d->inversePolar(magIn, phaseIn, realOut);
|
Chris@29
|
3245 }
|
Chris@29
|
3246
|
Chris@29
|
3247 void
|
Chris@29
|
3248 FFT::inverseCepstral(const double *BQ_R__ magIn, double *BQ_R__ cepOut)
|
Chris@29
|
3249 {
|
Chris@29
|
3250 CHECK_NOT_NULL(magIn);
|
Chris@29
|
3251 CHECK_NOT_NULL(cepOut);
|
Chris@29
|
3252 d->inverseCepstral(magIn, cepOut);
|
Chris@29
|
3253 }
|
Chris@29
|
3254
|
Chris@29
|
3255 void
|
Chris@29
|
3256 FFT::inverse(const float *BQ_R__ realIn, const float *BQ_R__ imagIn, float *BQ_R__ realOut)
|
Chris@29
|
3257 {
|
Chris@29
|
3258 CHECK_NOT_NULL(realIn);
|
Chris@29
|
3259 CHECK_NOT_NULL(imagIn);
|
Chris@29
|
3260 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3261 d->inverse(realIn, imagIn, realOut);
|
Chris@29
|
3262 }
|
Chris@29
|
3263
|
Chris@29
|
3264 void
|
Chris@29
|
3265 FFT::inverseInterleaved(const float *BQ_R__ complexIn, float *BQ_R__ realOut)
|
Chris@29
|
3266 {
|
Chris@29
|
3267 CHECK_NOT_NULL(complexIn);
|
Chris@29
|
3268 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3269 d->inverseInterleaved(complexIn, realOut);
|
Chris@29
|
3270 }
|
Chris@29
|
3271
|
Chris@29
|
3272 void
|
Chris@29
|
3273 FFT::inversePolar(const float *BQ_R__ magIn, const float *BQ_R__ phaseIn, float *BQ_R__ realOut)
|
Chris@29
|
3274 {
|
Chris@29
|
3275 CHECK_NOT_NULL(magIn);
|
Chris@29
|
3276 CHECK_NOT_NULL(phaseIn);
|
Chris@29
|
3277 CHECK_NOT_NULL(realOut);
|
Chris@29
|
3278 d->inversePolar(magIn, phaseIn, realOut);
|
Chris@29
|
3279 }
|
Chris@29
|
3280
|
Chris@29
|
3281 void
|
Chris@29
|
3282 FFT::inverseCepstral(const float *BQ_R__ magIn, float *BQ_R__ cepOut)
|
Chris@29
|
3283 {
|
Chris@29
|
3284 CHECK_NOT_NULL(magIn);
|
Chris@29
|
3285 CHECK_NOT_NULL(cepOut);
|
Chris@29
|
3286 d->inverseCepstral(magIn, cepOut);
|
Chris@29
|
3287 }
|
Chris@29
|
3288
|
Chris@29
|
3289 void
|
Chris@29
|
3290 FFT::initFloat()
|
Chris@29
|
3291 {
|
Chris@29
|
3292 d->initFloat();
|
Chris@29
|
3293 }
|
Chris@29
|
3294
|
Chris@29
|
3295 void
|
Chris@29
|
3296 FFT::initDouble()
|
Chris@29
|
3297 {
|
Chris@29
|
3298 d->initDouble();
|
Chris@29
|
3299 }
|
Chris@29
|
3300
|
Chris@29
|
3301 FFT::Precisions
|
Chris@29
|
3302 FFT::getSupportedPrecisions() const
|
Chris@29
|
3303 {
|
Chris@29
|
3304 return d->getSupportedPrecisions();
|
Chris@29
|
3305 }
|
Chris@29
|
3306
|
Chris@29
|
3307 #ifdef FFT_MEASUREMENT
|
Chris@29
|
3308
|
Chris@29
|
3309 std::string
|
Chris@29
|
3310 FFT::tune()
|
Chris@29
|
3311 {
|
Chris@29
|
3312 std::ostringstream os;
|
Chris@29
|
3313 os << "FFT::tune()..." << std::endl;
|
Chris@29
|
3314
|
Chris@29
|
3315 std::vector<int> sizes;
|
Chris@29
|
3316 std::map<FFTImpl *, int> candidates;
|
Chris@29
|
3317 std::map<int, int> wins;
|
Chris@29
|
3318
|
Chris@29
|
3319 sizes.push_back(512);
|
Chris@29
|
3320 sizes.push_back(1024);
|
Chris@29
|
3321 sizes.push_back(4096);
|
Chris@29
|
3322
|
Chris@29
|
3323 for (unsigned int si = 0; si < sizes.size(); ++si) {
|
Chris@29
|
3324
|
Chris@29
|
3325 int size = sizes[si];
|
Chris@29
|
3326
|
Chris@29
|
3327 while (!candidates.empty()) {
|
Chris@29
|
3328 delete candidates.begin()->first;
|
Chris@29
|
3329 candidates.erase(candidates.begin());
|
Chris@29
|
3330 }
|
Chris@29
|
3331
|
Chris@29
|
3332 FFTImpl *d;
|
Chris@29
|
3333
|
Chris@29
|
3334 #ifdef HAVE_IPP
|
Chris@29
|
3335 std::cerr << "Constructing new IPP FFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3336 d = new FFTs::D_IPP(size);
|
Chris@29
|
3337 d->initFloat();
|
Chris@29
|
3338 d->initDouble();
|
Chris@29
|
3339 candidates[d] = 0;
|
Chris@29
|
3340 #endif
|
Chris@29
|
3341
|
Chris@29
|
3342 #ifdef HAVE_FFTW3
|
Chris@29
|
3343 os << "Constructing new FFTW3 FFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3344 d = new FFTs::D_FFTW(size);
|
Chris@29
|
3345 d->initFloat();
|
Chris@29
|
3346 d->initDouble();
|
Chris@29
|
3347 candidates[d] = 1;
|
Chris@29
|
3348 #endif
|
Chris@29
|
3349
|
Chris@29
|
3350 #ifdef HAVE_KISSFFT
|
Chris@29
|
3351 os << "Constructing new KISSFFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3352 d = new FFTs::D_KISSFFT(size);
|
Chris@29
|
3353 d->initFloat();
|
Chris@29
|
3354 d->initDouble();
|
Chris@29
|
3355 candidates[d] = 2;
|
Chris@29
|
3356 #endif
|
Chris@29
|
3357
|
Chris@29
|
3358 #ifdef USE_BUILTIN_FFT
|
Chris@29
|
3359 os << "Constructing new Cross FFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3360 d = new FFTs::D_Cross(size);
|
Chris@29
|
3361 d->initFloat();
|
Chris@29
|
3362 d->initDouble();
|
Chris@29
|
3363 candidates[d] = 3;
|
Chris@29
|
3364 #endif
|
Chris@29
|
3365
|
Chris@29
|
3366 #ifdef HAVE_VDSP
|
Chris@29
|
3367 os << "Constructing new vDSP FFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3368 d = new FFTs::D_VDSP(size);
|
Chris@29
|
3369 d->initFloat();
|
Chris@29
|
3370 d->initDouble();
|
Chris@29
|
3371 candidates[d] = 4;
|
Chris@29
|
3372 #endif
|
Chris@29
|
3373
|
Chris@29
|
3374 #ifdef HAVE_MEDIALIB
|
Chris@29
|
3375 std::cerr << "Constructing new MediaLib FFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3376 d = new FFTs::D_MEDIALIB(size);
|
Chris@29
|
3377 d->initFloat();
|
Chris@29
|
3378 d->initDouble();
|
Chris@29
|
3379 candidates[d] = 5;
|
Chris@29
|
3380 #endif
|
Chris@29
|
3381
|
Chris@29
|
3382 #ifdef HAVE_OPENMAX
|
Chris@29
|
3383 os << "Constructing new OpenMAX FFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3384 d = new FFTs::D_OPENMAX(size);
|
Chris@29
|
3385 d->initFloat();
|
Chris@29
|
3386 d->initDouble();
|
Chris@29
|
3387 candidates[d] = 6;
|
Chris@29
|
3388 #endif
|
Chris@29
|
3389
|
Chris@29
|
3390 #ifdef HAVE_SFFT
|
Chris@29
|
3391 os << "Constructing new SFFT FFT object for size " << size << "..." << std::endl;
|
Chris@29
|
3392 d = new FFTs::D_SFFT(size);
|
Chris@29
|
3393 // d->initFloat();
|
Chris@29
|
3394 d->initDouble();
|
Chris@29
|
3395 candidates[d] = 6;
|
Chris@29
|
3396 #endif
|
Chris@29
|
3397
|
Chris@29
|
3398 os << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << std::endl;
|
Chris@29
|
3399 float divisor = float(CLOCKS_PER_SEC) / 1000.f;
|
Chris@29
|
3400
|
Chris@29
|
3401 os << "Timing order is: ";
|
Chris@29
|
3402 for (std::map<FFTImpl *, int>::iterator ci = candidates.begin();
|
Chris@29
|
3403 ci != candidates.end(); ++ci) {
|
Chris@29
|
3404 os << ci->second << " ";
|
Chris@29
|
3405 }
|
Chris@29
|
3406 os << std::endl;
|
Chris@29
|
3407
|
Chris@29
|
3408 int iterations = 500;
|
Chris@29
|
3409 os << "Iterations: " << iterations << std::endl;
|
Chris@29
|
3410
|
Chris@29
|
3411 double *da = new double[size];
|
Chris@29
|
3412 double *db = new double[size];
|
Chris@29
|
3413 double *dc = new double[size];
|
Chris@29
|
3414 double *dd = new double[size];
|
Chris@29
|
3415 double *di = new double[size + 2];
|
Chris@29
|
3416 double *dj = new double[size + 2];
|
Chris@29
|
3417
|
Chris@29
|
3418 float *fa = new float[size];
|
Chris@29
|
3419 float *fb = new float[size];
|
Chris@29
|
3420 float *fc = new float[size];
|
Chris@29
|
3421 float *fd = new float[size];
|
Chris@29
|
3422 float *fi = new float[size + 2];
|
Chris@29
|
3423 float *fj = new float[size + 2];
|
Chris@29
|
3424
|
Chris@29
|
3425 for (int type = 0; type < 16; ++type) {
|
Chris@29
|
3426
|
Chris@29
|
3427 //!!!
|
Chris@29
|
3428 if ((type > 3 && type < 8) ||
|
Chris@29
|
3429 (type > 11)) {
|
Chris@29
|
3430 continue;
|
Chris@29
|
3431 }
|
Chris@29
|
3432
|
Chris@29
|
3433 if (type > 7) {
|
Chris@29
|
3434 // inverse transform: bigger inputs, to simulate the
|
Chris@29
|
3435 // fact that the forward transform is unscaled
|
Chris@29
|
3436 for (int i = 0; i < size; ++i) {
|
Chris@29
|
3437 da[i] = drand48() * size;
|
Chris@29
|
3438 fa[i] = da[i];
|
Chris@29
|
3439 db[i] = drand48() * size;
|
Chris@29
|
3440 fb[i] = db[i];
|
Chris@29
|
3441 }
|
Chris@29
|
3442 } else {
|
Chris@29
|
3443 for (int i = 0; i < size; ++i) {
|
Chris@29
|
3444 da[i] = drand48();
|
Chris@29
|
3445 fa[i] = da[i];
|
Chris@29
|
3446 db[i] = drand48();
|
Chris@29
|
3447 fb[i] = db[i];
|
Chris@29
|
3448 }
|
Chris@29
|
3449 }
|
Chris@29
|
3450
|
Chris@29
|
3451 for (int i = 0; i < size + 2; ++i) {
|
Chris@29
|
3452 di[i] = drand48();
|
Chris@29
|
3453 fi[i] = di[i];
|
Chris@29
|
3454 }
|
Chris@29
|
3455
|
Chris@29
|
3456 int low = -1;
|
Chris@29
|
3457 int lowscore = 0;
|
Chris@29
|
3458
|
Chris@29
|
3459 const char *names[] = {
|
Chris@29
|
3460
|
Chris@29
|
3461 "Forward Cartesian Double",
|
Chris@29
|
3462 "Forward Interleaved Double",
|
Chris@29
|
3463 "Forward Polar Double",
|
Chris@29
|
3464 "Forward Magnitude Double",
|
Chris@29
|
3465 "Forward Cartesian Float",
|
Chris@29
|
3466 "Forward Interleaved Float",
|
Chris@29
|
3467 "Forward Polar Float",
|
Chris@29
|
3468 "Forward Magnitude Float",
|
Chris@29
|
3469
|
Chris@29
|
3470 "Inverse Cartesian Double",
|
Chris@29
|
3471 "Inverse Interleaved Double",
|
Chris@29
|
3472 "Inverse Polar Double",
|
Chris@29
|
3473 "Inverse Cepstral Double",
|
Chris@29
|
3474 "Inverse Cartesian Float",
|
Chris@29
|
3475 "Inverse Interleaved Float",
|
Chris@29
|
3476 "Inverse Polar Float",
|
Chris@29
|
3477 "Inverse Cepstral Float"
|
Chris@29
|
3478 };
|
Chris@29
|
3479 os << names[type] << " :: ";
|
Chris@29
|
3480
|
Chris@29
|
3481 for (std::map<FFTImpl *, int>::iterator ci = candidates.begin();
|
Chris@29
|
3482 ci != candidates.end(); ++ci) {
|
Chris@29
|
3483
|
Chris@29
|
3484 FFTImpl *d = ci->first;
|
Chris@29
|
3485
|
Chris@29
|
3486 double mean = 0;
|
Chris@29
|
3487
|
Chris@29
|
3488 clock_t start = clock();
|
Chris@29
|
3489
|
Chris@29
|
3490 for (int i = 0; i < iterations; ++i) {
|
Chris@29
|
3491
|
Chris@29
|
3492 if (i == 0) {
|
Chris@29
|
3493 for (int j = 0; j < size; ++j) {
|
Chris@29
|
3494 dc[j] = 0;
|
Chris@29
|
3495 dd[j] = 0;
|
Chris@29
|
3496 fc[j] = 0;
|
Chris@29
|
3497 fd[j] = 0;
|
Chris@29
|
3498 fj[j] = 0;
|
Chris@29
|
3499 dj[j] = 0;
|
Chris@29
|
3500 }
|
Chris@29
|
3501 }
|
Chris@29
|
3502
|
Chris@29
|
3503 switch (type) {
|
Chris@29
|
3504 case 0: d->forward(da, dc, dd); break;
|
Chris@29
|
3505 case 1: d->forwardInterleaved(da, dj); break;
|
Chris@29
|
3506 case 2: d->forwardPolar(da, dc, dd); break;
|
Chris@29
|
3507 case 3: d->forwardMagnitude(da, dc); break;
|
Chris@29
|
3508 case 4: d->forward(fa, fc, fd); break;
|
Chris@29
|
3509 case 5: d->forwardInterleaved(fa, fj); break;
|
Chris@29
|
3510 case 6: d->forwardPolar(fa, fc, fd); break;
|
Chris@29
|
3511 case 7: d->forwardMagnitude(fa, fc); break;
|
Chris@29
|
3512 case 8: d->inverse(da, db, dc); break;
|
Chris@29
|
3513 case 9: d->inverseInterleaved(di, dc); break;
|
Chris@29
|
3514 case 10: d->inversePolar(da, db, dc); break;
|
Chris@29
|
3515 case 11: d->inverseCepstral(da, dc); break;
|
Chris@29
|
3516 case 12: d->inverse(fa, fb, fc); break;
|
Chris@29
|
3517 case 13: d->inverseInterleaved(fi, fc); break;
|
Chris@29
|
3518 case 14: d->inversePolar(fa, fb, fc); break;
|
Chris@29
|
3519 case 15: d->inverseCepstral(fa, fc); break;
|
Chris@29
|
3520 }
|
Chris@29
|
3521
|
Chris@29
|
3522 if (i == 0) {
|
Chris@29
|
3523 mean = 0;
|
Chris@29
|
3524 for (int j = 0; j < size; ++j) {
|
Chris@29
|
3525 mean += dc[j];
|
Chris@29
|
3526 mean += dd[j];
|
Chris@29
|
3527 mean += fc[j];
|
Chris@29
|
3528 mean += fd[j];
|
Chris@29
|
3529 mean += fj[j];
|
Chris@29
|
3530 mean += dj[j];
|
Chris@29
|
3531 }
|
Chris@29
|
3532 mean /= size * 6;
|
Chris@29
|
3533 }
|
Chris@29
|
3534 }
|
Chris@29
|
3535
|
Chris@29
|
3536 clock_t end = clock();
|
Chris@29
|
3537
|
Chris@29
|
3538 os << float(end - start)/divisor << " (" << mean << ") ";
|
Chris@29
|
3539
|
Chris@29
|
3540 if (low == -1 || (end - start) < lowscore) {
|
Chris@29
|
3541 low = ci->second;
|
Chris@29
|
3542 lowscore = end - start;
|
Chris@29
|
3543 }
|
Chris@29
|
3544 }
|
Chris@29
|
3545
|
Chris@29
|
3546 os << std::endl;
|
Chris@29
|
3547
|
Chris@29
|
3548 os << " size " << size << ", type " << type << ": fastest is " << low << " (time " << float(lowscore)/divisor << ")" << std::endl;
|
Chris@29
|
3549
|
Chris@29
|
3550 wins[low]++;
|
Chris@29
|
3551 }
|
Chris@29
|
3552
|
Chris@29
|
3553 delete[] fa;
|
Chris@29
|
3554 delete[] fb;
|
Chris@29
|
3555 delete[] fc;
|
Chris@29
|
3556 delete[] fd;
|
Chris@29
|
3557 delete[] da;
|
Chris@29
|
3558 delete[] db;
|
Chris@29
|
3559 delete[] dc;
|
Chris@29
|
3560 delete[] dd;
|
Chris@29
|
3561 }
|
Chris@29
|
3562
|
Chris@29
|
3563 while (!candidates.empty()) {
|
Chris@29
|
3564 delete candidates.begin()->first;
|
Chris@29
|
3565 candidates.erase(candidates.begin());
|
Chris@29
|
3566 }
|
Chris@29
|
3567
|
Chris@29
|
3568 int bestscore = 0;
|
Chris@29
|
3569 int best = -1;
|
Chris@29
|
3570
|
Chris@29
|
3571 for (std::map<int, int>::iterator wi = wins.begin(); wi != wins.end(); ++wi) {
|
Chris@29
|
3572 if (best == -1 || wi->second > bestscore) {
|
Chris@29
|
3573 best = wi->first;
|
Chris@29
|
3574 bestscore = wi->second;
|
Chris@29
|
3575 }
|
Chris@29
|
3576 }
|
Chris@29
|
3577
|
Chris@29
|
3578 os << "overall winner is " << best << " with " << bestscore << " wins" << std::endl;
|
Chris@29
|
3579
|
Chris@29
|
3580 return os.str();
|
Chris@29
|
3581 }
|
Chris@29
|
3582
|
Chris@29
|
3583 #endif
|
Chris@29
|
3584
|
Chris@29
|
3585 }
|