Skip to main content

selene_core/symphonia_helpers/
raw_decoder.rs

1use std::fs;
2
3use symphonia::{
4    core::{
5        audio::{GenericAudioBuffer, GenericAudioBufferRef},
6        codecs::audio::{AudioDecoder, AudioDecoderOptions},
7        errors::Error as SymphoniaError,
8        formats::{FormatOptions, FormatReader, TrackType},
9        io::{MediaSourceStream, MediaSourceStreamOptions},
10    },
11    default::formats::{FlacReader, MpaReader, OggReader, WavReader},
12};
13
14use thiserror::Error;
15
16use crate::{
17    errors::ContainerError,
18    media_container::{ContainerFormat, MediaContainer, Stream},
19};
20
21#[derive(Debug, Error)]
22pub enum DecodingError {
23    #[error("{0}")]
24    Io(#[from] std::io::Error),
25
26    #[error("{0}")]
27    Symphonia(#[from] SymphoniaError),
28
29    #[error("{0}")]
30    Container(#[from] ContainerError),
31
32    #[error("Player attempted to play an unsupported container: '{0:?}'")]
33    UnsupportedContainer(ContainerFormat),
34}
35
36pub struct RawDecoder {
37    pub stream: Stream,
38    pub format_reader: Box<dyn FormatReader>,
39    pub decoder: Box<dyn AudioDecoder>,
40}
41
42impl RawDecoder {
43    pub fn from_container(
44        container: &MediaContainer,
45        buffer_len: usize,
46    ) -> Result<Self, DecodingError> {
47        let file = fs::File::open(container.path())?;
48
49        let options = MediaSourceStreamOptions { buffer_len };
50        let mss = MediaSourceStream::new(Box::new(file), options);
51
52        let fmt_opts = FormatOptions::default();
53        let format_reader: Box<dyn FormatReader> = match container.format() {
54            ContainerFormat::Flac => Box::new(FlacReader::try_new(mss, fmt_opts)?),
55            ContainerFormat::Mpa => Box::new(MpaReader::try_new(mss, fmt_opts)?),
56            ContainerFormat::Ogg => Box::new(OggReader::try_new(mss, fmt_opts)?),
57            ContainerFormat::Wav => Box::new(WavReader::try_new(mss, fmt_opts)?),
58            other => return Err(DecodingError::UnsupportedContainer(*other)),
59        };
60
61        let track = format_reader
62            .default_track(TrackType::Audio)
63            .expect("Playable file does not have any supported codecs");
64
65        let dec_opts: AudioDecoderOptions = Default::default();
66
67        let params = track
68            .codec_params
69            .as_ref()
70            .expect("Track is not playable")
71            .audio()
72            .unwrap();
73        let decoder = symphonia::default::get_codecs().make_audio_decoder(params, &dec_opts)?;
74
75        Ok(Self {
76            stream: Stream::try_from(track)?,
77            format_reader,
78            decoder,
79        })
80    }
81
82    pub fn decode_next_packet(&mut self) -> Result<Option<GenericAudioBuffer>, 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                Ok(None) => return Ok(None),
91                Err(err) => return Err(DecodingError::Symphonia(err)),
92            };
93
94            while !self.format_reader.metadata().is_latest() {
95                self.format_reader.metadata().pop();
96            }
97
98            if packet.track_id() != self.stream.id {
99                continue;
100            }
101
102            let decoded = match self.decoder.decode(&packet) {
103                Ok(decoded) => decoded,
104                Err(SymphoniaError::DecodeError(_)) => continue,
105                Err(SymphoniaError::IoError(_)) => continue,
106                Err(err) => return Err(DecodingError::Symphonia(err)),
107            };
108
109            let audio_buf = match decoded {
110                GenericAudioBufferRef::U8(audio_buffer) => {
111                    GenericAudioBuffer::U8(audio_buffer.clone())
112                }
113                GenericAudioBufferRef::U16(audio_buffer) => {
114                    GenericAudioBuffer::U16(audio_buffer.clone())
115                }
116                GenericAudioBufferRef::U24(audio_buffer) => {
117                    GenericAudioBuffer::U24(audio_buffer.clone())
118                }
119                GenericAudioBufferRef::U32(audio_buffer) => {
120                    GenericAudioBuffer::U32(audio_buffer.clone())
121                }
122                GenericAudioBufferRef::S8(audio_buffer) => {
123                    GenericAudioBuffer::S8(audio_buffer.clone())
124                }
125                GenericAudioBufferRef::S16(audio_buffer) => {
126                    GenericAudioBuffer::S16(audio_buffer.clone())
127                }
128                GenericAudioBufferRef::S24(audio_buffer) => {
129                    GenericAudioBuffer::S24(audio_buffer.clone())
130                }
131                GenericAudioBufferRef::S32(audio_buffer) => {
132                    GenericAudioBuffer::S32(audio_buffer.clone())
133                }
134                GenericAudioBufferRef::F32(audio_buffer) => {
135                    GenericAudioBuffer::F32(audio_buffer.clone())
136                }
137                GenericAudioBufferRef::F64(audio_buffer) => {
138                    GenericAudioBuffer::F64(audio_buffer.clone())
139                }
140            };
141
142            return Ok(Some(audio_buf));
143        }
144    }
145}