1pub type Sample = i16;
2pub type PcmBuf = Vec<Sample>;
3
4pub mod g722;
5pub mod g729;
6#[cfg(feature = "opus")]
7pub mod opus;
8pub mod pcma;
9pub mod pcmu;
10pub mod resampler;
11pub mod telephone_event;
12pub use resampler::{Resampler, resample};
13
14#[derive(Debug, Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
15pub enum CodecType {
16 PCMU,
17 PCMA,
18 G722,
19 G729,
20 #[cfg(feature = "opus")]
21 Opus,
22 TelephoneEvent,
23}
24
25pub trait Decoder: Send + Sync {
26 fn decode(&mut self, data: &[u8]) -> PcmBuf;
28
29 fn sample_rate(&self) -> u32;
31
32 fn channels(&self) -> u16;
34}
35
36pub trait Encoder: Send + Sync {
37 fn encode(&mut self, samples: &[Sample]) -> Vec<u8>;
39
40 fn sample_rate(&self) -> u32;
42
43 fn channels(&self) -> u16;
45}
46
47pub fn create_decoder(codec: CodecType) -> Box<dyn Decoder> {
48 match codec {
49 CodecType::PCMU => Box::new(pcmu::PcmuDecoder::new()),
50 CodecType::PCMA => Box::new(pcma::PcmaDecoder::new()),
51 CodecType::G722 => Box::new(g722::G722Decoder::new()),
52 CodecType::G729 => Box::new(g729::G729Decoder::new()),
53 #[cfg(feature = "opus")]
54 CodecType::Opus => Box::new(opus::OpusDecoder::new_default()),
55 CodecType::TelephoneEvent => Box::new(telephone_event::TelephoneEventDecoder::new()),
56 }
57}
58
59pub fn create_encoder(codec: CodecType) -> Box<dyn Encoder> {
60 match codec {
61 CodecType::PCMU => Box::new(pcmu::PcmuEncoder::new()),
62 CodecType::PCMA => Box::new(pcma::PcmaEncoder::new()),
63 CodecType::G722 => Box::new(g722::G722Encoder::new()),
64 CodecType::G729 => Box::new(g729::G729Encoder::new()),
65 #[cfg(feature = "opus")]
66 CodecType::Opus => Box::new(opus::OpusEncoder::new_default()),
67 CodecType::TelephoneEvent => Box::new(telephone_event::TelephoneEventEncoder::new()),
68 }
69}
70
71impl CodecType {
72 pub fn mime_type(&self) -> &str {
73 match self {
74 CodecType::PCMU => "audio/PCMU",
75 CodecType::PCMA => "audio/PCMA",
76 CodecType::G722 => "audio/G722",
77 CodecType::G729 => "audio/G729",
78 #[cfg(feature = "opus")]
79 CodecType::Opus => "audio/opus",
80 CodecType::TelephoneEvent => "audio/telephone-event",
81 }
82 }
83 pub fn rtpmap(&self) -> &str {
84 match self {
85 CodecType::PCMU => "PCMU/8000",
86 CodecType::PCMA => "PCMA/8000",
87 CodecType::G722 => "G722/8000",
88 CodecType::G729 => "G729/8000",
89 #[cfg(feature = "opus")]
90 CodecType::Opus => "opus/48000/2",
91 CodecType::TelephoneEvent => "telephone-event/8000",
92 }
93 }
94 pub fn fmtp(&self) -> Option<&str> {
95 match self {
96 CodecType::PCMU => None,
97 CodecType::PCMA => None,
98 CodecType::G722 => None,
99 CodecType::G729 => None,
100 #[cfg(feature = "opus")]
101 CodecType::Opus => Some("minptime=10;useinbandfec=1"),
102 CodecType::TelephoneEvent => Some("0-16"),
103 }
104 }
105
106 pub fn clock_rate(&self) -> u32 {
107 match self {
108 CodecType::PCMU => 8000,
109 CodecType::PCMA => 8000,
110 CodecType::G722 => 8000,
111 CodecType::G729 => 8000,
112 #[cfg(feature = "opus")]
113 CodecType::Opus => 48000,
114 CodecType::TelephoneEvent => 8000,
115 }
116 }
117
118 pub fn channels(&self) -> u16 {
119 match self {
120 #[cfg(feature = "opus")]
121 CodecType::Opus => 2,
122 _ => 1,
123 }
124 }
125
126 pub fn payload_type(&self) -> u8 {
127 match self {
128 CodecType::PCMU => 0,
129 CodecType::PCMA => 8,
130 CodecType::G722 => 9,
131 CodecType::G729 => 18,
132 #[cfg(feature = "opus")]
133 CodecType::Opus => 111,
134 CodecType::TelephoneEvent => 101,
135 }
136 }
137 pub fn samplerate(&self) -> u32 {
138 match self {
139 CodecType::PCMU => 8000,
140 CodecType::PCMA => 8000,
141 CodecType::G722 => 16000,
142 CodecType::G729 => 8000,
143 #[cfg(feature = "opus")]
144 CodecType::Opus => 48000,
145 CodecType::TelephoneEvent => 8000,
146 }
147 }
148 pub fn is_audio(&self) -> bool {
149 match self {
150 CodecType::PCMU | CodecType::PCMA | CodecType::G722 => true,
151 CodecType::G729 => true,
152 #[cfg(feature = "opus")]
153 CodecType::Opus => true,
154 _ => false,
155 }
156 }
157
158 pub fn is_dynamic(&self) -> bool {
159 match self {
160 #[cfg(feature = "opus")]
161 CodecType::Opus => true,
162 CodecType::TelephoneEvent => true,
163 _ => false,
164 }
165 }
166}
167
168impl TryFrom<u8> for CodecType {
169 type Error = anyhow::Error;
170
171 fn try_from(value: u8) -> Result<Self, Self::Error> {
172 match value {
173 0 => Ok(CodecType::PCMU),
174 8 => Ok(CodecType::PCMA),
175 9 => Ok(CodecType::G722),
176 18 => Ok(CodecType::G729), 101 => Ok(CodecType::TelephoneEvent),
179 #[cfg(feature = "opus")]
180 111 => Ok(CodecType::Opus), _ => Err(anyhow::anyhow!("Invalid codec type: {}", value)),
182 }
183 }
184}
185
186impl TryFrom<&str> for CodecType {
187 type Error = anyhow::Error;
188
189 fn try_from(name: &str) -> Result<Self, Self::Error> {
190 match name.to_lowercase().as_str() {
191 "pcmu" | "ulaw" => Ok(CodecType::PCMU),
192 "pcma" | "alaw" => Ok(CodecType::PCMA),
193 "g722" => Ok(CodecType::G722),
194 "g729" => Ok(CodecType::G729),
195 #[cfg(feature = "opus")]
196 "opus" => Ok(CodecType::Opus),
197 "telephone-event" => Ok(CodecType::TelephoneEvent),
198 _ => Err(anyhow::anyhow!("Invalid codec name: {}", name)),
199 }
200 }
201}
202
203#[cfg(target_endian = "little")]
204pub fn samples_to_bytes(samples: &[Sample]) -> Vec<u8> {
205 unsafe {
206 std::slice::from_raw_parts(
207 samples.as_ptr() as *const u8,
208 samples.len() * std::mem::size_of::<Sample>(),
209 )
210 .to_vec()
211 }
212}
213
214#[cfg(target_endian = "big")]
215pub fn samples_to_bytes(samples: &[Sample]) -> Vec<u8> {
216 samples.iter().flat_map(|s| s.to_le_bytes()).collect()
217}
218
219#[cfg(target_endian = "little")]
220pub fn bytes_to_samples(u8_data: &[u8]) -> PcmBuf {
221 unsafe {
222 std::slice::from_raw_parts(
223 u8_data.as_ptr() as *const Sample,
224 u8_data.len() / std::mem::size_of::<Sample>(),
225 )
226 .to_vec()
227 }
228}
229#[cfg(target_endian = "big")]
230pub fn bytes_to_samples(u8_data: &[u8]) -> PcmBuf {
231 u8_data
232 .chunks(2)
233 .map(|chunk| (chunk[0] as i16) | ((chunk[1] as i16) << 8))
234 .collect()
235}