annotate sv/transform/FeatureExtractionPluginTransform.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents fc9323a41f5a
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam and QMUL.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include "FeatureExtractionPluginTransform.h"
lbajardsilogic@0 17
lbajardsilogic@0 18 #include "plugin/FeatureExtractionPluginFactory.h"
lbajardsilogic@0 19 #include "plugin/PluginXml.h"
lbajardsilogic@0 20 #include "vamp-sdk/Plugin.h"
lbajardsilogic@0 21
lbajardsilogic@0 22 #include "data/model/Model.h"
lbajardsilogic@0 23 #include "base/Window.h"
lbajardsilogic@0 24 #include "data/model/SparseOneDimensionalModel.h"
lbajardsilogic@0 25 #include "data/model/SparseTimeValueModel.h"
lbajardsilogic@0 26 #include "data/model/EditableDenseThreeDimensionalModel.h"
lbajardsilogic@0 27 #include "data/model/DenseTimeValueModel.h"
lbajardsilogic@0 28 #include "data/model/NoteModel.h"
lbajardsilogic@0 29 #include "data/model/FFTModel.h"
lbajardsilogic@0 30 #include "data/model/WaveFileModel.h"
lbajardsilogic@0 31
lbajardsilogic@0 32 #include <QMessageBox>
lbajardsilogic@0 33
lbajardsilogic@0 34 #include <iostream>
lbajardsilogic@0 35
lbajardsilogic@0 36 FeatureExtractionPluginTransform::FeatureExtractionPluginTransform(Model *inputModel,
lbajardsilogic@0 37 QString pluginId,
lbajardsilogic@0 38 const ExecutionContext &context,
lbajardsilogic@0 39 QString configurationXml,
lbajardsilogic@0 40 QString outputName) :
lbajardsilogic@0 41 PluginTransform(inputModel, context),
lbajardsilogic@0 42 m_plugin(0),
lbajardsilogic@0 43 m_descriptor(0),
lbajardsilogic@0 44 m_outputFeatureNo(0)
lbajardsilogic@0 45 {
lbajardsilogic@0 46 // std::cerr << "FeatureExtractionPluginTransform::FeatureExtractionPluginTransform: plugin " << pluginId.toStdString() << ", outputName " << outputName.toStdString() << std::endl;
lbajardsilogic@0 47
lbajardsilogic@0 48 FeatureExtractionPluginFactory *factory =
lbajardsilogic@0 49 FeatureExtractionPluginFactory::instanceFor(pluginId);
lbajardsilogic@0 50
lbajardsilogic@0 51 if (!factory) {
lbajardsilogic@0 52 std::cerr << "FeatureExtractionPluginTransform: No factory available for plugin id \""
lbajardsilogic@0 53 << pluginId.toStdString() << "\"" << std::endl;
lbajardsilogic@0 54 return;
lbajardsilogic@0 55 }
lbajardsilogic@0 56
lbajardsilogic@0 57 m_plugin = factory->instantiatePlugin(pluginId, m_input->getSampleRate());
lbajardsilogic@0 58
lbajardsilogic@0 59 if (!m_plugin) {
lbajardsilogic@0 60 std::cerr << "FeatureExtractionPluginTransform: Failed to instantiate plugin \""
lbajardsilogic@0 61 << pluginId.toStdString() << "\"" << std::endl;
lbajardsilogic@0 62 return;
lbajardsilogic@0 63 }
lbajardsilogic@0 64
lbajardsilogic@0 65 if (configurationXml != "") {
lbajardsilogic@0 66 PluginXml(m_plugin).setParametersFromXml(configurationXml);
lbajardsilogic@0 67 }
lbajardsilogic@0 68
lbajardsilogic@0 69 DenseTimeValueModel *input = getInput();
lbajardsilogic@0 70 if (!input) return;
lbajardsilogic@0 71
lbajardsilogic@0 72 size_t channelCount = input->getChannelCount();
lbajardsilogic@0 73 if (m_plugin->getMaxChannelCount() < channelCount) {
lbajardsilogic@0 74 channelCount = 1;
lbajardsilogic@0 75 }
lbajardsilogic@0 76 if (m_plugin->getMinChannelCount() > channelCount) {
lbajardsilogic@0 77 std::cerr << "FeatureExtractionPluginTransform:: "
lbajardsilogic@0 78 << "Can't provide enough channels to plugin (plugin min "
lbajardsilogic@0 79 << m_plugin->getMinChannelCount() << ", max "
lbajardsilogic@0 80 << m_plugin->getMaxChannelCount() << ", input model has "
lbajardsilogic@0 81 << input->getChannelCount() << ")" << std::endl;
lbajardsilogic@0 82 return;
lbajardsilogic@0 83 }
lbajardsilogic@0 84
lbajardsilogic@0 85 std::cerr << "Initialising feature extraction plugin with channels = "
lbajardsilogic@0 86 << channelCount << ", step = " << m_context.stepSize
lbajardsilogic@0 87 << ", block = " << m_context.blockSize << std::endl;
lbajardsilogic@0 88
lbajardsilogic@0 89 if (!m_plugin->initialise(channelCount,
lbajardsilogic@0 90 m_context.stepSize,
lbajardsilogic@0 91 m_context.blockSize)) {
lbajardsilogic@0 92 std::cerr << "FeatureExtractionPluginTransform: Plugin "
lbajardsilogic@0 93 << m_plugin->getIdentifier() << " failed to initialise!" << std::endl;
lbajardsilogic@0 94 return;
lbajardsilogic@0 95 }
lbajardsilogic@0 96
lbajardsilogic@0 97 Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors();
lbajardsilogic@0 98
lbajardsilogic@0 99 if (outputs.empty()) {
lbajardsilogic@0 100 std::cerr << "FeatureExtractionPluginTransform: Plugin \""
lbajardsilogic@0 101 << pluginId.toStdString() << "\" has no outputs" << std::endl;
lbajardsilogic@0 102 return;
lbajardsilogic@0 103 }
lbajardsilogic@0 104
lbajardsilogic@0 105 for (size_t i = 0; i < outputs.size(); ++i) {
lbajardsilogic@0 106 if (outputName == "" || outputs[i].identifier == outputName.toStdString()) {
lbajardsilogic@0 107 m_outputFeatureNo = i;
lbajardsilogic@0 108 m_descriptor = new Vamp::Plugin::OutputDescriptor
lbajardsilogic@0 109 (outputs[i]);
lbajardsilogic@0 110 break;
lbajardsilogic@0 111 }
lbajardsilogic@0 112 }
lbajardsilogic@0 113
lbajardsilogic@0 114 if (!m_descriptor) {
lbajardsilogic@0 115 std::cerr << "FeatureExtractionPluginTransform: Plugin \""
lbajardsilogic@0 116 << pluginId.toStdString() << "\" has no output named \""
lbajardsilogic@0 117 << outputName.toStdString() << "\"" << std::endl;
lbajardsilogic@0 118 return;
lbajardsilogic@0 119 }
lbajardsilogic@0 120
lbajardsilogic@0 121 // std::cerr << "FeatureExtractionPluginTransform: output sample type "
lbajardsilogic@0 122 // << m_descriptor->sampleType << std::endl;
lbajardsilogic@0 123
lbajardsilogic@0 124 int binCount = 1;
lbajardsilogic@0 125 float minValue = 0.0, maxValue = 0.0;
lbajardsilogic@0 126 bool haveExtents = false;
lbajardsilogic@0 127
lbajardsilogic@0 128 if (m_descriptor->hasFixedBinCount) {
lbajardsilogic@0 129 binCount = m_descriptor->binCount;
lbajardsilogic@0 130 }
lbajardsilogic@0 131
lbajardsilogic@0 132 // std::cerr << "FeatureExtractionPluginTransform: output bin count "
lbajardsilogic@0 133 // << binCount << std::endl;
lbajardsilogic@0 134
lbajardsilogic@0 135 if (binCount > 0 && m_descriptor->hasKnownExtents) {
lbajardsilogic@0 136 minValue = m_descriptor->minValue;
lbajardsilogic@0 137 maxValue = m_descriptor->maxValue;
lbajardsilogic@0 138 haveExtents = true;
lbajardsilogic@0 139 }
lbajardsilogic@0 140
lbajardsilogic@0 141 size_t modelRate = m_input->getSampleRate();
lbajardsilogic@0 142 size_t modelResolution = 1;
lbajardsilogic@0 143
lbajardsilogic@0 144 switch (m_descriptor->sampleType) {
lbajardsilogic@0 145
lbajardsilogic@0 146 case Vamp::Plugin::OutputDescriptor::VariableSampleRate:
lbajardsilogic@0 147 if (m_descriptor->sampleRate != 0.0) {
lbajardsilogic@0 148 modelResolution = size_t(modelRate / m_descriptor->sampleRate + 0.001);
lbajardsilogic@0 149 }
lbajardsilogic@0 150 break;
lbajardsilogic@0 151
lbajardsilogic@0 152 case Vamp::Plugin::OutputDescriptor::OneSamplePerStep:
lbajardsilogic@0 153 modelResolution = m_context.stepSize;
lbajardsilogic@0 154 break;
lbajardsilogic@0 155
lbajardsilogic@0 156 case Vamp::Plugin::OutputDescriptor::FixedSampleRate:
lbajardsilogic@0 157 modelRate = size_t(m_descriptor->sampleRate + 0.001);
lbajardsilogic@0 158 break;
lbajardsilogic@0 159 }
lbajardsilogic@0 160
lbajardsilogic@0 161 if (binCount == 0) {
lbajardsilogic@0 162
lbajardsilogic@0 163 m_output = new SparseOneDimensionalModel(modelRate, modelResolution,
lbajardsilogic@0 164 false);
lbajardsilogic@0 165
lbajardsilogic@0 166 } else if (binCount == 1) {
lbajardsilogic@0 167
lbajardsilogic@0 168 SparseTimeValueModel *model;
lbajardsilogic@0 169 if (haveExtents) {
lbajardsilogic@0 170 model = new SparseTimeValueModel
lbajardsilogic@0 171 (modelRate, modelResolution, minValue, maxValue, false);
lbajardsilogic@0 172 } else {
lbajardsilogic@0 173 model = new SparseTimeValueModel
lbajardsilogic@0 174 (modelRate, modelResolution, false);
lbajardsilogic@0 175 }
lbajardsilogic@0 176 model->setScaleUnits(outputs[m_outputFeatureNo].unit.c_str());
lbajardsilogic@0 177
lbajardsilogic@0 178 m_output = model;
lbajardsilogic@0 179
lbajardsilogic@0 180 } else if (m_descriptor->sampleType ==
lbajardsilogic@0 181 Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
lbajardsilogic@0 182
lbajardsilogic@0 183 // We don't have a sparse 3D model, so interpret this as a
lbajardsilogic@0 184 // note model. There's nothing to define which values to use
lbajardsilogic@0 185 // as which parameters of the note -- for the moment let's
lbajardsilogic@0 186 // treat the first as pitch, second as duration in frames,
lbajardsilogic@0 187 // third (if present) as velocity. (Our note model doesn't
lbajardsilogic@0 188 // yet store velocity.)
lbajardsilogic@0 189 //!!! todo: ask the user!
lbajardsilogic@0 190
lbajardsilogic@0 191 NoteModel *model;
lbajardsilogic@0 192 if (haveExtents) {
lbajardsilogic@0 193 model = new NoteModel
lbajardsilogic@0 194 (modelRate, modelResolution, minValue, maxValue, false);
lbajardsilogic@0 195 } else {
lbajardsilogic@0 196 model = new NoteModel
lbajardsilogic@0 197 (modelRate, modelResolution, false);
lbajardsilogic@0 198 }
lbajardsilogic@0 199 model->setScaleUnits(outputs[m_outputFeatureNo].unit.c_str());
lbajardsilogic@0 200
lbajardsilogic@0 201 m_output = model;
lbajardsilogic@0 202
lbajardsilogic@0 203 } else {
lbajardsilogic@0 204
lbajardsilogic@0 205 EditableDenseThreeDimensionalModel *model =
lbajardsilogic@0 206 new EditableDenseThreeDimensionalModel
lbajardsilogic@0 207 (modelRate, modelResolution, binCount, false);
lbajardsilogic@0 208
lbajardsilogic@0 209 if (!m_descriptor->binNames.empty()) {
lbajardsilogic@0 210 std::vector<QString> names;
lbajardsilogic@0 211 for (size_t i = 0; i < m_descriptor->binNames.size(); ++i) {
lbajardsilogic@0 212 names.push_back(m_descriptor->binNames[i].c_str());
lbajardsilogic@0 213 }
lbajardsilogic@0 214 model->setBinNames(names);
lbajardsilogic@0 215 }
lbajardsilogic@0 216
lbajardsilogic@0 217 m_output = model;
lbajardsilogic@0 218 }
lbajardsilogic@0 219 }
lbajardsilogic@0 220
lbajardsilogic@0 221 FeatureExtractionPluginTransform::~FeatureExtractionPluginTransform()
lbajardsilogic@0 222 {
lbajardsilogic@0 223 delete m_plugin;
lbajardsilogic@0 224 delete m_descriptor;
lbajardsilogic@0 225 }
lbajardsilogic@0 226
lbajardsilogic@0 227 DenseTimeValueModel *
lbajardsilogic@0 228 FeatureExtractionPluginTransform::getInput()
lbajardsilogic@0 229 {
lbajardsilogic@0 230 DenseTimeValueModel *dtvm =
lbajardsilogic@0 231 dynamic_cast<DenseTimeValueModel *>(getInputModel());
lbajardsilogic@0 232 if (!dtvm) {
lbajardsilogic@0 233 std::cerr << "FeatureExtractionPluginTransform::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
lbajardsilogic@0 234 }
lbajardsilogic@0 235 return dtvm;
lbajardsilogic@0 236 }
lbajardsilogic@0 237
lbajardsilogic@0 238 void
lbajardsilogic@0 239 FeatureExtractionPluginTransform::run()
lbajardsilogic@0 240 {
lbajardsilogic@0 241 DenseTimeValueModel *input = getInput();
lbajardsilogic@0 242 if (!input) return;
lbajardsilogic@0 243
lbajardsilogic@0 244 while (!input->isReady()) {
lbajardsilogic@0 245 if (dynamic_cast<WaveFileModel *>(input)) break; // no need to wait
lbajardsilogic@0 246 std::cerr << "FeatureExtractionPluginTransform::run: Waiting for input model to be ready..." << std::endl;
lbajardsilogic@0 247 sleep(1);
lbajardsilogic@0 248 }
lbajardsilogic@0 249
lbajardsilogic@0 250 if (!m_output) return;
lbajardsilogic@0 251
lbajardsilogic@0 252 size_t sampleRate = m_input->getSampleRate();
lbajardsilogic@0 253
lbajardsilogic@0 254 size_t channelCount = input->getChannelCount();
lbajardsilogic@0 255 if (m_plugin->getMaxChannelCount() < channelCount) {
lbajardsilogic@0 256 channelCount = 1;
lbajardsilogic@0 257 }
lbajardsilogic@0 258
lbajardsilogic@0 259 float **buffers = new float*[channelCount];
lbajardsilogic@0 260 for (size_t ch = 0; ch < channelCount; ++ch) {
lbajardsilogic@0 261 buffers[ch] = new float[m_context.blockSize + 2];
lbajardsilogic@0 262 }
lbajardsilogic@0 263
lbajardsilogic@0 264 bool frequencyDomain = (m_plugin->getInputDomain() ==
lbajardsilogic@0 265 Vamp::Plugin::FrequencyDomain);
lbajardsilogic@0 266 std::vector<FFTModel *> fftModels;
lbajardsilogic@0 267
lbajardsilogic@0 268 if (frequencyDomain) {
lbajardsilogic@0 269 for (size_t ch = 0; ch < channelCount; ++ch) {
lbajardsilogic@0 270 FFTModel *model = new FFTModel
lbajardsilogic@0 271 (getInput(),
lbajardsilogic@0 272 channelCount == 1 ? m_context.channel : ch,
lbajardsilogic@0 273 m_context.windowType,
lbajardsilogic@0 274 m_context.blockSize,
lbajardsilogic@0 275 m_context.stepSize,
lbajardsilogic@0 276 m_context.blockSize,
lbajardsilogic@0 277 false);
lbajardsilogic@0 278 if (!model->isOK()) {
lbajardsilogic@0 279 QMessageBox::critical
lbajardsilogic@0 280 (0, tr("FFT cache failed"),
lbajardsilogic@0 281 tr("Failed to create the FFT model for this transform.\n"
lbajardsilogic@0 282 "There may be insufficient memory or disc space to continue."));
lbajardsilogic@0 283 delete model;
lbajardsilogic@0 284 setCompletion(100);
lbajardsilogic@0 285 return;
lbajardsilogic@0 286 }
lbajardsilogic@0 287 model->resume();
lbajardsilogic@0 288 fftModels.push_back(model);
lbajardsilogic@0 289 }
lbajardsilogic@0 290 }
lbajardsilogic@0 291
lbajardsilogic@0 292 long startFrame = m_input->getStartFrame();
lbajardsilogic@0 293 long endFrame = m_input->getEndFrame();
lbajardsilogic@0 294 long blockFrame = startFrame;
lbajardsilogic@0 295
lbajardsilogic@0 296 long prevCompletion = 0;
lbajardsilogic@0 297
lbajardsilogic@0 298 while (!m_abandoned) {
lbajardsilogic@0 299
lbajardsilogic@0 300 if (frequencyDomain) {
lbajardsilogic@0 301 if (blockFrame - int(m_context.blockSize)/2 > endFrame) break;
lbajardsilogic@0 302 } else {
lbajardsilogic@0 303 if (blockFrame >= endFrame) break;
lbajardsilogic@0 304 }
lbajardsilogic@0 305
lbajardsilogic@0 306 // std::cerr << "FeatureExtractionPluginTransform::run: blockFrame "
lbajardsilogic@0 307 // << blockFrame << std::endl;
lbajardsilogic@0 308
lbajardsilogic@0 309 long completion =
lbajardsilogic@0 310 (((blockFrame - startFrame) / m_context.stepSize) * 99) /
lbajardsilogic@0 311 ( (endFrame - startFrame) / m_context.stepSize);
lbajardsilogic@0 312
lbajardsilogic@0 313 // channelCount is either m_input->channelCount or 1
lbajardsilogic@0 314
lbajardsilogic@0 315 for (size_t ch = 0; ch < channelCount; ++ch) {
lbajardsilogic@0 316 if (frequencyDomain) {
lbajardsilogic@0 317 int column = (blockFrame - startFrame) / m_context.stepSize;
lbajardsilogic@0 318 for (size_t i = 0; i <= m_context.blockSize/2; ++i) {
lbajardsilogic@0 319 fftModels[ch]->getValuesAt
lbajardsilogic@0 320 (column, i, buffers[ch][i*2], buffers[ch][i*2+1]);
lbajardsilogic@0 321 }
lbajardsilogic@0 322 } else {
lbajardsilogic@0 323 getFrames(ch, channelCount,
lbajardsilogic@0 324 blockFrame, m_context.blockSize, buffers[ch]);
lbajardsilogic@0 325 }
lbajardsilogic@0 326 }
lbajardsilogic@0 327
lbajardsilogic@0 328 Vamp::Plugin::FeatureSet features = m_plugin->process
lbajardsilogic@0 329 (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
lbajardsilogic@0 330
lbajardsilogic@0 331 for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) {
lbajardsilogic@0 332 Vamp::Plugin::Feature feature =
lbajardsilogic@0 333 features[m_outputFeatureNo][fi];
lbajardsilogic@0 334 addFeature(blockFrame, feature);
lbajardsilogic@0 335 }
lbajardsilogic@0 336
lbajardsilogic@0 337 if (blockFrame == startFrame || completion > prevCompletion) {
lbajardsilogic@0 338 setCompletion(completion);
lbajardsilogic@0 339 prevCompletion = completion;
lbajardsilogic@0 340 }
lbajardsilogic@0 341
lbajardsilogic@0 342 blockFrame += m_context.stepSize;
lbajardsilogic@0 343 }
lbajardsilogic@0 344
lbajardsilogic@0 345 if (m_abandoned) return;
lbajardsilogic@0 346
lbajardsilogic@0 347 Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures();
lbajardsilogic@0 348
lbajardsilogic@0 349 for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) {
lbajardsilogic@0 350 Vamp::Plugin::Feature feature =
lbajardsilogic@0 351 features[m_outputFeatureNo][fi];
lbajardsilogic@0 352 addFeature(blockFrame, feature);
lbajardsilogic@0 353 }
lbajardsilogic@0 354
lbajardsilogic@0 355 if (frequencyDomain) {
lbajardsilogic@0 356 for (size_t ch = 0; ch < channelCount; ++ch) {
lbajardsilogic@0 357 delete fftModels[ch];
lbajardsilogic@0 358 }
lbajardsilogic@0 359 }
lbajardsilogic@0 360
lbajardsilogic@0 361 setCompletion(100);
lbajardsilogic@0 362 }
lbajardsilogic@0 363
lbajardsilogic@0 364 void
lbajardsilogic@0 365 FeatureExtractionPluginTransform::getFrames(int channel, int channelCount,
lbajardsilogic@0 366 long startFrame, long size,
lbajardsilogic@0 367 float *buffer)
lbajardsilogic@0 368 {
lbajardsilogic@0 369 long offset = 0;
lbajardsilogic@0 370
lbajardsilogic@0 371 if (startFrame < 0) {
lbajardsilogic@0 372 for (int i = 0; i < size && startFrame + i < 0; ++i) {
lbajardsilogic@0 373 buffer[i] = 0.0f;
lbajardsilogic@0 374 }
lbajardsilogic@0 375 offset = -startFrame;
lbajardsilogic@0 376 size -= offset;
lbajardsilogic@0 377 if (size <= 0) return;
lbajardsilogic@0 378 startFrame = 0;
lbajardsilogic@0 379 }
lbajardsilogic@0 380
lbajardsilogic@0 381 long got = getInput()->getValues
lbajardsilogic@0 382 ((channelCount == 1 ? m_context.channel : channel),
lbajardsilogic@0 383 startFrame, startFrame + size, buffer + offset);
lbajardsilogic@0 384
lbajardsilogic@0 385 while (got < size) {
lbajardsilogic@0 386 buffer[offset + got] = 0.0;
lbajardsilogic@0 387 ++got;
lbajardsilogic@0 388 }
lbajardsilogic@0 389
lbajardsilogic@0 390 if (m_context.channel == -1 && channelCount == 1 &&
lbajardsilogic@0 391 getInput()->getChannelCount() > 1) {
lbajardsilogic@0 392 // use mean instead of sum, as plugin input
lbajardsilogic@0 393 int cc = getInput()->getChannelCount();
lbajardsilogic@0 394 for (long i = 0; i < size; ++i) {
lbajardsilogic@0 395 buffer[i] /= cc;
lbajardsilogic@0 396 }
lbajardsilogic@0 397 }
lbajardsilogic@0 398 }
lbajardsilogic@0 399
lbajardsilogic@0 400 void
lbajardsilogic@0 401 FeatureExtractionPluginTransform::addFeature(size_t blockFrame,
lbajardsilogic@0 402 const Vamp::Plugin::Feature &feature)
lbajardsilogic@0 403 {
lbajardsilogic@0 404 size_t inputRate = m_input->getSampleRate();
lbajardsilogic@0 405
lbajardsilogic@0 406 // std::cerr << "FeatureExtractionPluginTransform::addFeature("
lbajardsilogic@0 407 // << blockFrame << ")" << std::endl;
lbajardsilogic@0 408
lbajardsilogic@0 409 int binCount = 1;
lbajardsilogic@0 410 if (m_descriptor->hasFixedBinCount) {
lbajardsilogic@0 411 binCount = m_descriptor->binCount;
lbajardsilogic@0 412 }
lbajardsilogic@0 413
lbajardsilogic@0 414 size_t frame = blockFrame;
lbajardsilogic@0 415
lbajardsilogic@0 416 if (m_descriptor->sampleType ==
lbajardsilogic@0 417 Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
lbajardsilogic@0 418
lbajardsilogic@0 419 if (!feature.hasTimestamp) {
lbajardsilogic@0 420 std::cerr
lbajardsilogic@0 421 << "WARNING: FeatureExtractionPluginTransform::addFeature: "
lbajardsilogic@0 422 << "Feature has variable sample rate but no timestamp!"
lbajardsilogic@0 423 << std::endl;
lbajardsilogic@0 424 return;
lbajardsilogic@0 425 } else {
lbajardsilogic@0 426 frame = Vamp::RealTime::realTime2Frame(feature.timestamp, inputRate);
lbajardsilogic@0 427 }
lbajardsilogic@0 428
lbajardsilogic@0 429 } else if (m_descriptor->sampleType ==
lbajardsilogic@0 430 Vamp::Plugin::OutputDescriptor::FixedSampleRate) {
lbajardsilogic@0 431
lbajardsilogic@0 432 if (feature.hasTimestamp) {
lbajardsilogic@0 433 //!!! warning: sampleRate may be non-integral
lbajardsilogic@0 434 frame = Vamp::RealTime::realTime2Frame(feature.timestamp,
lbajardsilogic@0 435 lrintf(m_descriptor->sampleRate));
lbajardsilogic@0 436 } else {
lbajardsilogic@0 437 frame = m_output->getEndFrame();
lbajardsilogic@0 438 }
lbajardsilogic@0 439 }
lbajardsilogic@0 440
lbajardsilogic@0 441 if (binCount == 0) {
lbajardsilogic@0 442
lbajardsilogic@0 443 SparseOneDimensionalModel *model = getOutput<SparseOneDimensionalModel>();
lbajardsilogic@0 444 if (!model) return;
lbajardsilogic@0 445 model->addPoint(SparseOneDimensionalModel::Point(frame, feature.label.c_str()));
lbajardsilogic@0 446
lbajardsilogic@0 447 } else if (binCount == 1) {
lbajardsilogic@0 448
lbajardsilogic@0 449 float value = 0.0;
lbajardsilogic@0 450 if (feature.values.size() > 0) value = feature.values[0];
lbajardsilogic@0 451
lbajardsilogic@0 452 SparseTimeValueModel *model = getOutput<SparseTimeValueModel>();
lbajardsilogic@0 453 if (!model) return;
lbajardsilogic@0 454 model->addPoint(SparseTimeValueModel::Point(frame, value, feature.label.c_str()));
lbajardsilogic@0 455
lbajardsilogic@0 456 } else if (m_descriptor->sampleType ==
lbajardsilogic@0 457 Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
lbajardsilogic@0 458
lbajardsilogic@0 459 float pitch = 0.0;
lbajardsilogic@0 460 if (feature.values.size() > 0) pitch = feature.values[0];
lbajardsilogic@0 461
lbajardsilogic@0 462 float duration = 1;
lbajardsilogic@0 463 if (feature.values.size() > 1) duration = feature.values[1];
lbajardsilogic@0 464
lbajardsilogic@0 465 float velocity = 100;
lbajardsilogic@0 466 if (feature.values.size() > 2) velocity = feature.values[2];
lbajardsilogic@0 467
lbajardsilogic@0 468 NoteModel *model = getOutput<NoteModel>();
lbajardsilogic@0 469 if (!model) return;
lbajardsilogic@0 470
lbajardsilogic@0 471 model->addPoint(NoteModel::Point(frame, pitch,
lbajardsilogic@0 472 lrintf(duration),
lbajardsilogic@0 473 feature.label.c_str()));
lbajardsilogic@0 474
lbajardsilogic@0 475 } else {
lbajardsilogic@0 476
lbajardsilogic@0 477 DenseThreeDimensionalModel::Column values = feature.values;
lbajardsilogic@0 478
lbajardsilogic@0 479 EditableDenseThreeDimensionalModel *model =
lbajardsilogic@0 480 getOutput<EditableDenseThreeDimensionalModel>();
lbajardsilogic@0 481 if (!model) return;
lbajardsilogic@0 482
lbajardsilogic@0 483 model->setColumn(frame / model->getResolution(), values);
lbajardsilogic@0 484 }
lbajardsilogic@0 485 }
lbajardsilogic@0 486
lbajardsilogic@0 487 void
lbajardsilogic@0 488 FeatureExtractionPluginTransform::setCompletion(int completion)
lbajardsilogic@0 489 {
lbajardsilogic@0 490 int binCount = 1;
lbajardsilogic@0 491 if (m_descriptor->hasFixedBinCount) {
lbajardsilogic@0 492 binCount = m_descriptor->binCount;
lbajardsilogic@0 493 }
lbajardsilogic@0 494
lbajardsilogic@0 495 std::cerr << "FeatureExtractionPluginTransform::setCompletion("
lbajardsilogic@0 496 << completion << ")" << std::endl;
lbajardsilogic@0 497
lbajardsilogic@0 498 if (binCount == 0) {
lbajardsilogic@0 499
lbajardsilogic@0 500 SparseOneDimensionalModel *model = getOutput<SparseOneDimensionalModel>();
lbajardsilogic@0 501 if (!model) return;
lbajardsilogic@0 502 model->setCompletion(completion);
lbajardsilogic@0 503
lbajardsilogic@0 504 } else if (binCount == 1) {
lbajardsilogic@0 505
lbajardsilogic@0 506 SparseTimeValueModel *model = getOutput<SparseTimeValueModel>();
lbajardsilogic@0 507 if (!model) return;
lbajardsilogic@0 508 model->setCompletion(completion);
lbajardsilogic@0 509
lbajardsilogic@0 510 } else if (m_descriptor->sampleType ==
lbajardsilogic@0 511 Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
lbajardsilogic@0 512
lbajardsilogic@0 513 NoteModel *model = getOutput<NoteModel>();
lbajardsilogic@0 514 if (!model) return;
lbajardsilogic@0 515 model->setCompletion(completion);
lbajardsilogic@0 516
lbajardsilogic@0 517 } else {
lbajardsilogic@0 518
lbajardsilogic@0 519 EditableDenseThreeDimensionalModel *model =
lbajardsilogic@0 520 getOutput<EditableDenseThreeDimensionalModel>();
lbajardsilogic@0 521 if (!model) return;
lbajardsilogic@0 522 model->setCompletion(completion);
lbajardsilogic@0 523 }
lbajardsilogic@0 524 }
lbajardsilogic@0 525