annotate 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
rev   line source
Chris@337 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@337 2
Chris@337 3 /*
Chris@337 4 Vamp
Chris@337 5
Chris@337 6 An API for audio analysis and feature extraction plugins.
Chris@337 7
Chris@337 8 Centre for Digital Music, Queen Mary, University of London.
Chris@337 9 Copyright 2006-2012 Chris Cannam and QMUL.
Chris@337 10
Chris@337 11 Permission is hereby granted, free of charge, to any person
Chris@337 12 obtaining a copy of this software and associated documentation
Chris@337 13 files (the "Software"), to deal in the Software without
Chris@337 14 restriction, including without limitation the rights to use, copy,
Chris@337 15 modify, merge, publish, distribute, sublicense, and/or sell copies
Chris@337 16 of the Software, and to permit persons to whom the Software is
Chris@337 17 furnished to do so, subject to the following conditions:
Chris@337 18
Chris@337 19 The above copyright notice and this permission notice shall be
Chris@337 20 included in all copies or substantial portions of the Software.
Chris@337 21
Chris@337 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@337 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@337 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Chris@337 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
Chris@337 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@337 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@337 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@337 29
Chris@337 30 Except as contained in this notice, the names of the Centre for
Chris@337 31 Digital Music; Queen Mary, University of London; and Chris Cannam
Chris@337 32 shall not be used in advertising or otherwise to promote the sale,
Chris@337 33 use or other dealings in this Software without prior written
Chris@337 34 authorization.
Chris@337 35 */
Chris@337 36
Chris@337 37 #include <vamp-sdk/FFT.h>
Chris@337 38
Chris@434 39 #include <stdlib.h>
Chris@434 40 #include <stdio.h>
Chris@434 41 #include <math.h>
Chris@434 42 #include <string.h>
Chris@337 43
Chris@424 44 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 7 )
Chris@337 45 #error Unexpected version of Vamp SDK header included
Chris@337 46 #endif
Chris@337 47
Chris@434 48 _VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp)
chris@340 49
Chris@434 50 // Override C linkage for KissFFT headers. So long as we have already
Chris@434 51 // included all of the other (system etc) headers KissFFT depends on,
Chris@434 52 // this should work out OK
Chris@434 53 #undef __cplusplus
Chris@434 54
Chris@434 55 namespace KissSingle {
Chris@434 56 #undef KISS_FFT_H
Chris@434 57 #undef KISS_FTR_H
Chris@434 58 #undef KISS_FFT__GUTS_H
Chris@434 59 #undef FIXED_POINT
Chris@434 60 #undef USE_SIMD
Chris@434 61 #undef kiss_fft_scalar
Chris@434 62 #define kiss_fft_scalar float
Chris@434 63 inline void free(void *ptr) { ::free(ptr); }
Chris@434 64 #include "ext/kiss_fft.c"
Chris@434 65 #include "ext/kiss_fftr.c"
Chris@434 66 }
Chris@434 67
Chris@434 68 namespace KissDouble {
Chris@434 69 #undef KISS_FFT_H
Chris@434 70 #undef KISS_FTR_H
Chris@434 71 #undef KISS_FFT__GUTS_H
Chris@434 72 #undef FIXED_POINT
Chris@434 73 #undef USE_SIMD
Chris@434 74 #undef kiss_fft_scalar
Chris@434 75 #define kiss_fft_scalar double
Chris@434 76 inline void free(void *ptr) { ::free(ptr); }
Chris@434 77 #include "ext/kiss_fft.c"
Chris@434 78 #include "ext/kiss_fftr.c"
Chris@434 79 }
Chris@337 80
Chris@337 81 namespace Vamp {
Chris@337 82
Chris@337 83 void
Chris@434 84 FFT::forward(unsigned int un,
Chris@337 85 const double *ri, const double *ii,
Chris@337 86 double *ro, double *io)
Chris@337 87 {
Chris@434 88 int n(un);
Chris@434 89 KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, false, 0, 0);
Chris@434 90 KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n];
Chris@434 91 KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n];
Chris@434 92 for (int i = 0; i < n; ++i) {
Chris@434 93 in[i].r = ri[i];
Chris@434 94 in[i].i = 0;
Chris@434 95 }
Chris@434 96 if (ii) {
Chris@434 97 for (int i = 0; i < n; ++i) {
Chris@434 98 in[i].i = ii[i];
Chris@434 99 }
Chris@434 100 }
Chris@434 101 kiss_fft(c, in, out);
Chris@434 102 for (int i = 0; i < n; ++i) {
Chris@434 103 ro[i] = out[i].r;
Chris@434 104 io[i] = out[i].i;
Chris@434 105 }
Chris@434 106 KissDouble::kiss_fft_free(c);
Chris@434 107 delete[] in;
Chris@434 108 delete[] out;
Chris@337 109 }
Chris@337 110
Chris@337 111 void
Chris@434 112 FFT::inverse(unsigned int un,
Chris@337 113 const double *ri, const double *ii,
Chris@337 114 double *ro, double *io)
Chris@337 115 {
Chris@434 116 int n(un);
Chris@434 117 KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, true, 0, 0);
Chris@434 118 KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n];
Chris@434 119 KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n];
Chris@434 120 for (int i = 0; i < n; ++i) {
Chris@434 121 in[i].r = ri[i];
Chris@434 122 in[i].i = 0;
Chris@434 123 }
Chris@434 124 if (ii) {
Chris@434 125 for (int i = 0; i < n; ++i) {
Chris@434 126 in[i].i = ii[i];
Chris@434 127 }
Chris@434 128 }
Chris@434 129 kiss_fft(c, in, out);
Chris@434 130 double scale = 1.0 / double(n);
Chris@434 131 for (int i = 0; i < n; ++i) {
Chris@434 132 ro[i] = out[i].r * scale;
Chris@434 133 io[i] = out[i].i * scale;
Chris@434 134 }
Chris@434 135 KissDouble::kiss_fft_free(c);
Chris@434 136 delete[] in;
Chris@434 137 delete[] out;
Chris@434 138 KissDouble::kiss_fft_free(c);
Chris@434 139 }
Chris@434 140
Chris@434 141 class FFTReal::D
Chris@434 142 {
Chris@434 143 public:
Chris@434 144
Chris@434 145 D(int n) :
Chris@434 146 m_n(n),
Chris@434 147 m_cf(KissSingle::kiss_fftr_alloc(n, false, 0, 0)),
Chris@434 148 m_ci(KissSingle::kiss_fftr_alloc(n, true, 0, 0)),
Chris@434 149 m_freq(new KissSingle::kiss_fft_cpx[n/2+1]) { }
Chris@434 150
Chris@434 151 ~D() {
Chris@434 152 KissSingle::kiss_fftr_free(m_cf);
Chris@434 153 KissSingle::kiss_fftr_free(m_ci);
Chris@434 154 delete[] m_freq;
Chris@434 155 }
Chris@434 156
Chris@434 157 void forward(const float *ri, float *co) {
Chris@434 158 KissSingle::kiss_fftr(m_cf, ri, m_freq);
Chris@434 159 int hs = m_n/2 + 1;
Chris@434 160 for (int i = 0; i < hs; ++i) {
Chris@434 161 co[i*2] = m_freq[i].r;
Chris@434 162 co[i*2+1] = m_freq[i].i;
Chris@434 163 }
Chris@434 164 }
Chris@434 165
Chris@434 166 void inverse(const float *ci, float *ro) {
Chris@434 167 int hs = m_n/2 + 1;
Chris@434 168 for (int i = 0; i < hs; ++i) {
Chris@434 169 m_freq[i].r = ci[i*2];
Chris@434 170 m_freq[i].i = ci[i*2+1];
Chris@434 171 }
Chris@434 172 KissSingle::kiss_fftri(m_ci, m_freq, ro);
Chris@434 173 double scale = 1.0 / double(m_n);
Chris@434 174 for (int i = 0; i < m_n; ++i) {
Chris@434 175 ro[i] *= scale;
Chris@434 176 }
Chris@434 177 }
Chris@434 178
Chris@434 179 private:
Chris@434 180 int m_n;
Chris@434 181 KissSingle::kiss_fftr_cfg m_cf;
Chris@434 182 KissSingle::kiss_fftr_cfg m_ci;
Chris@434 183 KissSingle::kiss_fft_cpx *m_freq;
Chris@434 184 };
Chris@434 185
Chris@434 186 FFTReal::FFTReal(unsigned int n) :
Chris@434 187 m_d(new D(n))
Chris@434 188 {
Chris@434 189 }
Chris@434 190
Chris@434 191 FFTReal::~FFTReal()
Chris@434 192 {
Chris@434 193 delete m_d;
Chris@434 194 }
Chris@434 195
Chris@434 196 void
Chris@434 197 FFTReal::forward(const float *ri, float *co)
Chris@434 198 {
Chris@434 199 m_d->forward(ri, co);
Chris@434 200 }
Chris@434 201
Chris@434 202 void
Chris@434 203 FFTReal::inverse(const float *ci, float *ro)
Chris@434 204 {
Chris@434 205 m_d->inverse(ci, ro);
Chris@337 206 }
Chris@337 207
Chris@337 208 }
Chris@337 209
Chris@337 210 _VAMP_SDK_PLUGSPACE_END(FFT.cpp)
Chris@337 211