#[derive(Clone)]
pub struct StereoLimiter {
    threshold: f32,
    knee_width: f32,
}

impl StereoLimiter {
    pub fn new(threshold: f32, knee_width: f32) -> Self {
        StereoLimiter {
            threshold,
            knee_width,
        }
    }

    pub fn update(&mut self, knee_width: f32, threshold: f32) {
        self.threshold = threshold;
        self.knee_width = knee_width;
    }

    pub fn process(&self, left_in: f32, right_in: f32) -> (f32, f32) {
        let left_gain = self.limit(left_in);
        let right_gain = self.limit(right_in);
        (left_gain, right_gain)
    }

    pub fn limit(&self, input: f32) -> f32 {
        let knee_range = self.knee_width / 2.0;
        let soft_threshold = self.threshold + knee_range;

        if input.abs() > soft_threshold {
            let gain_reduction = (input.abs() - soft_threshold) / knee_range;
            let gain = 1.0 / (1.0 + gain_reduction);
            gain * input.signum() * soft_threshold.abs()
        } else {
            input
        }
    }
}
