diff data/model/AlignmentModel.cpp @ 338:f14e2f7b24f7

* More space and time efficient AlignmentModel
author Chris Cannam
date Thu, 22 Nov 2007 11:09:26 +0000
parents 1afaf98dbf11
children ba30f4a3e3be
line wrap: on
line diff
--- a/data/model/AlignmentModel.cpp	Thu Nov 15 13:19:25 2007 +0000
+++ b/data/model/AlignmentModel.cpp	Thu Nov 22 11:09:26 2007 +0000
@@ -24,26 +24,29 @@
     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()),
+    connect(m_rawPath, SIGNAL(modelChanged()),
             this, SLOT(pathChanged()));
 
-    connect(m_path, SIGNAL(modelChanged(size_t, size_t)),
+    connect(m_rawPath, SIGNAL(modelChanged(size_t, size_t)),
             this, SLOT(pathChanged(size_t, size_t)));
 
-    connect(m_path, SIGNAL(completionChanged()),
+    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 +54,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 +69,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 +86,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 *
@@ -127,6 +133,7 @@
 AlignmentModel::fromReference(size_t frame) const
 {
 //    std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl;
+    if (!m_path) constructPath();
     return align(m_path, frame);
 }
 
@@ -139,6 +146,7 @@
 AlignmentModel::pathChanged(size_t, size_t)
 {
     if (!m_pathComplete) return;
+    constructPath();
     constructReversePath();
 }    
 
@@ -148,13 +156,23 @@
     m_pathBegun = true;
 
     if (!m_pathComplete) {
+
         int completion = 0;
-        m_path->isReady(&completion);
+        m_rawPath->isReady(&completion);
+
 //        std::cerr << "AlignmentModel::pathCompletionChanged: completion = "
 //                  << completion << std::endl;
+
         m_pathComplete = (completion == 100);
+
         if (m_pathComplete) {
+
+            constructPath();
             constructReversePath();
+
+            delete m_rawPath;
+            m_rawPath = 0;
+
             delete m_inputModel;
             m_inputModel = 0;
         }
@@ -164,78 +182,108 @@
 }
 
 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;
+    std::cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl;
+}
+
+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));
+    }
+
+    std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl;
 }
 
 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.
+    // 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 SparseTimeValueModel::PointList &points = path->getPoints();
+    const PathModel::PointList &points = path->getPoints();
 
     if (points.empty()) {
 //        std::cerr << "AlignmentModel::align: No points" << std::endl;
         return frame;
     }        
 
-    SparseTimeValueModel::Point point(frame);
-    SparseTimeValueModel::PointList::const_iterator i = points.lower_bound(point);
+    PathModel::Point point(frame);
+    PathModel::PointList::const_iterator i = points.lower_bound(point);
     if (i == points.end()) --i;
-    while (i != points.begin() && i->frame > frame) --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()) {
         followingFrame = i->frame;
-        followingTime = i->value;
+        followingMapFrame = i->mapframe;
     }
 
-    float resultTime = foundTime;
+    if (foundMapFrame < 0) return 0;
 
-    if (followingFrame != foundFrame && frame > foundFrame) {
+    size_t resultFrame = foundMapFrame;
 
-//        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;
+    if (followingFrame != foundFrame && long(frame) > foundFrame) {
+        float interp =
+            float(frame - foundFrame) /
+            float(followingFrame - foundFrame);
+        resultFrame += lrintf((followingMapFrame - foundMapFrame) * interp);
     }
 
-    size_t resultFrame = lrintf(resultTime * getSampleRate());
-
-//    std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl;
+    std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl;
 
     return resultFrame;
 }