1
0
Fork 0

Clear auxiliary output buffers at start of process

This prevents uninitialized data from lingering if the plugin doesn't
write to these buffers. Seen this happen in Bitwig.
This commit is contained in:
Robbert van der Helm 2022-05-29 14:07:13 +02:00
parent 87813fb9dc
commit 7a4e7b187a
2 changed files with 44 additions and 10 deletions

View file

@ -1693,6 +1693,28 @@ impl<P: ClapPlugin> Wrapper<P> {
// we'll process every incoming event.
let process = &*process;
// Before doing anything, clear out any auxiliary outputs since they may contain
// uninitialized data when the host assumes that we'll always write soemthing there
let current_bus_config = wrapper.current_bus_config.load();
let has_main_input = current_bus_config.num_input_channels > 0;
let has_main_output = current_bus_config.num_output_channels > 0;
if !process.audio_outputs.is_null() {
for output_idx in
if has_main_output { 1 } else { 0 }..process.audio_outputs_count as isize
{
let host_output = process.audio_outputs.offset(output_idx);
if !(*host_output).data32.is_null() {
for channel_idx in 0..(*host_output).channel_count as isize {
ptr::write_bytes(
*((*host_output).data32.offset(channel_idx)) as *mut f32,
0,
process.frames_count as usize,
);
}
}
}
}
// If `P::SAMPLE_ACCURATE_AUTOMATION` is set, then we'll split up the audio buffer into
// chunks whenever a parameter change occurs
let mut block_start = 0;
@ -1824,10 +1846,6 @@ impl<P: ClapPlugin> Wrapper<P> {
}
}
let current_bus_config = wrapper.current_bus_config.load();
let has_main_input = current_bus_config.num_input_channels > 0;
let has_main_output = current_bus_config.num_output_channels > 0;
// We'll need to do the same thing for auxiliary input sidechain buffers. Since we
// don't know whether overwriting the host's buffers is safe here or not, we'll copy
// the data to our own buffers instead. These buffers are only accessible through

View file

@ -1024,6 +1024,28 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
);
nih_debug_assert!(data.num_samples >= 0);
// Before doing anything, clear out any auxiliary outputs since they may contain
// uninitialized data when the host assumes that we'll always write soemthing there
let current_bus_config = self.inner.current_bus_config.load();
let has_main_input = current_bus_config.num_input_channels > 0;
// HACK: Bitwig requires VST3 plugins to always have a main output. We'll however still
// use this variable here to maintain consistency between the backends.
let has_main_output = true;
if !data.outputs.is_null() {
for output_idx in if has_main_output { 1 } else { 0 }..data.num_outputs as isize {
let host_output = data.outputs.offset(output_idx);
if !(*host_output).buffers.is_null() {
for channel_idx in 0..(*host_output).num_channels as isize {
ptr::write_bytes(
*((*host_output).buffers.offset(channel_idx)) as *mut f32,
0,
data.num_samples as usize,
);
}
}
}
}
// If `P::SAMPLE_ACCURATE_AUTOMATION` is set, then we'll split up the audio buffer into
// chunks whenever a parameter change occurs. To do that, we'll store all of those
// parameter changes in a vector. Otherwise all parameter changes are handled right here
@ -1319,12 +1341,6 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
}
}
let current_bus_config = self.inner.current_bus_config.load();
let has_main_input = current_bus_config.num_input_channels > 0;
// HACK: Bitwig requires VST3 plugins to always have a main output. We'll however
// still use this variable here to maintain consistency between the backends.
let has_main_output = true;
// We'll need to do the same thing for auxiliary input sidechain buffers. Since we
// don't know whether overwriting the host's buffers is safe here or not, we'll copy
// the data to our own buffers instead. These buffers are only accessible through