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