changeset 158:d6cdbd814c8c structure

Merge from refactors branch
author Chris Cannam
date Thu, 29 Jan 2015 13:29:48 +0000
parents 2b61e0cb6847 (diff) d6c1556fadd0 (current diff)
children 28c73e5db2eb
files src/MatchVampPlugin.cpp
diffstat 11 files changed, 209 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.linux	Thu Jan 29 10:55:24 2015 +0000
+++ b/Makefile.linux	Thu Jan 29 13:29:48 2015 +0000
@@ -1,6 +1,6 @@
 
-#CXXFLAGS	+= -fPIC -ffast-math -O3 -Wall -Werror -Wfloat-conversion
-CXXFLAGS	+= -fPIC -g -Wall -Werror -DPERFORM_ERROR_CHECKS=1
+CXXFLAGS	+= -fPIC -ffast-math -O3 -Wall -Werror -Wfloat-conversion
+#CXXFLAGS	+= -fPIC -g -Wall -Werror -DPERFORM_ERROR_CHECKS=1
 
 LDFLAGS		+= -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic
 PLUGIN_LDFLAGS	+= -shared -Wl,-Bsymbolic -Wl,-z,defs -lpthread -Wl,--version-script=vamp-plugin.map
--- a/src/Finder.cpp	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/Finder.cpp	Thu Jan 29 13:29:48 2015 +0000
@@ -38,6 +38,13 @@
 }
 
 void
+Finder::setMatcher(Matcher *pm)
+{
+    cerr << "Finder::setMatcher: finder " << this << ", matcher " << pm << endl;
+    m_m = pm;
+}
+
+void
 Finder::setDurations(int d1, int d2)
 {
 #ifdef DEBUG_FINDER
@@ -47,13 +54,55 @@
     m_duration2 = d2;
 }
 
-Matcher::Advance
-Finder::getExpandDirection(int row, int col)
+bool
+Finder::getBestRowCost(int row, int &bestCol, double &min)
 {
-    double min = m_m->getPathCost(row, col);
+    cerr << "Finder " << this << "::getBestRowCost(" << row << ")" << endl;
+    if (!m_m->isRowAvailable(row)) {
+        cerr << "row not available: " << row << endl;
+        return false;
+    }
+    pair<int, int> colRange = m_m->getColRange(row);
+    if (colRange.first >= colRange.second) {
+        cerr << "row " << row << " has invalid col range " << colRange.first
+             << " -> " << colRange.second << endl;
+        return false;
+    }
+    for (int index = colRange.first; index < colRange.second; index++) {
+        double tmp = m_m->getNormalisedPathCost(row, index);
+        if (index == colRange.first || tmp < min) {
+            min = tmp;
+            bestCol = index;
+        }
+    }
+    return true;
+}    
+
+bool
+Finder::getBestColCost(int col, int &bestRow, double &min)
+{
+    if (!m_m->isColAvailable(col)) return false;
+    pair<int, int> rowRange = m_m->getRowRange(col);
+    if (rowRange.first >= rowRange.second) return false;
+    for (int index = rowRange.first; index < rowRange.second; index++) {
+        double tmp = m_m->getNormalisedPathCost(index, col);
+        if (index == rowRange.first || tmp < min) {
+            min = tmp;
+            bestRow = index;
+        }
+    }
+    return true;
+}    
+
+void
+Finder::getBestEdgeCost(int row, int col,
+                        int &bestRow, int &bestCol,
+                        double &min)
+{
+    min = m_m->getPathCost(row, col);
     
-    int bestRow = row;
-    int bestCol = col;
+    bestRow = row;
+    bestCol = col;
 
     pair<int, int> rowRange = m_m->getRowRange(col);
     if (rowRange.second > row+1) {
@@ -79,8 +128,32 @@
             bestRow = row;
         }
     }
+}
 
