mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-22 14:46:34 +01:00
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
This commit is contained in:
parent
5ea9dee73b
commit
5f61efff8f
12 changed files with 750 additions and 17 deletions
23
SConstruct
23
SConstruct
|
|
@ -57,7 +57,9 @@ opts.AddOptions(
|
||||||
BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 0),
|
BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 0),
|
||||||
BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
|
BoolOption('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
|
||||||
BoolOption('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0),
|
BoolOption('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0),
|
||||||
BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1)
|
BoolOption('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1),
|
||||||
|
BoolOption('AUBIO', "Use Paul Brossier's aubio library for feature detection (if available)", 1)
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
@ -450,7 +452,8 @@ deps = \
|
||||||
'raptor' : '1.4.2',
|
'raptor' : '1.4.2',
|
||||||
'lrdf' : '0.4.0',
|
'lrdf' : '0.4.0',
|
||||||
'jack' : '0.101.1',
|
'jack' : '0.101.1',
|
||||||
'libgnomecanvas-2.0' : '2.0'
|
'libgnomecanvas-2.0' : '2.0',
|
||||||
|
'aubio' : '0.3.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
def DependenciesRequiredMessage():
|
def DependenciesRequiredMessage():
|
||||||
|
|
@ -523,6 +526,10 @@ if conf.CheckPKGExists ('fftw3'):
|
||||||
libraries['fftw3'] = LibraryInfo()
|
libraries['fftw3'] = LibraryInfo()
|
||||||
libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
|
libraries['fftw3'].ParseConfig('pkg-config --cflags --libs fftw3')
|
||||||
|
|
||||||
|
if conf.CheckPKGExists ('aubio'):
|
||||||
|
libraries['aubio'] = LibraryInfo()
|
||||||
|
libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
|
||||||
|
|
||||||
env = conf.Finish ()
|
env = conf.Finish ()
|
||||||
|
|
||||||
if env['FFT_ANALYSIS']:
|
if env['FFT_ANALYSIS']:
|
||||||
|
|
@ -537,6 +544,18 @@ if env['FFT_ANALYSIS']:
|
||||||
sys.exit (1)
|
sys.exit (1)
|
||||||
conf.Finish()
|
conf.Finish()
|
||||||
|
|
||||||
|
if env['AUBIO']:
|
||||||
|
#
|
||||||
|
# Check for aubio header as well as the library
|
||||||
|
#
|
||||||
|
|
||||||
|
conf = Configure(libraries['aubio'])
|
||||||
|
|
||||||
|
if conf.CheckHeader ('aubio/aubio.h') == False:
|
||||||
|
print ('AUBIO-related features be compiled without the aubio headers, which do not seem to be installed')
|
||||||
|
env['AUBIO'] = 0
|
||||||
|
conf.Finish()
|
||||||
|
|
||||||
if env['FREESOUND']:
|
if env['FREESOUND']:
|
||||||
#
|
#
|
||||||
# Check for curl header as well as the library
|
# Check for curl header as well as the library
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,7 @@
|
||||||
<menuitem action='boost-region-gain'/>
|
<menuitem action='boost-region-gain'/>
|
||||||
<menuitem action='cut-region-gain'/>
|
<menuitem action='cut-region-gain'/>
|
||||||
<menuitem action='pitch-shift-region'/>
|
<menuitem action='pitch-shift-region'/>
|
||||||
|
<menuitem action='toggle-opaque-region'/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<menuitem action='duplicate-region'/>
|
<menuitem action='duplicate-region'/>
|
||||||
<menuitem action='multi-duplicate-region'/>
|
<menuitem action='multi-duplicate-region'/>
|
||||||
|
|
|
||||||
|
|
@ -365,6 +365,8 @@ Editor::register_actions ()
|
||||||
ActionManager::region_selection_sensitive_actions.push_back (act);
|
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));
|
act = ActionManager::register_action (editor_actions, "pitch-shift-region", _("Transpose"), mem_fun(*this, &Editor::pitch_shift_regions));
|
||||||
ActionManager::session_sensitive_actions.push_back (act);
|
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);
|
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));
|
act = ActionManager::register_action (editor_actions, "set-fade-in-length", _("Set Fade In Length"), bind (mem_fun(*this, &Editor::set_fade_length), true));
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <pbd/memento_command.h>
|
#include <pbd/memento_command.h>
|
||||||
|
|
||||||
#include <ardour/transient_detector.h>
|
#include <ardour/transient_detector.h>
|
||||||
|
#include <ardour/onset_detector.h>
|
||||||
#include <ardour/audiosource.h>
|
#include <ardour/audiosource.h>
|
||||||
#include <ardour/audioregion.h>
|
#include <ardour/audioregion.h>
|
||||||
#include <ardour/playlist.h>
|
#include <ardour/playlist.h>
|
||||||
|
|
@ -32,6 +33,17 @@ static const gchar * _analysis_mode_strings[] = {
|
||||||
0
|
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)
|
RhythmFerret::RhythmFerret (PublicEditor& e)
|
||||||
: ArdourDialog (_("Rhythm Ferret"))
|
: ArdourDialog (_("Rhythm Ferret"))
|
||||||
, editor (e)
|
, editor (e)
|
||||||
|
|
@ -50,6 +62,13 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
|
||||||
, sensitivity_scale (sensitivity_adjustment)
|
, sensitivity_scale (sensitivity_adjustment)
|
||||||
, sensitivity_label (_("Sensitivity"))
|
, sensitivity_label (_("Sensitivity"))
|
||||||
, analyze_button (_("Analyze"))
|
, 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_adjustment (3, 0, 100, 1, 10)
|
||||||
, trigger_gap_spinner (trigger_gap_adjustment)
|
, trigger_gap_spinner (trigger_gap_adjustment)
|
||||||
, trigger_gap_label (_("Trigger gap (msecs)"))
|
, trigger_gap_label (_("Trigger gap (msecs)"))
|
||||||
|
|
@ -78,6 +97,14 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
|
||||||
analysis_mode_strings = I18N (_analysis_mode_strings);
|
analysis_mode_strings = I18N (_analysis_mode_strings);
|
||||||
Gtkmm2ext::set_popdown_strings (analysis_mode_selector, 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.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 = manage (new HBox);
|
||||||
box->set_spacing (6);
|
box->set_spacing (6);
|
||||||
|
|
@ -85,17 +112,7 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
|
||||||
box->pack_start (analysis_mode_selector, true, true);
|
box->pack_start (analysis_mode_selector, true, true);
|
||||||
ferret_packer.pack_start (*box, false, false);
|
ferret_packer.pack_start (*box, false, false);
|
||||||
|
|
||||||
box = manage (new HBox);
|
ferret_packer.pack_start (analysis_packer, false, false);
|
||||||
box->set_spacing (6);
|
|
||||||
box->pack_start (detection_threshold_label, false, false);
|
|
||||||
box->pack_start (detection_threshold_scale, true, true);
|
|
||||||
ferret_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);
|
|
||||||
|
|
||||||
box = manage (new HBox);
|
box = manage (new HBox);
|
||||||
box->set_spacing (6);
|
box->set_spacing (6);
|
||||||
|
|
@ -107,6 +124,38 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
|
||||||
|
|
||||||
analyze_button.signal_clicked().connect (mem_fun (*this, &RhythmFerret::run_analysis));
|
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);
|
||||||
|
perc_onset_packer.pack_start (*box, false, false);
|
||||||
|
|
||||||
|
box = manage (new HBox);
|
||||||
|
box->set_spacing (6);
|
||||||
|
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);
|
||||||
|
|
||||||
|
analysis_mode_changed ();
|
||||||
|
|
||||||
ferret_frame.add (ferret_packer);
|
ferret_frame.add (ferret_packer);
|
||||||
|
|
||||||
logo = manage (new Gtk::Image (::get_icon (X_("ferret_02"))));
|
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::AnalysisMode
|
||||||
RhythmFerret::get_analysis_mode () const
|
RhythmFerret::get_analysis_mode () const
|
||||||
{
|
{
|
||||||
string str = analysis_mode_selector.get_active_text ();
|
string str = analysis_mode_selector.get_active_text ();
|
||||||
|
|
||||||
if (str == _(_analysis_mode_strings[(int) NoteOnset])) {
|
if (str == analysis_mode_strings[(int) NoteOnset]) {
|
||||||
return NoteOnset;
|
return NoteOnset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,6 +251,9 @@ RhythmFerret::run_analysis ()
|
||||||
case PercussionOnset:
|
case PercussionOnset:
|
||||||
run_percussion_onset_analysis (rd, (*i)->region()->position(), current_results);
|
run_percussion_onset_analysis (rd, (*i)->region()->position(), current_results);
|
||||||
break;
|
break;
|
||||||
|
case NoteOnset:
|
||||||
|
run_note_onset_analysis (rd, (*i)->region()->position(), current_results);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +302,67 @@ RhythmFerret::run_percussion_onset_analysis (boost::shared_ptr<Readable> readabl
|
||||||
return 0;
|
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
|
void
|
||||||
RhythmFerret::do_action ()
|
RhythmFerret::do_action ()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,9 @@ class RhythmFerret : public ArdourDialog {
|
||||||
Gtk::VBox ferret_packer;
|
Gtk::VBox ferret_packer;
|
||||||
Gtk::ComboBoxText analysis_mode_selector;
|
Gtk::ComboBoxText analysis_mode_selector;
|
||||||
Gtk::Label analysis_mode_label;
|
Gtk::Label analysis_mode_label;
|
||||||
|
|
||||||
|
/* transient detection widgets */
|
||||||
|
|
||||||
Gtk::Adjustment detection_threshold_adjustment;
|
Gtk::Adjustment detection_threshold_adjustment;
|
||||||
Gtk::HScale detection_threshold_scale;
|
Gtk::HScale detection_threshold_scale;
|
||||||
Gtk::Label detection_threshold_label;
|
Gtk::Label detection_threshold_label;
|
||||||
|
|
@ -78,22 +81,44 @@ class RhythmFerret : public ArdourDialog {
|
||||||
Gtk::HScale sensitivity_scale;
|
Gtk::HScale sensitivity_scale;
|
||||||
Gtk::Label sensitivity_label;
|
Gtk::Label sensitivity_label;
|
||||||
Gtk::Button analyze_button;
|
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::Adjustment trigger_gap_adjustment;
|
||||||
Gtk::SpinButton trigger_gap_spinner;
|
Gtk::SpinButton trigger_gap_spinner;
|
||||||
Gtk::Label trigger_gap_label;
|
Gtk::Label trigger_gap_label;
|
||||||
|
|
||||||
|
Gtk::VBox analysis_packer;
|
||||||
|
|
||||||
Gtk::Label operation_clarification_label;
|
Gtk::Label operation_clarification_label;
|
||||||
Gtk::Button action_button;
|
Gtk::Button action_button;
|
||||||
|
|
||||||
std::vector<std::string> analysis_mode_strings;
|
std::vector<std::string> analysis_mode_strings;
|
||||||
|
std::vector<std::string> onset_function_strings;
|
||||||
|
|
||||||
ARDOUR::AnalysisFeatureList current_results;
|
ARDOUR::AnalysisFeatureList current_results;
|
||||||
|
|
||||||
AnalysisMode get_analysis_mode () const;
|
AnalysisMode get_analysis_mode () const;
|
||||||
Action get_action() const;
|
Action get_action() const;
|
||||||
|
void analysis_mode_changed ();
|
||||||
|
int get_note_onset_function ();
|
||||||
|
|
||||||
void run_analysis ();
|
void run_analysis ();
|
||||||
int run_percussion_onset_analysis (boost::shared_ptr<ARDOUR::Readable> region, nframes64_t offset, ARDOUR::AnalysisFeatureList& results);
|
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_action ();
|
||||||
void do_split_action ();
|
void do_split_action ();
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ location.cc
|
||||||
mix.cc
|
mix.cc
|
||||||
mtc_slave.cc
|
mtc_slave.cc
|
||||||
named_selection.cc
|
named_selection.cc
|
||||||
|
onset_detector.cc
|
||||||
panner.cc
|
panner.cc
|
||||||
pcm_utils.cc
|
pcm_utils.cc
|
||||||
playlist.cc
|
playlist.cc
|
||||||
|
|
|
||||||
56
libs/ardour/ardour/onset_detector.h
Normal file
56
libs/ardour/ardour/onset_detector.h
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Paul Davis
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_onset_detector_h__
|
||||||
|
#define __ardour_onset_detector_h__
|
||||||
|
|
||||||
|
#include <ardour/audioanalyser.h>
|
||||||
|
|
||||||
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class AudioSource;
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
class OnsetDetector : public AudioAnalyser
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
OnsetDetector (float sample_rate);
|
||||||
|
~OnsetDetector();
|
||||||
|
|
||||||
|
static std::string operational_identifier();
|
||||||
|
|
||||||
|
void set_silence_threshold (float);
|
||||||
|
void set_peak_threshold (float);
|
||||||
|
void set_function (int);
|
||||||
|
|
||||||
|
int run (const std::string& path, Readable*, uint32_t channel, AnalysisFeatureList& results);
|
||||||
|
|
||||||
|
static void cleanup_onsets (AnalysisFeatureList&, float sr, float gap_msecs);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
AnalysisFeatureList* current_results;
|
||||||
|
int use_features (Vamp::Plugin::FeatureSet&, std::ostream*);
|
||||||
|
|
||||||
|
static std::string _op_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace */
|
||||||
|
|
||||||
|
#endif /* __ardour_audioanalyser_h__ */
|
||||||
126
libs/ardour/onset_detector.cc
Normal file
126
libs/ardour/onset_detector.cc
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
#include <ardour/onset_detector.h>
|
||||||
|
|
||||||
|
#include "i18n.h"
|
||||||
|
|
||||||
|
using namespace Vamp;
|
||||||
|
using namespace ARDOUR;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
/* need a static initializer function for this */
|
||||||
|
|
||||||
|
string OnsetDetector::_op_id = X_("libardourvampplugins:aubioonset:2");
|
||||||
|
|
||||||
|
OnsetDetector::OnsetDetector (float sr)
|
||||||
|
: AudioAnalyser (sr, X_("libardourvampplugins:aubioonset"))
|
||||||
|
{
|
||||||
|
/* update the op_id */
|
||||||
|
|
||||||
|
_op_id = X_("libardourvampplugins:aubioonset");
|
||||||
|
|
||||||
|
// XXX this should load the above-named plugin and get the current version
|
||||||
|
|
||||||
|
_op_id += ":2";
|
||||||
|
}
|
||||||
|
|
||||||
|
OnsetDetector::~OnsetDetector()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
OnsetDetector::operational_identifier()
|
||||||
|
{
|
||||||
|
return _op_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
OnsetDetector::run (const std::string& path, Readable* src, uint32_t channel, AnalysisFeatureList& results)
|
||||||
|
{
|
||||||
|
current_results = &results;
|
||||||
|
int ret = analyse (path, src, channel);
|
||||||
|
|
||||||
|
current_results = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
OnsetDetector::use_features (Plugin::FeatureSet& features, ostream* out)
|
||||||
|
{
|
||||||
|
const Plugin::FeatureList& fl (features[0]);
|
||||||
|
|
||||||
|
for (Plugin::FeatureList::const_iterator f = fl.begin(); f != fl.end(); ++f) {
|
||||||
|
|
||||||
|
if ((*f).hasTimestamp) {
|
||||||
|
|
||||||
|
if (out) {
|
||||||
|
(*out) << (*f).timestamp.toString() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_results->push_back (RealTime::realTime2Frame ((*f).timestamp, (nframes_t) floor(sample_rate)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OnsetDetector::set_silence_threshold (float val)
|
||||||
|
{
|
||||||
|
if (plugin) {
|
||||||
|
plugin->setParameter ("silencethreshold", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OnsetDetector::set_peak_threshold (float val)
|
||||||
|
{
|
||||||
|
if (plugin) {
|
||||||
|
plugin->setParameter ("peakpickthreshold", val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OnsetDetector::set_function (int val)
|
||||||
|
{
|
||||||
|
if (plugin) {
|
||||||
|
plugin->setParameter ("onsettype", (float) val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OnsetDetector::cleanup_onsets (AnalysisFeatureList& t, float sr, float gap_msecs)
|
||||||
|
{
|
||||||
|
if (t.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
t.sort ();
|
||||||
|
|
||||||
|
/* remove duplicates or other things that are too close */
|
||||||
|
|
||||||
|
AnalysisFeatureList::iterator i = t.begin();
|
||||||
|
AnalysisFeatureList::iterator f, b;
|
||||||
|
const nframes64_t gap_frames = (nframes64_t) floor (gap_msecs * (sr / 1000.0));
|
||||||
|
|
||||||
|
while (i != t.end()) {
|
||||||
|
|
||||||
|
// move front iterator to just past i, and back iterator the same place
|
||||||
|
|
||||||
|
f = i;
|
||||||
|
++f;
|
||||||
|
b = f;
|
||||||
|
|
||||||
|
// move f until we find a new value that is far enough away
|
||||||
|
|
||||||
|
while ((f != t.end()) && (((*f) - (*i)) < gap_frames)) {
|
||||||
|
++f;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = f;
|
||||||
|
|
||||||
|
// if f moved forward from b, we had duplicates/too-close points: get rid of them
|
||||||
|
|
||||||
|
if (b != f) {
|
||||||
|
t.erase (b, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
280
libs/vamp-plugins/Onset.cpp
Normal file
280
libs/vamp-plugins/Onset.cpp
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Vamp feature extraction plugins using Paul Brossier's Aubio library.
|
||||||
|
|
||||||
|
Centre for Digital Music, Queen Mary, University of London.
|
||||||
|
This file copyright 2006 Chris Cannam.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version. See the file
|
||||||
|
COPYING included with this distribution for more information.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include "Onset.h"
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
Onset::Onset(float inputSampleRate) :
|
||||||
|
Plugin(inputSampleRate),
|
||||||
|
m_ibuf(0),
|
||||||
|
m_fftgrain(0),
|
||||||
|
m_onset(0),
|
||||||
|
m_pv(0),
|
||||||
|
m_peakpick(0),
|
||||||
|
m_onsetdet(0),
|
||||||
|
m_onsettype(aubio_onset_complex),
|
||||||
|
m_threshold(0.3),
|
||||||
|
m_silence(-90),
|
||||||
|
m_channelCount(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Onset::~Onset()
|
||||||
|
{
|
||||||
|
if (m_onsetdet) aubio_onsetdetection_free(m_onsetdet);
|
||||||
|
if (m_ibuf) del_fvec(m_ibuf);
|
||||||
|
if (m_onset) del_fvec(m_onset);
|
||||||
|
if (m_fftgrain) del_cvec(m_fftgrain);
|
||||||
|
if (m_pv) del_aubio_pvoc(m_pv);
|
||||||
|
if (m_peakpick) del_aubio_peakpicker(m_peakpick);
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Onset::getIdentifier() const
|
||||||
|
{
|
||||||
|
return "aubioonset";
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Onset::getName() const
|
||||||
|
{
|
||||||
|
return "Aubio Onset Detector";
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Onset::getDescription() const
|
||||||
|
{
|
||||||
|
return "Estimate note onset times";
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Onset::getMaker() const
|
||||||
|
{
|
||||||
|
return "Paul Brossier (plugin by Chris Cannam)";
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Onset::getPluginVersion() const
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
Onset::getCopyright() const
|
||||||
|
{
|
||||||
|
return "GPL";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Onset::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
||||||
|
{
|
||||||
|
m_channelCount = channels;
|
||||||
|
m_stepSize = stepSize;
|
||||||
|
m_blockSize = blockSize;
|
||||||
|
|
||||||
|
m_ibuf = new_fvec(stepSize, channels);
|
||||||
|
m_onset = new_fvec(1, channels);
|
||||||
|
m_fftgrain = new_cvec(blockSize, channels);
|
||||||
|
m_pv = new_aubio_pvoc(blockSize, stepSize, channels);
|
||||||
|
m_peakpick = new_aubio_peakpicker(m_threshold);
|
||||||
|
|
||||||
|
m_onsetdet = new_aubio_onsetdetection(m_onsettype, blockSize, channels);
|
||||||
|
|
||||||
|
m_delay = Vamp::RealTime::frame2RealTime(4 * stepSize,
|
||||||
|
lrintf(m_inputSampleRate));
|
||||||
|
|
||||||
|
m_lastOnset = Vamp::RealTime::zeroTime - m_delay - m_delay;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Onset::reset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
Onset::getPreferredStepSize() const
|
||||||
|
{
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
Onset::getPreferredBlockSize() const
|
||||||
|
{
|
||||||
|
return 2 * getPreferredStepSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Onset::ParameterList
|
||||||
|
Onset::getParameterDescriptors() const
|
||||||
|
{
|
||||||
|
ParameterList list;
|
||||||
|
|
||||||
|
ParameterDescriptor desc;
|
||||||
|
desc.identifier = "onsettype";
|
||||||
|
desc.name = "Onset Detection Function Type";
|
||||||
|
desc.minValue = 0;
|
||||||
|
desc.maxValue = 6;
|
||||||
|
desc.defaultValue = (int)aubio_onset_complex;
|
||||||
|
desc.isQuantized = true;
|
||||||
|
desc.quantizeStep = 1;
|
||||||
|
desc.valueNames.push_back("Energy Based");
|
||||||
|
desc.valueNames.push_back("Spectral Difference");
|
||||||
|
desc.valueNames.push_back("High-Frequency Content");
|
||||||
|
desc.valueNames.push_back("Complex Domain");
|
||||||
|
desc.valueNames.push_back("Phase Deviation");
|
||||||
|
desc.valueNames.push_back("Kullback-Liebler");
|
||||||
|
desc.valueNames.push_back("Modified Kullback-Liebler");
|
||||||
|
list.push_back(desc);
|
||||||
|
|
||||||
|
desc = ParameterDescriptor();
|
||||||
|
desc.identifier = "peakpickthreshold";
|
||||||
|
desc.name = "Peak Picker Threshold";
|
||||||
|
desc.minValue = 0;
|
||||||
|
desc.maxValue = 1;
|
||||||
|
desc.defaultValue = 0.3;
|
||||||
|
desc.isQuantized = false;
|
||||||
|
list.push_back(desc);
|
||||||
|
|
||||||
|
desc = ParameterDescriptor();
|
||||||
|
desc.identifier = "silencethreshold";
|
||||||
|
desc.name = "Silence Threshold";
|
||||||
|
desc.minValue = -120;
|
||||||
|
desc.maxValue = 0;
|
||||||
|
desc.defaultValue = -90;
|
||||||
|
desc.unit = "dB";
|
||||||
|
desc.isQuantized = false;
|
||||||
|
list.push_back(desc);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
Onset::getParameter(std::string param) const
|
||||||
|
{
|
||||||
|
if (param == "onsettype") {
|
||||||
|
return m_onsettype;
|
||||||
|
} else if (param == "peakpickthreshold") {
|
||||||
|
return m_threshold;
|
||||||
|
} else if (param == "silencethreshold") {
|
||||||
|
return m_silence;
|
||||||
|
} else {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Onset::setParameter(std::string param, float value)
|
||||||
|
{
|
||||||
|
if (param == "onsettype") {
|
||||||
|
switch (lrintf(value)) {
|
||||||
|
case 0: m_onsettype = aubio_onset_energy; break;
|
||||||
|
case 1: m_onsettype = aubio_onset_specdiff; break;
|
||||||
|
case 2: m_onsettype = aubio_onset_hfc; break;
|
||||||
|
case 3: m_onsettype = aubio_onset_complex; break;
|
||||||
|
case 4: m_onsettype = aubio_onset_phase; break;
|
||||||
|
case 5: m_onsettype = aubio_onset_kl; break;
|
||||||
|
case 6: m_onsettype = aubio_onset_mkl; break;
|
||||||
|
}
|
||||||
|
} else if (param == "peakpickthreshold") {
|
||||||
|
m_threshold = value;
|
||||||
|
} else if (param == "silencethreshold") {
|
||||||
|
m_silence = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Onset::OutputList
|
||||||
|
Onset::getOutputDescriptors() const
|
||||||
|
{
|
||||||
|
OutputList list;
|
||||||
|
|
||||||
|
OutputDescriptor d;
|
||||||
|
d.identifier = "onsets";
|
||||||
|
d.name = "Onsets";
|
||||||
|
d.unit = "";
|
||||||
|
d.hasFixedBinCount = true;
|
||||||
|
d.binCount = 0;
|
||||||
|
d.sampleType = OutputDescriptor::VariableSampleRate;
|
||||||
|
d.sampleRate = 0;
|
||||||
|
list.push_back(d);
|
||||||
|
|
||||||
|
d = OutputDescriptor();
|
||||||
|
d.identifier = "detectionfunction";
|
||||||
|
d.name = "Onset Detection Function";
|
||||||
|
d.unit = "";
|
||||||
|
d.hasFixedBinCount = true;
|
||||||
|
d.binCount = m_channelCount;
|
||||||
|
d.hasKnownExtents = false;
|
||||||
|
d.isQuantized = false;
|
||||||
|
d.sampleType = OutputDescriptor::OneSamplePerStep;
|
||||||
|
list.push_back(d);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
Onset::FeatureSet
|
||||||
|
Onset::process(const float *const *inputBuffers,
|
||||||
|
Vamp::RealTime timestamp)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_stepSize; ++i) {
|
||||||
|
for (size_t j = 0; j < m_channelCount; ++j) {
|
||||||
|
fvec_write_sample(m_ibuf, inputBuffers[j][i], j, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aubio_pvoc_do(m_pv, m_ibuf, m_fftgrain);
|
||||||
|
aubio_onsetdetection(m_onsetdet, m_fftgrain, m_onset);
|
||||||
|
|
||||||
|
bool isonset = aubio_peakpick_pimrt(m_onset, m_peakpick);
|
||||||
|
|
||||||
|
if (isonset) {
|
||||||
|
if (aubio_silence_detection(m_ibuf, m_silence)) {
|
||||||
|
isonset = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FeatureSet returnFeatures;
|
||||||
|
|
||||||
|
if (isonset) {
|
||||||
|
if (timestamp - m_lastOnset >= m_delay) {
|
||||||
|
Feature onsettime;
|
||||||
|
onsettime.hasTimestamp = true;
|
||||||
|
if (timestamp < m_delay) timestamp = m_delay;
|
||||||
|
onsettime.timestamp = timestamp - m_delay;
|
||||||
|
returnFeatures[0].push_back(onsettime);
|
||||||
|
m_lastOnset = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Feature feature;
|
||||||
|
for (size_t j = 0; j < m_channelCount; ++j) {
|
||||||
|
feature.values.push_back(m_onset->data[j][0]);
|
||||||
|
}
|
||||||
|
returnFeatures[1].push_back(feature);
|
||||||
|
|
||||||
|
return returnFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
Onset::FeatureSet
|
||||||
|
Onset::getRemainingFeatures()
|
||||||
|
{
|
||||||
|
return FeatureSet();
|
||||||
|
}
|
||||||
|
|
||||||
73
libs/vamp-plugins/Onset.h
Normal file
73
libs/vamp-plugins/Onset.h
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Vamp feature extraction plugins using Paul Brossier's Aubio library.
|
||||||
|
|
||||||
|
Centre for Digital Music, Queen Mary, University of London.
|
||||||
|
This file copyright 2006 Chris Cannam.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation; either version 2 of the
|
||||||
|
License, or (at your option) any later version. See the file
|
||||||
|
COPYING included with this distribution for more information.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ONSET_PLUGIN_H_
|
||||||
|
#define _ONSET_PLUGIN_H_
|
||||||
|
|
||||||
|
#include <vamp-sdk/Plugin.h>
|
||||||
|
#include <aubio/aubio.h>
|
||||||
|
|
||||||
|
class Onset : public Vamp::Plugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Onset(float inputSampleRate);
|
||||||
|
virtual ~Onset();
|
||||||
|
|
||||||
|
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
InputDomain getInputDomain() const { return TimeDomain; }
|
||||||
|
|
||||||
|
std::string getIdentifier() const;
|
||||||
|
std::string getName() const;
|
||||||
|
std::string getDescription() const;
|
||||||
|
std::string getMaker() const;
|
||||||
|
int getPluginVersion() const;
|
||||||
|
std::string getCopyright() const;
|
||||||
|
|
||||||
|
ParameterList getParameterDescriptors() const;
|
||||||
|
float getParameter(std::string) const;
|
||||||
|
void setParameter(std::string, float);
|
||||||
|
|
||||||
|
size_t getPreferredStepSize() const;
|
||||||
|
size_t getPreferredBlockSize() const;
|
||||||
|
|
||||||
|
OutputList getOutputDescriptors() const;
|
||||||
|
|
||||||
|
FeatureSet process(const float *const *inputBuffers,
|
||||||
|
Vamp::RealTime timestamp);
|
||||||
|
|
||||||
|
FeatureSet getRemainingFeatures();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
fvec_t *m_ibuf;
|
||||||
|
cvec_t *m_fftgrain;
|
||||||
|
fvec_t *m_onset;
|
||||||
|
aubio_pvoc_t *m_pv;
|
||||||
|
aubio_pickpeak_t *m_peakpick;
|
||||||
|
aubio_onsetdetection_t *m_onsetdet;
|
||||||
|
aubio_onsetdetection_type m_onsettype;
|
||||||
|
float m_threshold;
|
||||||
|
float m_silence;
|
||||||
|
size_t m_stepSize;
|
||||||
|
size_t m_blockSize;
|
||||||
|
size_t m_channelCount;
|
||||||
|
Vamp::RealTime m_delay;
|
||||||
|
Vamp::RealTime m_lastOnset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -4,7 +4,17 @@ import os
|
||||||
import os.path
|
import os.path
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
plugin_files = glob.glob ("*.cpp")
|
plugin_files = Split("""
|
||||||
|
plugins.cpp
|
||||||
|
AmplitudeFollower.cpp
|
||||||
|
PercussionOnsetDetector.cpp
|
||||||
|
SpectralCentroid.cpp
|
||||||
|
ZeroCrossing.cpp
|
||||||
|
""")
|
||||||
|
|
||||||
|
aubio_files = Split ("""
|
||||||
|
Onset.cpp
|
||||||
|
""")
|
||||||
|
|
||||||
Import('env install_prefix libraries')
|
Import('env install_prefix libraries')
|
||||||
vampplugs = env.Copy()
|
vampplugs = env.Copy()
|
||||||
|
|
@ -14,7 +24,13 @@ vampplugs.Merge ([libraries['vamp'],
|
||||||
libraries['vamphost']
|
libraries['vamphost']
|
||||||
])
|
])
|
||||||
|
|
||||||
libvampplugins = vampplugs.SharedLibrary('ardourvampplugins', plugin_files)
|
sources = plugin_files
|
||||||
|
|
||||||
|
if vampplugs['AUBIO']:
|
||||||
|
sources += aubio_files
|
||||||
|
vampplugs.Merge ([libraries['aubio']])
|
||||||
|
|
||||||
|
libvampplugins = vampplugs.SharedLibrary('ardourvampplugins', sources)
|
||||||
|
|
||||||
Default(libvampplugins)
|
Default(libvampplugins)
|
||||||
|
|
||||||
|
|
@ -22,5 +38,5 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar
|
||||||
|
|
||||||
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
env.Alias('tarball', env.Distribute (env['DISTTREE'],
|
||||||
[ 'SConscript' ] +
|
[ 'SConscript' ] +
|
||||||
plugin_files +
|
plugin_files + aubio_files +
|
||||||
glob.glob('*.h')))
|
glob.glob('*.h')))
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,13 @@
|
||||||
#include "SpectralCentroid.h"
|
#include "SpectralCentroid.h"
|
||||||
#include "PercussionOnsetDetector.h"
|
#include "PercussionOnsetDetector.h"
|
||||||
#include "AmplitudeFollower.h"
|
#include "AmplitudeFollower.h"
|
||||||
|
#include "Onset.h"
|
||||||
|
|
||||||
static Vamp::PluginAdapter<ZeroCrossing> zeroCrossingAdapter;
|
static Vamp::PluginAdapter<ZeroCrossing> zeroCrossingAdapter;
|
||||||
static Vamp::PluginAdapter<SpectralCentroid> spectralCentroidAdapter;
|
static Vamp::PluginAdapter<SpectralCentroid> spectralCentroidAdapter;
|
||||||
static Vamp::PluginAdapter<PercussionOnsetDetector> percussionOnsetAdapter;
|
static Vamp::PluginAdapter<PercussionOnsetDetector> percussionOnsetAdapter;
|
||||||
static Vamp::PluginAdapter<AmplitudeFollower> amplitudeAdapter;
|
static Vamp::PluginAdapter<AmplitudeFollower> amplitudeAdapter;
|
||||||
|
static Vamp::PluginAdapter<Onset> onsetAdapter;
|
||||||
|
|
||||||
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
|
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
|
||||||
unsigned int index)
|
unsigned int index)
|
||||||
|
|
@ -57,6 +59,7 @@ const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
|
||||||
case 1: return spectralCentroidAdapter.getDescriptor();
|
case 1: return spectralCentroidAdapter.getDescriptor();
|
||||||
case 2: return percussionOnsetAdapter.getDescriptor();
|
case 2: return percussionOnsetAdapter.getDescriptor();
|
||||||
case 3: return amplitudeAdapter.getDescriptor();
|
case 3: return amplitudeAdapter.getDescriptor();
|
||||||
|
case 4: return onsetAdapter.getDescriptor();
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue