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