1
0
Fork 0

Consider block start with buffer management

This broke sample accurate automation.
This commit is contained in:
Robbert van der Helm 2023-04-24 23:47:29 +02:00
parent 4912962551
commit 5e69910616
7 changed files with 157 additions and 143 deletions

View file

@ -24,6 +24,11 @@ state is to list breaking changes.
structure and to more explicitly mention that the non-lifecycle methods are structure and to more explicitly mention that the non-lifecycle methods are
called once immediately after creating the plugin object. called once immediately after creating the plugin object.
### Fixed
- The buffer changes from March 31st broke the sample accurate automation
feature. This has now been fixed.
## [2023-04-22] ## [2023-04-22]
### Added ### Added

View file

@ -2020,10 +2020,11 @@ impl<P: ClapPlugin> Wrapper<P> {
// TODO: Like with VST3, should we expose some way to access or set the silence/constant // TODO: Like with VST3, should we expose some way to access or set the silence/constant
// flags? // flags?
let mut buffer_manager = wrapper.buffer_manager.borrow_mut(); let mut buffer_manager = wrapper.buffer_manager.borrow_mut();
let buffers = buffer_manager.create_buffers(block_len, |buffer_source| { let buffers =
// Explicitly take plugins with no main output that does have auxiliary outputs buffer_manager.create_buffers(block_start, block_len, |buffer_source| {
// into account. Shouldn't happen, but if we just start copying audio here then // Explicitly take plugins with no main output that does have auxiliary
// that would result in unsoundness. // outputs into account. Shouldn't happen, but if we just start copying
// audio here then that would result in unsoundness.
if process.audio_outputs_count > 0 if process.audio_outputs_count > 0
&& !process.audio_outputs.is_null() && !process.audio_outputs.is_null()
&& !(*process.audio_outputs).data32.is_null() && !(*process.audio_outputs).data32.is_null()

View file

@ -825,7 +825,7 @@ impl CpalMidir {
{ {
let buffers = unsafe { let buffers = unsafe {
buffer_manager.create_buffers(buffer_size, |buffer_sources| { buffer_manager.create_buffers(0, buffer_size, |buffer_sources| {
*buffer_sources.main_output_channel_pointers = Some(ChannelPointers { *buffer_sources.main_output_channel_pointers = Some(ChannelPointers {
ptrs: NonNull::new(main_io_channel_pointers.get().as_mut_ptr()) ptrs: NonNull::new(main_io_channel_pointers.get().as_mut_ptr())
.unwrap(), .unwrap(),

View file

@ -121,7 +121,7 @@ impl<P: Plugin> Backend<P> for Dummy {
} }
let buffers = unsafe { let buffers = unsafe {
buffer_manager.create_buffers(num_samples, |buffer_sources| { buffer_manager.create_buffers(0, num_samples, |buffer_sources| {
*buffer_sources.main_output_channel_pointers = Some(ChannelPointers { *buffer_sources.main_output_channel_pointers = Some(ChannelPointers {
ptrs: NonNull::new(main_io_channel_pointers.as_mut_ptr()).unwrap(), ptrs: NonNull::new(main_io_channel_pointers.as_mut_ptr()).unwrap(),
num_channels: main_io_channel_pointers.len(), num_channels: main_io_channel_pointers.len(),

View file

@ -204,7 +204,7 @@ impl<P: Plugin> Backend<P> for Jack {
} }
let buffers = unsafe { let buffers = unsafe {
buffer_manager.create_buffers(num_frames as usize, |buffer_sources| { buffer_manager.create_buffers(0, num_frames as usize, |buffer_sources| {
*buffer_sources.main_output_channel_pointers = Some(ChannelPointers { *buffer_sources.main_output_channel_pointers = Some(ChannelPointers {
ptrs: NonNull::new(main_output_channel_pointers.get().as_mut_ptr()) ptrs: NonNull::new(main_output_channel_pointers.get().as_mut_ptr())
.unwrap(), .unwrap(),

View file

@ -151,7 +151,9 @@ impl BufferManager {
/// uninitialized buffer data (aux outputs, and main output channels with no matching input /// uninitialized buffer data (aux outputs, and main output channels with no matching input
/// channel) are filled with zeroes. /// channel) are filled with zeroes.
/// ///
/// If any of the output /// `sample_offset` and `num_samples` can be used to slice a set of host channel pointers for
/// sample accurate automation. If any of the outputs are missing because the host hasn't
/// provided enough channels or outputs, then they will be replaced by empty slices.
/// ///
/// # Panics /// # Panics
/// ///
@ -163,6 +165,7 @@ impl BufferManager {
/// or write to for the lifetime of the returned [`Buffers`]. /// or write to for the lifetime of the returned [`Buffers`].
pub unsafe fn create_buffers<'a, 'buffer: 'a>( pub unsafe fn create_buffers<'a, 'buffer: 'a>(
&'a mut self, &'a mut self,
sample_offset: usize,
num_samples: usize, num_samples: usize,
set_buffer_sources: impl FnOnce(&mut BufferSource), set_buffer_sources: impl FnOnce(&mut BufferSource),
) -> Buffers<'a, 'buffer> { ) -> Buffers<'a, 'buffer> {
@ -192,8 +195,10 @@ impl BufferManager {
output_channel_pointers.ptrs.as_ptr().add(channel_idx); output_channel_pointers.ptrs.as_ptr().add(channel_idx);
assert!(!output_channel_pointer.is_null()); assert!(!output_channel_pointer.is_null());
*output_slice = *output_slice = std::slice::from_raw_parts_mut(
std::slice::from_raw_parts_mut(*output_channel_pointer, num_samples); (*output_channel_pointer).add(sample_offset),
num_samples,
);
} }
// If the caller/host should have provided buffer pointers but didn't then we // If the caller/host should have provided buffer pointers but didn't then we
@ -229,7 +234,7 @@ impl BufferManager {
assert!(!input_channel_pointer.is_null()); assert!(!input_channel_pointer.is_null());
output_slice.copy_from_slice(std::slice::from_raw_parts_mut( output_slice.copy_from_slice(std::slice::from_raw_parts_mut(
*input_channel_pointer, (*input_channel_pointer).add(sample_offset),
num_samples, num_samples,
)) ))
} }
@ -275,7 +280,7 @@ impl BufferManager {
nih_debug_assert!(num_samples <= channel.capacity()); nih_debug_assert!(num_samples <= channel.capacity());
channel.resize(num_samples, 0.0); channel.resize(num_samples, 0.0);
channel.copy_from_slice(std::slice::from_raw_parts_mut( channel.copy_from_slice(std::slice::from_raw_parts_mut(
*input_channel_pointer, (*input_channel_pointer).add(sample_offset),
num_samples, num_samples,
)) ))
} }
@ -334,7 +339,7 @@ impl BufferManager {
assert!(!output_channel_pointer.is_null()); assert!(!output_channel_pointer.is_null());
*output_slice = std::slice::from_raw_parts_mut( *output_slice = std::slice::from_raw_parts_mut(
*output_channel_pointer, (*output_channel_pointer).add(sample_offset),
num_samples, num_samples,
); );
@ -424,7 +429,7 @@ mod miri {
// implementation for more information. // implementation for more information.
let mut buffer_manager = BufferManager::for_audio_io_layout(BUFFER_SIZE, AUDIO_IO_LAYOUT); let mut buffer_manager = BufferManager::for_audio_io_layout(BUFFER_SIZE, AUDIO_IO_LAYOUT);
let buffers = unsafe { let buffers = unsafe {
buffer_manager.create_buffers(BUFFER_SIZE, |buffer_sources| { buffer_manager.create_buffers(0, BUFFER_SIZE, |buffer_sources| {
*buffer_sources.main_output_channel_pointers = Some(ChannelPointers { *buffer_sources.main_output_channel_pointers = Some(ChannelPointers {
ptrs: NonNull::new(main_io_channel_pointers.as_mut_ptr()).unwrap(), ptrs: NonNull::new(main_io_channel_pointers.as_mut_ptr()).unwrap(),
num_channels: main_io_channel_pointers.len(), num_channels: main_io_channel_pointers.len(),

View file

@ -1229,14 +1229,16 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
// The buffer manager preallocated buffer slices for all the IO and storage for // The buffer manager preallocated buffer slices for all the IO and storage for
// any axuiliary inputs. // any axuiliary inputs.
let mut buffer_manager = self.inner.buffer_manager.borrow_mut(); let mut buffer_manager = self.inner.buffer_manager.borrow_mut();
let buffers = buffer_manager.create_buffers(block_len, |buffer_source| { let buffers =
buffer_manager.create_buffers(block_start, block_len, |buffer_source| {
if data.num_outputs > 0 if data.num_outputs > 0
&& !data.outputs.is_null() && !data.outputs.is_null()
&& !(*data.outputs).buffers.is_null() && !(*data.outputs).buffers.is_null()
&& has_main_output && has_main_output
{ {
let audio_output = &*data.outputs; let audio_output = &*data.outputs;
let ptrs = NonNull::new(audio_output.buffers as *mut *mut f32).unwrap(); let ptrs =
NonNull::new(audio_output.buffers as *mut *mut f32).unwrap();
let num_channels = audio_output.num_channels as usize; let num_channels = audio_output.num_channels as usize;
*buffer_source.main_output_channel_pointers = *buffer_source.main_output_channel_pointers =
@ -1249,7 +1251,8 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
&& has_main_input && has_main_input
{ {
let audio_input = &*data.inputs; let audio_input = &*data.inputs;
let ptrs = NonNull::new(audio_input.buffers as *mut *mut f32).unwrap(); let ptrs =
NonNull::new(audio_input.buffers as *mut *mut f32).unwrap();
let num_channels = audio_input.num_channels as usize; let num_channels = audio_input.num_channels as usize;
*buffer_source.main_input_channel_pointers = *buffer_source.main_input_channel_pointers =