use cpal::traits::HostTrait; use cpal::traits::DeviceTrait; use cpal::traits::StreamTrait; use std::time; use std::thread; use std::sync::mpsc; struct AudioSink { recv: mpsc::Receiver>, buffer: Option>, idx: usize } impl AudioSink { fn new(recv: mpsc::Receiver>) -> Self { Self { recv: recv, buffer: None, idx: 0 } } fn pour(&mut self, mut dst: &mut [f32], i: usize) { loop { match self.buffer.as_ref() { Some(src) => { let src_new = &src[self.idx..]; let count = std::cmp::min(src_new.len(), dst.len()); let src_new = &src_new[..count]; let dst_new = &mut dst[..count]; dst_new.copy_from_slice(&src_new); self.idx += count; if self.idx >= src.len() { self.buffer = None; self.idx = 0; } if dst.len() > count { dst = &mut dst[count..]; continue; } return; }, None => { self.buffer = Some(self.recv.recv().unwrap()); } }; } } } fn main() { let host = cpal::default_host(); let dev = host.default_output_device().expect("no audio device found"); let cfg: cpal::StreamConfig = dev.supported_output_configs() .expect("couldn't find configs") .next() .expect("bogus device") .with_max_sample_rate().into(); let denom = cfg.sample_rate.0 as f32 * cfg.channels as f32; let (send, recv) = mpsc::sync_channel(1); let mut snk = AudioSink::new(recv); let mut snum: f32 = 0.0; let stream = dev.build_output_stream( &cfg, move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { snk.pour(data, 0); }, move |err| { println!("err: {}", err); } ).expect("could not build stream"); stream.play().unwrap(); let mut snum: usize = 0; loop { let mut samples = vec![0.0f32;1024].into_boxed_slice(); for s in samples.iter_mut() { *s += (snum as f32 / denom * 2.0 * 3.141592 * 200.0 as f32).sin(); snum = snum.wrapping_add(1); } send.send(samples).unwrap(); } }