svcore  1.9
AlignmentModel.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2007 QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "AlignmentModel.h"
17 
18 #include "SparseTimeValueModel.h"
19 
20 //#define DEBUG_ALIGNMENT_MODEL 1
21 
23  Model *aligned,
24  Model *inputModel,
25  SparseTimeValueModel *path) :
26  m_reference(reference),
27  m_aligned(aligned),
28  m_inputModel(inputModel),
29  m_rawPath(path),
30  m_path(0),
31  m_reversePath(0),
32  m_pathBegun(false),
33  m_pathComplete(false)
34 {
35  if (m_rawPath) {
36 
37  connect(m_rawPath, SIGNAL(modelChanged()),
38  this, SLOT(pathChanged()));
39 
40  connect(m_rawPath, SIGNAL(modelChangedWithin(int, int)),
41  this, SLOT(pathChangedWithin(int, int)));
42 
43  connect(m_rawPath, SIGNAL(completionChanged()),
44  this, SLOT(pathCompletionChanged()));
45 
46  constructPath();
48  }
49 
50  if (m_rawPath && m_rawPath->isReady()) {
52  }
53 }
54 
56 {
58  delete m_inputModel;
59 
61  delete m_rawPath;
62 
63  if (m_path) m_path->aboutToDelete();
64  delete m_path;
65 
67  delete m_reversePath;
68 }
69 
70 bool
72 {
73  if (m_rawPath) return m_rawPath->isOK();
74  else return true;
75 }
76 
77 int
79 {
80  int a = m_reference->getStartFrame();
81  int b = m_aligned->getStartFrame();
82  return std::min(a, b);
83 }
84 
85 int
87 {
88  int a = m_reference->getEndFrame();
89  int b = m_aligned->getEndFrame();
90  return std::max(a, b);
91 }
92 
93 int
95 {
96  return m_reference->getSampleRate();
97 }
98 
99 Model *
101 {
102  return new AlignmentModel
105  m_rawPath ? static_cast<SparseTimeValueModel *>(m_rawPath->clone()) : 0);
106 }
107 
108 bool
109 AlignmentModel::isReady(int *completion) const
110 {
111  if (!m_pathBegun && m_rawPath) {
112  if (completion) *completion = 0;
113  return false;
114  }
115  if (m_pathComplete || !m_rawPath) {
116  if (completion) *completion = 100;
117  return true;
118  }
119  return m_rawPath->isReady(completion);
120 }
121 
122 const ZoomConstraint *
124 {
125  return 0;
126 }
127 
128 const Model *
130 {
131  return m_reference;
132 }
133 
134 const Model *
136 {
137  return m_aligned;
138 }
139 
140 int
142 {
143 #ifdef DEBUG_ALIGNMENT_MODEL
144  SVDEBUG << "AlignmentModel::toReference(" << frame << ")" << endl;
145 #endif
146  if (!m_path) {
147  if (!m_rawPath) return frame;
148  constructPath();
149  }
150  return align(m_path, frame);
151 }
152 
153 int
155 {
156 #ifdef DEBUG_ALIGNMENT_MODEL
157  SVDEBUG << "AlignmentModel::fromReference(" << frame << ")" << endl;
158 #endif
159  if (!m_reversePath) {
160  if (!m_rawPath) return frame;
162  }
163  return align(m_reversePath, frame);
164 }
165 
166 void
168 {
169  if (m_pathComplete) {
170  cerr << "AlignmentModel: deleting raw path model" << endl;
172  delete m_rawPath;
173  m_rawPath = 0;
174  }
175 }
176 
177 void
179 {
180  if (!m_pathComplete) return;
181  constructPath();
183 }
184 
185 void
187 {
188  if (!m_rawPath) return;
189  m_pathBegun = true;
190 
191  if (!m_pathComplete) {
192 
193  int completion = 0;
194  m_rawPath->isReady(&completion);
195 
196 #ifdef DEBUG_ALIGNMENT_MODEL
197  SVDEBUG << "AlignmentModel::pathCompletionChanged: completion = "
198  << completion << endl;
199 #endif
200 
201  m_pathComplete = (completion == 100);
202 
203  if (m_pathComplete) {
204 
205  constructPath();
207 
209  delete m_inputModel;
210  m_inputModel = 0;
211  }
212  }
213 
214  emit completionChanged();
215 }
216 
217 void
219 {
220  if (!m_path) {
221  if (!m_rawPath) {
222  cerr << "ERROR: AlignmentModel::constructPath: "
223  << "No raw path available" << endl;
224  return;
225  }
226  m_path = new PathModel
228  } else {
229  if (!m_rawPath) return;
230  }
231 
232  m_path->clear();
233 
235 
236  for (SparseTimeValueModel::PointList::const_iterator i = points.begin();
237  i != points.end(); ++i) {
238  long frame = i->frame;
239  float value = i->value;
240  long rframe = lrintf(value * m_aligned->getSampleRate());
241  m_path->addPoint(PathPoint(frame, rframe));
242  }
243 
244 #ifdef DEBUG_ALIGNMENT_MODEL
245  SVDEBUG << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl;
246 #endif
247 }
248 
249 void
251 {
252  if (!m_reversePath) {
253  if (!m_path) {
254  cerr << "ERROR: AlignmentModel::constructReversePath: "
255  << "No forward path available" << endl;
256  return;
257  }
259  (m_path->getSampleRate(), m_path->getResolution(), false);
260  } else {
261  if (!m_path) return;
262  }
263 
264  m_reversePath->clear();
265 
267 
268  for (PathModel::PointList::const_iterator i = points.begin();
269  i != points.end(); ++i) {
270  long frame = i->frame;
271  long rframe = i->mapframe;
272  m_reversePath->addPoint(PathPoint(rframe, frame));
273  }
274 
275 #ifdef DEBUG_ALIGNMENT_MODEL
276  SVDEBUG << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl;
277 #endif
278 }
279 
280 int
281 AlignmentModel::align(PathModel *path, int frame) const
282 {
283  if (!path) return frame;
284 
285  // The path consists of a series of points, each with frame equal
286  // to the frame on the source model and mapframe equal to the
287  // frame on the target model. Both should be monotonically
288  // increasing.
289 
290  const PathModel::PointList &points = path->getPoints();
291 
292  if (points.empty()) {
293 #ifdef DEBUG_ALIGNMENT_MODEL
294  SVDEBUG << "AlignmentModel::align: No points" << endl;
295 #endif
296  return frame;
297  }
298 
299 #ifdef DEBUG_ALIGNMENT_MODEL
300  SVDEBUG << "AlignmentModel::align: frame " << frame << " requested" << endl;
301 #endif
302 
303  PathModel::Point point(frame);
304  PathModel::PointList::const_iterator i = points.lower_bound(point);
305  if (i == points.end()) {
306 #ifdef DEBUG_ALIGNMENT_MODEL
307  cerr << "Note: i == points.end()" << endl;
308 #endif
309  --i;
310  }
311  while (i != points.begin() && i->frame > long(frame)) --i;
312 
313  long foundFrame = i->frame;
314  long foundMapFrame = i->mapframe;
315 
316  long followingFrame = foundFrame;
317  long followingMapFrame = foundMapFrame;
318 
319  if (++i != points.end()) {
320 #ifdef DEBUG_ALIGNMENT_MODEL
321  cerr << "another point available" << endl;
322 #endif
323  followingFrame = i->frame;
324  followingMapFrame = i->mapframe;
325  } else {
326 #ifdef DEBUG_ALIGNMENT_MODEL
327  cerr << "no other point available" << endl;
328 #endif
329  }
330 
331  if (foundMapFrame < 0) return 0;
332 
333  int resultFrame = foundMapFrame;
334 
335  if (followingFrame != foundFrame && long(frame) > foundFrame) {
336  float interp =
337  float(frame - foundFrame) /
338  float(followingFrame - foundFrame);
339  resultFrame += lrintf((followingMapFrame - foundMapFrame) * interp);
340  }
341 
342 #ifdef DEBUG_ALIGNMENT_MODEL
343  SVDEBUG << "AlignmentModel::align: resultFrame = " << resultFrame << endl;
344 #endif
345 
346  return resultFrame;
347 }
348 
349 void
351 {
352  if (m_path) m_path->aboutToDelete();
353  delete m_path;
354  m_path = path;
355 #ifdef DEBUG_ALIGNMENT_MODEL
356  SVDEBUG << "AlignmentModel::setPath: path = " << m_path << endl;
357 #endif
359 #ifdef DEBUG_ALIGNMENT_MODEL
360  SVDEBUG << "AlignmentModel::setPath: after construction path = "
361  << m_path << ", rpath = " << m_reversePath << endl;
362 #endif
363 }
364 
365 void
366 AlignmentModel::toXml(QTextStream &stream,
367  QString indent,
368  QString extraAttributes) const
369 {
370  if (!m_path) {
371  SVDEBUG << "AlignmentModel::toXml: no path" << endl;
372  return;
373  }
374 
375  m_path->toXml(stream, indent, "");
376 
377  Model::toXml(stream, indent,
378  QString("type=\"alignment\" reference=\"%1\" aligned=\"%2\" path=\"%3\" %4")
382  .arg(extraAttributes));
383 }
384 
385 
virtual void toXml(QTextStream &out, QString indent="", QString extraAttributes="") const
Stream this exportable object out to XML on a text stream.
Definition: PathModel.h:73
void pathCompletionChanged()
std::multiset< TimeValuePoint, typename TimeValuePoint ::OrderComparator > PointList
Definition: SparseModel.h:69
virtual int getStartFrame() const
Return the first audio frame spanned by the model.
const Model * getAlignedModel() const
void completionChanged()
int fromReference(int frame) const
virtual int getSampleRate() const
Return the frame rate in frames per second.
Definition: SparseModel.h:53
void setPath(PathModel *path)
virtual int getStartFrame() const =0
Return the first audio frame spanned by the model.
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Stream this exportable object out to XML on a text stream.
static int getObjectExportId(const void *)
virtual bool isOK() const
Return true if the model was constructed successfully.
int toReference(int frame) const
virtual void addPoint(const PointType &point)
Add a point.
Definition: SparseModel.h:704
virtual int getPointCount() const
Get the total number of points in the model.
Definition: SparseModel.h:530
void modelChangedWithin(int startFrame, int endFrame)
void constructReversePath() const
virtual void toXml(QTextStream &stream, QString indent="", QString extraAttributes="") const
Stream this exportable object out to XML on a text stream.
Definition: Model.cpp:174
void constructPath() const
virtual Model * clone() const =0
Return a copy of this model.
virtual const PointList & getPoints() const
Get all points.
Definition: SparseModel.h:537
AlignmentModel(Model *reference, Model *aligned, Model *inputModel, SparseTimeValueModel *path)
void modelChanged()
PathModel * m_reversePath
virtual int getSampleRate() const =0
Return the frame rate in frames per second.
Model is the base class for all data models that represent any sort of data on a time scale based on ...
Definition: Model.h:35
PathModel * m_path
virtual bool isOK() const
Return true if the model was constructed successfully.
Definition: SparseModel.h:50
virtual void clear()
Remove all points.
Definition: SparseModel.h:691
Model * m_inputModel
virtual int getResolution() const
Definition: SparseModel.h:62
virtual bool isReady(int *completion=0) const
Return true if the model has finished loading or calculating all its data, for a model that is capabl...
virtual Model * clone() const
Return a copy of this model.
Definition: SparseModel.h:509
#define SVDEBUG
Definition: Debug.h:42
virtual int getEndFrame() const =0
Return the last audio frame spanned by the model.
virtual Model * clone() const
Return a copy of this model.
virtual int getEndFrame() const
Return the last audio frame spanned by the model.
void aboutToDelete()
Definition: Model.cpp:60
virtual const ZoomConstraint * getZoomConstraint() const
If this model imposes a zoom constraint, i.e.
SparseTimeValueModel * m_rawPath
ZoomConstraint is a simple interface that describes a limitation on the available zoom sizes for a vi...
int align(PathModel *path, int frame) const
void pathChangedWithin(int startFrame, int endFrame)
virtual bool isReady(int *completion=0) const
Return true if the model has finished loading or calculating all its data, for a model that is capabl...
Definition: SparseModel.h:132
const Model * getReferenceModel() const
Model * m_reference
virtual int getSampleRate() const
Return the frame rate in frames per second.