diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index dda63d0f55..78cf3f4c85 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -432,7 +432,11 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) BYTE *buffer = NULL; if (device->hidden->render) { - if (WasapiFailed(device, IAudioRenderClient_GetBuffer(device->hidden->render, device->sample_frames, &buffer))) { + const HRESULT ret = IAudioRenderClient_GetBuffer(device->hidden->render, device->sample_frames, &buffer); + if (ret == AUDCLNT_E_BUFFER_TOO_LARGE) { + SDL_assert(buffer == NULL); + *buffer_size = 0; // just go back to WaitDevice and try again after the hardware has consumed some more data. + } else if (WasapiFailed(device, ret)) { SDL_assert(buffer == NULL); if (device->hidden->device_lost) { // just use an available buffer, we won't be playing it anyhow. *buffer_size = 0; // we'll recover during WaitDevice and try again. @@ -642,11 +646,16 @@ static int mgmtthrtask_PrepDevice(void *userdata) return WIN_SetErrorFromHRESULT("WASAPI can't determine buffer size", ret); } - /* Match the callback size to the period size to cut down on the number of - interrupts waited for in each call to WaitDevice */ + // Match the callback size to the period size to cut down on the number of + // interrupts waited for in each call to WaitDevice const float period_millis = default_period / 10000.0f; const float period_frames = period_millis * newspec.freq / 1000.0f; - const int new_sample_frames = (int) SDL_ceilf(period_frames); + int new_sample_frames = (int) SDL_ceilf(period_frames); + + // regardless of what we calculated for the period size, clamp it to the expected hardware buffer size. + if (new_sample_frames > (int) bufsize) { + new_sample_frames = (int) bufsize; + } // Update the fragment size as size in bytes if (SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames) < 0) {