From 64846d8d9911fe033214751499b4de48949706f2 Mon Sep 17 00:00:00 2001 From: Cory Forsstrom Date: Tue, 8 Sep 2020 13:56:45 -0700 Subject: [PATCH] custom rodio source for audio (#145) support custom rodio source for audio --- .gitignore | 2 +- crates/bevy_audio/src/audio_output.rs | 43 +++++++++++++++++---------- crates/bevy_audio/src/audio_source.rs | 16 +++++++++- crates/bevy_audio/src/lib.rs | 9 ++++-- 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index e690fffaad245..dc30af69dfa81 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,4 @@ Cargo.lock .cargo/config /.idea /.vscode -/benches/target \ No newline at end of file +/benches/target diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs index d81157070d9b8..d484e46b03da6 100644 --- a/crates/bevy_audio/src/audio_output.rs +++ b/crates/bevy_audio/src/audio_output.rs @@ -1,17 +1,23 @@ -use crate::AudioSource; +use crate::{AudioSource, Decodable}; use bevy_asset::{Assets, Handle}; use bevy_ecs::Res; use parking_lot::RwLock; -use rodio::{Decoder, Device, Sink}; -use std::{collections::VecDeque, io::Cursor}; +use rodio::{Device, Sink}; +use std::collections::VecDeque; /// 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(), @@ -20,18 +26,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().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(); let len = queue.len(); let mut i = 0; @@ -49,9 +60,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 16a032e3ae31e..3635d802dcc59 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 46270278f58da..945ba853f6000 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(), + ); } }