use crate::{Frame, SoundHandle};
use parking_lot::{Mutex, MutexGuard};
use std::sync::Arc;
pub trait Renderer: Clone + Send + 'static {
fn next_frame(&mut self, sample_rate: u32) -> Frame;
#[cfg(feature = "cpal")]
fn on_buffer<T>(&mut self, _buffer: &mut [T])
where
T: cpal::SizedSample + cpal::FromSample<f32>,
{
}
}
#[derive(Debug, Clone, Default)]
pub struct DefaultRenderer {
pub sounds: Vec<SoundHandle>,
pub last_buffer_size: usize,
}
impl DefaultRenderer {
#[inline]
pub fn add_sound(&mut self, sound: impl Into<SoundHandle>) {
self.sounds.push(sound.into());
}
pub fn has_sounds(&self) -> bool {
!self.sounds.is_empty()
}
}
impl Renderer for DefaultRenderer {
fn next_frame(&mut self, sample_rate: u32) -> Frame {
let mut out = Frame::ZERO;
self.sounds.retain_mut(|sound| {
let frame = sound.next_frame(sample_rate);
if let Some(frame) = frame {
out += frame;
true
} else {
false
}
});
out
}
#[cfg(feature = "cpal")]
fn on_buffer<T>(&mut self, buffer: &mut [T])
where
T: cpal::SizedSample + cpal::FromSample<f32>,
{
self.last_buffer_size = buffer.len();
}
}
#[derive(Clone)]
pub struct RendererHandle<R: Renderer>(Arc<Mutex<R>>);
impl From<DefaultRenderer> for RendererHandle<DefaultRenderer> {
fn from(val: DefaultRenderer) -> Self {
RendererHandle::new(val)
}
}
impl<R: Renderer> RendererHandle<R> {
pub fn new(renderer: R) -> Self {
Self(Arc::new(Mutex::new(renderer)))
}
#[inline(always)]
pub fn guard(&self) -> MutexGuard<'_, R> {
self.0.lock()
}
}