Tempo lines display subdivisions correctly over a tempo change
authornick_m <mainsbridge@gmail.com>
Thu, 8 Jun 2017 15:44:48 +0000 (01:44 +1000)
committernick_m <mainsbridge@gmail.com>
Thu, 8 Jun 2017 15:44:48 +0000 (01:44 +1000)
TempoMap::get_grid() supplies a list of beat positions, leaving the lines
to work out any subdivision positions.
This is fine, unless a tempo section falls in between beats.
Use a BeatsFramesConverter along with a quarter note position
(in the BBTPointsList) to make this easier.

gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/tempo_lines.cc
gtk2_ardour/tempo_lines.h
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index e90c99baa647c88dc4edc65850edc322fb3d4e07..b11bee44d3921acff36a7257589b40bf880c8aee 100644 (file)
@@ -394,7 +394,7 @@ Editor::draw_measures (std::vector<ARDOUR::TempoMap::BBTPoint>& grid)
        }
 
        if (tempo_lines == 0) {
-               tempo_lines = new TempoLines (time_line_group, ArdourCanvas::LineSet::Vertical);
+               tempo_lines = new TempoLines (time_line_group, ArdourCanvas::LineSet::Vertical, new BeatsFramesConverter (_session->tempo_map(), 0));
        }
 
        const unsigned divisions = get_grid_beat_divisions(leftmost_frame);
index 7a780c424e72d36b4b29f15396ffd1b36d3ec839..ff7b8ad529b17754816cbbe865eb3440fd6fddf6 100644 (file)
@@ -29,8 +29,9 @@
 
 using namespace std;
 
-TempoLines::TempoLines (ArdourCanvas::Container* group, double)
+TempoLines::TempoLines (ArdourCanvas::Container* group, double, ARDOUR::BeatsFramesConverter* bfc)
        : lines (group, ArdourCanvas::LineSet::Vertical)
+       , _bfc (bfc)
 {
        lines.set_extent (ArdourCanvas::COORD_MAX);
 }
@@ -72,20 +73,8 @@ TempoLines::draw_ticks (std::vector<ARDOUR::TempoMap::BBTPoint>& grid,
                /* draw line with alpha corresponding to coarsest level */
                const uint8_t    a = max(8, (int)rint(UINT_RGBA_A(base) / (0.8 * log2(level))));
                const uint32_t   c = UINT_RGBA_CHANGE_A(base, a);
-               framepos_t f = 0;
+               const framepos_t f = _bfc->to (Evoral::Beats (grid.begin()->qn + (l / (double) divisions)));
 
-               if (grid.begin()->c != 0.0) {
-                       const double beat_divisions = (l / ((double) divisions)) * (grid.begin()->tempo.note_type() / grid.begin()->meter.note_divisor());
-                       const double time_at_division = log (((grid.begin()->c * (beat_divisions)) /
-                                                          grid.begin()->tempo.note_types_per_minute()) + 1) / grid.begin()->c;
-
-                       f = grid.begin()->frame + (framecnt_t) floor ((time_at_division * 60.0 * frame_rate) + 0.5);
-               } else {
-                       const double fpb  = grid.begin()->tempo.frames_per_note_type (frame_rate)
-                               * (grid.begin()->tempo.note_type() / grid.begin()->meter.note_divisor());
-
-                       f = grid.begin()->frame + (l * (fpb / (double) divisions));
-               }
                if (f > leftmost_frame) {
                        lines.add (PublicEditor::instance().sample_to_pixel_unrounded (f), 1.0, c);
                }
index 709602898177a39b0077d81e8d9c239854a75d40..7425f6aae3a77d92439c8f934ccb9cd64403db2b 100644 (file)
 #ifndef __ardour_tempo_lines_h__
 #define __ardour_tempo_lines_h__
 
+#include "ardour/beats_frames_converter.h"
 #include "ardour/tempo.h"
 
 #include "canvas/line_set.h"
 
 class TempoLines {
 public:
-       TempoLines (ArdourCanvas::Container* group, double screen_height);
+       TempoLines (ArdourCanvas::Container* group, double screen_height, ARDOUR::BeatsFramesConverter* bfc);
 
        void tempo_map_changed();
 
@@ -44,6 +45,7 @@ private:
                         ARDOUR::framecnt_t                                    frame_rate);
 
        ArdourCanvas::LineSet lines;
+       ARDOUR::BeatsFramesConverter* _bfc;
 };
 
 #endif /* __ardour_tempo_lines_h__ */
index 197c8c5f8f3807ea6c5ea8e4dbacd460222aab4e..da68f6516e127e0af653a1068653bd3600e31ae9 100644 (file)
@@ -343,16 +343,16 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
        };
 
        struct BBTPoint {
-               framepos_t          frame;
                Meter               meter;
                Tempo               tempo;
-               double              c;
+               framepos_t          frame;
                uint32_t            bar;
                uint32_t            beat;
+               double              qn;
 
                BBTPoint (const MeterSection& m, const Tempo& t, framepos_t f,
-                         uint32_t b, uint32_t e, double func_c)
-               : frame (f), meter (m.divisions_per_bar(), m.note_divisor()), tempo (t.note_types_per_minute(), t.note_type(), t.end_note_types_per_minute()), c (func_c), bar (b), beat (e) {}
+                         uint32_t b, uint32_t e, double qnote)
+               : meter (m), tempo (t), frame (f), bar (b), beat (e), qn (qnote) {}
 
                Timecode::BBT_Time bbt() const { return Timecode::BBT_Time (bar, beat, 0); }
                operator Timecode::BBT_Time() const { return bbt(); }
index e676c274f471725b634618e39b110b4840fdaeb2..47d718d2f8d95b9bd678c135420a12dd4a90c8aa 100644 (file)
@@ -4162,11 +4162,11 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
        if (bar_mod == 0) {
                while (pos >= 0 && pos < upper) {
                        pos = frame_at_minute (minute_at_beat_locked (_metrics, cnt));
-                       const TempoSection tempo = tempo_section_at_minute_locked (_metrics, minute_at_frame (pos));
                        const MeterSection meter = meter_section_at_minute_locked (_metrics, minute_at_frame (pos));
                        const BBT_Time bbt = bbt_at_beat_locked (_metrics, cnt);
+                       const double qn = pulse_at_beat_locked (_metrics, cnt) * 4.0;
 
-                       points.push_back (BBTPoint (meter, tempo_at_minute_locked (_metrics, minute_at_frame (pos)), pos, bbt.bars, bbt.beats, tempo.c()));
+                       points.push_back (BBTPoint (meter, tempo_at_minute_locked (_metrics, minute_at_frame (pos)), pos, bbt.bars, bbt.beats, qn));
                        ++cnt;
                }
        } else {
@@ -4181,9 +4181,10 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
 
                while (pos >= 0 && pos < upper) {
                        pos = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
-                       const TempoSection tempo = tempo_section_at_minute_locked (_metrics, minute_at_frame (pos));
                        const MeterSection meter = meter_section_at_minute_locked (_metrics, minute_at_frame (pos));
-                       points.push_back (BBTPoint (meter, tempo_at_minute_locked (_metrics, minute_at_frame (pos)), pos, bbt.bars, bbt.beats, tempo.c()));
+                       const double qn = pulse_at_bbt_locked (_metrics, bbt) * 4.0;
+
+                       points.push_back (BBTPoint (meter, tempo_at_minute_locked (_metrics, minute_at_frame (pos)), pos, bbt.bars, bbt.beats, qn));
                        bbt.bars += bar_mod;
                }
        }