lavende-core 0.1.0

Core in-process Discord voice connection and playback engine
Documentation
pub mod standard {
use flume::Sender;
use super::Engine;
use crate::audio::AudioFrame;
pub struct StandardEngine {
    frame_tx: Sender<AudioFrame>,
}
impl StandardEngine {
    pub fn new(frame_tx: Sender<AudioFrame>) -> Self {
        Self { frame_tx }
    }
}
impl Engine for StandardEngine {
    fn push(&mut self, frame: AudioFrame) -> bool {
        self.frame_tx.send(frame).is_ok()
    }
}
}
pub mod encoder {
use audiopus::{Application, Bitrate, Channels, SampleRate, coder::Encoder as OpusEncoder};
use crate::common::types::AnyResult;
pub struct Encoder {
    encoder: OpusEncoder,
}
impl Encoder {
    pub fn new() -> AnyResult<Self> {
        let mut encoder =
            OpusEncoder::new(SampleRate::Hz48000, Channels::Stereo, Application::Audio)
                .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
        encoder
            .set_bitrate(Bitrate::Auto)
            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
        Ok(Self { encoder })
    }
    pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> AnyResult<usize> {
        let size = self
            .encoder
            .encode(input, output)
            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
        Ok(size)
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_encoder_new() {
        let result = Encoder::new();
        assert!(result.is_ok(), "Encoder creation should succeed");
    }
    #[test]
    fn test_encoder_encode_silence() {
        let mut encoder = Encoder::new().unwrap();
        let input = vec![0i16; 960 * 2]; 
        let mut output = vec![0u8; 4000];
        let result = encoder.encode(&input, &mut output);
        assert!(result.is_ok(), "Encoding silence should succeed");
        let size = result.unwrap();
        assert!(size > 0, "Encoded size should be greater than 0");
        assert!(
            size < output.len(),
            "Encoded size should be less than buffer"
        );
    }
    #[test]
    fn test_encoder_encode_tone() {
        let mut encoder = Encoder::new().unwrap();
        let mut input = vec![0i16; 960 * 2];
        for (i, sample) in input.iter_mut().enumerate() {
            let t = (i / 2) as f32 / 48000.0;
            *sample = (10000.0 * (2.0 * std::f32::consts::PI * 440.0 * t).sin()) as i16;
        }
        let mut output = vec![0u8; 4000];
        let result = encoder.encode(&input, &mut output);
        assert!(result.is_ok(), "Encoding tone should succeed");
        let size = result.unwrap();
        assert!(size > 0, "Encoded size should be greater than 0");
    }
    #[test]
    fn test_encoder_encode_max_amplitude() {
        let mut encoder = Encoder::new().unwrap();
        let input = vec![i16::MAX; 960 * 2];
        let mut output = vec![0u8; 4000];
        let result = encoder.encode(&input, &mut output);
        assert!(result.is_ok(), "Encoding max amplitude should succeed");
        assert!(result.unwrap() > 0);
    }
    #[test]
    fn test_encoder_encode_min_amplitude() {
        let mut encoder = Encoder::new().unwrap();
        let input = vec![i16::MIN; 960 * 2];
        let mut output = vec![0u8; 4000];
        let result = encoder.encode(&input, &mut output);
        assert!(result.is_ok(), "Encoding min amplitude should succeed");
        assert!(result.unwrap() > 0);
    }
    #[test]
    fn test_encoder_encode_multiple_frames() {
        let mut encoder = Encoder::new().unwrap();
        let input = vec![1000i16; 960 * 2];
        let mut output = vec![0u8; 4000];
        for _ in 0..5 {
            let result = encoder.encode(&input, &mut output);
            assert!(result.is_ok(), "Multiple encodings should succeed");
            assert!(result.unwrap() > 0);
        }
    }
    #[test]
    fn test_encoder_output_varies_with_input() {
        let mut encoder1 = Encoder::new().unwrap();
        let mut output1 = vec![0u8; 4000];
        let silence = vec![0i16; 960 * 2];
        let size1 = encoder1.encode(&silence, &mut output1).unwrap();
        let mut encoder2 = Encoder::new().unwrap();
        let mut output2 = vec![0u8; 4000];
        let tone = vec![5000i16; 960 * 2];
        let size2 = encoder2.encode(&tone, &mut output2).unwrap();
        assert!(size1 > 0);
        assert!(size2 > 0);
        assert_ne!(
            &output1[..size1],
            &output2[..size2],
            "Encoded silence and tone payloads should differ"
        );
    }
}
}
pub use encoder::Encoder;
pub use standard::StandardEngine;
use crate::audio::frame::AudioFrame;
pub trait Engine: Send {
    fn push(&mut self, frame: AudioFrame) -> bool;
}
pub type BoxedEngine = Box<dyn Engine>;