mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
custom rodio source for audio (#145)
support custom rodio source for audio
This commit is contained in:
parent
9c850057c0
commit
2667c24656
4 changed files with 50 additions and 20 deletions
|
@ -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(),
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue