1use std::fmt;
4use std::string::*;
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8pub struct Soniton {
9 pub bits: u8,
11 pub be: bool,
13 pub packed: bool,
15 pub planar: bool,
19 pub float: bool,
21 pub signed: bool,
23}
24
25fn align(v: usize, a: usize) -> usize {
28 (v + a - 1) & !(a - 1)
29}
30
31fn round_to_byte(v: usize) -> usize {
34 (v + 7) >> 3
35}
36
37impl Soniton {
38 pub fn new(bits: u8, be: bool, packed: bool, planar: bool, float: bool, signed: bool) -> Self {
40 Soniton {
41 bits,
42 be,
43 packed,
44 planar,
45 float,
46 signed,
47 }
48 }
49
50 pub fn get_audio_size(self, length: usize, alignment: usize) -> usize {
53 let s = if self.packed {
54 round_to_byte(length * (self.bits as usize))
55 } else {
56 length * round_to_byte(self.bits as usize)
57 };
58
59 align(s, alignment)
60 }
61}
62
63impl fmt::Display for Soniton {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 let fmt = if self.float {
66 "float"
67 } else if self.signed {
68 "int"
69 } else {
70 "uint"
71 };
72 let end = if self.be { "BE" } else { "LE" };
73 write!(
74 f,
75 "({} bps, {} planar: {} packed: {} {})",
76 self.bits, end, self.packed, self.planar, fmt
77 )
78 }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83#[allow(clippy::upper_case_acronyms)]
84pub enum ChannelType {
85 C,
87 L,
89 R,
91 Cs,
93 Ls,
95 Rs,
97 Lss,
99 Rss,
101 LFE,
103 Lc,
105 Rc,
107 Lh,
109 Rh,
111 Ch,
113 LFE2,
115 Lw,
117 Rw,
119 Ov,
125 Lhs,
127 Rhs,
129 Chs,
131 Ll,
134 Rl,
137 Cl,
140 Lt,
142 Rt,
144 Lo,
146 Ro,
148}
149
150impl ChannelType {
151 pub fn is_center(self) -> bool {
153 matches!(
154 self,
155 ChannelType::C
156 | ChannelType::Ch
157 | ChannelType::Cl
158 | ChannelType::Ov
159 | ChannelType::LFE
160 | ChannelType::LFE2
161 | ChannelType::Cs
162 | ChannelType::Chs
163 )
164 }
165
166 pub fn is_left(self) -> bool {
168 matches!(
169 self,
170 ChannelType::L
171 | ChannelType::Ls
172 | ChannelType::Lss
173 | ChannelType::Lc
174 | ChannelType::Lh
175 | ChannelType::Lw
176 | ChannelType::Lhs
177 | ChannelType::Ll
178 | ChannelType::Lt
179 | ChannelType::Lo
180 )
181 }
182
183 pub fn is_right(self) -> bool {
185 matches!(
186 self,
187 ChannelType::R
188 | ChannelType::Rs
189 | ChannelType::Rss
190 | ChannelType::Rc
191 | ChannelType::Rh
192 | ChannelType::Rw
193 | ChannelType::Rhs
194 | ChannelType::Rl
195 | ChannelType::Rt
196 | ChannelType::Ro
197 )
198 }
199}
200
201impl fmt::Display for ChannelType {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 let name = match *self {
204 ChannelType::C => "C".to_string(),
205 ChannelType::L => "L".to_string(),
206 ChannelType::R => "R".to_string(),
207 ChannelType::Cs => "Cs".to_string(),
208 ChannelType::Ls => "Ls".to_string(),
209 ChannelType::Rs => "Rs".to_string(),
210 ChannelType::Lss => "Lss".to_string(),
211 ChannelType::Rss => "Rss".to_string(),
212 ChannelType::LFE => "LFE".to_string(),
213 ChannelType::Lc => "Lc".to_string(),
214 ChannelType::Rc => "Rc".to_string(),
215 ChannelType::Lh => "Lh".to_string(),
216 ChannelType::Rh => "Rh".to_string(),
217 ChannelType::Ch => "Ch".to_string(),
218 ChannelType::LFE2 => "LFE2".to_string(),
219 ChannelType::Lw => "Lw".to_string(),
220 ChannelType::Rw => "Rw".to_string(),
221 ChannelType::Ov => "Ov".to_string(),
222 ChannelType::Lhs => "Lhs".to_string(),
223 ChannelType::Rhs => "Rhs".to_string(),
224 ChannelType::Chs => "Chs".to_string(),
225 ChannelType::Ll => "Ll".to_string(),
226 ChannelType::Rl => "Rl".to_string(),
227 ChannelType::Cl => "Cl".to_string(),
228 ChannelType::Lt => "Lt".to_string(),
229 ChannelType::Rt => "Rt".to_string(),
230 ChannelType::Lo => "Lo".to_string(),
231 ChannelType::Ro => "Ro".to_string(),
232 };
233 write!(f, "{}", name)
234 }
235}
236
237#[derive(Clone, Debug, PartialEq, Eq, Default)]
239pub struct ChannelMap {
240 ids: Vec<ChannelType>,
241}
242
243impl ChannelMap {
244 pub fn new() -> Self {
246 ChannelMap { ids: Vec::new() }
247 }
248
249 pub fn add_channel(&mut self, ch: ChannelType) {
251 self.ids.push(ch);
252 }
253
254 pub fn add_channels(&mut self, chs: &[ChannelType]) {
256 for ch in chs {
257 self.ids.push(*ch);
258 }
259 }
260
261 pub fn len(&self) -> usize {
263 self.ids.len()
264 }
265
266 pub fn is_empty(&self) -> bool {
268 self.ids.is_empty()
269 }
270
271 pub fn get_channel(&self, idx: usize) -> ChannelType {
273 self.ids[idx]
274 }
275
276 pub fn find_channel_id(&self, t: ChannelType) -> Option<u8> {
278 for i in 0..self.ids.len() {
279 if self.ids[i] as i32 == t as i32 {
280 return Some(i as u8);
281 }
282 }
283 None
284 }
285
286 pub fn default_map(count: usize) -> Self {
298 use self::ChannelType::*;
299 let ids = match count {
300 1 => vec![C],
301 2 => vec![R, L],
302 _ => unimplemented!(),
303 };
304
305 ChannelMap { ids }
306 }
307}
308
309pub mod formats {
311 use super::*;
312
313 pub const U8: Soniton = Soniton {
315 bits: 8,
316 be: false,
317 packed: false,
318 planar: false,
319 float: false,
320 signed: false,
321 };
322
323 pub const S16: Soniton = Soniton {
325 bits: 16,
326 be: false,
327 packed: false,
328 planar: false,
329 float: false,
330 signed: true,
331 };
332
333 pub const S32: Soniton = Soniton {
335 bits: 32,
336 be: false,
337 packed: false,
338 planar: false,
339 float: false,
340 signed: true,
341 };
342
343 pub const F32: Soniton = Soniton {
345 bits: 32,
346 be: false,
347 packed: false,
348 planar: false,
349 float: true,
350 signed: true,
351 };
352
353 pub const F64: Soniton = Soniton {
355 bits: 64,
356 be: false,
357 packed: false,
358 planar: false,
359 float: true,
360 signed: true,
361 };
362}
363
364#[cfg(test)]
365mod test {
366 use super::*;
367
368 #[test]
369 fn fmt() {
370 println!("{}", formats::S16);
371 println!("{}", formats::U8);
372 println!("{}", formats::F32);
373 }
374}