Chris@105: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@105: /* Chris@105: Vamp feature extraction plugin using the MATCH audio alignment Chris@105: algorithm. Chris@105: Chris@105: Centre for Digital Music, Queen Mary, University of London. Chris@105: This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. Chris@105: Chris@105: This program is free software; you can redistribute it and/or Chris@105: modify it under the terms of the GNU General Public License as Chris@105: published by the Free Software Foundation; either version 2 of the Chris@105: License, or (at your option) any later version. See the file Chris@105: COPYING included with this distribution for more information. Chris@105: */ Chris@105: Chris@105: #include "MatchPipeline.h" Chris@105: Chris@140: //#define DEBUG_MATCH_PIPELINE 1 Chris@140: Chris@105: MatchPipeline::MatchPipeline(FeatureExtractor::Parameters feParams, Chris@105: FeatureConditioner::Parameters fcParams, Chris@143: DistanceMetric::Parameters dParams, Chris@105: Matcher::Parameters matchParams) : Chris@105: m_fe1(feParams), Chris@105: m_fe2(feParams), Chris@105: m_fc1(fcParams), Chris@105: m_fc2(fcParams), Chris@143: m_pm1(matchParams, dParams, 0), Chris@143: m_pm2(matchParams, dParams, &m_pm1), Chris@105: m_feeder(&m_pm1, &m_pm2), Chris@105: m_lastFrameIn1(0), Chris@105: m_lastFrameIn2(0), Chris@105: m_frameNo(0) Chris@105: { Chris@105: m_pm1.setOtherMatcher(&m_pm2); Chris@105: } Chris@105: Chris@105: MatchPipeline::~MatchPipeline() Chris@105: { Chris@105: } Chris@105: Chris@105: void Chris@105: MatchPipeline::feedFrequencyDomainAudio(const float *arr1, const float *arr2) Chris@105: { Chris@105: feedFeatures(m_fe1.process(arr1), m_fe2.process(arr2)); Chris@105: } Chris@105: Chris@105: void Chris@105: MatchPipeline::feedFeatures(const vector &f1, const vector &f2) Chris@105: { Chris@106: m_f1 = f1; Chris@106: m_f2 = f2; Chris@106: Chris@140: #ifdef DEBUG_MATCH_PIPELINE Chris@140: if (m_lastFrameIn1 == 1) { Chris@140: cerr << "features 1 -> "; Chris@140: for (int i = 0; i < (int) m_f1.size(); ++i) { Chris@140: cerr << m_f1[i] << " "; Chris@140: } Chris@140: cerr << endl; Chris@140: } Chris@140: #endif Chris@140: Chris@105: feedConditionedFeatures(m_fc1.process(f1), m_fc2.process(f2)); Chris@105: } Chris@105: Chris@105: void Chris@106: MatchPipeline::feedConditionedFeatures(const vector &c1, const vector &c2) Chris@105: { Chris@106: m_c1 = c1; Chris@106: m_c2 = c2; Chris@140: Chris@140: #ifdef DEBUG_MATCH_PIPELINE Chris@140: if (m_lastFrameIn1 == 1) { Chris@140: cerr << "conditioned features 1 -> "; Chris@140: for (int i = 0; i < (int) m_c1.size(); ++i) { Chris@140: cerr << m_c1[i] << " "; Chris@140: } Chris@140: cerr << endl; Chris@140: } Chris@140: #endif Chris@106: Chris@106: m_feeder.feed(c1, c2); Chris@105: Chris@106: if (aboveThreshold(c1)) m_lastFrameIn1 = m_frameNo; Chris@106: if (aboveThreshold(c2)) m_lastFrameIn2 = m_frameNo; Chris@105: Chris@140: #ifdef DEBUG_MATCH_PIPELINE Chris@140: cerr << "last frames are " << m_lastFrameIn1 << ", " << m_lastFrameIn2 Chris@140: << endl; Chris@140: #endif Chris@140: Chris@105: ++m_frameNo; Chris@105: } Chris@105: Chris@106: void Chris@106: MatchPipeline::extractFeatures(vector &f1, vector &f2) Chris@106: { Chris@106: f1 = m_f1; Chris@106: f2 = m_f2; Chris@106: } Chris@106: Chris@106: void Chris@106: MatchPipeline::extractConditionedFeatures(vector &c1, vector &c2) Chris@106: { Chris@106: c1 = m_c1; Chris@106: c2 = m_c2; Chris@106: } Chris@106: Chris@105: bool Chris@105: MatchPipeline::aboveThreshold(const vector &f) Chris@105: { Chris@140: // This threshold is used only to determine when either of the Chris@140: // input streams has ended -- the last frame for a stream is Chris@140: // considered to be the last one that was above the Chris@140: // threshold. This is different from the silence threshold in Chris@140: // FeatureConditioner. Chris@105: double threshold = 1e-4f; Chris@105: double sum = 0.f; Chris@105: for (int i = 0; i < int(f.size()); ++i) { Chris@105: sum += f[i] * f[i]; Chris@105: } Chris@140: #ifdef DEBUG_MATCH_PIPELINE Chris@140: cerr << "aboveThreshold: sum " << sum << ", threshold " << threshold Chris@140: << ", returning " << (sum >= threshold) << endl; Chris@140: #endif Chris@105: return (sum >= threshold); Chris@105: } Chris@105: Chris@105: void Chris@105: MatchPipeline::finish() Chris@105: { Chris@105: m_feeder.finish(); Chris@155: m_feeder.getFinder()->setDurations(m_lastFrameIn1, m_lastFrameIn2); Chris@105: } Chris@105: Chris@155: int Chris@155: MatchPipeline::retrievePath(bool smooth, std::vector &pathx, std::vector &pathy) Chris@135: { Chris@155: return m_feeder.getFinder()->retrievePath(smooth, pathx, pathy); Chris@135: } Chris@135: Chris@155: void Chris@155: MatchPipeline::retrieveForwardPath(std::vector &pathx, std::vector &pathy) { Chris@155: return m_feeder.retrieveForwardPath(pathx, pathy); Chris@105: } Chris@105: Chris@105: Chris@105: