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 }