Mercurial > hg > svcore
comparison 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 |
comparison
equal
deleted
inserted
replaced
337:a6fab10ff9e6 | 384:6f6ab834449d |
---|---|
15 | 15 |
16 #include "AlignmentModel.h" | 16 #include "AlignmentModel.h" |
17 | 17 |
18 #include "SparseTimeValueModel.h" | 18 #include "SparseTimeValueModel.h" |
19 | 19 |
20 //#define DEBUG_ALIGNMENT_MODEL 1 | |
21 | |
20 AlignmentModel::AlignmentModel(Model *reference, | 22 AlignmentModel::AlignmentModel(Model *reference, |
21 Model *aligned, | 23 Model *aligned, |
22 Model *inputModel, | 24 Model *inputModel, |
23 SparseTimeValueModel *path) : | 25 SparseTimeValueModel *path) : |
24 m_reference(reference), | 26 m_reference(reference), |
25 m_aligned(aligned), | 27 m_aligned(aligned), |
26 m_inputModel(inputModel), | 28 m_inputModel(inputModel), |
27 m_path(path), | 29 m_rawPath(path), |
30 m_path(0), | |
28 m_reversePath(0), | 31 m_reversePath(0), |
29 m_pathBegun(false), | 32 m_pathBegun(false), |
30 m_pathComplete(false) | 33 m_pathComplete(false) |
31 { | 34 { |
32 connect(m_path, SIGNAL(modelChanged()), | 35 if (m_rawPath) { |
33 this, SLOT(pathChanged())); | 36 |
34 | 37 connect(m_rawPath, SIGNAL(modelChanged()), |
35 connect(m_path, SIGNAL(modelChanged(size_t, size_t)), | 38 this, SLOT(pathChanged())); |
36 this, SLOT(pathChanged(size_t, size_t))); | 39 |
37 | 40 connect(m_rawPath, SIGNAL(modelChanged(size_t, size_t)), |
38 connect(m_path, SIGNAL(completionChanged()), | 41 this, SLOT(pathChanged(size_t, size_t))); |
39 this, SLOT(pathCompletionChanged())); | 42 |
40 | 43 connect(m_rawPath, SIGNAL(completionChanged()), |
44 this, SLOT(pathCompletionChanged())); | |
45 } | |
46 | |
47 constructPath(); | |
41 constructReversePath(); | 48 constructReversePath(); |
42 } | 49 } |
43 | 50 |
44 AlignmentModel::~AlignmentModel() | 51 AlignmentModel::~AlignmentModel() |
45 { | 52 { |
46 delete m_inputModel; | 53 delete m_inputModel; |
54 delete m_rawPath; | |
47 delete m_path; | 55 delete m_path; |
48 delete m_reversePath; | 56 delete m_reversePath; |
49 } | 57 } |
50 | 58 |
51 bool | 59 bool |
52 AlignmentModel::isOK() const | 60 AlignmentModel::isOK() const |
53 { | 61 { |
54 return m_path->isOK(); | 62 if (m_rawPath) return m_rawPath->isOK(); |
63 else return true; | |
55 } | 64 } |
56 | 65 |
57 size_t | 66 size_t |
58 AlignmentModel::getStartFrame() const | 67 AlignmentModel::getStartFrame() const |
59 { | 68 { |
60 //!!! do we care about distinct rates? | |
61 size_t a = m_reference->getStartFrame(); | 69 size_t a = m_reference->getStartFrame(); |
62 size_t b = m_aligned->getStartFrame(); | 70 size_t b = m_aligned->getStartFrame(); |
63 return std::min(a, b); | 71 return std::min(a, b); |
64 } | 72 } |
65 | 73 |
66 size_t | 74 size_t |
67 AlignmentModel::getEndFrame() const | 75 AlignmentModel::getEndFrame() const |
68 { | 76 { |
69 //!!! do we care about distinct rates? | |
70 size_t a = m_reference->getEndFrame(); | 77 size_t a = m_reference->getEndFrame(); |
71 size_t b = m_aligned->getEndFrame(); | 78 size_t b = m_aligned->getEndFrame(); |
72 return std::max(a, b); | 79 return std::max(a, b); |
73 } | 80 } |
74 | 81 |
82 AlignmentModel::clone() const | 89 AlignmentModel::clone() const |
83 { | 90 { |
84 return new AlignmentModel | 91 return new AlignmentModel |
85 (m_reference, m_aligned, | 92 (m_reference, m_aligned, |
86 m_inputModel ? m_inputModel->clone() : 0, | 93 m_inputModel ? m_inputModel->clone() : 0, |
87 m_path ? static_cast<SparseTimeValueModel *>(m_path->clone()) : 0); | 94 m_rawPath ? static_cast<SparseTimeValueModel *>(m_rawPath->clone()) : 0); |
88 } | 95 } |
89 | 96 |
90 bool | 97 bool |
91 AlignmentModel::isReady(int *completion) const | 98 AlignmentModel::isReady(int *completion) const |
92 { | 99 { |
93 if (!m_pathBegun) { | 100 if (!m_pathBegun) { |
94 completion = 0; | 101 if (completion) *completion = 0; |
95 return false; | 102 return false; |
96 } | 103 } |
97 return m_path->isReady(completion); | 104 if (m_pathComplete || !m_rawPath) { |
105 if (completion) *completion = 100; | |
106 return true; | |
107 } | |
108 return m_rawPath->isReady(completion); | |
98 } | 109 } |
99 | 110 |
100 const ZoomConstraint * | 111 const ZoomConstraint * |
101 AlignmentModel::getZoomConstraint() const | 112 AlignmentModel::getZoomConstraint() const |
102 { | 113 { |
103 return m_path->getZoomConstraint(); | 114 return 0; |
104 } | 115 } |
105 | 116 |
106 const Model * | 117 const Model * |
107 AlignmentModel::getReferenceModel() const | 118 AlignmentModel::getReferenceModel() const |
108 { | 119 { |
116 } | 127 } |
117 | 128 |
118 size_t | 129 size_t |
119 AlignmentModel::toReference(size_t frame) const | 130 AlignmentModel::toReference(size_t frame) const |
120 { | 131 { |
121 // std::cerr << "AlignmentModel::toReference(" << frame << ")" << std::endl; | 132 #ifdef DEBUG_ALIGNMENT_MODEL |
122 if (!m_reversePath) constructReversePath(); | 133 std::cerr << "AlignmentModel::toReference(" << frame << ")" << std::endl; |
134 #endif | |
135 if (!m_path) { | |
136 if (!m_rawPath) return frame; | |
137 constructPath(); | |
138 } | |
139 return align(m_path, frame); | |
140 } | |
141 | |
142 size_t | |
143 AlignmentModel::fromReference(size_t frame) const | |
144 { | |
145 #ifdef DEBUG_ALIGNMENT_MODEL | |
146 std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl; | |
147 #endif | |
148 if (!m_reversePath) { | |
149 if (!m_rawPath) return frame; | |
150 constructReversePath(); | |
151 } | |
123 return align(m_reversePath, frame); | 152 return align(m_reversePath, frame); |
124 } | 153 } |
125 | 154 |
126 size_t | |
127 AlignmentModel::fromReference(size_t frame) const | |
128 { | |
129 // std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl; | |
130 return align(m_path, frame); | |
131 } | |
132 | |
133 void | 155 void |
134 AlignmentModel::pathChanged() | 156 AlignmentModel::pathChanged() |
135 { | 157 { |
158 if (m_pathComplete) { | |
159 std::cerr << "AlignmentModel: deleting raw path model" << std::endl; | |
160 delete m_rawPath; | |
161 m_rawPath = 0; | |
162 } | |
136 } | 163 } |
137 | 164 |
138 void | 165 void |
139 AlignmentModel::pathChanged(size_t, size_t) | 166 AlignmentModel::pathChanged(size_t, size_t) |
140 { | 167 { |
141 if (!m_pathComplete) return; | 168 if (!m_pathComplete) return; |
169 constructPath(); | |
142 constructReversePath(); | 170 constructReversePath(); |
143 } | 171 } |
144 | 172 |
145 void | 173 void |
146 AlignmentModel::pathCompletionChanged() | 174 AlignmentModel::pathCompletionChanged() |
147 { | 175 { |
176 if (!m_rawPath) return; | |
148 m_pathBegun = true; | 177 m_pathBegun = true; |
149 | 178 |
150 if (!m_pathComplete) { | 179 if (!m_pathComplete) { |
180 | |
151 int completion = 0; | 181 int completion = 0; |
152 m_path->isReady(&completion); | 182 m_rawPath->isReady(&completion); |
153 // std::cerr << "AlignmentModel::pathCompletionChanged: completion = " | 183 |
154 // << completion << std::endl; | 184 #ifdef DEBUG_ALIGNMENT_MODEL |
185 std::cerr << "AlignmentModel::pathCompletionChanged: completion = " | |
186 << completion << std::endl; | |
187 #endif | |
188 | |
155 m_pathComplete = (completion == 100); | 189 m_pathComplete = (completion == 100); |
190 | |
156 if (m_pathComplete) { | 191 if (m_pathComplete) { |
192 | |
193 constructPath(); | |
157 constructReversePath(); | 194 constructReversePath(); |
195 | |
158 delete m_inputModel; | 196 delete m_inputModel; |
159 m_inputModel = 0; | 197 m_inputModel = 0; |
160 } | 198 } |
161 } | 199 } |
162 | 200 |
163 emit completionChanged(); | 201 emit completionChanged(); |
164 } | 202 } |
165 | 203 |
166 void | 204 void |
167 AlignmentModel::constructReversePath() const | 205 AlignmentModel::constructPath() const |
168 { | 206 { |
169 if (!m_reversePath) { | 207 if (!m_path) { |
170 m_reversePath = new SparseTimeValueModel | 208 if (!m_rawPath) { |
171 (m_path->getSampleRate(), m_path->getResolution(), false); | 209 std::cerr << "ERROR: AlignmentModel::constructPath: " |
172 } | 210 << "No raw path available" << std::endl; |
173 | 211 return; |
174 m_reversePath->clear(); | 212 } |
175 | 213 m_path = new PathModel |
176 SparseTimeValueModel::PointList points = m_path->getPoints(); | 214 (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false); |
215 } else { | |
216 if (!m_rawPath) return; | |
217 } | |
218 | |
219 m_path->clear(); | |
220 | |
221 SparseTimeValueModel::PointList points = m_rawPath->getPoints(); | |
177 | 222 |
178 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); | 223 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); |
179 i != points.end(); ++i) { | 224 i != points.end(); ++i) { |
180 long frame = i->frame; | 225 long frame = i->frame; |
181 float value = i->value; | 226 float value = i->value; |
182 long rframe = lrintf(value * m_aligned->getSampleRate()); | 227 long rframe = lrintf(value * m_aligned->getSampleRate()); |
183 float rvalue = (float)frame / (float)m_reference->getSampleRate(); | 228 m_path->addPoint(PathPoint(frame, rframe)); |
184 m_reversePath->addPoint | 229 } |
185 (SparseTimeValueModel::Point(rframe, rvalue, "")); | 230 |
186 } | 231 #ifdef DEBUG_ALIGNMENT_MODEL |
187 | 232 std::cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl; |
188 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; | 233 #endif |
189 } | 234 } |
190 | 235 |
191 size_t | 236 void |
192 AlignmentModel::align(SparseTimeValueModel *path, size_t frame) const | 237 AlignmentModel::constructReversePath() const |
193 { | 238 { |
194 // The path consists of a series of points, each with x (time) | 239 if (!m_reversePath) { |
195 // equal to the time on the source model and y (value) equal to | 240 if (!m_rawPath) { |
196 // the time on the target model. Times and values are both | 241 std::cerr << "ERROR: AlignmentModel::constructReversePath: " |
197 // monotonically increasing. | 242 << "No raw path available" << std::endl; |
198 | 243 return; |
199 const SparseTimeValueModel::PointList &points = path->getPoints(); | 244 } |
245 m_reversePath = new PathModel | |
246 (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false); | |
247 } else { | |
248 if (!m_rawPath) return; | |
249 } | |
250 | |
251 m_reversePath->clear(); | |
252 | |
253 SparseTimeValueModel::PointList points = m_rawPath->getPoints(); | |
254 | |
255 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); | |
256 i != points.end(); ++i) { | |
257 long frame = i->frame; | |
258 float value = i->value; | |
259 long rframe = lrintf(value * m_aligned->getSampleRate()); | |
260 m_reversePath->addPoint(PathPoint(rframe, frame)); | |
261 } | |
262 | |
263 #ifdef DEBUG_ALIGNMENT_MODEL | |
264 std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl; | |
265 #endif | |
266 } | |
267 | |
268 size_t | |
269 AlignmentModel::align(PathModel *path, size_t frame) const | |
270 { | |
271 if (!path) return frame; | |
272 | |
273 // The path consists of a series of points, each with frame equal | |
274 // to the frame on the source model and mapframe equal to the | |
275 // frame on the target model. Both should be monotonically | |
276 // increasing. | |
277 | |
278 const PathModel::PointList &points = path->getPoints(); | |
200 | 279 |
201 if (points.empty()) { | 280 if (points.empty()) { |
202 // std::cerr << "AlignmentModel::align: No points" << std::endl; | 281 #ifdef DEBUG_ALIGNMENT_MODEL |
282 std::cerr << "AlignmentModel::align: No points" << std::endl; | |
283 #endif | |
203 return frame; | 284 return frame; |
204 } | 285 } |
205 | 286 |
206 SparseTimeValueModel::Point point(frame); | 287 #ifdef DEBUG_ALIGNMENT_MODEL |
207 SparseTimeValueModel::PointList::const_iterator i = points.lower_bound(point); | 288 std::cerr << "AlignmentModel::align: frame " << frame << " requested" << std::endl; |
208 if (i == points.end()) --i; | 289 #endif |
209 while (i != points.begin() && i->frame > frame) --i; | 290 |
291 PathModel::Point point(frame); | |
292 PathModel::PointList::const_iterator i = points.lower_bound(point); | |
293 if (i == points.end()) { | |
294 #ifdef DEBUG_ALIGNMENT_MODEL | |
295 std::cerr << "Note: i == points.end()" << std::endl; | |
296 #endif | |
297 --i; | |
298 } | |
299 while (i != points.begin() && i->frame > long(frame)) --i; | |
210 | 300 |
211 long foundFrame = i->frame; | 301 long foundFrame = i->frame; |
212 float foundTime = i->value; | 302 long foundMapFrame = i->mapframe; |
213 | 303 |
214 long followingFrame = foundFrame; | 304 long followingFrame = foundFrame; |
215 float followingTime = foundTime; | 305 long followingMapFrame = foundMapFrame; |
216 | 306 |
217 if (++i != points.end()) { | 307 if (++i != points.end()) { |
308 #ifdef DEBUG_ALIGNMENT_MODEL | |
309 std::cerr << "another point available" << std::endl; | |
310 #endif | |
218 followingFrame = i->frame; | 311 followingFrame = i->frame; |
219 followingTime = i->value; | 312 followingMapFrame = i->mapframe; |
220 } | 313 } else { |
221 | 314 #ifdef DEBUG_ALIGNMENT_MODEL |
222 float resultTime = foundTime; | 315 std::cerr << "no other point available" << std::endl; |
223 | 316 #endif |
224 if (followingFrame != foundFrame && frame > foundFrame) { | 317 } |
225 | 318 |
226 // std::cerr << "AlignmentModel::align: foundFrame = " << foundFrame << ", frame = " << frame << ", followingFrame = " << followingFrame << std::endl; | 319 if (foundMapFrame < 0) return 0; |
227 | 320 |
228 float interp = float(frame - foundFrame) / float(followingFrame - foundFrame); | 321 size_t resultFrame = foundMapFrame; |
229 // std::cerr << "AlignmentModel::align: interp = " << interp << ", result " << resultTime << " -> "; | 322 |
230 | 323 if (followingFrame != foundFrame && long(frame) > foundFrame) { |
231 resultTime += (followingTime - foundTime) * interp; | 324 float interp = |
232 | 325 float(frame - foundFrame) / |
233 // std::cerr << resultTime << std::endl; | 326 float(followingFrame - foundFrame); |
234 } | 327 resultFrame += lrintf((followingMapFrame - foundMapFrame) * interp); |
235 | 328 } |
236 size_t resultFrame = lrintf(resultTime * getSampleRate()); | 329 |
237 | 330 #ifdef DEBUG_ALIGNMENT_MODEL |
238 // std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl; | 331 std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl; |
332 #endif | |
239 | 333 |
240 return resultFrame; | 334 return resultFrame; |
241 } | 335 } |
242 | 336 |