voice_engine/media/codecs/
g729.rs

1use super::{Decoder, Encoder};
2use crate::media::{PcmBuf, Sample};
3
4const L_FRAME: usize = 80; // 10ms frame at 8kHz
5const L_FRAME_COMPRESSED: usize = 10; // G.729 frame size in bytes
6
7/// G.729 audio decoder using g729-sys
8pub struct G729Decoder {
9    decoder: g729_sys::Decoder,
10}
11
12impl G729Decoder {
13    /// Create a new G.729 decoder instance
14    pub fn new() -> Self {
15        Self {
16            decoder: g729_sys::Decoder::new().expect("Failed to create g729 decoder"),
17        }
18    }
19}
20
21unsafe impl Send for G729Decoder {}
22unsafe impl Sync for G729Decoder {}
23
24impl Decoder for G729Decoder {
25    fn decode(&mut self, data: &[u8]) -> PcmBuf {
26        if data.is_empty() {
27            return vec![];
28        }
29
30        // G.729 processes 10-byte frames
31        let mut output = Vec::new();
32        let mut pos = 0;
33
34        while pos + L_FRAME_COMPRESSED <= data.len() {
35            let frame_data = &data[pos..pos + L_FRAME_COMPRESSED];
36            // g729-sys: decode(frame, bfi, vad, dtx) -> [i16;80]
37            let decoded_frame = self.decoder.decode(frame_data, false, false, false);
38            output.extend_from_slice(&decoded_frame);
39
40            pos += L_FRAME_COMPRESSED;
41        }
42
43        output
44    }
45
46    fn sample_rate(&self) -> u32 {
47        8000 // G.729 operates at 8kHz
48    }
49
50    fn channels(&self) -> u16 {
51        1 // G.729 is always mono
52    }
53}
54
55/// G.729 audio encoder using g729-sys
56pub struct G729Encoder {
57    encoder: g729_sys::Encoder,
58}
59
60impl G729Encoder {
61    /// Create a new G.729 encoder instance
62    pub fn new() -> Self {
63        Self {
64            // The argument typically enables/disables Annex B (VAD/DTX). Use false by default.
65            encoder: g729_sys::Encoder::new(false).expect("Failed to create g729 encoder"),
66        }
67    }
68}
69
70unsafe impl Send for G729Encoder {}
71unsafe impl Sync for G729Encoder {}
72
73impl Encoder for G729Encoder {
74    fn encode(&mut self, samples: &[Sample]) -> Vec<u8> {
75        if samples.is_empty() {
76            return vec![];
77        }
78
79        let mut output = Vec::new();
80        let mut pos = 0;
81
82        // Process samples in 80-sample (10ms @ 8kHz) frames
83        while pos + L_FRAME <= samples.len() {
84            let mut frame_arr = [0i16; L_FRAME];
85            frame_arr.copy_from_slice(&samples[pos..pos + L_FRAME]);
86
87            let encoded_frame = self.encoder.encode(&frame_arr);
88            output.extend_from_slice(&encoded_frame);
89
90            pos += L_FRAME;
91        }
92
93        output
94    }
95
96    fn sample_rate(&self) -> u32 {
97        8000 // G.729 operates at 8kHz
98    }
99
100    fn channels(&self) -> u16 {
101        1 // G.729 is always mono
102    }
103}