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:
Paul Davis 2008-05-15 19:37:35 +00:00
parent 5ea9dee73b
commit 5f61efff8f
12 changed files with 750 additions and 17 deletions

View file

@ -57,7 +57,9 @@ opts.AddOptions(
BoolOption('LV2', 'Compile with support for LV2 (if slv2 is available)', 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('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',
'lrdf' : '0.4.0',
'jack' : '0.101.1',
'libgnomecanvas-2.0' : '2.0'
'libgnomecanvas-2.0' : '2.0',
'aubio' : '0.3.2'
}
def DependenciesRequiredMessage():
@ -523,6 +526,10 @@ if conf.CheckPKGExists ('fftw3'):
libraries['fftw3'] = LibraryInfo()
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 ()
if env['FFT_ANALYSIS']:
@ -537,6 +544,18 @@ if env['FFT_ANALYSIS']:
sys.exit (1)
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']:
#
# Check for curl header as well as the library

View file

@ -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'/>

View file

@ -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));

View file

@ -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,17 +112,7 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
box->pack_start (analysis_mode_selector, true, true);
ferret_packer.pack_start (*box, 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);
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);
ferret_packer.pack_start (analysis_packer, false, false);
box = manage (new HBox);
box->set_spacing (6);
@ -107,6 +124,38 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
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);
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 ()
{

View file

@ -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 ();

View file

@ -65,6 +65,7 @@ location.cc
mix.cc
mtc_slave.cc
named_selection.cc
onset_detector.cc
panner.cc
pcm_utils.cc
playlist.cc

View 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__ */

View 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
View 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
View 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

View file

@ -4,7 +4,17 @@ import os
import os.path
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')
vampplugs = env.Copy()
@ -14,7 +24,13 @@ vampplugs.Merge ([libraries['vamp'],
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)
@ -22,5 +38,5 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar
env.Alias('tarball', env.Distribute (env['DISTTREE'],
[ 'SConscript' ] +
plugin_files +
plugin_files + aubio_files +
glob.glob('*.h')))

View file

@ -41,11 +41,13 @@
#include "SpectralCentroid.h"
#include "PercussionOnsetDetector.h"
#include "AmplitudeFollower.h"
#include "Onset.h"
static Vamp::PluginAdapter<ZeroCrossing> zeroCrossingAdapter;
static Vamp::PluginAdapter<SpectralCentroid> spectralCentroidAdapter;
static Vamp::PluginAdapter<PercussionOnsetDetector> percussionOnsetAdapter;
static Vamp::PluginAdapter<AmplitudeFollower> amplitudeAdapter;
static Vamp::PluginAdapter<Onset> onsetAdapter;
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
unsigned int index)
@ -57,6 +59,7 @@ const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
case 1: return spectralCentroidAdapter.getDescriptor();
case 2: return percussionOnsetAdapter.getDescriptor();
case 3: return amplitudeAdapter.getDescriptor();
case 4: return onsetAdapter.getDescriptor();
default: return 0;
}
}