use std::fmt::{Debug, Display};
use crate::utils::smoothing::{ExponentialSmoothedValue, SmoothedValue};
use super::{FloatParameter, ParameterValueUpdate};
#[derive(Debug, Clone)]
pub struct SmoothedParameterValue<Value: SmoothedValue = ExponentialSmoothedValue> {
description: FloatParameter,
value: Value,
}
impl<Value: SmoothedValue> SmoothedParameterValue<Value> {
pub fn from_description(description: FloatParameter) -> Self
where
Value: From<f32>,
{
let value = Value::from(description.default_value());
Self { value, description }
}
pub fn with_smoother(mut self, value: Value) -> Self {
self.value = value;
self.value.init(self.description.default_value());
self
}
pub fn description(&self) -> &FloatParameter {
&self.description
}
pub fn set_sample_rate(&mut self, sample_rate: u32) {
self.value.set_sample_rate(sample_rate)
}
pub fn value_need_ramp(&self) -> bool {
self.value.need_ramp()
}
#[inline(always)]
pub fn next_value(&mut self) -> f32 {
self.value.next()
}
#[inline(always)]
pub fn current_value(&self) -> f32 {
self.value.current()
}
#[inline(always)]
pub fn target_value(&self) -> f32 {
self.value.target()
}
#[inline]
pub fn set_target_value(&mut self, value: f32) {
assert!(
self.description.range().contains(&value),
"Value out of bounds"
);
self.value.set_target(value);
}
#[inline]
pub fn set_target_value_clamped(&mut self, value: f32) {
self.value.set_target(self.description.clamp_value(value));
}
pub fn process(&mut self, output: &mut [f32]) -> bool {
if !self.value_need_ramp() {
output.fill(self.value.target());
false
} else {
for value in output {
*value = self.value.next();
}
true
}
}
#[inline]
pub fn init_value(&mut self, value: f32) {
assert!(
self.description.range().contains(&value),
"Value out of bounds"
);
self.value.init(value);
}
#[inline]
pub fn init_value_clamped(&mut self, value: f32) {
self.value.init(self.description.clamp_value(value));
}
pub fn apply_update(&mut self, update: &ParameterValueUpdate) {
match update {
ParameterValueUpdate::Raw(raw) => {
if let Some(value) = raw.downcast_ref::<f32>() {
self.set_target_value_clamped(*value);
} else if let Some(value) = raw.downcast_ref::<f64>() {
self.set_target_value_clamped(*value as f32);
} else {
log::warn!(
"Invalid value type for float parameter '{}'",
self.description.id()
);
}
}
ParameterValueUpdate::Normalized(normalized) => {
let value = self
.description
.denormalize_value(normalized.clamp(0.0, 1.0));
self.set_target_value(value);
}
}
}
}
impl<Value: SmoothedValue> From<FloatParameter> for SmoothedParameterValue<Value>
where
Value: From<f32>,
{
fn from(description: FloatParameter) -> Self {
Self::from_description(description)
}
}
impl<Value: SmoothedValue> Display for SmoothedParameterValue<Value> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let include_unit = true;
f.write_str(
&self
.description
.value_to_string(self.value.target(), include_unit),
)
}
}