comparison plugin/transform/FeatureExtractionModelTransformer.cpp @ 383:94fc0591ea43 1.2-stable

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