Mercurial > hg > match-vamp
comparison MatchVampPlugin.cpp @ 16:4c8526c5bf58
Implement features outputs
author | Chris Cannam |
---|---|
date | Fri, 10 Oct 2014 13:16:54 +0100 |
parents | a82276091bbd |
children | 27f418d77095 |
comparison
equal
deleted
inserted
replaced
15:a82276091bbd | 16:4c8526c5bf58 |
---|---|
47 | 47 |
48 static float defaultStepTime = 0.020; | 48 static float defaultStepTime = 0.020; |
49 | 49 |
50 MatchVampPlugin::MatchVampPlugin(float inputSampleRate) : | 50 MatchVampPlugin::MatchVampPlugin(float inputSampleRate) : |
51 Plugin(inputSampleRate), | 51 Plugin(inputSampleRate), |
52 m_stepSize(0), | 52 m_stepSize(inputSampleRate * defaultStepTime + 0.001), |
53 m_stepTime(defaultStepTime), | 53 m_stepTime(defaultStepTime), |
54 m_blockSize(0), | 54 m_blockSize(2048), |
55 m_serialise(false), | 55 m_serialise(false), |
56 m_begin(true), | 56 m_begin(true), |
57 m_locked(false) | 57 m_locked(false) |
58 { | 58 { |
59 if (inputSampleRate < sampleRateMin) { | 59 if (inputSampleRate < sampleRateMin) { |
250 desc.hasKnownExtents = false; | 250 desc.hasKnownExtents = false; |
251 desc.isQuantized = true; | 251 desc.isQuantized = true; |
252 desc.quantizeStep = 1; | 252 desc.quantizeStep = 1; |
253 desc.sampleType = OutputDescriptor::VariableSampleRate; | 253 desc.sampleType = OutputDescriptor::VariableSampleRate; |
254 desc.sampleRate = outRate; | 254 desc.sampleRate = outRate; |
255 m_pathOutNo = list.size(); | |
255 list.push_back(desc); | 256 list.push_back(desc); |
256 | 257 |
257 desc.identifier = "a_b"; | 258 desc.identifier = "a_b"; |
258 desc.name = "A-B Timeline"; | 259 desc.name = "A-B Timeline"; |
259 desc.description = "Timing in performance B corresponding to moments in performance A"; | 260 desc.description = "Timing in performance B corresponding to moments in performance A"; |
262 desc.binCount = 1; | 263 desc.binCount = 1; |
263 desc.hasKnownExtents = false; | 264 desc.hasKnownExtents = false; |
264 desc.isQuantized = false; | 265 desc.isQuantized = false; |
265 desc.sampleType = OutputDescriptor::VariableSampleRate; | 266 desc.sampleType = OutputDescriptor::VariableSampleRate; |
266 desc.sampleRate = outRate; | 267 desc.sampleRate = outRate; |
268 m_abOutNo = list.size(); | |
267 list.push_back(desc); | 269 list.push_back(desc); |
268 | 270 |
269 desc.identifier = "b_a"; | 271 desc.identifier = "b_a"; |
270 desc.name = "B-A Timeline"; | 272 desc.name = "B-A Timeline"; |
271 desc.description = "Timing in performance A corresponding to moments in performance B"; | 273 desc.description = "Timing in performance A corresponding to moments in performance B"; |
274 desc.binCount = 1; | 276 desc.binCount = 1; |
275 desc.hasKnownExtents = false; | 277 desc.hasKnownExtents = false; |
276 desc.isQuantized = false; | 278 desc.isQuantized = false; |
277 desc.sampleType = OutputDescriptor::VariableSampleRate; | 279 desc.sampleType = OutputDescriptor::VariableSampleRate; |
278 desc.sampleRate = outRate; | 280 desc.sampleRate = outRate; |
281 m_baOutNo = list.size(); | |
279 list.push_back(desc); | 282 list.push_back(desc); |
280 | 283 |
281 desc.identifier = "a_b_divergence"; | 284 desc.identifier = "a_b_divergence"; |
282 desc.name = "A-B Divergence"; | 285 desc.name = "A-B Divergence"; |
283 desc.description = "Difference between timings in performances A and B"; | 286 desc.description = "Difference between timings in performances A and B"; |
286 desc.binCount = 1; | 289 desc.binCount = 1; |
287 desc.hasKnownExtents = false; | 290 desc.hasKnownExtents = false; |
288 desc.isQuantized = false; | 291 desc.isQuantized = false; |
289 desc.sampleType = OutputDescriptor::VariableSampleRate; | 292 desc.sampleType = OutputDescriptor::VariableSampleRate; |
290 desc.sampleRate = outRate; | 293 desc.sampleRate = outRate; |
294 m_abDivOutNo = list.size(); | |
291 list.push_back(desc); | 295 list.push_back(desc); |
292 | 296 |
293 desc.identifier = "a_b_temporatio"; | 297 desc.identifier = "a_b_temporatio"; |
294 desc.name = "A-B Tempo Ratio"; | 298 desc.name = "A-B Tempo Ratio"; |
295 desc.description = "Ratio of tempi between performances A and B"; | 299 desc.description = "Ratio of tempi between performances A and B"; |
298 desc.binCount = 1; | 302 desc.binCount = 1; |
299 desc.hasKnownExtents = false; | 303 desc.hasKnownExtents = false; |
300 desc.isQuantized = false; | 304 desc.isQuantized = false; |
301 desc.sampleType = OutputDescriptor::VariableSampleRate; | 305 desc.sampleType = OutputDescriptor::VariableSampleRate; |
302 desc.sampleRate = outRate; | 306 desc.sampleRate = outRate; |
303 list.push_back(desc); | 307 m_abRatioOutNo = list.size(); |
308 list.push_back(desc); | |
309 | |
310 Matcher::Parameters params(m_inputSampleRate, m_stepTime, m_blockSize); | |
304 | 311 |
305 desc.identifier = "a_features"; | 312 desc.identifier = "a_features"; |
306 desc.name = "A Features"; | 313 desc.name = "A Features"; |
307 desc.description = "Spectral features extracted from performance A"; | 314 desc.description = "Spectral features extracted from performance A"; |
308 desc.unit = ""; | 315 desc.unit = ""; |
309 desc.hasFixedBinCount = true; | 316 desc.hasFixedBinCount = true; |
310 desc.binCount = 1; | 317 desc.binCount = Matcher::getFeatureSize(params); |
311 desc.hasKnownExtents = false; | 318 desc.hasKnownExtents = false; |
312 desc.isQuantized = false; | 319 desc.isQuantized = false; |
313 desc.sampleType = OutputDescriptor::VariableSampleRate; | 320 desc.sampleType = OutputDescriptor::FixedSampleRate; |
314 desc.sampleRate = outRate; | 321 desc.sampleRate = outRate; |
322 m_aFeaturesOutNo = list.size(); | |
323 list.push_back(desc); | |
324 | |
325 desc.identifier = "b_features"; | |
326 desc.name = "B Features"; | |
327 desc.description = "Spectral features extracted from performance B"; | |
328 desc.unit = ""; | |
329 desc.hasFixedBinCount = true; | |
330 desc.binCount = Matcher::getFeatureSize(params); | |
331 desc.hasKnownExtents = false; | |
332 desc.isQuantized = false; | |
333 desc.sampleType = OutputDescriptor::FixedSampleRate; | |
334 desc.sampleRate = outRate; | |
335 m_bFeaturesOutNo = list.size(); | |
315 list.push_back(desc); | 336 list.push_back(desc); |
316 | 337 |
317 return list; | 338 return list; |
318 } | 339 } |
319 | 340 |
334 m_begin = false; | 355 m_begin = false; |
335 } | 356 } |
336 | 357 |
337 // std::cerr << timestamp.toString(); | 358 // std::cerr << timestamp.toString(); |
338 | 359 |
339 feeder->feed(inputBuffers); | 360 MatchFeeder::Features ff = feeder->feedAndGetFeatures(inputBuffers); |
361 | |
362 FeatureSet returnFeatures; | |
363 | |
364 Feature f; | |
365 f.hasTimestamp = false; | |
366 | |
367 for (int i = 0; i < (int)ff.f1.size(); ++i) { | |
368 f.values.clear(); | |
369 for (int j = 0; j < (int)ff.f1[i].size(); ++j) { | |
370 f.values.push_back(ff.f1[i][j]); | |
371 } | |
372 returnFeatures[m_aFeaturesOutNo].push_back(f); | |
373 } | |
374 | |
375 for (int i = 0; i < (int)ff.f2.size(); ++i) { | |
376 f.values.clear(); | |
377 for (int j = 0; j < (int)ff.f2[i].size(); ++j) { | |
378 f.values.push_back(ff.f2[i][j]); | |
379 } | |
380 returnFeatures[m_bFeaturesOutNo].push_back(f); | |
381 } | |
340 | 382 |
341 // std::cerr << "."; | 383 // std::cerr << "."; |
342 // std::cerr << std::endl; | 384 // std::cerr << std::endl; |
343 | 385 |
344 return FeatureSet(); | 386 return returnFeatures; |
345 } | 387 } |
346 | 388 |
347 MatchVampPlugin::FeatureSet | 389 MatchVampPlugin::FeatureSet |
348 MatchVampPlugin::getRemainingFeatures() | 390 MatchVampPlugin::getRemainingFeatures() |
349 { | 391 { |
362 pathx.push_back(x); | 404 pathx.push_back(x); |
363 pathy.push_back(y); | 405 pathy.push_back(y); |
364 | 406 |
365 // std::cerr << pathx.size() << ": (" << x << "," << y << ")" << std::endl; | 407 // std::cerr << pathx.size() << ": (" << x << "," << y << ")" << std::endl; |
366 | 408 |
367 switch (finder->getDistance() & ADVANCE_BOTH){ | 409 switch (finder->getDistance() & ADVANCE_BOTH) { |
368 case ADVANCE_THIS: y--; break; | 410 case ADVANCE_THIS: y--; break; |
369 case ADVANCE_OTHER: x--; break; | 411 case ADVANCE_OTHER: x--; break; |
370 case ADVANCE_BOTH: x--; y--; break; | 412 case ADVANCE_BOTH: x--; y--; break; |
371 default: // this would indicate a bug, but we wouldn't want to hang | 413 default: // this would indicate a bug, but we wouldn't want to hang |
372 std::cerr << "WARNING: MatchVampPlugin::getRemainingFeatures: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << std::endl; | 414 std::cerr << "WARNING: MatchVampPlugin::getRemainingFeatures: Neither matcher advanced in path backtrack at (" << x << "," << y << ")" << std::endl; |
397 Feature feature; | 439 Feature feature; |
398 feature.hasTimestamp = true; | 440 feature.hasTimestamp = true; |
399 feature.timestamp = m_startTime + xt; | 441 feature.timestamp = m_startTime + xt; |
400 feature.values.clear(); | 442 feature.values.clear(); |
401 feature.values.push_back(yt.sec + double(yt.nsec)/1.0e9); | 443 feature.values.push_back(yt.sec + double(yt.nsec)/1.0e9); |
402 returnFeatures[0].push_back(feature); | 444 returnFeatures[m_pathOutNo].push_back(feature); |
403 | 445 |
404 if (x != prevx) { | 446 if (x != prevx) { |
405 | 447 |
406 feature.hasTimestamp = true; | 448 feature.hasTimestamp = true; |
407 feature.timestamp = m_startTime + xt; | 449 feature.timestamp = m_startTime + xt; |
408 feature.values.clear(); | 450 feature.values.clear(); |
409 feature.values.push_back(yt.sec + yt.msec()/1000.0); | 451 feature.values.push_back(yt.sec + yt.msec()/1000.0); |
410 returnFeatures[1].push_back(feature); | 452 returnFeatures[m_abOutNo].push_back(feature); |
411 | 453 |
412 Vamp::RealTime diff = yt - xt; | 454 Vamp::RealTime diff = yt - xt; |
413 feature.values.clear(); | 455 feature.values.clear(); |
414 feature.values.push_back(diff.sec + diff.msec()/1000.0); | 456 feature.values.push_back(diff.sec + diff.msec()/1000.0); |
415 returnFeatures[3].push_back(feature); | 457 returnFeatures[m_abDivOutNo].push_back(feature); |
416 | 458 |
417 if (i > 0) { | 459 if (i > 0) { |
418 int lookback = 100; //!!! arbitrary | 460 int lookback = 100; //!!! arbitrary |
419 if (lookback > i) lookback = i; | 461 if (lookback > i) lookback = i; |
420 int xdiff = x - pathx[i-lookback]; | 462 int xdiff = x - pathx[i-lookback]; |
422 if (xdiff != 0 && ydiff != 0) { | 464 if (xdiff != 0 && ydiff != 0) { |
423 float ratio = float(ydiff)/float(xdiff); | 465 float ratio = float(ydiff)/float(xdiff); |
424 if (ratio < 8 && ratio > (1.0/8)) { //!!! just for now, since we aren't dealing properly with silence yet | 466 if (ratio < 8 && ratio > (1.0/8)) { //!!! just for now, since we aren't dealing properly with silence yet |
425 feature.values.clear(); | 467 feature.values.clear(); |
426 feature.values.push_back(ratio); | 468 feature.values.push_back(ratio); |
427 returnFeatures[4].push_back(feature); | 469 returnFeatures[m_abRatioOutNo].push_back(feature); |
428 } | 470 } |
429 } | 471 } |
430 } | 472 } |
431 } | 473 } |
432 | 474 |
433 if (y != prevy) { | 475 if (y != prevy) { |
434 feature.hasTimestamp = true; | 476 feature.hasTimestamp = true; |
435 feature.timestamp = m_startTime + yt; | 477 feature.timestamp = m_startTime + yt; |
436 feature.values.clear(); | 478 feature.values.clear(); |
437 feature.values.push_back(xt.sec + xt.msec()/1000.0); | 479 feature.values.push_back(xt.sec + xt.msec()/1000.0); |
438 returnFeatures[2].push_back(feature); | 480 returnFeatures[m_baOutNo].push_back(feature); |
439 } | 481 } |
440 | 482 |
441 prevx = x; | 483 prevx = x; |
442 prevy = y; | 484 prevy = y; |
443 } | 485 } |