use super::{AUDIO_BUFFER_LEN, CHANNEL_COUNT, SAMPLE_RATE}; use crossbeam_channel::{Receiver, Sender, TrySendError}; use rodio::Source; use std::collections::VecDeque; pub struct AudioMPSC; impl AudioMPSC { pub fn new() -> (AudioSender, AudioReceiver) { // TODO: Can we provide an upper limit for this? // The larger this channel is, the more lag there is between the Audio and // Emulator let (send, recv) = crossbeam_channel::unbounded(); (AudioSender { inner: send }, AudioReceiver { inner: recv }) } } #[derive(Debug, Clone)] pub struct AudioSender { inner: Sender, } impl AudioSender { pub(crate) fn send_samples(&self, left: T, right: T) -> Result<(), TrySendError> { self.inner.try_send(left).and(self.inner.try_send(right))?; Ok(()) } } pub struct AudioReceiver { inner: Receiver, } impl Iterator for AudioReceiver { type Item = T; fn next(&mut self) -> Option { // TODO: Should this never return none? self.inner.recv().ok() } } impl Source for AudioReceiver { fn current_frame_len(&self) -> Option { // A frame changes when the samples rate or // number of channels change. This will never happen, so // we return None } fn channels(&self) -> u16 { // The Gameboy supports two channels CHANNEL_COUNT as u16 } fn sample_rate(&self) -> u32 { SAMPLE_RATE } fn total_duration(&self) -> Option { // The duration of this source is infinite None } } #[derive(Debug, Clone)] pub(crate) struct AudioBuffer { inner: VecDeque, } impl Default for AudioBuffer { fn default() -> Self { Self { inner: VecDeque::with_capacity(AUDIO_BUFFER_LEN * CHANNEL_COUNT), } } } impl AudioBuffer { pub(crate) fn push_back(&mut self, value: T) { self.inner.push_back(value) } pub(crate) fn pop_front(&mut self) -> Option { self.inner.pop_front() } pub(crate) fn len(&self) -> usize { self.inner.len() } }