mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
Improve playhead updates, reduce jitter for follow PH, stationary PH
* resolve rounding mistakes * extrapolate and filter position using GUI timing * track engine's position
This commit is contained in:
parent
446041d6b9
commit
55b8b44889
2 changed files with 78 additions and 41 deletions
|
|
@ -343,7 +343,8 @@ Editor::Editor ()
|
||||||
, _full_canvas_height (0)
|
, _full_canvas_height (0)
|
||||||
, edit_controls_left_menu (0)
|
, edit_controls_left_menu (0)
|
||||||
, edit_controls_right_menu (0)
|
, edit_controls_right_menu (0)
|
||||||
, last_update_frame (0)
|
, _last_update_time (0)
|
||||||
|
, _err_screen_engine (0)
|
||||||
, cut_buffer_start (0)
|
, cut_buffer_start (0)
|
||||||
, cut_buffer_length (0)
|
, cut_buffer_length (0)
|
||||||
, button_bindings (0)
|
, button_bindings (0)
|
||||||
|
|
@ -4668,7 +4669,7 @@ Editor::visual_changer (const VisualChange& vc)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vc.pending & VisualChange::TimeOrigin) {
|
if (vc.pending & VisualChange::TimeOrigin) {
|
||||||
set_horizontal_position (vc.time_origin / samples_per_pixel);
|
set_horizontal_position (sample_to_pixel_unrounded (vc.time_origin));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vc.pending & VisualChange::YOrigin) {
|
if (vc.pending & VisualChange::YOrigin) {
|
||||||
|
|
@ -5778,8 +5779,6 @@ Editor::super_rapid_screen_update ()
|
||||||
|
|
||||||
/* PLAYHEAD AND VIEWPORT */
|
/* PLAYHEAD AND VIEWPORT */
|
||||||
|
|
||||||
framepos_t const frame = _session->audible_frame();
|
|
||||||
|
|
||||||
/* There are a few reasons why we might not update the playhead / viewport stuff:
|
/* There are a few reasons why we might not update the playhead / viewport stuff:
|
||||||
*
|
*
|
||||||
* 1. we don't update things when there's a pending locate request, otherwise
|
* 1. we don't update things when there's a pending locate request, otherwise
|
||||||
|
|
@ -5789,46 +5788,82 @@ Editor::super_rapid_screen_update ()
|
||||||
* 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
|
* 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
|
||||||
* 3. if we're still at the same frame that we were last time, there's nothing to do.
|
* 3. if we're still at the same frame that we were last time, there's nothing to do.
|
||||||
*/
|
*/
|
||||||
|
if (_pending_locate_request || _session->transport_speed() == 0) {
|
||||||
|
_last_update_time = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
|
if (_dragging_playhead) {
|
||||||
|
_last_update_time = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
last_update_frame = frame;
|
framepos_t frame = _session->audible_frame();
|
||||||
|
const int64_t now = g_get_monotonic_time ();
|
||||||
|
double err = 0;
|
||||||
|
|
||||||
if (!_dragging_playhead) {
|
if (_last_update_time > 0) {
|
||||||
playhead_cursor->set_position (frame);
|
const double ds = (now - _last_update_time) * _session->transport_speed() * _session->nominal_frame_rate () * 1e-6;
|
||||||
|
framepos_t guess = playhead_cursor->current_frame () + rint (ds);
|
||||||
|
err = frame - guess;
|
||||||
|
|
||||||
|
guess += err * .12 + _err_screen_engine; // time-constant based on 25fps (super_rapid_screen_update)
|
||||||
|
_err_screen_engine += .0144 * (err - _err_screen_engine); // tc^2
|
||||||
|
|
||||||
|
#if 0 // DEBUG
|
||||||
|
printf ("eng: %ld gui:%ld (%+6.1f) diff: %6.1f (err: %7.2f)\n",
|
||||||
|
frame, guess, ds,
|
||||||
|
err, _err_screen_engine);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
frame = guess;
|
||||||
|
} else {
|
||||||
|
_err_screen_engine = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err > 8192) {
|
||||||
|
// in case of x-runs or freewheeling
|
||||||
|
_last_update_time = 0;
|
||||||
|
} else {
|
||||||
|
_last_update_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playhead_cursor->current_frame () == frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
playhead_cursor->set_position (frame);
|
||||||
|
|
||||||
|
if (_session->requested_return_frame() >= 0) {
|
||||||
|
_last_update_time = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_follow_playhead || pending_visual_change.being_handled) {
|
||||||
|
/* We only do this if we aren't already
|
||||||
|
* handling a visual change (ie if
|
||||||
|
* pending_visual_change.being_handled is
|
||||||
|
* false) so that these requests don't stack
|
||||||
|
* up there are too many of them to handle in
|
||||||
|
* time.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_stationary_playhead) {
|
||||||
|
reset_x_origin_to_follow_playhead ();
|
||||||
|
} else {
|
||||||
|
framepos_t const frame = playhead_cursor->current_frame ();
|
||||||
|
double target = ((double)frame - (double)current_page_samples() / 2.0);
|
||||||
|
if (target <= 0.0) {
|
||||||
|
target = 0.0;
|
||||||
}
|
}
|
||||||
|
// compare to EditorCursor::set_position()
|
||||||
if (!_stationary_playhead) {
|
double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
|
||||||
|
double const new_pos = sample_to_pixel_unrounded (target);
|
||||||
if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
|
if (rint (new_pos) != rint (old_pos)) {
|
||||||
/* We only do this if we aren't already
|
reset_x_origin (pixel_to_sample (new_pos));
|
||||||
handling a visual change (ie if
|
|
||||||
pending_visual_change.being_handled is
|
|
||||||
false) so that these requests don't stack
|
|
||||||
up there are too many of them to handle in
|
|
||||||
time.
|
|
||||||
*/
|
|
||||||
reset_x_origin_to_follow_playhead ();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
|
|
||||||
framepos_t const frame = playhead_cursor->current_frame ();
|
|
||||||
double target = ((double)frame - (double)current_page_samples()/2.0);
|
|
||||||
if (target <= 0.0) {
|
|
||||||
target = 0.0;
|
|
||||||
}
|
|
||||||
// compare to EditorCursor::set_position()
|
|
||||||
double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
|
|
||||||
double const new_pos = sample_to_pixel_unrounded (target);
|
|
||||||
if (rint (new_pos) != rint (old_pos)) {
|
|
||||||
reset_x_origin (pixel_to_sample (floor (new_pos)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5850,7 +5885,7 @@ Editor::session_going_away ()
|
||||||
clicked_routeview = 0;
|
clicked_routeview = 0;
|
||||||
entered_regionview = 0;
|
entered_regionview = 0;
|
||||||
entered_track = 0;
|
entered_track = 0;
|
||||||
last_update_frame = 0;
|
_last_update_time = 0;
|
||||||
_drags->abort ();
|
_drags->abort ();
|
||||||
|
|
||||||
playhead_cursor->hide ();
|
playhead_cursor->hide ();
|
||||||
|
|
|
||||||
|
|
@ -1160,11 +1160,13 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
|
||||||
TrackViewList get_tracks_for_range_action () const;
|
TrackViewList get_tracks_for_range_action () const;
|
||||||
|
|
||||||
sigc::connection super_rapid_screen_update_connection;
|
sigc::connection super_rapid_screen_update_connection;
|
||||||
framepos_t last_update_frame;
|
|
||||||
void center_screen_internal (framepos_t, float);
|
void center_screen_internal (framepos_t, float);
|
||||||
|
|
||||||
void super_rapid_screen_update ();
|
void super_rapid_screen_update ();
|
||||||
|
|
||||||
|
int64_t _last_update_time;
|
||||||
|
double _err_screen_engine;
|
||||||
|
|
||||||
void session_going_away ();
|
void session_going_away ();
|
||||||
|
|
||||||
framepos_t cut_buffer_start;
|
framepos_t cut_buffer_start;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue