From 57c1b6e261076cae9b61e74aa0aff47a9f296c0f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 22 Nov 2014 21:49:42 -0500 Subject: Fix quantization and other time-related ops. --- gtk2_ardour/edit_note_dialog.cc | 4 ++-- gtk2_ardour/editor_drag.cc | 5 +++-- gtk2_ardour/editor_ops.cc | 4 ++-- gtk2_ardour/midi_list_editor.cc | 27 ++++++++++++------------- gtk2_ardour/midi_region_view.cc | 26 +++++++++---------------- gtk2_ardour/quantize_dialog.cc | 2 +- gtk2_ardour/step_entry.cc | 2 +- libs/ardour/ardour/midi_operator.h | 2 +- libs/ardour/ardour/quantize.h | 2 +- libs/ardour/quantize.cc | 14 ++++++------- libs/ardour/tempo.cc | 8 ++++---- libs/evoral/evoral/types.hpp | 40 ++++++++++++++++++++++++++++++++++---- 12 files changed, 81 insertions(+), 55 deletions(-) diff --git a/gtk2_ardour/edit_note_dialog.cc b/gtk2_ardour/edit_note_dialog.cc index 149b212926..5f8add9ffd 100644 --- a/gtk2_ardour/edit_note_dialog.cc +++ b/gtk2_ardour/edit_note_dialog.cc @@ -116,8 +116,8 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set n) int test_channel = (*_events.begin())->note()->channel (); int test_pitch = (*_events.begin())->note()->note (); int test_velocity = (*_events.begin())->note()->velocity (); - double test_time = (*_events.begin())->note()->time (); - double test_length = (*_events.begin())->note()->length (); + Evoral::MusicalTime test_time = (*_events.begin())->note()->time (); + Evoral::MusicalTime test_length = (*_events.begin())->note()->length (); for (set::iterator i = _events.begin(); i != _events.end(); ++i) { if ((*i)->note()->channel() != test_channel) { diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index fa66c952dc..30cad7771d 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -5279,10 +5279,11 @@ NoteCreateDrag::finished (GdkEvent*, bool had_movement) Evoral::MusicalTime const one_tick = Evoral::MusicalTime::ticks(1); if (_editor->snap_mode() == SnapNormal && length < g) { - length = g - one_tick; + length = g; } - Evoral::MusicalTime const length_beats = max (one_tick, _region_view->region_frames_to_region_beats (length)); + Evoral::MusicalTime length_beats = max ( + one_tick, _region_view->region_frames_to_region_beats (length) - one_tick); _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 856b311ebd..e5fc42af17 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -4849,8 +4849,8 @@ Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv vector::Notes> v; v.push_back (selected); - framepos_t pos_frames = mrv.midi_region()->position() - mrv.midi_region()->start(); - double pos_beats = _session->tempo_map().framewalk_to_beats(0, pos_frames); + framepos_t pos_frames = mrv.midi_region()->position() - mrv.midi_region()->start(); + Evoral::MusicalTime pos_beats = _session->tempo_map().framewalk_to_beats(0, pos_frames); return op (mrv.midi_region()->model(), pos_beats, v); } diff --git a/gtk2_ardour/midi_list_editor.cc b/gtk2_ardour/midi_list_editor.cc index 32c87bae86..0a87823f8e 100644 --- a/gtk2_ardour/midi_list_editor.cc +++ b/gtk2_ardour/midi_list_editor.cc @@ -291,17 +291,18 @@ MidiListEditor::scroll_event (GdkEventScroll* ev) if (note->time() + fdelta >= 0) { cmd->change (note, prop, note->time() + fdelta); } else { - cmd->change (note, prop, 0.0); + cmd->change (note, prop, Evoral::MusicalTime()); } break; case MidiModel::NoteDiffCommand::Velocity: cmd->change (note, prop, (uint8_t) (note->velocity() + idelta)); break; case MidiModel::NoteDiffCommand::Length: - if (note->length() + fdelta >= 1.0/BBT_Time::ticks_per_beat) { + if (note->length().to_double() + fdelta >= + Evoral::MusicalTime::tick().to_double()) { cmd->change (note, prop, note->length() + fdelta); } else { - cmd->change (note, prop, 1.0/BBT_Time::ticks_per_beat); + cmd->change (note, prop, Evoral::MusicalTime::tick()); } break; case MidiModel::NoteDiffCommand::Channel: @@ -333,17 +334,18 @@ MidiListEditor::scroll_event (GdkEventScroll* ev) if (note->time() + fdelta >= 0) { cmd->change (note, prop, note->time() + fdelta); } else { - cmd->change (note, prop, 0.0); + cmd->change (note, prop, Evoral::MusicalTime()); } break; case MidiModel::NoteDiffCommand::Velocity: cmd->change (note, prop, (uint8_t) (note->velocity() + idelta)); break; case MidiModel::NoteDiffCommand::Length: - if (note->length() + fdelta >= 1.0/BBT_Time::ticks_per_beat) { + if (note->length() + fdelta >= + Evoral::MusicalTime::tick().to_double()) { cmd->change (note, prop, note->length() + fdelta); } else { - cmd->change (note, prop, 1.0/BBT_Time::ticks_per_beat); + cmd->change (note, prop, Evoral::MusicalTime::tick()); } break; case MidiModel::NoteDiffCommand::Channel: @@ -637,7 +639,7 @@ MidiListEditor::edited (const std::string& path, const std::string& text) * entry for the actual note ticks */ - int len_ticks = lrint (note->length() * Timecode::BBT_Time::ticks_per_beat); + uint64_t len_ticks = note->length().to_ticks(); std::map::iterator x = note_length_map.find (len_ticks); if (x == note_length_map.end()) { @@ -682,7 +684,7 @@ MidiListEditor::edited (const std::string& path, const std::string& text) } if (fval > 0.0) { - fdelta = fval - note->length(); + fdelta = fval - note->length().to_double(); prop = MidiModel::NoteDiffCommand::Length; opname = _("change note length"); apply = true; @@ -762,7 +764,6 @@ MidiListEditor::redisplay_model () row[columns.velocity] = (*i)->velocity(); Timecode::BBT_Time bbt; - double dur; _session->tempo_map().bbt_time (conv.to ((*i)->time()), bbt); @@ -771,11 +772,11 @@ MidiListEditor::redisplay_model () row[columns.start] = ss.str(); bbt.bars = 0; - dur = (*i)->end_time() - (*i)->time(); - bbt.beats = floor (dur); - bbt.ticks = (uint32_t) lrint (fmod (dur, 1.0) * Timecode::BBT_Time::ticks_per_beat); + const Evoral::MusicalTime dur = (*i)->end_time() - (*i)->time(); + bbt.beats = dur.get_beats (); + bbt.ticks = dur.get_ticks (); - int len_ticks = lrint ((*i)->length() * Timecode::BBT_Time::ticks_per_beat); + int len_ticks = (*i)->length().to_ticks(); std::map::iterator x = note_length_map.find (len_ticks); if (x != note_length_map.end()) { diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index d134e3d2f5..b82115da9e 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -1856,7 +1856,7 @@ MidiRegionView::patch_change_to_patch_key (MidiModel::PatchChangePtr p) /// Return true iff @p pc applies to the given time on the given channel. static bool -patch_applies (const ARDOUR::MidiModel::constPatchChangePtr pc, double time, uint8_t channel) +patch_applies (const ARDOUR::MidiModel::constPatchChangePtr pc, Evoral::MusicalTime time, uint8_t channel) { return pc->time() <= time && pc->channel() == channel; } @@ -2672,30 +2672,23 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_ } if (!cursor_set) { - double beats; - - beats = snap_pixel_to_sample (current_x); - beats = region_frames_to_region_beats (beats); - - double len; + const double snapped_x = snap_pixel_to_sample (current_x); + Evoral::MusicalTime beats = region_frames_to_region_beats (snapped_x); + Evoral::MusicalTime len = Evoral::MusicalTime(); if (at_front) { if (beats < canvas_note->note()->end_time()) { len = canvas_note->note()->time() - beats; len += canvas_note->note()->length(); - } else { - len = 0; } } else { if (beats >= canvas_note->note()->time()) { len = beats - canvas_note->note()->time(); - } else { - len = 0; } } char buf[16]; - snprintf (buf, sizeof (buf), "%.3g beats", len); + snprintf (buf, sizeof (buf), "%.3g beats", len.to_double()); show_verbose_cursor (buf, 0, 0); cursor_set = true; @@ -2756,8 +2749,7 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_ Evoral::MusicalTime len = canvas_note->note()->time() - x_beats; len += canvas_note->note()->length(); - if (len) { - /* XXX convert to beats */ + if (!!len) { note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len); } } @@ -2765,7 +2757,7 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_ if (!at_front) { const Evoral::MusicalTime len = x_beats - canvas_note->note()->time(); - if (len) { + if (!!len) { /* XXX convert to beats */ note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len); } @@ -2839,7 +2831,7 @@ MidiRegionView::trim_note (NoteBase* event, Evoral::MusicalTime front_delta, Evo if negative - move the end of the note earlier in time (shortening it) */ - if (front_delta) { + if (!!front_delta) { if (front_delta < 0) { if (event->note()->time() < -front_delta) { @@ -2871,7 +2863,7 @@ MidiRegionView::trim_note (NoteBase* event, Evoral::MusicalTime front_delta, Evo } - if (end_delta) { + if (!!end_delta) { bool can_change = true; if (end_delta < 0) { if (event->note()->length() < -end_delta) { diff --git a/gtk2_ardour/quantize_dialog.cc b/gtk2_ardour/quantize_dialog.cc index 98514326d5..45a96e1fc3 100644 --- a/gtk2_ardour/quantize_dialog.cc +++ b/gtk2_ardour/quantize_dialog.cc @@ -135,7 +135,7 @@ QuantizeDialog::grid_size_to_musical_time (const string& txt) const if (!success) { return 1.0; } - return (double) b; + return b.to_double(); } if (txt == _("Beats/128")) { diff --git a/gtk2_ardour/step_entry.cc b/gtk2_ardour/step_entry.cc index 607f4abd62..d7b177949f 100644 --- a/gtk2_ardour/step_entry.cc +++ b/gtk2_ardour/step_entry.cc @@ -555,7 +555,7 @@ StepEntry::note_length () uint8_t StepEntry::note_velocity () const { - return (Evoral::MusicalTime) velocity_adjustment.get_value(); + return velocity_adjustment.get_value(); } uint8_t diff --git a/libs/ardour/ardour/midi_operator.h b/libs/ardour/ardour/midi_operator.h index 00678a2831..36e87b714b 100644 --- a/libs/ardour/ardour/midi_operator.h +++ b/libs/ardour/ardour/midi_operator.h @@ -38,7 +38,7 @@ class LIBARDOUR_API MidiOperator { virtual ~MidiOperator() {} virtual Command* operator() (boost::shared_ptr, - double, + Evoral::MusicalTime, std::vector::Notes>&) = 0; virtual std::string name() const = 0; }; diff --git a/libs/ardour/ardour/quantize.h b/libs/ardour/ardour/quantize.h index c41d172177..1434a85f8e 100644 --- a/libs/ardour/ardour/quantize.h +++ b/libs/ardour/ardour/quantize.h @@ -37,7 +37,7 @@ public: ~Quantize (); Command* operator() (boost::shared_ptr, - double position, + Evoral::MusicalTime position, std::vector::Notes>&); std::string name() const { return std::string ("quantize"); } diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc index 13b1cf3b36..b543c5e67b 100644 --- a/libs/ardour/quantize.cc +++ b/libs/ardour/quantize.cc @@ -55,7 +55,7 @@ Quantize::~Quantize () Command* Quantize::operator () (boost::shared_ptr model, - double position, + Evoral::MusicalTime position, std::vector::Notes>& seqs) { /* TODO: Rewrite this to be precise with fixed point? */ @@ -64,8 +64,8 @@ Quantize::operator () (boost::shared_ptr model, to quantize relative to actual session beats (etc.) rather than from the start of the model. */ - const double round_pos = round(position / _start_grid) * _start_grid; - const double offset = round_pos - position; + const double round_pos = round(position.to_double() / _start_grid) * _start_grid; + const double offset = round_pos - position.to_double(); bool even; MidiModel::NoteDiffCommand* cmd = new MidiModel::NoteDiffCommand (model, "quantize"); @@ -112,7 +112,7 @@ Quantize::operator () (boost::shared_ptr model, if (_snap_start) { delta *= _strength; cmd->change ((*i), MidiModel::NoteDiffCommand::StartTime, - (*i)->time().to_double() + delta); + (*i)->time() + delta); } } @@ -120,10 +120,10 @@ Quantize::operator () (boost::shared_ptr model, delta = new_end - (*i)->end_time().to_double(); if (fabs (delta) >= _threshold) { - double new_dur = new_end - new_start; + Evoral::MusicalTime new_dur(new_end - new_start); - if (new_dur == 0.0) { - new_dur = _end_grid; + if (!new_dur) { + new_dur = Evoral::MusicalTime(_end_grid); } cmd->change ((*i), MidiModel::NoteDiffCommand::Length, new_dur); diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc index 1767c8100d..486cbb0643 100644 --- a/libs/ardour/tempo.cc +++ b/libs/ardour/tempo.cc @@ -1885,7 +1885,7 @@ TempoMap::framepos_plus_beats (framepos_t pos, Evoral::MusicalTime beats) const string_compose ("frame %1 plus %2 beats, start with tempo = %3 @ %4\n", pos, beats, *((const Tempo*)tempo), tempo->frame())); - while (beats) { + while (!!beats) { /* Distance to the end of this section in frames */ framecnt_t distance_frames = (next_tempo == metrics.end() ? max_framepos : ((*next_tempo)->frame() - pos)); @@ -1994,7 +1994,7 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const prev_tempo -> the first metric before "pos", possibly metrics.rend() */ - while (beats) { + while (!!beats) { /* Distance to the start of this section in frames */ framecnt_t distance_frames = (pos - tempo->frame()); @@ -2011,7 +2011,7 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const /* Update */ beats -= sub; - pos -= sub * tempo->frames_per_beat (_frame_rate); + pos -= sub.to_double() * tempo->frames_per_beat (_frame_rate); DEBUG_TRACE (DEBUG::TempoMath, string_compose ("\tnow at %1, %2 beats left, prev at end ? %3\n", pos, beats, (prev_tempo == metrics.rend()))); @@ -2036,7 +2036,7 @@ TempoMap::framepos_minus_beats (framepos_t pos, Evoral::MusicalTime beats) const } } } else { - pos -= llrint (beats * tempo->frames_per_beat (_frame_rate)); + pos -= llrint (beats.to_double() * tempo->frames_per_beat (_frame_rate)); beats = Evoral::MusicalTime(); } } diff --git a/libs/evoral/evoral/types.hpp b/libs/evoral/evoral/types.hpp index ee93bc3998..719007abe5 100644 --- a/libs/evoral/evoral/types.hpp +++ b/libs/evoral/evoral/types.hpp @@ -126,14 +126,35 @@ public: } inline bool operator>=(const MusicalTime& b) const { + return operator==(b) || operator>(b); + } + + inline bool operator<(double b) const { /* Acceptable tolerance is 1 tick. */ - if (fabs(_time - b._time) <= (1.0 / PPQN)) { - return true; /* Effectively identical. */ + if (fabs(_time - b) <= (1.0 / PPQN)) { + return false; /* Effectively identical. */ + } else { + return _time < b; + } + } + + inline bool operator<=(double b) const { + return operator==(b) || operator<(b); + } + + inline bool operator>(double b) const { + /* Acceptable tolerance is 1 tick. */ + if (fabs(_time - b) <= (1.0 / PPQN)) { + return false; /* Effectively identical. */ } else { - return _time >= b._time; + return _time > b; } } + inline bool operator>=(double b) const { + return operator==(b) || operator>(b); + } + MusicalTime operator+(const MusicalTime& b) const { return MusicalTime(_time + b._time); } @@ -142,6 +163,14 @@ public: return MusicalTime(_time - b._time); } + MusicalTime operator+(double d) const { + return MusicalTime(_time + d); + } + + MusicalTime operator-(double d) const { + return MusicalTime(_time - d); + } + MusicalTime operator-() const { return MusicalTime(-_time); } @@ -165,7 +194,10 @@ public: 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; } + uint32_t get_beats() const { return floor(_time); } + uint32_t get_ticks() const { return (uint32_t)lrint(fmod(_time, 1.0) * PPQN); } + + bool operator!() const { return _time == 0; } static MusicalTime min() { return MusicalTime(DBL_MIN); } static MusicalTime max() { return MusicalTime(DBL_MAX); } -- cgit v1.2.3