Tempo ramps - more code reorganization, almost audio-locked meter nirvana.
authornick_m <mainsbridge@gmail.com>
Wed, 30 Mar 2016 17:50:26 +0000 (04:50 +1100)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:13 +0000 (23:38 +1000)
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index 894e870a5f237e77ac7ed1df94f2b20e350a885b..6cb4850288fbcf7ae902b0242f75983567e1172e 100644 (file)
@@ -447,9 +447,6 @@ private:
        double pulse_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
        framecnt_t frame_at_pulse_locked (const Metrics& metrics, const double& beat) const;
 
-       double beat_offset_at (const Metrics& metrics, const double& beat) const;
-       frameoffset_t frame_offset_at (const Metrics& metrics, const framepos_t& frame) const;
-
        double beat_at_frame_locked (const Metrics& metrics, const framecnt_t& frame) const;
        framecnt_t frame_at_beat_locked (const Metrics& metrics, const double& beat) const;
        double bbt_to_beats_locked (const Metrics& metrics, const Timecode::BBT_Time& bbt) const ;
index f47780b3116094494d0ef05a8d31283311f337ec..7c1ce40789a96ef545437bda299450e9c6f7aca1 100644 (file)
@@ -1062,220 +1062,6 @@ TempoMap::add_meter_locked (const Meter& meter, framepos_t frame, double beat, T
 
 }
 
