Skip to main content

lavende_core/audio/
engine.rs

1pub mod standard {
2    use super::Engine;
3    use crate::audio::AudioFrame;
4    use flume::Sender;
5    pub struct StandardEngine {
6        frame_tx: Sender<AudioFrame>,
7    }
8    impl StandardEngine {
9        pub fn new(frame_tx: Sender<AudioFrame>) -> Self {
10            Self { frame_tx }
11        }
12    }
13    impl Engine for StandardEngine {
14        fn push(&mut self, frame: AudioFrame) -> bool {
15            self.frame_tx.send(frame).is_ok()
16        }
17    }
18}
19pub mod encoder {
20    use crate::common::types::AnyResult;
21    use audiopus::{Application, Bitrate, Channels, SampleRate, coder::Encoder as OpusEncoder};
22    pub struct Encoder {
23        encoder: OpusEncoder,
24    }
25    impl Encoder {
26        pub fn new() -> AnyResult<Self> {
27            let mut encoder =
28                OpusEncoder::new(SampleRate::Hz48000, Channels::Stereo, Application::Audio)
29                    .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
30            encoder
31                .set_bitrate(Bitrate::Auto)
32                .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
33            Ok(Self { encoder })
34        }
35        pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> AnyResult<usize> {
36            let size = self
37                .encoder
38                .encode(input, output)
39                .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
40            Ok(size)
41        }
42    }
43    #[cfg(test)]
44    mod tests {
45        use super::*;
46        #[test]
47        fn test_encoder_new() {
48            let result = Encoder::new();
49            assert!(result.is_ok(), "Encoder creation should succeed");
50        }
51        #[test]
52        fn test_encoder_encode_silence() {
53            let mut encoder = Encoder::new().unwrap();
54            let input = vec![0i16; 960 * 2];
55            let mut output = vec![0u8; 4000];
56            let result = encoder.encode(&input, &mut output);
57            assert!(result.is_ok(), "Encoding silence should succeed");
58            let size = result.unwrap();
59            assert!(size > 0, "Encoded size should be greater than 0");
60            assert!(
61                size < output.len(),
62                "Encoded size should be less than buffer"
63            );
64        }
65        #[test]
66        fn test_encoder_encode_tone() {
67            let mut encoder = Encoder::new().unwrap();
68            let mut input = vec![0i16; 960 * 2];
69            for (i, sample) in input.iter_mut().enumerate() {
70                let t = (i / 2) as f32 / 48000.0;
71                *sample = (10000.0 * (2.0 * std::f32::consts::PI * 440.0 * t).sin()) as i16;
72            }
73            let mut output = vec![0u8; 4000];
74            let result = encoder.encode(&input, &mut output);
75            assert!(result.is_ok(), "Encoding tone should succeed");
76            let size = result.unwrap();
77            assert!(size > 0, "Encoded size should be greater than 0");
78        }
79        #[test]
80        fn test_encoder_encode_max_amplitude() {
81            let mut encoder = Encoder::new().unwrap();
82            let input = vec![i16::MAX; 960 * 2];
83            let mut output = vec![0u8; 4000];
84            let result = encoder.encode(&input, &mut output);
85            assert!(result.is_ok(), "Encoding max amplitude should succeed");
86            assert!(result.unwrap() > 0);
87        }
88        #[test]
89        fn test_encoder_encode_min_amplitude() {
90            let mut encoder = Encoder::new().unwrap();
91            let input = vec![i16::MIN; 960 * 2];
92            let mut output = vec![0u8; 4000];
93            let result = encoder.encode(&input, &mut output);
94            assert!(result.is_ok(), "Encoding min amplitude should succeed");
95            assert!(result.unwrap() > 0);
96        }
97        #[test]
98        fn test_encoder_encode_multiple_frames() {
99            let mut encoder = Encoder::new().unwrap();
100            let input = vec![1000i16; 960 * 2];
101            let mut output = vec![0u8; 4000];
102            for _ in 0..5 {
103                let result = encoder.encode(&input, &mut output);
104                assert!(result.is_ok(), "Multiple encodings should succeed");
105                assert!(result.unwrap() > 0);
106            }
107        }
108        #[test]
109        fn test_encoder_output_varies_with_input() {
110            let mut encoder1 = Encoder::new().unwrap();
111            let mut output1 = vec![0u8; 4000];
112            let silence = vec![0i16; 960 * 2];
113            let size1 = encoder1.encode(&silence, &mut output1).unwrap();
114            let mut encoder2 = Encoder::new().unwrap();
115            let mut output2 = vec![0u8; 4000];
116            let tone = vec![5000i16; 960 * 2];
117            let size2 = encoder2.encode(&tone, &mut output2).unwrap();
118            assert!(size1 > 0);
119            assert!(size2 > 0);
120            assert_ne!(
121                &output1[..size1],
122                &output2[..size2],
123                "Encoded silence and tone payloads should differ"
124            );
125        }
126    }
127}
128use crate::audio::frame::AudioFrame;
129pub use encoder::Encoder;
130pub use standard::StandardEngine;
131pub trait Engine: Send {
132    fn push(&mut self, frame: AudioFrame) -> bool;
133}
134pub type BoxedEngine = Box<dyn Engine>;