diff src/Matcher.cpp @ 75:e1a5f3095ba6 cheap_diagonals

Merge from branch refactors
author Chris Cannam
date Wed, 19 Nov 2014 12:13:28 +0000
parents fb6e4829c1af b9aa663a607b
children
line wrap: on
line diff
--- a/src/Matcher.cpp	Tue Nov 18 10:33:12 2014 +0000
+++ b/src/Matcher.cpp	Wed Nov 19 12:13:28 2014 +0000
@@ -21,38 +21,13 @@
 #include <cstdlib>
 #include <cassert>
 
+using namespace std;
+
 //#define DEBUG_MATCHER 1
 
-Matcher::Matcher(Parameters parameters,
-                 FeatureExtractor::Parameters feParams,
-                 Matcher *p) :
-    m_params(parameters),
-    m_featureExtractor(feParams),
-    m_metric(parameters.distanceNorm)
-{
-#ifdef DEBUG_MATCHER
-    cerr << "Matcher::Matcher(" << m_params.sampleRate << ", " << p << ")" << endl;
-#endif
-
-    m_otherMatcher = p;	// the first matcher will need this to be set later
-    m_firstPM = (!p);
-    m_frameCount = 0;
-    m_runCount = 0;
-    m_featureSize = m_featureExtractor.getFeatureSize();
-    m_blockSize = 0;
-
-    m_blockSize = lrint(m_params.blockTime / m_params.hopTime);
-#ifdef DEBUG_MATCHER
-    cerr << "Matcher: m_blockSize = " << m_blockSize << endl;
-#endif
-
-    m_initialised = false;
-}
-
 Matcher::Matcher(Parameters parameters, Matcher *p, int m_featureSize_) :
     m_params(parameters),
     m_featureSize(m_featureSize_),
