codec_core/codecs/g711/
mod.rs1use crate::error::CodecError;
62
63mod reference;
64
65#[cfg(test)]
66pub mod tests;
67
68pub use reference::{alaw_compress, alaw_expand, ulaw_compress, ulaw_expand};
70
71pub struct G711Codec {
73 variant: G711Variant,
74 frame_size: usize,
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq)]
79pub enum G711Variant {
80 ALaw,
82 MuLaw,
84}
85
86impl G711Codec {
87 pub fn new(variant: G711Variant) -> Self {
89 Self {
90 variant,
91 frame_size: 160, }
93 }
94
95 pub fn new_with_config(
97 variant: G711Variant,
98 config: crate::types::CodecConfig,
99 ) -> Result<Self, CodecError> {
100 if config.sample_rate.hz() != 8000 {
102 return Err(CodecError::InvalidSampleRate {
103 rate: config.sample_rate.hz(),
104 supported: vec![8000],
105 });
106 }
107
108 if config.channels != 1 {
110 return Err(CodecError::InvalidChannelCount {
111 channels: config.channels,
112 supported: vec![1],
113 });
114 }
115
116 let frame_size = if let Some(frame_ms) = config.frame_size_ms {
118 let samples_per_ms = 8000.0 / 1000.0; (samples_per_ms * frame_ms) as usize
120 } else {
121 160 };
123
124 let valid_sizes = [80, 160, 240, 320];
126 if !valid_sizes.contains(&frame_size) {
127 return Err(CodecError::InvalidFrameSize {
128 expected: 160,
129 actual: frame_size,
130 });
131 }
132
133 Ok(Self {
134 variant,
135 frame_size,
136 })
137 }
138
139 pub fn new_pcmu(config: crate::types::CodecConfig) -> Result<Self, CodecError> {
141 Self::new_with_config(G711Variant::MuLaw, config)
142 }
143
144 pub fn new_pcma(config: crate::types::CodecConfig) -> Result<Self, CodecError> {
146 Self::new_with_config(G711Variant::ALaw, config)
147 }
148
149 pub fn variant(&self) -> G711Variant {
151 self.variant
152 }
153
154 pub fn compress(&self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
156 match self.variant {
157 G711Variant::ALaw => Ok(samples
158 .iter()
159 .map(|&sample| alaw_compress(sample))
160 .collect()),
161 G711Variant::MuLaw => Ok(samples
162 .iter()
163 .map(|&sample| ulaw_compress(sample))
164 .collect()),
165 }
166 }
167
168 pub fn expand(&self, compressed: &[u8]) -> Result<Vec<i16>, CodecError> {
170 match self.variant {
171 G711Variant::ALaw => Ok(compressed
172 .iter()
173 .map(|&sample| alaw_expand(sample))
174 .collect()),
175 G711Variant::MuLaw => Ok(compressed
176 .iter()
177 .map(|&sample| ulaw_expand(sample))
178 .collect()),
179 }
180 }
181
182 pub fn compress_alaw(&self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
184 Ok(samples
185 .iter()
186 .map(|&sample| alaw_compress(sample))
187 .collect())
188 }
189
190 pub fn expand_alaw(&self, compressed: &[u8]) -> Result<Vec<i16>, CodecError> {
192 Ok(compressed
193 .iter()
194 .map(|&sample| alaw_expand(sample))
195 .collect())
196 }
197
198 pub fn compress_ulaw(&self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
200 Ok(samples
201 .iter()
202 .map(|&sample| ulaw_compress(sample))
203 .collect())
204 }
205
206 pub fn expand_ulaw(&self, compressed: &[u8]) -> Result<Vec<i16>, CodecError> {
208 Ok(compressed
209 .iter()
210 .map(|&sample| ulaw_expand(sample))
211 .collect())
212 }
213}
214
215impl crate::types::AudioCodec for G711Codec {
217 fn encode(&mut self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
218 self.compress(samples)
219 }
220
221 fn decode(&mut self, data: &[u8]) -> Result<Vec<i16>, CodecError> {
222 self.expand(data)
223 }
224
225 fn info(&self) -> crate::types::CodecInfo {
226 let (name, payload_type) = match self.variant {
227 G711Variant::ALaw => ("PCMA", Some(8)),
228 G711Variant::MuLaw => ("PCMU", Some(0)),
229 };
230
231 crate::types::CodecInfo {
232 name,
233 sample_rate: 8000,
234 channels: 1,
235 bitrate: 64000,
236 frame_size: self.frame_size,
237 payload_type,
238 }
239 }
240
241 fn reset(&mut self) -> Result<(), CodecError> {
242 Ok(())
244 }
245
246 fn frame_size(&self) -> usize {
247 self.frame_size
248 }
249
250 fn supports_variable_frame_size(&self) -> bool {
251 true
252 }
253}
254
255impl crate::types::AudioCodecExt for G711Codec {
257 fn encode_to_buffer(
258 &mut self,
259 samples: &[i16],
260 output: &mut [u8],
261 ) -> Result<usize, CodecError> {
262 if output.len() < samples.len() {
263 return Err(CodecError::BufferTooSmall {
264 needed: samples.len(),
265 actual: output.len(),
266 });
267 }
268
269 match self.variant {
270 G711Variant::ALaw => {
271 for (i, &sample) in samples.iter().enumerate() {
272 output[i] = alaw_compress(sample);
273 }
274 }
275 G711Variant::MuLaw => {
276 for (i, &sample) in samples.iter().enumerate() {
277 output[i] = ulaw_compress(sample);
278 }
279 }
280 }
281
282 Ok(samples.len())
283 }
284
285 fn decode_to_buffer(&mut self, data: &[u8], output: &mut [i16]) -> Result<usize, CodecError> {
286 if output.len() < data.len() {
287 return Err(CodecError::BufferTooSmall {
288 needed: data.len(),
289 actual: output.len(),
290 });
291 }
292
293 match self.variant {
294 G711Variant::ALaw => {
295 for (i, &encoded) in data.iter().enumerate() {
296 output[i] = alaw_expand(encoded);
297 }
298 }
299 G711Variant::MuLaw => {
300 for (i, &encoded) in data.iter().enumerate() {
301 output[i] = ulaw_expand(encoded);
302 }
303 }
304 }
305
306 Ok(data.len())
307 }
308
309 fn max_encoded_size(&self, input_samples: usize) -> usize {
310 input_samples }
312
313 fn max_decoded_size(&self, input_bytes: usize) -> usize {
314 input_bytes }
316}
317
318pub fn init_tables() {
320 }