1
0
Fork 0

Add functions for allocating block smoothers

This commit is contained in:
Robbert van der Helm 2022-03-01 17:07:03 +01:00
parent 892aef7e37
commit d470a1db5a
6 changed files with 50 additions and 0 deletions

View file

@ -67,6 +67,10 @@ pub trait Param: Display {
/// reset to the current value. /// reset to the current value.
fn update_smoother(&mut self, sample_rate: f32, reset: bool); fn update_smoother(&mut self, sample_rate: f32, reset: bool);
/// Allocate memory for block-based smoothing. The [crate::Plugin::initialize_block_smoothers()]
/// method will do this for every smoother.
fn initialize_block_smoother(&mut self, max_block_size: usize);
/// Internal implementation detail for implementing [internals::Params]. This should not be used /// Internal implementation detail for implementing [internals::Params]. This should not be used
/// directly. /// directly.
fn as_ptr(&self) -> internals::ParamPtr; fn as_ptr(&self) -> internals::ParamPtr;

View file

@ -122,6 +122,8 @@ impl Param for BoolParam {
// Can't really smooth a binary parameter now can you // Can't really smooth a binary parameter now can you
} }
fn initialize_block_smoother(&mut self, _max_block_size: usize) {}
fn as_ptr(&self) -> ParamPtr { fn as_ptr(&self) -> ParamPtr {
ParamPtr::BoolParam(self as *const BoolParam as *mut BoolParam) ParamPtr::BoolParam(self as *const BoolParam as *mut BoolParam)
} }

View file

@ -140,6 +140,10 @@ impl<T: Enum> Param for EnumParam<T> {
self.inner.update_smoother(sample_rate, reset) self.inner.update_smoother(sample_rate, reset)
} }
fn initialize_block_smoother(&mut self, max_block_size: usize) {
self.inner.initialize_block_smoother(max_block_size)
}
fn as_ptr(&self) -> ParamPtr { fn as_ptr(&self) -> ParamPtr {
self.inner.as_ptr() self.inner.as_ptr()
} }
@ -198,6 +202,10 @@ impl Param for EnumParamInner {
self.inner.update_smoother(sample_rate, reset) self.inner.update_smoother(sample_rate, reset)
} }
fn initialize_block_smoother(&mut self, max_block_size: usize) {
self.inner.initialize_block_smoother(max_block_size)
}
fn as_ptr(&self) -> ParamPtr { fn as_ptr(&self) -> ParamPtr {
ParamPtr::EnumParam(self as *const EnumParamInner as *mut EnumParamInner) ParamPtr::EnumParam(self as *const EnumParamInner as *mut EnumParamInner)
} }

View file

@ -149,6 +149,22 @@ impl ParamPtr {
} }
} }
/// Allocate memory for block-based smoothing. The [crate::Plugin::initialize_block_smoothers()]
/// method will do this for every smoother.
///
/// # Safety
///
/// Calling this function is only safe as long as the object this `ParamPtr` was created for is
/// still alive.
pub unsafe fn initialize_block_smoother(&mut self, max_block_size: usize) {
match &self {
ParamPtr::FloatParam(p) => (**p).initialize_block_smoother(max_block_size),
ParamPtr::IntParam(p) => (**p).initialize_block_smoother(max_block_size),
ParamPtr::BoolParam(p) => (**p).initialize_block_smoother(max_block_size),
ParamPtr::EnumParam(p) => (**p).initialize_block_smoother(max_block_size),
}
}
/// Set this parameter based on a string. Returns whether the updating succeeded. That can fail /// Set this parameter based on a string. Returns whether the updating succeeded. That can fail
/// if the string cannot be parsed. /// if the string cannot be parsed.
/// ///

View file

@ -186,6 +186,10 @@ macro_rules! impl_plainparam {
} }
} }
fn initialize_block_smoother(&mut self, max_block_size: usize) {
self.smoothed.initialize_block_smoother(max_block_size);
}
fn as_ptr(&self) -> ParamPtr { fn as_ptr(&self) -> ParamPtr {
ParamPtr::$ty(self as *const $ty as *mut $ty) ParamPtr::$ty(self as *const $ty as *mut $ty)
} }

View file

@ -1,4 +1,5 @@
use atomic_float::AtomicF32; use atomic_float::AtomicF32;
use parking_lot::Mutex;
use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::atomic::{AtomicI32, Ordering};
/// Controls if and how parameters gets smoothed. /// Controls if and how parameters gets smoothed.
@ -37,6 +38,10 @@ pub struct Smoother<T> {
current: AtomicF32, current: AtomicF32,
/// The value we're smoothing towards /// The value we're smoothing towards
target: T, target: T,
/// A dense buffer containing smoothed values for an entire block of audio. Useful when using
/// [crate::Buffer::iter_blocks()] to process small blocks of audio multiple times.
block_values: Mutex<Vec<T>>,
} }
impl<T: Default> Default for Smoother<T> { impl<T: Default> Default for Smoother<T> {
@ -47,6 +52,8 @@ impl<T: Default> Default for Smoother<T> {
step_size: Default::default(), step_size: Default::default(),
current: AtomicF32::new(0.0), current: AtomicF32::new(0.0),
target: Default::default(), target: Default::default(),
block_values: Mutex::new(Vec::new()),
} }
} }
} }
@ -70,6 +77,15 @@ impl<T: Default> Smoother<T> {
pub fn is_smoothing(&self) -> bool { pub fn is_smoothing(&self) -> bool {
self.steps_left.load(Ordering::Relaxed) > 0 self.steps_left.load(Ordering::Relaxed) > 0
} }
/// Allocate memory to store smoothed values for an entire block of audio. Call this in
/// [crate::Plugin::initialize()] with the same max block size you are going to pass to
/// [crate::Buffer::iter_blocks()].
pub fn initialize_block_smoother(&mut self, max_block_size: usize) {
self.block_values
.lock()
.resize_with(max_block_size, || T::default());
}
} }
// These are not iterators for the sole reason that this will always yield a value, and needing to // These are not iterators for the sole reason that this will always yield a value, and needing to