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@445: #include "FFTimpl.cpp" Chris@337: Chris@337: namespace Vamp { Chris@337: Chris@501: using namespace Kiss; Chris@501: 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@501: vamp_kiss_fft_cfg c = vamp_kiss_fft_alloc(n, false, 0, 0); Chris@501: vamp_kiss_fft_cpx *in = new vamp_kiss_fft_cpx[n]; Chris@501: vamp_kiss_fft_cpx *out = new vamp_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@501: vamp_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@501: vamp_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@501: vamp_kiss_fft_cfg c = vamp_kiss_fft_alloc(n, true, 0, 0); Chris@501: vamp_kiss_fft_cpx *in = new vamp_kiss_fft_cpx[n]; Chris@501: vamp_kiss_fft_cpx *out = new vamp_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@501: vamp_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@501: vamp_kiss_fft_free(c); Chris@434: delete[] in; Chris@434: delete[] out; Chris@434: } Chris@434: Chris@446: class FFTComplex::D Chris@446: { Chris@446: public: Chris@446: D(int n) : Chris@446: m_n(n), Chris@501: m_fconf(vamp_kiss_fft_alloc(n, false, 0, 0)), Chris@501: m_iconf(vamp_kiss_fft_alloc(n, true, 0, 0)), Chris@501: m_ci(new vamp_kiss_fft_cpx[m_n]), Chris@501: m_co(new vamp_kiss_fft_cpx[m_n]) { } Chris@446: Chris@446: ~D() { Chris@501: vamp_kiss_fftr_free(m_fconf); Chris@501: vamp_kiss_fftr_free(m_iconf); Chris@446: delete[] m_ci; Chris@446: delete[] m_co; Chris@446: } Chris@446: Chris@446: void forward(const double *ci, double *co) { Chris@446: for (int i = 0; i < m_n; ++i) { Chris@446: m_ci[i].r = ci[i*2]; Chris@446: m_ci[i].i = ci[i*2+1]; Chris@446: } Chris@501: vamp_kiss_fft(m_fconf, m_ci, m_co); Chris@446: for (int i = 0; i < m_n; ++i) { Chris@446: co[i*2] = m_co[i].r; Chris@446: co[i*2+1] = m_co[i].i; Chris@446: } Chris@446: } Chris@446: Chris@446: void inverse(const double *ci, double *co) { Chris@446: for (int i = 0; i < m_n; ++i) { Chris@446: m_ci[i].r = ci[i*2]; Chris@446: m_ci[i].i = ci[i*2+1]; Chris@446: } Chris@501: vamp_kiss_fft(m_iconf, m_ci, m_co); Chris@446: double scale = 1.0 / double(m_n); Chris@446: for (int i = 0; i < m_n; ++i) { Chris@446: co[i*2] = m_co[i].r * scale; Chris@446: co[i*2+1] = m_co[i].i * scale; Chris@446: } Chris@446: } Chris@446: Chris@446: private: Chris@446: int m_n; Chris@501: vamp_kiss_fft_cfg m_fconf; Chris@501: vamp_kiss_fft_cfg m_iconf; Chris@501: vamp_kiss_fft_cpx *m_ci; Chris@501: vamp_kiss_fft_cpx *m_co; Chris@446: }; Chris@446: Chris@446: FFTComplex::FFTComplex(unsigned int n) : Chris@446: m_d(new D(n)) Chris@446: { Chris@446: } Chris@446: Chris@446: FFTComplex::~FFTComplex() Chris@446: { Chris@446: delete m_d; Chris@446: } Chris@446: Chris@446: void Chris@446: FFTComplex::forward(const double *ci, double *co) Chris@446: { Chris@446: m_d->forward(ci, co); Chris@446: } Chris@446: Chris@446: void Chris@446: FFTComplex::inverse(const double *ci, double *co) Chris@446: { Chris@446: m_d->inverse(ci, co); Chris@446: } Chris@446: Chris@434: class FFTReal::D Chris@434: { Chris@434: public: Chris@434: D(int n) : Chris@434: m_n(n), Chris@501: m_fconf(vamp_kiss_fftr_alloc(n, false, 0, 0)), Chris@501: m_iconf(vamp_kiss_fftr_alloc(n, true, 0, 0)), Chris@501: m_ri(new vamp_kiss_fft_scalar[m_n]), Chris@501: m_ro(new vamp_kiss_fft_scalar[m_n]), Chris@501: m_freq(new vamp_kiss_fft_cpx[n/2+1]) { } Chris@434: Chris@434: ~D() { Chris@501: vamp_kiss_fftr_free(m_fconf); Chris@501: vamp_kiss_fftr_free(m_iconf); Chris@445: delete[] m_ri; Chris@445: delete[] m_ro; Chris@434: delete[] m_freq; Chris@434: } Chris@434: Chris@445: void forward(const double *ri, double *co) { Chris@445: for (int i = 0; i < m_n; ++i) { Chris@501: // in case vamp_kiss_fft_scalar is float Chris@445: m_ri[i] = ri[i]; Chris@445: } Chris@501: vamp_kiss_fftr(m_fconf, m_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@445: void inverse(const double *ci, double *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@501: vamp_kiss_fftri(m_iconf, m_freq, m_ro); Chris@434: double scale = 1.0 / double(m_n); Chris@434: for (int i = 0; i < m_n; ++i) { Chris@445: ro[i] = m_ro[i] * scale; Chris@434: } Chris@434: } Chris@434: Chris@434: private: Chris@434: int m_n; Chris@501: vamp_kiss_fftr_cfg m_fconf; Chris@501: vamp_kiss_fftr_cfg m_iconf; Chris@501: vamp_kiss_fft_scalar *m_ri; Chris@501: vamp_kiss_fft_scalar *m_ro; Chris@501: vamp_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@445: FFTReal::forward(const double *ri, double *co) Chris@434: { Chris@434: m_d->forward(ri, co); Chris@434: } Chris@434: Chris@434: void Chris@445: FFTReal::inverse(const double *ci, double *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: