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 #[allow(dead_code)]
101 pub emphasis: Emphasis,
102 #[allow(dead_code)]
103 pub is_copyrighted: bool,
104 #[allow(dead_code)]
105 pub is_original: bool,
106 #[allow(dead_code)]
107 pub has_padding: bool,
108 pub has_crc: bool,
109 pub frame_size: usize,
110}
111
112impl FrameHeader {
113 #[inline(always)]
115 pub fn is_mpeg1(&self) -> bool {
116 self.version == MpegVersion::Mpeg1
117 }
118
119 #[inline(always)]
121 #[allow(dead_code)]
122 pub fn is_mpeg2p5(&self) -> bool {
123 self.version == MpegVersion::Mpeg2p5
124 }
125
126 pub fn codec(&self) -> CodecType {
128 match self.layer {
129 MpegLayer::Layer1 => CODEC_TYPE_MP1,
130 MpegLayer::Layer2 => CODEC_TYPE_MP2,
131 MpegLayer::Layer3 => CODEC_TYPE_MP3,
132 }
133 }
134
135 #[allow(dead_code)]
137 pub fn spec(&self) -> SignalSpec {
138 let layout = match self.n_channels() {
139 1 => Layout::Mono,
140 2 => Layout::Stereo,
141 _ => unreachable!(),
142 };
143
144 SignalSpec::new_with_layout(self.sample_rate, layout)
145 }
146
147 pub fn duration(&self) -> u64 {
149 match self.layer {
150 MpegLayer::Layer1 => 384,
151 MpegLayer::Layer2 => 1152,
152 MpegLayer::Layer3 => 576 * self.n_granules() as u64,
153 }
154 }
155
156 #[inline(always)]
158 pub fn n_granules(&self) -> usize {
159 match self.version {
160 MpegVersion::Mpeg1 => 2,
161 _ => 1,
162 }
163 }
164
165 #[inline(always)]
167 pub fn n_channels(&self) -> usize {
168 self.channel_mode.count()
169 }
170
171 #[allow(dead_code)]
173 #[inline(always)]
174 pub fn is_intensity_stereo(&self) -> bool {
175 match self.channel_mode {
176 ChannelMode::JointStereo(Mode::Intensity { .. }) => true,
177 ChannelMode::JointStereo(Mode::Layer3 { intensity, .. }) => intensity,
178 _ => false,
179 }
180 }
181
182 #[inline(always)]
184 pub fn side_info_len(&self) -> usize {
185 match (self.version, self.channel_mode) {
186 (MpegVersion::Mpeg1, ChannelMode::Mono) => 17,
187 (MpegVersion::Mpeg1, _) => 32,
188 (_, ChannelMode::Mono) => 9,
189 (_, _) => 17,
190 }
191 }
192}
193
194pub trait Layer {
195 fn decode(
196 &mut self,
197 reader: &mut BufReader<'_>,
198 header: &FrameHeader,
199 out: &mut AudioBuffer<f32>,
200 ) -> Result<()>;
201}