-//    cerr << "at [" << row << "," << col << "] (cost " << m_m->getPathCost(row, col) << ") blocksize = " << m_m->getBlockSize() << " best is [" << bestRow << "," << bestCol << "] (cost " << min << ")" << endl;
+Matcher::Advance
+Finder::getExpandDirection(int row, int col)
+{
+    // To determine which direction to expand the search area in, we
+    // look at the path costs along the leading edges of the search
+    // area (the final row and column within the area). We find the
+    // lowest path cost within the final row, and the lowest within
+    // the final column, and we compare them. If the row is cheaper
+    // then we expand by adding another row next to it; if the column
+    // is cheaper then we expand by adding another column next to
+    // it. (The overall lowest path cost across the row and column
+    // represents the best alignment we have within the entire search
+    // area given the data available and the assumption that the piece
+    // is not ending yet.)
+
+    int bestRow = row;
+    int bestCol = col;
+    double bestCost = -1;
+
+//    cerr << "Finder " << this << "::getExpandDirection: ";
+    
+    getBestEdgeCost(row, col, bestRow, bestCol, bestCost);
+
+//    cerr << "at [" << row << "," << col << "] (cost " << m_m->getPathCost(row, col) << ") blocksize = " << m_m->getBlockSize() << " best is [" << bestRow << "," << bestCol << "] (cost " << bestCost << ")" << endl;
     
     if (bestRow == row) {
         if (bestCol == col) {
--- a/src/Finder.h	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/Finder.h	Thu Jan 29 13:29:48 2015 +0000
@@ -29,6 +29,8 @@
 
     ~Finder();
 
+    void setMatcher(Matcher *pm);
+    
     /**
      * Tell the finder that one or both files ends sooner than it
      * thought, i.e. that some of the trailing features are silence or
@@ -37,7 +39,38 @@
      * duration of each input will be considered.
      */
     void setDurations(int d1, int d2);
+
+    /**
+     * Find the location and cost of the column with the cheapest path
+     * cost within the given row. If the row is out of range, return
+     * false and leave the bestCol and bestCost variables unchanged.
+     */
+    bool getBestRowCost(int row, int &bestCol, double &bestCost);
+
+    /**
+     * Find the location and cost of the row with the cheapest path
+     * cost within the given column. If the column is out of range,
+     * return false and leave the bestRow and bestCost variables
+     * unchanged.
+     */
+    bool getBestColCost(int col, int &bestRow, double &bestCost);
     
+    /**
+     * Find the location and cost of the cheapest path cost within the
+     * final row and column of the search area, given that the area
+     * extends as far as the point at (row, col). This is used by
+     * getExpandDirection and can also be used, for example, to
+     * determine the current best estimate alignment for a frame we
+     * have just reached.
+     */
+    void getBestEdgeCost(int row, int col,
+                         int &bestRow, int &bestCol,
+                         double &bestCost);
+
+    /**
+     * Calculate which direction to expand the search area in, given
+     * that so far it extends as far as the point at (row, col).
+     */
     Matcher::Advance getExpandDirection(int row, int col);
     
     /** Calculates a rectangle of the path cost matrix so that the
@@ -84,9 +117,10 @@
     void checkAndReport();
 #endif
     
-    Matcher *m_m;
+    Matcher *m_m;   // I do not own this
+    
     int m_duration1;
     int m_duration2;
-}; // class Finder
+};
 
 #endif
--- a/src/MatchFeatureFeeder.cpp	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/MatchFeatureFeeder.cpp	Thu Jan 29 13:29:48 2015 +0000
@@ -29,6 +29,30 @@
     delete m_finder;
 }
 
+MatchFeatureFeeder::MatchFeatureFeeder(const MatchFeatureFeeder &other) :
+    m_pm1(other.m_pm1), m_pm2(other.m_pm2)
+{
+    //!!! This is gross. Finder should probably not be heap allocated at all
+    m_finder = new Finder(*other.m_finder);
+}
+
+MatchFeatureFeeder &
+MatchFeatureFeeder::operator=(const MatchFeatureFeeder &other)
+{
+    m_pm1 = other.m_pm1;
+    m_pm2 = other.m_pm2;
+    m_finder = new Finder(*other.m_finder);
+    return *this;
+}
+
+void
+MatchFeatureFeeder::setMatchers(Matcher *m1, Matcher *m2)
+{
+    m_pm1 = m1;
+    m_pm2 = m2;
+    m_finder->setMatcher(m_pm1);
+}
+
 void
 MatchFeatureFeeder::feed(vector<double> f1, vector<double> f2)
 {
--- a/src/MatchFeatureFeeder.h	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/MatchFeatureFeeder.h	Thu Jan 29 13:29:48 2015 +0000
@@ -28,6 +28,11 @@
     MatchFeatureFeeder(Matcher *m1, Matcher *m2);
     ~MatchFeatureFeeder();
 
+    MatchFeatureFeeder(const MatchFeatureFeeder &other);
+    MatchFeatureFeeder &operator=(const MatchFeatureFeeder &other);
+    
+    void setMatchers(Matcher *m1, Matcher *m2);
+    
     /**
      * Feed the two supplied feature vectors to feeders 1 and 2
      * respectively (depending on their advance status). Matchers must
@@ -67,9 +72,10 @@
     void feed1();
     void feed2();
 
-    Finder *m_finder;
-    Matcher *m_pm1;
-    Matcher *m_pm2;
+    Finder *m_finder; // I own this, and it refers to m_pm1 and m_pm2
+    
+    Matcher *m_pm1;   // I do not own this
+    Matcher *m_pm2;   // I do not own this
 
     std::queue<std::vector<double> > m_q1;
     std::queue<std::vector<double> > m_q2;
--- a/src/MatchPipeline.cpp	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/MatchPipeline.cpp	Thu Jan 29 13:29:48 2015 +0000
@@ -131,21 +131,19 @@
 MatchPipeline::finish()
 {
     m_feeder.finish();
-    getFinder()->setDurations(m_lastFrameIn1, m_lastFrameIn2);
+    m_feeder.getFinder()->setDurations(m_lastFrameIn1, m_lastFrameIn2);
 }
 
-MatchFeatureFeeder *
-MatchPipeline::getFeeder()
+int
+MatchPipeline::retrievePath(bool smooth, std::vector<int> &pathx, std::vector<int> &pathy)
 {
-    return &m_feeder;
+    return m_feeder.getFinder()->retrievePath(smooth, pathx, pathy);
 }
 
-Finder *
-MatchPipeline::getFinder()
-{
-    return m_feeder.getFinder();
+void
+MatchPipeline::retrieveForwardPath(std::vector<int> &pathx, std::vector<int> &pathy) {
+    return m_feeder.retrieveForwardPath(pathx, pathy);
 }
 
 
 
-
--- a/src/MatchPipeline.h	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/MatchPipeline.h	Thu Jan 29 13:29:48 2015 +0000
@@ -89,8 +89,20 @@
      */
     void finish();
 
-    MatchFeatureFeeder *getFeeder();
-    Finder *getFinder();
+    /**
+     * Retrieve the final path. Only valid once all the features have
+     * been supplied and finish() has been called.
+     *
+     * See Finder::retrievePath for more details.
+     */
+    int retrievePath(bool smooth, std::vector<int> &pathx, std::vector<int> &pathy);
+
+    /**
+     * Retrieve the forward path resulting from the online search.
+     *
+     * See MatchFeatureFeeder::retrieveForwardPath for more details.
+     */
+    void retrieveForwardPath(std::vector<int> &pathx, std::vector<int> &pathy);
     
 private:
     FeatureExtractor m_fe1;
--- a/src/MatchVampPlugin.cpp	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/MatchVampPlugin.cpp	Thu Jan 29 13:29:48 2015 +0000
@@ -211,7 +211,7 @@
     desc.description = "Total frame energy threshold below which a feature will be regarded as silent";
     desc.minValue = 0;
     desc.maxValue = 1;
-    desc.defaultValue = m_defaultFcParams.silenceThreshold;
+    desc.defaultValue = (float)m_defaultFcParams.silenceThreshold;
     desc.isQuantized = false;
     list.push_back(desc);
 
@@ -307,7 +307,7 @@
     } else if (name == "smooth") {
         return m_smooth ? 1.0 : 0.0;
     } else if (name == "silencethreshold") {
-        return m_fcParams.silenceThreshold;
+        return (float)m_fcParams.silenceThreshold;
     } else if (name == "metric") {
         return (int)m_dParams.metric;
     } else if (name == "noise") {
@@ -606,10 +606,9 @@
 
     FeatureSet returnFeatures;
     
-    Finder *finder = m_pipeline->getFinder();
     std::vector<int> pathx;
     std::vector<int> pathy;
-    int len = finder->retrievePath(m_smooth, pathx, pathy);
+    int len = m_pipeline->retrievePath(m_smooth, pathx, pathy);
 
     int prevx = 0;
     int prevy = 0;
--- a/src/Matcher.cpp	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/Matcher.cpp	Thu Jan 29 13:29:48 2015 +0000
@@ -76,6 +76,26 @@
 }
 
 bool
+Matcher::isRowAvailable(int i)
+{
+    if (i < 0 || i >= int(m_first.size())) return false;
+
+    for (int j = m_first[i]; j < int(m_first[i] + m_bestPathCost[i].size()); ++j) {
+        if (isAvailable(i, j)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool
+Matcher::isColAvailable(int i)
+{
+    return m_otherMatcher->isRowAvailable(i);
+}
+
+bool
 Matcher::isInRange(int i, int j)
 {
     if (m_firstPM) {
--- a/src/Matcher.h	Thu Jan 29 10:55:24 2015 +0000
+++ b/src/Matcher.h	Thu Jan 29 13:29:48 2015 +0000
@@ -158,6 +158,14 @@
      *  @return true if the location is in range
      */
     bool isInRange(int i, int j);
+
+    /** Tests whether any locations in the given row are available.
+     */
+    bool isRowAvailable(int i);
+
+    /** Tests whether any locations in the given column are available.
+     */
+    bool isColAvailable(int i);
     
     /** Tests whether a location is available in the minimum cost matrix.
      *
@@ -167,8 +175,9 @@
      */
     bool isAvailable(int i, int j);
 
-    /** Returns the valid range of frames in the other Matcher for the
-     *  given frame in this Matcher's minimum cost matrix.
+    /** Returns the valid range of columns for the given row, that is,
+     *  the range of frames in the other Matcher for the given frame
+     *  in this Matcher's minimum cost matrix.
      *
      *  @param i the frame number of this Matcher
      *  @return the first, last pair of frame numbers for the other
@@ -177,8 +186,9 @@
      */
     std::pair<int, int> getColRange(int i);
 
-    /** Returns the valid range of frames in this Matcher for the
-     *  given frame in the other Matcher's minimum cost matrix.
+    /** Returns the valid range of rows for the given column, that is,
+     *  the range of frames in this Matcher for the given frame in the
+     *  other Matcher's minimum cost matrix.
      *
      *  @param i the frame number of the other Matcher
      *  @return the first, last pair of frame numbers for this
--- a/test/TestFeatureExtractor.cpp	Thu Jan 29 10:55:24 2015 +0000
+++ b/test/TestFeatureExtractor.cpp	Thu Jan 29 13:29:48 2015 +0000
@@ -14,7 +14,7 @@
 
 static int freq2mid(double freq)
 {
-    return round(57.0 + 12.0 * log(freq / 220.) / log(2.));
+    return int(round(57.0 + 12.0 * log(freq / 220.) / log(2.)));
 }
 
 static int freq2chroma(double freq)