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

custom rodio source for audio #145

Merged
merged 3 commits into from
Sep 8, 2020
Merged
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ Cargo.lock
.cargo/config
/.idea
/.vscode
/benches/target
/benches/target
43 changes: 28 additions & 15 deletions crates/bevy_audio/src/audio_output.rs
Original file line number Diff line number Diff line change
@@ -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<P = AudioSource>
where
P: Decodable,
{
device: Device,
queue: RwLock<VecDeque<Handle<AudioSource>>>,
queue: RwLock<VecDeque<Handle<P>>>,
}

impl Default for AudioOutput {
impl<P> Default for AudioOutput<P>
where
P: Decodable,
{
fn default() -> Self {
Self {
device: rodio::default_output_device().unwrap(),
Expand All @@ -20,18 +26,23 @@ impl Default for AudioOutput {
}
}

impl AudioOutput {
pub fn play_source(&self, audio_source: &AudioSource) {
impl<P> AudioOutput<P>
where
P: Decodable,
<P as Decodable>::Decoder: rodio::Source + Send + Sync,
<<P as Decodable>::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<AudioSource>) {
pub fn play(&self, audio_source: Handle<P>) {
self.queue.write().push_front(audio_source);
}

pub fn try_play_queued(&self, audio_sources: &Assets<AudioSource>) {
pub fn try_play_queued(&self, audio_sources: &Assets<P>) {
let mut queue = self.queue.write();
let len = queue.len();
let mut i = 0;
Expand All @@ -49,9 +60,11 @@ impl AudioOutput {
}

/// Plays audio currently queued in the [AudioOutput] resource
pub(crate) fn play_queued_audio_system(
audio_sources: Res<Assets<AudioSource>>,
audio_output: Res<AudioOutput>,
) {
pub fn play_queued_audio_system<P>(audio_sources: Res<Assets<P>>, audio_output: Res<AudioOutput<P>>)
where
P: Decodable,
<P as Decodable>::Decoder: rodio::Source + Send + Sync,
<<P as Decodable>::Decoder as Iterator>::Item: rodio::Sample + Send + Sync,
{
audio_output.try_play_queued(&audio_sources);
}
16 changes: 15 additions & 1 deletion crates/bevy_audio/src/audio_source.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -30,3 +30,17 @@ impl AssetLoader<AudioSource> for Mp3Loader {
EXTENSIONS
}
}

pub trait Decodable: Send + Sync + 'static {
type Decoder;

fn decoder(&self) -> Self::Decoder;
}

impl Decodable for AudioSource {
type Decoder = rodio::Decoder<Cursor<AudioSource>>;

fn decoder(&self) -> Self::Decoder {
rodio::Decoder::new(Cursor::new(self.clone())).unwrap()
}
}
9 changes: 6 additions & 3 deletions crates/bevy_audio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -18,9 +18,12 @@ pub struct AudioPlugin;

impl Plugin for AudioPlugin {
fn build(&self, app: &mut AppBuilder) {
app.init_resource::<AudioOutput>()
app.init_resource::<AudioOutput<AudioSource>>()
.add_asset::<AudioSource>()
.add_asset_loader::<AudioSource, Mp3Loader>()
.add_system_to_stage(stage::POST_UPDATE, play_queued_audio_system.system());
.add_system_to_stage(
stage::POST_UPDATE,
play_queued_audio_system::<AudioSource>.system(),
);
}
}