Mercurial > hg > qm-vamp-plugins
comparison plugins/SimilarityPlugin.cpp @ 44:1dc00e4dbae6
* add a sorted vector output
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Thu, 17 Jan 2008 15:37:37 +0000 |
parents | 1389f05cb688 |
children | 5d7ce1d87301 |
comparison
equal
deleted
inserted
replaced
43:1389f05cb688 | 44:1dc00e4dbae6 |
---|---|
6 * Copyright 2008 Centre for Digital Music, Queen Mary, University of London. | 6 * Copyright 2008 Centre for Digital Music, Queen Mary, University of London. |
7 * All rights reserved. | 7 * All rights reserved. |
8 */ | 8 */ |
9 | 9 |
10 #include <iostream> | 10 #include <iostream> |
11 #include <sstream> | 11 #include <cstdio> |
12 | 12 |
13 #include "SimilarityPlugin.h" | 13 #include "SimilarityPlugin.h" |
14 #include "base/Pitch.h" | 14 #include "base/Pitch.h" |
15 #include "dsp/mfcc/MFCC.h" | 15 #include "dsp/mfcc/MFCC.h" |
16 #include "dsp/chromagram/Chromagram.h" | 16 #include "dsp/chromagram/Chromagram.h" |
86 | 86 |
87 size_t | 87 size_t |
88 SimilarityPlugin::getMaxChannelCount() const | 88 SimilarityPlugin::getMaxChannelCount() const |
89 { | 89 { |
90 return 1024; | 90 return 1024; |
91 // return 1; | |
91 } | 92 } |
92 | 93 |
93 bool | 94 bool |
94 SimilarityPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) | 95 SimilarityPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) |
95 { | 96 { |
112 return false; | 113 return false; |
113 } | 114 } |
114 | 115 |
115 m_blockSize = blockSize; | 116 m_blockSize = blockSize; |
116 m_channels = channels; | 117 m_channels = channels; |
118 | |
119 m_lastNonEmptyFrame = std::vector<int>(m_channels); | |
120 for (int i = 0; i < m_channels; ++i) m_lastNonEmptyFrame[i] = -1; | |
121 m_frameNo = 0; | |
117 | 122 |
118 int decimationFactor = getDecimationFactor(); | 123 int decimationFactor = getDecimationFactor(); |
119 if (decimationFactor > 1) { | 124 if (decimationFactor > 1) { |
120 m_decimator = new Decimator(m_blockSize, decimationFactor); | 125 m_decimator = new Decimator(m_blockSize, decimationFactor); |
121 } | 126 } |
309 simvec.sampleRate = 1; | 314 simvec.sampleRate = 1; |
310 | 315 |
311 m_distanceVectorOutput = list.size(); | 316 m_distanceVectorOutput = list.size(); |
312 list.push_back(simvec); | 317 list.push_back(simvec); |
313 | 318 |
319 OutputDescriptor sortvec; | |
320 sortvec.identifier = "sorteddistancevector"; | |
321 sortvec.name = "Ordered Distances from First Channel"; | |
322 sortvec.description = "Vector of the order of other channels in similarity to the first, followed by distance vector for similarity of each to the first. Smaller = more similar."; | |
323 sortvec.unit = ""; | |
324 sortvec.hasFixedBinCount = true; | |
325 sortvec.binCount = m_channels; | |
326 sortvec.hasKnownExtents = false; | |
327 sortvec.isQuantized = false; | |
328 sortvec.sampleType = OutputDescriptor::FixedSampleRate; | |
329 sortvec.sampleRate = 1; | |
330 | |
331 m_sortedVectorOutput = list.size(); | |
332 list.push_back(sortvec); | |
333 | |
314 OutputDescriptor means; | 334 OutputDescriptor means; |
315 means.identifier = "means"; | 335 means.identifier = "means"; |
316 means.name = "Feature Means"; | 336 means.name = "Feature Means"; |
317 means.description = "Means of the feature bins. Feature time (sec) corresponds to input channel. Number of bins depends on selected feature type."; | 337 means.description = "Means of the feature bins. Feature time (sec) corresponds to input channel. Number of bins depends on selected feature type."; |
318 means.unit = ""; | 338 means.unit = ""; |
370 if (fabs(val) > threshold) empty = false; | 390 if (fabs(val) > threshold) empty = false; |
371 dblbuf[i] = val; | 391 dblbuf[i] = val; |
372 } | 392 } |
373 | 393 |
374 if (empty) continue; | 394 if (empty) continue; |
395 m_lastNonEmptyFrame[c] = m_frameNo; | |
375 | 396 |
376 if (m_decimator) { | 397 if (m_decimator) { |
377 m_decimator->process(dblbuf, decbuf); | 398 m_decimator->process(dblbuf, decbuf); |
378 } | 399 } |
379 | 400 |
382 } else if (m_type == TypeChroma) { | 403 } else if (m_type == TypeChroma) { |
383 raw = m_chromagram->process(decbuf); | 404 raw = m_chromagram->process(decbuf); |
384 } | 405 } |
385 | 406 |
386 FeatureColumn mf(m_featureColumnSize); | 407 FeatureColumn mf(m_featureColumnSize); |
387 for (int i = 0; i < m_featureColumnSize; ++i) mf[i] = raw[i]; | 408 // std::cout << m_frameNo << ":" << c << ": "; |
409 for (int i = 0; i < m_featureColumnSize; ++i) { | |
410 mf[i] = raw[i]; | |
411 // std::cout << raw[i] << " "; | |
412 } | |
413 // std::cout << std::endl; | |
388 | 414 |
389 m_values[c].push_back(mf); | 415 m_values[c].push_back(mf); |
390 } | 416 } |
391 | 417 |
392 if (m_decimator) delete[] decbuf; | 418 if (m_decimator) delete[] decbuf; |
393 delete[] dblbuf; | 419 delete[] dblbuf; |
394 | 420 |
395 if (ownRaw) delete[] raw; | 421 if (ownRaw) delete[] raw; |
396 | 422 |
423 ++m_frameNo; | |
424 | |
397 return FeatureSet(); | 425 return FeatureSet(); |
398 } | 426 } |
399 | 427 |
400 SimilarityPlugin::FeatureSet | 428 SimilarityPlugin::FeatureSet |
401 SimilarityPlugin::getRemainingFeatures() | 429 SimilarityPlugin::getRemainingFeatures() |
411 | 439 |
412 mean[j] = 0.0; | 440 mean[j] = 0.0; |
413 variance[j] = 0.0; | 441 variance[j] = 0.0; |
414 int count; | 442 int count; |
415 | 443 |
416 // we need to use at least one value, but we want to | 444 // We want to take values up to, but not including, the |
417 // disregard the final value because it may have come from | 445 // last non-empty frame (which may be partial) |
418 // incomplete data | 446 |
419 | 447 int sz = m_lastNonEmptyFrame[i]; |
420 int sz = m_values[i].size(); | 448 if (sz < 0) sz = 0; |
421 if (sz > 1) --sz; | |
422 | 449 |
423 // std::cout << "\nBin " << j << ":" << std::endl; | 450 // std::cout << "\nBin " << j << ":" << std::endl; |
424 | 451 |
425 count = 0; | 452 count = 0; |
426 for (int k = 0; k < sz; ++k) { | 453 for (int k = 0; k < sz; ++k) { |
482 d /= 2.0; | 509 d /= 2.0; |
483 distances[i].push_back(d); | 510 distances[i].push_back(d); |
484 } | 511 } |
485 } | 512 } |
486 | 513 |
514 // We give all features a timestamp, otherwise hosts will tend to | |
515 // stamp them at the end of the file, which is annoying | |
516 | |
487 FeatureSet returnFeatures; | 517 FeatureSet returnFeatures; |
518 | |
519 Feature feature; | |
520 feature.hasTimestamp = true; | |
488 | 521 |
489 Feature distanceVectorFeature; | 522 Feature distanceVectorFeature; |
490 distanceVectorFeature.label = "Distance from first channel"; | 523 distanceVectorFeature.label = "Distance from first channel"; |
524 distanceVectorFeature.hasTimestamp = true; | |
525 distanceVectorFeature.timestamp = Vamp::RealTime::zeroTime; | |
526 | |
527 std::map<double, int> sorted; | |
528 | |
529 char labelBuffer[100]; | |
491 | 530 |
492 for (int i = 0; i < m_channels; ++i) { | 531 for (int i = 0; i < m_channels; ++i) { |
493 | 532 |
494 Feature feature; | |
495 feature.hasTimestamp = true; // otherwise hosts will tend to stamp them at the end of the file, which is annoying | |
496 feature.timestamp = Vamp::RealTime(i, 0); | 533 feature.timestamp = Vamp::RealTime(i, 0); |
534 | |
535 sprintf(labelBuffer, "Means for channel %d", i+1); | |
536 feature.label = labelBuffer; | |
497 | 537 |
498 feature.values.clear(); | 538 feature.values.clear(); |
499 for (int k = 0; k < m_featureColumnSize; ++k) { | 539 for (int k = 0; k < m_featureColumnSize; ++k) { |
500 feature.values.push_back(m[i][k]); | 540 feature.values.push_back(m[i][k]); |
501 } | 541 } |
502 | 542 |
503 returnFeatures[m_meansOutput].push_back(feature); | 543 returnFeatures[m_meansOutput].push_back(feature); |
504 | 544 |
545 sprintf(labelBuffer, "Variances for channel %d", i+1); | |
546 feature.label = labelBuffer; | |
547 | |
505 feature.values.clear(); | 548 feature.values.clear(); |
506 for (int k = 0; k < m_featureColumnSize; ++k) { | 549 for (int k = 0; k < m_featureColumnSize; ++k) { |
507 feature.values.push_back(v[i][k]); | 550 feature.values.push_back(v[i][k]); |
508 } | 551 } |
509 | 552 |
512 feature.values.clear(); | 555 feature.values.clear(); |
513 for (int j = 0; j < m_channels; ++j) { | 556 for (int j = 0; j < m_channels; ++j) { |
514 feature.values.push_back(distances[i][j]); | 557 feature.values.push_back(distances[i][j]); |
515 } | 558 } |
516 | 559 |
517 ostringstream oss; | 560 sprintf(labelBuffer, "Distances from channel %d", i+1); |
518 oss << "Distance from " << (i + 1); | 561 feature.label = labelBuffer; |
519 feature.label = oss.str(); | |
520 | 562 |
521 returnFeatures[m_distanceMatrixOutput].push_back(feature); | 563 returnFeatures[m_distanceMatrixOutput].push_back(feature); |
522 | 564 |
523 distanceVectorFeature.values.push_back(distances[0][i]); | 565 distanceVectorFeature.values.push_back(distances[0][i]); |
566 | |
567 sorted[distances[0][i]] = i; | |
524 } | 568 } |
525 | 569 |
526 returnFeatures[m_distanceVectorOutput].push_back(distanceVectorFeature); | 570 returnFeatures[m_distanceVectorOutput].push_back(distanceVectorFeature); |
527 | 571 |
572 feature.label = "Order of channels by similarity to first channel"; | |
573 feature.values.clear(); | |
574 feature.timestamp = Vamp::RealTime(0, 0); | |
575 | |
576 for (std::map<double, int>::iterator i = sorted.begin(); | |
577 i != sorted.end(); ++i) { | |
578 feature.values.push_back(i->second); | |
579 } | |
580 | |
581 returnFeatures[m_sortedVectorOutput].push_back(feature); | |
582 | |
583 feature.label = "Ordered distances of channels from first channel"; | |
584 feature.values.clear(); | |
585 feature.timestamp = Vamp::RealTime(1, 0); | |
586 | |
587 for (std::map<double, int>::iterator i = sorted.begin(); | |
588 i != sorted.end(); ++i) { | |
589 feature.values.push_back(i->first); | |
590 } | |
591 | |
592 returnFeatures[m_sortedVectorOutput].push_back(feature); | |
593 | |
528 return returnFeatures; | 594 return returnFeatures; |
529 } | 595 } |