From e534334dce462eee99842934fcefd3ca09b056d7 Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Sun, 6 Apr 2008 20:03:41 +0000 Subject: [PATCH] * bugfix: creating notes not sample accurate * bugfix: resizing notes not sample accurate * bugfix: resizing notes broken due to region resizing patch git-svn-id: svn://localhost/ardour2/branches/3.0@3221 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/canvas-midi-event.cc | 8 ++-- gtk2_ardour/midi_region_view.cc | 68 ++++++++++++++++++++++---------- gtk2_ardour/midi_region_view.h | 17 +++++--- 3 files changed, 64 insertions(+), 29 deletions(-) diff --git a/gtk2_ardour/canvas-midi-event.cc b/gtk2_ardour/canvas-midi-event.cc index 416c667938..0709024075 100644 --- a/gtk2_ardour/canvas-midi-event.cc +++ b/gtk2_ardour/canvas-midi-event.cc @@ -99,10 +99,8 @@ CanvasMidiEvent::on_event(GdkEvent* ev) static double drag_delta_x = 0; static double last_x, last_y; double event_x, event_y, dx, dy; - nframes_t event_frame; bool select_mod; uint8_t d_velocity = 10; - nframes_t midi_region_start = _region.midi_region()->start(); if (_region.get_time_axis_view().editor.current_mouse_mode() != Editing::MouseNote) return false; @@ -172,7 +170,6 @@ CanvasMidiEvent::on_event(GdkEvent* ev) case GDK_MOTION_NOTIFY: event_x = ev->motion.x; event_y = ev->motion.y; - _item->property_parent().get_value()->w2i(event_x, event_y); switch (_state) { case Pressed: // Drag begin @@ -180,6 +177,8 @@ CanvasMidiEvent::on_event(GdkEvent* ev) _item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, Gdk::Cursor(Gdk::FLEUR), ev->motion.time); _state = Dragging; + _item->property_parent().get_value()->w2i(event_x, event_y); + event_x = _region.snap_to_pixel(event_x); last_x = event_x; last_y = event_y; drag_delta_x = 0; @@ -197,7 +196,8 @@ CanvasMidiEvent::on_event(GdkEvent* ev) event_x = t_x; event_y = t_y; } - + _item->property_parent().get_value()->w2i(event_x, event_y); + // Snap event_x = _region.snap_to_pixel(event_x); diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 7b73dd37e5..abe429497c 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -314,9 +314,6 @@ MidiRegionView::canvas_event(GdkEvent* ev) clear_selection(); break; case MidiEditPencil: - event_frame += _region->start(); - trackview.editor.snap_to(event_frame, -1); - event_x = trackview.editor.frame_to_pixel(event_frame); create_note_at(event_x, event_y, _default_note_length); default: break; @@ -331,10 +328,10 @@ MidiRegionView::canvas_event(GdkEvent* ev) case AddDragging: // Add drag done _mouse_state = None; if (drag_rect->property_x2() > drag_rect->property_x1() + 2) { - const double x = - drag_rect->property_x1() + trackview.editor.frame_to_pixel(_region->start()); - const double length = - trackview.editor.pixel_to_frame(drag_rect->property_x2() - drag_rect->property_x1()); + const double x = drag_rect->property_x1() + + trackview.editor.frame_to_pixel(_region->start()); + const double length = trackview.editor.pixel_to_frame( + drag_rect->property_x2() - drag_rect->property_x1()); create_note_at(x, drag_rect->property_y1(), length); } @@ -356,7 +353,7 @@ MidiRegionView::canvas_event(GdkEvent* ev) /** Add a note to the model, and the view, at a canvas (click) coordinate */ void -MidiRegionView::create_note_at(double x, double y, double dur) +MidiRegionView::create_note_at(double x, double y, double duration) { MidiTimeAxisView* const mtv = dynamic_cast(&trackview); MidiStreamView* const view = mtv->midi_view(); @@ -366,17 +363,27 @@ MidiRegionView::create_note_at(double x, double y, double dur) assert(note >= 0.0); assert(note <= 127.0); - nframes_t stamp = trackview.editor.pixel_to_frame (x); - assert(stamp >= 0); - //assert(stamp <= _region->length()); + nframes_t new_note_time = trackview.editor.pixel_to_frame (x); + assert(new_note_time >= 0); - //const Meter& m = trackview.session().tempo_map().meter_at(stamp); - //const Tempo& t = trackview.session().tempo_map().tempo_at(stamp); - //double dur = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar(); - - // Add a 1 beat long note (for now) - const boost::shared_ptr new_note(new Note(0, stamp, dur, (uint8_t)note, 0x40)); + /* + const Meter& m = trackview.session().tempo_map().meter_at(new_note_time); + const Tempo& t = trackview.session().tempo_map().tempo_at(new_note_time); + double duration = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar(); + */ + + // we need to snap here again in nframes_t in order to be sample accurate + // since note time is region-absolute but snap_to_frame expects position-relative + // time we have to coordinate transform back and forth here. + nframes_t new_note_time_position_relative = new_note_time - _region->start(); + new_note_time = snap_to_frame(new_note_time_position_relative) + _region->start(); + + // we need to snap the duration too to be sample accurate + nframes_t new_note_duration = nframes_t(duration); + new_note_duration = snap_to_frame(new_note_time_position_relative + new_note_duration) + _region->start() + - new_note_time; + const boost::shared_ptr new_note(new Note(0, new_note_time, new_note_duration, (uint8_t)note, 0x40)); view->update_bounds(new_note->note()); MidiModel::DeltaCommand* cmd = _model->new_delta_command("add note"); @@ -901,10 +908,18 @@ MidiRegionView::note_dropped(CanvasMidiEvent* ev, double dt, uint8_t dnote) command_remove_note(*i); const boost::shared_ptr copy(new Note(*(*i)->note().get())); - copy->set_time((*i)->note()->time() + dt); - if(copy->time() < 0) { - copy->set_time(0); + // we need to snap here again in nframes_t in order to be sample accurate + nframes_t new_note_time = nframes_t((*i)->note()->time()); + new_note_time += nframes_t(dt); + // since note time is region-absolute but snap_to_frame expects position-relative + // time we have to coordinate transform back and forth here. + new_note_time = snap_to_frame(new_note_time - _region->start()) + _region->start(); + + if(new_note_time < 0) { + new_note_time = 0; } + + copy->set_time(new_note_time); uint8_t original_pitch = (*i)->note()->note(); uint8_t new_pitch = original_pitch + dnote - highest_note_difference; @@ -952,6 +967,19 @@ MidiRegionView::snap_to_frame(double x) return frame; } +nframes_t +MidiRegionView::snap_to_frame(nframes_t x) +{ + PublicEditor &editor = trackview.editor; + // x is region relative + // convert x to global frame + nframes_t frame = x + _region->position(); + editor.snap_to(frame); + // convert event_frame back to local coordinates relative to position + frame -= _region->position(); + return frame; +} + double MidiRegionView::snap_to_pixel(double x) { diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 1c107561b1..bb63ad82ce 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -85,7 +85,7 @@ class MidiRegionView : public RegionView void end_write(); void extend_active_notes(); - void create_note_at(double x, double y, double dur); + void create_note_at(double x, double y, double duration); void display_model(boost::shared_ptr model); @@ -181,20 +181,27 @@ class MidiRegionView : public RegionView }; /** - * This function provides the snap function for pixel units (double) - * instead of nframes_t + * This function provides the snap function for region position relative coordinates + * for pixel units (double) instead of nframes_t * @param x a pixel coordinate relative to region start * @return the snapped pixel coordinate relative to region start */ double snap_to_pixel(double x); /** - * This function provides the snap function for pixel units (double) - * instead of nframes_t + * This function provides the snap function for region position relative coordinates + * for pixel units (double) instead of nframes_t * @param x a pixel coordinate relative to region start * @return the snapped nframes_t coordinate relative to region start */ nframes_t snap_to_frame(double x); + + /** + * This function provides the snap function for region position relative coordinates + * @param x a pixel coordinate relative to region start + * @return the snapped nframes_t coordinate relative to region start + */ + nframes_t snap_to_frame(nframes_t x); protected: