comparison data/model/AlignmentModel.cpp @ 1737:5d631f6129fe by-id

More on AlignmentModel
author Chris Cannam
date Tue, 25 Jun 2019 18:56:57 +0100
parents d91ff235e69d
children 4abc0f08adf9
comparison
equal deleted inserted replaced
1736:d9082ed16931 1737:5d631f6129fe
28 m_path(nullptr), 28 m_path(nullptr),
29 m_reversePath(nullptr), 29 m_reversePath(nullptr),
30 m_pathBegun(false), 30 m_pathBegun(false),
31 m_pathComplete(false) 31 m_pathComplete(false)
32 { 32 {
33 auto pathSourceModel = ModelById::getAs<SparseTimeValueModel>(pathSource); 33 setPathFrom(pathSource);
34
35 if (pathSourceModel) {
36
37 connect(pathSourceModel.get(), SIGNAL(modelChanged()),
38 this, SLOT(pathSourceChanged()));
39
40 connect(pathSourceModel.get(),
41 SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
42 this, SLOT(pathSourceChangedWithin(sv_frame_t, sv_frame_t)));
43
44 connect(pathSourceModel.get(), SIGNAL(completionChanged()),
45 this, SLOT(pathSourceCompletionChanged()));
46
47 constructPath();
48 constructReversePath();
49
50 if (pathSourceModel->isReady()) {
51 pathSourceCompletionChanged();
52 }
53 }
54 34
55 if (m_reference == m_aligned) { 35 if (m_reference == m_aligned) {
56 // Trivial alignment, e.g. of main model to itself, which we 36 // Trivial alignment, e.g. of main model to itself, which we
57 // record so that we can distinguish the reference model for 37 // record so that we can distinguish the reference model for
58 // alignments from an unaligned model. No path required 38 // alignments from an unaligned model. No path required
78 58
79 bool 59 bool
80 AlignmentModel::isOK() const 60 AlignmentModel::isOK() const
81 { 61 {
82 if (m_error != "") return false; 62 if (m_error != "") return false;
83 if (m_pathSource) return m_pathSource->isOK(); 63 if (m_pathSource.isNone()) return true;
64 auto pathSourceModel =
65 ModelById::getAs<SparseTimeValueModel>(m_pathSource);
66 if (pathSourceModel) {
67 return pathSourceModel->isOK();
68 }
84 return true; 69 return true;
85 } 70 }
86 71
87 sv_frame_t 72 sv_frame_t
88 AlignmentModel::getStartFrame() const 73 AlignmentModel::getStartFrame() const
89 { 74 {
90 sv_frame_t a = m_reference->getStartFrame(); 75 auto reference = ModelById::get(m_reference);
91 sv_frame_t b = m_aligned->getStartFrame(); 76 auto aligned = ModelById::get(m_aligned);
92 return std::min(a, b); 77
78 if (reference && aligned) {
79 sv_frame_t a = reference->getStartFrame();
80 sv_frame_t b = aligned->getStartFrame();
81 return std::min(a, b);
82 } else {
83 return 0;
84 }
93 } 85 }
94 86
95 sv_frame_t 87 sv_frame_t
96 AlignmentModel::getTrueEndFrame() const 88 AlignmentModel::getTrueEndFrame() const
97 { 89 {
98 sv_frame_t a = m_reference->getEndFrame(); 90 auto reference = ModelById::get(m_reference);
99 sv_frame_t b = m_aligned->getEndFrame(); 91 auto aligned = ModelById::get(m_aligned);
100 return std::max(a, b); 92
93 if (reference && aligned) {
94 sv_frame_t a = reference->getEndFrame();
95 sv_frame_t b = aligned->getEndFrame();
96 return std::max(a, b);
97 } else {
98 return 0;
99 }
101 } 100 }
102 101
103 sv_samplerate_t 102 sv_samplerate_t
104 AlignmentModel::getSampleRate() const 103 AlignmentModel::getSampleRate() const
105 { 104 {
106 return m_reference->getSampleRate(); 105 auto reference = ModelById::get(m_reference);
106 if (reference) {
107 return reference->getSampleRate();
108 } else {
109 return 0;
110 }
107 } 111 }
108 112
109 bool 113 bool
110 AlignmentModel::isReady(int *completion) const 114 AlignmentModel::isReady(int *completion) const
111 { 115 {
112 if (!m_pathBegun && m_pathSource) { 116 if (!m_pathBegun && !m_pathSource.isNone()) {
113 if (completion) *completion = 0; 117 if (completion) *completion = 0;
114 #ifdef DEBUG_ALIGNMENT_MODEL 118 #ifdef DEBUG_ALIGNMENT_MODEL
115 SVCERR << "AlignmentModel::isReady: path not begun" << endl; 119 SVCERR << "AlignmentModel::isReady: path not begun" << endl;
116 #endif 120 #endif
117 return false; 121 return false;
121 #ifdef DEBUG_ALIGNMENT_MODEL 125 #ifdef DEBUG_ALIGNMENT_MODEL
122 SVCERR << "AlignmentModel::isReady: path complete" << endl; 126 SVCERR << "AlignmentModel::isReady: path complete" << endl;
123 #endif 127 #endif
124 return true; 128 return true;
125 } 129 }
126 if (!m_pathSource) { 130 if (m_pathSource.isNone()) {
127 // lack of raw path could mean path is complete (in which case 131 // lack of raw path could mean path is complete (in which case
128 // m_pathComplete true above) or else no alignment has been 132 // m_pathComplete true above) or else no path source has been
129 // set at all yet (this case) 133 // set at all yet (this case)
130 if (completion) *completion = 0; 134 if (completion) *completion = 0;
131 #ifdef DEBUG_ALIGNMENT_MODEL 135 #ifdef DEBUG_ALIGNMENT_MODEL
132 SVCERR << "AlignmentModel::isReady: no raw path" << endl; 136 SVCERR << "AlignmentModel::isReady: no raw path" << endl;
133 #endif 137 #endif
134 return false; 138 return false;
135 } 139 }
136 return m_pathSource->isReady(completion); 140 auto pathSourceModel =
141 ModelById::getAs<SparseTimeValueModel>(m_pathSource);
142 if (pathSourceModel) {
143 return pathSourceModel->isReady(completion);
144 } else {
145 return true; // there is no meaningful answer here
146 }
137 } 147 }
138 148
139 const ZoomConstraint * 149 const ZoomConstraint *
140 AlignmentModel::getZoomConstraint() const 150 AlignmentModel::getZoomConstraint() const
141 { 151 {
142 return nullptr; 152 return nullptr;
143 } 153 }
144 154
145 const Model * 155 ModelId
146 AlignmentModel::getReferenceModel() const 156 AlignmentModel::getReferenceModel() const
147 { 157 {
148 return m_reference; 158 return m_reference;
149 } 159 }
150 160
151 const Model * 161 ModelId
152 AlignmentModel::getAlignedModel() const 162 AlignmentModel::getAlignedModel() const
153 { 163 {
154 return m_aligned; 164 return m_aligned;
155 } 165 }
156 166
159 { 169 {
160 #ifdef DEBUG_ALIGNMENT_MODEL 170 #ifdef DEBUG_ALIGNMENT_MODEL
161 cerr << "AlignmentModel::toReference(" << frame << ")" << endl; 171 cerr << "AlignmentModel::toReference(" << frame << ")" << endl;
162 #endif 172 #endif
163 if (!m_path) { 173 if (!m_path) {
164 if (!m_pathSource) return frame; 174 if (m_pathSource.isNone()) return frame;
165 constructPath(); 175 constructPath();
166 } 176 if (!m_path) return frame;
167 return align(m_path, frame); 177 }
178 return align(*m_path, frame);
168 } 179 }
169 180
170 sv_frame_t 181 sv_frame_t
171 AlignmentModel::fromReference(sv_frame_t frame) const 182 AlignmentModel::fromReference(sv_frame_t frame) const
172 { 183 {
173 #ifdef DEBUG_ALIGNMENT_MODEL 184 #ifdef DEBUG_ALIGNMENT_MODEL
174 cerr << "AlignmentModel::fromReference(" << frame << ")" << endl; 185 cerr << "AlignmentModel::fromReference(" << frame << ")" << endl;
175 #endif 186 #endif
176 if (!m_reversePath) { 187 if (!m_reversePath) {
177 if (!m_pathSource) return frame; 188 if (m_pathSource.isNone()) return frame;
178 constructReversePath(); 189 constructReversePath();
179 } 190 if (!m_reversePath) return frame;
180 return align(m_reversePath, frame); 191 }
192 return align(*m_reversePath, frame);
181 } 193 }
182 194
183 void 195 void
184 AlignmentModel::pathSourceChanged() 196 AlignmentModel::pathSourceChanged()
185 { 197 {
186 if (m_pathComplete) { 198 if (m_pathComplete) {
199 /*!!!
187 cerr << "AlignmentModel: deleting raw path model" << endl; 200 cerr << "AlignmentModel: deleting raw path model" << endl;
188 if (m_pathSource) m_pathSource->aboutToDelete(); 201 if (m_pathSource) m_pathSource->aboutToDelete();
189 delete m_pathSource; 202 delete m_pathSource;
190 m_pathSource = nullptr; 203 m_pathSource = nullptr;
204 */
205 m_pathSource = {};
191 } 206 }
192 } 207 }
193 208
194 void 209 void
195 AlignmentModel::pathSourceChangedWithin(sv_frame_t, sv_frame_t) 210 AlignmentModel::pathSourceChangedWithin(sv_frame_t, sv_frame_t)
200 } 215 }
201 216
202 void 217 void
203 AlignmentModel::pathSourceCompletionChanged() 218 AlignmentModel::pathSourceCompletionChanged()
204 { 219 {
205 if (!m_pathSource) return; 220 auto pathSourceModel =
221 ModelById::getAs<SparseTimeValueModel>(m_pathSource);
222 if (!pathSourceModel) return;
223
206 m_pathBegun = true; 224 m_pathBegun = true;
207 225
208 if (!m_pathComplete) { 226 if (!m_pathComplete) {
209 227
210 int completion = 0; 228 int completion = 0;
211 m_pathSource->isReady(&completion); 229 pathSourceModel->isReady(&completion);
212 230
213 #ifdef DEBUG_ALIGNMENT_MODEL 231 #ifdef DEBUG_ALIGNMENT_MODEL
214 SVCERR << "AlignmentModel::pathCompletionChanged: completion = " 232 SVCERR << "AlignmentModel::pathCompletionChanged: completion = "
215 << completion << endl; 233 << completion << endl;
216 #endif 234 #endif
232 } 250 }
233 251
234 void 252 void
235 AlignmentModel::constructPath() const 253 AlignmentModel::constructPath() const
236 { 254 {
255 auto alignedModel = ModelById::get(m_aligned);
256 if (!alignedModel) return;
257
258 auto pathSourceModel =
259 ModelById::getAs<SparseTimeValueModel>(m_pathSource);
237 if (!m_path) { 260 if (!m_path) {
238 if (!m_pathSource) { 261 if (pathSourceModel) {
239 cerr << "ERROR: AlignmentModel::constructPath: " 262 cerr << "ERROR: AlignmentModel::constructPath: "
240 << "No raw path available" << endl; 263 << "No raw path available" << endl;
241 return; 264 return;
242 } 265 }
243 m_path = new PathModel 266 m_path.reset(new PathModel
244 (m_pathSource->getSampleRate(), m_pathSource->getResolution(), false); 267 (pathSourceModel->getSampleRate(),
245 } else { 268 pathSourceModel->getResolution(), false));
246 if (!m_pathSource) return; 269 } else {
270 if (!pathSourceModel) return;
247 } 271 }
248 272
249 m_path->clear(); 273 m_path->clear();
250 274
251 EventVector points = m_pathSource->getAllEvents(); 275 EventVector points = pathSourceModel->getAllEvents();
252 276
253 for (const auto &p: points) { 277 for (const auto &p: points) {
254 sv_frame_t frame = p.getFrame(); 278 sv_frame_t frame = p.getFrame();
255 double value = p.getValue(); 279 double value = p.getValue();
256 sv_frame_t rframe = lrint(value * m_aligned->getSampleRate()); 280 sv_frame_t rframe = lrint(value * alignedModel->getSampleRate());
257 m_path->add(PathPoint(frame, rframe)); 281 m_path->add(PathPoint(frame, rframe));
258 } 282 }
259 283
260 #ifdef DEBUG_ALIGNMENT_MODEL 284 #ifdef DEBUG_ALIGNMENT_MODEL
261 cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl; 285 cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl;
269 if (!m_path) { 293 if (!m_path) {
270 cerr << "ERROR: AlignmentModel::constructReversePath: " 294 cerr << "ERROR: AlignmentModel::constructReversePath: "
271 << "No forward path available" << endl; 295 << "No forward path available" << endl;
272 return; 296 return;
273 } 297 }
274 m_reversePath = new PathModel 298 m_reversePath.reset(new PathModel
275 (m_path->getSampleRate(), m_path->getResolution(), false); 299 (m_path->getSampleRate(),
300 m_path->getResolution(), false));
276 } else { 301 } else {
277 if (!m_path) return; 302 if (!m_path) return;
278 } 303 }
279 304
280 m_reversePath->clear(); 305 m_reversePath->clear();
292 cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl; 317 cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << endl;
293 #endif 318 #endif
294 } 319 }
295 320
296 sv_frame_t 321 sv_frame_t
297 AlignmentModel::align(PathModel *path, sv_frame_t frame) const 322 AlignmentModel::align(const PathModel &path, sv_frame_t frame) const
298 { 323 {
299 if (!path) return frame;
300
301 // The path consists of a series of points, each with frame equal 324 // The path consists of a series of points, each with frame equal
302 // to the frame on the source model and mapframe equal to the 325 // to the frame on the source model and mapframe equal to the
303 // frame on the target model. Both should be monotonically 326 // frame on the target model. Both should be monotonically
304 // increasing. 327 // increasing.
305 328
306 const PathModel::PointList &points = path->getPoints(); 329 const PathModel::PointList &points = path.getPoints();
307 330
308 if (points.empty()) { 331 if (points.empty()) {
309 #ifdef DEBUG_ALIGNMENT_MODEL 332 #ifdef DEBUG_ALIGNMENT_MODEL
310 cerr << "AlignmentModel::align: No points" << endl; 333 cerr << "AlignmentModel::align: No points" << endl;
311 #endif 334 #endif
367 390
368 return resultFrame; 391 return resultFrame;
369 } 392 }
370 393
371 void 394 void
372 AlignmentModel::setPathFrom(SparseTimeValueModel *rawpath) 395 AlignmentModel::setPathFrom(ModelId pathSource)
373 { 396 {
374 if (m_pathSource) m_pathSource->aboutToDelete(); 397 m_pathSource = pathSource;
375 delete m_pathSource; 398
376 399 auto pathSourceModel =
377 m_pathSource = rawpath; 400 ModelById::getAs<SparseTimeValueModel>(m_pathSource);
378 401
379 if (!m_pathSource) { 402 if (pathSourceModel) {
380 return; 403
381 } 404 connect(pathSourceModel.get(), SIGNAL(modelChanged()),
382 405 this, SLOT(pathSourceChanged()));
383 connect(m_pathSource, SIGNAL(modelChanged()), 406
384 this, SLOT(pathChanged())); 407 connect(pathSourceModel.get(),
385 408 SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
386 connect(m_pathSource, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)), 409 this, SLOT(pathSourceChangedWithin(sv_frame_t, sv_frame_t)));
387 this, SLOT(pathChangedWithin(sv_frame_t, sv_frame_t)));
388 410
389 connect(m_pathSource, SIGNAL(completionChanged()), 411 connect(pathSourceModel.get(), SIGNAL(completionChanged()),
390 this, SLOT(pathCompletionChanged())); 412 this, SLOT(pathSourceCompletionChanged()));
391 413
392 constructPath(); 414 constructPath();
393 constructReversePath(); 415 constructReversePath();
394 416
395 if (m_pathSource->isReady()) { 417 if (pathSourceModel->isReady()) {
396 pathCompletionChanged(); 418 pathSourceCompletionChanged();
397 } 419 }
398 } 420 }
399 421 }
400 void 422
401 AlignmentModel::setPath(PathModel *path) 423 void
402 { 424 AlignmentModel::setPath(const PathModel &path)
403 if (m_path) m_path->aboutToDelete(); 425 {
404 delete m_path; 426 //!!! if (m_path) m_path->aboutToDelete();
427 // delete m_path;
405 m_path = path; 428 m_path = path;
406 m_pathComplete = true; 429 m_pathComplete = true;
407 #ifdef DEBUG_ALIGNMENT_MODEL 430 #ifdef DEBUG_ALIGNMENT_MODEL
408 cerr << "AlignmentModel::setPath: path = " << m_path << endl; 431 cerr << "AlignmentModel::setPath: path = " << m_path << endl;
409 #endif 432 #endif