1use std::fmt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5#[repr(i32)]
6pub enum Channel {
7 FrontLeft = 0,
8 FrontRight = 1,
9 FrontCenter = 2,
10 LowFrequency = 3,
11 BackLeft = 4,
12 BackRight = 5,
13 FrontLeftOfCenter = 6,
14 FrontRightOfCenter = 7,
15 BackCenter = 8,
16 SideLeft = 9,
17 SideRight = 10,
18 TopCenter = 11,
19 TopFrontLeft = 12,
20 TopFrontCenter = 13,
21 TopFrontRight = 14,
22 TopBackLeft = 15,
23 TopBackCenter = 16,
24 TopBackRight = 17,
25 StereoLeft = 29,
26 StereoRight = 30,
27 WideLeft = 31,
28 WideRight = 32,
29 SurroundDirectLeft = 33,
30 SurroundDirectRight = 34,
31 LowFrequency2 = 35,
32 TopSideLeft = 36,
33 TopSideRight = 37,
34 BottomFrontCenter = 38,
35 BottomFrontLeft = 39,
36 BottomFrontRight = 40,
37 BinauralLeft = 61,
38 BinauralRight = 62,
39}
40
41impl Channel {
42 pub fn name(self) -> &'static str {
43 match self {
44 Channel::FrontLeft => "FL",
45 Channel::FrontRight => "FR",
46 Channel::FrontCenter => "FC",
47 Channel::LowFrequency => "LFE",
48 Channel::BackLeft => "BL",
49 Channel::BackRight => "BR",
50 Channel::FrontLeftOfCenter => "FLC",
51 Channel::FrontRightOfCenter => "FRC",
52 Channel::BackCenter => "BC",
53 Channel::SideLeft => "SL",
54 Channel::SideRight => "SR",
55 Channel::TopCenter => "TC",
56 Channel::TopFrontLeft => "TFL",
57 Channel::TopFrontCenter => "TFC",
58 Channel::TopFrontRight => "TFR",
59 Channel::TopBackLeft => "TBL",
60 Channel::TopBackCenter => "TBC",
61 Channel::TopBackRight => "TBR",
62 Channel::StereoLeft => "DL",
63 Channel::StereoRight => "DR",
64 Channel::WideLeft => "WL",
65 Channel::WideRight => "WR",
66 Channel::SurroundDirectLeft => "SDL",
67 Channel::SurroundDirectRight => "SDR",
68 Channel::LowFrequency2 => "LFE2",
69 Channel::TopSideLeft => "TSL",
70 Channel::TopSideRight => "TSR",
71 Channel::BottomFrontCenter => "BFC",
72 Channel::BottomFrontLeft => "BFL",
73 Channel::BottomFrontRight => "BFR",
74 Channel::BinauralLeft => "BinL",
75 Channel::BinauralRight => "BinR",
76 }
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum ChannelOrder {
83 Native,
86 Custom,
88 Unspec,
90}
91
92#[derive(Debug, Clone)]
94pub struct ChannelLayout {
95 pub order: ChannelOrder,
96 pub nb_channels: i32,
97 pub channels: Vec<Channel>,
98}
99
100impl ChannelLayout {
101 pub fn mono() -> Self {
103 Self {
104 order: ChannelOrder::Native,
105 nb_channels: 1,
106 channels: vec![Channel::FrontCenter],
107 }
108 }
109
110 pub fn stereo() -> Self {
112 Self {
113 order: ChannelOrder::Native,
114 nb_channels: 2,
115 channels: vec![Channel::FrontLeft, Channel::FrontRight],
116 }
117 }
118
119 pub fn surround_5_1() -> Self {
121 Self {
122 order: ChannelOrder::Native,
123 nb_channels: 6,
124 channels: vec![
125 Channel::FrontLeft,
126 Channel::FrontRight,
127 Channel::FrontCenter,
128 Channel::LowFrequency,
129 Channel::BackLeft,
130 Channel::BackRight,
131 ],
132 }
133 }
134
135 pub fn surround_7_1() -> Self {
137 Self {
138 order: ChannelOrder::Native,
139 nb_channels: 8,
140 channels: vec![
141 Channel::FrontLeft,
142 Channel::FrontRight,
143 Channel::FrontCenter,
144 Channel::LowFrequency,
145 Channel::BackLeft,
146 Channel::BackRight,
147 Channel::SideLeft,
148 Channel::SideRight,
149 ],
150 }
151 }
152
153 pub fn unspec(nb_channels: i32) -> Self {
155 Self {
156 order: ChannelOrder::Unspec,
157 nb_channels,
158 channels: Vec::new(),
159 }
160 }
161
162 pub fn from_wav_channel_mask(mask: u32) -> Self {
177 const WAV_CHANNELS: [(u32, Channel); 18] = [
178 (1 << 0, Channel::FrontLeft),
179 (1 << 1, Channel::FrontRight),
180 (1 << 2, Channel::FrontCenter),
181 (1 << 3, Channel::LowFrequency),
182 (1 << 4, Channel::BackLeft),
183 (1 << 5, Channel::BackRight),
184 (1 << 6, Channel::FrontLeftOfCenter),
185 (1 << 7, Channel::FrontRightOfCenter),
186 (1 << 8, Channel::BackCenter),
187 (1 << 9, Channel::SideLeft),
188 (1 << 10, Channel::SideRight),
189 (1 << 11, Channel::TopCenter),
190 (1 << 12, Channel::TopFrontLeft),
191 (1 << 13, Channel::TopFrontCenter),
192 (1 << 14, Channel::TopFrontRight),
193 (1 << 15, Channel::TopBackLeft),
194 (1 << 16, Channel::TopBackCenter),
195 (1 << 17, Channel::TopBackRight),
196 ];
197
198 if mask == 0 {
199 return Self::unspec(0);
200 }
201
202 let mut channels = Vec::new();
203 for &(bit, channel) in &WAV_CHANNELS {
204 if mask & bit != 0 {
205 channels.push(channel);
206 }
207 }
208
209 let nb_channels = channels.len() as i32;
210 Self {
211 order: ChannelOrder::Native,
212 nb_channels,
213 channels,
214 }
215 }
216}
217
218impl fmt::Display for ChannelLayout {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 if self.channels.is_empty() {
221 return write!(f, "{} channels", self.nb_channels);
222 }
223 if let Some(name) = self.standard_name() {
225 return write!(f, "{name}");
226 }
227 let names: Vec<&str> = self.channels.iter().map(|c| c.name()).collect();
228 write!(f, "{}", names.join("+"))
229 }
230}
231
232impl ChannelLayout {
233 pub fn standard_name(&self) -> Option<&'static str> {
239 use Channel::*;
240 match self.channels.as_slice() {
241 [FrontCenter] => Some("mono"),
243 [FrontLeft, FrontRight] => Some("stereo"),
245 [FrontLeft, FrontRight, LowFrequency] => Some("2.1"),
247 [FrontLeft, FrontRight, FrontCenter] => Some("3.0"),
249 [FrontLeft, FrontRight, BackCenter] => Some("3.0(back)"),
251 [FrontLeft, FrontRight, FrontCenter, BackCenter] => Some("4.0"),
253 [FrontLeft, FrontRight, BackLeft, BackRight] => Some("quad"),
255 [FrontLeft, FrontRight, SideLeft, SideRight] => Some("quad(side)"),
257 [FrontLeft, FrontRight, FrontCenter, LowFrequency] => Some("3.1"),
259 [FrontLeft, FrontRight, FrontCenter, BackLeft, BackRight] => Some("5.0"),
261 [FrontLeft, FrontRight, FrontCenter, SideLeft, SideRight] => Some("5.0(side)"),
263 [FrontLeft, FrontRight, FrontCenter, LowFrequency, BackCenter] => Some("4.1"),
265 [
267 FrontLeft,
268 FrontRight,
269 FrontCenter,
270 LowFrequency,
271 BackLeft,
272 BackRight,
273 ] => Some("5.1"),
274 [
276 FrontLeft,
277 FrontRight,
278 FrontCenter,
279 LowFrequency,
280 SideLeft,
281 SideRight,
282 ] => Some("5.1(side)"),
283 [
285 FrontLeft,
286 FrontRight,
287 FrontCenter,
288 BackCenter,
289 SideLeft,
290 SideRight,
291 ] => Some("6.0"),
292 [
294 FrontLeft,
295 FrontRight,
296 FrontLeftOfCenter,
297 FrontRightOfCenter,
298 SideLeft,
299 SideRight,
300 ] => Some("6.0(front)"),
301 [
303 FrontLeft,
304 FrontRight,
305 FrontCenter,
306 LowFrequency,
307 TopFrontLeft,
308 TopFrontRight,
309 ] => Some("3.1.2"),
310 [
312 FrontLeft,
313 FrontRight,
314 FrontCenter,
315 BackLeft,
316 BackRight,
317 BackCenter,
318 ] => Some("hexagonal"),
319 [
321 FrontLeft,
322 FrontRight,
323 FrontCenter,
324 LowFrequency,
325 BackCenter,
326 SideLeft,
327 SideRight,
328 ] => Some("6.1"),
329 [
331 FrontLeft,
332 FrontRight,
333 FrontCenter,
334 LowFrequency,
335 BackLeft,
336 BackRight,
337 BackCenter,
338 ] => Some("6.1(back)"),
339 [
341 FrontLeft,
342 FrontRight,
343 LowFrequency,
344 FrontLeftOfCenter,
345 FrontRightOfCenter,
346 SideLeft,
347 SideRight,
348 ] => Some("6.1(front)"),
349 [
351 FrontLeft,
352 FrontRight,
353 FrontCenter,
354 BackLeft,
355 BackRight,
356 SideLeft,
357 SideRight,
358 ] => Some("7.0"),
359 [
361 FrontLeft,
362 FrontRight,
363 FrontCenter,
364 FrontLeftOfCenter,
365 FrontRightOfCenter,
366 SideLeft,
367 SideRight,
368 ] => Some("7.0(front)"),
369 [
371 FrontLeft,
372 FrontRight,
373 FrontCenter,
374 LowFrequency,
375 BackLeft,
376 BackRight,
377 SideLeft,
378 SideRight,
379 ] => Some("7.1"),
380 [
382 FrontLeft,
383 FrontRight,
384 FrontCenter,
385 LowFrequency,
386 BackLeft,
387 BackRight,
388 FrontLeftOfCenter,
389 FrontRightOfCenter,
390 ] => Some("7.1(wide)"),
391 [
393 FrontLeft,
394 FrontRight,
395 FrontCenter,
396 LowFrequency,
397 FrontLeftOfCenter,
398 FrontRightOfCenter,
399 SideLeft,
400 SideRight,
401 ] => Some("7.1(wide-side)"),
402 [
404 FrontLeft,
405 FrontRight,
406 FrontCenter,
407 LowFrequency,
408 SideLeft,
409 SideRight,
410 TopFrontLeft,
411 TopFrontRight,
412 ] => Some("5.1.2"),
413 [
415 FrontLeft,
416 FrontRight,
417 FrontCenter,
418 LowFrequency,
419 BackLeft,
420 BackRight,
421 TopFrontLeft,
422 TopFrontRight,
423 ] => Some("5.1.2(back)"),
424 [
426 FrontLeft,
427 FrontRight,
428 FrontCenter,
429 BackLeft,
430 BackRight,
431 BackCenter,
432 SideLeft,
433 SideRight,
434 ] => Some("octagonal"),
435 [
437 FrontLeft,
438 FrontRight,
439 BackLeft,
440 BackRight,
441 TopFrontLeft,
442 TopFrontRight,
443 TopBackLeft,
444 TopBackRight,
445 ] => Some("cube"),
446 [
448 FrontLeft,
449 FrontRight,
450 FrontCenter,
451 LowFrequency,
452 SideLeft,
453 SideRight,
454 TopFrontLeft,
455 TopFrontRight,
456 TopBackLeft,
457 TopBackRight,
458 ] => Some("5.1.4"),
459 [
461 FrontLeft,
462 FrontRight,
463 FrontCenter,
464 LowFrequency,
465 BackLeft,
466 BackRight,
467 SideLeft,
468 SideRight,
469 TopFrontLeft,
470 TopFrontRight,
471 ] => Some("7.1.2"),
472 [
474 FrontLeft,
475 FrontRight,
476 FrontCenter,
477 LowFrequency,
478 BackLeft,
479 BackRight,
480 SideLeft,
481 SideRight,
482 TopFrontLeft,
483 TopFrontRight,
484 TopBackLeft,
485 TopBackRight,
486 ] => Some("7.1.4"),
487 [
489 FrontLeft,
490 FrontRight,
491 FrontCenter,
492 LowFrequency,
493 BackLeft,
494 BackRight,
495 SideLeft,
496 SideRight,
497 TopFrontLeft,
498 TopFrontRight,
499 TopBackCenter,
500 LowFrequency2,
501 ] => Some("7.2.3"),
502 [
504 FrontLeft,
505 FrontRight,
506 FrontCenter,
507 LowFrequency,
508 BackLeft,
509 BackRight,
510 FrontLeftOfCenter,
511 FrontRightOfCenter,
512 SideLeft,
513 SideRight,
514 TopFrontLeft,
515 TopFrontRight,
516 TopBackLeft,
517 TopBackRight,
518 ] => Some("9.1.4"),
519 [
521 FrontLeft,
522 FrontRight,
523 FrontCenter,
524 LowFrequency,
525 BackLeft,
526 BackRight,
527 FrontLeftOfCenter,
528 FrontRightOfCenter,
529 SideLeft,
530 SideRight,
531 TopFrontLeft,
532 TopFrontRight,
533 TopBackLeft,
534 TopBackRight,
535 TopSideLeft,
536 TopSideRight,
537 ] => Some("9.1.6"),
538 [
540 FrontLeft,
541 FrontRight,
542 FrontCenter,
543 BackLeft,
544 BackRight,
545 BackCenter,
546 SideLeft,
547 SideRight,
548 TopFrontLeft,
549 TopFrontCenter,
550 TopFrontRight,
551 TopBackLeft,
552 TopBackCenter,
553 TopBackRight,
554 WideLeft,
555 WideRight,
556 ] => Some("hexadecagonal"),
557 [StereoLeft, StereoRight] => Some("downmix"),
559 [BinauralLeft, BinauralRight] => Some("binaural"),
561 [
563 FrontLeft,
564 FrontRight,
565 FrontCenter,
566 LowFrequency,
567 BackLeft,
568 BackRight,
569 FrontLeftOfCenter,
570 FrontRightOfCenter,
571 BackCenter,
572 SideLeft,
573 SideRight,
574 TopCenter,
575 TopFrontLeft,
576 TopFrontCenter,
577 TopFrontRight,
578 TopBackLeft,
579 TopBackCenter,
580 TopBackRight,
581 LowFrequency2,
582 TopSideLeft,
583 TopSideRight,
584 BottomFrontCenter,
585 BottomFrontLeft,
586 BottomFrontRight,
587 ] => Some("22.2"),
588 _ => None,
589 }
590 }
591}