changeset 133:92ca8e401044

* PluginBufferingAdapter: Rewrite OneSamplePerStep to FixedSampleRate, not VariableSampleRate (so result is still dense); do not change FixedSampleRate to VariableSampleRate either; do not do the work of rewriting outputs that don't need to be rewritten
author cannam
date Thu, 20 Mar 2008 13:22:02 +0000
parents f5fff1c6f06d
children c1dce0b033cb
files vamp-sdk/hostext/PluginBufferingAdapter.cpp vamp-sdk/hostext/PluginBufferingAdapter.h
diffstat 2 files changed, 74 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/vamp-sdk/hostext/PluginBufferingAdapter.cpp	Thu Mar 20 13:16:04 2008 +0000
+++ b/vamp-sdk/hostext/PluginBufferingAdapter.cpp	Thu Mar 20 13:22:02 2008 +0000
@@ -229,7 +229,8 @@
     float m_inputSampleRate;
     RealTime m_timestamp;
     bool m_unrun;
-    OutputList m_outputs;
+    mutable OutputList m_outputs;
+    mutable std::map<int, bool> m_rewriteOutputTimes;
 		
     void processBlock(FeatureSet& allFeatureSets, RealTime timestamp);
 };
@@ -289,7 +290,7 @@
     m_timestamp(RealTime::zeroTime),
     m_unrun(true)
 {
-    m_outputs = plugin->getOutputDescriptors();
+    (void)getOutputDescriptors(); // set up m_outputs and m_rewriteOutputTimes
 }
 		
 PluginBufferingAdapter::Impl::~Impl()
@@ -365,13 +366,39 @@
 PluginBufferingAdapter::OutputList
 PluginBufferingAdapter::Impl::getOutputDescriptors() const
 {
-    OutputList outs = m_plugin->getOutputDescriptors();
+    if (m_outputs.empty()) {
+        m_outputs = m_plugin->getOutputDescriptors();
+    }
+
+    PluginBufferingAdapter::OutputList outs;
+
     for (size_t i = 0; i < outs.size(); ++i) {
-        if (outs[i].sampleType == OutputDescriptor::OneSamplePerStep) {
+
+        switch (outs[i].sampleType) {
+
+        case OutputDescriptor::OneSamplePerStep:
+            outs[i].sampleType = OutputDescriptor::FixedSampleRate;
             outs[i].sampleRate = 1.f / m_stepSize;
+            m_rewriteOutputTimes[i] = true;
+            break;
+            
+        case OutputDescriptor::FixedSampleRate:
+            if (outs[i].sampleRate == 0.f) {
+                outs[i].sampleRate = 1.f / m_stepSize;
+            }
+            // We actually only need to rewrite output times for
+            // features that don't have timestamps already, but we
+            // can't tell from here whether our features will have
+            // timestamps or not
+            m_rewriteOutputTimes[i] = true;
+            break;
+
+        case OutputDescriptor::VariableSampleRate:
+            m_rewriteOutputTimes[i] = false;
+            break;
         }
-        outs[i].sampleType = OutputDescriptor::VariableSampleRate;
     }
+
     return outs;
 }
 
@@ -463,35 +490,48 @@
 
     FeatureSet featureSet = m_plugin->process(m_buffers, m_timestamp);
     
-    for (map<int, FeatureList>::iterator iter = featureSet.begin();
+    for (FeatureSet::iterator iter = featureSet.begin();
          iter != featureSet.end(); ++iter) {
+
+        int outputNo = iter->first;
+
+        if (m_rewriteOutputTimes[outputNo]) {
+            
+            // Make sure the timestamp is always set
 	
-        FeatureList featureList = iter->second;
-        int outputNo = iter->first;
+            FeatureList featureList = iter->second;
 	
-        for (size_t i = 0; i < featureList.size(); ++i) {
+            for (size_t i = 0; i < featureList.size(); ++i) {
+
+                switch (m_outputs[outputNo].sampleType) {
+
+                case OutputDescriptor::OneSamplePerStep:
+                    // use our internal timestamp, always
+                    featureList[i].timestamp = m_timestamp;
+                    featureList[i].hasTimestamp = true;
+                    break;
+
+                case OutputDescriptor::FixedSampleRate:
+                    // use our internal timestamp if feature lacks one
+                    if (!featureList[i].hasTimestamp) {
+                        featureList[i].timestamp = m_timestamp;
+                        featureList[i].hasTimestamp = true;
+                    }
+                    break;
+
+                case OutputDescriptor::VariableSampleRate:
+                    break;		// plugin must set timestamp
+
+                default:
+                    break;
+                }
             
-            // make sure the timestamp is set
-            switch (m_outputs[outputNo].sampleType) {
-
-            case OutputDescriptor::OneSamplePerStep:
-		// use our internal timestamp - OK????
-                featureList[i].timestamp = m_timestamp;
-                break;
-
-            case OutputDescriptor::FixedSampleRate:
-		// use our internal timestamp
-                featureList[i].timestamp = m_timestamp;
-                break;
-
-            case OutputDescriptor::VariableSampleRate:
-                break;		// plugin must set timestamp
-
-            default:
-                break;
+                allFeatureSets[outputNo].push_back(featureList[i]);
             }
-            
-            allFeatureSets[outputNo].push_back(featureList[i]);		
+        } else {
+            for (size_t i = 0; i < iter->second.size(); ++i) {
+                allFeatureSets[outputNo].push_back(iter->second[i]);
+            }
         }
     }
     
--- a/vamp-sdk/hostext/PluginBufferingAdapter.h	Thu Mar 20 13:16:04 2008 +0000
+++ b/vamp-sdk/hostext/PluginBufferingAdapter.h	Thu Mar 20 13:22:02 2008 +0000
@@ -58,11 +58,11 @@
  * stepSize should be equal to the blockSize.
  *
  * If the internal step size used for the plugin differs from that
- * supplied by the host, the adapter will modify the sample rate
- * specifications for the plugin outputs (setting them all to
- * VariableSampleRate) and set timestamps on the output features for
- * outputs that formerly used a different sample rate specification.
- * This is necessary in order to obtain correct time stamping.
+ * supplied by the host, the adapter will modify the sample type and
+ * rate specifications for the plugin outputs appropriately, and set
+ * timestamps on the output features for outputs that formerly used a
+ * different sample rate specification.  This is necessary in order to
+ * obtain correct time stamping.
  * 
  * In other respects, the PluginBufferingAdapter behaves identically
  * to the plugin that it wraps. The wrapped plugin will be deleted