changeset 14:cdead4a52755

Make feeder/matcher able to return feature vectors
author Chris Cannam
date Fri, 10 Oct 2014 12:04:54 +0100
parents 66082cc488c3
children a82276091bbd
files Makefile.linux MatchFeeder.cpp MatchFeeder.h Matcher.cpp Matcher.h Path.cpp
diffstat 6 files changed, 83 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.linux	Fri Oct 10 10:52:07 2014 +0100
+++ b/Makefile.linux	Fri Oct 10 12:04:54 2014 +0100
@@ -1,5 +1,5 @@
 
-CXXFLAGS	+= -fPIC -ffast-math -O3 -Wall
+CXXFLAGS	+= -fPIC -ffast-math -O3 -Wall -Werror
 LDFLAGS		+= -shared -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -lpthread -Wl,--version-script=vamp-plugin.map
 
 include Makefile.inc
--- a/MatchFeeder.cpp	Fri Oct 10 10:52:07 2014 +0100
+++ b/MatchFeeder.cpp	Fri Oct 10 12:04:54 2014 +0100
@@ -16,6 +16,8 @@
 
 #include "MatchFeeder.h"
 
+using std::vector;
+
 MatchFeeder::MatchFeeder(Matcher *m1, Matcher *m2) :
     pm1(m1), pm2(m2)
 {
@@ -49,6 +51,33 @@
     // It loops, processing up to one block per matcher, until a queue
     // is empty.  Then it returns, to be called again with more data.
 
+    prepare(input);
+
+    while (!q1.empty() && !q2.empty()) {
+//        std::cerr << "MatchFeeder::feed: q1 " << q1.size() << " q2 " << q2.size() << std::endl;
+        (void)feedBlock();
+    }
+}
+
+MatchFeeder::Features
+MatchFeeder::feedAndGetFeatures(const float *const *input)
+{
+    prepare(input);
+
+    Features all;
+
+    while (!q1.empty() && !q2.empty()) {
+        Features ff = feedBlock();
+        all.f1.insert(all.f1.end(), ff.f1.begin(), ff.f1.end());
+        all.f2.insert(all.f2.end(), ff.f2.begin(), ff.f2.end());
+    }
+
+    return all;
+}
+
+void
+MatchFeeder::prepare(const float *const *input)
+{
     float *block = new float[fftSize+2];
     for (size_t i = 0; i < fftSize+2; ++i) {
         block[i] = input[0][i];
@@ -60,20 +89,18 @@
         block[i] = input[1][i];
     }
     q2.push(block);
-
-    while (!q1.empty() && !q2.empty()) {
-//        std::cerr << "MatchFeeder::feed: q1 " << q1.size() << " q2 " << q2.size() << std::endl;
-        feedBlock();
-    }
 }
 
-void
+MatchFeeder::Features
 MatchFeeder::feedBlock()
 {
+    Features ff;
+    vector<double> f1, f2;
+
     if (pm1->frameCount < pm1->blockSize) {		// fill initial block
 //        std::cerr << "feeding initial block" << std::endl;
-        feed1();
-        feed2();
+        f1 = feed1();
+        f2 = feed2();
     }
 //!!!    } else if (pm1->atEnd) {
 //        feed2();
@@ -81,31 +108,35 @@
 //        feed1();
     else if (pm1->runCount >= Matcher::MAX_RUN_COUNT) {  // slope constraints
 //        std::cerr << "pm1 too slopey" << std::endl;
-        feed2();
+        f2 = feed2();
     } else if (pm2->runCount >= Matcher::MAX_RUN_COUNT) {
 //        std::cerr << "pm2 too slopey" << std::endl;
-        feed1();
+        f1 = feed1();
     } else {
         switch (finder->getExpandDirection
                 (pm1->frameCount-1, pm2->frameCount-1)) {
         case ADVANCE_THIS:
 //            std::cerr << "finder says ADVANCE_THIS" << std::endl;
-            feed1();
+            f1 = feed1();
             break;
         case ADVANCE_OTHER:
 //            std::cerr << "finder says ADVANCE_OTHER" << std::endl;
-            feed2();
+            f2 = feed2();
             break;
         case ADVANCE_BOTH:
 //            std::cerr << "finder says ADVANCE_BOTH" << std::endl;
-            feed1();
-            feed2();
+            f1 = feed1();
+            f2 = feed2();
             break;
         }
     }
+
+    if (!f1.empty()) ff.f1.push_back(f1);
+    if (!f2.empty()) ff.f2.push_back(f2);
+    return ff;
 }
 
