X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fplugin_insert.cc;h=eebd07a2c5e55ab5aecfe6c2ca0cb4dcda5c8f88;hb=db2a55f88a1fe849d57ead54288a78501aa9bda1;hp=250eaae11e856de0bcd0650a02affccd9dc0b963;hpb=4aa4b803eee7392124a53d1392cb53e7a9c0317b;p=ardour.git diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index 250eaae11e..eebd07a2c5 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -79,6 +79,10 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr plug) if (plug) { add_plugin (plug); create_automatable_parameters (); + const ChanCount& sc (sidechain_input_pins ()); + if (sc.n_total () > 0) { + add_sidechain (sc.n_audio ()); + } } } @@ -290,15 +294,31 @@ PluginInsert::internal_input_streams() const ChanCount PluginInsert::natural_output_streams() const { +#ifdef MIXBUS + if (is_channelstrip ()) { + return _configured_out; + } +#endif return _plugins[0]->get_info()->n_outputs; } ChanCount PluginInsert::natural_input_streams() const { +#ifdef MIXBUS + if (is_channelstrip ()) { + return _configured_in; + } +#endif return _plugins[0]->get_info()->n_inputs; } +ChanCount +PluginInsert::sidechain_input_pins() const +{ + return _cached_sidechain_pins; +} + bool PluginInsert::has_no_inputs() const { @@ -530,7 +550,7 @@ PluginInsert::connect_and_run (BufferSet& bufs, pframes_t nframes, framecnt_t of } #ifdef MIXBUS - if (_plugins.front()->is_channelstrip() ) { + if (is_channelstrip ()) { if (_configured_in.n_audio() > 0) { ChanMapping mb_in_map (ChanCount::min (_configured_in, ChanCount (DataType::AUDIO, 2))); ChanMapping mb_out_map (ChanCount::min (_configured_out, ChanCount (DataType::AUDIO, 2))); @@ -687,7 +707,7 @@ PluginInsert::silence (framecnt_t nframes) ChanMapping in_map (natural_input_streams ()); ChanMapping out_map (natural_output_streams ()); - // TODO fake run sidechain, too? (maybe once it has meters) + // TODO run sidechain (delaylines) for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { (*i)->connect_and_run (_session.get_scratch_buffers ((*i)->get_info()->n_inputs, true), in_map, out_map, nframes, 0); } @@ -700,7 +720,8 @@ PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame /* run as normal if we are active or moving from inactive to active */ if (_sidechain) { - // collect sidechain input for complete cycle. + // collect sidechain input for complete cycle (!) + // TODO we need delaylines here for latency compensation _sidechain->run (bufs, start_frame, end_frame, nframes, true); } @@ -984,12 +1005,30 @@ PluginInsert::output_map () const bool PluginInsert::has_midi_bypass () const { - if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1 && natural_output_streams ().n_midi () == 0) { + if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1 + && natural_output_streams ().n_midi () == 0) { return true; } return false; } +bool +PluginInsert::has_midi_thru () const +{ + if (_configured_in.n_midi () == 1 && _configured_out.n_midi () == 1 + && natural_input_streams ().n_midi () == 0 && natural_output_streams ().n_midi () == 0) { + return true; + } + return false; +} + +#ifdef MIXBUS +bool +PluginInsert::is_channelstrip () const { + return _plugins.front()->is_channelstrip(); +} +#endif + bool PluginInsert::sanitize_maps () { @@ -1057,26 +1096,39 @@ PluginInsert::reset_map (bool emit) _in_map.clear (); _out_map.clear (); for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i, ++pc) { + ChanCount ns_inputs = natural_input_streams() - sidechain_input_pins (); if (_match.method == Split) { _in_map[pc] = ChanMapping (); - /* connect inputs in round-robin fashion */ + /* connect no sidechain sinks in round-robin fashion */ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - const uint32_t cend = _configured_internal.get (*t); + const uint32_t cend = _configured_in.get (*t); if (cend == 0) { continue; } uint32_t c = 0; - for (uint32_t in = 0; in < natural_input_streams().get (*t); ++in) { + for (uint32_t in = 0; in < ns_inputs.get (*t); ++in) { _in_map[pc].set (*t, in, c); - c = c + 1 % cend; + c = (c + 1) % cend; } } } else { - _in_map[pc] = ChanMapping (ChanCount::min (natural_input_streams (), _configured_internal)); + _in_map[pc] = ChanMapping (ChanCount::min (ns_inputs, _configured_in)); } _out_map[pc] = ChanMapping (ChanCount::min (natural_output_streams(), _configured_out)); for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - _in_map[pc].offset_to(*t, pc * natural_input_streams().get(*t)); + const uint32_t nis = natural_input_streams ().get(*t); + const uint32_t stride = nis - sidechain_input_pins().get (*t); + _in_map[pc].offset_to(*t, stride * pc); _out_map[pc].offset_to(*t, pc * natural_output_streams().get(*t)); + + // connect side-chains + const uint32_t sc_start = _configured_in.get (*t); + const uint32_t sc_len = _configured_internal.get (*t) - sc_start; + if (sc_len == 0) { continue; } + uint32_t c = 0; + for (uint32_t in = ns_inputs.get (*t); in < nis; ++in) { + _in_map[pc].set (*t, in, sc_start + c); + c = (c + 1) % sc_len; + } } } sanitize_maps (); @@ -1187,6 +1239,9 @@ PluginInsert::configure_io (ChanCount in, ChanCount out) } else if (_match.custom_cfg && _configured) { mapping_changed = sanitize_maps (); } else { +#ifdef MIXBUS + if (is_channelstrip ()) { _maps_from_state = false; } +#endif if (_maps_from_state) { _maps_from_state = false; mapping_changed = true; @@ -1283,6 +1338,13 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC return Match(); } +#ifdef MIXBUS + if (is_channelstrip ()) { + out = inx; + return Match (ExactMatch, 1); + } +#endif + /* if a user specified a custom cfg, so be it. */ if (_custom_cfg) { out = _custom_out; @@ -1317,17 +1379,15 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC * at least enough to feed every output port. */ uint32_t f = 1; // at least one. e.g. control data filters, no in, no out. for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - uint32_t nin = inputs.get (*t); - if (nin == 0 || inx.get(*t) == 0) { continue; } - f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin)); + uint32_t nout = outputs.get (*t); + if (nout == 0 || inx.get(*t) == 0) { continue; } + f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nout)); } out = inx; DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("special case strict-i/o generator: %1\n", name())); return Match (Replicate, f, _strict_io); } break; - case Split: - break; default: break; } @@ -1340,16 +1400,19 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC return m; } + ChanCount ns_inputs = inputs - sidechain_input_pins (); + DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("resolving 'Impossible' match for %1\n", name())); if (info->reconfigurable_io()) { ChanCount useins; + // TODO add sidechains here bool const r = _plugins.front()->can_support_io_configuration (inx, out, &useins); if (!r) { // houston, we have a problem. return Match (Impossible, 0); } - return Match (Delegate, 1); + return Match (Delegate, 1, _strict_io); } ChanCount midi_bypass; @@ -1357,10 +1420,10 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC midi_bypass.set (DataType::MIDI, 1); } - // add at least as many plugins so that output count matches input count + // add at least as many plugins so that output count matches input count (w/o sidechain pins) uint32_t f = 0; for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - uint32_t nin = inputs.get (*t); + uint32_t nin = ns_inputs.get (*t); uint32_t nout = outputs.get (*t); if (nin == 0 || inx.get(*t) == 0) { continue; } // prefer floor() so the count won't overly increase IFF (nin < nout) @@ -1368,7 +1431,19 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC } if (f > 0 && outputs * f >= _configured_out) { out = outputs * f + midi_bypass; - return Match (Replicate, f); + return Match (Replicate, f, _strict_io); + } + + // add at least as many plugins needed to connect all inputs (w/o sidechain pins) + f = 0; + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + uint32_t nin = ns_inputs.get (*t); + if (nin == 0 || inx.get(*t) == 0) { continue; } + f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin)); + } + if (f > 0) { + out = outputs * f + midi_bypass; + return Match (Replicate, f, _strict_io); } // add at least as many plugins needed to connect all inputs @@ -1379,7 +1454,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanC f = max (f, (uint32_t) ceil (inx.get(*t) / (float)nin)); } out = outputs * f + midi_bypass; - return Match (Replicate, f); + return Match (Replicate, f, _strict_io); } /* this is the original Ardour 3/4 behavior, mainly for backwards compatibility */ @@ -1405,6 +1480,7 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha ChanCount inputs = info->n_inputs; ChanCount outputs = info->n_outputs; + ChanCount ns_inputs = inputs - sidechain_input_pins (); if (in.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) { DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("bypassing midi-data around %1\n", name())); @@ -1415,6 +1491,9 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha in.set(DataType::MIDI, 0); } + // add internally provided sidechain ports + ChanCount insc = in + sidechain_input_ports (); + bool no_inputs = true; for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { if (inputs.get (*t) != 0) { @@ -1429,8 +1508,14 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha return Match (NoInputs, 1); } - /* Plugin inputs match requested inputs exactly */ - if (inputs == in) { + /* Plugin inputs match requested inputs + side-chain-ports exactly */ + if (inputs == insc) { + out = outputs + midi_bypass; + return Match (ExactMatch, 1); + } + + /* Plugin inputs matches without side-chain-pins */ + if (ns_inputs == in) { out = outputs + midi_bypass; return Match (ExactMatch, 1); } @@ -1443,9 +1528,10 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha uint32_t f = 0; bool can_replicate = true; - for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + for (DataType::iterator t = DataType::begin(); t != DataType::end() && can_replicate; ++t) { - uint32_t nin = inputs.get (*t); + // ignore side-chains + uint32_t nin = ns_inputs.get (*t); // No inputs of this type if (nin == 0 && in.get(*t) == 0) { @@ -1488,7 +1574,7 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha bool can_split = true; for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - bool const can_split_type = (in.get (*t) == 1 && inputs.get (*t) > 1); + bool const can_split_type = (in.get (*t) == 1 && ns_inputs.get (*t) > 1); bool const nothing_to_do_for_type = (in.get (*t) == 0 && inputs.get (*t) == 0); if (!can_split_type && !nothing_to_do_for_type) { @@ -2175,14 +2261,23 @@ PluginInsert::add_plugin (boost::shared_ptr plugin) plugin->set_insert_id (this->id()); if (_plugins.empty()) { - /* first (and probably only) plugin instance - connect to relevant signals - */ + /* first (and probably only) plugin instance - connect to relevant signals */ plugin->ParameterChangedExternally.connect_same_thread (*this, boost::bind (&PluginInsert::parameter_changed_externally, this, _1, _2)); - plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1)); - plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1)); + plugin->StartTouch.connect_same_thread (*this, boost::bind (&PluginInsert::start_touch, this, _1)); + plugin->EndTouch.connect_same_thread (*this, boost::bind (&PluginInsert::end_touch, this, _1)); + // cache sidechain ports + _cached_sidechain_pins.reset (); + const ChanCount& nis (plugin->get_info()->n_inputs); + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + for (uint32_t in = 0; in < nis.get (*t); ++in) { + const Plugin::IOPortDescription& iod (plugin->describe_io_port (*t, true, in)); + if (iod.is_sidechain) { + _cached_sidechain_pins.set (*t, 1 + _cached_sidechain_pins.n(*t)); + } + } + } } - _plugins.push_back (plugin); }