makepad_audio_graph/
audio_stream.rs

1
2use {
3    crate::{
4        makepad_platform::audio::*,
5    },
6    std::sync::{Arc, Mutex},
7    std::sync::mpsc::{
8        channel,
9        Sender,
10        Receiver,
11        SendError
12    }
13};
14
15#[derive(Clone)]
16pub struct AudioStreamSender {
17    stream_send: Sender<(u64, AudioBuffer)>,
18}
19unsafe impl Send for AudioStreamSender {}
20
21#[derive(Clone)]
22pub struct AudioStreamReceiver(Arc<Mutex<ReceiverInner>>);
23
24pub struct ReceiverInner {
25    pub routes: Vec<AudioRoute>,
26    stream_recv: Receiver<(u64, AudioBuffer)>,
27}
28
29unsafe impl Send for AudioStreamReceiver {}
30
31pub struct AudioRoute {
32    id: u64,
33    start_offset: usize,
34    buffers: Vec<AudioBuffer>
35}
36
37impl AudioStreamSender {
38    pub fn create_pair() -> (AudioStreamSender, AudioStreamReceiver) {
39        let (stream_send, stream_recv) = channel::<(u64, AudioBuffer)>();
40        (AudioStreamSender {
41            stream_send,
42        }, AudioStreamReceiver(Arc::new(Mutex::new(ReceiverInner {
43            stream_recv,
44            routes: Vec::new()
45        }))))
46    }
47    
48    pub fn write_buffer(&self, route_id: u64, buffer: AudioBuffer) -> Result<(), SendError<(u64, AudioBuffer) >> {
49        self.stream_send.send((route_id, buffer))
50    }
51}
52
53impl AudioStreamReceiver {
54    pub fn num_routes(&self) -> usize {
55        let iself = self.0.lock().unwrap();
56        iself.routes.len()
57    }
58    
59    pub fn route_id(&self, route_num: usize) -> u64 {
60        let iself = self.0.lock().unwrap();
61        iself.routes[route_num].id
62    }
63
64    pub fn try_recv_stream(&mut self) {
65        let mut iself = self.0.lock().unwrap();
66        while let Ok((route_id, buf)) = iself.stream_recv.try_recv() {
67            if let Some(route) = iself.routes.iter_mut().find( | v | v.id == route_id) {
68                route.buffers.push(buf);
69            }
70            else {
71                iself.routes.push(AudioRoute {
72                    id: route_id,
73                    buffers: vec![buf],
74                    start_offset: 0
75                });
76            }
77        }
78    }
79    
80    pub fn recv_stream(&mut self) {
81        {
82            let mut iself = self.0.lock().unwrap();
83            if let Ok((route_id, buf)) = iself.stream_recv.recv() {
84                if let Some(route) = iself.routes.iter_mut().find( | v | v.id == route_id) {
85                    route.buffers.push(buf);
86                }
87                else {
88                    iself.routes.push(AudioRoute {
89                        id: route_id,
90                        buffers: vec![buf],
91                        start_offset: 0
92                    });
93                }
94            }
95        }
96        self.try_recv_stream();
97    }
98    
99    pub fn read_buffer(&mut self, route_num: usize, output: &mut AudioBuffer, min_buf: usize, max_buf:usize) -> usize {
100        let mut iself = self.0.lock().unwrap();
101        let route = if let Some(route) = iself.routes.get_mut(route_num) {
102            route
103        }
104        else {
105            return 0;
106        };
107        
108        // ok if we dont have enough data in our stack for output, just output nothing
109        let mut total = 0;
110        for buf in route.buffers.iter() { 
111            total += buf.frame_count();
112        }
113
114        // check if we have enough buffer
115        if total - route.start_offset < output.frame_count() * min_buf {
116            return 0
117        }
118         
119        // flush down the buffer
120        while total > output.frame_count() * max_buf{
121            let buf = route.buffers.remove(0);
122            total -= buf.frame_count();
123        }
124        
125        // ok so we need to eat from the start of the buffer vec until output is filled
126        let mut frames_read = 0;
127        let out_channel_count = output.channel_count();
128        let out_frame_count = output.frame_count();
129        while let Some(input) = route.buffers.first() {
130            // ok so. we can copy buffer from start_offset
131            let mut start_offset = None;
132            let start_frames_read = frames_read;
133            for chan in 0..out_channel_count {
134                frames_read = start_frames_read;
135                let inp = input.channel(chan.min(input.channel_count() - 1));
136                let out = output.channel_mut(chan);
137                // alright so we write into the output buffer
138                for i in route.start_offset..inp.len() {
139                    if frames_read >= out_frame_count {
140                        start_offset = Some(i);
141                        break;
142                    }
143                    out[frames_read] = inp[i];
144                    frames_read += 1;
145                }
146            }
147            // only consumed a part of the buffer
148            if let Some(start_offset) = start_offset {
149                route.start_offset = start_offset;
150                break
151            }
152            else { // consumed entire buffer
153                route.start_offset = 0;
154                route.buffers.remove(0);
155            }
156        }
157        
158        frames_read
159    }
160}