annotate plugins/SegmenterPlugin.cpp @ 45:5d7ce1d87301

* Add MFCC plugin * Add means output to Chromagram plugin * Update similarity plugin for MFCC changes
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 18 Jan 2008 13:30:56 +0000
parents 0f85778f1b53
children fc88b465548a
rev   line source
c@38 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@38 2
c@36 3 /*
c@38 4 * SegmenterPlugin.cpp
c@36 5 *
c@38 6 * Created by Mark Levy on 24/03/2006.
c@38 7 * Copyright 2006 Centre for Digital Music, Queen Mary, University of London.
c@38 8 * All rights reserved.
c@36 9 */
c@36 10
c@36 11 #include <iostream>
c@36 12 #include <sstream>
c@36 13
c@36 14 #include "SegmenterPlugin.h"
c@37 15 #include "dsp/segmentation/ClusterMeltSegmenter.h"
c@36 16
c@36 17 using std::string;
c@36 18 using std::vector;
c@36 19 using std::cerr;
c@36 20 using std::endl;
c@36 21 using std::ostringstream;
c@36 22
c@36 23 SegmenterPlugin::SegmenterPlugin(float inputSampleRate) :
c@38 24 Plugin(inputSampleRate),
c@38 25 segmenter(0),
c@38 26 nSegmentTypes(10),
c@38 27 featureType(feature_types(1))
c@36 28 {
c@36 29
c@36 30 }
c@36 31
c@36 32 SegmenterPlugin::~SegmenterPlugin()
c@36 33 {
c@38 34 delete segmenter;
c@36 35 }
c@36 36
c@45 37 std::string SegmenterPlugin::getIdentifier() const
c@45 38 {
c@45 39 return "qm-segmenter";
c@45 40 }
c@45 41
c@45 42 std::string SegmenterPlugin::getName() const
c@45 43 {
c@45 44 return "Segmenter";
c@45 45 }
c@45 46
c@45 47 std::string SegmenterPlugin::getDescription() const
c@45 48 {
c@45 49 return "Divide the track into a sequence of consistent segments";
c@45 50 }
c@45 51
c@36 52 string
c@36 53 SegmenterPlugin::getMaker() const
c@36 54 {
c@36 55 return "Mark Levy, Queen Mary, University of London";
c@36 56 }
c@36 57
c@36 58 int
c@36 59 SegmenterPlugin::getPluginVersion() const
c@36 60 {
c@36 61 return 2;
c@36 62 }
c@36 63
c@36 64 string
c@36 65 SegmenterPlugin::getCopyright() const
c@36 66 {
c@37 67 return "Copyright (c) 2006-2008 - All Rights Reserved";
c@36 68 }
c@36 69
c@36 70 bool
c@36 71 SegmenterPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
c@36 72 {
c@36 73 if (channels < getMinChannelCount() ||
c@36 74 channels > getMaxChannelCount()) return false;
c@36 75
c@36 76 if (!segmenter) makeSegmenter();
c@36 77
c@39 78 if (stepSize != hopsize) {
c@39 79 std::cerr << "SegmenterPlugin::initialise: supplied step size "
c@39 80 << stepSize << " differs from required step size " << hopsize
c@39 81 << std::endl;
c@39 82 return false;
c@39 83 }
c@39 84
c@39 85 if (blockSize != windowsize) {
c@39 86 std::cerr << "SegmenterPlugin::initialise: supplied block size "
c@39 87 << blockSize << " differs from required block size " << windowsize
c@39 88 << std::endl;
c@39 89 return false;
c@39 90 }
c@36 91
c@36 92 return true;
c@36 93 }
c@36 94
c@36 95 void
c@36 96 SegmenterPlugin::reset()
c@36 97 {
c@38 98 //!!!
c@36 99 }
c@36 100
c@36 101 size_t
c@36 102 SegmenterPlugin::getPreferredStepSize() const
c@36 103 {
c@38 104 if (!segmenter) makeSegmenter();
c@38 105 return hopsize;
c@36 106 }
c@36 107
c@36 108 size_t
c@36 109 SegmenterPlugin::getPreferredBlockSize() const
c@36 110 {
c@38 111 if (!segmenter) makeSegmenter();
c@38 112 return windowsize;
c@36 113 }
c@36 114
c@36 115 SegmenterPlugin::ParameterList SegmenterPlugin::getParameterDescriptors() const
c@36 116 {
c@36 117 ParameterList list;
c@36 118
c@36 119 ParameterDescriptor desc;
c@36 120 desc.identifier = "nSegmentTypes";
c@36 121 desc.name = "Number of segment-types";
c@36 122 desc.description = "Maximum number of different kinds of segment to find";
c@36 123 desc.unit = "";
c@36 124 desc.minValue = 2;
c@36 125 desc.maxValue = 12;
c@36 126 desc.defaultValue = 10;
c@36 127 desc.isQuantized = true;
c@36 128 desc.quantizeStep = 1;
c@36 129 list.push_back(desc);
c@36 130
c@36 131 ParameterDescriptor desc2;
c@36 132 desc2.identifier = "featureType";
c@36 133 desc2.name = "Feature Type";
c@39 134 desc2.description = "Try Chromatic for acoustic or pre-1980 recordings, otherwise use Hybrid";
c@36 135 desc2.unit = "";
c@36 136 desc2.minValue = 1;
c@39 137 desc2.maxValue = 3;
c@36 138 desc2.defaultValue = 1;
c@36 139 desc2.isQuantized = true;
c@36 140 desc2.quantizeStep = 1;
c@39 141 desc2.valueNames.push_back("Hybrid (Constant-Q)");
c@39 142 desc2.valueNames.push_back("Chromatic (Chroma)");
c@39 143 desc2.valueNames.push_back("Timbral (MFCC)");
c@36 144 list.push_back(desc2);
c@36 145
c@36 146 return list;
c@36 147 }
c@36 148
c@36 149 float
c@36 150 SegmenterPlugin::getParameter(std::string param) const
c@36 151 {
c@36 152 if (param == "nSegmentTypes") {
c@36 153 return nSegmentTypes;
c@36 154 }
c@36 155
c@38 156 if (param == "featureType") {
c@38 157 return featureType;
c@38 158 }
c@36 159
c@38 160 std::cerr << "WARNING: SegmenterPlugin::getParameter: unknown parameter \""
c@38 161 << param << "\"" << std::endl;
c@36 162 return 0.0;
c@36 163 }
c@36 164
c@36 165 void
c@36 166 SegmenterPlugin::setParameter(std::string param, float value)
c@36 167 {
c@36 168 if (param == "nSegmentTypes") {
c@38 169
c@42 170 nSegmentTypes = int(value + 0.0001);
c@38 171
c@38 172 } else {
c@38 173
c@38 174 if (param == "featureType") {
c@38 175 if (featureType != feature_types(value)) // feature type changed, create a new segmenter
c@38 176 {
c@38 177 featureType = feature_types(value);
c@38 178 makeSegmenter();
c@38 179 }
c@38 180 }
c@38 181 else
c@38 182 {
c@38 183 std::cerr << "WARNING: SegmenterPlugin::setParameter: unknown parameter \""
c@38 184 << param << "\"" << std::endl;
c@38 185 }
c@38 186 }
c@36 187 }
c@36 188
c@36 189 void
c@36 190 SegmenterPlugin::makeSegmenter() const
c@36 191 {
c@38 192 ClusterMeltSegmenterParams params = ClusterMeltSegmenterParams();
c@38 193 params.featureType = (feature_types) featureType;
c@38 194
c@38 195 if (params.featureType == FEATURE_TYPE_CONSTQ)
c@38 196 {
c@38 197 params.ncomponents = 20;
c@38 198 params.neighbourhoodLimit = 30;
c@38 199 }
c@38 200 if (params.featureType == FEATURE_TYPE_CHROMA)
c@38 201 {
c@38 202 params.hopSize = 0.1;
c@38 203 params.windowSize = 0.372;
c@38 204 params.nbins = 12;
c@38 205 params.histogramLength = 20;
c@38 206 params.neighbourhoodLimit = 40;
c@38 207 }
c@39 208 if (params.featureType == FEATURE_TYPE_MFCC)
c@39 209 {
c@39 210 params.ncomponents = 20;
c@39 211 params.neighbourhoodLimit = 30;
c@39 212 }
c@38 213 delete segmenter;
c@38 214
c@38 215 segmenter = new ClusterMeltSegmenter(params);
c@38 216 segmenter->initialise(m_inputSampleRate);
c@38 217 hopsize = segmenter->getHopsize();
c@38 218 windowsize = segmenter->getWindowsize();
c@38 219
c@45 220 // std::cerr << "segmenter window size: " << segmenter->getWindowsize()
c@45 221 // << std::endl;
c@36 222 }
c@36 223
c@36 224 SegmenterPlugin::OutputList
c@36 225 SegmenterPlugin::getOutputDescriptors() const
c@36 226 {
c@36 227 OutputList list;
c@36 228
c@38 229 OutputDescriptor segmentation;
c@38 230 segmentation.identifier = "segmentation";
c@36 231 segmentation.name = "Segmentation";
c@36 232 segmentation.description = "Segmentation";
c@36 233 segmentation.unit = "segment-type";
c@36 234 segmentation.hasFixedBinCount = true;
c@36 235 segmentation.binCount = 1;
c@40 236 segmentation.hasKnownExtents = true;
c@38 237 segmentation.minValue = 1;
c@38 238 segmentation.maxValue = nSegmentTypes;
c@38 239 segmentation.isQuantized = true;
c@38 240 segmentation.quantizeStep = 1;
c@36 241 segmentation.sampleType = OutputDescriptor::VariableSampleRate;
c@36 242 segmentation.sampleRate = m_inputSampleRate / getPreferredStepSize();
c@36 243
c@36 244 list.push_back(segmentation);
c@36 245
c@38 246 return list;
c@36 247 }
c@36 248
c@36 249 SegmenterPlugin::FeatureSet
c@36 250 SegmenterPlugin::process(const float *const *inputBuffers, Vamp::RealTime /* timestamp */)
c@36 251 {
c@36 252 // convert float* to double*
c@36 253 double *tempBuffer = new double[windowsize];
c@36 254 for (size_t i = 0; i < windowsize; ++i) {
c@38 255 tempBuffer[i] = inputBuffers[0][i];
c@36 256 }
c@38 257
c@38 258 segmenter->extractFeatures(tempBuffer, segmenter->getWindowsize());
c@38 259
c@38 260 delete [] tempBuffer;
c@36 261
c@38 262 return FeatureSet();
c@36 263 }
c@36 264
c@36 265 SegmenterPlugin::FeatureSet
c@36 266 SegmenterPlugin::getRemainingFeatures()
c@36 267 {
c@36 268 segmenter->segment(nSegmentTypes);
c@38 269 Segmentation segm = segmenter->getSegmentation();
c@36 270
c@38 271 FeatureSet returnFeatures;
c@36 272
c@36 273 for (int i = 0; i < segm.segments.size(); ++i) {
c@36 274
c@38 275 Segment s = segm.segments[i];
c@36 276
c@38 277 Feature feature;
c@38 278 feature.hasTimestamp = true;
c@38 279 feature.timestamp = Vamp::RealTime::frame2RealTime(s.start, static_cast<unsigned int>(m_inputSampleRate));
c@36 280
c@38 281 vector<float> floatval;
c@38 282 floatval.push_back(s.type);
c@38 283 feature.values = floatval;
c@36 284
c@38 285 ostringstream oss;
c@38 286 oss << s.type;
c@38 287 feature.label = oss.str();
c@36 288
c@38 289 returnFeatures[0].push_back(feature);
c@36 290 }
c@36 291
c@36 292 return returnFeatures;
c@36 293 }