From 76b2670f059a1ea54ea3e1597b660db317860491 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 25 Jan 2021 16:48:53 +0100 Subject: [PATCH] Towards variable-i/o VST3 #8549 --- libs/ardour/ardour/vst3_plugin.h | 6 ++ libs/ardour/vst3_plugin.cc | 111 +++++++++++++++++++++++++++---- 2 files changed, 105 insertions(+), 12 deletions(-) diff --git a/libs/ardour/ardour/vst3_plugin.h b/libs/ardour/ardour/vst3_plugin.h index 68a6f83b2f..06fa893578 100644 --- a/libs/ardour/ardour/vst3_plugin.h +++ b/libs/ardour/ardour/vst3_plugin.h @@ -180,6 +180,7 @@ public: void set_owner (ARDOUR::SessionObject* o); void enable_io (std::vector const&, std::vector const&); + void try_set_io (uint32_t in, uint32_t aux_in, uint32_t out); void process (float** ins, float** outs, uint32_t n_samples); @@ -335,8 +336,12 @@ public: bool parameter_is_input (uint32_t) const; bool parameter_is_output (uint32_t) const; + bool match_variable_io (ChanCount&, ChanCount&, ChanCount&); bool reconfigure_io (ChanCount, ChanCount, ChanCount); + ChanCount output_streams () const { return _configured_out; } + ChanCount input_streams () const { return _configured_in; } + uint32_t designated_bypass_port (); std::set automatable () const; @@ -423,6 +428,7 @@ public: PluginPtr load (Session& session); std::vector get_presets (bool user_only) const; bool is_instrument () const; + bool reconfigurable_io() const { return true; } boost::shared_ptr m; }; diff --git a/libs/ardour/vst3_plugin.cc b/libs/ardour/vst3_plugin.cc index 9b6f067870..278a8973ef 100644 --- a/libs/ardour/vst3_plugin.cc +++ b/libs/ardour/vst3_plugin.cc @@ -139,6 +139,20 @@ VST3Plugin::parameter_change_handler (VST3PI::ParameterChange t, uint32_t param, /* ***************************************************************************/ +bool +VST3Plugin::match_variable_io (ChanCount& in, ChanCount& aux_in, ChanCount& out) +{ + _plug->try_set_io (in.n_audio (), aux_in.n_audio (), out.n_audio ()); + + in.set_audio (_plug->n_audio_inputs (false)); + aux_in.set_audio (_plug->n_audio_aux_in ()); + out.set_audio (_plug->n_audio_outputs ()); + + in.set_midi (_plug->n_midi_inputs ()); + out.set_midi (_plug->n_midi_outputs ()); + return true; +} + bool VST3Plugin::reconfigure_io (ChanCount in, ChanCount aux_in, ChanCount out) { @@ -146,10 +160,8 @@ VST3Plugin::reconfigure_io (ChanCount in, ChanCount aux_in, ChanCount out) _configured_in = in + aux_in; _configured_out = out; -#if 0 _info->n_inputs = in; _info->n_outputs = out; -#endif /* apply new portlayout */ _connected_inputs.clear (); @@ -161,16 +173,6 @@ VST3Plugin::reconfigure_io (ChanCount in, ChanCount aux_in, ChanCount out) for (uint32_t i = 0; i < _configured_out.n_audio (); ++i) { _connected_outputs.push_back (true); } - -#if 1 - while (_connected_inputs.size () < _plug->n_audio_inputs ()) { - _connected_inputs.push_back (false); - } - while (_connected_outputs.size () < _plug->n_audio_outputs ()) { - _connected_outputs.push_back (false); - } -#endif - /* pre-configure from GUI thread */ _plug->enable_io (_connected_inputs, _connected_outputs); @@ -1951,6 +1953,91 @@ VST3PI::set_event_bus_state (bool enable) } } +void +VST3PI::try_set_io (uint32_t in, uint32_t aux_in, uint32_t out) +{ + /* Try to set (host => plug-in) a wanted arrangement for inputs and outputs. + * The host should always deliver the same number of input and output busses than the plug-in needs (see IComponent::getBusCount). + * The plug-in has 3 possibilities to react on this setBusArrangements call: + * + * - The plug-in accepts these arrangements, then it should modify, if needed, its busses to match these new arrangements + * (later on asked by the host with IComponent::getBusInfo () or IAudioProcessor::getBusArrangement ()) and then should return kResultTrue. + * + * - The plug-in does not accept or support these requested arrangements for all inputs/outputs or just for some or only one bus, + * but the plug-in can try to adapt its current arrangements according to the requested ones (requested arrangements for kMain busses + * should be handled with more priority than the ones for kAux busses), then it should modify its busses arrangements and should return kResultFalse. + * + * - Same than the point 2 above the plug-in does not support these requested arrangements but the plug-in cannot find corresponding arrangements, + * the plug-in could keep its current arrangement or fall back to a default arrangement by modifying its busses arrangements and should return kResultFalse. + */ + + std::vector sa_in; + std::vector sa_out; + + if (_n_bus_in < 2 ) { + in += aux_in; + } + + Vst::SpeakerArrangement sa = 0; + for (uint32_t i = 0; i < in; ++i) { + sa |= (uint64_t)1 << i; + } + if (_n_bus_in > 0) { + sa_in.push_back (sa); + } + + if (_n_bus_in > 1) { + sa = 0; + for (uint32_t i = 0; i < aux_in; ++i) { + sa |= (uint64_t)1 << i; + } + sa_in.push_back (sa); + } + + /* disable remaining input busses and set their speaker-count to zero */ + while (sa_in.size () < _n_bus_in) { + sa_in.push_back (0); + } + + /* try to max-out outs and aux-outs, but disable remaining output busses */ + sa = 0; + for (uint32_t i = 0; i < out; ++i) { + sa |= (uint64_t)1 << i; + } + while (sa_out.size () < _n_bus_out) { + sa_out.push_back (sa_out.size () < 2 ? sa : 0); + } + + DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::try_set_io: setBusArrangements ins = %1 outs = %2\n", sa_in.size (), sa_out.size ())); + tresult rv = _processor->setBusArrangements (sa_in.size () > 0 ? &sa_in[0] : NULL, sa_in.size (), + sa_out.size () > 0 ? &sa_out[0] : NULL, sa_out.size ()); + + printf ("VST3PI::try_set_io: %d\n", rv); + + update_channelcount (); + + int32 n_bus_in = _component->getBusCount (Vst::kAudio, Vst::kInput); + Vst::SpeakerArrangement arr; + + if (n_bus_in > 0) { + if (_processor->getBusArrangement (Vst::kInput, Vst::kMain, arr) == kResultOk) { + int cc = Vst::SpeakerArr::getChannelCount (arr); + std::cerr << "VST3: Input BusArrangements: " << Vst::kMain << " chan: " << cc << " bits: " << arr << "\n"; + std::cerr << "VST3: overriding n_inputs: from: " << _n_inputs << " to: " << cc << "\n"; + _n_inputs = cc; + } + } + + if (n_bus_in > 1) { + if (_processor->getBusArrangement (Vst::kInput, Vst::kAux, arr) == kResultOk) { + int cc = Vst::SpeakerArr::getChannelCount (arr); + std::cerr << "VST3: Input BusArrangements: " << Vst::kAux << " chan: " << cc << " bits: " << arr << "\n"; + std::cerr << "VST3: overriding n_aux_inputs: from: " << _n_aux_inputs << " to: " << cc << "\n"; + _n_aux_inputs = cc; + } + } +} + void VST3PI::enable_io (std::vector const& ins, std::vector const& outs) {