1use std::io;
2
3use fixed::types::extra::{U8, U16};
4use fixed::{FixedI16, FixedU32};
5use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize};
6use scuffle_bytes_util::{BitWriter, BytesCow};
7
8use super::SampleEntry;
9use crate::utils::pad_to_u64;
10use crate::{BoxHeader, FullBoxHeader, IsoBox, IsoSized};
11
12#[derive(IsoBox, Debug, PartialEq, Eq, Default)]
16#[iso_box(box_type = b"smhd", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
17pub struct SoundMediaHeaderBox {
18 pub full_header: FullBoxHeader,
20 pub balance: FixedI16<U8>,
23 pub reserved: u16,
25}
26
27impl<'a> DeserializeSeed<'a, BoxHeader> for SoundMediaHeaderBox {
28 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> io::Result<Self>
29 where
30 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
31 {
32 let full_header = FullBoxHeader::deserialize(&mut reader)?;
33 let balance = FixedI16::from_bits(i16::deserialize(&mut reader)?);
34 let reserved = u16::deserialize(&mut reader)?;
35
36 Ok(Self {
37 full_header,
38 balance,
39 reserved,
40 })
41 }
42}
43
44impl Serialize for SoundMediaHeaderBox {
45 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
46 where
47 W: std::io::Write,
48 {
49 self.serialize_box_header(&mut writer)?;
50 self.full_header.serialize(&mut writer)?;
51 self.balance.to_bits().serialize(&mut writer)?;
52 self.reserved.serialize(&mut writer)?;
53 Ok(())
54 }
55}
56
57impl IsoSized for SoundMediaHeaderBox {
58 fn size(&self) -> usize {
59 Self::add_header_size(self.full_header.size() + 2 + 2)
60 }
61}
62
63#[derive(Debug, PartialEq, Eq)]
79pub struct AudioSampleEntry {
80 pub sample_entry: SampleEntry,
82 pub reserved1: u64,
84 pub channelcount: u16,
91 pub samplesize: u16,
93 pub pre_defined: u16,
95 pub reserved2: u16,
97 pub samplerate: FixedU32<U16>,
100}
101
102impl AudioSampleEntry {
103 pub fn new(sample_entry: SampleEntry, channelcount: u16, samplesize: u16, samplerate: FixedU32<U16>) -> Self {
105 Self {
106 sample_entry,
107 reserved1: 0,
108 channelcount,
109 samplesize,
110 pre_defined: 0,
111 reserved2: 0,
112 samplerate,
113 }
114 }
115}
116
117impl<'a> Deserialize<'a> for AudioSampleEntry {
118 fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
119 where
120 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
121 {
122 let sample_entry = SampleEntry::deserialize(&mut reader)?;
123 let reserved1 = u64::deserialize(&mut reader)?;
124 let channelcount = u16::deserialize(&mut reader)?;
125 let samplesize = u16::deserialize(&mut reader)?;
126 let pre_defined = u16::deserialize(&mut reader)?;
127 let reserved2 = u16::deserialize(&mut reader)?;
128 let samplerate = FixedU32::from_bits(u32::deserialize(&mut reader)?);
129
130 Ok(Self {
131 sample_entry,
132 reserved1,
133 channelcount,
134 samplesize,
135 pre_defined,
136 reserved2,
137 samplerate,
138 })
139 }
140}
141
142impl Serialize for AudioSampleEntry {
143 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
144 where
145 W: std::io::Write,
146 {
147 self.sample_entry.serialize(&mut writer)?;
148 self.reserved1.serialize(&mut writer)?;
149 self.channelcount.serialize(&mut writer)?;
150 self.samplesize.serialize(&mut writer)?;
151 self.pre_defined.serialize(&mut writer)?;
152 self.reserved2.serialize(&mut writer)?;
153 self.samplerate.to_bits().serialize(&mut writer)?;
154 Ok(())
155 }
156}
157
158impl IsoSized for AudioSampleEntry {
159 fn size(&self) -> usize {
160 self.sample_entry.size()
161 + 8 + 2 + 2 + 2 + 2 + 4 }
168}
169
170#[derive(IsoBox, Debug, PartialEq, Eq)]
174#[iso_box(box_type = b"srat", crate_path = crate)]
175pub struct SamplingRateBox {
176 pub full_header: FullBoxHeader,
178 pub sampling_rate: u32,
180}
181
182#[derive(Debug, PartialEq, Eq)]
198pub struct AudioSampleEntryV1 {
199 pub sample_entry: SampleEntry,
201 pub entry_version: u16,
203 pub reserved1: [u16; 3],
205 pub channelcount: u16,
212 pub samplesize: u16,
214 pub pre_defined: u16,
216 pub reserved2: u16,
218 pub samplerate: FixedU32<U16>,
221}
222
223impl<'a> Deserialize<'a> for AudioSampleEntryV1 {
224 fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
225 where
226 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
227 {
228 let sample_entry = SampleEntry::deserialize(&mut reader)?;
229 let entry_version = u16::deserialize(&mut reader)?;
230 let reserved1 = <[u16; 3]>::deserialize(&mut reader)?;
231 let channelcount = u16::deserialize(&mut reader)?;
232 let samplesize = u16::deserialize(&mut reader)?;
233 let pre_defined = u16::deserialize(&mut reader)?;
234 let reserved2 = u16::deserialize(&mut reader)?;
235 let samplerate = FixedU32::from_bits(u32::deserialize(&mut reader)?);
236
237 Ok(Self {
238 sample_entry,
239 entry_version,
240 reserved1,
241 channelcount,
242 samplesize,
243 pre_defined,
244 reserved2,
245 samplerate,
246 })
247 }
248}
249
250impl Serialize for AudioSampleEntryV1 {
251 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
252 where
253 W: std::io::Write,
254 {
255 self.sample_entry.serialize(&mut writer)?;
256 self.entry_version.serialize(&mut writer)?;
257 self.reserved1.serialize(&mut writer)?;
258 self.channelcount.serialize(&mut writer)?;
259 self.samplesize.serialize(&mut writer)?;
260 self.pre_defined.serialize(&mut writer)?;
261 self.reserved2.serialize(&mut writer)?;
262 self.samplerate.to_bits().serialize(&mut writer)?;
263 Ok(())
264 }
265}
266
267impl IsoSized for AudioSampleEntryV1 {
268 fn size(&self) -> usize {
269 self.sample_entry.size()
270 + 2 + 2 * 3 + 2 + 2 + 2 + 2 + 4 }
278}
279
280#[derive(IsoBox, Debug, PartialEq, Eq)]
284#[iso_box(box_type = b"chnl", crate_path = crate)]
285pub struct ChannelLayout<'a> {
286 pub full_header: FullBoxHeader,
288 pub data: BytesCow<'a>,
290}
291
292#[derive(IsoBox, Debug, PartialEq, Eq)]
296#[iso_box(box_type = b"dmix", crate_path = crate)]
297pub struct DownMixInstructions<'a> {
298 pub full_header: FullBoxHeader,
300 pub data: BytesCow<'a>,
302}
303
304#[derive(Debug, PartialEq, Eq)]
308pub struct LoudnessBaseBox {
309 pub loudness_info_type: Option<u8>,
313 pub loudness_base_count: u8,
315 pub mae_group_id: Option<u8>,
320 pub loudness_bases: Vec<LoudnessBase>,
322}
323
324impl<'a> DeserializeSeed<'a, &FullBoxHeader> for LoudnessBaseBox {
325 fn deserialize_seed<R>(mut reader: R, seed: &FullBoxHeader) -> std::io::Result<Self>
326 where
327 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
328 {
329 let (loudness_info_type, loudness_base_count, mae_group_id) = if seed.version >= 2 {
330 let byte = u8::deserialize(&mut reader)?;
331 let loudness_info_type = (byte >> 6) & 0b11;
332 let loudness_base_count = byte & 0b0011_1111;
333 let mae_group_id = if loudness_info_type == 1 || loudness_info_type == 2 {
334 Some(u8::deserialize(&mut reader)? & 0b0111_1111)
335 } else if loudness_info_type == 3 {
336 Some(u8::deserialize(&mut reader)? & 0b0001_1111)
337 } else {
338 None
339 };
340 (Some(loudness_info_type), loudness_base_count, mae_group_id)
341 } else if seed.version == 1 {
342 let byte = u8::deserialize(&mut reader)?;
343 (None, byte & 0b0011_1111, None)
344 } else {
345 (None, 1, None)
346 };
347
348 let mut loudness_bases = Vec::with_capacity(loudness_base_count as usize);
349 for _ in 0..loudness_base_count {
350 loudness_bases.push(LoudnessBase::deserialize_seed(&mut reader, seed)?);
351 }
352
353 Ok(Self {
354 loudness_info_type,
355 loudness_base_count,
356 mae_group_id,
357 loudness_bases,
358 })
359 }
360}
361
362impl LoudnessBaseBox {
363 fn serialize<W>(&self, writer: W, version: u8) -> std::io::Result<()>
364 where
365 W: std::io::Write,
366 {
367 let mut bit_writer = BitWriter::new(writer);
368
369 if version >= 2 {
370 let loudness_info_type = self
371 .loudness_info_type
372 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "loudness_info_type is required"))?;
373 bit_writer.write_bits(loudness_info_type as u64, 2)?;
374 bit_writer.write_bits(self.loudness_base_count as u64, 6)?;
375
376 if loudness_info_type == 1 || loudness_info_type == 2 {
377 bit_writer.write_bit(false)?;
378 bit_writer.write_bits(
379 self.mae_group_id
380 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "mae_group_ID is required"))?
381 as u64,
382 7,
383 )?;
384 } else if loudness_info_type == 3 {
385 bit_writer.write_bits(0, 3)?;
386 bit_writer.write_bits(
387 self.mae_group_id
388 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "mae_group_preset_ID is required"))?
389 as u64,
390 5,
391 )?;
392 }
393 } else if version == 1 {
394 bit_writer.write_bits(0, 2)?;
395 bit_writer.write_bits(self.loudness_base_count as u64, 6)?;
396 }
397
398 for loudness_base in &self.loudness_bases {
399 loudness_base.serialize(&mut bit_writer, version)?;
400 }
401
402 Ok(())
403 }
404}
405
406impl LoudnessBaseBox {
407 pub fn size(&self, version: u8) -> usize {
409 let mut size = 0;
410
411 if version >= 2 {
412 size += 1; if self.loudness_info_type.is_some_and(|t| t == 1 || t == 2 || t == 3) {
414 size += 1; }
416 } else if version == 1 {
417 size += 1; }
419
420 size += self.loudness_bases.size();
421
422 size
423 }
424}
425
426#[derive(Debug, PartialEq, Eq)]
428pub struct LoudnessBase {
429 pub eq_set_id: Option<u8>,
433 pub downmix_id: u8,
437 pub drc_set_id: u8,
441 pub bs_sample_peak_level: i16,
443 pub bs_true_peak_level: i16,
445 pub measurement_system_for_tp: u8,
447 pub reliability_for_tp: u8,
453 pub measurement_count: u8,
455 pub measurements: Vec<LoudnessBaseMeasurement>,
457}
458
459impl<'a> DeserializeSeed<'a, &FullBoxHeader> for LoudnessBase {
460 fn deserialize_seed<R>(mut reader: R, seed: &FullBoxHeader) -> std::io::Result<Self>
461 where
462 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
463 {
464 let eq_set_id = if seed.version >= 1 {
465 Some(u8::deserialize(&mut reader)? & 0b0011_1111)
466 } else {
467 None
468 };
469
470 let bytes = u16::deserialize(&mut reader)?;
471 let downmix_id = ((bytes >> 6) & 0b00_0111_1111) as u8;
472 let drc_set_id = (bytes & 0b11_1111) as u8;
473
474 let bytes = u32::deserialize(&mut reader)?;
475 let bs_sample_peak_level = (bytes >> 20) as i16;
476 let bs_true_peak_level = ((bytes >> 8) & 0b1111_1111_1111) as i16;
477 let measurement_system_for_tp = ((bytes >> 4) & 0b1111) as u8;
478 let reliability_for_tp = (bytes & 0b1111) as u8;
479
480 let measurement_count = u8::deserialize(&mut reader)?;
481 let mut measurements = Vec::with_capacity(measurement_count as usize);
482 for _ in 0..measurement_count {
483 measurements.push(LoudnessBaseMeasurement::deserialize(&mut reader)?);
484 }
485
486 Ok(Self {
487 eq_set_id,
488 downmix_id,
489 drc_set_id,
490 bs_sample_peak_level,
491 bs_true_peak_level,
492 measurement_system_for_tp,
493 reliability_for_tp,
494 measurement_count,
495 measurements,
496 })
497 }
498}
499
500impl LoudnessBase {
501 fn serialize<W>(&self, writer: W, version: u8) -> std::io::Result<()>
502 where
503 W: std::io::Write,
504 {
505 let mut bit_writer = BitWriter::new(writer);
506
507 if version >= 1 {
508 bit_writer.write_bits(0, 2)?;
509 bit_writer.write_bits(
510 self.eq_set_id
511 .ok_or(io::Error::new(io::ErrorKind::InvalidData, "eq_set_ID is required"))? as u64,
512 6,
513 )?;
514 }
515
516 bit_writer.write_bits(0, 3)?;
517 bit_writer.write_bits(self.downmix_id as u64, 7)?;
518 bit_writer.write_bits(self.drc_set_id as u64, 6)?;
519
520 bit_writer.write_bits(pad_to_u64(&self.bs_sample_peak_level.to_be_bytes()), 12)?;
521 bit_writer.write_bits(pad_to_u64(&self.bs_true_peak_level.to_be_bytes()), 12)?;
522 bit_writer.write_bits(self.measurement_system_for_tp as u64, 4)?;
523 bit_writer.write_bits(self.reliability_for_tp as u64, 4)?;
524
525 self.measurement_count.serialize(&mut bit_writer)?;
526 for measurement in &self.measurements {
527 measurement.serialize(&mut bit_writer)?;
528 }
529
530 Ok(())
531 }
532}
533
534impl IsoSized for LoudnessBase {
535 fn size(&self) -> usize {
536 let mut size = 0;
537 if self.eq_set_id.is_some() {
538 size += 1;
539 }
540
541 size += 2; size += 4; size += 1; size += self.measurements.size();
545 size
546 }
547}
548
549#[derive(Debug, PartialEq, Eq)]
551pub struct LoudnessBaseMeasurement {
552 pub method_definition: u8,
554 pub method_value: u8,
558 pub measurement_system: u8,
560 pub reliability: u8,
566}
567
568impl<'a> Deserialize<'a> for LoudnessBaseMeasurement {
569 fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
570 where
571 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
572 {
573 let method_definition = u8::deserialize(&mut reader)?;
574 let method_value = u8::deserialize(&mut reader)?;
575 let byte = u8::deserialize(&mut reader)?;
576 let measurement_system = (byte >> 4) & 0x0F;
577 let reliability = byte & 0x0F;
578
579 Ok(Self {
580 method_definition,
581 method_value,
582 measurement_system,
583 reliability,
584 })
585 }
586}
587
588impl Serialize for LoudnessBaseMeasurement {
589 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
590 where
591 W: std::io::Write,
592 {
593 self.method_definition.serialize(&mut writer)?;
594 self.method_value.serialize(&mut writer)?;
595
596 let mut byte = 0u8;
597 byte |= (self.measurement_system & 0b1111) << 4;
598 byte |= self.reliability & 0b1111;
599 byte.serialize(&mut writer)?;
600
601 Ok(())
602 }
603}
604
605impl IsoSized for LoudnessBaseMeasurement {
606 fn size(&self) -> usize {
607 1 + 1 + 1 }
611}
612
613#[derive(IsoBox, Debug, PartialEq, Eq)]
617#[iso_box(box_type = b"tlou", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
618pub struct TrackLoudnessInfo {
619 pub full_header: FullBoxHeader,
621 pub base_box: LoudnessBaseBox,
623}
624
625impl<'a> DeserializeSeed<'a, BoxHeader> for TrackLoudnessInfo {
626 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> std::io::Result<Self>
627 where
628 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
629 {
630 let full_header = FullBoxHeader::deserialize(&mut reader)?;
631 let base_box = LoudnessBaseBox::deserialize_seed(&mut reader, &full_header)?;
632
633 Ok(Self { full_header, base_box })
634 }
635}
636
637impl Serialize for TrackLoudnessInfo {
638 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
639 where
640 W: std::io::Write,
641 {
642 self.serialize_box_header(&mut writer)?;
643 self.full_header.serialize(&mut writer)?;
644 self.base_box.serialize(&mut writer, self.full_header.version)?;
645 Ok(())
646 }
647}
648
649impl IsoSized for TrackLoudnessInfo {
650 fn size(&self) -> usize {
651 Self::add_header_size(self.full_header.size() + self.base_box.size(self.full_header.version))
652 }
653}
654
655#[derive(IsoBox, Debug, PartialEq, Eq)]
659#[iso_box(box_type = b"alou", skip_impl(deserialize_seed, serialize, sized), crate_path = crate)]
660pub struct AlbumLoudnessInfo {
661 pub full_header: FullBoxHeader,
663 pub base_box: LoudnessBaseBox,
665}
666
667impl<'a> DeserializeSeed<'a, BoxHeader> for AlbumLoudnessInfo {
668 fn deserialize_seed<R>(mut reader: R, _seed: BoxHeader) -> std::io::Result<Self>
669 where
670 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
671 {
672 let full_header = FullBoxHeader::deserialize(&mut reader)?;
673 let base_box = LoudnessBaseBox::deserialize_seed(&mut reader, &full_header)?;
674
675 Ok(Self { full_header, base_box })
676 }
677}
678
679impl Serialize for AlbumLoudnessInfo {
680 fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
681 where
682 W: std::io::Write,
683 {
684 self.serialize_box_header(&mut writer)?;
685 self.full_header.serialize(&mut writer)?;
686 self.base_box.serialize(&mut writer, self.full_header.version)?;
687 Ok(())
688 }
689}
690
691impl IsoSized for AlbumLoudnessInfo {
692 fn size(&self) -> usize {
693 Self::add_header_size(self.full_header.size() + self.base_box.size(self.full_header.version))
694 }
695}
696
697#[derive(IsoBox, Debug, PartialEq, Eq)]
701#[iso_box(box_type = b"ludt", crate_path = crate)]
702pub struct LoudnessBox {
703 #[iso_box(nested_box(collect))]
705 pub loudness: Vec<TrackLoudnessInfo>,
706 #[iso_box(nested_box(collect))]
708 pub album_loudness: Vec<AlbumLoudnessInfo>,
709}