changeset 288:283e15f6e548

* The beginnings of making the shift-timestamp or shift-data behaviour of PluginInputDomainAdapter into an option
author cannam
date Tue, 15 Sep 2009 16:24:53 +0000
parents f3b1ba71a305
children 3e5ab1c7ea8c
files src/vamp-hostsdk/PluginInputDomainAdapter.cpp vamp-hostsdk/PluginInputDomainAdapter.h
diffstat 2 files changed, 135 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/vamp-hostsdk/PluginInputDomainAdapter.cpp	Thu Sep 10 15:21:34 2009 +0000
+++ b/src/vamp-hostsdk/PluginInputDomainAdapter.cpp	Tue Sep 15 16:24:53 2009 +0000
@@ -83,11 +83,15 @@
     ~Impl();
     
     bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void reset();
 
     size_t getPreferredStepSize() const;
     size_t getPreferredBlockSize() const;
 
     FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+    void setProcessTimestampMethod(ProcessTimestampMethod m);
+    ProcessTimestampMethod getProcessTimestampMethod() const;
     
     RealTime getTimestampAdjustment() const;
 
@@ -95,12 +99,18 @@
     Plugin *m_plugin;
     float m_inputSampleRate;
     int m_channels;
+    int m_stepSize;
     int m_blockSize;
     float **m_freqbuf;
 
     double *m_ri;
     double *m_window;
 
+    ProcessTimestampMethod m_method;
+    int m_processCount;
+    FeatureSet prepadProcess(const float *const *inputBuffers,
+                             RealTime timestamp);
+
 #ifdef HAVE_FFTW3
     fftw_plan m_plan;
     fftw_complex *m_cbuf;
@@ -131,6 +141,12 @@
     return m_impl->initialise(channels, stepSize, blockSize);
 }
 
+void
+PluginInputDomainAdapter::reset()
+{
+    m_impl->reset();
+}
+
 Plugin::InputDomain
 PluginInputDomainAdapter::getInputDomain() const
 {
@@ -155,6 +171,18 @@
     return m_impl->process(inputBuffers, timestamp);
 }
 
+void
+PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
+{
+    m_impl->setProcessTimestampMethod(m);
+}
+
+PluginInputDomainAdapter::ProcessTimestampMethod
+PluginInputDomainAdapter::getProcessTimestampMethod() const
+{
+    return m_impl->getProcessTimestampMethod();
+}
+
 RealTime
 PluginInputDomainAdapter::getTimestampAdjustment() const
 {
@@ -166,10 +194,13 @@
     m_plugin(plugin),
     m_inputSampleRate(inputSampleRate),
     m_channels(0),
+    m_stepSize(0),
     m_blockSize(0),
     m_freqbuf(0),
     m_ri(0),
     m_window(0),
+    m_method(ShiftTimestamp),
+    m_processCount(0),
 #ifdef HAVE_FFTW3
     m_plan(0),
     m_cbuf(0)
@@ -215,6 +246,7 @@
 {
     if (m_plugin->getInputDomain() == TimeDomain) {
 
+        m_stepSize = int(stepSize);
         m_blockSize = int(blockSize);
         m_channels = int(channels);
 
@@ -251,6 +283,7 @@
         delete[] m_window;
     }
 
+    m_stepSize = int(stepSize);
     m_blockSize = int(blockSize);
     m_channels = int(channels);
 
@@ -275,9 +308,18 @@
     m_io = new double[m_blockSize];
 #endif
 
+    m_processCount = 0;
+
     return m_plugin->initialise(channels, stepSize, blockSize);
 }
 
+void
+PluginInputDomainAdapter::Impl::reset()
+{
+    m_processCount = 0;
+    m_plugin->reset();
+}
+
 size_t
 PluginInputDomainAdapter::Impl::getPreferredStepSize() const
 {
@@ -360,6 +402,18 @@
     }
 }
 
+void
+PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
+{
+    m_method = m;
+}
+
+PluginInputDomainAdapter::ProcessTimestampMethod
+PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
+{
+    return m_method;
+}
+
 Plugin::FeatureSet
 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
                                         RealTime timestamp)
@@ -412,7 +466,15 @@
 
 //    std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp;
 
