1
0
Fork 0

Completely reset smoothing on init or restore

This commit is contained in:
Robbert van der Helm 2022-02-02 21:41:20 +01:00
parent f8eb0e4ea6
commit 0ecec104fb
4 changed files with 49 additions and 37 deletions

View file

@ -34,9 +34,10 @@ pub trait Param {
/// The plain parameter type.
type Plain;
/// Update the smoother state to point to the current value. Used when initializing and
/// restoring a plugin so everything is in sync.
fn update_smoother(&mut self, sample_rate: f32);
/// Update the smoother state to point to the current value. Also used when initializing and
/// restoring a plugin so everything is in sync. In that case the smoother should completely
/// reset to the current value.
fn update_smoother(&mut self, sample_rate: f32, reset: bool);
/// Set this parameter based on a string. Returns whether the updating succeeded. That can fail
/// if the string cannot be parsed.
@ -162,8 +163,8 @@ macro_rules! impl_plainparam {
impl Param for $ty {
type Plain = $plain;
fn update_smoother(&mut self, sample_rate: f32) {
self.smoothed.set_target(sample_rate, self.value);
fn update_smoother(&mut self, sample_rate: f32, reset: bool) {
self.smoothed.set_target(sample_rate, self.value, reset);
}
fn set_from_string(&mut self, string: &str) -> bool {
@ -234,7 +235,7 @@ impl_plainparam!(IntParam, i32);
impl Param for BoolParam {
type Plain = bool;
fn update_smoother(&mut self, _sample_rate: f32) {
fn update_smoother(&mut self, _sample_rate: f32, _init: bool) {
// Can't really smooth a binary parameter now can you
}

View file

@ -119,18 +119,19 @@ impl ParamPtr {
}
}
/// Update the smoother state to point to the current value. Used when initializing and
/// restoring a plugin so everything is in sync.
/// Update the smoother state to point to the current value. Also used when initializing and
/// restoring a plugin so everything is in sync. In that case the smoother should completely
/// reset to the current value.
///
/// # Safety
///
/// Calling this function is only safe as long as the object this `ParamPtr` was created for is
/// still alive.
pub unsafe fn update_smoother(&self, sample_rate: f32) {
pub unsafe fn update_smoother(&self, sample_rate: f32, reset: bool) {
match &self {
ParamPtr::FloatParam(p) => (**p).update_smoother(sample_rate),
ParamPtr::IntParam(p) => (**p).update_smoother(sample_rate),
ParamPtr::BoolParam(p) => (**p).update_smoother(sample_rate),
ParamPtr::FloatParam(p) => (**p).update_smoother(sample_rate, reset),
ParamPtr::IntParam(p) => (**p).update_smoother(sample_rate, reset),
ParamPtr::BoolParam(p) => (**p).update_smoother(sample_rate, reset),
}
}

View file

@ -71,18 +71,23 @@ impl<T: Default> Smoother<T> {
// unwrap all of those options is not going to be very fun.
impl Smoother<f32> {
/// Set the target value.
pub fn set_target(&mut self, sample_rate: f32, target: f32) {
pub fn set_target(&mut self, sample_rate: f32, target: f32, reset: bool) {
self.target = target;
self.steps_left = match self.style {
SmoothingStyle::None => 1,
SmoothingStyle::SmoothLinear(time) => (sample_rate * time / 1000.0).round() as u32,
};
self.step_size = match self.style {
SmoothingStyle::None => 0.0,
SmoothingStyle::SmoothLinear(_) => {
(self.target - self.current) / self.steps_left as f32
}
};
if reset {
self.current = self.target;
self.steps_left = 0;
} else {
self.steps_left = match self.style {
SmoothingStyle::None => 1,
SmoothingStyle::SmoothLinear(time) => (sample_rate * time / 1000.0).round() as u32,
};
self.step_size = match self.style {
SmoothingStyle::None => 0.0,
SmoothingStyle::SmoothLinear(_) => {
(self.target - self.current) / self.steps_left as f32
}
};
}
}
// Yes, Clippy, like I said, this was intentional
@ -109,18 +114,23 @@ impl Smoother<f32> {
}
impl Smoother<i32> {
pub fn set_target(&mut self, sample_rate: f32, target: i32) {
pub fn set_target(&mut self, sample_rate: f32, target: i32, reset: bool) {
self.target = target;
self.steps_left = match self.style {
SmoothingStyle::None => 1,
SmoothingStyle::SmoothLinear(time) => (sample_rate * time / 1000.0).round() as u32,
};
self.step_size = match self.style {
SmoothingStyle::None => 0.0,
SmoothingStyle::SmoothLinear(_) => {
(self.target as f32 - self.current) / self.steps_left as f32
}
};
if reset {
self.current = self.target as f32;
self.steps_left = 0;
} else {
self.steps_left = match self.style {
SmoothingStyle::None => 1,
SmoothingStyle::SmoothLinear(time) => (sample_rate * time / 1000.0).round() as u32,
};
self.step_size = match self.style {
SmoothingStyle::None => 0.0,
SmoothingStyle::SmoothLinear(_) => {
(self.target as f32 - self.current) / self.steps_left as f32
}
};
}
}
#[allow(clippy::should_implement_trait)]

View file

@ -277,7 +277,7 @@ impl<P: Plugin> WrapperInner<'_, P> {
match (param_ptr, sample_rate) {
(_, Some(sample_rate)) => {
param_ptr.set_normalized_value(normalized_value as f32);
param_ptr.update_smoother(sample_rate);
param_ptr.update_smoother(sample_rate, false);
}
_ => param_ptr.set_normalized_value(normalized_value as f32),
}
@ -536,7 +536,7 @@ impl<P: Plugin> IComponent for Wrapper<'_, P> {
// Make sure everything starts out in sync
if let Some(sample_rate) = sample_rate {
param_ptr.update_smoother(sample_rate);
param_ptr.update_smoother(sample_rate, true);
}
}
@ -934,7 +934,7 @@ impl<P: Plugin> IAudioProcessor for Wrapper<'_, P> {
// Befure initializing the plugin, make sure all smoothers are set the the default values
for param in self.inner.param_by_hash.values() {
param.update_smoother(buffer_config.sample_rate);
param.update_smoother(buffer_config.sample_rate, true);
}
if self