summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-01-12 23:45:50 +0000
committerDavid Robillard <d@drobilla.net>2008-01-12 23:45:50 +0000
commite92c1669c1cdf857b8a3900abb9f891e6ca9fdad (patch)
treef02725efdfd3473527cb7fa94471a7cff2528880 /libs
parentbf256c168170de1b9e1411bb563c571d67470c05 (diff)
Merge with 2.0-ongoing R2885.
Fix loading of 2.0 sessions. git-svn-id: svn://localhost/ardour2/trunk@2904 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/audio_unit.h2
-rw-r--r--libs/ardour/ardour/ladspa_plugin.h102
-rw-r--r--libs/ardour/ardour/plugin.h3
-rw-r--r--libs/ardour/ardour/plugin_insert.h1
-rw-r--r--libs/ardour/ardour/plugin_state.h14
-rw-r--r--libs/ardour/ardour/port_insert.h1
-rw-r--r--libs/ardour/ardour/processor.h1
-rw-r--r--libs/ardour/ardour/rb_effect.h2
-rw-r--r--libs/ardour/ardour/vst_plugin.h2
-rw-r--r--libs/ardour/audio_unit.cc12
-rw-r--r--libs/ardour/audioregion.cc2
-rw-r--r--libs/ardour/ladspa_plugin.cc105
-rw-r--r--libs/ardour/plugin_manager.cc2
-rw-r--r--libs/ardour/session.cc3
-rw-r--r--libs/ardour/session_state.cc6
-rw-r--r--libs/ardour/vst_plugin.cc12
-rw-r--r--libs/gtkmm2ext/fastmeter.cc8
-rw-r--r--libs/vamp-sdk/COPYING26
-rw-r--r--libs/vamp-sdk/README240
-rw-r--r--libs/vamp-sdk/SConscript39
-rw-r--r--libs/vamp-sdk/vamp-sdk/Plugin.h405
-rw-r--r--libs/vamp-sdk/vamp-sdk/PluginAdapter.cpp851
-rw-r--r--libs/vamp-sdk/vamp-sdk/PluginAdapter.h117
-rw-r--r--libs/vamp-sdk/vamp-sdk/PluginBase.h252
-rw-r--r--libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp418
-rw-r--r--libs/vamp-sdk/vamp-sdk/PluginHostAdapter.h117
-rw-r--r--libs/vamp-sdk/vamp-sdk/RealTime.cpp254
-rw-r--r--libs/vamp-sdk/vamp-sdk/RealTime.h154
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp228
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h128
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp458
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h103
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp601
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h218
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp201
-rw-r--r--libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h106
-rw-r--r--libs/vamp-sdk/vamp-sdk/libvamp-hostsdk.la.in9
-rw-r--r--libs/vamp-sdk/vamp-sdk/libvamp-sdk.la.in9
-rw-r--r--libs/vamp-sdk/vamp/vamp.h339
-rw-r--r--libs/vamp-sdk/vamp/vamp.pc.in10
40 files changed, 5379 insertions, 182 deletions
diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
index b0e4d34c28..115e008a54 100644
--- a/libs/ardour/ardour/audio_unit.h
+++ b/libs/ardour/ardour/audio_unit.h
@@ -70,8 +70,6 @@ class AUPlugin : public ARDOUR::Plugin
int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
std::set<uint32_t> automatable() const;
- void store_state (ARDOUR::PluginState&);
- void restore_state (ARDOUR::PluginState&);
string describe_parameter (uint32_t);
string state_node_name () const { return "audiounit"; }
void print_parameter (uint32_t, char*, uint32_t len) const;
diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h
index 7c0b0b2abe..976584b687 100644
--- a/libs/ardour/ardour/ladspa_plugin.h
+++ b/libs/ardour/ardour/ladspa_plugin.h
@@ -32,7 +32,6 @@
#include <jack/types.h>
#include <ardour/ladspa.h>
-#include <ardour/plugin_state.h>
#include <ardour/plugin.h>
#include <ardour/ladspa_plugin.h>
@@ -54,53 +53,47 @@ class LadspaPlugin : public ARDOUR::Plugin
/* Plugin interface */
std::string unique_id() const;
- const char * label() const { return descriptor->Label; }
- const char * name() const { return descriptor->Name; }
- const char * maker() const { return descriptor->Maker; }
- uint32_t parameter_count() const { return descriptor->PortCount; }
- float default_value (uint32_t port);
- nframes_t signal_latency() const;
- void set_parameter (uint32_t port, float val);
- float get_parameter (uint32_t port) const;
- int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
+ const char* label() const { return _descriptor->Label; }
+ const char* name() const { return _descriptor->Name; }
+ const char* maker() const { return _descriptor->Maker; }
+ uint32_t parameter_count() const { return _descriptor->PortCount; }
+ float default_value (uint32_t port);
+ nframes_t signal_latency() const;
+ void set_parameter (uint32_t port, float val);
+ float get_parameter (uint32_t port) const;
+ int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
+ uint32_t nth_parameter (uint32_t port, bool& ok) const;
+
std::set<Parameter> automatable() const;
- uint32_t nth_parameter (uint32_t port, bool& ok) const;
- void activate () {
- if (was_activated)
- return;
- if (descriptor->activate) {
- descriptor->activate (handle);
- }
+ void activate () {
+ if (!_was_activated && _descriptor->activate)
+ _descriptor->activate (_handle);
- was_activated = true;
+ _was_activated = true;
}
- void deactivate () {
- if (!was_activated)
- return;
- if (descriptor->deactivate) {
- descriptor->deactivate (handle);
- }
+ void deactivate () {
+ if (_was_activated && _descriptor->deactivate)
+ _descriptor->deactivate (_handle);
- was_activated = false;
+ _was_activated = false;
}
+
void cleanup () {
activate();
deactivate();
- if (descriptor->cleanup) {
- descriptor->cleanup (handle);
- }
+ if (_descriptor->cleanup)
+ _descriptor->cleanup (_handle);
}
+
void set_block_size (nframes_t nframes) {}
int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
- void store_state (ARDOUR::PluginState&);
- void restore_state (ARDOUR::PluginState&);
string describe_parameter (Parameter);
string state_node_name() const { return "ladspa"; }
- void print_parameter (uint32_t, char*, uint32_t len) const;
+ void print_parameter (uint32_t, char*, uint32_t len) const;
bool parameter_is_audio(uint32_t) const;
bool parameter_is_control(uint32_t) const;
@@ -109,8 +102,8 @@ class LadspaPlugin : public ARDOUR::Plugin
bool parameter_is_toggled(uint32_t) const;
XMLNode& get_state();
- int set_state(const XMLNode& node);
- bool save_preset(string name);
+ int set_state(const XMLNode& node);
+ bool save_preset(string name);
bool has_editor() const { return false; }
@@ -118,32 +111,27 @@ class LadspaPlugin : public ARDOUR::Plugin
/* LADSPA extras */
- LADSPA_Properties properties() const { return descriptor->Properties; }
- uint32_t index() const { return _index; }
- const char * copyright() const { return descriptor->Copyright; }
- LADSPA_PortDescriptor port_descriptor(uint32_t i) const { return descriptor->PortDescriptors[i]; }
- const LADSPA_PortRangeHint * port_range_hints() const { return descriptor->PortRangeHints; }
- const char * const * port_names() const { return descriptor->PortNames; }
- void set_gain (float gain) {
- descriptor->set_run_adding_gain (handle, gain);
- }
- void run_adding (uint32_t nsamples) {
- descriptor->run_adding (handle, nsamples);
- }
- void connect_port (uint32_t port, float *ptr) {
- descriptor->connect_port (handle, port, ptr);
- }
+ LADSPA_Properties properties() const { return _descriptor->Properties; }
+ uint32_t index() const { return _index; }
+ const char * copyright() const { return _descriptor->Copyright; }
+ LADSPA_PortDescriptor port_descriptor(uint32_t i) const { return _descriptor->PortDescriptors[i]; }
+ const LADSPA_PortRangeHint* port_range_hints() const { return _descriptor->PortRangeHints; }
+ const char * const * port_names() const { return _descriptor->PortNames; }
+
+ void set_gain (float gain) { _descriptor->set_run_adding_gain (_handle, gain); }
+ void run_adding (uint32_t nsamples) { _descriptor->run_adding (_handle, nsamples); }
+ void connect_port (uint32_t port, float *ptr) { _descriptor->connect_port (_handle, port, ptr); }
private:
- void *module;
- const LADSPA_Descriptor *descriptor;
- LADSPA_Handle handle;
- nframes_t sample_rate;
- LADSPA_Data *control_data;
- LADSPA_Data *shadow_data;
- LADSPA_Data *latency_control_port;
- uint32_t _index;
- bool was_activated;
+ void* _module;
+ const LADSPA_Descriptor* _descriptor;
+ LADSPA_Handle _handle;
+ nframes_t _sample_rate;
+ LADSPA_Data* _control_data;
+ LADSPA_Data* _shadow_data;
+ LADSPA_Data* _latency_control_port;
+ uint32_t _index;
+ bool _was_activated;
void init (void *mod, uint32_t index, nframes_t rate);
void run_in_place (nframes_t nsamples);
diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h
index d721476db7..73f89f1a91 100644
--- a/libs/ardour/ardour/plugin.h
+++ b/libs/ardour/ardour/plugin.h
@@ -30,7 +30,6 @@
#include <jack/types.h>
#include <ardour/types.h>
#include <ardour/chan_count.h>
-#include <ardour/plugin_state.h>
#include <ardour/cycles.h>
#include <ardour/latent.h>
#include <ardour/parameter.h>
@@ -131,8 +130,6 @@ class Plugin : public PBD::StatefulDestructible, public Latent
virtual int connect_and_run (BufferSet& bufs, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset) = 0;
virtual std::set<Parameter> automatable() const = 0;
- virtual void store_state (ARDOUR::PluginState&) = 0;
- virtual void restore_state (ARDOUR::PluginState&) = 0;
virtual string describe_parameter (Parameter) = 0;
virtual string state_node_name() const = 0;
virtual void print_parameter (uint32_t, char*, uint32_t len) const = 0;
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index 2038153d86..42c53c487c 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -25,7 +25,6 @@
#include <sigc++/signal.h>
#include <ardour/ardour.h>
-#include <ardour/plugin_state.h>
#include <ardour/types.h>
#include <ardour/processor.h>
#include <ardour/automation_event.h>
diff --git a/libs/ardour/ardour/plugin_state.h b/libs/ardour/ardour/plugin_state.h
deleted file mode 100644
index bd499e2b90..0000000000
--- a/libs/ardour/ardour/plugin_state.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __ardour_plugin_state_h__
-#define __ardour_plugin_state_h__
-
-#include <map>
-
-namespace ARDOUR {
-
-struct PluginState {
- std::map<uint32_t,float> parameters;
-};
-
-}
-
-#endif /* __ardour_plugin_state_h__ */
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index 114d196750..1743040bf5 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -27,7 +27,6 @@
#include <sigc++/signal.h>
#include <ardour/ardour.h>
#include <ardour/io_processor.h>
-#include <ardour/plugin_state.h>
#include <ardour/types.h>
class XMLNode;
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index bf9dfe0430..d3e95e8ebf 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -30,7 +30,6 @@
#include <ardour/types.h>
#include <ardour/ardour.h>
-#include <ardour/plugin_state.h>
#include <ardour/buffer_set.h>
#include <ardour/automatable.h>
#include <ardour/latent.h>
diff --git a/libs/ardour/ardour/rb_effect.h b/libs/ardour/ardour/rb_effect.h
index bde0422335..a536a309b3 100644
--- a/libs/ardour/ardour/rb_effect.h
+++ b/libs/ardour/ardour/rb_effect.h
@@ -20,7 +20,7 @@
#ifndef __ardour_rbeffect_h__
#define __ardour_rbeffect_h__
-#include <ardour/audiofilter.h>
+#include <ardour/filter.h>
namespace ARDOUR {
diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h
index 3a05360f15..e41d000f9c 100644
--- a/libs/ardour/ardour/vst_plugin.h
+++ b/libs/ardour/ardour/vst_plugin.h
@@ -72,8 +72,6 @@ class VSTPlugin : public ARDOUR::Plugin
void deactivate ();
void set_block_size (nframes_t nframes);
int connect_and_run (BufferSet&, uint32_t& in, uint32_t& out, nframes_t nframes, nframes_t offset);
- void store_state (ARDOUR::PluginState&);
- void restore_state (ARDOUR::PluginState&);
string describe_parameter (uint32_t);
string state_node_name() const { return "vst"; }
void print_parameter (uint32_t, char*, uint32_t len) const;
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
index f86e784169..9f19a21865 100644
--- a/libs/ardour/audio_unit.cc
+++ b/libs/ardour/audio_unit.cc
@@ -401,18 +401,6 @@ AUPlugin::automatable() const
return automates;
}
-void
-AUPlugin::store_state (ARDOUR::PluginState&)
-{
-
-}
-
-void
-AUPlugin::restore_state (ARDOUR::PluginState&)
-{
-
-}
-
string
AUPlugin::describe_parameter (uint32_t)
{
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index f1534827fd..86abd4beaa 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -636,7 +636,7 @@ AudioRegion::set_live_state (const XMLNode& node, Change& what_changed, bool sen
set_fade_out_active (false);
}
}
-
+
}
}
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index 696ada3b81..ccc12f8cf8 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -62,11 +62,11 @@ LadspaPlugin::LadspaPlugin (void *mod, AudioEngine& e, Session& session, uint32_
LadspaPlugin::LadspaPlugin (const LadspaPlugin &other)
: Plugin (other)
{
- init (other.module, other._index, other.sample_rate);
+ init (other._module, other._index, other._sample_rate);
for (uint32_t i = 0; i < parameter_count(); ++i) {
- control_data[i] = other.shadow_data[i];
- shadow_data[i] = other.shadow_data[i];
+ _control_data[i] = other._shadow_data[i];
+ _shadow_data[i] = other._shadow_data[i];
}
}
@@ -77,61 +77,61 @@ LadspaPlugin::init (void *mod, uint32_t index, nframes_t rate)
uint32_t i, port_cnt;
const char *errstr;
- module = mod;
- control_data = 0;
- shadow_data = 0;
- latency_control_port = 0;
- was_activated = false;
+ _module = mod;
+ _control_data = 0;
+ _shadow_data = 0;
+ _latency_control_port = 0;
+ _was_activated = false;
- dfunc = (LADSPA_Descriptor_Function) dlsym (module, "ladspa_descriptor");
+ dfunc = (LADSPA_Descriptor_Function) dlsym (_module, "ladspa_descriptor");
if ((errstr = dlerror()) != NULL) {
error << _("LADSPA: module has no descriptor function.") << endmsg;
throw failed_constructor();
}
- if ((descriptor = dfunc (index)) == 0) {
+ if ((_descriptor = dfunc (index)) == 0) {
error << _("LADSPA: plugin has gone away since discovery!") << endmsg;
throw failed_constructor();
}
_index = index;
- if (LADSPA_IS_INPLACE_BROKEN(descriptor->Properties)) {
- error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), descriptor->Name) << endmsg;
+ if (LADSPA_IS_INPLACE_BROKEN(_descriptor->Properties)) {
+ error << string_compose(_("LADSPA: \"%1\" cannot be used, since it cannot do inplace processing"), _descriptor->Name) << endmsg;
throw failed_constructor();
}
- sample_rate = rate;
+ _sample_rate = rate;
- if (descriptor->instantiate == 0) {
+ if (_descriptor->instantiate == 0) {
throw failed_constructor();
}
- if ((handle = descriptor->instantiate (descriptor, rate)) == 0) {
+ if ((_handle = _descriptor->instantiate (_descriptor, rate)) == 0) {
throw failed_constructor();
}
port_cnt = parameter_count();
- control_data = new LADSPA_Data[port_cnt];
- shadow_data = new LADSPA_Data[port_cnt];
+ _control_data = new LADSPA_Data[port_cnt];
+ _shadow_data = new LADSPA_Data[port_cnt];
for (i = 0; i < port_cnt; ++i) {
if (LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
- connect_port (i, &control_data[i]);
+ connect_port (i, &_control_data[i]);
if (LADSPA_IS_PORT_OUTPUT(port_descriptor (i)) &&
strcmp (port_names()[i], X_("latency")) == 0) {
- latency_control_port = &control_data[i];
- *latency_control_port = 0;
+ _latency_control_port = &_control_data[i];
+ *_latency_control_port = 0;
}
if (!LADSPA_IS_PORT_INPUT(port_descriptor (i))) {
continue;
}
- shadow_data[i] = default_value (i);
+ _shadow_data[i] = default_value (i);
}
}
@@ -149,39 +149,12 @@ LadspaPlugin::~LadspaPlugin ()
// dlclose (module);
- if (control_data) {
- delete [] control_data;
+ if (_control_data) {
+ delete [] _control_data;
}
- if (shadow_data) {
- delete [] shadow_data;
- }
-}
-
-void
-LadspaPlugin::store_state (PluginState& state)
-{
- state.parameters.clear ();
-
- for (uint32_t i = 0; i < parameter_count(); ++i){
-
- if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) &&
- LADSPA_IS_PORT_CONTROL(port_descriptor (i))){
- pair<uint32_t,float> datum;
-
- datum.first = i;
- datum.second = shadow_data[i];
-
- state.parameters.insert (datum);
- }
- }
-}
-
-void
-LadspaPlugin::restore_state (PluginState& state)
-{
- for (map<uint32_t,float>::iterator i = state.parameters.begin(); i != state.parameters.end(); ++i) {
- set_parameter (i->first, i->second);
+ if (_shadow_data) {
+ delete [] _shadow_data;
}
}
@@ -189,7 +162,7 @@ string
LadspaPlugin::unique_id() const
{
char buf[32];
- snprintf (buf, sizeof (buf), "%lu", descriptor->UniqueID);
+ snprintf (buf, sizeof (buf), "%lu", _descriptor->UniqueID);
return string (buf);
}
@@ -308,10 +281,10 @@ LadspaPlugin::default_value (uint32_t port)
if (LADSPA_IS_HINT_SAMPLE_RATE(prh[port].HintDescriptor) && !earlier_hint) {
if (bounds_given) {
if (sr_scaling) {
- ret *= sample_rate;
+ ret *= _sample_rate;
}
} else {
- ret = sample_rate;
+ ret = _sample_rate;
}
}
@@ -321,8 +294,8 @@ LadspaPlugin::default_value (uint32_t port)
void
LadspaPlugin::set_parameter (uint32_t which, float val)
{
- if (which < descriptor->PortCount) {
- shadow_data[which] = (LADSPA_Data) val;
+ if (which < _descriptor->PortCount) {
+ _shadow_data[which] = (LADSPA_Data) val;
#if 0
ParameterChanged (Parameter(PluginAutomation, which), val); /* EMIT SIGNAL */
@@ -343,9 +316,9 @@ float
LadspaPlugin::get_parameter (uint32_t which) const
{
if (LADSPA_IS_PORT_INPUT(port_descriptor (which))) {
- return (float) shadow_data[which];
+ return (float) _shadow_data[which];
} else {
- return (float) control_data[which];
+ return (float) _control_data[which];
}
}
@@ -356,7 +329,7 @@ LadspaPlugin::nth_parameter (uint32_t n, bool& ok) const
ok = false;
- for (c = 0, x = 0; x < descriptor->PortCount; ++x) {
+ for (c = 0, x = 0; x < _descriptor->PortCount; ++x) {
if (LADSPA_IS_PORT_CONTROL (port_descriptor (x))) {
if (c++ == n) {
ok = true;
@@ -383,7 +356,7 @@ LadspaPlugin::get_state()
child = new XMLNode("port");
snprintf(buf, sizeof(buf), "%u", i);
child->add_property("number", string(buf));
- snprintf(buf, sizeof(buf), "%+f", shadow_data[i]);
+ snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]);
child->add_property("value", string(buf));
root->add_child_nocopy (*child);
}
@@ -515,8 +488,8 @@ LadspaPlugin::signal_latency () const
return _user_latency;
}
- if (latency_control_port) {
- return (nframes_t) floor (*latency_control_port);
+ if (_latency_control_port) {
+ return (nframes_t) floor (*_latency_control_port);
} else {
return 0;
}
@@ -617,16 +590,16 @@ LadspaPlugin::run_in_place (nframes_t nframes)
{
for (uint32_t i = 0; i < parameter_count(); ++i) {
if (LADSPA_IS_PORT_INPUT(port_descriptor (i)) && LADSPA_IS_PORT_CONTROL(port_descriptor (i))) {
- control_data[i] = shadow_data[i];
+ _control_data[i] = _shadow_data[i];
}
}
- descriptor->run (handle, nframes);
+ _descriptor->run (_handle, nframes);
}
void
LadspaPlugin::latency_compute_run ()
{
- if (!latency_control_port) {
+ if (!_latency_control_port) {
return;
}
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index f0465d0ad5..d321d6f259 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -328,7 +328,7 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
}
pattern.subject = matches1->object;
- pattern.predicate = (char*)LADSPA_BASE "hasLabel";
+ pattern.predicate = (char*)(LADSPA_BASE "hasLabel");
pattern.object = 0;
pattern.object_type = lrdf_literal;
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index cef5c7df48..19d562f844 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -273,7 +273,6 @@ Session::Session (AudioEngine &eng,
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
-
Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
}
@@ -711,7 +710,7 @@ Session::when_engine_running ()
osc->set_session (*this);
#endif
-
+
}
void
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index a08d09d949..d8d3d82810 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -716,7 +716,7 @@ Session::save_state (string snapshot_name, bool pending)
bool was_dirty = dirty();
_state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
-
+
if (was_dirty) {
DirtyChanged (); /* EMIT SIGNAL */
}
@@ -1270,8 +1270,8 @@ Session::set_state (const XMLNode& node)
}
if ((child = find_named_node (node, "Bundles")) == 0) {
- error << _("Session: XML state has no bundles section") << endmsg;
- goto out;
+ warning << _("Session: XML state has no bundles section (2.0 session?)") << endmsg;
+ //goto out;
} else {
/* We can't load Bundles yet as they need to be able
to convert from port names to Port objects, which can't happen until
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index 5969d91982..47b5cb4fba 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -510,15 +510,3 @@ VSTPluginInfo::load (Session& session)
return PluginPtr ((Plugin*) 0);
}
}
-
-void
-VSTPlugin::store_state (ARDOUR::PluginState& s)
-{
-
-}
-
-void
-VSTPlugin::restore_state (ARDOUR::PluginState& s)
-{
-
-}
diff --git a/libs/gtkmm2ext/fastmeter.cc b/libs/gtkmm2ext/fastmeter.cc
index 60fb35b969..1b440aaac9 100644
--- a/libs/gtkmm2ext/fastmeter.cc
+++ b/libs/gtkmm2ext/fastmeter.cc
@@ -97,6 +97,8 @@ Glib::RefPtr<Gdk::Pixbuf> FastMeter::request_vertical_meter(int width, int heigh
height = min_v_pixbuf_size;
if (height > max_v_pixbuf_size)
height = max_v_pixbuf_size;
+
+ //int index = height - 1;
//if (v_pixbuf_cache == 0) {
// v_pixbuf_cache = (Glib::RefPtr<Gdk::Pixbuf>*) malloc(sizeof(Glib::RefPtr<Gdk::Pixbuf>) * max_v_pixbuf_size);
@@ -363,7 +365,7 @@ FastMeter::vertical_expose (GdkEventExpose* ev)
background.width = pixrect.width;
background.height = pixheight - top_of_meter;
- if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
+ if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
get_window()->draw_rectangle (get_style()->get_black_gc(), true,
intersection.x, intersection.y,
intersection.width, intersection.height);
@@ -408,7 +410,7 @@ FastMeter::horizontal_expose (GdkEventExpose* ev)
background.width = pixwidth - right_of_meter;
background.height = pixrect.height;
- if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
+ if (gdk_rectangle_intersect (&background, &ev->area, &intersection)) {
get_window()->draw_rectangle (get_style()->get_black_gc(), true,
intersection.x + right_of_meter, intersection.y,
intersection.width, intersection.height);
@@ -419,7 +421,7 @@ FastMeter::horizontal_expose (GdkEventExpose* ev)
get_window()->draw_pixbuf(get_style()->get_fg_gc(get_state()), pixbuf,
intersection.x, intersection.y,
intersection.x, intersection.y,
- intersection.width, intersection.height,
+ pixrect.width, intersection.height,
Gdk::RGB_DITHER_NONE, 0, 0);
}
diff --git a/libs/vamp-sdk/COPYING b/libs/vamp-sdk/COPYING
new file mode 100644
index 0000000000..19fa472218
--- /dev/null
+++ b/libs/vamp-sdk/COPYING
@@ -0,0 +1,26 @@
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+
diff --git a/libs/vamp-sdk/README b/libs/vamp-sdk/README
new file mode 100644
index 0000000000..9454038260
--- /dev/null
+++ b/libs/vamp-sdk/README
@@ -0,0 +1,240 @@
+
+Vamp
+====
+
+An API for audio analysis and feature extraction plugins.
+
+ http://www.vamp-plugins.org/
+
+Vamp is an API for C and C++ plugins that process sampled audio data
+to produce descriptive output (measurements or semantic observations).
+
+The principal differences between Vamp and a real-time audio
+processing plugin system such as VST are:
+
+ * Vamp plugins may output complex multidimensional data with labels.
+ As a consequence, they are likely to work best when the output
+ data has a much lower sampling rate than the input. (This also
+ means it is usually desirable to implement them in C++ using the
+ high-level base class provided rather than use the raw C API.)
+
+ * While Vamp plugins receive data block-by-block, they are not
+ required to return output immediately on receiving the input.
+ A Vamp plugin may be non-causal, preferring to store up data
+ based on its input until the end of a processing run and then
+ return all results at once.
+
+ * Vamp plugins have more control over their inputs than a typical
+ real-time processing plugin. For example, they can indicate to
+ the host their preferred processing block and step sizes, and these
+ may differ.
+
+ * Vamp plugins may ask to receive data in the frequency domain
+ instead of the time domain. The host takes the responsibility
+ for converting the input data using an FFT of windowed frames.
+ This simplifies plugins that do straightforward frequency-domain
+ processing and permits the host to cache frequency-domain data
+ when possible.
+
+ * A Vamp plugin is configured once before each processing run, and
+ receives no further parameter changes during use -- unlike real-
+ time plugin APIs in which the input parameters may change at any
+ time. This also means that fundamental properties such as the
+ number of values per output or the preferred processing block
+ size may depend on the input parameters.
+
+ * Vamp plugins do not have to be able to run in real time.
+
+
+About this SDK
+==============
+
+This is version 1.1b of the Vamp plugin Software Development Kit.
+Plugins and hosts built with this SDK are binary compatible with those
+built using version 1.0 of the SDK.
+
+This SDK contains the following:
+
+ * vamp/vamp.h
+
+The formal C language plugin API for Vamp plugins.
+
+A Vamp plugin is a dynamic library (.so, .dll or .dylib depending on
+platform) exposing one C-linkage entry point (vampGetPluginDescriptor)
+which returns data defined in the rest of this C header.
+
+Although the C API is the official API for Vamp, we don't recommend
+that you program directly to it. The C++ abstraction found in the
+vamp-sdk directory (below) is preferable for most purposes and is
+more thoroughly documented.
+
+ * vamp-sdk
+
+C++ classes for straightforwardly implementing Vamp plugins and hosts.
+
+Plugins should subclass Vamp::Plugin and then use Vamp::PluginAdapter
+to expose the correct C API for the plugin. Plugin authors should
+read vamp-sdk/PluginBase.h and Plugin.h for code documentation, and
+refer to the example plugin code in the examples directory. Plugins
+should link with -lvampsdk. [*NOTE: this has changed from vamp-sdk in
+previous versions, to avoid conflict with the use of hyphens for
+library versioning schemes on some platforms.]
+
+Hosts may use the Vamp::PluginHostAdapter to convert the loaded
+plugin's C API back into a Vamp::Plugin object. Host authors should
+refer to the example host code in the host directory. Hosts should
+link with -lvamphostsdk. [*NOTE: this has changed from vamp-hostsdk
+in previous versions, to avoid conflict with the use of hyphens for
+library versioning schemes on some platforms.]
+
+ * vamp-sdk/hostext
+
+Additional C++ classes to make a host's life easier (introduced in
+version 1.1 of the Vamp SDK).
+
+Vamp::HostExt::PluginLoader provides a very easy interface for a host
+to discover, load, and find out category information about the
+available plugins. Most "casual" Vamp hosts will probably want to use
+this class.
+
+Vamp::HostExt::PluginInputDomainAdapter provides a means for hosts to
+handle plugins that expect frequency-domain input, without having to
+convert the input themselves.
+
+Vamp::HostExt::PluginChannelAdapter provides a means for hosts to use
+plugins that do not necessarily support the same number of audio
+channels as they have available, without having to worry about
+applying a channel management / mixdown policy themselves.
+
+The PluginLoader class can also use the input domain and channel
+adapters automatically to make the entire conversion process
+transparent to the host if required.
+
+ * examples
+
+Example plugins implemented using the C++ classes. ZeroCrossing
+calculates the positions and density of zero-crossing points in an
+audio waveform. SpectralCentroid calculates the centre of gravity of
+the frequency domain representation of each block of audio.
+AmplitudeFollower tracks the amplitude of a signal based on a method
+from the SuperCollider real-time audio system.
+PercussionOnsetDetector estimates the locations of percussive onsets
+using a simple method described in "Drum Source Separation using
+Percussive Feature Detection and Spectral Modulation" by Dan Barry,
+Derry Fitzgerald, Eugene Coyle and Bob Lawlor, ISSC 2005.
+
+ * host
+
+A simple command-line Vamp host, capable of loading a plugin and using
+it to process a complete audio file, with its default parameters.
+Requires libsndfile (http://www.mega-nerd.com/libsndfile/).
+
+If you don't have libsndfile, you may want to edit the Makefile to
+change the default build target from "all" to "sdk", so as to compile
+only the SDK and not the host.
+
+
+Plugin Lookup and Categorisation
+================================
+
+The Vamp API does not officially specify how to load plugin libraries
+or where to find them. However, the SDK does include a function
+(Vamp::PluginHostAdapter::getPluginPath()) that returns a recommended
+directory search path that hosts may use for plugin libraries, and a
+class (Vamp::HostExt::PluginLoader) that implements a sensible
+cross-platform lookup policy using this path. We recommend using this
+class in your host unless you have a good reason not to want to. This
+implementation also permits the user to set the environment variable
+VAMP_PATH to override the default path if desired.
+
+The policy used by Vamp::HostExt::PluginLoader -- and our
+recommendation for any host -- is to search each directory in the path
+returned by getPluginPath for .DLL (on Windows), .so (on Linux,
+Solaris, BSD etc) or .dylib (on OS/X) files, then to load each one and
+perform a dynamic name lookup on the vampGetPluginDescriptor function
+to enumerate the plugins in the library. This operation will
+necessarily be system-dependent.
+
+Vamp also has an informal convention for sorting plugins into
+functional categories. In addition to the library file itself, a
+plugin library may install a category file with the same name as the
+library but .cat extension. The existence and format of this file are
+not specified by the Vamp API, but by convention the file may contain
+lines of the format
+
+vamp:pluginlibrary:pluginname::General Category > Specific Category
+
+which a host may read and use to assign plugins a location within a
+category tree for display to the user. The expectation is that
+advanced users may also choose to set up their own preferred category
+trees, which is why this information is not queried as part of the
+Vamp plugin's API itself. The Vamp::HostExt::PluginLoader class also
+provides support for plugin category lookup using this scheme.
+
+
+Building and Installing the SDK and Examples
+============================================
+
+To build the SDK, the simple host, and the example plugins, edit the
+Makefile to suit your platform according to the comments in it, then
+run "make".
+
+To use an IDE to build a plugin or host using the Vamp SDK, simply add
+the .cpp files in the vamp-sdk directory to your project.
+
+Installing the example plugins so that they can be found by other Vamp
+hosts depends on your platform:
+
+ * Windows: copy the files
+ examples/vamp-example-plugins.dll
+ examples/vamp-example-plugins.cat
+ to
+ C:\Program Files\Vamp Plugins
+
+ * Linux: copy the files
+ examples/vamp-example-plugins.so
+ examples/vamp-example-plugins.cat
+ to
+ /usr/local/lib/vamp/
+
+ * OS/X: copy the files
+ examples/vamp-example-plugins.dylib
+ examples/vamp-example-plugins.cat
+ to
+ /Library/Audio/Plug-Ins/Vamp
+
+
+Licensing
+=========
+
+This plugin SDK is freely redistributable under a "new-style BSD"
+licence. See the file COPYING for more details. In short, you may
+modify and redistribute the SDK and example plugins within any
+commercial or non-commercial, proprietary or open-source plugin or
+application under almost any conditions, with no obligation to provide
+source code, provided you retain the original copyright note.
+
+
+See Also
+========
+
+Sonic Visualiser, an interactive open-source graphical audio
+inspection, analysis and visualisation tool supporting Vamp plugins.
+http://www.sonicvisualiser.org/
+
+
+Authors
+=======
+
+Vamp and the Vamp SDK were designed and made at the Centre for Digital
+Music at Queen Mary, University of London.
+
+The SDK was written by Chris Cannam, copyright (c) 2005-2007
+Chris Cannam and QMUL.
+
+Mark Sandler and Christian Landone provided ideas and direction, and
+Mark Levy, Dan Stowell, Martin Gasser and Craig Sapp provided testing
+and other input for the 1.0 API and SDK. The API also uses some ideas
+from prior plugin systems, notably DSSI (http://dssi.sourceforge.net)
+and FEAPI (http://feapi.sourceforge.net).
+
diff --git a/libs/vamp-sdk/SConscript b/libs/vamp-sdk/SConscript
new file mode 100644
index 0000000000..ddd3d8ebbc
--- /dev/null
+++ b/libs/vamp-sdk/SConscript
@@ -0,0 +1,39 @@
+# -*- python -*-
+
+import os
+import os.path
+import glob
+
+vampsdk_files = Split ("""
+vamp-sdk/PluginAdapter.cpp
+vamp-sdk/RealTime.cpp
+""")
+
+vamphostsdk_files = Split ("""
+vamp-sdk/PluginHostAdapter.cpp
+vamp-sdk/hostext/PluginChannelAdapter.cpp
+vamp-sdk/hostext/PluginInputDomainAdapter.cpp
+vamp-sdk/hostext/PluginLoader.cpp
+vamp-sdk/hostext/PluginWrapper.cpp
+vamp-sdk/RealTime.cpp
+""")
+
+Import('env install_prefix libraries')
+vampsdk = env.Copy()
+
+vampsdk.Append (CPPATH='#libs/vamp-sdk/vamp', CXXFLAGS="-Ilibs/vamp-sdk")
+
+libvampsdk = vampsdk.SharedLibrary('vampsdk', vampsdk_files)
+libvamphostsdk = vampsdk.SharedLibrary('vamphostsdk', vamphostsdk_files)
+
+Default(libvampsdk)
+Default(libvamphostsdk)
+
+env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ardour2'), libvampsdk))
+env.Alias('tarball', env.Distribute (env['DISTTREE'],
+ [ 'SConscript', 'COPYING', 'README' ] +
+ vampsdk_files +
+ vamphostsdk_files +
+ glob.glob('vamp/*.h') +
+ glob.glob('vamp-sdk/*.h') +
+ glob.glob('vamp-sdk/hostext/*.h')))
diff --git a/libs/vamp-sdk/vamp-sdk/Plugin.h b/libs/vamp-sdk/vamp-sdk/Plugin.h
new file mode 100644
index 0000000000..159bf4fac6
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/Plugin.h
@@ -0,0 +1,405 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_H_
+#define _VAMP_PLUGIN_H_
+
+#include "PluginBase.h"
+#include "RealTime.h"
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace Vamp {
+
+/**
+ * \class Plugin Plugin.h <vamp-sdk/Plugin.h>
+ *
+ * Vamp::Plugin is a base class for plugin instance classes
+ * that provide feature extraction from audio or related data.
+ *
+ * In most cases, the input will be audio and the output will be a
+ * stream of derived data at a lower sampling resolution than the
+ * input.
+ *
+ * Note that this class inherits several abstract methods from
+ * PluginBase. These must be implemented by the subclass.
+ *
+ *
+ * PLUGIN LIFECYCLE
+ *
+ * Feature extraction plugins are managed differently from real-time
+ * plugins (such as VST effects). The main difference is that the
+ * parameters for a feature extraction plugin are configured before
+ * the plugin is used, and do not change during use.
+ *
+ * 1. Host constructs the plugin, passing it the input sample rate.
+ * The plugin may do basic initialisation, but should not do anything
+ * computationally expensive at this point. You must make sure your
+ * plugin is cheap to construct, otherwise you'll seriously affect the
+ * startup performance of almost all hosts. If you have serious
+ * initialisation to do, the proper place is in initialise() (step 5).
+ *
+ * 2. Host may query the plugin's available outputs.
+ *
+ * 3. Host queries programs and parameter descriptors, and may set
+ * some or all of them. Parameters that are not explicitly set should
+ * take their default values as specified in the parameter descriptor.
+ * When a program is set, the parameter values may change and the host
+ * will re-query them to check.
+ *
+ * 4. Host queries the preferred step size, block size and number of
+ * channels. These may all vary depending on the parameter values.
+ * (Note however that you cannot make the number of distinct outputs
+ * dependent on parameter values.)
+ *
+ * 5. Plugin is properly initialised with a call to initialise. This
+ * fixes the step size, block size, and number of channels, as well as
+ * all of the parameter and program settings. If the values passed in
+ * to initialise do not match the plugin's advertised preferred values
+ * from step 4, the plugin may refuse to initialise and return false
+ * (although if possible it should accept the new values). Any
+ * computationally expensive setup code should take place here.
+ *
+ * 6. Host finally checks the number of values, resolution, extents
+ * etc per output (which may vary depending on the number of channels,
+ * step size and block size as well as the parameter values).
+ *
+ * 7. Host will repeatedly call the process method to pass in blocks
+ * of input data. This method may return features extracted from that
+ * data (if the plugin is causal).
+ *
+ * 8. Host will call getRemainingFeatures exactly once, after all the
+ * input data has been processed. This may return any non-causal or
+ * leftover features.
+ *
+ * 9. At any point after initialise was called, the host may
+ * optionally call the reset method and restart processing. (This
+ * does not mean it can change the parameters, which are fixed from
+ * initialise until destruction.)
+ *
+ * A plugin does not need to handle the case where setParameter or
+ * selectProgram is called after initialise has been called. It's the
+ * host's responsibility not to do that. Similarly, the plugin may
+ * safely assume that initialise is called no more than once.
+ */
+
+class Plugin : public PluginBase
+{
+public:
+ virtual ~Plugin() { }
+
+ /**
+ * Initialise a plugin to prepare it for use with the given number
+ * of input channels, step size (window increment, in sample
+ * frames) and block size (window size, in sample frames).
+ *
+ * The input sample rate should have been already specified at
+ * construction time.
+ *
+ * Return true for successful initialisation, false if the number
+ * of input channels, step size and/or block size cannot be
+ * supported.
+ */
+ virtual bool initialise(size_t inputChannels,
+ size_t stepSize,
+ size_t blockSize) = 0;
+
+ /**
+ * Reset the plugin after use, to prepare it for another clean
+ * run. Not called for the first initialisation (i.e. initialise
+ * must also do a reset).
+ */
+ virtual void reset() = 0;
+
+ enum InputDomain { TimeDomain, FrequencyDomain };
+
+ /**
+ * Get the plugin's required input domain. If this is TimeDomain,
+ * the samples provided to the process() function (below) will be
+ * in the time domain, as for a traditional audio processing
+ * plugin. If this is FrequencyDomain, the host will carry out a
+ * windowed FFT of size equal to the negotiated block size on the
+ * data before passing the frequency bin data in to process().
+ * The plugin does not get to choose the window type -- the host
+ * will either let the user do so, or will use a Hanning window.
+ */
+ virtual InputDomain getInputDomain() const = 0;
+
+ /**
+ * Get the preferred block size (window size -- the number of
+ * sample frames passed in each block to the process() function).
+ * This should be called before initialise().
+ *
+ * A plugin that can handle any block size may return 0. The
+ * final block size will be set in the initialise() call.
+ */
+ virtual size_t getPreferredBlockSize() const { return 0; }
+
+ /**
+ * Get the preferred step size (window increment -- the distance
+ * in sample frames between the start frames of consecutive blocks
+ * passed to the process() function) for the plugin. This should
+ * be called before initialise().
+ *
+ * A plugin may return 0 if it has no particular interest in the
+ * step size. In this case, the host should make the step size
+ * equal to the block size if the plugin is accepting input in the
+ * time domain. If the plugin is accepting input in the frequency
+ * domain, the host may use any step size. The final step size
+ * will be set in the initialise() call.
+ */
+ virtual size_t getPreferredStepSize() const { return 0; }
+
+ /**
+ * Get the minimum supported number of input channels.
+ */
+ virtual size_t getMinChannelCount() const { return 1; }
+
+ /**
+ * Get the maximum supported number of input channels.
+ */
+ virtual size_t getMaxChannelCount() const { return 1; }
+
+ struct OutputDescriptor
+ {
+ /**
+ * The name of the output, in computer-usable form. Should be
+ * reasonably short and without whitespace or punctuation, using
+ * the characters [a-zA-Z0-9_] only.
+ * Example: "zero_crossing_count"
+ */
+ std::string identifier;
+
+ /**
+ * The human-readable name of the output.
+ * Example: "Zero Crossing Counts"
+ */
+ std::string name;
+
+ /**
+ * A human-readable short text describing the output. May be
+ * empty if the name has said it all already.
+ * Example: "The number of zero crossing points per processing block"
+ */
+ std::string description;
+
+ /**
+ * The unit of the output, in human-readable form.
+ */
+ std::string unit;
+
+ /**
+ * True if the output has the same number of values per sample
+ * for every output sample. Outputs for which this is false
+ * are unlikely to be very useful in a general-purpose host.
+ */
+ bool hasFixedBinCount;
+
+ /**
+ * The number of values per result of the output. Undefined
+ * if hasFixedBinCount is false. If this is zero, the output
+ * is point data (i.e. only the time of each output is of
+ * interest, the value list will be empty).
+ */
+ size_t binCount;
+
+ /**
+ * The (human-readable) names of each of the bins, if
+ * appropriate. This is always optional.
+ */
+ std::vector<std::string> binNames;
+
+ /**
+ * True if the results in each output bin fall within a fixed
+ * numeric range (minimum and maximum values). Undefined if
+ * binCount is zero.
+ */
+ bool hasKnownExtents;
+
+ /**
+ * Minimum value of the results in the output. Undefined if
+ * hasKnownExtents is false or binCount is zero.
+ */
+ float minValue;
+
+ /**
+ * Maximum value of the results in the output. Undefined if
+ * hasKnownExtents is false or binCount is zero.
+ */
+ float maxValue;
+
+ /**
+ * True if the output values are quantized to a particular
+ * resolution. Undefined if binCount is zero.
+ */
+ bool isQuantized;
+
+ /**
+ * Quantization resolution of the output values (e.g. 1.0 if
+ * they are all integers). Undefined if isQuantized is false
+ * or binCount is zero.
+ */
+ float quantizeStep;
+
+ enum SampleType {
+
+ /// Results from each process() align with that call's block start
+ OneSamplePerStep,
+
+ /// Results are evenly spaced in time (sampleRate specified below)
+ FixedSampleRate,
+
+ /// Results are unevenly spaced and have individual timestamps
+ VariableSampleRate
+ };
+
+ /**
+ * Positioning in time of the output results.
+ */
+ SampleType sampleType;
+
+ /**
+ * Sample rate of the output results, as samples per second.
+ * Undefined if sampleType is OneSamplePerStep.
+ *
+ * If sampleType is VariableSampleRate and this value is
+ * non-zero, then it may be used to calculate a resolution for
+ * the output (i.e. the "duration" of each sample, in time,
+ * will be 1/sampleRate seconds). It's recommended to set
+ * this to zero if that behaviour is not desired.
+ */
+ float sampleRate;
+ };
+
+ typedef std::vector<OutputDescriptor> OutputList;
+
+ /**
+ * Get the outputs of this plugin. An output's index in this list
+ * is used as its numeric index when looking it up in the
+ * FeatureSet returned from the process() call.
+ */
+ virtual OutputList getOutputDescriptors() const = 0;
+
+ struct Feature
+ {
+ /**
+ * True if an output feature has its own timestamp. This is
+ * mandatory if the output has VariableSampleRate, and is
+ * likely to be disregarded otherwise.
+ */
+ bool hasTimestamp;
+
+ /**
+ * Timestamp of the output feature. This is mandatory if the
+ * output has VariableSampleRate, and is likely to be
+ * disregarded otherwise. Undefined if hasTimestamp is false.
+ */
+ RealTime timestamp;
+
+ /**
+ * Results for a single sample of this feature. If the output
+ * hasFixedBinCount, there must be the same number of values
+ * as the output's binCount count.
+ */
+ std::vector<float> values;
+
+ /**
+ * Label for the sample of this feature.
+ */
+ std::string label;
+ };
+
+ typedef std::vector<Feature> FeatureList;
+ typedef std::map<int, FeatureList> FeatureSet; // key is output no
+
+ /**
+ * Process a single block of input data.
+ *
+ * If the plugin's inputDomain is TimeDomain, inputBuffers will
+ * point to one array of floats per input channel, and each of
+ * these arrays will contain blockSize consecutive audio samples
+ * (the host will zero-pad as necessary). The timestamp will be
+ * the real time in seconds of the start of the supplied block of
+ * samples.
+ *
+ * If the plugin's inputDomain is FrequencyDomain, inputBuffers
+ * will point to one array of floats per input channel, and each
+ * of these arrays will contain blockSize/2+1 consecutive pairs of
+ * real and imaginary component floats corresponding to bins
+ * 0..(blockSize/2) of the FFT output. That is, bin 0 (the first
+ * pair of floats) contains the DC output, up to bin blockSize/2
+ * which contains the Nyquist-frequency output. There will
+ * therefore be blockSize+2 floats per channel in total. The
+ * timestamp will be the real time in seconds of the centre of the
+ * FFT input window (i.e. the very first block passed to process
+ * might contain the FFT of half a block of zero samples and the
+ * first half-block of the actual data, with a timestamp of zero).
+ *
+ * Return any features that have become available after this
+ * process call. (These do not necessarily have to fall within
+ * the process block, except for OneSamplePerStep outputs.)
+ */
+ virtual FeatureSet process(const float *const *inputBuffers,
+ RealTime timestamp) = 0;
+
+ /**
+ * After all blocks have been processed, calculate and return any
+ * remaining features derived from the complete input.
+ */
+ virtual FeatureSet getRemainingFeatures() = 0;
+
+ /**
+ * Used to distinguish between Vamp::Plugin and other potential
+ * sibling subclasses of PluginBase. Do not reimplement this
+ * function in your subclass.
+ */
+ virtual std::string getType() const { return "Feature Extraction Plugin"; }
+
+protected:
+ Plugin(float inputSampleRate) :
+ m_inputSampleRate(inputSampleRate) { }
+
+ float m_inputSampleRate;
+};
+
+}
+
+#endif
+
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/PluginAdapter.cpp b/libs/vamp-sdk/vamp-sdk/PluginAdapter.cpp
new file mode 100644
index 0000000000..1549b4f3aa
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/PluginAdapter.cpp
@@ -0,0 +1,851 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include "PluginAdapter.h"
+
+//#define DEBUG_PLUGIN_ADAPTER 1
+
+
+namespace Vamp {
+
+class PluginAdapterBase::Impl
+{
+public:
+ Impl(PluginAdapterBase *);
+ ~Impl();
+
+ const VampPluginDescriptor *getDescriptor();
+
+protected:
+ PluginAdapterBase *m_base;
+
+ static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc,
+ float inputSampleRate);
+
+ static void vampCleanup(VampPluginHandle handle);
+
+ static int vampInitialise(VampPluginHandle handle, unsigned int channels,
+ unsigned int stepSize, unsigned int blockSize);
+
+ static void vampReset(VampPluginHandle handle);
+
+ static float vampGetParameter(VampPluginHandle handle, int param);
+ static void vampSetParameter(VampPluginHandle handle, int param, float value);
+
+ static unsigned int vampGetCurrentProgram(VampPluginHandle handle);
+ static void vampSelectProgram(VampPluginHandle handle, unsigned int program);
+
+ static unsigned int vampGetPreferredStepSize(VampPluginHandle handle);
+ static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle);
+ static unsigned int vampGetMinChannelCount(VampPluginHandle handle);
+ static unsigned int vampGetMaxChannelCount(VampPluginHandle handle);
+
+ static unsigned int vampGetOutputCount(VampPluginHandle handle);
+
+ static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle,
+ unsigned int i);
+
+ static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc);
+
+ static VampFeatureList *vampProcess(VampPluginHandle handle,
+ const float *const *inputBuffers,
+ int sec,
+ int nsec);
+
+ static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle);
+
+ static void vampReleaseFeatureSet(VampFeatureList *fs);
+
+ void cleanup(Plugin *plugin);
+ void checkOutputMap(Plugin *plugin);
+ unsigned int getOutputCount(Plugin *plugin);
+ VampOutputDescriptor *getOutputDescriptor(Plugin *plugin,
+ unsigned int i);
+ VampFeatureList *process(Plugin *plugin,
+ const float *const *inputBuffers,
+ int sec, int nsec);
+ VampFeatureList *getRemainingFeatures(Plugin *plugin);
+ VampFeatureList *convertFeatures(Plugin *plugin,
+ const Plugin::FeatureSet &features);
+
+ // maps both plugins and descriptors to adapters
+ typedef std::map<const void *, Impl *> AdapterMap;
+ static AdapterMap *m_adapterMap;
+ static Impl *lookupAdapter(VampPluginHandle);
+
+ bool m_populated;
+ VampPluginDescriptor m_descriptor;
+ Plugin::ParameterList m_parameters;
+ Plugin::ProgramList m_programs;
+
+ typedef std::map<Plugin *, Plugin::OutputList *> OutputMap;
+ OutputMap m_pluginOutputs;
+
+ std::map<Plugin *, VampFeatureList *> m_fs;
+ std::map<Plugin *, std::vector<size_t> > m_fsizes;
+ std::map<Plugin *, std::vector<std::vector<size_t> > > m_fvsizes;
+ void resizeFS(Plugin *plugin, int n);
+ void resizeFL(Plugin *plugin, int n, size_t sz);
+ void resizeFV(Plugin *plugin, int n, int j, size_t sz);
+};
+
+PluginAdapterBase::PluginAdapterBase()
+{
+ m_impl = new Impl(this);
+}
+
+PluginAdapterBase::~PluginAdapterBase()
+{
+ delete m_impl;
+}
+
+const VampPluginDescriptor *
+PluginAdapterBase::getDescriptor()
+{
+ return m_impl->getDescriptor();
+}
+
+PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
+ m_base(base),
+ m_populated(false)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << std::endl;
+#endif
+}
+
+const VampPluginDescriptor *
+PluginAdapterBase::Impl::getDescriptor()
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << std::endl;
+#endif
+
+ if (m_populated) return &m_descriptor;
+
+ Plugin *plugin = m_base->createPlugin(48000);
+
+ if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
+ std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
+ << "Plugin object API version "
+ << plugin->getVampApiVersion()
+ << " does not match actual API version "
+ << VAMP_API_VERSION << std::endl;
+ delete plugin;
+ return 0;
+ }
+
+ m_parameters = plugin->getParameterDescriptors();
+ m_programs = plugin->getPrograms();
+
+ m_descriptor.vampApiVersion = plugin->getVampApiVersion();
+ m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
+ m_descriptor.name = strdup(plugin->getName().c_str());
+ m_descriptor.description = strdup(plugin->getDescription().c_str());
+ m_descriptor.maker = strdup(plugin->getMaker().c_str());
+ m_descriptor.pluginVersion = plugin->getPluginVersion();
+ m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
+
+ m_descriptor.parameterCount = m_parameters.size();
+ m_descriptor.parameters = (const VampParameterDescriptor **)
+ malloc(m_parameters.size() * sizeof(VampParameterDescriptor));
+
+ unsigned int i;
+
+ for (i = 0; i < m_parameters.size(); ++i) {
+ VampParameterDescriptor *desc = (VampParameterDescriptor *)
+ malloc(sizeof(VampParameterDescriptor));
+ desc->identifier = strdup(m_parameters[i].identifier.c_str());
+ desc->name = strdup(m_parameters[i].name.c_str());
+ desc->description = strdup(m_parameters[i].description.c_str());
+ desc->unit = strdup(m_parameters[i].unit.c_str());
+ desc->minValue = m_parameters[i].minValue;
+ desc->maxValue = m_parameters[i].maxValue;
+ desc->defaultValue = m_parameters[i].defaultValue;
+ desc->isQuantized = m_parameters[i].isQuantized;
+ desc->quantizeStep = m_parameters[i].quantizeStep;
+ desc->valueNames = 0;
+ if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
+ desc->valueNames = (const char **)
+ malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
+ for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
+ desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
+ }
+ desc->valueNames[m_parameters[i].valueNames.size()] = 0;
+ }
+ m_descriptor.parameters[i] = desc;
+ }
+
+ m_descriptor.programCount = m_programs.size();
+ m_descriptor.programs = (const char **)
+ malloc(m_programs.size() * sizeof(const char *));
+
+ for (i = 0; i < m_programs.size(); ++i) {
+ m_descriptor.programs[i] = strdup(m_programs[i].c_str());
+ }
+
+ if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
+ m_descriptor.inputDomain = vampFrequencyDomain;
+ } else {
+ m_descriptor.inputDomain = vampTimeDomain;
+ }
+
+ m_descriptor.instantiate = vampInstantiate;
+ m_descriptor.cleanup = vampCleanup;
+ m_descriptor.initialise = vampInitialise;
+ m_descriptor.reset = vampReset;
+ m_descriptor.getParameter = vampGetParameter;
+ m_descriptor.setParameter = vampSetParameter;
+ m_descriptor.getCurrentProgram = vampGetCurrentProgram;
+ m_descriptor.selectProgram = vampSelectProgram;
+ m_descriptor.getPreferredStepSize = vampGetPreferredStepSize;
+ m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize;
+ m_descriptor.getMinChannelCount = vampGetMinChannelCount;
+ m_descriptor.getMaxChannelCount = vampGetMaxChannelCount;
+ m_descriptor.getOutputCount = vampGetOutputCount;
+ m_descriptor.getOutputDescriptor = vampGetOutputDescriptor;
+ m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor;
+ m_descriptor.process = vampProcess;
+ m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
+ m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
+
+ if (!m_adapterMap) {
+ m_adapterMap = new AdapterMap;
+ }
+ (*m_adapterMap)[&m_descriptor] = this;
+
+ delete plugin;
+
+ m_populated = true;
+ return &m_descriptor;
+}
+
+PluginAdapterBase::Impl::~Impl()
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << std::endl;
+#endif
+
+ if (!m_populated) return;
+
+ free((void *)m_descriptor.identifier);
+ free((void *)m_descriptor.name);
+ free((void *)m_descriptor.description);
+ free((void *)m_descriptor.maker);
+ free((void *)m_descriptor.copyright);
+
+ for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
+ const VampParameterDescriptor *desc = m_descriptor.parameters[i];
+ free((void *)desc->identifier);
+ free((void *)desc->name);
+ free((void *)desc->description);
+ free((void *)desc->unit);
+ if (desc->valueNames) {
+ for (unsigned int j = 0; desc->valueNames[j]; ++j) {
+ free((void *)desc->valueNames[j]);
+ }
+ free((void *)desc->valueNames);
+ }
+ }
+ free((void *)m_descriptor.parameters);
+
+ for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
+ free((void *)m_descriptor.programs[i]);
+ }
+ free((void *)m_descriptor.programs);
+
+ if (m_adapterMap) {
+
+ m_adapterMap->erase(&m_descriptor);
+
+ if (m_adapterMap->empty()) {
+ delete m_adapterMap;
+ m_adapterMap = 0;
+ }
+ }
+}
+
+PluginAdapterBase::Impl *
+PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << std::endl;
+#endif
+
+ if (!m_adapterMap) return 0;
+ AdapterMap::const_iterator i = m_adapterMap->find(handle);
+ if (i == m_adapterMap->end()) return 0;
+ return i->second;
+}
+
+VampPluginHandle
+PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
+ float inputSampleRate)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << std::endl;
+#endif
+
+ if (!m_adapterMap) {
+ m_adapterMap = new AdapterMap();
+ }
+
+ if (m_adapterMap->find(desc) == m_adapterMap->end()) {
+ std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl;
+ return 0;
+ }
+
+ Impl *adapter = (*m_adapterMap)[desc];
+ if (desc != &adapter->m_descriptor) return 0;
+
+ Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
+ if (plugin) {
+ (*m_adapterMap)[plugin] = adapter;
+ }
+
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << std::endl;
+#endif
+
+ return plugin;
+}
+
+void
+PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) {
+ delete ((Plugin *)handle);
+ return;
+ }
+ adapter->cleanup(((Plugin *)handle));
+}
+
+int
+PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
+ unsigned int channels,
+ unsigned int stepSize,
+ unsigned int blockSize)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << std::endl;
+#endif
+
+ bool result = ((Plugin *)handle)->initialise
+ (channels, stepSize, blockSize);
+ return result ? 1 : 0;
+}
+
+void
+PluginAdapterBase::Impl::vampReset(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << std::endl;
+#endif
+
+ ((Plugin *)handle)->reset();
+}
+
+float
+PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
+ int param)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0.0;
+ Plugin::ParameterList &list = adapter->m_parameters;
+ return ((Plugin *)handle)->getParameter(list[param].identifier);
+}
+
+void
+PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
+ int param, float value)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return;
+ Plugin::ParameterList &list = adapter->m_parameters;
+ ((Plugin *)handle)->setParameter(list[param].identifier, value);
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0;
+ Plugin::ProgramList &list = adapter->m_programs;
+ std::string program = ((Plugin *)handle)->getCurrentProgram();
+ for (unsigned int i = 0; i < list.size(); ++i) {
+ if (list[i] == program) return i;
+ }
+ return 0;
+}
+
+void
+PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
+ unsigned int program)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return;
+ Plugin::ProgramList &list = adapter->m_programs;
+ ((Plugin *)handle)->selectProgram(list[program]);
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getPreferredStepSize();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getPreferredBlockSize();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getMinChannelCount();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << std::endl;
+#endif
+
+ return ((Plugin *)handle)->getMaxChannelCount();
+}
+
+unsigned int
+PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+
+// std::cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << std::endl;
+
+ if (!adapter) return 0;
+ return adapter->getOutputCount((Plugin *)handle);
+}
+
+VampOutputDescriptor *
+PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
+ unsigned int i)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+
+// std::cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << std::endl;
+
+ if (!adapter) return 0;
+ return adapter->getOutputDescriptor((Plugin *)handle, i);
+}
+
+void
+PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << std::endl;
+#endif
+
+ if (desc->identifier) free((void *)desc->identifier);
+ if (desc->name) free((void *)desc->name);
+ if (desc->description) free((void *)desc->description);
+ if (desc->unit) free((void *)desc->unit);
+ if (desc->hasFixedBinCount && desc->binNames) {
+ for (unsigned int i = 0; i < desc->binCount; ++i) {
+ if (desc->binNames[i]) {
+ free((void *)desc->binNames[i]);
+ }
+ }
+ }
+ if (desc->binNames) free((void *)desc->binNames);
+ free((void *)desc);
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
+ const float *const *inputBuffers,
+ int sec,
+ int nsec)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0;
+ return adapter->process((Plugin *)handle,
+ inputBuffers, sec, nsec);
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << std::endl;
+#endif
+
+ Impl *adapter = lookupAdapter(handle);
+ if (!adapter) return 0;
+ return adapter->getRemainingFeatures((Plugin *)handle);
+}
+
+void
+PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs)
+{
+#ifdef DEBUG_PLUGIN_ADAPTER
+ std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl;
+#endif
+}
+
+void
+PluginAdapterBase::Impl::cleanup(Plugin *plugin)
+{
+ if (m_fs.find(plugin) != m_fs.end()) {
+ size_t outputCount = 0;
+ if (m_pluginOutputs[plugin]) {
+ outputCount = m_pluginOutputs[plugin]->size();
+ }
+ VampFeatureList *list = m_fs[plugin];
+ for (unsigned int i = 0; i < outputCount; ++i) {
+ for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
+ if (list[i].features[j].label) {
+ free(list[i].features[j].label);
+ }
+ if (list[i].features[j].values) {
+ free(list[i].features[j].values);
+ }
+ }
+ if (list[i].features) free(list[i].features);
+ }
+ m_fs.erase(plugin);
+ m_fsizes.erase(plugin);
+ m_fvsizes.erase(plugin);
+ }
+
+ if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
+ delete m_pluginOutputs[plugin];
+ m_pluginOutputs.erase(plugin);
+ }
+
+ if (m_adapterMap) {
+ m_adapterMap->erase(plugin);
+
+ if (m_adapterMap->empty()) {
+ delete m_adapterMap;
+ m_adapterMap = 0;
+ }
+ }
+
+ delete ((Plugin *)plugin);
+}
+
+void
+PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
+{
+ if (m_pluginOutputs.find(plugin) == m_pluginOutputs.end() ||
+ !m_pluginOutputs[plugin]) {
+ m_pluginOutputs[plugin] = new Plugin::OutputList
+ (plugin->getOutputDescriptors());
+// std::cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << std::endl;
+ }
+}
+
+unsigned int
+PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
+{
+ checkOutputMap(plugin);
+ return m_pluginOutputs[plugin]->size();
+}
+
+VampOutputDescriptor *
+PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
+ unsigned int i)
+{
+ checkOutputMap(plugin);
+ Plugin::OutputDescriptor &od =
+ (*m_pluginOutputs[plugin])[i];
+
+ VampOutputDescriptor *desc = (VampOutputDescriptor *)
+ malloc(sizeof(VampOutputDescriptor));
+
+ desc->identifier = strdup(od.identifier.c_str());
+ desc->name = strdup(od.name.c_str());
+ desc->description = strdup(od.description.c_str());
+ desc->unit = strdup(od.unit.c_str());
+ desc->hasFixedBinCount = od.hasFixedBinCount;
+ desc->binCount = od.binCount;
+
+ if (od.hasFixedBinCount && od.binCount > 0) {
+ desc->binNames = (const char **)
+ malloc(od.binCount * sizeof(const char *));
+
+ for (unsigned int i = 0; i < od.binCount; ++i) {
+ if (i < od.binNames.size()) {
+ desc->binNames[i] = strdup(od.binNames[i].c_str());
+ } else {
+ desc->binNames[i] = 0;
+ }
+ }
+ } else {
+ desc->binNames = 0;
+ }
+
+ desc->hasKnownExtents = od.hasKnownExtents;
+ desc->minValue = od.minValue;
+ desc->maxValue = od.maxValue;
+ desc->isQuantized = od.isQuantized;
+ desc->quantizeStep = od.quantizeStep;
+
+ switch (od.sampleType) {
+ case Plugin::OutputDescriptor::OneSamplePerStep:
+ desc->sampleType = vampOneSamplePerStep; break;
+ case Plugin::OutputDescriptor::FixedSampleRate:
+ desc->sampleType = vampFixedSampleRate; break;
+ case Plugin::OutputDescriptor::VariableSampleRate:
+ desc->sampleType = vampVariableSampleRate; break;
+ }
+
+ desc->sampleRate = od.sampleRate;
+
+ return desc;
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::process(Plugin *plugin,
+ const float *const *inputBuffers,
+ int sec, int nsec)
+{
+// std::cerr << "PluginAdapterBase::Impl::process" << std::endl;
+ RealTime rt(sec, nsec);
+ checkOutputMap(plugin);
+ return convertFeatures(plugin, plugin->process(inputBuffers, rt));
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
+{
+// std::cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << std::endl;
+ checkOutputMap(plugin);
+ return convertFeatures(plugin, plugin->getRemainingFeatures());
+}
+
+VampFeatureList *
+PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
+ const Plugin::FeatureSet &features)
+{
+ int lastN = -1;
+
+ int outputCount = 0;
+ if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
+
+ resizeFS(plugin, outputCount);
+ VampFeatureList *fs = m_fs[plugin];
+
+ for (Plugin::FeatureSet::const_iterator fi = features.begin();
+ fi != features.end(); ++fi) {
+
+ int n = fi->first;
+
+// std::cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << std::endl;
+
+ if (n >= int(outputCount)) {
+ std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl;
+ continue;
+ }
+
+ if (n > lastN + 1) {
+ for (int i = lastN + 1; i < n; ++i) {
+ fs[i].featureCount = 0;
+ }
+ }
+
+ const Plugin::FeatureList &fl = fi->second;
+
+ size_t sz = fl.size();
+ if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
+ fs[n].featureCount = sz;
+
+ for (size_t j = 0; j < sz; ++j) {
+
+// std::cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << std::endl;
+
+ VampFeature *feature = &fs[n].features[j];
+
+ feature->hasTimestamp = fl[j].hasTimestamp;
+ feature->sec = fl[j].timestamp.sec;
+ feature->nsec = fl[j].timestamp.nsec;
+ feature->valueCount = fl[j].values.size();
+
+ if (feature->label) free(feature->label);
+
+ if (fl[j].label.empty()) {
+ feature->label = 0;
+ } else {
+ feature->label = strdup(fl[j].label.c_str());
+ }
+
+ if (feature->valueCount > m_fvsizes[plugin][n][j]) {
+ resizeFV(plugin, n, j, feature->valueCount);
+ }
+
+ for (unsigned int k = 0; k < feature->valueCount; ++k) {
+// std::cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << std::endl;
+ feature->values[k] = fl[j].values[k];
+ }
+ }
+
+ lastN = n;
+ }
+
+ if (lastN == -1) return 0;
+
+ if (int(outputCount) > lastN + 1) {
+ for (int i = lastN + 1; i < int(outputCount); ++i) {
+ fs[i].featureCount = 0;
+ }
+ }
+
+ return fs;
+}
+
+void
+PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
+{
+// std::cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << std::endl;
+
+ int i = m_fsizes[plugin].size();
+ if (i >= n) return;
+
+// std::cerr << "resizing from " << i << std::endl;
+
+ m_fs[plugin] = (VampFeatureList *)realloc
+ (m_fs[plugin], n * sizeof(VampFeatureList));
+
+ while (i < n) {
+ m_fs[plugin][i].featureCount = 0;
+ m_fs[plugin][i].features = 0;
+ m_fsizes[plugin].push_back(0);
+ m_fvsizes[plugin].push_back(std::vector<size_t>());
+ i++;
+ }
+}
+
+void
+PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
+{
+// std::cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
+// << sz << ")" << std::endl;
+
+ size_t i = m_fsizes[plugin][n];
+ if (i >= sz) return;
+
+// std::cerr << "resizing from " << i << std::endl;
+
+ m_fs[plugin][n].features = (VampFeature *)realloc
+ (m_fs[plugin][n].features, sz * sizeof(VampFeature));
+
+ while (m_fsizes[plugin][n] < sz) {
+ m_fs[plugin][n].features[m_fsizes[plugin][n]].valueCount = 0;
+ m_fs[plugin][n].features[m_fsizes[plugin][n]].values = 0;
+ m_fs[plugin][n].features[m_fsizes[plugin][n]].label = 0;
+ m_fvsizes[plugin][n].push_back(0);
+ m_fsizes[plugin][n]++;
+ }
+}
+
+void
+PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
+{
+// std::cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
+// << j << ", " << sz << ")" << std::endl;
+
+ size_t i = m_fvsizes[plugin][n][j];
+ if (i >= sz) return;
+
+// std::cerr << "resizing from " << i << std::endl;
+
+ m_fs[plugin][n].features[j].values = (float *)realloc
+ (m_fs[plugin][n].features[j].values, sz * sizeof(float));
+
+ m_fvsizes[plugin][n][j] = sz;
+}
+
+PluginAdapterBase::Impl::AdapterMap *
+PluginAdapterBase::Impl::m_adapterMap = 0;
+
+}
+
diff --git a/libs/vamp-sdk/vamp-sdk/PluginAdapter.h b/libs/vamp-sdk/vamp-sdk/PluginAdapter.h
new file mode 100644
index 0000000000..bfc97508eb
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/PluginAdapter.h
@@ -0,0 +1,117 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_ADAPTER_H_
+#define _VAMP_PLUGIN_ADAPTER_H_
+
+#include <vamp/vamp.h>
+
+#include "Plugin.h"
+
+#include <map>
+
+namespace Vamp {
+
+/**
+ * \class PluginAdapterBase PluginAdapter.h <vamp-sdk/PluginAdapter.h>
+ *
+ * PluginAdapter and PluginAdapterBase provide a wrapper class that a
+ * plugin library can use to make its C++ Vamp::Plugin objects
+ * available through the Vamp C API.
+ *
+ * Almost all Vamp plugin libraries will want to make use of this. To
+ * do so, all they need to do is declare a PluginAdapter<T> for each
+ * plugin class T in their library. It's very simple, and you need to
+ * know absolutely nothing about how it works in order to use it.
+ * Just cut and paste from an existing plugin's discovery function.
+ * \see vampGetPluginDescriptor
+ */
+
+class PluginAdapterBase
+{
+public:
+ virtual ~PluginAdapterBase();
+
+ /**
+ * Return a VampPluginDescriptor describing the plugin that is
+ * wrapped by this adapter.
+ */
+ const VampPluginDescriptor *getDescriptor();
+
+protected:
+ PluginAdapterBase();
+
+ virtual Plugin *createPlugin(float inputSampleRate) = 0;
+
+ class Impl;
+ Impl *m_impl;
+};
+
+/**
+ * \class PluginAdapter PluginAdapter.h <vamp-sdk/PluginAdapter.h>
+ *
+ * PluginAdapter turns a PluginAdapterBase into a specific wrapper for
+ * a particular plugin implementation.
+ *
+ * See PluginAdapterBase.
+ */
+
+template <typename P>
+class PluginAdapter : public PluginAdapterBase
+{
+public:
+ PluginAdapter() : PluginAdapterBase() { }
+ virtual ~PluginAdapter() { }
+
+protected:
+ Plugin *createPlugin(float inputSampleRate) {
+ P *p = new P(inputSampleRate);
+ Plugin *plugin = dynamic_cast<Plugin *>(p);
+ if (!plugin) {
+ std::cerr << "ERROR: PluginAdapter::createPlugin: "
+ << "Template type is not a plugin!"
+ << std::endl;
+ delete p;
+ return 0;
+ }
+ return plugin;
+ }
+};
+
+}
+
+#endif
+
diff --git a/libs/vamp-sdk/vamp-sdk/PluginBase.h b/libs/vamp-sdk/vamp-sdk/PluginBase.h
new file mode 100644
index 0000000000..38d2b49904
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/PluginBase.h
@@ -0,0 +1,252 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_BASE_H_
+#define _VAMP_PLUGIN_BASE_H_
+
+#include <string>
+#include <vector>
+
+#define VAMP_SDK_VERSION "1.1"
+
+namespace Vamp {
+
+/**
+ * A base class for plugins with optional configurable parameters,
+ * programs, etc. The Vamp::Plugin is derived from this, and
+ * individual Vamp plugins should derive from that.
+ *
+ * This class does not provide the necessary interfaces to instantiate
+ * or run a plugin. It only specifies an interface for retrieving
+ * those controls that the host may wish to show to the user for
+ * editing. It could meaningfully be subclassed by real-time plugins
+ * or other sorts of plugin as well as Vamp plugins.
+ */
+
+class PluginBase
+{
+public:
+ virtual ~PluginBase() { }
+
+ /**
+ * Get the Vamp API compatibility level of the plugin.
+ */
+ virtual unsigned int getVampApiVersion() const { return 1; }
+
+ /**
+ * Get the computer-usable name of the plugin. This should be
+ * reasonably short and contain no whitespace or punctuation
+ * characters. It may only contain the characters [a-zA-Z0-9_].
+ * This is the authoritative way for a program to identify a
+ * plugin within a given library.
+ *
+ * This text may be visible to the user, but it should not be the
+ * main text used to identify a plugin to the user (that will be
+ * the name, below).
+ *
+ * Example: "zero_crossings"
+ */
+ virtual std::string getIdentifier() const = 0;
+
+ /**
+ * Get a human-readable name or title of the plugin. This
+ * should be brief and self-contained, as it may be used to
+ * identify the plugin to the user in isolation (i.e. without also
+ * showing the plugin's "identifier").
+ *
+ * Example: "Zero Crossings"
+ */
+ virtual std::string getName() const = 0;
+
+ /**
+ * Get a human-readable description for the plugin, typically
+ * a line of text that may optionally be displayed in addition
+ * to the plugin's "name". May be empty if the name has said
+ * it all already.
+ *
+ * Example: "Detect and count zero crossing points"
+ */
+ virtual std::string getDescription() const = 0;
+
+ /**
+ * Get the name of the author or vendor of the plugin in
+ * human-readable form. This should be a short identifying text,
+ * as it may be used to label plugins from the same source in a
+ * menu or similar.
+ */
+ virtual std::string getMaker() const = 0;
+
+ /**
+ * Get the copyright statement or licensing summary for the
+ * plugin. This can be an informative text, without the same
+ * presentation constraints as mentioned for getMaker above.
+ */
+ virtual std::string getCopyright() const = 0;
+
+ /**
+ * Get the version number of the plugin.
+ */
+ virtual int getPluginVersion() const = 0;
+
+
+ struct ParameterDescriptor
+ {
+ /**
+ * The name of the parameter, in computer-usable form. Should
+ * be reasonably short, and may only contain the characters
+ * [a-zA-Z0-9_].
+ */
+ std::string identifier;
+
+ /**
+ * The human-readable name of the parameter.
+ */
+ std::string name;
+
+ /**
+ * A human-readable short text describing the parameter. May be
+ * empty if the name has said it all already.
+ */
+ std::string description;
+
+ /**
+ * The unit of the parameter, in human-readable form.
+ */
+ std::string unit;
+
+ /**
+ * The minimum value of the parameter.
+ */
+ float minValue;
+
+ /**
+ * The maximum value of the parameter.
+ */
+ float maxValue;
+
+ /**
+ * The default value of the parameter. The plugin should
+ * ensure that parameters have this value on initialisation
+ * (i.e. the host is not required to explicitly set parameters
+ * if it wants to use their default values).
+ */
+ float defaultValue;
+
+ /**
+ * True if the parameter values are quantized to a particular
+ * resolution.
+ */
+ bool isQuantized;
+
+ /**
+ * Quantization resolution of the parameter values (e.g. 1.0
+ * if they are all integers). Undefined if isQuantized is
+ * false.
+ */
+ float quantizeStep;
+
+ /**
+ * Names for the quantized values. If isQuantized is true,
+ * this may either be empty or contain one string for each of
+ * the quantize steps from minValue up to maxValue inclusive.
+ * Undefined if isQuantized is false.
+ *
+ * If these names are provided, they should be shown to the
+ * user in preference to the values themselves. The user may
+ * never see the actual numeric values unless they are also
+ * encoded in the names.
+ */
+ std::vector<std::string> valueNames;
+ };
+
+ typedef std::vector<ParameterDescriptor> ParameterList;
+
+ /**
+ * Get the controllable parameters of this plugin.
+ */
+ virtual ParameterList getParameterDescriptors() const {
+ return ParameterList();
+ }
+
+ /**
+ * Get the value of a named parameter. The argument is the identifier
+ * field from that parameter's descriptor.
+ */
+ virtual float getParameter(std::string) const { return 0.0; }
+
+ /**
+ * Set a named parameter. The first argument is the identifier field
+ * from that parameter's descriptor.
+ */
+ virtual void setParameter(std::string, float) { }
+
+
+ typedef std::vector<std::string> ProgramList;
+
+ /**
+ * Get the program settings available in this plugin. A program
+ * is a named shorthand for a set of parameter values; changing
+ * the program may cause the plugin to alter the values of its
+ * published parameters (and/or non-public internal processing
+ * parameters). The host should re-read the plugin's parameter
+ * values after setting a new program.
+ *
+ * The programs must have unique names.
+ */
+ virtual ProgramList getPrograms() const { return ProgramList(); }
+
+ /**
+ * Get the current program.
+ */
+ virtual std::string getCurrentProgram() const { return ""; }
+
+ /**
+ * Select a program. (If the given program name is not one of the
+ * available programs, do nothing.)
+ */
+ virtual void selectProgram(std::string) { }
+
+ /**
+ * Get the type of plugin. This is to be implemented by the
+ * immediate subclass, not by actual plugins. Do not attempt to
+ * implement this in plugin code.
+ */
+ virtual std::string getType() const = 0;
+};
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp
new file mode 100644
index 0000000000..12e15393fc
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.cpp
@@ -0,0 +1,418 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include "PluginHostAdapter.h"
+
+namespace Vamp
+{
+
+PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
+ float inputSampleRate) :
+ Plugin(inputSampleRate),
+ m_descriptor(descriptor)
+{
+// std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
+ m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
+ if (!m_handle) {
+// std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
+ }
+}
+
+PluginHostAdapter::~PluginHostAdapter()
+{
+// std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
+ if (m_handle) m_descriptor->cleanup(m_handle);
+}
+
+std::vector<std::string>
+PluginHostAdapter::getPluginPath()
+{
+ std::vector<std::string> path;
+ std::string envPath;
+
+ char *cpath = getenv("VAMP_PATH");
+ if (cpath) envPath = cpath;
+
+#ifdef _WIN32
+#define PATH_SEPARATOR ';'
+#define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
+#else
+#define PATH_SEPARATOR ':'
+#ifdef __APPLE__
+#define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
+#else
+#define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
+#endif
+#endif
+
+ if (envPath == "") {
+ envPath = DEFAULT_VAMP_PATH;
+ char *chome = getenv("HOME");
+ if (chome) {
+ std::string home(chome);
+ std::string::size_type f;
+ while ((f = envPath.find("$HOME")) != std::string::npos &&
+ f < envPath.length()) {
+ envPath.replace(f, 5, home);
+ }
+ }
+#ifdef _WIN32
+ char *cpfiles = getenv("ProgramFiles");
+ if (!cpfiles) cpfiles = "C:\\Program Files";
+ std::string pfiles(cpfiles);
+ std::string::size_type f;
+ while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
+ f < envPath.length()) {
+ envPath.replace(f, 14, pfiles);
+ }
+#endif
+ }
+
+ std::string::size_type index = 0, newindex = 0;
+
+ while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
+ path.push_back(envPath.substr(index, newindex - index));
+ index = newindex + 1;
+ }
+
+ path.push_back(envPath.substr(index));
+
+ return path;
+}
+
+bool
+PluginHostAdapter::initialise(size_t channels,
+ size_t stepSize,
+ size_t blockSize)
+{
+ if (!m_handle) return false;
+ return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
+ true : false;
+}
+
+void
+PluginHostAdapter::reset()
+{
+ if (!m_handle) return;
+ m_descriptor->reset(m_handle);
+}
+
+PluginHostAdapter::InputDomain
+PluginHostAdapter::getInputDomain() const
+{
+ if (m_descriptor->inputDomain == vampFrequencyDomain) {
+ return FrequencyDomain;
+ } else {
+ return TimeDomain;
+ }
+}
+
+unsigned int
+PluginHostAdapter::getVampApiVersion() const
+{
+ return m_descriptor->vampApiVersion;
+}
+
+std::string
+PluginHostAdapter::getIdentifier() const
+{
+ return m_descriptor->identifier;
+}
+
+std::string
+PluginHostAdapter::getName() const
+{
+ return m_descriptor->name;
+}
+
+std::string
+PluginHostAdapter::getDescription() const
+{
+ return m_descriptor->description;
+}
+
+std::string
+PluginHostAdapter::getMaker() const
+{
+ return m_descriptor->maker;
+}
+
+int
+PluginHostAdapter::getPluginVersion() const
+{
+ return m_descriptor->pluginVersion;
+}
+
+std::string
+PluginHostAdapter::getCopyright() const
+{
+ return m_descriptor->copyright;
+}
+
+PluginHostAdapter::ParameterList
+PluginHostAdapter::getParameterDescriptors() const
+{
+ ParameterList list;
+ for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+ const VampParameterDescriptor *spd = m_descriptor->parameters[i];
+ ParameterDescriptor pd;
+ pd.identifier = spd->identifier;
+ pd.name = spd->name;
+ pd.description = spd->description;
+ pd.unit = spd->unit;
+ pd.minValue = spd->minValue;
+ pd.maxValue = spd->maxValue;
+ pd.defaultValue = spd->defaultValue;
+ pd.isQuantized = spd->isQuantized;
+ pd.quantizeStep = spd->quantizeStep;
+ if (pd.isQuantized && spd->valueNames) {
+ for (unsigned int j = 0; spd->valueNames[j]; ++j) {
+ pd.valueNames.push_back(spd->valueNames[j]);
+ }
+ }
+ list.push_back(pd);
+ }
+ return list;
+}
+
+float
+PluginHostAdapter::getParameter(std::string param) const
+{
+ if (!m_handle) return 0.0;
+
+ for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+ if (param == m_descriptor->parameters[i]->identifier) {
+ return m_descriptor->getParameter(m_handle, i);
+ }
+ }
+
+ return 0.0;
+}
+
+void
+PluginHostAdapter::setParameter(std::string param,
+ float value)
+{
+ if (!m_handle) return;
+
+ for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
+ if (param == m_descriptor->parameters[i]->identifier) {
+ m_descriptor->setParameter(m_handle, i, value);
+ return;
+ }
+ }
+}
+
+PluginHostAdapter::ProgramList
+PluginHostAdapter::getPrograms() const
+{
+ ProgramList list;
+
+ for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
+ list.push_back(m_descriptor->programs[i]);
+ }
+
+ return list;
+}
+
+std::string
+PluginHostAdapter::getCurrentProgram() const
+{
+ if (!m_handle) return "";
+
+ int pn = m_descriptor->getCurrentProgram(m_handle);
+ return m_descriptor->programs[pn];
+}
+
+void
+PluginHostAdapter::selectProgram(std::string program)
+{
+ if (!m_handle) return;
+
+ for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
+ if (program == m_descriptor->programs[i]) {
+ m_descriptor->selectProgram(m_handle, i);
+ return;
+ }
+ }
+}
+
+size_t
+PluginHostAdapter::getPreferredStepSize() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getPreferredStepSize(m_handle);
+}
+
+size_t
+PluginHostAdapter::getPreferredBlockSize() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getPreferredBlockSize(m_handle);
+}
+
+size_t
+PluginHostAdapter::getMinChannelCount() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getMinChannelCount(m_handle);
+}
+
+size_t
+PluginHostAdapter::getMaxChannelCount() const
+{
+ if (!m_handle) return 0;
+ return m_descriptor->getMaxChannelCount(m_handle);
+}
+
+PluginHostAdapter::OutputList
+PluginHostAdapter::getOutputDescriptors() const
+{
+ OutputList list;
+ if (!m_handle) {
+// std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
+ return list;
+ }
+
+ unsigned int count = m_descriptor->getOutputCount(m_handle);
+
+ for (unsigned int i = 0; i < count; ++i) {
+ VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
+ OutputDescriptor d;
+ d.identifier = sd->identifier;
+ d.name = sd->name;
+ d.description = sd->description;
+ d.unit = sd->unit;
+ d.hasFixedBinCount = sd->hasFixedBinCount;
+ d.binCount = sd->binCount;
+ if (d.hasFixedBinCount) {
+ for (unsigned int j = 0; j < sd->binCount; ++j) {
+ d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
+ }
+ }
+ d.hasKnownExtents = sd->hasKnownExtents;
+ d.minValue = sd->minValue;
+ d.maxValue = sd->maxValue;
+ d.isQuantized = sd->isQuantized;
+ d.quantizeStep = sd->quantizeStep;
+
+ switch (sd->sampleType) {
+ case vampOneSamplePerStep:
+ d.sampleType = OutputDescriptor::OneSamplePerStep; break;
+ case vampFixedSampleRate:
+ d.sampleType = OutputDescriptor::FixedSampleRate; break;
+ case vampVariableSampleRate:
+ d.sampleType = OutputDescriptor::VariableSampleRate; break;
+ }
+
+ d.sampleRate = sd->sampleRate;
+
+ list.push_back(d);
+
+ m_descriptor->releaseOutputDescriptor(sd);
+ }
+
+ return list;
+}
+
+PluginHostAdapter::FeatureSet
+PluginHostAdapter::process(const float *const *inputBuffers,
+ RealTime timestamp)
+{
+ FeatureSet fs;
+ if (!m_handle) return fs;
+
+ int sec = timestamp.sec;
+ int nsec = timestamp.nsec;
+
+ VampFeatureList *features = m_descriptor->process(m_handle,
+ inputBuffers,
+ sec, nsec);
+
+ convertFeatures(features, fs);
+ m_descriptor->releaseFeatureSet(features);
+ return fs;
+}
+
+PluginHostAdapter::FeatureSet
+PluginHostAdapter::getRemainingFeatures()
+{
+ FeatureSet fs;
+ if (!m_handle) return fs;
+
+ VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
+
+ convertFeatures(features, fs);
+ m_descriptor->releaseFeatureSet(features);
+ return fs;
+}
+
+void
+PluginHostAdapter::convertFeatures(VampFeatureList *features,
+ FeatureSet &fs)
+{
+ if (!features) return;
+
+ unsigned int outputs = m_descriptor->getOutputCount(m_handle);
+
+ for (unsigned int i = 0; i < outputs; ++i) {
+
+ VampFeatureList &list = features[i];
+
+ if (list.featureCount > 0) {
+
+ for (unsigned int j = 0; j < list.featureCount; ++j) {
+
+ Feature feature;
+ feature.hasTimestamp = list.features[j].hasTimestamp;
+ feature.timestamp = RealTime(list.features[j].sec,
+ list.features[j].nsec);
+
+ for (unsigned int k = 0; k < list.features[j].valueCount; ++k) {
+ feature.values.push_back(list.features[j].values[k]);
+ }
+
+ if (list.features[j].label) {
+ feature.label = list.features[j].label;
+ }
+
+ fs[i].push_back(feature);
+ }
+ }
+ }
+}
+
+}
diff --git a/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.h b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.h
new file mode 100644
index 0000000000..80ae6208a4
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/PluginHostAdapter.h
@@ -0,0 +1,117 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_HOST_ADAPTER_H_
+#define _VAMP_PLUGIN_HOST_ADAPTER_H_
+
+#include <vamp/vamp.h>
+#include <vamp-sdk/Plugin.h>
+
+#include <vector>
+
+namespace Vamp {
+
+/**
+ * \class PluginHostAdapter PluginHostAdapter.h <vamp-sdk/PluginHostAdapter.h>
+ *
+ * PluginHostAdapter is a wrapper class that a Vamp host can use to
+ * make the C-language VampPluginDescriptor object appear as a C++
+ * Vamp::Plugin object.
+ *
+ * The Vamp API is defined in vamp/vamp.h as a C API. The C++ objects
+ * used for convenience by plugins and hosts actually communicate
+ * using the C low-level API, but the details of this communication
+ * are handled seamlessly by the Vamp SDK implementation provided the
+ * plugin and host use the proper C++ wrapper objects.
+ *
+ * See also PluginAdapter, the plugin-side wrapper that makes a C++
+ * plugin object available using the C query API.
+ */
+
+class PluginHostAdapter : public Plugin
+{
+public:
+ PluginHostAdapter(const VampPluginDescriptor *descriptor,
+ float inputSampleRate);
+ virtual ~PluginHostAdapter();
+
+ static std::vector<std::string> getPluginPath();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+ void reset();
+
+ InputDomain getInputDomain() const;
+
+ unsigned int getVampApiVersion() const;
+ 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);
+
+ ProgramList getPrograms() const;
+ std::string getCurrentProgram() const;
+ void selectProgram(std::string);
+
+ size_t getPreferredStepSize() const;
+ size_t getPreferredBlockSize() const;
+
+ size_t getMinChannelCount() const;
+ size_t getMaxChannelCount() const;
+
+ OutputList getOutputDescriptors() const;
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+ FeatureSet getRemainingFeatures();
+
+protected:
+ void convertFeatures(VampFeatureList *, FeatureSet &);
+
+ const VampPluginDescriptor *m_descriptor;
+ VampPluginHandle m_handle;
+};
+
+}
+
+#endif
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/RealTime.cpp b/libs/vamp-sdk/vamp-sdk/RealTime.cpp
new file mode 100644
index 0000000000..0b541cc33e
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/RealTime.cpp
@@ -0,0 +1,254 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+/*
+ This is a modified version of a source file from the
+ Rosegarden MIDI and audio sequencer and notation editor.
+ This file copyright 2000-2006 Chris Cannam.
+ Relicensed by the author as detailed above.
+*/
+
+#include <iostream>
+
+#if (__GNUC__ < 3)
+#include <strstream>
+#define stringstream strstream
+#else
+#include <sstream>
+#endif
+
+using std::cerr;
+using std::endl;
+
+#include "RealTime.h"
+
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
+namespace Vamp {
+
+// A RealTime consists of two ints that must be at least 32 bits each.
+// A signed 32-bit int can store values exceeding +/- 2 billion. This
+// means we can safely use our lower int for nanoseconds, as there are
+// 1 billion nanoseconds in a second and we need to handle double that
+// because of the implementations of addition etc that we use.
+//
+// The maximum valid RealTime on a 32-bit system is somewhere around
+// 68 years: 999999999 nanoseconds longer than the classic Unix epoch.
+
+#define ONE_BILLION 1000000000
+
+RealTime::RealTime(int s, int n) :
+ sec(s), nsec(n)
+{
+ if (sec == 0) {
+ while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
+ while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
+ } else if (sec < 0) {
+ while (nsec <= -ONE_BILLION) { nsec += ONE_BILLION; --sec; }
+ while (nsec > 0) { nsec -= ONE_BILLION; ++sec; }
+ } else {
+ while (nsec >= ONE_BILLION) { nsec -= ONE_BILLION; ++sec; }
+ while (nsec < 0) { nsec += ONE_BILLION; --sec; }
+ }
+}
+
+RealTime
+RealTime::fromSeconds(double sec)
+{
+ return RealTime(int(sec), int((sec - int(sec)) * ONE_BILLION + 0.5));
+}
+
+RealTime
+RealTime::fromMilliseconds(int msec)
+{
+ return RealTime(msec / 1000, (msec % 1000) * 1000000);
+}
+
+#ifndef _WIN32
+RealTime
+RealTime::fromTimeval(const struct timeval &tv)
+{
+ return RealTime(tv.tv_sec, tv.tv_usec * 1000);
+}
+#endif
+
+std::ostream &operator<<(std::ostream &out, const RealTime &rt)
+{
+ if (rt < RealTime::zeroTime) {
+ out << "-";
+ } else {
+ out << " ";
+ }
+
+ int s = (rt.sec < 0 ? -rt.sec : rt.sec);
+ int n = (rt.nsec < 0 ? -rt.nsec : rt.nsec);
+
+ out << s << ".";
+
+ int nn(n);
+ if (nn == 0) out << "00000000";
+ else while (nn < (ONE_BILLION / 10)) {
+ out << "0";
+ nn *= 10;
+ }
+
+ out << n << "R";
+ return out;
+}
+
+std::string
+RealTime::toString() const
+{
+ std::stringstream out;
+ out << *this;
+
+#if (__GNUC__ < 3)
+ out << std::ends;
+#endif
+
+ std::string s = out.str();
+
+ // remove trailing R
+ return s.substr(0, s.length() - 1);
+}
+
+std::string
+RealTime::toText(bool fixedDp) const
+{
+ if (*this < RealTime::zeroTime) return "-" + (-*this).toText();
+
+ std::stringstream out;
+
+ if (sec >= 3600) {
+ out << (sec / 3600) << ":";
+ }
+
+ if (sec >= 60) {
+ out << (sec % 3600) / 60 << ":";
+ }
+
+ if (sec >= 10) {
+ out << ((sec % 60) / 10);
+ }
+
+ out << (sec % 10);
+
+ int ms = msec();
+
+ if (ms != 0) {
+ out << ".";
+ out << (ms / 100);
+ ms = ms % 100;
+ if (ms != 0) {
+ out << (ms / 10);
+ ms = ms % 10;
+ } else if (fixedDp) {
+ out << "0";
+ }
+ if (ms != 0) {
+ out << ms;
+ } else if (fixedDp) {
+ out << "0";
+ }
+ } else if (fixedDp) {
+ out << ".000";
+ }
+
+#if (__GNUC__ < 3)
+ out << std::ends;
+#endif
+
+ std::string s = out.str();
+
+ return s;
+}
+
+
+RealTime
+RealTime::operator/(int d) const
+{
+ int secdiv = sec / d;
+ int secrem = sec % d;
+
+ double nsecdiv = (double(nsec) + ONE_BILLION * double(secrem)) / d;
+
+ return RealTime(secdiv, int(nsecdiv + 0.5));
+}
+
+double
+RealTime::operator/(const RealTime &r) const
+{
+ double lTotal = double(sec) * ONE_BILLION + double(nsec);
+ double rTotal = double(r.sec) * ONE_BILLION + double(r.nsec);
+
+ if (rTotal == 0) return 0.0;
+ else return lTotal/rTotal;
+}
+
+long
+RealTime::realTime2Frame(const RealTime &time, unsigned int sampleRate)
+{
+ if (time < zeroTime) return -realTime2Frame(-time, sampleRate);
+
+ // We like integers. The last term is always zero unless the
+ // sample rate is greater than 1MHz, but hell, you never know...
+
+ long frame =
+ time.sec * sampleRate +
+ (time.msec() * sampleRate) / 1000 +
+ ((time.usec() - 1000 * time.msec()) * sampleRate) / 1000000 +
+ ((time.nsec - 1000 * time.usec()) * sampleRate) / 1000000000;
+
+ return frame;
+}
+
+RealTime
+RealTime::frame2RealTime(long frame, unsigned int sampleRate)
+{
+ if (frame < 0) return -frame2RealTime(-frame, sampleRate);
+
+ RealTime rt;
+ rt.sec = frame / long(sampleRate);
+ frame -= rt.sec * long(sampleRate);
+ rt.nsec = (int)(((float(frame) * 1000000) / long(sampleRate)) * 1000);
+ return rt;
+}
+
+const RealTime RealTime::zeroTime(0,0);
+
+}
diff --git a/libs/vamp-sdk/vamp-sdk/RealTime.h b/libs/vamp-sdk/vamp-sdk/RealTime.h
new file mode 100644
index 0000000000..4dd78fd209
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/RealTime.h
@@ -0,0 +1,154 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+/*
+ This is a modified version of a source file from the
+ Rosegarden MIDI and audio sequencer and notation editor.
+ This file copyright 2000-2006 Chris Cannam.
+ Relicensed by the author as detailed above.
+*/
+
+#ifndef _VAMP_REAL_TIME_H_
+#define _VAMP_REAL_TIME_H_
+
+#include <iostream>
+#include <string>
+
+#ifndef _WIN32
+struct timeval;
+#endif
+
+namespace Vamp {
+
+/**
+ * \class RealTime RealTime.h <vamp-sdk/RealTime.h>
+ *
+ * RealTime represents time values to nanosecond precision
+ * with accurate arithmetic and frame-rate conversion functions.
+ */
+
+struct RealTime
+{
+ int sec;
+ int nsec;
+
+ int usec() const { return nsec / 1000; }
+ int msec() const { return nsec / 1000000; }
+
+ RealTime(): sec(0), nsec(0) {}
+ RealTime(int s, int n);
+
+ RealTime(const RealTime &r) :
+ sec(r.sec), nsec(r.nsec) { }
+
+ static RealTime fromSeconds(double sec);
+ static RealTime fromMilliseconds(int msec);
+
+#ifndef _WIN32
+ static RealTime fromTimeval(const struct timeval &);
+#endif
+
+ RealTime &operator=(const RealTime &r) {
+ sec = r.sec; nsec = r.nsec; return *this;
+ }
+
+ RealTime operator+(const RealTime &r) const {
+ return RealTime(sec + r.sec, nsec + r.nsec);
+ }
+ RealTime operator-(const RealTime &r) const {
+ return RealTime(sec - r.sec, nsec - r.nsec);
+ }
+ RealTime operator-() const {
+ return RealTime(-sec, -nsec);
+ }
+
+ bool operator <(const RealTime &r) const {
+ if (sec == r.sec) return nsec < r.nsec;
+ else return sec < r.sec;
+ }
+
+ bool operator >(const RealTime &r) const {
+ if (sec == r.sec) return nsec > r.nsec;
+ else return sec > r.sec;
+ }
+
+ bool operator==(const RealTime &r) const {
+ return (sec == r.sec && nsec == r.nsec);
+ }
+
+ bool operator!=(const RealTime &r) const {
+ return !(r == *this);
+ }
+
+ bool operator>=(const RealTime &r) const {
+ if (sec == r.sec) return nsec >= r.nsec;
+ else return sec >= r.sec;
+ }
+
+ bool operator<=(const RealTime &r) const {
+ if (sec == r.sec) return nsec <= r.nsec;
+ else return sec <= r.sec;
+ }
+
+ RealTime operator/(int d) const;
+
+ // Find the fractional difference between times
+ //
+ double operator/(const RealTime &r) const;
+
+ // Return a human-readable debug-type string to full precision
+ // (probably not a format to show to a user directly)
+ //
+ std::string toString() const;
+
+ // Return a user-readable string to the nearest millisecond
+ // in a form like HH:MM:SS.mmm
+ //
+ std::string toText(bool fixedDp = false) const;
+
+ // Convenience functions for handling sample frames
+ //
+ static long realTime2Frame(const RealTime &r, unsigned int sampleRate);
+ static RealTime frame2RealTime(long frame, unsigned int sampleRate);
+
+ static const RealTime zeroTime;
+};
+
+std::ostream &operator<<(std::ostream &out, const RealTime &rt);
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp
new file mode 100644
index 0000000000..3ce51cedd2
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.cpp
@@ -0,0 +1,228 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include "PluginChannelAdapter.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginChannelAdapter::Impl
+{
+public:
+ Impl(Plugin *plugin);
+ ~Impl();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+ Plugin *m_plugin;
+ size_t m_blockSize;
+ size_t m_inputChannels;
+ size_t m_pluginChannels;
+ float **m_buffer;
+ const float **m_forwardPtrs;
+};
+
+PluginChannelAdapter::PluginChannelAdapter(Plugin *plugin) :
+ PluginWrapper(plugin)
+{
+ m_impl = new Impl(plugin);
+}
+
+PluginChannelAdapter::~PluginChannelAdapter()
+{
+ delete m_impl;
+}
+
+bool
+PluginChannelAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+ return m_impl->initialise(channels, stepSize, blockSize);
+}
+
+PluginChannelAdapter::FeatureSet
+PluginChannelAdapter::process(const float *const *inputBuffers,
+ RealTime timestamp)
+{
+ return m_impl->process(inputBuffers, timestamp);
+}
+
+PluginChannelAdapter::Impl::Impl(Plugin *plugin) :
+ m_plugin(plugin),
+ m_blockSize(0),
+ m_inputChannels(0),
+ m_pluginChannels(0),
+ m_buffer(0),
+ m_forwardPtrs(0)
+{
+}
+
+PluginChannelAdapter::Impl::~Impl()
+{
+ // the adapter will delete the plugin
+
+ if (m_buffer) {
+ if (m_inputChannels > m_pluginChannels) {
+ delete[] m_buffer[0];
+ } else {
+ for (size_t i = 0; i < m_pluginChannels - m_inputChannels; ++i) {
+ delete[] m_buffer[i];
+ }
+ }
+ delete[] m_buffer;
+ m_buffer = 0;
+ }
+
+ if (m_forwardPtrs) {
+ delete[] m_forwardPtrs;
+ m_forwardPtrs = 0;
+ }
+}
+
+bool
+PluginChannelAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+ m_blockSize = blockSize;
+
+ size_t minch = m_plugin->getMinChannelCount();
+ size_t maxch = m_plugin->getMaxChannelCount();
+
+ m_inputChannels = channels;
+
+ if (m_inputChannels < minch) {
+
+ m_forwardPtrs = new const float *[minch];
+
+ if (m_inputChannels > 1) {
+ // We need a set of zero-valued buffers to add to the
+ // forwarded pointers
+ m_buffer = new float*[minch - channels];
+ for (size_t i = 0; i < minch; ++i) {
+ m_buffer[i] = new float[blockSize];
+ for (size_t j = 0; j < blockSize; ++j) {
+ m_buffer[i][j] = 0.f;
+ }
+ }
+ }
+
+ m_pluginChannels = minch;
+
+ std::cerr << "PluginChannelAdapter::initialise: expanding " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
+
+ } else if (m_inputChannels > maxch) {
+
+ // We only need m_buffer if we are mixing down to a single
+ // channel -- otherwise we can just forward the same float* as
+ // passed in to process(), expecting the excess to be ignored
+
+ if (maxch == 1) {
+ m_buffer = new float *[1];
+ m_buffer[0] = new float[blockSize];
+
+ std::cerr << "PluginChannelAdapter::initialise: mixing " << m_inputChannels << " to mono for plugin" << std::endl;
+
+ } else {
+
+ std::cerr << "PluginChannelAdapter::initialise: reducing " << m_inputChannels << " to " << m_pluginChannels << " for plugin" << std::endl;
+ }
+
+ m_pluginChannels = maxch;
+
+ } else {
+
+ std::cerr << "PluginChannelAdapter::initialise: accepting given number of channels (" << m_inputChannels << ")" << std::endl;
+ m_pluginChannels = m_inputChannels;
+ }
+
+ return m_plugin->initialise(m_pluginChannels, stepSize, blockSize);
+}
+
+PluginChannelAdapter::FeatureSet
+PluginChannelAdapter::Impl::process(const float *const *inputBuffers,
+ RealTime timestamp)
+{
+// std::cerr << "PluginChannelAdapter::process: " << m_inputChannels << " -> " << m_pluginChannels << " channels" << std::endl;
+
+ if (m_inputChannels < m_pluginChannels) {
+
+ if (m_inputChannels == 1) {
+ for (size_t i = 0; i < m_pluginChannels; ++i) {
+ m_forwardPtrs[i] = inputBuffers[0];
+ }
+ } else {
+ for (size_t i = 0; i < m_inputChannels; ++i) {
+ m_forwardPtrs[i] = inputBuffers[i];
+ }
+ for (size_t i = m_inputChannels; i < m_pluginChannels; ++i) {
+ m_forwardPtrs[i] = m_buffer[i - m_inputChannels];
+ }
+ }
+
+ return m_plugin->process(m_forwardPtrs, timestamp);
+
+ } else if (m_inputChannels > m_pluginChannels) {
+
+ if (m_pluginChannels == 1) {
+ for (size_t j = 0; j < m_blockSize; ++j) {
+ m_buffer[0][j] = inputBuffers[0][j];
+ }
+ for (size_t i = 1; i < m_inputChannels; ++i) {
+ for (size_t j = 0; j < m_blockSize; ++j) {
+ m_buffer[0][j] += inputBuffers[i][j];
+ }
+ }
+ for (size_t j = 0; j < m_blockSize; ++j) {
+ m_buffer[0][j] /= m_inputChannels;
+ }
+ return m_plugin->process(m_buffer, timestamp);
+ } else {
+ return m_plugin->process(inputBuffers, timestamp);
+ }
+
+ } else {
+
+ return m_plugin->process(inputBuffers, timestamp);
+ }
+}
+
+}
+
+}
+
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h
new file mode 100644
index 0000000000..a2b4d89aee
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginChannelAdapter.h
@@ -0,0 +1,128 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
+#define _VAMP_PLUGIN_CHANNEL_ADAPTER_H_
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginChannelAdapter PluginChannelAdapter.h <vamp-sdk/hostext/PluginChannelAdapter.h>
+ *
+ * PluginChannelAdapter is a Vamp plugin adapter that implements a
+ * policy for management of plugins that expect a different number of
+ * input channels from the number actually available in the source
+ * audio data.
+ *
+ * A host using PluginChannelAdapter may ignore the getMinChannelCount
+ * and getMaxChannelCount reported by the plugin, and still expect the
+ * plugin to run.
+ *
+ * PluginChannelAdapter implements the following policy:
+ *
+ * - If the plugin supports the provided number of channels directly,
+ * PluginChannelAdapter will just run the plugin as normal.
+ *
+ * - If the plugin only supports exactly one channel but more than
+ * one channel is provided, PluginChannelAdapter will use the mean of
+ * the channels. This ensures that the resulting values remain
+ * within the same magnitude range as expected for mono data.
+ *
+ * - If the plugin requires more than one channel but exactly one is
+ * provided, the provided channel will be duplicated across all the
+ * plugin input channels.
+ *
+ * If none of the above apply:
+ *
+ * - If the plugin requires more channels than are provided, the
+ * minimum acceptable number of channels will be produced by adding
+ * empty (zero valued) channels to those provided.
+ *
+ * - If the plugin requires fewer channels than are provided, the
+ * maximum acceptable number of channels will be produced by
+ * discarding the excess channels.
+ *
+ * Hosts requiring a different channel policy from the above will need
+ * to implement it themselves, instead of using PluginChannelAdapter.
+ *
+ * Note that PluginChannelAdapter does not override the minimum and
+ * maximum channel counts returned by the wrapped plugin. The host
+ * will need to be aware that it is using a PluginChannelAdapter, and
+ * be prepared to ignore these counts as necessary. (This contrasts
+ * with the approach used in PluginInputDomainAdapter, which aims to
+ * make the host completely unaware of which underlying input domain
+ * is in fact in use.)
+ *
+ * (The rationale for this is that a host may wish to use the
+ * PluginChannelAdapter but still discriminate in some way on the
+ * basis of the number of channels actually supported. For example, a
+ * simple stereo audio host may prefer to reject plugins that require
+ * more than two channels on the grounds that doesn't actually
+ * understand what they are for, rather than allow the channel adapter
+ * to make a potentially meaningless channel conversion for them.)
+ *
+ * In every respect other than its management of channels, the
+ * PluginChannelAdapter behaves identically to the plugin that it
+ * wraps. The wrapped plugin will be deleted when the wrapper is
+ * deleted.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginChannelAdapter : public PluginWrapper
+{
+public:
+ PluginChannelAdapter(Plugin *plugin); // I take ownership of plugin
+ virtual ~PluginChannelAdapter();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+ class Impl;
+ Impl *m_impl;
+};
+
+}
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp
new file mode 100644
index 0000000000..3fc0d74720
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.cpp
@@ -0,0 +1,458 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include "PluginInputDomainAdapter.h"
+
+#include <cmath>
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginInputDomainAdapter::Impl
+{
+public:
+ Impl(Plugin *plugin, float inputSampleRate);
+ ~Impl();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+ size_t getPreferredStepSize() const;
+ size_t getPreferredBlockSize() const;
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+ Plugin *m_plugin;
+ float m_inputSampleRate;
+ size_t m_channels;
+ size_t m_blockSize;
+ float **m_freqbuf;
+ double *m_ri;
+ double *m_ro;
+ double *m_io;
+
+ void fft(unsigned int n, bool inverse,
+ double *ri, double *ii, double *ro, double *io);
+
+ size_t makeBlockSizeAcceptable(size_t) const;
+};
+
+PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
+ PluginWrapper(plugin)
+{
+ m_impl = new Impl(plugin, m_inputSampleRate);
+}
+
+PluginInputDomainAdapter::~PluginInputDomainAdapter()
+{
+ delete m_impl;
+}
+
+bool
+PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+ return m_impl->initialise(channels, stepSize, blockSize);
+}
+
+Plugin::InputDomain
+PluginInputDomainAdapter::getInputDomain() const
+{
+ return TimeDomain;
+}
+
+size_t
+PluginInputDomainAdapter::getPreferredStepSize() const
+{
+ return m_impl->getPreferredStepSize();
+}
+
+size_t
+PluginInputDomainAdapter::getPreferredBlockSize() const
+{
+ return m_impl->getPreferredBlockSize();
+}
+
+Plugin::FeatureSet
+PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
+{
+ return m_impl->process(inputBuffers, timestamp);
+}
+
+ PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
+ m_plugin(plugin),
+ m_inputSampleRate(inputSampleRate),
+ m_channels(0),
+ m_blockSize(0),
+ m_freqbuf(0)
+{
+}
+
+PluginInputDomainAdapter::Impl::~Impl()
+{
+ // the adapter will delete the plugin
+
+ if (m_channels > 0) {
+ for (size_t c = 0; c < m_channels; ++c) {
+ delete[] m_freqbuf[c];
+ }
+ delete[] m_freqbuf;
+ delete[] m_ri;
+ delete[] m_ro;
+ delete[] m_io;
+ }
+}
+
+bool
+PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+ if (m_plugin->getInputDomain() == TimeDomain) {
+
+ m_blockSize = blockSize;
+ m_channels = channels;
+
+ return m_plugin->initialise(channels, stepSize, blockSize);
+ }
+
+ if (blockSize < 2) {
+ std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not supported" << std::endl;
+ return false;
+ }
+
+ if (blockSize & (blockSize-1)) {
+ std::cerr << "ERROR: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported" << std::endl;
+ return false;
+ }
+
+ if (m_channels > 0) {
+ for (size_t c = 0; c < m_channels; ++c) {
+ delete[] m_freqbuf[c];
+ }
+ delete[] m_freqbuf;
+ delete[] m_ri;
+ delete[] m_ro;
+ delete[] m_io;
+ }
+
+ m_blockSize = blockSize;
+ m_channels = channels;
+
+ m_freqbuf = new float *[m_channels];
+ for (size_t c = 0; c < m_channels; ++c) {
+ m_freqbuf[c] = new float[m_blockSize + 2];
+ }
+ m_ri = new double[m_blockSize];
+ m_ro = new double[m_blockSize];
+ m_io = new double[m_blockSize];
+
+ return m_plugin->initialise(channels, stepSize, blockSize);
+}
+
+size_t
+PluginInputDomainAdapter::Impl::getPreferredStepSize() const
+{
+ size_t step = m_plugin->getPreferredStepSize();
+
+ if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
+ step = getPreferredBlockSize() / 2;
+ }
+
+ return step;
+}
+
+size_t
+PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
+{
+ size_t block = m_plugin->getPreferredBlockSize();
+
+ if (m_plugin->getInputDomain() == FrequencyDomain) {
+ if (block == 0) {
+ block = 1024;
+ } else {
+ block = makeBlockSizeAcceptable(block);
+ }
+ }
+
+ return block;
+}
+
+size_t
+PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
+{
+ if (blockSize < 2) {
+
+ std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: blocksize < 2 not" << std::endl
+ << "supported, increasing from " << blockSize << " to 2" << std::endl;
+ blockSize = 2;
+
+ } else if (blockSize & (blockSize-1)) {
+
+ // not a power of two, can't handle that with our current fft
+ // implementation
+
+ size_t nearest = blockSize;
+ size_t power = 0;
+ while (nearest > 1) {
+ nearest >>= 1;
+ ++power;
+ }
+ nearest = 1;
+ while (power) {
+ nearest <<= 1;
+ --power;
+ }
+
+ if (blockSize - nearest > (nearest*2) - blockSize) {
+ nearest = nearest*2;
+ }
+
+ std::cerr << "WARNING: Vamp::HostExt::PluginInputDomainAdapter::Impl::initialise: non-power-of-two\nblocksize " << blockSize << " not supported, using blocksize " << nearest << " instead" << std::endl;
+ blockSize = nearest;
+ }
+
+ return blockSize;
+}
+
+// for some visual studii apparently
+#ifndef M_PI
+#define M_PI 3.14159265358979232846
+#endif
+
+Plugin::FeatureSet
+PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
+ RealTime timestamp)
+{
+ if (m_plugin->getInputDomain() == TimeDomain) {
+ return m_plugin->process(inputBuffers, timestamp);
+ }
+
+ // The timestamp supplied should be (according to the Vamp::Plugin
+ // spec) the time of the start of the time-domain input block.
+ // However, we want to pass to the plugin an FFT output calculated
+ // from the block of samples _centred_ on that timestamp.
+ //
+ // We have two options:
+ //
+ // 1. Buffer the input, calculating the fft of the values at the
+ // passed-in block minus blockSize/2 rather than starting at the
+ // passed-in block. So each time we call process on the plugin,
+ // we are passing in the same timestamp as was passed to our own
+ // process plugin, but not (the frequency domain representation
+ // of) the same set of samples. Advantages: avoids confusion in
+ // the host by ensuring the returned values have timestamps
+ // comparable with that passed in to this function (in fact this
+ // is pretty much essential for one-value-per-block outputs);
+ // consistent with hosts such as SV that deal with the
+ // frequency-domain transform themselves. Disadvantages: means
+ // making the not necessarily correct assumption that the samples
+ // preceding the first official block are all zero (or some other
+ // known value).
+ //
+ // 2. Increase the passed-in timestamps by half the blocksize. So
+ // when we call process, we are passing in the frequency domain
+ // representation of the same set of samples as passed to us, but
+ // with a different timestamp. Advantages: simplicity; avoids
+ // iffy assumption mentioned above. Disadvantages: inconsistency
+ // with SV in cases where stepSize != blockSize/2; potential
+ // confusion arising from returned timestamps being calculated
+ // from the adjusted input timestamps rather than the original
+ // ones (and inaccuracy where the returned timestamp is implied,
+ // as in one-value-per-block).
+ //
+ // Neither way is ideal, but I don't think either is strictly
+ // incorrect either. I think this is just a case where the same
+ // plugin can legitimately produce differing results from the same
+ // input data, depending on how that data is packaged.
+ //
+ // We'll go for option 2, adjusting the timestamps. Note in
+ // particular that this means some results can differ from those
+ // produced by SV.
+
+// std::cerr << "PluginInputDomainAdapter: sampleRate " << m_inputSampleRate << ", blocksize " << m_blockSize << ", adjusting time from " << timestamp;
+
+ timestamp = timestamp + RealTime::frame2RealTime
+ (m_blockSize/2, int(m_inputSampleRate + 0.5));
+
+// std::cerr << " to " << timestamp << std::endl;
+
+ for (size_t c = 0; c < m_channels; ++c) {
+
+ for (size_t i = 0; i < m_blockSize; ++i) {
+ // Hanning window
+ m_ri[i] = double(inputBuffers[c][i])
+ * (0.50 - 0.50 * cos((2 * M_PI * i)
+ / m_blockSize));
+ }
+
+ for (size_t i = 0; i < m_blockSize/2; ++i) {
+ // FFT shift
+ double value = m_ri[i];
+ m_ri[i] = m_ri[i + m_blockSize/2];
+ m_ri[i + m_blockSize/2] = value;
+ }
+
+ fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
+
+ for (size_t i = 0; i <= m_blockSize/2; ++i) {
+ m_freqbuf[c][i * 2] = m_ro[i];
+ m_freqbuf[c][i * 2 + 1] = m_io[i];
+ }
+ }
+
+ return m_plugin->process(m_freqbuf, timestamp);
+}
+
+void
+PluginInputDomainAdapter::Impl::fft(unsigned int n, bool inverse,
+ double *ri, double *ii, double *ro, double *io)
+{
+ if (!ri || !ro || !io) return;
+
+ unsigned int bits;
+ unsigned int i, j, k, m;
+ unsigned int blockSize, blockEnd;
+
+ double tr, ti;
+
+ if (n < 2) return;
+ if (n & (n-1)) return;
+
+ double angle = 2.0 * M_PI;
+ if (inverse) angle = -angle;
+
+ for (i = 0; ; ++i) {
+ if (n & (1 << i)) {
+ bits = i;
+ break;
+ }
+ }
+
+ static unsigned int tableSize = 0;
+ static int *table = 0;
+
+ if (tableSize != n) {
+
+ delete[] table;
+
+ table = new int[n];
+
+ for (i = 0; i < n; ++i) {
+
+ m = i;
+
+ for (j = k = 0; j < bits; ++j) {
+ k = (k << 1) | (m & 1);
+ m >>= 1;
+ }
+
+ table[i] = k;
+ }
+
+ tableSize = n;
+ }
+
+ if (ii) {
+ for (i = 0; i < n; ++i) {
+ ro[table[i]] = ri[i];
+ io[table[i]] = ii[i];
+ }
+ } else {
+ for (i = 0; i < n; ++i) {
+ ro[table[i]] = ri[i];
+ io[table[i]] = 0.0;
+ }
+ }
+
+ blockEnd = 1;
+
+ for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
+
+ double delta = angle / (double)blockSize;
+ double sm2 = -sin(-2 * delta);
+ double sm1 = -sin(-delta);
+ double cm2 = cos(-2 * delta);
+ double cm1 = cos(-delta);
+ double w = 2 * cm1;
+ double ar[3], ai[3];
+
+ for (i = 0; i < n; i += blockSize) {
+
+ ar[2] = cm2;
+ ar[1] = cm1;
+
+ ai[2] = sm2;
+ ai[1] = sm1;
+
+ for (j = i, m = 0; m < blockEnd; j++, m++) {
+
+ ar[0] = w * ar[1] - ar[2];
+ ar[2] = ar[1];
+ ar[1] = ar[0];
+
+ ai[0] = w * ai[1] - ai[2];
+ ai[2] = ai[1];
+ ai[1] = ai[0];
+
+ k = j + blockEnd;
+ tr = ar[0] * ro[k] - ai[0] * io[k];
+ ti = ar[0] * io[k] + ai[0] * ro[k];
+
+ ro[k] = ro[j] - tr;
+ io[k] = io[j] - ti;
+
+ ro[j] += tr;
+ io[j] += ti;
+ }
+ }
+
+ blockEnd = blockSize;
+ }
+
+ if (inverse) {
+
+ double denom = (double)n;
+
+ for (i = 0; i < n; i++) {
+ ro[i] /= denom;
+ io[i] /= denom;
+ }
+ }
+}
+
+}
+
+}
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h
new file mode 100644
index 0000000000..73da053149
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginInputDomainAdapter.h
@@ -0,0 +1,103 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
+#define _VAMP_PLUGIN_INPUT_DOMAIN_ADAPTER_H_
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginInputDomainAdapter PluginInputDomainAdapter.h <vamp-sdk/hostext/PluginInputDomainAdapter.h>
+ *
+ * PluginInputDomainAdapter is a Vamp plugin adapter that converts
+ * time-domain input into frequency-domain input for plugins that need
+ * it. This permits a host to use time- and frequency-domain plugins
+ * interchangeably without needing to handle the conversion itself.
+ *
+ * This adapter uses a basic Hanning windowed FFT that supports
+ * power-of-two block sizes only. If a frequency domain plugin
+ * requests a non-power-of-two blocksize, the adapter will adjust it
+ * to a nearby power of two instead. Thus, getPreferredBlockSize()
+ * will always return a power of two if the wrapped plugin is a
+ * frequency domain one. If the plugin doesn't accept the adjusted
+ * power of two block size, initialise() will fail.
+ *
+ * The adapter provides no way for the host to discover whether the
+ * underlying plugin is actually a time or frequency domain plugin
+ * (except that if the preferred block size is not a power of two, it
+ * must be a time domain plugin).
+ *
+ * The FFT implementation is simple and self-contained, but unlikely
+ * to be the fastest available: a host can usually do better if it
+ * cares enough.
+ *
+ * In every respect other than its input domain handling, the
+ * PluginInputDomainAdapter behaves identically to the plugin that it
+ * wraps. The wrapped plugin will be deleted when the wrapper is
+ * deleted.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginInputDomainAdapter : public PluginWrapper
+{
+public:
+ PluginInputDomainAdapter(Plugin *plugin); // I take ownership of plugin
+ virtual ~PluginInputDomainAdapter();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+
+ InputDomain getInputDomain() const;
+
+ size_t getPreferredStepSize() const;
+ size_t getPreferredBlockSize() const;
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+protected:
+ class Impl;
+ Impl *m_impl;
+};
+
+}
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp
new file mode 100644
index 0000000000..cb71fc4750
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.cpp
@@ -0,0 +1,601 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include "vamp-sdk/PluginHostAdapter.h"
+#include "PluginLoader.h"
+#include "PluginInputDomainAdapter.h"
+#include "PluginChannelAdapter.h"
+
+#include <fstream>
+#include <cctype> // tolower
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <tchar.h>
+#define PLUGIN_SUFFIX "dll"
+
+#else /* ! _WIN32 */
+
+#include <dirent.h>
+#include <dlfcn.h>
+
+#ifdef __APPLE__
+#define PLUGIN_SUFFIX "dylib"
+#else /* ! __APPLE__ */
+#define PLUGIN_SUFFIX "so"
+#endif /* ! __APPLE__ */
+
+#endif /* ! _WIN32 */
+
+using namespace std;
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginLoader::Impl
+{
+public:
+ Impl();
+ virtual ~Impl();
+
+ PluginKeyList listPlugins();
+
+ Plugin *loadPlugin(PluginKey key,
+ float inputSampleRate,
+ int adapterFlags);
+
+ PluginKey composePluginKey(string libraryName, string identifier);
+
+ PluginCategoryHierarchy getPluginCategory(PluginKey key);
+
+ string getLibraryPathForPlugin(PluginKey key);
+
+protected:
+ class PluginDeletionNotifyAdapter : public PluginWrapper {
+ public:
+ PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader);
+ virtual ~PluginDeletionNotifyAdapter();
+ protected:
+ Impl *m_loader;
+ };
+
+ virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter);
+
+ map<PluginKey, string> m_pluginLibraryNameMap;
+ bool m_allPluginsEnumerated;
+ void enumeratePlugins(PluginKey forPlugin = "");
+
+ map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
+ void generateTaxonomy();
+
+ map<Plugin *, void *> m_pluginLibraryHandleMap;
+
+ bool decomposePluginKey(PluginKey key,
+ string &libraryName, string &identifier);
+
+ void *loadLibrary(string path);
+ void unloadLibrary(void *handle);
+ void *lookupInLibrary(void *handle, const char *symbol);
+
+ string splicePath(string a, string b);
+ vector<string> listFiles(string dir, string ext);
+};
+
+PluginLoader *
+PluginLoader::m_instance = 0;
+
+PluginLoader::PluginLoader()
+{
+ m_impl = new Impl();
+}
+
+PluginLoader::~PluginLoader()
+{
+ delete m_impl;
+}
+
+PluginLoader *
+PluginLoader::getInstance()
+{
+ if (!m_instance) m_instance = new PluginLoader();
+ return m_instance;
+}
+
+vector<PluginLoader::PluginKey>
+PluginLoader::listPlugins()
+{
+ return m_impl->listPlugins();
+}
+
+Plugin *
+PluginLoader::loadPlugin(PluginKey key,
+ float inputSampleRate,
+ int adapterFlags)
+{
+ return m_impl->loadPlugin(key, inputSampleRate, adapterFlags);
+}
+
+PluginLoader::PluginKey
+PluginLoader::composePluginKey(string libraryName, string identifier)
+{
+ return m_impl->composePluginKey(libraryName, identifier);
+}
+
+PluginLoader::PluginCategoryHierarchy
+PluginLoader::getPluginCategory(PluginKey key)
+{
+ return m_impl->getPluginCategory(key);
+}
+
+string
+PluginLoader::getLibraryPathForPlugin(PluginKey key)
+{
+ return m_impl->getLibraryPathForPlugin(key);
+}
+
+PluginLoader::Impl::Impl() :
+ m_allPluginsEnumerated(false)
+{
+}
+
+PluginLoader::Impl::~Impl()
+{
+}
+
+vector<PluginLoader::PluginKey>
+PluginLoader::Impl::listPlugins()
+{
+ if (!m_allPluginsEnumerated) enumeratePlugins();
+
+ vector<PluginKey> plugins;
+ for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
+ mi != m_pluginLibraryNameMap.end(); ++mi) {
+ plugins.push_back(mi->first);
+ }
+
+ return plugins;
+}
+
+void
+PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
+{
+ vector<string> path = PluginHostAdapter::getPluginPath();
+
+ string libraryName, identifier;
+ if (forPlugin != "") {
+ if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
+ std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
+ << forPlugin << "\" in enumerate" << std::endl;
+ return;
+ }
+ }
+
+ for (size_t i = 0; i < path.size(); ++i) {
+
+ vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
+
+ for (vector<string>::iterator fi = files.begin();
+ fi != files.end(); ++fi) {
+
+ if (libraryName != "") {
+ // libraryName is lowercased and lacking an extension,
+ // as it came from the plugin key
+ string temp = *fi;
+ for (size_t i = 0; i < temp.length(); ++i) {
+ temp[i] = tolower(temp[i]);
+ }
+ string::size_type pi = temp.find('.');
+ if (pi == string::npos) {
+ if (libraryName != temp) continue;
+ } else {
+ if (libraryName != temp.substr(0, pi)) continue;
+ }
+ }
+
+ string fullPath = path[i];
+ fullPath = splicePath(fullPath, *fi);
+ void *handle = loadLibrary(fullPath);
+ if (!handle) continue;
+
+ VampGetPluginDescriptorFunction fn =
+ (VampGetPluginDescriptorFunction)lookupInLibrary
+ (handle, "vampGetPluginDescriptor");
+
+ if (!fn) {
+ unloadLibrary(handle);
+ continue;
+ }
+
+ int index = 0;
+ const VampPluginDescriptor *descriptor = 0;
+
+ while ((descriptor = fn(VAMP_API_VERSION, index))) {
+ ++index;
+ if (identifier != "") {
+ if (descriptor->identifier != identifier) continue;
+ }
+ PluginKey key = composePluginKey(*fi, descriptor->identifier);
+// std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
+ if (m_pluginLibraryNameMap.find(key) ==
+ m_pluginLibraryNameMap.end()) {
+ m_pluginLibraryNameMap[key] = fullPath;
+ }
+ }
+
+ unloadLibrary(handle);
+ }
+ }
+
+ if (forPlugin == "") m_allPluginsEnumerated = true;
+}
+
+PluginLoader::PluginKey
+PluginLoader::Impl::composePluginKey(string libraryName, string identifier)
+{
+ string basename = libraryName;
+
+ string::size_type li = basename.rfind('/');
+ if (li != string::npos) basename = basename.substr(li + 1);
+
+ li = basename.find('.');
+ if (li != string::npos) basename = basename.substr(0, li);
+
+ for (size_t i = 0; i < basename.length(); ++i) {
+ basename[i] = tolower(basename[i]);
+ }
+
+ return basename + ":" + identifier;
+}
+
+bool
+PluginLoader::Impl::decomposePluginKey(PluginKey key,
+ string &libraryName,
+ string &identifier)
+{
+ string::size_type ki = key.find(':');
+ if (ki == string::npos) {
+ return false;
+ }
+
+ libraryName = key.substr(0, ki);
+ identifier = key.substr(ki + 1);
+ return true;
+}
+
+PluginLoader::PluginCategoryHierarchy
+PluginLoader::Impl::getPluginCategory(PluginKey plugin)
+{
+ if (m_taxonomy.empty()) generateTaxonomy();
+ if (m_taxonomy.find(plugin) == m_taxonomy.end()) {
+ return PluginCategoryHierarchy();
+ }
+ return m_taxonomy[plugin];
+}
+
+string
+PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
+{
+ if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
+ if (m_allPluginsEnumerated) return "";
+ enumeratePlugins(plugin);
+ }
+ if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
+ return "";
+ }
+ return m_pluginLibraryNameMap[plugin];
+}
+
+Plugin *
+PluginLoader::Impl::loadPlugin(PluginKey key,
+ float inputSampleRate, int adapterFlags)
+{
+ string libname, identifier;
+ if (!decomposePluginKey(key, libname, identifier)) {
+ std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \""
+ << key << "\" in loadPlugin" << std::endl;
+ return 0;
+ }
+
+ string fullPath = getLibraryPathForPlugin(key);
+ if (fullPath == "") return 0;
+
+ void *handle = loadLibrary(fullPath);
+ if (!handle) return 0;
+
+ VampGetPluginDescriptorFunction fn =
+ (VampGetPluginDescriptorFunction)lookupInLibrary
+ (handle, "vampGetPluginDescriptor");
+
+ if (!fn) {
+ unloadLibrary(handle);
+ return 0;
+ }
+
+ int index = 0;
+ const VampPluginDescriptor *descriptor = 0;
+
+ while ((descriptor = fn(VAMP_API_VERSION, index))) {
+
+ if (string(descriptor->identifier) == identifier) {
+
+ Vamp::PluginHostAdapter *plugin =
+ new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
+
+ Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this);
+
+ m_pluginLibraryHandleMap[adapter] = handle;
+
+ if (adapterFlags & ADAPT_INPUT_DOMAIN) {
+ if (adapter->getInputDomain() == Plugin::FrequencyDomain) {
+ adapter = new PluginInputDomainAdapter(adapter);
+ }
+ }
+
+ if (adapterFlags & ADAPT_CHANNEL_COUNT) {
+ adapter = new PluginChannelAdapter(adapter);
+ }
+
+ return adapter;
+ }
+
+ ++index;
+ }
+
+ cerr << "Vamp::HostExt::PluginLoader: Plugin \""
+ << identifier << "\" not found in library \""
+ << fullPath << "\"" << endl;
+
+ return 0;
+}
+
+void
+PluginLoader::Impl::generateTaxonomy()
+{
+// cerr << "PluginLoader::Impl::generateTaxonomy" << endl;
+
+ vector<string> path = PluginHostAdapter::getPluginPath();
+ string libfragment = "/lib/";
+ vector<string> catpath;
+
+ string suffix = "cat";
+
+ for (vector<string>::iterator i = path.begin();
+ i != path.end(); ++i) {
+
+ // It doesn't matter that we're using literal forward-slash in
+ // this bit, as it's only relevant if the path contains
+ // "/lib/", which is only meaningful and only plausible on
+ // systems with forward-slash delimiters
+
+ string dir = *i;
+ string::size_type li = dir.find(libfragment);
+
+ if (li != string::npos) {
+ catpath.push_back
+ (dir.substr(0, li)
+ + "/share/"
+ + dir.substr(li + libfragment.length()));
+ }
+
+ catpath.push_back(dir);
+ }
+
+ char buffer[1024];
+
+ for (vector<string>::iterator i = catpath.begin();
+ i != catpath.end(); ++i) {
+
+ vector<string> files = listFiles(*i, suffix);
+
+ for (vector<string>::iterator fi = files.begin();
+ fi != files.end(); ++fi) {
+
+ string filepath = splicePath(*i, *fi);
+ ifstream is(filepath.c_str(), ifstream::in | ifstream::binary);
+
+ if (is.fail()) {
+// cerr << "failed to open: " << filepath << endl;
+ continue;
+ }
+
+// cerr << "opened: " << filepath << endl;
+
+ while (!!is.getline(buffer, 1024)) {
+
+ string line(buffer);
+
+// cerr << "line = " << line << endl;
+
+ string::size_type di = line.find("::");
+ if (di == string::npos) continue;
+
+ string id = line.substr(0, di);
+ string encodedCat = line.substr(di + 2);
+
+ if (id.substr(0, 5) != "vamp:") continue;
+ id = id.substr(5);
+
+ while (encodedCat.length() >= 1 &&
+ encodedCat[encodedCat.length()-1] == '\r') {
+ encodedCat = encodedCat.substr(0, encodedCat.length()-1);
+ }
+
+// cerr << "id = " << id << ", cat = " << encodedCat << endl;
+
+ PluginCategoryHierarchy category;
+ string::size_type ai;
+ while ((ai = encodedCat.find(" > ")) != string::npos) {
+ category.push_back(encodedCat.substr(0, ai));
+ encodedCat = encodedCat.substr(ai + 3);
+ }
+ if (encodedCat != "") category.push_back(encodedCat);
+
+ m_taxonomy[id] = category;
+ }
+ }
+ }
+}
+
+void *
+PluginLoader::Impl::loadLibrary(string path)
+{
+ void *handle = 0;
+#ifdef _WIN32
+ handle = LoadLibrary(path.c_str());
+ if (!handle) {
+ cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
+ << path << "\"" << endl;
+ }
+#else
+ handle = dlopen(path.c_str(), RTLD_LAZY);
+ if (!handle) {
+ cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
+ << path << "\": " << dlerror() << endl;
+ }
+#endif
+ return handle;
+}
+
+void
+PluginLoader::Impl::unloadLibrary(void *handle)
+{
+#ifdef _WIN32
+ FreeLibrary((HINSTANCE)handle);
+#else
+ dlclose(handle);
+#endif
+}
+
+void *
+PluginLoader::Impl::lookupInLibrary(void *handle, const char *symbol)
+{
+#ifdef _WIN32
+ return (void *)GetProcAddress((HINSTANCE)handle, symbol);
+#else
+ return (void *)dlsym(handle, symbol);
+#endif
+}
+
+string
+PluginLoader::Impl::splicePath(string a, string b)
+{
+#ifdef _WIN32
+ return a + "\\" + b;
+#else
+ return a + "/" + b;
+#endif
+}
+
+vector<string>
+PluginLoader::Impl::listFiles(string dir, string extension)
+{
+ vector<string> files;
+
+#ifdef _WIN32
+
+ string expression = dir + "\\*." + extension;
+ WIN32_FIND_DATA data;
+ HANDLE fh = FindFirstFile(expression.c_str(), &data);
+ if (fh == INVALID_HANDLE_VALUE) return files;
+
+ bool ok = true;
+ while (ok) {
+ files.push_back(data.cFileName);
+ ok = FindNextFile(fh, &data);
+ }
+
+ FindClose(fh);
+
+#else
+
+ size_t extlen = extension.length();
+ DIR *d = opendir(dir.c_str());
+ if (!d) return files;
+
+ struct dirent *e = 0;
+ while ((e = readdir(d))) {
+
+ if (!(e->d_type & DT_REG) || !e->d_name) continue;
+
+ size_t len = strlen(e->d_name);
+ if (len < extlen + 2 ||
+ e->d_name + len - extlen - 1 != "." + extension) {
+ continue;
+ }
+
+ files.push_back(e->d_name);
+ }
+
+ closedir(d);
+#endif
+
+ return files;
+}
+
+void
+PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter)
+{
+ void *handle = m_pluginLibraryHandleMap[adapter];
+ if (handle) unloadLibrary(handle);
+ m_pluginLibraryHandleMap.erase(adapter);
+}
+
+PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin,
+ Impl *loader) :
+ PluginWrapper(plugin),
+ m_loader(loader)
+{
+}
+
+PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
+{
+ // We need to delete the plugin before calling pluginDeleted, as
+ // the delete call may require calling through to the descriptor
+ // (for e.g. cleanup) but pluginDeleted may unload the required
+ // library for the call. To prevent a double deletion when our
+ // parent's destructor runs (after this one), be sure to set
+ // m_plugin to 0 after deletion.
+ delete m_plugin;
+ m_plugin = 0;
+
+ if (m_loader) m_loader->pluginDeleted(this);
+}
+
+}
+
+}
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h
new file mode 100644
index 0000000000..82ae22b930
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginLoader.h
@@ -0,0 +1,218 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_LOADER_H_
+#define _VAMP_PLUGIN_LOADER_H_
+
+#include <vector>
+#include <string>
+#include <map>
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+class Plugin;
+
+namespace HostExt {
+
+/**
+ * \class PluginLoader PluginLoader.h <vamp-sdk/hostext/PluginLoader.h>
+ *
+ * Vamp::HostExt::PluginLoader is a convenience class for discovering
+ * and loading Vamp plugins using the typical plugin-path, library
+ * naming, and categorisation conventions described in the Vamp SDK
+ * documentation. This class is intended to greatly simplify the task
+ * of becoming a Vamp plugin host for any C++ application.
+ *
+ * Hosts are not required by the Vamp specification to use the same
+ * plugin search path and naming conventions as implemented by this
+ * class, and are certainly not required to use this actual class.
+ * But we do strongly recommend it.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginLoader
+{
+public:
+ /**
+ * Obtain a pointer to the singleton instance of PluginLoader.
+ * Use this to obtain your loader object.
+ */
+ static PluginLoader *getInstance();
+
+ /**
+ * PluginKey is a string type that is used to identify a plugin
+ * uniquely within the scope of "the current system". It consists
+ * of the lower-cased base name of the plugin library, a colon
+ * separator, and the identifier string for the plugin. It is
+ * only meaningful in the context of a given plugin path (the one
+ * returned by PluginHostAdapter::getPluginPath()).
+ *
+ * Use composePluginKey() to construct a plugin key from a known
+ * plugin library name and identifier.
+ *
+ * Note: the fact that the library component of the key is
+ * lower-cased implies that library names are matched
+ * case-insensitively by the PluginLoader class, regardless of the
+ * case sensitivity of the underlying filesystem. (Plugin
+ * identifiers _are_ case sensitive, however.) Also, it is not
+ * possible to portably extract a working library name from a
+ * plugin key, as the result may fail on case-sensitive
+ * filesystems. Use getLibraryPathForPlugin() instead.
+ */
+ typedef std::string PluginKey;
+
+ /**
+ * PluginKeyList is a sequence of plugin keys, such as returned by
+ * listPlugins().
+ */
+ typedef std::vector<PluginKey> PluginKeyList;
+
+ /**
+ * PluginCategoryHierarchy is a sequence of general->specific
+ * category names, as may be associated with a single plugin.
+ * This sequence describes the location of a plugin within a
+ * category forest, containing the human-readable names of the
+ * plugin's category tree root, followed by each of the nodes down
+ * to the leaf containing the plugin.
+ *
+ * \see getPluginCategory()
+ */
+ typedef std::vector<std::string> PluginCategoryHierarchy;
+
+ /**
+ * Search for all available Vamp plugins, and return a list of
+ * them in the order in which they were found.
+ */
+ PluginKeyList listPlugins();
+
+ /**
+ * AdapterFlags contains a set of values that may be OR'd together
+ * to indicate in which circumstances PluginLoader should use a
+ * plugin adapter to make a plugin easier to use for a host that
+ * does not want to cater for complex features.
+ *
+ * The available flags are:
+ *
+ * ADAPT_INPUT_DOMAIN - If the plugin expects frequency domain
+ * input, wrap it in a PluginInputDomainAdapter that automatically
+ * converts the plugin to one that expects time-domain input.
+ * This enables a host to accommodate time- and frequency-domain
+ * plugins without needing to do any conversion itself.
+ *
+ * ADAPT_CHANNEL_COUNT - Wrap the plugin in a PluginChannelAdapter
+ * to handle any mismatch between the number of channels of audio
+ * the plugin can handle and the number available in the host.
+ * This enables a host to use plugins that may require the input
+ * to be mixed down to mono, etc., without having to worry about
+ * doing that itself.
+ *
+ * ADAPT_ALL - Perform all available adaptations, where meaningful.
+ *
+ * See PluginInputDomainAdapter and PluginChannelAdapter for more
+ * details of the classes that the loader may use if these flags
+ * are set.
+ */
+ enum AdapterFlags {
+ ADAPT_INPUT_DOMAIN = 0x01,
+ ADAPT_CHANNEL_COUNT = 0x02,
+ ADAPT_ALL = 0xff
+ };
+
+ /**
+ * Load a Vamp plugin, given its identifying key. If the plugin
+ * could not be loaded, returns 0.
+ *
+ * The returned plugin should be deleted (using the standard C++
+ * delete keyword) after use.
+ *
+ * \param adapterFlags a bitwise OR of the values in the AdapterFlags
+ * enumeration, indicating under which circumstances an adapter should be
+ * used to wrap the original plugin. If adapterFlags is 0, no
+ * optional adapters will be used. Otherwise, the returned plugin
+ * may be of an adapter class type which will behave identically
+ * to the original plugin, apart from any particular features
+ * implemented by the adapter itself.
+ *
+ * \see AdapterFlags, PluginInputDomainAdapter, PluginChannelAdapter
+ */
+ Plugin *loadPlugin(PluginKey key,
+ float inputSampleRate,
+ int adapterFlags = 0);
+
+ /**
+ * Given a Vamp plugin library name and plugin identifier, return
+ * the corresponding plugin key in a form suitable for passing in to
+ * loadPlugin().
+ */
+ PluginKey composePluginKey(std::string libraryName,
+ std::string identifier);
+
+ /**
+ * Return the category hierarchy for a Vamp plugin, given its
+ * identifying key.
+ *
+ * If the plugin has no category information, return an empty
+ * hierarchy.
+ *
+ * \see PluginCategoryHierarchy
+ */
+ PluginCategoryHierarchy getPluginCategory(PluginKey plugin);
+
+ /**
+ * Return the file path of the dynamic library from which the
+ * given plugin will be loaded (if available).
+ */
+ std::string getLibraryPathForPlugin(PluginKey plugin);
+
+protected:
+ PluginLoader();
+ virtual ~PluginLoader();
+
+ class Impl;
+ Impl *m_impl;
+
+ static PluginLoader *m_instance;
+};
+
+}
+
+}
+
+#endif
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp b/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp
new file mode 100644
index 0000000000..dcbdf5b73a
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.cpp
@@ -0,0 +1,201 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#include "PluginWrapper.h"
+
+namespace Vamp {
+
+namespace HostExt {
+
+class PluginRateExtractor : public Plugin
+{
+public:
+ PluginRateExtractor() : Plugin(0) { }
+ float getRate() const { return m_inputSampleRate; }
+};
+
+PluginWrapper::PluginWrapper(Plugin *plugin) :
+ Plugin(((PluginRateExtractor *)plugin)->getRate()),
+ m_plugin(plugin)
+{
+}
+
+PluginWrapper::~PluginWrapper()
+{
+ delete m_plugin;
+}
+
+bool
+PluginWrapper::initialise(size_t channels, size_t stepSize, size_t blockSize)
+{
+ return m_plugin->initialise(channels, stepSize, blockSize);
+}
+
+void
+PluginWrapper::reset()
+{
+ m_plugin->reset();
+}
+
+Plugin::InputDomain
+PluginWrapper::getInputDomain() const
+{
+ return m_plugin->getInputDomain();
+}
+
+unsigned int
+PluginWrapper::getVampApiVersion() const
+{
+ return m_plugin->getVampApiVersion();
+}
+
+std::string
+PluginWrapper::getIdentifier() const
+{
+ return m_plugin->getIdentifier();
+}
+
+std::string
+PluginWrapper::getName() const
+{
+ return m_plugin->getName();
+}
+
+std::string
+PluginWrapper::getDescription() const
+{
+ return m_plugin->getDescription();
+}
+
+std::string
+PluginWrapper::getMaker() const
+{
+ return m_plugin->getMaker();
+}
+
+int
+PluginWrapper::getPluginVersion() const
+{
+ return m_plugin->getPluginVersion();
+}
+
+std::string
+PluginWrapper::getCopyright() const
+{
+ return m_plugin->getCopyright();
+}
+
+PluginBase::ParameterList
+PluginWrapper::getParameterDescriptors() const
+{
+ return m_plugin->getParameterDescriptors();
+}
+
+float
+PluginWrapper::getParameter(std::string parameter) const
+{
+ return m_plugin->getParameter(parameter);
+}
+
+void
+PluginWrapper::setParameter(std::string parameter, float value)
+{
+ m_plugin->setParameter(parameter, value);
+}
+
+PluginBase::ProgramList
+PluginWrapper::getPrograms() const
+{
+ return m_plugin->getPrograms();
+}
+
+std::string
+PluginWrapper::getCurrentProgram() const
+{
+ return m_plugin->getCurrentProgram();
+}
+
+void
+PluginWrapper::selectProgram(std::string program)
+{
+ m_plugin->selectProgram(program);
+}
+
+size_t
+PluginWrapper::getPreferredStepSize() const
+{
+ return m_plugin->getPreferredStepSize();
+}
+
+size_t
+PluginWrapper::getPreferredBlockSize() const
+{
+ return m_plugin->getPreferredBlockSize();
+}
+
+size_t
+PluginWrapper::getMinChannelCount() const
+{
+ return m_plugin->getMinChannelCount();
+}
+
+size_t PluginWrapper::getMaxChannelCount() const
+{
+ return m_plugin->getMaxChannelCount();
+}
+
+Plugin::OutputList
+PluginWrapper::getOutputDescriptors() const
+{
+ return m_plugin->getOutputDescriptors();
+}
+
+Plugin::FeatureSet
+PluginWrapper::process(const float *const *inputBuffers, RealTime timestamp)
+{
+ return m_plugin->process(inputBuffers, timestamp);
+}
+
+Plugin::FeatureSet
+PluginWrapper::getRemainingFeatures()
+{
+ return m_plugin->getRemainingFeatures();
+}
+
+}
+
+}
+
diff --git a/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h b/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h
new file mode 100644
index 0000000000..d5ec1da0e8
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/hostext/PluginWrapper.h
@@ -0,0 +1,106 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006-2007 Chris Cannam and QMUL.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef _VAMP_PLUGIN_WRAPPER_H_
+#define _VAMP_PLUGIN_WRAPPER_H_
+
+#include <vamp-sdk/Plugin.h>
+
+namespace Vamp {
+
+namespace HostExt {
+
+/**
+ * \class PluginWrapper PluginWrapper.h <vamp-sdk/hostext/PluginWrapper.h>
+ *
+ * PluginWrapper is a simple base class for adapter plugins. It takes
+ * a pointer to a "to be wrapped" Vamp plugin on construction, and
+ * provides implementations of all the Vamp plugin methods that simply
+ * delegate through to the wrapped plugin. A subclass can therefore
+ * override only the methods that are meaningful for the particular
+ * adapter.
+ *
+ * \note This class was introduced in version 1.1 of the Vamp plugin SDK.
+ */
+
+class PluginWrapper : public Plugin
+{
+public:
+ virtual ~PluginWrapper();
+
+ bool initialise(size_t channels, size_t stepSize, size_t blockSize);
+ void reset();
+
+ InputDomain getInputDomain() const;
+
+ unsigned int getVampApiVersion() const;
+ 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);
+
+ ProgramList getPrograms() const;
+ std::string getCurrentProgram() const;
+ void selectProgram(std::string);
+
+ size_t getPreferredStepSize() const;
+ size_t getPreferredBlockSize() const;
+
+ size_t getMinChannelCount() const;
+ size_t getMaxChannelCount() const;
+
+ OutputList getOutputDescriptors() const;
+
+ FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
+
+ FeatureSet getRemainingFeatures();
+
+protected:
+ PluginWrapper(Plugin *plugin); // I take ownership of plugin
+ Plugin *m_plugin;
+};
+
+}
+
+}
+
+#endif
diff --git a/libs/vamp-sdk/vamp-sdk/libvamp-hostsdk.la.in b/libs/vamp-sdk/vamp-sdk/libvamp-hostsdk.la.in
new file mode 100644
index 0000000000..83362dc39c
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/libvamp-hostsdk.la.in
@@ -0,0 +1,9 @@
+dlname='%LINK_ABI%'
+library_names='%LIBNAME% %LINK_ABI% %LINK_DEV%'
+old_library='%STATIC%'
+dependency_libs=''
+current=2
+age=0
+revision=0
+installed=yes
+libdir='%LIBS%'
diff --git a/libs/vamp-sdk/vamp-sdk/libvamp-sdk.la.in b/libs/vamp-sdk/vamp-sdk/libvamp-sdk.la.in
new file mode 100644
index 0000000000..1674afe3e4
--- /dev/null
+++ b/libs/vamp-sdk/vamp-sdk/libvamp-sdk.la.in
@@ -0,0 +1,9 @@
+dlname='%LINK_ABI%'
+library_names='%LIBNAME% %LINK_ABI% %LINK_DEV%'
+old_library='%STATIC%'
+dependency_libs=''
+current=1
+age=1
+revision=0
+installed=yes
+libdir='%LIBS%'
diff --git a/libs/vamp-sdk/vamp/vamp.h b/libs/vamp-sdk/vamp/vamp.h
new file mode 100644
index 0000000000..4f0145ab59
--- /dev/null
+++ b/libs/vamp-sdk/vamp/vamp.h
@@ -0,0 +1,339 @@
+/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
+
+/*
+ Vamp
+
+ An API for audio analysis and feature extraction plugins.
+
+ Centre for Digital Music, Queen Mary, University of London.
+ Copyright 2006 Chris Cannam.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
+ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the Centre for
+ Digital Music; Queen Mary, University of London; and Chris Cannam
+ shall not be used in advertising or otherwise to promote the sale,
+ use or other dealings in this Software without prior written
+ authorization.
+*/
+
+#ifndef VAMP_HEADER_INCLUDED
+#define VAMP_HEADER_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Plugin API version. This is incremented when a change is made that
+ * changes the binary layout of the descriptor records. When this
+ * happens, there should be a mechanism for retaining compatibility
+ * with older hosts and/or plugins.
+ *
+ * See also the vampApiVersion field in the plugin descriptor, and the
+ * hostApiVersion argument to the vampGetPluginDescriptor function.
+ */
+#define VAMP_API_VERSION 1
+
+/**
+ * C language API for Vamp plugins.
+ *
+ * This is the formal plugin API for Vamp. Plugin authors may prefer
+ * to use the C++ classes provided in the Vamp plugin SDK, instead of
+ * using this API directly. There is an adapter class provided that
+ * makes C++ plugins available using this C API with relatively little
+ * work, and the C++ headers are more thoroughly documented.
+ *
+ * IMPORTANT: The comments in this file summarise the purpose of each
+ * of the declared fields and functions, but do not provide a complete
+ * guide to their permitted values and expected usage. Please refer
+ * to the C++ headers in the Vamp plugin SDK for further details and
+ * plugin lifecycle documentation.
+ */
+
+typedef struct _VampParameterDescriptor
+{
+ /** Computer-usable name of the parameter. Must not change. [a-zA-Z0-9_] */
+ const char *identifier;
+
+ /** Human-readable name of the parameter. May be translatable. */
+ const char *name;
+
+ /** Human-readable short text about the parameter. May be translatable. */
+ const char *description;
+
+ /** Human-readable unit of the parameter. */
+ const char *unit;
+
+ /** Minimum value. */
+ float minValue;
+
+ /** Maximum value. */
+ float maxValue;
+
+ /** Default value. Plugin is responsible for setting this on initialise. */
+ float defaultValue;
+
+ /** 1 if parameter values are quantized to a particular resolution. */
+ int isQuantized;
+
+ /** Quantization resolution, if isQuantized. */
+ float quantizeStep;
+
+ /** Human-readable names of the values, if isQuantized. May be NULL. */
+ const char **valueNames;
+
+} VampParameterDescriptor;
+
+typedef enum
+{
+ /** Each process call returns results aligned with call's block start. */
+ vampOneSamplePerStep,
+
+ /** Returned results are evenly spaced at samplerate specified below. */
+ vampFixedSampleRate,
+
+ /** Returned results have their own individual timestamps. */
+ vampVariableSampleRate
+
+} VampSampleType;
+
+typedef struct _VampOutputDescriptor
+{
+ /** Computer-usable name of the output. Must not change. [a-zA-Z0-9_] */
+ const char *identifier;
+
+ /** Human-readable name of the output. May be translatable. */
+ const char *name;
+
+ /** Human-readable short text about the output. May be translatable. */
+ const char *description;
+
+ /** Human-readable name of the unit of the output. */
+ const char *unit;
+
+ /** 1 if output has equal number of values for each returned result. */
+ int hasFixedBinCount;
+
+ /** Number of values per result, if hasFixedBinCount. */
+ unsigned int binCount;
+
+ /** Names of returned value bins, if hasFixedBinCount. May be NULL. */
+ const char **binNames;
+
+ /** 1 if each returned value falls within the same fixed min/max range. */
+ int hasKnownExtents;
+
+ /** Minimum value for a returned result in any bin, if hasKnownExtents. */
+ float minValue;
+
+ /** Maximum value for a returned result in any bin, if hasKnownExtents. */
+ float maxValue;
+
+ /** 1 if returned results are quantized to a particular resolution. */
+ int isQuantized;
+
+ /** Quantization resolution for returned results, if isQuantized. */
+ float quantizeStep;
+
+ /** Time positioning method for returned results (see VampSampleType). */
+ VampSampleType sampleType;
+
+ /** Sample rate of returned results, if sampleType is vampFixedSampleRate.
+ "Resolution" of result, if sampleType is vampVariableSampleRate. */
+ float sampleRate;
+
+} VampOutputDescriptor;
+
+typedef struct _VampFeature
+{
+ /** 1 if the feature has a timestamp (i.e. if vampVariableSampleRate). */
+ int hasTimestamp;
+
+ /** Seconds component of timestamp. */
+ int sec;
+
+ /** Nanoseconds component of timestamp. */
+ int nsec;
+
+ /** Number of values. Must be binCount if hasFixedBinCount. */
+ unsigned int valueCount;
+
+ /** Values for this returned sample. */
+ float *values;
+
+ /** Label for this returned sample. May be NULL. */
+ char *label;
+
+} VampFeature;
+
+typedef struct _VampFeatureList
+{
+ /** Number of features in this feature list. */
+ unsigned int featureCount;
+
+ /** Features in this feature list. May be NULL if featureCount is zero. */
+ VampFeature *features;
+
+} VampFeatureList;
+
+typedef enum
+{
+ vampTimeDomain,
+ vampFrequencyDomain
+
+} VampInputDomain;
+
+typedef void *VampPluginHandle;
+
+typedef struct _VampPluginDescriptor
+{
+ /** API version with which this descriptor is compatible. */
+ unsigned int vampApiVersion;
+
+ /** Computer-usable name of the plugin. Must not change. [a-zA-Z0-9_] */
+ const char *identifier;
+
+ /** Human-readable name of the plugin. May be translatable. */
+ const char *name;
+
+ /** Human-readable short text about the plugin. May be translatable. */
+ const char *description;
+
+ /** Human-readable name of plugin's author or vendor. */
+ const char *maker;
+
+ /** Version number of the plugin. */
+ int pluginVersion;
+
+ /** Human-readable summary of copyright or licensing for plugin. */
+ const char *copyright;
+
+ /** Number of parameter inputs. */
+ unsigned int parameterCount;
+
+ /** Fixed descriptors for parameter inputs. */
+ const VampParameterDescriptor **parameters;
+
+ /** Number of programs. */
+ unsigned int programCount;
+
+ /** Fixed names for programs. */
+ const char **programs;
+
+ /** Preferred input domain for audio input (time or frequency). */
+ VampInputDomain inputDomain;
+
+ /** Create and return a new instance of this plugin. */
+ VampPluginHandle (*instantiate)(const struct _VampPluginDescriptor *,
+ float inputSampleRate);
+
+ /** Destroy an instance of this plugin. */
+ void (*cleanup)(VampPluginHandle);
+
+ /** Initialise an instance following parameter configuration. */
+ int (*initialise)(VampPluginHandle,
+ unsigned int inputChannels,
+ unsigned int stepSize,
+ unsigned int blockSize);
+
+ /** Reset an instance, ready to use again on new input data. */
+ void (*reset)(VampPluginHandle);
+
+ /** Get a parameter value. */
+ float (*getParameter)(VampPluginHandle, int);
+
+ /** Set a parameter value. May only be called before initialise. */
+ void (*setParameter)(VampPluginHandle, int, float);
+
+ /** Get the current program (if programCount > 0). */
+ unsigned int (*getCurrentProgram)(VampPluginHandle);
+
+ /** Set the current program. May only be called before initialise. */
+ void (*selectProgram)(VampPluginHandle, unsigned int);
+
+ /** Get the plugin's preferred processing window increment in samples. */
+ unsigned int (*getPreferredStepSize)(VampPluginHandle);
+
+ /** Get the plugin's preferred processing window size in samples. */
+ unsigned int (*getPreferredBlockSize)(VampPluginHandle);
+
+ /** Get the minimum number of input channels this plugin can handle. */
+ unsigned int (*getMinChannelCount)(VampPluginHandle);
+
+ /** Get the maximum number of input channels this plugin can handle. */
+ unsigned int (*getMaxChannelCount)(VampPluginHandle);
+
+ /** Get the number of feature outputs (distinct sets of results). */
+ unsigned int (*getOutputCount)(VampPluginHandle);
+
+ /** Get a descriptor for a given feature output. Returned pointer
+ is valid only until next call to getOutputDescriptor for this
+ handle, or releaseOutputDescriptor for this descriptor. Host
+ must call releaseOutputDescriptor after use. */
+ VampOutputDescriptor *(*getOutputDescriptor)(VampPluginHandle,
+ unsigned int);
+
+ /** Destroy a descriptor for a feature output. */
+ void (*releaseOutputDescriptor)(VampOutputDescriptor *);
+
+ /** Process an input block and return a set of features. Returned
+ pointer is valid only until next call to process,
+ getRemainingFeatures, or cleanup for this handle, or
+ releaseFeatureSet for this feature set. Host must call
+ releaseFeatureSet after use. */
+ VampFeatureList *(*process)(VampPluginHandle,
+ const float *const *inputBuffers,
+ int sec,
+ int nsec);
+
+ /** Return any remaining features at the end of processing. */
+ VampFeatureList *(*getRemainingFeatures)(VampPluginHandle);
+
+ /** Release a feature set returned from process or getRemainingFeatures. */
+ void (*releaseFeatureSet)(VampFeatureList *);
+
+} VampPluginDescriptor;
+
+/** Get the descriptor for a given plugin index in this library.
+ Return NULL if the index is outside the range of valid indices for
+ this plugin library.
+
+ The hostApiVersion argument tells the library code the highest
+ Vamp API version supported by the host. The function should
+ return a plugin descriptor compatible with the highest API version
+ supported by the library that is no higher than that supported by
+ the host. Provided the descriptor has the correct vampApiVersion
+ field for its actual compatibility level, the host should be able
+ to do the right thing with it: use it if possible, discard it
+ otherwise.
+*/
+const VampPluginDescriptor *vampGetPluginDescriptor
+ (unsigned int hostApiVersion, unsigned int index);
+
+/** Function pointer type for vampGetPluginDescriptor. */
+typedef const VampPluginDescriptor *(*VampGetPluginDescriptorFunction)
+ (unsigned int, unsigned int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/vamp-sdk/vamp/vamp.pc.in b/libs/vamp-sdk/vamp/vamp.pc.in
new file mode 100644
index 0000000000..82d4decd34
--- /dev/null
+++ b/libs/vamp-sdk/vamp/vamp.pc.in
@@ -0,0 +1,10 @@
+prefix=%PREFIX%
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: vamp
+Version: 1.0
+Description: An API for audio analysis and feature extraction plugins
+Libs:
+Cflags: -I${includedir}