From 57b76983121906710853ea46ebd5089a6f7d40a7 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 24 Mar 2016 21:36:07 +0100 Subject: [PATCH] Consistent C++ & Lua Namespace/Class names + documentation. --- libs/ardour/ardour/dsp_filter.h | 92 +++++++++++++++++++++++++++++-- libs/ardour/ardour/lua_api.h | 95 +++++++++++++++++++++++++++++---- libs/ardour/lua_api.cc | 6 +-- libs/ardour/luabindings.cc | 6 +-- scripts/osc_hook_example.lua | 2 +- 5 files changed, 181 insertions(+), 20 deletions(-) diff --git a/libs/ardour/ardour/dsp_filter.h b/libs/ardour/ardour/dsp_filter.h index 1b4cb6eed8..c2572e0a71 100644 --- a/libs/ardour/ardour/dsp_filter.h +++ b/libs/ardour/ardour/dsp_filter.h @@ -27,9 +27,20 @@ namespace ARDOUR { namespace DSP { - /** a convenience class for lua scripts to use C memory for DSP operations. + /** C Shared Memory * - * It should be allocated during dsp_init() or dsp_configure(). + * A convenience class representing a C array or float[] or int32_t[] + * data values. This is useful for lua scripts to perform DSP operations + * directly using C, C++. + * Access to this memory area is always 4 byte aligned: float, int. + * + * This memory area can also be shared between different instances. + * + * Since memory allocation is not realtime safe it should be + * allocated during dsp_init() or dsp_configure(). + * + * The memory is free()ed automatically when the lua instance is + * destroyed. */ class DspShm { public: @@ -45,29 +56,62 @@ namespace ARDOUR { namespace DSP { free (_data); } + /** [re] allocate memory in host's memory space + * + * @param s size, total number of float or integer elements to store. + */ void allocate (size_t s) { _data = realloc (_data, sizeof(float) * s); if (_data) { _size = s; } } + /** clear memory (set to zero) */ void clear () { memset (_data, 0, sizeof(float) * _size); } + /** access memory as float array + * + * @param off offset in shared memory region + * @returns float[] + */ float* to_float (size_t off) { if (off >= _size) { return 0; } return &(((float*)_data)[off]); } + /** access memory as integer array + * + * @param off offset in shared memory region + * @returns int_32_t[] + */ int32_t* to_int (size_t off) { if (off >= _size) { return 0; } return &(((int32_t*)_data)[off]); } + /** atomically set integer at offset + * + * This involves a memory barrier. This call + * is intended for buffers which are + * shared with another instance. + * + * @param off offset in shared memory region + * @param val value to set + */ void atomic_set_int (size_t off, int32_t val) { g_atomic_int_set (&(((int32_t*)_data)[off]), val); } + /** atomically read integer at offset + * + * This involves a memory barrier. This call + * is intended for buffers which are + * shared with another instance. + * + * @param off offset in shared memory region + * @returns value at offset + */ int32_t atomic_get_int (size_t off) { return g_atomic_int_get (&(((int32_t*)_data)[off])); } @@ -84,12 +128,36 @@ namespace ARDOUR { namespace DSP { float log_meter (float power); float log_meter_coeff (float coeff); + /** 1st order Low Pass filter */ class LIBARDOUR_API LowPass { public: + /** instantiate a LPF + * + * @param samplerate samplerate + * @param freq cut-off frequency + */ LowPass (double samplerate, float freq); + /** process audio data + * + * @param data pointer to audio-data + * @param n_samples number of samples to process + */ void proc (float *data, const uint32_t n_samples); + /** filter control data + * + * This is useful for parameter smoothing. + * + * @param data pointer to control-data array + * @param val target value + * @param array length + */ void ctrl (float *data, const float val, const uint32_t n_samples); + /** update filter cut-off frequency + * + * @param freq cut-off frequency + */ void set_cutoff (float freq); + /** reset filter state */ void reset () { _z = 0.f; } private: float _rate; @@ -97,6 +165,7 @@ namespace ARDOUR { namespace DSP { float _a; }; + /** Biquad Filter */ class LIBARDOUR_API BiQuad { public: enum Type { @@ -111,11 +180,28 @@ namespace ARDOUR { namespace DSP { HighShelf }; + /** Instantiate Biquad Filter + * + * @param samplerate Samplerate + */ BiQuad (double samplerate); BiQuad (const BiQuad &other); + /** process audio data + * + * @param data pointer to audio-data + * @param n_samples number of samples to process + */ void run (float *data, const uint32_t n_samples); - void compute (Type, double freq, double Q, double gain); + /** setup filter, compute coefficients + * + * @param t filter type + * @param freq filter frequency + * @param Q filter quality + * @param gain filter gain + */ + void compute (Type t, double freq, double Q, double gain); + /** reset filter state */ void reset () { _z1 = _z2 = 0.0; } private: double _rate; diff --git a/libs/ardour/ardour/lua_api.h b/libs/ardour/ardour/lua_api.h index 997e0036df..cd84f448ca 100644 --- a/libs/ardour/ardour/lua_api.h +++ b/libs/ardour/ardour/lua_api.h @@ -30,23 +30,98 @@ namespace ARDOUR { namespace LuaAPI { - boost::shared_ptr new_luaproc (ARDOUR::Session *s, const std::string&); - boost::shared_ptr new_plugin_info (const std::string&, ARDOUR::PluginType); - boost::shared_ptr new_plugin (ARDOUR::Session *s, const std::string&, ARDOUR::PluginType, const std::string& preset = ""); + /** create a new Lua Processor (Plugin) + * + * @param s Session Handle + * @param p Identifier or Name of the Processor + * @returns Processor object (may be nil) + */ + boost::shared_ptr new_luaproc (ARDOUR::Session *s, const std::string& p); + + /** search a Plugin + * + * @param id Plugin Name, ID or URI + * @param type Plugin Type + * @returns PluginInfo or nil if not found + */ + boost::shared_ptr new_plugin_info (const std::string& id, ARDOUR::PluginType type); + + /** create a new Plugin Instance + * + * @param s Session Handle + * @param id Plugin Name, ID or URI + * @param type Plugin Type + * @returns Processor or nil + */ + boost::shared_ptr new_plugin (ARDOUR::Session *s, const std::string& id, ARDOUR::PluginType type, const std::string& preset = ""); + + /** set a plugin control-input parameter value + * + * @param proc Plugin-Processor + * @param which control-input to set (starting at 0) + * @param value value to set + * @returns true on success, false on error or out-of-bounds value + */ bool set_processor_param (boost::shared_ptr proc, uint32_t which, float val); + /** set a plugin control-input parameter value + * + * This is a wrapper around set_processor_param which looks up the Processor by plugin-insert. + * + * @param proc Plugin-Insert + * @param which control-input to set (starting at 0) + * @param value value to set + * @returns true on success, false on error or out-of-bounds value + */ bool set_plugin_insert_param (boost::shared_ptr pi, uint32_t which, float val); - /** - * OSC is kinda special, lo_address is a void* and lo_send() has varags - * and typed arguments which makes it hard to bind, even lo_cpp. +} } /* namespace */ + +namespace ARDOUR { namespace LuaOSC { + /** OSC transmitter + * + * A Class to send OSC messages. */ - class LuaOSCAddress { + class Address { + /* + * OSC is kinda special, lo_address is a void* and lo_send() has varags + * and typed arguments which makes it hard to bind, even lo_cpp. + */ public: - LuaOSCAddress (std::string uri) { + /** Construct a new OSC transmitter object + * @param uri the destination uri e.g. "osc.udp://localhost:7890" + */ + Address (std::string uri) { _addr = lo_address_new_from_url (uri.c_str()); } - ~LuaOSCAddress () { if (_addr) { lo_address_free (_addr); } } - int send (lua_State *L); + + ~Address () { if (_addr) { lo_address_free (_addr); } } + /** Transmit an OSC message + * + * Path (string) and type (string) must always be given. + * The number of following args must match the type. + * Supported types are: + * + * 'i': integer (lua number) + * + * 'f': float (lua number) + * + * 'd': double (lua number) + * + * 'h': 64bit integer (lua number) + * + * 's': string (lua string) + * + * 'c': character (lua string) + * + * 'T': boolean (lua bool) -- this is not implicily True, a lua true/false must be given + * + * 'F': boolean (lua bool) -- this is not implicily False, a lua true/false must be given + * + * @param lua: lua arguments: path, types, ... + * @returns boolean true if successful, false on error. + */ + int send (lua_State *lua); + private: lo_address _addr; }; diff --git a/libs/ardour/lua_api.cc b/libs/ardour/lua_api.cc index c8c1217bc2..855172278e 100644 --- a/libs/ardour/lua_api.cc +++ b/libs/ardour/lua_api.cc @@ -151,9 +151,9 @@ ARDOUR::LuaAPI::set_processor_param (boost::shared_ptr proc, uint32_t } int -ARDOUR::LuaAPI::LuaOSCAddress::send (lua_State *L) +ARDOUR::LuaOSC::Address::send (lua_State *L) { - LuaOSCAddress * const luaosc = luabridge::Userdata::get (L, 1, false); + Address * const luaosc = luabridge::Userdata::get
(L, 1, false); if (!luaosc) { return luaL_error (L, "Invalid pointer to OSC.Address"); } @@ -222,6 +222,6 @@ ARDOUR::LuaAPI::LuaOSCAddress::send (lua_State *L) int rv = lo_send_message (luaosc->_addr, path, msg); lo_message_free (msg); - luabridge::Stack::push (L, rv); + luabridge::Stack::push (L, (rv == 0)); return 1; } diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index ced3e9fcec..7e9dac8dbb 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -749,10 +749,10 @@ void LuaBindings::osc (lua_State* L) { luabridge::getGlobalNamespace (L) - .beginNamespace ("OSC") - .beginClass ("Address") + .beginNamespace ("LuaOSC") + .beginClass ("Address") .addConstructor () - .addCFunction ("send", &LuaAPI::LuaOSCAddress::send) + .addCFunction ("send", &LuaOSC::Address::send) .endClass () .endNamespace (); } diff --git a/scripts/osc_hook_example.lua b/scripts/osc_hook_example.lua index c204ed9a8e..4b1619bf0e 100644 --- a/scripts/osc_hook_example.lua +++ b/scripts/osc_hook_example.lua @@ -28,7 +28,7 @@ end function factory (params) return function (signal, ref, ...) local uri = params["unique"] or "osc.udp://localhost:7890" - local tx = OSC.Address (uri) + local tx = LuaOSC.Address (uri) -- debug print (stdout) -- print (signal, ref, ...) -- 2.30.2