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    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    /// Returns true if this a MPEG1 frame, false otherwise.
110    #[inline(always)]
111    pub fn is_mpeg1(&self) -> bool {
112        self.version == MpegVersion::Mpeg1
113    }
114
115    /// Returns true if this a MPEG2.5 frame, false otherwise.
116    #[inline(always)]
117    #[allow(dead_code)]
118    pub fn is_mpeg2p5(&self) -> bool {
119        self.version == MpegVersion::Mpeg2p5
120    }
121
122    /// Returns the codec type for the frame.
123    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    /// Returns a signal specification for the frame.
132    #[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    /// Returns the number of audio samples in the frame per channel.
144    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    /// Returns the number of granules in the frame.
153    #[inline(always)]
154    pub fn n_granules(&self) -> usize {
155        match self.version {
156            MpegVersion::Mpeg1 => 2,
157            _ => 1,
158        }
159    }
160
161    /// Returns the number of channels per granule.
162    #[inline(always)]
163    pub fn n_channels(&self) -> usize {
164        self.channel_mode.count()
165    }
166
167    /// Returns true if Intensity Stereo encoding is used, false otherwise.
168    #[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    /// Get the side information length.
179    #[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}