use crate::core::{AudioFrame, AudioResult, AudioSpec};
use crate::mic_sim::contracts::MicrophoneSimProcessor;
pub struct SaturationProcessor {
amount: f32,
}
impl SaturationProcessor {
pub fn new(amount: f32) -> Self {
Self {
amount: amount.clamp(0.0, 0.2),
}
}
}
impl MicrophoneSimProcessor for SaturationProcessor {
fn name(&self) -> &'static str {
"saturation"
}
fn prepare(&mut self, _spec: AudioSpec) -> AudioResult<()> {
Ok(())
}
fn process(&mut self, frame: &mut AudioFrame) -> AudioResult<()> {
if self.amount <= f32::EPSILON {
return Ok(());
}
let drive = 1.0 + self.amount * 2.4;
let output_trim = 1.0 + self.amount * 0.6;
for sample in &mut frame.samples {
*sample = ((*sample * drive).tanh() / output_trim).clamp(-1.0, 1.0);
}
Ok(())
}
}