use std::io::Cursor;
use symphonia::core::io::{MediaSource, MediaSourceStream};
use crate::sound::{
FromFileError, static_sound::StaticSoundSettings, symphonia::load_frames_from_buffer_ref,
};
use super::StaticSoundData;
impl StaticSoundData {
#[cfg(not(target_arch = "wasm32"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "symphonia", not(wasm32)))))]
pub fn from_file(path: impl AsRef<std::path::Path>) -> Result<Self, FromFileError> {
Self::from_media_source(std::fs::File::open(path)?)
}
#[cfg_attr(docsrs, doc(cfg(feature = "symphonia")))]
pub fn from_cursor<T: AsRef<[u8]> + Send + Sync + 'static>(
cursor: Cursor<T>,
) -> Result<StaticSoundData, FromFileError> {
Self::from_media_source(cursor)
}
#[cfg_attr(docsrs, doc(cfg(feature = "symphonia")))]
pub fn from_media_source(
media_source: impl MediaSource + 'static,
) -> Result<Self, FromFileError> {
Self::from_boxed_media_source(Box::new(media_source))
}
fn from_boxed_media_source(media_source: Box<dyn MediaSource>) -> Result<Self, FromFileError> {
let codecs = symphonia::default::get_codecs();
let probe = symphonia::default::get_probe();
let mss = MediaSourceStream::new(media_source, Default::default());
let mut format_reader = probe
.format(
&Default::default(),
mss,
&Default::default(),
&Default::default(),
)?
.format;
let default_track = format_reader
.default_track()
.ok_or(FromFileError::NoDefaultTrack)?;
let default_track_id = default_track.id;
let codec_params = &default_track.codec_params;
let sample_rate = codec_params
.sample_rate
.ok_or(FromFileError::UnknownSampleRate)?;
let mut decoder = codecs.make(codec_params, &Default::default())?;
let mut frames = vec![];
loop {
match format_reader.next_packet() {
Ok(packet) => {
if default_track_id == packet.track_id() {
let buffer = decoder.decode(&packet)?;
frames.append(&mut load_frames_from_buffer_ref(&buffer)?);
}
}
Err(error) => match error {
symphonia::core::errors::Error::IoError(error) => {
if error.kind() == std::io::ErrorKind::UnexpectedEof {
break;
}
return Err(symphonia::core::errors::Error::IoError(error).into());
}
error => return Err(error.into()),
},
}
}
Ok(Self {
sample_rate,
frames: frames.into(),
settings: StaticSoundSettings::default(),
slice: None,
})
}
}