diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index 060507676d..92549d29e1 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -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; diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 5b83f008d2..74033983af 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -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)); } } }