From d067e27762e6ee69dabc9d48a80828b6287511c1 Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Wed, 14 May 2014 02:47:32 -0400 Subject: [PATCH] fix accumulated rounding error in BBT grid Though current_frame is an integral type (framepos_t), it was being added to as if it were floating-point, leading to an ever-increasing rounding error when creating the grid for bars/beats/ticks. --- libs/ardour/tempo.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 0bb2fea0cf..a2a400ad32 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -884,6 +884,7 @@ TempoMap::_extend_map (TempoSection* tempo, MeterSection* meter, TempoSection* ts; MeterSection* ms; double beat_frames; + double current_frame_exact; framepos_t bar_start_frame; DEBUG_TRACE (DEBUG::TempoMath, string_compose ("Extend map to %1 from %2 = %3\n", end, current, current_frame)); @@ -895,11 +896,13 @@ TempoMap::_extend_map (TempoSection* tempo, MeterSection* meter, } beat_frames = meter->frames_per_grid (*tempo,_frame_rate); + current_frame_exact = current_frame; while (current_frame < end) { current.beats++; - current_frame += beat_frames; + current_frame_exact += beat_frames; + current_frame = llrint(current_frame_exact); if (current.beats > meter->divisions_per_bar()) { current.bars++; @@ -942,7 +945,8 @@ TempoMap::_extend_map (TempoSection* tempo, MeterSection* meter, tempo->start(), current_frame, tempo->bar_offset())); /* back up to previous beat */ - current_frame -= beat_frames; + current_frame_exact -= beat_frames; + current_frame = llrint(current_frame_exact); /* set tempo section location * based on offset from last @@ -963,7 +967,8 @@ TempoMap::_extend_map (TempoSection* tempo, MeterSection* meter, double offset_within_old_beat = (tempo->frame() - current_frame) / beat_frames; - current_frame += (offset_within_old_beat * beat_frames) + ((1.0 - offset_within_old_beat) * next_beat_frames); + current_frame_exact += (offset_within_old_beat * beat_frames) + ((1.0 - offset_within_old_beat) * next_beat_frames); + current_frame = llrint(current_frame_exact); /* next metric doesn't have to * match this precisely to