Tempo ramps - improve music-locked meter drags, improve dump().
authornick_m <mainsbridge@gmail.com>
Mon, 21 Mar 2016 12:47:57 +0000 (23:47 +1100)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:11 +0000 (23:38 +1000)
- dump now shows cross-calculation of tempo positions.

gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_tempodisplay.cc
libs/ardour/tempo.cc

index 54dcd25ac1ed2b269c982ac60cc752e506fd81a1..3e46a0a3fe3abc8aea733536039793f371e9cd55 100644 (file)
@@ -3185,7 +3185,7 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move)
        framepos_t const pf = adjusted_current_frame (event);
        _marker->set_position (pf);
        if (_marker->meter().position_lock_style() == MusicTime) {
-               double const baf = _editor->session()->tempo_map().beat_at_frame (pf);
+               double const baf = _editor->session()->tempo_map().beat_at_frame (_editor->session()->tempo_map().round_to_bar (pf, (RoundMode) 0));
                _editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), baf);
        } else {
                _editor->session()->tempo_map().gui_move_meter (_real_section, _marker->meter(), pf);
index 3f19665760ccc4f13bc75455c6c42c954ed5da7a..d817c440131d511e0b1368c05a9a68e7092da0cb 100644 (file)
@@ -336,8 +336,9 @@ Editor::edit_meter_section (MeterSection* section)
        meter_dialog.get_bbt_time(when);
        framepos_t const frame = _session->tempo_map().frame_at_beat (_session->tempo_map().bbt_to_beats (when));
 
-       begin_reversible_command (_("replace tempo mark"));
+       begin_reversible_command (_("replace meter mark"));
         XMLNode &before = _session->tempo_map().get_state();
+       section->set_position_lock_style (meter_dialog.get_lock_style());
        if (meter_dialog.get_lock_style() == MusicTime) {
                _session->tempo_map().replace_meter (*section, Meter (bpb, note_type), when);
        } else {
index 8af8424a63fe0f2988406041e82387c16495924d..2d77d18db44bfbb3a985cf6d8c7e3ef3d977ca30 100644 (file)
@@ -770,6 +770,7 @@ TempoMap::do_insert (MetricSection* section)
                                         */
 
                                        *(dynamic_cast<Meter*>(*i)) = *(dynamic_cast<Meter*>(insert_meter));
+                                       (*i)->set_position_lock_style (insert_meter->position_lock_style());
                                        need_add = false;
                                } else {
                                        _metrics.erase (i);
@@ -917,12 +918,14 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const BBT_T
        {
                Glib::Threads::RWLock::WriterLock lm (lock);
                MeterSection& first (first_meter());
+               const PositionLockStyle pl = ms.position_lock_style();
                if (ms.pulse() != first.pulse()) {
                        remove_meter_locked (ms);
                        add_meter_locked (meter, bbt_to_beats_locked (_metrics, where), where, true);
                } else {
                        /* cannot move the first meter section */
                        *static_cast<Meter*>(&first) = meter;
+                       first.set_position_lock_style (pl);
                        recompute_map (_metrics);
                }
        }
@@ -936,12 +939,14 @@ TempoMap::replace_meter (const MeterSection& ms, const Meter& meter, const frame
        {
                Glib::Threads::RWLock::WriterLock lm (lock);
                MeterSection& first (first_meter());
+               const PositionLockStyle pl = ms.position_lock_style();
                if (ms.pulse() != first.pulse()) {
                        remove_meter_locked (ms);
                        add_meter_locked (meter, frame, true);
                } else {
                        /* cannot move the first meter section */
                        *static_cast<Meter*>(&first) = meter;
+                       first.set_position_lock_style (pl);
                        recompute_map (_metrics);
                }
        }
@@ -1000,7 +1005,6 @@ TempoMap::add_meter_locked (const Meter& meter, double beat, BBT_Time where, boo
                where.beats = 1;
                where.bars++;
        }
-
        /* new meters *always* start on a beat. */
        where.ticks = 0;
        double pulse = pulse_at_beat (_metrics, beat);
@@ -1285,7 +1289,7 @@ TempoMap::first_meter () const
                }
        }
 
-       fatal << _("programming error: no tempo section in tempo map!") << endmsg;
+       fatal << _("programming error: no meter section in tempo map!") << endmsg;
        abort(); /*NOTREACHED*/
        return *m;
 }
