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