From 0b7db6ebbb5dc297d9feeac3fac687c93651e6e4 Mon Sep 17 00:00:00 2001 From: nick_m Date: Wed, 9 Nov 2016 00:37:52 +1100 Subject: [PATCH] add empoMap::quarter_notes_between_frames(). - in an ideal world, this wouldn't be here at all, but is required to support framewalk_to_qn(). if Beats are at tick resolution, the frame-induced temporal rounding is acceptable. --- libs/ardour/ardour/tempo.h | 2 ++ libs/ardour/tempo.cc | 70 +++++++++++++++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index e820a1cbdc..a35e1b4fba 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -458,6 +458,7 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible framepos_t frame_at_quarter_note (const double quarter_note) const; framecnt_t frames_between_quarter_notes (const double start, const double end) const; + double quarter_notes_between_frames (const framecnt_t start, const framecnt_t end) const; double quarter_note_at_beat (const double beat); double beat_at_quarter_note (const double beat); @@ -515,6 +516,7 @@ private: double beat_at_quarter_note_locked (const Metrics& metrics, const double beat) const; double minutes_between_quarter_notes_locked (const Metrics& metrics, const double start_qn, const double end_qn) const; + double quarter_notes_between_frames_locked (const Metrics& metrics, const framecnt_t start, const framecnt_t end) const; const TempoSection& tempo_section_at_minute_locked (const Metrics& metrics, double minute) const; const TempoSection& tempo_section_at_beat_locked (const Metrics& metrics, const double& beat) const; diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 0279007a21..8ae25fe24d 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -334,6 +334,26 @@ TempoSection::minute_at_pulse (const double& p) const return _time_at_pulse (p - pulse()) + minute(); } +double +TempoSection::pulse_at_frame (const framepos_t& f) const +{ + if (_type == Constant || _c_func == 0.0) { + return (minute_at_frame (f - frame()) * pulses_per_minute()) + pulse(); + } + + return _pulse_at_time (minute_at_frame (f - frame())) + pulse(); +} + +framepos_t +TempoSection::frame_at_pulse (const double& p) const +{ + if (_type == Constant || _c_func == 0.0) { + return frame_at_minute (((p - pulse()) / pulses_per_minute()) + minute()); + } + + return frame_at_minute (_time_at_pulse (p - pulse()) + minute()); +} + /* Ramp Overview @@ -2392,6 +2412,54 @@ TempoMap::minutes_between_quarter_notes_locked (const Metrics& metrics, const do return minute_at_pulse_locked (metrics, end / 4.0) - minute_at_pulse_locked (metrics, start / 4.0); } +double +TempoMap::quarter_notes_between_frames (const framecnt_t start, const framecnt_t end) const +{ + Glib::Threads::RWLock::ReaderLock lm (lock); + + return quarter_notes_between_frames_locked (_metrics, start, end); +} + +double +TempoMap::quarter_notes_between_frames_locked (const Metrics& metrics, const framecnt_t start, const framecnt_t end) const +{ + const TempoSection* prev_t = 0; + + for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { + TempoSection* t; + + if ((*i)->is_tempo()) { + t = static_cast (*i); + if (!t->active()) { + continue; + } + if (prev_t && t->frame() > start) { + break; + } + prev_t = t; + } + } + const double start_qn = prev_t->pulse_at_frame (start); + + for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { + TempoSection* t; + + if ((*i)->is_tempo()) { + t = static_cast (*i); + if (!t->active()) { + continue; + } + if (prev_t && t->frame() > end) { + break; + } + prev_t = t; + } + } + const double end_qn = prev_t->pulse_at_frame (end); + + return (end_qn - start_qn) * 4.0; +} + bool TempoMap::check_solved (const Metrics& metrics) const { @@ -4329,7 +4397,7 @@ TempoMap::framewalk_to_qn (framepos_t pos, framecnt_t distance) const { Glib::Threads::RWLock::ReaderLock lm (lock); - return Evoral::Beats (quarter_note_at_minute_locked (_metrics, minute_at_frame (pos + distance)) - quarter_note_at_minute_locked (_metrics, minute_at_frame (pos))); + return Evoral::Beats (quarter_notes_between_frames_locked (_metrics, pos, pos + distance)); } struct bbtcmp {