Tempo ramps - fix constant tempo thinko.
authornick_m <mainsbridge@gmail.com>
Thu, 3 Mar 2016 15:22:37 +0000 (02:22 +1100)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:11 +0000 (23:38 +1000)
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index 060507676db6463ae9165557e1e74dcd84e9c264..92549d29e1dbe084299703aa2b8cfb9a81415a95 100644 (file)
@@ -183,17 +183,17 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
        Type type () const { return _type; }
 
        double tempo_at_frame (framepos_t frame, framecnt_t frame_rate) const;
-       framepos_t frame_at_tempo (double tempo, framecnt_t frame_rate) const;
+       framepos_t frame_at_tempo (double tempo, double beat, framecnt_t frame_rate) const;
 
        double tempo_at_beat (double beat) const;
-       double beat_at_tempo (double tempo) const;
-
-       double tick_at_frame (framepos_t frame, framecnt_t frame_rate) const;
-       framepos_t frame_at_tick (double tick, framecnt_t frame_rate) const;
+       double beat_at_tempo (double tempo, framepos_t frame, framecnt_t frame_rate) const;
 
        double beat_at_frame (framepos_t frame, framecnt_t frame_rate) const;
        framepos_t frame_at_beat (double beat, framecnt_t frame_rate) const;
 
+       double tick_at_frame (framepos_t frame, framecnt_t frame_rate) const;
+       framepos_t frame_at_tick (double tick, framecnt_t frame_rate) const;
+
        void set_c_func_from_tempo_and_beat (double end_bpm, double end_beat, framecnt_t frame_rate);
        double compute_c_func (double end_bpm, framepos_t end_frame, framecnt_t frame_rate) const;
 
index 5b83f008d2bc28e195807a6b2f3ddf2b805087b7..74033983afb47d5dbb245072b11856cf4110d220 100644 (file)
@@ -219,10 +219,10 @@ TempoSection::tempo_at_frame (framepos_t f, framecnt_t frame_rate) const
    where the tempo occurs in this section. note that the tempo map may have multiple such values.
 */
 framepos_t
