annotate plugins/SegmenterPlugin.cpp @ 38:9a2edd83775f

* Fixes and tidying in segmenter &c
author Chris Cannam <c.cannam@qmul.ac.uk>
date Thu, 10 Jan 2008 15:15:12 +0000
parents 9ce0db4770a2
children 7f499758cb23
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@36 37 string
c@36 38 SegmenterPlugin::getMaker() const
c@36 39 {
c@36 40 return "Mark Levy, Queen Mary, University of London";
c@36 41 }
c@36 42
c@36 43 int
c@36 44 SegmenterPlugin::getPluginVersion() const
c@36 45 {
c@36 46 return 2;
c@36 47 }
c@36 48
c@36 49 string
c@36 50 SegmenterPlugin::getCopyright() const
c@36 51 {
c@37 52 return "Copyright (c) 2006-2008 - All Rights Reserved";
c@36 53 }
c@36 54
c@36 55 bool
c@36 56 SegmenterPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
c@36 57 {
c@36 58 if (channels < getMinChannelCount() ||
c@36 59 channels > getMaxChannelCount()) return false;
c@36 60
c@36 61 if (!segmenter) makeSegmenter();
c@36 62
c@36 63 //!!! TODO: print out a helpful error message
c@36 64
c@36 65 if (stepSize != hopsize) return false;
c@36 66 if (blockSize != windowsize) return false;
c@36 67
c@36 68 return true;
c@36 69 }
c@36 70
c@36 71 void
c@36 72 SegmenterPlugin::reset()
c@36 73 {
c@38 74 //!!!
c@36 75 }
c@36 76
c@36 77 size_t
c@36 78 SegmenterPlugin::getPreferredStepSize() const
c@36 79 {
c@38 80 if (!segmenter) makeSegmenter();
c@38 81 return hopsize;
c@36 82 }
c@36 83
c@36 84 size_t
c@36 85 SegmenterPlugin::getPreferredBlockSize() const
c@36 86 {
c@38 87 if (!segmenter) makeSegmenter();
c@38 88 return windowsize;
c@36 89 }
c@36 90
c@36 91 SegmenterPlugin::ParameterList SegmenterPlugin::getParameterDescriptors() const
c@36 92 {
c@36 93 ParameterList list;
c@36 94
c@36 95 ParameterDescriptor desc;
c@36 96 desc.identifier = "nSegmentTypes";
c@36 97 desc.name = "Number of segment-types";
c@36 98 desc.description = "Maximum number of different kinds of segment to find";
c@36 99 desc.unit = "";
c@36 100 desc.minValue = 2;
c@36 101 desc.maxValue = 12;
c@36 102 desc.defaultValue = 10;
c@36 103 desc.isQuantized = true;
c@36 104 desc.quantizeStep = 1;
c@36 105 list.push_back(desc);
c@36 106
c@36 107 ParameterDescriptor desc2;
c@36 108 desc2.identifier = "featureType";
c@36 109 desc2.name = "Feature Type";
c@36 110 desc2.description = "Try Chroma for acoustic or pre-1980 recordings, otherwise use Constant-Q";
c@36 111 desc2.unit = "";
c@36 112 desc2.minValue = 1;
c@36 113 desc2.maxValue = 2;
c@36 114 desc2.defaultValue = 1;
c@36 115 desc2.isQuantized = true;
c@36 116 desc2.quantizeStep = 1;
c@36 117 desc2.valueNames.push_back("Constant-Q");
c@36 118 desc2.valueNames.push_back("Chroma");
c@36 119 list.push_back(desc2);
c@36 120
c@36 121 return list;
c@36 122 }
c@36 123
c@36 124 float
c@36 125 SegmenterPlugin::getParameter(std::string param) const
c@36 126 {
c@36 127 if (param == "nSegmentTypes") {
c@36 128 return nSegmentTypes;
c@36 129 }
c@36 130
c@38 131 if (param == "featureType") {
c@38 132 return featureType;
c@38 133 }
c@36 134
c@38 135 std::cerr << "WARNING: SegmenterPlugin::getParameter: unknown parameter \""
c@38 136 << param << "\"" << std::endl;
c@36 137 return 0.0;
c@36 138 }
c@36 139
c@36 140 void
c@36 141 SegmenterPlugin::setParameter(std::string param, float value)
c@36 142 {
c@36 143 if (param == "nSegmentTypes") {
c@38 144
c@36 145 nSegmentTypes = int(value);
c@38 146
c@38 147 } else {
c@38 148
c@38 149 if (param == "featureType") {
c@38 150 if (featureType != feature_types(value)) // feature type changed, create a new segmenter
c@38 151 {
c@38 152 featureType = feature_types(value);
c@38 153 makeSegmenter();
c@38 154 }
c@38 155 }
c@38 156 else
c@38 157 {
c@38 158 std::cerr << "WARNING: SegmenterPlugin::setParameter: unknown parameter \""
c@38 159 << param << "\"" << std::endl;
c@38 160 }
c@38 161 }
c@36 162 }
c@36 163
c@36 164 void
c@36 165 SegmenterPlugin::makeSegmenter() const
c@36 166 {
c@38 167 ClusterMeltSegmenterParams params = ClusterMeltSegmenterParams();
c@38 168 params.featureType = (feature_types) featureType;
c@38 169
c@38 170 if (params.featureType == FEATURE_TYPE_CONSTQ)
c@38 171 {
c@38 172 params.ncomponents = 20;
c@38 173 params.neighbourhoodLimit = 30;
c@38 174 }
c@38 175 if (params.featureType == FEATURE_TYPE_CHROMA)
c@38 176 {
c@38 177 params.hopSize = 0.1;
c@38 178 params.windowSize = 0.372;
c@38 179 params.nbins = 12;
c@38 180 params.histogramLength = 20;
c@38 181 params.neighbourhoodLimit = 40;
c@38 182 }
c@38 183 delete segmenter;
c@38 184
c@38 185 segmenter = new ClusterMeltSegmenter(params);
c@38 186 segmenter->initialise(m_inputSampleRate);
c@38 187 hopsize = segmenter->getHopsize();
c@38 188 windowsize = segmenter->getWindowsize();
c@38 189
c@38 190 std::cerr << "segmenter window size: " << segmenter->getWindowsize()
c@38 191 << std::endl;
c@36 192 }
c@36 193
c@36 194 SegmenterPlugin::OutputList
c@36 195 SegmenterPlugin::getOutputDescriptors() const
c@36 196 {
c@36 197 OutputList list;
c@36 198
c@38 199 OutputDescriptor segmentation;
c@38 200 segmentation.identifier = "segmentation";
c@36 201 segmentation.name = "Segmentation";
c@36 202 segmentation.description = "Segmentation";
c@36 203 segmentation.unit = "segment-type";
c@36 204 segmentation.hasFixedBinCount = true;
c@36 205 segmentation.binCount = 1;
c@38 206 segmentation.minValue = 1;
c@38 207 segmentation.maxValue = nSegmentTypes;
c@38 208 segmentation.isQuantized = true;
c@38 209 segmentation.quantizeStep = 1;
c@36 210 segmentation.sampleType = OutputDescriptor::VariableSampleRate;
c@36 211 segmentation.sampleRate = m_inputSampleRate / getPreferredStepSize();
c@36 212
c@36 213 list.push_back(segmentation);
c@36 214
c@38 215 return list;
c@36 216 }
c@36 217
c@36 218 SegmenterPlugin::FeatureSet
c@36 219 SegmenterPlugin::process(const float *const *inputBuffers, Vamp::RealTime /* timestamp */)
c@36 220 {
c@36 221 // convert float* to double*
c@36 222 double *tempBuffer = new double[windowsize];
c@36 223 for (size_t i = 0; i < windowsize; ++i) {
c@38 224 tempBuffer[i] = inputBuffers[0][i];
c@36 225 }
c@38 226
c@38 227 segmenter->extractFeatures(tempBuffer, segmenter->getWindowsize());
c@38 228
c@38 229 delete [] tempBuffer;
c@36 230
c@38 231 return FeatureSet();
c@36 232 }
c@36 233
c@36 234 SegmenterPlugin::FeatureSet
c@36 235 SegmenterPlugin::getRemainingFeatures()
c@36 236 {
c@36 237 segmenter->segment(nSegmentTypes);
c@38 238 Segmentation segm = segmenter->getSegmentation();
c@36 239
c@38 240 FeatureSet returnFeatures;
c@36 241
c@36 242 for (int i = 0; i < segm.segments.size(); ++i) {
c@36 243
c@38 244 Segment s = segm.segments[i];
c@36 245
c@38 246 Feature feature;
c@38 247 feature.hasTimestamp = true;
c@38 248 feature.timestamp = Vamp::RealTime::frame2RealTime(s.start, static_cast<unsigned int>(m_inputSampleRate));
c@36 249
c@38 250 vector<float> floatval;
c@38 251 floatval.push_back(s.type);
c@38 252 feature.values = floatval;
c@36 253
c@38 254 ostringstream oss;
c@38 255 oss << s.type;
c@38 256 feature.label = oss.str();
c@36 257
c@38 258 returnFeatures[0].push_back(feature);
c@36 259 }
c@36 260
c@36 261 return returnFeatures;
c@36 262 }