Mercurial > hg > svcore
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 |