summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2008-05-15 19:37:35 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2008-05-15 19:37:35 +0000
commit5f61efff8f4d80c9576fb8524f37cb8905ba51a8 (patch)
tree65789ad104dd88209dfb1a518f610457a127650a /gtk2_ardour
parent5ea9dee73b75b01e6db3a5a97c5a02493b358b00 (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.menus1
-rw-r--r--gtk2_ardour/editor_actions.cc2
-rw-r--r--gtk2_ardour/rhythm_ferret.cc151
-rw-r--r--gtk2_ardour/rhythm_ferret.h25
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 ();