Mercurial > hg > vamp-plugin-sdk
changeset 446:d132b92ec65d vampipe
Add FFTComplex class by analogy to FFTReal
author | Chris Cannam |
---|---|
date | Thu, 18 Aug 2016 16:04:25 +0100 |
parents | 7f7a10bcaff1 |
children | 80b46389aab0 |
files | src/vamp-sdk/FFT.cpp vamp-sdk/FFT.h |
diffstat | 2 files changed, 144 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/src/vamp-sdk/FFT.cpp Thu Aug 18 15:06:23 2016 +0100 +++ b/src/vamp-sdk/FFT.cpp Thu Aug 18 16:04:25 2016 +0100 @@ -108,21 +108,92 @@ delete[] out; } +class FFTComplex::D +{ +public: + D(int n) : + m_n(n), + m_fconf(Kiss::kiss_fft_alloc(n, false, 0, 0)), + m_iconf(Kiss::kiss_fft_alloc(n, true, 0, 0)), + m_ci(new Kiss::kiss_fft_cpx[m_n]), + m_co(new Kiss::kiss_fft_cpx[m_n]) { } + + ~D() { + Kiss::kiss_fftr_free(m_fconf); + Kiss::kiss_fftr_free(m_iconf); + delete[] m_ci; + delete[] m_co; + } + + void forward(const double *ci, double *co) { + for (int i = 0; i < m_n; ++i) { + m_ci[i].r = ci[i*2]; + m_ci[i].i = ci[i*2+1]; + } + Kiss::kiss_fft(m_fconf, m_ci, m_co); + for (int i = 0; i < m_n; ++i) { + co[i*2] = m_co[i].r; + co[i*2+1] = m_co[i].i; + } + } + + void inverse(const double *ci, double *co) { + for (int i = 0; i < m_n; ++i) { + m_ci[i].r = ci[i*2]; + m_ci[i].i = ci[i*2+1]; + } + Kiss::kiss_fft(m_iconf, m_ci, m_co); + double scale = 1.0 / double(m_n); + for (int i = 0; i < m_n; ++i) { + co[i*2] = m_co[i].r * scale; + co[i*2+1] = m_co[i].i * scale; + } + } + +private: + int m_n; + Kiss::kiss_fft_cfg m_fconf; + Kiss::kiss_fft_cfg m_iconf; + Kiss::kiss_fft_cpx *m_ci; + Kiss::kiss_fft_cpx *m_co; +}; + +FFTComplex::FFTComplex(unsigned int n) : + m_d(new D(n)) +{ +} + +FFTComplex::~FFTComplex() +{ + delete m_d; +} + +void +FFTComplex::forward(const double *ci, double *co) +{ + m_d->forward(ci, co); +} + +void +FFTComplex::inverse(const double *ci, double *co) +{ + m_d->inverse(ci, co); +} + class FFTReal::D { public: - D(int n) : m_n(n), - m_cf(Kiss::kiss_fftr_alloc(n, false, 0, 0)), - m_ci(Kiss::kiss_fftr_alloc(n, true, 0, 0)), + m_fconf(Kiss::kiss_fftr_alloc(n, false, 0, 0)), + m_iconf(Kiss::kiss_fftr_alloc(n, true, 0, 0)), m_ri(new Kiss::kiss_fft_scalar[m_n]), m_ro(new Kiss::kiss_fft_scalar[m_n]), m_freq(new Kiss::kiss_fft_cpx[n/2+1]) { } ~D() { - Kiss::kiss_fftr_free(m_cf); - Kiss::kiss_fftr_free(m_ci); + Kiss::kiss_fftr_free(m_fconf); + Kiss::kiss_fftr_free(m_iconf); delete[] m_ri; delete[] m_ro; delete[] m_freq; @@ -133,7 +204,7 @@ // in case kiss_fft_scalar is float m_ri[i] = ri[i]; } - Kiss::kiss_fftr(m_cf, m_ri, m_freq); + Kiss::kiss_fftr(m_fconf, m_ri, m_freq); int hs = m_n/2 + 1; for (int i = 0; i < hs; ++i) { co[i*2] = m_freq[i].r; @@ -147,7 +218,7 @@ m_freq[i].r = ci[i*2]; m_freq[i].i = ci[i*2+1]; } - Kiss::kiss_fftri(m_ci, m_freq, m_ro); + Kiss::kiss_fftri(m_iconf, m_freq, m_ro); double scale = 1.0 / double(m_n); for (int i = 0; i < m_n; ++i) { ro[i] = m_ro[i] * scale; @@ -156,8 +227,8 @@ private: int m_n; - Kiss::kiss_fftr_cfg m_cf; - Kiss::kiss_fftr_cfg m_ci; + Kiss::kiss_fftr_cfg m_fconf; + Kiss::kiss_fftr_cfg m_iconf; Kiss::kiss_fft_scalar *m_ri; Kiss::kiss_fft_scalar *m_ro; Kiss::kiss_fft_cpx *m_freq;
--- a/vamp-sdk/FFT.h Thu Aug 18 15:06:23 2016 +0100 +++ b/vamp-sdk/FFT.h Thu Aug 18 16:04:25 2016 +0100 @@ -47,7 +47,11 @@ * authors. This class provides one-shot (i.e. fixed table state is * recalculated every time) double-precision complex-complex * transforms. For repeated transforms from real time-domain data, use - * an FFTReal object instead. + * an FFTComplex or FFTReal object instead. + * + * Note: If the SDK has been compiled with the SINGLE_PRECISION_FFT + * flag, then all FFTs will use single precision internally. The + * default is double precision. The API uses doubles in either case. * * The forward transform is unscaled; the inverse transform is scaled * by 1/n. @@ -57,7 +61,7 @@ public: /** * Calculate a one-shot forward transform of size n. - * n must be a power of 2, greater than 1. + * n must be a multiple of 2. * * ri and ii must point to the real and imaginary component arrays * of the input. For real input, ii may be NULL. @@ -92,10 +96,64 @@ /** * A simple FFT implementation provided for convenience of plugin + * authors. This class provides double-precision complex-complex + * transforms. + * + * Note: If the SDK has been compiled with the SINGLE_PRECISION_FFT + * flag, then all FFTs will use single precision internally. The + * default is double precision. The API uses doubles in either case. + * + * The forward transform is unscaled; the inverse transform is scaled + * by 1/n. + */ +class FFTComplex +{ + /** + * Prepare to calculate transforms of size n. + * n must be a multiple of 2. + */ + FFTComplex(unsigned int n); + + ~FFTComplex(); + + /** + * Calculate a forward transform of size n. + * + * ci must point to the interleaved complex input data of size n + * (that is, 2n doubles in total). + * + * co must point to enough space to receive an interleaved complex + * output array of size n (that is, 2n doubles in total). + */ + void forward(const double *ci, double *co); + + /** + * Calculate an inverse transform of size n. + * + * ci must point to an interleaved complex input array of size n + * (that is, 2n doubles in total). + * + * co must point to enough space to receive the interleaved + * complex output data of size n (that is, 2n doubles in + * total). The output is scaled by 1/n. + */ + void inverse(const double *ci, double *co); + +private: + class D; + D *m_d; +}; + +/** + * A simple FFT implementation provided for convenience of plugin * authors. This class provides transforms between double-precision * real time-domain and double-precision complex frequency-domain * data. * + * Note: If the SDK has been compiled with the SINGLE_PRECISION_FFT + * flag, then all FFTs will use single precision internally. The + * default is double precision. The API uses doubles in either case. + * * The forward transform is unscaled; the inverse transform is scaled * by 1/n. */ @@ -103,7 +161,7 @@ { /** * Prepare to calculate transforms of size n. - * n must be a power of 2, greater than 1. + * n must be a multiple of 2. */ FFTReal(unsigned int n); @@ -115,14 +173,15 @@ * ri must point to the real input data of size n. * * co must point to enough space to receive an interleaved complex - * output array of size n/2+1. + * output array of size n/2+1 (that is, n+2 doubles in total). */ void forward(const double *ri, double *co); /** * Calculate an inverse transform of size n. * - * ci must point to an interleaved complex input array of size n/2+1. + * ci must point to an interleaved complex input array of size + * n/2+1 (that is, n+2 doubles in total). * * ro must point to enough space to receive the real output data * of size n. The output is scaled by 1/n and only the real part