@@ -1373,21 +1377,25 @@ TempoMap::recompute_meters (Metrics& metrics)
        MeterSection* meter = 0;
        MeterSection* prev_m = 0;
        double accumulated_beats = 0.0;
-
+       uint32_t accumulated_bars = 0;
        for (Metrics::const_iterator mi = metrics.begin(); mi != metrics.end(); ++mi) {
                if ((meter = dynamic_cast<MeterSection*> (*mi)) != 0) {
                        if (prev_m) {
-                               accumulated_beats += (meter->pulse() - prev_m->pulse()) * prev_m->note_divisor();
+                               const double beats_in_m = (meter->pulse() - prev_m->pulse()) * prev_m->note_divisor();
+                               accumulated_beats += beats_in_m;
+                               accumulated_bars += (beats_in_m + 1) / prev_m->divisions_per_bar();
                        }
+
                        if (meter->position_lock_style() == AudioTime) {
                                pair<double, BBT_Time> pr;
-                               pr.first = ceil (pulse_at_frame_locked (metrics, meter->frame()));
-                               BBT_Time const where = beats_to_bbt_locked (metrics, accumulated_beats);
+                               pr.first =  pulse_at_frame_locked (metrics, meter->frame());
+                               BBT_Time const where = BBT_Time (accumulated_bars + 1, 1, 0);
                                pr.second = where;
                                meter->set_pulse (pr);
                        } else {
                                meter->set_frame (frame_at_pulse_locked (metrics, meter->pulse()));
                        }
+
                        meter->set_beat (accumulated_beats);
                        prev_m = meter;
                }
@@ -1706,51 +1714,6 @@ TempoMap::pulse_to_bbt (const double& pulse)
        return ret;
 }
 
-double
-TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) const
-{
-       MeterSection* prev_m = 0;
-       double beat_off = 0.0;
-
-       for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
-               MeterSection* m = 0;
-               if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
-                       if (prev_m) {
-                               if (m->beat() > beat) {
-                                       break;
-                               }
-
-                               if (m->position_lock_style() == AudioTime) {
-                                       beat_off += ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()) - floor ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor());
-                               }
-                       }
-                       prev_m = m;
-               }
-       }
-
-       return beat_off;
-}
-
-frameoffset_t
-TempoMap::frame_offset_at (const Metrics& metrics, const framepos_t& frame) const
-{
-       frameoffset_t frame_off = 0;
-
-       for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
-               MeterSection* m = 0;
-               if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
-                       if (m->frame() > frame) {
-                               break;
-                       }
-                       if (m->position_lock_style() == AudioTime) {
-                               frame_off += frame_at_pulse_locked (metrics, m->pulse()) - m->frame();
-                       }
-               }
-       }
-
-       return frame_off;
-}
-
 double
 TempoMap::beat_at_frame (const framecnt_t& frame) const
 {
@@ -1841,6 +1804,51 @@ TempoMap::frame_at_pulse_locked (const Metrics& metrics, const double& pulse) co
        return ret;
 }
 
