prototype support for arbitrary plugin channel maps

This commit is contained in:
Robin Gareus 2016-03-26 01:03:46 +01:00
parent 0954efffd3
commit 1503db4a28
3 changed files with 124 additions and 12 deletions

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

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

View 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 ();
}
}
}