1use symphonia_core::audio::{AudioBuffer, Channels, Layout, SignalSpec};
9use symphonia_core::codecs::{CodecType, CODEC_TYPE_MP1, CODEC_TYPE_MP2, CODEC_TYPE_MP3};
10use symphonia_core::errors::Result;
11
12use symphonia_core::io::BufReader;
13
14#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16pub enum MpegVersion {
17 Mpeg2p5,
19 Mpeg2,
21 Mpeg1,
23}
24
25#[derive(Copy, Clone, Debug, PartialEq, Eq)]
27pub enum MpegLayer {
28 Layer1,
30 Layer2,
32 Layer3,
34}
35
36#[derive(Copy, Clone, Debug, PartialEq, Eq)]
39pub enum Mode {
40 Layer3 { mid_side: bool, intensity: bool },
42 Intensity { bound: u32 },
45}
46
47#[derive(Copy, Clone, Debug, PartialEq, Eq)]
49pub enum ChannelMode {
50 Mono,
52 DualMono,
54 Stereo,
56 JointStereo(Mode),
58}
59
60impl ChannelMode {
61 #[inline(always)]
63 pub fn count(&self) -> usize {
64 match self {
65 ChannelMode::Mono => 1,
66 _ => 2,
67 }
68 }
69
70 #[inline(always)]
72 pub fn channels(&self) -> Channels {
73 match self {
74 ChannelMode::Mono => Channels::FRONT_LEFT,
75 _ => Channels::FRONT_LEFT | Channels::FRONT_RIGHT,
76 }
77 }
78}
79
80#[derive(Copy, Clone, Debug, PartialEq, Eq)]
82pub enum Emphasis {
83 None,
85 Fifty15,
87 CcitJ17,
89}
90
91#[derive(Debug)]
93pub struct FrameHeader {
94 pub version: MpegVersion,
95 pub layer: MpegLayer,
96 pub bitrate: u32,
97 pub sample_rate: u32,
98 pub sample_rate_idx: usize,
99 pub channel_mode: ChannelMode,
100 pub emphasis: Emphasis,
101 pub is_copyrighted: bool,
102 pub is_original: bool,
103 pub has_padding: bool,
104 pub has_crc: bool,
105 pub frame_size: usize,
106}
107
108impl FrameHeader {
109 #[inline(always)]
111 pub fn is_mpeg1(&self) -> bool {
112 self.version == MpegVersion::Mpeg1
113 }
114
115 #[inline(always)]
117 #[allow(dead_code)]
118 pub fn is_mpeg2p5(&self) -> bool {
119 self.version == MpegVersion::Mpeg2p5
120 }
121
122 pub fn codec(&self) -> CodecType {
124 match self.layer {
125 MpegLayer::Layer1 => CODEC_TYPE_MP1,
126 MpegLayer::Layer2 => CODEC_TYPE_MP2,
127 MpegLayer::Layer3 => CODEC_TYPE_MP3,
128 }
129 }
130
131 #[allow(dead_code)]
133 pub fn spec(&self) -> SignalSpec {
134 let layout = match self.n_channels() {
135 1 => Layout::Mono,
136 2 => Layout::Stereo,
137 _ => unreachable!(),
138 };
139
140 SignalSpec::new_with_layout(self.sample_rate, layout)
141 }
142
143 pub fn duration(&self) -> u64 {
145 match self.layer {
146 MpegLayer::Layer1 => 384,
147 MpegLayer::Layer2 => 1152,
148 MpegLayer::Layer3 => 576 * self.n_granules() as u64,
149 }
150 }
151
152 #[inline(always)]
154 pub fn n_granules(&self) -> usize {
155 match self.version {
156 MpegVersion::Mpeg1 => 2,
157 _ => 1,
158 }
159 }
160
161 #[inline(always)]
163 pub fn n_channels(&self) -> usize {
164 self.channel_mode.count()
165 }
166
167 #[allow(dead_code)]
169 #[inline(always)]
170 pub fn is_intensity_stereo(&self) -> bool {
171 match self.channel_mode {
172 ChannelMode::JointStereo(Mode::Intensity { .. }) => true,
173 ChannelMode::JointStereo(Mode::Layer3 { intensity, .. }) => intensity,
174 _ => false,
175 }
176 }
177
178 #[inline(always)]
180 pub fn side_info_len(&self) -> usize {
181 match (self.version, self.channel_mode) {
182 (MpegVersion::Mpeg1, ChannelMode::Mono) => 17,
183 (MpegVersion::Mpeg1, _) => 32,
184 (_, ChannelMode::Mono) => 9,
185 (_, _) => 17,
186 }
187 }
188}
189
190pub trait Layer {
191 fn decode(
192 &mut self,
193 reader: &mut BufReader<'_>,
194 header: &FrameHeader,
195 out: &mut AudioBuffer<f32>,
196 ) -> Result<()>;
197}