use crate::dsp::audio_buffer::{AudioBuffer, AudioEffectState, AudioSettings};
const NUM_INTERPOLATION_FRAMES: usize = 4;
pub struct GainEffectParameters {
pub gain: f32,
}
pub struct GainEffect {
frame_size: usize,
previous_gain: f32,
first_frame: bool,
}
impl GainEffect {
pub fn new(audio_settings: AudioSettings) -> Self {
Self {
frame_size: audio_settings.frame_size,
previous_gain: 0.0,
first_frame: true,
}
}
pub(crate) fn reset(&mut self) {
self.previous_gain = 0.0;
self.first_frame = true;
}
pub fn apply(
&mut self,
parameters: GainEffectParameters,
input: &AudioBuffer<1>,
output: &mut AudioBuffer<1>,
) -> AudioEffectState {
if self.first_frame {
output.0[0] = input.0[0].iter().map(|x| x * parameters.gain).collect();
self.previous_gain = parameters.gain;
self.first_frame = false;
} else {
let target_gain = self.previous_gain
+ (1.0 / NUM_INTERPOLATION_FRAMES as f32) * (parameters.gain - self.previous_gain);
let mut current_gain = self.previous_gain;
let d_gain = (target_gain - self.previous_gain) / self.frame_size as f32;
output.0[0] = input.0[0]
.iter()
.map(|x| {
let sample = current_gain * x;
current_gain += d_gain;
sample
})
.collect();
self.previous_gain = target_gain;
}
AudioEffectState::TailComplete
}
#[expect(dead_code)]
pub(crate) fn tail_apply(
&mut self,
input: &AudioBuffer<1>,
output: &mut AudioBuffer<1>,
) -> AudioEffectState {
let previous_params = GainEffectParameters {
gain: self.previous_gain,
};
self.apply(previous_params, input, output)
}
#[expect(dead_code)]
pub(crate) fn tail(output: &mut AudioBuffer<1>) -> AudioEffectState {
output.make_silent();
AudioEffectState::TailComplete
}
}