summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2014-11-22 04:05:42 -0500
committerDavid Robillard <d@drobilla.net>2014-11-22 04:05:42 -0500
commitc1cfa12d6e5136d2e3e5501e83ff74c5009a9e60 (patch)
tree56d2811bc8b9d6f2a5accfa8e497ddd5976c7c7a /libs/ardour
parentcae74309a583c29dd6cc2081425c2e7b673ea13e (diff)
Wrap MusicalTime in a class.
This lets us get a more explicit handle on time conversions, and is the main step towards using actual beat:tick time and getting away from floating point precision problems.
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/automation_control.h1
-rw-r--r--libs/ardour/ardour/automation_list.h5
-rw-r--r--libs/ardour/ardour/beats_frames_converter.h28
-rw-r--r--libs/ardour/ardour/midi_model.h23
-rw-r--r--libs/ardour/ardour/midi_region.h2
-rw-r--r--libs/ardour/ardour/midi_source.h12
-rw-r--r--libs/ardour/ardour/smf_source.h7
-rw-r--r--libs/ardour/beats_frames_converter.cc33
-rw-r--r--libs/ardour/import.cc17
-rw-r--r--libs/ardour/midi_diskstream.cc2
-rw-r--r--libs/ardour/midi_model.cc20
-rw-r--r--libs/ardour/midi_region.cc18
-rw-r--r--libs/ardour/midi_source.cc6
-rw-r--r--libs/ardour/midi_state_tracker.cc2
-rw-r--r--libs/ardour/midi_stretch.cc4
-rw-r--r--libs/ardour/quantize.cc12
-rw-r--r--libs/ardour/smf_source.cc54
-rw-r--r--libs/ardour/tempo.cc22
-rw-r--r--libs/ardour/test/framepos_minus_beats_test.cc17
-rw-r--r--libs/ardour/test/framepos_plus_beats_test.cc16
20 files changed, 173 insertions, 128 deletions
diff --git a/libs/ardour/ardour/automation_control.h b/libs/ardour/ardour/automation_control.h
index 639c5b5287..d73b2fc822 100644
--- a/libs/ardour/ardour/automation_control.h
+++ b/libs/ardour/ardour/automation_control.h
@@ -24,6 +24,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
+#include "evoral/types.hpp"
#include "pbd/controllable.h"
#include "evoral/Control.hpp"
diff --git a/libs/ardour/ardour/automation_list.h b/libs/ardour/ardour/automation_list.h
index 72c26420c0..28f9be3fd4 100644
--- a/libs/ardour/ardour/automation_list.h
+++ b/libs/ardour/ardour/automation_list.h
@@ -27,6 +27,9 @@
#include <glibmm/threads.h>
+#include "evoral/ControlList.hpp"
+#include "evoral/Parameter.hpp"
+
#include "pbd/undo.h"
#include "pbd/xml++.h"
#include "pbd/statefuldestructible.h"
@@ -34,8 +37,6 @@
#include "ardour/ardour.h"
-#include "evoral/ControlList.hpp"
-
namespace ARDOUR {
class AutomationList;
diff --git a/libs/ardour/ardour/beats_frames_converter.h b/libs/ardour/ardour/beats_frames_converter.h
index 2e170d278a..ada09b1179 100644
--- a/libs/ardour/ardour/beats_frames_converter.h
+++ b/libs/ardour/ardour/beats_frames_converter.h
@@ -20,6 +20,8 @@
*/
#include "evoral/TimeConverter.hpp"
+#include "evoral/types.hpp"
+
#include "ardour/libardour_visibility.h"
#include "ardour/types.h"
@@ -34,15 +36,35 @@ class TempoMap;
* from some origin (supplied to the constructor in frames), and converts
* them to the opposite unit, taking tempo changes into account.
*/
-class LIBARDOUR_API BeatsFramesConverter : public Evoral::TimeConverter<double,framepos_t> {
+class LIBARDOUR_API BeatsFramesConverter
+ : public Evoral::TimeConverter<Evoral::MusicalTime,framepos_t> {
public:
BeatsFramesConverter (TempoMap& tempo_map, framepos_t origin)
+ : Evoral::TimeConverter<Evoral::MusicalTime, framepos_t> (origin)
+ , _tempo_map(tempo_map)
+ {}
+
+ framepos_t to (Evoral::MusicalTime beats) const;
+ Evoral::MusicalTime from (framepos_t frames) const;
+
+private:
+ TempoMap& _tempo_map;
+};
+
+/** Converter between beats and frames. Takes distances in beats or frames
+ * from some origin (supplied to the constructor in frames), and converts
+ * them to the opposite unit, taking tempo changes into account.
+ */
+class LIBARDOUR_API DoubleBeatsFramesConverter
+ : public Evoral::TimeConverter<double,framepos_t> {
+public:
+ DoubleBeatsFramesConverter (TempoMap& tempo_map, framepos_t origin)
: Evoral::TimeConverter<double, framepos_t> (origin)
, _tempo_map(tempo_map)
{}
- framepos_t to (double beats) const;
- double from (framepos_t frames) const;
+ framepos_t to (double beats) const;
+ double from (framepos_t frames) const;
private:
TempoMap& _tempo_map;
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index dc1c7af0e9..31df5ef040 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -116,16 +116,11 @@ public:
struct NoteChange {
NoteDiffCommand::Property property;
NotePtr note;
- uint32_t note_id;
-
- union {
- uint8_t old_value;
- TimeType old_time;
- };
- union {
- uint8_t new_value;
- TimeType new_time;
- };
+ uint32_t note_id;
+ uint8_t old_value; // or...
+ TimeType old_time; // this
+ uint8_t new_value; // or...
+ TimeType new_time; // this
};
typedef std::list<NoteChange> ChangeList;
@@ -209,16 +204,16 @@ public:
struct Change {
PatchChangePtr patch;
Property property;
- gint patch_id;
+ gint patch_id;
+ TimeType old_time;
union {
- TimeType old_time;
uint8_t old_channel;
int old_bank;
uint8_t old_program;
};
+ TimeType new_time;
union {
uint8_t new_channel;
- TimeType new_time;
uint8_t new_program;
int new_bank;
};
@@ -311,7 +306,5 @@ private:
} /* namespace ARDOUR */
-/* This is a very long comment and stuff oh my god it's so long what are we going to do oh no oh no*/
-
#endif /* __ardour_midi_model_h__ */
diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h
index 38229b998b..2a4e3a6190 100644
--- a/libs/ardour/ardour/midi_region.h
+++ b/libs/ardour/ardour/midi_region.h
@@ -23,6 +23,8 @@
#include <vector>
+#include "evoral/types.hpp"
+
#include "ardour/ardour.h"
#include "ardour/region.h"
diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h
index 65e382c4b7..2ce92ba3cf 100644
--- a/libs/ardour/ardour/midi_source.h
+++ b/libs/ardour/ardour/midi_source.h
@@ -43,7 +43,7 @@ template<typename T> class MidiRingBuffer;
class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_shared_from_this<MidiSource>
{
public:
- typedef double TimeType;
+ typedef Evoral::MusicalTime TimeType;
MidiSource (Session& session, std::string name, Source::Flag flags = Source::Flag(0));
MidiSource (Session& session, const XMLNode&);
@@ -120,7 +120,7 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha
*/
virtual void mark_midi_streaming_write_completed (
Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption stuck_option,
- Evoral::MusicalTime when = 0);
+ Evoral::MusicalTime when = Evoral::MusicalTime());
virtual void session_saved();
@@ -134,8 +134,8 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha
bool length_mutable() const { return true; }
- void set_length_beats(double l) { _length_beats = l; }
- double length_beats() const { return _length_beats; }
+ void set_length_beats(TimeType l) { _length_beats = l; }
+ TimeType length_beats() const { return _length_beats; }
virtual void load_model(bool lock=true, bool force_reload=false) = 0;
virtual void destroy_model() = 0;
@@ -194,8 +194,8 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha
mutable Evoral::Sequence<Evoral::MusicalTime>::const_iterator _model_iter;
mutable bool _model_iter_valid;
- mutable double _length_beats;
- mutable framepos_t _last_read_end;
+ mutable Evoral::MusicalTime _length_beats;
+ mutable framepos_t _last_read_end;
/** The total duration of the current capture. */
framepos_t _capture_length;
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index 84c45f9b3c..1c1f2bbcba 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -56,7 +56,8 @@ public:
void mark_streaming_midi_write_started (NoteMode mode);
void mark_streaming_write_completed ();
- void mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption, Evoral::MusicalTime when = 0);
+ void mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption,
+ Evoral::MusicalTime when = Evoral::MusicalTime());
XMLNode& get_state ();
int set_state (const XMLNode&, int version);
@@ -88,8 +89,8 @@ public:
framepos_t position,
framecnt_t cnt);
- double _last_ev_time_beats;
- framepos_t _last_ev_time_frames;
+ Evoral::MusicalTime _last_ev_time_beats;
+ framepos_t _last_ev_time_frames;
/** end time (start + duration) of last call to read_unlocked */
mutable framepos_t _smf_last_read_end;
/** time (in SMF ticks, 1 tick per _ppqn) of the last event read by read_unlocked */
diff --git a/libs/ardour/beats_frames_converter.cc b/libs/ardour/beats_frames_converter.cc
index 94042b1b03..b99edbf51e 100644
--- a/libs/ardour/beats_frames_converter.cc
+++ b/libs/ardour/beats_frames_converter.cc
@@ -31,26 +31,43 @@ namespace ARDOUR {
* taking tempo changes into account.
*/
framepos_t
-BeatsFramesConverter::to (double beats) const
+BeatsFramesConverter::to (Evoral::MusicalTime beats) const
{
- if (beats < 0) {
+ if (beats < Evoral::MusicalTime()) {
std::cerr << "negative beats passed to BFC: " << beats << std::endl;
PBD::stacktrace (std::cerr, 30);
+ return 0;
}
- assert (beats >= 0);
- framecnt_t r = _tempo_map.framepos_plus_beats (_origin_b, beats) - _origin_b;
- return r;
+ return _tempo_map.framepos_plus_beats (_origin_b, beats) - _origin_b;
}
/** Takes a duration in frames and considers it as a distance from the origin
* supplied to the constructor. Returns the equivalent number of beats,
* taking tempo changes into account.
*/
-double
+Evoral::MusicalTime
BeatsFramesConverter::from (framepos_t frames) const
{
- double b = _tempo_map.framewalk_to_beats (_origin_b, frames);
- return b;
+ return _tempo_map.framewalk_to_beats (_origin_b, frames);
+}
+
+/** As above, but with beats in double instead (for GUI). */
+framepos_t
+DoubleBeatsFramesConverter::to (double beats) const
+{
+ if (beats < 0.0) {
+ std::cerr << "negative beats passed to BFC: " << beats << std::endl;
+ PBD::stacktrace (std::cerr, 30);
+ return 0;
+ }
+ return _tempo_map.framepos_plus_beats (_origin_b, Evoral::MusicalTime(beats)) - _origin_b;
+}
+
+/** As above, but with beats in double instead (for GUI). */
+double
+DoubleBeatsFramesConverter::from (framepos_t frames) const
+{
+ return _tempo_map.framewalk_to_beats (_origin_b, frames).to_double();
}
} /* namespace ARDOUR */
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index ae5f751767..38a3da2fdc 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -389,10 +389,11 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
}
smfs->append_event_unlocked_beats(
- Evoral::Event<double>(0,
- (double)t / (double)source->ppqn(),
- size,
- buf));
+ Evoral::Event<Evoral::MusicalTime>(
+ 0,
+ Evoral::MusicalTime::ticks_at_rate(t, source->ppqn()),
+ size,
+ buf));
if (status.progress < 0.99) {
status.progress += 0.01;
@@ -403,10 +404,10 @@ write_midi_data_to_new_files (Evoral::SMF* source, ImportStatus& status,
/* we wrote something */
- const framepos_t pos = 0;
- const double length_beats = ceil(t / (double)source->ppqn());
- BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
- smfs->update_length(pos + converter.to(length_beats));
+ const framepos_t pos = 0;
+ const Evoral::MusicalTime length_beats = Evoral::MusicalTime::ticks_at_rate(t, source->ppqn());
+ BeatsFramesConverter converter(smfs->session().tempo_map(), pos);
+ smfs->update_length(pos + converter.to(length_beats.round_up_to_beat()));
smfs->mark_streaming_write_completed ();
if (status.cancel) {
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 69eca996aa..40d333d584 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -927,7 +927,7 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
/* set length in beats to entire capture length */
BeatsFramesConverter converter (_session.tempo_map(), capture_info.front()->start);
- const double total_capture_beats = converter.from (total_capture);
+ const Evoral::MusicalTime total_capture_beats = converter.from (total_capture);
_write_source->set_length_beats (total_capture_beats);
/* flush to disk: this step differs from the audio path,
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 259a04bc0f..6c2132562a 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -226,13 +226,13 @@ MidiModel::NoteDiffCommand::change (const NotePtr note, Property prop,
break;
case StartTime:
- if (Evoral::musical_time_equal (note->time(), new_time)) {
+ if (note->time() == new_time) {
return;
}
change.old_time = note->time();
break;
case Length:
- if (Evoral::musical_time_equal (note->length(), new_time)) {
+ if (note->length() == new_time) {
return;
}
change.old_time = note->length();
@@ -556,7 +556,7 @@ MidiModel::NoteDiffCommand::unmarshal_note (XMLNode *xml_note)
time_str >> time;
} else {
warning << "note information missing time" << endmsg;
- time = 0;
+ time = MidiModel::TimeType();
}
if ((prop = xml_note->property("length")) != 0) {
@@ -564,7 +564,7 @@ MidiModel::NoteDiffCommand::unmarshal_note (XMLNode *xml_note)
length_str >> length;
} else {
warning << "note information missing length" << endmsg;
- length = 1;
+ length = MidiModel::TimeType(1);
}
if ((prop = xml_note->property("velocity")) != 0) {
@@ -1253,7 +1253,7 @@ MidiModel::PatchChangeDiffCommand::unmarshal_patch_change (XMLNode* n)
{
XMLProperty* prop;
Evoral::event_id_t id = 0;
- Evoral::MusicalTime time = 0;
+ Evoral::MusicalTime time = Evoral::MusicalTime();
int channel = 0;
int program = 0;
int bank = 0;
@@ -1439,7 +1439,7 @@ MidiModel::write_to (boost::shared_ptr<MidiSource> source)
source->drop_model();
source->mark_streaming_midi_write_started (note_mode());
- for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
+ for (Evoral::Sequence<TimeType>::const_iterator i = begin(TimeType(), true); i != end(); ++i) {
source->append_event_unlocked_beats(*i);
}
@@ -1469,7 +1469,7 @@ MidiModel::sync_to_source ()
ms->mark_streaming_midi_write_started (note_mode());
- for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
+ for (Evoral::Sequence<TimeType>::const_iterator i = begin(TimeType(), true); i != end(); ++i) {
ms->append_event_unlocked_beats(*i);
}
@@ -1503,7 +1503,7 @@ MidiModel::write_section_to (boost::shared_ptr<MidiSource> source, Evoral::Music
source->drop_model();
source->mark_streaming_midi_write_started (note_mode());
- for (Evoral::Sequence<TimeType>::const_iterator i = begin(0, true); i != end(); ++i) {
+ for (Evoral::Sequence<TimeType>::const_iterator i = begin(TimeType(), true); i != end(); ++i) {
const Evoral::Event<Evoral::MusicalTime>& ev (*i);
if (ev.time() >= begin_time && ev.time() < end_time) {
@@ -1662,7 +1662,7 @@ MidiModel::resolve_overlaps_unlocked (const NotePtr note, void* arg)
TimeType ea = note->end_time();
const Pitches& p (pitches (note->channel()));
- NotePtr search_note(new Note<TimeType>(0, 0, 0, note->note()));
+ NotePtr search_note(new Note<TimeType>(0, TimeType(), TimeType(), note->note()));
set<NotePtr> to_be_deleted;
bool set_note_length = false;
bool set_note_time = false;
@@ -1979,7 +1979,7 @@ MidiModel::insert_silence_at_start (TimeType t)
for (Controls::iterator i = controls().begin(); i != controls().end(); ++i) {
boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (i->second);
XMLNode& before = ac->alist()->get_state ();
- i->second->list()->shift (0, t);
+ i->second->list()->shift (0, t.to_double());
XMLNode& after = ac->alist()->get_state ();
s->session().add_command (new MementoCommand<AutomationList> (new MidiAutomationListBinder (s, i->first), &before, &after));
}
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index 71fd796b81..f6631b9de5 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -28,6 +28,8 @@
#include <glibmm/fileutils.h>
#include <glibmm/miscutils.h>
+#include "evoral/types.hpp"
+
#include "pbd/xml++.h"
#include "pbd/basename.h"
@@ -78,7 +80,7 @@ MidiRegion::register_properties ()
/* Basic MidiRegion constructor (many channels) */
MidiRegion::MidiRegion (const SourceList& srcs)
: Region (srcs)
- , _start_beats (Properties::start_beats, 0)
+ , _start_beats (Properties::start_beats, Evoral::MusicalTime())
, _length_beats (Properties::length_beats, midi_source(0)->length_beats())
{
register_properties ();
@@ -92,7 +94,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)
+ , _length_beats (Properties::length_beats, Evoral::MusicalTime())
{
update_length_beats ();
register_properties ();
@@ -105,14 +107,14 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
/** 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)
+ , _start_beats (Properties::start_beats, Evoral::MusicalTime())
+ , _length_beats (Properties::length_beats, Evoral::MusicalTime())
{
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;
+ _start_beats = other->_start_beats.val() + offset_beats;
+ _length_beats = other->_length_beats.val() - offset_beats;
register_properties ();
@@ -216,7 +218,7 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute)
/* zero length regions don't exist - so if _length_beats is zero, this object
is under construction.
*/
- if (_length_beats) {
+ if (_length_beats.val() == Evoral::MusicalTime()) {
/* leave _length_beats alone, and change _length to reflect the state of things
at the new position (tempo map may dictate a different number of frames
*/
@@ -440,7 +442,7 @@ MidiRegion::fix_negative_start ()
model()->insert_silence_at_start (c.from (-_start));
_start = 0;
- _start_beats = 0;
+ _start_beats = Evoral::MusicalTime();
}
/** Transpose the notes in this region by a given number of semitones */
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index 823ca9dc5c..1c050733c2 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -153,13 +153,13 @@ MidiSource::set_state (const XMLNode& node, int /*version*/)
bool
MidiSource::empty () const
{
- return _length_beats == 0;
+ return !_length_beats;
}
framecnt_t
MidiSource::length (framepos_t pos) const
{
- if (_length_beats == 0) {
+ if (!_length_beats) {
return 0;
}
@@ -198,7 +198,7 @@ MidiSource::midi_read (Evoral::EventSink<framepos_t>& dst,
if (_model) {
// Find appropriate model iterator
- Evoral::Sequence<double>::const_iterator& i = _model_iter;
+ Evoral::Sequence<Evoral::MusicalTime>::const_iterator& i = _model_iter;
if (_last_read_end == 0 || start != _last_read_end || !_model_iter_valid) {
// Cached iterator is invalid, search for the first event past start
i = _model->begin(converter.from(start), false, filtered);
diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc
index f006004621..0eac3819f2 100644
--- a/libs/ardour/midi_state_tracker.cc
+++ b/libs/ardour/midi_state_tracker.cc
@@ -173,7 +173,7 @@ MidiStateTracker::resolve_notes (MidiSource& src, Evoral::MusicalTime time)
this, (int) note, (int) channel, time));
_active_notes[note + 128 * channel]--;
/* don't stack events up at the same time */
- time += 1.0/128.0;
+ time += Evoral::MusicalTime::tick();
}
}
}
diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc
index 38cab08ace..f5b3a47b41 100644
--- a/libs/ardour/midi_stretch.cc
+++ b/libs/ardour/midi_stretch.cc
@@ -95,9 +95,9 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*)
/* Note: pass true into force_discrete for the begin() iterator so that the model doesn't
* do interpolation of controller data when we stretch.
*/
- for (Evoral::Sequence<MidiModel::TimeType>::const_iterator i = old_model->begin (0, true);
+ for (Evoral::Sequence<MidiModel::TimeType>::const_iterator i = old_model->begin (MidiModel::TimeType(), true);
i != old_model->end(); ++i) {
- const double new_time = i->time() * _request.time_fraction;
+ const MidiModel::TimeType new_time = i->time() * (double)_request.time_fraction;
// FIXME: double copy
Evoral::Event<MidiModel::TimeType> ev(*i, true);
diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc
index 7da1edaaa1..13b1cf3b36 100644
--- a/libs/ardour/quantize.cc
+++ b/libs/ardour/quantize.cc
@@ -58,6 +58,8 @@ Quantize::operator () (boost::shared_ptr<MidiModel> model,
double position,
std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>& seqs)
{
+ /* TODO: Rewrite this to be precise with fixed point? */
+
/* Calculate offset from start of model to next closest quantize step,
to quantize relative to actual session beats (etc.) rather than from the
start of the model.
@@ -77,8 +79,8 @@ Quantize::operator () (boost::shared_ptr<MidiModel> model,
*/
for (Evoral::Sequence<MidiModel::TimeType>::Notes::iterator i = (*s).begin(); i != (*s).end(); ++i) {
- double new_start = round (((*i)->time() - offset) / _start_grid) * _start_grid + offset;
- double new_end = round (((*i)->end_time() - offset) / _end_grid) * _end_grid + offset;
+ double new_start = round (((*i)->time().to_double() - offset) / _start_grid) * _start_grid + offset;
+ double new_end = round (((*i)->end_time().to_double() - offset) / _end_grid) * _end_grid + offset;
if (_swing > 0.0 && !even) {
@@ -104,18 +106,18 @@ Quantize::operator () (boost::shared_ptr<MidiModel> model,
}
- double delta = new_start - (*i)->time();
+ double delta = new_start - (*i)->time().to_double();
if (fabs (delta) >= _threshold) {
if (_snap_start) {
delta *= _strength;
cmd->change ((*i), MidiModel::NoteDiffCommand::StartTime,
- (*i)->time() + delta);
+ (*i)->time().to_double() + delta);
}
}
if (_snap_end) {
- delta = new_end - (*i)->end_time();
+ delta = new_end - (*i)->end_time().to_double();
if (fabs (delta) >= _threshold) {
double new_dur = new_end - new_start;
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 8a956495a5..1ffcdac1b2 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -225,7 +225,7 @@ SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination,
BeatsFramesConverter converter(_session.tempo_map(), source_start);
- const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
+ const uint64_t start_ticks = converter.from(start).to_ticks();
DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start in ticks %1\n", start_ticks));
if (_smf_last_read_end == 0 || start != _smf_last_read_end) {
@@ -273,7 +273,7 @@ SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination,
/* Note that we add on the source start time (in session frames) here so that ev_frame_time
is in session frames.
*/
- const framepos_t ev_frame_time = converter.to(time / (double)ppqn()) + source_start;
+ const framepos_t ev_frame_time = converter.to(Evoral::MusicalTime::ticks_at_rate(time, ppqn())) + source_start;
if (ev_frame_time < start + duration) {
destination.write (ev_frame_time, ev_type, ev_size, ev_buffer);
@@ -377,9 +377,9 @@ SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source,
return cnt;
}
-/** Append an event with a timestamp in beats (double) */
+/** Append an event with a timestamp in beats */
void
-SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
+SMFSource::append_event_unlocked_beats (const Evoral::Event<Evoral::MusicalTime>& ev)
{
if (!_writing || ev.size() == 0) {
return;
@@ -389,10 +389,10 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
name().c_str(), ev.id(), ev.time(), ev.size());
for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");*/
- double time = ev.time();
+ Evoral::MusicalTime time = ev.time();
if (time < _last_ev_time_beats) {
- const double difference = _last_ev_time_beats - time;
- if (difference / (double)ppqn() < 1.0) {
+ const Evoral::MusicalTime difference = _last_ev_time_beats - time;
+ if (difference.to_double() / (double)ppqn() < 1.0) {
/* Close enough. This problem occurs because Sequence is not
actually ordered due to fuzzy time comparison. I'm pretty sure
this is inherently a bad idea which causes problems all over the
@@ -401,7 +401,7 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
} else {
/* Out of order by more than a tick. */
warning << string_compose(_("Skipping event with unordered beat time %1 < %2 (off by %3 beats, %4 ticks)"),
- ev.time(), _last_ev_time_beats, difference, difference / (double)ppqn())
+ ev.time(), _last_ev_time_beats, difference, difference.to_double() / (double)ppqn())
<< endmsg;
return;
}
@@ -421,8 +421,8 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
_length_beats = max(_length_beats, time);
- const double delta_time_beats = time - _last_ev_time_beats;
- const uint32_t delta_time_ticks = (uint32_t)lrint(delta_time_beats * (double)ppqn());
+ const Evoral::MusicalTime delta_time_beats = time - _last_ev_time_beats;
+ const uint32_t delta_time_ticks = delta_time_beats.to_ticks(ppqn());
Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
_last_ev_time_beats = time;
@@ -448,9 +448,9 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, fr
return;
}
- BeatsFramesConverter converter(_session.tempo_map(), position);
- const double ev_time_beats = converter.from(ev.time());
- Evoral::event_id_t event_id;
+ BeatsFramesConverter converter(_session.tempo_map(), position);
+ const Evoral::MusicalTime ev_time_beats = converter.from(ev.time());
+ Evoral::event_id_t event_id;
if (ev.id() < 0) {
event_id = Evoral::next_event_id();
@@ -459,10 +459,10 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, fr
}
if (_model) {
- const Evoral::Event<double> beat_ev (ev.event_type(),
- ev_time_beats,
- ev.size(),
- const_cast<uint8_t*>(ev.buffer()));
+ const Evoral::Event<Evoral::MusicalTime> beat_ev (ev.event_type(),
+ ev_time_beats,
+ ev.size(),
+ const_cast<uint8_t*>(ev.buffer()));
_model->append (beat_ev, event_id);
}
@@ -470,7 +470,7 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, fr
const Evoral::MusicalTime last_time_beats = converter.from (_last_ev_time_frames);
const Evoral::MusicalTime delta_time_beats = ev_time_beats - last_time_beats;
- const uint32_t delta_time_ticks = (uint32_t)(lrint(delta_time_beats * (double)ppqn()));
+ const uint32_t delta_time_ticks = delta_time_beats.to_ticks(ppqn());
Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
_last_ev_time_frames = ev.time();
@@ -516,7 +516,7 @@ SMFSource::mark_streaming_midi_write_started (NoteMode mode)
MidiSource::mark_streaming_midi_write_started (mode);
Evoral::SMF::begin_write ();
- _last_ev_time_beats = 0.0;
+ _last_ev_time_beats = Evoral::MusicalTime();
_last_ev_time_frames = 0;
}
@@ -586,8 +586,8 @@ SMFSource::safe_midi_file_extension (const string& file)
}
static bool compare_eventlist (
- const std::pair< Evoral::Event<double>*, gint >& a,
- const std::pair< Evoral::Event<double>*, gint >& b) {
+ const std::pair< Evoral::Event<Evoral::MusicalTime>*, gint >& a,
+ const std::pair< Evoral::Event<Evoral::MusicalTime>*, gint >& b) {
return ( a.first->time() < b.first->time() );
}
@@ -620,7 +620,7 @@ SMFSource::load_model (bool lock, bool force_reload)
Evoral::SMF::seek_to_start();
uint64_t time = 0; /* in SMF ticks */
- Evoral::Event<double> ev;
+ Evoral::Event<Evoral::MusicalTime> ev;
uint32_t scratch_size = 0; // keep track of scratch and minimize reallocs
@@ -632,7 +632,7 @@ SMFSource::load_model (bool lock, bool force_reload)
bool have_event_id;
// TODO simplify event allocation
- std::list< std::pair< Evoral::Event<double>*, gint > > eventlist;
+ std::list< std::pair< Evoral::Event<Evoral::MusicalTime>*, gint > > eventlist;
for (unsigned i = 1; i <= num_tracks(); ++i) {
if (seek_to_track(i)) continue;
@@ -658,8 +658,8 @@ SMFSource::load_model (bool lock, bool force_reload)
if (!have_event_id) {
event_id = Evoral::next_event_id();
}
- uint32_t event_type = midi_parameter_type(buf[0]);
- double event_time = time / (double) ppqn();
+ const uint32_t event_type = midi_parameter_type(buf[0]);
+ const Evoral::MusicalTime event_time = Evoral::MusicalTime::ticks_at_rate(time, ppqn());
#ifndef NDEBUG
std::string ss;
@@ -674,7 +674,7 @@ SMFSource::load_model (bool lock, bool force_reload)
#endif
eventlist.push_back(make_pair (
- new Evoral::Event<double> (
+ new Evoral::Event<Evoral::MusicalTime> (
event_type, event_time,
size, buf, true)
, event_id));
@@ -693,7 +693,7 @@ SMFSource::load_model (bool lock, bool force_reload)
eventlist.sort(compare_eventlist);
- std::list< std::pair< Evoral::Event<double>*, gint > >::iterator it;
+ std::list< std::pair< Evoral::Event<Evoral::MusicalTime>*, gint > >::iterator it;
for (it=eventlist.begin(); it!=eventlist.end(); ++it) {
_model->append (*it->first, it->second);
delete it->first;
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 57bf9fe674..1767c8100d 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -1891,10 +1891,11 @@ TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats) const
framecnt_t distance_frames = (next_tempo == metrics.end() ? max_framepos : ((*next_tempo)->frame() - pos));
/* Distance to the end in beats */
- Evoral::MusicalTime distance_beats = distance_frames / tempo->frames_per_beat (_frame_rate);
+ Evoral::MusicalTime distance_beats = Evoral::MusicalTime::ticks_at_rate(
+ distance_frames, tempo->frames_per_beat (_frame_rate));
/* Amount to subtract this time */
- double const delta = min (distance_beats, beats);
+ Evoral::MusicalTime const delta = min (distance_beats, beats);
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("\tdistance to %1 = %2 (%3 beats)\n",
(next_tempo == metrics.end() ? max_framepos : (*next_tempo)->frame()),
@@ -1902,7 +1903,7 @@ TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats) const
/* Update */
beats -= delta;
- pos += delta * tempo->frames_per_beat (_frame_rate);
+ pos += delta.to_ticks(tempo->frames_per_beat (_frame_rate));
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("\tnow at %1, %2 beats left\n", pos, beats));
@@ -1999,10 +2000,11 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const
framecnt_t distance_frames = (pos - tempo->frame());
/* Distance to the start in beats */
- Evoral::MusicalTime distance_beats = distance_frames / tempo->frames_per_beat (_frame_rate);
+ Evoral::MusicalTime distance_beats = Evoral::MusicalTime::ticks_at_rate(
+ distance_frames, tempo->frames_per_beat (_frame_rate));
/* Amount to subtract this time */
- double const sub = min (distance_beats, beats);
+ Evoral::MusicalTime const sub = min (distance_beats, beats);
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("\tdistance to %1 = %2 (%3 beats)\n",
tempo->frame(), distance_frames, distance_beats));
@@ -2035,7 +2037,7 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const
}
} else {
pos -= llrint (beats * tempo->frames_per_beat (_frame_rate));
- beats = 0;
+ beats = Evoral::MusicalTime();
}
}
@@ -2216,7 +2218,7 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
string_compose ("frame %1 walk by %2 frames, start with tempo = %3 @ %4\n",
pos, distance, *((const Tempo*)tempo), tempo->frame()));
- Evoral::MusicalTime beats = 0;
+ Evoral::MusicalTime beats = Evoral::MusicalTime();
while (distance) {
@@ -2234,8 +2236,8 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
distance_to_end = end - pos;
}
- /* Amount to subtract this time */
- double const sub = min (distance, distance_to_end);
+ /* Amount to subtract this time in frames */
+ framecnt_t const sub = min (distance, distance_to_end);
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("to reach end at %1 (end ? %2), distance= %3 sub=%4\n", end, (next_tempo == metrics.end()),
distance_to_end, sub));
@@ -2244,7 +2246,7 @@ TempoMap::framewalk_to_beats (framepos_t pos, framecnt_t distance) const
pos += sub;
distance -= sub;
assert (tempo);
- beats += sub / tempo->frames_per_beat (_frame_rate);
+ beats += Evoral::MusicalTime::ticks_at_rate(sub, tempo->frames_per_beat (_frame_rate));
DEBUG_TRACE (DEBUG::TempoMath, string_compose ("now at %1, beats = %2 distance left %3\n",
pos, beats, distance));
diff --git a/libs/ardour/test/framepos_minus_beats_test.cc b/libs/ardour/test/framepos_minus_beats_test.cc
index 01bafc1606..e4c4844146 100644
--- a/libs/ardour/test/framepos_minus_beats_test.cc
+++ b/libs/ardour/test/framepos_minus_beats_test.cc
@@ -7,6 +7,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION (FrameposMinusBeatsTest);
using namespace std;
using namespace ARDOUR;
using namespace Timecode;
+using namespace Evoral;
/* Basic tests with no tempo / meter changes */
void
@@ -25,11 +26,11 @@ FrameposMinusBeatsTest::singleTempoTest ()
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);
+ framepos_t r = map.framepos_minus_beats (frames_per_beat * 2, MusicalTime(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);
+ r = map.framepos_minus_beats (frames_per_beat * 3, MusicalTime(4));
CPPUNIT_ASSERT_EQUAL (r, framepos_t (- frames_per_beat));
}
@@ -69,15 +70,15 @@ FrameposMinusBeatsTest::doubleTempoTest ()
/* Now some tests */
/* Subtract 1 beat from 1|2 */
- framepos_t r = map.framepos_minus_beats (24e3, 1);
+ framepos_t r = map.framepos_minus_beats (24e3, MusicalTime(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);
+ r = map.framepos_minus_beats (288e3 + 12e3, MusicalTime(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);
+ r = map.framepos_minus_beats (288e3 + 12e3, MusicalTime(2.5));
CPPUNIT_ASSERT_EQUAL (r, framepos_t (288e3 - 24e3 - 12e3));
}
@@ -123,15 +124,15 @@ FrameposMinusBeatsTest::doubleTempoWithMeterTest ()
/* Now some tests */
/* Subtract 1 beat from 1|2 */
- framepos_t r = map.framepos_minus_beats (24e3, 1);
+ framepos_t r = map.framepos_minus_beats (24e3, MusicalTime(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);
+ r = map.framepos_minus_beats (288e3 + 12e3, MusicalTime(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);
+ r = map.framepos_minus_beats (288e3 + 12e3, MusicalTime(2.5));
CPPUNIT_ASSERT_EQUAL (r, framepos_t (288e3 - 24e3 - 12e3));
}
diff --git a/libs/ardour/test/framepos_plus_beats_test.cc b/libs/ardour/test/framepos_plus_beats_test.cc
index c95c2a7a66..abe1310f62 100644
--- a/libs/ardour/test/framepos_plus_beats_test.cc
+++ b/libs/ardour/test/framepos_plus_beats_test.cc
@@ -25,11 +25,11 @@ FrameposPlusBeatsTest::singleTempoTest ()
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);
+ framepos_t r = map.framepos_plus_beats (frames_per_beat * 2, Evoral::MusicalTime(1));
CPPUNIT_ASSERT_EQUAL (framepos_t (frames_per_beat * 3), r);
/* Add 4 beats to a -ve frame of 1 beat before zero */
- r = map.framepos_plus_beats (-frames_per_beat * 1, 4);
+ r = map.framepos_plus_beats (-frames_per_beat * 1, Evoral::MusicalTime(4));
CPPUNIT_ASSERT_EQUAL (framepos_t (frames_per_beat * 3), r);
}
@@ -69,15 +69,15 @@ FrameposPlusBeatsTest::doubleTempoTest ()
/* Now some tests */
/* Add 1 beat to 1|2 */
- framepos_t r = map.framepos_plus_beats (24e3, 1);
+ framepos_t r = map.framepos_plus_beats (24e3, Evoral::MusicalTime(1));
CPPUNIT_ASSERT_EQUAL (framepos_t (48e3), r);
/* Add 2 beats to 3|4 (over the tempo change) */
- r = map.framepos_plus_beats (264e3, 2);
+ r = map.framepos_plus_beats (264e3, Evoral::MusicalTime(2));
CPPUNIT_ASSERT_EQUAL (framepos_t (264e3 + 24e3 + 12e3), r);
/* Add 2.5 beats to 3|3|960 (over the tempo change) */
- r = map.framepos_plus_beats (264e3 - 12e3, 2.5);
+ r = map.framepos_plus_beats (264e3 - 12e3, Evoral::MusicalTime(2.5));
CPPUNIT_ASSERT_EQUAL (framepos_t (264e3 + 24e3 + 12e3), r);
}
@@ -123,15 +123,15 @@ FrameposPlusBeatsTest::doubleTempoWithMeterTest ()
/* Now some tests */
/* Add 1 beat to 1|2 */
- framepos_t r = map.framepos_plus_beats (24e3, 1);
+ framepos_t r = map.framepos_plus_beats (24e3, Evoral::MusicalTime(1));
CPPUNIT_ASSERT_EQUAL (framepos_t (48e3), r);
/* Add 2 beats to 3|4 (over the tempo change) */
- r = map.framepos_plus_beats (264e3, 2);
+ r = map.framepos_plus_beats (264e3, Evoral::MusicalTime(2));
CPPUNIT_ASSERT_EQUAL (framepos_t (264e3 + 24e3 + 12e3), r);
/* Add 2.5 beats to 3|3|960 (over the tempo change) */
- r = map.framepos_plus_beats (264e3 - 12e3, 2.5);
+ r = map.framepos_plus_beats (264e3 - 12e3, Evoral::MusicalTime(2.5));
CPPUNIT_ASSERT_EQUAL (framepos_t (264e3 + 24e3 + 12e3), r);
}