Mercurial > hg > vamp-plugin-sdk
diff src/vamp-sdk/FFT.cpp @ 434:e979a9c4ffb6 vampipe
Switch from Cross FFT with option of FFTW build, to KissFFT only (code bundled). This is much faster than the default build and simpler than managing two options.
author | Chris Cannam |
---|---|
date | Tue, 16 Aug 2016 16:04:09 +0100 |
parents | abdf03252c8a |
children | 41baa6241da2 |
line wrap: on
line diff
--- a/src/vamp-sdk/FFT.cpp Wed May 18 12:21:17 2016 +0100 +++ b/src/vamp-sdk/FFT.cpp Tue Aug 16 16:04:09 2016 +0100 @@ -36,37 +36,173 @@ #include <vamp-sdk/FFT.h> -#include <cmath> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <string.h> #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 7 ) #error Unexpected version of Vamp SDK header included #endif -#ifdef _MSC_VER -#include <stdlib.h> -#include <malloc.h> -#endif +_VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp) -_VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp) +// Override C linkage for KissFFT headers. So long as we have already +// included all of the other (system etc) headers KissFFT depends on, +// this should work out OK +#undef __cplusplus + +namespace KissSingle { +#undef KISS_FFT_H +#undef KISS_FTR_H +#undef KISS_FFT__GUTS_H +#undef FIXED_POINT +#undef USE_SIMD +#undef kiss_fft_scalar +#define kiss_fft_scalar float +inline void free(void *ptr) { ::free(ptr); } +#include "ext/kiss_fft.c" +#include "ext/kiss_fftr.c" +} + +namespace KissDouble { +#undef KISS_FFT_H +#undef KISS_FTR_H +#undef KISS_FFT__GUTS_H +#undef FIXED_POINT +#undef USE_SIMD +#undef kiss_fft_scalar +#define kiss_fft_scalar double +inline void free(void *ptr) { ::free(ptr); } +#include "ext/kiss_fft.c" +#include "ext/kiss_fftr.c" +} namespace Vamp { -#include "FFTimpl.cpp" - void -FFT::forward(unsigned int n, +FFT::forward(unsigned int un, const double *ri, const double *ii, double *ro, double *io) { - fft(n, false, ri, ii, ro, io); + int n(un); + KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, false, 0, 0); + KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n]; + KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n]; + for (int i = 0; i < n; ++i) { + in[i].r = ri[i]; + in[i].i = 0; + } + if (ii) { + for (int i = 0; i < n; ++i) { + in[i].i = ii[i]; + } + } + kiss_fft(c, in, out); + for (int i = 0; i < n; ++i) { + ro[i] = out[i].r; + io[i] = out[i].i; + } + KissDouble::kiss_fft_free(c); + delete[] in; + delete[] out; } void -FFT::inverse(unsigned int n, +FFT::inverse(unsigned int un, const double *ri, const double *ii, double *ro, double *io) { - fft(n, true, ri, ii, ro, io); + int n(un); + KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, true, 0, 0); + KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n]; + KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n]; + for (int i = 0; i < n; ++i) { + in[i].r = ri[i]; + in[i].i = 0; + } + if (ii) { + for (int i = 0; i < n; ++i) { + in[i].i = ii[i]; + } + } + kiss_fft(c, in, out); + double scale = 1.0 / double(n); + for (int i = 0; i < n; ++i) { + ro[i] = out[i].r * scale; + io[i] = out[i].i * scale; + } + KissDouble::kiss_fft_free(c); + delete[] in; + delete[] out; + KissDouble::kiss_fft_free(c); +} + +class FFTReal::D +{ +public: + + D(int n) : + m_n(n), + m_cf(KissSingle::kiss_fftr_alloc(n, false, 0, 0)), + m_ci(KissSingle::kiss_fftr_alloc(n, true, 0, 0)), + m_freq(new KissSingle::kiss_fft_cpx[n/2+1]) { } + + ~D() { + KissSingle::kiss_fftr_free(m_cf); + KissSingle::kiss_fftr_free(m_ci); + delete[] m_freq; + } + + void forward(const float *ri, float *co) { + KissSingle::kiss_fftr(m_cf, ri, m_freq); + int hs = m_n/2 + 1; + for (int i = 0; i < hs; ++i) { + co[i*2] = m_freq[i].r; + co[i*2+1] = m_freq[i].i; + } + } + + void inverse(const float *ci, float *ro) { + int hs = m_n/2 + 1; + for (int i = 0; i < hs; ++i) { + m_freq[i].r = ci[i*2]; + m_freq[i].i = ci[i*2+1]; + } + KissSingle::kiss_fftri(m_ci, m_freq, ro); + double scale = 1.0 / double(m_n); + for (int i = 0; i < m_n; ++i) { + ro[i] *= scale; + } + } + +private: + int m_n; + KissSingle::kiss_fftr_cfg m_cf; + KissSingle::kiss_fftr_cfg m_ci; + KissSingle::kiss_fft_cpx *m_freq; +}; + +FFTReal::FFTReal(unsigned int n) : + m_d(new D(n)) +{ +} + +FFTReal::~FFTReal() +{ + delete m_d; +} + +void +FFTReal::forward(const float *ri, float *co) +{ + m_d->forward(ri, co); +} + +void +FFTReal::inverse(const float *ci, float *ro) +{ + m_d->inverse(ci, ro); } }