-TempoSection::frame_at_tempo (double bpm, framecnt_t frame_rate) const
+TempoSection::frame_at_tempo (double bpm, double b, framecnt_t frame_rate) const
 {
        if (_type == Constant) {
-               return frame();
+               return ((b - beat())  * frames_per_beat (frame_rate))  + frame();
        }
 
        return minute_to_frame (time_at_tick_tempo (bpm *  BBT_Time::ticks_per_beat), frame_rate) + frame();
@@ -244,15 +244,36 @@ TempoSection::tempo_at_beat (double b) const
    where the tempo occurs in this section. note that the tempo map may have multiple such values.
 */
 double
-TempoSection::beat_at_tempo (double bpm) const
+TempoSection::beat_at_tempo (double bpm, framepos_t f, framecnt_t frame_rate) const
 {
        if (_type == Constant) {
-               return beat();
+               double const ticks = (((f - frame()) / frames_per_beat (frame_rate)) * BBT_Time::ticks_per_beat) + tick();
+               return ticks / BBT_Time::ticks_per_beat;
        }
 
-       return (tick_at_tick_tempo (bpm *  BBT_Time::ticks_per_beat) / BBT_Time::ticks_per_beat) + beat();
+       return (tick_at_tick_tempo (bpm *  BBT_Time::ticks_per_beat) + tick()) / BBT_Time::ticks_per_beat;
 }
 
+/** returns the zero-based beat (relative to session origin)
+   where the zero-based frame (relative to session)
+   lies.
+*/
+double
+TempoSection::beat_at_frame (framepos_t frame, framecnt_t frame_rate) const
+{
+       return tick_at_frame (frame, frame_rate) / BBT_Time::ticks_per_beat;
+}
+
+/** returns the zero-based frame (relative to session start frame)
+   where the zero-based beat (relative to session start)
+   falls.
+*/
+
+framepos_t
+TempoSection::frame_at_beat (double beat, framecnt_t frame_rate) const
+{
+       return frame_at_tick (beat * BBT_Time::ticks_per_beat, frame_rate);
+}
 
 /** returns the zero-based tick (relative to session origin)
    where the zero-based frame (relative to tempo section)
@@ -282,27 +303,6 @@ TempoSection::frame_at_tick (double t, framecnt_t frame_rate) const
        return minute_to_frame (time_at_tick (t - tick()), frame_rate) + frame();
 }
 
-/** returns the zero-based beat (relative to session origin)
-   where the zero-based frame (relative to session)
-   lies.
-*/
-double
-TempoSection::beat_at_frame (framepos_t frame, framecnt_t frame_rate) const
-{
-       return tick_at_frame (frame, frame_rate) / BBT_Time::ticks_per_beat;
-}
-
-/** returns the zero-based frame (relative to session start frame)
-   where the zero-based beat (relative to session start)
-   falls.
-*/
-
-framepos_t
-TempoSection::frame_at_beat (double beat, framecnt_t frame_rate) const
-{
-       return frame_at_tick (beat * BBT_Time::ticks_per_beat, frame_rate);
-}
-
 /*
 Ramp Overview
 
@@ -337,6 +337,12 @@ t(b) = log((cb / T0) + 1) / c
 The time t at which Tempo T occurs is a as above:
 t(T) = log(T / T0) / c
 
+The beat at which a Tempo T occurs is:
+b(T) = (T - T0) / c
+
+The Tempo at which beat b occurs is:
+T(b) = b.c + T0
+
 We define c for this tempo ramp by placing a new tempo section at some time t after this one.
 Our problem is that we usually don't know t.
 We almost always know the duration in beats between this and the new section, so we need to find c in terms of the beat function.
@@ -350,8 +356,7 @@ We can now store c for future time calculations.
 If the following tempo section (the one that defines c in conjunction with this one)
 is changed or moved, c is no longer valid.
 
-The private methods' position parameters are all relative to this tempo section.
-the public ones are session-relative
+The public methods are session-relative.
 
 Most of this stuff is taken from this paper:
 
@@ -1007,18 +1012,18 @@ TempoMap::imagine_new_order (TempoSection* section, const Tempo& bpm, const fram
                                        /* we have already set the frame - set the beat */
                                        prev_ts->set_c_func (prev_ts->compute_c_func (bpm.beats_per_minute(), frame, _frame_rate));
                                        //section->set_beat (prev_ts->beat_at_frame (frame, _frame_rate));
-                                       section->set_beat (prev_ts->beat_at_tempo (bpm.beats_per_minute()));
+                                       section->set_beat (prev_ts->beat_at_tempo (bpm.beats_per_minute(), frame, _frame_rate));
                                        prev_ts = t;
                                        continue;
                                }
                                if (t->position_lock_style() == MusicTime) {
                                        prev_ts->set_c_func_from_tempo_and_beat (t->beats_per_minute(), t->beat(), _frame_rate);
                                        //t->set_frame (prev_ts->frame_at_beat (t->beat(), _frame_rate));
-                                       t->set_frame (prev_ts->frame_at_tempo (t->beats_per_minute(), _frame_rate));
+                                       t->set_frame (prev_ts->frame_at_tempo (t->beats_per_minute(), t->beat(), _frame_rate));
                                } else {
                                        prev_ts->set_c_func (prev_ts->compute_c_func (t->beats_per_minute(), t->frame(), _frame_rate));
                                        //t->set_beat (prev_ts->beat_at_frame (t->frame(), _frame_rate));
-                                       t->set_beat (prev_ts->beat_at_tempo (t->beats_per_minute()));
+                                       t->set_beat (prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate));
                                }
                        }
                        prev_ts = t;
@@ -1471,21 +1476,21 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
                                        if (prev_ts->type() == TempoSection::Ramp) {
                                                prev_ts->set_c_func (prev_ts->compute_c_func (t->beats_per_minute(), t->frame(), _frame_rate));
                                                //t->set_beat (prev_ts->beat_at_frame (t->frame(), _frame_rate));
-                                               t->set_beat (prev_ts->beat_at_tempo (t->beats_per_minute()));
+                                               t->set_beat (prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate));
                                        } else {
                                                prev_ts->set_c_func (0.0);
                                                //t->set_beat (prev_ts->beat_at_frame (t->frame(), _frame_rate));
-                                               t->set_beat (prev_ts->beat_at_tempo (t->beats_per_minute()));
+                                               t->set_beat (prev_ts->beat_at_tempo (t->beats_per_minute(), t->frame(), _frame_rate));
                                        }
                                } else {
                                        if (prev_ts->type() == TempoSection::Ramp) {
                                                prev_ts->set_c_func_from_tempo_and_beat (t->beats_per_minute(), t->beat(), _frame_rate);
                                                //t->set_frame (prev_ts->frame_at_beat (t->beat(), _frame_rate));
-                                               t->set_frame (prev_ts->frame_at_tempo (t->beats_per_minute(), _frame_rate));
+                                               t->set_frame (prev_ts->frame_at_tempo (t->beats_per_minute(), t->beat(), _frame_rate));
                                        } else {
                                                prev_ts->set_c_func (0.0);
                                                //t->set_frame (prev_ts->frame_at_beat (t->beat(), _frame_rate));
-                                               t->set_frame (prev_ts->frame_at_tempo (t->beats_per_minute(), _frame_rate));
+                                               t->set_frame (prev_ts->frame_at_tempo (t->beats_per_minute(), t->beat(), _frame_rate));
                                        }
                                }
                        }