codewandler_audio/
playback.rs1use crate::channel::new_audio_channel;
2use crate::format::SampleFormat;
3use crossbeam_channel::{Receiver, Sender};
4use rodio::dynamic_mixer::DynamicMixerController;
5use rodio::dynamic_mixer::mixer;
6use rodio::source::SineWave;
7use rodio::{OutputStream, Sink, Source};
8use std::sync::Arc;
9use std::time::Duration;
10
11pub struct AudioPlayback<F>
12where
13 F: SampleFormat,
14{
15 _stream: OutputStream,
16 _sink: Arc<Sink>,
17 _mixer_handle: Arc<DynamicMixerController<F>>,
18}
19
20pub struct AudioPlaybackOutput<F>
21where
22 F: SampleFormat,
23{
24 sample_rate: u32,
25 _tx: Sender<F>,
26 rx: Receiver<F>,
27}
28
29impl Source for AudioPlaybackOutput<f32> {
30 fn current_frame_len(&self) -> Option<usize> {
31 None
32 }
33
34 fn channels(&self) -> u16 {
35 1
36 }
37
38 fn sample_rate(&self) -> u32 {
39 self.sample_rate
40 }
41
42 fn total_duration(&self) -> Option<Duration> {
43 None
44 }
45}
46
47impl Iterator for AudioPlaybackOutput<f32> {
48 type Item = f32;
49
50 fn next(&mut self) -> Option<Self::Item> {
51 match self.rx.try_recv() {
52 Ok(data) => Some(data),
53 Err(err) => match err {
54 crossbeam_channel::TryRecvError::Empty => Some(0.0),
55 crossbeam_channel::TryRecvError::Disconnected => None,
56 },
57 }
58 }
59}
60
61impl AudioPlayback<f32> {
62 pub fn new(sample_rate: u32) -> anyhow::Result<Self> {
63 let (_stream, stream_handle) = OutputStream::try_default()?;
64 let sink = Sink::try_new(&stream_handle)?;
65
66 let (mixer_handle, mixer_source) = mixer::<f32>(1, sample_rate);
67 sink.append(mixer_source);
68 sink.play();
69
70 Ok(Self {
71 _stream,
72 _sink: Arc::new(sink),
73 _mixer_handle: mixer_handle,
74 })
75 }
76
77 pub fn sine(&self, freq: f32, duration: Duration) {
78 self.play(SineWave::new(freq).take_duration(duration))
79 }
80
81 pub fn play<S>(&self, source: S)
82 where
83 S: Source<Item = f32> + Send + 'static,
84 {
85 self._mixer_handle.add(source);
86 }
87
88 pub fn new_output(&self, sample_rate: u32) -> Sender<f32> {
89 let (tx1, rx1) = new_audio_channel();
90
91 let out = AudioPlaybackOutput {
92 _tx: tx1.clone(),
93 rx: rx1,
94 sample_rate,
95 };
96
97 self.play(out);
98
99 tx1
100 }
101}