Use data-based API for controlling play state, and aggressively clean up stopped sources.

This commit is contained in:
Nolan Darilek 2021-01-07 16:18:26 -06:00
parent acc004b2ef
commit 2410d00b8c

View File

@ -4,10 +4,10 @@ use std::ops::{Deref, DerefMut};
use std::sync::Arc; use std::sync::Arc;
pub use alto::efx; pub use alto::efx;
use alto::efx::AuxEffectSlot;
pub use alto::Context; pub use alto::Context;
pub use alto::Device; pub use alto::Device;
pub use alto::Source; pub use alto::Source;
use alto::{efx::AuxEffectSlot, SourceState};
use alto::{Alto, Mono, StaticSource, Stereo}; use alto::{Alto, Mono, StaticSource, Stereo};
use bevy::{ use bevy::{
asset::{AssetLoader, HandleId, LoadContext, LoadedAsset}, asset::{AssetLoader, HandleId, LoadContext, LoadedAsset},
@ -119,15 +119,25 @@ fn buffer_creation(
} }
} }
#[derive(Reflect)] #[derive(Clone, Copy, Debug, PartialEq)]
#[reflect(Component)] pub enum SoundState {
Stopped,
Playing,
Paused,
}
impl Default for SoundState {
fn default() -> Self {
SoundState::Stopped
}
}
pub struct Sound { pub struct Sound {
pub buffer: Handle<Buffer>, pub buffer: Handle<Buffer>,
pub autoplay: bool, pub state: SoundState,
pub gain: f32, pub gain: f32,
pub looping: bool, pub looping: bool,
pub pitch: f32, pub pitch: f32,
#[reflect(ignore)]
pub source: Option<StaticSource>, pub source: Option<StaticSource>,
} }
@ -135,7 +145,7 @@ impl Default for Sound {
fn default() -> Self { fn default() -> Self {
Self { Self {
buffer: Default::default(), buffer: Default::default(),
autoplay: false, state: Default::default(),
gain: 1., gain: 1.,
looping: false, looping: false,
pitch: 1., pitch: 1.,
@ -144,26 +154,6 @@ impl Default for Sound {
} }
} }
impl Sound {
pub fn play(&mut self) {
if let Some(source) = self.source.as_mut() {
source.play();
}
}
pub fn stop(&mut self) {
if let Some(source) = self.source.as_mut() {
source.stop();
}
}
pub fn pause(&mut self) {
if let Some(source) = self.source.as_mut() {
source.pause();
}
}
}
pub type Sounds = HashMap<String, Sound>; pub type Sounds = HashMap<String, Sound>;
#[derive(Default)] #[derive(Default)]
@ -191,36 +181,67 @@ fn source_update(
) { ) {
for (mut sounds, transform) in query.iter_mut() { for (mut sounds, transform) in query.iter_mut() {
for mut sound in sounds.values_mut() { for mut sound in sounds.values_mut() {
if sound.source.is_none() { let state = sound.state;
if let Ok(mut source) = context.new_static_source() { match state {
if let Some(buffer) = buffers.0.get(&sound.buffer.id) { SoundState::Stopped => {
source.set_buffer(buffer.clone()).unwrap(); if let Some(source) = sound.source.as_mut() {
source.stop();
sound.source = None;
} }
if sound.autoplay { }
SoundState::Playing => {
if sound.source.is_none() {
let mut source = context.new_static_source().unwrap();
if let Some(buffer) = buffers.0.get(&sound.buffer.id) {
source.set_buffer(buffer.clone()).unwrap();
}
source.play(); source.play();
sound.source = Some(source);
}
}
SoundState::Paused => {
if let Some(source) = sound.source.as_mut() {
source.pause();
} else {
let mut source = context.new_static_source().unwrap();
if let Some(buffer) = buffers.0.get(&sound.buffer.id) {
source.set_buffer(buffer.clone()).unwrap();
}
source.pause();
sound.source = Some(source);
} }
sound.source = Some(source);
} }
} }
if let Some(source) = sound.source.as_mut() { if let Some(source) = sound.source.as_mut() {
source.set_gain(sound.gain).unwrap(); sound.state = match source.state() {
source.set_looping(sound.looping); SourceState::Initial => SoundState::Stopped,
source.set_pitch(sound.pitch).unwrap(); SourceState::Playing => SoundState::Playing,
if let Some(transform) = transform { SourceState::Paused => SoundState::Paused,
source.set_relative(false); SourceState::Stopped => SoundState::Stopped,
source SourceState::Unknown(_) => SoundState::Stopped,
.set_position([ };
transform.translation.x, if sound.state != SoundState::Stopped {
transform.translation.y, source.set_gain(sound.gain).unwrap();
transform.translation.z, source.set_looping(sound.looping);
]) source.set_pitch(sound.pitch).unwrap();
.unwrap(); if let Some(transform) = transform {
source.set_relative(false);
source
.set_position([
transform.translation.x,
transform.translation.y,
transform.translation.z,
])
.unwrap();
} else {
source.set_relative(true);
source.set_position([0., 0., 0.]).unwrap();
}
for (send, effect) in global_effects.iter_mut().enumerate() {
source.set_aux_send(send as i32, effect).unwrap();
}
} else { } else {
source.set_relative(true); sound.source = None;
source.set_position([0., 0., 0.]).unwrap();
}
for (send, effect) in global_effects.iter_mut().enumerate() {
source.set_aux_send(send as i32, effect).unwrap();
} }
} }
} }