00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "AlignmentModel.h"
00017
00018 #include "SparseTimeValueModel.h"
00019
00020
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
00274
00275
00276
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