Mercurial > hg > vamp-plugin-sdk
comparison src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 444:7bab0c5422f4 vampipe
Make single/double-precision selectable for input domain adapter windowing and FFTs. Double precision is necessary to pass Sonic Annotator regression tests, though in practice most real-world methods would be fine with single precision.
author | Chris Cannam |
---|---|
date | Thu, 18 Aug 2016 14:43:52 +0100 |
parents | 27c3448df198 |
children | 7f7a10bcaff1 |
comparison
equal
deleted
inserted
replaced
443:d3f676c07359 | 444:7bab0c5422f4 |
---|---|
47 #include <stdio.h> | 47 #include <stdio.h> |
48 #include <math.h> | 48 #include <math.h> |
49 #include <string.h> | 49 #include <string.h> |
50 #include <limits.h> | 50 #include <limits.h> |
51 | 51 |
52 // Define this symbol in the build if you want to use single-precision | |
53 // FFTs in the input domain adapter. The default is to use | |
54 // double-precision FFTs. | |
55 // | |
56 //#define SINGLE_PRECISION_INPUT_DOMAIN_ADAPTER 1 | |
57 | |
52 // Override C linkage for KissFFT headers. So long as we have already | 58 // Override C linkage for KissFFT headers. So long as we have already |
53 // included all of the other (system etc) headers KissFFT depends on, | 59 // included all of the other (system etc) headers KissFFT depends on, |
54 // this should work out OK | 60 // this should work out OK |
55 #undef __cplusplus | 61 #undef __cplusplus |
56 | 62 |
57 namespace KissSingle { | 63 namespace Kiss { |
64 | |
58 #undef KISS_FFT_H | 65 #undef KISS_FFT_H |
59 #undef KISS_FTR_H | 66 #undef KISS_FTR_H |
60 #undef KISS_FFT__GUTS_H | 67 #undef KISS_FFT__GUTS_H |
61 #undef FIXED_POINT | 68 #undef FIXED_POINT |
62 #undef USE_SIMD | 69 #undef USE_SIMD |
63 #undef kiss_fft_scalar | 70 #undef kiss_fft_scalar |
71 | |
72 #ifdef SINGLE_PRECISION_INPUT_DOMAIN_ADAPTER | |
73 typedef float kiss_fft_scalar; | |
64 #define kiss_fft_scalar float | 74 #define kiss_fft_scalar float |
75 #else | |
76 typedef double kiss_fft_scalar; | |
77 #define kiss_fft_scalar double | |
78 #endif | |
79 | |
65 inline void free(void *ptr) { ::free(ptr); } | 80 inline void free(void *ptr) { ::free(ptr); } |
66 #include "../vamp-sdk/ext/kiss_fft.c" | 81 #include "../vamp-sdk/ext/kiss_fft.c" |
67 #include "../vamp-sdk/ext/kiss_fftr.c" | 82 #include "../vamp-sdk/ext/kiss_fftr.c" |
83 | |
84 #undef kiss_fft_scalar // leaving only the namespaced typedef | |
85 | |
68 } | 86 } |
69 | 87 |
70 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp) | 88 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp) |
71 | 89 |
72 namespace Vamp { | 90 namespace Vamp { |
100 float m_inputSampleRate; | 118 float m_inputSampleRate; |
101 int m_channels; | 119 int m_channels; |
102 int m_stepSize; | 120 int m_stepSize; |
103 int m_blockSize; | 121 int m_blockSize; |
104 float **m_freqbuf; | 122 float **m_freqbuf; |
105 float *m_ri; | 123 Kiss::kiss_fft_scalar *m_ri; |
106 | 124 |
107 WindowType m_windowType; | 125 WindowType m_windowType; |
108 Window<float> *m_window; | 126 typedef Window<Kiss::kiss_fft_scalar> W; |
127 W *m_window; | |
109 | 128 |
110 ProcessTimestampMethod m_method; | 129 ProcessTimestampMethod m_method; |
111 int m_processCount; | 130 int m_processCount; |
112 float **m_shiftBuffers; | 131 float **m_shiftBuffers; |
113 | 132 |
114 KissSingle::kiss_fftr_cfg m_cfg; | 133 Kiss::kiss_fftr_cfg m_cfg; |
115 KissSingle::kiss_fft_cpx *m_cbuf; | 134 Kiss::kiss_fft_cpx *m_cbuf; |
116 | 135 |
117 FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp); | 136 FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp); |
118 FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp); | 137 FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp); |
119 | 138 |
120 size_t makeBlockSizeAcceptable(size_t) const; | 139 size_t makeBlockSizeAcceptable(size_t) const; |
121 | 140 |
122 Window<float>::WindowType convertType(WindowType t) const; | 141 W::WindowType convertType(WindowType t) const; |
123 }; | 142 }; |
124 | 143 |
125 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) : | 144 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) : |
126 PluginWrapper(plugin) | 145 PluginWrapper(plugin) |
127 { | 146 { |
234 delete[] m_freqbuf[c]; | 253 delete[] m_freqbuf[c]; |
235 } | 254 } |
236 delete[] m_freqbuf; | 255 delete[] m_freqbuf; |
237 delete[] m_ri; | 256 delete[] m_ri; |
238 if (m_cfg) { | 257 if (m_cfg) { |
239 KissSingle::kiss_fftr_free(m_cfg); | 258 Kiss::kiss_fftr_free(m_cfg); |
240 m_cfg = 0; | 259 m_cfg = 0; |
241 delete[] m_cbuf; | 260 delete[] m_cbuf; |
242 m_cbuf = 0; | 261 m_cbuf = 0; |
243 } | 262 } |
244 delete m_window; | 263 delete m_window; |
277 delete[] m_freqbuf[c]; | 296 delete[] m_freqbuf[c]; |
278 } | 297 } |
279 delete[] m_freqbuf; | 298 delete[] m_freqbuf; |
280 delete[] m_ri; | 299 delete[] m_ri; |
281 if (m_cfg) { | 300 if (m_cfg) { |
282 KissSingle::kiss_fftr_free(m_cfg); | 301 Kiss::kiss_fftr_free(m_cfg); |
283 m_cfg = 0; | 302 m_cfg = 0; |
284 delete[] m_cbuf; | 303 delete[] m_cbuf; |
285 m_cbuf = 0; | 304 m_cbuf = 0; |
286 } | 305 } |
287 delete m_window; | 306 delete m_window; |
293 | 312 |
294 m_freqbuf = new float *[m_channels]; | 313 m_freqbuf = new float *[m_channels]; |
295 for (int c = 0; c < m_channels; ++c) { | 314 for (int c = 0; c < m_channels; ++c) { |
296 m_freqbuf[c] = new float[m_blockSize + 2]; | 315 m_freqbuf[c] = new float[m_blockSize + 2]; |
297 } | 316 } |
298 m_ri = new float[m_blockSize]; | 317 m_ri = new Kiss::kiss_fft_scalar[m_blockSize]; |
299 | 318 |
300 m_window = new Window<float>(convertType(m_windowType), m_blockSize); | 319 m_window = new W(convertType(m_windowType), m_blockSize); |
301 | 320 |
302 m_cfg = KissSingle::kiss_fftr_alloc(m_blockSize, false, 0, 0); | 321 m_cfg = Kiss::kiss_fftr_alloc(m_blockSize, false, 0, 0); |
303 m_cbuf = new KissSingle::kiss_fft_cpx[m_blockSize/2+1]; | 322 m_cbuf = new Kiss::kiss_fft_cpx[m_blockSize/2+1]; |
304 | 323 |
305 m_processCount = 0; | 324 m_processCount = 0; |
306 | 325 |
307 return m_plugin->initialise(channels, stepSize, m_blockSize); | 326 return m_plugin->initialise(channels, stepSize, m_blockSize); |
308 } | 327 } |
391 { | 410 { |
392 if (m_windowType == t) return; | 411 if (m_windowType == t) return; |
393 m_windowType = t; | 412 m_windowType = t; |
394 if (m_window) { | 413 if (m_window) { |
395 delete m_window; | 414 delete m_window; |
396 m_window = new Window<float>(convertType(m_windowType), m_blockSize); | 415 m_window = new W(convertType(m_windowType), m_blockSize); |
397 } | 416 } |
398 } | 417 } |
399 | 418 |
400 PluginInputDomainAdapter::WindowType | 419 PluginInputDomainAdapter::WindowType |
401 PluginInputDomainAdapter::Impl::getWindowType() const | 420 PluginInputDomainAdapter::Impl::getWindowType() const |
402 { | 421 { |
403 return m_windowType; | 422 return m_windowType; |
404 } | 423 } |
405 | 424 |
406 Window<float>::WindowType | 425 PluginInputDomainAdapter::Impl::W::WindowType |
407 PluginInputDomainAdapter::Impl::convertType(WindowType t) const | 426 PluginInputDomainAdapter::Impl::convertType(WindowType t) const |
408 { | 427 { |
409 switch (t) { | 428 switch (t) { |
410 case RectangularWindow: | 429 case RectangularWindow: |
411 return Window<float>::RectangularWindow; | 430 return W::RectangularWindow; |
412 case BartlettWindow: | 431 case BartlettWindow: |
413 return Window<float>::BartlettWindow; | 432 return W::BartlettWindow; |
414 case HammingWindow: | 433 case HammingWindow: |
415 return Window<float>::HammingWindow; | 434 return W::HammingWindow; |
416 case HanningWindow: | 435 case HanningWindow: |
417 return Window<float>::HanningWindow; | 436 return W::HanningWindow; |
418 case BlackmanWindow: | 437 case BlackmanWindow: |
419 return Window<float>::BlackmanWindow; | 438 return W::BlackmanWindow; |
420 case NuttallWindow: | 439 case NuttallWindow: |
421 return Window<float>::NuttallWindow; | 440 return W::NuttallWindow; |
422 case BlackmanHarrisWindow: | 441 case BlackmanHarrisWindow: |
423 return Window<float>::BlackmanHarrisWindow; | 442 return W::BlackmanHarrisWindow; |
424 default: | 443 default: |
425 return Window<float>::HanningWindow; | 444 return W::HanningWindow; |
426 } | 445 } |
427 } | 446 } |
428 | 447 |
429 Plugin::FeatureSet | 448 Plugin::FeatureSet |
430 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers, | 449 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers, |
465 | 484 |
466 m_window->cut(inputBuffers[c], m_ri); | 485 m_window->cut(inputBuffers[c], m_ri); |
467 | 486 |
468 for (int i = 0; i < m_blockSize/2; ++i) { | 487 for (int i = 0; i < m_blockSize/2; ++i) { |
469 // FFT shift | 488 // FFT shift |
470 float value = m_ri[i]; | 489 Kiss::kiss_fft_scalar value = m_ri[i]; |
471 m_ri[i] = m_ri[i + m_blockSize/2]; | 490 m_ri[i] = m_ri[i + m_blockSize/2]; |
472 m_ri[i + m_blockSize/2] = value; | 491 m_ri[i + m_blockSize/2] = value; |
473 } | 492 } |
474 | 493 |
475 KissSingle::kiss_fftr(m_cfg, m_ri, m_cbuf); | 494 Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf); |
476 | 495 |
477 for (int i = 0; i <= m_blockSize/2; ++i) { | 496 for (int i = 0; i <= m_blockSize/2; ++i) { |
478 m_freqbuf[c][i * 2] = m_cbuf[i].r; | 497 m_freqbuf[c][i * 2] = m_cbuf[i].r; |
479 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i; | 498 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i; |
480 } | 499 } |
514 | 533 |
515 m_window->cut(m_shiftBuffers[c], m_ri); | 534 m_window->cut(m_shiftBuffers[c], m_ri); |
516 | 535 |
517 for (int i = 0; i < m_blockSize/2; ++i) { | 536 for (int i = 0; i < m_blockSize/2; ++i) { |
518 // FFT shift | 537 // FFT shift |
519 float value = m_ri[i]; | 538 Kiss::kiss_fft_scalar value = m_ri[i]; |
520 m_ri[i] = m_ri[i + m_blockSize/2]; | 539 m_ri[i] = m_ri[i + m_blockSize/2]; |
521 m_ri[i + m_blockSize/2] = value; | 540 m_ri[i + m_blockSize/2] = value; |
522 } | 541 } |
523 | 542 |
524 KissSingle::kiss_fftr(m_cfg, m_ri, m_cbuf); | 543 Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf); |
525 | 544 |
526 for (int i = 0; i <= m_blockSize/2; ++i) { | 545 for (int i = 0; i <= m_blockSize/2; ++i) { |
527 m_freqbuf[c][i * 2] = m_cbuf[i].r; | 546 m_freqbuf[c][i * 2] = m_cbuf[i].r; |
528 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i; | 547 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i; |
529 } | 548 } |