use {
crate::{GenericSample, OperationError, samples_to_f32},
cpal::{
BufferSize, Device, HostId, Stream, StreamConfig, SupportedStreamConfig, default_host,
traits::{DeviceTrait, HostTrait, StreamTrait},
},
rodio::{ChannelCount, SampleRate, buffer::SamplesBuffer, source::UniformSourceIterator},
std::{
fmt::{Debug, Error as FmtError, Formatter, Result as FmtResult},
io::Error as IoError,
mem::replace,
},
tokio::sync::{
mpsc::{Sender as MpscSender, channel as mpsc_channel},
watch::{Sender as WatchSender, channel as watch_channel},
},
};
pub struct AudioPlayer {
device: Device,
host_id: HostId,
stream_config: StreamConfig,
supported_stream_config: SupportedStreamConfig,
stream: Stream,
write_sender: MpscSender<f32>,
stop_sender: WatchSender<bool>,
}
impl AudioPlayer {
fn create_stream(
device: &Device,
stream_config: &StreamConfig,
) -> Result<(MpscSender<f32>, WatchSender<bool>, Stream), OperationError> {
let buffer_size = match stream_config.buffer_size {
BufferSize::Default => 8192,
BufferSize::Fixed(size) => size as _,
};
let (write_tx, mut write_rx) = mpsc_channel(buffer_size);
let (stop_tx, stop_rx) = watch_channel(false);
Ok((
write_tx,
stop_tx,
device.build_output_stream(
stream_config.clone(),
move |buffer: &mut [f32], _| {
let buf = buffer.iter_mut();
if *stop_rx.borrow() {
buf.for_each(|i| *i = Default::default());
while let Ok(_) = write_rx.try_recv() {}
} else {
buf.for_each(|i| *i = write_rx.try_recv().unwrap_or_default());
}
},
|e| eprintln!("{}", e),
None,
)?,
))
}
fn update_stream(&mut self) -> Result<(), OperationError> {
let (write_sender, stop_sender, stream) =
Self::create_stream(&self.device, &self.stream_config)?;
drop(replace(&mut self.stream, stream));
drop(replace(&mut self.write_sender, write_sender));
drop(replace(&mut self.stop_sender, stop_sender));
Ok(())
}
pub fn new() -> Result<Self, OperationError> {
let host = default_host();
let device = host
.default_output_device()
.ok_or(OperationError::NoDevice(
"No default audio output device.".to_owned(),
))?;
let host_id = host.id();
let supported_stream_config = device.default_output_config()?;
let stream_config = supported_stream_config.config();
let (write_sender, stop_sender, stream) = Self::create_stream(&device, &stream_config)?;
Ok(Self {
device,
host_id,
stream_config,
supported_stream_config,
stream,
write_sender,
stop_sender,
})
}
pub fn get_name(&self) -> Result<String, OperationError> {
Ok(self.device.description()?.name().to_owned())
}
pub fn get_supported_stream_channels(&self) -> usize {
self.supported_stream_config.channels() as _
}
pub fn get_supported_stream_sample_rate(&self) -> usize {
self.supported_stream_config.sample_rate() as _
}
pub fn set_stream_channels(&mut self, channels: usize) -> Result<(), OperationError> {
self.stream_config.channels = channels as _;
self.update_stream()
}
pub fn set_stream_sample_rate(&mut self, sample_rate: usize) -> Result<(), OperationError> {
self.stream_config.sample_rate = sample_rate as _;
self.update_stream()
}
pub fn get_stream_channels(&self) -> usize {
self.stream_config.channels as _
}
pub fn get_stream_sample_rate(&self) -> usize {
self.stream_config.sample_rate as _
}
pub fn play(&self) -> Result<(), OperationError> {
self.stop_sender.send(false)?;
Ok(self.stream.play()?)
}
pub fn pause(&self) -> Result<(), OperationError> {
Ok(self.stream.pause()?)
}
pub fn stop(&self) -> Result<(), OperationError> {
self.stop_sender.send(true)?;
self.stream.pause()?;
Ok(())
}
pub async fn write<const SR: usize, S>(
&mut self,
samples: &[S],
channels: usize,
) -> Result<(), OperationError>
where
S: GenericSample,
{
if self.get_stream_channels() != channels || self.get_stream_sample_rate() != SR {
let f32_samples = samples_to_f32(samples);
let mut iter = UniformSourceIterator::new(
SamplesBuffer::new(
ChannelCount::new(channels as _)
.ok_or(IoError::other("invalid channel count"))?,
SampleRate::new(SR as _).ok_or(IoError::other("invalid sample rate"))?,
f32_samples,
),
ChannelCount::new(self.stream_config.channels)
.ok_or(IoError::other("invalid channel count"))?,
SampleRate::new(self.stream_config.sample_rate)
.ok_or(IoError::other("invalid sample rate"))?,
);
while !*self.stop_sender.borrow() {
let mut p = self.write_sender.reserve_many(256).await?;
while let Some(w) = p.next()
&& let Some(i) = iter.next()
{
w.send(i);
}
}
return Ok(());
}
for s in samples {
self.write_sender.send(s.to_f32()).await?;
}
Ok(())
}
}
impl Debug for AudioPlayer {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(
f,
"AudioPlayer({}, {})",
self.host_id.name(),
self.get_name().map_err(|_| FmtError)?
)
}
}