summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-10-03 03:51:53 +0200
committerRobin Gareus <robin@gareus.org>2016-10-03 03:52:51 +0200
commit330e69b5652676653d4c49d33e503617ad476194 (patch)
treef6f2f6eafb849e05fa3647d276fcb18f6c91ae7a /libs
parentaf289cab6231ec8785a2e69ab78f6257626aef9f (diff)
Add Vamp-plugin Lua bindings (work in progress)
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/lua_api.h65
-rw-r--r--libs/ardour/lua_api.cc98
-rw-r--r--libs/ardour/luabindings.cc123
3 files changed, 285 insertions, 1 deletions
diff --git a/libs/ardour/ardour/lua_api.h b/libs/ardour/ardour/lua_api.h
index bfe2e16283..85fe92f28c 100644
--- a/libs/ardour/ardour/lua_api.h
+++ b/libs/ardour/ardour/lua_api.h
@@ -22,12 +22,17 @@
#include <string>
#include <lo/lo.h>
#include <boost/shared_ptr.hpp>
+#include <vamp-sdk/Plugin.h>
#include "ardour/libardour_visibility.h"
#include "ardour/processor.h"
#include "ardour/session.h"
+namespace ARDOUR {
+ class Readable;
+}
+
namespace ARDOUR { namespace LuaAPI {
/** convenience constructor for DataType::NIL with managed lifetime
@@ -157,6 +162,66 @@ namespace ARDOUR { namespace LuaAPI {
*/
int build_filename (lua_State *lua);
+ class Vamp {
+ /** Vamp Plugin Interface
+ *
+ * Vamp is an audio processing plugin system for plugins that extract descriptive information
+ * from audio data - typically referred to as audio analysis plugins or audio feature
+ * extraction plugins.
+ *
+ * This interface allows to load a plugins and directly access it using the Vamp Plugin API.
+ *
+ * A convenience method is provided to analyze Ardour::Readable objects (Regions).
+ */
+ public:
+ Vamp (const std::string&, float sample_rate);
+ ~Vamp ();
+ ::Vamp::Plugin* plugin () { return _plugin; }
+
+ /* high-level abstraction to process a single channel of the given Readable.
+ *
+ * If the plugin is not yet initialized, initialize() is called.
+ *
+ * if @cb is not nil, it is called with the immediate
+ * Vamp::Plugin::Features on every process call.
+ *
+ * @r readable
+ * @channel channel to process
+ * @cb lua callback function
+ * @return 0 on success
+ */
+ int analyze (boost::shared_ptr<ARDOUR::Readable>, uint32_t channel, luabridge::LuaRef fn);
+
+ /** call plugin():reset() and clear intialization flag */
+ void reset ();
+
+ /** initialize the plugin for use with analyze().
+ *
+ * This is equivalent to plugin():initialise (1, 8192, 8192)
+ * and prepares a plugin for analyze.
+ *
+ * Manual initialization is only required to set plugin-parameters
+ * which depend on prior initialization of the plugin.
+ *
+ * @code
+ * vamp:reset ()
+ * vamp:initialize ()
+ * vamp:plugin():setParameter (0, 1.5)
+ * vamp:analyze (r, 0)
+ * @endcode
+ */
+ bool initialize ();
+
+ bool initialized () const { return _initialized; }
+
+ private:
+ ::Vamp::Plugin* _plugin;
+ float _sample_rate;
+ framecnt_t _bufsize;
+ bool _initialized;
+
+ };
+
} } /* namespace */
namespace ARDOUR { namespace LuaOSC {
diff --git a/libs/ardour/lua_api.cc b/libs/ardour/lua_api.cc
index 201ca7de0e..2f6c995851 100644
--- a/libs/ardour/lua_api.cc
+++ b/libs/ardour/lua_api.cc
@@ -17,9 +17,11 @@
*
*/
#include <cstring>
+#include <vamp-hostsdk/PluginLoader.h>
-#include "pbd/error.h"
#include "pbd/compose.h"
+#include "pbd/error.h"
+#include "pbd/failed_constructor.h"
#include "ardour/lua_api.h"
#include "ardour/luaproc.h"
@@ -27,6 +29,7 @@
#include "ardour/plugin.h"
#include "ardour/plugin_insert.h"
#include "ardour/plugin_manager.h"
+#include "ardour/readable.h"
#include "LuaBridge/LuaBridge.h"
@@ -535,3 +538,96 @@ void LuaTableRef::assign (luabridge::LuaRef* rv, T key, const LuaTableEntry& s)
break;
}
}
+
+
+LuaAPI::Vamp::Vamp (const std::string& key, float sample_rate)
+ : _plugin (0)
+ , _sample_rate (sample_rate)
+ , _bufsize (8192)
+ , _initialized (false)
+{
+ using namespace ::Vamp::HostExt;
+
+ PluginLoader* loader (PluginLoader::getInstance());
+ _plugin = loader->loadPlugin (key, _sample_rate, PluginLoader::ADAPT_ALL_SAFE);
+
+ if (!_plugin) {
+ PBD::error << string_compose (_("VAMP Plugin \"%1\" could not be loaded"), key) << endmsg;
+ throw failed_constructor ();
+ }
+}
+
+LuaAPI::Vamp::~Vamp ()
+{
+ delete _plugin;
+}
+
+void
+LuaAPI::Vamp::reset ()
+{
+ _initialized = false;
+ if (_plugin) {
+ _plugin->reset ();
+ }
+}
+
+bool
+LuaAPI::Vamp::initialize ()
+{
+ if (!_plugin || _plugin->getMinChannelCount() > 1) {
+ return false;
+ }
+ if (!_plugin->initialise (1, _bufsize, _bufsize)) {
+ return false;
+ }
+ _initialized = true;
+ return true;
+}
+
+int
+LuaAPI::Vamp::analyze (boost::shared_ptr<ARDOUR::Readable> r, uint32_t channel, luabridge::LuaRef cb)
+{
+ if (!_initialized) {
+ if (!initialize ()) {
+ return -1;
+ }
+ }
+ assert (_initialized);
+
+ ::Vamp::Plugin::FeatureSet features;
+ float* data = new float[_bufsize];
+ float* bufs[1] = { data };
+
+ framecnt_t len = r->readable_length();
+ framepos_t pos = 0;
+
+ int rv = 0;
+ while (1) {
+ framecnt_t to_read = std::min ((len - pos), _bufsize);
+ if (r->read (data, pos, to_read, channel) != to_read) {
+ rv = -1;
+ break;
+ }
+ if (to_read != _bufsize) {
+ memset (data + to_read, 0, (_bufsize - to_read) * sizeof (float));
+ }
+
+ features = _plugin->process (bufs, ::Vamp::RealTime::fromSeconds ((double) pos / _sample_rate));
+
+ if (cb.type () == LUA_TFUNCTION) {
+ /* TODO existing "features" binding fails here
+ * std::map<int, std::vector<_VampHost::Vamp::Plugin::Feature> >
+ */
+ // cb (features, pos); // XXX
+ }
+
+ pos += to_read;
+
+ if (pos >= len) {
+ break;
+ }
+ }
+
+ delete [] data;
+ return rv;
+}
diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc
index 096c0647ae..59e64d3a86 100644
--- a/libs/ardour/luabindings.cc
+++ b/libs/ardour/luabindings.cc
@@ -32,6 +32,7 @@
#include "ardour/audio_buffer.h"
#include "ardour/audio_port.h"
#include "ardour/audio_track.h"
+#include "ardour/audioplaylist.h"
#include "ardour/buffer_set.h"
#include "ardour/chan_mapping.h"
#include "ardour/dB.h"
@@ -239,6 +240,10 @@ LuaBindings::stddef (lua_State* L)
.beginStdVector <std::string> ("StringVector")
.endClass ()
+ // std::vector<float>
+ .beginStdVector <float> ("FloatVector")
+ .endClass ()
+
// register float array (uint8_t*)
.registerArray <uint8_t> ("ByteArray")
@@ -437,6 +442,103 @@ LuaBindings::common (lua_State* L)
.endNamespace () // Evoral
+ .beginNamespace ("Vamp")
+
+ .beginClass<Vamp::RealTime> ("RealTime")
+ .addConstructor <void (*) (int, int)> ()
+ .addFunction ("usec", &Vamp::RealTime::usec)
+ .addFunction ("msec", &Vamp::RealTime::msec)
+ .addFunction ("toString", &Vamp::RealTime::toString)
+ .endClass ()
+
+ .beginClass<Vamp::PluginBase> ("PluginBase")
+ .addFunction ("getIdentifier", &Vamp::PluginBase::getIdentifier)
+ .addFunction ("getName", &Vamp::PluginBase::getName)
+ .addFunction ("getDescription", &Vamp::PluginBase::getDescription)
+ .addFunction ("getMaker", &Vamp::PluginBase::getMaker)
+ .addFunction ("getCopyright", &Vamp::PluginBase::getCopyright)
+ .addFunction ("getPluginVersion", &Vamp::PluginBase::getPluginVersion)
+ .addFunction ("getParameterDescriptors", &Vamp::PluginBase::getParameterDescriptors)
+ .addFunction ("getParameter", &Vamp::PluginBase::getParameter)
+ .addFunction ("setParameter", &Vamp::PluginBase::setParameter)
+ .addFunction ("getPrograms", &Vamp::PluginBase::getPrograms)
+ .addFunction ("getCurrentProgram", &Vamp::PluginBase::getCurrentProgram)
+ .addFunction ("selectProgram", &Vamp::PluginBase::selectProgram)
+ .addFunction ("getType", &Vamp::PluginBase::getType)
+ .endClass ()
+
+ .beginNamespace ("PluginBase")
+ .beginClass<Vamp::PluginBase::ParameterDescriptor> ("ParameterDescriptor")
+ .addData ("identifier", &Vamp::PluginBase::ParameterDescriptor::identifier)
+ .addData ("name", &Vamp::PluginBase::ParameterDescriptor::name)
+ .addData ("description", &Vamp::PluginBase::ParameterDescriptor::description)
+ .addData ("unit", &Vamp::PluginBase::ParameterDescriptor::unit)
+ .addData ("minValue", &Vamp::PluginBase::ParameterDescriptor::minValue)
+ .addData ("maxValue", &Vamp::PluginBase::ParameterDescriptor::maxValue)
+ .addData ("defaultValue", &Vamp::PluginBase::ParameterDescriptor::defaultValue)
+ .addData ("isQuantized", &Vamp::PluginBase::ParameterDescriptor::isQuantized)
+ .addData ("quantizeStep", &Vamp::PluginBase::ParameterDescriptor::quantizeStep)
+ .addData ("valueNames", &Vamp::PluginBase::ParameterDescriptor::valueNames)
+ .endClass ()
+
+ .beginStdVector <Vamp::PluginBase::ParameterDescriptor> ("ParameterList")
+ .endClass ()
+ .endNamespace () // Vamp::PluginBase
+
+ .deriveClass<Vamp::Plugin, Vamp::PluginBase> ("Plugin")
+ // TODO add wrapper std::vector<FloatArray>
+ .addFunction ("process", &Vamp::Plugin::process) // XXX unusable due to float * const *
+ .addFunction ("getRemainingFeatures", &Vamp::Plugin::getRemainingFeatures)
+ .endClass ()
+
+ .beginNamespace ("Plugin")
+ .beginClass<Vamp::Plugin::OutputDescriptor> ("OutputDescriptor")
+ .addData ("identifier", &Vamp::Plugin::OutputDescriptor::identifier)
+ .addData ("description", &Vamp::Plugin::OutputDescriptor::description)
+ .addData ("unit", &Vamp::Plugin::OutputDescriptor::unit)
+ .addData ("hasFixedBinCount", &Vamp::Plugin::OutputDescriptor::hasFixedBinCount)
+ .addData ("binCount", &Vamp::Plugin::OutputDescriptor::binCount)
+ .addData ("binNames", &Vamp::Plugin::OutputDescriptor::binNames)
+ .addData ("hasKnownExtents", &Vamp::Plugin::OutputDescriptor::hasKnownExtents)
+ .addData ("minValue", &Vamp::Plugin::OutputDescriptor::minValue)
+ .addData ("maxValue", &Vamp::Plugin::OutputDescriptor::maxValue)
+ .addData ("isQuantized", &Vamp::Plugin::OutputDescriptor::isQuantized)
+ .addData ("quantizeStep", &Vamp::Plugin::OutputDescriptor::quantizeStep)
+ .addData ("sampleType", &Vamp::Plugin::OutputDescriptor::sampleType)
+ .addData ("sampleRate", &Vamp::Plugin::OutputDescriptor::sampleRate)
+ .addData ("hasDuration", &Vamp::Plugin::OutputDescriptor::hasDuration)
+ .endClass ()
+
+ .beginNamespace ("OutputDescriptor")
+ /* Vamp::Plugin::OutputDescriptor enum */
+ .beginNamespace ("SampleType")
+ .addConst ("OneSamplePerStep", Vamp::Plugin::OutputDescriptor::SampleType(Vamp::Plugin::OutputDescriptor::OneSamplePerStep))
+ .addConst ("FixedSampleRate", Vamp::Plugin::OutputDescriptor::SampleType(Vamp::Plugin::OutputDescriptor::FixedSampleRate))
+ .addConst ("VariableSampleRate", Vamp::Plugin::OutputDescriptor::SampleType(Vamp::Plugin::OutputDescriptor::VariableSampleRate))
+ .endNamespace ()
+ .endNamespace () /* Vamp::Plugin::OutputDescriptor */
+
+ .beginClass<Vamp::Plugin::Feature> ("Feature")
+ .addData ("hasTimestamp", &Vamp::Plugin::Feature::hasTimestamp, false)
+ .addData ("timestamp", &Vamp::Plugin::Feature::timestamp, false)
+ .addData ("hasDuration", &Vamp::Plugin::Feature::hasDuration, false)
+ .addData ("duration", &Vamp::Plugin::Feature::duration, false)
+ .addData ("values", &Vamp::Plugin::Feature::values, false)
+ .addData ("label", &Vamp::Plugin::Feature::label, false)
+ .endClass ()
+
+ .beginStdVector <Vamp::Plugin::OutputDescriptor> ("OutputList")
+ .endClass ()
+
+ .beginStdVector <Vamp::Plugin::Feature> ("FeatureList")
+ .endClass ()
+
+ .beginStdMap <int, Vamp::Plugin::FeatureList> ("FeatureSet")
+ .endClass ()
+
+ .endNamespace () // Vamp::Plugin
+ .endNamespace () // Vamp
+
.beginNamespace ("ARDOUR")
.beginClass <InterThreadInfo> ("InterThreadInfo")
@@ -712,6 +814,7 @@ LuaBindings::common (lua_State* L)
.endClass ()
.deriveWSPtrClass <Playlist, SessionObject> ("Playlist")
+ .addCast<AudioPlaylist> ("to_audioplaylist")
.addFunction ("region_by_id", &Playlist::region_by_id)
.addFunction ("data_type", &Playlist::data_type)
.addFunction ("n_regions", &Playlist::n_regions)
@@ -746,6 +849,10 @@ LuaBindings::common (lua_State* L)
#endif
.endClass ()
+ .deriveWSPtrClass <AudioPlaylist, Playlist> ("AudioPlaylist")
+ .addFunction ("read", &AudioPlaylist::read)
+ .endClass ()
+
.deriveWSPtrClass <Track, Route> ("Track")
.addCast<AudioTrack> ("to_audio_track")
.addCast<MidiTrack> ("to_midi_track")
@@ -763,7 +870,14 @@ LuaBindings::common (lua_State* L)
.deriveWSPtrClass <MidiTrack, Track> ("MidiTrack")
.endClass ()
+ .beginWSPtrClass <Readable> ("Readable")
+ .addFunction ("read", &Readable::read)
+ .addFunction ("readable_length", &Readable::readable_length)
+ .addFunction ("n_channels", &Readable::n_channels)
+ .endClass ()
+
.deriveWSPtrClass <Region, SessionObject> ("Region")
+ .addCast<Readable> ("to_readable")
/* properties */
.addFunction ("position", &Region::position)
.addFunction ("start", &Region::start)
@@ -1472,6 +1586,15 @@ LuaBindings::common (lua_State* L)
.addCFunction ("hsla_to_rgba", ARDOUR::LuaAPI::hsla_to_rgba)
.addFunction ("usleep", Glib::usleep)
.addCFunction ("build_filename", ARDOUR::LuaAPI::build_filename)
+
+ .beginClass <ARDOUR::LuaAPI::Vamp> ("Vamp")
+ .addConstructor <void (*) (const std::string&, float)> ()
+ .addFunction ("plugin", &ARDOUR::LuaAPI::Vamp::plugin)
+ .addFunction ("analyze", &ARDOUR::LuaAPI::Vamp::analyze)
+ .addFunction ("reset", &ARDOUR::LuaAPI::Vamp::reset)
+ .addFunction ("initialize", &ARDOUR::LuaAPI::Vamp::initialize)
+ .endClass ()
+
.endNamespace () // end LuaAPI
.endNamespace ();// end ARDOUR
}