-    timestamp = timestamp + getTimestampAdjustment();
+    //!!! update the above comment for ProcessTimestampMethod
+
+    FeatureSet fs;
+    if (m_method == ShiftTimestamp) {
+        timestamp = timestamp + getTimestampAdjustment();
+    } else if (m_processCount == 0) {
+        fs = prepadProcess(inputBuffers, timestamp);
+    }
+    ++m_processCount;
 
 //    std::cerr << " to " << timestamp << std::endl;
 
@@ -450,7 +512,28 @@
 #endif
     }
 
-    return m_plugin->process(m_freqbuf, timestamp);
+    FeatureSet pfs(m_plugin->process(m_freqbuf, timestamp));
+
+    if (!fs.empty()) { // add any prepad results back in
+        for (FeatureSet::const_iterator i = pfs.begin(); i != pfs.end(); ++i) {
+            for (FeatureList::const_iterator j = i->second.begin();
+                 j != i->second.end(); ++j) {
+                fs[i->first].push_back(*j);
+            }
+        }
+        pfs = fs;
+    }
+
+    return pfs;
+}
+
+Plugin::FeatureSet
+PluginInputDomainAdapter::Impl::prepadProcess(const float *const *inputBuffers,
+                                              RealTime timestamp)
+{
+    FeatureSet fs;
+    //!!!
+    return fs;
 }
 
 #ifndef HAVE_FFTW3
--- a/vamp-hostsdk/PluginInputDomainAdapter.h	Thu Sep 10 15:21:34 2009 +0000
+++ b/vamp-hostsdk/PluginInputDomainAdapter.h	Tue Sep 15 16:24:53 2009 +0000
@@ -91,6 +91,7 @@
     virtual ~PluginInputDomainAdapter();
     
     bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+    void reset();
 
     InputDomain getInputDomain() const;
 
@@ -100,6 +101,48 @@
     FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
 
     /**
+     * ProcessTimestampMethod determines how the
+     * PluginInputDomainAdapter handles timestamps for the data passed
+     * to the process() function of the plugin it wraps, in the case
+     * where the plugin is expecting frequency-domain data.
+     *
+     *
+     * The Vamp API mandates that the timestamp passed to the plugin
+     * for time-domain input should be the time of the first sample in
+     * the block, but the timestamp passed for frequency-domain input
+     * should be the timestamp of the centre of the block.
+     *
+     * Since we claim to permit the code that uses this plugin wrapper
+     * not to care whether the plugin itself has time or frequency
+     * domain input, that means that we need to ensure this timestamp
+     * is correctly adjusted ourselves, and the way we handle this is
+     * controlled by the ProcessTimestampMethod.
+     *
+     * If ProcessTimestampMethod is ShiftTimestamp (the default), then
+     * the data passed to the wrapped plugin will be calculated from
+     * the same input data block as passed to the wrapper, but the
+     * timestamp passed to the plugin will be advanced by half of the
+     * window size.
+     * 
+     * If ProcessTimestampMethod is ShiftData, then the timestamp
+     * passed to the wrapped plugin will be the same as that passed to
+     * the process call of the wrapper, but the data block used to
+     * calculate the input will be shifted back (earlier) by half of
+     * the window size, with half a block of padding at the start of
+     * the first process call.
+     *
+     * This function must be called before the first call to
+     * process().
+     */
+    enum ProcessTimestampMethod {
+        ShiftTimestamp,
+        ShiftData
+    };
+
+    void setProcessTimestampMethod(ProcessTimestampMethod);
+    ProcessTimestampMethod getProcessTimestampMethod() const;
+
+    /**
      * Return the amount by which the timestamps supplied to process()
      * are being incremented when they are passed to the plugin's own
      * process() implementation.
@@ -116,9 +159,13 @@
      * timestamps) the host may need to be aware that this adjustment
      * is taking place.
      *
-     * If the plugin requires time-domain input, this function will
-     * return zero.  The result of calling this function before
-     * initialise() has been called is undefined.
+     * If the plugin requires time-domain input or the
+     * PluginInputDomainAdapter is configured with its
+     * ProcessTimestampMethod set to ShiftData instead of
+     * ShiftTimestamp, then this function will return zero.
+     *
+     * The result of calling this function before initialise() has
+     * been called is undefined.
      */
     RealTime getTimestampAdjustment() const;