-    m_featureExtractor(FeatureExtractor::Parameters(m_params.sampleRate, m_params.fftSize)), // unused default config
     m_metric(parameters.distanceNorm)
 {
 #ifdef DEBUG_MATCHER
@@ -86,7 +61,7 @@
     if (m_initialised) return;
 
     m_frames = vector<vector<double> >
-        (m_blockSize, vector<double>(m_featureSize, 0));
+        (m_blockSize, vector<double>(m_featureSize, -1.0));
 
     m_distXSize = m_blockSize * 2;
 
@@ -102,31 +77,15 @@
 Matcher::size()
 {
     int distSize = (m_params.maxRunCount + 1) * m_blockSize;
-    m_bestPathCost.resize(m_distXSize, vector<double>(distSize, 0));
-    m_distance.resize(m_distXSize, vector<float>(distSize, 0));
+    m_bestPathCost.resize(m_distXSize, vector<double>(distSize, -1));
+    m_distance.resize(m_distXSize, vector<float>(distSize, -1));
     m_advance.resize(m_distXSize, vector<Advance>(distSize, AdvanceNone));
-    m_distYSizes.resize(m_distXSize, distSize);
     m_first.resize(m_distXSize, 0);
     m_last.resize(m_distXSize, 0);
 }
 
-vector<double>
-Matcher::consumeFrame(double *reBuffer, double *imBuffer)
-{
-    if (!m_initialised) init();
-
-    vector<double> real(reBuffer, reBuffer + m_params.fftSize/2 + 1);
-    vector<double> imag(imBuffer, imBuffer + m_params.fftSize/2 + 1);
-    vector<double> feature = m_featureExtractor.process(real, imag);
-    int frameIndex = m_frameCount % m_blockSize;
-    m_frames[frameIndex] = feature;
-    calcAdvance();
-
-    return feature;
-}
-
 void
-Matcher::consumeFeatureVector(std::vector<double> feature)
+Matcher::consumeFeatureVector(vector<double> feature)
 {
     if (!m_initialised) init();
     int frameIndex = m_frameCount % m_blockSize; 
@@ -153,22 +112,30 @@
         // distance[m_frameCount], and then truncate
         // distance[m_frameCount-m_blockSize] to its first len elements.
         // Same for bestPathCost.
-/*
-        std::cerr << "Matcher(" << this << "): moving " << distYSizes[m_frameCount - m_blockSize] << " from " << m_frameCount - m_blockSize << " to "
-                  << m_frameCount << ", allocating " << len << " for "
-                  << m_frameCount - m_blockSize << std::endl;
-*/
-        m_distance[m_frameCount] = m_distance[m_frameCount - m_blockSize];
-        m_distance[m_frameCount - m_blockSize].resize(len, 0);
 
-        m_bestPathCost[m_frameCount] = m_bestPathCost[m_frameCount - m_blockSize];
-        m_bestPathCost[m_frameCount - m_blockSize].resize(len, 0);
+        vector<float> dOld = m_distance[m_frameCount - m_blockSize];
+        vector<float> dNew(len, -1.f);
 
-        m_advance[m_frameCount] = m_advance[m_frameCount - m_blockSize];
-        m_advance[m_frameCount - m_blockSize].resize(len, AdvanceNone);
+        vector<double> bpcOld = m_bestPathCost[m_frameCount - m_blockSize];
+        vector<double> bpcNew(len, -1.0);
+
+        vector<Advance> adOld = m_advance[m_frameCount - m_blockSize];
+        vector<Advance> adNew(len, AdvanceNone);
+
+        for (int i = 0; i < len; ++i) {
+            dNew[i] = dOld[i];
+            bpcNew[i] = bpcOld[i];
+            adNew[i] = adOld[i];
+        }
         
-        m_distYSizes[m_frameCount] = m_distYSizes[m_frameCount - m_blockSize];
-        m_distYSizes[m_frameCount - m_blockSize] = len;
+        m_distance[m_frameCount] = dOld;
+        m_distance[m_frameCount - m_blockSize] = dNew;
+
+        m_bestPathCost[m_frameCount] = bpcOld;
+        m_bestPathCost[m_frameCount - m_blockSize] = bpcNew;
+
+        m_advance[m_frameCount] = adOld;
+        m_advance[m_frameCount - m_blockSize] = adNew;
     }
 
     int stop = m_otherMatcher->m_frameCount;
@@ -194,43 +161,43 @@
             mn = dMN;
 
         if ((m_frameCount == 0) && (index == 0))    // first element
-            setValue(0, 0, AdvanceNone, 0, dMN);
+            updateValue(0, 0, AdvanceNone, 0, dMN);
         else if (m_frameCount == 0)                 // first row
-            setValue(0, index, AdvanceOther,
-                     getValue(0, index-1, true), dMN);
+            updateValue(0, index, AdvanceOther,
+                        getPathCost(0, index-1), dMN);
         else if (index == 0)                      // first column
-            setValue(m_frameCount, index, AdvanceThis,
-                     getValue(m_frameCount - 1, 0, true), dMN);
+            updateValue(m_frameCount, index, AdvanceThis,
+                        getPathCost(m_frameCount - 1, 0), dMN);
         else if (index == m_otherMatcher->m_frameCount - m_blockSize) {
             // missing value(s) due to cutoff
             //  - no previous value in current row (resp. column)
             //  - no diagonal value if prev. dir. == curr. dirn
-            double min2 = getValue(m_frameCount - 1, index, true);
+            double min2 = getPathCost(m_frameCount - 1, index);
             //	if ((m_firstPM && (first[m_frameCount - 1] == index)) ||
             //			(!m_firstPM && (m_last[index-1] < m_frameCount)))
             if (m_first[m_frameCount - 1] == index)
-                setValue(m_frameCount, index, AdvanceThis, min2, dMN);
+                updateValue(m_frameCount, index, AdvanceThis, min2, dMN);
             else {
-                double min1 = getValue(m_frameCount - 1, index - 1, true);
+                double min1 = getPathCost(m_frameCount - 1, index - 1);
                 if (min1 + dMN <= min2)
-                    setValue(m_frameCount, index, AdvanceBoth, min1,dMN);
+                    updateValue(m_frameCount, index, AdvanceBoth, min1,dMN);
                 else
-                    setValue(m_frameCount, index, AdvanceThis, min2,dMN);
+                    updateValue(m_frameCount, index, AdvanceThis, min2,dMN);
             }
         } else {
-            double min1 = getValue(m_frameCount, index-1, true);
-            double min2 = getValue(m_frameCount - 1, index, true);
-            double min3 = getValue(m_frameCount - 1, index-1, true);
+            double min1 = getPathCost(m_frameCount, index-1);
+            double min2 = getPathCost(m_frameCount - 1, index);
+            double min3 = getPathCost(m_frameCount - 1, index-1);
             if (min1 <= min2) {
                 if (min3 + dMN <= min1)
-                    setValue(m_frameCount, index, AdvanceBoth, min3,dMN);
+                    updateValue(m_frameCount, index, AdvanceBoth, min3,dMN);
                 else
-                    setValue(m_frameCount, index, AdvanceOther,min1,dMN);
+                    updateValue(m_frameCount, index, AdvanceOther,min1,dMN);
             } else {
                 if (min3 + dMN <= min2)
-                    setValue(m_frameCount, index, AdvanceBoth, min3,dMN);
+                    updateValue(m_frameCount, index, AdvanceBoth, min3,dMN);
                 else
-                    setValue(m_frameCount, index, AdvanceThis, min2,dMN);
+                    updateValue(m_frameCount, index, AdvanceThis, min2,dMN);
             }
         }
         m_otherMatcher->m_last[index]++;
@@ -242,55 +209,178 @@
     m_otherMatcher->m_runCount = 0;
 }
 
