Add auxiliary buffers in dummy standalone backwend
This commit is contained in:
parent
a8be77a513
commit
9e2c2b776b
|
@ -1,3 +1,4 @@
|
|||
use crate::audio_setup::AuxiliaryBuffers;
|
||||
use crate::context::process::Transport;
|
||||
use crate::midi::PluginNoteEvent;
|
||||
|
||||
|
@ -17,12 +18,11 @@ pub trait Backend<P: Plugin>: 'static + Send + Sync {
|
|||
/// there's a new block of audio to be processed. The process callback receives the audio
|
||||
/// buffers for the wrapped plugin's outputs. Any inputs will have already been copied to this
|
||||
/// buffer. This will block until the process callback returns `false`.
|
||||
///
|
||||
/// TODO: Auxiliary inputs and outputs
|
||||
fn run(
|
||||
&mut self,
|
||||
cb: impl FnMut(
|
||||
&mut Buffer,
|
||||
&mut AuxiliaryBuffers,
|
||||
Transport,
|
||||
&[PluginNoteEvent<P>],
|
||||
&mut Vec<PluginNoteEvent<P>>,
|
||||
|
|
|
@ -10,7 +10,7 @@ use rtrb::RingBuffer;
|
|||
|
||||
use super::super::config::WrapperConfig;
|
||||
use super::Backend;
|
||||
use crate::audio_setup::AudioIOLayout;
|
||||
use crate::audio_setup::{AudioIOLayout, AuxiliaryBuffers};
|
||||
use crate::buffer::Buffer;
|
||||
use crate::context::process::Transport;
|
||||
use crate::midi::{MidiConfig, PluginNoteEvent};
|
||||
|
@ -34,6 +34,7 @@ impl<P: Plugin> Backend<P> for Cpal {
|
|||
&mut self,
|
||||
cb: impl FnMut(
|
||||
&mut Buffer,
|
||||
&mut AuxiliaryBuffers,
|
||||
Transport,
|
||||
&[PluginNoteEvent<P>],
|
||||
&mut Vec<PluginNoteEvent<P>>,
|
||||
|
@ -321,6 +322,7 @@ impl Cpal {
|
|||
mut input_rb_consumer: Option<rtrb::Consumer<f32>>,
|
||||
mut cb: impl FnMut(
|
||||
&mut Buffer,
|
||||
&mut AuxiliaryBuffers,
|
||||
Transport,
|
||||
&[PluginNoteEvent<P>],
|
||||
&mut Vec<PluginNoteEvent<P>>,
|
||||
|
@ -404,6 +406,11 @@ impl Cpal {
|
|||
midi_output_events.clear();
|
||||
if !cb(
|
||||
&mut buffer,
|
||||
// FIXME: Use zero filled buffers with the correct size instead
|
||||
&mut AuxiliaryBuffers {
|
||||
inputs: &mut [],
|
||||
outputs: &mut [],
|
||||
},
|
||||
transport,
|
||||
&midi_input_events,
|
||||
&mut midi_output_events,
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::time::{Duration, Instant};
|
|||
|
||||
use super::super::config::WrapperConfig;
|
||||
use super::Backend;
|
||||
use crate::audio_setup::AudioIOLayout;
|
||||
use crate::audio_setup::{AudioIOLayout, AuxiliaryBuffers};
|
||||
use crate::buffer::Buffer;
|
||||
use crate::context::process::Transport;
|
||||
use crate::midi::PluginNoteEvent;
|
||||
|
@ -22,6 +22,7 @@ impl<P: Plugin> Backend<P> for Dummy {
|
|||
&mut self,
|
||||
mut cb: impl FnMut(
|
||||
&mut Buffer,
|
||||
&mut AuxiliaryBuffers,
|
||||
Transport,
|
||||
&[PluginNoteEvent<P>],
|
||||
&mut Vec<PluginNoteEvent<P>>,
|
||||
|
@ -52,6 +53,50 @@ impl<P: Plugin> Backend<P> for Dummy {
|
|||
})
|
||||
}
|
||||
|
||||
// We'll do the same thing for auxiliary inputs and outputs, so the plugin always gets the
|
||||
// buffers it expects
|
||||
let mut aux_input_storage: Vec<Vec<Vec<f32>>> = Vec::new();
|
||||
let mut aux_input_buffers: Vec<Buffer> = Vec::new();
|
||||
for channel_count in self.audio_io_layout.aux_input_ports {
|
||||
aux_input_storage.push(vec![
|
||||
vec![0.0f32; self.config.period_size as usize];
|
||||
channel_count.get() as usize
|
||||
]);
|
||||
|
||||
let aux_storage = aux_input_storage.last_mut().unwrap();
|
||||
let mut aux_buffer = Buffer::default();
|
||||
unsafe {
|
||||
aux_buffer.set_slices(self.config.period_size as usize, |output_slices| {
|
||||
// SAFETY: `aux_storage` is no longer used directly after this
|
||||
*output_slices = aux_storage
|
||||
.iter_mut()
|
||||
.map(|channel| &mut *(channel.as_mut_slice() as *mut [f32]))
|
||||
.collect();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let mut aux_output_storage: Vec<Vec<Vec<f32>>> = Vec::new();
|
||||
let mut aux_output_buffers: Vec<Buffer> = Vec::new();
|
||||
for channel_count in self.audio_io_layout.aux_output_ports {
|
||||
aux_output_storage.push(vec![
|
||||
vec![0.0f32; self.config.period_size as usize];
|
||||
channel_count.get() as usize
|
||||
]);
|
||||
|
||||
let aux_storage = aux_output_storage.last_mut().unwrap();
|
||||
let mut aux_buffer = Buffer::default();
|
||||
unsafe {
|
||||
aux_buffer.set_slices(self.config.period_size as usize, |output_slices| {
|
||||
// SAFETY: `aux_storage` is no longer used directly after this
|
||||
*output_slices = aux_storage
|
||||
.iter_mut()
|
||||
.map(|channel| &mut *(channel.as_mut_slice() as *mut [f32]))
|
||||
.collect();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// This queue will never actually be used
|
||||
let mut midi_output_events = Vec::with_capacity(1024);
|
||||
let mut num_processed_samples = 0;
|
||||
|
@ -68,9 +113,35 @@ impl<P: Plugin> Backend<P> for Dummy {
|
|||
for channel in buffer.as_slice() {
|
||||
channel.fill(0.0);
|
||||
}
|
||||
for aux_buffer in &mut aux_input_buffers {
|
||||
for channel in aux_buffer.as_slice() {
|
||||
channel.fill(0.0);
|
||||
}
|
||||
}
|
||||
for aux_buffer in &mut aux_output_buffers {
|
||||
for channel in aux_buffer.as_slice() {
|
||||
channel.fill(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Shortening these borrows is safe as even if the plugin overwrites the
|
||||
// slices (which it cannot do without using unsafe code), then they
|
||||
// would still be reset on the next iteration
|
||||
let mut aux = unsafe {
|
||||
AuxiliaryBuffers {
|
||||
inputs: &mut *(aux_input_buffers.as_mut_slice() as *mut [Buffer]),
|
||||
outputs: &mut *(aux_output_buffers.as_mut_slice() as *mut [Buffer]),
|
||||
}
|
||||
};
|
||||
|
||||
midi_output_events.clear();
|
||||
if !cb(&mut buffer, transport, &[], &mut midi_output_events) {
|
||||
if !cb(
|
||||
&mut buffer,
|
||||
&mut aux,
|
||||
transport,
|
||||
&[],
|
||||
&mut midi_output_events,
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use parking_lot::Mutex;
|
|||
|
||||
use super::super::config::WrapperConfig;
|
||||
use super::Backend;
|
||||
use crate::audio_setup::AuxiliaryBuffers;
|
||||
use crate::buffer::Buffer;
|
||||
use crate::context::process::Transport;
|
||||
use crate::midi::{MidiConfig, MidiResult, NoteEvent, PluginNoteEvent};
|
||||
|
@ -39,6 +40,7 @@ impl<P: Plugin> Backend<P> for Jack {
|
|||
&mut self,
|
||||
mut cb: impl FnMut(
|
||||
&mut Buffer,
|
||||
&mut AuxiliaryBuffers,
|
||||
Transport,
|
||||
&[PluginNoteEvent<P>],
|
||||
&mut Vec<PluginNoteEvent<P>>,
|
||||
|
@ -134,7 +136,17 @@ impl<P: Plugin> Backend<P> for Jack {
|
|||
}
|
||||
|
||||
output_events.clear();
|
||||
if cb(&mut buffer, transport, &input_events, &mut output_events) {
|
||||
if cb(
|
||||
&mut buffer,
|
||||
// TODO: Support auxiliary IO in the JACK backend
|
||||
&mut AuxiliaryBuffers {
|
||||
inputs: &mut [],
|
||||
outputs: &mut [],
|
||||
},
|
||||
transport,
|
||||
&input_events,
|
||||
&mut output_events,
|
||||
) {
|
||||
if let Some(midi_output) = &midi_output {
|
||||
let mut midi_output = midi_output.lock();
|
||||
let mut midi_writer = midi_output.writer(ps);
|
||||
|
|
|
@ -13,7 +13,6 @@ use std::thread;
|
|||
use super::backend::Backend;
|
||||
use super::config::WrapperConfig;
|
||||
use super::context::{WrapperGuiContext, WrapperInitContext, WrapperProcessContext};
|
||||
use crate::audio_setup::AuxiliaryBuffers;
|
||||
use crate::audio_setup::{AudioIOLayout, BufferConfig, ProcessMode};
|
||||
use crate::context::gui::AsyncExecutor;
|
||||
use crate::context::process::Transport;
|
||||
|
@ -466,7 +465,7 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
|||
gui_task_sender: channel::Sender<GuiTask>,
|
||||
) {
|
||||
self.clone().backend.borrow_mut().run(
|
||||
move |buffer, transport, input_events, output_events| {
|
||||
move |buffer, aux, transport, input_events, output_events| {
|
||||
// TODO: This process wrapper should actually be in the backends (since the backends
|
||||
// should also not allocate in their audio callbacks), but that's a bit more
|
||||
// error prone
|
||||
|
@ -479,11 +478,7 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
|||
let mut plugin = self.plugin.lock();
|
||||
if let ProcessStatus::Error(err) = plugin.process(
|
||||
buffer,
|
||||
// TODO: Provide extra inputs and outputs in the JACk backend
|
||||
&mut AuxiliaryBuffers {
|
||||
inputs: &mut [],
|
||||
outputs: &mut [],
|
||||
},
|
||||
aux,
|
||||
&mut self.make_process_context(transport, input_events, output_events),
|
||||
) {
|
||||
nih_error!("The plugin returned an error while processing:");
|
||||
|
|
Loading…
Reference in a new issue