diff src/vamp-hostsdk/PluginInputDomainAdapter.cpp @ 434:e979a9c4ffb6 vampipe

Switch from Cross FFT with option of FFTW build, to KissFFT only (code bundled). This is much faster than the default build and simpler than managing two options.
author Chris Cannam
date Tue, 16 Aug 2016 16:04:09 +0100
parents 9a2998401bbe
children 27c3448df198
line wrap: on
line diff
--- a/src/vamp-hostsdk/PluginInputDomainAdapter.cpp	Wed May 18 12:21:17 2016 +0100
+++ b/src/vamp-hostsdk/PluginInputDomainAdapter.cpp	Tue Aug 16 16:04:09 2016 +0100
@@ -43,37 +43,29 @@
 
 #include "Window.h"
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <limits.h>
 
-/**
- * If you want to compile using FFTW instead of the built-in FFT
- * implementation for the PluginInputDomainAdapter, define HAVE_FFTW3
- * in the Makefile.
- *
- * Be aware that FFTW is licensed under the GPL -- unlike this SDK,
- * which is provided under a more liberal BSD license in order to
- * permit use in closed source applications.  The use of FFTW would
- * mean that your code would need to be licensed under the GPL as
- * well.  Do not define this symbol unless you understand and accept
- * the implications of this.
- *
- * Parties such as Linux distribution packagers who redistribute this
- * SDK for use in other programs should _not_ define this symbol, as
- * it would change the effective licensing terms under which the SDK
- * was available to third party developers.
- *
- * The default is not to use FFTW, and to use the built-in FFT instead.
- * 
- * Note: The FFTW code uses FFTW_MEASURE, and so will perform badly on
- * its first invocation unless the host has saved and restored FFTW
- * wisdom (see the FFTW documentation).
- */
-#ifdef HAVE_FFTW3
-#include <fftw3.h>
-#pragma message("*** NOTE: Compiling with FFTW3 support will result in a GPL binary")
-#else
-#include "../vamp-sdk/FFTimpl.cpp"
-#endif
+// 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 {
+#undef KISS_FFT_H
+#undef KISS_FTR_H
+#undef KISS_FFT__GUTS_H
+#undef FIXED_POINT
+#undef USE_SIMD
+#undef kiss_fft_scalar
+#define kiss_fft_scalar float
+inline void free(void *ptr) { ::free(ptr); }
+#include "../vamp-sdk/ext/kiss_fft.c"
+#include "../vamp-sdk/ext/kiss_fftr.c"
+}
 
 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp)
 
@@ -110,30 +102,24 @@
     int m_stepSize;
     int m_blockSize;
     float **m_freqbuf;
-
-    double *m_ri;
+    float *m_ri;
 
     WindowType m_windowType;
-    Window<double> *m_window;
+    Window<float> *m_window;
 
     ProcessTimestampMethod m_method;
     int m_processCount;
     float **m_shiftBuffers;
 
-#ifdef HAVE_FFTW3
-    fftw_plan m_plan;
-    fftw_complex *m_cbuf;
-#else
-    double *m_ro;
-    double *m_io;
-#endif
+    KissSingle::kiss_fftr_cfg m_cfg;
+    KissSingle::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<double>::WindowType convertType(WindowType t) const;
+    Window<float>::WindowType convertType(WindowType t) const;
 };
 
 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
@@ -227,13 +213,8 @@
     m_method(ShiftTimestamp),
     m_processCount(0),
     m_shiftBuffers(0),
-#ifdef HAVE_FFTW3
-    m_plan(0),
+    m_cfg(0),
     m_cbuf(0)
-#else
-    m_ro(0),
-    m_io(0)
-#endif
 {
 }
 
@@ -253,19 +234,11 @@
             delete[] m_freqbuf[c];
         }
         delete[] m_freqbuf;
-#ifdef HAVE_FFTW3
-        if (m_plan) {
-            fftw_destroy_plan(m_plan);
-            fftw_free(m_ri);
-            fftw_free(m_cbuf);
-            m_plan = 0;
+        if (m_cfg) {
+            KissSingle::kiss_fftr_free(m_cfg);
+            delete[] m_cbuf;
+            m_cfg = 0;
         }
-#else
-        delete[] m_ri;
-        delete[] m_ro;
-        delete[] m_io;
-#endif
-
         delete m_window;
     }
 }
@@ -292,30 +265,21 @@
         return false;
     }                
         
