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 Kira to 0.9 #131

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
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 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", 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
19 changes: 16 additions & 3 deletions src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use bevy::asset::{AssetId, Handle};
use bevy::ecs::system::Resource;
use bevy::prelude::{default, IntoSystemConfigs, PostUpdate};
use kira::sound::static_sound::{StaticSoundData, StaticSoundHandle};
use kira::sound::EndPosition;
use kira::sound::{EndPosition, PlaybackPosition};
use kira::tween::Value;
use kira::Volume;
use std::marker::PhantomData;
Expand Down Expand Up @@ -133,11 +133,24 @@ impl PartialSoundSettings {
sound.settings.playback_rate = playback_rate.into();
}
if let Some(start) = self.start_position {
sound.settings.playback_region.start = start.into();
sound.settings.start_position = PlaybackPosition::Seconds(start);
}

if let Some(end) = self.end_position {
sound.settings.playback_region.end = EndPosition::Custom(end.into());
let end_frame = (end * sound.sample_rate as f64).round() as usize;

if let Some(start) = self.start_position {
let start_frame = (start * sound.sample_rate as f64).round() as usize;

sound.slice = Some((start_frame, end_frame));
} else {
sound.slice = Some((0, end_frame));
}
} else if let Some(start) = self.start_position {
let start_frame = (start * sound.sample_rate as f64).round() as usize;
sound.slice = Some((start_frame, sound.frames.len()));
}

if let Some(panning) = self.panning {
sound.settings.panning = Value::Fixed(panning);
}
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
5 changes: 2 additions & 3 deletions src/source/flac_loader.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use bevy::asset::io::Reader;
use kira::sound::static_sound::StaticSoundData;
use bevy::asset::{AssetLoader, LoadContext};
use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings};
use kira::sound::FromFileError;
use std::io::Cursor;
use thiserror::Error;
Expand Down Expand Up @@ -37,8 +37,7 @@ impl AssetLoader for FlacLoader {
) -> Result<Self::Asset, Self::Error> {
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 })
}

Expand Down
5 changes: 2 additions & 3 deletions src/source/mp3_loader.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use bevy::asset::io::Reader;
use kira::sound::static_sound::StaticSoundData;
use bevy::asset::{AssetLoader, LoadContext};
use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings};
use kira::sound::FromFileError;
use std::io::Cursor;
use thiserror::Error;
Expand Down Expand Up @@ -37,8 +37,7 @@ impl AssetLoader for Mp3Loader {
) -> Result<Self::Asset, Self::Error> {
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 })
}

Expand Down
5 changes: 2 additions & 3 deletions src/source/ogg_loader.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use bevy::asset::io::Reader;
use kira::sound::static_sound::StaticSoundData;
use bevy::asset::{AssetLoader, LoadContext};
use kira::sound::static_sound::{StaticSoundData, StaticSoundSettings};
use kira::sound::FromFileError;
use std::io::Cursor;
use thiserror::Error;
Expand Down Expand Up @@ -37,8 +37,7 @@ impl AssetLoader for OggLoader {
) -> Result<Self::Asset, Self::Error> {
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 })
}

Expand Down
Loading
Loading