-/**
-* This is for a gui that needs to know the frame of a tempo section if it were to be moved to some bbt time,
-* taking any possible reordering as a consequence of this into account.
-* @param section - the section to be altered
-* @param bpm - the new Tempo
-* @param bbt - the bbt where the altered tempo will fall
-* @return returns - the position in frames where the new tempo section will lie.
-*/
-framepos_t
-TempoMap::predict_tempo_frame (TempoSection* section, const Tempo& bpm, const BBT_Time& bbt)
-{
-       Glib::Threads::RWLock::ReaderLock lm (lock);
-       Metrics future_map;
-       framepos_t ret = 0;
-       TempoSection* new_section = copy_metrics_and_point (future_map, section);
-
-       double const beat = bbt_to_beats_locked (future_map, bbt);
-       if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) {
-               ret = new_section->frame();
-       } else {
-               ret = frame_at_beat_locked (_metrics, beat);
-       }
-
-       Metrics::const_iterator d = future_map.begin();
-       while (d != future_map.end()) {
-               delete (*d);
-               ++d;
-       }
-       return ret;
-}
-
-double
-TempoMap::predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame)
-{
-       Glib::Threads::RWLock::ReaderLock lm (lock);
-       Metrics future_map;
-       double ret = 0.0;
-       TempoSection* new_section = copy_metrics_and_point (future_map, section);
-
-       if (solve_map (future_map, new_section, bpm, frame)) {
-               ret = new_section->pulse();
-       } else {
-               ret = pulse_at_frame_locked (_metrics, frame);
-       }
-
-       Metrics::const_iterator d = future_map.begin();
-       while (d != future_map.end()) {
-               delete (*d);
-               ++d;
-       }
-       return ret;
-}
-
-void
-TempoMap::gui_move_tempo_frame (TempoSection* ts,  const Tempo& bpm, const framepos_t& frame)
-{
-       Metrics future_map;
-       {
-               Glib::Threads::RWLock::WriterLock lm (lock);
-               TempoSection* new_section = copy_metrics_and_point (future_map, ts);
-               if (solve_map (future_map, new_section, bpm, frame)) {
-                       solve_map (_metrics, ts, bpm, frame);
-               }
-       }
-
-       Metrics::const_iterator d = future_map.begin();
-       while (d != future_map.end()) {
-               delete (*d);
-               ++d;
-       }
-
-       MetricPositionChanged (); // Emit Signal
-}
-
-void
-TempoMap::gui_move_tempo_beat (TempoSection* ts,  const Tempo& bpm, const double& beat)
-{
-       Metrics future_map;
-       {
-               Glib::Threads::RWLock::WriterLock lm (lock);
-               TempoSection* new_section = copy_metrics_and_point (future_map, ts);
-               if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) {
-                       solve_map (_metrics, ts, bpm, pulse_at_beat_locked (_metrics, beat));
-               }
-       }
-
-       Metrics::const_iterator d = future_map.begin();
-       while (d != future_map.end()) {
-               delete (*d);
-               ++d;
-       }
-
-       MetricPositionChanged (); // Emit Signal
-}
-
-void
-TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const framepos_t&  frame)
-{
-       {
-               Glib::Threads::RWLock::WriterLock lm (lock);
-               solve_map (_metrics, ms, mt, frame);
-       }
-
-       MetricPositionChanged (); // Emit Signal
-}
-
-void
-TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const double&  beat)
-{
-       {
-               Glib::Threads::RWLock::WriterLock lm (lock);
-               solve_map (_metrics, ms, mt, pulse_at_beat_locked (_metrics, beat));
-       }
-
-       MetricPositionChanged (); // Emit Signal
-}
-
-bool
-TempoMap::gui_change_tempo (TempoSection* ts,  const Tempo& bpm)
-{
-       Metrics future_map;
-       bool can_solve = false;
-       {
-               Glib::Threads::RWLock::WriterLock lm (lock);
-               TempoSection* new_section = copy_metrics_and_point (future_map, ts);
-               new_section->set_beats_per_minute (bpm.beats_per_minute());
-               recompute_tempos (future_map);
-
-               if (check_solved (future_map, true)) {
-                       ts->set_beats_per_minute (bpm.beats_per_minute());
-                       recompute_map (_metrics);
-                       can_solve = true;
-               }
-       }
-
-       Metrics::const_iterator d = future_map.begin();
-       while (d != future_map.end()) {
-               delete (*d);
-               ++d;
-       }
-       if (can_solve) {
-               MetricPositionChanged (); // Emit Signal
-       }
-       return can_solve;
-}
-
-TempoSection*
-TempoMap::copy_metrics_and_point (Metrics& copy, TempoSection* section)
-{
-       TempoSection* t;
-       TempoSection* ret = 0;
-       MeterSection* m;
-
-       for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
-               if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
-                       if (t == section) {
-                               if (t->position_lock_style() == MusicTime) {
-                                       ret = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
-                               } else {
-                                       ret = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
-                               }
-                               ret->set_active (t->active());
-                               ret->set_movable (t->movable());
-                               copy.push_back (ret);
-                               continue;
-                       }
-                       TempoSection* cp = 0;
-                       if (t->position_lock_style() == MusicTime) {
-                               cp = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
-                       } else {
-                               cp = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
-                       }
-                       cp->set_active (t->active());
-                       cp->set_movable (t->movable());
-                       copy.push_back (cp);
-               }
-               if ((m = dynamic_cast<MeterSection *> (*i)) != 0) {
-                       MeterSection* cp = 0;
-                       if (m->position_lock_style() == MusicTime) {
-                               cp = new MeterSection (m->pulse(), m->beat(), m->bbt(), m->divisions_per_bar(), m->note_divisor());
-                       } else {
-                               cp = new MeterSection (m->frame(), m->beat(), m->bbt(), m->divisions_per_bar(), m->note_divisor());
-                       }
-                       cp->set_movable (m->movable());
-                       copy.push_back (cp);
-               }
-       }
-       //recompute_map (copy);
-       return ret;
-}
-
-bool
-TempoMap::can_solve_bbt (TempoSection* ts,  const Tempo& bpm, const BBT_Time& bbt)
-{
-       Metrics copy;
-       TempoSection* new_section = 0;
-
-       {
-               Glib::Threads::RWLock::ReaderLock lm (lock);
-               new_section = copy_metrics_and_point (copy, ts);
-       }
-
-       double const beat = bbt_to_beats_locked (copy, bbt);
-       bool ret = solve_map (copy, new_section, bpm, pulse_at_beat_locked (copy, beat));
-
-       Metrics::const_iterator d = copy.begin();
-       while (d != copy.end()) {
-               delete (*d);
-               ++d;
-       }
-
-       return ret;
-}
-
 void
 TempoMap::change_initial_tempo (double beats_per_minute, double note_type)
 {
@@ -1473,14 +1259,13 @@ TempoMap::recompute_meters (Metrics& metrics)
                        if (meter->position_lock_style() == AudioTime) {
                                double pulse = 0.0;
                                pair<double, BBT_Time> b_bbt;
-                               if (prev_m) {
-                                       double beats = ((pulse_at_frame_locked (metrics, meter->frame()) - prev_m->pulse()) * prev_m->note_divisor()) - prev_m->beat();
+                               if (meter->movable()) {
+                                       const double beats = ((pulse_at_frame_locked (metrics, meter->frame()) - prev_m->pulse()) * prev_m->note_divisor()) - prev_m->beat();
                                        b_bbt = make_pair (ceil (beats), BBT_Time (accumulated_bars + 1, 1, 0));
                                        const double true_pulse = prev_m->pulse() + (ceil (beats) - prev_m->beat()) / prev_m->note_divisor();
                                        const double pulse_off = true_pulse - ((beats - prev_m->beat()) / prev_m->note_divisor());
                                        pulse = true_pulse - pulse_off;
-                               }
-                               if (!meter->movable()) {
+                               } else {
                                        b_bbt = make_pair (0.0, BBT_Time (1, 1, 0));
                                }
                                meter->set_beat (b_bbt);
@@ -1918,54 +1703,6 @@ 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 = first_meter().pulse();
-
-       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->beat() - prev_m->beat()) / prev_m->note_divisor()) - floor (m->pulse() - prev_m->pulse());
-                               }
-                       }
-                       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;
-       MeterSection* prev_m = 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 (prev_m && m->position_lock_style() == AudioTime) {
-                               const double pulse = prev_m->pulse() + ((m->beat() - prev_m->beat()) / prev_m->note_divisor());
-                               frame_off += frame_at_pulse_locked (metrics, pulse) - m->frame();
-                       }
-                       prev_m = m;
-               }
-       }
-
-       return frame_off;
-}
-
 framepos_t
 TempoMap::frame_time (const BBT_Time& bbt)
 {
@@ -2276,7 +2013,7 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
                                /*
                                  here we set the beat for this frame.
                                  we're going to set it 'incorrectly' to the next integer and use this difference
-                                 to find the meter's pulse later.
+                                 to find the meter's pulse.
                                  (meters should fall on integral beats to keep us sane)
                                */
                                double pulse = 0.0;
@@ -2301,11 +2038,19 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
                                        m->set_frame (frame_at_pulse_locked (imaginary, pulse));
                                        m->set_pulse (pulse);
                                } else {
-                                       if (!m->movable()) {
-                                               pair<double, BBT_Time> b_bbt = make_pair (0.0, BBT_Time (1, 1, 0));
-                                               m->set_beat (b_bbt);
+                                       double pulse = 0.0;
+                                       pair<double, BBT_Time> b_bbt;
+                                       if (m->movable()) {
+                                               const double beats = ((pulse_at_frame_locked (imaginary, m->frame()) - prev_ms->pulse()) * prev_ms->note_divisor()) - prev_ms->beat();
+                                               const double true_pulse = prev_ms->pulse() + (m->beat() - prev_ms->beat()) / prev_ms->note_divisor();
+                                               const double pulse_off = true_pulse - ((beats - prev_ms->beat()) / prev_ms->note_divisor());
+                                               b_bbt = make_pair (ceil (beats), BBT_Time (accumulated_bars + 1, 1, 0));
+                                               pulse = true_pulse - pulse_off;
+                                       } else {
+                                               b_bbt = make_pair (0.0, BBT_Time (1, 1, 0));
+                                               pulse = 0.0;
                                        }
-                                       const double pulse = prev_ms->pulse() + (m->beat() - prev_ms->beat()) / prev_ms->note_divisor();
+                                       m->set_beat (b_bbt);
                                        m->set_pulse (pulse);
                                }
                        }
