From 044046bc50b45c3b9ed0c00b772f48fa3918ab77 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" 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 f6bdfc83a1..d5475bbd84 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 284a718241..6800317156 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