changeset 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 d3f676c07359
children 7f7a10bcaff1
files src/vamp-hostsdk/PluginInputDomainAdapter.cpp src/vamp-hostsdk/PluginSummarisingAdapter.cpp src/vamp-hostsdk/Window.h
diffstat 3 files changed, 66 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/src/vamp-hostsdk/PluginInputDomainAdapter.cpp	Thu Aug 18 12:03:09 2016 +0100
+++ b/src/vamp-hostsdk/PluginInputDomainAdapter.cpp	Thu Aug 18 14:43:52 2016 +0100
@@ -49,22 +49,40 @@
 #include <string.h>
 #include <limits.h>
 
+// Define this symbol in the build if you want to use single-precision
+// FFTs in the input domain adapter. The default is to use
+// double-precision FFTs.
+//
+//#define SINGLE_PRECISION_INPUT_DOMAIN_ADAPTER 1
+
 // Override C linkage for KissFFT headers. So long as we have already
 // included all of the other (system etc) headers KissFFT depends on,
 // this should work out OK
 #undef __cplusplus
 
-namespace KissSingle {
+namespace Kiss {
+
 #undef KISS_FFT_H
 #undef KISS_FTR_H
 #undef KISS_FFT__GUTS_H
 #undef FIXED_POINT
 #undef USE_SIMD
 #undef kiss_fft_scalar
+
+#ifdef SINGLE_PRECISION_INPUT_DOMAIN_ADAPTER
+typedef float kiss_fft_scalar;
 #define kiss_fft_scalar float
+#else
+typedef double kiss_fft_scalar;
+#define kiss_fft_scalar double
+#endif
+
 inline void free(void *ptr) { ::free(ptr); }
 #include "../vamp-sdk/ext/kiss_fft.c"
 #include "../vamp-sdk/ext/kiss_fftr.c"
+
+#undef kiss_fft_scalar // leaving only the namespaced typedef
+
 }
 
 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp)
@@ -102,24 +120,25 @@
     int m_stepSize;
     int m_blockSize;
     float **m_freqbuf;
-    float *m_ri;
+    Kiss::kiss_fft_scalar *m_ri;
 
     WindowType m_windowType;
-    Window<float> *m_window;
+    typedef Window<Kiss::kiss_fft_scalar> W;
+    W *m_window;
 
     ProcessTimestampMethod m_method;
     int m_processCount;
     float **m_shiftBuffers;
 
-    KissSingle::kiss_fftr_cfg m_cfg;
-    KissSingle::kiss_fft_cpx *m_cbuf;
+    Kiss::kiss_fftr_cfg m_cfg;
+    Kiss::kiss_fft_cpx *m_cbuf;
 
     FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
     FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
 
     size_t makeBlockSizeAcceptable(size_t) const;
     
-    Window<float>::WindowType convertType(WindowType t) const;
+    W::WindowType convertType(WindowType t) const;
 };
 
 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
@@ -236,7 +255,7 @@
         delete[] m_freqbuf;
         delete[] m_ri;
         if (m_cfg) {
-            KissSingle::kiss_fftr_free(m_cfg);
+            Kiss::kiss_fftr_free(m_cfg);
             m_cfg = 0;
             delete[] m_cbuf;
             m_cbuf = 0;
@@ -279,7 +298,7 @@
         delete[] m_freqbuf;
         delete[] m_ri;
         if (m_cfg) {
-            KissSingle::kiss_fftr_free(m_cfg);
+            Kiss::kiss_fftr_free(m_cfg);
             m_cfg = 0;
             delete[] m_cbuf;
             m_cbuf = 0;
@@ -295,12 +314,12 @@
     for (int c = 0; c < m_channels; ++c) {
         m_freqbuf[c] = new float[m_blockSize + 2];
     }
-    m_ri = new float[m_blockSize];
+    m_ri = new Kiss::kiss_fft_scalar[m_blockSize];
 
-    m_window = new Window<float>(convertType(m_windowType), m_blockSize);
+    m_window = new W(convertType(m_windowType), m_blockSize);
 
-    m_cfg = KissSingle::kiss_fftr_alloc(m_blockSize, false, 0, 0);
-    m_cbuf = new KissSingle::kiss_fft_cpx[m_blockSize/2+1];
+    m_cfg = Kiss::kiss_fftr_alloc(m_blockSize, false, 0, 0);
+    m_cbuf = new Kiss::kiss_fft_cpx[m_blockSize/2+1];
 
     m_processCount = 0;
 
@@ -393,7 +412,7 @@
     m_windowType = t;
     if (m_window) {
         delete m_window;
-        m_window = new Window<float>(convertType(m_windowType), m_blockSize);
+        m_window = new W(convertType(m_windowType), m_blockSize);
     }
 }
 
@@ -403,26 +422,26 @@
     return m_windowType;
 }
 
