Mercurial > hg > vamp-plugin-sdk
comparison src/vamp-sdk/FFT.cpp @ 445:7f7a10bcaff1 vampipe
Single or double-precision FFTs (double in the default build), not both
author | Chris Cannam |
---|---|
date | Thu, 18 Aug 2016 15:06:23 +0100 |
parents | 41baa6241da2 |
children | d132b92ec65d |
comparison
equal
deleted
inserted
replaced
444:7bab0c5422f4 | 445:7f7a10bcaff1 |
---|---|
45 #error Unexpected version of Vamp SDK header included | 45 #error Unexpected version of Vamp SDK header included |
46 #endif | 46 #endif |
47 | 47 |
48 _VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp) | 48 _VAMP_SDK_PLUGSPACE_BEGIN(FFT.cpp) |
49 | 49 |
50 // Override C linkage for KissFFT headers. So long as we have already | 50 #include "FFTimpl.cpp" |
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 | 51 |
81 namespace Vamp { | 52 namespace Vamp { |
82 | 53 |
83 void | 54 void |
84 FFT::forward(unsigned int un, | 55 FFT::forward(unsigned int un, |
85 const double *ri, const double *ii, | 56 const double *ri, const double *ii, |
86 double *ro, double *io) | 57 double *ro, double *io) |
87 { | 58 { |
88 int n(un); | 59 int n(un); |
89 KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, false, 0, 0); | 60 Kiss::kiss_fft_cfg c = Kiss::kiss_fft_alloc(n, false, 0, 0); |
90 KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n]; | 61 Kiss::kiss_fft_cpx *in = new Kiss::kiss_fft_cpx[n]; |
91 KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n]; | 62 Kiss::kiss_fft_cpx *out = new Kiss::kiss_fft_cpx[n]; |
92 for (int i = 0; i < n; ++i) { | 63 for (int i = 0; i < n; ++i) { |
93 in[i].r = ri[i]; | 64 in[i].r = ri[i]; |
94 in[i].i = 0; | 65 in[i].i = 0; |
95 } | 66 } |
96 if (ii) { | 67 if (ii) { |
101 kiss_fft(c, in, out); | 72 kiss_fft(c, in, out); |
102 for (int i = 0; i < n; ++i) { | 73 for (int i = 0; i < n; ++i) { |
103 ro[i] = out[i].r; | 74 ro[i] = out[i].r; |
104 io[i] = out[i].i; | 75 io[i] = out[i].i; |
105 } | 76 } |
106 KissDouble::kiss_fft_free(c); | 77 Kiss::kiss_fft_free(c); |
107 delete[] in; | 78 delete[] in; |
108 delete[] out; | 79 delete[] out; |
109 } | 80 } |
110 | 81 |
111 void | 82 void |
112 FFT::inverse(unsigned int un, | 83 FFT::inverse(unsigned int un, |
113 const double *ri, const double *ii, | 84 const double *ri, const double *ii, |
114 double *ro, double *io) | 85 double *ro, double *io) |
115 { | 86 { |
116 int n(un); | 87 int n(un); |
117 KissDouble::kiss_fft_cfg c = KissDouble::kiss_fft_alloc(n, true, 0, 0); | 88 Kiss::kiss_fft_cfg c = Kiss::kiss_fft_alloc(n, true, 0, 0); |
118 KissDouble::kiss_fft_cpx *in = new KissDouble::kiss_fft_cpx[n]; | 89 Kiss::kiss_fft_cpx *in = new Kiss::kiss_fft_cpx[n]; |
119 KissDouble::kiss_fft_cpx *out = new KissDouble::kiss_fft_cpx[n]; | 90 Kiss::kiss_fft_cpx *out = new Kiss::kiss_fft_cpx[n]; |
120 for (int i = 0; i < n; ++i) { | 91 for (int i = 0; i < n; ++i) { |
121 in[i].r = ri[i]; | 92 in[i].r = ri[i]; |
122 in[i].i = 0; | 93 in[i].i = 0; |
123 } | 94 } |
124 if (ii) { | 95 if (ii) { |
130 double scale = 1.0 / double(n); | 101 double scale = 1.0 / double(n); |
131 for (int i = 0; i < n; ++i) { | 102 for (int i = 0; i < n; ++i) { |
132 ro[i] = out[i].r * scale; | 103 ro[i] = out[i].r * scale; |
133 io[i] = out[i].i * scale; | 104 io[i] = out[i].i * scale; |
134 } | 105 } |
135 KissDouble::kiss_fft_free(c); | 106 Kiss::kiss_fft_free(c); |
136 delete[] in; | 107 delete[] in; |
137 delete[] out; | 108 delete[] out; |
138 } | 109 } |
139 | 110 |
140 class FFTReal::D | 111 class FFTReal::D |
141 { | 112 { |
142 public: | 113 public: |
143 | 114 |
144 D(int n) : | 115 D(int n) : |
145 m_n(n), | 116 m_n(n), |
146 m_cf(KissSingle::kiss_fftr_alloc(n, false, 0, 0)), | 117 m_cf(Kiss::kiss_fftr_alloc(n, false, 0, 0)), |
147 m_ci(KissSingle::kiss_fftr_alloc(n, true, 0, 0)), | 118 m_ci(Kiss::kiss_fftr_alloc(n, true, 0, 0)), |
148 m_freq(new KissSingle::kiss_fft_cpx[n/2+1]) { } | 119 m_ri(new Kiss::kiss_fft_scalar[m_n]), |
120 m_ro(new Kiss::kiss_fft_scalar[m_n]), | |
121 m_freq(new Kiss::kiss_fft_cpx[n/2+1]) { } | |
149 | 122 |
150 ~D() { | 123 ~D() { |
151 KissSingle::kiss_fftr_free(m_cf); | 124 Kiss::kiss_fftr_free(m_cf); |
152 KissSingle::kiss_fftr_free(m_ci); | 125 Kiss::kiss_fftr_free(m_ci); |
126 delete[] m_ri; | |
127 delete[] m_ro; | |
153 delete[] m_freq; | 128 delete[] m_freq; |
154 } | 129 } |
155 | 130 |
156 void forward(const float *ri, float *co) { | 131 void forward(const double *ri, double *co) { |
157 KissSingle::kiss_fftr(m_cf, ri, m_freq); | 132 for (int i = 0; i < m_n; ++i) { |
133 // in case kiss_fft_scalar is float | |
134 m_ri[i] = ri[i]; | |
135 } | |
136 Kiss::kiss_fftr(m_cf, m_ri, m_freq); | |
158 int hs = m_n/2 + 1; | 137 int hs = m_n/2 + 1; |
159 for (int i = 0; i < hs; ++i) { | 138 for (int i = 0; i < hs; ++i) { |
160 co[i*2] = m_freq[i].r; | 139 co[i*2] = m_freq[i].r; |
161 co[i*2+1] = m_freq[i].i; | 140 co[i*2+1] = m_freq[i].i; |
162 } | 141 } |
163 } | 142 } |
164 | 143 |
165 void inverse(const float *ci, float *ro) { | 144 void inverse(const double *ci, double *ro) { |
166 int hs = m_n/2 + 1; | 145 int hs = m_n/2 + 1; |
167 for (int i = 0; i < hs; ++i) { | 146 for (int i = 0; i < hs; ++i) { |
168 m_freq[i].r = ci[i*2]; | 147 m_freq[i].r = ci[i*2]; |
169 m_freq[i].i = ci[i*2+1]; | 148 m_freq[i].i = ci[i*2+1]; |
170 } | 149 } |
171 KissSingle::kiss_fftri(m_ci, m_freq, ro); | 150 Kiss::kiss_fftri(m_ci, m_freq, m_ro); |
172 double scale = 1.0 / double(m_n); | 151 double scale = 1.0 / double(m_n); |
173 for (int i = 0; i < m_n; ++i) { | 152 for (int i = 0; i < m_n; ++i) { |
174 ro[i] *= scale; | 153 ro[i] = m_ro[i] * scale; |
175 } | 154 } |
176 } | 155 } |
177 | 156 |
178 private: | 157 private: |
179 int m_n; | 158 int m_n; |
180 KissSingle::kiss_fftr_cfg m_cf; | 159 Kiss::kiss_fftr_cfg m_cf; |
181 KissSingle::kiss_fftr_cfg m_ci; | 160 Kiss::kiss_fftr_cfg m_ci; |
182 KissSingle::kiss_fft_cpx *m_freq; | 161 Kiss::kiss_fft_scalar *m_ri; |
162 Kiss::kiss_fft_scalar *m_ro; | |
163 Kiss::kiss_fft_cpx *m_freq; | |
183 }; | 164 }; |
184 | 165 |
185 FFTReal::FFTReal(unsigned int n) : | 166 FFTReal::FFTReal(unsigned int n) : |
186 m_d(new D(n)) | 167 m_d(new D(n)) |
187 { | 168 { |
191 { | 172 { |
192 delete m_d; | 173 delete m_d; |
193 } | 174 } |
194 | 175 |
195 void | 176 void |
196 FFTReal::forward(const float *ri, float *co) | 177 FFTReal::forward(const double *ri, double *co) |
197 { | 178 { |
198 m_d->forward(ri, co); | 179 m_d->forward(ri, co); |
199 } | 180 } |
200 | 181 |
201 void | 182 void |
202 FFTReal::inverse(const float *ci, float *ro) | 183 FFTReal::inverse(const double *ci, double *ro) |
203 { | 184 { |
204 m_d->inverse(ci, ro); | 185 m_d->inverse(ci, ro); |
205 } | 186 } |
206 | 187 |
207 } | 188 } |