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 //! Provides an interface for playing and recording audio. 6 //! 7 //! When implementing an audio playback system, the `StreamSource` trait is implemented. 8 //! Implementors of this trait allow creation of `PlaybackBufferStream` objects. The 9 //! `PlaybackBufferStream` provides the actual audio buffers to be filled with audio samples. These 10 //! buffers are obtained by calling `next_playback_buffer`. 11 //! 12 //! Users playing audio fill the provided buffers with audio. When a `PlaybackBuffer` is dropped, 13 //! the samples written to it are committed to the `PlaybackBufferStream` it came from. 14 //! 15 //! ``` 16 //! use audio_streams::{StreamSource, DummyStreamSource}; 17 //! use std::io::Write; 18 //! 19 //! const buffer_size: usize = 120; 20 //! const num_channels: usize = 2; 21 //! const frame_size: usize = num_channels * 2; // 16-bit samples are two bytes. 22 //! 23 //! # fn main() -> std::result::Result<(), Box<std::error::Error>> { 24 //! let mut stream_source = DummyStreamSource::new(); 25 //! 26 //! let (_, mut stream) = stream_source 27 //! .new_playback_stream(num_channels, 48000, buffer_size)?; 28 //! // Play 10 buffers of DC. 29 //! let pb_bufs = [[0xa5u8; buffer_size * frame_size]; 10]; 30 //! for pb_buf in &pb_bufs { 31 //! let mut stream_buffer = stream.next_playback_buffer()?; 32 //! assert_eq!(stream_buffer.write(pb_buf)?, buffer_size * frame_size); 33 //! } 34 //! # Ok (()) 35 //! # } 36 //! ``` 37 38 use std::error; 39 use std::fmt::{self, Display}; 40 use std::io::{self, Write}; 41 use std::os::unix::io::RawFd; 42 use std::result::Result; 43 use std::time::{Duration, Instant}; 44 45 pub mod capture; 46 47 /// `StreamSource` creates streams for playback or capture of audio. 48 pub trait StreamSource: Send { 49 /// Returns a stream control and buffer generator object. These are separate as the buffer 50 /// generator might want to be passed to the audio stream. new_playback_stream( &mut self, num_channels: usize, frame_rate: usize, buffer_size: usize, ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), Box<dyn error::Error>>51 fn new_playback_stream( 52 &mut self, 53 num_channels: usize, 54 frame_rate: usize, 55 buffer_size: usize, 56 ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), Box<dyn error::Error>>; 57 58 /// Returns a stream control and buffer generator object. These are separate as the buffer 59 /// generator might want to be passed to the audio stream. 60 /// Default implementation returns `DummyStreamControl` and `DummyCaptureStream`. new_capture_stream( &mut self, num_channels: usize, frame_rate: usize, buffer_size: usize, ) -> Result< ( Box<dyn StreamControl>, Box<dyn capture::CaptureBufferStream>, ), Box<dyn error::Error>, >61 fn new_capture_stream( 62 &mut self, 63 num_channels: usize, 64 frame_rate: usize, 65 buffer_size: usize, 66 ) -> Result< 67 ( 68 Box<dyn StreamControl>, 69 Box<dyn capture::CaptureBufferStream>, 70 ), 71 Box<dyn error::Error>, 72 > { 73 Ok(( 74 Box::new(DummyStreamControl::new()), 75 Box::new(capture::DummyCaptureStream::new( 76 num_channels, 77 frame_rate, 78 buffer_size, 79 )), 80 )) 81 } 82 83 /// Returns any open file descriptors needed by the implementor. The FD list helps users of the 84 /// StreamSource enter Linux jails making sure not to close needed FDs. keep_fds(&self) -> Option<Vec<RawFd>>85 fn keep_fds(&self) -> Option<Vec<RawFd>> { 86 None 87 } 88 } 89 90 /// `PlaybackBufferStream` provides `PlaybackBuffer`s to fill with audio samples for playback. 91 pub trait PlaybackBufferStream: Send { next_playback_buffer<'a>(&'a mut self) -> Result<PlaybackBuffer<'a>, Box<dyn error::Error>>92 fn next_playback_buffer<'a>(&'a mut self) -> Result<PlaybackBuffer<'a>, Box<dyn error::Error>>; 93 } 94 95 /// `StreamControl` provides a way to set the volume and mute states of a stream. `StreamControl` 96 /// is separate from the stream so it can be owned by a different thread if needed. 97 pub trait StreamControl: Send + Sync { set_volume(&mut self, _scaler: f64)98 fn set_volume(&mut self, _scaler: f64) {} set_mute(&mut self, _mute: bool)99 fn set_mute(&mut self, _mute: bool) {} 100 } 101 102 /// `BufferDrop` is used as a callback mechanism for `PlaybackBuffer` objects. It is meant to be 103 /// implemented by the audio stream, allowing arbitrary code to be run after a buffer is filled or 104 /// read by the user. 105 pub trait BufferDrop { 106 /// Called when an audio buffer is dropped. `nframes` indicates the number of audio frames that 107 /// were read or written to the device. trigger(&mut self, nframes: usize)108 fn trigger(&mut self, nframes: usize); 109 } 110 111 /// Errors that are possible from a `PlaybackBuffer`. 112 #[derive(Debug)] 113 pub enum PlaybackBufferError { 114 InvalidLength, 115 } 116 117 impl error::Error for PlaybackBufferError {} 118 119 impl Display for PlaybackBufferError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 121 match self { 122 PlaybackBufferError::InvalidLength => write!(f, "Invalid buffer length"), 123 } 124 } 125 } 126 127 /// `AudioBuffer` is one buffer that holds buffer_size audio frames and its drop function. 128 /// It is the inner data of `PlaybackBuffer` and `CaptureBuffer`. 129 struct AudioBuffer<'a> { 130 buffer: &'a mut [u8], 131 offset: usize, // Read or Write offset in frames. 132 frame_size: usize, // Size of a frame in bytes. 133 drop: &'a mut dyn BufferDrop, 134 } 135 136 /// `PlaybackBuffer` is one buffer that holds buffer_size audio frames. It is used to temporarily 137 /// allow access to an audio buffer and notifes the owning stream of write completion when dropped. 138 pub struct PlaybackBuffer<'a> { 139 buffer: AudioBuffer<'a>, 140 } 141 142 impl<'a> PlaybackBuffer<'a> { 143 /// Creates a new `PlaybackBuffer` that holds a reference to the backing memory specified in 144 /// `buffer`. new<F>( frame_size: usize, buffer: &'a mut [u8], drop: &'a mut F, ) -> Result<Self, PlaybackBufferError> where F: BufferDrop,145 pub fn new<F>( 146 frame_size: usize, 147 buffer: &'a mut [u8], 148 drop: &'a mut F, 149 ) -> Result<Self, PlaybackBufferError> 150 where 151 F: BufferDrop, 152 { 153 if buffer.len() % frame_size != 0 { 154 return Err(PlaybackBufferError::InvalidLength); 155 } 156 157 Ok(PlaybackBuffer { 158 buffer: AudioBuffer { 159 buffer, 160 offset: 0, 161 frame_size, 162 drop, 163 }, 164 }) 165 } 166 167 /// Returns the number of audio frames that fit in the buffer. frame_capacity(&self) -> usize168 pub fn frame_capacity(&self) -> usize { 169 self.buffer.buffer.len() / self.buffer.frame_size 170 } 171 172 /// Writes up to `size` bytes directly to this buffer inside of the given callback function. copy_cb<F: FnOnce(&mut [u8])>(&mut self, size: usize, cb: F)173 pub fn copy_cb<F: FnOnce(&mut [u8])>(&mut self, size: usize, cb: F) { 174 // only write complete frames. 175 let len = size / self.buffer.frame_size * self.buffer.frame_size; 176 cb(&mut self.buffer.buffer[self.buffer.offset..(self.buffer.offset + len)]); 177 self.buffer.offset += len; 178 } 179 } 180 181 impl<'a> Write for PlaybackBuffer<'a> { write(&mut self, buf: &[u8]) -> io::Result<usize>182 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 183 // only write complete frames. 184 let len = buf.len() / self.buffer.frame_size * self.buffer.frame_size; 185 let written = (&mut self.buffer.buffer[self.buffer.offset..]).write(&buf[..len])?; 186 self.buffer.offset += written; 187 Ok(written) 188 } 189 flush(&mut self) -> io::Result<()>190 fn flush(&mut self) -> io::Result<()> { 191 Ok(()) 192 } 193 } 194 195 impl<'a> Drop for PlaybackBuffer<'a> { drop(&mut self)196 fn drop(&mut self) { 197 self.buffer 198 .drop 199 .trigger(self.buffer.offset / self.buffer.frame_size); 200 } 201 } 202 203 /// Stream that accepts playback samples but drops them. 204 pub struct DummyStream { 205 buffer: Vec<u8>, 206 frame_size: usize, 207 interval: Duration, 208 next_frame: Duration, 209 start_time: Option<Instant>, 210 buffer_drop: DummyBufferDrop, 211 } 212 213 /// DummyStream data that is needed from the buffer complete callback. 214 struct DummyBufferDrop { 215 which_buffer: bool, 216 } 217 218 impl BufferDrop for DummyBufferDrop { trigger(&mut self, _nwritten: usize)219 fn trigger(&mut self, _nwritten: usize) { 220 // When a buffer completes, switch to the other one. 221 self.which_buffer ^= true; 222 } 223 } 224 225 impl DummyStream { 226 // TODO(allow other formats) new(num_channels: usize, frame_rate: usize, buffer_size: usize) -> Self227 pub fn new(num_channels: usize, frame_rate: usize, buffer_size: usize) -> Self { 228 const S16LE_SIZE: usize = 2; 229 let frame_size = S16LE_SIZE * num_channels; 230 let interval = Duration::from_millis(buffer_size as u64 * 1000 / frame_rate as u64); 231 DummyStream { 232 buffer: vec![0; buffer_size * frame_size], 233 frame_size, 234 interval, 235 next_frame: interval, 236 start_time: None, 237 buffer_drop: DummyBufferDrop { 238 which_buffer: false, 239 }, 240 } 241 } 242 } 243 244 impl PlaybackBufferStream for DummyStream { next_playback_buffer<'a>(&'a mut self) -> Result<PlaybackBuffer<'a>, Box<dyn error::Error>>245 fn next_playback_buffer<'a>(&'a mut self) -> Result<PlaybackBuffer<'a>, Box<dyn error::Error>> { 246 if let Some(start_time) = self.start_time { 247 if start_time.elapsed() < self.next_frame { 248 std::thread::sleep(self.next_frame - start_time.elapsed()); 249 } 250 self.next_frame += self.interval; 251 } else { 252 self.start_time = Some(Instant::now()); 253 self.next_frame = self.interval; 254 } 255 Ok(PlaybackBuffer::new( 256 self.frame_size, 257 &mut self.buffer, 258 &mut self.buffer_drop, 259 )?) 260 } 261 } 262 263 /// No-op control for `DummyStream`s. 264 #[derive(Default)] 265 pub struct DummyStreamControl; 266 267 impl DummyStreamControl { new() -> Self268 pub fn new() -> Self { 269 DummyStreamControl {} 270 } 271 } 272 273 impl StreamControl for DummyStreamControl {} 274 275 /// Source of `DummyStream` and `DummyStreamControl` objects. 276 #[derive(Default)] 277 pub struct DummyStreamSource; 278 279 impl DummyStreamSource { new() -> Self280 pub fn new() -> Self { 281 DummyStreamSource {} 282 } 283 } 284 285 impl StreamSource for DummyStreamSource { new_playback_stream( &mut self, num_channels: usize, frame_rate: usize, buffer_size: usize, ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), Box<dyn error::Error>>286 fn new_playback_stream( 287 &mut self, 288 num_channels: usize, 289 frame_rate: usize, 290 buffer_size: usize, 291 ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), Box<dyn error::Error>> 292 { 293 Ok(( 294 Box::new(DummyStreamControl::new()), 295 Box::new(DummyStream::new(num_channels, frame_rate, buffer_size)), 296 )) 297 } 298 } 299 300 #[cfg(test)] 301 mod tests { 302 use super::*; 303 304 #[test] invalid_buffer_length()305 fn invalid_buffer_length() { 306 // Playback buffers can't be created with a size that isn't divisible by the frame size. 307 let mut pb_buf = [0xa5u8; 480 * 2 * 2 + 1]; 308 let mut buffer_drop = DummyBufferDrop { 309 which_buffer: false, 310 }; 311 assert!(PlaybackBuffer::new(2, &mut pb_buf, &mut buffer_drop).is_err()); 312 } 313 314 #[test] trigger()315 fn trigger() { 316 struct TestDrop { 317 frame_count: usize, 318 }; 319 impl BufferDrop for TestDrop { 320 fn trigger(&mut self, nwritten: usize) { 321 self.frame_count += nwritten; 322 } 323 } 324 let mut test_drop = TestDrop { frame_count: 0 }; 325 { 326 const FRAME_SIZE: usize = 4; 327 let mut buf = [0u8; 480 * FRAME_SIZE]; 328 let mut pb_buf = PlaybackBuffer::new(FRAME_SIZE, &mut buf, &mut test_drop).unwrap(); 329 pb_buf.write(&[0xa5u8; 480 * FRAME_SIZE]).unwrap(); 330 } 331 assert_eq!(test_drop.frame_count, 480); 332 } 333 334 #[test] sixteen_bit_stereo()335 fn sixteen_bit_stereo() { 336 let mut server = DummyStreamSource::new(); 337 let (_, mut stream) = server.new_playback_stream(2, 48000, 480).unwrap(); 338 let mut stream_buffer = stream.next_playback_buffer().unwrap(); 339 assert_eq!(stream_buffer.frame_capacity(), 480); 340 let pb_buf = [0xa5u8; 480 * 2 * 2]; 341 assert_eq!(stream_buffer.write(&pb_buf).unwrap(), 480 * 2 * 2); 342 } 343 344 #[test] consumption_rate()345 fn consumption_rate() { 346 let mut server = DummyStreamSource::new(); 347 let (_, mut stream) = server.new_playback_stream(2, 48000, 480).unwrap(); 348 let start = Instant::now(); 349 { 350 let mut stream_buffer = stream.next_playback_buffer().unwrap(); 351 let pb_buf = [0xa5u8; 480 * 2 * 2]; 352 assert_eq!(stream_buffer.write(&pb_buf).unwrap(), 480 * 2 * 2); 353 } 354 // The second call should block until the first buffer is consumed. 355 let _stream_buffer = stream.next_playback_buffer().unwrap(); 356 let elapsed = start.elapsed(); 357 assert!( 358 elapsed > Duration::from_millis(10), 359 "next_playback_buffer didn't block long enough {}", 360 elapsed.subsec_millis() 361 ); 362 } 363 } 364