Skip to content

Commit a81cf56

Browse files
committed
wasapi: Force enumerated audio devices to report themselves as float32 format.
This is what they'll end up being when used through WASAPI in shared mode, regardless of what the hardware actually expects. Reference Issue #12914.
1 parent 92e8224 commit a81cf56

File tree

4 files changed

+16
-12
lines changed

4 files changed

+16
-12
lines changed

src/audio/directsound/SDL_directsound.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDe
206206
{
207207
#ifdef HAVE_MMDEVICEAPI_H
208208
if (SupportsIMMDevice) {
209-
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording);
209+
SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording, SDL_AUDIO_UNKNOWN);
210210
} else
211211
#endif
212212
{

src/audio/wasapi/SDL_wasapi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ typedef struct
337337
static bool mgmtthrtask_DetectDevices(void *userdata)
338338
{
339339
mgmtthrtask_DetectDevicesData *data = (mgmtthrtask_DetectDevicesData *)userdata;
340-
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording);
340+
SDL_IMMDevice_EnumerateEndpoints(data->default_playback, data->default_recording, SDL_AUDIO_F32);
341341
return true;
342342
}
343343

src/core/windows/SDL_immdevice.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device)
120120
}
121121
}
122122

123-
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid)
123+
static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid, SDL_AudioFormat force_format)
124124
{
125125
/* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever).
126126
In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for
@@ -162,7 +162,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devn
162162
SDL_zero(spec);
163163
spec.channels = (Uint8)fmt->Format.nChannels;
164164
spec.freq = fmt->Format.nSamplesPerSec;
165-
spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
165+
spec.format = (force_format != SDL_AUDIO_UNKNOWN) ? force_format : SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt);
166166

167167
device = SDL_AddAudioDevice(recording, devname, &spec, handle);
168168
if (!device) {
@@ -183,6 +183,7 @@ typedef struct SDLMMNotificationClient
183183
{
184184
const IMMNotificationClientVtbl *lpVtbl;
185185
SDL_AtomicInt refcount;
186+
SDL_AudioFormat force_format;
186187
} SDLMMNotificationClient;
187188

188189
static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_QueryInterface(IMMNotificationClient *client, REFIID iid, void **ppv)
@@ -241,6 +242,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceRemoved(IMMNoti
241242

242243
static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IMMNotificationClient *iclient, LPCWSTR pwstrDeviceId, DWORD dwNewState)
243244
{
245+
SDLMMNotificationClient *client = (SDLMMNotificationClient *)iclient;
244246
IMMDevice *device = NULL;
245247

246248
if (SUCCEEDED(IMMDeviceEnumerator_GetDevice(enumerator, pwstrDeviceId, &device))) {
@@ -255,7 +257,7 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM
255257
GUID dsoundguid;
256258
GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid);
257259
if (utf8dev) {
258-
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid);
260+
SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid, client->force_format);
259261
SDL_free(utf8dev);
260262
}
261263
} else {
@@ -286,7 +288,7 @@ static const IMMNotificationClientVtbl notification_client_vtbl = {
286288
SDLMMNotificationClient_OnPropertyValueChanged
287289
};
288290

289-
static SDLMMNotificationClient notification_client = { &notification_client_vtbl, { 1 } };
291+
static SDLMMNotificationClient notification_client = { &notification_client_vtbl, { 1 }, SDL_AUDIO_UNKNOWN };
290292

291293
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks)
292294
{
@@ -363,7 +365,7 @@ bool SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, bool reco
363365
return true;
364366
}
365367

366-
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device)
368+
static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device, SDL_AudioFormat force_format)
367369
{
368370
/* Note that WASAPI separates "adapter devices" from "audio endpoint devices"
369371
...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */
@@ -405,7 +407,7 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
405407
SDL_zero(dsoundguid);
406408
GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid);
407409
if (devname) {
408-
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid);
410+
SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid, force_format);
409411
if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) {
410412
*default_device = sdldevice;
411413
}
@@ -422,10 +424,12 @@ static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **de
422424
IMMDeviceCollection_Release(collection);
423425
}
424426

425-
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording)
427+
void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording, SDL_AudioFormat force_format)
426428
{
427-
EnumerateEndpointsForFlow(false, default_playback);
428-
EnumerateEndpointsForFlow(true, default_recording);
429+
EnumerateEndpointsForFlow(false, default_playback, force_format);
430+
EnumerateEndpointsForFlow(true, default_recording, force_format);
431+
432+
notification_client.force_format = force_format;
429433

430434
// if this fails, we just won't get hotplug events. Carry on anyhow.
431435
IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)&notification_client);

src/core/windows/SDL_immdevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ typedef struct SDL_IMMDevice_callbacks
3737
bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks);
3838
void SDL_IMMDevice_Quit(void);
3939
bool SDL_IMMDevice_Get(struct SDL_AudioDevice *device, IMMDevice **immdevice, bool recording);
40-
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording);
40+
void SDL_IMMDevice_EnumerateEndpoints(struct SDL_AudioDevice **default_playback, struct SDL_AudioDevice **default_recording, SDL_AudioFormat force_format);
4141
LPGUID SDL_IMMDevice_GetDirectSoundGUID(struct SDL_AudioDevice *device);
4242
LPCWSTR SDL_IMMDevice_GetDevID(struct SDL_AudioDevice *device);
4343
void SDL_IMMDevice_FreeDeviceHandle(struct SDL_AudioDevice *device);

0 commit comments

Comments
 (0)