You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.4 KiB
89 lines
2.4 KiB
use crate::beep::hack::StableClamp;
|
|
use std::time::Duration;
|
|
|
|
/// Scale function amplitude by a gain
|
|
pub trait GainScale {
|
|
fn scale_gain(self, gain: f32) -> Self;
|
|
}
|
|
|
|
impl GainScale for f32 {
|
|
/// Scale by gain 0-1
|
|
fn scale_gain(self, gain: f32) -> Self {
|
|
// TODO what scaling to use?
|
|
// self * (1.0 + gain * 9.0).log10()
|
|
// self * gain.sqrt()
|
|
self * gain
|
|
}
|
|
}
|
|
|
|
|
|
/// Value fader
|
|
#[derive(Clone,Debug)]
|
|
pub(crate) struct Tween {
|
|
/// Actual value
|
|
pub actual: f32,
|
|
/// Target value, approached by adding "step" to :actual" every sample
|
|
pub target: f32,
|
|
/// Value added to "actual" per sample. None = set to target at the end of a cycle
|
|
pub step: Option<f32>,
|
|
// Min value
|
|
pub min: f32,
|
|
// Max value
|
|
pub max: f32,
|
|
/// Sample rate, used to calculate time based effects
|
|
pub sample_rate : f32,
|
|
}
|
|
|
|
|
|
impl Tween {
|
|
/// Update values for the next sample
|
|
pub fn tick(&mut self) {
|
|
if let Some(step) = self.step {
|
|
let actual0 = self.actual;
|
|
self.actual += step;
|
|
if (self.target > actual0 && self.target <= self.actual)
|
|
|| (self.target <= actual0 && self.target > self.actual)
|
|
{
|
|
self.step = None;
|
|
self.actual = self.target;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Get actual value
|
|
pub fn actual(&self) -> f32 {
|
|
self.actual
|
|
}
|
|
|
|
/// Check if the change from actual to target is scheduled to happen instantly
|
|
/// at the end of a cycle.
|
|
pub fn is_change_scheduled_at_crossover(&self) -> bool {
|
|
self.target != self.actual
|
|
&& self.step.is_none()
|
|
}
|
|
|
|
/// Check if the fading is in progress
|
|
pub fn is_fading(&self) -> bool {
|
|
self.step.is_some()
|
|
}
|
|
|
|
/// Schedule change at crossover
|
|
pub(crate) fn set_at_crossover(&mut self, val: f32) {
|
|
self.target = val.clamp_(self.min, self.max);
|
|
self.step = None; // change at the earliest convenience
|
|
}
|
|
|
|
/// Start fading
|
|
pub(crate) fn fade(&mut self, val: f32, time: Duration) {
|
|
self.target = val.clamp_(self.min, self.max);
|
|
let nsamples = (time.as_secs_f32() * self.sample_rate).ceil();
|
|
self.step = Some((self.target - self.actual) / nsamples);
|
|
}
|
|
|
|
/// Set value immediately
|
|
pub(crate) fn set_immediate(&mut self, val: f32) {
|
|
self.target = val.clamp_(self.min, self.max);
|
|
self.actual = self.target;
|
|
self.step = None;
|
|
}
|
|
}
|
|
|