-void
+vector<double>
 MatchFeeder::feed1()
 {
 //    std::cerr << "feed1" << std::endl;
@@ -118,10 +149,10 @@
         imBuffer[i] = block[i*2+1];
     }
     delete[] block;
-    pm1->processFrame(reBuffer, imBuffer);
+    return pm1->processFrame(reBuffer, imBuffer);
 }
 
-void
+vector<double>
 MatchFeeder::feed2()
 {
 //    std::cerr << "feed2" << std::endl;
@@ -134,6 +165,6 @@
         imBuffer[i] = block[i*2+1];
     }
     delete[] block;
-    pm2->processFrame(reBuffer, imBuffer);
+    return pm2->processFrame(reBuffer, imBuffer);
 }
 
--- a/MatchFeeder.h	Fri Oct 10 10:52:07 2014 +0100
+++ b/MatchFeeder.h	Fri Oct 10 12:04:54 2014 +0100
@@ -20,6 +20,7 @@
 #include "Finder.h"
 
 #include <queue>
+#include <vector>
 
 class MatchFeeder
 {
@@ -27,14 +28,33 @@
     MatchFeeder(Matcher *m1, Matcher *m2);
     ~MatchFeeder();
 
+    /**
+     * Feed the two supplied channels of frequency-domain input data
+     * to feeders 1 and 2 respectively, as appropriate (depending on
+     * their advance status).
+     */
     void feed(const float *const *input);
 
+    struct Features {
+        std::vector<std::vector<double> > f1;
+        std::vector<std::vector<double> > f2;
+    };
+
+    /**
+     * Feed the two supplied channels of frequency-domain input data
+     * to feeders 1 and 2 respectively, as appropriate (depending on
+     * their advance status) and return any new feature vectors
+     * calculated by the two feeders.
+     */
+    Features feedAndGetFeatures(const float *const *input);
+
     Finder *getFinder() { return finder; }
 
 protected:
-    void feedBlock();
-    void feed1();
-    void feed2();
+    void prepare(const float *const *input);
+    Features feedBlock();
+    std::vector<double> feed1();
+    std::vector<double> feed2();
 
     Finder *finder;
     Matcher *pm1;
--- a/Matcher.cpp	Fri Oct 10 10:52:07 2014 +0100
+++ b/Matcher.cpp	Fri Oct 10 12:04:54 2014 +0100
@@ -230,7 +230,7 @@
     }
 } // makeChromaFrequencyMap()
 
-void
+vector<double>
 Matcher::processFrame(double *reBuffer, double *imBuffer)
 {
     if (!initialised) init();
@@ -341,6 +341,8 @@
         for (int i = 0; i < freqMapSize; i++)
             frames[frameIndex][i] /= ltAverage;
 
+    vector<double> processedFrame = frames[frameIndex];
+
     int stop = otherMatcher->frameCount;
     int index = stop - blockSize;
     if (index < 0)
@@ -426,12 +428,10 @@
     if ((frameCount % 100) == 0) {
         if (!silent) {
             cerr << "Progress:" << frameCount << " " << ltAverage << endl;
-//                Profile.report();
         }
     }
-//!!!        if (frameCount == maxFrames)
-//            closeStreams();
-//    }
+
+    return processedFrame;
 } // processFrame()
 
 int
--- a/Matcher.h	Fri Oct 10 10:52:07 2014 +0100
+++ b/Matcher.h	Fri Oct 10 12:04:54 2014 +0100
@@ -303,8 +303,11 @@
      *  otherMatcher and storing them in the distance matrix, and
      *  finally updating the optimal path matrix using the dynamic
      *  time warping algorithm.
+     *
+     *  Return value is the frame (post-processed, with warping,
+     *  rectification, and normalisation as appropriate).
      */
-    void processFrame(double *reBuffer, double *imBuffer);
+    std::vector<double> processFrame(double *reBuffer, double *imBuffer);
 
     /** Calculates the Manhattan distance between two vectors, with an
      *  optional normalisation by the combined values in the
--- a/Path.cpp	Fri Oct 10 10:52:07 2014 +0100
+++ b/Path.cpp	Fri Oct 10 12:04:54 2014 +0100
@@ -21,7 +21,7 @@
 {
     if (length == 0)
         return 0;
-    while (val.size() < length) {
+    while ((int)val.size() < length) {
         val.push_back(0);
         len.push_back(0);
     }