annotate src/MatchFeatureFeeder.cpp @ 167:28c73e5db2eb structure

Allow querying the best-estimate reference frame for the current feed point; don't heap-allocate finder
author Chris Cannam
date Thu, 05 Feb 2015 14:06:57 +0000
parents 2b61e0cb6847
children 70636e3c5a46
rev   line source
cannam@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@0 2
cannam@0 3 /*
cannam@0 4 Vamp feature extraction plugin using the MATCH audio alignment
cannam@0 5 algorithm.
cannam@0 6
cannam@0 7 Centre for Digital Music, Queen Mary, University of London.
cannam@0 8 This file copyright 2007 Simon Dixon, Chris Cannam and QMUL.
cannam@0 9
cannam@0 10 This program is free software; you can redistribute it and/or
cannam@0 11 modify it under the terms of the GNU General Public License as
cannam@0 12 published by the Free Software Foundation; either version 2 of the
cannam@0 13 License, or (at your option) any later version. See the file
cannam@0 14 COPYING included with this distribution for more information.
cannam@0 15 */
cannam@0 16
Chris@24 17 #include "MatchFeatureFeeder.h"
cannam@0 18
Chris@14 19 using std::vector;
Chris@14 20
Chris@24 21 MatchFeatureFeeder::MatchFeatureFeeder(Matcher *m1, Matcher *m2) :
Chris@167 22 m_pm1(m1),
Chris@167 23 m_pm2(m2),
Chris@167 24 m_finder(m_pm1)
cannam@0 25 {
cannam@0 26 }
cannam@0 27
Chris@24 28 MatchFeatureFeeder::~MatchFeatureFeeder()
cannam@0 29 {
cannam@0 30 }
cannam@0 31
Chris@155 32 MatchFeatureFeeder::MatchFeatureFeeder(const MatchFeatureFeeder &other) :
Chris@167 33 m_pm1(other.m_pm1),
Chris@167 34 m_pm2(other.m_pm2),
Chris@167 35 m_finder(m_pm1)
Chris@155 36 {
Chris@155 37 }
Chris@155 38
Chris@155 39 MatchFeatureFeeder &
Chris@155 40 MatchFeatureFeeder::operator=(const MatchFeatureFeeder &other)
Chris@155 41 {
Chris@155 42 m_pm1 = other.m_pm1;
Chris@155 43 m_pm2 = other.m_pm2;
Chris@167 44 m_finder = Finder(m_pm1);
Chris@155 45 return *this;
Chris@155 46 }
Chris@155 47
cannam@0 48 void
Chris@154 49 MatchFeatureFeeder::setMatchers(Matcher *m1, Matcher *m2)
Chris@154 50 {
Chris@154 51 m_pm1 = m1;
Chris@154 52 m_pm2 = m2;
Chris@167 53 m_finder.setMatcher(m_pm1);
Chris@154 54 }
Chris@154 55
Chris@154 56 void
Chris@24 57 MatchFeatureFeeder::feed(vector<double> f1, vector<double> f2)
cannam@0 58 {
Chris@49 59 // We maintain two FIFO queues of feature vectors, one per input
Chris@49 60 // stream. When the match-feeder function is entered, it knows
Chris@49 61 // that it has at least one feature in each queue. It loops,
Chris@49 62 // processing up to one feature per matcher, until a queue is
Chris@49 63 // empty. Then it returns, to be called again with more data.
Chris@49 64
Chris@60 65 if (!f1.empty()) {
Chris@74 66 m_q1.push(f1);
Chris@60 67 }
Chris@60 68
Chris@60 69 if (!f2.empty()) {
Chris@74 70 m_q2.push(f2);
Chris@60 71 }
Chris@14 72
Chris@74 73 while (!m_q1.empty() && !m_q2.empty()) {
Chris@63 74 feedBlock();
Chris@63 75 }
Chris@63 76 }
Chris@63 77
Chris@167 78 int
Chris@167 79 MatchFeatureFeeder::getEstimatedReferenceFrame()
Chris@167 80 {
Chris@167 81 if (m_pm1->getFrameCount() == 0 || m_pm2->getFrameCount() == 0) {
Chris@167 82 return 0;
Chris@167 83 }
Chris@167 84 int bestRow = 0;
Chris@167 85 double bestCost = 0;
Chris@167 86 if (!m_finder.getBestColCost(m_pm2->getFrameCount()-1, bestRow, bestCost)) {
Chris@167 87 return -1;
Chris@167 88 } else {
Chris@167 89 return bestRow;
Chris@167 90 }
Chris@167 91 }
Chris@167 92
Chris@63 93 void
Chris@63 94 MatchFeatureFeeder::finish()
Chris@63 95 {
Chris@74 96 while (!m_q1.empty() || !m_q2.empty()) {
Chris@24 97 feedBlock();
Chris@14 98 }
Chris@14 99 }
Chris@14 100
Chris@24 101 void
Chris@24 102 MatchFeatureFeeder::feedBlock()
Chris@14 103 {
Chris@74 104 if (m_q1.empty()) { // ended
Chris@60 105 feed2();
Chris@74 106 } else if (m_q2.empty()) { // ended
Chris@60 107 feed1();
Chris@78 108 } else if (m_pm1->getFrameCount() < m_pm1->getBlockSize()) { // fill initial block
Chris@24 109 feed1();
Chris@24 110 feed2();
Chris@78 111 } else if (m_pm1->isOverrunning()) { // slope constraints
Chris@24 112 feed2();
Chris@78 113 } else if (m_pm2->isOverrunning()) {
Chris@24 114 feed1();
cannam@0 115 } else {
Chris@167 116 switch (m_finder.getExpandDirection
Chris@78 117 (m_pm1->getFrameCount()-1, m_pm2->getFrameCount()-1)) {
Chris@45 118 case Matcher::AdvanceThis:
Chris@24 119 feed1();
cannam@0 120 break;
Chris@45 121 case Matcher::AdvanceOther:
Chris@24 122 feed2();
cannam@0 123 break;
Chris@45 124 case Matcher::AdvanceBoth:
Chris@24 125 feed1();
Chris@24 126 feed2();
cannam@0 127 break;
Chris@45 128 case Matcher::AdvanceNone:
Chris@74 129 cerr << "m_finder says AdvanceNone!" << endl;
Chris@45 130 break;
cannam@0 131 }
cannam@0 132 }
Chris@135 133
Chris@135 134 m_fpx.push_back(m_pm2->getFrameCount());
Chris@135 135 m_fpy.push_back(m_pm1->getFrameCount());
cannam@0 136 }
cannam@0 137
Chris@24 138 void
Chris@24 139 MatchFeatureFeeder::feed1()
cannam@0 140 {
Chris@74 141 m_pm1->consumeFeatureVector(m_q1.front());
Chris@74 142 m_q1.pop();
cannam@0 143 }
cannam@0 144
Chris@24 145 void
Chris@24 146 MatchFeatureFeeder::feed2()
cannam@0 147 {
Chris@74 148 m_pm2->consumeFeatureVector(m_q2.front());
Chris@74 149 m_q2.pop();
cannam@0 150 }
cannam@0 151