From cea85fd39722335610344cab912f2c63fe96c3de Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Tue, 11 Aug 2020 14:42:39 -0700 Subject: [PATCH] init draft of custom rodio source for audio --- .gitignore | 3 +- crates/bevy_audio/src/audio_output.rs | 43 +++++++++++++++++---------- crates/bevy_audio/src/audio_source.rs | 16 +++++++++- crates/bevy_audio/src/lib.rs | 9 ++++-- examples/audio/audio.rs | 2 +- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index b3c22eedfbd838..840c8c0bb1390b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ **/*.rs.bk Cargo.lock .cargo/config -/.idea \ No newline at end of file +/.idea +/.vscode diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs index 5b578fbfebde9a..3d61bb2366fe57 100644 --- a/crates/bevy_audio/src/audio_output.rs +++ b/crates/bevy_audio/src/audio_output.rs @@ -1,16 +1,22 @@ -use crate::AudioSource; +use crate::Decodable; use bevy_asset::{Assets, Handle}; use bevy_ecs::Res; -use rodio::{Decoder, Device, Sink}; -use std::{collections::VecDeque, io::Cursor, sync::RwLock}; +use rodio::{Device, Sink}; +use std::{collections::VecDeque, sync::RwLock}; /// Used to play audio on the current "audio device" -pub struct AudioOutput { +pub struct AudioOutput

+where + P: Decodable, +{ device: Device, - queue: RwLock>>, + queue: RwLock>>, } -impl Default for AudioOutput { +impl

Default for AudioOutput

+where + P: Decodable, +{ fn default() -> Self { Self { device: rodio::default_output_device().unwrap(), @@ -19,18 +25,23 @@ impl Default for AudioOutput { } } -impl AudioOutput { - pub fn play_source(&self, audio_source: &AudioSource) { +impl

AudioOutput

+where + P: Decodable, +

::Decoder: rodio::Source + Send + Sync, + <

::Decoder as Iterator>::Item: rodio::Sample + Send + Sync, +{ + pub fn play_source(&self, audio_source: &P) { let sink = Sink::new(&self.device); - sink.append(Decoder::new(Cursor::new(audio_source.clone())).unwrap()); + sink.append(audio_source.decoder()); sink.detach(); } - pub fn play(&self, audio_source: Handle) { + pub fn play(&self, audio_source: Handle

) { self.queue.write().unwrap().push_front(audio_source); } - pub fn try_play_queued(&self, audio_sources: &Assets) { + pub fn try_play_queued(&self, audio_sources: &Assets

) { let mut queue = self.queue.write().unwrap(); let len = queue.len(); let mut i = 0; @@ -48,9 +59,11 @@ impl AudioOutput { } /// Plays audio currently queued in the [AudioOutput] resource -pub(crate) fn play_queued_audio_system( - audio_sources: Res>, - audio_output: Res, -) { +pub fn play_queued_audio_system

(audio_sources: Res>, audio_output: Res>) +where + P: Decodable, +

::Decoder: rodio::Source + Send + Sync, + <

::Decoder as Iterator>::Item: rodio::Sample + Send + Sync, +{ audio_output.try_play_queued(&audio_sources); } diff --git a/crates/bevy_audio/src/audio_source.rs b/crates/bevy_audio/src/audio_source.rs index 16a032e3ae31ea..3635d802dcc59f 100644 --- a/crates/bevy_audio/src/audio_source.rs +++ b/crates/bevy_audio/src/audio_source.rs @@ -1,6 +1,6 @@ use anyhow::Result; use bevy_asset::AssetLoader; -use std::{path::Path, sync::Arc}; +use std::{io::Cursor, path::Path, sync::Arc}; /// A source of audio data #[derive(Clone)] @@ -30,3 +30,17 @@ impl AssetLoader for Mp3Loader { EXTENSIONS } } + +pub trait Decodable: Send + Sync + 'static { + type Decoder; + + fn decoder(&self) -> Self::Decoder; +} + +impl Decodable for AudioSource { + type Decoder = rodio::Decoder>; + + fn decoder(&self) -> Self::Decoder { + rodio::Decoder::new(Cursor::new(self.clone())).unwrap() + } +} diff --git a/crates/bevy_audio/src/lib.rs b/crates/bevy_audio/src/lib.rs index 46270278f58da9..945ba853f60009 100644 --- a/crates/bevy_audio/src/lib.rs +++ b/crates/bevy_audio/src/lib.rs @@ -5,7 +5,7 @@ pub use audio_output::*; pub use audio_source::*; pub mod prelude { - pub use crate::{AudioOutput, AudioSource}; + pub use crate::{AudioOutput, AudioSource, Decodable}; } use bevy_app::prelude::*; @@ -18,9 +18,12 @@ pub struct AudioPlugin; impl Plugin for AudioPlugin { fn build(&self, app: &mut AppBuilder) { - app.init_resource::() + app.init_resource::>() .add_asset::() .add_asset_loader::() - .add_system_to_stage(stage::POST_UPDATE, play_queued_audio_system.system()); + .add_system_to_stage( + stage::POST_UPDATE, + play_queued_audio_system::.system(), + ); } } diff --git a/examples/audio/audio.rs b/examples/audio/audio.rs index 21744477c8ce15..1be30281575d8a 100644 --- a/examples/audio/audio.rs +++ b/examples/audio/audio.rs @@ -8,7 +8,7 @@ fn main() { .run(); } -fn setup(asset_server: Res, audio_output: Res) { +fn setup(asset_server: Res, audio_output: Res>) { let music = asset_server .load("assets/sounds/Windless Slopes.mp3") .unwrap();