+bool
+Matcher::isInRange(int i, int j)
+{
+    if (m_firstPM) {
+        return ((i >= 0) &&
+                (i < int(m_first.size())) &&
+                (j >= m_first[i]) &&
+                (j < int(m_first[i] + m_bestPathCost[i].size())));
+    } else {
+        return m_otherMatcher->isInRange(j, i);
+    }
+}
+
+bool
+Matcher::isAvailable(int i, int j)
+{
+    if (m_firstPM) {
+        if (isInRange(i, j)) {
+            return (m_bestPathCost[i][j - m_first[i]] >= 0);
+        } else {
+            return false;
+        }
+    } else {
+        return m_otherMatcher->isAvailable(j, i);
+    }
+}
+
+pair<int, int>
+Matcher::getColRange(int i)
+{
+    if (i < 0 || i >= int(m_first.size())) {
+        cerr << "ERROR: Matcher::getColRange(" << i << "): Index out of range"
+             << endl;
+        throw "Index out of range";
+    } else {
+        return pair<int, int>(m_first[i], m_last[i]);
+    }
+}
+
+pair<int, int>
+Matcher::getRowRange(int i)
+{
+    return m_otherMatcher->getColRange(i);
+}
+
+float
+Matcher::getDistance(int i, int j)
+{
+    if (m_firstPM) {
+        if (!isInRange(i, j)) {
+            cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): "
+                 << "Location is not in range" << endl;
+            throw "Distance not available";
+        }
+        float dist = m_distance[i][j - m_first[i]];
+        if (dist < 0) {
+            cerr << "ERROR: Matcher::getDistance(" << i << ", " << j << "): "
+                 << "Location is in range, but distance ("
+                 << dist << ") is invalid or has not been set" << endl;
+            throw "Distance not available";
+        }
+        return dist;
+    } else {
+        return m_otherMatcher->getDistance(j, i);
+    }
+}
+                
+void
+Matcher::setDistance(int i, int j, float distance)
+{
+    if (m_firstPM) {
+        if (!isInRange(i, j)) {
+            cerr << "ERROR: Matcher::setDistance(" << i << ", " << j << ", "
+                 << distance << "): Location is out of range" << endl;
+            throw "Indices out of range";
+        }
+        m_distance[i][j - m_first[i]] = distance;
+    } else {
+        m_otherMatcher->setDistance(j, i, distance);
+    }
+}
+
 double
