Skip to main content

selene_core/symphonia_helpers/
raw_decoder.rs

1use std::fs;
2
3use symphonia::{
4    core::{
5        audio::GenericAudioBufferRef,
6        codecs::audio::{AudioDecoder, AudioDecoderOptions},
7        errors::Error as SymphoniaError,
8        formats::{FormatOptions, FormatReader, TrackType},
9        io::{MediaSourceStream, MediaSourceStreamOptions},
10    },
11    default::formats::{AiffReader, FlacReader, MpaReader, OggReader, WavReader},
12};
13
14use thiserror::Error;
15
16use crate::media_container::{ContainerError, ContainerFormat, MediaContainer, Stream};
17
18#[derive(Debug, Error)]
19pub enum DecodingError {
20    #[error("{0}")]
21    Io(#[from] std::io::Error),
22
23    #[error("{0}")]
24    Symphonia(#[from] SymphoniaError),
25
26    #[error("{0}")]
27    Container(#[from] ContainerError),
28
29    #[error("Player attempted to play an unsupported container: '{0:?}'")]
30    UnsupportedContainer(ContainerFormat),
31}
32
33pub struct RawDecoder {
34    pub stream: Stream,
35    pub format_reader: Box<dyn FormatReader>,
36    pub decoder: Box<dyn AudioDecoder>,
37}
38
39impl RawDecoder {
40    pub fn from_container(
41        container: &MediaContainer,
42        buffer_len: usize,
43    ) -> Result<Self, DecodingError> {
44        let file = fs::File::open(container.path())?;
45
46        let options = MediaSourceStreamOptions { buffer_len };
47        let mss = MediaSourceStream::new(Box::new(file), options);
48
49        let fmt_opts = FormatOptions::default();
50        let format_reader: Box<dyn FormatReader> = match container.format() {
51            ContainerFormat::Flac => Box::new(FlacReader::try_new(mss, fmt_opts)?),
52            ContainerFormat::Mpa => Box::new(MpaReader::try_new(mss, fmt_opts)?),
53            ContainerFormat::Ogg => Box::new(OggReader::try_new(mss, fmt_opts)?),
54            ContainerFormat::Wav => Box::new(WavReader::try_new(mss, fmt_opts)?),
55            ContainerFormat::Aiff => Box::new(AiffReader::try_new(mss, fmt_opts)?),
56            other => return Err(DecodingError::UnsupportedContainer(*other)),
57        };
58
59        let track = format_reader
60            .default_track(TrackType::Audio)
61            .expect("Playable file does not have any supported codecs");
62
63        let dec_opts: AudioDecoderOptions = Default::default();
64
65        let params = track
66            .codec_params
67            .as_ref()
68            .expect("Track is not playable")
69            .audio()
70            .unwrap();
71        let decoder = symphonia::default::get_codecs().make_audio_decoder(params, &dec_opts)?;
72
73        Ok(Self {
74            stream: Stream::try_from(track)?,
75            format_reader,
76            decoder,
77        })
78    }
79
80    pub fn decode_next_packet(
81        &mut self,
82    ) -> Result<Option<GenericAudioBufferRef<'_>>, DecodingError> {
83        loop {
84            let packet = match self.format_reader.next_packet() {
85                Ok(Some(packet)) => packet,
86                Err(SymphoniaError::ResetRequired) => {
87                    self.decoder.reset();
88                    continue;
89                }
90                Err(SymphoniaError::IoError(err))
91                    if matches!(err.kind(), std::io::ErrorKind::UnexpectedEof) =>
92                {
93                    return Ok(None);
94                }
95                Ok(None) => return Ok(None),
96                Err(err) => return Err(DecodingError::Symphonia(err)),
97            };
98
99            while !self.format_reader.metadata().is_latest() {
100                self.format_reader.metadata().pop();
101            }
102
103            if packet.track_id() == self.stream.id {
104                return match self.decoder.decode(&packet) {
105                    Ok(decoded) => Ok(Some(decoded)),
106                    Err(SymphoniaError::DecodeError(_)) => Ok(None),
107                    Err(SymphoniaError::IoError(_)) => Ok(None),
108                    Err(err) => Err(DecodingError::Symphonia(err)),
109                };
110            }
111        }
112    }
113}