fix bypassing plugins with sidechain i/o
[ardour.git] / libs / ardour / tempo.cc
index d46656c4c79272dd2a1dc508af50507e0f9bb4ed..c5c7e2c52fa90ad158c22b4126f4c0473acade76 100644 (file)
@@ -2027,6 +2027,9 @@ TempoMap::solve_map_frame (Metrics& imaginary, TempoSection* section, const fram
                        if (prev_t) {
                                if (t == section) {
                                        section_prev = prev_t;
+                                       if (t->locked_to_meter()) {
+                                               prev_t = t;
+                                       }
                                        continue;
                                }
                                if (t->position_lock_style() == MusicTime) {
@@ -2525,15 +2528,42 @@ TempoMap::predict_tempo_position (TempoSection* section, const BBT_Time& bbt)
 }
 
 void
-TempoMap::gui_move_tempo (TempoSection* ts, const framepos_t& frame)
+TempoMap::gui_move_tempo (TempoSection* ts, const framepos_t& frame, const int& sub_num)
 {
        Metrics future_map;
+       bool was_musical = ts->position_lock_style() == MusicTime;
+
+       if (sub_num == 0 && was_musical) {
+               /* if we're not snapping to music,
+                  AudioTime and MusicTime may be treated identically.
+               */
+               ts->set_position_lock_style (AudioTime);
+       }
 
        if (ts->position_lock_style() == MusicTime) {
                {
+                       /* if we're snapping to a musical grid, set the pulse exactly instead of via the supplied frame. */
                        Glib::Threads::RWLock::WriterLock lm (lock);
                        TempoSection* tempo_copy = copy_metrics_and_point (_metrics, future_map, ts);
-                       const double pulse = pulse_at_frame_locked (future_map, frame);
+                       double beat = beat_at_frame_locked (future_map, frame);
+
+                       if (sub_num > 1) {
+                               beat = floor (beat) + (floor (((beat - floor (beat)) * (double) sub_num) + 0.5) / sub_num);
+                       } else if (sub_num == 1) {
+                               /* snap to beat */
+                               beat = floor (beat + 0.5);
+                       }
+
+                       double pulse = pulse_at_beat_locked (future_map, beat);
+
+                       if (sub_num == -1) {
+                               /* snap to  bar */
+                               BBT_Time bbt = bbt_at_beat_locked (future_map, beat);
+                               bbt.beats = 1;
+                               bbt.ticks = 0;
+                               pulse = pulse_at_bbt_locked (future_map, bbt);
+                       }
+
                        if (solve_map_pulse (future_map, tempo_copy, pulse)) {
                                solve_map_pulse (_metrics, ts, pulse);
                                recompute_meters (_metrics);
@@ -2552,6 +2582,10 @@ TempoMap::gui_move_tempo (TempoSection* ts, const framepos_t& frame)
                }
        }
 
+       if (sub_num == 0 && was_musical) {
+               ts->set_position_lock_style (MusicTime);
+       }
+
        Metrics::const_iterator d = future_map.begin();
        while (d != future_map.end()) {
                delete (*d);
@@ -2668,6 +2702,8 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
                                }
                        }
                }
+               /* minimum allowed measurement distance in frames */
+               const framepos_t min_dframe = 2;
 
                /* the change in frames is the result of changing the slope of at most 2 previous tempo sections.
                   constant to constant is straightforward, as the tempo prev to prev_t has constant slope.
@@ -2689,14 +2725,17 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
 
                        if (prev_t->position_lock_style() == MusicTime) {
                                if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) {
+                                       if (frame > prev_to_prev_t->frame() + min_dframe && (frame + prev_t_frame_contribution) > prev_to_prev_t->frame() + min_dframe) {
 
-                                       new_bpm = prev_t->beats_per_minute() * ((frame - prev_to_prev_t->frame())
-                                                                               / (double) ((frame + prev_t_frame_contribution) - prev_to_prev_t->frame()));
-
+                                               new_bpm = prev_t->beats_per_minute() * ((frame - prev_to_prev_t->frame())
+                                                                                       / (double) ((frame + prev_t_frame_contribution) - prev_to_prev_t->frame()));
+                                       } else {
+                                               new_bpm = prev_t->beats_per_minute();
+                                       }
                                } else {
                                        /* prev to prev is irrelevant */
 
-                                       if (start_pulse != prev_t->pulse()) {
+                                       if (start_pulse > prev_t->pulse() && end_pulse > prev_t->pulse()) {
                                                new_bpm = prev_t->beats_per_minute() * ((start_pulse - prev_t->pulse()) / (end_pulse - prev_t->pulse()));
                                        } else {
                                                new_bpm = prev_t->beats_per_minute();
@@ -2705,12 +2744,17 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
                        } else {
                                /* AudioTime */
                                if (prev_to_prev_t && prev_to_prev_t->type() == TempoSection::Ramp) {
-                                       new_bpm = prev_t->beats_per_minute() * ((frame - prev_to_prev_t->frame())
-                                                                               / (double) ((end_frame) - prev_to_prev_t->frame()));
+                                       if (frame > prev_to_prev_t->frame() + min_dframe && end_frame > prev_to_prev_t->frame() + min_dframe) {
+
+                                               new_bpm = prev_t->beats_per_minute() * ((frame - prev_to_prev_t->frame())
+                                                                                       / (double) ((end_frame) - prev_to_prev_t->frame()));
+                                       } else {
+                                               new_bpm = prev_t->beats_per_minute();
+                                       }
                                } else {
                                        /* prev_to_prev_t is irrelevant */
 
-                                       if (end_frame != prev_t->frame()) {
+                                       if (frame > prev_t->frame() + min_dframe && end_frame > prev_t->frame() + min_dframe) {
                                                new_bpm = prev_t->beats_per_minute() * ((frame - prev_t->frame()) / (double) (end_frame - prev_t->frame()));
                                        } else {
                                                new_bpm = prev_t->beats_per_minute();
@@ -2719,22 +2763,34 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
                        }
                } else {
 
-                       double frame_ratio;
-                       double pulse_ratio;
+                       double frame_ratio = 1.0;
+                       double pulse_ratio = 1.0;
                        const framepos_t pulse_pos = prev_t->frame_at_pulse (pulse, _frame_rate);
 
                        if (prev_to_prev_t) {
-
-                               frame_ratio = (((pulse_pos - fr_off) - prev_to_prev_t->frame()) / (double) ((pulse_pos) - prev_to_prev_t->frame()));
-                               pulse_ratio = ((start_pulse - prev_to_prev_t->pulse()) / (end_pulse - prev_to_prev_t->pulse()));
+                               if (pulse_pos > prev_to_prev_t->frame() + min_dframe && (pulse_pos - fr_off) > prev_to_prev_t->frame() + min_dframe) {
+                                       frame_ratio = (((pulse_pos - fr_off) - prev_to_prev_t->frame()) / (double) ((pulse_pos) - prev_to_prev_t->frame()));
+                               }
+                               if (end_pulse > prev_to_prev_t->pulse() && start_pulse > prev_to_prev_t->pulse()) {
+                                       pulse_ratio = ((start_pulse - prev_to_prev_t->pulse()) / (end_pulse - prev_to_prev_t->pulse()));
+                               }
                        } else {
-
-                               frame_ratio = (((pulse_pos - fr_off) - prev_t->frame()) / (double) ((pulse_pos) - prev_t->frame()));
+                               if (pulse_pos > prev_t->frame() + min_dframe && (pulse_pos - fr_off) > prev_t->frame() + min_dframe) {
+                                       frame_ratio = (((pulse_pos - fr_off) - prev_t->frame()) / (double) ((pulse_pos) - prev_t->frame()));
+                               }
                                pulse_ratio = (start_pulse / end_pulse);
                        }
                        new_bpm = prev_t->beats_per_minute() * (pulse_ratio * frame_ratio);
                }
 
+               /* don't clamp and proceed here.
+                  testing has revealed that this can go negative,
+                  which is an entirely different thing to just being too low.
+               */
+               if (new_bpm < 0.5) {
+                       return;
+               }
+               new_bpm = min (new_bpm, (double) 1000.0);
                prev_t->set_beats_per_minute (new_bpm);
                recompute_tempos (future_map);
                recompute_meters (future_map);
@@ -2940,6 +2996,11 @@ TempoMap::get_grid (vector<TempoMap::BBTPoint>& points,
        if (cnt < 0.0) {
                cnt = 0.0;
        }
+
+       if (frame_at_beat_locked (_metrics, cnt) >= upper) {
+               return;
+       }
+
        while (pos < upper) {
                pos = frame_at_beat_locked (_metrics, cnt);
                const TempoSection tempo = tempo_section_at_frame_locked (_metrics, pos);