comparison layer/TimeRulerLayer.cpp @ 1341:ab2cafd3a7cb zoom

Fixes for TimeRuler spacing and for the boundaries of the WaveformLayer paint area
author Chris Cannam
date Thu, 27 Sep 2018 15:20:25 +0100
parents 97c68bffbda6
children ed6400d5b571
comparison
equal deleted inserted replaced
1340:fc3c9971a43a 1341:ab2cafd3a7cb
57 resolution = 1; 57 resolution = 1;
58 return false; 58 return false;
59 } 59 }
60 60
61 bool q; 61 bool q;
62 int tick = getMajorTickSpacing(v, q); 62 int tickUSec = getMajorTickUSec(v, q);
63 RealTime rtick = RealTime::fromMilliseconds(tick); 63 RealTime rtick = RealTime(0, tickUSec * 1000);
64 sv_samplerate_t rate = m_model->getSampleRate(); 64 sv_samplerate_t rate = m_model->getSampleRate();
65 65
66 RealTime rt = RealTime::frame2RealTime(frame, rate); 66 RealTime rt = RealTime::frame2RealTime(frame, rate);
67 double ratio = rt / rtick; 67 double ratio = rt / rtick;
68 68
140 140
141 return true; 141 return true;
142 } 142 }
143 143
144 int 144 int
145 TimeRulerLayer::getMajorTickSpacing(LayerGeometryProvider *v, bool &quarterTicks) const 145 TimeRulerLayer::getMajorTickUSec(LayerGeometryProvider *v,
146 { 146 bool &quarterTicks) const
147 // return value is in milliseconds 147 {
148 148 // return value is in microseconds
149 if (!m_model || !v) return 1000; 149 if (!m_model || !v) return 1000 * 1000;
150 150
151 sv_samplerate_t sampleRate = m_model->getSampleRate(); 151 sv_samplerate_t sampleRate = m_model->getSampleRate();
152 if (!sampleRate) return 1000; 152 if (!sampleRate) return 1000 * 1000;
153 153
154 sv_frame_t startFrame = v->getStartFrame(); 154 sv_frame_t startFrame = v->getStartFrame();
155 sv_frame_t endFrame = v->getEndFrame(); 155 sv_frame_t endFrame = v->getEndFrame();
156 156
157 int minPixelSpacing = 50; 157 int minPixelSpacing = ViewManager::scalePixelSize(50);
158 158
159 RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate); 159 RealTime rtStart = RealTime::frame2RealTime(startFrame, sampleRate);
160 RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate); 160 RealTime rtEnd = RealTime::frame2RealTime(endFrame, sampleRate);
161 161
162 int count = v->getPaintWidth() / minPixelSpacing; 162 int count = v->getPaintWidth() / minPixelSpacing;
163 if (count < 1) count = 1; 163 if (count < 1) count = 1;
164 RealTime rtGap = (rtEnd - rtStart) / count; 164 RealTime rtGap = (rtEnd - rtStart) / count;
165 165
166 int incms; 166 int incus;
167 quarterTicks = false; 167 quarterTicks = false;
168 168
169 if (rtGap.sec > 0) { 169 if (rtGap.sec > 0) {
170 incms = 1000; 170 incus = 1000 * 1000;
171 int s = rtGap.sec; 171 int s = rtGap.sec;
172 if (s > 0) { incms *= 5; s /= 5; } 172 if (s > 0) { incus *= 5; s /= 5; }
173 if (s > 0) { incms *= 2; s /= 2; } 173 if (s > 0) { incus *= 2; s /= 2; }
174 if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } 174 if (s > 0) { incus *= 6; s /= 6; quarterTicks = true; }
175 if (s > 0) { incms *= 5; s /= 5; quarterTicks = false; } 175 if (s > 0) { incus *= 5; s /= 5; quarterTicks = false; }
176 if (s > 0) { incms *= 2; s /= 2; } 176 if (s > 0) { incus *= 2; s /= 2; }
177 if (s > 0) { incms *= 6; s /= 6; quarterTicks = true; } 177 if (s > 0) { incus *= 6; s /= 6; quarterTicks = true; }
178 while (s > 0) { 178 while (s > 0) {
179 incms *= 10; 179 incus *= 10;
180 s /= 10; 180 s /= 10;
181 quarterTicks = false; 181 quarterTicks = false;
182 } 182 }
183 } else if (rtGap.msec() > 0) {
184 incus = 1000;
185 int ms = rtGap.msec();
186 if (ms > 0) { incus *= 10; ms /= 10; }
187 if (ms > 0) { incus *= 10; ms /= 10; }
188 if (ms > 0) { incus *= 5; ms /= 5; }
189 if (ms > 0) { incus *= 2; ms /= 2; }
183 } else { 190 } else {
184 incms = 1; 191 incus = 1;
185 int ms = rtGap.msec(); 192 int us = rtGap.usec();
186 // cerr << "rtGap.msec = " << ms << ", rtGap = " << rtGap << ", count = " << count << endl; 193 if (us > 0) { incus *= 10; us /= 10; }
187 // cerr << "startFrame = " << startFrame << ", endFrame = " << endFrame << " rtStart = " << rtStart << ", rtEnd = " << rtEnd << endl; 194 if (us > 0) { incus *= 10; us /= 10; }
188 if (ms > 0) { incms *= 10; ms /= 10; } 195 if (us > 0) { incus *= 5; us /= 5; }
189 if (ms > 0) { incms *= 10; ms /= 10; } 196 if (us > 0) { incus *= 2; us /= 2; }
190 if (ms > 0) { incms *= 5; ms /= 5; } 197 }
191 if (ms > 0) { incms *= 2; ms /= 2; } 198
192 } 199 return incus;
193 200 }
194 return incms; 201
202 int
203 TimeRulerLayer::getXForUSec(LayerGeometryProvider *v, double us) const
204 {
205 sv_samplerate_t sampleRate = m_model->getSampleRate();
206 double dframe = (us * sampleRate) / 1000000.0;
207 double eps = 1e-7;
208 sv_frame_t frame = sv_frame_t(floor(dframe + eps));
209 int x;
210
211 ZoomLevel zoom = v->getZoomLevel();
212
213 if (zoom.zone == ZoomLevel::FramesPerPixel) {
214
215 frame /= zoom.level;
216 frame *= zoom.level; // so frame corresponds to an exact pixel
217
218 x = v->getXForFrame(frame);
219
220 } else {
221
222 double off = dframe - double(frame);
223 int x0 = v->getXForFrame(frame);
224 int x1 = v->getXForFrame(frame + 1);
225
226 x = int(x0 + off * (x1 - x0));
227 }
228
229 #ifdef DEBUG_TIME_RULER_LAYER
230 cerr << "Considering frame = " << frame << ", x = " << x << endl;
231 #endif
232
233 return x;
195 } 234 }
196 235
197 void 236 void
198 TimeRulerLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const 237 TimeRulerLayer::paint(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
199 { 238 {
212 #ifdef DEBUG_TIME_RULER_LAYER 251 #ifdef DEBUG_TIME_RULER_LAYER
213 cerr << "start frame = " << startFrame << endl; 252 cerr << "start frame = " << startFrame << endl;
214 #endif 253 #endif
215 254
216 bool quarter = false; 255 bool quarter = false;
217 int incms = getMajorTickSpacing(v, quarter); 256 int incus = getMajorTickUSec(v, quarter);
218 257
219 int ms = int(lrint(1000.0 * (double(startFrame) / double(sampleRate)))); 258 int us = int(lrint(1000.0 * 1000.0 * (double(startFrame) /
220 ms = (ms / incms) * incms - incms; 259 double(sampleRate))));
221 260 us = (us / incus) * incus - incus;
222 #ifdef DEBUG_TIME_RULER_LAYER 261
223 cerr << "start ms = " << ms << " at step " << incms << endl; 262 #ifdef DEBUG_TIME_RULER_LAYER
263 cerr << "start us = " << us << " at step " << incus << endl;
224 #endif 264 #endif
225 265
226 // Calculate the number of ticks per increment -- approximate 266 // Calculate the number of ticks per increment -- approximate
227 // values for x and frame counts here will do, no rounding issue. 267 // values for x and frame counts here will do, no rounding issue.
228 // We always use the exact incms in our calculations for where to 268 // We always use the exact incus in our calculations for where to
229 // draw the actual ticks or lines. 269 // draw the actual ticks or lines.
230 270
231 int minPixelSpacing = 50; 271 int minPixelSpacing = 50;
232 sv_frame_t incFrame = lrint((incms * sampleRate) / 1000); 272 sv_frame_t incFrame = lrint((incus * sampleRate) / 1000000);
233 int incX = int(round(v->getZoomLevel().framesToPixels(double(incFrame)))); 273 int incX = int(round(v->getZoomLevel().framesToPixels(double(incFrame))));
234 int ticks = 10; 274 int ticks = 10;
235 if (incX < minPixelSpacing * 2) { 275 if (incX < minPixelSpacing * 2) {
236 ticks = quarter ? 4 : 5; 276 ticks = quarter ? 4 : 5;
237 } 277 }
240 280
241 paint.save(); 281 paint.save();
242 282
243 // Do not label time zero - we now overlay an opaque area over 283 // Do not label time zero - we now overlay an opaque area over
244 // time < 0 which would cut it in half 284 // time < 0 which would cut it in half
245 int minlabel = 1; // ms 285 int minlabel = 1; // us
246
247 // used for a sanity check
248 sv_frame_t prevframe = 0;
249 286
250 while (1) { 287 while (1) {
251 288
252 // frame is used to determine where to draw the lines, so it 289 // frame is used to determine where to draw the lines, so it
253 // needs to correspond to an exact pixel (so that we don't get 290 // needs to correspond to an exact pixel (so that we don't get
254 // a different pixel when scrolling a small amount and 291 // a different pixel when scrolling a small amount and
255 // re-drawing with a different start frame). 292 // re-drawing with a different start frame).
256 293
257 double dms = ms; 294 double dus = us;
258 sv_frame_t frame = lrint((dms * sampleRate) / 1000.0); 295
259 ZoomLevel zoom = v->getZoomLevel(); 296 int x = getXForUSec(v, dus);
260 if (zoom.zone == ZoomLevel::FramesPerPixel) {
261 frame /= zoom.level;
262 frame *= zoom.level; // so frame corresponds to an exact pixel
263 }
264
265 if (frame == prevframe && prevframe != 0) {
266 cerr << "ERROR: frame == prevframe (== " << frame
267 << ") in TimeRulerLayer::paint" << endl;
268 throw std::logic_error("frame == prevframe in TimeRulerLayer::paint");
269 }
270 prevframe = frame;
271
272 int x = v->getXForFrame(frame);
273
274 #ifdef DEBUG_TIME_RULER_LAYER
275 cerr << "Considering frame = " << frame << ", x = " << x << endl;
276 #endif
277 297
278 if (x >= rect.x() + rect.width() + 50) { 298 if (x >= rect.x() + rect.width() + 50) {
279 #ifdef DEBUG_TIME_RULER_LAYER 299 #ifdef DEBUG_TIME_RULER_LAYER
280 cerr << "X well out of range, ending here" << endl; 300 cerr << "X well out of range, ending here" << endl;
281 #endif 301 #endif
282 break; 302 break;
283 } 303 }
284 304
285 if (x >= rect.x() - 50 && ms >= minlabel) { 305 if (x >= rect.x() - 50 && us >= minlabel) {
286 306
287 RealTime rt = RealTime::fromMilliseconds(ms); 307 RealTime rt = RealTime(0, us * 1000);
288 308
289 #ifdef DEBUG_TIME_RULER_LAYER 309 #ifdef DEBUG_TIME_RULER_LAYER
290 cerr << "X in range, drawing line here for time " << rt.toText() << endl; 310 cerr << "X in range, drawing line here for time " << rt.toText() << endl;
291 #endif 311 #endif
292 312
336 356
337 paint.setPen(greyColour); 357 paint.setPen(greyColour);
338 358
339 for (int i = 1; i < ticks; ++i) { 359 for (int i = 1; i < ticks; ++i) {
340 360
341 dms = ms + (i * double(incms)) / ticks; 361 dus = us + (i * double(incus)) / ticks;
342 frame = lrint((dms * sampleRate) / 1000.0); 362
343 if (zoom.zone == ZoomLevel::FramesPerPixel) { 363 x = getXForUSec(v, dus);
344 frame /= zoom.level;
345 frame *= zoom.level; // exact pixel as above
346 }
347
348 x = v->getXForFrame(frame);
349 364
350 if (x < rect.x() || x >= rect.x() + rect.width()) { 365 if (x < rect.x() || x >= rect.x() + rect.width()) {
351 #ifdef DEBUG_TIME_RULER_LAYER 366 #ifdef DEBUG_TIME_RULER_LAYER
352 // cerr << "tick " << i << ": X out of range, going on to next tick" << endl; 367 // cerr << "tick " << i << ": X out of range, going on to next tick" << endl;
353 #endif 368 #endif
370 } 385 }
371 paint.drawLine(x, 0, x, sz); 386 paint.drawLine(x, 0, x, sz);
372 paint.drawLine(x, v->getPaintHeight() - sz - 1, x, v->getPaintHeight() - 1); 387 paint.drawLine(x, v->getPaintHeight() - sz - 1, x, v->getPaintHeight() - 1);
373 } 388 }
374 389
375 ms += incms; 390 us += incus;
376 } 391 }
377 392
378 paint.restore(); 393 paint.restore();
379 } 394 }
380 395