Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to Kira 0.9 #138

Merged
merged 1 commit into from
Jan 3, 2025
Merged
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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion assets/sounds/loop_with_settings.ogg.ron
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion examples/stress_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 5 additions & 14 deletions src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AudioTween>),
Expand All @@ -28,14 +29,13 @@ pub(crate) enum AudioCommand {
Resume(Option<AudioTween>),
}

#[derive(Clone, Default)]
#[derive(Clone, Default, Debug)]
pub(crate) struct PartialSoundSettings {
pub(crate) loop_start: Option<f64>,
pub(crate) loop_end: Option<f64>,
pub(crate) volume: Option<Volume>,
pub(crate) playback_rate: Option<f64>,
pub(crate) start_position: Option<f64>,
pub(crate) end_position: Option<f64>,
pub(crate) panning: Option<f64>,
pub(crate) reverse: Option<bool>,
pub(crate) paused: bool,
Expand All @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -154,6 +151,7 @@ impl PartialSoundSettings {
}
}

#[derive(Debug)]
pub struct PlayAudioSettings {
pub(crate) instance_handle: Handle<AudioInstance>,
pub(crate) source: Handle<AudioSource>,
Expand Down Expand Up @@ -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.
Expand Down
57 changes: 12 additions & 45 deletions src/audio_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -57,15 +57,7 @@ impl<B: Backend> AudioOutput<B> {
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);
}
}
}
Expand All @@ -84,9 +76,7 @@ impl<B: Backend> AudioOutput<B> {
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);
}
}
}
Expand Down Expand Up @@ -116,9 +106,7 @@ impl<B: Backend> AudioOutput<B> {
|| 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);
}
}
}
Expand All @@ -142,9 +130,7 @@ impl<B: Backend> AudioOutput<B> {
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);
}
}
}
Expand All @@ -170,9 +156,7 @@ impl<B: Backend> AudioOutput<B> {
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);
}
}
}
Expand All @@ -198,9 +182,7 @@ impl<B: Backend> AudioOutput<B> {
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);
}
}
}
Expand Down Expand Up @@ -244,32 +226,17 @@ impl<B: Backend> AudioOutput<B> {
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,
Expand Down
2 changes: 1 addition & 1 deletion src/backend_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
88 changes: 17 additions & 71 deletions src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,28 @@ 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
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<CommandError> 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<AudioCommandError> {
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<AudioCommandError> {
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<AudioCommandError> {
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
Expand All @@ -65,58 +34,35 @@ impl AudioInstance {
/// Set the volume of the audio instance
///
/// Default is `1.0`
pub fn set_volume(
&mut self,
volume: impl Into<Value<Volume>>,
tween: AudioTween,
) -> Option<AudioCommandError> {
self.handle
.set_volume(volume, tween.into())
.err()
.map(|kira_error| kira_error.into())
pub fn set_volume(&mut self, volume: impl Into<Value<Volume>>, 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<AudioCommandError> {
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
///
/// `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<AudioCommandError> {
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<AudioCommandError> {
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<AudioCommandError> {
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);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -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,
};
}

Expand Down
Loading
Loading