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.
This commit is contained in:
parent
cae74309a5
commit
c1cfa12d6e
|
@ -54,11 +54,11 @@ public:
|
|||
float times,
|
||||
boost::shared_ptr<const ARDOUR::AutomationList> slist);
|
||||
|
||||
ARDOUR::BeatsFramesConverter const & region_relative_time_converter () const {
|
||||
ARDOUR::DoubleBeatsFramesConverter const & region_relative_time_converter () const {
|
||||
return _region_relative_time_converter;
|
||||
}
|
||||
|
||||
ARDOUR::BeatsFramesConverter const & source_relative_time_converter () const {
|
||||
ARDOUR::DoubleBeatsFramesConverter const & source_relative_time_converter () const {
|
||||
return _source_relative_time_converter;
|
||||
}
|
||||
|
||||
|
@ -83,10 +83,10 @@ protected:
|
|||
void exited();
|
||||
|
||||
private:
|
||||
ARDOUR::BeatsFramesConverter _region_relative_time_converter;
|
||||
ARDOUR::BeatsFramesConverter _source_relative_time_converter;
|
||||
Evoral::Parameter _parameter;
|
||||
boost::shared_ptr<AutomationLine> _line;
|
||||
ARDOUR::DoubleBeatsFramesConverter _region_relative_time_converter;
|
||||
ARDOUR::DoubleBeatsFramesConverter _source_relative_time_converter;
|
||||
Evoral::Parameter _parameter;
|
||||
boost::shared_ptr<AutomationLine> _line;
|
||||
};
|
||||
|
||||
#endif /* __gtk_ardour_automation_region_view_h__ */
|
||||
|
|
|
@ -193,7 +193,7 @@ EditNoteDialog::done (int r)
|
|||
}
|
||||
}
|
||||
|
||||
double const t = _region_view->source_relative_time_converter().from (_time_clock.current_time ());
|
||||
Evoral::MusicalTime const t = _region_view->source_relative_time_converter().from (_time_clock.current_time ());
|
||||
|
||||
if (!_time_all.get_sensitive() || _time_all.get_active ()) {
|
||||
for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||
|
@ -204,7 +204,7 @@ EditNoteDialog::done (int r)
|
|||
}
|
||||
}
|
||||
|
||||
double const d = _region_view->region_relative_time_converter().from (_length_clock.current_duration ());
|
||||
Evoral::MusicalTime const d = _region_view->region_relative_time_converter().from (_length_clock.current_duration ());
|
||||
|
||||
if (!_length_all.get_sensitive() || _length_all.get_active ()) {
|
||||
for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
|
||||
|
|
|
@ -3901,64 +3901,64 @@ Editor::get_grid_type_as_beats (bool& success, framepos_t position)
|
|||
|
||||
switch (_snap_type) {
|
||||
case SnapToBeat:
|
||||
return 1.0;
|
||||
return Evoral::MusicalTime(1.0);
|
||||
break;
|
||||
|
||||
case SnapToBeatDiv128:
|
||||
return 1.0/128.0;
|
||||
return Evoral::MusicalTime(1.0/128.0);
|
||||
break;
|
||||
case SnapToBeatDiv64:
|
||||
return 1.0/64.0;
|
||||
return Evoral::MusicalTime(1.0/64.0);
|
||||
break;
|
||||
case SnapToBeatDiv32:
|
||||
return 1.0/32.0;
|
||||
return Evoral::MusicalTime(1.0/32.0);
|
||||
break;
|
||||
case SnapToBeatDiv28:
|
||||
return 1.0/28.0;
|
||||
return Evoral::MusicalTime(1.0/28.0);
|
||||
break;
|
||||
case SnapToBeatDiv24:
|
||||
return 1.0/24.0;
|
||||
return Evoral::MusicalTime(1.0/24.0);
|
||||
break;
|
||||
case SnapToBeatDiv20:
|
||||
return 1.0/20.0;
|
||||
return Evoral::MusicalTime(1.0/20.0);
|
||||
break;
|
||||
case SnapToBeatDiv16:
|
||||
return 1.0/16.0;
|
||||
return Evoral::MusicalTime(1.0/16.0);
|
||||
break;
|
||||
case SnapToBeatDiv14:
|
||||
return 1.0/14.0;
|
||||
return Evoral::MusicalTime(1.0/14.0);
|
||||
break;
|
||||
case SnapToBeatDiv12:
|
||||
return 1.0/12.0;
|
||||
return Evoral::MusicalTime(1.0/12.0);
|
||||
break;
|
||||
case SnapToBeatDiv10:
|
||||
return 1.0/10.0;
|
||||
return Evoral::MusicalTime(1.0/10.0);
|
||||
break;
|
||||
case SnapToBeatDiv8:
|
||||
return 1.0/8.0;
|
||||
return Evoral::MusicalTime(1.0/8.0);
|
||||
break;
|
||||
case SnapToBeatDiv7:
|
||||
return 1.0/7.0;
|
||||
return Evoral::MusicalTime(1.0/7.0);
|
||||
break;
|
||||
case SnapToBeatDiv6:
|
||||
return 1.0/6.0;
|
||||
return Evoral::MusicalTime(1.0/6.0);
|
||||
break;
|
||||
case SnapToBeatDiv5:
|
||||
return 1.0/5.0;
|
||||
return Evoral::MusicalTime(1.0/5.0);
|
||||
break;
|
||||
case SnapToBeatDiv4:
|
||||
return 1.0/4.0;
|
||||
return Evoral::MusicalTime(1.0/4.0);
|
||||
break;
|
||||
case SnapToBeatDiv3:
|
||||
return 1.0/3.0;
|
||||
return Evoral::MusicalTime(1.0/3.0);
|
||||
break;
|
||||
case SnapToBeatDiv2:
|
||||
return 1.0/2.0;
|
||||
return Evoral::MusicalTime(1.0/2.0);
|
||||
break;
|
||||
|
||||
case SnapToBar:
|
||||
if (_session) {
|
||||
return _session->tempo_map().meter_at (position).divisions_per_bar();
|
||||
return Evoral::MusicalTime(_session->tempo_map().meter_at (position).divisions_per_bar());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -3977,7 +3977,7 @@ Editor::get_grid_type_as_beats (bool& success, framepos_t position)
|
|||
break;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
return Evoral::MusicalTime();
|
||||
}
|
||||
|
||||
framecnt_t
|
||||
|
|
|
@ -5220,7 +5220,7 @@ NoteCreateDrag::grid_frames (framepos_t t) const
|
|||
bool success;
|
||||
Evoral::MusicalTime grid_beats = _editor->get_grid_type_as_beats (success, t);
|
||||
if (!success) {
|
||||
grid_beats = 1;
|
||||
grid_beats = Evoral::MusicalTime(1);
|
||||
}
|
||||
|
||||
return _region_view->region_beats_to_region_frames (grid_beats);
|
||||
|
@ -5276,13 +5276,13 @@ NoteCreateDrag::finished (GdkEvent*, bool had_movement)
|
|||
framecnt_t length = (framecnt_t) fabs ((double)(_note[0] - _note[1]));
|
||||
|
||||
framecnt_t const g = grid_frames (start);
|
||||
double const one_tick = 1 / Timecode::BBT_Time::ticks_per_beat;
|
||||
Evoral::MusicalTime const one_tick = Evoral::MusicalTime::ticks(1);
|
||||
|
||||
if (_editor->snap_mode() == SnapNormal && length < g) {
|
||||
length = g - one_tick;
|
||||
}
|
||||
|
||||
double const length_beats = max (one_tick, _region_view->region_frames_to_region_beats (length));
|
||||
Evoral::MusicalTime const length_beats = max (one_tick, _region_view->region_frames_to_region_beats (length));
|
||||
|
||||
_region_view->create_note_at (start, _drag_rect->y0(), length_beats, false);
|
||||
}
|
||||
|
|
|
@ -4988,7 +4988,7 @@ Editor::insert_patch_change (bool from_context)
|
|||
*/
|
||||
MidiRegionView* first = dynamic_cast<MidiRegionView*> (rs.front ());
|
||||
|
||||
Evoral::PatchChange<Evoral::MusicalTime> empty (0, 0, 0, 0);
|
||||
Evoral::PatchChange<Evoral::MusicalTime> empty (Evoral::MusicalTime(), 0, 0, 0);
|
||||
PatchChangeDialog d (0, _session, empty, first->instrument_info(), Gtk::Stock::ADD);
|
||||
|
||||
if (d.run() == RESPONSE_CANCEL) {
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace ArdourCanvas {
|
|||
class Hit : public NoteBase
|
||||
{
|
||||
public:
|
||||
typedef Evoral::Note<double> NoteType;
|
||||
typedef Evoral::Note<Evoral::MusicalTime> NoteType;
|
||||
|
||||
Hit (MidiRegionView& region,
|
||||
ArdourCanvas::Item* parent,
|
||||
|
|
|
@ -550,7 +550,7 @@ MidiRegionView::button_release (GdkEventButton* ev)
|
|||
/* Shorten the length by 1 tick so that we can add a new note at the next
|
||||
grid snap without it overlapping this one.
|
||||
*/
|
||||
beats -= 1.0 / Timecode::BBT_Time::ticks_per_beat;
|
||||
beats -= Evoral::MusicalTime::tick();
|
||||
|
||||
create_note_at (editor.pixel_to_sample (event_x), event_y, beats, true);
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ MidiRegionView::button_release (GdkEventButton* ev)
|
|||
/* Shorten the length by 1 tick so that we can add a new note at the next
|
||||
grid snap without it overlapping this one.
|
||||
*/
|
||||
beats -= 1.0 / Timecode::BBT_Time::ticks_per_beat;
|
||||
beats -= Evoral::MusicalTime::tick();
|
||||
|
||||
create_note_at (editor.pixel_to_sample (event_x), event_y, beats, true);
|
||||
|
||||
|
@ -728,7 +728,7 @@ MidiRegionView::key_press (GdkEventKey* ev)
|
|||
bool shorter = Keyboard::modifier_state_contains (ev->state, Keyboard::PrimaryModifier);
|
||||
bool fine = Keyboard::modifier_state_contains (ev->state, Keyboard::SecondaryModifier);
|
||||
|
||||
change_note_lengths (fine, shorter, 0.0, start, end);
|
||||
change_note_lengths (fine, shorter, Evoral::MusicalTime(), start, end);
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -909,7 +909,7 @@ MidiRegionView::show_list_editor ()
|
|||
* \param snap_t true to snap t to the grid, otherwise false.
|
||||
*/
|
||||
void
|
||||
MidiRegionView::create_note_at (framepos_t t, double y, double length, bool snap_t)
|
||||
MidiRegionView::create_note_at (framepos_t t, double y, Evoral::MusicalTime length, bool snap_t)
|
||||
{
|
||||
if (length < 2 * DBL_EPSILON) {
|
||||
return;
|
||||
|
@ -1521,7 +1521,7 @@ MidiRegionView::end_write()
|
|||
/** Resolve an active MIDI note (while recording).
|
||||
*/
|
||||
void
|
||||
MidiRegionView::resolve_note(uint8_t note, double end_time)
|
||||
MidiRegionView::resolve_note(uint8_t note, Evoral::MusicalTime end_time)
|
||||
{
|
||||
if (midi_view()->note_mode() != Sustained) {
|
||||
return;
|
||||
|
@ -1660,7 +1660,7 @@ MidiRegionView::update_note (Note* ev, bool update_ghost_regions)
|
|||
|
||||
ev->set_y1 (y0 + std::max(1., floor(midi_stream_view()->note_height()) - 1));
|
||||
|
||||
if (note->length() == 0) {
|
||||
if (!note->length()) {
|
||||
if (_active_notes && note->note() < 128) {
|
||||
// If this note is already active there's a stuck note,
|
||||
// finish the old note rectangle
|
||||
|
@ -1862,7 +1862,7 @@ patch_applies (const ARDOUR::MidiModel::constPatchChangePtr pc, double time, uin
|
|||
}
|
||||
|
||||
void
|
||||
MidiRegionView::get_patch_key_at (double time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const
|
||||
MidiRegionView::get_patch_key_at (Evoral::MusicalTime time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const
|
||||
{
|
||||
// The earliest event not before time
|
||||
MidiModel::PatchChanges::iterator i = _model->patch_change_lower_bound (time);
|
||||
|
@ -2260,7 +2260,7 @@ MidiRegionView::note_selected (NoteBase* ev, bool add, bool extend)
|
|||
/* find end of latest note selected, select all between that and the start of "ev" */
|
||||
|
||||
Evoral::MusicalTime earliest = Evoral::MaxMusicalTime;
|
||||
Evoral::MusicalTime latest = 0;
|
||||
Evoral::MusicalTime latest = Evoral::MusicalTime();
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||
if ((*i)->note()->end_time() > latest) {
|
||||
|
@ -2421,7 +2421,7 @@ MidiRegionView::move_selection(double dx, double dy, double cumulative_dy)
|
|||
}
|
||||
|
||||
for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
|
||||
if (Evoral::musical_time_equal ((*i)->note()->time(), earliest)) {
|
||||
if ((*i)->note()->time() == earliest) {
|
||||
to_play.push_back ((*i)->note());
|
||||
}
|
||||
(*i)->move_event(dx, dy);
|
||||
|
@ -2548,7 +2548,7 @@ MidiRegionView::get_end_position_pixels()
|
|||
}
|
||||
|
||||
framepos_t
|
||||
MidiRegionView::source_beats_to_absolute_frames(double beats) const
|
||||
MidiRegionView::source_beats_to_absolute_frames(Evoral::MusicalTime beats) const
|
||||
{
|
||||
/* the time converter will return the frame corresponding to `beats'
|
||||
relative to the start of the source. The start of the source
|
||||
|
@ -2558,7 +2558,7 @@ MidiRegionView::source_beats_to_absolute_frames(double beats) const
|
|||
return source_start + _source_relative_time_converter.to (beats);
|
||||
}
|
||||
|
||||
double
|
||||
Evoral::MusicalTime
|
||||
MidiRegionView::absolute_frames_to_source_beats(framepos_t frames) const
|
||||
{
|
||||
/* the `frames' argument needs to be converted into a frame count
|
||||
|
@ -2570,12 +2570,12 @@ MidiRegionView::absolute_frames_to_source_beats(framepos_t frames) const
|
|||
}
|
||||
|
||||
framepos_t
|
||||
MidiRegionView::region_beats_to_region_frames(double beats) const
|
||||
MidiRegionView::region_beats_to_region_frames(Evoral::MusicalTime beats) const
|
||||
{
|
||||
return _region_relative_time_converter.to(beats);
|
||||
}
|
||||
|
||||
double
|
||||
Evoral::MusicalTime
|
||||
MidiRegionView::region_frames_to_region_beats(framepos_t frames) const
|
||||
{
|
||||
return _region_relative_time_converter.from(frames);
|
||||
|
@ -2827,8 +2827,8 @@ MidiRegionView::trim_note (NoteBase* event, Evoral::MusicalTime front_delta, Evo
|
|||
{
|
||||
bool change_start = false;
|
||||
bool change_length = false;
|
||||
Evoral::MusicalTime new_start = 0;
|
||||
Evoral::MusicalTime new_length = 0;
|
||||
Evoral::MusicalTime new_start;
|
||||
Evoral::MusicalTime new_length;
|
||||
|
||||
/* NOTE: the semantics of the two delta arguments are slightly subtle:
|
||||
|
||||
|
@ -2843,7 +2843,7 @@ MidiRegionView::trim_note (NoteBase* event, Evoral::MusicalTime front_delta, Evo
|
|||
if (front_delta < 0) {
|
||||
|
||||
if (event->note()->time() < -front_delta) {
|
||||
new_start = 0;
|
||||
new_start = Evoral::MusicalTime();
|
||||
} else {
|
||||
new_start = event->note()->time() + front_delta; // moves earlier
|
||||
}
|
||||
|
@ -2924,7 +2924,7 @@ MidiRegionView::change_note_time (NoteBase* event, Evoral::MusicalTime delta, bo
|
|||
if (relative) {
|
||||
if (delta < 0.0) {
|
||||
if (event->note()->time() < -delta) {
|
||||
new_time = 0;
|
||||
new_time = Evoral::MusicalTime();
|
||||
} else {
|
||||
new_time = event->note()->time() + delta;
|
||||
}
|
||||
|
@ -3053,9 +3053,9 @@ MidiRegionView::transpose (bool up, bool fine, bool allow_smush)
|
|||
void
|
||||
MidiRegionView::change_note_lengths (bool fine, bool shorter, Evoral::MusicalTime delta, bool start, bool end)
|
||||
{
|
||||
if (delta == 0.0) {
|
||||
if (!delta) {
|
||||
if (fine) {
|
||||
delta = 1.0/128.0;
|
||||
delta = Evoral::MusicalTime(1.0/128.0);
|
||||
} else {
|
||||
/* grab the current grid distance */
|
||||
delta = get_grid_beats(_region->position());
|
||||
|
@ -3074,7 +3074,9 @@ MidiRegionView::change_note_lengths (bool fine, bool shorter, Evoral::MusicalTim
|
|||
|
||||
/* note the negation of the delta for start */
|
||||
|
||||
trim_note (*i, (start ? -delta : 0), (end ? delta : 0));
|
||||
trim_note (*i,
|
||||
(start ? -delta : Evoral::MusicalTime()),
|
||||
(end ? delta : Evoral::MusicalTime()));
|
||||
i = next;
|
||||
}
|
||||
|
||||
|
@ -3402,10 +3404,10 @@ MidiRegionView::paste_internal (framepos_t pos, unsigned paste_count, float time
|
|||
const Evoral::MusicalTime first_time = (*mcb.notes().begin())->time();
|
||||
const Evoral::MusicalTime last_time = (*mcb.notes().rbegin())->end_time();
|
||||
const Evoral::MusicalTime duration = last_time - first_time;
|
||||
const Evoral::MusicalTime snap_duration = ceil(duration / snap_beats) * snap_beats;
|
||||
const Evoral::MusicalTime paste_offset = paste_count * snap_duration;
|
||||
const Evoral::MusicalTime snap_duration = duration.snap_to(snap_beats);
|
||||
const Evoral::MusicalTime paste_offset = snap_duration * paste_count;
|
||||
const Evoral::MusicalTime pos_beats = absolute_frames_to_source_beats(pos) + paste_offset;
|
||||
Evoral::MusicalTime end_point = 0;
|
||||
Evoral::MusicalTime end_point = Evoral::MusicalTime();
|
||||
|
||||
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste data spans from %1 to %2 (%3) ; paste pos beats = %4 (based on %5 - %6)\n",
|
||||
first_time,
|
||||
|
@ -3585,7 +3587,8 @@ MidiRegionView::update_ghost_note (double x, double y)
|
|||
the start of the source; that is how all note times are stored.
|
||||
*/
|
||||
_ghost_note->note()->set_time (
|
||||
std::max(0.0, absolute_frames_to_source_beats (f + _region->position ())));
|
||||
std::max(Evoral::MusicalTime(),
|
||||
absolute_frames_to_source_beats (f + _region->position ())));
|
||||
_ghost_note->note()->set_length (length);
|
||||
_ghost_note->note()->set_note (midi_stream_view()->y_to_note (y));
|
||||
_ghost_note->note()->set_channel (mtv->get_channel_for_add ());
|
||||
|
@ -3786,7 +3789,7 @@ MidiRegionView::data_recorded (boost::weak_ptr<MidiSource> w)
|
|||
|
||||
if (ev.type() == MIDI_CMD_NOTE_ON) {
|
||||
boost::shared_ptr<NoteType> note (
|
||||
new NoteType (ev.channel(), time_beats, 0, ev.note(), ev.velocity()));
|
||||
new NoteType (ev.channel(), time_beats, Evoral::MusicalTime(), ev.note(), ev.velocity()));
|
||||
|
||||
add_note (note, true);
|
||||
|
||||
|
@ -3969,7 +3972,7 @@ MidiRegionView::get_grid_beats(framepos_t pos) const
|
|||
bool success = false;
|
||||
Evoral::MusicalTime beats = editor.get_grid_type_as_beats(success, pos);
|
||||
if (!success) {
|
||||
beats = 1;
|
||||
beats = Evoral::MusicalTime(1);
|
||||
}
|
||||
return beats;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ public:
|
|||
GhostRegion* add_ghost (TimeAxisView&);
|
||||
|
||||
void add_note(const boost::shared_ptr<NoteType> note, bool visible);
|
||||
void resolve_note(uint8_t note_num, double end_time);
|
||||
void resolve_note(uint8_t note_num, Evoral::MusicalTime end_time);
|
||||
|
||||
void cut_copy_clear (Editing::CutCopyOp);
|
||||
bool paste (framepos_t pos, unsigned paste_count, float times, const ::Selection& selection, ItemCounts& counts);
|
||||
|
@ -124,7 +124,7 @@ public:
|
|||
* @key a reference to an instance of MIDI::Name::PatchPrimaryKey whose fields will
|
||||
* will be set according to the result of the lookup
|
||||
*/
|
||||
void get_patch_key_at (double time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const;
|
||||
void get_patch_key_at (Evoral::MusicalTime time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key) const;
|
||||
|
||||
/** Convert a given PatchChange into a PatchPrimaryKey
|
||||
*/
|
||||
|
@ -258,22 +258,22 @@ public:
|
|||
framepos_t snap_pixel_to_sample(double x);
|
||||
|
||||
/** Convert a timestamp in beats into frames (both relative to region position) */
|
||||
framepos_t region_beats_to_region_frames(double beats) const;
|
||||
framepos_t region_beats_to_region_frames(Evoral::MusicalTime beats) const;
|
||||
/** Convert a timestamp in beats into absolute frames */
|
||||
framepos_t region_beats_to_absolute_frames(double beats) const {
|
||||
framepos_t region_beats_to_absolute_frames(Evoral::MusicalTime beats) const {
|
||||
return _region->position() + region_beats_to_region_frames (beats);
|
||||
}
|
||||
/** Convert a timestamp in frames to beats (both relative to region position) */
|
||||
double region_frames_to_region_beats(framepos_t) const;
|
||||
Evoral::MusicalTime region_frames_to_region_beats(framepos_t) const;
|
||||
|
||||
/** Convert a timestamp in beats measured from source start into absolute frames */
|
||||
framepos_t source_beats_to_absolute_frames(double beats) const;
|
||||
framepos_t source_beats_to_absolute_frames(Evoral::MusicalTime beats) const;
|
||||
/** Convert a timestamp in beats measured from source start into region-relative frames */
|
||||
framepos_t source_beats_to_region_frames(double beats) const {
|
||||
framepos_t source_beats_to_region_frames(Evoral::MusicalTime beats) const {
|
||||
return source_beats_to_absolute_frames (beats) - _region->position();
|
||||
}
|
||||
/** Convert a timestamp in absolute frames to beats measured from source start*/
|
||||
double absolute_frames_to_source_beats(framepos_t) const;
|
||||
Evoral::MusicalTime absolute_frames_to_source_beats(framepos_t) const;
|
||||
|
||||
ARDOUR::BeatsFramesConverter const & region_relative_time_converter () const {
|
||||
return _region_relative_time_converter;
|
||||
|
@ -309,7 +309,13 @@ public:
|
|||
void trim_front_starting ();
|
||||
void trim_front_ending ();
|
||||
|
||||
void create_note_at (framepos_t, double, double, bool);
|
||||
/** Add a note to the model, and the view, at a canvas (click) coordinate.
|
||||
* \param t time in frames relative to the position of the region
|
||||
* \param y vertical position in pixels
|
||||
* \param length duration of the note in beats
|
||||
* \param snap_t true to snap t to the grid, otherwise false.
|
||||
*/
|
||||
void create_note_at (framepos_t t, double y, Evoral::MusicalTime length, bool snap_t);
|
||||
|
||||
void clear_selection (bool signal = true) { clear_selection_except (0, signal); }
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ PatchChangeDialog::instrument_info_changed ()
|
|||
Evoral::PatchChange<Evoral::MusicalTime>
|
||||
PatchChangeDialog::patch () const
|
||||
{
|
||||
Evoral::MusicalTime t = 0;
|
||||
Evoral::MusicalTime t = Evoral::MusicalTime();
|
||||
|
||||
if (_time_converter) {
|
||||
t = _time_converter->from (_time.current_time ());
|
||||
|
|
|
@ -41,7 +41,7 @@ StepEditor::StepEditor (PublicEditor& e, boost::shared_ptr<MidiTrack> t, MidiTim
|
|||
step_edit_insert_position = 0;
|
||||
_step_edit_triplet_countdown = 0;
|
||||
_step_edit_within_chord = 0;
|
||||
_step_edit_chord_duration = 0.0;
|
||||
_step_edit_chord_duration = Evoral::MusicalTime();
|
||||
step_edit_region_view = 0;
|
||||
|
||||
_track->PlaylistChanged.connect (*this, invalidator (*this),
|
||||
|
@ -60,11 +60,11 @@ StepEditor::start_step_editing ()
|
|||
{
|
||||
_step_edit_triplet_countdown = 0;
|
||||
_step_edit_within_chord = 0;
|
||||
_step_edit_chord_duration = 0.0;
|
||||
_step_edit_chord_duration = Evoral::MusicalTime();
|
||||
step_edit_region.reset ();
|
||||
step_edit_region_view = 0;
|
||||
last_added_pitch = -1;
|
||||
last_added_end = 0;
|
||||
last_added_end = Evoral::MusicalTime();
|
||||
|
||||
resync_step_edit_position ();
|
||||
prepare_step_edit_region ();
|
||||
|
@ -198,7 +198,7 @@ StepEditor::check_step_edit ()
|
|||
incoming.read_contents (size, buf);
|
||||
|
||||
if ((buf[0] & 0xf0) == MIDI_CMD_NOTE_ON) {
|
||||
step_add_note (buf[0] & 0xf, buf[1], buf[2], 0.0);
|
||||
step_add_note (buf[0] & 0xf, buf[1], buf[2], Evoral::MusicalTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ StepEditor::move_step_edit_beat_pos (Evoral::MusicalTime beats)
|
|||
if (-beats < step_edit_beat_pos) {
|
||||
step_edit_beat_pos += beats; // its negative, remember
|
||||
} else {
|
||||
step_edit_beat_pos = 0;
|
||||
step_edit_beat_pos = Evoral::MusicalTime();
|
||||
}
|
||||
}
|
||||
step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos);
|
||||
|
@ -292,8 +292,8 @@ StepEditor::step_add_note (uint8_t channel, uint8_t pitch, uint8_t velocity, Evo
|
|||
up by 1 tick from where the last note ended
|
||||
*/
|
||||
|
||||
at += 1.0/Timecode::BBT_Time::ticks_per_beat;
|
||||
len -= 1.0/Timecode::BBT_Time::ticks_per_beat;
|
||||
at += Evoral::MusicalTime::ticks(1);
|
||||
len -= Evoral::MusicalTime::ticks(1);
|
||||
}
|
||||
|
||||
step_edit_region_view->step_add_note (channel, pitch, velocity, at, len);
|
||||
|
@ -313,7 +313,7 @@ StepEditor::step_add_note (uint8_t channel, uint8_t pitch, uint8_t velocity, Evo
|
|||
step_edit_beat_pos += beat_duration;
|
||||
step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos);
|
||||
} else {
|
||||
step_edit_beat_pos += 1.0/Timecode::BBT_Time::ticks_per_beat; // tiny, but no longer overlapping
|
||||
step_edit_beat_pos += Evoral::MusicalTime::ticks(1); // tiny, but no longer overlapping
|
||||
_step_edit_chord_duration = max (_step_edit_chord_duration, beat_duration);
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ StepEditor::step_edit_rest (Evoral::MusicalTime beats)
|
|||
void
|
||||
StepEditor::step_edit_beat_sync ()
|
||||
{
|
||||
step_edit_beat_pos = ceil (step_edit_beat_pos);
|
||||
step_edit_beat_pos = step_edit_beat_pos.round_up_to_beat();
|
||||
step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos);
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ StepEditor::step_edit_bar_sync ()
|
|||
|
||||
framepos_t fpos = step_edit_region_view->region_beats_to_absolute_frames (step_edit_beat_pos);
|
||||
fpos = _session->tempo_map().round_to_bar (fpos, RoundUpAlways);
|
||||
step_edit_beat_pos = ceil (step_edit_region_view->region_frames_to_region_beats (fpos - step_edit_region->position()));
|
||||
step_edit_beat_pos = step_edit_region_view->region_frames_to_region_beats (fpos - step_edit_region->position()).round_up_to_beat();
|
||||
step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos);
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ StepEditor::region_removed (boost::weak_ptr<Region> wr)
|
|||
step_edit_region.reset();
|
||||
step_edit_region_view = 0;
|
||||
// force a recompute of the insert position
|
||||
step_edit_beat_pos = -1.0;
|
||||
step_edit_beat_pos = Evoral::MusicalTime(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -526,13 +526,13 @@ StepEntry::on_key_release_event (GdkEventKey* ev)
|
|||
void
|
||||
StepEntry::rest_event_handler ()
|
||||
{
|
||||
se->step_edit_rest (0.0);
|
||||
se->step_edit_rest (Evoral::MusicalTime());
|
||||
}
|
||||
|
||||
Evoral::MusicalTime
|
||||
StepEntry::note_length ()
|
||||
{
|
||||
Evoral::MusicalTime base_time = 4.0 / (Evoral::MusicalTime) length_divisor_adjustment.get_value();
|
||||
double base_time = 4.0 / (double) length_divisor_adjustment.get_value();
|
||||
|
||||
RefPtr<Action> act = myactions.find_action ("StepEditing/toggle-triplet");
|
||||
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic (act);
|
||||
|
@ -549,7 +549,7 @@ StepEntry::note_length ()
|
|||
base_time *= 1 + ((dots - 1.0)/dots);
|
||||
}
|
||||
|
||||
return base_time;
|
||||
return Evoral::MusicalTime(base_time);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
|
@ -795,7 +795,7 @@ StepEntry::insert_rest ()
|
|||
void
|
||||
StepEntry::insert_grid_rest ()
|
||||
{
|
||||
se->step_edit_rest (0.0);
|
||||
se->step_edit_rest (Evoral::MusicalTime());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "evoral/types.hpp"
|
||||
|
||||
#include "ardour/ardour.h"
|
||||
#include "ardour/region.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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ template<typename Time>
|
|||
class LIBEVORAL_API Event {
|
||||
public:
|
||||
#ifdef EVORAL_EVENT_ALLOC
|
||||
Event (EventType type=0, Time time=0, uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
|
||||
Event (EventType type=0, Time time=Time(), uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
|
||||
|
||||
/** Copy \a copy.
|
||||
*
|
||||
|
@ -114,11 +114,11 @@ public:
|
|||
}
|
||||
|
||||
inline void clear() {
|
||||
_type = 0;
|
||||
_original_time = 0;
|
||||
_nominal_time = 0;
|
||||
_size = 0;
|
||||
_buf = NULL;
|
||||
_type = 0;
|
||||
_original_time = Time();
|
||||
_nominal_time = Time();
|
||||
_size = 0;
|
||||
_buf = NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -154,9 +154,6 @@ protected:
|
|||
#endif
|
||||
};
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
|
||||
template<typename Time>
|
||||
/*LIBEVORAL_API*/ std::ostream& operator<<(std::ostream& o, const Evoral::Event<Time>& ev) {
|
||||
o << "Event #" << ev.id() << " type = " << ev.event_type() << " @ " << ev.time();
|
||||
|
@ -168,6 +165,7 @@ template<typename Time>
|
|||
return o;
|
||||
}
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
#endif // EVORAL_EVENT_HPP
|
||||
|
||||
|
|
|
@ -39,16 +39,16 @@ class LIBEVORAL_LOCAL Note {
|
|||
class LIBEVORAL_TEMPLATE_API Note {
|
||||
#endif
|
||||
public:
|
||||
Note(uint8_t chan=0, Time time=0, Time len=0, uint8_t note=0, uint8_t vel=0x40);
|
||||
Note(uint8_t chan=0, Time time=Time(), Time len=Time(), uint8_t note=0, uint8_t vel=0x40);
|
||||
Note(const Note<Time>& copy);
|
||||
~Note();
|
||||
|
||||
const Note<Time>& operator=(const Note<Time>& copy);
|
||||
|
||||
inline bool operator==(const Note<Time>& other) {
|
||||
return musical_time_equal (time(), other.time()) &&
|
||||
return time() == other.time() &&
|
||||
note() == other.note() &&
|
||||
musical_time_equal (length(), other.length()) &&
|
||||
length() == other.length() &&
|
||||
velocity() == other.velocity() &&
|
||||
off_velocity() == other.off_velocity() &&
|
||||
channel() == other.channel();
|
||||
|
@ -109,8 +109,6 @@ private:
|
|||
MIDIEvent<Time> _off_event;
|
||||
};
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
template<typename Time>
|
||||
/*LIBEVORAL_API*/ std::ostream& operator<<(std::ostream& o, const Evoral::Note<Time>& n) {
|
||||
o << "Note #" << n.id() << ": pitch = " << (int) n.note()
|
||||
|
@ -120,6 +118,8 @@ template<typename Time>
|
|||
return o;
|
||||
}
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
#ifdef COMPILER_MSVC
|
||||
#include "../src/Note.impl"
|
||||
#endif
|
||||
|
|
|
@ -120,7 +120,7 @@ public:
|
|||
uint8_t channel () const { return _program_change.buffer()[0] & 0xf; }
|
||||
|
||||
inline bool operator< (const PatchChange<Time>& o) const {
|
||||
if (!musical_time_equal (time(), o.time())) {
|
||||
if (time() != o.time()) {
|
||||
return time() < o.time();
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ public:
|
|||
}
|
||||
|
||||
inline bool operator== (const PatchChange<Time>& o) const {
|
||||
return (musical_time_equal (time(), o.time()) && program() == o.program() && bank() == o.bank());
|
||||
return (time() == o.time() && program() == o.program() && bank() == o.bank());
|
||||
}
|
||||
|
||||
/** The PatchChange is made up of messages() MIDI messages; this method returns them by index.
|
||||
|
|
|
@ -105,7 +105,7 @@ public:
|
|||
ResolveStuckNotes
|
||||
};
|
||||
|
||||
void end_write (StuckNoteOption, Time when = 0);
|
||||
void end_write (StuckNoteOption, Time when = Time());
|
||||
|
||||
void append(const Event<Time>& ev, Evoral::event_id_t evid);
|
||||
|
||||
|
@ -127,7 +127,7 @@ public:
|
|||
struct EarlierNoteComparator {
|
||||
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
||||
const boost::shared_ptr< const Note<Time> > b) const {
|
||||
return musical_time_less_than (a->time(), b->time());
|
||||
return a->time() < b->time();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -135,7 +135,7 @@ public:
|
|||
typedef const Note<Time>* value_type;
|
||||
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
||||
const boost::shared_ptr< const Note<Time> > b) const {
|
||||
return musical_time_greater_than (a->time(), b->time());
|
||||
return a->time() > b->time();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -143,7 +143,7 @@ public:
|
|||
typedef const Note<Time>* value_type;
|
||||
inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
|
||||
const boost::shared_ptr< const Note<Time> > b) const {
|
||||
return musical_time_greater_than (a->end_time(), b->end_time());
|
||||
return a->end_time() > b->end_time();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -187,7 +187,7 @@ public:
|
|||
|
||||
struct EarlierSysExComparator {
|
||||
inline bool operator() (constSysExPtr a, constSysExPtr b) const {
|
||||
return musical_time_less_than (a->time(), b->time());
|
||||
return a->time() < b->time();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -200,7 +200,7 @@ public:
|
|||
|
||||
struct EarlierPatchChangeComparator {
|
||||
inline bool operator() (constPatchChangePtr a, constPatchChangePtr b) const {
|
||||
return musical_time_less_than (a->time(), b->time());
|
||||
return a->time() < b->time();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -262,7 +262,7 @@ public:
|
|||
};
|
||||
|
||||
const_iterator begin (
|
||||
Time t = 0,
|
||||
Time t = Time(),
|
||||
bool force_discrete = false,
|
||||
std::set<Evoral::Parameter> const & f = std::set<Evoral::Parameter> ()) const {
|
||||
return const_iterator (*this, t, force_discrete, f);
|
||||
|
|
|
@ -19,15 +19,18 @@
|
|||
#ifndef EVORAL_TYPES_HPP
|
||||
#define EVORAL_TYPES_HPP
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
#include <cmath>
|
||||
#include <cfloat>
|
||||
|
||||
#include "pbd/debug.h"
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
|
||||
#include "evoral/visibility.h"
|
||||
|
||||
#include "pbd/debug.h"
|
||||
|
||||
namespace Evoral {
|
||||
|
||||
/** ID of an event (note or other). This must be operable on by glib
|
||||
|
@ -36,47 +39,174 @@ namespace Evoral {
|
|||
typedef int32_t event_id_t;
|
||||
|
||||
/** Musical time: beats relative to some defined origin */
|
||||
typedef double MusicalTime;
|
||||
class LIBEVORAL_API MusicalTime {
|
||||
public:
|
||||
MusicalTime() : _time(0.0) {}
|
||||
|
||||
const MusicalTime MaxMusicalTime = DBL_MAX;
|
||||
const MusicalTime MinMusicalTime = DBL_MIN;
|
||||
/** Create from a real number of beats. */
|
||||
explicit MusicalTime(double time) : _time(time) {}
|
||||
|
||||
static inline bool musical_time_equal (MusicalTime a, MusicalTime b) {
|
||||
/* acceptable tolerance is 1 tick. Nice if there was no magic number here
|
||||
* -> Timecode::BBT_Time::ticks_per_beat */
|
||||
return fabs (a - b) <= (1.0/1920.0);
|
||||
}
|
||||
|
||||
static inline bool musical_time_less_than (MusicalTime a, MusicalTime b) {
|
||||
/* acceptable tolerance is 1 tick. Nice if there was no magic number here */
|
||||
if (fabs (a - b) <= (1.0/1920.0)) {
|
||||
return false; /* effectively identical */
|
||||
} else {
|
||||
return a < b;
|
||||
/** Create from an integer number of beats. */
|
||||
static MusicalTime beats(int32_t beats) {
|
||||
return MusicalTime((double)beats);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool musical_time_greater_than (MusicalTime a, MusicalTime b) {
|
||||
/* acceptable tolerance is 1 tick. Nice if there was no magic number here */
|
||||
if (fabs (a - b) <= (1.0/1920.0)) {
|
||||
return false; /* effectively identical */
|
||||
} else {
|
||||
return a > b;
|
||||
/** Create from ticks at the standard PPQN. */
|
||||
static MusicalTime ticks(uint32_t ticks) {
|
||||
return MusicalTime(ticks / _ppqn);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool musical_time_greater_or_equal_to (MusicalTime a, MusicalTime b) {
|
||||
/* acceptable tolerance is 1 tick. Nice if there was no magic number here */
|
||||
if (fabs (a - b) <= (1.0/1920.0)) {
|
||||
return true; /* effectively identical, note the "or_equal_to" */
|
||||
} else {
|
||||
return a >= b;
|
||||
/** Create from ticks at a given rate.
|
||||
*
|
||||
* Note this can also be used to create from frames by setting ppqn to the
|
||||
* number of samples per beat.
|
||||
*/
|
||||
static MusicalTime ticks_at_rate(uint64_t ticks, uint32_t ppqn) {
|
||||
return MusicalTime((double)ticks / (double)ppqn);
|
||||
}
|
||||
}
|
||||
|
||||
MusicalTime& operator=(const MusicalTime& other) {
|
||||
_time = other._time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MusicalTime round_up_to_beat() const {
|
||||
return Evoral::MusicalTime(ceil(_time));
|
||||
}
|
||||
|
||||
MusicalTime round_down_to_beat() const {
|
||||
return Evoral::MusicalTime(floor(_time));
|
||||
}
|
||||
|
||||
MusicalTime snap_to(const Evoral::MusicalTime& snap) const {
|
||||
return MusicalTime(ceil(_time / snap._time) * snap._time);
|
||||
}
|
||||
|
||||
inline bool operator==(const MusicalTime& b) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
return fabs(_time - b._time) <= (1.0/_ppqn);
|
||||
}
|
||||
|
||||
inline bool operator==(double t) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
return fabs(_time - t) <= (1.0/_ppqn);
|
||||
}
|
||||
|
||||
inline bool operator==(int beats) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
return fabs(_time - beats) <= (1.0/_ppqn);
|
||||
}
|
||||
|
||||
inline bool operator!=(const MusicalTime& b) const {
|
||||
return !operator==(b);
|
||||
}
|
||||
|
||||
inline bool operator<(const MusicalTime& b) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
if (fabs(_time - b._time) <= (1.0/_ppqn)) {
|
||||
return false; /* Effectively identical. */
|
||||
} else {
|
||||
return _time < b._time;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator<=(const MusicalTime& b) const {
|
||||
return operator==(b) || operator<(b);
|
||||
}
|
||||
|
||||
inline bool operator>(const MusicalTime& b) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
if (fabs(_time - b._time) <= (1.0/_ppqn)) {
|
||||
return false; /* Effectively identical. */
|
||||
} else {
|
||||
return _time > b._time;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator>=(const MusicalTime& b) const {
|
||||
/* Acceptable tolerance is 1 tick. */
|
||||
if (fabs(_time - b._time) <= (1.0/_ppqn)) {
|
||||
return true; /* Effectively identical. */
|
||||
} else {
|
||||
return _time >= b._time;
|
||||
}
|
||||
}
|
||||
|
||||
MusicalTime operator+(const MusicalTime& b) const {
|
||||
return MusicalTime(_time + b._time);
|
||||
}
|
||||
|
||||
MusicalTime operator-(const MusicalTime& b) const {
|
||||
return MusicalTime(_time - b._time);
|
||||
}
|
||||
|
||||
MusicalTime operator-() const {
|
||||
return MusicalTime(-_time);
|
||||
}
|
||||
|
||||
template<typename Number>
|
||||
MusicalTime operator*(Number factor) const {
|
||||
return MusicalTime(_time * factor);
|
||||
}
|
||||
|
||||
MusicalTime& operator+=(const MusicalTime& b) {
|
||||
_time += b._time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MusicalTime& operator-=(const MusicalTime& b) {
|
||||
_time -= b._time;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double to_double() const { return _time; }
|
||||
uint64_t to_ticks() const { return lrint(_time * _ppqn); }
|
||||
uint64_t to_ticks(uint32_t ppqn) const { return lrint(_time * ppqn); }
|
||||
|
||||
operator bool() const { return _time != 0; }
|
||||
|
||||
static MusicalTime min() { return MusicalTime(DBL_MIN); }
|
||||
static MusicalTime max() { return MusicalTime(DBL_MAX); }
|
||||
static MusicalTime tick() { return MusicalTime(1.0 / _ppqn); }
|
||||
|
||||
private:
|
||||
static const double _ppqn = 1920.0; /* TODO: Make configurable. */
|
||||
|
||||
double _time;
|
||||
};
|
||||
|
||||
const MusicalTime MaxMusicalTime = Evoral::MusicalTime::max();
|
||||
const MusicalTime MinMusicalTime = Evoral::MusicalTime::min();
|
||||
|
||||
/** Type of an event (opaque, mapped by application) */
|
||||
typedef uint32_t EventType;
|
||||
|
||||
/*
|
||||
TIL, several horrible hours later, that sometimes the compiler looks in the
|
||||
namespace of a type (Evoral::MusicalTime in this case) for an operator, and
|
||||
does *NOT* look in the global namespace.
|
||||
|
||||
C++ is proof that hell exists and we are living in it. In any case, move
|
||||
these to the global namespace and PBD::Property's loopy
|
||||
virtual-method-in-a-template will bite you.
|
||||
*/
|
||||
|
||||
inline std::ostream&
|
||||
operator<<(std::ostream& os, const MusicalTime& t)
|
||||
{
|
||||
os << t.to_double();
|
||||
return os;
|
||||
}
|
||||
|
||||
inline std::istream&
|
||||
operator>>(std::istream& is, MusicalTime& t)
|
||||
{
|
||||
double beats;
|
||||
is >> beats;
|
||||
t = MusicalTime(beats);
|
||||
return is;
|
||||
}
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
namespace PBD {
|
||||
|
@ -84,7 +214,16 @@ namespace PBD {
|
|||
LIBEVORAL_API extern uint64_t Sequence;
|
||||
LIBEVORAL_API extern uint64_t Note;
|
||||
LIBEVORAL_API extern uint64_t ControlList;
|
||||
LIBEVORAL_API extern uint64_t MusicalTime;
|
||||
}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct numeric_limits<Evoral::MusicalTime> {
|
||||
static Evoral::MusicalTime min() { return Evoral::MusicalTime::min(); }
|
||||
static Evoral::MusicalTime max() { return Evoral::MusicalTime::max(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif // EVORAL_TYPES_HPP
|
||||
|
|
|
@ -156,6 +156,7 @@ Event<Timestamp>::set_original_time (Timestamp t)
|
|||
#endif // EVORAL_EVENT_ALLOC
|
||||
|
||||
template class Event<Evoral::MusicalTime>;
|
||||
template class Event<double>;
|
||||
template class Event<int64_t>;
|
||||
|
||||
} // namespace Evoral
|
||||
|
|
|
@ -39,8 +39,8 @@ Note<Time>::Note(uint8_t chan, Time t, Time l, uint8_t n, uint8_t v)
|
|||
_off_event.buffer()[1] = n;
|
||||
_off_event.buffer()[2] = 0x40;
|
||||
|
||||
assert(musical_time_equal (time(),t));
|
||||
assert(musical_time_equal (length(), l));
|
||||
assert(time() == t);
|
||||
assert(length() == l);
|
||||
assert(note() == n);
|
||||
assert(velocity() == v);
|
||||
assert(_on_event.channel() == _off_event.channel());
|
||||
|
@ -67,9 +67,9 @@ Note<Time>::Note(const Note<Time>& copy)
|
|||
memcpy(_off_event_buffer, copy._off_event_buffer, 3);
|
||||
*/
|
||||
|
||||
assert(musical_time_equal (time(),copy.time()));
|
||||
assert(musical_time_equal (end_time(), copy.end_time()));
|
||||
assert(musical_time_equal (length(), copy.length()));
|
||||
assert(time() == copy.time());
|
||||
assert(end_time() == copy.end_time());
|
||||
assert(length() == copy.length());
|
||||
assert(note() == copy.note());
|
||||
assert(velocity() == copy.velocity());
|
||||
assert(_on_event.channel() == _off_event.channel());
|
||||
|
@ -95,9 +95,9 @@ Note<Time>::operator=(const Note<Time>& other)
|
|||
_on_event = other._on_event;
|
||||
_off_event = other._off_event;
|
||||
|
||||
assert(musical_time_equal (time(),other.time()));
|
||||
assert(musical_time_equal (end_time(), other.end_time()));
|
||||
assert(musical_time_equal (length(), other.length()));
|
||||
assert(time() == other.time());
|
||||
assert(end_time() == other.end_time());
|
||||
assert(length() == other.length());
|
||||
assert(note() == other.note());
|
||||
assert(velocity() == other.velocity());
|
||||
assert(_on_event.channel() == _off_event.channel());
|
||||
|
|
|
@ -129,9 +129,9 @@ Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t
|
|||
double x, y;
|
||||
bool ret;
|
||||
if (_force_discrete || i->second->list()->interpolation() == ControlList::Discrete) {
|
||||
ret = i->second->list()->rt_safe_earliest_event_discrete_unlocked (t, x, y, true);
|
||||
ret = i->second->list()->rt_safe_earliest_event_discrete_unlocked (t.to_double(), x, y, true);
|
||||
} else {
|
||||
ret = i->second->list()->rt_safe_earliest_event_unlocked(t, x, y, true);
|
||||
ret = i->second->list()->rt_safe_earliest_event_unlocked(t.to_double(), x, y, true);
|
||||
}
|
||||
if (!ret) {
|
||||
DEBUG_TRACE (DEBUG::Sequence, string_compose ("Iterator: CC %1 (size %2) has no events past %3\n",
|
||||
|
@ -188,10 +188,10 @@ Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t
|
|||
}
|
||||
|
||||
if (_control_iter != _control_iters.end()
|
||||
&& earliest_control.list && earliest_control.x >= t
|
||||
&& (earliest_control.x < earliest_t || _type == NIL)) {
|
||||
&& earliest_control.list && earliest_control.x >= t.to_double()
|
||||
&& (earliest_control.x < earliest_t.to_double() || _type == NIL)) {
|
||||
_type = CONTROL;
|
||||
earliest_t = earliest_control.x;
|
||||
earliest_t = Time(earliest_control.x);
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
|
@ -357,9 +357,9 @@ Sequence<Time>::const_iterator::operator++()
|
|||
|
||||
// Use the next earliest controller iff it's earlier than the note event
|
||||
if (_control_iter != _control_iters.end() && _control_iter->x != DBL_MAX) {
|
||||
if (_type == NIL || _control_iter->x < earliest_t) {
|
||||
if (_type == NIL || _control_iter->x < earliest_t.to_double()) {
|
||||
_type = CONTROL;
|
||||
earliest_t = _control_iter->x;
|
||||
earliest_t = Time(_control_iter->x);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,7 +470,7 @@ Sequence<Time>::Sequence(const TypeMap& type_map)
|
|||
, _overlap_pitch_resolution (FirstOnFirstOff)
|
||||
, _writing(false)
|
||||
, _type_map(type_map)
|
||||
, _end_iter(*this, DBL_MAX, false, std::set<Evoral::Parameter> ())
|
||||
, _end_iter(*this, std::numeric_limits<Time>::max(), false, std::set<Evoral::Parameter> ())
|
||||
, _percussive(false)
|
||||
, _lowest_note(127)
|
||||
, _highest_note(0)
|
||||
|
@ -492,7 +492,7 @@ Sequence<Time>::Sequence(const Sequence<Time>& other)
|
|||
, _overlap_pitch_resolution (other._overlap_pitch_resolution)
|
||||
, _writing(false)
|
||||
, _type_map(other._type_map)
|
||||
, _end_iter(*this, DBL_MAX, false, std::set<Evoral::Parameter> ())
|
||||
, _end_iter(*this, std::numeric_limits<Time>::max(), false, std::set<Evoral::Parameter> ())
|
||||
, _percussive(other._percussive)
|
||||
, _lowest_note(other._lowest_note)
|
||||
, _highest_note(other._highest_note)
|
||||
|
@ -537,7 +537,7 @@ Sequence<Time>::control_to_midi_event(
|
|||
|
||||
// initialize the event pointer with a new event, if necessary
|
||||
if (!ev) {
|
||||
ev = boost::shared_ptr< Event<Time> >(new Event<Time>(event_type, 0, 3, NULL, true));
|
||||
ev = boost::shared_ptr< Event<Time> >(new Event<Time>(event_type, Time(), 3, NULL, true));
|
||||
}
|
||||
|
||||
uint8_t midi_type = _type_map.parameter_midi_type(iter.list->parameter());
|
||||
|
@ -549,7 +549,7 @@ Sequence<Time>::control_to_midi_event(
|
|||
assert(iter.list->parameter().id() <= INT8_MAX);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev->set_time(iter.x);
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(3);
|
||||
ev->buffer()[0] = MIDI_CMD_CONTROL + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = (uint8_t)iter.list->parameter().id();
|
||||
|
@ -561,7 +561,7 @@ Sequence<Time>::control_to_midi_event(
|
|||
assert(iter.list->parameter().channel() < 16);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev->set_time(iter.x);
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(2);
|
||||
ev->buffer()[0] = MIDI_CMD_PGM_CHANGE + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = (uint8_t)iter.y;
|
||||
|
@ -572,7 +572,7 @@ Sequence<Time>::control_to_midi_event(
|
|||
assert(iter.list->parameter().channel() < 16);
|
||||
assert(iter.y < (1<<14));
|
||||
|
||||
ev->set_time(iter.x);
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(3);
|
||||
ev->buffer()[0] = MIDI_CMD_BENDER + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = uint16_t(iter.y) & 0x7F; // LSB
|
||||
|
@ -584,7 +584,7 @@ Sequence<Time>::control_to_midi_event(
|
|||
assert(iter.list->parameter().channel() < 16);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev->set_time(iter.x);
|
||||
ev->set_time(Time(iter.x));
|
||||
ev->realloc(2);
|
||||
ev->buffer()[0] = MIDI_CMD_CHANNEL_PRESSURE + iter.list->parameter().channel();
|
||||
ev->buffer()[1] = (uint8_t)iter.y;
|
||||
|
@ -653,7 +653,7 @@ Sequence<Time>::end_write (StuckNoteOption option, Time when)
|
|||
typename Notes::iterator next = n;
|
||||
++next;
|
||||
|
||||
if ((*n)->length() == 0) {
|
||||
if (!(*n)->length()) {
|
||||
switch (option) {
|
||||
case Relax:
|
||||
break;
|
||||
|
@ -737,7 +737,7 @@ Sequence<Time>::remove_note_unlocked(const constNotePtr note)
|
|||
|
||||
typename Sequence<Time>::Notes::iterator i;
|
||||
|
||||
for (i = note_lower_bound(note->time()); i != _notes.end() && musical_time_equal ((*i)->time(), note->time()); ++i) {
|
||||
for (i = note_lower_bound(note->time()); i != _notes.end() && (*i)->time() == note->time(); ++i) {
|
||||
|
||||
if (*i == note) {
|
||||
|
||||
|
@ -832,7 +832,7 @@ Sequence<Time>::remove_note_unlocked(const constNotePtr note)
|
|||
* so the search_note has all other properties unset.
|
||||
*/
|
||||
|
||||
NotePtr search_note (new Note<Time>(0, 0, 0, note->note(), 0));
|
||||
NotePtr search_note (new Note<Time>(0, Time(), Time(), note->note(), 0));
|
||||
|
||||
for (j = p.lower_bound (search_note); j != p.end() && (*j)->note() == note->note(); ++j) {
|
||||
|
||||
|
@ -861,7 +861,7 @@ Sequence<Time>::remove_patch_change_unlocked (const constPatchChangePtr p)
|
|||
{
|
||||
typename Sequence<Time>::PatchChanges::iterator i = patch_change_lower_bound (p->time ());
|
||||
|
||||
while (i != _patch_changes.end() && (musical_time_equal ((*i)->time(), p->time()))) {
|
||||
while (i != _patch_changes.end() && ((*i)->time() == p->time())) {
|
||||
|
||||
typename Sequence<Time>::PatchChanges::iterator tmp = i;
|
||||
++tmp;
|
||||
|
@ -906,7 +906,7 @@ Sequence<Time>::append(const Event<Time>& event, event_id_t evid)
|
|||
|
||||
const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
|
||||
|
||||
assert(_notes.empty() || musical_time_greater_or_equal_to(ev.time(), (*_notes.rbegin())->time()));
|
||||
assert(_notes.empty() || ev.time() >= (*_notes.rbegin())->time());
|
||||
assert(_writing);
|
||||
|
||||
if (!midi_event_is_valid(ev.buffer(), ev.size())) {
|
||||
|
@ -915,10 +915,10 @@ Sequence<Time>::append(const Event<Time>& event, event_id_t evid)
|
|||
}
|
||||
|
||||
if (ev.is_note_on()) {
|
||||
NotePtr note(new Note<Time>(ev.channel(), ev.time(), 0, ev.note(), ev.velocity()));
|
||||
NotePtr note(new Note<Time>(ev.channel(), ev.time(), Time(), ev.note(), ev.velocity()));
|
||||
append_note_on_unlocked (note, evid);
|
||||
} else if (ev.is_note_off()) {
|
||||
NotePtr note(new Note<Time>(ev.channel(), ev.time(), 0, ev.note(), ev.velocity()));
|
||||
NotePtr note(new Note<Time>(ev.channel(), ev.time(), Time(), ev.note(), ev.velocity()));
|
||||
/* XXX note: event ID is discarded because we merge the on+off events into
|
||||
a single note object
|
||||
*/
|
||||
|
@ -1053,7 +1053,7 @@ Sequence<Time>::append_note_off_unlocked (NotePtr note)
|
|||
|
||||
NotePtr nn = *n;
|
||||
if (note->note() == nn->note() && nn->channel() == note->channel()) {
|
||||
assert(musical_time_greater_or_equal_to(note->time(), nn->time()));
|
||||
assert(note->time() >= nn->time());
|
||||
|
||||
nn->set_length (note->time() - nn->time());
|
||||
nn->set_off_velocity (note->velocity());
|
||||
|
@ -1080,7 +1080,7 @@ Sequence<Time>::append_control_unlocked(const Parameter& param, Time time, doubl
|
|||
DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 %2 @ %3 = %4 # controls: %5\n",
|
||||
this, _type_map.to_symbol(param), time, value, _controls.size()));
|
||||
boost::shared_ptr<Control> c = control(param, true);
|
||||
c->list()->add (time, value);
|
||||
c->list()->add (time.to_double(), value);
|
||||
/* XXX control events should use IDs */
|
||||
}
|
||||
|
||||
|
@ -1148,7 +1148,7 @@ bool
|
|||
Sequence<Time>::contains_unlocked (const NotePtr& note) const
|
||||
{
|
||||
const Pitches& p (pitches (note->channel()));
|
||||
NotePtr search_note(new Note<Time>(0, 0, 0, note->note()));
|
||||
NotePtr search_note(new Note<Time>(0, Time(), Time(), note->note()));
|
||||
|
||||
for (typename Pitches::const_iterator i = p.lower_bound (search_note);
|
||||
i != p.end() && (*i)->note() == note->note(); ++i) {
|
||||
|
@ -1177,7 +1177,7 @@ Sequence<Time>::overlaps_unlocked (const NotePtr& note, const NotePtr& without)
|
|||
Time ea = note->end_time();
|
||||
|
||||
const Pitches& p (pitches (note->channel()));
|
||||
NotePtr search_note(new Note<Time>(0, 0, 0, note->note()));
|
||||
NotePtr search_note(new Note<Time>(0, Time(), Time(), note->note()));
|
||||
|
||||
for (typename Pitches::const_iterator i = p.lower_bound (search_note);
|
||||
i != p.end() && (*i)->note() == note->note(); ++i) {
|
||||
|
@ -1214,9 +1214,9 @@ template<typename Time>
|
|||
typename Sequence<Time>::Notes::const_iterator
|
||||
Sequence<Time>::note_lower_bound (Time t) const
|
||||
{
|
||||
NotePtr search_note(new Note<Time>(0, t, 0, 0, 0));
|
||||
NotePtr search_note(new Note<Time>(0, t, Time(), 0, 0));
|
||||
typename Sequence<Time>::Notes::const_iterator i = _notes.lower_bound(search_note);
|
||||
assert(i == _notes.end() || musical_time_greater_or_equal_to((*i)->time(), t));
|
||||
assert(i == _notes.end() || (*i)->time() >= t);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1227,7 +1227,7 @@ Sequence<Time>::patch_change_lower_bound (Time t) const
|
|||
{
|
||||
PatchChangePtr search (new PatchChange<Time> (t, 0, 0, 0));
|
||||
typename Sequence<Time>::PatchChanges::const_iterator i = _patch_changes.lower_bound (search);
|
||||
assert (i == _patch_changes.end() || musical_time_greater_or_equal_to ((*i)->time(), t));
|
||||
assert (i == _patch_changes.end() || (*i)->time() >= t);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1238,7 +1238,7 @@ Sequence<Time>::sysex_lower_bound (Time t) const
|
|||
{
|
||||
SysExPtr search (new Event<Time> (0, t));
|
||||
typename Sequence<Time>::SysExes::const_iterator i = _sysexes.lower_bound (search);
|
||||
assert (i == _sysexes.end() || musical_time_greater_or_equal_to((*i)->time(), t));
|
||||
assert (i == _sysexes.end() || (*i)->time() >= t);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1249,9 +1249,9 @@ template<typename Time>
|
|||
typename Sequence<Time>::Notes::iterator
|
||||
Sequence<Time>::note_lower_bound (Time t)
|
||||
{
|
||||
NotePtr search_note(new Note<Time>(0, t, 0, 0, 0));
|
||||
NotePtr search_note(new Note<Time>(0, t, Time(), 0, 0));
|
||||
typename Sequence<Time>::Notes::iterator i = _notes.lower_bound(search_note);
|
||||
assert(i == _notes.end() || musical_time_greater_or_equal_to((*i)->time(), t));
|
||||
assert(i == _notes.end() || (*i)->time() >= t);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1262,7 +1262,7 @@ Sequence<Time>::patch_change_lower_bound (Time t)
|
|||
{
|
||||
PatchChangePtr search (new PatchChange<Time> (t, 0, 0, 0));
|
||||
typename Sequence<Time>::PatchChanges::iterator i = _patch_changes.lower_bound (search);
|
||||
assert (i == _patch_changes.end() || musical_time_greater_or_equal_to ((*i)->time(), t));
|
||||
assert (i == _patch_changes.end() || (*i)->time() >= t);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1273,7 +1273,7 @@ Sequence<Time>::sysex_lower_bound (Time t)
|
|||
{
|
||||
SysExPtr search (new Event<Time> (0, t));
|
||||
typename Sequence<Time>::SysExes::iterator i = _sysexes.lower_bound (search);
|
||||
assert (i == _sysexes.end() || musical_time_greater_or_equal_to((*i)->time(), t));
|
||||
assert (i == _sysexes.end() || (*i)->time() >= t);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -1311,7 +1311,7 @@ Sequence<Time>::get_notes_by_pitch (Notes& n, NoteOperator op, uint8_t val, int
|
|||
}
|
||||
|
||||
const Pitches& p (pitches (c));
|
||||
NotePtr search_note(new Note<Time>(0, 0, 0, val, 0));
|
||||
NotePtr search_note(new Note<Time>(0, Time(), Time(), val, 0));
|
||||
typename Pitches::const_iterator i;
|
||||
switch (op) {
|
||||
case PitchEqual:
|
||||
|
|
|
@ -29,27 +29,25 @@ SMFTest::takeFiveTest ()
|
|||
smf.seek_to_start();
|
||||
|
||||
uint64_t time = 0; /* in SMF ticks */
|
||||
Evoral::Event<double> ev;
|
||||
|
||||
const double frames_per_beat = 100.0;
|
||||
Evoral::Event<Evoral::MusicalTime> ev;
|
||||
|
||||
uint32_t delta_t = 0;
|
||||
uint32_t size = 0;
|
||||
uint8_t* buf = NULL;
|
||||
int ret;
|
||||
while ((ret = smf.read_event(&delta_t, &size, &buf)) >= 0) {
|
||||
ev.set(buf, size, 0.0);
|
||||
ev.set(buf, size, Evoral::MusicalTime());
|
||||
time += delta_t;
|
||||
|
||||
if (ret > 0) { // didn't skip (meta) event
|
||||
//cerr << "read smf event type " << hex << int(buf[0]) << endl;
|
||||
// make ev.time absolute time in frames
|
||||
ev.set_time(time * frames_per_beat / (double)smf.ppqn());
|
||||
ev.set_time(Evoral::MusicalTime::ticks_at_rate(time, smf.ppqn()));
|
||||
ev.set_event_type(type_map->midi_event_type(buf[0]));
|
||||
seq->append(ev, next_event_id ());
|
||||
}
|
||||
}
|
||||
|
||||
seq->end_write (Sequence<Time>::Relax, false);
|
||||
seq->end_write (Sequence<Time>::Relax,
|
||||
Evoral::MusicalTime::ticks_at_rate(time, smf.ppqn()));
|
||||
CPPUNIT_ASSERT(!seq->empty());
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <sigc++/sigc++.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include "evoral/types.hpp"
|
||||
#include "evoral/SMF.hpp"
|
||||
#include "SequenceTest.hpp"
|
||||
|
||||
|
@ -56,7 +57,7 @@ class SMFTest : public CppUnit::TestFixture
|
|||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
typedef double Time;
|
||||
typedef Evoral::MusicalTime Time;
|
||||
|
||||
void setUp() {
|
||||
type_map = new DummyTypeMap();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
CPPUNIT_TEST_SUITE_REGISTRATION(SequenceTest);
|
||||
|
||||
using namespace std;
|
||||
using namespace Evoral;
|
||||
|
||||
void
|
||||
SequenceTest::createTest ()
|
||||
|
@ -75,7 +76,7 @@ SequenceTest::iteratorSeekTest ()
|
|||
}
|
||||
|
||||
bool on = true;
|
||||
for (Sequence<Time>::const_iterator i = seq->begin(600); i != seq->end(); ++i) {
|
||||
for (Sequence<Time>::const_iterator i = seq->begin(Evoral::MusicalTime(600)); i != seq->end(); ++i) {
|
||||
if (on) {
|
||||
CPPUNIT_ASSERT(((const MIDIEvent<Time>&)*i).is_note_on());
|
||||
CPPUNIT_ASSERT_EQUAL(i->time(), Time((num_notes + 6) * 100));
|
||||
|
@ -136,7 +137,7 @@ SequenceTest::controlInterpolationTest ()
|
|||
sink.write(i->time(), i->event_type(), i->size(), i->buffer());
|
||||
}
|
||||
CPPUNIT_ASSERT(sink.events.size() == 128 * 2 - 1);
|
||||
Time last_time = 0;
|
||||
Time last_time(0);
|
||||
int16_t last_value = -1;
|
||||
bool ascending = true;
|
||||
for (CCTestSink<Time>::Events::const_iterator i = sink.events.begin();
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
};
|
||||
}
|
||||
|
||||
bool is_integer (const Evoral::Parameter& /*param*/) const { return true; }
|
||||
bool is_integer (const Parameter& /*param*/) const { return true; }
|
||||
|
||||
Parameter new_parameter(uint32_t type, uint8_t channel, uint32_t id) const {
|
||||
Parameter p(type, channel, id);
|
||||
|
@ -119,7 +119,7 @@ class SequenceTest : public CppUnit::TestFixture
|
|||
CPPUNIT_TEST_SUITE_END ();
|
||||
|
||||
public:
|
||||
typedef double Time;
|
||||
typedef MusicalTime Time;
|
||||
typedef std::vector< boost::shared_ptr< Note<Time> > > Notes;
|
||||
|
||||
void setUp () {
|
||||
|
@ -129,8 +129,9 @@ public:
|
|||
assert(seq);
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
test_notes.push_back(boost::shared_ptr<Note<Time> >
|
||||
(new Note<Time>(0, i * 100, 100, 64 + i, 64)));
|
||||
test_notes.push_back(
|
||||
boost::shared_ptr<Note<Time> >(
|
||||
new Note<Time>(0, MusicalTime(i * 100), MusicalTime(100), 64 + i, 64)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ Patch::get_state (void)
|
|||
node->add_property("Name", _name);
|
||||
|
||||
/*
|
||||
typedef std::list< boost::shared_ptr< Evoral::MIDIEvent<double> > > PatchMidiCommands;
|
||||
typedef std::list< boost::shared_ptr< Evoral::MIDIEvent<Evoral::MusicalTime> > > PatchMidiCommands;
|
||||
XMLNode* commands = node->add_child("PatchMIDICommands");
|
||||
for (PatchMidiCommands::const_iterator event = _patch_midi_commands.begin();
|
||||
event != _patch_midi_commands.end();
|
||||
|
|
Loading…
Reference in New Issue
Block a user