1
0
Fork 0

Report at least a channel output bus for VST3

Bitwig just doesn't call the process function if plugins have no audio
IO.
This commit is contained in:
Robbert van der Helm 2022-05-26 12:36:57 +02:00
parent 7fce56d863
commit 7eee0b032e

View file

@ -86,6 +86,11 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
type_: vst3_sys::vst::MediaType, type_: vst3_sys::vst::MediaType,
dir: vst3_sys::vst::BusDirection, dir: vst3_sys::vst::BusDirection,
) -> i32 { ) -> i32 {
// HACK: Bitwig will not call the process function at all if the plugin does not have any
// audio IO, so we'll add a zero channel output to work around this if that is the
// case
let no_main_audio_io = P::DEFAULT_NUM_INPUTS == 0 && P::DEFAULT_NUM_OUTPUTS == 0;
// A plugin has a main input and output bus if the default number of channels is non-zero, // A plugin has a main input and output bus if the default number of channels is non-zero,
// and a plugin can also have auxiliary input and output busses // and a plugin can also have auxiliary input and output busses
match type_ { match type_ {
@ -103,8 +108,12 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
let main_busses = if P::DEFAULT_NUM_OUTPUTS > 0 { 1 } else { 0 }; let main_busses = if P::DEFAULT_NUM_OUTPUTS > 0 { 1 } else { 0 };
let aux_busses = P::DEFAULT_AUX_OUTPUTS.unwrap_or_default().num_busses as i32; let aux_busses = P::DEFAULT_AUX_OUTPUTS.unwrap_or_default().num_busses as i32;
if no_main_audio_io {
1
} else {
main_busses + aux_busses main_busses + aux_busses
} }
}
x if x == vst3_sys::vst::MediaTypes::kEvent as i32 x if x == vst3_sys::vst::MediaTypes::kEvent as i32
&& dir == vst3_sys::vst::BusDirections::kInput as i32 && dir == vst3_sys::vst::BusDirections::kInput as i32
&& P::MIDI_INPUT >= MidiConfig::Basic => && P::MIDI_INPUT >= MidiConfig::Basic =>
@ -130,6 +139,11 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
) -> tresult { ) -> tresult {
check_null_ptr!(info); check_null_ptr!(info);
// HACK: Bitwig will not call the process function at all if the plugin does not have any
// audio IO, so we'll add a zero channel output to work around this if that is the
// case
let no_main_audio_io = P::DEFAULT_NUM_INPUTS == 0 && P::DEFAULT_NUM_OUTPUTS == 0;
match (type_, dir, index) { match (type_, dir, index) {
(t, _, _) if t == vst3_sys::vst::MediaTypes::kAudio as i32 => { (t, _, _) if t == vst3_sys::vst::MediaTypes::kAudio as i32 => {
*info = mem::zeroed(); *info = mem::zeroed();
@ -174,7 +188,7 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
let aux_outputs_only = let aux_outputs_only =
P::DEFAULT_NUM_OUTPUTS == 0 && P::DEFAULT_AUX_OUTPUTS.is_some(); P::DEFAULT_NUM_OUTPUTS == 0 && P::DEFAULT_AUX_OUTPUTS.is_some();
let aux_output_start_idx = if aux_outputs_only { 0 } else { 1 }; let aux_output_start_idx = if aux_outputs_only { 0 } else { 1 };
if !aux_outputs_only && index == 0 { if (!aux_outputs_only || no_main_audio_io) && index == 0 {
info.bus_type = vst3_sys::vst::BusTypes::kMain as i32; info.bus_type = vst3_sys::vst::BusTypes::kMain as i32;
info.channel_count = bus_config.num_output_channels as i32; info.channel_count = bus_config.num_output_channels as i32;
u16strlcpy(&mut info.name, "Output"); u16strlcpy(&mut info.name, "Output");
@ -285,6 +299,11 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
index: i32, index: i32,
_state: vst3_sys::base::TBool, _state: vst3_sys::base::TBool,
) -> tresult { ) -> tresult {
// HACK: Bitwig will not call the process function at all if the plugin does not have any
// audio IO, so we'll add a zero channel output to work around this if that is the
// case
let no_main_audio_io = P::DEFAULT_NUM_INPUTS == 0 && P::DEFAULT_NUM_OUTPUTS == 0;
// We don't need any special handling here // We don't need any special handling here
match (type_, dir, index) { match (type_, dir, index) {
(t, d, _) (t, d, _)
@ -304,7 +323,11 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
if t == vst3_sys::vst::MediaTypes::kAudio as i32 if t == vst3_sys::vst::MediaTypes::kAudio as i32
&& d == vst3_sys::vst::BusDirections::kOutput as i32 => && d == vst3_sys::vst::BusDirections::kOutput as i32 =>
{ {
let main_busses = if P::DEFAULT_NUM_OUTPUTS > 0 { 1 } else { 0 }; let main_busses = if P::DEFAULT_NUM_OUTPUTS > 0 || no_main_audio_io {
1
} else {
0
};
let aux_busses = P::DEFAULT_AUX_OUTPUTS.unwrap_or_default().num_busses as i32; let aux_busses = P::DEFAULT_AUX_OUTPUTS.unwrap_or_default().num_busses as i32;
if (0..main_busses + aux_busses).contains(&index) { if (0..main_busses + aux_busses).contains(&index) {
@ -699,6 +722,11 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
) -> tresult { ) -> tresult {
check_null_ptr!(inputs, outputs); check_null_ptr!(inputs, outputs);
// HACK: Bitwig will not call the process function at all if the plugin does not have any
// audio IO, so we'll add a zero channel output to work around this if that is the
// case
let no_main_audio_io = P::DEFAULT_NUM_INPUTS == 0 && P::DEFAULT_NUM_OUTPUTS == 0;
// Why are these signed integers again? // Why are these signed integers again?
if num_ins < 0 || num_outs < 0 { if num_ins < 0 || num_outs < 0 {
return kInvalidArgument; return kInvalidArgument;
@ -732,14 +760,14 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
} }
let aux_outputs_only = P::DEFAULT_NUM_OUTPUTS == 0 && P::DEFAULT_AUX_OUTPUTS.is_some(); let aux_outputs_only = P::DEFAULT_NUM_OUTPUTS == 0 && P::DEFAULT_AUX_OUTPUTS.is_some();
let num_output_channels = if aux_outputs_only || num_ins < 1 { let num_output_channels = if (aux_outputs_only && !no_main_audio_io) || num_outs < 1 {
0 0
} else { } else {
(*outputs).count_ones() (*outputs).count_ones()
}; };
let aux_output_start_idx = if aux_outputs_only { 0 } else { 1 }; let aux_output_start_idx = if aux_outputs_only { 0 } else { 1 };
let num_aux_output_busses = (num_ins as u32).saturating_sub(aux_output_start_idx); let num_aux_output_busses = (num_outs as u32).saturating_sub(aux_output_start_idx);
let num_aux_output_channels = if num_aux_output_busses == 0 { let num_aux_output_channels = if num_aux_output_busses == 0 {
0 0
} else { } else {
@ -788,6 +816,11 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
) -> tresult { ) -> tresult {
check_null_ptr!(arr); check_null_ptr!(arr);
// HACK: Bitwig will not call the process function at all if the plugin does not have any
// audio IO, so we'll add a zero channel output to work around this if that is the
// case
let no_main_audio_io = P::DEFAULT_NUM_INPUTS == 0 && P::DEFAULT_NUM_OUTPUTS == 0;
let channel_count_to_map = |count| match count { let channel_count_to_map = |count| match count {
0 => vst3_sys::vst::kEmpty, 0 => vst3_sys::vst::kEmpty,
1 => vst3_sys::vst::kMono, 1 => vst3_sys::vst::kMono,
@ -822,7 +855,7 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
} else if dir == vst3_sys::vst::BusDirections::kOutput as i32 { } else if dir == vst3_sys::vst::BusDirections::kOutput as i32 {
let aux_outputs_only = P::DEFAULT_NUM_OUTPUTS == 0 && P::DEFAULT_AUX_OUTPUTS.is_some(); let aux_outputs_only = P::DEFAULT_NUM_OUTPUTS == 0 && P::DEFAULT_AUX_OUTPUTS.is_some();
let aux_output_start_idx = if aux_outputs_only { 0 } else { 1 }; let aux_output_start_idx = if aux_outputs_only { 0 } else { 1 };
if !aux_outputs_only && index == 0 { if (!aux_outputs_only || no_main_audio_io) && index == 0 {
bus_config.num_output_channels bus_config.num_output_channels
} else if (aux_output_start_idx } else if (aux_output_start_idx
..(aux_output_start_idx + bus_config.aux_output_busses.num_busses as i32)) ..(aux_output_start_idx + bus_config.aux_output_busses.num_busses as i32))