symphonia_bundle_mp3/
common.rs

1// Symphonia
2// Copyright (c) 2019-2022 The Project Symphonia Developers.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
8use 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/// The MPEG audio version.
15#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16pub enum MpegVersion {
17    /// Version 2.5
18    Mpeg2p5,
19    /// Version 2
20    Mpeg2,
21    /// Version 1
22    Mpeg1,
23}
24
25/// The MPEG audio layer.
26#[derive(Copy, Clone, Debug, PartialEq, Eq)]
27pub enum MpegLayer {
28    /// Layer 1
29    Layer1,
30    /// Layer 2
31    Layer2,
32    /// Layer 3
33    Layer3,
34}
35
36/// For Joint Stereo channel mode, the mode extension describes the features and parameters of the
37/// stereo encoding.
38#[derive(Copy, Clone, Debug, PartialEq, Eq)]
39pub enum Mode {
40    /// Joint Stereo in layer 3 may use both Mid-Side and Intensity encoding.
41    Layer3 { mid_side: bool, intensity: bool },
42    /// Joint Stereo in layers 1 and 2 may only use Intensity encoding on a set of bands. The range
43    /// of bands using intensity encoding is `bound..32`.
44    Intensity { bound: u32 },
45}
46
47/// The channel mode.
48#[derive(Copy, Clone, Debug, PartialEq, Eq)]
49pub enum ChannelMode {
50    /// Single mono audio channel.
51    Mono,
52    /// Dual mono audio channels.
53    DualMono,
54    /// Stereo channels.
55    Stereo,
56    /// Joint Stereo encoded channels (decodes to Stereo).
57    JointStereo(Mode),
58}
59
60impl ChannelMode {
61    /// Gets the number of channels.
62    #[inline(always)]
63    pub fn count(&self) -> usize {
64        match self {
65            ChannelMode::Mono => 1,
66            _ => 2,
67        }
68    }
69
70    /// Gets the the channel map.
71    #[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/// The emphasis applied during encoding.
81#[derive(Copy, Clone, Debug, PartialEq, Eq)]
82pub enum Emphasis {
83    /// No emphasis
84    None,
85    /// 50/15us
86    Fifty15,
87    /// CCIT J.17
88    CcitJ17,
89}
90
91/// A MPEG 1, 2, or 2.5 audio frame header.
92#[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    /// Returns true if this a MPEG1 frame, false otherwise.
114    #[inline(always)]
115    pub fn is_mpeg1(&self) -> bool {
116        self.version == MpegVersion::Mpeg1
117    }
118
119    /// Returns true if this a MPEG2.5 frame, false otherwise.
120    #[inline(always)]
121    #[allow(dead_code)]
122    pub fn is_mpeg2p5(&self) -> bool {
123        self.version == MpegVersion::Mpeg2p5
124    }
125
126    /// Returns the codec type for the frame.
127    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    /// Returns a signal specification for the frame.
136    #[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    /// Returns the number of audio samples in the frame per channel.
148    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    /// Returns the number of granules in the frame.
157    #[inline(always)]
158    pub fn n_granules(&self) -> usize {
159        match self.version {
160            MpegVersion::Mpeg1 => 2,
161            _ => 1,
162        }
163    }
164
165    /// Returns the number of channels per granule.
166    #[inline(always)]
167    pub fn n_channels(&self) -> usize {
168        self.channel_mode.count()
169    }
170
171    /// Returns true if Intensity Stereo encoding is used, false otherwise.
172    #[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    /// Get the side information length.
183    #[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}