prototype support for arbitrary plugin channel maps
authorRobin Gareus <robin@gareus.org>
Sat, 26 Mar 2016 00:03:46 +0000 (01:03 +0100)
committerRobin Gareus <robin@gareus.org>
Sat, 26 Mar 2016 00:03:46 +0000 (01:03 +0100)
libs/ardour/ardour/plugin_insert.h
libs/ardour/luabindings.cc
libs/ardour/plugin_insert.cc

index 453b9a0f0c62907e1633d309bc55acd2fc119b77..d9db98dee4ec2d6fb2f8d1299cc38f133a0eb31c 100644 (file)
@@ -69,6 +69,35 @@ class LIBARDOUR_API PluginInsert : public Processor
 
        int set_block_size (pframes_t nframes);
 
+       ChanMapping input_map (uint32_t num=0) const {
+               if (num < _in_map.size()) {
+                       return _in_map.find (num)->second;
+               } else {
+                       return ChanMapping ();
+               }
+       }
+
+       ChanMapping output_map (uint32_t num=0) const {
+               if (num < _out_map.size()) {
+                       return _out_map.find (num)->second;
+               } else {
+                       return ChanMapping ();
+               }
+       }
+
+#ifndef NDEBUG // prototyping -- this should be done synchroneously in configure_io()
+       void set_input_map (uint32_t num, ChanMapping m) {
+               if (num < _in_map.size()) {
+                       _in_map[num] = m;
+               }
+       }
+       void set_output_map (uint32_t num, ChanMapping m) {
+               if (num < _in_map.size()) {
+                       _out_map[num] = m;
+               }
+       }
+#endif
+
        ChanCount output_streams() const;
        ChanCount input_streams() const;
        ChanCount natural_output_streams() const;
@@ -143,6 +172,14 @@ class LIBARDOUR_API PluginInsert : public Processor
 
        void collect_signal_for_analysis (framecnt_t nframes);
 
+       bool no_inplace () const {
+               return _pending_no_inplace;
+       }
+
+       void set_no_inplace (bool b) {
+               _pending_no_inplace = b;
+       }
+
        void set_strict_io (bool b) {
                _strict_io = b;
        }
@@ -199,6 +236,8 @@ class LIBARDOUR_API PluginInsert : public Processor
        ChanCount _configured_in;
        ChanCount _configured_out;
 
+       bool _no_inplace;
+       bool _pending_no_inplace;
        bool _strict_io;
        bool _strict_io_configured;
 
index 1c8630790b88f46d19fe67c9dd074c92f567e9be..61e3f817a5e3f489a0e6f1e9656af2b707af67b5 100644 (file)
@@ -179,6 +179,13 @@ LuaBindings::common (lua_State* L)
                .endClass ()
                .endNamespace ()
 
+               .beginClass <ChanMapping> ("ChanMapping")
+               .addVoidConstructor ()
+               .addFunction ("get", static_cast<uint32_t(ChanMapping::*)(DataType, uint32_t)>(&ChanMapping::get))
+               .addFunction ("set", &ChanMapping::set)
+               .addConst ("Invalid", 4294967295) // UINT32_MAX
+               .endClass ()
+
                .beginNamespace ("Properties")
                // templated class definitions
                .beginClass <PBD::PropertyDescriptor<bool> > ("BoolProperty").endClass ()
@@ -344,7 +351,7 @@ LuaBindings::common (lua_State* L)
                .addFunction ("automation_control", (boost::shared_ptr<AutomationControl>(Automatable::*)(const Evoral::Parameter&, bool))&Automatable::automation_control)
                .endClass ()
 
-               .deriveWSPtrClass <Plugin, PBD::StatefulDestructible> ("PluginInsert")
+               .deriveWSPtrClass <Plugin, PBD::StatefulDestructible> ("Plugin")
                .addFunction ("label", &Plugin::label)
                .addFunction ("name", &Plugin::name)
                .addFunction ("maker", &Plugin::maker)
@@ -365,6 +372,14 @@ LuaBindings::common (lua_State* L)
                .addFunction ("deactivate", &PluginInsert::deactivate)
                .addFunction ("strict_io_configured", &PluginInsert::strict_io_configured)
                .addFunction ("set_strict_io", &PluginInsert::set_strict_io)
+               .addFunction ("no_inplace", &PluginInsert::no_inplace)
+               .addFunction ("input_map", &PluginInsert::input_map)
+               .addFunction ("output_map", &PluginInsert::output_map)
+#ifndef NDEBUG -- this is not safe, prototyping only
+               .addFunction ("set_no_inplace", &PluginInsert::set_no_inplace)
+               .addFunction ("set_input_map", &PluginInsert::set_input_map)
+               .addFunction ("set_output_map", &PluginInsert::set_output_map)
+#endif
                .endClass ()
 
                .deriveWSPtrClass <AutomationControl, Evoral::Control> ("AutomationControl")
