Chris@337: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@337: Chris@337: /* Chris@337: Vamp Chris@337: Chris@337: An API for audio analysis and feature extraction plugins. Chris@337: Chris@337: Centre for Digital Music, Queen Mary, University of London. Chris@337: Copyright 2006-2012 Chris Cannam and QMUL. Chris@337: Chris@337: Permission is hereby granted, free of charge, to any person Chris@337: obtaining a copy of this software and associated documentation Chris@337: files (the "Software"), to deal in the Software without Chris@337: restriction, including without limitation the rights to use, copy, Chris@337: modify, merge, publish, distribute, sublicense, and/or sell copies Chris@337: of the Software, and to permit persons to whom the Software is Chris@337: furnished to do so, subject to the following conditions: Chris@337: Chris@337: The above copyright notice and this permission notice shall be Chris@337: included in all copies or substantial portions of the Software. Chris@337: Chris@337: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, Chris@337: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF Chris@337: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND Chris@337: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR Chris@337: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF Chris@337: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION Chris@337: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Chris@337: Chris@337: Except as contained in this notice, the names of the Centre for Chris@337: Digital Music; Queen Mary, University of London; and Chris Cannam Chris@337: shall not be used in advertising or otherwise to promote the sale, Chris@337: use or other dealings in this Software without prior written Chris@337: authorization. Chris@337: */ Chris@337: Chris@337: #include Chris@337: Chris@434: #include Chris@434: #include Chris@434: #include Chris@434: #include Chris@337: Chris@424: #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 7 ) Chris@337: #error Unexpected version of Vamp SDK header included Chris@337: #endif Chris@337: Chris@434: _VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp) chris@340: Chris@434: // Override C linkage for KissFFT headers. So long as we have already Chris@434: // included all of the other (system etc) headers KissFFT depends on, Chris@434: // this should work out OK Chris@434: #undef __cplusplus Chris@434: Chris@434: namespace KissSingle { Chris@434: #undef KISS_FFT_H Chris@434: #undef KISS_FTR_H Chris@434: #undef KISS_FFT__GUTS_H Chris@434: #undef FIXED_POINT Chris@434: #undef USE_SIMD Chris@434: #undef kiss_fft_scalar Chris@434: #define kiss_fft_scalar float Chris@434: inline void free(void *ptr) { ::free(ptr); } Chris@434: #include "ext/kiss_fft.c" Chris@434: #include "ext/kiss_fftr.c" Chris@434: } Chris@434: Chris@434: namespace KissDouble { Chris@434: #undef KISS_FFT_H Chris@434: #undef KISS_FTR_H Chris@434: #undef KISS_FFT__GUTS_H Chris@434: #undef FIXED_POINT Chris@434: #undef USE_SIMD Chris@434: #undef kiss_fft_scalar Chris@434: #define kiss_fft_scalar double Chris@434: inline void free(void *ptr) { ::free(ptr); } Chris@434: #include "ext/kiss_fft.c" Chris@434: #include "ext/kiss_fftr.c" Chris@434: } Chris@337: Chris@337: namespace Vamp { Chris@337: Chris@337: void Chris@434: FFT::forward(unsigned int un, Chris@337: const double *ri, const double *ii, Chris@337: double *ro, double *io) Chris@337: { Chris@434: int n(un); Chris@434: KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, false, 0, 0); Chris@434: KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n]; Chris@434: KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n]; Chris@434: for (int i = 0; i < n; ++i) { Chris@434: in[i].r = ri[i]; Chris@434: in[i].i = 0; Chris@434: } Chris@434: if (ii) { Chris@434: for (int i = 0; i < n; ++i) { Chris@434: in[i].i = ii[i]; Chris@434: } Chris@434: } Chris@434: kiss_fft(c, in, out); Chris@434: for (int i = 0; i < n; ++i) { Chris@434: ro[i] = out[i].r; Chris@434: io[i] = out[i].i; Chris@434: } Chris@434: KissDouble::kiss_fft_free(c); Chris@434: delete[] in; Chris@434: delete[] out; Chris@337: } Chris@337: Chris@337: void Chris@434: FFT::inverse(unsigned int un, Chris@337: const double *ri, const double *ii, Chris@337: double *ro, double *io) Chris@337: { Chris@434: int n(un); Chris@434: KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, true, 0, 0); Chris@434: KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n]; Chris@434: KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n]; Chris@434: for (int i = 0; i < n; ++i) { Chris@434: in[i].r = ri[i]; Chris@434: in[i].i = 0; Chris@434: } Chris@434: if (ii) { Chris@434: for (int i = 0; i < n; ++i) { Chris@434: in[i].i = ii[i]; Chris@434: } Chris@434: } Chris@434: kiss_fft(c, in, out); Chris@434: double scale = 1.0 / double(n); Chris@434: for (int i = 0; i < n; ++i) { Chris@434: ro[i] = out[i].r * scale; Chris@434: io[i] = out[i].i * scale; Chris@434: } Chris@434: KissDouble::kiss_fft_free(c); Chris@434: delete[] in; Chris@434: delete[] out; Chris@434: KissDouble::kiss_fft_free(c); Chris@434: } Chris@434: Chris@434: class FFTReal::D Chris@434: { Chris@434: public: Chris@434: Chris@434: D(int n) : Chris@434: m_n(n), Chris@434: m_cf(KissSingle::kiss_fftr_alloc(n, false, 0, 0)), Chris@434: m_ci(KissSingle::kiss_fftr_alloc(n, true, 0, 0)), Chris@434: m_freq(new KissSingle::kiss_fft_cpx[n/2+1]) { } Chris@434: Chris@434: ~D() { Chris@434: KissSingle::kiss_fftr_free(m_cf); Chris@434: KissSingle::kiss_fftr_free(m_ci); Chris@434: delete[] m_freq; Chris@434: } Chris@434: Chris@434: void forward(const float *ri, float *co) { Chris@434: KissSingle::kiss_fftr(m_cf, ri, m_freq); Chris@434: int hs = m_n/2 + 1; Chris@434: for (int i = 0; i < hs; ++i) { Chris@434: co[i*2] = m_freq[i].r; Chris@434: co[i*2+1] = m_freq[i].i; Chris@434: } Chris@434: } Chris@434: Chris@434: void inverse(const float *ci, float *ro) { Chris@434: int hs = m_n/2 + 1; Chris@434: for (int i = 0; i < hs; ++i) { Chris@434: m_freq[i].r = ci[i*2]; Chris@434: m_freq[i].i = ci[i*2+1]; Chris@434: } Chris@434: KissSingle::kiss_fftri(m_ci, m_freq, ro); Chris@434: double scale = 1.0 / double(m_n); Chris@434: for (int i = 0; i < m_n; ++i) { Chris@434: ro[i] *= scale; Chris@434: } Chris@434: } Chris@434: Chris@434: private: Chris@434: int m_n; Chris@434: KissSingle::kiss_fftr_cfg m_cf; Chris@434: KissSingle::kiss_fftr_cfg m_ci; Chris@434: KissSingle::kiss_fft_cpx *m_freq; Chris@434: }; Chris@434: Chris@434: FFTReal::FFTReal(unsigned int n) : Chris@434: m_d(new D(n)) Chris@434: { Chris@434: } Chris@434: Chris@434: FFTReal::~FFTReal() Chris@434: { Chris@434: delete m_d; Chris@434: } Chris@434: Chris@434: void Chris@434: FFTReal::forward(const float *ri, float *co) Chris@434: { Chris@434: m_d->forward(ri, co); Chris@434: } Chris@434: Chris@434: void Chris@434: FFTReal::inverse(const float *ci, float *ro) Chris@434: { Chris@434: m_d->inverse(ci, ro); Chris@337: } Chris@337: Chris@337: } Chris@337: Chris@337: _VAMP_SDK_PLUGSPACE_END(FFT.cpp) Chris@337: