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