@@ -633,12 +648,6 @@ LuaBindings::dsp (lua_State* L)
                .addFunction ("get_audio", static_cast<AudioBuffer&(BufferSet::*)(size_t)>(&BufferSet::get_audio))
                .addFunction ("count", static_cast<const ChanCount&(BufferSet::*)()const>(&BufferSet::count))
                .endClass()
-
-               .beginClass <ChanMapping> ("ChanMapping")
-               .addFunction ("get", static_cast<uint32_t(ChanMapping::*)(DataType, uint32_t)>(&ChanMapping::get))
-               .addFunction ("set", &ChanMapping::set)
-               .addConst ("Invalid", 4294967295) // UINT32_MAX
-               .endClass ()
                .endNamespace ();
 
        luabridge::getGlobalNamespace (L)
index cb386b940c06720d8279f89c3336ce9a5ec4d124..b174ceb2fe57ce67d32b669765ae38ab5d03a177 100644 (file)
@@ -68,6 +68,8 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
        : Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
        , _signal_analysis_collected_nframes(0)
        , _signal_analysis_collect_nframes_max(0)
+       , _no_inplace (false)
+       , _pending_no_inplace (false)
        , _strict_io (false)
        , _strict_io_configured (false)
 {
@@ -364,6 +366,7 @@ PluginInsert::flush ()
 void
 PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t offset, bool with_auto, framepos_t now)
 {
+       _no_inplace = _pending_no_inplace;
        // Calculate if, and how many frames we need to collect for analysis
        framecnt_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
                                             _signal_analysis_collected_nframes);
@@ -374,13 +377,13 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
        ChanCount const in_streams = input_streams ();
        ChanCount const out_streams = output_streams ();
 
-       bool valid;
        if (_match.method == Split) {
                assert (_in_map.size () == 1);
                /* fix the input mapping so that we have maps for each of the plugin's inputs */
 
                /* copy the first stream's buffer contents to the others */
                /* XXX: audio only */
+               bool valid;
                uint32_t first_idx = _in_map[0].get (DataType::AUDIO, 0, &valid);
                if (valid) {
                        for (uint32_t i = in_streams.n_audio(); i < natural_input_streams().n_audio(); ++i) {
@@ -444,10 +447,71 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of
 
        }
 
-       uint32_t pc = 0;
-       for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
-               if ((*i)->connect_and_run(bufs, _in_map[pc], _out_map[pc], nframes, offset)) {
-                       deactivate ();
+       if (_no_inplace) {
+               BufferSet& inplace_bufs  = _session.get_noinplace_buffers();
+
+               uint32_t pc = 0;
+               for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
+
+                       ARDOUR::ChanMapping in_map (natural_input_streams());
+                       ARDOUR::ChanMapping out_map;
+                       ARDOUR::ChanCount mapped;
+                       ARDOUR::ChanCount backmap;
+
+                       // map inputs sequentially
+                       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+                               for (uint32_t in = 0; in < natural_input_streams().get (*t); ++in) {
+                                       bool valid;
+                                       uint32_t in_idx = _in_map[pc].get (*t, in, &valid);
+                                       uint32_t m = mapped.get (*t);
+                                       if (valid) {
+                                               inplace_bufs.get (*t, m).read_from (bufs.get (*t, in_idx), nframes, offset, offset);
+                                       } else {
+                                               inplace_bufs.get (*t, m).silence (nframes, offset);
+                                       }
+                                       mapped.set (*t, m + 1);
+                               }
+                       }
+
+                       backmap = mapped;
+
+                       // map outputs
+                       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+                               for (uint32_t out = 0; out < natural_output_streams().get (*t); ++out) {
+                                       uint32_t m = mapped.get (*t);
+                                       inplace_bufs.get (*t, m).silence (nframes, offset);
+                                       out_map.set (*t, out, m);
+                                       mapped.set (*t, m + 1);
+                               }
+                       }
+
+                       if ((*i)->connect_and_run(inplace_bufs, in_map, out_map, nframes, offset)) {
+                               deactivate ();
+                       }
+
+                       // clear output buffers
+                       bufs.silence (nframes, offset);
+
+                       // copy back outputs
+                       for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+                               for (uint32_t out = 0; out < natural_output_streams().get (*t); ++out) {
+                                       uint32_t m = backmap.get (*t);
+                                       bool valid;
+                                       uint32_t out_idx = _out_map[pc].get (*t, out, &valid);
+                                       if (valid) {
+                                               bufs.get (*t, out_idx).read_from (inplace_bufs.get (*t, m), nframes, offset, offset);
+                                       }
+                                       backmap.set (*t, m + 1);
+                               }
+                       }
+               }
+
+       } else {
+               uint32_t pc = 0;
+               for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) {
+                       if ((*i)->connect_and_run(bufs, _in_map[pc], _out_map[pc], nframes, offset)) {
+                               deactivate ();
+                       }
                }
        }