symphonia_bundle_mp3/
decoder.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::{AsAudioBufferRef, AudioBuffer, AudioBufferRef, Signal};
9use symphonia_core::codecs::{CodecDescriptor, CodecParameters, CodecType};
10use symphonia_core::codecs::{Decoder, DecoderOptions, FinalizeResult};
11use symphonia_core::errors::{decode_error, unsupported_error, Result};
12use symphonia_core::formats::Packet;
13use symphonia_core::io::FiniteStream;
14use symphonia_core::support_codec;
15
16#[cfg(feature = "mp1")]
17use symphonia_core::codecs::CODEC_TYPE_MP1;
18#[cfg(feature = "mp2")]
19use symphonia_core::codecs::CODEC_TYPE_MP2;
20#[cfg(feature = "mp3")]
21use symphonia_core::codecs::CODEC_TYPE_MP3;
22
23use super::{common::*, header};
24
25#[cfg(feature = "mp1")]
26use crate::layer1;
27#[cfg(feature = "mp2")]
28use crate::layer2;
29#[cfg(feature = "mp3")]
30use crate::layer3;
31
32enum State {
33    #[cfg(feature = "mp1")]
34    Layer1(layer1::Layer1),
35    #[cfg(feature = "mp2")]
36    Layer2(layer2::Layer2),
37    #[cfg(feature = "mp3")]
38    Layer3(Box<layer3::Layer3>),
39}
40
41impl State {
42    fn new(codec: CodecType) -> Self {
43        match codec {
44            #[cfg(feature = "mp1")]
45            CODEC_TYPE_MP1 => State::Layer1(layer1::Layer1::new()),
46            #[cfg(feature = "mp2")]
47            CODEC_TYPE_MP2 => State::Layer2(layer2::Layer2::new()),
48            #[cfg(feature = "mp3")]
49            CODEC_TYPE_MP3 => State::Layer3(Box::new(layer3::Layer3::new())),
50            _ => unreachable!(),
51        }
52    }
53}
54
55/// MPEG1 and MPEG2 audio layer 1, 2, and 3 decoder.
56pub struct MpaDecoder {
57    params: CodecParameters,
58    state: State,
59    buf: AudioBuffer<f32>,
60}
61
62impl MpaDecoder {
63    fn decode_inner(&mut self, packet: &Packet) -> Result<()> {
64        let mut reader = packet.as_buf_reader();
65
66        let header = header::read_frame_header(&mut reader)?;
67
68        // The packet should be the size stated in the header.
69        if header.frame_size != reader.bytes_available() as usize {
70            return decode_error("mpa: invalid packet length");
71        }
72
73        // The audio buffer can only be created after the first frame is decoded.
74        if self.buf.is_unused() {
75            self.buf = AudioBuffer::new(1152, header.spec());
76        }
77        else {
78            // Ensure the packet contains an audio frame with the same signal specification as the
79            // buffer.
80            //
81            // TODO: Is it worth it to support changing signal specifications?
82            if self.buf.spec() != &header.spec() {
83                return decode_error("mpa: invalid audio buffer signal spec for packet");
84            }
85        }
86
87        // Clear the audio buffer.
88        self.buf.clear();
89
90        // Choose the decode step based on the MPEG layer and the current codec type.
91        match &mut self.state {
92            #[cfg(feature = "mp1")]
93            State::Layer1(layer) if header.layer == MpegLayer::Layer1 => {
94                layer.decode(&mut reader, &header, &mut self.buf)?;
95            }
96            #[cfg(feature = "mp2")]
97            State::Layer2(layer) if header.layer == MpegLayer::Layer2 => {
98                layer.decode(&mut reader, &header, &mut self.buf)?;
99            }
100            #[cfg(feature = "mp3")]
101            State::Layer3(layer) if header.layer == MpegLayer::Layer3 => {
102                layer.decode(&mut reader, &header, &mut self.buf)?;
103            }
104            _ => return decode_error("mpa: invalid mpeg audio layer"),
105        }
106
107        self.buf.trim(packet.trim_start() as usize, packet.trim_end() as usize);
108
109        Ok(())
110    }
111}
112
113impl Decoder for MpaDecoder {
114    fn try_new(params: &CodecParameters, _: &DecoderOptions) -> Result<Self> {
115        // This decoder only supports MP1, MP2, and MP3.
116        match params.codec {
117            #[cfg(feature = "mp1")]
118            CODEC_TYPE_MP1 => (),
119            #[cfg(feature = "mp2")]
120            CODEC_TYPE_MP2 => (),
121            #[cfg(feature = "mp3")]
122            CODEC_TYPE_MP3 => (),
123            _ => return unsupported_error("mpa: invalid codec type"),
124        }
125
126        // Create decoder state.
127        let state = State::new(params.codec);
128
129        Ok(MpaDecoder { params: params.clone(), state, buf: AudioBuffer::unused() })
130    }
131
132    fn supported_codecs() -> &'static [CodecDescriptor] {
133        &[
134            #[cfg(feature = "mp1")]
135            support_codec!(CODEC_TYPE_MP1, "mp1", "MPEG Audio Layer 1"),
136            #[cfg(feature = "mp2")]
137            support_codec!(CODEC_TYPE_MP2, "mp2", "MPEG Audio Layer 2"),
138            #[cfg(feature = "mp3")]
139            support_codec!(CODEC_TYPE_MP3, "mp3", "MPEG Audio Layer 3"),
140        ]
141    }
142
143    fn codec_params(&self) -> &CodecParameters {
144        &self.params
145    }
146
147    fn reset(&mut self) {
148        // Fully reset the decoder state.
149        self.state = State::new(self.params.codec);
150    }
151
152    fn decode(&mut self, packet: &Packet) -> Result<AudioBufferRef<'_>> {
153        if let Err(e) = self.decode_inner(packet) {
154            self.buf.clear();
155            Err(e)
156        }
157        else {
158            Ok(self.buf.as_audio_buffer_ref())
159        }
160    }
161
162    fn finalize(&mut self) -> FinalizeResult {
163        Default::default()
164    }
165
166    fn last_decoded(&self) -> AudioBufferRef<'_> {
167        self.buf.as_audio_buffer_ref()
168    }
169}