Skip to content

Commit

Permalink
Combine playback settings with channel settings
Browse files Browse the repository at this point in the history
  • Loading branch information
NiklasEi committed Jan 11, 2024
1 parent 2d59ec8 commit 0387710
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 65 deletions.
8 changes: 4 additions & 4 deletions examples/custom_channel.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bevy::prelude::*;
use bevy_kira_audio::prelude::*;
use bevy_kira_audio::{
AudioBundle, AudioChannel, AudioChannelBundle, AudioRegion, ChannelState, PlaybackSettings,
AudioBundle, AudioChannel, AudioChannelBundle, AudioRegion, ChannelSettings, PlaybackSettings,
};

fn main() {
Expand All @@ -15,7 +15,7 @@ fn main() {

// Use the channel via the `AudioChannel<Background>` resource
fn play(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(AudioChannelBundle::<Background>::default());
commands.spawn(AudioChannelBundle::new::<Background>());
commands.spawn((
AudioBundle {
source: asset_server.load("sounds/loop.ogg"),
Expand All @@ -25,7 +25,7 @@ fn play(mut commands: Commands, asset_server: Res<AssetServer>) {
},
..default()
},
AudioChannel::<Background>::default(),
AudioChannel::new::<Background>(),
));
}

Expand All @@ -42,7 +42,7 @@ fn on_click_single(mut audio: Query<&mut AudioInstance>, input: Res<Input<MouseB
}

fn on_click_channel(
mut channel: Query<&mut ChannelState, With<AudioChannel<Background>>>,
mut channel: Query<&mut ChannelSettings, (With<AudioChannel>, With<Background>)>,
input: Res<Input<MouseButton>>,
) {
let Ok(mut audio_channel) = channel.get_single_mut() else {
Expand Down
90 changes: 58 additions & 32 deletions src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ use crate::channel::typed::OldAudioChannel;
use crate::channel::AudioCommandQue;
use crate::instance::AudioInstance;
use crate::source::AudioSource;
use crate::{AudioSystemSet, ChannelState};
use bevy::app::App;
use crate::{AudioChannel, AudioSystemSet, ChannelSettings};
use bevy::app::{App, Startup};
use bevy::asset::{AssetId, Handle};
use bevy::ecs::system::Resource;
use bevy::prelude::{default, Bundle, Component, IntoSystemConfigs, PostUpdate};
use bevy::prelude::{
default, Bundle, Commands, Component, In, IntoSystem, IntoSystemConfigs, PostUpdate,
};
use bevy::utils::Uuid;
use kira::sound::static_sound::{StaticSoundData, StaticSoundHandle};
use kira::sound::EndPosition;
use kira::tween::Value;
use kira::Volume;
use std::any::TypeId;
use std::marker::PhantomData;
use std::time::Duration;

Expand Down Expand Up @@ -403,37 +406,43 @@ impl Default for AudioBundle {
}
}

#[derive(Component)]
#[derive(Component, Clone)]
pub struct PlaybackSettings {
pub loop_region: Option<AudioRegion>,
pub custom_playback_region: Option<AudioRegion>,
pub paused: bool,
pub reverse: bool,
pub playback_rate: f64,
pub volume: f64,
pub panning: f64,
pub fade_in: Option<AudioTween>,
}

impl Default for PlaybackSettings {
fn default() -> Self {
Self {
loop_region: None,
custom_playback_region: None,
fade_in: None,
paused: false,
reverse: false,
playback_rate: 1.0,
volume: 1.0,
panning: 0.5,
}
}
}

impl PlaybackSettings {
pub(crate) fn apply(&self, sound: &mut StaticSoundData) {
self.apply_with_channel_state(&ChannelState::default(), sound);
pub fn apply_channel_settings(&mut self, channel_state: &ChannelSettings) {
self.paused = self.paused || channel_state.paused;
self.volume = self.volume * channel_state.volume.as_amplitude();
self.playback_rate = self.playback_rate * channel_state.playback_rate;
// Todo: combine panning?
//self.panning =
}

pub(crate) fn apply_with_channel_state(
&self,
channel_state: &ChannelState,
sound: &mut StaticSoundData,
) {
pub(crate) fn apply(&self, sound: &mut StaticSoundData) {
if let Some(loop_settings) = &self.loop_region {
sound
.settings
Expand All @@ -444,33 +453,28 @@ impl PlaybackSettings {
sound.settings.loop_region.unwrap().end = EndPosition::Custom(end.into());
}
}
sound.settings.volume =
Value::Fixed((self.volume * channel_state.volume.as_amplitude()).into());
sound.settings.playback_rate =
Value::Fixed((self.playback_rate * channel_state.playback_rate).into());
sound.settings.volume = Value::Fixed(self.volume.into());
sound.settings.playback_rate = Value::Fixed(self.playback_rate.into());
if let Some(region) = &self.custom_playback_region {
sound.settings.playback_region.start = region.start.into();
if let Some(end) = region.end {
sound.settings.playback_region.end = EndPosition::Custom(end.into());
}
}
// if let Some(panning) = self.panning {
// sound.settings.panning = Value::Fixed(panning);
// }
// if let Some(reverse) = self.reverse {
// sound.settings.reverse = reverse;
// }
// if let Some(AudioTween { duration, easing }) = self.fade_in {
// sound.settings.fade_in_tween = Some(kira::tween::Tween {
// duration,
// easing,
// ..default()
// });
// }
}
}

#[derive(Component, Default)]
if self.reverse {
sound.settings.reverse = true;
}
if let Some(AudioTween { duration, easing }) = self.fade_in {
sound.settings.fade_in_tween = Some(kira::tween::Tween {
duration,
easing,
..default()
});
}
}
}

#[derive(Component, Default, Clone)]
pub struct AudioRegion {
start: f64,
end: Option<f64>,
Expand Down Expand Up @@ -565,6 +569,11 @@ pub trait AudioApp {
/// ```
#[deprecated]
fn add_audio_channel<T: Resource>(&mut self) -> &mut Self;

fn register_audio_channel<C: Component + Default>(
&mut self,
settings: ChannelSettings,
) -> &mut Self;
}

impl AudioApp for App {
Expand All @@ -575,4 +584,21 @@ impl AudioApp for App {
)
.insert_resource(OldAudioChannel::<T>::default())
}

fn register_audio_channel<C: Component + Default>(
&mut self,
settings: ChannelSettings,
) -> &mut Self {
self.add_systems(
Startup,
(move || settings.clone()).pipe(setup_audio_channel::<C>),
)
}
}

fn setup_audio_channel<C: Component + Default>(
In(settings): In<ChannelSettings>,
mut commands: Commands,
) {
commands.spawn((AudioChannel::new::<C>(), settings, C::default()));
}
19 changes: 10 additions & 9 deletions src/audio_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::any::TypeId;

use crate::backend_settings::AudioSettings;
use crate::channel::dynamic::DynamicAudioChannels;
use crate::channel::{Channel, ChannelState};
use crate::channel::{Channel, ChannelSettings};
use crate::instance::AudioInstance;
use crate::source::AudioSource;
use crate::{AudioChannel, OldAudioChannel, PlaybackState};
Expand All @@ -29,7 +29,7 @@ use std::collections::HashMap;
pub(crate) struct AudioOutput<B: Backend = DefaultBackend> {
manager: Option<AudioManager<B>>,
instances: HashMap<Channel, Vec<Handle<AudioInstance>>>,
channels: HashMap<Channel, ChannelState>,
channels: HashMap<Channel, ChannelSettings>,
}

impl FromWorld for AudioOutput {
Expand Down Expand Up @@ -96,7 +96,7 @@ impl<B: Backend> AudioOutput<B> {
if let Some(channel_state) = self.channels.get_mut(channel) {
channel_state.paused = true;
} else {
let channel_state = ChannelState {
let channel_state = ChannelSettings {
paused: true,
..Default::default()
};
Expand Down Expand Up @@ -129,7 +129,7 @@ impl<B: Backend> AudioOutput<B> {
channel_state.paused = false;
} else {
self.channels
.insert(channel.clone(), ChannelState::default());
.insert(channel.clone(), ChannelSettings::default());
}
}

Expand All @@ -153,7 +153,7 @@ impl<B: Backend> AudioOutput<B> {
if let Some(channel_state) = self.channels.get_mut(channel) {
channel_state.volume = volume;
} else {
let channel_state = ChannelState {
let channel_state = ChannelSettings {
volume,
..Default::default()
};
Expand Down Expand Up @@ -181,7 +181,7 @@ impl<B: Backend> AudioOutput<B> {
if let Some(channel_state) = self.channels.get_mut(channel) {
channel_state.panning = panning;
} else {
let channel_state = ChannelState {
let channel_state = ChannelSettings {
panning,
..Default::default()
};
Expand Down Expand Up @@ -209,7 +209,7 @@ impl<B: Backend> AudioOutput<B> {
if let Some(channel_state) = self.channels.get_mut(channel) {
channel_state.playback_rate = playback_rate;
} else {
let channel_state = ChannelState {
let channel_state = ChannelSettings {
playback_rate,
..Default::default()
};
Expand Down Expand Up @@ -413,14 +413,15 @@ impl<B: Backend> AudioOutput<B> {
&mut self,
audio_sources: &Assets<AudioSource>,
source: &Handle<AudioSource>,
settings: &PlaybackSettings,
mut settings: PlaybackSettings,
audio_entity_commands: &mut EntityCommands,
) {
let Some(audio_source) = audio_sources.get(source) else {
return;
};
let mut sound = audio_source.sound.clone();

settings.apply_channel_settings(&ChannelSettings::default());
if settings.paused {
sound.settings.playback_rate = kira::tween::Value::Fixed(PlaybackRate::Factor(0.0));
}
Expand Down Expand Up @@ -459,7 +460,7 @@ pub fn start_audio_playback(
audio_output.play_new(
&audio_sources,
source,
settings,
settings.clone(),
&mut commands.entity(audio_entity),
);
}
Expand Down
35 changes: 15 additions & 20 deletions src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use kira::sound::static_sound::StaticSoundData;
use kira::tween::Value;
use kira::Volume;
use std::any::TypeId;
use std::marker::PhantomData;

#[derive(Clone, PartialEq, Eq, Hash)]
pub enum Channel {
Expand All @@ -20,44 +19,40 @@ pub enum Channel {
}

#[derive(Bundle)]
pub struct AudioChannelBundle<C: Component> {
state: ChannelState,
channel: AudioChannel<C>,
pub struct AudioChannelBundle {
state: ChannelSettings,
channel: AudioChannel,
}

impl<C: Component> Default for AudioChannelBundle<C> {
fn default() -> Self {
impl AudioChannelBundle {
pub fn new<C: Component>() -> Self {
Self {
state: default(),
channel: AudioChannel::<C>::default(),
channel: AudioChannel::new::<C>(),
}
}
}

#[derive(Component)]
pub struct AudioChannel<C: Component> {
_marker: PhantomData<C>,
}
pub struct AudioChannel(TypeId);

impl<C: Component> Default for AudioChannel<C> {
fn default() -> Self {
Self {
_marker: PhantomData,
}
impl AudioChannel {
pub fn new<C: Component>() -> Self {
Self(TypeId::of::<C>())
}
}

#[derive(Component)]
pub struct ChannelState {
#[derive(Component, Clone, Debug)]
pub struct ChannelSettings {
pub paused: bool,
pub volume: Volume,
pub playback_rate: f64,
pub panning: f64,
}

impl Default for ChannelState {
impl Default for ChannelSettings {
fn default() -> Self {
ChannelState {
ChannelSettings {
paused: false,
volume: 1.0.into(),
playback_rate: 1.0,
Expand All @@ -66,7 +61,7 @@ impl Default for ChannelState {
}
}

impl ChannelState {
impl ChannelSettings {
pub(crate) fn apply(&self, sound: &mut StaticSoundData) {
sound.settings.volume = Value::Fixed(self.volume);
sound.settings.playback_rate = self.playback_rate.into();
Expand Down

0 comments on commit 0387710

Please sign in to comment.