diff --git a/src/audio/wasapi/SDL_wasapi.c b/src/audio/wasapi/SDL_wasapi.c index 2ef4de82fe..bdbbf81772 100644 --- a/src/audio/wasapi/SDL_wasapi.c +++ b/src/audio/wasapi/SDL_wasapi.c @@ -64,6 +64,19 @@ static const IID SDL_IID_IAudioClient3 = { 0x7ed4ee07, 0x8e67, 0x4cd4, { 0x8c, 0 static bool immdevice_initialized = false; static bool supports_recording_on_playback_devices = false; +#ifdef __IAudioClient2_INTERFACE_DEFINED__ +#define SDL_AUDCLNT_STREAMOPTIONS_RAW 0x1 +typedef union SDL_AudioClientProperties { + AudioClientProperties a; + struct _SDL_AudioClientProperties { + UINT32 cbSize; + BOOL bIsOffload; + AUDIO_STREAM_CATEGORY eCategory; + int Options; // AUDCLNT_STREAMOPTIONS + } s; +} SDL_AudioClientProperties; +#endif // + // WASAPI is _really_ particular about various things happening on the same thread, for COM and such, // so we proxy various stuff to a single background thread to manage. @@ -741,10 +754,10 @@ static bool mgmtthrtask_PrepDevice(void *userdata) IAudioClient2 *client2 = NULL; ret = IAudioClient_QueryInterface(client, &SDL_IID_IAudioClient2, (void **)&client2); if (SUCCEEDED(ret)) { - AudioClientProperties audioProps; + SDL_AudioClientProperties audioProps; SDL_zero(audioProps); - audioProps.cbSize = sizeof(audioProps); + audioProps.a.cbSize = sizeof(audioProps); // Setting AudioCategory_GameChat breaks audio on several devices, including Behringer U-PHORIA UM2 and RODE NT-USB Mini. // We'll disable this for now until we understand more about what's happening. @@ -752,25 +765,28 @@ static bool mgmtthrtask_PrepDevice(void *userdata) const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_ROLE); if (hint && *hint) { if (SDL_strcasecmp(hint, "Communications") == 0) { - audioProps.eCategory = AudioCategory_Communications; + audioProps.a.eCategory = AudioCategory_Communications; } else if (SDL_strcasecmp(hint, "Game") == 0) { // We'll add support for GameEffects as distinct from GameMedia later when we add stream roles - audioProps.eCategory = AudioCategory_GameEffects; + audioProps.a.eCategory = AudioCategory_GameEffects; } else if (SDL_strcasecmp(hint, "GameChat") == 0) { - audioProps.eCategory = AudioCategory_GameChat; + audioProps.a.eCategory = AudioCategory_GameChat; } else if (SDL_strcasecmp(hint, "Movie") == 0) { - audioProps.eCategory = AudioCategory_Movie; + audioProps.a.eCategory = AudioCategory_Movie; } else if (SDL_strcasecmp(hint, "Media") == 0) { - audioProps.eCategory = AudioCategory_Media; + audioProps.a.eCategory = AudioCategory_Media; } } #endif - if (SDL_GetHintBoolean(SDL_HINT_AUDIO_DEVICE_RAW_STREAM, false)) { - audioProps.Options = AUDCLNT_STREAMOPTIONS_RAW; + if (WIN_IsWindows81OrGreater() && + SDL_GetHintBoolean(SDL_HINT_AUDIO_DEVICE_RAW_STREAM, false)) { + audioProps.s.Options = SDL_AUDCLNT_STREAMOPTIONS_RAW; + } else { + audioProps.a.cbSize = sizeof (AudioClientProperties); } - ret = IAudioClient2_SetClientProperties(client2, &audioProps); + ret = IAudioClient2_SetClientProperties(client2, (AudioClientProperties *)&audioProps); if (FAILED(ret)) { // This isn't fatal, let's log it instead of failing SDL_LogWarn(SDL_LOG_CATEGORY_AUDIO, "IAudioClient2_SetClientProperties failed: 0x%" SDL_PRIxSLONG, ret); diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c index eaedd59e96..0be19bd2ec 100644 --- a/src/core/windows/SDL_windows.c +++ b/src/core/windows/SDL_windows.c @@ -374,6 +374,11 @@ BOOL WIN_IsWindows8OrGreater(void) CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0)); } +BOOL WIN_IsWindows81OrGreater(void) +{ + CHECKWINVER(TRUE, IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0)); +} + BOOL WIN_IsWindows11OrGreater(void) { return IsWindowsBuildVersionAtLeast(22000); diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index 62c1c3a9af..0a7c785493 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -193,6 +193,9 @@ extern BOOL WIN_IsWindows7OrGreater(void); // Returns true if we're running on Windows 8 and newer extern BOOL WIN_IsWindows8OrGreater(void); +// Returns true if we're running on Windows 8.1 and newer +extern BOOL WIN_IsWindows81OrGreater(void); + // Returns true if we're running on Windows 11 and newer extern BOOL WIN_IsWindows11OrGreater(void);