mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 11:46:25 +01:00
* 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
This commit is contained in:
parent
c1d5a721d2
commit
e534334dce
3 changed files with 64 additions and 29 deletions
|
|
@ -99,10 +99,8 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
|
||||||
static double drag_delta_x = 0;
|
static double drag_delta_x = 0;
|
||||||
static double last_x, last_y;
|
static double last_x, last_y;
|
||||||
double event_x, event_y, dx, dy;
|
double event_x, event_y, dx, dy;
|
||||||
nframes_t event_frame;
|
|
||||||
bool select_mod;
|
bool select_mod;
|
||||||
uint8_t d_velocity = 10;
|
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)
|
if (_region.get_time_axis_view().editor.current_mouse_mode() != Editing::MouseNote)
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -172,7 +170,6 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
event_x = ev->motion.x;
|
event_x = ev->motion.x;
|
||||||
event_y = ev->motion.y;
|
event_y = ev->motion.y;
|
||||||
_item->property_parent().get_value()->w2i(event_x, event_y);
|
|
||||||
|
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case Pressed: // Drag begin
|
case Pressed: // Drag begin
|
||||||
|
|
@ -180,6 +177,8 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
|
||||||
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
_item->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
||||||
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
|
Gdk::Cursor(Gdk::FLEUR), ev->motion.time);
|
||||||
_state = Dragging;
|
_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_x = event_x;
|
||||||
last_y = event_y;
|
last_y = event_y;
|
||||||
drag_delta_x = 0;
|
drag_delta_x = 0;
|
||||||
|
|
@ -197,7 +196,8 @@ CanvasMidiEvent::on_event(GdkEvent* ev)
|
||||||
event_x = t_x;
|
event_x = t_x;
|
||||||
event_y = t_y;
|
event_y = t_y;
|
||||||
}
|
}
|
||||||
|
_item->property_parent().get_value()->w2i(event_x, event_y);
|
||||||
|
|
||||||
// Snap
|
// Snap
|
||||||
event_x = _region.snap_to_pixel(event_x);
|
event_x = _region.snap_to_pixel(event_x);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -314,9 +314,6 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
||||||
clear_selection();
|
clear_selection();
|
||||||
break;
|
break;
|
||||||
case MidiEditPencil:
|
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);
|
create_note_at(event_x, event_y, _default_note_length);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -331,10 +328,10 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
||||||
case AddDragging: // Add drag done
|
case AddDragging: // Add drag done
|
||||||
_mouse_state = None;
|
_mouse_state = None;
|
||||||
if (drag_rect->property_x2() > drag_rect->property_x1() + 2) {
|
if (drag_rect->property_x2() > drag_rect->property_x1() + 2) {
|
||||||
const double x =
|
const double x = drag_rect->property_x1()
|
||||||
drag_rect->property_x1() + trackview.editor.frame_to_pixel(_region->start());
|
+ trackview.editor.frame_to_pixel(_region->start());
|
||||||
const double length =
|
const double length = trackview.editor.pixel_to_frame(
|
||||||
trackview.editor.pixel_to_frame(drag_rect->property_x2() - drag_rect->property_x1());
|
drag_rect->property_x2() - drag_rect->property_x1());
|
||||||
|
|
||||||
create_note_at(x, drag_rect->property_y1(), length);
|
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 */
|
/** Add a note to the model, and the view, at a canvas (click) coordinate */
|
||||||
void
|
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<MidiTimeAxisView*>(&trackview);
|
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
|
||||||
MidiStreamView* const view = mtv->midi_view();
|
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 >= 0.0);
|
||||||
assert(note <= 127.0);
|
assert(note <= 127.0);
|
||||||
|
|
||||||
nframes_t stamp = trackview.editor.pixel_to_frame (x);
|
nframes_t new_note_time = trackview.editor.pixel_to_frame (x);
|
||||||
assert(stamp >= 0);
|
assert(new_note_time >= 0);
|
||||||
//assert(stamp <= _region->length());
|
|
||||||
|
|
||||||
//const Meter& m = trackview.session().tempo_map().meter_at(stamp);
|
/*
|
||||||
//const Tempo& t = trackview.session().tempo_map().tempo_at(stamp);
|
const Meter& m = trackview.session().tempo_map().meter_at(new_note_time);
|
||||||
//double dur = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar();
|
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();
|
||||||
// Add a 1 beat long note (for now)
|
*/
|
||||||
const boost::shared_ptr<Note> new_note(new Note(0, stamp, dur, (uint8_t)note, 0x40));
|
|
||||||
|
// 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<Note> new_note(new Note(0, new_note_time, new_note_duration, (uint8_t)note, 0x40));
|
||||||
view->update_bounds(new_note->note());
|
view->update_bounds(new_note->note());
|
||||||
|
|
||||||
MidiModel::DeltaCommand* cmd = _model->new_delta_command("add 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);
|
command_remove_note(*i);
|
||||||
const boost::shared_ptr<Note> copy(new Note(*(*i)->note().get()));
|
const boost::shared_ptr<Note> copy(new Note(*(*i)->note().get()));
|
||||||
|
|
||||||
copy->set_time((*i)->note()->time() + dt);
|
// we need to snap here again in nframes_t in order to be sample accurate
|
||||||
if(copy->time() < 0) {
|
nframes_t new_note_time = nframes_t((*i)->note()->time());
|
||||||
copy->set_time(0);
|
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 original_pitch = (*i)->note()->note();
|
||||||
uint8_t new_pitch = original_pitch + dnote - highest_note_difference;
|
uint8_t new_pitch = original_pitch + dnote - highest_note_difference;
|
||||||
|
|
@ -952,6 +967,19 @@ MidiRegionView::snap_to_frame(double x)
|
||||||
return frame;
|
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
|
double
|
||||||
MidiRegionView::snap_to_pixel(double x)
|
MidiRegionView::snap_to_pixel(double x)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ class MidiRegionView : public RegionView
|
||||||
void end_write();
|
void end_write();
|
||||||
void extend_active_notes();
|
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<ARDOUR::MidiModel> model);
|
void display_model(boost::shared_ptr<ARDOUR::MidiModel> model);
|
||||||
|
|
||||||
|
|
@ -181,20 +181,27 @@ class MidiRegionView : public RegionView
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function provides the snap function for pixel units (double)
|
* This function provides the snap function for region position relative coordinates
|
||||||
* instead of nframes_t
|
* for pixel units (double) instead of nframes_t
|
||||||
* @param x a pixel coordinate relative to region start
|
* @param x a pixel coordinate relative to region start
|
||||||
* @return the snapped pixel coordinate relative to region start
|
* @return the snapped pixel coordinate relative to region start
|
||||||
*/
|
*/
|
||||||
double snap_to_pixel(double x);
|
double snap_to_pixel(double x);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function provides the snap function for pixel units (double)
|
* This function provides the snap function for region position relative coordinates
|
||||||
* instead of nframes_t
|
* for pixel units (double) instead of nframes_t
|
||||||
* @param x a pixel coordinate relative to region start
|
* @param x a pixel coordinate relative to region start
|
||||||
* @return the snapped nframes_t coordinate relative to region start
|
* @return the snapped nframes_t coordinate relative to region start
|
||||||
*/
|
*/
|
||||||
nframes_t snap_to_frame(double x);
|
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:
|
protected:
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue