mum-cli 0.5.1

Core functionality to build a Mumble client.
Documentation
/// A trait that represents a transform of an 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.
#[derive(Debug)]
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))
        }
    }
}