dango_core/music_player/
music_output.rs1use std::result;
2
3use symphonia::core::audio::{AudioBufferRef, SignalSpec, RawSample, SampleBuffer};
4use symphonia::core::conv::{ConvertibleSample, IntoSample};
5use symphonia::core::units::Duration;
6
7use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
8use cpal::{self, SizedSample};
9
10use rb::*;
11
12pub trait AudioStream {
13 fn write(&mut self, decoded: AudioBufferRef<'_>) -> Result<()>;
14 fn flush(&mut self);
15}
16
17#[derive(Debug)]
18pub enum AudioOutputError {
19 OpenStreamError,
20 PlayStreamError,
21 StreamClosedError,
22}
23
24pub type Result<T> = result::Result<T, AudioOutputError>;
25
26pub trait OutputSample: SizedSample + IntoSample<f64> +cpal::Sample + ConvertibleSample + RawSample + std::marker::Send + 'static {}
27
28pub struct AudioOutput<T>
29where T: OutputSample,
30{
31 ring_buf_producer: rb::Producer<T>,
32 sample_buf: SampleBuffer<T>,
33 stream: cpal::Stream,
34 resampler: Option<T>,
35}
36impl OutputSample for i8 {}
37impl OutputSample for i16 {}
38impl OutputSample for i32 {}
39impl OutputSample for u8 {}
41impl OutputSample for u16 {}
42impl OutputSample for u32 {}
43impl OutputSample for f32 {}
45impl OutputSample for f64 {}
46pub fn open_stream(spec: SignalSpec, duration: Duration) -> Result<Box<dyn AudioStream>> {
49 let host = cpal::default_host();
50
51 let device = match host.default_output_device() {
53 Some(device) => device,
54 _ => return Err(AudioOutputError::OpenStreamError),
55 };
56
57 let config = match device.default_output_config() {
58 Ok(config) => config,
59 Err(err) => return Err(AudioOutputError::OpenStreamError),
60 };
61
62 return match config.sample_format(){
63 cpal::SampleFormat::I8 => AudioOutput::<i8>::create_stream(spec, &device, &config.into(), duration),
64 cpal::SampleFormat::I16 => AudioOutput::<i16>::create_stream(spec, &device, &config.into(), duration),
65 cpal::SampleFormat::I32 => AudioOutput::<i32>::create_stream(spec, &device, &config.into(), duration),
66 cpal::SampleFormat::U8 => AudioOutput::<u8>::create_stream(spec, &device, &config.into(), duration),
68 cpal::SampleFormat::U16 => AudioOutput::<u16>::create_stream(spec, &device, &config.into(), duration),
69 cpal::SampleFormat::U32 => AudioOutput::<u32>::create_stream(spec, &device, &config.into(), duration),
70 cpal::SampleFormat::F32 => AudioOutput::<f32>::create_stream(spec, &device, &config.into(), duration),
72 cpal::SampleFormat::F64 => AudioOutput::<f64>::create_stream(spec, &device, &config.into(), duration),
73 _ => todo!(),
74 };
75 }
76
77
78impl<T: OutputSample> AudioOutput<T> {
79 fn create_stream(spec: SignalSpec, device: &cpal::Device, config: &cpal::StreamConfig, duration: Duration) -> Result<Box<dyn AudioStream>> {
81 let num_channels = config.channels as usize;
82
83 let ring_len = ((200 * config.sample_rate.0 as usize) / 1000) * num_channels;
85 let ring_buf= rb::SpscRb::new(ring_len);
86
87 let ring_buf_producer = ring_buf.producer();
88 let ring_buf_consumer = ring_buf.consumer();
89
90 let stream_result = device.build_output_stream(
91 config,
92 move |data: &mut [T], _: &cpal::OutputCallbackInfo| {
93 let written = ring_buf_consumer.read(data).unwrap_or(0);
95
96 data[written..].iter_mut().for_each(|sample| *sample = T::MID);
98 },
99 move |err| println!("Yeah we erroring out here"),
101 None
102 );
103
104 if let Err(err) = stream_result {
105 return Err(AudioOutputError::OpenStreamError);
106 }
107
108 let stream = stream_result.unwrap();
109
110 if let Err(err) = stream.play() {
112 return Err(AudioOutputError::PlayStreamError);
113 }
114
115 let sample_buf = SampleBuffer::<T>::new(duration, spec);
116
117 let resampler: Option<T> = None;
118
119 Ok(Box::new(AudioOutput { ring_buf_producer, sample_buf, stream, resampler}))
120 }
121}
122
123impl<T: OutputSample> AudioStream for AudioOutput<T> {
124 fn write(&mut self, decoded: AudioBufferRef<'_>) -> Result<()> {
126 if decoded.frames() == 0 {
127 return Ok(());
128 }
129
130 let mut samples: &[T] = if let Some(resampler) = &mut self.resampler {
131 println!("this should not print");
133 return Ok(())
134 } else {
135 self.sample_buf.copy_interleaved_ref(decoded);
136 self.sample_buf.samples()
137 };
138
139 while let Some(written) = self.ring_buf_producer.write_blocking(samples) {
141 samples = &samples[written..];
142 }
143
144 Ok(())
145 }
146
147 fn flush(&mut self) {
149 if let Some(resampler) = &mut self.resampler {
150 }
152
153 let _ = self.stream.pause();
154 }
155}