VST3: support VST I/O busses
This unconditionally enable all busses with connected pins. It does not provide re/configurable I/O (like Audio Unit), nor implement dynamic Vst::kIoChanged callbacks. But regardless this allows for plugins with multiple I/O busses (e.g. drum synths).
This commit is contained in:
parent
0063211b4e
commit
1cbd2d3468
@ -133,8 +133,21 @@ public:
|
||||
|
||||
ARDOUR::Plugin::IOPortDescription describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const;
|
||||
|
||||
uint32_t n_audio_inputs () const;
|
||||
uint32_t n_audio_outputs () const;
|
||||
uint32_t n_audio_inputs (bool with_aux = true) const;
|
||||
uint32_t n_audio_outputs (bool with_aux = true) const;
|
||||
|
||||
uint32_t n_audio_aux_in () const { return _n_aux_inputs; }
|
||||
uint32_t n_audio_aux_out () const { return _n_aux_outputs; }
|
||||
|
||||
struct AudioBusInfo {
|
||||
AudioBusInfo (Vst::BusType t, int32_t c) : type (t), n_chn (c) {}
|
||||
AudioBusInfo () : type (Vst::kMain), n_chn (0) {}
|
||||
Vst::BusType type;
|
||||
int32_t n_chn;
|
||||
};
|
||||
|
||||
std::map<int, AudioBusInfo> const& bus_info_in () const { return _bus_info_in; }
|
||||
std::map<int, AudioBusInfo> const& bus_info_out () const { return _bus_info_out; }
|
||||
|
||||
/* MIDI/Event interface */
|
||||
void cycle_start ();
|
||||
@ -295,6 +308,13 @@ private:
|
||||
std::vector<Vst::AudioBusBuffers> _busbuf_in;
|
||||
std::vector<Vst::AudioBusBuffers> _busbuf_out;
|
||||
|
||||
/* cache channels/bus Vst::AudioBusBuffers::numChannels */
|
||||
std::map<int, int> _n_buschn_in;
|
||||
std::map<int, int> _n_buschn_out;
|
||||
|
||||
std::map<int, AudioBusInfo> _bus_info_in;
|
||||
std::map<int, AudioBusInfo> _bus_info_out;
|
||||
|
||||
int _n_inputs;
|
||||
int _n_outputs;
|
||||
int _n_aux_inputs;
|
||||
|
@ -1635,15 +1635,6 @@ VST3PI::count_channels (Vst::MediaType media, Vst::BusDirection dir, Vst::BusTyp
|
||||
for (int32 i = 0; i < n_busses; ++i) {
|
||||
Vst::BusInfo bus;
|
||||
if (_component->getBusInfo (media, dir, i, bus) == kResultTrue && bus.busType == type) {
|
||||
#if 1
|
||||
if ((type == Vst::kMain && i != 0) || (type == Vst::kAux && i != 1)) {
|
||||
/* For now allow we only support one main bus, and one aux-bus.
|
||||
* Also an aux-bus by itself is currently N/A.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string bus_name = tchar_to_utf8 (bus.name);
|
||||
bool is_sidechain = (type == Vst::kAux) && (dir == Vst::kInput);
|
||||
|
||||
@ -1670,6 +1661,12 @@ VST3PI::count_channels (Vst::MediaType media, Vst::BusDirection dir, Vst::BusTyp
|
||||
_io_name[media][dir].push_back (Plugin::IOPortDescription (channel_name, is_sidechain, bus_name, j, i));
|
||||
}
|
||||
n_channels += bus.channelCount;
|
||||
|
||||
if (dir == Vst::kInput) {
|
||||
_bus_info_in.insert (std::make_pair(i, AudioBusInfo (type, bus.channelCount)));
|
||||
} else {
|
||||
_bus_info_out.insert (std::make_pair(i, AudioBusInfo (type, bus.channelCount)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1751,15 +1748,15 @@ VST3PI::print_parameter (Vst::ParamID id, Vst::ParamValue value) const
|
||||
}
|
||||
|
||||
uint32_t
|
||||
VST3PI::n_audio_inputs () const
|
||||
VST3PI::n_audio_inputs (bool with_aux) const
|
||||
{
|
||||
return _n_inputs + _n_aux_inputs;
|
||||
return _n_inputs + (with_aux ? _n_aux_inputs : 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
VST3PI::n_audio_outputs () const
|
||||
VST3PI::n_audio_outputs (bool with_aux) const
|
||||
{
|
||||
return _n_outputs + _n_aux_outputs;
|
||||
return _n_outputs + (with_aux ? _n_aux_outputs : 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@ -2035,75 +2032,35 @@ VST3PI::enable_io (std::vector<bool> const& ins, std::vector<bool> const& outs)
|
||||
VSTSpeakerArrangements sa_in;
|
||||
VSTSpeakerArrangements sa_out;
|
||||
|
||||
bool enable = false;
|
||||
Vst::SpeakerArrangement sa = 0;
|
||||
size_t cnt = 0;
|
||||
|
||||
for (int i = 0; i < _n_inputs; ++i) {
|
||||
if (ins[i]) {
|
||||
enable = true;
|
||||
}
|
||||
sa |= (uint64_t)1 << i;
|
||||
}
|
||||
if (_n_inputs > 0) {
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kInput, 0, %1)\n", enable));
|
||||
_component->activateBus (Vst::kAudio, Vst::kInput, 0, enable);
|
||||
sa_in.push_back (sa);
|
||||
}
|
||||
|
||||
enable = false;
|
||||
sa = 0;
|
||||
for (int i = 0; i < _n_aux_inputs; ++i) {
|
||||
if (ins[i + _n_inputs]) {
|
||||
enable = true;
|
||||
}
|
||||
sa |= (uint64_t)1 << i;
|
||||
}
|
||||
if (_n_aux_inputs > 0) {
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kInput, 1, %1)\n", enable));
|
||||
_component->activateBus (Vst::kAudio, Vst::kInput, 1, enable);
|
||||
sa_in.push_back (sa);
|
||||
}
|
||||
|
||||
/* disable remaining input busses and set their speaker-count to zero */
|
||||
while (sa_in.size () < (VSTSpeakerArrangements::size_type) _n_bus_in) {
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kInput, %1, false)\n", sa_in.size ()));
|
||||
_component->activateBus (Vst::kAudio, Vst::kInput, sa_in.size (), false);
|
||||
sa_in.push_back (0);
|
||||
}
|
||||
|
||||
enable = false;
|
||||
sa = 0;
|
||||
for (int i = 0; i < _n_outputs; ++i) {
|
||||
if (outs[i]) {
|
||||
enable = true;
|
||||
bool enable = false;
|
||||
Vst::SpeakerArrangement sa = 0;
|
||||
for (int i = 0; i < _bus_info_in[sa_in.size ()].n_chn; ++i) {
|
||||
if (ins[cnt++]) {
|
||||
sa |= (uint64_t)1 << i;
|
||||
enable = true;
|
||||
}
|
||||
}
|
||||
sa |= (uint64_t)1 << i;
|
||||
}
|
||||
|
||||
if (_n_outputs > 0) {
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kOutput, 0, %1)\n", enable));
|
||||
_component->activateBus (Vst::kAudio, Vst::kOutput, 0, enable);
|
||||
sa_out.push_back (sa);
|
||||
}
|
||||
|
||||
enable = false;
|
||||
sa = 0;
|
||||
for (int i = 0; i < _n_aux_outputs; ++i) {
|
||||
if (outs[i + _n_outputs]) {
|
||||
enable = true;
|
||||
}
|
||||
sa |= (uint64_t)1 << i;
|
||||
}
|
||||
if (_n_aux_outputs > 0) {
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kOutput, 1, %1)\n", enable));
|
||||
_component->activateBus (Vst::kAudio, Vst::kOutput, 1, enable);
|
||||
sa_out.push_back (sa);
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kInput, %1, %2)\n", sa_in.size (), enable));
|
||||
_component->activateBus (Vst::kAudio, Vst::kInput, sa_in.size (), enable);
|
||||
sa_in.push_back (sa);
|
||||
}
|
||||
|
||||
cnt = 0;
|
||||
while (sa_out.size () < (VSTSpeakerArrangements::size_type) _n_bus_out) {
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kOutput, %1, false)\n", sa_out.size ()));
|
||||
_component->activateBus (Vst::kAudio, Vst::kOutput, sa_out.size (), false);
|
||||
sa_out.push_back (0);
|
||||
bool enable = false;
|
||||
Vst::SpeakerArrangement sa = 0;
|
||||
for (int i = 0; i < _bus_info_out[sa_out.size ()].n_chn; ++i) {
|
||||
if (outs[cnt++]) {
|
||||
sa |= (uint64_t)1 << i;
|
||||
enable = true;
|
||||
}
|
||||
}
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: activateBus (kAudio, kOutput, %1, %2)\n", sa_out.size (), enable));
|
||||
_component->activateBus (Vst::kAudio, Vst::kOutput, sa_out.size (), enable);
|
||||
sa_out.push_back (sa);
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::VST3Config, string_compose ("VST3PI::enable_io: setBusArrangements ins = %1 outs = %2\n", sa_in.size (), sa_out.size ()));
|
||||
@ -2128,18 +2085,6 @@ VST3PI::enable_io (std::vector<bool> const& ins, std::vector<bool> const& outs)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32
|
||||
used_bus_count (int auxes, int inputs)
|
||||
{
|
||||
if (auxes > 0 && inputs > 0) {
|
||||
return 2;
|
||||
}
|
||||
if (auxes == 0 && inputs == 0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
VST3PI::process (float** ins, float** outs, uint32_t n_samples)
|
||||
{
|
||||
@ -2150,8 +2095,8 @@ VST3PI::process (float** ins, float** outs, uint32_t n_samples)
|
||||
data.numSamples = n_samples;
|
||||
data.processMode = AudioEngine::instance ()->freewheeling () ? Vst::kOffline : Vst::kRealtime;
|
||||
data.symbolicSampleSize = Vst::kSample32;
|
||||
data.numInputs = used_bus_count (_n_aux_inputs, _n_inputs); // _n_bus_in;
|
||||
data.numOutputs = used_bus_count (_n_aux_outputs, _n_outputs); // _n_bus_out;
|
||||
data.numInputs = _n_bus_in;
|
||||
data.numOutputs = _n_bus_out;
|
||||
data.inputs = inputs;
|
||||
data.outputs = outputs;
|
||||
|
||||
@ -2162,48 +2107,24 @@ VST3PI::process (float** ins, float** outs, uint32_t n_samples)
|
||||
data.inputParameterChanges = &_input_param_changes;
|
||||
data.outputParameterChanges = &_output_param_changes;
|
||||
|
||||
int used_ins = 0;
|
||||
int used_outs = 0;
|
||||
uint32_t used_ins = 0;
|
||||
uint32_t used_outs = 0;
|
||||
|
||||
if (_n_bus_in > 0) {
|
||||
inputs[0].silenceFlags = 0;
|
||||
inputs[0].numChannels = _n_inputs;
|
||||
inputs[0].channelBuffers32 = ins;
|
||||
++used_ins;
|
||||
}
|
||||
|
||||
if (_n_bus_in > 1 && _n_aux_inputs > 0) {
|
||||
inputs[1].silenceFlags = 0;
|
||||
inputs[1].numChannels = _n_aux_inputs;
|
||||
inputs[1].channelBuffers32 = &ins[_n_inputs];
|
||||
++used_ins;
|
||||
}
|
||||
|
||||
if (_n_bus_out > 0) {
|
||||
outputs[0].silenceFlags = 0;
|
||||
outputs[0].numChannels = _n_outputs;
|
||||
outputs[0].channelBuffers32 = outs;
|
||||
++used_outs;
|
||||
}
|
||||
|
||||
if (_n_bus_out > 1 && _n_aux_outputs > 0) {
|
||||
outputs[1].silenceFlags = 0;
|
||||
outputs[1].numChannels = _n_outputs;
|
||||
outputs[1].channelBuffers32 = &outs[_n_outputs];
|
||||
++used_outs;
|
||||
}
|
||||
|
||||
for (int i = used_ins; i < _n_bus_in; ++i) {
|
||||
for (int i = 0; i < _n_bus_in; ++i) {
|
||||
inputs[i].silenceFlags = 0;
|
||||
inputs[i].numChannels = 0;
|
||||
inputs[i].channelBuffers32 = 0;
|
||||
inputs[i].numChannels = _bus_info_in[i].n_chn;
|
||||
inputs[i].channelBuffers32 = &ins[used_ins];
|
||||
used_ins += _bus_info_in[i].n_chn;
|
||||
}
|
||||
|
||||
for (int i = used_outs; i < _n_bus_out; ++i) {
|
||||
for (int i = 0; i < _n_bus_out; ++i) {
|
||||
outputs[i].silenceFlags = 0;
|
||||
outputs[i].numChannels = 0;
|
||||
outputs[i].channelBuffers32 = 0;
|
||||
outputs[i].numChannels = _bus_info_out[i].n_chn;
|
||||
outputs[i].channelBuffers32 = &outs[used_outs];
|
||||
used_outs += _bus_info_out[i].n_chn;
|
||||
}
|
||||
assert (used_ins == n_audio_inputs ());
|
||||
assert (used_outs == n_audio_outputs ());
|
||||
|
||||
/* and go */
|
||||
if (_processor->process (data) != kResultOk) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Robin Gareus <robin@gareus.org>
|
||||
* Copyright (C) 2019-2023 Robin Gareus <robin@gareus.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -84,15 +84,6 @@ count_channels (Vst::IComponent* c, Vst::MediaType media, Vst::BusDirection dir,
|
||||
Vst::BusInfo bus;
|
||||
tresult rv = c->getBusInfo (media, dir, i, bus);
|
||||
if (rv == kResultTrue && bus.busType == type) {
|
||||
#if 1
|
||||
if ((type == Vst::kMain && i != 0) || (type == Vst::kAux && i != 1)) {
|
||||
/* For now allow we only support one main bus, and one aux-bus.
|
||||
* Also an aux-bus by itself is currently N/A.
|
||||
*/
|
||||
PBD::info << "VST3: \\ ignored bus: " << i << " type: " << fmt_type (bus.busType) << " count: " << bus.channelCount << endmsg;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (verbose) {
|
||||
PBD::info << "VST3: - bus: " << i << " count: " << bus.channelCount << endmsg;
|
||||
}
|
||||
@ -107,9 +98,7 @@ count_channels (Vst::IComponent* c, Vst::MediaType media, Vst::BusDirection dir,
|
||||
} else {
|
||||
n_channels += bus.channelCount;
|
||||
}
|
||||
} else if (verbose && rv == kResultTrue) {
|
||||
PBD::info << "VST3: \\ ignored bus: " << i << " mismatched type: " << fmt_type (bus.busType) << endmsg;
|
||||
} else if (verbose) {
|
||||
} else if (verbose && rv != kResultTrue) {
|
||||
PBD::info << "VST3: \\ error getting busInfo for bus: " << i << " rv: " << rv << ", got type: " << fmt_type (bus.busType) << endmsg;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user