xref: /aosp_15_r20/external/crosvm/android_audio/src/lib.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #[cfg(feature = "libaaudio_stub")]
6 mod libaaudio_stub;
7 
8 use std::os::raw::c_void;
9 use std::time::Duration;
10 use std::time::Instant;
11 
12 use async_trait::async_trait;
13 use audio_streams::capture::AsyncCaptureBuffer;
14 use audio_streams::capture::AsyncCaptureBufferStream;
15 use audio_streams::capture::CaptureBuffer;
16 use audio_streams::capture::CaptureBufferStream;
17 use audio_streams::AsyncBufferCommit;
18 use audio_streams::AsyncPlaybackBuffer;
19 use audio_streams::AsyncPlaybackBufferStream;
20 use audio_streams::AudioStreamsExecutor;
21 use audio_streams::BoxError;
22 use audio_streams::BufferCommit;
23 use audio_streams::NoopStreamControl;
24 use audio_streams::PlaybackBuffer;
25 use audio_streams::PlaybackBufferStream;
26 use audio_streams::SampleFormat;
27 use audio_streams::StreamControl;
28 use audio_streams::StreamEffect;
29 use audio_streams::StreamSource;
30 use audio_streams::StreamSourceGenerator;
31 use base::warn;
32 use thiserror::Error;
33 
34 #[derive(Clone, Copy)]
35 enum AndroidAudioStreamDirection {
36     Input = 1,
37     Output = 0,
38 }
39 
40 #[derive(Error, Debug)]
41 pub enum AAudioError {
42     #[error("Failed to create stream builder")]
43     StreamBuilderCreation,
44     #[error("Failed to open stream")]
45     StreamOpen,
46     #[error("Failed to start stream")]
47     StreamStart,
48     #[error("Failed to delete stream builder")]
49     StreamBuilderDelete,
50 }
51 
52 // Opaque blob
53 #[repr(C)]
54 struct AAudioStream {
55     _data: [u8; 0],
56     _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
57 }
58 
59 // Opaque blob
60 #[repr(C)]
61 struct AAudioStreamBuilder {
62     _data: [u8; 0],
63     _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
64 }
65 
66 type AaudioFormatT = i32;
67 type AaudioResultT = i32;
68 const AAUDIO_OK: AaudioResultT = 0;
69 
70 extern "C" {
AAudio_createStreamBuilder(builder: *mut *mut AAudioStreamBuilder) -> AaudioResultT71     fn AAudio_createStreamBuilder(builder: *mut *mut AAudioStreamBuilder) -> AaudioResultT;
AAudioStreamBuilder_delete(builder: *mut AAudioStreamBuilder) -> AaudioResultT72     fn AAudioStreamBuilder_delete(builder: *mut AAudioStreamBuilder) -> AaudioResultT;
AAudioStreamBuilder_setBufferCapacityInFrames( builder: *mut AAudioStreamBuilder, num_frames: i32, )73     fn AAudioStreamBuilder_setBufferCapacityInFrames(
74         builder: *mut AAudioStreamBuilder,
75         num_frames: i32,
76     );
AAudioStreamBuilder_setDirection(builder: *mut AAudioStreamBuilder, direction: u32)77     fn AAudioStreamBuilder_setDirection(builder: *mut AAudioStreamBuilder, direction: u32);
AAudioStreamBuilder_setFormat(builder: *mut AAudioStreamBuilder, format: AaudioFormatT)78     fn AAudioStreamBuilder_setFormat(builder: *mut AAudioStreamBuilder, format: AaudioFormatT);
AAudioStreamBuilder_setSampleRate(builder: *mut AAudioStreamBuilder, sample_rate: i32)79     fn AAudioStreamBuilder_setSampleRate(builder: *mut AAudioStreamBuilder, sample_rate: i32);
AAudioStreamBuilder_setChannelCount(builder: *mut AAudioStreamBuilder, channel_count: i32)80     fn AAudioStreamBuilder_setChannelCount(builder: *mut AAudioStreamBuilder, channel_count: i32);
AAudioStreamBuilder_openStream( builder: *mut AAudioStreamBuilder, stream: *mut *mut AAudioStream, ) -> AaudioResultT81     fn AAudioStreamBuilder_openStream(
82         builder: *mut AAudioStreamBuilder,
83         stream: *mut *mut AAudioStream,
84     ) -> AaudioResultT;
AAudioStream_getBufferSizeInFrames(stream: *mut AAudioStream) -> i3285     fn AAudioStream_getBufferSizeInFrames(stream: *mut AAudioStream) -> i32;
AAudioStream_requestStart(stream: *mut AAudioStream) -> AaudioResultT86     fn AAudioStream_requestStart(stream: *mut AAudioStream) -> AaudioResultT;
AAudioStream_read( stream: *mut AAudioStream, buffer: *mut c_void, num_frames: i32, timeout_nanoseconds: i64, ) -> AaudioResultT87     fn AAudioStream_read(
88         stream: *mut AAudioStream,
89         buffer: *mut c_void,
90         num_frames: i32,
91         timeout_nanoseconds: i64,
92     ) -> AaudioResultT;
AAudioStream_write( stream: *mut AAudioStream, buffer: *const c_void, num_frames: i32, timeout_nanoseconds: i64, ) -> AaudioResultT93     fn AAudioStream_write(
94         stream: *mut AAudioStream,
95         buffer: *const c_void,
96         num_frames: i32,
97         timeout_nanoseconds: i64,
98     ) -> AaudioResultT;
AAudioStream_close(stream: *mut AAudioStream) -> AaudioResultT99     fn AAudioStream_close(stream: *mut AAudioStream) -> AaudioResultT;
100 }
101 
102 struct AAudioStreamPtr {
103     // TODO: Use callback function to avoid possible thread preemption and glitches cause by
104     // using AAudio APIs in different threads.
105     stream_ptr: *mut AAudioStream,
106 }
107 
108 // SAFETY:
109 // AudioStream.drop.buffer_ptr: *const u8 points to AudioStream.buffer, which would be alive
110 // whenever AudioStream.drop.buffer_ptr is alive.
111 unsafe impl Send for AndroidAudioStreamCommit {}
112 
113 struct AudioStream {
114     buffer: Box<[u8]>,
115     frame_size: usize,
116     frame_rate: u32,
117     next_frame: Instant,
118     start_time: Option<Instant>,
119     total_frames: i32,
120     buffer_drop: AndroidAudioStreamCommit,
121     read_count: i32,
122     aaudio_buffer_size: usize,
123 }
124 
125 struct AndroidAudioStreamCommit {
126     buffer_ptr: *const u8,
127     stream: AAudioStreamPtr,
128     direction: AndroidAudioStreamDirection,
129 }
130 
131 impl BufferCommit for AndroidAudioStreamCommit {
commit(&mut self, _nwritten: usize)132     fn commit(&mut self, _nwritten: usize) {
133         // This traits function is never called.
134         unimplemented!();
135     }
136 }
137 
138 #[async_trait(?Send)]
139 impl AsyncBufferCommit for AndroidAudioStreamCommit {
commit(&mut self, nwritten: usize)140     async fn commit(&mut self, nwritten: usize) {
141         match self.direction {
142             AndroidAudioStreamDirection::Input => {}
143             AndroidAudioStreamDirection::Output => {
144                 // SAFETY:
145                 // The AAudioStream_write reads buffer for nwritten * frame_size bytes
146                 // It is safe since nwritten < buffer_size and the buffer.len() == buffer_size *
147                 // frame_size
148                 let frames_written: i32 = unsafe {
149                     AAudioStream_write(
150                         self.stream.stream_ptr,
151                         self.buffer_ptr as *const c_void,
152                         nwritten as i32,
153                         0, // this call will not wait.
154                     )
155                 };
156                 if frames_written < 0 {
157                     warn!("AAudio stream write failed.");
158                 } else if (frames_written as usize) < nwritten {
159                     // Currently, the frames unable to write by the AAudio API are dropped.
160                     warn!(
161                         "Android Audio Stream:  Drop {} frames",
162                         nwritten - (frames_written as usize)
163                     );
164                 }
165             }
166         }
167     }
168 }
169 
170 impl AudioStream {
new( num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, direction: AndroidAudioStreamDirection, ) -> Result<Self, BoxError>171     pub fn new(
172         num_channels: usize,
173         format: SampleFormat,
174         frame_rate: u32,
175         buffer_size: usize,
176         direction: AndroidAudioStreamDirection,
177     ) -> Result<Self, BoxError> {
178         let frame_size = format.sample_bytes() * num_channels;
179 
180         let mut stream_ptr: *mut AAudioStream = std::ptr::null_mut();
181         let mut builder: *mut AAudioStreamBuilder = std::ptr::null_mut();
182         // SAFETY:
183         // Interfacing with the AAudio C API. Assumes correct linking
184         // and `builder` and `stream_ptr` pointers are valid and properly initialized.
185         unsafe {
186             if AAudio_createStreamBuilder(&mut builder) != AAUDIO_OK {
187                 return Err(Box::new(AAudioError::StreamBuilderCreation));
188             }
189             AAudioStreamBuilder_setDirection(builder, direction as u32);
190             AAudioStreamBuilder_setBufferCapacityInFrames(builder, buffer_size as i32 * 2);
191             AAudioStreamBuilder_setFormat(builder, format as AaudioFormatT);
192             AAudioStreamBuilder_setSampleRate(builder, frame_rate as i32);
193             AAudioStreamBuilder_setChannelCount(builder, num_channels as i32);
194             if AAudioStreamBuilder_openStream(builder, &mut stream_ptr) != AAUDIO_OK {
195                 return Err(Box::new(AAudioError::StreamOpen));
196             }
197             if AAudioStreamBuilder_delete(builder) != AAUDIO_OK {
198                 return Err(Box::new(AAudioError::StreamBuilderDelete));
199             }
200             if AAudioStream_requestStart(stream_ptr) != AAUDIO_OK {
201                 return Err(Box::new(AAudioError::StreamStart));
202             }
203         }
204         // SAFETY:
205         // Interfacing with the AAudio C API. Assumes correct linking
206         // and `stream_ptr` pointers are valid and properly initialized.
207         let aaudio_buffer_size = unsafe { AAudioStream_getBufferSizeInFrames(stream_ptr) } as usize;
208         let buffer = vec![0; buffer_size * frame_size].into_boxed_slice();
209         let stream = AAudioStreamPtr { stream_ptr };
210         let buffer_drop = AndroidAudioStreamCommit {
211             stream,
212             buffer_ptr: buffer.as_ptr(),
213             direction,
214         };
215         Ok(AudioStream {
216             buffer,
217             frame_size,
218             frame_rate,
219             next_frame: Instant::now(),
220             start_time: None,
221             total_frames: 0,
222             buffer_drop,
223             read_count: 0,
224             aaudio_buffer_size,
225         })
226     }
227 }
228 
229 impl PlaybackBufferStream for AudioStream {
next_playback_buffer<'b, 's: 'b>(&'s mut self) -> Result<PlaybackBuffer<'b>, BoxError>230     fn next_playback_buffer<'b, 's: 'b>(&'s mut self) -> Result<PlaybackBuffer<'b>, BoxError> {
231         // This traits function is never called.
232         unimplemented!();
233     }
234 }
235 
236 #[async_trait(?Send)]
237 impl AsyncPlaybackBufferStream for AudioStream {
next_playback_buffer<'a>( &'a mut self, ex: &dyn AudioStreamsExecutor, ) -> Result<AsyncPlaybackBuffer<'a>, BoxError>238     async fn next_playback_buffer<'a>(
239         &'a mut self,
240         ex: &dyn AudioStreamsExecutor,
241     ) -> Result<AsyncPlaybackBuffer<'a>, BoxError> {
242         self.total_frames += (self.buffer.len() / self.frame_size) as i32;
243         let start_time = match self.start_time {
244             Some(time) => {
245                 ex.delay(self.next_frame.saturating_duration_since(Instant::now()))
246                     .await?;
247                 time
248             }
249             None => {
250                 let now = Instant::now();
251                 self.start_time = Some(now);
252                 now
253             }
254         };
255         self.next_frame = start_time
256             + Duration::from_millis(self.total_frames as u64 * 1000 / self.frame_rate as u64);
257         Ok(
258             AsyncPlaybackBuffer::new(self.frame_size, self.buffer.as_mut(), &mut self.buffer_drop)
259                 .map_err(Box::new)?,
260         )
261     }
262 }
263 
264 #[async_trait(?Send)]
265 impl CaptureBufferStream for AudioStream {
next_capture_buffer<'b, 's: 'b>(&'s mut self) -> Result<CaptureBuffer<'b>, BoxError>266     fn next_capture_buffer<'b, 's: 'b>(&'s mut self) -> Result<CaptureBuffer<'b>, BoxError> {
267         // This traits function is never called.
268         unimplemented!()
269     }
270 }
271 
272 #[async_trait(?Send)]
273 impl AsyncCaptureBufferStream for AudioStream {
next_capture_buffer<'a>( &'a mut self, ex: &dyn AudioStreamsExecutor, ) -> Result<AsyncCaptureBuffer<'a>, BoxError>274     async fn next_capture_buffer<'a>(
275         &'a mut self,
276         ex: &dyn AudioStreamsExecutor,
277     ) -> Result<AsyncCaptureBuffer<'a>, BoxError> {
278         let buffer_size = self.buffer.len() / self.frame_size;
279         self.read_count += 1;
280         self.total_frames += buffer_size as i32;
281         let start_time = match self.start_time {
282             Some(time) => {
283                 ex.delay(self.next_frame.saturating_duration_since(Instant::now()))
284                     .await?;
285                 time
286             }
287             None => {
288                 let now = Instant::now();
289                 self.start_time = Some(now);
290                 now
291             }
292         };
293         self.next_frame = start_time
294             + Duration::from_millis(self.total_frames as u64 * 1000 / self.frame_rate as u64);
295 
296         // Skip for at least (1.5x aaudio buffer size - buffer_size) to ensure there is always a
297         // aaudio buffer available for read.
298         if self.read_count < (self.aaudio_buffer_size * 3 / 2 / buffer_size) as i32 + 1 {
299             self.buffer.fill(0);
300             return Ok(AsyncCaptureBuffer::new(
301                 buffer_size,
302                 self.buffer.as_mut(),
303                 &mut self.buffer_drop,
304             )
305             .map_err(Box::new)?);
306         }
307 
308         // SAFETY:
309         // The AAudioStream_read writes buffer for buffer.len() / frame_size * frame_size bytes
310         let frames_read = unsafe {
311             AAudioStream_read(
312                 self.buffer_drop.stream.stream_ptr,
313                 self.buffer.as_mut_ptr() as *mut c_void,
314                 (buffer_size) as i32,
315                 0,
316             )
317         };
318 
319         if frames_read < 0 {
320             warn!("AAudio stream read failed: {frames_read}");
321             self.buffer.fill(0);
322         } else if (frames_read as usize) < buffer_size {
323             warn!(
324                 "AAudio stream read data not enough. frames read: {frames_read}, buffer size: {buffer_size}",
325             );
326             self.buffer[frames_read as usize * self.frame_size..].fill(0);
327         }
328 
329         Ok(
330             AsyncCaptureBuffer::new(buffer_size, self.buffer.as_mut(), &mut self.buffer_drop)
331                 .map_err(Box::new)?,
332         )
333     }
334 }
335 
336 impl Drop for AAudioStreamPtr {
drop(&mut self)337     fn drop(&mut self) {
338         // SAFETY:
339         // Interfacing with the AAudio C API. Assumes correct linking
340         // and `stream_ptr` are valid and properly initialized.
341         if unsafe { AAudioStream_close(self.stream_ptr) } != AAUDIO_OK {
342             warn!("AAudio stream close failed.");
343         }
344     }
345 }
346 
347 #[derive(Default)]
348 struct AndroidAudioStreamSource;
349 
350 impl StreamSource for AndroidAudioStreamSource {
351     #[allow(clippy::type_complexity)]
new_playback_stream( &mut self, _num_channels: usize, _format: SampleFormat, _frame_rate: u32, _buffer_size: usize, ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError>352     fn new_playback_stream(
353         &mut self,
354         _num_channels: usize,
355         _format: SampleFormat,
356         _frame_rate: u32,
357         _buffer_size: usize,
358     ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError> {
359         // This traits function is never called.
360         unimplemented!();
361     }
362 
363     #[allow(clippy::type_complexity)]
new_async_playback_stream( &mut self, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, _ex: &dyn AudioStreamsExecutor, ) -> Result<(Box<dyn StreamControl>, Box<dyn AsyncPlaybackBufferStream>), BoxError>364     fn new_async_playback_stream(
365         &mut self,
366         num_channels: usize,
367         format: SampleFormat,
368         frame_rate: u32,
369         buffer_size: usize,
370         _ex: &dyn AudioStreamsExecutor,
371     ) -> Result<(Box<dyn StreamControl>, Box<dyn AsyncPlaybackBufferStream>), BoxError> {
372         let audio_stream = AudioStream::new(
373             num_channels,
374             format,
375             frame_rate,
376             buffer_size,
377             AndroidAudioStreamDirection::Output,
378         )?;
379         Ok((Box::new(NoopStreamControl::new()), Box::new(audio_stream)))
380     }
381 
382     #[allow(clippy::type_complexity)]
new_capture_stream( &mut self, _num_channels: usize, _format: SampleFormat, _frame_rate: u32, _buffer_size: usize, _effects: &[StreamEffect], ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError>383     fn new_capture_stream(
384         &mut self,
385         _num_channels: usize,
386         _format: SampleFormat,
387         _frame_rate: u32,
388         _buffer_size: usize,
389         _effects: &[StreamEffect],
390     ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn CaptureBufferStream>), BoxError> {
391         // This traits function is never called.
392         unimplemented!();
393     }
394 
395     #[allow(clippy::type_complexity)]
new_async_capture_stream( &mut self, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, _effects: &[StreamEffect], _ex: &dyn AudioStreamsExecutor, ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn AsyncCaptureBufferStream>), BoxError>396     fn new_async_capture_stream(
397         &mut self,
398         num_channels: usize,
399         format: SampleFormat,
400         frame_rate: u32,
401         buffer_size: usize,
402         _effects: &[StreamEffect],
403         _ex: &dyn AudioStreamsExecutor,
404     ) -> std::result::Result<(Box<dyn StreamControl>, Box<dyn AsyncCaptureBufferStream>), BoxError>
405     {
406         let audio_stream = AudioStream::new(
407             num_channels,
408             format,
409             frame_rate,
410             buffer_size,
411             AndroidAudioStreamDirection::Input,
412         )?;
413         Ok((Box::new(NoopStreamControl::new()), Box::new(audio_stream)))
414     }
415 }
416 
417 #[derive(Default)]
418 pub struct AndroidAudioStreamSourceGenerator;
419 
420 impl AndroidAudioStreamSourceGenerator {
new() -> Self421     pub fn new() -> Self {
422         AndroidAudioStreamSourceGenerator {}
423     }
424 }
425 
426 /// `AndroidAudioStreamSourceGenerator` is a struct that implements [`StreamSourceGenerator`]
427 /// for `AndroidAudioStreamSource`.
428 impl StreamSourceGenerator for AndroidAudioStreamSourceGenerator {
generate(&self) -> Result<Box<dyn StreamSource>, BoxError>429     fn generate(&self) -> Result<Box<dyn StreamSource>, BoxError> {
430         Ok(Box::new(AndroidAudioStreamSource))
431     }
432 }
433