use crate::audio::{audio, SoundControl, SoundInstance};
use crate::math::lerp;
use crate::{App, Context};
use alloc::{sync::Arc, vec::Vec};
#[derive(Copy, Clone, Debug)]
pub enum SoundError {
UnsupportedChannelCount,
UnsupportedFeature,
InvalidFormat,
}
#[derive(Copy, Clone, Debug)]
enum Channels {
Mono,
Stero,
}
#[derive(Clone)]
pub struct Sound {
sample_rate: f64,
duration: f64,
samples: Arc<[[f32; 2]]>,
}
impl Sound {
pub fn from_flac(bytes: &[u8]) -> Result<Sound, SoundError> {
crate::audio::read_flac(bytes)
}
pub fn new(sample_rate: u32, samples: Vec<[f32; 2]>) -> Result<Sound, SoundError> {
let sample_rate = sample_rate as f64;
Ok(Sound {
sample_rate,
duration: samples.len() as f64 / sample_rate,
samples: samples.into(),
})
}
pub fn duration(&self) -> f64 {
self.duration
}
pub fn sample_rate(&self) -> f64 {
self.sample_rate
}
pub fn play(&self, _ctx: &Context<impl App>, volume: f32, smooth: f32) -> SoundControl {
let control = SoundControl::new(volume, smooth, false);
let instance = SoundInstance::new(self, &control);
audio().push_sound(instance);
control
}
pub(crate) fn mix(&self, sample: f64, amplitude: f32, out: &mut [f32; 2]) {
if sample < 0.0 {
return;
}
let trunc = sample.trunc();
let whole = trunc as usize;
if whole + 1 >= self.samples.len() {
return;
}
let t = (sample - trunc) as f32;
let a = unsafe { self.samples.get_unchecked(whole) };
let b = unsafe { self.samples.get_unchecked(whole + 1) };
out[0] += lerp(a[0], b[0], t) * amplitude;
out[1] += lerp(a[1], b[1], t) * amplitude;
}
}