Tempo ramps - make legacy session detection more robust.
authornick_m <mainsbridge@gmail.com>
Mon, 4 Apr 2016 19:22:44 +0000 (05:22 +1000)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:14 +0000 (23:38 +1000)
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index 06fdbf77befa42a92c4e03b6dd2ff1b2f9a8d6c4..3f81a6a9384e71a1075757d3c33d6a57d65993a0 100644 (file)
@@ -406,6 +406,8 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
 
        void set_length (framepos_t frames);
 
+       void fix_legacy_session();
+
        XMLNode& get_state (void);
        int set_state (const XMLNode&, int version);
 
index 0c044f968ad9eb297301083d67cf7b09bd133782..5ace190101c6b229da0231bfc2df535264f2d59d 100644 (file)
@@ -84,6 +84,8 @@ TempoSection::TempoSection (const XMLNode& node)
        double pulse;
        uint32_t frame;
 
+       _legacy_bbt = BBT_Time (0, 0, 0);
+
        if ((prop = node.property ("start")) != 0) {
                if (sscanf (prop->value().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32,
                            &bbt.bars,
@@ -1290,13 +1292,16 @@ TempoMap::recompute_meters (Metrics& metrics)
                                meter->set_pulse (pulse);
                        } else {
                                double pulse = 0.0;
+                               pair<double, BBT_Time> new_beat;
                                if (prev_m) {
                                        pulse = prev_m->pulse() + ((meter->bbt().bars - prev_m->bbt().bars) *  prev_m->divisions_per_bar() / prev_m->note_divisor());
+                                       new_beat = make_pair (((pulse - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat(), meter->bbt());
                                } else {
                                        /* shouldn't happen - the first is audio-locked */
                                        pulse = pulse_at_beat_locked (metrics, meter->beat());
+                                       new_beat = make_pair (pulse, meter->bbt());
                                }
-                               pair<double, BBT_Time> new_beat (((pulse - prev_m->pulse()) * prev_m->note_divisor()) + prev_m->beat(), meter->bbt());
+
                                meter->set_beat (new_beat);
                                meter->set_frame (frame_at_pulse_locked (metrics, pulse));
                                meter->set_pulse (pulse);
@@ -2776,6 +2781,68 @@ TempoMap::meter_section_at (const double& beat) const
        return *prev_m;
 }
 
+void
+TempoMap::fix_legacy_session ()
+{
+       MeterSection* prev_m = 0;
+       TempoSection* prev_t = 0;
+
+       for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
+               MeterSection* m;
+               TempoSection* t;
+
+               if ((m = dynamic_cast<MeterSection*>(*i)) != 0) {
+                       if (!m->movable()) {
+                               pair<double, BBT_Time> bbt = make_pair (0.0, BBT_Time (1, 1, 0));
+                               m->set_beat (bbt);
+                               m->set_pulse (0.0);
+                               m->set_frame (0);
+                               m->set_position_lock_style (AudioTime);
+                               prev_m = m;
+                               continue;
+                       }
+                       if (prev_m) {
+                               pair<double, BBT_Time> start = make_pair (((m->bbt().bars - 1) * prev_m->note_divisor())
+                                                                         + (m->bbt().beats - 1)
+                                                                         + (m->bbt().ticks / BBT_Time::ticks_per_beat)
+                                                                         , m->bbt());
+                               m->set_beat (start);
+                               const double start_beat = ((m->bbt().bars - 1) * prev_m->note_divisor())
+                                       + (m->bbt().beats - 1)
+                                       + (m->bbt().ticks / BBT_Time::ticks_per_beat);
+                               m->set_pulse (start_beat / prev_m->note_divisor());
+                       }
+                       prev_m = m;
+               } else if ((t = dynamic_cast<TempoSection*>(*i)) != 0) {
+
+                       if (!t->active()) {
+                               continue;
+                       }
+
+                       if (!t->movable()) {
+                               t->set_pulse (0.0);
+                               t->set_frame (0);
+                               t->set_position_lock_style (AudioTime);
+                               prev_t = t;
+                               continue;
+                       }
+
+                       if (prev_t) {
+                               const double beat = ((t->legacy_bbt().bars - 1) * ((prev_m) ? prev_m->note_divisor() : 4.0))
+                                       + (t->legacy_bbt().beats - 1)
+                                       + (t->legacy_bbt().ticks / BBT_Time::ticks_per_beat);
+                               if (prev_m) {
+                                       t->set_pulse (beat / prev_m->note_divisor());
+                               } else {
+                                       /* really shouldn't happen but.. */
+                                       t->set_pulse (beat / 4.0);
+                               }
+                       }
+                       prev_t = t;
+               }
+       }
+}
+
 XMLNode&
 TempoMap::get_state ()
 {
@@ -2841,66 +2908,6 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
                        _metrics.sort (cmp);
                }
 
-               /* check for legacy sessions where bbt was the base musical unit for tempo */
-               MeterSection* prev_m = 0;
-               TempoSection* prev_t = 0;
-
-               for (Metrics::iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
-                       MeterSection* m;
-                       TempoSection* t;
-
-                       /* if one is < 0.0, they all are. this is a legacy session */
-                       if ((m = dynamic_cast<MeterSection*>(*i)) != 0 && m->pulse() < 0.0) {
-                               if (!m->movable()) {
-                                       pair<double, BBT_Time> bbt = make_pair (0.0, BBT_Time (1, 1, 0));
-                                       m->set_beat (bbt);
-                                       m->set_pulse (0.0);
-                                       m->set_frame (0);
-                                       m->set_position_lock_style (AudioTime);
-                                       prev_m = m;
-                                       continue;
-                               }
-                               if (prev_m) {
-                                       /*XX we cannot possibly make this work??. */
-                                       pair<double, BBT_Time> start = make_pair (((m->bbt().bars - 1) * prev_m->note_divisor())
-                                                                                 + (m->bbt().beats - 1)
-                                                                                 + (m->bbt().ticks / BBT_Time::ticks_per_beat)
-                                                                                 , m->bbt());
-                                       m->set_beat (start);
-                                       const double start_beat = ((m->bbt().bars - 1) * prev_m->note_divisor())
-                                               + (m->bbt().beats - 1)
-                                               + (m->bbt().ticks / BBT_Time::ticks_per_beat);
-                                       m->set_pulse (start_beat / prev_m->note_divisor());
-                               }
-                               prev_m = m;
-                       } else if ((t = dynamic_cast<TempoSection*>(*i)) != 0 && t->pulse() < 0.0) {
-
-                               if (!t->active()) {
-                                       continue;
-                               }
-
-                               if (!t->movable()) {
-                                       t->set_pulse (0.0);
-                                       t->set_frame (0);
-                                       t->set_position_lock_style (AudioTime);
-                                       prev_t = t;
-                                       continue;
-                               }
-
-                               if (prev_t) {
-                                       const double beat = ((t->legacy_bbt().bars - 1) * ((prev_m) ? prev_m->note_divisor() : 4.0))
-                                               + (t->legacy_bbt().beats - 1)
-                                               + (t->legacy_bbt().ticks / BBT_Time::ticks_per_beat);
-                                       if (prev_m) {
-                                               t->set_pulse (beat / prev_m->note_divisor());
-                                       } else {
-                                               /* really shouldn't happen but.. */
-                                               t->set_pulse (beat / 4.0);
-                                       }
-                               }
-                               prev_t = t;
-                       }
-               }
                /* check for multiple tempo/meters at the same location, which
                   ardour2 somehow allowed.
                */
@@ -2929,6 +2936,17 @@ TempoMap::set_state (const XMLNode& node, int /*version*/)
                        prev = i;
                }
 
+               /* check for legacy sessions where bbt was the base musical unit for tempo */
+               for (Metrics::const_iterator i = _metrics.begin(); i != _metrics.end(); ++i) {
+                       TempoSection* t;
+                       if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
+                               if (t->legacy_bbt().bars != 0) {
+                                       fix_legacy_session();
+                                       break;
+                               }
+                       }
+               }
+
                recompute_map (_metrics);
        }