Similar hacks to framepos_minus_beats to handle -ve
authorCarl Hetherington <carl@carlh.net>
Sun, 11 Dec 2011 21:14:35 +0000 (21:14 +0000)
committerCarl Hetherington <carl@carlh.net>
Sun, 11 Dec 2011 21:14:35 +0000 (21:14 +0000)
positions as were appled to framepos_plus_beats.

git-svn-id: svn://localhost/ardour2/branches/3.0@10984 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/tempo.cc
libs/ardour/test/framepos_minus_beats_test.cc

index 351b5979e6219927704e983e0c848e6f7bdad6b8..dc811aff83bc1b8e170ed50a37f9dfbb3d22c853 100644 (file)
@@ -2024,6 +2024,15 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const
 
        for (i = metrics->begin(); i != metrics->end(); ++i) {
 
+               /* This is a bit of a hack, but pos could be -ve, and if it is,
+                  we consider the initial metric changes (at time 0) to actually
+                  be in effect at pos.
+               */
+               framepos_t f = (*i)->frame ();
+               if (pos < 0 && f == 0) {
+                       f = pos;
+               }
+
                if ((*i)->frame() > pos) {
                        break;
                }
@@ -2038,9 +2047,13 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const
                }
        }
 
+       bool no_more_metrics = false;
+
        /* Move i back to the metric before "pos" */
        if (i != metrics->begin ()) {
                --i;
+       } else {
+               no_more_metrics = true;
        }
 
        /* We now have:
@@ -2052,11 +2065,11 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const
 
        while (beats) {
 
-               /* End of this section (looking backwards) */
-               framepos_t end = i == metrics->end() ? max_framepos : (*i)->frame ();
+               /* Distance to the end of this section in frames */
+               framecnt_t distance_frames = no_more_metrics ? max_framepos : (pos - (*i)->frame());
 
                /* Distance to the end in beats */
-               Evoral::MusicalTime distance_beats = (pos - end) / tempo->frames_per_beat (_frame_rate, *meter);
+               Evoral::MusicalTime distance_beats = distance_frames / tempo->frames_per_beat (_frame_rate, *meter);
 
                /* Amount to subtract this time */
                double const sub = min (distance_beats, beats);
@@ -2112,6 +2125,8 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const
                                        break;
                                }
                        }
+               } else {
+                       no_more_metrics = true;
                }
        }
 
index f80f57d969bbc4a608b2ea290334780adc28419a..01bafc1606f4d77f5f76c5268549ca3bc6d027de 100644 (file)
@@ -27,6 +27,10 @@ FrameposMinusBeatsTest::singleTempoTest ()
        /* Subtract 1 beat from beat 3 of the first bar */
        framepos_t r = map.framepos_minus_beats (frames_per_beat * 2, 1);
        CPPUNIT_ASSERT_EQUAL (r, framepos_t (frames_per_beat * 1));
+
+       /* Subtract 4 beats from 3 beats in, to go beyond zero */
+       r = map.framepos_minus_beats (frames_per_beat * 3, 4);
+       CPPUNIT_ASSERT_EQUAL (r, framepos_t (- frames_per_beat));
 }
 
 /* Test adding things that overlap a tempo change */