Tempo ramps - minor optimisation and comment clarification.
authornick_m <mainsbridge@gmail.com>
Thu, 25 Feb 2016 20:01:37 +0000 (07:01 +1100)
committernick_m <mainsbridge@gmail.com>
Fri, 27 May 2016 13:38:10 +0000 (23:38 +1000)
libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index d0c8381b2b711cb5d135b5201bcdc2666bc781a0..bb8848e020cb686c48df69661519c4e6c590a006 100644 (file)
@@ -190,8 +190,7 @@ class LIBARDOUR_API TempoSection : public MetricSection, public Tempo {
        double beat_at_frame (framepos_t frame, framecnt_t frame_rate) const;
        framepos_t frame_at_beat (double beat, framecnt_t frame_rate) const;
 
-       framecnt_t ramp_duration_from_tempo_and_beat (double end_tpm, double end_beat, framecnt_t frame_rate);
-
+       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;
        double get_c_func () const { return _c_func; }
        void set_c_func (double c_func) { _c_func = c_func; }
index dc19d8141e38f1966d79482a614db70bf4273b76..42b4dce3bace010a1aa1e00b2be61488028b096b 100644 (file)
@@ -264,7 +264,7 @@ TempoSection::frame_at_beat (double beat, framecnt_t frame_rate) const
 /*
 Ramp Overview
 
-
+      |                     *
 Tempo |                   *
 Tt----|-----------------*|
 Ta----|--------------|*  |
@@ -272,7 +272,7 @@ Ta----|--------------|*  |
       |         *    |   |
       |     *        |   |
 T0----|*             |   |
-      |              |   |
+  *   |              |   |
       _______________|___|_____
       time           a   t (next tempo)
       [        c         ] defines c
@@ -286,21 +286,21 @@ c = log(Ta/T0)/a
 and
 a = log(Ta/T0)/c
 
-We define c for a tempo ramp by placing a new tempo at some distance t away from our existing one.
-
-Given the function constant, the beat function (duration in beats at some time t) is:
+Given the function constant, the integral of the Tempo function (the beat function, which is the duration in beats at some time t) is:
 b(t) = T0(e^(ct) - 1) / c
 
-To find the time t at any beat b on the curve, we use the inverse function of the beat function:
+To find the time t at any beat b, we use the inverse function of the beat function (the time function) which can be shown to be :
 t(b) = log((cb / T0) + 1) / c
 
-When we add or move the next tempo section, we change the function constant. We take advantage of t being equal to a here.
+We define c for a tempo ramp by placing a new tempo at some distance t away from our existing one.
 The problem is that we usually don't know t.
-We do know the beat duration until the next tempo section.
-Substituting t = a into the beat function allows us to find a in terms of beat duration b and the two relevant tempos:
+We do know the duration in beats where the next tempo section lies.
+Where t = a (when we define c), we can solve a in terms of beat duration b and the two relevant tempos using the beat function:
 a = b log (Ta / T0) / (T0 (e^(log (Ta / T0)) - 1))
 
 We then use a to set the function constant c (above).
+Solving a and setting c in one operation allows us to further reduce the problem to:
+c = T0 (e^(log (Ta / T0)) - 1) / b
 
 Most of this stuff is taken from this paper:
 WHERE’S THE BEAT?
@@ -312,12 +312,12 @@ https://www.zhdk.ch/fileadmin/data_subsites/data_icst/Downloads/Timegrid/ICST_Te
 
 */
 
-/* compute the duration of this tempo section givan the end tempo and duration in beats of some later tempo section*/
-framecnt_t
-TempoSection::ramp_duration_from_tempo_and_beat (double end_bpm, double end_beat, framecnt_t frame_rate)
+/* set this ramp's function constant using the end tempo and duration in beats of some later tempo section*/
+void
+TempoSection::set_c_func_from_tempo_and_beat (double end_bpm, double end_beat, framecnt_t frame_rate)
 {
        double const log_tempo_ratio = log ((end_bpm * BBT_Time::ticks_per_beat) / ticks_per_minute());
-       return minute_to_frame (((end_beat * BBT_Time::ticks_per_beat) * log_tempo_ratio) / (ticks_per_minute() * (exp (log_tempo_ratio) - 1)), frame_rate);
+       _c_func = ticks_per_minute() *  (exp (log_tempo_ratio) - 1) / (end_beat * BBT_Time::ticks_per_beat);
 }
 
 /* compute the function constant from some later tempo section, given tempo (beats/min.) and distance (in frames) from this tempo section */
@@ -1124,17 +1124,16 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
                if ((t = dynamic_cast<TempoSection*> (*i)) != 0) {
 
                        if (prev_ts) {
-                               double const ticks_relative_to_prev = (t->beat() - prev_ts->beat()) * BBT_Time::ticks_per_beat;
-
-                               framecnt_t duration;
                                if (prev_ts->type() == TempoSection::Ramp) {
-                                       duration = prev_ts->ramp_duration_from_tempo_and_beat (t->beats_per_minute(), t->beat() - prev_ts->beat(), _frame_rate);
+                                       prev_ts->set_c_func_from_tempo_and_beat (t->beats_per_minute(), t->beat() - prev_ts->beat(), _frame_rate);
+                                       t->set_frame (prev_ts->frame_at_tempo (t->beats_per_minute(), _frame_rate) + prev_ts->frame());
                                } else {
-                                       duration = (framecnt_t) floor (ticks_relative_to_prev * prev_ts->frames_per_beat (_frame_rate) * BBT_Time::ticks_per_beat);
+                                       double const ticks_relative_to_prev = (t->beat() - prev_ts->beat()) * BBT_Time::ticks_per_beat;
+                                       framecnt_t const duration = (framecnt_t) floor (ticks_relative_to_prev * prev_ts->frames_per_beat (_frame_rate)
+                                                                                        * BBT_Time::ticks_per_beat);
+                                       prev_ts->set_c_func (0.0);
+                                       t->set_frame (duration + prev_ts->frame());
                                }
-
-                               prev_ts->set_c_func (prev_ts->compute_c_func (t->beats_per_minute(), duration, _frame_rate));
-                               t->set_frame (duration + prev_ts->frame());
                        }
                        prev_ts = t;
                }
@@ -1144,7 +1143,7 @@ TempoMap::recompute_map (bool reassign_tempo_bbt, framepos_t end)
        MeterSection* meter = 0;
 
        for (mi = metrics.begin(); mi != metrics.end(); ++mi) {
-               /* we can do this beacuse we have the tempo section frames set */
+               /* We now have the tempo map set. use it to set meter positions.*/
                if ((meter = dynamic_cast<MeterSection*> (*mi)) != 0) {
                        meter->set_frame (frame_at_tick (meter->beat() * BBT_Time::ticks_per_beat));
                }