Mercurial > hg > svcore
comparison data/model/AlignmentModel.cpp @ 338:f14e2f7b24f7
* More space and time efficient AlignmentModel
author | Chris Cannam |
---|---|
date | Thu, 22 Nov 2007 11:09:26 +0000 |
parents | 1afaf98dbf11 |
children | ba30f4a3e3be |
comparison
equal
deleted
inserted
replaced
336:5cd7f6d10d47 | 338:f14e2f7b24f7 |
---|---|
22 Model *inputModel, | 22 Model *inputModel, |
23 SparseTimeValueModel *path) : | 23 SparseTimeValueModel *path) : |
24 m_reference(reference), | 24 m_reference(reference), |
25 m_aligned(aligned), | 25 m_aligned(aligned), |
26 m_inputModel(inputModel), | 26 m_inputModel(inputModel), |
27 m_path(path), | 27 m_rawPath(path), |
28 m_path(0), | |
28 m_reversePath(0), | 29 m_reversePath(0), |
29 m_pathBegun(false), | 30 m_pathBegun(false), |
30 m_pathComplete(false) | 31 m_pathComplete(false) |
31 { | 32 { |
32 connect(m_path, SIGNAL(modelChanged()), | 33 connect(m_rawPath, SIGNAL(modelChanged()), |
33 this, SLOT(pathChanged())); | 34 this, SLOT(pathChanged())); |
34 | 35 |
35 connect(m_path, SIGNAL(modelChanged(size_t, size_t)), | 36 connect(m_rawPath, SIGNAL(modelChanged(size_t, size_t)), |
36 this, SLOT(pathChanged(size_t, size_t))); | 37 this, SLOT(pathChanged(size_t, size_t))); |
37 | 38 |
38 connect(m_path, SIGNAL(completionChanged()), | 39 connect(m_rawPath, SIGNAL(completionChanged()), |
39 this, SLOT(pathCompletionChanged())); | 40 this, SLOT(pathCompletionChanged())); |
40 | 41 |
42 constructPath(); | |
41 constructReversePath(); | 43 constructReversePath(); |
42 } | 44 } |
43 | 45 |
44 AlignmentModel::~AlignmentModel() | 46 AlignmentModel::~AlignmentModel() |
45 { | 47 { |
46 delete m_inputModel; | 48 delete m_inputModel; |
49 delete m_rawPath; | |
47 delete m_path; | 50 delete m_path; |
48 delete m_reversePath; | 51 delete m_reversePath; |
49 } | 52 } |
50 | 53 |
51 bool | 54 bool |
52 AlignmentModel::isOK() const | 55 AlignmentModel::isOK() const |
53 { | 56 { |
54 return m_path->isOK(); | 57 if (m_rawPath) return m_rawPath->isOK(); |
58 else return true; | |
55 } | 59 } |
56 | 60 |
57 size_t | 61 size_t |
58 AlignmentModel::getStartFrame() const | 62 AlignmentModel::getStartFrame() const |
59 { | 63 { |
60 //!!! do we care about distinct rates? | |
61 size_t a = m_reference->getStartFrame(); | 64 size_t a = m_reference->getStartFrame(); |
62 size_t b = m_aligned->getStartFrame(); | 65 size_t b = m_aligned->getStartFrame(); |
63 return std::min(a, b); | 66 return std::min(a, b); |
64 } | 67 } |
65 | 68 |
66 size_t | 69 size_t |
67 AlignmentModel::getEndFrame() const | 70 AlignmentModel::getEndFrame() const |
68 { | 71 { |
69 //!!! do we care about distinct rates? | |
70 size_t a = m_reference->getEndFrame(); | 72 size_t a = m_reference->getEndFrame(); |
71 size_t b = m_aligned->getEndFrame(); | 73 size_t b = m_aligned->getEndFrame(); |
72 return std::max(a, b); | 74 return std::max(a, b); |
73 } | 75 } |
74 | 76 |
82 AlignmentModel::clone() const | 84 AlignmentModel::clone() const |
83 { | 85 { |
84 return new AlignmentModel | 86 return new AlignmentModel |
85 (m_reference, m_aligned, | 87 (m_reference, m_aligned, |
86 m_inputModel ? m_inputModel->clone() : 0, | 88 m_inputModel ? m_inputModel->clone() : 0, |
87 m_path ? static_cast<SparseTimeValueModel *>(m_path->clone()) : 0); | 89 m_rawPath ? static_cast<SparseTimeValueModel *>(m_rawPath->clone()) : 0); |
88 } | 90 } |
89 | 91 |
90 bool | 92 bool |
91 AlignmentModel::isReady(int *completion) const | 93 AlignmentModel::isReady(int *completion) const |
92 { | 94 { |
93 if (!m_pathBegun) { | 95 if (!m_pathBegun) { |
94 completion = 0; | 96 if (completion) *completion = 0; |
95 return false; | 97 return false; |
96 } | 98 } |
97 return m_path->isReady(completion); | 99 if (m_pathComplete || !m_rawPath) { |
100 if (completion) *completion = 100; | |
101 return true; | |
102 } | |
103 return m_rawPath->isReady(completion); | |
98 } | 104 } |
99 | 105 |
100 const ZoomConstraint * | 106 const ZoomConstraint * |
101 AlignmentModel::getZoomConstraint() const | 107 AlignmentModel::getZoomConstraint() const |
102 { | 108 { |
103 return m_path->getZoomConstraint(); | 109 return 0; |
104 } | 110 } |
105 | 111 |
106 const Model * | 112 const Model * |
107 AlignmentModel::getReferenceModel() const | 113 AlignmentModel::getReferenceModel() const |
108 { | 114 { |
125 | 131 |
126 size_t | 132 size_t |
127 AlignmentModel::fromReference(size_t frame) const | 133 AlignmentModel::fromReference(size_t frame) const |
128 { | 134 { |
129 // std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl; | 135 // std::cerr << "AlignmentModel::fromReference(" << frame << ")" << std::endl; |
136 if (!m_path) constructPath(); | |
130 return align(m_path, frame); | 137 return align(m_path, frame); |
131 } | 138 } |
132 | 139 |
133 void | 140 void |
134 AlignmentModel::pathChanged() | 141 AlignmentModel::pathChanged() |
137 | 144 |
138 void | 145 void |
139 AlignmentModel::pathChanged(size_t, size_t) | 146 AlignmentModel::pathChanged(size_t, size_t) |
140 { | 147 { |
141 if (!m_pathComplete) return; | 148 if (!m_pathComplete) return; |
149 constructPath(); | |
142 constructReversePath(); | 150 constructReversePath(); |
143 } | 151 } |
144 | 152 |
145 void | 153 void |
146 AlignmentModel::pathCompletionChanged() | 154 AlignmentModel::pathCompletionChanged() |
147 { | 155 { |
148 m_pathBegun = true; | 156 m_pathBegun = true; |
149 | 157 |
150 if (!m_pathComplete) { | 158 if (!m_pathComplete) { |
159 | |
151 int completion = 0; | 160 int completion = 0; |
152 m_path->isReady(&completion); | 161 m_rawPath->isReady(&completion); |
162 | |
153 // std::cerr << "AlignmentModel::pathCompletionChanged: completion = " | 163 // std::cerr << "AlignmentModel::pathCompletionChanged: completion = " |
154 // << completion << std::endl; | 164 // << completion << std::endl; |
165 | |
155 m_pathComplete = (completion == 100); | 166 m_pathComplete = (completion == 100); |
167 | |
156 if (m_pathComplete) { | 168 if (m_pathComplete) { |
169 | |
170 constructPath(); | |
157 constructReversePath(); | 171 constructReversePath(); |
172 | |
173 delete m_rawPath; | |
174 m_rawPath = 0; | |
175 | |
158 delete m_inputModel; | 176 delete m_inputModel; |
159 m_inputModel = 0; | 177 m_inputModel = 0; |
160 } | 178 } |
161 } | 179 } |
162 | 180 |
163 emit completionChanged(); | 181 emit completionChanged(); |
164 } | 182 } |
165 | 183 |
166 void | 184 void |
167 AlignmentModel::constructReversePath() const | 185 AlignmentModel::constructPath() const |
168 { | 186 { |
169 if (!m_reversePath) { | 187 if (!m_path) { |
170 m_reversePath = new SparseTimeValueModel | 188 if (!m_rawPath) { |
171 (m_path->getSampleRate(), m_path->getResolution(), false); | 189 std::cerr << "ERROR: AlignmentModel::constructPath: " |
172 } | 190 << "No raw path available" << std::endl; |
173 | 191 return; |
174 m_reversePath->clear(); | 192 } |
175 | 193 m_path = new PathModel |
176 SparseTimeValueModel::PointList points = m_path->getPoints(); | 194 (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false); |
195 } else { | |
196 if (!m_rawPath) return; | |
197 } | |
198 | |
199 m_path->clear(); | |
200 | |
201 SparseTimeValueModel::PointList points = m_rawPath->getPoints(); | |
177 | 202 |
178 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); | 203 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); |
179 i != points.end(); ++i) { | 204 i != points.end(); ++i) { |
180 long frame = i->frame; | 205 long frame = i->frame; |
181 float value = i->value; | 206 float value = i->value; |
182 long rframe = lrintf(value * m_aligned->getSampleRate()); | 207 long rframe = lrintf(value * m_aligned->getSampleRate()); |
183 float rvalue = (float)frame / (float)m_reference->getSampleRate(); | 208 m_path->addPoint(PathPoint(frame, rframe)); |
184 m_reversePath->addPoint | 209 } |
185 (SparseTimeValueModel::Point(rframe, rvalue, "")); | 210 |
186 } | 211 std::cerr << "AlignmentModel::constructPath: " << m_path->getPointCount() << " points, at least " << (2 * m_path->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl; |
187 | 212 } |
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; | 213 |
189 } | 214 void |
190 | 215 AlignmentModel::constructReversePath() const |
191 size_t | 216 { |
192 AlignmentModel::align(SparseTimeValueModel *path, size_t frame) const | 217 if (!m_reversePath) { |
193 { | 218 if (!m_rawPath) { |
194 // The path consists of a series of points, each with x (time) | 219 std::cerr << "ERROR: AlignmentModel::constructReversePath: " |
195 // equal to the time on the source model and y (value) equal to | 220 << "No raw path available" << std::endl; |
196 // the time on the target model. Times and values are both | 221 return; |
197 // monotonically increasing. | 222 } |
198 | 223 m_reversePath = new PathModel |
199 const SparseTimeValueModel::PointList &points = path->getPoints(); | 224 (m_rawPath->getSampleRate(), m_rawPath->getResolution(), false); |
225 } else { | |
226 if (!m_rawPath) return; | |
227 } | |
228 | |
229 m_reversePath->clear(); | |
230 | |
231 SparseTimeValueModel::PointList points = m_rawPath->getPoints(); | |
232 | |
233 for (SparseTimeValueModel::PointList::const_iterator i = points.begin(); | |
234 i != points.end(); ++i) { | |
235 long frame = i->frame; | |
236 float value = i->value; | |
237 long rframe = lrintf(value * m_aligned->getSampleRate()); | |
238 m_reversePath->addPoint(PathPoint(rframe, frame)); | |
239 } | |
240 | |
241 std::cerr << "AlignmentModel::constructReversePath: " << m_reversePath->getPointCount() << " points, at least " << (2 * m_reversePath->getPointCount() * (3 * sizeof(void *) + sizeof(int) + sizeof(PathPoint))) << " bytes" << std::endl; | |
242 } | |
243 | |
244 size_t | |
245 AlignmentModel::align(PathModel *path, size_t frame) const | |
246 { | |
247 // The path consists of a series of points, each with frame equal | |
248 // to the frame on the source model and mapframe equal to the | |
249 // frame on the target model. Both should be monotonically | |
250 // increasing. | |
251 | |
252 const PathModel::PointList &points = path->getPoints(); | |
200 | 253 |
201 if (points.empty()) { | 254 if (points.empty()) { |
202 // std::cerr << "AlignmentModel::align: No points" << std::endl; | 255 // std::cerr << "AlignmentModel::align: No points" << std::endl; |
203 return frame; | 256 return frame; |
204 } | 257 } |
205 | 258 |
206 SparseTimeValueModel::Point point(frame); | 259 PathModel::Point point(frame); |
207 SparseTimeValueModel::PointList::const_iterator i = points.lower_bound(point); | 260 PathModel::PointList::const_iterator i = points.lower_bound(point); |
208 if (i == points.end()) --i; | 261 if (i == points.end()) --i; |
209 while (i != points.begin() && i->frame > frame) --i; | 262 while (i != points.begin() && i->frame > long(frame)) --i; |
210 | 263 |
211 long foundFrame = i->frame; | 264 long foundFrame = i->frame; |
212 float foundTime = i->value; | 265 long foundMapFrame = i->mapframe; |
213 | 266 |
214 long followingFrame = foundFrame; | 267 long followingFrame = foundFrame; |
215 float followingTime = foundTime; | 268 long followingMapFrame = foundMapFrame; |
216 | 269 |
217 if (++i != points.end()) { | 270 if (++i != points.end()) { |
218 followingFrame = i->frame; | 271 followingFrame = i->frame; |
219 followingTime = i->value; | 272 followingMapFrame = i->mapframe; |
220 } | 273 } |
221 | 274 |
222 float resultTime = foundTime; | 275 if (foundMapFrame < 0) return 0; |
223 | 276 |
224 if (followingFrame != foundFrame && frame > foundFrame) { | 277 size_t resultFrame = foundMapFrame; |
225 | 278 |
226 // std::cerr << "AlignmentModel::align: foundFrame = " << foundFrame << ", frame = " << frame << ", followingFrame = " << followingFrame << std::endl; | 279 if (followingFrame != foundFrame && long(frame) > foundFrame) { |
227 | 280 float interp = |
228 float interp = float(frame - foundFrame) / float(followingFrame - foundFrame); | 281 float(frame - foundFrame) / |
229 // std::cerr << "AlignmentModel::align: interp = " << interp << ", result " << resultTime << " -> "; | 282 float(followingFrame - foundFrame); |
230 | 283 resultFrame += lrintf((followingMapFrame - foundMapFrame) * interp); |
231 resultTime += (followingTime - foundTime) * interp; | 284 } |
232 | 285 |
233 // std::cerr << resultTime << std::endl; | 286 std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl; |
234 } | |
235 | |
236 size_t resultFrame = lrintf(resultTime * getSampleRate()); | |
237 | |
238 // std::cerr << "AlignmentModel::align: resultFrame = " << resultFrame << std::endl; | |
239 | 287 |
240 return resultFrame; | 288 return resultFrame; |
241 } | 289 } |
242 | 290 |