-#ifndef HAVE_FFTW3
-    if (blockSize & (blockSize-1)) {
-        std::cerr << "ERROR: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
+    if (blockSize % 2) {
+        std::cerr << "ERROR: PluginInputDomainAdapter::initialise: odd blocksize " << blockSize << " not supported" << std::endl;
         return false;
     }
-#endif
 
     if (m_channels > 0) {
         for (int c = 0; c < m_channels; ++c) {
             delete[] m_freqbuf[c];
         }
         delete[] m_freqbuf;
-#ifdef HAVE_FFTW3
-        if (m_plan) {
-            fftw_destroy_plan(m_plan);
-            fftw_free(m_ri);
-            fftw_free(m_cbuf);
-            m_plan = 0;
+        if (m_cfg) {
+            KissSingle::kiss_fftr_free(m_cfg);
+            delete[] m_cbuf;
+            m_cfg = 0;
         }
-#else
-        delete[] m_ri;
-        delete[] m_ro;
-        delete[] m_io;
-#endif
         delete m_window;
     }
 
@@ -328,17 +292,10 @@
         m_freqbuf[c] = new float[m_blockSize + 2];
     }
 
-    m_window = new Window<double>(convertType(m_windowType), m_blockSize);
+    m_window = new Window<float>(convertType(m_windowType), m_blockSize);
 
-#ifdef HAVE_FFTW3
-    m_ri = (double *)fftw_malloc(blockSize * sizeof(double));
-    m_cbuf = (fftw_complex *)fftw_malloc((blockSize/2 + 1) * sizeof(fftw_complex));
-    m_plan = fftw_plan_dft_r2c_1d(int(blockSize), m_ri, m_cbuf, FFTW_MEASURE);
-#else
-    m_ri = new double[m_blockSize];
-    m_ro = new double[m_blockSize];
-    m_io = new double[m_blockSize];
-#endif
+    m_cfg = KissSingle::kiss_fftr_alloc(blockSize, false, 0, 0);
+    m_cbuf = new KissSingle::kiss_fft_cpx[blockSize/2+1];
 
     m_processCount = 0;
 
@@ -388,36 +345,12 @@
         std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
                   << "supported, increasing from " << blockSize << " to 2" << std::endl;
         blockSize = 2;
+
+    } else if (blockSize % 2) {
         
-    } else if (blockSize & (blockSize-1)) {
-            
-#ifdef HAVE_FFTW3
-        // not an issue with FFTW
-#else
-
-        // not a power of two, can't handle that with our built-in FFT
-        // implementation
-
-        size_t nearest = blockSize;
-        size_t power = 0;
-        while (nearest > 1) {
-            nearest >>= 1;
-            ++power;
-        }
-        nearest = 1;
-        while (power) {
-            nearest <<= 1;
-            --power;
-        }
-        
-        if (blockSize - nearest > (nearest*2) - blockSize) {
-            nearest = nearest*2;
-        }
-        
-        std::cerr << "WARNING: PluginInputDomainAdapter::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
-        blockSize = nearest;
-
-#endif
+        std::cerr << "WARNING: PluginInputDomainAdapter::initialise: odd blocksize not" << std::endl
+                  << "supported, increasing from " << blockSize << " to " << (blockSize+1) << std::endl;
+        blockSize = blockSize+1;
     }
 
     return blockSize;
@@ -455,7 +388,7 @@
     m_windowType = t;
     if (m_window) {
         delete m_window;
-        m_window = new Window<double>(convertType(m_windowType), m_blockSize);
+        m_window = new Window<float>(convertType(m_windowType), m_blockSize);
     }
 }
 
@@ -465,26 +398,26 @@
     return m_windowType;
 }
 
-Window<double>::WindowType
+Window<float>::WindowType
 PluginInputDomainAdapter::Impl::convertType(WindowType t) const
 {
     switch (t) {
     case RectangularWindow:
-        return Window<double>::RectangularWindow;
+        return Window<float>::RectangularWindow;
     case BartlettWindow:
-        return Window<double>::BartlettWindow;
+        return Window<float>::BartlettWindow;
     case HammingWindow:
-        return Window<double>::HammingWindow;
+        return Window<float>::HammingWindow;
     case HanningWindow:
-        return Window<double>::HanningWindow;
+        return Window<float>::HanningWindow;
     case BlackmanWindow:
-        return Window<double>::BlackmanWindow;
+        return Window<float>::BlackmanWindow;
     case NuttallWindow:
-        return Window<double>::NuttallWindow;
+        return Window<float>::NuttallWindow;
     case BlackmanHarrisWindow:
-        return Window<double>::BlackmanHarrisWindow;
+        return Window<float>::BlackmanHarrisWindow;
     default:
-	return Window<double>::HanningWindow;
+	return Window<float>::HanningWindow;
     }
 }
 
@@ -529,26 +462,17 @@
 
         for (int i = 0; i < m_blockSize/2; ++i) {
             // FFT shift
-            double value = m_ri[i];
+            float value = m_ri[i];
             m_ri[i] = m_ri[i + m_blockSize/2];
             m_ri[i + m_blockSize/2] = value;
         }
 
-#ifdef HAVE_FFTW3
-        fftw_execute(m_plan);
-
+        KissSingle::kiss_fftr(m_cfg, m_ri, m_cbuf);
+        
         for (int i = 0; i <= m_blockSize/2; ++i) {
-            m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
-            m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
+            m_freqbuf[c][i * 2] = m_cbuf[i].r;
+            m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i;
         }
-#else
-        fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
-
-        for (int i = 0; i <= m_blockSize/2; ++i) {
-            m_freqbuf[c][i * 2] = float(m_ro[i]);
-            m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
-        }
-#endif
     }
 
     return m_plugin->process(m_freqbuf, timestamp);
@@ -587,26 +511,17 @@
 
         for (int i = 0; i < m_blockSize/2; ++i) {
             // FFT shift
-            double value = m_ri[i];
+            float value = m_ri[i];
             m_ri[i] = m_ri[i + m_blockSize/2];
             m_ri[i + m_blockSize/2] = value;
         }
 
-#ifdef HAVE_FFTW3
-        fftw_execute(m_plan);
-
+        KissSingle::kiss_fftr(m_cfg, m_ri, m_cbuf);
+        
         for (int i = 0; i <= m_blockSize/2; ++i) {
-            m_freqbuf[c][i * 2] = float(m_cbuf[i][0]);
-            m_freqbuf[c][i * 2 + 1] = float(m_cbuf[i][1]);
+            m_freqbuf[c][i * 2] = m_cbuf[i].r;
+            m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i;
         }
-#else
-        fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
-
-        for (int i = 0; i <= m_blockSize/2; ++i) {
-            m_freqbuf[c][i * 2] = float(m_ro[i]);
-            m_freqbuf[c][i * 2 + 1] = float(m_io[i]);
-        }
-#endif
     }
 
     ++m_processCount;
@@ -614,10 +529,6 @@
     return m_plugin->process(m_freqbuf, timestamp);
 }
 
-#ifndef HAVE_FFTW3
-
-#endif
-
 }
         
 }