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 }