From 044046bc50b45c3b9ed0c00b772f48fa3918ab77 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 11 Oct 2023 10:37:28 -0400
Subject: [PATCH] audio: Fixed assertions when capture devices have wrong audio
formats.
Fixes #8376.
---
src/audio/SDL_audio.c | 44 ++++++++++++++++++++++++++--------------
src/audio/SDL_sysaudio.h | 2 ++
2 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c
index f6bdfc83a1fa..d5475bbd8476 100644
--- a/src/audio/SDL_audio.c
+++ b/src/audio/SDL_audio.c
@@ -189,23 +189,25 @@ static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device)
// should hold device->lock before calling.
static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device)
{
- const SDL_bool iscapture = device->iscapture;
- const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device);
- SDL_AudioSpec spec;
+ if (!device->iscapture) { // for capture devices, we only want to move to float32 for postmix, which we'll handle elsewhere.
+ const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device);
+ SDL_AudioSpec spec;
- device->simple_copy = simple_copy;
- SDL_copyp(&spec, &device->spec);
- if (!simple_copy) {
- spec.format = SDL_AUDIO_F32; // mixing and postbuf operates in float32 format.
- }
+ device->simple_copy = simple_copy;
+ SDL_copyp(&spec, &device->spec);
- for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) {
- for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) {
- // set the proper end of the stream to the device's format.
- // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec.
- SDL_LockMutex(stream->lock);
- SDL_copyp(iscapture ? &stream->src_spec : &stream->dst_spec, &spec);
- SDL_UnlockMutex(stream->lock);
+ if (!simple_copy) {
+ spec.format = SDL_AUDIO_F32; // mixing and postbuf operates in float32 format.
+ }
+
+ for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev != NULL; logdev = logdev->next) {
+ for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) {
+ // set the proper end of the stream to the device's format.
+ // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec.
+ SDL_LockMutex(stream->lock);
+ SDL_copyp(&stream->dst_spec, &spec);
+ SDL_UnlockMutex(stream->lock);
+ }
}
}
}
@@ -1567,6 +1569,16 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac
if (retval == 0) {
logdev->postmix = callback;
logdev->postmix_userdata = userdata;
+
+ if (device->iscapture) {
+ for (SDL_AudioStream *stream = logdev->bound_streams; stream != NULL; stream = stream->next_binding) {
+ // set the proper end of the stream to the device's format.
+ // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec.
+ SDL_LockMutex(stream->lock);
+ stream->src_spec.format = callback ? SDL_AUDIO_F32 : device->spec.format;
+ SDL_UnlockMutex(stream->lock);
+ }
+ }
}
UpdateAudioStreamFormatsPhysical(device);
@@ -1639,6 +1651,8 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int
}
logdev->bound_streams = stream;
+ stream->src_spec.format = logdev->postmix ? SDL_AUDIO_F32 : device->spec.format;
+
SDL_UnlockMutex(stream->lock);
}
}
diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h
index 284a718241ac..68003171563e 100644
--- a/src/audio/SDL_sysaudio.h
+++ b/src/audio/SDL_sysaudio.h
@@ -156,6 +156,8 @@ typedef struct SDL_AudioDriver
SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams.
SDL_AudioDeviceID default_output_device_id;
SDL_AudioDeviceID default_capture_device_id;
+
+ // !!! FIXME: most (all?) of these don't have to be atomic.
SDL_AtomicInt output_device_count;
SDL_AtomicInt capture_device_count;
SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs