mum_cli/audio/
transformers.rs

1/// A trait that represents a transform of an audio buffer in some way.
2pub trait Transformer {
3    /// Do the transform. Returning `None` is interpreted as "the buffer is unwanted".
4    /// The implementor is free to modify the buffer however it wants to.
5    fn transform<'a>(
6        &mut self,
7        buf: (opus::Channels, &'a mut [f32]),
8    ) -> Option<(opus::Channels, &'a mut [f32])>;
9}
10
11/// A struct representing a noise gate transform.
12#[derive(Debug)]
13pub struct NoiseGate {
14    alltime_high: f32,
15    open: usize,
16    deactivation_delay: usize,
17}
18
19impl NoiseGate {
20    /// Create a new noise gate. `deactivation_delay` is defined in terms of
21    /// how many quiet frames it receives before closing the noise gate.
22    pub fn new(deactivation_delay: usize) -> Self {
23        Self {
24            alltime_high: 0.0,
25            open: 0,
26            deactivation_delay,
27        }
28    }
29}
30
31impl Transformer for NoiseGate {
32    fn transform<'a>(
33        &mut self,
34        (channels, buf): (opus::Channels, &'a mut [f32]),
35    ) -> Option<(opus::Channels, &'a mut [f32])> {
36        const MUTE_PERCENTAGE: f32 = 0.1;
37
38        let max = buf
39            .iter()
40            .map(|e| e.abs())
41            .max_by(|a, b| a.partial_cmp(b).unwrap())
42            .unwrap();
43
44        if max > self.alltime_high {
45            self.alltime_high = max;
46        }
47
48        if max > self.alltime_high * MUTE_PERCENTAGE {
49            self.open = self.deactivation_delay;
50        } else if self.open > 0 {
51            self.open -= 1;
52        }
53
54        if self.open == 0 {
55            None
56        } else {
57            Some((channels, buf))
58        }
59    }
60}