changeset 173:eeed3498fe96 refactors

Merge from branch structure
author Chris Cannam
date Fri, 06 Feb 2015 18:41:35 +0000
parents d23dad16d6f9 (current diff) 30d59e1e4232 (diff)
children ef3c4b451c57
files src/Finder.cpp src/Finder.h src/MatchPipeline.cpp src/MatchPipeline.h src/MatchVampPlugin.cpp
diffstat 9 files changed, 233 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/src/Finder.cpp	Thu Feb 05 11:53:23 2015 +0000
+++ b/src/Finder.cpp	Fri Feb 06 18:41:35 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,47 @@
     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);
+    if (!m_m->isRowAvailable(row)) return false;
+    pair<int, int> colRange = m_m->getColRange(row);
+    if (colRange.first >= colRange.second) 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 +120,39 @@
             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()
+{
+    return getExpandDirection(m_m->getFrameCount() - 1,
+                              m_m->getOtherFrameCount() - 1);
+}
+
+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 Feb 05 11:53:23 2015 +0000
+++ b/src/Finder.h	Fri Feb 06 18:41:35 2015 +0000
@@ -27,8 +27,12 @@
 public:
     Finder(Matcher *pm);
 
+    // default copy ctor and operator= are fine
+
     ~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 +41,44 @@
      * 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
+     * its current extents.
+     */
+    Matcher::Advance getExpandDirection();
+    
+    /**
+     * 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
@@ -89,10 +130,11 @@
     ErrorPosition checkPathCostMatrix();
     void checkAndReport();
 #endif
+
+    Matcher *m_m;   // I do not own this
     
-    Matcher *m_m;
     int m_duration1;
     int m_duration2;
-}; // class Finder
+};
 
 #endif
--- a/src/MatchFeatureFeeder.cpp	Thu Feb 05 11:53:23 2015 +0000
+++ b/src/MatchFeatureFeeder.cpp	Fri Feb 06 18:41:35 2015 +0000
@@ -19,14 +19,14 @@
 using std::vector;
 
 MatchFeatureFeeder::MatchFeatureFeeder(Matcher *m1, Matcher *m2) :
-    m_pm1(m1), m_pm2(m2)
+    m_pm1(m1),
+    m_pm2(m2),
+    m_finder(m_pm1)
 {
-    m_finder = new Finder(m1);
 }
 
 MatchFeatureFeeder::~MatchFeatureFeeder()
 {
-    delete m_finder;
 }
 
 void
@@ -51,6 +51,21 @@
     }
 }
 
+int
+MatchFeatureFeeder::getEstimatedReferenceFrame()
+{
+    if (m_pm1->getFrameCount() == 0 || m_pm2->getFrameCount() == 0) {
+        return 0;
+    }
+    int bestRow = 0;
+    double bestCost = 0;
+    if (!m_finder.getBestColCost(m_pm2->getFrameCount()-1, bestRow, bestCost)) {
+        return -1;
+    } else {
+        return bestRow;
+    }
+}
+
 void
 MatchFeatureFeeder::finish()
 {
@@ -66,7 +81,7 @@
         feed2();
     } else if (m_q2.empty()) { // ended
         feed1();
-    } else if (m_pm1->getFrameCount() < m_pm1->getBlockSize()) { // fill initial block
+    } else if (m_pm1->isFillingInitialBlock()) {
         feed1();
         feed2();
     } else if (m_pm1->isOverrunning()) { // slope constraints
@@ -74,8 +89,7 @@
     } else if (m_pm2->isOverrunning()) {
         feed1();
     } else {
-        switch (m_finder->getExpandDirection
-                (m_pm1->getFrameCount()-1, m_pm2->getFrameCount()-1)) {
+        switch (m_finder.getExpandDirection()) {
         case Matcher::AdvanceThis:
             feed1();
             break;
--- a/src/MatchFeatureFeeder.h	Thu Feb 05 11:53:23 2015 +0000
+++ b/src/MatchFeatureFeeder.h	Fri Feb 06 18:41:35 2015 +0000
@@ -44,6 +44,12 @@
     void feed(std::vector<double> f1, std::vector<double> f2);
 
     /**
+     * Get the best estimate for the frame in the reference (f1)
+     * corresponding to the latest frame in the other input (f2).
+     */
+    int getEstimatedReferenceFrame();
+    
+    /**
      * Indicate that both inputs have come to an end.
      */
     void finish();
@@ -60,22 +66,27 @@
         pathy = m_fpy;
     }
 
-    Finder *getFinder() { return m_finder; }
+    Finder *getFinder() { return &m_finder; }
 
 protected:
     void feedBlock();
     void feed1();
     void feed2();
 
-    Finder *m_finder;
-    Matcher *m_pm1;
-    Matcher *m_pm2;
+    Matcher *m_pm1;   // I do not own this
+    Matcher *m_pm2;   // I do not own this
 
+    Finder m_finder; // I own this, and it refers to m_pm1
+    
     std::queue<std::vector<double> > m_q1;
     std::queue<std::vector<double> > m_q2;
 
     vector<int> m_fpx;
     vector<int> m_fpy;
+
+    // not provided:
+    MatchFeatureFeeder(const MatchFeatureFeeder &other);
+    MatchFeatureFeeder &operator=(const MatchFeatureFeeder &other);
 };
 
 #endif
--- a/src/MatchPipeline.cpp	Thu Feb 05 11:53:23 2015 +0000
+++ b/src/MatchPipeline.cpp	Fri Feb 06 18:41:35 2015 +0000
@@ -140,21 +140,23 @@
 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);
 }
 
+double
+MatchPipeline::getOverallCost()
+{
+    return m_feeder.getFinder()->getOverallCost();
+}
 
-
-
--- a/src/MatchPipeline.h	Thu Feb 05 11:53:23 2015 +0000
+++ b/src/MatchPipeline.h	Fri Feb 06 18:41:35 2015 +0000
@@ -96,9 +96,29 @@
      */
     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);
+
+    /**
+     * Get the path cost for the overall path to the end of both
+     * sources.
+     *
+     * See Finder::getOverallCost for more details.
+     */
+    double getOverallCost();
+
 private:
     FeatureExtractor m_fe1;
     FeatureExtractor m_fe2;
--- a/src/MatchVampPlugin.cpp	Thu Feb 05 11:53:23 2015 +0000
+++ b/src/MatchVampPlugin.cpp	Fri Feb 06 18:41:35 2015 +0000
@@ -208,6 +208,7 @@
     desc.valueNames.push_back("Long-term average");
     list.push_back(desc);
     desc.valueNames.clear();
+    desc.defaultValue = (float)m_defaultFcParams.silenceThreshold;
 
     desc.identifier = "metric";
     desc.name = "Distance metric";
@@ -659,12 +660,11 @@
 
     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);
 
-    double cost = finder->getOverallCost();
+    double cost = m_pipeline->getOverallCost();
     Feature costFeature;
     costFeature.hasTimestamp = false;
     costFeature.values.push_back((float)cost);
--- a/src/Matcher.cpp	Thu Feb 05 11:53:23 2015 +0000
+++ b/src/Matcher.cpp	Fri Feb 06 18:41:35 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 Feb 05 11:53:23 2015 +0000
+++ b/src/Matcher.h	Fri Feb 06 18:41:35 2015 +0000
@@ -123,6 +123,10 @@
         return m_blockSize;
     }
 
+    bool isFillingInitialBlock() {
+        return m_frameCount < m_blockSize;
+    }
+    
     bool isOverrunning() {
         return m_runCount >= m_params.maxRunCount;
     }
@@ -158,6 +162,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 +179,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 +190,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