cannam@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@0: cannam@0: /* cannam@0: Vamp feature extraction plugin using the MATCH audio alignment cannam@0: algorithm. cannam@0: cannam@0: Centre for Digital Music, Queen Mary, University of London. cannam@0: This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. cannam@0: cannam@0: This program is free software; you can redistribute it and/or cannam@0: modify it under the terms of the GNU General Public License as cannam@0: published by the Free Software Foundation; either version 2 of the cannam@0: License, or (at your option) any later version. See the file cannam@0: COPYING included with this distribution for more information. cannam@0: */ cannam@0: cannam@0: #include "MatchFeeder.h" cannam@0: cannam@0: MatchFeeder::MatchFeeder(Matcher *m1, Matcher *m2) : cannam@0: pm1(m1), pm2(m2) cannam@0: { cannam@0: fftSize = m1->fftSize; cannam@0: finder = new Finder(m1, m2); cannam@0: reBuffer = new double[fftSize/2+1]; cannam@0: imBuffer = new double[fftSize/2+1]; cannam@0: } cannam@0: cannam@0: MatchFeeder::~MatchFeeder() cannam@0: { cannam@0: delete[] imBuffer; cannam@0: delete[] reBuffer; cannam@0: while (!q1.empty()) { cannam@0: delete[] q1.front(); cannam@0: q1.pop(); cannam@0: } cannam@0: while (!q2.empty()) { cannam@0: delete[] q2.front(); cannam@0: q2.pop(); cannam@0: } cannam@0: delete finder; cannam@0: } cannam@0: cannam@0: void cannam@0: MatchFeeder::feed(const float *const *input) cannam@0: { cannam@0: // We maintain two FIFO queues of audio data frame block pointers, cannam@0: // one per input stream. When the match-feeder function is cannam@0: // entered, it knows that it has at least one block in each queue. cannam@0: // It loops, processing up to one block per matcher, until a queue cannam@0: // is empty. Then it returns, to be called again with more data. cannam@0: cannam@0: float *block = new float[fftSize+2]; cannam@0: for (size_t i = 0; i < fftSize+2; ++i) { cannam@0: block[i] = input[0][i]; cannam@0: } cannam@0: q1.push(block); cannam@0: cannam@0: block = new float[fftSize+2]; cannam@0: for (size_t i = 0; i < fftSize+2; ++i) { cannam@0: block[i] = input[1][i]; cannam@0: } cannam@0: q2.push(block); cannam@0: cannam@0: while (!q1.empty() && !q2.empty()) { cannam@0: // std::cerr << "MatchFeeder::feed: q1 " << q1.size() << " q2 " << q2.size() << std::endl; cannam@0: feedBlock(); cannam@0: } cannam@0: } cannam@0: cannam@0: void cannam@0: MatchFeeder::feedBlock() cannam@0: { cannam@0: if (pm1->frameCount < pm1->blockSize) { // fill initial block cannam@0: // std::cerr << "feeding initial block" << std::endl; cannam@0: feed1(); cannam@0: feed2(); cannam@0: } cannam@0: //!!! } else if (pm1->atEnd) { cannam@0: // feed2(); cannam@0: //!!! } else if (pm2->atEnd) cannam@0: // feed1(); cannam@0: else if (pm1->runCount >= Matcher::MAX_RUN_COUNT) { // slope constraints cannam@0: // std::cerr << "pm1 too slopey" << std::endl; cannam@0: feed2(); cannam@0: } else if (pm2->runCount >= Matcher::MAX_RUN_COUNT) { cannam@0: // std::cerr << "pm2 too slopey" << std::endl; cannam@0: feed1(); cannam@0: } else { cannam@0: switch (finder->getExpandDirection cannam@0: (pm1->frameCount-1, pm2->frameCount-1)) { cannam@0: case ADVANCE_THIS: cannam@0: // std::cerr << "finder says ADVANCE_THIS" << std::endl; cannam@0: feed1(); cannam@0: break; cannam@0: case ADVANCE_OTHER: cannam@0: // std::cerr << "finder says ADVANCE_OTHER" << std::endl; cannam@0: feed2(); cannam@0: break; cannam@0: case ADVANCE_BOTH: cannam@0: // std::cerr << "finder says ADVANCE_BOTH" << std::endl; cannam@0: feed1(); cannam@0: feed2(); cannam@0: break; cannam@0: } cannam@0: } cannam@0: } cannam@0: cannam@0: void cannam@0: MatchFeeder::feed1() cannam@0: { cannam@0: // std::cerr << "feed1" << std::endl; cannam@0: float *block = q1.front(); cannam@0: q1.pop(); cannam@0: for (size_t i = 0; i <= fftSize/2; ++i) { cannam@0: reBuffer[i] = block[i*2]; cannam@0: } cannam@0: for (size_t i = 0; i <= fftSize/2; ++i) { cannam@0: imBuffer[i] = block[i*2+1]; cannam@0: } cannam@0: delete[] block; cannam@0: pm1->processFrame(reBuffer, imBuffer); cannam@0: } cannam@0: cannam@0: void cannam@0: MatchFeeder::feed2() cannam@0: { cannam@0: // std::cerr << "feed2" << std::endl; cannam@0: float *block = q2.front(); cannam@0: q2.pop(); cannam@0: for (size_t i = 0; i <= fftSize/2; ++i) { cannam@0: reBuffer[i] = block[i*2]; cannam@0: } cannam@0: for (size_t i = 0; i <= fftSize/2; ++i) { cannam@0: imBuffer[i] = block[i*2+1]; cannam@0: } cannam@0: delete[] block; cannam@0: pm2->processFrame(reBuffer, imBuffer); cannam@0: } cannam@0: