diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-05-15 19:37:35 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-05-15 19:37:35 +0000 |
commit | 5f61efff8f4d80c9576fb8524f37cb8905ba51a8 (patch) | |
tree | 65789ad104dd88209dfb1a518f610457a127650a /gtk2_ardour | |
parent | 5ea9dee73b75b01e6db3a5a97c5a02493b358b00 (diff) |
add note onset detection to the ferret, c/o the aubio-based Onset VAMP plugin (REQUIRES libaubio installed); add toggle-region-opaque menu item for scalable ops on region opacity
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3356 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/ardour.menus | 1 | ||||
-rw-r--r-- | gtk2_ardour/editor_actions.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/rhythm_ferret.cc | 151 | ||||
-rw-r--r-- | gtk2_ardour/rhythm_ferret.h | 25 |
4 files changed, 169 insertions, 10 deletions
diff --git a/gtk2_ardour/ardour.menus b/gtk2_ardour/ardour.menus index 5df1eceef2..91d48477c4 100644 --- a/gtk2_ardour/ardour.menus +++ b/gtk2_ardour/ardour.menus @@ -224,6 +224,7 @@ <menuitem action='boost-region-gain'/> <menuitem action='cut-region-gain'/> <menuitem action='pitch-shift-region'/> + <menuitem action='toggle-opaque-region'/> <separator/> <menuitem action='duplicate-region'/> <menuitem action='multi-duplicate-region'/> diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index d7611eb350..5899293e84 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -365,6 +365,8 @@ Editor::register_actions () ActionManager::region_selection_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "pitch-shift-region", _("Transpose"), mem_fun(*this, &Editor::pitch_shift_regions)); ActionManager::session_sensitive_actions.push_back (act); + act = ActionManager::register_action (editor_actions, "toggle-opaque-region", _("Toggle Opaque"), mem_fun(*this, &Editor::toggle_region_opaque)); + ActionManager::session_sensitive_actions.push_back (act); ActionManager::region_selection_sensitive_actions.push_back (act); act = ActionManager::register_action (editor_actions, "set-fade-in-length", _("Set Fade In Length"), bind (mem_fun(*this, &Editor::set_fade_length), true)); diff --git a/gtk2_ardour/rhythm_ferret.cc b/gtk2_ardour/rhythm_ferret.cc index 92bd2360a0..4a4f3d4ec4 100644 --- a/gtk2_ardour/rhythm_ferret.cc +++ b/gtk2_ardour/rhythm_ferret.cc @@ -4,6 +4,7 @@ #include <pbd/memento_command.h> #include <ardour/transient_detector.h> +#include <ardour/onset_detector.h> #include <ardour/audiosource.h> #include <ardour/audioregion.h> #include <ardour/playlist.h> @@ -32,6 +33,17 @@ static const gchar * _analysis_mode_strings[] = { 0 }; +static const gchar * _onset_function_strings[] = { + N_("Energy Based"), + N_("Spectral Difference"), + N_("High-Frequency Content"), + N_("Complex Domain"), + N_("Phase Deviation"), + N_("Kullback-Liebler"), + N_("Modified Kullback-Liebler"), + 0 +}; + RhythmFerret::RhythmFerret (PublicEditor& e) : ArdourDialog (_("Rhythm Ferret")) , editor (e) @@ -50,6 +62,13 @@ RhythmFerret::RhythmFerret (PublicEditor& e) , sensitivity_scale (sensitivity_adjustment) , sensitivity_label (_("Sensitivity")) , analyze_button (_("Analyze")) + , onset_function_label (_("Detection function")) + , peak_picker_threshold_adjustment (0.3, 0.0, 1.0, 0.01, 0.1) + , peak_picker_threshold_scale (peak_picker_threshold_adjustment) + , peak_picker_label (_("Peak Threshold")) + , silence_threshold_adjustment (-90.0, -120.0, 0.0, 1, 10) + , silence_threshold_scale (silence_threshold_adjustment) + , silence_label (_("Silent Threshold (dB)")) , trigger_gap_adjustment (3, 0, 100, 1, 10) , trigger_gap_spinner (trigger_gap_adjustment) , trigger_gap_label (_("Trigger gap (msecs)")) @@ -78,6 +97,14 @@ RhythmFerret::RhythmFerret (PublicEditor& e) analysis_mode_strings = I18N (_analysis_mode_strings); Gtkmm2ext::set_popdown_strings (analysis_mode_selector, analysis_mode_strings); analysis_mode_selector.set_active_text (analysis_mode_strings.front()); + analysis_mode_selector.signal_changed().connect (mem_fun (*this, &RhythmFerret::analysis_mode_changed)); + + onset_function_strings = I18N (_onset_function_strings); + Gtkmm2ext::set_popdown_strings (onset_detection_function_selector, onset_function_strings); + /* Onset plugin uses complex domain as default function + XXX there should be a non-hacky way to set this + */ + onset_detection_function_selector.set_active_text (onset_function_strings[3]); box = manage (new HBox); box->set_spacing (6); @@ -85,28 +112,50 @@ RhythmFerret::RhythmFerret (PublicEditor& e) box->pack_start (analysis_mode_selector, true, true); ferret_packer.pack_start (*box, false, false); + ferret_packer.pack_start (analysis_packer, false, false); + box = manage (new HBox); box->set_spacing (6); - box->pack_start (detection_threshold_label, false, false); - box->pack_start (detection_threshold_scale, true, true); + box->pack_start (trigger_gap_label, false, false); + box->pack_start (trigger_gap_spinner, false, false); ferret_packer.pack_start (*box, false, false); + ferret_packer.pack_start (analyze_button, false, false); + + analyze_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::run_analysis)); + + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (detection_threshold_label, false, false); + box->pack_start (detection_threshold_scale, true, true); + perc_onset_packer.pack_start (*box, false, false); + box = manage (new HBox); box->set_spacing (6); box->pack_start (sensitivity_label, false, false); box->pack_start (sensitivity_scale, true, true); - ferret_packer.pack_start (*box, false, false); + perc_onset_packer.pack_start (*box, false, false); box = manage (new HBox); box->set_spacing (6); - box->pack_start (trigger_gap_label, false, false); - box->pack_start (trigger_gap_spinner, false, false); - ferret_packer.pack_start (*box, false, false); + box->pack_start (onset_function_label, false, false); + box->pack_start (onset_detection_function_selector, true, true); + note_onset_packer.pack_start (*box, false, false); + + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (peak_picker_label, false, false); + box->pack_start (peak_picker_threshold_scale, true, true); + note_onset_packer.pack_start (*box, false, false); + + box = manage (new HBox); + box->set_spacing (6); + box->pack_start (silence_label, false, false); + box->pack_start (silence_threshold_scale, true, true); + note_onset_packer.pack_start (*box, false, false); - ferret_packer.pack_start (analyze_button, false, false); + analysis_mode_changed (); - analyze_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::run_analysis)); - ferret_frame.add (ferret_packer); logo = manage (new Gtk::Image (::get_icon (X_("ferret_02")))); @@ -137,12 +186,30 @@ RhythmFerret::~RhythmFerret() } } +void +RhythmFerret::analysis_mode_changed () +{ + analysis_packer.children().clear (); + + switch (get_analysis_mode()) { + case PercussionOnset: + analysis_packer.pack_start (perc_onset_packer); + break; + + case NoteOnset: + analysis_packer.pack_start (note_onset_packer); + break; + } + + analysis_packer.show_all (); +} + RhythmFerret::AnalysisMode RhythmFerret::get_analysis_mode () const { string str = analysis_mode_selector.get_active_text (); - if (str == _(_analysis_mode_strings[(int) NoteOnset])) { + if (str == analysis_mode_strings[(int) NoteOnset]) { return NoteOnset; } @@ -184,6 +251,9 @@ RhythmFerret::run_analysis () case PercussionOnset: run_percussion_onset_analysis (rd, (*i)->region()->position(), current_results); break; + case NoteOnset: + run_note_onset_analysis (rd, (*i)->region()->position(), current_results); + break; default: break; } @@ -232,6 +302,67 @@ RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readabl return 0; } +int +RhythmFerret::get_note_onset_function () +{ + string txt = onset_detection_function_selector.get_active_text(); + + for (int n = 0; _onset_function_strings[n]; ++n) { + /* compare translated versions */ + if (txt == onset_function_strings[n]) { + return n; + } + } + fatal << string_compose (_("programming error: %1 (%2)"), X_("illegal note onset function string"), txt) + << endmsg; + /*NOTREACHED*/ + return -1; +} + +int +RhythmFerret::run_note_onset_analysis (boost::shared_ptr<Readable> readable, nframes64_t offset, AnalysisFeatureList& results) +{ + try { + OnsetDetector t (session->frame_rate()); + + for (uint32_t i = 0; i < readable->n_channels(); ++i) { + + AnalysisFeatureList these_results; + + t.reset (); + + t.set_function (get_note_onset_function()); + t.set_silence_threshold (silence_threshold_adjustment.get_value()); + t.set_peak_threshold (peak_picker_threshold_adjustment.get_value()); + + if (t.run ("", readable.get(), i, these_results)) { + continue; + } + + /* translate all transients to give absolute position */ + + for (AnalysisFeatureList::iterator x = these_results.begin(); x != these_results.end(); ++x) { + (*x) += offset; + } + + /* merge */ + + results.insert (results.end(), these_results.begin(), these_results.end()); + these_results.clear (); + } + + } catch (failed_constructor& err) { + error << "Could not load note onset detection plugin" << endmsg; + return -1; + } + + if (!results.empty()) { + OnsetDetector::cleanup_onsets (results, session->frame_rate(), trigger_gap_adjustment.get_value()); + } + + return 0; +} + void RhythmFerret::do_action () { diff --git a/gtk2_ardour/rhythm_ferret.h b/gtk2_ardour/rhythm_ferret.h index 2ddb2a4ffd..91c10695ad 100644 --- a/gtk2_ardour/rhythm_ferret.h +++ b/gtk2_ardour/rhythm_ferret.h @@ -71,6 +71,9 @@ class RhythmFerret : public ArdourDialog { Gtk::VBox ferret_packer; Gtk::ComboBoxText analysis_mode_selector; Gtk::Label analysis_mode_label; + + /* transient detection widgets */ + Gtk::Adjustment detection_threshold_adjustment; Gtk::HScale detection_threshold_scale; Gtk::Label detection_threshold_label; @@ -78,22 +81,44 @@ class RhythmFerret : public ArdourDialog { Gtk::HScale sensitivity_scale; Gtk::Label sensitivity_label; Gtk::Button analyze_button; + Gtk::VBox perc_onset_packer; + + /* onset detection widgets */ + + Gtk::ComboBoxText onset_detection_function_selector; + Gtk::Label onset_function_label; + Gtk::Adjustment peak_picker_threshold_adjustment; + Gtk::HScale peak_picker_threshold_scale; + Gtk::Label peak_picker_label; + Gtk::Adjustment silence_threshold_adjustment; + Gtk::HScale silence_threshold_scale; + Gtk::Label silence_label; + Gtk::VBox note_onset_packer; + + /* generic stuff */ + Gtk::Adjustment trigger_gap_adjustment; Gtk::SpinButton trigger_gap_spinner; Gtk::Label trigger_gap_label; + Gtk::VBox analysis_packer; + Gtk::Label operation_clarification_label; Gtk::Button action_button; std::vector<std::string> analysis_mode_strings; + std::vector<std::string> onset_function_strings; ARDOUR::AnalysisFeatureList current_results; AnalysisMode get_analysis_mode () const; Action get_action() const; + void analysis_mode_changed (); + int get_note_onset_function (); void run_analysis (); int run_percussion_onset_analysis (boost::shared_ptr<ARDOUR::Readable> region, nframes64_t offset, ARDOUR::AnalysisFeatureList& results); + int run_note_onset_analysis (boost::shared_ptr<ARDOUR::Readable> region, nframes64_t offset, ARDOUR::AnalysisFeatureList& results); void do_action (); void do_split_action (); |