diff --git a/crates/kira/Cargo.toml b/crates/kira/Cargo.toml index 4be18d7c..3f3a5e6f 100644 --- a/crates/kira/Cargo.toml +++ b/crates/kira/Cargo.toml @@ -18,7 +18,7 @@ mint = "0.5.9" pastey = "0.2.1" rtrb = "0.3.2" serde = { version = "1.0.219", features = ["derive"], optional = true } -symphonia = { version = "0.5.4", optional = true, default-features = false } +symphonia = { version = "0.6.0", optional = true, default-features = false } triple_buffer = "9.0.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies.cpal] diff --git a/crates/kira/src/sound/static_sound/data/from_file.rs b/crates/kira/src/sound/static_sound/data/from_file.rs index cf232072..e2736df8 100644 --- a/crates/kira/src/sound/static_sound/data/from_file.rs +++ b/crates/kira/src/sound/static_sound/data/from_file.rs @@ -1,6 +1,7 @@ use std::io::Cursor; use symphonia::core::io::{MediaSource, MediaSourceStream}; +use symphonia::core::{codecs::CodecParameters, formats::TrackType}; use crate::sound::{ FromFileError, static_sound::StaticSoundSettings, symphonia::load_frames_from_buffer_ref, @@ -37,41 +38,35 @@ impl StaticSoundData { 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 mut format_reader = probe.probe( + &Default::default(), + mss, + Default::default(), + Default::default(), + )?; let default_track = format_reader - .default_track() + .default_track(TrackType::Audio) .ok_or(FromFileError::NoDefaultTrack)?; let default_track_id = default_track.id; - let codec_params = &default_track.codec_params; - let sample_rate = codec_params + let audio_params = match default_track.codec_params.as_ref() { + Some(CodecParameters::Audio(p)) => p, + _ => return Err(FromFileError::NoDefaultTrack), + }; + let sample_rate = audio_params .sample_rate .ok_or(FromFileError::UnknownSampleRate)?; - let mut decoder = codecs.make(codec_params, &Default::default())?; + let mut decoder = codecs.make_audio_decoder(audio_params, &Default::default())?; let mut frames = vec![]; loop { match format_reader.next_packet() { - Ok(packet) => { - if default_track_id == packet.track_id() { + Ok(Some(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(None) => break, + Err(error) => return Err(error.into()), } } Ok(Self { diff --git a/crates/kira/src/sound/streaming/decoder/symphonia.rs b/crates/kira/src/sound/streaming/decoder/symphonia.rs index 129539d7..618dde20 100644 --- a/crates/kira/src/sound/streaming/decoder/symphonia.rs +++ b/crates/kira/src/sound/streaming/decoder/symphonia.rs @@ -5,15 +5,15 @@ use crate::{ sound::{FromFileError, symphonia::load_frames_from_buffer_ref}, }; use symphonia::core::{ - codecs::Decoder, - formats::{FormatReader, SeekMode, SeekTo}, + codecs::{CodecParameters, audio::AudioDecoder}, + formats::{FormatReader, SeekMode, SeekTo, TrackType, probe::Hint}, io::{MediaSource, MediaSourceStream}, - probe::Hint, + units::Timestamp, }; pub(crate) struct SymphoniaDecoder { format_reader: Box, - decoder: Box, + decoder: Box, sample_rate: u32, num_frames: usize, track_id: u32, @@ -24,28 +24,28 @@ impl SymphoniaDecoder { let codecs = symphonia::default::get_codecs(); let probe = symphonia::default::get_probe(); let mss = MediaSourceStream::new(media_source, Default::default()); - let format_reader = probe - .format( - &Hint::default(), - mss, - &Default::default(), - &Default::default(), - )? - .format; + let format_reader = probe.probe( + &Hint::default(), + mss, + Default::default(), + Default::default(), + )?; let default_track = format_reader - .default_track() + .default_track(TrackType::Audio) .ok_or(FromFileError::NoDefaultTrack)?; - let sample_rate = default_track - .codec_params + let audio_params = match default_track.codec_params.as_ref() { + Some(CodecParameters::Audio(p)) => p, + _ => return Err(FromFileError::NoDefaultTrack), + }; + let sample_rate = audio_params .sample_rate .ok_or(FromFileError::UnknownSampleRate)?; let num_frames = default_track - .codec_params - .n_frames + .num_frames .ok_or(FromFileError::UnknownSampleRate)? .try_into() .expect("could not convert u64 into usize"); - let decoder = codecs.make(&default_track.codec_params, &Default::default())?; + let decoder = codecs.make_audio_decoder(audio_params, &Default::default())?; let track_id = default_track.id; Ok(Self { format_reader, @@ -70,9 +70,10 @@ impl super::Decoder for SymphoniaDecoder { fn decode(&mut self) -> Result, Self::Error> { let packet = loop { - let packet = self.format_reader.next_packet()?; - if self.track_id == packet.track_id() { - break packet; + match self.format_reader.next_packet()? { + Some(packet) if packet.track_id == self.track_id => break packet, + Some(_) => continue, + None => return Ok(vec![]), } }; let buffer = self.decoder.decode(&packet)?; @@ -82,14 +83,16 @@ impl super::Decoder for SymphoniaDecoder { fn seek(&mut self, index: usize) -> Result { let seeked_to = self.format_reader.seek( SeekMode::Accurate, - SeekTo::TimeStamp { - ts: index.try_into().expect("could not convert usize into u64"), + SeekTo::Timestamp { + ts: Timestamp::new(index as i64), track_id: self.track_id, }, )?; - Ok(seeked_to - .actual_ts - .try_into() - .expect("could not convert u64 into usize")) + let actual = seeked_to.actual_ts.get(); + Ok(if actual < 0 { + 0 + } else { + (actual as usize).min(self.num_frames) + }) } } diff --git a/crates/kira/src/sound/symphonia.rs b/crates/kira/src/sound/symphonia.rs index d707a546..15954b46 100644 --- a/crates/kira/src/sound/symphonia.rs +++ b/crates/kira/src/sound/symphonia.rs @@ -1,5 +1,5 @@ -use symphonia::core::{ - audio::{AudioBuffer, AudioBufferRef, Signal}, +use symphonia::core::audio::{ + Audio, AudioBuffer, GenericAudioBufferRef, conv::{FromSample, IntoSample}, sample::Sample, }; @@ -8,18 +8,20 @@ use crate::frame::Frame; use super::FromFileError; -pub fn load_frames_from_buffer_ref(buffer: &AudioBufferRef) -> Result, FromFileError> { +pub fn load_frames_from_buffer_ref( + buffer: &GenericAudioBufferRef, +) -> Result, FromFileError> { match buffer { - AudioBufferRef::U8(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::U16(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::U24(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::U32(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::S8(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::S16(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::S24(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::S32(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::F32(buffer) => load_frames_from_buffer(buffer), - AudioBufferRef::F64(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::U8(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::U16(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::U24(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::U32(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::S8(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::S16(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::S24(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::S32(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::F32(buffer) => load_frames_from_buffer(buffer), + GenericAudioBufferRef::F64(buffer) => load_frames_from_buffer(buffer), } } @@ -29,16 +31,18 @@ pub fn load_frames_from_buffer( where f32: FromSample, { - match buffer.spec().channels.count() { + match buffer.num_planes() { 1 => Ok(buffer - .chan(0) + .plane(0) + .unwrap() .iter() .map(|sample| Frame::from_mono((*sample).into_sample())) .collect()), 2 => Ok(buffer - .chan(0) + .plane(0) + .unwrap() .iter() - .zip(buffer.chan(1).iter()) + .zip(buffer.plane(1).unwrap().iter()) .map(|(left, right)| Frame::new((*left).into_sample(), (*right).into_sample())) .collect()), _ => Err(FromFileError::UnsupportedChannelConfiguration),