Mercurial > hg > svcore
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; }