From 94e0a15325278ec26dbeba4990a0e883db859338 Mon Sep 17 00:00:00 2001 From: nick_m Date: Thu, 16 Jun 2016 00:18:27 +1000 Subject: Exact beat - provide audio->music mapping for region split. - for those not in the know, this series provides a way to remove the temporal distortion introduced when using an audio frame-based gui for music-locked objects. In short, the gui uses an audio frame representation to move objects. It displays the object using frame_at_beat(), quantizing the time value to audio frames. This is fine until the user selects that frame but expects it to be interpreted as a beat. Thus beat_at_frame() would not produce the user-expected beat (temporal quantization error of up to 0.5 audio samples). This is one method of mapping audio time to music time accurately. --- gtk2_ardour/audio_streamview.cc | 5 +++-- gtk2_ardour/editor.h | 2 +- gtk2_ardour/editor_drag.cc | 8 ++++---- gtk2_ardour/editor_mouse.cc | 2 +- gtk2_ardour/editor_ops.cc | 13 +++++++++---- gtk2_ardour/midi_region_view.cc | 12 +++++++----- gtk2_ardour/midi_streamview.cc | 2 +- gtk2_ardour/midi_time_axis.cc | 1 + gtk2_ardour/public_editor.h | 2 +- gtk2_ardour/region_view.cc | 6 +++--- gtk2_ardour/region_view.h | 2 +- 11 files changed, 32 insertions(+), 23 deletions(-) (limited to 'gtk2_ardour') diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index ed9ec23b02..511b4296eb 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -353,8 +353,9 @@ AudioStreamView::update_rec_regions (framepos_t start, framecnt_t cnt) if (nlen != region->length()) { region->suspend_property_changes (); + /* set non-musical position / length */ region->set_position (_trackview.track()->get_capture_start_frame(n)); - region->set_length (nlen); + region->set_length (nlen, 0); region->resume_property_changes (); if (origlen == 1) { @@ -381,7 +382,7 @@ AudioStreamView::update_rec_regions (framepos_t start, framecnt_t cnt) region->suspend_property_changes (); region->set_position (_trackview.track()->get_capture_start_frame(n)); - region->set_length (nlen); + region->set_length (nlen, 0); region->resume_property_changes (); if (origlen == 1) { diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 8bbc7fee2b..af781f019c 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -534,7 +534,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD /* editing operations that need to be public */ void mouse_add_new_marker (framepos_t where, bool is_cd=false); - void split_regions_at (framepos_t, RegionSelection&); + void split_regions_at (framepos_t, RegionSelection&, const int32_t& sub_num); void split_region_at_points (boost::shared_ptr, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false); RegionSelection get_regions_from_selection_and_mouse (framepos_t); diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index d87388e888..11809af788 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -2323,7 +2323,7 @@ RegionCreateDrag::motion (GdkEvent* event, bool first_move) */ framecnt_t const len = (framecnt_t) fabs ((double)(f - grab_frame () - 1)); - _region->set_length (len < 1 ? 1 : len); + _region->set_length (len < 1 ? 1 : len, _editor->get_grid_music_divisions (event->button.state)); } } } @@ -2934,7 +2934,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move) case EndTrim: for (list::iterator i = _views.begin(); i != _views.end(); ++i) { - bool changed = i->view->trim_end (i->initial_end + dt, non_overlap_trim); + bool changed = i->view->trim_end (i->initial_end + dt, non_overlap_trim, _editor->get_grid_music_divisions (event->button.state)); if (changed && _preserve_fade_anchor) { AudioRegionView* arv = dynamic_cast (i->view); if (arv) { @@ -6333,7 +6333,7 @@ RegionCutDrag::motion (GdkEvent*, bool) } void -RegionCutDrag::finished (GdkEvent*, bool) +RegionCutDrag::finished (GdkEvent* event, bool) { _editor->get_track_canvas()->canvas()->re_enter(); @@ -6347,7 +6347,7 @@ RegionCutDrag::finished (GdkEvent*, bool) return; } - _editor->split_regions_at (pos, rs); + _editor->split_regions_at (pos, rs, _editor->get_grid_music_divisions (event->button.state)); } void diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index dfdd7d995f..86386c21fb 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -1037,7 +1037,7 @@ Editor::button_press_handler_1 (ArdourCanvas::Item* item, GdkEvent* event, ItemT if (!prev) { _drags->set (new RegionCreateDrag (this, item, parent), event); } else { - prev->set_length (t - prev->position ()); + prev->set_length (t - prev->position (), get_grid_music_divisions (event->button.state)); } } } else { diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index d22df0a0bf..80a5ee399e 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -151,7 +151,7 @@ Editor::redo (uint32_t n) } void -Editor::split_regions_at (framepos_t where, RegionSelection& regions) +Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int32_t& sub_num) { bool frozen = false; @@ -226,7 +226,7 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions) if (pl) { pl->clear_changes (); - pl->split_region ((*a)->region(), where); + pl->split_region ((*a)->region(), where, sub_num); _session->add_command (new StatefulDiffCommand (pl)); } @@ -6151,7 +6151,11 @@ Editor::split_region () return; } - split_regions_at (where, rs); + if (snap_musical()) { + split_regions_at (where, rs, get_grid_music_divisions (0)); + } else { + split_regions_at (where, rs, 0); + } } } @@ -7294,7 +7298,8 @@ Editor::insert_time ( (*i)->clear_owned_changes (); if (opt == SplitIntersected) { - (*i)->split (pos); + /* non musical split */ + (*i)->split (pos, 0); } (*i)->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue); diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 9e271cc398..6ffba154f4 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -1872,7 +1872,8 @@ MidiRegionView::step_add_note (uint8_t channel, uint8_t number, uint8_t velocity framepos_t region_end = _region->last_frame(); if (end_frame > region_end) { - _region->set_length (end_frame - _region->position()); + /* XX sets length in beats from audio space. make musical */ + _region->set_length (end_frame - _region->position(), 0); } MidiTimeAxisView* const mtv = dynamic_cast(&trackview); @@ -2877,13 +2878,13 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_ /* Convert the new x position to a frame within the source */ framepos_t current_fr; if (with_snap) { - current_fr = snap_pixel_to_sample (current_x, ensure_snap) + _region->start (); + current_fr = snap_pixel_to_sample (current_x, ensure_snap); } else { - current_fr = trackview.editor().pixel_to_sample (current_x) + _region->start (); + current_fr = trackview.editor().pixel_to_sample (current_x); } /* and then to beats */ - const Evoral::Beats x_beats = region_frames_to_region_beats (current_fr); + const Evoral::Beats x_beats = region_frames_to_region_beats (current_fr + _region->start()); if (at_front && x_beats < canvas_note->note()->end_time()) { note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats - (sign * snap_delta_beats)); @@ -3568,7 +3569,8 @@ MidiRegionView::paste_internal (framepos_t pos, unsigned paste_count, float time DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste extended region from %1 to %2\n", region_end, end_frame)); _region->clear_changes (); - _region->set_length (end_frame - _region->position()); + /* we probably need to get the snap modifier somehow to make this correct for non-musical use */ + _region->set_length (end_frame - _region->position(), trackview.editor().get_grid_music_divisions (0)); trackview.session()->add_command (new StatefulDiffCommand (_region)); } diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index e369c5842d..88947e7e3d 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -610,7 +610,7 @@ MidiStreamView::update_rec_box () /* Update the region being recorded to reflect where we currently are */ boost::shared_ptr region = rec_regions.back().first; - region->set_length (_trackview.track()->current_capture_end () - _trackview.track()->current_capture_start()); + region->set_length (_trackview.track()->current_capture_end () - _trackview.track()->current_capture_start(), 0); MidiRegionView* mrv = dynamic_cast (rec_regions.back().second); mrv->extend_active_notes (); diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc index 074f2a115b..4b709c4e5c 100644 --- a/gtk2_ardour/midi_time_axis.cc +++ b/gtk2_ardour/midi_time_axis.cc @@ -1526,6 +1526,7 @@ MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit, co plist.add (ARDOUR::Properties::name, PBD::basename_nosuffix(src->name())); boost::shared_ptr region = (RegionFactory::create (src, plist)); + /* sets beat position */ region->set_position (pos, sub_num); playlist()->add_region (region, pos); _session->add_command (new StatefulDiffCommand (playlist())); diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index e562e1cb37..a86169b4db 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -289,7 +289,7 @@ class PublicEditor : public Gtkmm2ext::Tabbable { virtual void restore_editing_space () = 0; virtual framepos_t get_preferred_edit_position (Editing::EditIgnoreOption = Editing::EDIT_IGNORE_NONE, bool from_context_menu = false, bool from_outside_canvas = false) = 0; virtual void toggle_meter_updating() = 0; - virtual void split_regions_at (framepos_t, RegionSelection&) = 0; + virtual void split_regions_at (framepos_t, RegionSelection&, const int32_t& sub_num) = 0; virtual void split_region_at_points (boost::shared_ptr, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false) = 0; virtual void mouse_add_new_marker (framepos_t where, bool is_cd=false) = 0; virtual void foreach_time_axis_view (sigc::slot) = 0; diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index b9648bbbc3..4f904d9f2b 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -861,7 +861,7 @@ RegionView::trim_front (framepos_t new_bound, bool no_overlap, const int32_t& su } bool -RegionView::trim_end (framepos_t new_bound, bool no_overlap) +RegionView::trim_end (framepos_t new_bound, bool no_overlap, const int32_t& sub_num) { if (_region->locked()) { return false; @@ -872,7 +872,7 @@ RegionView::trim_end (framepos_t new_bound, bool no_overlap) framepos_t const pre_trim_last_frame = _region->last_frame(); - _region->trim_end ((framepos_t) (new_bound * speed)); + _region->trim_end ((framepos_t) (new_bound * speed), sub_num); if (no_overlap) { // Get the next region on the right of this region and shrink/expand it. @@ -887,7 +887,7 @@ RegionView::trim_end (framepos_t new_bound, bool no_overlap) // Only trim region on the right if the last frame has gone beyond the right region's first frame. if (region_right != 0 && (region_right->first_frame() < _region->last_frame() || regions_touching)) { - region_right->trim_front (_region->last_frame() + 1); + region_right->trim_front (_region->last_frame() + 1, sub_num); } region_changed (ARDOUR::bounds_change); diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 43608c31d1..40485f93cf 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -107,7 +107,7 @@ class RegionView : public TimeAxisViewItem /** Called when a start trim has finished */ virtual void trim_front_ending () {} - bool trim_end (framepos_t, bool); + bool trim_end (framepos_t, bool, const int32_t& sub_num); void move_contents (ARDOUR::frameoffset_t); virtual void thaw_after_trim (); -- cgit v1.2.3