diff --git a/plugins/gain/src/lib.rs b/plugins/gain/src/lib.rs index 51802ae8..da486346 100644 --- a/plugins/gain/src/lib.rs +++ b/plugins/gain/src/lib.rs @@ -18,6 +18,7 @@ extern crate nih_plug; use nih_plug::{ + context::ProcessContext, formatters, params::{BoolParam, FloatParam, Param, Params, Range}, plugin::{BufferConfig, BusConfig, Plugin, ProcessStatus, Vst3Plugin}, @@ -105,14 +106,23 @@ impl Plugin for Gain { config.num_input_channels == config.num_output_channels && config.num_input_channels > 0 } - fn initialize(&mut self, _bus_config: &BusConfig, _buffer_config: &BufferConfig) -> bool { + fn initialize( + &mut self, + _bus_config: &BusConfig, + _buffer_config: &BufferConfig, + _context: &dyn ProcessContext, + ) -> bool { // This plugin doesn't need any special initialization, but if you need to do anything // expensive then this would be the place. State is kept around while when the host // reconfigures the plugin. true } - fn process(&mut self, samples: &mut [&mut [f32]]) -> ProcessStatus { + fn process( + &mut self, + samples: &mut [&mut [f32]], + _context: &dyn ProcessContext, + ) -> ProcessStatus { if samples.is_empty() { return ProcessStatus::Error("Empty buffers"); } diff --git a/src/plugin.rs b/src/plugin.rs index 2e0792a3..21efe1ad 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -16,6 +16,7 @@ use std::pin::Pin; +use crate::context::ProcessContext; use crate::params::Params; /// Basic functionality that needs to be implemented by a plugin. The wrappers will use this to @@ -72,11 +73,19 @@ pub trait Plugin: Default + Send + Sync { /// shouldn't do anything beyond returning true or false. fn accepts_bus_config(&self, config: &BusConfig) -> bool; - /// Initialize the plugin for the given bus and buffer configurations. + /// Initialize the plugin for the given bus and buffer configurations. If the plugin is being + /// restored from an old state, then that state will have already been restored at this point. + /// If based on those parameters (or for any reason whatsoever) the plugin needs to introduce + /// latency, then you can do so here using the process context. /// - /// Before this point, the plugin should not have done any expensive initialization. Pleaes + /// Before this point, the plugin should not have done any expensive initialization. Please /// don't be that plugin that takes twenty seconds to scan. - fn initialize(&mut self, bus_config: &BusConfig, buffer_config: &BufferConfig) -> bool; + fn initialize( + &mut self, + bus_config: &BusConfig, + buffer_config: &BufferConfig, + context: &dyn ProcessContext, + ) -> bool; /// Process audio. To not have to worry about aliasing, the host's input buffer have already /// been copied to the output buffers if they are not handling buffers in place (most hosts do @@ -87,7 +96,11 @@ pub trait Plugin: Default + Send + Sync { /// assymetric /// TODO: Handle FTZ stuff on the wrapper side and mention that this has been handled /// TODO: Pass transport and other context information to the plugin - fn process(&mut self, samples: &mut [&mut [f32]]) -> ProcessStatus; + fn process( + &mut self, + samples: &mut [&mut [f32]], + context: &dyn ProcessContext, + ) -> ProcessStatus; } /// Provides auxiliary metadata needed for a VST3 plugin. diff --git a/src/wrapper/vst3.rs b/src/wrapper/vst3.rs index 323b274b..8ef8e4df 100644 --- a/src/wrapper/vst3.rs +++ b/src/wrapper/vst3.rs @@ -876,7 +876,7 @@ impl IAudioProcessor for Wrapper<'_, P> { .inner .plugin .write() - .initialize(&bus_config, &buffer_config) + .initialize(&bus_config, &buffer_config, self.inner.as_ref()) { // Preallocate enough room in the output slices vector so we can convert a `*mut *mut // f32` to a `&mut [&mut f32]` in the process call @@ -995,7 +995,12 @@ impl IAudioProcessor for Wrapper<'_, P> { } } - match self.inner.plugin.write().process(&mut output_slices) { + match self + .inner + .plugin + .write() + .process(&mut output_slices, self.inner.as_ref()) + { ProcessStatus::Error(err) => { nih_debug_assert_failure!("Process error: {}", err);