aboutsummaryrefslogtreecommitdiffstats
path: root/mumd/src/audio/transformers.rs
blob: 91cf3ac7055e1fedc3b308487fa273c52cfdcc72 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/// A trait that represents a transform of a audio buffer in some way.
pub trait Transformer {
    /// Do the transform. Returning `None` is interpreted as "the buffer is unwanted".
    /// The implementor is free to modify the buffer however it wants to.
    fn transform<'a>(&mut self, buf: (opus::Channels, &'a mut [f32])) -> Option<(opus::Channels, &'a mut [f32])>;
}

/// A struct representing a noise gate transform.
pub struct NoiseGate {
    alltime_high: f32,
    open: usize,
    deactivation_delay: usize,
}

impl NoiseGate {
    /// Create a new noise gate. `deactivation_delay` is defined in terms of
    /// how many quiet frames it receives before closing the noise gate.
    pub fn new(deactivation_delay: usize) -> Self {
        Self {
            alltime_high: 0.0,
            open: 0,
            deactivation_delay,
        }
    }
}

impl Transformer for NoiseGate {
    fn transform<'a>(&mut self, (channels, buf): (opus::Channels, &'a mut [f32])) -> Option<(opus::Channels, &'a mut [f32])> {
        const MUTE_PERCENTAGE: f32 = 0.1;

        let max = buf.iter().map(|e| e.abs()).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();

        if max > self.alltime_high {
            self.alltime_high = max;
        }

        if max > self.alltime_high * MUTE_PERCENTAGE {
            self.open = self.deactivation_delay;
        } else if self.open > 0 {
            self.open -= 1;
        }

        if self.open == 0 {
            None
        } else {
            Some((channels, buf))
        }
    }
}