use {
crate::AudioSource,
bevy::asset::{AssetLoader, BoxedFuture, Error, LoadContext, LoadedAsset},
};
#[derive(Default)]
pub struct WavLoader;
impl AssetLoader for WavLoader {
fn load<'a>(
&'a self,
bytes: &'a [u8],
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), Error>> {
#[allow(clippy::cast_lossless, clippy::cast_precision_loss)]
Box::pin(async move {
let mut reader = hound::WavReader::new(bytes)?;
let hound::WavSpec {
sample_rate: source_sample_rate,
sample_format,
bits_per_sample,
channels,
} = reader.spec();
let samples_result: Result<Vec<f32>, _> = match sample_format {
hound::SampleFormat::Int => {
let max_value = 2_u32.pow(bits_per_sample as u32 - 1) - 1;
reader
.samples::<i32>()
.map(|sample| sample.map(|sample| sample as f32 / max_value as f32))
.collect()
}
hound::SampleFormat::Float => reader.samples::<f32>().collect(),
};
let mut samples = samples_result?;
match channels {
1 => {
let samples = samples.into_iter().map(|s| [s]);
let frames = oddio::Frames::from_iter(source_sample_rate, samples);
let audio_source = AudioSource { frames };
load_context.set_default_asset(LoadedAsset::new(audio_source));
}
2 => {
let samples_stereo = oddio::frame_stereo(&mut samples).iter().copied();
let frames = oddio::Frames::from_iter(source_sample_rate, samples_stereo);
let audio_source = AudioSource { frames };
load_context.set_default_asset(LoadedAsset::new(audio_source));
}
_ => unimplemented!("bevy_oddio only have support for 1 or 2 channels only."),
}
Ok(())
})
}
fn extensions(&self) -> &[&str] {
&["wav"]
}
}