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 }