1#[cfg(feature = "libaaudio_stub")]
6mod libaaudio_stub;
7
8use std::os::raw::c_void;
9use std::time::Duration;
10use std::time::Instant;
11
12use async_trait::async_trait;
13use audio_streams::capture::AsyncCaptureBuffer;
14use audio_streams::capture::AsyncCaptureBufferStream;
15use audio_streams::capture::CaptureBuffer;
16use audio_streams::capture::CaptureBufferStream;
17use audio_streams::AsyncBufferCommit;
18use audio_streams::AsyncPlaybackBuffer;
19use audio_streams::AsyncPlaybackBufferStream;
20use audio_streams::AudioStreamsExecutor;
21use audio_streams::BoxError;
22use audio_streams::BufferCommit;
23use audio_streams::NoopStreamControl;
24use audio_streams::PlaybackBuffer;
25use audio_streams::PlaybackBufferStream;
26use audio_streams::SampleFormat;
27use audio_streams::StreamControl;
28use audio_streams::StreamEffect;
29use audio_streams::StreamSource;
30use audio_streams::StreamSourceGenerator;
31use base::warn;
32use thiserror::Error;
33
34#[derive(Clone, Copy)]
35enum AndroidAudioStreamDirection {
36 Input = 1,
37 Output = 0,
38}
39
40#[derive(Error, Debug)]
41pub 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#[repr(C)]
54struct AAudioStream {
55 _data: [u8; 0],
56 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
57}
58
59#[repr(C)]
61struct AAudioStreamBuilder {
62 _data: [u8; 0],
63 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
64}
65
66type AaudioFormatT = i32;
67type AaudioResultT = i32;
68const AAUDIO_OK: AaudioResultT = 0;
69
70extern "C" {
71 fn AAudio_createStreamBuilder(builder: *mut *mut AAudioStreamBuilder) -> AaudioResultT;
72 fn AAudioStreamBuilder_delete(builder: *mut AAudioStreamBuilder) -> AaudioResultT;
73 fn AAudioStreamBuilder_setBufferCapacityInFrames(
74 builder: *mut AAudioStreamBuilder,
75 num_frames: i32,
76 );
77 fn AAudioStreamBuilder_setDirection(builder: *mut AAudioStreamBuilder, direction: u32);
78 fn AAudioStreamBuilder_setFormat(builder: *mut AAudioStreamBuilder, format: AaudioFormatT);
79 fn AAudioStreamBuilder_setSampleRate(builder: *mut AAudioStreamBuilder, sample_rate: i32);
80 fn AAudioStreamBuilder_setChannelCount(builder: *mut AAudioStreamBuilder, channel_count: i32);
81 fn AAudioStreamBuilder_openStream(
82 builder: *mut AAudioStreamBuilder,
83 stream: *mut *mut AAudioStream,
84 ) -> AaudioResultT;
85 fn AAudioStream_getBufferSizeInFrames(stream: *mut AAudioStream) -> i32;
86 fn AAudioStream_requestStart(stream: *mut AAudioStream) -> AaudioResultT;
87 fn AAudioStream_read(
88 stream: *mut AAudioStream,
89 buffer: *mut c_void,
90 num_frames: i32,
91 timeout_nanoseconds: i64,
92 ) -> AaudioResultT;
93 fn AAudioStream_write(
94 stream: *mut AAudioStream,
95 buffer: *const c_void,
96 num_frames: i32,
97 timeout_nanoseconds: i64,
98 ) -> AaudioResultT;
99 fn AAudioStream_close(stream: *mut AAudioStream) -> AaudioResultT;
100}
101
102struct AAudioStreamPtr {
103 stream_ptr: *mut AAudioStream,
106}
107
108unsafe impl Send for AndroidAudioStreamCommit {}
112
113struct 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
125struct AndroidAudioStreamCommit {
126 buffer_ptr: *const u8,
127 stream: AAudioStreamPtr,
128 direction: AndroidAudioStreamDirection,
129}
130
131impl BufferCommit for AndroidAudioStreamCommit {
132 fn commit(&mut self, _nwritten: usize) {
133 unimplemented!();
135 }
136}
137
138#[async_trait(?Send)]
139impl AsyncBufferCommit for AndroidAudioStreamCommit {
140 async fn commit(&mut self, nwritten: usize) {
141 match self.direction {
142 AndroidAudioStreamDirection::Input => {}
143 AndroidAudioStreamDirection::Output => {
144 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, )
155 };
156 if frames_written < 0 {
157 warn!("AAudio stream write failed.");
158 } else if (frames_written as usize) < nwritten {
159 warn!(
161 "Android Audio Stream: Drop {} frames",
162 nwritten - (frames_written as usize)
163 );
164 }
165 }
166 }
167 }
168}
169
170impl AudioStream {
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 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 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
229impl PlaybackBufferStream for AudioStream {
230 fn next_playback_buffer<'b, 's: 'b>(&'s mut self) -> Result<PlaybackBuffer<'b>, BoxError> {
231 unimplemented!();
233 }
234}
235
236#[async_trait(?Send)]
237impl AsyncPlaybackBufferStream for AudioStream {
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)]
265impl CaptureBufferStream for AudioStream {
266 fn next_capture_buffer<'b, 's: 'b>(&'s mut self) -> Result<CaptureBuffer<'b>, BoxError> {
267 unimplemented!()
269 }
270}
271
272#[async_trait(?Send)]
273impl AsyncCaptureBufferStream for AudioStream {
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 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 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
336impl Drop for AAudioStreamPtr {
337 fn drop(&mut self) {
338 if unsafe { AAudioStream_close(self.stream_ptr) } != AAUDIO_OK {
342 warn!("AAudio stream close failed.");
343 }
344 }
345}
346
347#[derive(Default)]
348struct AndroidAudioStreamSource;
349
350impl StreamSource for AndroidAudioStreamSource {
351 #[allow(clippy::type_complexity)]
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 unimplemented!();
361 }
362
363 #[allow(clippy::type_complexity)]
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)]
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 unimplemented!();
393 }
394
395 #[allow(clippy::type_complexity)]
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)]
418pub struct AndroidAudioStreamSourceGenerator;
419
420impl AndroidAudioStreamSourceGenerator {
421 pub fn new() -> Self {
422 AndroidAudioStreamSourceGenerator {}
423 }
424}
425
426impl StreamSourceGenerator for AndroidAudioStreamSourceGenerator {
429 fn generate(&self) -> Result<Box<dyn StreamSource>, BoxError> {
430 Ok(Box::new(AndroidAudioStreamSource))
431 }
432}