# HG changeset patch # User Chris Cannam # Date 1417701245 0 # Node ID 4b263ef50c9be2eee0744ca802ca2d732116b7c5 # Parent 2e6144da14af99808d2993317746099d2f6d49c0# Parent a07b962e9f0372ef41bb363ccf376a815b2b4de2 Merge from branch feature_conditioner, but leave the confidence calculation unfinished (need to move this) diff -r 2e6144da14af -r 4b263ef50c9b src/FeatureConditioner.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/FeatureConditioner.cpp Thu Dec 04 13:54:05 2014 +0000 @@ -0,0 +1,80 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "FeatureConditioner.h" + +#include + +using namespace std; + +vector +FeatureConditioner::process(const vector &feature) +{ + if (m_prev.empty()) { + m_prev.resize(feature.size(), 0.0); + } + if (m_prev.size() != feature.size()) { + cerr << "ERROR: FeatureConditioner::process: feature size " + << feature.size() << " differs from previous feature size " + << m_prev.size() << endl; + return feature; + } + + int size = feature.size(); + + vector out(size, 0.0); + + double totalEnergy = 0; + if (m_params.order == OutputRectifiedDerivative) { + for (int i = 0; i < size; i++) { + totalEnergy += feature[i]; + if (feature[i] > m_prev[i]) { + out[i] = feature[i] - m_prev[i]; + } else { + out[i] = 0; + } + } + } else { + for (int i = 0; i < size; i++) { + out[i] = feature[i]; + totalEnergy += out[i]; + } + } + + if (m_ltAverage == 0) { + m_ltAverage = totalEnergy; + } else { + double decay = m_params.decay; + m_ltAverage = m_ltAverage * decay + totalEnergy * (1.0 - decay); + } + + if (totalEnergy <= m_params.silenceThreshold) { + for (int i = 0; i < size; i++) { + out[i] = 0; + } + } else if (m_params.norm == NormaliseToSum1) { + for (int i = 0; i < size; i++) { + out[i] /= totalEnergy; + } + } else if (m_params.norm == NormaliseToLTAverage) { + for (int i = 0; i < size; i++) { + out[i] /= m_ltAverage; + } + } + + m_prev = feature; + return out; +} + diff -r 2e6144da14af -r 4b263ef50c9b src/FeatureConditioner.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/FeatureConditioner.h Thu Dec 04 13:54:05 2014 +0000 @@ -0,0 +1,105 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef FEATURE_CONDITIONER_H +#define FEATURE_CONDITIONER_H + +#include + +/** + * Take a series of feature vectors and apply conditioning of some + * sort, such as normalisation or first-order derivative. + * + * Note that FeatureConditioner maintains internal frame-to-frame + * state: use one FeatureConditioner per audio source, and construct a + * new one for each new source. + */ +class FeatureConditioner +{ +public: + enum Normalisation { + + /** Do not normalise */ + NoNormalisation, + + /** Normalise each feature vector to have a sum of 1 */ + NormaliseToSum1, + + /** Normalise each feature vector by the long-term average of + * the summed energy */ + NormaliseToLTAverage, + }; + + enum OutputOrder { + + /** Output the normalised features without further processing */ + OutputFeatures, + + /** Output the half-wave rectified difference between the + * previous and current features instead of the straight + * feature values. */ + OutputRectifiedDerivative, + }; + + struct Parameters { + + Parameters() : + norm(NormaliseToSum1), + order(OutputRectifiedDerivative), + silenceThreshold(0.01), + decay(0.99) + {} + + /** Feature normalisation. */ + Normalisation norm; + + /** Type of output to generate (plain feature, derivative etc). */ + OutputOrder order; + + /** Silence threshold. If non-zero, any feature whose total + * energy (simply the sum of feature values) is below that + * threshold will be rounded down to all zeros. */ + double silenceThreshold; + + /** Frame-to-frame decay factor in calculating long-term average */ + double decay; + }; + + /** + * Construct a FeatureExtractor with the given parameters. + * + * Note that FeatureExtractor maintains internal frame-to-frame + * state: use one FeatureExtractor per audio source, and construct + * a new one for each new source. + */ + FeatureConditioner(Parameters parameters) : m_params(parameters) { } + + /** + * Process the given feature and return the conditioned feature. + */ + std::vector process(const std::vector &feature); + +protected: + Parameters m_params; + + /** Long term average feature energy. */ + double m_ltAverage; + + /** The most recent feature, used for calculating the feature to + * feature difference. This is therefore not yet normalised. */ + std::vector m_prev; +}; + +#endif diff -r 2e6144da14af -r 4b263ef50c9b src/FeatureExtractor.cpp --- a/src/FeatureExtractor.cpp Thu Dec 04 10:24:35 2014 +0000 +++ b/src/FeatureExtractor.cpp Thu Dec 04 13:54:05 2014 +0000 @@ -25,12 +25,9 @@ using namespace std; FeatureExtractor::FeatureExtractor(Parameters parameters) : - m_params(parameters), - m_ltAverage(0) + m_params(parameters) { m_featureSize = getFeatureSizeFor(parameters); - m_prevFrame = vector(m_featureSize, 0.0); - makeFreqMap(); } @@ -107,15 +104,12 @@ { vector frame(m_featureSize, 0.0); - double rms = 0; for (int i = 0; i <= m_params.fftSize/2; i++) { double mag = real[i] * real[i] + imag[i] * imag[i]; - rms += mag; frame[m_freqMap[i]] += mag; } - rms = sqrt(rms / (m_params.fftSize/2)); - return postProcess(frame, rms); + return frame; } vector @@ -123,61 +117,11 @@ { vector frame(m_featureSize, 0.0); - double rms = 0; for (int i = 0; i <= m_params.fftSize/2; i++) { double mag = cframe[i*2] * cframe[i*2] + cframe[i*2+1] * cframe[i*2+1]; - rms += mag; frame[m_freqMap[i]] += mag; } - rms = sqrt(rms / (m_params.fftSize/2)); - return postProcess(frame, rms); + return frame; } -vector -FeatureExtractor::postProcess(const vector &frame, double rms) -{ - vector feature(m_featureSize, 0.0); - - double totalEnergy = 0; - if (m_params.useSpectralDifference) { - for (int i = 0; i < m_featureSize; i++) { - totalEnergy += frame[i]; - if (frame[i] > m_prevFrame[i]) { - feature[i] = frame[i] - m_prevFrame[i]; - } else { - feature[i] = 0; - } - } - } else { - for (int i = 0; i < m_featureSize; i++) { - feature[i] = frame[i]; - totalEnergy += feature[i]; - } - } - - if (m_ltAverage == 0) { - m_ltAverage = totalEnergy; - } else { - double decay = m_params.decay; - m_ltAverage = m_ltAverage * decay + totalEnergy * (1.0 - decay); - } - - if (rms <= m_params.silenceThreshold) { - for (int i = 0; i < m_featureSize; i++) { - feature[i] = 0; - } - } else if (m_params.frameNorm == NormaliseFrameToSum1) { - for (int i = 0; i < m_featureSize; i++) { - feature[i] /= totalEnergy; - } - } else if (m_params.frameNorm == NormaliseFrameToLTAverage) { - for (int i = 0; i < m_featureSize; i++) { - feature[i] /= m_ltAverage; - } - } - - m_prevFrame = frame; - return feature; -} - diff -r 2e6144da14af -r 4b263ef50c9b src/FeatureExtractor.h --- a/src/FeatureExtractor.h Thu Dec 04 10:24:35 2014 +0000 +++ b/src/FeatureExtractor.h Thu Dec 04 13:54:05 2014 +0000 @@ -25,50 +25,24 @@ * the frequency data to map higher frequencies into a linear scale. A * chroma mapping is also available. * - * Note that FeatureExtractor maintains internal frame-to-frame state: - * use one FeatureExtractor per audio source, and construct a new one - * for each new source. + * Note that FeatureExtractor may maintain internal frame-to-frame + * state: use one FeatureExtractor per audio source, and construct a + * new one for each new source. */ class FeatureExtractor { public: - enum FrameNormalisation { - - /** Do not normalise frames */ - NoFrameNormalisation, - - /** Normalise each frame to have a sum of 1 */ - NormaliseFrameToSum1, - - /** Normalise each frame by the long-term average of the - * summed energy */ - NormaliseFrameToLTAverage, - }; - struct Parameters { Parameters(float rate_, int fftSize_) : sampleRate(rate_), - frameNorm(NormaliseFrameToSum1), - useSpectralDifference(true), useChromaFrequencyMap(false), - fftSize(fftSize_), - silenceThreshold(0.01), - decay(0.99) + fftSize(fftSize_) {} /** Sample rate of audio */ float sampleRate; - /** Type of audio frame normalisation */ - FrameNormalisation frameNorm; - - /** Flag indicating whether or not the half-wave rectified - * spectral difference should be used in calculating the - * distance metric for pairs of audio frames, instead of the - * straight spectrum values. */ - bool useSpectralDifference; - /** Flag indicating whether to use a chroma frequency map (12 * bins) instead of the default warped spectrogram */ bool useChromaFrequencyMap; @@ -82,12 +56,6 @@ * in is already in the frequency domain, so this expresses * the size of the frame that the caller will be providing. */ int fftSize; - - /** RMS level below which frame is considered silent */ - double silenceThreshold; - - /** Frame-to-frame decay factor in calculating long-term average */ - double decay; }; /** @@ -117,12 +85,8 @@ * have at least params.fftSize/2+1 elements each. * * Operates by mapping the frequency bins into a part-linear - * part-logarithmic array, then (optionally) computing the - * half-wave rectified spectral difference from the previous - * frame, then (optionally) normalising to a sum of 1. - * - * Return value is the frame (post-processed, with warping, - * rectification, and normalisation as appropriate). + * part-logarithmic array, unless useChromaFrequencyMap is true in + * which case they are mapped into chroma bins. */ std::vector process(const std::vector &real, const std::vector &imag); @@ -133,12 +97,8 @@ * must have at least 2 * (params.fftSize/2 + 1) elements. * * Operates by mapping the frequency bins into a part-linear - * part-logarithmic array, then (optionally) computing the - * half-wave rectified spectral difference from the previous - * frame, then (optionally) normalising to a sum of 1. - * - * Return value is the frame (post-processed, with warping, - * rectification, and normalisation as appropriate). + * part-logarithmic array, unless useChromaFrequencyMap is true in + * which case they are mapped into chroma bins. */ std::vector process(const float *carray); @@ -157,14 +117,8 @@ /** Creates a map of FFT frequency bins to semitone chroma bins. */ void makeChromaFrequencyMap(); - std::vector postProcess(const std::vector &, double rms); - /** Configuration parameters */ Parameters m_params; - - /** Long term average frame energy (in frequency domain - * representation). */ - double m_ltAverage; /** A mapping function for mapping FFT bins to final frequency * bins. The mapping is linear (1-1) until the resolution @@ -179,11 +133,6 @@ /** The size of a returned feature. */ int m_featureSize; - - /** The most recent frame; used for calculating the frame to frame - * spectral difference. This is therefore frequency warped but - * not yet normalised. */ - std::vector m_prevFrame; }; #endif diff -r 2e6144da14af -r 4b263ef50c9b src/MatchPipeline.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/MatchPipeline.cpp Thu Dec 04 13:54:05 2014 +0000 @@ -0,0 +1,108 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "MatchPipeline.h" + +MatchPipeline::MatchPipeline(FeatureExtractor::Parameters feParams, + FeatureConditioner::Parameters fcParams, + Matcher::Parameters matchParams) : + m_fe1(feParams), + m_fe2(feParams), + m_fc1(fcParams), + m_fc2(fcParams), + m_pm1(matchParams, 0), + m_pm2(matchParams, &m_pm1), + m_feeder(&m_pm1, &m_pm2), + m_lastFrameIn1(0), + m_lastFrameIn2(0), + m_frameNo(0) +{ + m_pm1.setOtherMatcher(&m_pm2); +} + +MatchPipeline::~MatchPipeline() +{ +} + +void +MatchPipeline::feedFrequencyDomainAudio(const float *arr1, const float *arr2) +{ + feedFeatures(m_fe1.process(arr1), m_fe2.process(arr2)); +} + +void +MatchPipeline::feedFeatures(const vector &f1, const vector &f2) +{ + m_f1 = f1; + m_f2 = f2; + + feedConditionedFeatures(m_fc1.process(f1), m_fc2.process(f2)); +} + +void +MatchPipeline::feedConditionedFeatures(const vector &c1, const vector &c2) +{ + m_c1 = c1; + m_c2 = c2; + + m_feeder.feed(c1, c2); + + if (aboveThreshold(c1)) m_lastFrameIn1 = m_frameNo; + if (aboveThreshold(c2)) m_lastFrameIn2 = m_frameNo; + + ++m_frameNo; +} + +void +MatchPipeline::extractFeatures(vector &f1, vector &f2) +{ + f1 = m_f1; + f2 = m_f2; +} + +void +MatchPipeline::extractConditionedFeatures(vector &c1, vector &c2) +{ + c1 = m_c1; + c2 = m_c2; +} + +bool +MatchPipeline::aboveThreshold(const vector &f) +{ + double threshold = 1e-4f; + double sum = 0.f; + for (int i = 0; i < int(f.size()); ++i) { + sum += f[i] * f[i]; + } + return (sum >= threshold); +} + +void +MatchPipeline::finish() +{ + m_feeder.finish(); + getFinder()->setDurations(m_lastFrameIn1, m_lastFrameIn2); +} + +Finder * +MatchPipeline::getFinder() +{ + return m_feeder.getFinder(); +} + + + + diff -r 2e6144da14af -r 4b263ef50c9b src/MatchPipeline.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/MatchPipeline.h Thu Dec 04 13:54:05 2014 +0000 @@ -0,0 +1,111 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ +/* + Vamp feature extraction plugin using the MATCH audio alignment + algorithm. + + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2007 Simon Dixon, Chris Cannam and QMUL. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef MATCH_PIPELINE_H +#define MATCH_PIPELINE_H + +#include "Matcher.h" +#include "Finder.h" +#include "FeatureExtractor.h" +#include "FeatureConditioner.h" +#include "MatchFeatureFeeder.h" + +class MatchPipeline +{ +public: + /** + * Pipeline consisting of two Matchers, two FeatureConditioners, + * two FeatureExtractors, and a Finder. Features may be inserted + * at any point in the pipeline. + * + * The pipeline goes: + * Frequency-domain audio + * -> Features + * -> Conditioned features + * -> Matcher + */ + MatchPipeline(FeatureExtractor::Parameters feParams, + FeatureConditioner::Parameters fcParams, + Matcher::Parameters matchParams); + + ~MatchPipeline(); + + /** + * Feed in data at the first pipeline stage. The input arrays + * represent frames of audio from the two different sources. Each + * is provided as a single array of alternating real and imaginary + * components. + * + * Input arrays must have at least 2 * (feParams.fftSize/2 + 1) + * elements. The arrays will be passed to FeatureExtractor and + * then on into the rest of the pipeline. + */ + void feedFrequencyDomainAudio(const float *arr1, const float *arr2); + + /** + * Feed in data at the second pipeline stage. The vectors + * represent feature frames from two different sources. They will + * be passed in to FeatureConditioner and then on to the rest of + * the pipeline. + */ + void feedFeatures(const vector &f1, const vector &f2); + + /** + * Feed in data at the third pipeline stage. The vectors represent + * conditioned feature frames from two different sources. They + * will be passed to MatchFeatureFeeder for feeding to the two + * matchers. + */ + void feedConditionedFeatures(const vector &f1, const vector &f2); + + /** + * If a frame was just fed in at the first or second pipeline + * stage, it can be retrieved from the second stage here. That is, + * if you provided frequency-domain audio, extractFeatures will + * give you back the FeatureExtractor's features. + */ + void extractFeatures(vector &f1, vector &f2); + + /** + * Retrieve the conditioned features from the third pipeline stage. + */ + void extractConditionedFeatures(vector &f1, vector &f2); + + /** + * Indicate that both inputs have come to an end. + */ + void finish(); + + Finder *getFinder(); + +private: + FeatureExtractor m_fe1; + FeatureExtractor m_fe2; + FeatureConditioner m_fc1; + FeatureConditioner m_fc2; + Matcher m_pm1; + Matcher m_pm2; + MatchFeatureFeeder m_feeder; + int m_lastFrameIn1; + int m_lastFrameIn2; + int m_frameNo; + vector m_f1; + vector m_f2; + vector m_c1; + vector m_c2; + bool aboveThreshold(const vector &f); +}; + +#endif diff -r 2e6144da14af -r 4b263ef50c9b src/MatchVampPlugin.cpp --- a/src/MatchVampPlugin.cpp Thu Dec 04 10:24:35 2014 +0000 +++ b/src/MatchVampPlugin.cpp Thu Dec 04 13:54:05 2014 +0000 @@ -61,12 +61,12 @@ m_locked(false), m_smooth(true), m_frameNo(0), - m_lastFrameIn1(0), - m_lastFrameIn2(0), m_params(inputSampleRate, defaultStepTime, m_blockSize), m_defaultParams(inputSampleRate, defaultStepTime, m_blockSize), m_feParams(inputSampleRate, m_blockSize), - m_defaultFeParams(inputSampleRate, m_blockSize) + m_defaultFeParams(inputSampleRate, m_blockSize), + m_fcParams(), + m_defaultFcParams() { if (inputSampleRate < sampleRateMin) { cerr << "MatchVampPlugin::MatchVampPlugin: input sample rate " @@ -84,23 +84,14 @@ #endif } - m_pm1 = 0; - m_pm2 = 0; - m_fe1 = 0; - m_fe2 = 0; - m_feeder = 0; -// cerr << "MatchVampPlugin::MatchVampPlugin(" << this << "): extant = " << ++extant << endl; + m_pipeline = 0; } MatchVampPlugin::~MatchVampPlugin() { // cerr << "MatchVampPlugin::~MatchVampPlugin(" << this << "): extant = " << --extant << endl; - delete m_feeder; - delete m_fe1; - delete m_fe2; - delete m_pm1; - delete m_pm2; + delete m_pipeline; if (m_locked) { #ifdef _WIN32 @@ -170,7 +161,7 @@ desc.description = "Type of normalisation to use for frequency-domain audio features"; desc.minValue = 0; desc.maxValue = 2; - desc.defaultValue = (int)m_defaultFeParams.frameNorm; + desc.defaultValue = (int)m_defaultFcParams.norm; desc.isQuantized = true; desc.quantizeStep = 1; desc.valueNames.clear(); @@ -200,7 +191,7 @@ desc.description = "Whether to use half-wave rectified spectral difference instead of straight spectrum"; desc.minValue = 0; desc.maxValue = 1; - desc.defaultValue = m_defaultFeParams.useSpectralDifference ? 1 : 0; + desc.defaultValue = (int)m_defaultFcParams.order; desc.isQuantized = true; desc.quantizeStep = 1; list.push_back(desc); @@ -266,11 +257,11 @@ if (name == "serialise") { return m_serialise ? 1.0 : 0.0; } else if (name == "framenorm") { - return (int)m_feParams.frameNorm; + return (int)m_fcParams.norm; } else if (name == "distnorm") { return (int)m_params.distanceNorm; } else if (name == "usespecdiff") { - return m_feParams.useSpectralDifference ? 1.0 : 0.0; + return (int)m_fcParams.order; } else if (name == "usechroma") { return m_feParams.useChromaFrequencyMap ? 1.0 : 0.0; } else if (name == "gradientlimit") { @@ -292,11 +283,11 @@ if (name == "serialise") { m_serialise = (value > 0.5); } else if (name == "framenorm") { - m_feParams.frameNorm = (FeatureExtractor::FrameNormalisation)(int(value + 0.1)); + m_fcParams.norm = (FeatureConditioner::Normalisation)(int(value + 0.1)); } else if (name == "distnorm") { m_params.distanceNorm = (DistanceMetric::DistanceNormalisation)(int(value + 0.1)); } else if (name == "usespecdiff") { - m_feParams.useSpectralDifference = (value > 0.5); + m_fcParams.order = (FeatureConditioner::OutputOrder)(int(value + 0.1)); } else if (name == "usechroma") { m_feParams.useChromaFrequencyMap = (value > 0.5); } else if (name == "gradientlimit") { @@ -328,12 +319,8 @@ m_params.hopTime = m_stepTime; m_params.fftSize = m_blockSize; m_feParams.fftSize = m_blockSize; - m_fe1 = new FeatureExtractor(m_feParams); - m_fe2 = new FeatureExtractor(m_feParams); - m_pm1 = new Matcher(m_params, 0, m_fe1->getFeatureSize()); - m_pm2 = new Matcher(m_params, m_pm1, m_fe2->getFeatureSize()); - m_pm1->setOtherMatcher(m_pm2); - m_feeder = new MatchFeatureFeeder(m_pm1, m_pm2); + + m_pipeline = new MatchPipeline(m_feParams, m_fcParams, m_params); } bool @@ -364,21 +351,9 @@ void MatchVampPlugin::reset() { - delete m_feeder; - delete m_fe1; - delete m_fe2; - delete m_pm1; - delete m_pm2; - - m_feeder = 0; - m_fe1 = 0; - m_fe2 = 0; - m_pm1 = 0; - m_pm2 = 0; - + delete m_pipeline; + m_pipeline = 0; m_frameNo = 0; - m_lastFrameIn1 = 0; - m_lastFrameIn2 = 0; m_mag1.clear(); m_mag2.clear(); @@ -532,18 +507,6 @@ return list; } -bool -MatchVampPlugin::aboveThreshold(const float *frame) -{ - float threshold = 1e-5f; - float rms = 0.f; - for (int i = 0; i < m_blockSize/2 + 2; ++i) { - rms += frame[i] * frame[i]; - } - rms = sqrtf(rms / (m_blockSize/2 + 2)); - return (rms > threshold); -} - MatchVampPlugin::FeatureSet MatchVampPlugin::process(const float *const *inputBuffers, Vamp::RealTime timestamp) @@ -563,13 +526,10 @@ // cerr << timestamp.toString(); - if (aboveThreshold(inputBuffers[0])) m_lastFrameIn1 = m_frameNo; - if (aboveThreshold(inputBuffers[1])) m_lastFrameIn2 = m_frameNo; + m_pipeline->feedFrequencyDomainAudio(inputBuffers[0], inputBuffers[1]); - vector f1 = m_fe1->process(inputBuffers[0]); - vector f2 = m_fe2->process(inputBuffers[1]); - - m_feeder->feed(f1, f2); + vector f1, f2; + m_pipeline->extractConditionedFeatures(f1, f2); FeatureSet returnFeatures; @@ -607,12 +567,11 @@ MatchVampPlugin::FeatureSet MatchVampPlugin::getRemainingFeatures() { - m_feeder->finish(); + m_pipeline->finish(); FeatureSet returnFeatures; - Finder *finder = m_feeder->getFinder(); - finder->setDurations(m_lastFrameIn1, m_lastFrameIn2); + Finder *finder = m_pipeline->getFinder(); vector pathx; vector pathy; int len = finder->retrievePath(false, pathx, pathy); //!!! smooth @@ -629,7 +588,8 @@ int y = pathy[i]; if (x != prevx) { double magSum = m_mag1[y] + m_mag2[x]; - double distance = m_pm1->getDistance(y, x); +// double distance = m_pm1->getDistance(y, x); + double distance = 0;///!!! float c = magSum - distance; confidence.push_back(c); } @@ -701,7 +661,8 @@ returnFeatures[m_abDivOutNo].push_back(feature); double magSum = m_mag1[y] + m_mag2[x]; - double distance = m_pm1->getDistance(y, x); +// double distance = m_pm1->getDistance(y, x); + double distance = 0;///!!! feature.values.clear(); feature.values.push_back(distance); @@ -739,13 +700,9 @@ prevx = x; prevy = y; } - - delete m_feeder; - delete m_pm1; - delete m_pm2; - m_feeder = 0; - m_pm1 = 0; - m_pm2 = 0; + + delete m_pipeline; + m_pipeline = 0; if (m_locked) { #ifdef _WIN32 diff -r 2e6144da14af -r 4b263ef50c9b src/MatchVampPlugin.h --- a/src/MatchVampPlugin.h Thu Dec 04 10:24:35 2014 +0000 +++ b/src/MatchVampPlugin.h Thu Dec 04 13:54:05 2014 +0000 @@ -25,10 +25,7 @@ #include #endif -#include "Matcher.h" -#include "FeatureExtractor.h" - -class MatchFeatureFeeder; +#include "MatchPipeline.h" class MatchVampPlugin : public Vamp::Plugin { @@ -69,11 +66,7 @@ void createMatchers(); bool aboveThreshold(const float *); - Matcher *m_pm1; - Matcher *m_pm2; - FeatureExtractor *m_fe1; - FeatureExtractor *m_fe2; - MatchFeatureFeeder *m_feeder; + MatchPipeline *m_pipeline; Vamp::RealTime m_startTime; int m_stepSize; @@ -94,6 +87,9 @@ FeatureExtractor::Parameters m_feParams; FeatureExtractor::Parameters m_defaultFeParams; + FeatureConditioner::Parameters m_fcParams; + FeatureConditioner::Parameters m_defaultFcParams; + std::vector m_mag1; std::vector m_mag2; diff -r 2e6144da14af -r 4b263ef50c9b src/Matcher.cpp --- a/src/Matcher.cpp Thu Dec 04 10:24:35 2014 +0000 +++ b/src/Matcher.cpp Thu Dec 04 13:54:05 2014 +0000 @@ -25,13 +25,12 @@ //#define DEBUG_MATCHER 1 -Matcher::Matcher(Parameters parameters, Matcher *p, int m_featureSize_) : +Matcher::Matcher(Parameters parameters, Matcher *p) : m_params(parameters), - m_featureSize(m_featureSize_), m_metric(parameters.distanceNorm) { #ifdef DEBUG_MATCHER - cerr << "Matcher::Matcher(" << m_params.sampleRate << ", " << p << ", " << m_featureSize << ")" << endl; + cerr << "Matcher::Matcher(" << m_params.sampleRate << ", " << p << ")" << endl; #endif m_otherMatcher = p; // the first matcher will need this to be set later @@ -60,8 +59,7 @@ { if (m_initialised) return; - m_frames = vector > - (m_blockSize, vector(m_featureSize, -1.0)); + m_frames = vector >(m_blockSize); m_distXSize = m_blockSize * 2; diff -r 2e6144da14af -r 4b263ef50c9b src/Matcher.h --- a/src/Matcher.h Thu Dec 04 10:24:35 2014 +0000 +++ b/src/Matcher.h Thu Dec 04 13:54:05 2014 +0000 @@ -119,11 +119,8 @@ * this one is going to be matched. Some information is shared * between the two matchers (currently one possesses the distance * matrix and optimal path matrix). - * - * @param featureSize Number of values in each of the feature - * vectors that will be provided. */ - Matcher(Parameters parameters, Matcher *p, int featureSize); + Matcher(Parameters parameters, Matcher *p); /** Destructor for Matcher. */ @@ -165,8 +162,8 @@ * updating the optimal path matrix using the dynamic time * warping algorithm. * - * The supplied feature must be of the size that was passed as - * featureSize to the constructor. + * The supplied features must always be of the same size (within + * any pair of Matcher objects). */ void consumeFeatureVector(std::vector feature); @@ -297,9 +294,6 @@ */ int m_runCount; - /** The number of values in a feature vector. */ - int m_featureSize; - /** A block of previously seen feature frames is stored in this * structure for calculation of the distance matrix as the new * frames are received. One can think of the structure of the