Fix quantization and other time-related ops.
authorDavid Robillard <d@drobilla.net>
Sun, 23 Nov 2014 02:49:42 +0000 (21:49 -0500)
committerDavid Robillard <d@drobilla.net>
Sun, 23 Nov 2014 02:49:42 +0000 (21:49 -0500)
12 files changed:
gtk2_ardour/edit_note_dialog.cc
gtk2_ardour/editor_drag.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/midi_list_editor.cc
gtk2_ardour/midi_region_view.cc
gtk2_ardour/quantize_dialog.cc
gtk2_ardour/step_entry.cc
libs/ardour/ardour/midi_operator.h
libs/ardour/ardour/quantize.h
libs/ardour/quantize.cc
libs/ardour/tempo.cc
libs/evoral/evoral/types.hpp

index 149b212926caeab7c8ef380606369522bbb2df61..5f8add9ffd9bd3adcdcceb649fa6a514dfb94b64 100644 (file)
@@ -116,8 +116,8 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set<NoteBase*> 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<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
                if ((*i)->note()->channel() != test_channel) {
index fa66c952dcd332b99c7179b8789d19fe83f6e32c..30cad7771dc25cb9d398bea95369576c8d5a9f53 100644 (file)
@@ -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);
 }
index 856b311ebdcd91274718e658e1aaddfc5c7bd83e..e5fc42af17c8991c5c0810a0e663e6846702c3eb 100644 (file)
@@ -4849,8 +4849,8 @@ Editor::apply_midi_note_edit_op_to_region (MidiOperator& op, MidiRegionView& mrv
        vector<Evoral::Sequence<Evoral::MusicalTime>::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);
 }
index 32c87bae866e76cf30b8fc469bbc324f8ed9b134..0a87823f8e577845060f9e2c34a3edd97d1a3f5f 100644 (file)
@@ -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<int,string>::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<int,string>::iterator x = note_length_map.find (len_ticks);
 
                        if (x != note_length_map.end()) {
index d134e3d2f59b9abc5243f866dbea6c1f8a4ca1b2..b82115da9e843336e234893575f1318d81a36c15 100644 (file)
@@ -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) {
index 98514326d5e9b6ef7c7a7ea081ef4a8a930876ac..45a96e1fc3db50c7da8037e438b6b8e3488240d7 100644 (file)
@@ -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")) {
index 607f4abd629579a4fac9f44059479f16e832954d..d7b177949f2e00a0b158b1b5590c95f1b5e98c41 100644 (file)
@@ -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
index 00678a283167fec88d343329f8762f624c9b2eb2..36e87b714b39b81dce74b16cff2b3a8b4a0d082c 100644 (file)
@@ -38,7 +38,7 @@ class LIBARDOUR_API MidiOperator {
        virtual ~MidiOperator() {}
 
        virtual Command* operator() (boost::shared_ptr<ARDOUR::MidiModel>,
-                                    double,
+                                    Evoral::MusicalTime,
                                     std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>&) = 0;
        virtual std::string name() const = 0;
 };
index c41d172177e3b3e7ebaaf99c30ca872d50a15250..1434a85f8e24294bbfa1f0ff2498d4d9a573fbe9 100644 (file)
@@ -37,7 +37,7 @@ public:
        ~Quantize ();
 
        Command* operator() (boost::shared_ptr<ARDOUR::MidiModel>,
-                            double position,
+                            Evoral::MusicalTime position,
                             std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>&);
        std::string name() const { return std::string ("quantize"); }
 
index 13b1cf3b362fa184c30385ac7f0d2bc2e00454d3..b543c5e67b3d4eaddf088b9673137d5851d977c3 100644 (file)
@@ -55,7 +55,7 @@ Quantize::~Quantize ()
 
 Command*
 Quantize::operator () (boost::shared_ptr<MidiModel> model,
-                       double position,
+                       Evoral::MusicalTime position,
                        std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>& seqs)
 {
        /* TODO: Rewrite this to be precise with fixed point? */
@@ -64,8 +64,8 @@ Quantize::operator () (boost::shared_ptr<MidiModel> 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<MidiModel> 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<MidiModel> 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);
index 1767c8100dce0e738f16cceeb16e54958ef079ad..486cbb0643d24b07b3a3225177b0cac6b0861d4a 100644 (file)
@@ -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();
                }
        }
index ee93bc39982519792e4d9b9341680048d2898ce9..719007abe5adde5c06bc51ca5479aef454b79896 100644 (file)
@@ -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); }