From 806e11ac005752c5628e394fac225806ac6d00ba Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sat, 30 Sep 2023 15:04:21 -0700
Subject: [PATCH] Update sample processing bookkeeping when recovering the
AAudio audio device
---
src/audio/aaudio/SDL_aaudio.c | 73 +++++++++++++++++------------------
1 file changed, 36 insertions(+), 37 deletions(-)
diff --git a/src/audio/aaudio/SDL_aaudio.c b/src/audio/aaudio/SDL_aaudio.c
index 5b4e6efb7248..4ea18c8afc0f 100644
--- a/src/audio/aaudio/SDL_aaudio.c
+++ b/src/audio/aaudio/SDL_aaudio.c
@@ -171,48 +171,40 @@ static void AAUDIO_WaitDevice(SDL_AudioDevice *device)
static int BuildAAudioStream(SDL_AudioDevice *device);
-static int RecoverAAudioDeviceIfFailed(SDL_AudioDevice *device)
+static int RecoverAAudioDevice(SDL_AudioDevice *device)
{
struct SDL_PrivateAudioData *hidden = device->hidden;
- const aaudio_result_t err = (aaudio_result_t) SDL_AtomicGet(&hidden->error_callback_triggered);
- if (err) {
- SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "aaudio: Audio device triggered error %d (%s)", (int) err, ctx.AAudio_convertResultToText(err));
- // attempt to build a new stream, in case there's a new default device.
- ctx.AAudioStream_requestStop(hidden->stream);
- ctx.AAudioStream_close(hidden->stream);
- hidden->stream = NULL;
+ // attempt to build a new stream, in case there's a new default device.
+ ctx.AAudioStream_requestStop(hidden->stream);
+ ctx.AAudioStream_close(hidden->stream);
+ hidden->stream = NULL;
- SDL_aligned_free(hidden->mixbuf);
- hidden->mixbuf = NULL;
+ SDL_aligned_free(hidden->mixbuf);
+ hidden->mixbuf = NULL;
- SDL_DestroySemaphore(hidden->semaphore);
- hidden->semaphore = NULL;
+ SDL_DestroySemaphore(hidden->semaphore);
+ hidden->semaphore = NULL;
- const int prev_sample_frames = device->sample_frames;
- SDL_AudioSpec prevspec;
- SDL_copyp(&prevspec, &device->spec);
+ const int prev_sample_frames = device->sample_frames;
+ SDL_AudioSpec prevspec;
+ SDL_copyp(&prevspec, &device->spec);
- if (BuildAAudioStream(device) == -1) {
- return -1; // oh well, we tried.
- }
-
- // we don't know the new device spec until we open the new device, so we saved off the old one and force it back
- // so SDL_AudioDeviceFormatChanged can set up all the important state if necessary and then set it back to the new spec.
- const int new_sample_frames = device->sample_frames;
- SDL_AudioSpec newspec;
- SDL_copyp(&newspec, &device->spec);
+ if (BuildAAudioStream(device) < 0) {
+ return -1; // oh well, we tried.
+ }
- device->sample_frames = prev_sample_frames;
- SDL_copyp(&device->spec, &prevspec);
- if (SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames) == -1) {
- return -1; // ugh
- }
+ // we don't know the new device spec until we open the new device, so we saved off the old one and force it back
+ // so SDL_AudioDeviceFormatChanged can set up all the important state if necessary and then set it back to the new spec.
+ const int new_sample_frames = device->sample_frames;
+ SDL_AudioSpec newspec;
+ SDL_copyp(&newspec, &device->spec);
- // we're recovering from PlayDevice, so wait until the data callback fires so we know we fed the pending buffer to the device.
- SDL_WaitSemaphore(device->hidden->semaphore);
+ device->sample_frames = prev_sample_frames;
+ SDL_copyp(&device->spec, &prevspec);
+ if (SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames) < 0) {
+ return -1; // ugh
}
-
return 0;
}
@@ -222,12 +214,17 @@ static int AAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int b
struct SDL_PrivateAudioData *hidden = device->hidden;
// AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here.
- if (RecoverAAudioDeviceIfFailed(device) == -1) {
- return -1; // oh well, we went down hard.
- }
+ const aaudio_result_t err = (aaudio_result_t) SDL_AtomicGet(&hidden->error_callback_triggered);
+ if (err) {
+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "aaudio: Audio device triggered error %d (%s)", (int) err, ctx.AAudio_convertResultToText(err));
- SDL_MemoryBarrierRelease();
- hidden->processed_bytes += buflen;
+ if (RecoverAAudioDevice(device) < 0) {
+ return -1; // oh well, we went down hard.
+ }
+ } else {
+ SDL_MemoryBarrierRelease();
+ hidden->processed_bytes += buflen;
+ }
return 0;
}
@@ -358,6 +355,8 @@ static int BuildAAudioStream(SDL_AudioDevice *device)
if (hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
+ hidden->processed_bytes = 0;
+ hidden->callback_bytes = 0;
hidden->semaphore = SDL_CreateSemaphore(iscapture ? 0 : hidden->num_buffers);
if (!hidden->semaphore) {