+double
+TempoMap::beat_offset_at (const Metrics& metrics, const double& beat) const
+{
+       MeterSection* prev_m = 0;
+       double beat_off = 0.0;
+
+       for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
+               MeterSection* m = 0;
+               if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+                       if (prev_m) {
+                               if (m->beat() > beat) {
+                                       break;
+                               }
+
+                               if (m->position_lock_style() == AudioTime) {
+                                       beat_off += ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor()) - floor ((m->pulse() - prev_m->pulse()) / prev_m->note_divisor());
+                               }
+                       }
+                       prev_m = m;
+               }
+       }
+
+       return beat_off;
+}
+
+frameoffset_t
+TempoMap::frame_offset_at (const Metrics& metrics, const framepos_t& frame) const
+{
+       frameoffset_t frame_off = 0;
+
+       for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) {
+               MeterSection* m = 0;
+               if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
+                       if (m->frame() > frame) {
+                               break;
+                       }
+                       if (m->position_lock_style() == AudioTime) {
+                               frame_off += frame_at_pulse_locked (metrics, m->pulse()) - m->frame();
+                       }
+               }
+       }
+
+       return frame_off;
+}
+
 framepos_t
 TempoMap::frame_time (const BBT_Time& bbt)
 {
@@ -1883,7 +1891,6 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame)
                                if (by_frame && t->frame() != prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate)) {
                                        return false;
                                }
-                               /*
                                if (!by_frame && fabs (t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate)) > 0.00001) {
                                        std::cerr << "beat precision too low for bpm: " << t->beats_per_minute() << std::endl <<
                                                " |error          :" << t->pulse() - prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) << std::endl <<
@@ -1891,7 +1898,6 @@ TempoMap::check_solved (Metrics& metrics, bool by_frame)
                                                " |frame at tempo : " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
                                        return false;
                                }
-                               */
                        }
                        prev_ts = t;
                }
@@ -2067,28 +2073,37 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
 {
        MeterSection* prev_ms = 0;
 
-       pair<double, BBT_Time> b_bbt = make_pair (pulse, beats_to_bbt_locked (imaginary, pulse));
+       pair<double, BBT_Time> b_bbt = make_pair (pulse, BBT_Time (1, 1, 0));
+       double accumulated_beats = 0.0;
+       uint32_t accumulated_bars = 0;
+
        section->set_pulse (b_bbt);
-       MetricSectionSorter cmp;
-       imaginary.sort (cmp);
 
        for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
                MeterSection* m;
                if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
                        if (prev_ms) {
-                               if (m == section){
-                                       section->set_frame (frame_at_pulse_locked (imaginary, pulse_at_beat (imaginary, pulse)));
-                                       prev_ms = section;
-                                       continue;
-                               }
+                               double const beats_in_m = (m->pulse() - prev_ms->pulse()) * prev_ms->note_divisor();
+                               accumulated_beats += beats_in_m;
+                               accumulated_bars += (beats_in_m + 1) / prev_ms->divisions_per_bar();
+                       }
+                       if (m == section){
+                               section->set_frame (frame_at_pulse_locked (imaginary, pulse));
+                               b_bbt = make_pair (pulse, BBT_Time (accumulated_bars + 1, 1, 0));
+                               section->set_pulse (b_bbt);
+                               m->set_beat (accumulated_beats);
+                               prev_ms = section;
+                               continue;
+                       }
+                       if (prev_ms) {
                                if (m->position_lock_style() == MusicTime) {
                                        m->set_frame (frame_at_pulse_locked (imaginary, m->pulse()));
                                } else {
-                                       pair<double, BBT_Time> b_bbt = make_pair (pulse_at_frame_locked (imaginary, m->frame()), BBT_Time (1, 1, 0));
-                                       b_bbt.second = beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, b_bbt.first));
+                                       pair<double, BBT_Time> b_bbt = make_pair (pulse_at_frame_locked (imaginary, m->frame()), BBT_Time (accumulated_bars + 1, 1, 0));
                                        m->set_pulse (b_bbt);
                                }
                        }
+                       m->set_beat (accumulated_beats);
                        prev_ms = m;
                }
        }
