Hold the RwLock guard in the process context
This avoids having to constantly acquire a new lock.
This commit is contained in:
parent
ce3da8ea44
commit
bbc190c67f
|
@ -111,7 +111,7 @@ impl Plugin for Gain {
|
|||
&mut self,
|
||||
_bus_config: &BusConfig,
|
||||
_buffer_config: &BufferConfig,
|
||||
_context: &impl ProcessContext,
|
||||
_context: &mut impl 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
|
||||
|
@ -119,7 +119,11 @@ impl Plugin for Gain {
|
|||
true
|
||||
}
|
||||
|
||||
fn process(&mut self, buffer: &mut Buffer, _context: &impl ProcessContext) -> ProcessStatus {
|
||||
fn process(
|
||||
&mut self,
|
||||
buffer: &mut Buffer,
|
||||
_context: &mut impl ProcessContext,
|
||||
) -> ProcessStatus {
|
||||
for samples in buffer.iter_mut() {
|
||||
// Smoothing is optionally built into the parameters themselves
|
||||
let gain = self.params.gain.smoothed.next();
|
||||
|
|
|
@ -145,14 +145,14 @@ impl Plugin for Sine {
|
|||
&mut self,
|
||||
_bus_config: &BusConfig,
|
||||
buffer_config: &BufferConfig,
|
||||
_context: &impl ProcessContext,
|
||||
_context: &mut impl ProcessContext,
|
||||
) -> bool {
|
||||
self.sample_rate = buffer_config.sample_rate;
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn process(&mut self, buffer: &mut Buffer, context: &impl ProcessContext) -> ProcessStatus {
|
||||
fn process(&mut self, buffer: &mut Buffer, context: &mut impl ProcessContext) -> ProcessStatus {
|
||||
let mut next_event = context.next_midi_event();
|
||||
for (sample_id, samples) in buffer.iter_mut().enumerate() {
|
||||
// Smoothing is optionally built into the parameters themselves
|
||||
|
|
|
@ -48,7 +48,7 @@ pub trait ProcessContext {
|
|||
/// TODO: Rethink this API, both in terms of ergonomics, and if we can do this in a way that
|
||||
/// doesn't require locks (because of the thread safe-ness, which we don't really need
|
||||
/// here)
|
||||
fn next_midi_event(&self) -> Option<NoteEvent>;
|
||||
fn next_midi_event(&mut self) -> Option<NoteEvent>;
|
||||
|
||||
// // TODO: Add this next
|
||||
// fn set_parameter<P>(&self, param: &P, value: P::Plain)
|
||||
|
|
|
@ -88,7 +88,7 @@ pub trait Plugin: Default + Send + Sync {
|
|||
&mut self,
|
||||
bus_config: &BusConfig,
|
||||
buffer_config: &BufferConfig,
|
||||
context: &impl ProcessContext,
|
||||
context: &mut impl ProcessContext,
|
||||
) -> bool {
|
||||
true
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ pub trait Plugin: Default + Send + Sync {
|
|||
/// TODO: Provide a way to access auxiliary input channels if the IO configuration is
|
||||
/// assymetric
|
||||
/// TODO: Pass transport and other context information to the plugin
|
||||
fn process(&mut self, buffer: &mut Buffer, context: &impl ProcessContext) -> ProcessStatus;
|
||||
fn process(&mut self, buffer: &mut Buffer, context: &mut impl ProcessContext) -> ProcessStatus;
|
||||
}
|
||||
|
||||
/// Provides auxiliary metadata needed for a VST3 plugin.
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::RwLock;
|
||||
use parking_lot::{RwLock, RwLockWriteGuard};
|
||||
use std::cmp;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::ffi::c_void;
|
||||
|
@ -152,6 +152,7 @@ pub(crate) struct Wrapper<P: Plugin> {
|
|||
/// unnecessary atomic operations to lock the uncontested RwLocks.
|
||||
struct WrapperProcessContext<'a, P: Plugin> {
|
||||
inner: &'a WrapperInner<P>,
|
||||
input_events_guard: RwLockWriteGuard<'a, VecDeque<NoteEvent>>,
|
||||
}
|
||||
|
||||
impl<P: Plugin> ProcessContext for WrapperProcessContext<'_, P> {
|
||||
|
@ -167,10 +168,8 @@ impl<P: Plugin> ProcessContext for WrapperProcessContext<'_, P> {
|
|||
}
|
||||
}
|
||||
|
||||
fn next_midi_event(&self) -> Option<NoteEvent> {
|
||||
// TODO: Instead of having to lock this queue, move the lock guard into
|
||||
// `WrapperProcessContext`. That's the whole reason this was split up.
|
||||
self.inner.input_events.write().pop_front()
|
||||
fn next_midi_event(&mut self) -> Option<NoteEvent> {
|
||||
self.input_events_guard.pop_front()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +292,10 @@ impl<P: Plugin> WrapperInner<P> {
|
|||
}
|
||||
|
||||
pub fn make_process_context(&self) -> WrapperProcessContext<'_, P> {
|
||||
WrapperProcessContext { inner: self }
|
||||
WrapperProcessContext {
|
||||
inner: self,
|
||||
input_events_guard: self.input_events.write(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience function for setting a value for a parameter as triggered by a VST3 parameter
|
||||
|
@ -607,7 +609,7 @@ impl<P: Plugin> IComponent for Wrapper<P> {
|
|||
self.inner.plugin.write().initialize(
|
||||
&bus_config,
|
||||
&buffer_config,
|
||||
&self.inner.make_process_context(),
|
||||
&mut self.inner.make_process_context(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -994,7 +996,7 @@ impl<P: Plugin> IAudioProcessor for Wrapper<P> {
|
|||
if self.inner.plugin.write().initialize(
|
||||
&bus_config,
|
||||
&buffer_config,
|
||||
&self.inner.make_process_context(),
|
||||
&mut self.inner.make_process_context(),
|
||||
) {
|
||||
// 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
|
||||
|
@ -1173,7 +1175,7 @@ impl<P: Plugin> IAudioProcessor for Wrapper<P> {
|
|||
.plugin
|
||||
.write()
|
||||
// SAFETY: Same here
|
||||
.process(&mut output_buffer, &self.inner.make_process_context())
|
||||
.process(&mut output_buffer, &mut self.inner.make_process_context())
|
||||
{
|
||||
ProcessStatus::Error(err) => {
|
||||
nih_debug_assert_failure!("Process error: {}", err);
|
||||
|
|
Loading…
Reference in a new issue