diff --git a/CHANGELOG.md b/CHANGELOG.md index c55cbe5..59e63c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog +- update Kira to 0.9 + - removed `playback_region` from `SoundSettings` - fix spatial audio when position of receiver and emitter are the same ([#135](https://github.com/NiklasEi/bevy_kira_audio/issues/135)) ## v0.21.0 - 30.11.2024 diff --git a/Cargo.toml b/Cargo.toml index 42cca5f..b038380 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ settings_loader = ["dep:ron", "dep:serde", "kira/serde"] bevy = { version = "0.15.0", default-features = false, features = ["bevy_asset"] } anyhow = "1.0" uuid = { version = "1", features = ["fast-rng"] } -kira = { version = "0.8.7", default-features = false, features = ["cpal"] } +kira = { version = "0.9.6", default-features = false, features = ["cpal"] } ron = { version = "0.8", optional = true } serde = { version = "1.0", features = ["derive"], optional = true } parking_lot = "0.12" diff --git a/assets/sounds/loop_with_settings.ogg.ron b/assets/sounds/loop_with_settings.ogg.ron index f857f37..ccb33a4 100644 --- a/assets/sounds/loop_with_settings.ogg.ron +++ b/assets/sounds/loop_with_settings.ogg.ron @@ -3,7 +3,7 @@ file: "sounds/loop.ogg", // Start sound at 2 seconds - playback_region: Region(start: Seconds(2.), end: EndOfAudio), + start_position: 2., // Half amplitude volume: 0.5, // Play 50% faster (this also changes the pitch) diff --git a/examples/stress_test.rs b/examples/stress_test.rs index cdce1a7..b1f69e6 100644 --- a/examples/stress_test.rs +++ b/examples/stress_test.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use bevy_kira_audio::prelude::*; /// This example needs to be played in release mode! `cargo run --example stress_test --release` -/// A large amount (75) of sounds will be played in every frame. +/// A large amount (100) of sounds will be played in every frame. /// /// The main objective here is to demonstrate that the plugin and Kira can handle /// large sound volumes over a longer period of time. diff --git a/src/audio.rs b/src/audio.rs index e65f632..2ac330e 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -18,6 +18,7 @@ use std::marker::PhantomData; use std::time::Duration; use uuid::Uuid; +#[derive(Debug)] pub(crate) enum AudioCommand { Play(PlayAudioSettings), SetVolume(Volume, Option), @@ -28,14 +29,13 @@ pub(crate) enum AudioCommand { Resume(Option), } -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub(crate) struct PartialSoundSettings { pub(crate) loop_start: Option, pub(crate) loop_end: Option, pub(crate) volume: Option, pub(crate) playback_rate: Option, pub(crate) start_position: Option, - pub(crate) end_position: Option, pub(crate) panning: Option, pub(crate) reverse: Option, pub(crate) paused: bool, @@ -45,10 +45,10 @@ pub(crate) struct PartialSoundSettings { /// Different kinds of easing for fade-in and fade-out pub type AudioEasing = kira::tween::Easing; -#[derive(Clone)] /// A tween for audio transitions /// /// Use the default for almost instantaneous transitions without audio artifacts +#[derive(Clone, Debug)] pub struct AudioTween { duration: Duration, easing: AudioEasing, @@ -133,10 +133,7 @@ impl PartialSoundSettings { sound.settings.playback_rate = playback_rate.into(); } if let Some(start) = self.start_position { - sound.settings.playback_region.start = start.into(); - } - if let Some(end) = self.end_position { - sound.settings.playback_region.end = EndPosition::Custom(end.into()); + sound.settings.start_position = start.into(); } if let Some(panning) = self.panning { sound.settings.panning = Value::Fixed(panning); @@ -154,6 +151,7 @@ impl PartialSoundSettings { } } +#[derive(Debug)] pub struct PlayAudioSettings { pub(crate) instance_handle: Handle, pub(crate) source: Handle, @@ -244,13 +242,6 @@ impl<'a> PlayAudioCommand<'a> { self } - /// End the sound at the given position in seconds. - pub fn end_at(&mut self, end_position: f64) -> &mut Self { - self.settings.end_position = Some(end_position); - - self - } - /// Set the panning of the sound. /// /// The default value is 0.5. diff --git a/src/audio_output.rs b/src/audio_output.rs index 353861d..88281d7 100644 --- a/src/audio_output.rs +++ b/src/audio_output.rs @@ -14,10 +14,10 @@ use bevy::asset::{Assets, Handle}; use bevy::ecs::change_detection::{NonSendMut, ResMut}; use bevy::ecs::system::{NonSend, Res, Resource}; use bevy::ecs::world::{FromWorld, World}; -use bevy::log::{error, warn}; +use bevy::log::warn; use kira::manager::backend::{Backend, DefaultBackend}; use kira::manager::AudioManager; -use kira::{sound::PlaybackRate, CommandError, Volume}; +use kira::{sound::PlaybackRate, Volume}; use std::collections::HashMap; /// Non-send resource that acts as audio output @@ -57,15 +57,7 @@ impl AudioOutput { let tween = map_tween(tween); for instance in instances { if let Some(instance) = audio_instances.get_mut(instance.id()) { - match instance.handle.stop(tween) { - Err(CommandError::CommandQueueFull) => { - return AudioCommandResult::Retry; - } - Err(error) => { - error!("Failed to stop instance: {:?}", error); - } - _ => (), - } + instance.handle.stop(tween); } } } @@ -84,9 +76,7 @@ impl AudioOutput { for instance in instance_handles.iter_mut() { if let Some(instance) = audio_instances.get_mut(instance.id()) { if kira::sound::PlaybackState::Playing == instance.handle.state() { - if let Err(error) = instance.handle.pause(tween) { - error!("Failed to pause instance: {:?}", error); - } + instance.handle.pause(tween); } } } @@ -116,9 +106,7 @@ impl AudioOutput { || instance.handle.state() == kira::sound::PlaybackState::Pausing || instance.handle.state() == kira::sound::PlaybackState::Stopping { - if let Err(error) = instance.handle.resume(tween) { - error!("Failed to resume instance: {:?}", error); - } + instance.handle.resume(tween); } } } @@ -142,9 +130,7 @@ impl AudioOutput { let tween = map_tween(tween); for instance in instances.iter_mut() { if let Some(instance) = audio_instances.get_mut(instance.id()) { - if let Err(error) = instance.handle.set_volume(volume, tween) { - error!("Failed to set volume for instance: {:?}", error); - } + instance.handle.set_volume(volume, tween); } } } @@ -170,9 +156,7 @@ impl AudioOutput { let tween = map_tween(tween); for instance in instances.iter_mut() { if let Some(instance) = audio_instances.get_mut(instance.id()) { - if let Err(error) = instance.handle.set_panning(panning, tween) { - error!("Failed to set panning for instance: {:?}", error); - } + instance.handle.set_panning(panning, tween); } } } @@ -198,9 +182,7 @@ impl AudioOutput { let tween = map_tween(tween); for instance in instances.iter_mut() { if let Some(instance) = audio_instances.get_mut(instance.id()) { - if let Err(error) = instance.handle.set_playback_rate(playback_rate, tween) { - error!("Failed to set playback rate for instance: {:?}", error); - } + instance.handle.set_playback_rate(playback_rate, tween); } } } @@ -244,32 +226,17 @@ impl AudioOutput { let mut sound_handle = sound_handle.unwrap(); if let Some(channel_state) = self.channels.get(channel) { if channel_state.paused { - if let Err(error) = sound_handle.pause(kira::tween::Tween::default()) { - warn!( - "Failed to pause instance (channel was paused) due to {:?}", - error - ); - } + sound_handle.pause(kira::tween::Tween::default()); let playback_rate = partial_sound_settings .playback_rate .unwrap_or(channel_state.playback_rate); - if let Err(error) = - sound_handle.set_playback_rate(playback_rate, kira::tween::Tween::default()) - { - error!("Failed to set playback rate for instance: {:?}", error); - } + sound_handle.set_playback_rate(playback_rate, kira::tween::Tween::default()); } } if partial_sound_settings.paused { - if let Err(error) = sound_handle.pause(kira::tween::Tween::default()) { - warn!("Failed to pause instance due to {:?}", error); - } + sound_handle.pause(kira::tween::Tween::default()); let playback_rate = partial_sound_settings.playback_rate.unwrap_or(1.0); - if let Err(error) = - sound_handle.set_playback_rate(playback_rate, kira::tween::Tween::default()) - { - error!("Failed to set playback rate for instance: {:?}", error); - } + sound_handle.set_playback_rate(playback_rate, kira::tween::Tween::default()); } audio_instances.insert( &instance_handle, diff --git a/src/backend_settings.rs b/src/backend_settings.rs index aec4bc9..431c1b2 100644 --- a/src/backend_settings.rs +++ b/src/backend_settings.rs @@ -17,7 +17,7 @@ pub struct AudioSettings { /// Note that configuring a channel will cause one command per sound in the channel! pub command_capacity: usize, /// The maximum number of sounds that can be playing at a time. - pub sound_capacity: usize, + pub sound_capacity: u16, } impl Default for AudioSettings { diff --git a/src/instance.rs b/src/instance.rs index 05b7dbc..deeee90 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -2,8 +2,7 @@ use crate::{AudioTween, PlaybackState}; use bevy::asset::{Asset, Assets, Handle}; use kira::sound::static_sound::StaticSoundHandle; use kira::tween::Value; -use kira::{CommandError, Volume}; -use thiserror::Error; +use kira::Volume; #[derive(Asset, bevy::reflect::TypePath)] /// Asset for direct audio control @@ -11,50 +10,20 @@ pub struct AudioInstance { pub(crate) handle: StaticSoundHandle, } -/// Errors that can occur when directly controlling audio -#[derive(Error, Debug)] -pub enum AudioCommandError { - /// The audio command que of the audio manager is full - #[error("the audio thread could not handle the command, because its command que is full")] - CommandQueueFull, - - /// Something went wrong when handling the command in the audio thread - #[error("an error occurred while handling the command in the audio thread")] - AudioThreadError, -} - -impl From for AudioCommandError { - fn from(kira_error: CommandError) -> Self { - match kira_error { - CommandError::CommandQueueFull => AudioCommandError::CommandQueueFull, - _ => AudioCommandError::AudioThreadError, - } - } -} - impl AudioInstance { /// Pause the audio instance with the given easing - pub fn pause(&mut self, tween: AudioTween) -> Option { - self.handle - .pause(tween.into()) - .err() - .map(|kira_error| kira_error.into()) + pub fn pause(&mut self, tween: AudioTween) { + self.handle.pause(tween.into()); } /// Resume the audio instance with the given easing - pub fn resume(&mut self, tween: AudioTween) -> Option { - self.handle - .resume(tween.into()) - .err() - .map(|kira_error| kira_error.into()) + pub fn resume(&mut self, tween: AudioTween) { + self.handle.resume(tween.into()); } /// Stop the audio instance with the given easing - pub fn stop(&mut self, tween: AudioTween) -> Option { - self.handle - .stop(tween.into()) - .err() - .map(|kira_error| kira_error.into()) + pub fn stop(&mut self, tween: AudioTween) { + self.handle.stop(tween.into()); } /// Get the state of the audio instance @@ -65,30 +34,16 @@ impl AudioInstance { /// Set the volume of the audio instance /// /// Default is `1.0` - pub fn set_volume( - &mut self, - volume: impl Into>, - tween: AudioTween, - ) -> Option { - self.handle - .set_volume(volume, tween.into()) - .err() - .map(|kira_error| kira_error.into()) + pub fn set_volume(&mut self, volume: impl Into>, tween: AudioTween) { + self.handle.set_volume(volume, tween.into()); } /// Sets the playback rate of the sound. /// /// Changing the playback rate will change both the speed /// and pitch of the sound. - pub fn set_playback_rate( - &mut self, - playback_rate: f64, - tween: AudioTween, - ) -> Option { - self.handle - .set_playback_rate(playback_rate, tween.into()) - .err() - .map(|kira_error| kira_error.into()) + pub fn set_playback_rate(&mut self, playback_rate: f64, tween: AudioTween) { + self.handle.set_playback_rate(playback_rate, tween.into()); } /// Sets the panning of the sound @@ -96,27 +51,18 @@ impl AudioInstance { /// `0.0` is hard left, /// `0.5` is center (default) /// `1.0` is hard right. - pub fn set_panning(&mut self, panning: f64, tween: AudioTween) -> Option { - self.handle - .set_panning(panning, tween.into()) - .err() - .map(|kira_error| kira_error.into()) + pub fn set_panning(&mut self, panning: f64, tween: AudioTween) { + self.handle.set_panning(panning, tween.into()); } /// Sets the playback position to the specified time in seconds. - pub fn seek_to(&mut self, position: f64) -> Option { - self.handle - .seek_to(position) - .err() - .map(|kira_error| kira_error.into()) + pub fn seek_to(&mut self, position: f64) { + self.handle.seek_to(position); } /// Moves the playback position by the specified amount of time in seconds. - pub fn seek_by(&mut self, amount: f64) -> Option { - self.handle - .seek_by(amount) - .err() - .map(|kira_error| kira_error.into()) + pub fn seek_by(&mut self, amount: f64) { + self.handle.seek_by(amount); } } diff --git a/src/lib.rs b/src/lib.rs index d834260..288569b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,7 +69,7 @@ pub mod prelude { #[doc(hidden)] pub use crate::channel::AudioControl; #[doc(hidden)] - pub use crate::instance::{AudioCommandError, AudioInstance, AudioInstanceAssetsExt}; + pub use crate::instance::{AudioInstance, AudioInstanceAssetsExt}; #[doc(hidden)] #[cfg(feature = "flac")] pub use crate::source::flac_loader::*; @@ -92,12 +92,11 @@ pub mod prelude { #[doc(hidden)] pub use crate::{Audio, AudioPlugin, MainTrack}; pub use kira::{ - dsp::Frame, sound::{ static_sound::{StaticSoundData, StaticSoundSettings}, FromFileError, Sound, SoundData, }, - Volume, + Frame, Volume, }; } diff --git a/src/source/flac_loader.rs b/src/source/flac_loader.rs index 7a81beb..7a56d2c 100644 --- a/src/source/flac_loader.rs +++ b/src/source/flac_loader.rs @@ -1,7 +1,7 @@ use anyhow::Result; use bevy::asset::io::Reader; use bevy::asset::{AssetLoader, LoadContext}; -use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings}; +use kira::sound::static_sound::StaticSoundData; use kira::sound::FromFileError; use std::io::Cursor; use thiserror::Error; @@ -37,8 +37,7 @@ impl AssetLoader for FlacLoader { ) -> Result { let mut sound_bytes = vec![]; reader.read_to_end(&mut sound_bytes).await?; - let sound = - StaticSoundData::from_cursor(Cursor::new(sound_bytes), StaticSoundSettings::default())?; + let sound = StaticSoundData::from_cursor(Cursor::new(sound_bytes))?; Ok(AudioSource { sound }) } diff --git a/src/source/mp3_loader.rs b/src/source/mp3_loader.rs index 2c91c2f..8204813 100644 --- a/src/source/mp3_loader.rs +++ b/src/source/mp3_loader.rs @@ -1,7 +1,7 @@ use anyhow::Result; use bevy::asset::io::Reader; use bevy::asset::{AssetLoader, LoadContext}; -use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings}; +use kira::sound::static_sound::StaticSoundData; use kira::sound::FromFileError; use std::io::Cursor; use thiserror::Error; @@ -37,8 +37,7 @@ impl AssetLoader for Mp3Loader { ) -> Result { let mut sound_bytes = vec![]; reader.read_to_end(&mut sound_bytes).await?; - let sound = - StaticSoundData::from_cursor(Cursor::new(sound_bytes), StaticSoundSettings::default())?; + let sound = StaticSoundData::from_cursor(Cursor::new(sound_bytes))?; Ok(AudioSource { sound }) } diff --git a/src/source/ogg_loader.rs b/src/source/ogg_loader.rs index 2c17471..afe7415 100644 --- a/src/source/ogg_loader.rs +++ b/src/source/ogg_loader.rs @@ -1,7 +1,7 @@ use anyhow::Result; use bevy::asset::io::Reader; use bevy::asset::{AssetLoader, LoadContext}; -use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings}; +use kira::sound::static_sound::StaticSoundData; use kira::sound::FromFileError; use std::io::Cursor; use thiserror::Error; @@ -37,8 +37,7 @@ impl AssetLoader for OggLoader { ) -> Result { let mut sound_bytes = vec![]; reader.read_to_end(&mut sound_bytes).await?; - let sound = - StaticSoundData::from_cursor(Cursor::new(sound_bytes), StaticSoundSettings::default())?; + let sound = StaticSoundData::from_cursor(Cursor::new(sound_bytes))?; Ok(AudioSource { sound }) } diff --git a/src/source/settings_loader.rs b/src/source/settings_loader.rs index 67b0046..cbb0f47 100644 --- a/src/source/settings_loader.rs +++ b/src/source/settings_loader.rs @@ -4,7 +4,7 @@ use std::{io::Cursor, path::PathBuf}; use bevy::asset::io::Reader; use bevy::asset::{AssetLoader, LoadContext, ReadAssetBytesError}; use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings}; -use kira::sound::{EndPosition, FromFileError, PlaybackPosition, PlaybackRate, Region}; +use kira::sound::{FromFileError, PlaybackPosition, PlaybackRate, Region}; use kira::tween::Tween; use kira::Volume; use serde::Deserialize; @@ -26,9 +26,9 @@ struct SoundSettings { /// Location of the sound file. file: PathBuf, - /// The region of the sound that should be played. - #[serde(default = "default_full_file")] - pub playback_region: Region, + /// The second from which the sound should be started. + #[serde(default)] + pub start_position: f64, /// The portion of the sound that should be looped. #[serde(default)] @@ -70,13 +70,6 @@ struct SoundSettings { pub fade_in_tween: Option, } -fn default_full_file() -> Region { - Region { - start: PlaybackPosition::Samples(0), - end: EndPosition::EndOfAudio, - } -} - fn default_one() -> f64 { 1.0 } @@ -89,7 +82,7 @@ impl From for StaticSoundSettings { fn from(settings: SoundSettings) -> Self { let mut static_sound_settings = StaticSoundSettings::new(); - static_sound_settings.playback_region = settings.playback_region; + static_sound_settings.start_position = PlaybackPosition::Seconds(settings.start_position); static_sound_settings.volume = Volume::from(settings.volume).into(); static_sound_settings.playback_rate = PlaybackRate::from(settings.playback_rate).into(); static_sound_settings.panning = settings.panning.into(); @@ -140,7 +133,8 @@ impl AssetLoader for SettingsLoader { .read_asset_bytes(sound_settings.file.clone()) .await?; - let sound = StaticSoundData::from_cursor(Cursor::new(sound_bytes), sound_settings.into())?; + let mut sound = StaticSoundData::from_cursor(Cursor::new(sound_bytes))?; + sound.settings = sound_settings.into(); Ok(AudioSource { sound }) } diff --git a/src/source/wav_loader.rs b/src/source/wav_loader.rs index b8130fb..ac3e8f6 100644 --- a/src/source/wav_loader.rs +++ b/src/source/wav_loader.rs @@ -1,7 +1,7 @@ use anyhow::Result; use bevy::asset::io::Reader; use bevy::asset::{AssetLoader, LoadContext}; -use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings}; +use kira::sound::static_sound::StaticSoundData; use kira::sound::FromFileError; use std::io::Cursor; use thiserror::Error; @@ -37,8 +37,7 @@ impl AssetLoader for WavLoader { ) -> Result { let mut sound_bytes = vec![]; reader.read_to_end(&mut sound_bytes).await?; - let sound = - StaticSoundData::from_cursor(Cursor::new(sound_bytes), StaticSoundSettings::default())?; + let sound = StaticSoundData::from_cursor(Cursor::new(sound_bytes))?; Ok(AudioSource { sound }) } fn extensions(&self) -> &[&str] {