diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-01-26 02:57:10 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-01-26 02:57:10 +0000 |
commit | 1e51f099fd7baef957204d46bee302908d65de6b (patch) | |
tree | efc8fbf95a139ee90508ad6f6ea17ab652457c5a | |
parent | 315dd3d7705d314b935a7a35007347a41e0f9bfd (diff) |
first pass attempt at tab-to-transient (to be improved)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2970 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r-- | gtk2_ardour/ardour.menus | 3 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 6 | ||||
-rw-r--r-- | gtk2_ardour/editor_ops.cc | 52 | ||||
-rw-r--r-- | gtk2_ardour/rhythm_ferret.cc | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/audioregion.h | 7 | ||||
-rw-r--r-- | libs/ardour/audioregion.cc | 89 |
7 files changed, 134 insertions, 27 deletions
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 87e300de0b..bcf4ada3e7 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -44,6 +44,9 @@ <menuitem action='GotoStart'/> <menuitem action='GotoEnd'/> <separator/> + <menuitem action='tab-to-transient-forwards'/> + <menuitem action='tab-to-transient-backwards'/> + <separator/> <menuitem action='Record'/> <separator/> <menuitem action='TransitionToRoll'/> diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 4c5dce6fad..2b89163687 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -987,6 +987,8 @@ class Editor : public PublicEditor void denormalize_region (); void adjust_region_scale_amplitude (bool up); + void tab_to_transient (bool forward); + void use_region_as_bar (); void use_range_as_bar (); diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 09414c66ef..8ec21850c1 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -369,6 +369,12 @@ Editor::register_actions () act = ActionManager::register_action (editor_actions, "toggle-rhythm-ferret", _("Rhythm Ferret"), mem_fun(*this, &Editor::show_rhythm_ferret)); ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "tab-to-transient-forwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), true)); + ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "tab-to-transient-backwards", _("Move Forward to Transient"), bind (mem_fun(*this, &Editor::tab_to_transient), false)); + ActionManager::session_sensitive_actions.push_back (act); + + act = ActionManager::register_action (editor_actions, "crop", _("Crop"), mem_fun(*this, &Editor::crop_region_to_selection)); ActionManager::session_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "insert-chunk", _("Insert Chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index da6774c560..2755fcc764 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -5127,3 +5127,55 @@ Editor::split_region_at_points (boost::shared_ptr<Region> r, vector<nframes64_t> session->add_command (new MementoCommand<Playlist>(*pl, &before, &after)); } +void +Editor::tab_to_transient (bool forward) +{ + + vector<nframes64_t> positions; + + if (!session) { + return; + } + + ExclusiveRegionSelection esr (*this, entered_regionview); + + if (selection->regions.empty()) { + return; + } + + boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (selection->regions.front()->region()); + + if (!ar) { + return; + } + + ar->get_transients (positions); + nframes64_t pos = session->audible_frame (); + + if (forward) { + vector<nframes64_t>::iterator x; + + for (x = positions.begin(); x != positions.end(); ++x) { + if ((*x) > pos) { + break; + } + } + + if (x != positions.end ()) { + session->request_locate (*x); + } + + } else { + vector<nframes64_t>::reverse_iterator x; + + for (x = positions.rbegin(); x != positions.rend(); ++x) { + if ((*x) < pos) { + break; + } + } + + if (x != positions.rend ()) { + session->request_locate (*x); + } + } +} diff --git a/gtk2_ardour/rhythm_ferret.cc b/gtk2_ardour/rhythm_ferret.cc index cc771a3f15..4cdb408076 100644 --- a/gtk2_ardour/rhythm_ferret.cc +++ b/gtk2_ardour/rhythm_ferret.cc @@ -222,7 +222,7 @@ RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readabl results.insert (results.end(), these_results.begin(), these_results.end()); } - if (!results.empty() && (existing_results || readable->n_channels() > 1)) { + if (!results.empty()) { /* now resort to bring transients from different channels together */ diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 5bc59a715a..ba14d05afe 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -148,7 +148,7 @@ class AudioRegion : public Region void set_playlist (boost::weak_ptr<Playlist>); - int get_transients (std::vector<nframes64_t>&); + int get_transients (std::vector<nframes64_t>&, bool force_new = false); private: friend class RegionFactory; @@ -207,6 +207,11 @@ class AudioRegion : public Region protected: int set_live_state (const XMLNode&, Change&, bool send); + + std::vector<nframes64_t> _transients; + bool valid_transients; + void invalidate_transients (); + void cleanup_transients (std::vector<nframes64_t>&); }; } /* namespace ARDOUR */ diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 01728a8c01..fd39e05636 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -80,6 +80,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, n } _scale_amplitude = 1.0; + valid_transients = false; set_default_fades (); set_default_envelope (); @@ -105,6 +106,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, nframes_t start, n } _scale_amplitude = 1.0; + valid_transients = false; set_default_fades (); set_default_envelope (); @@ -132,6 +134,7 @@ AudioRegion::AudioRegion (const SourceList& srcs, nframes_t start, nframes_t len } _scale_amplitude = 1.0; + valid_transients = false; set_default_fades (); set_default_envelope (); @@ -200,6 +203,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, nframes_t } _scale_amplitude = other->_scale_amplitude; + valid_transients = false; listen_to_my_curves (); } @@ -237,6 +241,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other) } _scale_amplitude = other->_scale_amplitude; + valid_transients = false; _envelope = other->_envelope; _fade_in_disabled = 0; @@ -261,6 +266,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> src, const XMLNode& nod } set_default_fades (); + valid_transients = false; if (set_state (node)) { throw failed_constructor(); @@ -301,6 +307,7 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node) set_default_fades (); _scale_amplitude = 1.0; + valid_transients = false; if (set_state (node)) { throw failed_constructor(); @@ -324,6 +331,13 @@ AudioRegion::~AudioRegion () } void +AudioRegion::invalidate_transients () +{ + valid_transients = false; + _transients.clear (); +} + +void AudioRegion::listen_to_my_curves () { _envelope.StateChanged.connect (mem_fun (*this, &AudioRegion::envelope_changed)); @@ -1503,16 +1517,50 @@ AudioRegion::set_playlist (boost::weak_ptr<Playlist> wpl) } } +void +AudioRegion::cleanup_transients (vector<nframes64_t>& t) +{ + sort (t.begin(), t.end()); + + /* remove duplicates or other things that are too close */ + + vector<nframes64_t>::iterator i = t.begin(); + nframes64_t curr = (*i); + + /* XXX force a 3msec gap - use a config variable */ + + nframes64_t gap_frames = (nframes64_t) floor (3.0 * (playlist()->session().frame_rate() / 1000.0)); + + ++i; + + while (i != t.end()) { + if (((*i) == curr) || (((*i) - curr) < gap_frames)) { + i = t.erase (i); + } else { + ++i; + curr = *i; + } + } +} + int -AudioRegion::get_transients (vector<nframes64_t>& results) +AudioRegion::get_transients (vector<nframes64_t>& results, bool force_new) { if (!playlist()) { return -1; } + if (valid_transients && !force_new) { + results = _transients; + return 0; + } + TransientDetector t (playlist()->session().frame_rate()); bool existing_results = !results.empty(); + _transients.clear (); + valid_transients = false; + for (uint32_t i = 0; i < n_channels(); ++i) { vector<nframes64_t> these_results; @@ -1531,36 +1579,27 @@ AudioRegion::get_transients (vector<nframes64_t>& results) /* merge */ - results.insert (results.end(), these_results.begin(), these_results.end()); + _transients.insert (_transients.end(), these_results.begin(), these_results.end()); } - - if (!results.empty() && (existing_results || n_channels() > 1)) { - - /* now resort to bring transients from different channels together */ - - sort (results.begin(), results.end()); - - /* remove duplicates or other things that are too close */ - - vector<nframes64_t>::iterator i = results.begin(); - nframes64_t curr = (*i); - - /* XXX force a 3msec gap - use a config variable */ + + if (!results.empty()) { + if (existing_results) { + + /* merge our transients into the existing ones, then clean up + those. + */ - nframes64_t gap_frames = (nframes64_t) floor (3.0 * (playlist()->session().frame_rate() / 1000.0)); + results.insert (results.end(), _transients.begin(), _transients.end()); + cleanup_transients (results); + } - ++i; + /* make sure ours are clean too */ - while (i != results.end()) { - if (((*i) == curr) || (((*i) - curr) < gap_frames)) { - i = results.erase (i); - } else { - ++i; - curr = *i; - } - } + cleanup_transients (_transients); } + valid_transients = true; + return 0; } |