use std::{
any::TypeId,
fmt::{Display, Error, Formatter},
future::Future,
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
};
use fon::{
chan::{Ch32, Channel},
mono::Mono32,
stereo::Stereo32,
surround::Surround32,
Frame, Resampler, Sink,
};
use super::SoundDevice;
pub(crate) struct Speakers {
buffer: Vec<f32>,
resampler: ([Ch32; 6], f64),
}
impl SoundDevice for Speakers {
const INPUT: bool = false;
}
impl Display for Speakers {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
f.write_str("Default")
}
}
impl Default for Speakers {
fn default() -> Self {
let state = super::state();
state.lazy_init();
if state.speaker.is_some() {
panic!("Already connected to speakers!");
}
state.speaker = Some(state.context.as_mut().unwrap().destination());
state
.proc
.as_ref()
.unwrap()
.connect_with_audio_node(state.speaker.as_ref().unwrap())
.ok()
.unwrap();
Self {
buffer: vec![0.0; super::BUFFER_SIZE.into()],
resampler: ([Ch32::MID; 6], 0.0),
}
}
}
impl Speakers {
pub(crate) fn play<F: Frame<Chan = Ch32>>(
&mut self,
) -> SpeakersSink<'_, F> {
if TypeId::of::<F>() == TypeId::of::<Mono32>() {
self.buffer.resize(super::BUFFER_SIZE.into(), 0.0);
} else if TypeId::of::<F>() == TypeId::of::<Stereo32>() {
self.buffer.resize(super::BUFFER_SIZE as usize * 2, 0.0);
} else {
panic!("Attempted to use Speakers with invalid frame type");
}
let resampler = Resampler::<F>::new(
Surround32::from_channels(&self.resampler.0[..]).convert(),
self.resampler.1,
);
SpeakersSink(self, resampler, PhantomData)
}
pub(crate) fn channels(&self) -> u8 {
0b0000_0011
}
}
impl Future for &mut Speakers {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let state = super::state();
if state.played {
state.played = false;
Poll::Ready(())
} else {
state.speaker_waker = Some(cx.waker().clone());
Poll::Pending
}
}
}
pub(crate) struct SpeakersSink<'a, F: Frame<Chan = Ch32>>(
&'a mut Speakers,
Resampler<F>,
PhantomData<F>,
);
impl<F: Frame<Chan = Ch32>> Sink<F> for SpeakersSink<'_, F> {
fn sample_rate(&self) -> f64 {
super::state().sample_rate.unwrap()
}
fn resampler(&mut self) -> &mut Resampler<F> {
&mut self.1
}
#[allow(unsafe_code)]
fn buffer(&mut self) -> &mut [F] {
let data = self.0.buffer.as_mut_ptr().cast();
let count = super::BUFFER_SIZE.into();
unsafe { &mut std::slice::from_raw_parts_mut(data, count)[..] }
}
}
impl<F: Frame<Chan = Ch32>> Drop for SpeakersSink<'_, F> {
fn drop(&mut self) {
if TypeId::of::<F>() == TypeId::of::<Mono32>() {
let state = super::state();
for (i, sample) in self.0.buffer.iter().cloned().enumerate() {
state.l_buffer[i] = sample;
state.r_buffer[i] = sample;
}
} else if TypeId::of::<F>() == TypeId::of::<Stereo32>() {
let state = super::state();
for (i, sample) in self.0.buffer.chunks(2).enumerate() {
state.l_buffer[i] = sample[0];
state.r_buffer[i] = sample[1];
}
} else {
unreachable!();
}
let frame: Surround32 = self.1.frame().convert();
self.0.resampler.0 = [
frame.channels()[0],
frame.channels()[1],
frame.channels()[2],
frame.channels()[3],
frame.channels()[4],
frame.channels()[5],
];
self.0.resampler.1 = self.1.index() % 1.0;
}
}