diff data/model/AlignmentModel.cpp @ 384:6f6ab834449d spectrogram-cache-rejig

* Merge from trunk
author Chris Cannam
date Wed, 27 Feb 2008 11:59:42 +0000
parents 1afaf98dbf11
children
line wrap: on
line diff
--- a/data/model/AlignmentModel.cpp	Thu Nov 15 14:03:56 2007 +0000
+++ b/data/model/AlignmentModel.cpp	Wed Feb 27 11:59:42 2008 +0000
@@ -17,6 +17,8 @@
 
 #include "SparseTimeValueModel.h"
 
+//#define DEBUG_ALIGNMENT_MODEL 1
+
 AlignmentModel::AlignmentModel(Model *reference,
                                Model *aligned,
                                Model *inputModel,
@@ -24,26 +26,32 @@
     m_reference(reference),
     m_aligned(aligned),
     m_inputModel(inputModel),
-    m_path(path),
+    m_rawPath(path),
+    m_path(0),
     m_reversePath(0),
     m_pathBegun(false),
     m_pathComplete(false)
 {
-    connect(m_path, SIGNAL(modelChanged()),
-            this, SLOT(pathChanged()));
+    if (m_rawPath) {
 
-    connect(m_path, SIGNAL(modelChanged(size_t, size_t)),
-            this, SLOT(pathChanged(size_t, size_t)));
+        connect(m_rawPath, SIGNAL(modelChanged()),
+                this, SLOT(pathChanged()));
 
-    connect(m_path, SIGNAL(completionChanged()),
-            this, SLOT(pathCompletionChanged()));
+        connect(m_rawPath, SIGNAL(modelChanged(size_t, size_t)),
+                this, SLOT(pathChanged(size_t, size_t)));
+        
+        connect(m_rawPath, SIGNAL(completionChanged()),
+                this, SLOT(pathCompletionChanged()));
+    }
 
+    constructPath();
     constructReversePath();
 }
 
 AlignmentModel::~AlignmentModel()
 {
     delete m_inputModel;
+    delete m_rawPath;
     delete m_path;
     delete m_reversePath;
 }
@@ -51,13 +59,13 @@
 bool
 AlignmentModel::isOK() const
 {
-    return m_path->isOK();
+    if (m_rawPath) return m_rawPath->isOK();
+    else return true;
 }
 
 size_t
 AlignmentModel::getStartFrame() const
 {
-    //!!! do we care about distinct rates?
     size_t a = m_reference->getStartFrame();
     size_t b = m_aligned->getStartFrame();
     return std::min(a, b);
@@ -66,7 +74,6 @@
 size_t
 AlignmentModel::getEndFrame() const
 {
-    //!!! do we care about distinct rates?
     size_t a = m_reference->getEndFrame();
     size_t b = m_aligned->getEndFrame();
     return std::max(a, b);
@@ -84,23 +91,27 @@
     return new AlignmentModel
         (m_reference, m_aligned,
          m_inputModel ? m_inputModel->clone() : 0,
-         m_path ? static_cast<SparseTimeValueModel *>(m_path->clone()) : 0);
+         m_rawPath ? static_cast<SparseTimeValueModel *>(m_rawPath->clone()) : 0);
 }
 
 bool
 AlignmentModel::isReady(int *completion) const
 {
     if (!m_pathBegun) {
-        completion = 0;
+        if (completion) *completion = 0;
         return false;
     }
-    return m_path->isReady(completion);
+    if (m_pathComplete || !m_rawPath) {
+        if (completion) *completion = 100;
+        return true;
+    }
+    return m_rawPath->isReady(completion);
 }
 
 const ZoomConstraint *
 AlignmentModel::getZoomConstraint() const
 {
-    return m_path->getZoomConstraint();
+    return 0;
 }
 
 const Model *
@@ -118,43 +129,70 @@
 size_t
 AlignmentModel::toReference(size_t frame) const
 {
-//    std::cerr << "AlignmentModel::toReference(" << frame << ")" << std::endl;
-    if (!m_reversePath) constructReversePath();
-    return align(m_reversePath, frame);
+#ifdef DEBUG_ALIGNMENT_MODEL
+    std::cerr << "AlignmentModel::toReference(" << frame << ")" << std::endl;
+#endif
+    if (!m_path) {
+        if (!m_rawPath) return frame;
+        constructPath();
+    }
+    return align(m_path, frame);
 }
 
 size_t
 AlignmentModel::fromReference(size_t frame) const
 {
-//    std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl;
-    return align(m_path, frame);
+#ifdef DEBUG_ALIGNMENT_MODEL
+    std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl;
+#endif
+    if (!m_reversePath) {
+        if (!m_rawPath) return frame;
+        constructReversePath();
+    }
+    return align(m_reversePath, frame);
 }
 
 void
 AlignmentModel::pathChanged()
 {
+    if (m_pathComplete) {
+        std::cerr << "AlignmentModel: deleting raw path model" << std::endl;
+        delete m_rawPath;
+        m_rawPath = 0;
+    }
 }
 
 void
 AlignmentModel::pathChanged(size_t, size_t)
 {
     if (!m_pathComplete) return;
+    constructPath();
     constructReversePath();
 }    
 
 void
 AlignmentModel::pathCompletionChanged()
 {
+    if (!m_rawPath) return;
     m_pathBegun = true;
 
     if (!m_pathComplete) {
+
         int completion = 0;
-        m_path->isReady(&completion);
-//        std::cerr << "AlignmentModel::pathCompletionChanged: completion = "
-//                  << completion << std::endl;
+        m_rawPath->isReady(&completion);
+
+#ifdef DEBUG_ALIGNMENT_MODEL
+        std::cerr << "AlignmentModel::pathCompletionChanged: completion = "
+                  << completion << std::endl;
+#endif
+
         m_pathComplete = (completion == 100);
+
         if (m_pathComplete) {
+
+            constructPath();
             constructReversePath();
+
             delete m_inputModel;
             m_inputModel = 0;
         }
@@ -164,78 +202,134 @@
 }
 
 void
-AlignmentModel::constructReversePath() const
+AlignmentModel::constructPath() const
 {
-    if (!m_reversePath) {
-        m_reversePath = new SparseTimeValueModel
-            (m_path->getSampleRate(), m_path->getResolution(), false);
+    if (!m_path) {
+        if (!m_rawPath) {
+            std::cerr << "ERROR: AlignmentModel::constructPath: "
+                      << "No raw path available" << std::endl;
+            return;
+        }
+        m_path = new PathModel
+            (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false);
+    } else {
+        if (!m_rawPath) return;
     }
         
-    m_reversePath->clear();
+    m_path->clear();
 
-    SparseTimeValueModel::PointList points = m_path->getPoints();
+    SparseTimeValueModel::PointList points = m_rawPath->getPoints();
         
     for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
          i != points.end(); ++i) {
         long frame = i->frame;
         float value = i->value;
         long rframe = lrintf(value * m_aligned->getSampleRate());
-        float rvalue = (float)frame / (float)m_reference->getSampleRate();
-        m_reversePath->addPoint
-            (SparseTimeValueModel::Point(rframe, rvalue, ""));
+        m_path->addPoint(PathPoint(frame, rframe));
     }
 
-    std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(SparseTimeValueModel::Point))) << " bytes" << std::endl;
+#ifdef DEBUG_ALIGNMENT_MODEL
+    std::cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl;
+#endif
+}
+
+void
+AlignmentModel::constructReversePath() const
+{
+    if (!m_reversePath) {
+        if (!m_rawPath) {
+            std::cerr << "ERROR: AlignmentModel::constructReversePath: "
+                      << "No raw path available" << std::endl;
+            return;
+        }
+        m_reversePath = new PathModel
+            (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false);
+    } else {
+        if (!m_rawPath) return;
+    }
+        
+    m_reversePath->clear();
+
+    SparseTimeValueModel::PointList points = m_rawPath->getPoints();
+        
+    for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
+         i != points.end(); ++i) {
+        long frame = i->frame;
+        float value = i->value;
+        long rframe = lrintf(value * m_aligned->getSampleRate());
+        m_reversePath->addPoint(PathPoint(rframe, frame));
+    }
+
+#ifdef DEBUG_ALIGNMENT_MODEL
+    std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl;
+#endif
 }
 
 size_t
