summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/tempo.cc34
-rw-r--r--libs/ardour/test/framewalk_to_beats_test.cc68
-rw-r--r--libs/ardour/test/framewalk_to_beats_test.h2
3 files changed, 101 insertions, 3 deletions
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 017ea20011..617553129c 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -2118,6 +2118,8 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
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,
@@ -2131,6 +2133,7 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
/* walk one beat */
+ last_dpos = dpos;
ddist -= frames_per_beat;
dpos += frames_per_beat;
beats += 1.0;
@@ -2140,7 +2143,34 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
*/
if (i != metrics->end()) {
- if ((*i)->frame() <= (framepos_t) dpos) {
+
+ 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]
+
+ 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.
+ */
+
+ beats -= 1;
+ beats += (f - last_dpos) / frames_per_beat;
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
tempo = t;
@@ -2149,6 +2179,8 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
}
++i;
frames_per_beat = tempo->frames_per_beat (_frame_rate, *meter);
+
+ beats += (dpos - f) / frames_per_beat;
}
}
}
diff --git a/libs/ardour/test/framewalk_to_beats_test.cc b/libs/ardour/test/framewalk_to_beats_test.cc
index c7fb45cada..c5bd47b62a 100644
--- a/libs/ardour/test/framewalk_to_beats_test.cc
+++ b/libs/ardour/test/framewalk_to_beats_test.cc
@@ -23,11 +23,75 @@ FramewalkToBeatsTest::singleTempoTest ()
map.add_meter (meter, BBT_Time (1, 1, 0));
map.add_tempo (tempo, BBT_Time (1, 1, 0));
- /* Add 1 beats-worth of frames to a 2 beat starting point */
+ /* Walk 1 beats-worth of frames from beat 3 */
double r = map.framewalk_to_beats (frames_per_beat * 2, frames_per_beat * 1);
CPPUNIT_ASSERT (r == 1);
- /* Add 6 beats-worth of frames to a 3 beat starting point */
+ /* Walk 6 beats-worth of frames from beat 4 */
r = map.framewalk_to_beats (frames_per_beat * 3, frames_per_beat * 6);
CPPUNIT_ASSERT (r == 6);
+
+ /* Walk 1.5 beats-worth of frames from beat 3 */
+ r = map.framewalk_to_beats (frames_per_beat * 2, frames_per_beat * 1.5);
+ CPPUNIT_ASSERT (r == 1.5);
+
+ /* Walk 1.5 beats-worth of frames from beat 2.5 */
+ r = map.framewalk_to_beats (frames_per_beat * 2.5, frames_per_beat * 1.5);
+ CPPUNIT_ASSERT (r == 1.5);
}
+
+void
+FramewalkToBeatsTest::doubleTempoTest ()
+{
+ int const sampling_rate = 48000;
+
+ TempoMap map (sampling_rate);
+ Meter meter (4, 4);
+ map.add_meter (meter, BBT_Time (1, 1, 0));
+
+ /*
+ 120bpm at bar 1, 240bpm at bar 4
+
+ 120bpm = 24e3 samples per beat
+ 240bpm = 12e3 samples per beat
+ */
+
+
+ /*
+
+ 120bpm 240bpm
+ 0 beats 12 beats
+ 0 frames 288e3 frames
+ | | | | |
+ | 1.1 1.2 1.3 1.4 | 2.1 2.2 2.3.2.4 | 3.1 3.2 3.3 3.4 | 4.1 4.2 4.3 4.4 |
+
+ */
+
+ Tempo tempoA (120);
+ map.add_tempo (tempoA, BBT_Time (1, 1, 0));
+ Tempo tempoB (240);
+ map.add_tempo (tempoB, BBT_Time (4, 1, 0));
+
+ /* Now some tests */
+
+ /* Walk 1 beat from 1.2 */
+ double r = map.framewalk_to_beats (24e3, 24e3);
+ assert (r == 1);
+
+ /* Walk 2 beats from 3.3 to 4.1 (over the tempo change) */
+ r = map.framewalk_to_beats (264e3, (24e3 + 12e3));
+ assert (r == 2);
+
+ /* Walk 2.5 beats from 3.3-and-a-half to 4.2 (over the tempo change) */
+ r = map.framewalk_to_beats (264e3 - 12e3, (24e3 + 12e3 + 12e3));
+ assert (r == 2.5);
+
+ /* Walk 3 beats from 3.3-and-a-half to 4.2-and-a-half (over the tempo change) */
+ r = map.framewalk_to_beats (264e3 - 12e3, (24e3 + 12e3 + 12e3 + 6e3));
+ assert (r == 3);
+
+ /* Walk 3.5 beats from 3.3-and-a-half to 4.3 (over the tempo change) */
+ r = map.framewalk_to_beats (264e3 - 12e3, (24e3 + 12e3 + 12e3 + 12e3));
+ assert (r == 3.5);
+}
+
diff --git a/libs/ardour/test/framewalk_to_beats_test.h b/libs/ardour/test/framewalk_to_beats_test.h
index 3dd24553e2..ae6ae646eb 100644
--- a/libs/ardour/test/framewalk_to_beats_test.h
+++ b/libs/ardour/test/framewalk_to_beats_test.h
@@ -6,6 +6,7 @@ class FramewalkToBeatsTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE (FramewalkToBeatsTest);
CPPUNIT_TEST (singleTempoTest);
+ CPPUNIT_TEST (doubleTempoTest);
CPPUNIT_TEST_SUITE_END ();
public:
@@ -13,5 +14,6 @@ public:
void tearDown () {}
void singleTempoTest ();
+ void doubleTempoTest ();
};