• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //! ```
5 //! use audio_streams::{StreamSource, DummyStreamSource};
6 //! use std::io::Read;
7 //!
8 //! const buffer_size: usize = 120;
9 //! const num_channels: usize = 2;
10 //! const frame_size: usize = num_channels * 2; // 16-bit samples are two bytes.
11 //!
12 //! # fn main() -> std::result::Result<(), Box<std::error::Error>> {
13 //! let mut stream_source = DummyStreamSource::new();
14 //!
15 //! let (_, mut stream) = stream_source
16 //!     .new_capture_stream(num_channels, 48000, buffer_size)?;
17 //! // Capture 10 buffers of zeros.
18 //! let mut cp_bufs = [[0xa5u8; buffer_size * frame_size]; 10];
19 //! for cp_buf in &mut cp_bufs {
20 //!     let mut stream_buffer = stream.next_capture_buffer()?;
21 //!     assert_eq!(stream_buffer.read(cp_buf)?, buffer_size * frame_size);
22 //! }
23 //! # Ok (())
24 //! # }
25 //! ```
26 
27 use std::{
28     error,
29     fmt::{self, Display},
30     io::{self, Read, Write},
31     time::{Duration, Instant},
32 };
33 
34 use super::{AudioBuffer, BufferDrop, DummyBufferDrop};
35 
36 /// `CaptureBufferStream` provides `CaptureBuffer`s to read with audio samples from capture.
37 pub trait CaptureBufferStream: Send {
next_capture_buffer<'a>(&'a mut self) -> Result<CaptureBuffer<'a>, Box<dyn error::Error>>38     fn next_capture_buffer<'a>(&'a mut self) -> Result<CaptureBuffer<'a>, Box<dyn error::Error>>;
39 }
40 
41 /// `CaptureBuffer` contains a block of audio samples got from capture stream. It provides
42 /// temporary view to those samples and will notifies capture stream when dropped.
43 /// Note that it'll always send `buffer.len() / frame_size` to drop function when it got destroyed
44 /// since `CaptureBufferStream` assumes that users get all the samples from the buffer.
45 pub struct CaptureBuffer<'a> {
46     buffer: AudioBuffer<'a>,
47 }
48 
49 /// Errors that are possible from a `CaptureBuffer`.
50 #[derive(Debug)]
51 pub enum CaptureBufferError {
52     InvalidLength,
53 }
54 
55 impl error::Error for CaptureBufferError {}
56 
57 impl Display for CaptureBufferError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result58     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59         match self {
60             CaptureBufferError::InvalidLength => write!(f, "Invalid buffer length"),
61         }
62     }
63 }
64 
65 impl<'a> CaptureBuffer<'a> {
66     /// Creates a new `CaptureBuffer` that holds a reference to the backing memory specified in
67     /// `buffer`.
new<F>( frame_size: usize, buffer: &'a mut [u8], drop: &'a mut F, ) -> Result<Self, CaptureBufferError> where F: BufferDrop,68     pub fn new<F>(
69         frame_size: usize,
70         buffer: &'a mut [u8],
71         drop: &'a mut F,
72     ) -> Result<Self, CaptureBufferError>
73     where
74         F: BufferDrop,
75     {
76         if buffer.len() % frame_size != 0 {
77             return Err(CaptureBufferError::InvalidLength);
78         }
79 
80         Ok(CaptureBuffer {
81             buffer: AudioBuffer {
82                 buffer,
83                 frame_size,
84                 offset: 0,
85                 drop,
86             },
87         })
88     }
89 
90     /// Returns the number of audio frames that fit in the buffer.
frame_capacity(&self) -> usize91     pub fn frame_capacity(&self) -> usize {
92         self.buffer.buffer.len() / self.buffer.frame_size
93     }
94 
95     /// Reads up to `size` bytes directly from this buffer inside of the given callback function.
copy_cb<F: FnOnce(&[u8])>(&mut self, size: usize, cb: F)96     pub fn copy_cb<F: FnOnce(&[u8])>(&mut self, size: usize, cb: F) {
97         let len = size / self.buffer.frame_size * self.buffer.frame_size;
98         cb(&self.buffer.buffer[self.buffer.offset..(self.buffer.offset + len)]);
99         self.buffer.offset += len;
100     }
101 }
102 
103 impl<'a> Read for CaptureBuffer<'a> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>104     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
105         let len = buf.len() / self.buffer.frame_size * self.buffer.frame_size;
106         let written = (&mut buf[..len]).write(&self.buffer.buffer[self.buffer.offset..])?;
107         self.buffer.offset += written;
108         Ok(written)
109     }
110 }
111 
112 /// Always sends `frame_capacity` when it drops.
113 impl<'a> Drop for CaptureBuffer<'a> {
drop(&mut self)114     fn drop(&mut self) {
115         self.buffer.drop.trigger(self.frame_capacity());
116     }
117 }
118 
119 /// Stream that provides null capture samples.
120 pub struct DummyCaptureStream {
121     buffer: Vec<u8>,
122     frame_size: usize,
123     interval: Duration,
124     next_frame: Duration,
125     start_time: Option<Instant>,
126     buffer_drop: DummyBufferDrop,
127 }
128 
129 impl DummyCaptureStream {
130     // TODO(allow other formats)
new(num_channels: usize, frame_rate: usize, buffer_size: usize) -> Self131     pub fn new(num_channels: usize, frame_rate: usize, buffer_size: usize) -> Self {
132         const S16LE_SIZE: usize = 2;
133         let frame_size = S16LE_SIZE * num_channels;
134         let interval = Duration::from_millis(buffer_size as u64 * 1000 / frame_rate as u64);
135         DummyCaptureStream {
136             buffer: vec![0; buffer_size * frame_size],
137             frame_size,
138             interval,
139             next_frame: interval,
140             start_time: None,
141             buffer_drop: DummyBufferDrop {
142                 which_buffer: false,
143             },
144         }
145     }
146 }
147 
148 impl CaptureBufferStream for DummyCaptureStream {
next_capture_buffer(&mut self) -> Result<CaptureBuffer, Box<dyn error::Error>>149     fn next_capture_buffer(&mut self) -> Result<CaptureBuffer, Box<dyn error::Error>> {
150         if let Some(start_time) = self.start_time {
151             if start_time.elapsed() < self.next_frame {
152                 std::thread::sleep(self.next_frame - start_time.elapsed());
153             }
154             self.next_frame += self.interval;
155         } else {
156             self.start_time = Some(Instant::now());
157             self.next_frame = self.interval;
158         }
159         Ok(CaptureBuffer::new(
160             self.frame_size,
161             &mut self.buffer,
162             &mut self.buffer_drop,
163         )?)
164     }
165 }
166 
167 #[cfg(test)]
168 mod tests {
169     use super::super::*;
170     use super::*;
171 
172     #[test]
invalid_buffer_length()173     fn invalid_buffer_length() {
174         // Capture buffers can't be created with a size that isn't divisible by the frame size.
175         let mut cp_buf = [0xa5u8; 480 * 2 * 2 + 1];
176         let mut buffer_drop = DummyBufferDrop {
177             which_buffer: false,
178         };
179         assert!(CaptureBuffer::new(2, &mut cp_buf, &mut buffer_drop).is_err());
180     }
181 
182     #[test]
trigger()183     fn trigger() {
184         struct TestDrop {
185             frame_count: usize,
186         };
187         impl BufferDrop for TestDrop {
188             fn trigger(&mut self, nwritten: usize) {
189                 self.frame_count += nwritten;
190             }
191         }
192         let mut test_drop = TestDrop { frame_count: 0 };
193         {
194             const FRAME_SIZE: usize = 4;
195             let mut buf = [0u8; 480 * FRAME_SIZE];
196             let mut cp_buf = CaptureBuffer::new(FRAME_SIZE, &mut buf, &mut test_drop).unwrap();
197             let mut local_buf = [0u8; 240 * FRAME_SIZE];
198             assert_eq!(cp_buf.read(&mut local_buf).unwrap(), 240 * FRAME_SIZE);
199         }
200         // This should be 480 no matter how many samples are read.
201         assert_eq!(test_drop.frame_count, 480);
202     }
203 
204     #[test]
sixteen_bit_stereo()205     fn sixteen_bit_stereo() {
206         let mut server = DummyStreamSource::new();
207         let (_, mut stream) = server.new_capture_stream(2, 48000, 480).unwrap();
208         let mut stream_buffer = stream.next_capture_buffer().unwrap();
209         assert_eq!(stream_buffer.frame_capacity(), 480);
210         let mut pb_buf = [0xa5u8; 480 * 2 * 2];
211         assert_eq!(stream_buffer.read(&mut pb_buf).unwrap(), 480 * 2 * 2);
212     }
213 
214     #[test]
consumption_rate()215     fn consumption_rate() {
216         let mut server = DummyStreamSource::new();
217         let (_, mut stream) = server.new_capture_stream(2, 48000, 480).unwrap();
218         let start = Instant::now();
219         {
220             let mut stream_buffer = stream.next_capture_buffer().unwrap();
221             let mut cp_buf = [0xa5u8; 480 * 2 * 2];
222             assert_eq!(stream_buffer.read(&mut cp_buf).unwrap(), 480 * 2 * 2);
223             for i in 0..cp_buf.len() {
224                 assert_eq!(cp_buf[i], 0, "Read samples should all be zeros.");
225             }
226         }
227         // The second call should block until the first buffer is consumed.
228         let _stream_buffer = stream.next_capture_buffer().unwrap();
229         let elapsed = start.elapsed();
230         assert!(
231             elapsed > Duration::from_millis(10),
232             "next_capture_buffer didn't block long enough {}",
233             elapsed.subsec_millis()
234         );
235     }
236 
237 }
238