use fon::chan::{Ch32, Channel};
#[derive(Debug, Clone, Copy, Default)]
pub struct Gate {
level: f32,
hold: f32,
}
impl Gate {
#[inline(always)]
pub fn new() -> Self {
Self::default()
}
#[inline(always)]
pub fn step(&mut self, gate: &GateParams) -> Ch32 {
if gate.key.to_f32() >= gate.open_threshold.to_f32() {
self.level = if gate.attack == 0.0 {
0.0
} else {
(self.level - (1.0 / 48_000.0) / gate.attack).max(0.0)
};
self.hold = f32::INFINITY;
}
if gate.key.to_f32() < gate.close_threshold.to_f32() {
if self.hold == f32::INFINITY {
self.hold = gate.hold;
}
if self.hold == 0.0 {
self.level = if gate.release == 0.0 {
1.0
} else {
(self.level + (1.0 / 48_000.0) / gate.release).min(1.0)
};
}
}
if self.hold != f32::INFINITY {
self.hold = (self.hold - (1.0 / 48_000.0)).max(0.0);
}
let level = 1.0 - gate.range.to_f32() * self.level;
Ch32::from(level * gate.input.to_f32())
}
}
#[derive(Debug, Copy, Clone)]
pub struct GateParams {
pub input: Ch32,
pub key: Ch32,
pub range: Ch32,
pub open_threshold: Ch32,
pub close_threshold: Ch32,
pub attack: f32,
pub hold: f32,
pub release: f32,
}