annotate fft/native/bqfft/src/FFT.cpp @ 40:223f770b5341 kissfft-double tip

Try a double-precision kissfft
author Chris Cannam
date Wed, 07 Sep 2016 10:40:32 +0100
parents cf59817a5983
children
rev   line source
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 }