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, PartialEq, Eq)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
48pub struct Pcm {
49 pub fourcc: FourCC,
50 pub audio: Audio,
51 pub pcmc: PcmC,
52 pub chnl: Option<Chnl>,
53 pub btrt: Option<Btrt>,
54}
55
56impl Pcm {
57 fn encode_fields<B: BufMut>(
58 audio: &Audio,
59 pcmc: &PcmC,
60 chnl: Option<&Chnl>,
61 btrt: Option<&Btrt>,
62 buf: &mut B,
63 ) -> Result<()> {
64 audio.encode(buf)?;
65 pcmc.encode(buf)?;
66
67 if let Some(chnl) = chnl {
68 chnl.encode(buf)?;
69 }
70
71 if let Some(btrt) = btrt {
72 btrt.encode(buf)?;
73 }
74
75 Ok(())
76 }
77
78 pub fn decode_with_fourcc<B: Buf>(fourcc: FourCC, buf: &mut B) -> Result<Self> {
79 let audio = Audio::decode(buf)?;
80
81 let mut chnl = None;
82 let mut pcmc = None;
83 let mut btrt = None;
84
85 while buf.remaining() > 0 {
86 let header = match Header::decode_maybe(buf)? {
87 Some(h) => h,
88 None => break,
89 };
90
91 let size = header.size.unwrap_or(buf.remaining());
92 if size > buf.remaining() {
93 break;
94 }
95
96 let mut limited = buf.slice(size);
97
98 if header.kind == Chnl::KIND {
99 chnl = Some(Chnl::decode_body_with_channel_count(
103 &mut limited,
104 audio.channel_count,
105 )?);
106 } else {
107 match Any::decode_atom(&header, &mut limited)? {
108 Any::PcmC(atom) => pcmc = Some(atom),
109 Any::Btrt(atom) => btrt = Some(atom),
110 atom => crate::decode_unknown(&atom, fourcc)?,
111 }
112 }
113
114 buf.advance(size);
115 }
116
117 Ok(Self {
118 fourcc,
119 audio,
120 pcmc: pcmc.ok_or(Error::MissingBox(PcmC::KIND))?,
121 chnl,
122 btrt,
123 })
124 }
125
126 pub fn encode_with_fourcc<B: BufMut>(&self, buf: &mut B) -> Result<()> {
127 Self::encode_fields(
128 &self.audio,
129 &self.pcmc,
130 self.chnl.as_ref(),
131 self.btrt.as_ref(),
132 buf,
133 )
134 }
135}
136
137macro_rules! define_pcm_sample_entry {
138 ($name:ident, $fourcc:expr) => {
139 #[derive(Debug, Clone, PartialEq, Eq)]
140 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141 pub struct $name {
142 pub audio: Audio,
143 pub pcmc: PcmC,
144 pub chnl: Option<Chnl>,
145 pub btrt: Option<Btrt>,
146 }
147
148 impl Atom for $name {
149 const KIND: FourCC = FourCC::new($fourcc);
150
151 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
152 let entry = Pcm::decode_with_fourcc(Self::KIND, buf)?;
153 Ok(Self {
154 audio: entry.audio,
155 pcmc: entry.pcmc,
156 chnl: entry.chnl,
157 btrt: entry.btrt,
158 })
159 }
160
161 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
162 Pcm::encode_fields(
163 &self.audio,
164 &self.pcmc,
165 self.chnl.as_ref(),
166 self.btrt.as_ref(),
167 buf,
168 )
169 }
170 }
171 };
172}
173
174define_pcm_sample_entry!(Sowt, b"sowt");
175define_pcm_sample_entry!(Twos, b"twos");
176define_pcm_sample_entry!(Lpcm, b"lpcm");
177define_pcm_sample_entry!(Ipcm, b"ipcm");
178define_pcm_sample_entry!(Fpcm, b"fpcm");
179define_pcm_sample_entry!(In24, b"in24");
180define_pcm_sample_entry!(In32, b"in32");
181define_pcm_sample_entry!(Fl32, b"fl32");
182define_pcm_sample_entry!(Fl64, b"fl64");
183define_pcm_sample_entry!(S16l, b"s16l");
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn test_pcmc_encode_decode() {
191 let pcmc = PcmC {
192 big_endian: true,
193 sample_size: 16,
194 };
195
196 let mut buf = Vec::new();
197 pcmc.encode(&mut buf).unwrap();
198
199 let decoded = PcmC::decode(&mut &buf[..]).unwrap();
200 assert_eq!(pcmc, decoded);
201 }
202
203 #[test]
204 fn test_pcm_encode_decode() {
205 let pcmc = PcmC {
206 big_endian: false,
207 sample_size: 16,
208 };
209 let chnl = Chnl {
210 channel_structure: Some(ChannelStructure::DefinedLayout {
211 layout: 2, omitted_channels_map: Some(0),
213 channel_order_definition: None,
214 }),
215 object_count: None,
216 format_ordering: None,
217 base_channel_count: None,
218 };
219 let pcm = Pcm {
220 fourcc: FourCC::new(b"fpcm"),
221 audio: Audio {
222 data_reference_index: 1,
223 channel_count: 2,
224 sample_size: 16,
225 sample_rate: 48000.into(),
226 },
227 pcmc,
228 chnl: Some(chnl),
229 btrt: None,
230 };
231
232 let mut buf = Vec::new();
233 pcm.encode_with_fourcc(&mut buf).unwrap();
234
235 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
236 assert_eq!(pcm, decoded);
237 }
238
239 #[test]
240 fn test_pcm_encode_decode_with_both_channel_and_object() {
241 let pcmc = PcmC {
242 big_endian: true,
243 sample_size: 16,
244 };
245 let chnl = Chnl {
246 channel_structure: Some(ChannelStructure::DefinedLayout {
247 layout: 2, omitted_channels_map: Some(0),
249 channel_order_definition: None,
250 }),
251 object_count: Some(2),
252 format_ordering: None,
253 base_channel_count: None,
254 };
255 let pcm = Pcm {
256 fourcc: FourCC::new(b"ipcm"),
257 audio: Audio {
258 data_reference_index: 1,
259 channel_count: 2,
260 sample_size: 16,
261 sample_rate: 48000.into(),
262 },
263 pcmc,
264 chnl: Some(chnl),
265 btrt: None,
266 };
267
268 let mut buf = Vec::new();
269 pcm.encode_with_fourcc(&mut buf).unwrap();
270
271 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"ipcm"), &mut &buf[..]).unwrap();
272 assert_eq!(pcm, decoded);
273 }
274
275 #[test]
276 fn test_pcm_encode_decode_with_both_channel_and_object_explicit_position() {
277 let pcmc = PcmC {
278 big_endian: true,
279 sample_size: 16,
280 };
281 let chnl = Chnl {
282 channel_structure: Some(ChannelStructure::ExplicitPositions {
283 positions: vec![
284 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
285 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
286 ],
287 }),
288 object_count: Some(2),
289 format_ordering: None,
290 base_channel_count: None,
291 };
292 let pcm = Pcm {
293 fourcc: FourCC::new(b"fpcm"),
294 audio: Audio {
295 data_reference_index: 1,
296 channel_count: 2,
297 sample_size: 16,
298 sample_rate: 48000.into(),
299 },
300 pcmc,
301 chnl: Some(chnl),
302 btrt: Some(Btrt {
303 buffer_size_db: 6,
304 max_bitrate: 2_304_096,
305 avg_bitrate: 2_304_000,
306 }),
307 };
308
309 let mut buf = Vec::new();
310 pcm.encode_with_fourcc(&mut buf).unwrap();
311
312 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
313 assert_eq!(pcm, decoded);
314 }
315
316 #[test]
317 fn test_pcm_encode_decode_with_chnl_explicit_positions() {
318 let pcmc = PcmC {
319 big_endian: true,
320 sample_size: 16,
321 };
322 let chnl = Chnl {
323 channel_structure: Some(ChannelStructure::ExplicitPositions {
324 positions: vec![
325 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
326 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
327 ],
328 }),
329 object_count: None,
330 format_ordering: None,
331 base_channel_count: None,
332 };
333 let pcm = Pcm {
334 fourcc: FourCC::new(b"fpcm"),
335 audio: Audio {
336 data_reference_index: 1,
337 channel_count: 2,
338 sample_size: 16,
339 sample_rate: 48000.into(),
340 },
341 pcmc,
342 chnl: Some(chnl),
343 btrt: None,
344 };
345
346 let mut buf = Vec::new();
347 pcm.encode_with_fourcc(&mut buf).unwrap();
348
349 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
350 assert_eq!(pcm, decoded);
351 }
352
353 #[test]
354 fn test_pcm_encode_decode_with_chnl_explicit_speaker_position() {
355 let pcmc = PcmC {
356 big_endian: true,
357 sample_size: 16,
358 };
359 let chnl = Chnl {
360 channel_structure: Some(ChannelStructure::ExplicitPositions {
361 positions: vec![
362 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
363 SpeakerPosition::Explicit(ExplicitSpeakerPosition {
364 azimuth: 45,
365 elevation: 10,
366 }),
367 ],
368 }),
369 object_count: None,
370 format_ordering: None,
371 base_channel_count: None,
372 };
373 let pcm = Pcm {
374 fourcc: FourCC::new(b"fpcm"),
375 audio: Audio {
376 data_reference_index: 1,
377 channel_count: 2,
378 sample_size: 16,
379 sample_rate: 48000.into(),
380 },
381 pcmc,
382 chnl: Some(chnl),
383 btrt: None,
384 };
385
386 let mut buf = Vec::new();
387 pcm.encode_with_fourcc(&mut buf).unwrap();
388
389 let decoded = Pcm::decode_with_fourcc(FourCC::new(b"fpcm"), &mut &buf[..]).unwrap();
390 assert_eq!(pcm, decoded);
391 }
392
393 #[test]
394 fn test_pcm_v1_chnl() {
395 let pcmc = PcmC {
396 big_endian: false,
397 sample_size: 24,
398 };
399 let chnl = Chnl {
400 channel_structure: Some(ChannelStructure::ExplicitPositions {
401 positions: vec![
402 SpeakerPosition::Standard(AudioChannelPosition::FrontLeft),
403 SpeakerPosition::Standard(AudioChannelPosition::FrontRight),
404 ],
405 }),
406 object_count: Some(1),
407 format_ordering: Some(1),
408 base_channel_count: Some(3),
409 };
410 let pcm = Lpcm {
411 audio: Audio {
412 data_reference_index: 1,
413 channel_count: 2,
414 sample_size: 24,
415 sample_rate: 48000.into(),
416 },
417 pcmc,
418 chnl: Some(chnl),
419 btrt: None,
420 };
421
422 let mut buf = Vec::new();
423 pcm.encode(&mut buf).unwrap();
424
425 let decoded = Lpcm::decode(&mut &buf[..]).unwrap();
426 assert_eq!(pcm, decoded);
427 }
428
429 const ENCODED_IPCM: &[u8] = &[
430 0x00, 0x00, 0x00, 0x5c, 0x69, 0x70, 0x63, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x18, 0x00, 0x00,
432 0x00, 0x00, 0xbb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x70, 0x63, 0x6d, 0x43, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x16, 0x63, 0x68, 0x6e, 0x6c, 0x00, 0x00,
434 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x14, 0x62, 0x74, 0x72, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x23, 0x28, 0x60, 0x00, 0x23,
436 0x28, 0x00,
437 ];
438
439 fn decoded_ipcm() -> Ipcm {
440 Ipcm {
441 audio: Audio {
442 data_reference_index: 1,
443 channel_count: 2,
444 sample_size: 24,
445 sample_rate: FixedPoint::new(48000, 0),
446 },
447 pcmc: PcmC {
448 big_endian: true,
449 sample_size: 24,
450 },
451 chnl: Some(Chnl {
452 channel_structure: Some(ChannelStructure::DefinedLayout {
453 layout: 2,
454 omitted_channels_map: Some(0),
455 channel_order_definition: None,
456 }),
457 object_count: None,
458 format_ordering: None,
459 base_channel_count: None,
460 }),
461 btrt: Some(Btrt {
462 buffer_size_db: 6,
463 max_bitrate: 2_304_096,
464 avg_bitrate: 2_304_000,
465 }),
466 }
467 }
468
469 #[test]
470 fn test_ipcm_decode() {
471 let buf = &mut std::io::Cursor::new(ENCODED_IPCM);
472 let ipcm = Ipcm::decode(buf).expect("failed to decode ipcm");
473 assert_eq!(ipcm, decoded_ipcm());
474 }
475
476 #[test]
477 fn test_ipcm_encode() {
478 let ipcm = decoded_ipcm();
479 let mut buf = Vec::new();
480 ipcm.encode(&mut buf).unwrap();
481 assert_eq!(buf.as_slice(), ENCODED_IPCM);
482 }
483}