brainvision 0.0.1

Rust library and TUI for Brain Products BrainVision RDA EEG streams over TCP/IP
Documentation
//! DSP helpers for BrainVision streams.

/// Simple EEG band-power container.
#[derive(Debug, Clone, Copy, Default)]
pub struct BandPowers {
    pub delta: f64,
    pub theta: f64,
    pub alpha: f64,
    pub beta: f64,
    pub gamma: f64,
}

impl BandPowers {
    pub fn as_array(&self) -> [f64; 5] {
        [self.delta, self.theta, self.alpha, self.beta, self.gamma]
    }
    pub fn normalised(&self) -> Self {
        let t = self.delta + self.theta + self.alpha + self.beta + self.gamma;
        if t == 0.0 {
            return *self;
        }
        Self {
            delta: self.delta / t,
            theta: self.theta / t,
            alpha: self.alpha / t,
            beta: self.beta / t,
            gamma: self.gamma / t,
        }
    }
}

/// Exponential moving average smoother.
#[derive(Debug, Clone)]
pub struct Ema {
    alpha: f64,
    value: Option<f64>,
}

impl Ema {
    pub fn new(alpha: f64) -> Self {
        assert!(alpha > 0.0 && alpha <= 1.0);
        Self { alpha, value: None }
    }
    pub fn update(&mut self, x: f64) -> f64 {
        let y = match self.value {
            None => x,
            Some(v) => self.alpha * x + (1.0 - self.alpha) * v,
        };
        self.value = Some(y);
        y
    }
    pub fn get(&self) -> f64 {
        self.value.unwrap_or(0.0)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_normalised() {
        let n = BandPowers {
            delta: 1.0,
            theta: 1.0,
            alpha: 1.0,
            beta: 1.0,
            gamma: 1.0,
        }
        .normalised();
        for v in n.as_array() {
            assert!((v - 0.2).abs() < 1e-9);
        }
    }

    #[test]
    fn test_ema() {
        let mut e = Ema::new(0.5);
        assert_eq!(e.update(1.0), 1.0);
        assert!((e.update(0.0) - 0.5).abs() < 1e-9);
    }
}