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