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