comparison plugin/transform/FeatureExtractionModelTransformer.cpp @ 384:6f6ab834449d spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents aa8dbac62024
children
comparison
equal deleted inserted replaced
337:a6fab10ff9e6 384:6f6ab834449d
27 #include "data/model/DenseTimeValueModel.h" 27 #include "data/model/DenseTimeValueModel.h"
28 #include "data/model/NoteModel.h" 28 #include "data/model/NoteModel.h"
29 #include "data/model/FFTModel.h" 29 #include "data/model/FFTModel.h"
30 #include "data/model/WaveFileModel.h" 30 #include "data/model/WaveFileModel.h"
31 31
32 #include "TransformFactory.h"
33
32 #include <QMessageBox> 34 #include <QMessageBox>
33 35
34 #include <iostream> 36 #include <iostream>
35 37
36 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Model *inputModel, 38 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in,
37 QString pluginId, 39 const Transform &transform) :
38 const ExecutionContext &context, 40 ModelTransformer(in, transform),
39 QString configurationXml,
40 QString outputName) :
41 PluginTransformer(inputModel, context),
42 m_plugin(0), 41 m_plugin(0),
43 m_descriptor(0), 42 m_descriptor(0),
44 m_outputFeatureNo(0) 43 m_outputFeatureNo(0)
45 { 44 {
46 // std::cerr << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId.toStdString() << ", outputName " << outputName.toStdString() << std::endl; 45 // std::cerr << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId.toStdString() << ", outputName " << m_transform.getOutput().toStdString() << std::endl;
46
47 QString pluginId = transform.getPluginIdentifier();
47 48
48 FeatureExtractionPluginFactory *factory = 49 FeatureExtractionPluginFactory *factory =
49 FeatureExtractionPluginFactory::instanceFor(pluginId); 50 FeatureExtractionPluginFactory::instanceFor(pluginId);
50 51
51 if (!factory) { 52 if (!factory) {
52 std::cerr << "FeatureExtractionModelTransformer: No factory available for plugin id \"" 53 m_message = tr("No factory available for feature extraction plugin id \"%1\" (unknown plugin type, or internal error?)").arg(pluginId);
53 << pluginId.toStdString() << "\"" << std::endl;
54 return; 54 return;
55 } 55 }
56 56
57 m_plugin = factory->instantiatePlugin(pluginId, m_input->getSampleRate()); 57 DenseTimeValueModel *input = getConformingInput();
58 58 if (!input) {
59 m_message = tr("Input model for feature extraction plugin \"%1\" is of wrong type (internal error?)").arg(pluginId);
60 return;
61 }
62
63 m_plugin = factory->instantiatePlugin(pluginId, input->getSampleRate());
59 if (!m_plugin) { 64 if (!m_plugin) {
60 std::cerr << "FeatureExtractionModelTransformer: Failed to instantiate plugin \"" 65 m_message = tr("Failed to instantiate plugin \"%1\"").arg(pluginId);
61 << pluginId.toStdString() << "\"" << std::endl;
62 return; 66 return;
63 } 67 }
64 68
65 if (configurationXml != "") { 69 TransformFactory::getInstance()->makeContextConsistentWithPlugin
66 PluginXml(m_plugin).setParametersFromXml(configurationXml); 70 (m_transform, m_plugin);
67 } 71
68 72 TransformFactory::getInstance()->setPluginParameters
69 DenseTimeValueModel *input = getInput(); 73 (m_transform, m_plugin);
70 if (!input) return;
71 74
72 size_t channelCount = input->getChannelCount(); 75 size_t channelCount = input->getChannelCount();
73 if (m_plugin->getMaxChannelCount() < channelCount) { 76 if (m_plugin->getMaxChannelCount() < channelCount) {
74 channelCount = 1; 77 channelCount = 1;
75 } 78 }
76 if (m_plugin->getMinChannelCount() > channelCount) { 79 if (m_plugin->getMinChannelCount() > channelCount) {
77 std::cerr << "FeatureExtractionModelTransformer:: " 80 m_message = tr("Cannot provide enough channels to feature extraction plugin \"%1\" (plugin min is %2, max %3; input model has %4)")
78 << "Can't provide enough channels to plugin (plugin min " 81 .arg(pluginId)
79 << m_plugin->getMinChannelCount() << ", max " 82 .arg(m_plugin->getMinChannelCount())
80 << m_plugin->getMaxChannelCount() << ", input model has " 83 .arg(m_plugin->getMaxChannelCount())
81 << input->getChannelCount() << ")" << std::endl; 84 .arg(input->getChannelCount());
82 return; 85 return;
83 } 86 }
84 87
85 std::cerr << "Initialising feature extraction plugin with channels = " 88 std::cerr << "Initialising feature extraction plugin with channels = "
86 << channelCount << ", step = " << m_context.stepSize 89 << channelCount << ", step = " << m_transform.getStepSize()
87 << ", block = " << m_context.blockSize << std::endl; 90 << ", block = " << m_transform.getBlockSize() << std::endl;
88 91
89 if (!m_plugin->initialise(channelCount, 92 if (!m_plugin->initialise(channelCount,
90 m_context.stepSize, 93 m_transform.getStepSize(),
91 m_context.blockSize)) { 94 m_transform.getBlockSize())) {
92 std::cerr << "FeatureExtractionModelTransformer: Plugin " 95
93 << m_plugin->getIdentifier() << " failed to initialise!" << std::endl; 96 size_t pstep = m_transform.getStepSize();
94 return; 97 size_t pblock = m_transform.getBlockSize();
98
99 m_transform.setStepSize(0);
100 m_transform.setBlockSize(0);
101 TransformFactory::getInstance()->makeContextConsistentWithPlugin
102 (m_transform, m_plugin);
103
104 if (m_transform.getStepSize() != pstep ||
105 m_transform.getBlockSize() != pblock) {
106
107 if (!m_plugin->initialise(channelCount,
108 m_transform.getStepSize(),
109 m_transform.getBlockSize())) {
110
111 m_message = tr("Failed to initialise feature extraction plugin \"%1\"").arg(pluginId);
112 return;
113
114 } else {
115
116 m_message = tr("Feature extraction plugin \"%1\" rejected the given step and block sizes (%2 and %3); using plugin defaults (%4 and %5) instead")
117 .arg(pluginId)
118 .arg(pstep)
119 .arg(pblock)
120 .arg(m_transform.getStepSize())
121 .arg(m_transform.getBlockSize());
122 }
123
124 } else {
125
126 m_message = tr("Failed to initialise feature extraction plugin \"%1\"").arg(pluginId);
127 return;
128 }
129 }
130
131 if (m_transform.getPluginVersion() != "") {
132 QString pv = QString("%1").arg(m_plugin->getPluginVersion());
133 if (pv != m_transform.getPluginVersion()) {
134 QString vm = tr("Transform was configured for version %1 of plugin \"%2\", but the plugin being used is version %3")
135 .arg(m_transform.getPluginVersion())
136 .arg(pluginId)
137 .arg(pv);
138 if (m_message != "") {
139 m_message = QString("%1; %2").arg(vm).arg(m_message);
140 } else {
141 m_message = vm;
142 }
143 }
95 } 144 }
96 145
97 Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); 146 Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors();
98 147
99 if (outputs.empty()) { 148 if (outputs.empty()) {
100 std::cerr << "FeatureExtractionModelTransformer: Plugin \"" 149 m_message = tr("Plugin \"%1\" has no outputs").arg(pluginId);
101 << pluginId.toStdString() << "\" has no outputs" << std::endl;
102 return; 150 return;
103 } 151 }
104 152
105 for (size_t i = 0; i < outputs.size(); ++i) { 153 for (size_t i = 0; i < outputs.size(); ++i) {
106 if (outputName == "" || outputs[i].identifier == outputName.toStdString()) { 154 if (m_transform.getOutput() == "" ||
155 outputs[i].identifier == m_transform.getOutput().toStdString()) {
107 m_outputFeatureNo = i; 156 m_outputFeatureNo = i;
108 m_descriptor = new Vamp::Plugin::OutputDescriptor 157 m_descriptor = new Vamp::Plugin::OutputDescriptor
109 (outputs[i]); 158 (outputs[i]);
110 break; 159 break;
111 } 160 }
112 } 161 }
113 162
114 if (!m_descriptor) { 163 if (!m_descriptor) {
115 std::cerr << "FeatureExtractionModelTransformer: Plugin \"" 164 m_message = tr("Plugin \"%1\" has no output named \"%2\"")
116 << pluginId.toStdString() << "\" has no output named \"" 165 .arg(pluginId)
117 << outputName.toStdString() << "\"" << std::endl; 166 .arg(m_transform.getOutput());
118 return; 167 return;
119 } 168 }
120 169
121 // std::cerr << "FeatureExtractionModelTransformer: output sample type " 170 // std::cerr << "FeatureExtractionModelTransformer: output sample type "
122 // << m_descriptor->sampleType << std::endl; 171 // << m_descriptor->sampleType << std::endl;
136 minValue = m_descriptor->minValue; 185 minValue = m_descriptor->minValue;
137 maxValue = m_descriptor->maxValue; 186 maxValue = m_descriptor->maxValue;
138 haveExtents = true; 187 haveExtents = true;
139 } 188 }
140 189
141 size_t modelRate = m_input->getSampleRate(); 190 size_t modelRate = input->getSampleRate();
142 size_t modelResolution = 1; 191 size_t modelResolution = 1;
143 192
144 switch (m_descriptor->sampleType) { 193 switch (m_descriptor->sampleType) {
145 194
146 case Vamp::Plugin::OutputDescriptor::VariableSampleRate: 195 case Vamp::Plugin::OutputDescriptor::VariableSampleRate:
148 modelResolution = size_t(modelRate / m_descriptor->sampleRate + 0.001); 197 modelResolution = size_t(modelRate / m_descriptor->sampleRate + 0.001);
149 } 198 }
150 break; 199 break;
151 200
152 case Vamp::Plugin::OutputDescriptor::OneSamplePerStep: 201 case Vamp::Plugin::OutputDescriptor::OneSamplePerStep:
153 modelResolution = m_context.stepSize; 202 modelResolution = m_transform.getStepSize();
154 break; 203 break;
155 204
156 case Vamp::Plugin::OutputDescriptor::FixedSampleRate: 205 case Vamp::Plugin::OutputDescriptor::FixedSampleRate:
157 modelRate = size_t(m_descriptor->sampleRate + 0.001); 206 modelRate = size_t(m_descriptor->sampleRate + 0.001);
158 break; 207 break;
215 } 264 }
216 265
217 m_output = model; 266 m_output = model;
218 } 267 }
219 268
220 if (m_output) m_output->setSourceModel(m_input); 269 if (m_output) m_output->setSourceModel(input);
221 } 270 }
222 271
223 FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer() 272 FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()
224 { 273 {
225 std::cerr << "FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()" << std::endl; 274 std::cerr << "FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()" << std::endl;
226 delete m_plugin; 275 delete m_plugin;
227 delete m_descriptor; 276 delete m_descriptor;
228 } 277 }
229 278
230 DenseTimeValueModel * 279 DenseTimeValueModel *
231 FeatureExtractionModelTransformer::getInput() 280 FeatureExtractionModelTransformer::getConformingInput()
232 { 281 {
233 DenseTimeValueModel *dtvm = 282 DenseTimeValueModel *dtvm =
234 dynamic_cast<DenseTimeValueModel *>(getInputModel()); 283 dynamic_cast<DenseTimeValueModel *>(getInputModel());
235 if (!dtvm) { 284 if (!dtvm) {
236 std::cerr << "FeatureExtractionModelTransformer::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl; 285 std::cerr << "FeatureExtractionModelTransformer::getConformingInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl;
237 } 286 }
238 return dtvm; 287 return dtvm;
239 } 288 }
240 289
241 void 290 void
242 FeatureExtractionModelTransformer::run() 291 FeatureExtractionModelTransformer::run()
243 { 292 {
244 DenseTimeValueModel *input = getInput(); 293 DenseTimeValueModel *input = getConformingInput();
245 if (!input) return; 294 if (!input) return;
246 295
247 if (!m_output) return; 296 if (!m_output) return;
248 297
249 while (!input->isReady()) { 298 while (!input->isReady()) {
256 */ 305 */
257 std::cerr << "FeatureExtractionModelTransformer::run: Waiting for input model to be ready..." << std::endl; 306 std::cerr << "FeatureExtractionModelTransformer::run: Waiting for input model to be ready..." << std::endl;
258 sleep(1); 307 sleep(1);
259 } 308 }
260 309
261 size_t sampleRate = m_input->getSampleRate(); 310 size_t sampleRate = input->getSampleRate();
262 311
263 size_t channelCount = input->getChannelCount(); 312 size_t channelCount = input->getChannelCount();
264 if (m_plugin->getMaxChannelCount() < channelCount) { 313 if (m_plugin->getMaxChannelCount() < channelCount) {
265 channelCount = 1; 314 channelCount = 1;
266 } 315 }
267 316
268 float **buffers = new float*[channelCount]; 317 float **buffers = new float*[channelCount];
269 for (size_t ch = 0; ch < channelCount; ++ch) { 318 for (size_t ch = 0; ch < channelCount; ++ch) {
270 buffers[ch] = new float[m_context.blockSize + 2]; 319 buffers[ch] = new float[m_transform.getBlockSize() + 2];
271 } 320 }
321
322 size_t stepSize = m_transform.getStepSize();
323 size_t blockSize = m_transform.getBlockSize();
272 324
273 bool frequencyDomain = (m_plugin->getInputDomain() == 325 bool frequencyDomain = (m_plugin->getInputDomain() ==
274 Vamp::Plugin::FrequencyDomain); 326 Vamp::Plugin::FrequencyDomain);
275 std::vector<FFTModel *> fftModels; 327 std::vector<FFTModel *> fftModels;
276 328
277 if (frequencyDomain) { 329 if (frequencyDomain) {
278 for (size_t ch = 0; ch < channelCount; ++ch) { 330 for (size_t ch = 0; ch < channelCount; ++ch) {
279 FFTModel *model = new FFTModel 331 FFTModel *model = new FFTModel
280 (getInput(), 332 (getConformingInput(),
281 channelCount == 1 ? m_context.channel : ch, 333 channelCount == 1 ? m_input.getChannel() : ch,
282 m_context.windowType, 334 m_transform.getWindowType(),
283 m_context.blockSize, 335 blockSize,
284 m_context.stepSize, 336 stepSize,
285 m_context.blockSize, 337 blockSize,
286 false, 338 false,
287 StorageAdviser::PrecisionCritical); 339 StorageAdviser::PrecisionCritical);
288 if (!model->isOK()) { 340 if (!model->isOK()) {
289 QMessageBox::critical 341 QMessageBox::critical
290 (0, tr("FFT cache failed"), 342 (0, tr("FFT cache failed"),
297 model->resume(); 349 model->resume();
298 fftModels.push_back(model); 350 fftModels.push_back(model);
299 } 351 }
300 } 352 }
301 353
302 long startFrame = m_input->getStartFrame(); 354 long startFrame = m_input.getModel()->getStartFrame();
303 long endFrame = m_input->getEndFrame(); 355 long endFrame = m_input.getModel()->getEndFrame();
304 356
305 long contextStart = m_context.startFrame; 357 RealTime contextStartRT = m_transform.getStartTime();
306 long contextDuration = m_context.duration; 358 RealTime contextDurationRT = m_transform.getDuration();
359
360 long contextStart =
361 RealTime::realTime2Frame(contextStartRT, sampleRate);
362
363 long contextDuration =
364 RealTime::realTime2Frame(contextDurationRT, sampleRate);
307 365
308 if (contextStart == 0 || contextStart < startFrame) { 366 if (contextStart == 0 || contextStart < startFrame) {
309 contextStart = startFrame; 367 contextStart = startFrame;
310 } 368 }
311 369
323 setCompletion(0); 381 setCompletion(0);
324 382
325 while (!m_abandoned) { 383 while (!m_abandoned) {
326 384
327 if (frequencyDomain) { 385 if (frequencyDomain) {
328 if (blockFrame - int(m_context.blockSize)/2 > 386 if (blockFrame - int(blockSize)/2 >
329 contextStart + contextDuration) break; 387 contextStart + contextDuration) break;
330 } else { 388 } else {
331 if (blockFrame >= 389 if (blockFrame >=
332 contextStart + contextDuration) break; 390 contextStart + contextDuration) break;
333 } 391 }
334 392
335 // std::cerr << "FeatureExtractionModelTransformer::run: blockFrame " 393 // std::cerr << "FeatureExtractionModelTransformer::run: blockFrame "
336 // << blockFrame << ", endFrame " << endFrame << ", blockSize " 394 // << blockFrame << ", endFrame " << endFrame << ", blockSize "
337 // << m_context.blockSize << std::endl; 395 // << blockSize << std::endl;
338 396
339 long completion = 397 long completion =
340 (((blockFrame - contextStart) / m_context.stepSize) * 99) / 398 (((blockFrame - contextStart) / stepSize) * 99) /
341 (contextDuration / m_context.stepSize); 399 (contextDuration / stepSize);
342 400
343 // channelCount is either m_input->channelCount or 1 401 // channelCount is either m_input.getModel()->channelCount or 1
344 402
345 for (size_t ch = 0; ch < channelCount; ++ch) { 403 if (frequencyDomain) {
346 if (frequencyDomain) { 404 for (size_t ch = 0; ch < channelCount; ++ch) {
347 int column = (blockFrame - startFrame) / m_context.stepSize; 405 int column = (blockFrame - startFrame) / stepSize;
348 for (size_t i = 0; i <= m_context.blockSize/2; ++i) { 406 for (size_t i = 0; i <= blockSize/2; ++i) {
349 fftModels[ch]->getValuesAt 407 fftModels[ch]->getValuesAt
350 (column, i, buffers[ch][i*2], buffers[ch][i*2+1]); 408 (column, i, buffers[ch][i*2], buffers[ch][i*2+1]);
351 } 409 }
352 } else { 410 }
353 getFrames(ch, channelCount, 411 } else {
354 blockFrame, m_context.blockSize, buffers[ch]); 412 getFrames(channelCount, blockFrame, blockSize, buffers);
355 }
356 } 413 }
357 414
358 Vamp::Plugin::FeatureSet features = m_plugin->process 415 Vamp::Plugin::FeatureSet features = m_plugin->process
359 (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate)); 416 (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate));
360 417
367 if (blockFrame == contextStart || completion > prevCompletion) { 424 if (blockFrame == contextStart || completion > prevCompletion) {
368 setCompletion(completion); 425 setCompletion(completion);
369 prevCompletion = completion; 426 prevCompletion = completion;
370 } 427 }
371 428
372 blockFrame += m_context.stepSize; 429 blockFrame += stepSize;
373 } 430 }
374 431
375 if (m_abandoned) return; 432 if (m_abandoned) return;
376 433
377 Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures(); 434 Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures();
390 447
391 setCompletion(100); 448 setCompletion(100);
392 } 449 }
393 450
394 void 451 void
395 FeatureExtractionModelTransformer::getFrames(int channel, int channelCount, 452 FeatureExtractionModelTransformer::getFrames(int channelCount,
396 long startFrame, long size, 453 long startFrame, long size,
397 float *buffer) 454 float **buffers)
398 { 455 {
399 long offset = 0; 456 long offset = 0;
400 457
401 if (startFrame < 0) { 458 if (startFrame < 0) {
402 for (int i = 0; i < size && startFrame + i < 0; ++i) { 459 for (int c = 0; c < channelCount; ++c) {
403 buffer[i] = 0.0f; 460 for (int i = 0; i < size && startFrame + i < 0; ++i) {
461 buffers[c][i] = 0.0f;
462 }
404 } 463 }
405 offset = -startFrame; 464 offset = -startFrame;
406 size -= offset; 465 size -= offset;
407 if (size <= 0) return; 466 if (size <= 0) return;
408 startFrame = 0; 467 startFrame = 0;
409 } 468 }
410 469
411 long got = getInput()->getData 470 DenseTimeValueModel *input = getConformingInput();
412 ((channelCount == 1 ? m_context.channel : channel), 471 if (!input) return;
413 startFrame, size, buffer + offset); 472
473 long got = 0;
474
475 if (channelCount == 1) {
476
477 got = input->getData(m_input.getChannel(), startFrame, size,
478 buffers[0] + offset);
479
480 if (m_input.getChannel() == -1 && input->getChannelCount() > 1) {
481 // use mean instead of sum, as plugin input
482 float cc = float(input->getChannelCount());
483 for (long i = 0; i < size; ++i) {
484 buffers[0][i + offset] /= cc;
485 }
486 }
487
488 } else {
489
490 float **writebuf = buffers;
491 if (offset > 0) {
492 writebuf = new float *[channelCount];
493 for (int i = 0; i < channelCount; ++i) {
494 writebuf[i] = buffers[i] + offset;
495 }
496 }
497
498 got = input->getData(0, channelCount-1, startFrame, size, writebuf);
499
500 if (writebuf != buffers) delete[] writebuf;
501 }
414 502
415 while (got < size) { 503 while (got < size) {
416 buffer[offset + got] = 0.0; 504 for (int c = 0; c < channelCount; ++c) {
505 buffers[c][got + offset] = 0.0;
506 }
417 ++got; 507 ++got;
418 }
419
420 if (m_context.channel == -1 && channelCount == 1 &&
421 getInput()->getChannelCount() > 1) {
422 // use mean instead of sum, as plugin input
423 int cc = getInput()->getChannelCount();
424 for (long i = 0; i < size; ++i) {
425 buffer[i] /= cc;
426 }
427 } 508 }
428 } 509 }
429 510
430 void 511 void
431 FeatureExtractionModelTransformer::addFeature(size_t blockFrame, 512 FeatureExtractionModelTransformer::addFeature(size_t blockFrame,
432 const Vamp::Plugin::Feature &feature) 513 const Vamp::Plugin::Feature &feature)
433 { 514 {
434 size_t inputRate = m_input->getSampleRate(); 515 size_t inputRate = m_input.getModel()->getSampleRate();
435 516
436 // std::cerr << "FeatureExtractionModelTransformer::addFeature(" 517 // std::cerr << "FeatureExtractionModelTransformer::addFeature("
437 // << blockFrame << ")" << std::endl; 518 // << blockFrame << ")" << std::endl;
438 519
439 int binCount = 1; 520 int binCount = 1;
468 } 549 }
469 } 550 }
470 551
471 if (binCount == 0) { 552 if (binCount == 0) {
472 553
473 SparseOneDimensionalModel *model = getOutput<SparseOneDimensionalModel>(); 554 SparseOneDimensionalModel *model =
555 getConformingOutput<SparseOneDimensionalModel>();
474 if (!model) return; 556 if (!model) return;
557
475 model->addPoint(SparseOneDimensionalModel::Point(frame, feature.label.c_str())); 558 model->addPoint(SparseOneDimensionalModel::Point(frame, feature.label.c_str()));
476 559
477 } else if (binCount == 1) { 560 } else if (binCount == 1) {
478 561
479 float value = 0.0; 562 float value = 0.0;
480 if (feature.values.size() > 0) value = feature.values[0]; 563 if (feature.values.size() > 0) value = feature.values[0];
481 564
482 SparseTimeValueModel *model = getOutput<SparseTimeValueModel>(); 565 SparseTimeValueModel *model =
566 getConformingOutput<SparseTimeValueModel>();
483 if (!model) return; 567 if (!model) return;
568
484 model->addPoint(SparseTimeValueModel::Point(frame, value, feature.label.c_str())); 569 model->addPoint(SparseTimeValueModel::Point(frame, value, feature.label.c_str()));
485 // std::cerr << "SparseTimeValueModel::addPoint(" << frame << ", " << value << "), " << feature.label.c_str() << std::endl; 570 // std::cerr << "SparseTimeValueModel::addPoint(" << frame << ", " << value << "), " << feature.label.c_str() << std::endl;
486 571
487 } else if (m_descriptor->sampleType == 572 } else if (m_descriptor->sampleType ==
488 Vamp::Plugin::OutputDescriptor::VariableSampleRate) { 573 Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
493 float duration = 1; 578 float duration = 1;
494 if (feature.values.size() > 1) duration = feature.values[1]; 579 if (feature.values.size() > 1) duration = feature.values[1];
495 580
496 float velocity = 100; 581 float velocity = 100;
497 if (feature.values.size() > 2) velocity = feature.values[2]; 582 if (feature.values.size() > 2) velocity = feature.values[2];
498 583 if (velocity < 0) velocity = 127;
499 NoteModel *model = getOutput<NoteModel>(); 584 if (velocity > 127) velocity = 127;
585
586 NoteModel *model = getConformingOutput<NoteModel>();
500 if (!model) return; 587 if (!model) return;
501 588
502 model->addPoint(NoteModel::Point(frame, pitch, 589 model->addPoint(NoteModel::Point(frame, pitch,
503 lrintf(duration), 590 lrintf(duration),
591 velocity / 127.f,
504 feature.label.c_str())); 592 feature.label.c_str()));
505 593
506 } else { 594 } else {
507 595
508 DenseThreeDimensionalModel::Column values = feature.values; 596 DenseThreeDimensionalModel::Column values = feature.values;
509 597
510 EditableDenseThreeDimensionalModel *model = 598 EditableDenseThreeDimensionalModel *model =
511 getOutput<EditableDenseThreeDimensionalModel>(); 599 getConformingOutput<EditableDenseThreeDimensionalModel>();
512 if (!model) return; 600 if (!model) return;
513 601
514 model->setColumn(frame / model->getResolution(), values); 602 model->setColumn(frame / model->getResolution(), values);
515 } 603 }
516 } 604 }
526 // std::cerr << "FeatureExtractionModelTransformer::setCompletion(" 614 // std::cerr << "FeatureExtractionModelTransformer::setCompletion("
527 // << completion << ")" << std::endl; 615 // << completion << ")" << std::endl;
528 616
529 if (binCount == 0) { 617 if (binCount == 0) {
530 618
531 SparseOneDimensionalModel *model = getOutput<SparseOneDimensionalModel>(); 619 SparseOneDimensionalModel *model =
620 getConformingOutput<SparseOneDimensionalModel>();
532 if (!model) return; 621 if (!model) return;
533 model->setCompletion(completion, m_context.updates); 622 model->setCompletion(completion, true); //!!!m_context.updates);
534 623
535 } else if (binCount == 1) { 624 } else if (binCount == 1) {
536 625
537 SparseTimeValueModel *model = getOutput<SparseTimeValueModel>(); 626 SparseTimeValueModel *model =
627 getConformingOutput<SparseTimeValueModel>();
538 if (!model) return; 628 if (!model) return;
539 model->setCompletion(completion, m_context.updates); 629 model->setCompletion(completion, true); //!!!m_context.updates);
540 630
541 } else if (m_descriptor->sampleType == 631 } else if (m_descriptor->sampleType ==
542 Vamp::Plugin::OutputDescriptor::VariableSampleRate) { 632 Vamp::Plugin::OutputDescriptor::VariableSampleRate) {
543 633
544 NoteModel *model = getOutput<NoteModel>(); 634 NoteModel *model =
635 getConformingOutput<NoteModel>();
545 if (!model) return; 636 if (!model) return;
546 model->setCompletion(completion, m_context.updates); 637 model->setCompletion(completion, true); //!!!m_context.updates);
547 638
548 } else { 639 } else {
549 640
550 EditableDenseThreeDimensionalModel *model = 641 EditableDenseThreeDimensionalModel *model =
551 getOutput<EditableDenseThreeDimensionalModel>(); 642 getConformingOutput<EditableDenseThreeDimensionalModel>();
552 if (!model) return; 643 if (!model) return;
553 model->setCompletion(completion, m_context.updates); 644 model->setCompletion(completion, true); //!!!m_context.updates);
554 } 645 }
555 } 646 }
556 647