@@ -2107,33 +2122,43 @@ void
 TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt, const framepos_t& frame)
 {
        MeterSection* prev_ms = 0;
+       double accumulated_beats = 0.0;
+       uint32_t accumulated_bars = 0;
+
        section->set_frame (frame);
 
        for (Metrics::iterator i = imaginary.begin(); i != imaginary.end(); ++i) {
                MeterSection* m;
                if ((m = dynamic_cast<MeterSection*> (*i)) != 0) {
                        if (prev_ms) {
-                               if (m == section){
+                               const double beats_in_m = (m->pulse() - prev_ms->pulse()) * prev_ms->note_divisor();
+                               accumulated_beats += beats_in_m;
+                               accumulated_bars += (beats_in_m + 1) / prev_ms->divisions_per_bar();
+                       }
+                       if (m == section){
                                        /*
                                          here we define the pulse for this frame.
                                          we're going to set it 'incorrectly' to the next integer and use this 'error'
                                          as an offset to the map as far as users of the public methods are concerned.
                                          (meters should go on absolute pulses to keep us sane)
                                        */
-                                       double const pulse_at_f = ceil (pulse_at_frame_locked (imaginary, m->frame()));
-                                       pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, pulse_at_f)));
+                                       double const pulse_at_f = pulse_at_frame_locked (imaginary, m->frame());
+                                       pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, BBT_Time (accumulated_bars + 1, 1, 0));
                                        m->set_pulse (b_bbt);
+                                       m->set_beat (accumulated_beats);
                                        prev_ms = m;
                                        continue;
-                               }
+                       }
+                       if (prev_ms) {
                                if (m->position_lock_style() == MusicTime) {
                                        m->set_frame (frame_at_pulse_locked (imaginary, m->pulse()));
                                } else {
                                        double const pulse_at_f = ceil (pulse_at_frame_locked (imaginary, frame));
-                                       pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, beats_to_bbt_locked (imaginary, beat_at_pulse (imaginary, pulse_at_f)));
+                                       pair<double, BBT_Time> b_bbt = make_pair (pulse_at_f, BBT_Time (accumulated_bars + 1, 1, 0));
                                        m->set_pulse (b_bbt);
                                }
                        }
+                       m->set_beat (accumulated_beats);
                        prev_ms = m;
                }
        }
@@ -2619,19 +2644,19 @@ TempoMap::dump (Metrics& metrics, std::ostream& o) const
 
                if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
                        o << "Tempo @ " << *i << " (Bar-offset: " << t->bar_offset() << ") " << t->beats_per_minute() << " BPM (pulse = 1/" << t->note_type() << ") at " << t->pulse() << " frame= " << t->frame() << " (movable? "
-                         << t->movable() << ')' << endl;
+                         << t->movable() << ')' << " pos lock: " << enum_2_string (t->position_lock_style()) << std::endl;
+                       o << "current      : " << t->beats_per_minute() << " | " << t->pulse() << " | " << t->frame() << std::endl;
                        if (prev_ts) {
-                               o << "current      : " << t->beats_per_minute() << " | " << t->pulse() << " | " << t->frame() << std::endl;
                                o << "previous     : " << prev_ts->beats_per_minute() << " | " << prev_ts->pulse() << " | " << prev_ts->frame() << std::endl;
-                               o << "calculated   : " << prev_ts->tempo_at_pulse (t->pulse()) << " | " << prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) <<  " | " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
-                               o << "------" << std::endl;
+                               o << "calculated   : " << prev_ts->tempo_at_pulse (t->pulse()) *  prev_ts->note_type() << " | " << prev_ts->pulse_at_tempo (t->pulses_per_minute(), t->frame(), _frame_rate) <<  " | " << prev_ts->frame_at_tempo (t->pulses_per_minute(), t->pulse(), _frame_rate) << std::endl;
                        }
+                       prev_ts = t;
                } else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
                        o << "Meter @ " << *i << ' ' << m->divisions_per_bar() << '/' << m->note_divisor() << " at " << m->bbt() << " frame= " << m->frame()
-                         << " (movable? " << m->movable() << ')' << endl;
+                         << " pulse: " << m->pulse() <<  " pos lock: " << enum_2_string (m->position_lock_style()) << " (movable? " << m->movable() << ')' << endl;
                }
-               prev_ts = t;
        }
+       o << "------" << std::endl;
 }
 
 int