Slightly simpler implementation of framewalk_to_beats.
authorCarl Hetherington <carl@carlh.net>
Sat, 10 Dec 2011 16:06:29 +0000 (16:06 +0000)
committerCarl Hetherington <carl@carlh.net>
Sat, 10 Dec 2011 16:06:29 +0000 (16:06 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@10967 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/tempo.h
libs/ardour/tempo.cc

index aa4266f35a599bf680f4679982333b8ad67518a1..a6f7a36541f5406bfc46c42eb437e7e5d36a5720 100644 (file)
@@ -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);
index 97ec1224f0101501ae902569cd05389a7885c500..7a653547da46dfa4411cd7a400521606b49593ac 100644 (file)
@@ -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<const TempoSection*>(*i)) != 0) {
                        tempo = t;
                } else if ((m = dynamic_cast<const MeterSection*>(*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<const TempoSection*>(*i)) != 0) {
-                                       tempo = t;
-                               } else if ((m = dynamic_cast<const MeterSection*>(*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<const TempoSection*>(*i)) != 0) {
+                               tempo = t;
+                       } else if ((m = dynamic_cast<const MeterSection*>(*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.