comparison 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
comparison
equal deleted inserted replaced
432:8dea61e4a7be 434:e979a9c4ffb6
34 authorization. 34 authorization.
35 */ 35 */
36 36
37 #include <vamp-sdk/FFT.h> 37 #include <vamp-sdk/FFT.h>
38 38
39 #include <cmath> 39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <math.h>
42 #include <string.h>
40 43
41 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 7 ) 44 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 7 )
42 #error Unexpected version of Vamp SDK header included 45 #error Unexpected version of Vamp SDK header included
43 #endif 46 #endif
44 47
45 #ifdef _MSC_VER
46 #include <stdlib.h>
47 #include <malloc.h>
48 #endif
49
50 _VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp) 48 _VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp)
51 49
50 // Override C linkage for KissFFT headers. So long as we have already
51 // included all of the other (system etc) headers KissFFT depends on,
52 // this should work out OK
53 #undef __cplusplus
54
55 namespace KissSingle {
56 #undef KISS_FFT_H
57 #undef KISS_FTR_H
58 #undef KISS_FFT__GUTS_H
59 #undef FIXED_POINT
60 #undef USE_SIMD
61 #undef kiss_fft_scalar
62 #define kiss_fft_scalar float
63 inline void free(void *ptr) { ::free(ptr); }
64 #include "ext/kiss_fft.c"
65 #include "ext/kiss_fftr.c"
66 }
67
68 namespace KissDouble {
69 #undef KISS_FFT_H
70 #undef KISS_FTR_H
71 #undef KISS_FFT__GUTS_H
72 #undef FIXED_POINT
73 #undef USE_SIMD
74 #undef kiss_fft_scalar
75 #define kiss_fft_scalar double
76 inline void free(void *ptr) { ::free(ptr); }
77 #include "ext/kiss_fft.c"
78 #include "ext/kiss_fftr.c"
79 }
80
52 namespace Vamp { 81 namespace Vamp {
53 82
54 #include "FFTimpl.cpp" 83 void
55 84 FFT::forward(unsigned int un,
56 void
57 FFT::forward(unsigned int n,
58 const double *ri, const double *ii, 85 const double *ri, const double *ii,
59 double *ro, double *io) 86 double *ro, double *io)
60 { 87 {
61 fft(n, false, ri, ii, ro, io); 88 int n(un);
62 } 89 KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, false, 0, 0);
63 90 KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n];
64 void 91 KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n];
65 FFT::inverse(unsigned int n, 92 for (int i = 0; i < n; ++i) {
93 in[i].r = ri[i];
94 in[i].i = 0;
95 }
96 if (ii) {
97 for (int i = 0; i < n; ++i) {
98 in[i].i = ii[i];
99 }
100 }
101 kiss_fft(c, in, out);
102 for (int i = 0; i < n; ++i) {
103 ro[i] = out[i].r;
104 io[i] = out[i].i;
105 }
106 KissDouble::kiss_fft_free(c);
107 delete[] in;
108 delete[] out;
109 }
110
111 void
112 FFT::inverse(unsigned int un,
66 const double *ri, const double *ii, 113 const double *ri, const double *ii,
67 double *ro, double *io) 114 double *ro, double *io)
68 { 115 {
69 fft(n, true, ri, ii, ro, io); 116 int n(un);
117 KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, true, 0, 0);
118 KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n];
119 KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n];
120 for (int i = 0; i < n; ++i) {
121 in[i].r = ri[i];
122 in[i].i = 0;
123 }
124 if (ii) {
125 for (int i = 0; i < n; ++i) {
126 in[i].i = ii[i];
127 }
128 }
129 kiss_fft(c, in, out);
130 double scale = 1.0 / double(n);
131 for (int i = 0; i < n; ++i) {
132 ro[i] = out[i].r * scale;
133 io[i] = out[i].i * scale;
134 }
135 KissDouble::kiss_fft_free(c);
136 delete[] in;
137 delete[] out;
138 KissDouble::kiss_fft_free(c);
139 }
140
141 class FFTReal::D
142 {
143 public:
144
145 D(int n) :
146 m_n(n),
147 m_cf(KissSingle::kiss_fftr_alloc(n, false, 0, 0)),
148 m_ci(KissSingle::kiss_fftr_alloc(n, true, 0, 0)),
149 m_freq(new KissSingle::kiss_fft_cpx[n/2+1]) { }
150
151 ~D() {
152 KissSingle::kiss_fftr_free(m_cf);
153 KissSingle::kiss_fftr_free(m_ci);
154 delete[] m_freq;
155 }
156
157 void forward(const float *ri, float *co) {
158 KissSingle::kiss_fftr(m_cf, ri, m_freq);
159 int hs = m_n/2 + 1;
160 for (int i = 0; i < hs; ++i) {
161 co[i*2] = m_freq[i].r;
162 co[i*2+1] = m_freq[i].i;
163 }
164 }
165
166 void inverse(const float *ci, float *ro) {
167 int hs = m_n/2 + 1;
168 for (int i = 0; i < hs; ++i) {
169 m_freq[i].r = ci[i*2];
170 m_freq[i].i = ci[i*2+1];
171 }
172 KissSingle::kiss_fftri(m_ci, m_freq, ro);
173 double scale = 1.0 / double(m_n);
174 for (int i = 0; i < m_n; ++i) {
175 ro[i] *= scale;
176 }
177 }
178
179 private:
180 int m_n;
181 KissSingle::kiss_fftr_cfg m_cf;
182 KissSingle::kiss_fftr_cfg m_ci;
183 KissSingle::kiss_fft_cpx *m_freq;
184 };
185
186 FFTReal::FFTReal(unsigned int n) :
187 m_d(new D(n))
188 {
189 }
190
191 FFTReal::~FFTReal()
192 {
193 delete m_d;
194 }
195
196 void
197 FFTReal::forward(const float *ri, float *co)
198 {
199 m_d->forward(ri, co);
200 }
201
202 void
203 FFTReal::inverse(const float *ci, float *ro)
204 {
205 m_d->inverse(ci, ro);
70 } 206 }
71 207
72 } 208 }
73 209
74 _VAMP_SDK_PLUGSPACE_END(FFT.cpp) 210 _VAMP_SDK_PLUGSPACE_END(FFT.cpp)