Keep track of MIDI region's start positions in beats, to
match the source, so that starts are not corrupted when tempos change (#4494). git-svn-id: svn://localhost/ardour2/branches/3.0@10976 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
ed360080d0
commit
1bbe08af1a
@ -35,6 +35,7 @@ namespace ARDOUR {
|
||||
MidiModel used by the MidiRegion
|
||||
*/
|
||||
extern PBD::PropertyDescriptor<void*> midi_data;
|
||||
extern PBD::PropertyDescriptor<Evoral::MusicalTime> start_beats;
|
||||
extern PBD::PropertyDescriptor<Evoral::MusicalTime> length_beats;
|
||||
}
|
||||
}
|
||||
@ -111,6 +112,7 @@ class MidiRegion : public Region
|
||||
|
||||
private:
|
||||
friend class RegionFactory;
|
||||
PBD::Property<Evoral::MusicalTime> _start_beats;
|
||||
PBD::Property<Evoral::MusicalTime> _length_beats;
|
||||
|
||||
MidiRegion (const SourceList&);
|
||||
@ -138,6 +140,9 @@ class MidiRegion : public Region
|
||||
void model_automation_state_changed (Evoral::Parameter const &);
|
||||
void model_contents_changed ();
|
||||
|
||||
void set_start_beats_from_start_frames ();
|
||||
void update_after_tempo_map_change ();
|
||||
|
||||
std::set<Evoral::Parameter> _filtered_parameters; ///< parameters that we ask our source not to return when reading
|
||||
PBD::ScopedConnection _model_connection;
|
||||
PBD::ScopedConnection _source_connection;
|
||||
|
@ -189,7 +189,7 @@ class Region
|
||||
void set_position (framepos_t);
|
||||
void set_position_on_top (framepos_t);
|
||||
void special_set_position (framepos_t);
|
||||
void update_position_after_tempo_map_change ();
|
||||
virtual void update_after_tempo_map_change ();
|
||||
void nudge_position (frameoffset_t);
|
||||
|
||||
bool at_natural_position () const;
|
||||
|
@ -249,6 +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;
|
||||
framepos_t framepos_minus_beats (framepos_t, Evoral::MusicalTime) 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);
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "ardour/playlist.h"
|
||||
#include "ardour/region_factory.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/tempo.h"
|
||||
#include "ardour/types.h"
|
||||
|
||||
#include "i18n.h"
|
||||
@ -52,6 +53,7 @@ using namespace PBD;
|
||||
namespace ARDOUR {
|
||||
namespace Properties {
|
||||
PBD::PropertyDescriptor<void*> midi_data;
|
||||
PBD::PropertyDescriptor<Evoral::MusicalTime> start_beats;
|
||||
PBD::PropertyDescriptor<Evoral::MusicalTime> length_beats;
|
||||
}
|
||||
}
|
||||
@ -61,6 +63,8 @@ MidiRegion::make_property_quarks ()
|
||||
{
|
||||
Properties::midi_data.property_id = g_quark_from_static_string (X_("midi-data"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for midi-data = %1\n", Properties::midi_data.property_id));
|
||||
Properties::start_beats.property_id = g_quark_from_static_string (X_("start-beats"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for start-beats = %1\n", Properties::start_beats.property_id));
|
||||
Properties::length_beats.property_id = g_quark_from_static_string (X_("length-beats"));
|
||||
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for length-beats = %1\n", Properties::length_beats.property_id));
|
||||
}
|
||||
@ -68,12 +72,14 @@ MidiRegion::make_property_quarks ()
|
||||
void
|
||||
MidiRegion::register_properties ()
|
||||
{
|
||||
add_property (_start_beats);
|
||||
add_property (_length_beats);
|
||||
}
|
||||
|
||||
/* Basic MidiRegion constructor (many channels) */
|
||||
MidiRegion::MidiRegion (const SourceList& srcs)
|
||||
: Region (srcs)
|
||||
, _start_beats (Properties::start_beats, 0)
|
||||
, _length_beats (Properties::length_beats, midi_source(0)->length_beats())
|
||||
{
|
||||
register_properties ();
|
||||
@ -86,6 +92,7 @@ MidiRegion::MidiRegion (const SourceList& srcs)
|
||||
|
||||
MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
|
||||
: Region (other)
|
||||
, _start_beats (Properties::start_beats, other->_start_beats)
|
||||
, _length_beats (Properties::length_beats, (Evoral::MusicalTime) 0)
|
||||
{
|
||||
update_length_beats ();
|
||||
@ -96,14 +103,16 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
|
||||
model_changed ();
|
||||
}
|
||||
|
||||
/** Create a new MidiRegion, that is part of an existing one */
|
||||
/** Create a new MidiRegion that is part of an existing one */
|
||||
MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t offset)
|
||||
: Region (other, offset)
|
||||
, _start_beats (Properties::start_beats, (Evoral::MusicalTime) 0)
|
||||
, _length_beats (Properties::length_beats, (Evoral::MusicalTime) 0)
|
||||
{
|
||||
BeatsFramesConverter bfc (_session.tempo_map(), _position);
|
||||
Evoral::MusicalTime const offset_beats = bfc.from (offset);
|
||||
|
||||
_start_beats = other->_start_beats + offset_beats;
|
||||
_length_beats = other->_length_beats - offset_beats;
|
||||
|
||||
register_properties ();
|
||||
@ -133,6 +142,7 @@ MidiRegion::clone () const
|
||||
plist.add (Properties::name, ms->name());
|
||||
plist.add (Properties::whole_file, true);
|
||||
plist.add (Properties::start, _start);
|
||||
plist.add (Properties::start_beats, _start_beats);
|
||||
plist.add (Properties::length, _length);
|
||||
plist.add (Properties::length_beats, _length_beats);
|
||||
plist.add (Properties::layer, 0);
|
||||
@ -145,9 +155,18 @@ MidiRegion::post_set (const PropertyChange& pc)
|
||||
{
|
||||
if (pc.contains (Properties::length) && !pc.contains (Properties::length_beats)) {
|
||||
update_length_beats ();
|
||||
} else if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) {
|
||||
set_start_beats_from_start_frames ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegion::set_start_beats_from_start_frames ()
|
||||
{
|
||||
BeatsFramesConverter c (_session.tempo_map(), _position - _start);
|
||||
_start_beats = c.from (_start);
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegion::set_length_internal (framecnt_t len)
|
||||
{
|
||||
@ -155,6 +174,17 @@ MidiRegion::set_length_internal (framecnt_t len)
|
||||
update_length_beats ();
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegion::update_after_tempo_map_change ()
|
||||
{
|
||||
Region::update_after_tempo_map_change ();
|
||||
|
||||
/* _position has now been updated for the new tempo map */
|
||||
_start = _position - _session.tempo_map().framepos_minus_beats (_position, _start_beats);
|
||||
|
||||
send_change (Properties::start);
|
||||
}
|
||||
|
||||
void
|
||||
MidiRegion::update_length_beats ()
|
||||
{
|
||||
|
@ -2979,7 +2979,7 @@ Playlist::update_after_tempo_map_change ()
|
||||
freeze ();
|
||||
|
||||
for (RegionList::iterator i = copy.begin(); i != copy.end(); ++i) {
|
||||
(*i)->update_position_after_tempo_map_change ();
|
||||
(*i)->update_after_tempo_map_change ();
|
||||
}
|
||||
|
||||
thaw ();
|
||||
|
@ -559,7 +559,7 @@ Region::set_position_lock_style (PositionLockStyle ps)
|
||||
}
|
||||
|
||||
void
|
||||
Region::update_position_after_tempo_map_change ()
|
||||
Region::update_after_tempo_map_change ()
|
||||
{
|
||||
boost::shared_ptr<Playlist> pl (playlist());
|
||||
|
||||
|
@ -1935,19 +1935,30 @@ 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 */
|
||||
/** Add some (fractional) beats to a session frame position, and return the result in frames.
|
||||
* pos can be -ve, if required.
|
||||
*/
|
||||
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) {
|
||||
/* 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 (f > pos) {
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1970,11 +1981,11 @@ TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats) const
|
||||
|
||||
while (beats) {
|
||||
|
||||
/* End of this section */
|
||||
framepos_t end = i == metrics->end() ? max_framepos : (*i)->frame ();
|
||||
/* Distance to the end of this section in frames */
|
||||
framecnt_t distance_frames = i == metrics->end() ? max_framepos : ((*i)->frame() - pos);
|
||||
|
||||
/* Distance to the end in beats */
|
||||
Evoral::MusicalTime distance_beats = (end - pos) / 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);
|
||||
@ -2001,6 +2012,112 @@ TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats) const
|
||||
return pos;
|
||||
}
|
||||
|
||||
/** Subtract some (fractional) beats to a frame position, and return the result in frames */
|
||||
framepos_t
|
||||
TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const
|
||||
{
|
||||
Metrics::const_iterator i;
|
||||
const TempoSection* tempo = 0;
|
||||
const MeterSection* meter = 0;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move i back to the metric before "pos" */
|
||||
if (i != metrics->begin ()) {
|
||||
--i;
|
||||
}
|
||||
|
||||
/* We now have:
|
||||
|
||||
meter -> the Meter for "pos"
|
||||
tempo -> the Tempo for "pos"
|
||||
i -> the first metric before "pos", possibly metrics->end()
|
||||
*/
|
||||
|
||||
while (beats) {
|
||||
|
||||
/* End of this section (looking backwards) */
|
||||
framepos_t end = i == metrics->end() ? max_framepos : (*i)->frame ();
|
||||
|
||||
/* Distance to the end in beats */
|
||||
Evoral::MusicalTime distance_beats = (pos - end) / 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 i, tempo and meter back, if there's anything to move to.
|
||||
This is more complicated than the forward case, as we have to
|
||||
a) move back to the previous change in tempo or metric
|
||||
then b) scan back further to the last change in the opposite thing
|
||||
so that tempo/meter are both set up correctly.
|
||||
|
||||
e.g. if we have (where M is a meter change and T a tempo change):
|
||||
M1 T1 T2 T3 M2
|
||||
|
||||
and we move i back to M2, we must also move tempo back to T3 so
|
||||
that tempo/meter continue to reflect the current state.
|
||||
|
||||
Moving further back we'd move i to T3, and meter to M1, then
|
||||
i to T2 and meter (still) to M1, etc.
|
||||
|
||||
XXX: this is slightly farcical.
|
||||
*/
|
||||
|
||||
if (i != metrics->begin ()) {
|
||||
|
||||
--i;
|
||||
|
||||
bool found_tempo = false;
|
||||
bool found_meter = false;
|
||||
|
||||
const TempoSection* t;
|
||||
const MeterSection* m;
|
||||
|
||||
if ((t = dynamic_cast<const TempoSection*>(*i)) != 0) {
|
||||
tempo = t;
|
||||
found_tempo = true;
|
||||
} else if ((m = dynamic_cast<const MeterSection*>(*i)) != 0) {
|
||||
meter = m;
|
||||
found_meter = true;
|
||||
}
|
||||
|
||||
Metrics::const_iterator j = i;
|
||||
while (j != metrics->begin ()) {
|
||||
--j;
|
||||
if (found_tempo && ((m = dynamic_cast<const MeterSection*> (*j)) != 0)) {
|
||||
meter = m;
|
||||
break;
|
||||
} else if (found_meter && ((t = dynamic_cast<const TempoSection*> (*j)) != 0)) {
|
||||
tempo = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@ -2135,7 +2252,9 @@ 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 */
|
||||
/** Count the number of beats that are equivalent to distance when going forward,
|
||||
starting at pos.
|
||||
*/
|
||||
Evoral::MusicalTime
|
||||
TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
|
||||
{
|
||||
@ -2165,7 +2284,7 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
|
||||
|
||||
meter -> the Meter for "pos"
|
||||
tempo -> the Tempo for "pos"
|
||||
i -> for first new metric after "pos", possibly metrics->end()
|
||||
i -> the first metric after "pos", possibly metrics->end()
|
||||
*/
|
||||
|
||||
Evoral::MusicalTime beats = 0;
|
||||
|
134
libs/ardour/test/framepos_minus_beats_test.cc
Normal file
134
libs/ardour/test/framepos_minus_beats_test.cc
Normal file
@ -0,0 +1,134 @@
|
||||
#include "framepos_minus_beats_test.h"
|
||||
#include "ardour/tempo.h"
|
||||
#include "timecode/bbt_time.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION (FrameposMinusBeatsTest);
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace Timecode;
|
||||
|
||||
/* Basic tests with no tempo / meter changes */
|
||||
void
|
||||
FrameposMinusBeatsTest::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));
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/* Test adding things that overlap a tempo change */
|
||||
void
|
||||
FrameposMinusBeatsTest::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 */
|
||||
|
||||
/* Subtract 1 beat from 1|2 */
|
||||
framepos_t r = map.framepos_minus_beats (24e3, 1);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (0));
|
||||
|
||||
/* Subtract 2 beats from 4|2 (over the tempo change) */
|
||||
r = map.framepos_minus_beats (288e3 + 12e3, 2);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (288e3 - 24e3));
|
||||
|
||||
/* Subtract 2.5 beats from 4|2 (over the tempo change) */
|
||||
r = map.framepos_minus_beats (288e3 + 12e3, 2.5);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (288e3 - 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
|
||||
FrameposMinusBeatsTest::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 */
|
||||
|
||||
/* Subtract 1 beat from 1|2 */
|
||||
framepos_t r = map.framepos_minus_beats (24e3, 1);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (0));
|
||||
|
||||
/* Subtract 2 beats from 4|2 (over the tempo change) */
|
||||
r = map.framepos_minus_beats (288e3 + 12e3, 2);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (288e3 - 24e3));
|
||||
|
||||
/* Subtract 2.5 beats from 4|2 (over the tempo change) */
|
||||
r = map.framepos_minus_beats (288e3 + 12e3, 2.5);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (288e3 - 24e3 - 12e3));
|
||||
}
|
||||
|
||||
|
21
libs/ardour/test/framepos_minus_beats_test.h
Normal file
21
libs/ardour/test/framepos_minus_beats_test.h
Normal file
@ -0,0 +1,21 @@
|
||||
#include <sigc++/sigc++.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
class FrameposMinusBeatsTest : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE (FrameposMinusBeatsTest);
|
||||
CPPUNIT_TEST (singleTempoTest);
|
||||
CPPUNIT_TEST (doubleTempoTest);
|
||||
CPPUNIT_TEST (doubleTempoWithMeterTest);
|
||||
CPPUNIT_TEST_SUITE_END ();
|
||||
|
||||
public:
|
||||
void setUp () {}
|
||||
void tearDown () {}
|
||||
|
||||
void singleTempoTest ();
|
||||
void doubleTempoTest ();
|
||||
void doubleTempoWithMeterTest ();
|
||||
};
|
||||
|
@ -27,6 +27,10 @@ FrameposPlusBeatsTest::singleTempoTest ()
|
||||
/* 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));
|
||||
|
||||
/* Add 4 beats to a -ve frame of 1 beat before zero */
|
||||
r = map.framepos_plus_beats (-frames_per_beat * 1, 4);
|
||||
CPPUNIT_ASSERT_EQUAL (r, framepos_t (frames_per_beat * 3));
|
||||
}
|
||||
|
||||
/* Test adding things that overlap a tempo change */
|
||||
|
@ -74,23 +74,23 @@ FramewalkToBeatsTest::doubleTempoTest ()
|
||||
|
||||
/* Now some tests */
|
||||
|
||||
/* Walk 1 beat from 1.2 */
|
||||
/* Walk 1 beat from 1|2 */
|
||||
double r = map.framewalk_to_beats (24e3, 24e3);
|
||||
CPPUNIT_ASSERT_EQUAL (r, 1.0);
|
||||
|
||||
/* Walk 2 beats from 3.3 to 4.1 (over the tempo change) */
|
||||
/* Walk 2 beats from 3|3 to 4|1 (over the tempo change) */
|
||||
r = map.framewalk_to_beats (264e3, (24e3 + 12e3));
|
||||
CPPUNIT_ASSERT_EQUAL (r, 2.0);
|
||||
|
||||
/* Walk 2.5 beats from 3.3-and-a-half to 4.2 (over the tempo change) */
|
||||
/* Walk 2.5 beats from 3|3.5 to 4.2 (over the tempo change) */
|
||||
r = map.framewalk_to_beats (264e3 - 12e3, (24e3 + 12e3 + 12e3));
|
||||
CPPUNIT_ASSERT_EQUAL (r, 2.5);
|
||||
|
||||
/* Walk 3 beats from 3.4-and-a-half to 4.3-and-a-half (over the tempo change) */
|
||||
/* Walk 3 beats from 3|4.5 to 4|3.5 (over the tempo change) */
|
||||
r = map.framewalk_to_beats (264e3 - 12e3, (24e3 + 12e3 + 12e3 + 6e3));
|
||||
CPPUNIT_ASSERT_EQUAL (r, 3.0);
|
||||
|
||||
/* Walk 3.5 beats from 3.4-and-a-half to 4.4 (over the tempo change) */
|
||||
/* Walk 3.5 beats from 3|4.5 to 4.4 (over the tempo change) */
|
||||
r = map.framewalk_to_beats (264e3 - 12e3, (24e3 + 12e3 + 12e3 + 12e3));
|
||||
CPPUNIT_ASSERT_EQUAL (r, 3.5);
|
||||
}
|
||||
|
@ -429,6 +429,7 @@ def build(bld):
|
||||
test/resampled_source_test.cc
|
||||
test/framewalk_to_beats_test.cc
|
||||
test/framepos_plus_beats_test.cc
|
||||
test/framepos_minus_beats_test.cc
|
||||
test/testrunner.cc
|
||||
'''.split()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user