codec_core/codecs/g711/
mod.rs1use crate::error::CodecError;
62
63mod reference;
64mod tables;
65
66#[cfg(test)]
67pub mod tests;
68
69pub use reference::{
71 alaw_compress, alaw_expand, ulaw_compress, ulaw_expand
72};
73
74pub struct G711Codec {
76 variant: G711Variant,
77 frame_size: usize,
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum G711Variant {
83 ALaw,
85 MuLaw,
87}
88
89impl G711Codec {
90 pub fn new(variant: G711Variant) -> Self {
92 Self {
93 variant,
94 frame_size: 160, }
96 }
97
98 pub fn new_with_config(variant: G711Variant, config: crate::types::CodecConfig) -> 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 { variant, frame_size })
134 }
135
136 pub fn new_pcmu(config: crate::types::CodecConfig) -> Result<Self, CodecError> {
138 Self::new_with_config(G711Variant::MuLaw, config)
139 }
140
141 pub fn new_pcma(config: crate::types::CodecConfig) -> Result<Self, CodecError> {
143 Self::new_with_config(G711Variant::ALaw, config)
144 }
145
146 pub fn variant(&self) -> G711Variant {
148 self.variant
149 }
150
151 pub fn compress(&self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
153 match self.variant {
154 G711Variant::ALaw => Ok(samples.iter().map(|&sample| alaw_compress(sample)).collect()),
155 G711Variant::MuLaw => Ok(samples.iter().map(|&sample| ulaw_compress(sample)).collect()),
156 }
157 }
158
159 pub fn expand(&self, compressed: &[u8]) -> Result<Vec<i16>, CodecError> {
161 match self.variant {
162 G711Variant::ALaw => Ok(compressed.iter().map(|&sample| alaw_expand(sample)).collect()),
163 G711Variant::MuLaw => Ok(compressed.iter().map(|&sample| ulaw_expand(sample)).collect()),
164 }
165 }
166
167 pub fn compress_alaw(&self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
169 Ok(samples.iter().map(|&sample| alaw_compress(sample)).collect())
170 }
171
172 pub fn expand_alaw(&self, compressed: &[u8]) -> Result<Vec<i16>, CodecError> {
174 Ok(compressed.iter().map(|&sample| alaw_expand(sample)).collect())
175 }
176
177 pub fn compress_ulaw(&self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
179 Ok(samples.iter().map(|&sample| ulaw_compress(sample)).collect())
180 }
181
182 pub fn expand_ulaw(&self, compressed: &[u8]) -> Result<Vec<i16>, CodecError> {
184 Ok(compressed.iter().map(|&sample| ulaw_expand(sample)).collect())
185 }
186}
187
188impl crate::types::AudioCodec for G711Codec {
190 fn encode(&mut self, samples: &[i16]) -> Result<Vec<u8>, CodecError> {
191 self.compress(samples)
192 }
193
194 fn decode(&mut self, data: &[u8]) -> Result<Vec<i16>, CodecError> {
195 self.expand(data)
196 }
197
198 fn info(&self) -> crate::types::CodecInfo {
199 let (name, payload_type) = match self.variant {
200 G711Variant::ALaw => ("PCMA", Some(8)),
201 G711Variant::MuLaw => ("PCMU", Some(0)),
202 };
203
204 crate::types::CodecInfo {
205 name,
206 sample_rate: 8000,
207 channels: 1,
208 bitrate: 64000,
209 frame_size: self.frame_size,
210 payload_type,
211 }
212 }
213
214 fn reset(&mut self) -> Result<(), CodecError> {
215 Ok(())
217 }
218
219 fn frame_size(&self) -> usize {
220 self.frame_size
221 }
222
223 fn supports_variable_frame_size(&self) -> bool {
224 true
225 }
226}
227
228impl crate::types::AudioCodecExt for G711Codec {
230 fn encode_to_buffer(&mut self, samples: &[i16], output: &mut [u8]) -> Result<usize, CodecError> {
231 if output.len() < samples.len() {
232 return Err(CodecError::BufferTooSmall { needed: samples.len(), actual: output.len() });
233 }
234
235 match self.variant {
236 G711Variant::ALaw => {
237 for (i, &sample) in samples.iter().enumerate() {
238 output[i] = alaw_compress(sample);
239 }
240 }
241 G711Variant::MuLaw => {
242 for (i, &sample) in samples.iter().enumerate() {
243 output[i] = ulaw_compress(sample);
244 }
245 }
246 }
247
248 Ok(samples.len())
249 }
250
251 fn decode_to_buffer(&mut self, data: &[u8], output: &mut [i16]) -> Result<usize, CodecError> {
252 if output.len() < data.len() {
253 return Err(CodecError::BufferTooSmall { needed: data.len(), actual: output.len() });
254 }
255
256 match self.variant {
257 G711Variant::ALaw => {
258 for (i, &encoded) in data.iter().enumerate() {
259 output[i] = alaw_expand(encoded);
260 }
261 }
262 G711Variant::MuLaw => {
263 for (i, &encoded) in data.iter().enumerate() {
264 output[i] = ulaw_expand(encoded);
265 }
266 }
267 }
268
269 Ok(data.len())
270 }
271
272 fn max_encoded_size(&self, input_samples: usize) -> usize {
273 input_samples }
275
276 fn max_decoded_size(&self, input_bytes: usize) -> usize {
277 input_bytes }
279}
280
281pub fn init_tables() {
283 }