summaryrefslogtreecommitdiff
path: root/libs/ardour/tempo.cc
diff options
context:
space:
mode:
authornick_m <mainsbridge@gmail.com>2016-08-31 03:19:39 +1000
committernick_m <mainsbridge@gmail.com>2016-08-31 23:12:11 +1000
commit395183ee7b51da12a77cf232db260435c0adb2c7 (patch)
treeff6da9cda2e1aec3d8df10fbbd22af48a3dcf1d5 /libs/ardour/tempo.cc
parent21054f6d8db2c69271bebb99c5a2800d38ae8afd (diff)
Add quarter-note position methods to TempoMap.
Diffstat (limited to 'libs/ardour/tempo.cc')
-rw-r--r--libs/ardour/tempo.cc195
1 files changed, 193 insertions, 2 deletions
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 65c4765dd4..de220b6ed7 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -2106,7 +2106,15 @@ TempoMap::quarter_note_at_frame (const framepos_t frame)
{
Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
- const double ret = pulse_at_frame_locked (_metrics, frame) * 4.0;
+ const double ret = quarter_note_at_frame_locked (_metrics, frame);
+
+ return ret;
+}
+
+double
+TempoMap::quarter_note_at_frame_locked (const Metrics& metrics, const framepos_t frame)
+{
+ const double ret = pulse_at_frame_locked (metrics, frame) * 4.0;
return ret;
}
@@ -2130,7 +2138,43 @@ TempoMap::frame_at_quarter_note (const double quarter_note)
{
Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
- const framepos_t ret = frame_at_pulse_locked (_metrics, quarter_note / 4.0);
+ const framepos_t ret = frame_at_quarter_note_locked (_metrics, quarter_note);
+
+ return ret;
+}
+
+framepos_t
+TempoMap::frame_at_quarter_note_locked (const Metrics& metrics, const double quarter_note)
+{
+ const framepos_t ret = frame_at_pulse_locked (metrics, quarter_note / 4.0);
+
+ return ret;
+}
+
+double
+TempoMap::quarter_note_at_beat (const double beat)
+{
+ Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
+
+ const double ret = quarter_note_at_beat_locked (_metrics, beat);
+
+ return ret;
+}
+
+double
+TempoMap::quarter_note_at_beat_locked (const Metrics& metrics, const double beat)
+{
+ const double ret = pulse_at_beat_locked (metrics, beat) * 4.0;
+
+ return ret;
+}
+
+double
+TempoMap::beat_at_quarter_note (const double quarter_note)
+{
+ Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
+
+ const double ret = beat_at_pulse_locked (_metrics, quarter_note / 4.0);
return ret;
}
@@ -3102,6 +3146,43 @@ TempoMap::exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t&
return beat;
}
+double
+TempoMap::exact_qn_at_frame (const framepos_t& frame, const int32_t sub_num)
+{
+ Glib::Threads::RWLock::ReaderLock lm (lock);
+
+ return exact_qn_at_frame_locked (_metrics, frame, sub_num);
+}
+
+double
+TempoMap::exact_qn_at_frame_locked (const Metrics& metrics, const framepos_t& frame, const int32_t sub_num)
+{
+ double qn = quarter_note_at_frame_locked (metrics, frame);
+
+ if (sub_num > 1) {
+ qn = floor (qn) + (floor (((qn - floor (qn)) * (double) sub_num) + 0.5) / sub_num);
+ } else if (sub_num == 1) {
+ /* snap to quarter note */
+ qn = floor (qn + 0.5);
+ } else if (sub_num == -1) {
+ /* snap to bar */
+ Timecode::BBT_Time bbt = bbt_at_pulse_locked (metrics, qn / 4.0);
+ bbt.beats = 1;
+ bbt.ticks = 0;
+
+ const double prev_b = pulse_at_bbt_locked (_metrics, bbt) * 4.0;
+ ++bbt.bars;
+ const double next_b = pulse_at_bbt_locked (_metrics, bbt) * 4.0;
+
+ if ((qn - prev_b) > (next_b - prev_b) / 2.0) {
+ qn = next_b;
+ } else {
+ qn = prev_b;
+ }
+ }
+
+ return qn;
+}
framecnt_t
TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
@@ -3224,6 +3305,102 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir)
}
framepos_t
+TempoMap::round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir)
+{
+ Glib::Threads::RWLock::ReaderLock lm (lock);
+ uint32_t ticks = (uint32_t) floor (max (0.0, quarter_note_at_frame_locked (_metrics, fr)) * BBT_Time::ticks_per_beat);
+ uint32_t beats = (uint32_t) floor (ticks / BBT_Time::ticks_per_beat);
+ uint32_t ticks_one_subdivisions_worth = (uint32_t) BBT_Time::ticks_per_beat / sub_num;
+
+ ticks -= beats * BBT_Time::ticks_per_beat;
+
+ if (dir > 0) {
+ /* round to next (or same iff dir == RoundUpMaybe) */
+
+ uint32_t mod = ticks % ticks_one_subdivisions_worth;
+
+ if (mod == 0 && dir == RoundUpMaybe) {
+ /* right on the subdivision, which is fine, so do nothing */
+
+ } else if (mod == 0) {
+ /* right on the subdivision, so the difference is just the subdivision ticks */
+ ticks += ticks_one_subdivisions_worth;
+
+ } else {
+ /* not on subdivision, compute distance to next subdivision */
+
+ ticks += ticks_one_subdivisions_worth - mod;
+ }
+
+ if (ticks >= BBT_Time::ticks_per_beat) {
+ ticks -= BBT_Time::ticks_per_beat;
+ }
+ } else if (dir < 0) {
+
+ /* round to previous (or same iff dir == RoundDownMaybe) */
+
+ uint32_t difference = ticks % ticks_one_subdivisions_worth;
+
+ if (difference == 0 && dir == RoundDownAlways) {
+ /* right on the subdivision, but force-rounding down,
+ so the difference is just the subdivision ticks */
+ difference = ticks_one_subdivisions_worth;
+ }
+
+ if (ticks < difference) {
+ ticks = BBT_Time::ticks_per_beat - ticks;
+ } else {
+ ticks -= difference;
+ }
+
+ } else {
+ /* round to nearest */
+ double rem;
+
+ /* compute the distance to the previous and next subdivision */
+
+ if ((rem = fmod ((double) ticks, (double) ticks_one_subdivisions_worth)) > ticks_one_subdivisions_worth/2.0) {
+
+ /* closer to the next subdivision, so shift forward */
+
+ ticks = lrint (ticks + (ticks_one_subdivisions_worth - rem));
+
+ DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("moved forward to %1\n", ticks));
+
+ if (ticks > BBT_Time::ticks_per_beat) {
+ ++beats;
+ ticks -= BBT_Time::ticks_per_beat;
+ DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("fold beat to %1\n", beats));
+ }
+
+ } else if (rem > 0) {
+
+ /* closer to previous subdivision, so shift backward */
+
+ if (rem > ticks) {
+ if (beats == 0) {
+ /* can't go backwards past zero, so ... */
+ return 0;
+ }
+ /* step back to previous beat */
+ --beats;
+ ticks = lrint (BBT_Time::ticks_per_beat - rem);
+ DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("step back beat to %1\n", beats));
+ } else {
+ ticks = lrint (ticks - rem);
+ DEBUG_TRACE (DEBUG::SnapBBT, string_compose ("moved backward to %1\n", ticks));
+ }
+ } else {
+ /* on the subdivision, do nothing */
+ }
+ }
+
+ const framepos_t ret_frame = frame_at_quarter_note_locked (_metrics, beats + (ticks / BBT_Time::ticks_per_beat));
+
+ return ret_frame;
+}
+
+framepos_t
TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
@@ -3904,6 +4081,13 @@ TempoMap::framepos_plus_beats (framepos_t frame, Evoral::Beats beats) const
return frame_at_beat_locked (_metrics, beat_at_frame_locked (_metrics, frame) + beats.to_double());
}
+framepos_t
+TempoMap::framepos_plus_qn (framepos_t frame, Evoral::Beats beats) const
+{
+ Glib::Threads::RWLock::ReaderLock lm (lock);
+
+ return frame_at_beat_locked (_metrics, beat_at_frame_locked (_metrics, frame) + beats.to_double());
+}
/** Subtract some (fractional) beats from a frame position, and return the result in frames */
framepos_t
@@ -3950,6 +4134,13 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
return Evoral::Beats (beat_at_frame_locked (_metrics, pos + distance) - beat_at_frame_locked (_metrics, pos));
}
+Evoral::Beats
+TempoMap::framewalk_to_qn (framepos_t pos, framecnt_t distance) const
+{
+ Glib::Threads::RWLock::ReaderLock lm (lock);
+
+ return Evoral::Beats (beat_at_frame_locked (_metrics, pos + distance) - beat_at_frame_locked (_metrics, pos));
+}
struct bbtcmp {
bool operator() (const BBT_Time& a, const BBT_Time& b) {
return a < b;