makepad_platform/
audio_stream.rs

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