-Matcher::getValue(int i, int j, bool firstAttempt)
+Matcher::getPathCost(int i, int j)
 {
-    if (m_firstPM)
+    if (m_firstPM) {
+        if (!isAvailable(i, j)) {
+            if (!isInRange(i, j)) {
+                cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): "
+                     << "Location is not in range" << endl;
+            } else {
+                cerr << "ERROR: Matcher::getPathCost(" << i << ", " << j << "): "
+                     << "Location is in range, but pathCost ("
+                     << m_bestPathCost[i][j - m_first[i]]
+                     << ") is invalid or has not been set" << endl;
+            }
+            throw "Path cost not available";
+        }
         return m_bestPathCost[i][j - m_first[i]];
-    else
-        return m_otherMatcher->m_bestPathCost[j][i - m_otherMatcher->m_first[j]];
-} // getValue()
-
+    } else {
+        return m_otherMatcher->getPathCost(j, i);
+    }
+}
+                
 void
-Matcher::setValue(int i, int j, Advance dir, double value, float dMN)
+Matcher::setPathCost(int i, int j, Advance dir, double pathCost)
 {
-    float diagonalWeight = sqrtf(2.f);
-    
-    if (dir == AdvanceBoth) {
-        dMN *= diagonalWeight;
-    }
-    
     if (m_firstPM) {
-
-        int jdx = j - m_first[i];
-        m_distance[i][jdx] = dMN;
-        m_advance[i][jdx] = dir;
-        m_bestPathCost[i][jdx] = value + dMN;
-
+        if (!isInRange(i, j)) {
+            cerr << "ERROR: Matcher::setPathCost(" << i << ", " << j << ", "
+                 << dir << ", " << pathCost
+                 << "): Location is out of range" << endl;
+            throw "Indices out of range";
+        }
+        m_advance[i][j - m_first[i]] = dir;
+        m_bestPathCost[i][j - m_first[i]] = pathCost;
     } else {
-
         if (dir == AdvanceThis) {
             dir = AdvanceOther;
         } else if (dir == AdvanceOther) {
             dir = AdvanceThis;
         }
+        m_otherMatcher->setPathCost(j, i, dir, pathCost);
+    }
+
+}
+
+void
+Matcher::updateValue(int i, int j, Advance dir, double value, float dMN)
+{
+    float diagonalWeight = sqrtf(2.f);
+
+    float weight = 1.f;
+    if (dir == AdvanceBoth) {
+        weight *= diagonalWeight;
+    }
+    
+    if (m_firstPM) {
+
+        m_distance[i][j - m_first[i]] = dMN;
+        setPathCost(i, j, dir, value + weight * dMN);
+
+    } else {
 
         int idx = i - m_otherMatcher->m_first[j];
         
-        if (idx == (int)m_otherMatcher->m_distYSizes[j]) {
+        if (idx == (int)m_otherMatcher->m_distance[j].size()) {
             // This should never happen, but if we allow arbitrary
             // pauses in either direction, and arbitrary lengths at
             // end, it is better than a segmentation fault.
-            std::cerr << "Emergency resize: " << idx << " -> " << idx * 2 << std::endl;
-            m_otherMatcher->m_distYSizes[j] = idx * 2;
-            m_otherMatcher->m_bestPathCost[j].resize(idx * 2, 0);
-            m_otherMatcher->m_distance[j].resize(idx * 2, 0);
+            cerr << "Emergency resize: " << idx << " -> " << idx * 2 << endl;
+            m_otherMatcher->m_bestPathCost[j].resize(idx * 2, -1);
+            m_otherMatcher->m_distance[j].resize(idx * 2, -1);
             m_otherMatcher->m_advance[j].resize(idx * 2, AdvanceNone);
         }
 
         m_otherMatcher->m_distance[j][idx] = dMN;
-        m_otherMatcher->m_advance[j][idx] = dir;
-        m_otherMatcher->m_bestPathCost[j][idx] = value + dMN;
+        m_otherMatcher->setPathCost(j, i, dir, value + weight * dMN);
     }
-} // setValue()
+}
 
+Matcher::Advance
+Matcher::getAdvance(int i, int j)
+{
+    if (m_firstPM) {
+        if (!isInRange(i, j)) {
+            cerr << "ERROR: Matcher::getAdvance(" << i << ", " << j << "): "
+                 << "Location is not in range" << endl;
+            throw "Advance not available";
+        }
+        return m_advance[i][j - m_first[i]];
+    } else {
+        return m_otherMatcher->getAdvance(j, i);
+    }
+}