-Window<float>::WindowType
+PluginInputDomainAdapter::Impl::W::WindowType
 PluginInputDomainAdapter::Impl::convertType(WindowType t) const
 {
     switch (t) {
     case RectangularWindow:
-        return Window<float>::RectangularWindow;
+        return W::RectangularWindow;
     case BartlettWindow:
-        return Window<float>::BartlettWindow;
+        return W::BartlettWindow;
     case HammingWindow:
-        return Window<float>::HammingWindow;
+        return W::HammingWindow;
     case HanningWindow:
-        return Window<float>::HanningWindow;
+        return W::HanningWindow;
     case BlackmanWindow:
-        return Window<float>::BlackmanWindow;
+        return W::BlackmanWindow;
     case NuttallWindow:
-        return Window<float>::NuttallWindow;
+        return W::NuttallWindow;
     case BlackmanHarrisWindow:
-        return Window<float>::BlackmanHarrisWindow;
+        return W::BlackmanHarrisWindow;
     default:
-	return Window<float>::HanningWindow;
+	return W::HanningWindow;
     }
 }
 
@@ -467,12 +486,12 @@
 
         for (int i = 0; i < m_blockSize/2; ++i) {
             // FFT shift
-            float value = m_ri[i];
+            Kiss::kiss_fft_scalar value = m_ri[i];
             m_ri[i] = m_ri[i + m_blockSize/2];
             m_ri[i + m_blockSize/2] = value;
         }
 
-        KissSingle::kiss_fftr(m_cfg, m_ri, m_cbuf);
+        Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf);
         
         for (int i = 0; i <= m_blockSize/2; ++i) {
             m_freqbuf[c][i * 2] = m_cbuf[i].r;
@@ -516,12 +535,12 @@
 
         for (int i = 0; i < m_blockSize/2; ++i) {
             // FFT shift
-            float value = m_ri[i];
+            Kiss::kiss_fft_scalar value = m_ri[i];
             m_ri[i] = m_ri[i + m_blockSize/2];
             m_ri[i + m_blockSize/2] = value;
         }
 
-        KissSingle::kiss_fftr(m_cfg, m_ri, m_cbuf);
+        Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf);
         
         for (int i = 0; i <= m_blockSize/2; ++i) {
             m_freqbuf[c][i * 2] = m_cbuf[i].r;
--- a/src/vamp-hostsdk/PluginSummarisingAdapter.cpp	Thu Aug 18 12:03:09 2016 +0100
+++ b/src/vamp-hostsdk/PluginSummarisingAdapter.cpp	Thu Aug 18 14:43:52 2016 +0100
@@ -868,10 +868,19 @@
                 
                 map<float, int> distribution;
 
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+                cerr << "summing (discrete): ";
+#endif
                 for (int k = 0; k < sz; ++k) {
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+                    cerr << accumulator.results[k].values[bin] << " ";
+#endif
                     summary.sum += accumulator.results[k].values[bin];
                     distribution[accumulator.results[k].values[bin]] += 1;
                 }
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+                cerr << endl;
+#endif
 
                 int md = 0;
 
@@ -908,11 +917,21 @@
 
                     double sum_c = 0.0;
 
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+                    cerr << "summing (continuous): ";
+#endif
                     for (int k = 0; k < sz; ++k) {
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+                        cerr << accumulator.results[k].values[bin] << "*"
+                             << toSec(accumulator.results[k].duration) << " ";
+#endif
                         double value = accumulator.results[k].values[bin]
                             * toSec(accumulator.results[k].duration);
                         sum_c += value;
                     }
+#ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
+                cerr << endl;
+#endif
 
 #ifdef DEBUG_PLUGIN_SUMMARISING_ADAPTER
                     cerr << "mean_c = " << sum_c << " / " << totalDuration << " = "
--- a/src/vamp-hostsdk/Window.h	Thu Aug 18 12:03:09 2016 +0100
+++ b/src/vamp-hostsdk/Window.h	Thu Aug 18 14:43:52 2016 +0100
@@ -76,8 +76,8 @@
     void cut(T *src, T *dst) const {
 	for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i];
     }
-    template <typename T0>
-    void cut(T0 *src, T *dst) const {
+    template <typename T0, typename T1>
+    void cut(T0 *src, T1 *dst) const {
 	for (size_t i = 0; i < m_size; ++i) dst[i] = src[i] * m_cache[i];
     }