diff plugins/SegmenterPlugin.cpp @ 36:5359ba489c0f

* Add segmenter plugin code (not built yet)
author Chris Cannam <c.cannam@qmul.ac.uk>
date Wed, 09 Jan 2008 10:39:43 +0000
parents
children 9ce0db4770a2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/SegmenterPlugin.cpp	Wed Jan 09 10:39:43 2008 +0000
@@ -0,0 +1,251 @@
+/*
+ *  SegmenterPlugin.cpp
+ *  soundbite
+ *
+ *  Created by Mark Levy on 24/03/2006.
+ *  Copyright 2006 Centre for Digital Music, Queen Mary, University of London. All rights reserved.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include "SegmenterPlugin.h"
+#include "ClusterMeltSegmenter.h"
+
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+using std::ostringstream;
+
+SegmenterPlugin::SegmenterPlugin(float inputSampleRate) :
+	Plugin(inputSampleRate), segmenter(0), nSegmentTypes(10), featureType(feature_types(1))
+{
+	
+}
+
+SegmenterPlugin::~SegmenterPlugin()
+{
+	if (segmenter)
+		delete segmenter;
+}
+
+string
+SegmenterPlugin::getMaker() const
+{
+    return "Mark Levy, Queen Mary, University of London";
+}
+
+int
+SegmenterPlugin::getPluginVersion() const
+{
+    return 2;
+}
+
+string
+SegmenterPlugin::getCopyright() const
+{
+    return "All rights reserved";
+}
+
+bool
+SegmenterPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+    if (channels < getMinChannelCount() ||
+	channels > getMaxChannelCount()) return false;
+
+    if (!segmenter) makeSegmenter();
+
+    //!!! TODO: print out a helpful error message
+    
+    if (stepSize != hopsize) return false;
+    if (blockSize != windowsize) return false;
+		
+    return true;
+}
+
+void
+SegmenterPlugin::reset()
+{
+}
+
+size_t
+SegmenterPlugin::getPreferredStepSize() const
+{
+	if (!segmenter) makeSegmenter();
+	return hopsize;
+}
+
+size_t
+SegmenterPlugin::getPreferredBlockSize() const
+{
+	if (!segmenter) makeSegmenter();
+	return windowsize;
+}
+
+SegmenterPlugin::ParameterList SegmenterPlugin::getParameterDescriptors() const
+{
+    ParameterList list;
+	
+    ParameterDescriptor desc;
+    desc.identifier = "nSegmentTypes";
+    desc.name = "Number of segment-types";
+    desc.description = "Maximum number of different kinds of segment to find";
+    desc.unit = "";
+    desc.minValue = 2;
+    desc.maxValue = 12;
+    desc.defaultValue = 10;
+    desc.isQuantized = true;
+    desc.quantizeStep = 1;
+    list.push_back(desc);
+	
+    ParameterDescriptor desc2;
+    desc2.identifier = "featureType";
+    desc2.name = "Feature Type";
+    desc2.description = "Try Chroma for acoustic or pre-1980 recordings, otherwise use Constant-Q";
+    desc2.unit = "";
+    desc2.minValue = 1;
+    desc2.maxValue = 2;
+    desc2.defaultValue = 1;
+    desc2.isQuantized = true;
+    desc2.quantizeStep = 1;
+    desc2.valueNames.push_back("Constant-Q");
+    desc2.valueNames.push_back("Chroma");
+    list.push_back(desc2);	
+	
+    return list;
+}
+
+float
+SegmenterPlugin::getParameter(std::string param) const
+{
+    if (param == "nSegmentTypes") {
+        return nSegmentTypes;
+    }
+	
+	if (param == "featureType") {
+		return featureType;
+	}
+    
+	std::cerr << "WARNING: SegmenterPlugin::getParameter: unknown parameter \""
+	<< param << "\"" << std::endl;
+    return 0.0;
+}
+
+void
+SegmenterPlugin::setParameter(std::string param, float value)
+{
+    if (param == "nSegmentTypes") {
+        nSegmentTypes = int(value);
+    } else 
+	{
+		if (param == "featureType") {
+			if (featureType != feature_types(value))	// feature type changed, create a new segmenter
+			{
+				featureType = feature_types(value);
+				makeSegmenter();
+			}
+		}
+		else
+		{
+			std::cerr << "WARNING: SegmenterPlugin::setParameter: unknown parameter \""
+			<< param << "\"" << std::endl;
+		}
+	}
+}
+
+void
+SegmenterPlugin::makeSegmenter() const
+{
+	ClusterMeltSegmenterParams params = ClusterMeltSegmenterParams();
+	params.featureType = (feature_types) featureType;
+	if (params.featureType == FEATURE_TYPE_CONSTQ)
+	{
+		params.ncomponents = 20;
+		params.neighbourhoodLimit = 30;					
+	}
+	if (params.featureType == FEATURE_TYPE_CHROMA)
+	{
+		params.hopSize = 0.1;
+		params.windowSize = 0.372;
+		params.nbins = 12;
+		params.histogramLength = 20;
+		params.neighbourhoodLimit = 40;
+	}
+	delete segmenter;
+	segmenter = new ClusterMeltSegmenter(params);
+	segmenter->initialise(static_cast<int>(m_inputSampleRate));
+	hopsize = segmenter->getHopsize();
+	windowsize = segmenter->getWindowsize();
+}
+
+SegmenterPlugin::OutputList
+SegmenterPlugin::getOutputDescriptors() const
+{
+    OutputList list;
+	
+	OutputDescriptor segmentation;
+	segmentation.identifier = "segmentation";
+    segmentation.name = "Segmentation";
+    segmentation.description = "Segmentation";
+    segmentation.unit = "segment-type";
+    segmentation.hasFixedBinCount = true;
+    segmentation.binCount = 1;
+	segmentation.minValue = 1;
+	segmentation.maxValue = nSegmentTypes;
+	segmentation.isQuantized = true;
+	segmentation.quantizeStep = 1;
+    segmentation.sampleType = OutputDescriptor::VariableSampleRate;
+    segmentation.sampleRate = m_inputSampleRate / getPreferredStepSize();
+	
+    list.push_back(segmentation);
+    
+	return list;
+}
+
+SegmenterPlugin::FeatureSet
+SegmenterPlugin::process(const float *const *inputBuffers, Vamp::RealTime /* timestamp */)
+{
+    // convert float* to double*
+    double *tempBuffer = new double[windowsize];
+    for (size_t i = 0; i < windowsize; ++i) {
+		tempBuffer[i] = inputBuffers[0][i];
+    }
+	
+    segmenter->extractFeatures(tempBuffer, windowsize);
+	
+	delete [] tempBuffer;
+	
+	return FeatureSet();
+}
+
+SegmenterPlugin::FeatureSet
+SegmenterPlugin::getRemainingFeatures()
+{
+    segmenter->segment(nSegmentTypes);
+	Segmentation segm = segmenter->getSegmentation();
+	
+	FeatureSet returnFeatures;
+	
+    for (int i = 0; i < segm.segments.size(); ++i) {
+		
+		Segment s = segm.segments[i];
+		
+		Feature feature;
+		feature.hasTimestamp = true;
+		feature.timestamp = Vamp::RealTime::frame2RealTime(s.start, static_cast<unsigned int>(m_inputSampleRate));
+		
+		vector<float> floatval;
+		floatval.push_back(s.type);
+		feature.values = floatval;
+		
+		ostringstream oss;
+		oss << s.type;
+		feature.label = oss.str();
+		
+		returnFeatures[0].push_back(feature);
+    }
+	
+    return returnFeatures;
+}