Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/kira/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
41 changes: 18 additions & 23 deletions crates/kira/src/sound/static_sound/data/from_file.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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 {
Expand Down
57 changes: 30 additions & 27 deletions crates/kira/src/sound/streaming/decoder/symphonia.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn FormatReader>,
decoder: Box<dyn Decoder>,
decoder: Box<dyn AudioDecoder>,
sample_rate: u32,
num_frames: usize,
track_id: u32,
Expand All @@ -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,
Expand All @@ -70,9 +70,10 @@ impl super::Decoder for SymphoniaDecoder {

fn decode(&mut self) -> Result<Vec<Frame>, 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)?;
Expand All @@ -82,14 +83,16 @@ impl super::Decoder for SymphoniaDecoder {
fn seek(&mut self, index: usize) -> Result<usize, Self::Error> {
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)
})
}
}
38 changes: 21 additions & 17 deletions crates/kira/src/sound/symphonia.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use symphonia::core::{
audio::{AudioBuffer, AudioBufferRef, Signal},
use symphonia::core::audio::{
Audio, AudioBuffer, GenericAudioBufferRef,
conv::{FromSample, IntoSample},
sample::Sample,
};
Expand All @@ -8,18 +8,20 @@ use crate::frame::Frame;

use super::FromFileError;

pub fn load_frames_from_buffer_ref(buffer: &AudioBufferRef) -> Result<Vec<Frame>, FromFileError> {
pub fn load_frames_from_buffer_ref(
buffer: &GenericAudioBufferRef,
) -> Result<Vec<Frame>, 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),
}
}

Expand All @@ -29,16 +31,18 @@ pub fn load_frames_from_buffer<S: Sample>(
where
f32: FromSample<S>,
{
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),
Expand Down