1#![forbid(unsafe_code)]
6#![allow(
7 clippy::redundant_pub_crate,
8 reason = "crate-private helpers used by mux.rs/demux.rs; module itself is private"
9)]
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[non_exhaustive]
14pub enum MpegVersion {
15 Mpeg1,
17 Mpeg2,
19 Mpeg25,
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25#[non_exhaustive]
26pub enum ChannelMode {
27 Stereo,
29 JointStereo,
31 DualChannel,
33 Mono,
35}
36
37impl ChannelMode {
38 pub(crate) const fn bits(self) -> u8 {
39 match self {
40 Self::Stereo => 0,
41 Self::JointStereo => 1,
42 Self::DualChannel => 2,
43 Self::Mono => 3,
44 }
45 }
46
47 pub(crate) const fn from_bits(bits: u8) -> Self {
48 match bits & 0x03 {
49 0 => Self::Stereo,
50 1 => Self::JointStereo,
51 2 => Self::DualChannel,
52 _ => Self::Mono,
53 }
54 }
55}
56
57const MPEG1_SAMPLE_RATES: [u32; 3] = [44_100, 48_000, 32_000];
58const MPEG2_SAMPLE_RATES: [u32; 3] = [22_050, 24_000, 16_000];
59const MPEG25_SAMPLE_RATES: [u32; 3] = [11_025, 12_000, 8_000];
60
61const MPEG1_LAYER3_BITRATES_KBPS: [u16; 14] = [
62 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,
63];
64const MPEG2_LAYER3_BITRATES_KBPS: [u16; 14] =
65 [8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160];
66
67pub(crate) const fn sample_rate_table(version: MpegVersion) -> [u32; 3] {
68 match version {
69 MpegVersion::Mpeg1 => MPEG1_SAMPLE_RATES,
70 MpegVersion::Mpeg2 => MPEG2_SAMPLE_RATES,
71 MpegVersion::Mpeg25 => MPEG25_SAMPLE_RATES,
72 }
73}
74
75pub(crate) const fn bitrate_table(version: MpegVersion) -> [u16; 14] {
76 match version {
77 MpegVersion::Mpeg1 => MPEG1_LAYER3_BITRATES_KBPS,
78 MpegVersion::Mpeg2 | MpegVersion::Mpeg25 => MPEG2_LAYER3_BITRATES_KBPS,
79 }
80}
81
82pub(crate) const fn frame_len_coefficient(version: MpegVersion) -> u32 {
84 match version {
85 MpegVersion::Mpeg1 => 144_000,
86 MpegVersion::Mpeg2 | MpegVersion::Mpeg25 => 72_000,
87 }
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq)]
97pub struct FrameHeader {
98 pub version: MpegVersion,
100 pub bitrate_kbps: u16,
102 pub sample_rate: u32,
104 pub channel_mode: ChannelMode,
106}
107
108impl FrameHeader {
109 #[must_use]
111 pub const fn frame_len(self, padding: bool) -> usize {
112 let coeff = frame_len_coefficient(self.version) * self.bitrate_kbps as u32;
113 let base = coeff / self.sample_rate;
114 base as usize + if padding { 1 } else { 0 }
115 }
116}