annotate src/MatchFeeder.cpp @ 67:a3efb15e7faf refactors

Merge from branch refactors_no_float
author Chris Cannam
date Tue, 18 Nov 2014 10:33:03 +0000
parents da9ead46abe9
children c3c50d5e05b7
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
cannam@0 17 #include "MatchFeeder.h"
cannam@0 18
Chris@14 19 using std::vector;
Chris@14 20
cannam@0 21 MatchFeeder::MatchFeeder(Matcher *m1, Matcher *m2) :
Chris@60 22 pm1(m1), pm2(m2), n(0), lastIn1(0), lastIn2(0)
cannam@0 23 {
Chris@43 24 fftSize = m1->m_params.fftSize;
cannam@0 25 finder = new Finder(m1, m2);
cannam@0 26 reBuffer = new double[fftSize/2+1];
cannam@0 27 imBuffer = new double[fftSize/2+1];
cannam@0 28 }
cannam@0 29
cannam@0 30 MatchFeeder::~MatchFeeder()
cannam@0 31 {
cannam@0 32 delete[] imBuffer;
cannam@0 33 delete[] reBuffer;
cannam@0 34 while (!q1.empty()) {
cannam@0 35 delete[] q1.front();
cannam@0 36 q1.pop();
cannam@0 37 }
cannam@0 38 while (!q2.empty()) {
cannam@0 39 delete[] q2.front();
cannam@0 40 q2.pop();
cannam@0 41 }
cannam@0 42 delete finder;
cannam@0 43 }
cannam@0 44
cannam@0 45 void
cannam@0 46 MatchFeeder::feed(const float *const *input)
cannam@0 47 {
cannam@0 48 // We maintain two FIFO queues of audio data frame block pointers,
cannam@0 49 // one per input stream. When the match-feeder function is
cannam@0 50 // entered, it knows that it has at least one block in each queue.
cannam@0 51 // It loops, processing up to one block per matcher, until a queue
cannam@0 52 // is empty. Then it returns, to be called again with more data.
cannam@0 53
Chris@14 54 prepare(input);
Chris@14 55
Chris@63 56 while (!q1.empty() && !q2.empty()) {
Chris@14 57 (void)feedBlock();
Chris@14 58 }
Chris@14 59 }
Chris@14 60
Chris@14 61 MatchFeeder::Features
Chris@14 62 MatchFeeder::feedAndGetFeatures(const float *const *input)
Chris@14 63 {
Chris@14 64 prepare(input);
Chris@14 65
Chris@14 66 Features all;
Chris@14 67
Chris@63 68 while (!q1.empty() && !q2.empty()) {
Chris@63 69 Features ff = feedBlock();
Chris@63 70 all.f1.insert(all.f1.end(), ff.f1.begin(), ff.f1.end());
Chris@63 71 all.f2.insert(all.f2.end(), ff.f2.begin(), ff.f2.end());
Chris@63 72 }
Chris@63 73
Chris@63 74 return all;
Chris@63 75 }
Chris@63 76
Chris@63 77 void
Chris@63 78 MatchFeeder::finish()
Chris@63 79 {
Chris@63 80 while (!q1.empty() || !q2.empty()) {
Chris@63 81 (void)feedBlock();
Chris@63 82 }
Chris@63 83 }
Chris@63 84
Chris@63 85 MatchFeeder::Features
Chris@63 86 MatchFeeder::finishAndGetFeatures()
Chris@63 87 {
Chris@63 88 Features all;
Chris@63 89
Chris@60 90 while (!q1.empty() || !q2.empty()) {
Chris@14 91 Features ff = feedBlock();
Chris@14 92 all.f1.insert(all.f1.end(), ff.f1.begin(), ff.f1.end());
Chris@14 93 all.f2.insert(all.f2.end(), ff.f2.begin(), ff.f2.end());
Chris@14 94 }
Chris@14 95
Chris@14 96 return all;
Chris@14 97 }
Chris@14 98
Chris@14 99 void
Chris@14 100 MatchFeeder::prepare(const float *const *input)
Chris@14 101 {
Chris@61 102 float threshold = 1e-5f;
Chris@60 103
cannam@0 104 float *block = new float[fftSize+2];
Chris@60 105 float rms = 0;
Chris@60 106
cannam@0 107 for (size_t i = 0; i < fftSize+2; ++i) {
cannam@0 108 block[i] = input[0][i];
Chris@60 109 rms += block[i] * block[i];
Chris@60 110 }
Chris@60 111 rms = sqrtf(rms / (fftSize+2));
Chris@60 112 if (rms > threshold) {
Chris@60 113 lastIn1 = n;
cannam@0 114 }
cannam@0 115 q1.push(block);
cannam@0 116
cannam@0 117 block = new float[fftSize+2];
Chris@60 118 rms = 0;
Chris@60 119
cannam@0 120 for (size_t i = 0; i < fftSize+2; ++i) {
cannam@0 121 block[i] = input[1][i];
Chris@60 122 rms += block[i] * block[i];
Chris@60 123 }
Chris@60 124 rms = sqrtf(rms / (fftSize+2));
Chris@60 125 if (rms > threshold) {
Chris@60 126 lastIn2 = n;
cannam@0 127 }
cannam@0 128 q2.push(block);
Chris@60 129
Chris@60 130 ++n;
Chris@60 131 finder->setDurations(lastIn1, lastIn2);
cannam@0 132 }
cannam@0 133
Chris@14 134 MatchFeeder::Features
cannam@0 135 MatchFeeder::feedBlock()
cannam@0 136 {
Chris@14 137 Features ff;
Chris@14 138 vector<double> f1, f2;
Chris@14 139
Chris@60 140 if (q1.empty()) {
Chris@63 141 f2 = feed2();
Chris@60 142 } else if (q2.empty()) {
Chris@63 143 f1 = feed1();
Chris@60 144 } else if (pm1->m_frameCount < pm1->m_blockSize) { // fill initial block
cannam@0 145 // std::cerr << "feeding initial block" << std::endl;
Chris@14 146 f1 = feed1();
Chris@14 147 f2 = feed2();
Chris@60 148 } else if (pm1->m_runCount >= pm1->m_params.maxRunCount) { // slope constraints
cannam@0 149 // std::cerr << "pm1 too slopey" << std::endl;
Chris@14 150 f2 = feed2();
Chris@43 151 } else if (pm2->m_runCount >= pm2->m_params.maxRunCount) {
cannam@0 152 // std::cerr << "pm2 too slopey" << std::endl;
Chris@14 153 f1 = feed1();
cannam@0 154 } else {
cannam@0 155 switch (finder->getExpandDirection
Chris@43 156 (pm1->m_frameCount-1, pm2->m_frameCount-1)) {
Chris@45 157 case Matcher::AdvanceThis:
Chris@14 158 f1 = feed1();
cannam@0 159 break;
Chris@45 160 case Matcher::AdvanceOther:
Chris@14 161 f2 = feed2();
cannam@0 162 break;
Chris@45 163 case Matcher::AdvanceBoth:
Chris@14 164 f1 = feed1();
Chris@14 165 f2 = feed2();
cannam@0 166 break;
Chris@45 167 case Matcher::AdvanceNone:
Chris@45 168 cerr << "finder says AdvanceNone!" << endl;
Chris@45 169 break;
cannam@0 170 }
cannam@0 171 }
Chris@14 172
Chris@14 173 if (!f1.empty()) ff.f1.push_back(f1);
Chris@14 174 if (!f2.empty()) ff.f2.push_back(f2);
Chris@14 175 return ff;
cannam@0 176 }
cannam@0 177
Chris@14 178 vector<double>
cannam@0 179 MatchFeeder::feed1()
cannam@0 180 {
cannam@0 181 // std::cerr << "feed1" << std::endl;
cannam@0 182 float *block = q1.front();
cannam@0 183 q1.pop();
cannam@0 184 for (size_t i = 0; i <= fftSize/2; ++i) {
cannam@0 185 reBuffer[i] = block[i*2];
cannam@0 186 }
cannam@0 187 for (size_t i = 0; i <= fftSize/2; ++i) {
cannam@0 188 imBuffer[i] = block[i*2+1];
cannam@0 189 }
cannam@0 190 delete[] block;
Chris@21 191 return pm1->consumeFrame(reBuffer, imBuffer);
cannam@0 192 }
cannam@0 193
Chris@14 194 vector<double>
cannam@0 195 MatchFeeder::feed2()
cannam@0 196 {
cannam@0 197 // std::cerr << "feed2" << std::endl;
cannam@0 198 float *block = q2.front();
cannam@0 199 q2.pop();
cannam@0 200 for (size_t i = 0; i <= fftSize/2; ++i) {
cannam@0 201 reBuffer[i] = block[i*2];
cannam@0 202 }
cannam@0 203 for (size_t i = 0; i <= fftSize/2; ++i) {
cannam@0 204 imBuffer[i] = block[i*2+1];
cannam@0 205 }
cannam@0 206 delete[] block;
Chris@21 207 return pm2->consumeFrame(reBuffer, imBuffer);
cannam@0 208 }
cannam@0 209