summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: b01dc9f8ad0e2de74b851bdb87e3a43f11036bbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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<Box<[f32]>>,
    buffer: Option<Box<[f32]>>,
    idx: usize
}

impl AudioSink {
    fn new(recv: mpsc::Receiver<Box<[f32]>>) -> 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();
    }
}