1use crate::*;
2
3ext! {
4 name: PcmC,
5 versions: [0],
6 flags: {}
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct PcmC {
12 pub big_endian: bool,
13 pub sample_size: u8,
14}
15
16impl AtomExt for PcmC {
17 const KIND_EXT: FourCC = FourCC::new(b"pcmC");
18
19 type Ext = PcmCExt;
20
21 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: PcmCExt) -> Result<Self> {
22 let format_flags = u8::decode(buf)?;
23 let sample_size = u8::decode(buf)?;
24
25 Ok(Self {
26 big_endian: format_flags == 0,
27 sample_size,
28 })
29 }
30
31 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<PcmCExt> {
32 let mut format_flags = 0u8;
33 if !self.big_endian {
34 format_flags = 1u8;
35 }
36
37 format_flags.encode(buf)?;
38 self.sample_size.encode(buf)?;
39
40 Ok(PcmCExt {
41 version: PcmCVersion::V0,
42 })
43 }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51pub struct PcmFormat {
52 pub big_endian: bool,
54 pub sample_size: u16,
56 pub float: bool,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
62pub struct Pcm {
63 pub fourcc: FourCC,
64 pub audio: Audio,
65 pub pcmc: Option<PcmC>,
66 pub chnl: Option<Chnl>,
67 pub btrt: Option<Btrt>,
68}
69
70impl Pcm {
71 fn encode_fields<B: BufMut>(
72 fourcc: FourCC,
73 audio: &Audio,
74 pcmc: Option<&PcmC>,
75 chnl: Option<&Chnl>,
76 btrt: Option<&Btrt>,
77 buf: &mut B,
78 ) -> Result<()> {
79 if pcmc.is_none() && Self::requires_pcmc(fourcc) {
81 return Err(Error::MissingBox(PcmC::KIND));
82 }
83
84 audio.encode(buf)?;
85
86 if let Some(pcmc) = pcmc {
87 pcmc.encode(buf)?;
88 }
89
90 if let Some(chnl) = chnl {
91 chnl.encode(buf)?;
92 }
93
94 if let Some(btrt) = btrt {
95 btrt.encode(buf)?;
96 }
97
98 Ok(())
99 }
100
101 pub fn decode_with_fourcc<B: Buf>(fourcc: FourCC, buf: &mut B) -> Result<Self> {
102 let audio = Audio::decode(buf)?;
103
104 let mut chnl = None;
105 let mut pcmc = None;
106 let mut btrt = None;
107
108 while buf.remaining() > 0 {
109 let header = match Header::decode_maybe(buf)? {
110 Some(h) => h,
111 None => break,
112 };
113
114 let size = header.size.unwrap_or(buf.remaining());
115 if size > buf.remaining() {
116 break;
117 }
118
119 let mut limited = buf.slice(size);
120
121 if header.kind == Chnl::KIND {
122 chnl = Some(Chnl::decode_body_with_channel_count(
126 &mut limited,
127 audio.channel_count,
128 )?);
129 } else {
130 match Any::decode_atom(&header, &mut limited)? {
131 Any::PcmC(atom) => pcmc = Some(atom),
132 Any::Btrt(atom) => btrt = Some(atom),
133 atom => crate::decode_unknown(&atom, fourcc)?,
134 }
135 }
136
137 buf.advance(size);
138 }
139
140 if pcmc.is_none() && Self::requires_pcmc(fourcc) {
142 return Err(Error::MissingBox(PcmC::KIND));
143 }
144
145 Ok(Self {
146 fourcc,
147 audio,
148 pcmc,
149 chnl,
150 btrt,
151 })
152 }
153
154 pub fn encode_with_fourcc<B: BufMut>(&self, buf: &mut B) -> Result<()> {
155 Self::encode_fields(
156 self.fourcc,
157 &self.audio,
158 self.pcmc.as_ref(),
159 self.chnl.as_ref(),
160 self.btrt.as_ref(),
161 buf,
162 )
163 }
164
165 pub fn format(&self) -> Option<PcmFormat> {
182 Self::resolve_format(self.fourcc, &self.audio, self.pcmc.as_ref())
183 }
184
185 fn requires_pcmc(fourcc: FourCC) -> bool {
190 matches!(fourcc, Ipcm::KIND | Fpcm::KIND)
191 }
192
193 fn resolve_format(fourcc: FourCC, audio: &Audio, pcmc: Option<&PcmC>) -> Option<PcmFormat> {
194 let float = matches!(fourcc, Fl32::KIND | Fl64::KIND | Fpcm::KIND);
196
197 if let Some(pcmc) = pcmc {
198 return Some(PcmFormat {
199 big_endian: pcmc.big_endian,
200 sample_size: pcmc.sample_size as u16,
201 float,
202 });
203 }
204
205 if Self::requires_pcmc(fourcc) {
208 return None;
209 }
210
211 let (big_endian, sample_size) = match fourcc {
212 Twos::KIND | Lpcm::KIND => (true, audio.sample_size),
213 Sowt::KIND => (false, audio.sample_size),
214 In24::KIND => (true, 24),
215 In32::KIND => (true, 32),
216 Fl32::KIND => (true, 32),
217 Fl64::KIND => (true, 64),
218 S16l::KIND => (false, 16),
219 _ => return None,
221 };
222
223 Some(PcmFormat {
224 big_endian,
225 sample_size,
226 float,
227 })
228 }
229}
230
231macro_rules! define_pcm_sample_entry {
232 ($name:ident, $fourcc:expr) => {
233 #[derive(Debug, Clone, PartialEq, Eq)]
234 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
235 pub struct $name {
236 pub audio: Audio,
237 pub pcmc: Option<PcmC>,
238 pub chnl: Option<Chnl>,
239 pub btrt: Option<Btrt>,
240 }
241
242 impl $name {
243 pub fn format(&self) -> Option<PcmFormat> {
247 Pcm::resolve_format(Self::KIND, &self.audio, self.pcmc.as_ref())
248 }
249 }
250
251 impl Atom for $name {
252 const KIND: FourCC = FourCC::new($fourcc);
253
254 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
255 let entry = Pcm::decode_with_fourcc(Self::KIND, buf)?;
256 Ok(Self {
257 audio: entry.audio,
258 pcmc: entry.pcmc,
259 chnl: entry.chnl,
260 btrt: entry.btrt,
261 })
262 }
263
264 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
265 Pcm::encode_fields(
266 Self::KIND,
267 &self.audio,
268 self.pcmc.as_ref(),
269 self.chnl.as_ref(),
270 self.btrt.as_ref(),
271 buf,
272 )
273 }
274 }
275 };
276}
277
278define_pcm_sample_entry!(Sowt, b"sowt");
279define_pcm_sample_entry!(Twos, b"twos");
280define_pcm_sample_entry!(Lpcm, b"lpcm");
281define_pcm_sample_entry!(Ipcm, b"ipcm");
282define_pcm_sample_entry!(Fpcm, b"fpcm");
283define_pcm_sample_entry!(In24, b"in24");
284define_pcm_sample_entry!(In32, b"in32");
285define_pcm_sample_entry!(Fl32, b"fl32");
286define_pcm_sample_entry!(Fl64, b"fl64");
287define_pcm_sample_entry!(S16l, b"s16l");
288
289#[cfg(test)]
290mod tests {
291 use super::*;
292
293 #[test]
294 fn test_pcmc_encode_decode() {
295 let pcmc = PcmC {
296 big_endian: true,
297 sample_size: 16,
298 };
299
300 let mut buf = Vec::new();
301 pcmc.encode(&mut buf).unwrap();
302
303 let decoded = PcmC::decode(&mut &buf[..]).unwrap();
304 assert_eq!(pcmc, decoded);
305 }
306
307 #[test]
308 fn test_pcm_encode_decode() {
309 let pcmc = PcmC {
310 big_endian: false,
311 sample_size: 16,
312 };
313 let chnl = Chnl {
314 channel_structure: Some(ChannelStructure::DefinedLayout {
315 layout: 2, omitted_channels_map: Some(0),
317 channel_order_definition: None,
318 }),
319 object_count: None,
320 format_ordering: None,
321 base_channel_count: None,
322 };
323 let pcm = Pcm {
324 fourcc: FourCC::new(b"fpcm"),
325 audio: Audio {
326 data_reference_index: 1,
327 channel_count: 2,
328 sample_size: 16,
329 sample_rate: 48000.into(),
330 },
331 pcmc: Some(pcmc),
332 chnl: Some(chnl),
333 btrt: None,
334 };
335
336 let mut buf = Vec::new();
337 pcm.encode_with_fourcc(&mut buf).unwrap();
338
339 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
340 assert_eq!(pcm, decoded);
341 }
342
343 #[test]
344 fn test_pcm_encode_decode_with_both_channel_and_object() {
345 let pcmc = PcmC {
346 big_endian: true,
347 sample_size: 16,
348 };
349 let chnl = Chnl {
350 channel_structure: Some(ChannelStructure::DefinedLayout {
351 layout: 2, omitted_channels_map: Some(0),
353 channel_order_definition: None,
354 }),
355 object_count: Some(2),
356 format_ordering: None,
357 base_channel_count: None,
358 };
359 let pcm = Pcm {
360 fourcc: FourCC::new(b"ipcm"),
361 audio: Audio {
362 data_reference_index: 1,
363 channel_count: 2,
364 sample_size: 16,
365 sample_rate: 48000.into(),
366 },
367 pcmc: Some(pcmc),
368 chnl: Some(chnl),
369 btrt: None,
370 };
371
372 let mut buf = Vec::new();
373 pcm.encode_with_fourcc(&mut buf).unwrap();
374
375 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"ipcm"), &mut &buf[..]).unwrap();
376 assert_eq!(pcm, decoded);
377 }
378
379 #[test]
380 fn test_pcm_encode_decode_with_both_channel_and_object_explicit_position() {
381 let pcmc = PcmC {
382 big_endian: true,
383 sample_size: 16,
384 };
385 let chnl = Chnl {
386 channel_structure: Some(ChannelStructure::ExplicitPositions {
387 positions: vec![
388 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
389 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
390 ],
391 }),
392 object_count: Some(2),
393 format_ordering: None,
394 base_channel_count: None,
395 };
396 let pcm = Pcm {
397 fourcc: FourCC::new(b"fpcm"),
398 audio: Audio {
399 data_reference_index: 1,
400 channel_count: 2,
401 sample_size: 16,
402 sample_rate: 48000.into(),
403 },
404 pcmc: Some(pcmc),
405 chnl: Some(chnl),
406 btrt: Some(Btrt {
407 buffer_size_db: 6,
408 max_bitrate: 2_304_096,
409 avg_bitrate: 2_304_000,
410 }),
411 };
412
413 let mut buf = Vec::new();
414 pcm.encode_with_fourcc(&mut buf).unwrap();
415
416 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
417 assert_eq!(pcm, decoded);
418 }
419
420 #[test]
421 fn test_pcm_encode_decode_with_chnl_explicit_positions() {
422 let pcmc = PcmC {
423 big_endian: true,
424 sample_size: 16,
425 };
426 let chnl = Chnl {
427 channel_structure: Some(ChannelStructure::ExplicitPositions {
428 positions: vec![
429 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
430 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
431 ],
432 }),
433 object_count: None,
434 format_ordering: None,
435 base_channel_count: None,
436 };
437 let pcm = Pcm {
438 fourcc: FourCC::new(b"fpcm"),
439 audio: Audio {
440 data_reference_index: 1,
441 channel_count: 2,
442 sample_size: 16,
443 sample_rate: 48000.into(),
444 },
445 pcmc: Some(pcmc),
446 chnl: Some(chnl),
447 btrt: None,
448 };
449
450 let mut buf = Vec::new();
451 pcm.encode_with_fourcc(&mut buf).unwrap();
452
453 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
454 assert_eq!(pcm, decoded);
455 }
456
457 #[test]
458 fn test_pcm_encode_decode_with_chnl_explicit_speaker_position() {
459 let pcmc = PcmC {
460 big_endian: true,
461 sample_size: 16,
462 };
463 let chnl = Chnl {
464 channel_structure: Some(ChannelStructure::ExplicitPositions {
465 positions: vec![
466 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
467 SpeakerPosition::Explicit(ExplicitSpeakerPosition {
468 azimuth: 45,
469 elevation: 10,
470 }),
471 ],
472 }),
473 object_count: None,
474 format_ordering: None,
475 base_channel_count: None,
476 };
477 let pcm = Pcm {
478 fourcc: FourCC::new(b"fpcm"),
479 audio: Audio {
480 data_reference_index: 1,
481 channel_count: 2,
482 sample_size: 16,
483 sample_rate: 48000.into(),
484 },
485 pcmc: Some(pcmc),
486 chnl: Some(chnl),
487 btrt: None,
488 };
489
490 let mut buf = Vec::new();
491 pcm.encode_with_fourcc(&mut buf).unwrap();
492
493 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
494 assert_eq!(pcm, decoded);
495 }
496
497 #[test]
498 fn test_pcm_v1_chnl() {
499 let pcmc = PcmC {
500 big_endian: false,
501 sample_size: 24,
502 };
503 let chnl = Chnl {
504 channel_structure: Some(ChannelStructure::ExplicitPositions {
505 positions: vec![
506 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
507 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
508 ],
509 }),
510 object_count: Some(1),
511 format_ordering: Some(1),
512 base_channel_count: Some(3),
513 };
514 let pcm = Lpcm {
515 audio: Audio {
516 data_reference_index: 1,
517 channel_count: 2,
518 sample_size: 24,
519 sample_rate: 48000.into(),
520 },
521 pcmc: Some(pcmc),
522 chnl: Some(chnl),
523 btrt: None,
524 };
525
526 let mut buf = Vec::new();
527 pcm.encode(&mut buf).unwrap();
528
529 let decoded = Lpcm::decode(&mut &buf[..]).unwrap();
530 assert_eq!(pcm, decoded);
531 }
532
533 const ENCODED_IPCM: &[u8] = &[
534 0x00, 0x00, 0x00, 0x5c, 0x69, 0x70, 0x63, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
535 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00,
536 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x70, 0x63, 0x6d, 0x43, 0x00,
537 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x16, 0x63, 0x68, 0x6e, 0x6c, 0x00, 0x00,
538 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
539 0x14, 0x62, 0x74, 0x72, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x23, 0x28, 0x60, 0x00, 0x23,
540 0x28, 0x00,
541 ];
542
543 fn decoded_ipcm() -> Ipcm {
544 Ipcm {
545 audio: Audio {
546 data_reference_index: 1,
547 channel_count: 2,
548 sample_size: 24,
549 sample_rate: FixedPoint::new(48000, 0),
550 },
551 pcmc: Some(PcmC {
552 big_endian: true,
553 sample_size: 24,
554 }),
555 chnl: Some(Chnl {
556 channel_structure: Some(ChannelStructure::DefinedLayout {
557 layout: 2,
558 omitted_channels_map: Some(0),
559 channel_order_definition: None,
560 }),
561 object_count: None,
562 format_ordering: None,
563 base_channel_count: None,
564 }),
565 btrt: Some(Btrt {
566 buffer_size_db: 6,
567 max_bitrate: 2_304_096,
568 avg_bitrate: 2_304_000,
569 }),
570 }
571 }
572
573 #[test]
574 fn test_ipcm_decode() {
575 let buf = &mut std::io::Cursor::new(ENCODED_IPCM);
576 let ipcm = Ipcm::decode(buf).expect("failed to decode ipcm");
577 assert_eq!(ipcm, decoded_ipcm());
578 }
579
580 #[test]
581 fn test_ipcm_encode() {
582 let ipcm = decoded_ipcm();
583 let mut buf = Vec::new();
584 ipcm.encode(&mut buf).unwrap();
585 assert_eq!(buf.as_slice(), ENCODED_IPCM);
586 }
587
588 const ENCODED_BARE_TWOS: &[u8] = &[
591 0x00, 0x00, 0x00, 0x24, 0x74, 0x77, 0x6f, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, ];
604
605 #[test]
606 fn test_bare_twos_decode() {
607 let buf = &mut std::io::Cursor::new(ENCODED_BARE_TWOS);
608 let twos = Twos::decode(buf).expect("failed to decode twos");
609 assert_eq!(
610 twos,
611 Twos {
612 audio: Audio {
613 data_reference_index: 1,
614 channel_count: 2,
615 sample_size: 16,
616 sample_rate: FixedPoint::new(48000, 0),
617 },
618 pcmc: None,
619 chnl: None,
620 btrt: None,
621 }
622 );
623 assert_eq!(
624 twos.format(),
625 Some(PcmFormat {
626 big_endian: true,
627 sample_size: 16,
628 float: false,
629 })
630 );
631 }
632
633 #[test]
634 fn test_bare_twos_roundtrip() {
635 let buf = &mut std::io::Cursor::new(ENCODED_BARE_TWOS);
636 let twos = Twos::decode(buf).expect("failed to decode twos");
637
638 let mut encoded = Vec::new();
639 twos.encode(&mut encoded).unwrap();
640 assert_eq!(encoded.as_slice(), ENCODED_BARE_TWOS);
641 }
642
643 #[test]
644 fn test_ipcm_missing_pcmc_decode() {
645 let mut encoded = ENCODED_BARE_TWOS.to_vec();
647 encoded[4..8].copy_from_slice(b"ipcm");
648
649 let buf = &mut std::io::Cursor::new(&encoded);
650 assert!(matches!(
651 Ipcm::decode(buf),
652 Err(Error::MissingBox(PcmC::KIND))
653 ));
654 }
655
656 #[test]
657 fn test_ipcm_missing_pcmc_encode() {
658 let ipcm = Ipcm {
659 audio: Audio {
660 data_reference_index: 1,
661 channel_count: 2,
662 sample_size: 16,
663 sample_rate: 48000.into(),
664 },
665 pcmc: None,
666 chnl: None,
667 btrt: None,
668 };
669
670 let mut buf = Vec::new();
671 assert!(matches!(
672 ipcm.encode(&mut buf),
673 Err(Error::MissingBox(PcmC::KIND))
674 ));
675 }
676}