From 3d454bfc9c763e8a7ea193cfc5c517eeb9d51e65 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 30 Apr 2022 02:00:09 +0200 Subject: [PATCH] Don't process audio at all with invalid buffers If the host does some kind of flush this way with num_samples > 0 but without any outputs or with zero output channels then we should not try to read from the now invalid pointers from the previous cycle. --- src/wrapper/clap/wrapper.rs | 10 ++++++++-- src/wrapper/vst3/wrapper.rs | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/wrapper/clap/wrapper.rs b/src/wrapper/clap/wrapper.rs index c0a7168a..c37bd067 100644 --- a/src/wrapper/clap/wrapper.rs +++ b/src/wrapper/clap/wrapper.rs @@ -1593,17 +1593,21 @@ impl Wrapper

{ // Right now we don't handle any auxiliary outputs // This vector has been preallocated to contain enough slices as there are output - // channels + // channels. If the host does not provide outputs or if it does not provide the + // required number of channels (should not happen, but Ableton Live does this for + // bypassed VST3 plugins) then we'll skip audio processing . // TODO: The audio buffers have a latency field, should we use those? // TODO: Like with VST3, should we expose some way to access or set the silence/constant // flags? let mut output_buffer = wrapper.output_buffer.borrow_mut(); + let mut buffer_is_valid = false; output_buffer.with_raw_vec(|output_slices| { if !process.audio_outputs.is_null() && !(*process.audio_outputs).data32.is_null() { let audio_outputs = &*process.audio_outputs; let num_output_channels = audio_outputs.channel_count as usize; + buffer_is_valid = num_output_channels == output_slices.len(); nih_debug_assert_eq!(num_output_channels, output_slices.len()); // NOTE: This `.take()` should not be necessary, but we'll do it as a safe @@ -1752,12 +1756,14 @@ impl Wrapper

{ } } - let result = { + let result = if buffer_is_valid { let mut plugin = wrapper.plugin.write(); let mut context = wrapper.make_process_context(transport); let result = plugin.process(&mut output_buffer, &mut context); wrapper.last_process_status.store(result); result + } else { + ProcessStatus::Normal }; let clap_result = match result { diff --git a/src/wrapper/vst3/wrapper.rs b/src/wrapper/vst3/wrapper.rs index 019d47b5..ea3a6af7 100644 --- a/src/wrapper/vst3/wrapper.rs +++ b/src/wrapper/vst3/wrapper.rs @@ -967,12 +967,16 @@ impl IAudioProcessor for Wrapper

{ parameter_values_changed = false; } - // This vector has been preallocated to contain enough slices as there are - // output channels + // This vector has been preallocated to contain enough slices as there are output + // channels. In case the does does not provide an output or if they don't provide + // all of the channels (this should not happen, but Ableton Live might do it) then + // we'll skip the process function. let mut output_buffer = self.inner.output_buffer.borrow_mut(); + let mut buffer_is_valid = false; output_buffer.with_raw_vec(|output_slices| { if !data.outputs.is_null() { let num_output_channels = (*data.outputs).num_channels as usize; + buffer_is_valid = num_output_channels == output_slices.len(); nih_debug_assert_eq!(num_output_channels, output_slices.len()); // In case the host does provide fewer output channels than we expect, we @@ -1084,12 +1088,15 @@ impl IAudioProcessor for Wrapper

{ } } - let result = { + let result = if buffer_is_valid { let mut plugin = self.inner.plugin.write(); let mut context = self.inner.make_process_context(transport); - plugin.process(&mut output_buffer, &mut context) + let result = plugin.process(&mut output_buffer, &mut context); + self.inner.last_process_status.store(result); + result + } else { + ProcessStatus::Normal }; - self.inner.last_process_status.store(result); // Send any events output by the plugin during the process cycle if let Some(events) = data.output_events.upgrade() {