From 6e211e27e2027da328b6fe117f10e1962c007afb Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 10 Dec 2011 16:06:29 +0000 Subject: [PATCH] Slightly simpler implementation of framewalk_to_beats. git-svn-id: svn://localhost/ardour2/branches/3.0@10967 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/tempo.h | 2 +- libs/ardour/tempo.cc | 111 ++++++++++--------------------------- 2 files changed, 30 insertions(+), 83 deletions(-) diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h index aa4266f35a..a6f7a36541 100644 --- a/libs/ardour/ardour/tempo.h +++ b/libs/ardour/ardour/tempo.h @@ -249,7 +249,7 @@ class TempoMap : public PBD::StatefulDestructible framepos_t framepos_plus_bbt (framepos_t pos, Timecode::BBT_Time b) const; framepos_t framepos_plus_beats (framepos_t, Evoral::MusicalTime) const; - double framewalk_to_beats (framepos_t pos, framecnt_t distance) const; + Evoral::MusicalTime framewalk_to_beats (framepos_t pos, framecnt_t distance) const; void change_existing_tempo_at (framepos_t, double bpm, double note_type); void change_initial_tempo (double bpm, double note_type); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 97ec1224f0..7a653547da 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -2135,29 +2135,15 @@ TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const return pos; } - /** Count the number of beats that are equivalent to distance when starting at pos */ -double +Evoral::MusicalTime TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const { Metrics::const_iterator i; - double beats = 0; - const MeterSection* meter; - const MeterSection* m; const TempoSection* tempo; - const TempoSection* t; - double frames_per_beat; - - double ddist = distance; - double dpos = pos; - - meter = &first_meter (); - tempo = &first_tempo (); - - assert (meter); - assert (tempo); - - /* find the starting metrics for tempo & meter */ + const MeterSection* meter; + + /* Find the starting metrics for tempo & meter */ for (i = metrics->begin(); i != metrics->end(); ++i) { @@ -2165,6 +2151,9 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const break; } + const TempoSection* t; + const MeterSection* m; + if ((t = dynamic_cast(*i)) != 0) { tempo = t; } else if ((m = dynamic_cast(*i)) != 0) { @@ -2179,83 +2168,41 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const i -> for first new metric after "pos", possibly metrics->end() */ - /* now comes the complicated part. we have to add one beat a time, - checking for a new metric on every beat. - */ - - frames_per_beat = tempo->frames_per_beat (_frame_rate, *meter); - - double last_dpos = 0; - - while (ddist > 0) { - - /* if we're nearly at the end, but have a fractional beat left, - compute the fraction and then its all over - */ - - if (ddist < frames_per_beat) { - beats += ddist / frames_per_beat; - break; - } - - /* walk one beat */ + Evoral::MusicalTime beats = 0; - last_dpos = dpos; - ddist -= frames_per_beat; - dpos += frames_per_beat; - beats += 1.0; + while (distance) { - /* check if we need to use a new metric section: has adding frames moved us - to or after the start of the next metric section? in which case, use it. - */ - - if (i != metrics->end()) { - - double const f = (*i)->frame (); - - if (f <= (framepos_t) dpos) { - - /* We just went past a tempo/meter section start at (*i)->frame(), - which will be on a beat. - - So what we have is - - (*i)->frame() [f] - beat beat beat beat - | | | | - | | | | - ^ ^ - | | - | new - | dpos [q] - last - dpos [p] + /* End of this section */ + framepos_t const end = i == metrics->end() ? max_framepos : (*i)->frame (); - We need to go back to last_dpos (1 beat ago) and re-add - (f - p) beats using the old frames per beat and (q - f) beats - using the new. - */ + /* Distance to the end in frames */ + framecnt_t const distance_to_end = end - pos; - beats -= 1; - beats += (f - last_dpos) / frames_per_beat; + /* Amount to subtract this time */ + double const sub = min (distance, distance_to_end); - if ((t = dynamic_cast(*i)) != 0) { - tempo = t; - } else if ((m = dynamic_cast(*i)) != 0) { - meter = m; - } - ++i; - frames_per_beat = tempo->frames_per_beat (_frame_rate, *meter); + /* Update */ + distance -= sub; + beats += sub / tempo->frames_per_beat (_frame_rate, *meter); - beats += (dpos - f) / frames_per_beat; + /* Move on if there's anything to move to */ + if (i != metrics->end ()) { + const TempoSection* t; + const MeterSection* m; + + if ((t = dynamic_cast(*i)) != 0) { + tempo = t; + } else if ((m = dynamic_cast(*i)) != 0) { + meter = m; } + + ++i; } } return beats; } - /** Compare the time of this with that of another MetricSection. * @param with_bbt True to compare using start(), false to use frame(). * @return -1 for less than, 0 for equal, 1 for greater than. -- 2.30.2