mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-27 00:47:43 +01:00
Add fixed-up framepos_plus_beats() and use it for the BeatsFramesConverter, since it only ever passed in beats to framepos_plus_bbt anyway.
git-svn-id: svn://localhost/ardour2/branches/3.0@10964 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
2a9ceb74c4
commit
e02e25e3f3
6 changed files with 228 additions and 3 deletions
|
|
@ -30,6 +30,7 @@
|
|||
#include "pbd/stateful.h"
|
||||
#include "pbd/statefuldestructible.h"
|
||||
|
||||
#include "evoral/types.hpp"
|
||||
|
||||
#include "ardour/ardour.h"
|
||||
|
||||
|
|
@ -247,6 +248,7 @@ class TempoMap : public PBD::StatefulDestructible
|
|||
Timecode::BBT_Time bbt_subtract (const Timecode::BBT_Time&, const Timecode::BBT_Time&) const;
|
||||
|
||||
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;
|
||||
|
||||
void change_existing_tempo_at (framepos_t, double bpm, double note_type);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ BeatsFramesConverter::to (double beats) const
|
|||
{
|
||||
assert (beats >= 0);
|
||||
|
||||
return _tempo_map.framepos_plus_bbt (_origin_b, Timecode::BBT_Time(beats)) - _origin_b;
|
||||
return _tempo_map.framepos_plus_beats (_origin_b, beats) - _origin_b;
|
||||
}
|
||||
|
||||
double
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
|
||||
#include <glibmm/thread.h>
|
||||
#include "pbd/xml++.h"
|
||||
#include "evoral/types.hpp"
|
||||
#include "ardour/debug.h"
|
||||
#include "ardour/tempo.h"
|
||||
#include "ardour/utils.h"
|
||||
|
|
@ -1935,6 +1935,72 @@ TempoMap::bbt_subtract (const BBT_Time& start, const BBT_Time& decrement) const
|
|||
return result;
|
||||
}
|
||||
|
||||
/** Add some (fractional) beats to a frame position, and return the result in frames */
|
||||
framepos_t
|
||||
TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats) const
|
||||
{
|
||||
Metrics::const_iterator i;
|
||||
const TempoSection* tempo;
|
||||
const MeterSection* meter;
|
||||
|
||||
/* Find the starting metrics for tempo & meter */
|
||||
|
||||
for (i = metrics->begin(); i != metrics->end(); ++i) {
|
||||
|
||||
if ((*i)->frame() > pos) {
|
||||
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) {
|
||||
meter = m;
|
||||
}
|
||||
}
|
||||
|
||||
/* We now have:
|
||||
|
||||
meter -> the Meter for "pos"
|
||||
tempo -> the Tempo for "pos"
|
||||
i -> for first new metric after "pos", possibly metrics->end()
|
||||
*/
|
||||
|
||||
while (beats) {
|
||||
|
||||
/* End of this section */
|
||||
framepos_t end = i == metrics->end() ? max_framepos : (*i)->frame ();
|
||||
|
||||
/* Distance to the end in beats */
|
||||
Evoral::MusicalTime distance_beats = (end - pos) / tempo->frames_per_beat (_frame_rate, *meter);
|
||||
|
||||
/* Amount to subtract this time */
|
||||
double const sub = min (distance_beats, beats);
|
||||
|
||||
/* Update */
|
||||
beats -= sub;
|
||||
pos += sub * tempo->frames_per_beat (_frame_rate, *meter);
|
||||
|
||||
/* 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 pos;
|
||||
}
|
||||
|
||||
/** Add the BBT interval op to pos and return the result */
|
||||
framepos_t
|
||||
TempoMap::framepos_plus_bbt (framepos_t pos, BBT_Time op) const
|
||||
|
|
@ -2069,6 +2135,7 @@ 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
|
||||
TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
|
||||
|
|
|
|||
134
libs/ardour/test/framepos_plus_beats_test.cc
Normal file
134
libs/ardour/test/framepos_plus_beats_test.cc
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#include "framepos_plus_beats_test.h"
|
||||
#include "ardour/tempo.h"
|
||||
#include "timecode/bbt_time.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION (FrameposPlusBeatsTest);
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace Timecode;
|
||||
|
||||
/* Basic tests with no tempo / meter changes */
|
||||
void
|
||||
FrameposPlusBeatsTest::singleTempoTest ()
|
||||
{
|
||||
int const sampling_rate = 48000;
|
||||
int const bpm = 120;
|
||||
|
||||
double const frames_per_beat = (60 / double (bpm)) * double (sampling_rate);
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Tempo tempo (bpm);
|
||||
Meter meter (4, 4);
|
||||
|
||||
map.add_meter (meter, BBT_Time (1, 1, 0));
|
||||
map.add_tempo (tempo, BBT_Time (1, 1, 0));
|
||||
|
||||
/* Add 1 beat to beat 3 of the first bar */
|
||||
framepos_t r = map.framepos_plus_beats (frames_per_beat * 2, 1);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (frames_per_beat * 3));
|
||||
}
|
||||
|
||||
/* Test adding things that overlap a tempo change */
|
||||
void
|
||||
FrameposPlusBeatsTest::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 */
|
||||
|
||||
/* Add 1 beat to 1|2 */
|
||||
framepos_t r = map.framepos_plus_beats (24e3, 1);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (48e3));
|
||||
|
||||
/* Add 2 beats to 3|4 (over the tempo change) */
|
||||
r = map.framepos_plus_beats (264e3, 2);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (264e3 + 24e3 + 12e3));
|
||||
|
||||
/* Add 2.5 beats to 3|3|960 (over the tempo change) */
|
||||
r = map.framepos_plus_beats (264e3 - 12e3, 2.5);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (264e3 + 24e3 + 12e3));
|
||||
}
|
||||
|
||||
/* Same as doubleTempoTest () except put a meter change at the same time as the
|
||||
tempo change (which shouldn't affect anything, since we are just dealing with
|
||||
beats)
|
||||
*/
|
||||
|
||||
void
|
||||
FrameposPlusBeatsTest::doubleTempoWithMeterTest ()
|
||||
{
|
||||
int const sampling_rate = 48000;
|
||||
|
||||
TempoMap map (sampling_rate);
|
||||
Meter meterA (4, 4);
|
||||
map.add_meter (meterA, 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 |
|
||||
|
||||
*/
|
||||
|
||||
Tempo tempoA (120);
|
||||
map.add_tempo (tempoA, BBT_Time (1, 1, 0));
|
||||
Tempo tempoB (240);
|
||||
map.add_tempo (tempoB, BBT_Time (4, 1, 0));
|
||||
Meter meterB (3, 4);
|
||||
map.add_meter (meterB, BBT_Time (4, 1, 0));
|
||||
|
||||
/* Now some tests */
|
||||
|
||||
/* Add 1 beat to 1|2 */
|
||||
framepos_t r = map.framepos_plus_beats (24e3, 1);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (48e3));
|
||||
|
||||
/* Add 2 beats to 3|4 (over the tempo change) */
|
||||
r = map.framepos_plus_beats (264e3, 2);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (264e3 + 24e3 + 12e3));
|
||||
|
||||
/* Add 2.5 beats to 3|3|960 (over the tempo change) */
|
||||
r = map.framepos_plus_beats (264e3 - 12e3, 2.5);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (264e3 + 24e3 + 12e3));
|
||||
}
|
||||
|
||||
|
||||
21
libs/ardour/test/framepos_plus_beats_test.h
Normal file
21
libs/ardour/test/framepos_plus_beats_test.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <sigc++/sigc++.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
class FrameposPlusBeatsTest : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE (FrameposPlusBeatsTest);
|
||||
CPPUNIT_TEST (singleTempoTest);
|
||||
CPPUNIT_TEST (doubleTempoTest);
|
||||
CPPUNIT_TEST (doubleTempoWithMeterTest);
|
||||
CPPUNIT_TEST_SUITE_END ();
|
||||
|
||||
public:
|
||||
void setUp () {}
|
||||
void tearDown () {}
|
||||
|
||||
void singleTempoTest ();
|
||||
void doubleTempoTest ();
|
||||
void doubleTempoWithMeterTest ();
|
||||
};
|
||||
|
||||
|
|
@ -427,7 +427,8 @@ def build(bld):
|
|||
test/interpolation_test.cc
|
||||
test/midi_clock_slave_test.cc
|
||||
test/resampled_source_test.cc
|
||||
test/framewalk_to_beats_test.cc
|
||||
test/framewalk_to_beats_test.cc
|
||||
test/framepos_plus_beats_test.cc
|
||||
test/testrunner.cc
|
||||
'''.split()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue