changeset 23:64c4c0cf80c9

Add alternate Matcher API calls to provide external feature data
author Chris Cannam
date Fri, 10 Oct 2014 16:27:45 +0100
parents ac39717fc88d
children 89929e9e54fb
files MatchVampPlugin.cpp Matcher.cpp Matcher.h
diffstat 3 files changed, 113 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/MatchVampPlugin.cpp	Fri Oct 10 16:27:29 2014 +0100
+++ b/MatchVampPlugin.cpp	Fri Oct 10 16:27:45 2014 +0100
@@ -394,7 +394,7 @@
     desc.description = "Spectral features extracted from performance A";
     desc.unit = "";
     desc.hasFixedBinCount = true;
-    desc.binCount = Matcher::getFeatureSize(m_params);
+    desc.binCount = Matcher::getFeatureSizeFor(m_params);
     desc.hasKnownExtents = false;
     desc.isQuantized = false;
     desc.sampleType = OutputDescriptor::FixedSampleRate;
@@ -407,7 +407,7 @@
     desc.description = "Spectral features extracted from performance B";
     desc.unit = "";
     desc.hasFixedBinCount = true;
-    desc.binCount = Matcher::getFeatureSize(m_params);
+    desc.binCount = Matcher::getFeatureSizeFor(m_params);
     desc.hasKnownExtents = false;
     desc.isQuantized = false;
     desc.sampleType = OutputDescriptor::FixedSampleRate;
--- a/Matcher.cpp	Fri Oct 10 16:27:29 2014 +0100
+++ b/Matcher.cpp	Fri Oct 10 16:27:45 2014 +0100
@@ -37,6 +37,40 @@
     ltAverage = 0;
     frameCount = 0;
     runCount = 0;
