comparison runner/FeatureExtractionManager.cpp @ 109:78a7c77ba432

A more general solution (I hope) to the problem of making sure transforms are always run in a consistent order
author Chris Cannam
date Thu, 02 Oct 2014 14:54:09 +0100
parents fae326c22df5
children ca565b18ba3e 74f7ad72fee6
comparison
equal deleted inserted replaced
108:8b4924a9a072 109:78a7c77ba432
348 } else { 348 } else {
349 349
350 plugin = m_transformPluginMap[transform]; 350 plugin = m_transformPluginMap[transform];
351 } 351 }
352 352
353 if (m_plugins.find(plugin) == m_plugins.end()) {
354 m_orderedPlugins.push_back(plugin);
355 }
356
353 m_plugins[plugin][transform] = writers; 357 m_plugins[plugin][transform] = writers;
354 358
355 return true; 359 return true;
356 } 360 }
357 361
611 615
612 int earliestStartFrame = 0; 616 int earliestStartFrame = 0;
613 int latestEndFrame = frameCount; 617 int latestEndFrame = frameCount;
614 bool haveExtents = false; 618 bool haveExtents = false;
615 619
616 for (PluginMap::iterator pi = m_plugins.begin(); 620 foreach (Plugin *plugin, m_orderedPlugins) {
617 pi != m_plugins.end(); ++pi) { 621
618 622 PluginMap::iterator pi = m_plugins.find(plugin);
619 Plugin *plugin = pi->first; 623
620 624 std::cerr << "Calling reset on " << plugin << std::endl;
621 // std::cerr << "Calling reset on " << plugin << std::endl;
622 plugin->reset(); 625 plugin->reset();
623 626
624 for (TransformWriterMap::iterator ti = pi->second.begin(); 627 for (TransformWriterMap::iterator ti = pi->second.begin();
625 ti != pi->second.end(); ++ti) { 628 ti != pi->second.end(); ++ti) {
626 629
638 earliestStartFrame = startFrame; 641 earliestStartFrame = startFrame;
639 } 642 }
640 if (!haveExtents || startFrame + duration > latestEndFrame) { 643 if (!haveExtents || startFrame + duration > latestEndFrame) {
641 latestEndFrame = startFrame + duration; 644 latestEndFrame = startFrame + duration;
642 } 645 }
646
647 cerr << "startFrame for transform " << startFrame << endl;
648 cerr << "duration for transform " << duration << endl;
649 cerr << "earliestStartFrame becomes " << earliestStartFrame << endl;
650 cerr << "latestEndFrame becomes " << latestEndFrame << endl;
643 651
644 haveExtents = true; 652 haveExtents = true;
645 653
646 string outputId = transform.getOutput().toStdString(); 654 string outputId = transform.getOutput().toStdString();
647 if (m_pluginOutputs[plugin].find(outputId) == 655 if (m_pluginOutputs[plugin].find(outputId) ==
670 } 678 }
671 679
672 int startFrame = earliestStartFrame; 680 int startFrame = earliestStartFrame;
673 int endFrame = latestEndFrame; 681 int endFrame = latestEndFrame;
674 682
675 for (PluginMap::iterator pi = m_plugins.begin(); 683 foreach (Plugin *plugin, m_orderedPlugins) {
676 pi != m_plugins.end(); ++pi) { 684
685 PluginMap::iterator pi = m_plugins.find(plugin);
677 686
678 for (TransformWriterMap::const_iterator ti = pi->second.begin(); 687 for (TransformWriterMap::const_iterator ti = pi->second.begin();
679 ti != pi->second.end(); ++ti) { 688 ti != pi->second.end(); ++ti) {
680 689
681 const vector<FeatureWriter *> &writers = ti->second; 690 const vector<FeatureWriter *> &writers = ti->second;
743 } 752 }
744 753
745 Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime 754 Vamp::RealTime timestamp = Vamp::RealTime::frame2RealTime
746 (i, m_sampleRate); 755 (i, m_sampleRate);
747 756
748 for (PluginMap::iterator pi = m_plugins.begin(); 757 foreach (Plugin *plugin, m_orderedPlugins) {
749 pi != m_plugins.end(); ++pi) { 758
750 759 PluginMap::iterator pi = m_plugins.find(plugin);
751 Plugin *plugin = pi->first;
752 Plugin::FeatureSet featureSet = plugin->process(data, timestamp); 760 Plugin::FeatureSet featureSet = plugin->process(data, timestamp);
753 761
754 if (!m_summariesOnly) { 762 if (!m_summariesOnly) {
755 writeFeatures(audioSource, plugin, featureSet); 763 writeFeatures(audioSource, plugin, featureSet);
756 } 764 }
763 771
764 // std::cerr << "FeatureExtractionManager: deleting audio file reader" << std::endl; 772 // std::cerr << "FeatureExtractionManager: deleting audio file reader" << std::endl;
765 773
766 lifemgr.destroy(); // deletes reader, data 774 lifemgr.destroy(); // deletes reader, data
767 775
768 // In order to ensure our results are written to the output in a 776 foreach (Plugin *plugin, m_orderedPlugins) {
769 // fixed order (and not one that depends on the pointer value of 777
770 // each plugin on the heap in any given run of the program) we 778 PluginMap::iterator pi = m_plugins.find(plugin);
771 // take the plugins' entries from the plugin map and sort them
772 // into a new, temporary map that is indexed by the first
773 // transform for each plugin. We then iterate over than instead of
774 // over m_plugins in order to get the right ordering.
775
776 // This is not the most elegant way to do this -- it would be more
777 // elegant to impose an ordering directly on the plugins that are
778 // used as keys to m_plugins. But the plugin type comes from the
779 // Vamp SDK, so this change is more localised.
780
781 // Thanks to Matthias for this.
782
783 typedef map<Transform, PluginMap::value_type> OrderedPluginMap;
784 OrderedPluginMap orderedPlugins;
785
786 for (PluginMap::iterator pi = m_plugins.begin();
787 pi != m_plugins.end(); ++pi) {
788 Transform firstForPlugin = (pi->second).begin()->first;
789 orderedPlugins.insert(OrderedPluginMap::value_type(firstForPlugin, *pi));
790 }
791
792 for (OrderedPluginMap::iterator superPi = orderedPlugins.begin();
793 superPi != orderedPlugins.end(); ++superPi) {
794
795 // The value we extract from this map is just the same as the
796 // value_type we get from iterating over our PluginMap
797 // directly -- but we happen to get them in the right order
798 // now because the map iterator is ordered by the Transform
799 // key type ordering
800 PluginMap::value_type pi = superPi->second;
801
802 Plugin *plugin = pi.first;
803 Plugin::FeatureSet featureSet = plugin->getRemainingFeatures(); 779 Plugin::FeatureSet featureSet = plugin->getRemainingFeatures();
804 780
805 if (!m_summariesOnly) { 781 if (!m_summariesOnly) {
806 writeFeatures(audioSource, plugin, featureSet); 782 writeFeatures(audioSource, plugin, featureSet);
807 } 783 }
940 } 916 }
941 } 917 }
942 918
943 void FeatureExtractionManager::finish() 919 void FeatureExtractionManager::finish()
944 { 920 {
945 for (PluginMap::iterator pi = m_plugins.begin(); 921 foreach (Plugin *plugin, m_orderedPlugins) {
946 pi != m_plugins.end(); ++pi) { 922
923 PluginMap::iterator pi = m_plugins.find(plugin);
947 924
948 for (TransformWriterMap::iterator ti = pi->second.begin(); 925 for (TransformWriterMap::iterator ti = pi->second.begin();
949 ti != pi->second.end(); ++ti) { 926 ti != pi->second.end(); ++ti) {
950 927
951 vector<FeatureWriter *> &writers = ti->second; 928 vector<FeatureWriter *> &writers = ti->second;