@@ -2376,6 +2121,225 @@ TempoMap::solve_map (Metrics& imaginary, MeterSection* section, const Meter& mt,
        }
 }
 
+/** places a copy of _metrics into copy and returns a pointer
+ *  to section's equivalent.
+ */
+TempoSection*
+TempoMap::copy_metrics_and_point (Metrics& copy, TempoSection* section)
+{
+       TempoSection* t;
+       TempoSection* ret = 0;
+       MeterSection* m;
+
+       for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
+               if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+                       if (t == section) {
+                               if (t->position_lock_style() == MusicTime) {
+                                       ret = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
+                               } else {
+                                       ret = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
+                               }
+                               ret->set_active (t->active());
+                               ret->set_movable (t->movable());
+                               copy.push_back (ret);
+                               continue;
+                       }
+                       TempoSection* cp = 0;
+                       if (t->position_lock_style() == MusicTime) {
+                               cp = new TempoSection (t->pulse(), t->beats_per_minute(), t->note_type(), t->type());
+                       } else {
+                               cp = new TempoSection (t->frame(), t->beats_per_minute(), t->note_type(), t->type());
+                       }
+                       cp->set_active (t->active());
+                       cp->set_movable (t->movable());
+                       copy.push_back (cp);
+               }
+               if ((m = dynamic_cast<MeterSection *> (*i)) != 0) {
+                       MeterSection* cp = 0;
+                       if (m->position_lock_style() == MusicTime) {
+                               cp = new MeterSection (m->pulse(), m->beat(), m->bbt(), m->divisions_per_bar(), m->note_divisor());
+                               cp->set_frame (m->frame());
+                       } else {
+                               cp = new MeterSection (m->frame(), m->beat(), m->bbt(), m->divisions_per_bar(), m->note_divisor());
+                               cp->set_pulse (m->pulse());
+                       }
+                       cp->set_movable (m->movable());
+                       copy.push_back (cp);
+               }
+       }
+       //recompute_map (copy);
+       return ret;
+}
+
+bool
+TempoMap::can_solve_bbt (TempoSection* ts,  const Tempo& bpm, const BBT_Time& bbt)
+{
+       Metrics copy;
+       TempoSection* new_section = 0;
+
+       {
+               Glib::Threads::RWLock::ReaderLock lm (lock);
+               new_section = copy_metrics_and_point (copy, ts);
+       }
+
+       double const beat = bbt_to_beats_locked (copy, bbt);
+       bool ret = solve_map (copy, new_section, bpm, pulse_at_beat_locked (copy, beat));
+
+       Metrics::const_iterator d = copy.begin();
+       while (d != copy.end()) {
+               delete (*d);
+               ++d;
+       }
+
+       return ret;
+}
+
+/**
+* This is for a gui that needs to know the frame of a tempo section if it were to be moved to some bbt time,
+* taking any possible reordering as a consequence of this into account.
+* @param section - the section to be altered
+* @param bpm - the new Tempo
+* @param bbt - the bbt where the altered tempo will fall
+* @return returns - the position in frames where the new tempo section will lie.
+*/
+framepos_t
+TempoMap::predict_tempo_frame (TempoSection* section, const Tempo& bpm, const BBT_Time& bbt)
+{
+       Glib::Threads::RWLock::ReaderLock lm (lock);
+       Metrics future_map;
+       framepos_t ret = 0;
+       TempoSection* new_section = copy_metrics_and_point (future_map, section);
+
+       double const beat = bbt_to_beats_locked (future_map, bbt);
+       if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) {
+               ret = new_section->frame();
+       } else {
+               ret = frame_at_beat_locked (_metrics, beat);
+       }
+
+       Metrics::const_iterator d = future_map.begin();
+       while (d != future_map.end()) {
+               delete (*d);
+               ++d;
+       }
+       return ret;
+}
+
+double
+TempoMap::predict_tempo_pulse (TempoSection* section, const Tempo& bpm, const framepos_t& frame)
+{
+       Glib::Threads::RWLock::ReaderLock lm (lock);
+       Metrics future_map;
+       double ret = 0.0;
+       TempoSection* new_section = copy_metrics_and_point (future_map, section);
+
+       if (solve_map (future_map, new_section, bpm, frame)) {
+               ret = new_section->pulse();
+       } else {
+               ret = pulse_at_frame_locked (_metrics, frame);
+       }
+
+       Metrics::const_iterator d = future_map.begin();
+       while (d != future_map.end()) {
+               delete (*d);
+               ++d;
+       }
+       return ret;
+}
+
+void
+TempoMap::gui_move_tempo_frame (TempoSection* ts,  const Tempo& bpm, const framepos_t& frame)
+{
+       Metrics future_map;
+       {
+               Glib::Threads::RWLock::WriterLock lm (lock);
+               TempoSection* new_section = copy_metrics_and_point (future_map, ts);
+               if (solve_map (future_map, new_section, bpm, frame)) {
+                       solve_map (_metrics, ts, bpm, frame);
+               }
+       }
+
+       Metrics::const_iterator d = future_map.begin();
+       while (d != future_map.end()) {
+               delete (*d);
+               ++d;
+       }
+
+       MetricPositionChanged (); // Emit Signal
+}
+
+void
+TempoMap::gui_move_tempo_beat (TempoSection* ts,  const Tempo& bpm, const double& beat)
+{
+       Metrics future_map;
+       {
+               Glib::Threads::RWLock::WriterLock lm (lock);
+               TempoSection* new_section = copy_metrics_and_point (future_map, ts);
+               if (solve_map (future_map, new_section, bpm, pulse_at_beat_locked (future_map, beat))) {
+                       solve_map (_metrics, ts, bpm, pulse_at_beat_locked (_metrics, beat));
+               }
+       }
+
+       Metrics::const_iterator d = future_map.begin();
+       while (d != future_map.end()) {
+               delete (*d);
+               ++d;
+       }
+
+       MetricPositionChanged (); // Emit Signal
+}
+
+void
+TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const framepos_t&  frame)
+{
+       {
+               Glib::Threads::RWLock::WriterLock lm (lock);
+               solve_map (_metrics, ms, mt, frame);
+       }
+
+       MetricPositionChanged (); // Emit Signal
+}
+
+void
+TempoMap::gui_move_meter (MeterSection* ms, const Meter& mt, const double&  beat)
+{
+       {
+               Glib::Threads::RWLock::WriterLock lm (lock);
+               solve_map (_metrics, ms, mt, pulse_at_beat_locked (_metrics, beat));
+       }
+
+       MetricPositionChanged (); // Emit Signal
+}
+
+bool
+TempoMap::gui_change_tempo (TempoSection* ts,  const Tempo& bpm)
+{
+       Metrics future_map;
+       bool can_solve = false;
+       {
+               Glib::Threads::RWLock::WriterLock lm (lock);
+               TempoSection* new_section = copy_metrics_and_point (future_map, ts);
+               new_section->set_beats_per_minute (bpm.beats_per_minute());
+               recompute_tempos (future_map);
+
+               if (check_solved (future_map, true)) {
+                       ts->set_beats_per_minute (bpm.beats_per_minute());
+                       recompute_map (_metrics);
+                       can_solve = true;
+               }
+       }
+
+       Metrics::const_iterator d = future_map.begin();
+       while (d != future_map.end()) {
+               delete (*d);
+               ++d;
+       }
+       if (can_solve) {
+               MetricPositionChanged (); // Emit Signal
+       }
+       return can_solve;
+}
+
 framecnt_t
 TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
 {