+    freqMapSize = 0;
+    externalFeatureSize = 0;
+    featureSize = 0;
+    blockSize = 0;
+    scale = 90;
+
+    blockSize = lrint(params.blockTime / params.hopTime);
+#ifdef DEBUG_MATCHER
+    cerr << "Matcher: blockSize = " << blockSize << endl;
+#endif
+
+    distance = 0;
+    bestPathCost = 0;
+    distYSizes = 0;
+    distXSize = 0;
+
+    initialised = false;
+}
+
+Matcher::Matcher(Parameters parameters, Matcher *p, int featureSize) :
+    params(parameters),
+    externalFeatureSize(featureSize)
+{
+#ifdef DEBUG_MATCHER
+    cerr << "Matcher::Matcher(" << params.sampleRate << ", " << p << ", " << featureSize << ")" << endl;
+#endif
+
+    otherMatcher = p;	// the first matcher will need this to be set later
+    firstPM = (!p);
+    ltAverage = 0;
+    frameCount = 0;
+    runCount = 0;
+    freqMapSize = 0;
+    featureSize = 0;
     blockSize = 0;
     scale = 90;
 
@@ -52,7 +86,7 @@
 
     initialised = false;
 
-} // default constructor
+} 
 
 Matcher::~Matcher()
 {
@@ -85,13 +119,17 @@
 
     initialised = true;
 
-    freqMapSize = getFeatureSize(params);
+    if (externalFeatureSize == 0) {
+        freqMapSize = getFeatureSizeFor(params);
+        featureSize = freqMapSize;
+        makeFreqMap();
+    } else {
+        featureSize = externalFeatureSize;
+    }
 
-    makeFreqMap();
-
-    initVector<double>(prevFrame, freqMapSize);
-    initVector<double>(newFrame, freqMapSize);
-    initMatrix<double>(frames, blockSize, freqMapSize);
+    initVector<double>(prevFrame, featureSize);
+    initVector<double>(newFrame, featureSize);
+    initMatrix<double>(frames, blockSize, featureSize);
     initVector<double>(totalEnergies, blockSize);
 
     int distSize = (params.maxRunCount + 1) * blockSize;
@@ -124,6 +162,7 @@
 Matcher::makeFreqMap()
 {
     initVector<int>(freqMap, params.fftSize/2 + 1);
+
     if (params.useChromaFrequencyMap) {
 #ifdef DEBUG_MATCHER
         cerr << "makeFreqMap: calling makeChromaFrequencyMap" << endl;
@@ -138,7 +177,7 @@
 } // makeFreqMap()
 
 int
-Matcher::getFeatureSize(Parameters params)
+Matcher::getFeatureSizeFor(Parameters params)
 {
     if (params.useChromaFrequencyMap) {
         return 13;
@@ -205,13 +244,16 @@
 
     calcAdvance();
 
-    if ((frameCount % 100) == 0) {
-        if (!silent) {
-            cerr << "Progress:" << frameCount << " " << ltAverage << endl;
-        }
-    }
+    return processedFrame;
+}
 
-    return processedFrame;
+void
+Matcher::consumeFeatureVector(std::vector<double> feature)
+{
+    if (!initialised) init();
+    int frameIndex = frameCount % blockSize; 
+    frames[frameIndex] = feature;
+    calcAdvance();
 }
 
 vector<double> 
@@ -275,6 +317,12 @@
 
     frames[frameIndex] = processedFrame;
 
+    if ((frameCount % 100) == 0) {
+        if (!silent) {
+            cerr << "Progress:" << frameCount << " " << ltAverage << endl;
+        }
+    }
+
     return processedFrame;
 }
 
@@ -417,7 +465,7 @@
 {
     double d = 0;
     double sum = 0;
-    for (int i = 0; i < freqMapSize; i++) {
+    for (int i = 0; i < featureSize; i++) {
         d += fabs(f1[i] - f2[i]);
         sum += f1[i] + f2[i];
     }
--- a/Matcher.h	Fri Oct 10 16:27:29 2014 +0100
+++ b/Matcher.h	Fri Oct 10 16:27:45 2014 +0100
@@ -186,11 +186,23 @@
      *  bin. */
     vector<int> freqMap;
 
-    /** The number of entries in <code>freqMap</code>. Note that the
-     *  length of the array is greater, because its size is not known
-     *  at creation time. */
+    /** The number of entries in <code>freqMap</code>. */
     int freqMapSize;
 
+    /** The number of values in an externally-supplied feature vector,
+     *  used in preference to freqMap/freqMapSize if constructed with
+     *  the external feature version of the Matcher constructor. If
+     *  this is zero, the internal feature extractor will be used as
+     *  normal.
+     */
+    int externalFeatureSize;
+
+    /** The number of values in the feature vectors actually in
+     *  use. This will be externalFeatureSize if greater than zero, or
+     *  freqMapSize otherwise.
+     */
+    int featureSize;
+
     /** The most recent frame; used for calculating the frame to frame
      *  spectral difference. These are therefore frequency warped but
      *  not yet normalised. */
@@ -240,6 +252,21 @@
      */
     Matcher(Parameters parameters, Matcher *p);
 
+    /** Constructor for Matcher using externally supplied features.
+     *  A Matcher made using this constructor will not carry out its
+     *  own feature extraction from frequency-domain audio data, but
+     *  instead will accept arbitrary feature frames calculated by
+     *  some external code.
+     *
+     *  @param p The Matcher representing the performance with which
+     *  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 feature vector.
+     */
+    Matcher(Parameters parameters, Matcher *p, int featureSize);
+
     ~Matcher();
 
     /** For debugging, outputs information about the Matcher to
@@ -264,7 +291,7 @@
      * Return the feature vector size that will be used for the given
      * parameters.
      */
-    static int getFeatureSize(Parameters params);
+    static int getFeatureSizeFor(Parameters params);
 
 protected:
     template <typename T>
@@ -315,9 +342,26 @@
      *
      *  Return value is the frame (post-processed, with warping,
      *  rectification, and normalisation as appropriate).
+     *
+     *  The Matcher must have been constructed using the constructor
+     *  without an external featureSize parameter in order to use this
+     *  function. (Otherwise it will be expecting you to call
+     *  consumeFeatureVector.)
      */
     std::vector<double> consumeFrame(double *reBuffer, double *imBuffer);
 
+    /** Processes a feature vector frame (presumably calculated from
+     *  audio data by some external code). As consumeFrame, except
+     *  that it does not calculate a feature from audio data but
+     *  instead uses the supplied feature directly.
+     *
+     *  The Matcher must have been constructed using the constructor
+     *  that accepts an external featureSize parameter in order to
+     *  use this function. The supplied feature must be of the size
+     *  that was passed to the constructor.
+     */
+    void consumeFeatureVector(std::vector<double> feature);
+
     /** Calculates the Manhattan distance between two vectors, with an
      *  optional normalisation by the combined values in the
      *  vectors. Since the vectors contain energy, this could be