AlignmentModel.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2007 QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "AlignmentModel.h"
00017 
00018 #include "SparseTimeValueModel.h"
00019 
00020 //#define DEBUG_ALIGNMENT_MODEL 1
00021 
00022 AlignmentModel::AlignmentModel(Model *reference,
00023                                Model *aligned,
00024                                Model *inputModel,
00025                                SparseTimeValueModel *path) :
00026     m_reference(reference),
00027     m_aligned(aligned),
00028     m_inputModel(inputModel),
00029     m_rawPath(path),
00030     m_path(0),
00031     m_reversePath(0),
00032     m_pathBegun(false),
00033     m_pathComplete(false)
00034 {
00035     if (m_rawPath) {
00036 
00037         connect(m_rawPath, SIGNAL(modelChanged()),
00038                 this, SLOT(pathChanged()));
00039 
00040         connect(m_rawPath, SIGNAL(modelChanged(size_t, size_t)),
00041                 this, SLOT(pathChanged(size_t, size_t)));
00042         
00043         connect(m_rawPath, SIGNAL(completionChanged()),
00044                 this, SLOT(pathCompletionChanged()));
00045     }
00046 
00047     constructPath();
00048     constructReversePath();
00049 }
00050 
00051 AlignmentModel::~AlignmentModel()
00052 {
00053     delete m_inputModel;
00054     delete m_rawPath;
00055     delete m_path;
00056     delete m_reversePath;
00057 }
00058 
00059 bool
00060 AlignmentModel::isOK() const
00061 {
00062     if (m_rawPath) return m_rawPath->isOK();
00063     else return true;
00064 }
00065 
00066 size_t
00067 AlignmentModel::getStartFrame() const
00068 {
00069     size_t a = m_reference->getStartFrame();
00070     size_t b = m_aligned->getStartFrame();
00071     return std::min(a, b);
00072 }
00073 
00074 size_t
00075 AlignmentModel::getEndFrame() const
00076 {
00077     size_t a = m_reference->getEndFrame();
00078     size_t b = m_aligned->getEndFrame();
00079     return std::max(a, b);
00080 }
00081 
00082 size_t
00083 AlignmentModel::getSampleRate() const
00084 {
00085     return m_reference->getSampleRate();
00086 }
00087 
00088 Model *
00089 AlignmentModel::clone() const
00090 {
00091     return new AlignmentModel
00092         (m_reference, m_aligned,
00093          m_inputModel ? m_inputModel->clone() : 0,
00094          m_rawPath ? static_cast<SparseTimeValueModel *>(m_rawPath->clone()) : 0);
00095 }
00096 
00097 bool
00098 AlignmentModel::isReady(int *completion) const
00099 {
00100     if (!m_pathBegun) {
00101         if (completion) *completion = 0;
00102         return false;
00103     }
00104     if (m_pathComplete || !m_rawPath) {
00105         if (completion) *completion = 100;
00106         return true;
00107     }
00108     return m_rawPath->isReady(completion);
00109 }
00110 
00111 const ZoomConstraint *
00112 AlignmentModel::getZoomConstraint() const
00113 {
00114     return 0;
00115 }
00116 
00117 const Model *
00118 AlignmentModel::getReferenceModel() const
00119 {
00120     return m_reference;
00121 }
00122 
00123 const Model *
00124 AlignmentModel::getAlignedModel() const
00125 {
00126     return m_aligned;
00127 }
00128 
00129 size_t
00130 AlignmentModel::toReference(size_t frame) const
00131 {
00132 #ifdef DEBUG_ALIGNMENT_MODEL
00133     std::cerr << "AlignmentModel::toReference(" << frame << ")" << std::endl;
00134 #endif
00135     if (!m_path) {
00136         if (!m_rawPath) return frame;
00137         constructPath();
00138     }
00139     return align(m_path, frame);
00140 }
00141 
00142 size_t
00143 AlignmentModel::fromReference(size_t frame) const
00144 {
00145 #ifdef DEBUG_ALIGNMENT_MODEL
00146     std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl;
00147 #endif
00148     if (!m_reversePath) {
00149         if (!m_rawPath) return frame;
00150         constructReversePath();
00151     }
00152     return align(m_reversePath, frame);
00153 }
00154 
00155 void
00156 AlignmentModel::pathChanged()
00157 {
00158     if (m_pathComplete) {
00159         std::cerr << "AlignmentModel: deleting raw path model" << std::endl;
00160         delete m_rawPath;
00161         m_rawPath = 0;
00162     }
00163 }
00164 
00165 void
00166 AlignmentModel::pathChanged(size_t, size_t)
00167 {
00168     if (!m_pathComplete) return;
00169     constructPath();
00170     constructReversePath();
00171 }    
00172 
00173 void
00174 AlignmentModel::pathCompletionChanged()
00175 {
00176     if (!m_rawPath) return;
00177     m_pathBegun = true;
00178 
00179     if (!m_pathComplete) {
00180 
00181         int completion = 0;
00182         m_rawPath->isReady(&completion);
00183 
00184 #ifdef DEBUG_ALIGNMENT_MODEL
00185         std::cerr << "AlignmentModel::pathCompletionChanged: completion = "
00186                   << completion << std::endl;
00187 #endif
00188 
00189         m_pathComplete = (completion == 100);
00190 
00191         if (m_pathComplete) {
00192 
00193             constructPath();
00194             constructReversePath();
00195 
00196             delete m_inputModel;
00197             m_inputModel = 0;
00198         }
00199     }
00200 
00201     emit completionChanged();
00202 }
00203 
00204 void
00205 AlignmentModel::constructPath() const
00206 {
00207     if (!m_path) {
00208         if (!m_rawPath) {
00209             std::cerr << "ERROR: AlignmentModel::constructPath: "
00210                       << "No raw path available" << std::endl;
00211             return;
00212         }
00213         m_path = new PathModel
00214             (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false);
00215     } else {
00216         if (!m_rawPath) return;
00217     }
00218         
00219     m_path->clear();
00220 
00221     SparseTimeValueModel::PointList points = m_rawPath->getPoints();
00222         
00223     for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
00224          i != points.end(); ++i) {
00225         long frame = i->frame;
00226         float value = i->value;
00227         long rframe = lrintf(value * m_aligned->getSampleRate());
00228         m_path->addPoint(PathPoint(frame, rframe));
00229     }
00230 
00231 #ifdef DEBUG_ALIGNMENT_MODEL
00232     std::cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl;
00233 #endif
00234 }
00235 
00236 void
00237 AlignmentModel::constructReversePath() const
00238 {
00239     if (!m_reversePath) {
00240         if (!m_rawPath) {
00241             std::cerr << "ERROR: AlignmentModel::constructReversePath: "
00242                       << "No raw path available" << std::endl;
00243             return;
00244         }
00245         m_reversePath = new PathModel
00246             (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false);
00247     } else {
00248         if (!m_rawPath) return;
00249     }
00250         
00251     m_reversePath->clear();
00252 
00253     SparseTimeValueModel::PointList points = m_rawPath->getPoints();
00254         
00255     for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
00256          i != points.end(); ++i) {
00257         long frame = i->frame;
00258         float value = i->value;
00259         long rframe = lrintf(value * m_aligned->getSampleRate());
00260         m_reversePath->addPoint(PathPoint(rframe, frame));
00261     }
00262 
00263 #ifdef DEBUG_ALIGNMENT_MODEL
00264     std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl;
00265 #endif
00266 }
00267 
00268 size_t
00269 AlignmentModel::align(PathModel *path, size_t frame) const
00270 {
00271     if (!path) return frame;
00272 
00273     // The path consists of a series of points, each with frame equal
00274     // to the frame on the source model and mapframe equal to the
00275     // frame on the target model.  Both should be monotonically
00276     // increasing.
00277 
00278     const PathModel::PointList &points = path->getPoints();
00279 
00280     if (points.empty()) {
00281 #ifdef DEBUG_ALIGNMENT_MODEL
00282         std::cerr << "AlignmentModel::align: No points" << std::endl;
00283 #endif
00284         return frame;
00285     }        
00286 
00287 #ifdef DEBUG_ALIGNMENT_MODEL
00288     std::cerr << "AlignmentModel::align: frame " << frame << " requested" << std::endl;
00289 #endif
00290 
00291     PathModel::Point point(frame);
00292     PathModel::PointList::const_iterator i = points.lower_bound(point);
00293     if (i == points.end()) {
00294 #ifdef DEBUG_ALIGNMENT_MODEL
00295         std::cerr << "Note: i == points.end()" << std::endl;
00296 #endif
00297         --i;
00298     }
00299     while (i != points.begin() && i->frame > long(frame)) --i;
00300 
00301     long foundFrame = i->frame;
00302     long foundMapFrame = i->mapframe;
00303 
00304     long followingFrame = foundFrame;
00305     long followingMapFrame = foundMapFrame;
00306 
00307     if (++i != points.end()) {
00308 #ifdef DEBUG_ALIGNMENT_MODEL
00309         std::cerr << "another point available" << std::endl;
00310 #endif
00311         followingFrame = i->frame;
00312         followingMapFrame = i->mapframe;
00313     } else {
00314 #ifdef DEBUG_ALIGNMENT_MODEL
00315         std::cerr << "no other point available" << std::endl;
00316 #endif
00317     }        
00318 
00319     if (foundMapFrame < 0) return 0;
00320 
00321     size_t resultFrame = foundMapFrame;
00322 
00323     if (followingFrame != foundFrame && long(frame) > foundFrame) {
00324         float interp =
00325             float(frame - foundFrame) /
00326             float(followingFrame - foundFrame);
00327         resultFrame += lrintf((followingMapFrame - foundMapFrame) * interp);
00328     }
00329 
00330 #ifdef DEBUG_ALIGNMENT_MODEL
00331     std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl;
00332 #endif
00333 
00334     return resultFrame;
00335 }
00336     

Generated on Wed Feb 20 15:45:24 2008 for SonicVisualiser by  doxygen 1.5.1