diff options
author | nick_m <mainsbridge@gmail.com> | 2016-06-16 00:18:27 +1000 |
---|---|---|
committer | nick_m <mainsbridge@gmail.com> | 2016-07-10 02:18:36 +1000 |
commit | 94e0a15325278ec26dbeba4990a0e883db859338 (patch) | |
tree | e4d97368112f92ba8a66c673b68c68f7a76b025a | |
parent | 2d5238d87581bc0ff9dcaaa8aad9e255b5d9c370 (diff) |
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.
-rw-r--r-- | gtk2_ardour/audio_streamview.cc | 5 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_drag.cc | 8 | ||||
-rw-r--r-- | gtk2_ardour/editor_mouse.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 13 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 12 | ||||
-rw-r--r-- | gtk2_ardour/midi_streamview.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/midi_time_axis.cc | 1 | ||||
-rw-r--r-- | gtk2_ardour/public_editor.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/region_view.cc | 6 | ||||
-rw-r--r-- | gtk2_ardour/region_view.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/audioregion.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_region.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/playlist.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/region.h | 12 | ||||
-rw-r--r-- | libs/ardour/ardour/region_factory.h | 4 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 4 | ||||
-rw-r--r-- | libs/ardour/audioregion.cc | 4 | ||||
-rw-r--r-- | libs/ardour/midi_region.cc | 47 | ||||
-rw-r--r-- | libs/ardour/midi_state_tracker.cc | 2 | ||||
-rw-r--r-- | libs/ardour/midi_stretch.cc | 4 | ||||
-rw-r--r-- | libs/ardour/playlist.cc | 16 | ||||
-rw-r--r-- | libs/ardour/rb_effect.cc | 4 | ||||
-rw-r--r-- | libs/ardour/region.cc | 37 | ||||
-rw-r--r-- | libs/ardour/region_factory.cc | 12 |
25 files changed, 115 insertions, 102 deletions
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::Region>, 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<DraggingView>::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<AudioRegionView*> (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<MidiTimeAxisView*>(&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<ARDOUR::Region> 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<MidiRegionView*> (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> 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::Region>, 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<void,TimeAxisView&>) = 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 (); diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 2d74d91482..bed64615b5 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -180,7 +180,7 @@ class LIBARDOUR_API AudioRegion : public Region AudioRegion (boost::shared_ptr<AudioSource>); AudioRegion (const SourceList &); AudioRegion (boost::shared_ptr<const AudioRegion>); - AudioRegion (boost::shared_ptr<const AudioRegion>, frameoffset_t offset); + AudioRegion (boost::shared_ptr<const AudioRegion>, frameoffset_t offset, const int32_t& sub_num); AudioRegion (boost::shared_ptr<const AudioRegion>, const SourceList&); AudioRegion (SourceList &); diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 3a097c907e..9de79a9513 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -115,7 +115,7 @@ class LIBARDOUR_API MidiRegion : public Region MidiRegion (const SourceList&); MidiRegion (boost::shared_ptr<const MidiRegion>); - MidiRegion (boost::shared_ptr<const MidiRegion>, frameoffset_t offset); + MidiRegion (boost::shared_ptr<const MidiRegion>, frameoffset_t offset, const int32_t& sub_num = 0); framecnt_t _read_at (const SourceList&, Evoral::EventSink<framepos_t>& dst, framepos_t position, @@ -131,11 +131,11 @@ class LIBARDOUR_API MidiRegion : public Region void recompute_at_start (); void recompute_at_end (); - void set_position_internal (framepos_t pos, bool allow_bbt_recompute); - void set_length_internal (framecnt_t len); + void set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t& sub_num); + void set_length_internal (framecnt_t len, const int32_t& sub_num); void set_start_internal (framecnt_t, const int32_t& sub_num); void trim_to_internal (framepos_t position, framecnt_t length, const int32_t& sub_num); - void update_length_beats (); + void update_length_beats (const int32_t& sub_num); void model_changed (); void model_automation_state_changed (Evoral::Parameter const &); diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 7b19a08f6a..0a5f5e4ddc 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -134,8 +134,8 @@ public: void get_region_list_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&); void get_source_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&); void replace_region (boost::shared_ptr<Region> old, boost::shared_ptr<Region> newr, framepos_t pos); - void split_region (boost::shared_ptr<Region>, framepos_t position); - void split (framepos_t at); + void split_region (boost::shared_ptr<Region>, framepos_t position, const int32_t& sub_num); + void split (framepos_t at, const int32_t& sub_num); void shift (framepos_t at, frameoffset_t distance, bool move_intersected, bool ignore_music_glue); void partition (framepos_t start, framepos_t end, bool cut = false); void duplicate (boost::shared_ptr<Region>, framepos_t position, float times); @@ -380,7 +380,7 @@ public: void begin_undo (); void end_undo (); - void _split_region (boost::shared_ptr<Region>, framepos_t position); + void _split_region (boost::shared_ptr<Region>, framepos_t position, const int32_t& sub_num); typedef std::pair<boost::shared_ptr<Region>, boost::shared_ptr<Region> > TwoRegions; diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index e0dd159ce5..ec4f559a87 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -171,9 +171,9 @@ class LIBARDOUR_API Region Trimmable::CanTrim can_trim () const; PositionLockStyle position_lock_style () const { return _position_lock_style; } - double beat () { return _beat; } + double beat () const { return _beat; } void set_position_lock_style (PositionLockStyle ps); - void recompute_position_from_lock_style (); + void recompute_position_from_lock_style (const int32_t& sub_num); void suspend_property_changes (); @@ -205,7 +205,7 @@ class LIBARDOUR_API Region /* EDITING OPERATIONS */ - void set_length (framecnt_t); + void set_length (framecnt_t, const int32_t& sub_num); void set_start (framepos_t); void set_position (framepos_t, int32_t sub_num = 0); void set_initial_position (framepos_t); @@ -339,7 +339,7 @@ class LIBARDOUR_API Region Region (boost::shared_ptr<const Region>); /** Construct a region from another region, at an offset within that region */ - Region (boost::shared_ptr<const Region>, frameoffset_t start_offset); + Region (boost::shared_ptr<const Region>, frameoffset_t start_offset, const int32_t& sub_num); /** Construct a region as a copy of another region, but with different sources */ Region (boost::shared_ptr<const Region>, const SourceList&); @@ -356,8 +356,8 @@ class LIBARDOUR_API Region void send_change (const PBD::PropertyChange&); virtual int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal); void post_set (const PBD::PropertyChange&); - virtual void set_position_internal (framepos_t pos, bool allow_bbt_recompute); - virtual void set_length_internal (framecnt_t); + virtual void set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t& sub_num); + virtual void set_length_internal (framecnt_t, const int32_t& sub_num); virtual void set_start_internal (framecnt_t, const int32_t& sub_num = 0); bool verify_start_and_length (framepos_t, framecnt_t&); void first_edit (); diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h index 08d9affc91..e331de2b00 100644 --- a/libs/ardour/ardour/region_factory.h +++ b/libs/ardour/ardour/region_factory.h @@ -59,7 +59,7 @@ public: static PBD::Signal1<void,boost::shared_ptr<Region> > CheckNewRegion; /** create a "pure copy" of Region @param other */ - static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false); + static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false, const int32_t& sub_num = 0); /** create a region from a single Source */ static boost::shared_ptr<Region> create (boost::shared_ptr<Source>, @@ -73,7 +73,7 @@ public: const PBD::PropertyList&, bool announce = true); /** create a copy of @param other starting at @param offset within @param other */ static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, frameoffset_t offset, - const PBD::PropertyList&, bool announce = true); + const PBD::PropertyList&, bool announce = true, const int32_t& sub_num = 0); /** create a "copy" of @param other but using a different set of sources @param srcs */ static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, const SourceList& srcs, const PBD::PropertyList&, bool announce = true); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index cab7f5faf8..e5ba4e8dcd 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -377,9 +377,9 @@ AudioDiskstream::use_destructive_playlist () throw failed_constructor(); } - /* be sure to stretch the region out to the maximum length */ + /* be sure to stretch the region out to the maximum length (non-musical)*/ - region->set_length (max_framepos - region->position()); + region->set_length (max_framepos - region->position(), 0); uint32_t n; ChannelList::iterator chan; diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 60a6282181..dff261a9df 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -279,8 +279,8 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other) assert (_sources.size() == _master_sources.size()); } -AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t offset) - : Region (other, offset) +AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t offset, const int32_t& sub_num) + : Region (other, offset, sub_num) , AUDIOREGION_COPY_STATE (other) /* As far as I can see, the _envelope's times are relative to region position, and have nothing to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset. diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index 26a8509aca..4d4c081c24 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -102,15 +102,14 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other) } /** Create a new MidiRegion that is part of an existing one */ -MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t offset) - : Region (other, offset) +MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t offset, const int32_t& sub_num) + : Region (other, offset, sub_num) , _start_beats (Properties::start_beats, Evoral::Beats()) , _length_beats (Properties::length_beats, other->_length_beats) { - BeatsFramesConverter bfc (_session.tempo_map(), other->_position); - Evoral::Beats const offset_beats = bfc.from (offset); - - _start_beats = other->_start_beats.val() + offset_beats; + const double offset_beat = _session.tempo_map().exact_beat_at_frame (other->_position + offset, sub_num) - other->beat(); + _start_beats = Evoral::Beats (other->_start_beats.val().to_double() + offset_beat); + update_length_beats (sub_num); register_properties (); assert(_name.val().find("/") == string::npos); @@ -173,7 +172,8 @@ MidiRegion::post_set (const PropertyChange& pc) Region::post_set (pc); if (pc.contains (Properties::length) && !pc.contains (Properties::length_beats)) { - update_length_beats (); + /* update non-musically */ + update_length_beats (0); } else if (pc.contains (Properties::start) && !pc.contains (Properties::start_beats)) { set_start_beats_from_start_frames (); } @@ -186,10 +186,10 @@ MidiRegion::set_start_beats_from_start_frames () } void -MidiRegion::set_length_internal (framecnt_t len) +MidiRegion::set_length_internal (framecnt_t len, const int32_t& sub_num) { - Region::set_length_internal (len); - update_length_beats (); + Region::set_length_internal (len, sub_num); + update_length_beats (sub_num); } void @@ -198,26 +198,27 @@ MidiRegion::update_after_tempo_map_change (bool /* send */) Region::update_after_tempo_map_change (false); /* _start has now been updated. */ - _length = _session.tempo_map().framepos_plus_beats (_position, _length_beats) - _position; + _length = _session.tempo_map().frame_at_beat (beat() + _length_beats.val().to_double()) - _position; PropertyChange s_and_l; s_and_l.add (Properties::start); s_and_l.add (Properties::length); + s_and_l.add (Properties::length_beats); s_and_l.add (Properties::position); send_change (s_and_l); } void -MidiRegion::update_length_beats () +MidiRegion::update_length_beats (const int32_t& sub_num) { - _length_beats = Evoral::Beats (_session.tempo_map().beat_at_frame (_position + _length) - beat()); + _length_beats = Evoral::Beats (_session.tempo_map().exact_beat_at_frame (_position + _length, sub_num) - beat()); } void -MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute) +MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t& sub_num) { - Region::set_position_internal (pos, allow_bbt_recompute); + Region::set_position_internal (pos, allow_bbt_recompute, sub_num); /* set _start to new position in tempo map */ _start = _position - _session.tempo_map().frame_at_beat (beat() - _start_beats.val().to_double()); @@ -225,7 +226,7 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute) /* leave _length_beats alone, and change _length to reflect the state of things at the new position (tempo map may dictate a different number of frames). */ - Region::set_length_internal (_session.tempo_map().frame_at_beat (beat() + _length_beats.val().to_double()) - _position); + Region::set_length_internal (_session.tempo_map().frame_at_beat (beat() + _length_beats.val().to_double()) - _position, sub_num); } framecnt_t @@ -328,7 +329,10 @@ MidiRegion::set_state (const XMLNode& node, int version) int ret = Region::set_state (node, version); if (ret == 0) { - update_length_beats (); + /* set length beats to the frame (non-musical) */ + if (position_lock_style() == AudioTime) { + update_length_beats (0); + } } return ret; @@ -490,11 +494,11 @@ MidiRegion::trim_to_internal (framepos_t position, framecnt_t length, const int3 */ if (_position != position) { - set_position_internal (position, true); + set_position_internal (position, true, sub_num); what_changed.add (Properties::position); } - const double new_beat = _session.tempo_map().beat_at_frame (position); + const double new_beat = _session.tempo_map().exact_beat_at_frame (position, sub_num); const double new_start_beat = _start_beats.val().to_double() + beat_delta; new_start = _position - _session.tempo_map().frame_at_beat (new_beat - new_start_beat); @@ -511,11 +515,10 @@ MidiRegion::trim_to_internal (framepos_t position, framecnt_t length, const int3 what_changed.add (Properties::start); } - - if (_length != length) { - set_length_internal (length); + set_length_internal (length, sub_num); what_changed.add (Properties::length); + what_changed.add (Properties::length_beats); } set_whole_file (false); diff --git a/libs/ardour/midi_state_tracker.cc b/libs/ardour/midi_state_tracker.cc index 0403461c73..884d1e16f0 100644 --- a/libs/ardour/midi_state_tracker.cc +++ b/libs/ardour/midi_state_tracker.cc @@ -55,7 +55,7 @@ MidiStateTracker::add (uint8_t note, uint8_t chn) ++_active_notes[note + 128 * chn]; if (_active_notes[note+128 * chn] > 1) { - cerr << this << " note " << (int) note << '/' << (int) chn << " was already on, now at " << (int) _active_notes[note+128*chn] << endl; + //cerr << this << " note " << (int) note << '/' << (int) chn << " was already on, now at " << (int) _active_notes[note+128*chn] << endl; } DEBUG_TRACE (PBD::DEBUG::MidiTrackers, string_compose ("%1 ON %2/%3 voices %5 total on %4\n", diff --git a/libs/ardour/midi_stretch.cc b/libs/ardour/midi_stretch.cc index 71ffcc21e1..7258f49a1c 100644 --- a/libs/ardour/midi_stretch.cc +++ b/libs/ardour/midi_stretch.cc @@ -114,8 +114,8 @@ MidiStretch::run (boost::shared_ptr<Region> r, Progress*) new_src->copy_interpolation_from (src); const int ret = finish (region, nsrcs, new_name); - - results[0]->set_length((framecnt_t) floor (r->length() * _request.time_fraction)); + /* non-musical */ + results[0]->set_length((framecnt_t) floor (r->length() * _request.time_fraction), 0); return ret; } diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 58405e4755..3797f2f0c1 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -1384,12 +1384,12 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float /* times */) /* XXX: may not be necessary; Region::post_set should do this, I think */ for (RegionList::iterator r = fixup.begin(); r != fixup.end(); ++r) { - (*r)->recompute_position_from_lock_style (); + (*r)->recompute_position_from_lock_style (0); } } void - Playlist::split (framepos_t at) + Playlist::split (framepos_t at, const int32_t& sub_num) { RegionWriteLock rlock (this); RegionList copy (regions.rlist()); @@ -1398,19 +1398,19 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float /* times */) */ for (RegionList::iterator r = copy.begin(); r != copy.end(); ++r) { - _split_region (*r, at); + _split_region (*r, at, sub_num); } } void - Playlist::split_region (boost::shared_ptr<Region> region, framepos_t playlist_position) + Playlist::split_region (boost::shared_ptr<Region> region, framepos_t playlist_position, const int32_t& sub_num) { RegionWriteLock rl (this); - _split_region (region, playlist_position); + _split_region (region, playlist_position, sub_num); } void - Playlist::_split_region (boost::shared_ptr<Region> region, framepos_t playlist_position) + Playlist::_split_region (boost::shared_ptr<Region> region, framepos_t playlist_position, const int32_t& sub_num) { if (!region->covers (playlist_position)) { return; @@ -1451,7 +1451,7 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float /* times */) since it supplies that offset to the Region constructor, which is necessary to get audio region gain envelopes right. */ - left = RegionFactory::create (region, 0, plist); + left = RegionFactory::create (region, 0, plist, true, sub_num); } RegionFactory::region_name (after_name, region->name(), false); @@ -1466,7 +1466,7 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float /* times */) plist.add (Properties::layer, region->layer ()); /* same note as above */ - right = RegionFactory::create (region, before, plist); + right = RegionFactory::create (region, before, plist, true, sub_num); } add_region_internal (left, region->position()); diff --git a/libs/ardour/rb_effect.cc b/libs/ardour/rb_effect.cc index 03ce918f31..9ae909780a 100644 --- a/libs/ardour/rb_effect.cc +++ b/libs/ardour/rb_effect.cc @@ -352,9 +352,9 @@ RBEffect::run (boost::shared_ptr<Region> r, Progress* progress) shift); (*x)->set_master_sources (region->master_sources()); /* multiply the old (possibly previously stretched) region length by the extra - stretch this time around to get its new length + stretch this time around to get its new length. this is a non-music based edit atm. */ - (*x)->set_length ((*x)->length() * tsr.time_fraction); + (*x)->set_length ((*x)->length() * tsr.time_fraction, 0); } /* stretch region gain envelope */ diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index 5fb5b30014..d308ea7797 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -320,7 +320,7 @@ Region::Region (boost::shared_ptr<const Region> other) the start within \a other is given by \a offset (i.e. relative to the start of \a other's sources, the start is \a offset + \a other.start() */ -Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset) +Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, const int32_t& sub_num) : SessionObject(other->session(), other->name()) , _type (other->data_type()) , REGION_COPY_STATE (other) @@ -344,7 +344,7 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset) set_master_sources (other->_master_sources); _start = other->_start + offset; - _beat = _session.tempo_map().beat_at_frame (_position); + _beat = _session.tempo_map().exact_beat_at_frame (_position, sub_num); /* if the other region had a distinct sync point set, then continue to use it as best we can. @@ -419,7 +419,7 @@ Region::set_name (const std::string& str) } void -Region::set_length (framecnt_t len) +Region::set_length (framecnt_t len, const int32_t& sub_num) { //cerr << "Region::set_length() len = " << len << endl; if (locked()) { @@ -441,7 +441,7 @@ Region::set_length (framecnt_t len) } - set_length_internal (len); + set_length_internal (len, sub_num); _whole_file = false; first_edit (); maybe_uncopy (); @@ -456,7 +456,7 @@ Region::set_length (framecnt_t len) } void -Region::set_length_internal (framecnt_t len) +Region::set_length_internal (framecnt_t len, const int32_t& sub_num) { _last_length = _length; _length = len; @@ -558,7 +558,8 @@ Region::update_after_tempo_map_change (bool send) } const framepos_t pos = _session.tempo_map().frame_at_beat (_beat); - set_position_internal (pos, false); + /* we have _beat. update frame position non-musically */ + set_position_internal (pos, false, 0); /* do this even if the position is the same. this helps out a GUI that has moved its representation already. @@ -577,11 +578,11 @@ Region::set_position (framepos_t pos, int32_t sub_num) } if (sub_num == 0) { - set_position_internal (pos, true); + set_position_internal (pos, true, 0); } else { double beat = _session.tempo_map().exact_beat_at_frame (pos, sub_num); _beat = beat; - set_position_internal (pos, false); + set_position_internal (pos, false, sub_num); } /* do this even if the position is the same. this helps out @@ -629,7 +630,7 @@ Region::set_initial_position (framepos_t pos) _length = max_framepos - _position; } - recompute_position_from_lock_style (); + recompute_position_from_lock_style (0); /* ensure that this move doesn't cause a range move */ _last_position = _position; } @@ -642,7 +643,7 @@ Region::set_initial_position (framepos_t pos) } void -Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute) +Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t& sub_num) { /* We emit a change of Properties::position even if the position hasn't changed (see Region::set_position), so we must always set this up so that @@ -654,7 +655,7 @@ Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute) _position = pos; if (allow_bbt_recompute) { - recompute_position_from_lock_style (); + recompute_position_from_lock_style (sub_num); } /* check that the new _position wouldn't make the current length impossible - if so, change the length. @@ -669,10 +670,10 @@ Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute) } void -Region::recompute_position_from_lock_style () +Region::recompute_position_from_lock_style (const int32_t& sub_num) { if (_position_lock_style == MusicTime) { - _beat = _session.tempo_map().beat_at_frame (_position); + _beat = _session.tempo_map().exact_beat_at_frame (_position, sub_num); } } @@ -702,8 +703,8 @@ Region::nudge_position (frameoffset_t n) new_position += n; } } - - set_position_internal (new_position, true); + /* assumes non-musical nudge */ + set_position_internal (new_position, true, 0); send_change (Properties::position); } @@ -949,7 +950,7 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, const int32_t& if (!property_changes_suspended()) { _last_position = _position; } - set_position_internal (position, true); + set_position_internal (position, true, sub_num); what_changed.add (Properties::position); } @@ -957,7 +958,7 @@ Region::trim_to_internal (framepos_t position, framecnt_t length, const int32_t& if (!property_changes_suspended()) { _last_length = _length; } - set_length_internal (length); + set_length_internal (length, sub_num); what_changed.add (Properties::length); } @@ -1846,7 +1847,7 @@ void Region::post_set (const PropertyChange& pc) { if (pc.contains (Properties::position)) { - recompute_position_from_lock_style (); + recompute_position_from_lock_style (0); } } diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc index 549d0a252e..fab9d8aaa8 100644 --- a/libs/ardour/region_factory.cc +++ b/libs/ardour/region_factory.cc @@ -46,7 +46,7 @@ std::map<std::string, PBD::ID> RegionFactory::region_name_map; RegionFactory::CompoundAssociations RegionFactory::_compound_associations; boost::shared_ptr<Region> -RegionFactory::create (boost::shared_ptr<const Region> region, bool announce) +RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, const int32_t& sub_num) { boost::shared_ptr<Region> ret; boost::shared_ptr<const AudioRegion> ar; @@ -54,7 +54,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce) if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) { - ret = boost::shared_ptr<Region> (new AudioRegion (ar, 0)); + ret = boost::shared_ptr<Region> (new AudioRegion (ar, 0, sub_num)); } else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) { @@ -71,7 +71,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce) source->set_ancestor_name(mr->sources().front()->name()); ret = mr->clone(source); } else { - ret = boost::shared_ptr<Region> (new MidiRegion (mr, 0)); + ret = boost::shared_ptr<Region> (new MidiRegion (mr, 0, sub_num)); } } else { @@ -144,7 +144,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli } boost::shared_ptr<Region> -RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, const PropertyList& plist, bool announce) +RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, const PropertyList& plist, bool announce, const int32_t& sub_num) { boost::shared_ptr<Region> ret; boost::shared_ptr<const AudioRegion> other_a; @@ -152,11 +152,11 @@ RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, c if ((other_a = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) { - ret = boost::shared_ptr<Region> (new AudioRegion (other_a, offset)); + ret = boost::shared_ptr<Region> (new AudioRegion (other_a, offset, sub_num)); } else if ((other_m = boost::dynamic_pointer_cast<MidiRegion>(region)) != 0) { - ret = boost::shared_ptr<Region> (new MidiRegion (other_m, offset)); + ret = boost::shared_ptr<Region> (new MidiRegion (other_m, offset, sub_num)); } else { fatal << _("programming error: RegionFactory::create() called with unknown Region type") |