use alloc::sync::Arc;
use bevy_asset::{io::Reader, Asset, AssetLoader, LoadContext};
use bevy_reflect::TypePath;
use std::io::Cursor;
#[derive(Asset, Debug, Clone, TypePath)]
pub struct AudioSource {
pub bytes: Arc<[u8]>,
}
impl AsRef<[u8]> for AudioSource {
fn as_ref(&self) -> &[u8] {
&self.bytes
}
}
#[derive(Default, TypePath)]
pub struct AudioLoader;
impl AssetLoader for AudioLoader {
type Asset = AudioSource;
type Settings = ();
type Error = std::io::Error;
async fn load(
&self,
reader: &mut dyn Reader,
_settings: &Self::Settings,
_load_context: &mut LoadContext<'_>,
) -> Result<AudioSource, Self::Error> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
Ok(AudioSource {
bytes: bytes.into(),
})
}
fn extensions(&self) -> &[&str] {
&[
#[cfg(feature = "mp3")]
"mp3",
#[cfg(feature = "flac")]
"flac",
#[cfg(feature = "wav")]
"wav",
#[cfg(feature = "vorbis")]
"oga",
#[cfg(feature = "vorbis")]
"ogg",
#[cfg(feature = "vorbis")]
"spx",
]
}
}
pub trait Decodable: Send + Sync + 'static {
type DecoderItem: rodio::Sample + Send + Sync;
type Decoder: rodio::Source + Send + Iterator<Item = Self::DecoderItem>;
fn decoder(&self) -> Self::Decoder;
}
impl Decodable for AudioSource {
type DecoderItem = <rodio::Decoder<Cursor<AudioSource>> as Iterator>::Item;
type Decoder = rodio::Decoder<Cursor<AudioSource>>;
fn decoder(&self) -> Self::Decoder {
rodio::Decoder::new(Cursor::new(self.clone())).unwrap()
}
}
pub trait AddAudioSource {
fn add_audio_source<T>(&mut self) -> &mut Self
where
T: Decodable + Asset,
f32: rodio::cpal::FromSample<T::DecoderItem>;
}