-AlignmentModel::align(SparseTimeValueModel *path, size_t frame) const
+AlignmentModel::align(PathModel *path, size_t frame) const
 {
-    // The path consists of a series of points, each with x (time)
-    // equal to the time on the source model and y (value) equal to
-    // the time on the target model.  Times and values are both
-    // monotonically increasing.
+    if (!path) return frame;
 
-    const SparseTimeValueModel::PointList &points = path->getPoints();
+    // The path consists of a series of points, each with frame equal
+    // to the frame on the source model and mapframe equal to the
+    // frame on the target model.  Both should be monotonically
+    // increasing.
+
+    const PathModel::PointList &points = path->getPoints();
 
     if (points.empty()) {
-//        std::cerr << "AlignmentModel::align: No points" << std::endl;
+#ifdef DEBUG_ALIGNMENT_MODEL
+        std::cerr << "AlignmentModel::align: No points" << std::endl;
+#endif
         return frame;
     }        
 
-    SparseTimeValueModel::Point point(frame);
-    SparseTimeValueModel::PointList::const_iterator i = points.lower_bound(point);
-    if (i == points.end()) --i;
-    while (i != points.begin() && i->frame > frame) --i;
+#ifdef DEBUG_ALIGNMENT_MODEL
+    std::cerr << "AlignmentModel::align: frame " << frame << " requested" << std::endl;
+#endif
+
+    PathModel::Point point(frame);
+    PathModel::PointList::const_iterator i = points.lower_bound(point);
+    if (i == points.end()) {
+#ifdef DEBUG_ALIGNMENT_MODEL
+        std::cerr << "Note: i == points.end()" << std::endl;
+#endif
+        --i;
+    }
+    while (i != points.begin() && i->frame > long(frame)) --i;
 
     long foundFrame = i->frame;
-    float foundTime = i->value;
+    long foundMapFrame = i->mapframe;
 
     long followingFrame = foundFrame;
-    float followingTime = foundTime;
+    long followingMapFrame = foundMapFrame;
 
     if (++i != points.end()) {
+#ifdef DEBUG_ALIGNMENT_MODEL
+        std::cerr << "another point available" << std::endl;
+#endif
         followingFrame = i->frame;
-        followingTime = i->value;
+        followingMapFrame = i->mapframe;
+    } else {
+#ifdef DEBUG_ALIGNMENT_MODEL
+        std::cerr << "no other point available" << std::endl;
+#endif
+    }        
+
+    if (foundMapFrame < 0) return 0;
+
+    size_t resultFrame = foundMapFrame;
+
+    if (followingFrame != foundFrame && long(frame) > foundFrame) {
+        float interp =
+            float(frame - foundFrame) /
+            float(followingFrame - foundFrame);
+        resultFrame += lrintf((followingMapFrame - foundMapFrame) * interp);
     }
 
-    float resultTime = foundTime;
-
-    if (followingFrame != foundFrame && frame > foundFrame) {
-
-//        std::cerr << "AlignmentModel::align: foundFrame = " << foundFrame << ", frame = " << frame << ", followingFrame = " << followingFrame << std::endl;
-
-        float interp = float(frame - foundFrame) / float(followingFrame - foundFrame);
-//        std::cerr << "AlignmentModel::align: interp = " << interp << ", result " << resultTime << " -> ";
-
-        resultTime += (followingTime - foundTime) * interp;
-
-//        std::cerr << resultTime << std::endl;
-    }
-
-    size_t resultFrame = lrintf(resultTime * getSampleRate());
-
-//    std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl;
+#ifdef DEBUG_ALIGNMENT_MODEL
+    std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl;
+#endif
 
     return resultFrame;
 }