Split up set_target and reset in smoothers
This makes it a bit less awkward to use in user code, if you need a separate smoother there.
This commit is contained in:
parent
15d0e69d46
commit
073fe743c2
2 changed files with 61 additions and 53 deletions
|
@ -164,7 +164,11 @@ macro_rules! impl_plainparam {
|
||||||
type Plain = $plain;
|
type Plain = $plain;
|
||||||
|
|
||||||
fn update_smoother(&mut self, sample_rate: f32, reset: bool) {
|
fn update_smoother(&mut self, sample_rate: f32, reset: bool) {
|
||||||
self.smoothed.set_target(sample_rate, self.value, reset);
|
if reset {
|
||||||
|
self.smoothed.reset(self.value);
|
||||||
|
} else {
|
||||||
|
self.smoothed.set_target(sample_rate, self.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_from_string(&mut self, string: &str) -> bool {
|
fn set_from_string(&mut self, string: &str) -> bool {
|
||||||
|
|
|
@ -82,30 +82,32 @@ impl<T: Default> Smoother<T> {
|
||||||
// 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
|
||||||
// unwrap all of those options is not going to be very fun.
|
// unwrap all of those options is not going to be very fun.
|
||||||
impl Smoother<f32> {
|
impl Smoother<f32> {
|
||||||
|
/// Reset the smoother the specified value.
|
||||||
|
pub fn reset(&mut self, value: f32) {
|
||||||
|
self.target = value;
|
||||||
|
self.current = value;
|
||||||
|
self.steps_left = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the target value.
|
/// Set the target value.
|
||||||
pub fn set_target(&mut self, sample_rate: f32, target: f32, reset: bool) {
|
pub fn set_target(&mut self, sample_rate: f32, target: f32) {
|
||||||
self.target = target;
|
self.target = target;
|
||||||
if reset {
|
self.steps_left = match self.style {
|
||||||
self.current = self.target;
|
SmoothingStyle::None => 1,
|
||||||
self.steps_left = 0;
|
SmoothingStyle::Linear(time) | SmoothingStyle::Logarithmic(time) => {
|
||||||
} else {
|
(sample_rate * time / 1000.0).round() as u32
|
||||||
self.steps_left = match self.style {
|
}
|
||||||
SmoothingStyle::None => 1,
|
};
|
||||||
SmoothingStyle::Linear(time) | SmoothingStyle::Logarithmic(time) => {
|
self.step_size = match self.style {
|
||||||
(sample_rate * time / 1000.0).round() as u32
|
SmoothingStyle::None => 0.0,
|
||||||
}
|
SmoothingStyle::Linear(_) => (self.target - self.current) / self.steps_left as f32,
|
||||||
};
|
SmoothingStyle::Logarithmic(_) => {
|
||||||
self.step_size = match self.style {
|
// We need to solve `current * (step_size ^ steps_left) = target` for
|
||||||
SmoothingStyle::None => 0.0,
|
// `step_size`
|
||||||
SmoothingStyle::Linear(_) => (self.target - self.current) / self.steps_left as f32,
|
nih_debug_assert_ne!(self.current, 0.0);
|
||||||
SmoothingStyle::Logarithmic(_) => {
|
(self.target / self.current).powf((self.steps_left as f32).recip())
|
||||||
// We need to solve `current * (step_size ^ steps_left) = target` for
|
}
|
||||||
// `step_size`
|
};
|
||||||
nih_debug_assert_ne!(self.current, 0.0);
|
|
||||||
(self.target / self.current).powf((self.steps_left as f32).recip())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes, Clippy, like I said, this was intentional
|
// Yes, Clippy, like I said, this was intentional
|
||||||
|
@ -133,29 +135,31 @@ impl Smoother<f32> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Smoother<i32> {
|
impl Smoother<i32> {
|
||||||
pub fn set_target(&mut self, sample_rate: f32, target: i32, reset: bool) {
|
/// Reset the smoother the specified value.
|
||||||
|
pub fn reset(&mut self, value: i32) {
|
||||||
|
self.target = value;
|
||||||
|
self.current = value as f32;
|
||||||
|
self.steps_left = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_target(&mut self, sample_rate: f32, target: i32) {
|
||||||
self.target = target;
|
self.target = target;
|
||||||
if reset {
|
self.steps_left = match self.style {
|
||||||
self.current = self.target as f32;
|
SmoothingStyle::None => 1,
|
||||||
self.steps_left = 0;
|
SmoothingStyle::Linear(time) | SmoothingStyle::Logarithmic(time) => {
|
||||||
} else {
|
(sample_rate * time / 1000.0).round() as u32
|
||||||
self.steps_left = match self.style {
|
}
|
||||||
SmoothingStyle::None => 1,
|
};
|
||||||
SmoothingStyle::Linear(time) | SmoothingStyle::Logarithmic(time) => {
|
self.step_size = match self.style {
|
||||||
(sample_rate * time / 1000.0).round() as u32
|
SmoothingStyle::None => 0.0,
|
||||||
}
|
SmoothingStyle::Linear(_) => {
|
||||||
};
|
(self.target as f32 - self.current) / self.steps_left as f32
|
||||||
self.step_size = match self.style {
|
}
|
||||||
SmoothingStyle::None => 0.0,
|
SmoothingStyle::Logarithmic(_) => {
|
||||||
SmoothingStyle::Linear(_) => {
|
nih_debug_assert_ne!(self.current, 0.0);
|
||||||
(self.target as f32 - self.current) / self.steps_left as f32
|
(self.target as f32 / self.current).powf((self.steps_left as f32).recip())
|
||||||
}
|
}
|
||||||
SmoothingStyle::Logarithmic(_) => {
|
};
|
||||||
nih_debug_assert_ne!(self.current, 0.0);
|
|
||||||
(self.target as f32 / self.current).powf((self.steps_left as f32).recip())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::should_implement_trait)]
|
#[allow(clippy::should_implement_trait)]
|
||||||
|
@ -186,12 +190,12 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn linear_f32_smoothing() {
|
fn linear_f32_smoothing() {
|
||||||
let mut smoother: Smoother<f32> = Smoother::new(SmoothingStyle::Linear(100.0));
|
let mut smoother: Smoother<f32> = Smoother::new(SmoothingStyle::Linear(100.0));
|
||||||
smoother.set_target(100.0, 10.0, true);
|
smoother.reset(10.0);
|
||||||
assert_eq!(smoother.next(), 10.0);
|
assert_eq!(smoother.next(), 10.0);
|
||||||
|
|
||||||
// Instead of testing the actual values, we'll make sure that we reach the target values at
|
// Instead of testing the actual values, we'll make sure that we reach the target values at
|
||||||
// the expected time.
|
// the expected time.
|
||||||
smoother.set_target(100.0, 20.0, false);
|
smoother.set_target(100.0, 20.0);
|
||||||
for _ in 0..(10 - 2) {
|
for _ in 0..(10 - 2) {
|
||||||
dbg!(smoother.next());
|
dbg!(smoother.next());
|
||||||
}
|
}
|
||||||
|
@ -202,11 +206,11 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn linear_i32_smoothing() {
|
fn linear_i32_smoothing() {
|
||||||
let mut smoother: Smoother<i32> = Smoother::new(SmoothingStyle::Linear(100.0));
|
let mut smoother: Smoother<i32> = Smoother::new(SmoothingStyle::Linear(100.0));
|
||||||
smoother.set_target(100.0, 10, true);
|
smoother.reset(10);
|
||||||
assert_eq!(smoother.next(), 10);
|
assert_eq!(smoother.next(), 10);
|
||||||
|
|
||||||
// Integers are rounded, but with these values we can still test this
|
// Integers are rounded, but with these values we can still test this
|
||||||
smoother.set_target(100.0, 20, false);
|
smoother.set_target(100.0, 20);
|
||||||
for _ in 0..(10 - 2) {
|
for _ in 0..(10 - 2) {
|
||||||
dbg!(smoother.next());
|
dbg!(smoother.next());
|
||||||
}
|
}
|
||||||
|
@ -217,12 +221,12 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn logarithmic_f32_smoothing() {
|
fn logarithmic_f32_smoothing() {
|
||||||
let mut smoother: Smoother<f32> = Smoother::new(SmoothingStyle::Logarithmic(100.0));
|
let mut smoother: Smoother<f32> = Smoother::new(SmoothingStyle::Logarithmic(100.0));
|
||||||
smoother.set_target(100.0, 10.0, true);
|
smoother.reset(10.0);
|
||||||
assert_eq!(smoother.next(), 10.0);
|
assert_eq!(smoother.next(), 10.0);
|
||||||
|
|
||||||
// Instead of testing the actual values, we'll make sure that we reach the target values at
|
// Instead of testing the actual values, we'll make sure that we reach the target values at
|
||||||
// the expected time.
|
// the expected time.
|
||||||
smoother.set_target(100.0, 20.0, false);
|
smoother.set_target(100.0, 20.0);
|
||||||
for _ in 0..(10 - 2) {
|
for _ in 0..(10 - 2) {
|
||||||
dbg!(smoother.next());
|
dbg!(smoother.next());
|
||||||
}
|
}
|
||||||
|
@ -233,11 +237,11 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn logarithmic_i32_smoothing() {
|
fn logarithmic_i32_smoothing() {
|
||||||
let mut smoother: Smoother<i32> = Smoother::new(SmoothingStyle::Logarithmic(100.0));
|
let mut smoother: Smoother<i32> = Smoother::new(SmoothingStyle::Logarithmic(100.0));
|
||||||
smoother.set_target(100.0, 10, true);
|
smoother.reset(10);
|
||||||
assert_eq!(smoother.next(), 10);
|
assert_eq!(smoother.next(), 10);
|
||||||
|
|
||||||
// Integers are rounded, but with these values we can still test this
|
// Integers are rounded, but with these values we can still test this
|
||||||
smoother.set_target(100.0, 20, false);
|
smoother.set_target(100.0, 20);
|
||||||
for _ in 0..(10 - 2) {
|
for _ in 0..(10 - 2) {
|
||||||
dbg!(smoother.next());
|
dbg!(smoother.next());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue