Switch the SDL2 sound backend to transparent audio format conversion.

Since the SDL 1.2 day the SDL sound backend relied on the sound driver
supporting the requested audio format. That workes fine for drivers
support transparent conversions into formats supported by the hardware.
But it failes with drivers which are unable to do such conversions. As
long as we hardcoded the sound driver this wasn't a problem, because all
our chouces supported transparent conversions. When we removed the
hardcoded choices and started to rely on SDLs choices especially the
wsaapi driver - which is SDLs default choice under windows - failed.
wsaapi only guarantees support for AUDIO_F32LSB (other formats may be
supported, depending on the hardware), Quake II needs AUDIO_S16SYS or
AUDIO_U8.

Solve this by switching to transparent conversions through SDL. This way
Quake II can send whatever it wants to SDL and SDL will make sure that
it is in the right format before sending it to the driver.

This isn't necessary for SDL3, SDL3 doesn't support explicit formats and
always relies on transparent conversions.

Remove hardcoded wsaapi on Windows, it's no longer necessary.

Part of #1135.
This commit is contained in:
Yamagi 2024-09-08 09:57:38 +02:00
parent 5ba7695d64
commit a969526d87
2 changed files with 24 additions and 37 deletions

View file

@ -301,10 +301,9 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable`
modern systems like Windows 10 or Linux with PulseAudio. modern systems like Windows 10 or Linux with PulseAudio.
* **s_sdldriver**: Can be set to the name of a SDL audio driver. If set * **s_sdldriver**: Can be set to the name of a SDL audio driver. If set
to `auto`, SDL chooses the driver. If set to anything else the given to `auto` (the defailt), SDL chooses the driver. If set to anything
driver is forced, regardless if supported by SDL or the platform or else the given driver is forced, regardless if supported by SDL or the
not. By default set to `directsound` under Windows and `auto` on all platform or not.
other platforms.
* **s_underwater**: Dampen sounds if submerged. Enabled by default. * **s_underwater**: Dampen sounds if submerged. Enabled by default.

View file

@ -1350,12 +1350,7 @@ SDL_BackendInit(void)
int sndbits = (Cvar_Get("sndbits", "16", CVAR_ARCHIVE))->value; int sndbits = (Cvar_Get("sndbits", "16", CVAR_ARCHIVE))->value;
int sndfreq = (Cvar_Get("s_khz", "44", CVAR_ARCHIVE))->value; int sndfreq = (Cvar_Get("s_khz", "44", CVAR_ARCHIVE))->value;
int sndchans = (Cvar_Get("sndchannels", "2", CVAR_ARCHIVE))->value; int sndchans = (Cvar_Get("sndchannels", "2", CVAR_ARCHIVE))->value;
#if _WIN32
cvar_t *s_sdldriver = (Cvar_Get("s_sdldriver", "directsound", CVAR_ARCHIVE));
#else
cvar_t *s_sdldriver = (Cvar_Get("s_sdldriver", "auto", CVAR_ARCHIVE)); cvar_t *s_sdldriver = (Cvar_Get("s_sdldriver", "auto", CVAR_ARCHIVE));
#endif
if (strcmp(s_sdldriver->string, "auto") != 0) if (strcmp(s_sdldriver->string, "auto") != 0)
{ {
@ -1502,8 +1497,7 @@ qboolean
SDL_BackendInit(void) SDL_BackendInit(void)
{ {
char reqdriver[128]; char reqdriver[128];
SDL_AudioSpec desired; SDL_AudioSpec spec;
SDL_AudioSpec obtained;
int tmp, val; int tmp, val;
/* This should never happen, /* This should never happen,
@ -1516,12 +1510,7 @@ SDL_BackendInit(void)
int sndbits = (Cvar_Get("sndbits", "16", CVAR_ARCHIVE))->value; int sndbits = (Cvar_Get("sndbits", "16", CVAR_ARCHIVE))->value;
int sndfreq = (Cvar_Get("s_khz", "44", CVAR_ARCHIVE))->value; int sndfreq = (Cvar_Get("s_khz", "44", CVAR_ARCHIVE))->value;
int sndchans = (Cvar_Get("sndchannels", "2", CVAR_ARCHIVE))->value; int sndchans = (Cvar_Get("sndchannels", "2", CVAR_ARCHIVE))->value;
#if _WIN32
cvar_t *s_sdldriver = (Cvar_Get("s_sdldriver", "directsound", CVAR_ARCHIVE));
#else
cvar_t *s_sdldriver = (Cvar_Get("s_sdldriver", "auto", CVAR_ARCHIVE)); cvar_t *s_sdldriver = (Cvar_Get("s_sdldriver", "auto", CVAR_ARCHIVE));
#endif
if (strcmp(s_sdldriver->string, "auto") != 0) if (strcmp(s_sdldriver->string, "auto") != 0)
{ {
@ -1547,8 +1536,7 @@ SDL_BackendInit(void)
Com_Printf("SDL audio driver is \"%s\".\n", drivername); Com_Printf("SDL audio driver is \"%s\".\n", drivername);
memset(&desired, '\0', sizeof(desired)); memset(&spec, '\0', sizeof(spec));
memset(&obtained, '\0', sizeof(obtained));
/* Users are stupid */ /* Users are stupid */
if ((sndbits != 16) && (sndbits != 8)) if ((sndbits != 16) && (sndbits != 8))
@ -1558,45 +1546,45 @@ SDL_BackendInit(void)
if (sndfreq == 48) if (sndfreq == 48)
{ {
desired.freq = 48000; spec.freq = 48000;
} }
else if (sndfreq == 44) else if (sndfreq == 44)
{ {
desired.freq = 44100; spec.freq = 44100;
} }
else if (sndfreq == 22) else if (sndfreq == 22)
{ {
desired.freq = 22050; spec.freq = 22050;
} }
else if (sndfreq == 11) else if (sndfreq == 11)
{ {
desired.freq = 11025; spec.freq = 11025;
} }
desired.format = ((sndbits == 16) ? AUDIO_S16SYS : AUDIO_U8); spec.format = ((sndbits == 16) ? AUDIO_S16SYS : AUDIO_U8);
if (desired.freq <= 11025) if (spec.freq <= 11025)
{ {
desired.samples = 256; spec.samples = 256;
} }
else if (desired.freq <= 22050) else if (spec.freq <= 22050)
{ {
desired.samples = 512; spec.samples = 512;
} }
else if (desired.freq <= 44100) else if (spec.freq <= 44100)
{ {
desired.samples = 1024; spec.samples = 1024;
} }
else else
{ {
desired.samples = 2048; spec.samples = 2048;
} }
desired.channels = sndchans; spec.channels = sndchans;
desired.callback = SDL_Callback; spec.callback = SDL_Callback;
/* Okay, let's try our luck */ /* Okay, let's try our luck */
if (SDL_OpenAudio(&desired, &obtained) == -1) if (SDL_OpenAudio(&spec, NULL) == -1)
{ {
Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError()); Com_Printf("SDL_OpenAudio() failed: %s\n", SDL_GetError());
SDL_QuitSubSystem(SDL_INIT_AUDIO); SDL_QuitSubSystem(SDL_INIT_AUDIO);
@ -1607,10 +1595,10 @@ SDL_BackendInit(void)
backend = &sound; backend = &sound;
playpos = 0; playpos = 0;
backend->samplebits = obtained.format & 0xFF; backend->samplebits = spec.format & 0xFF;
backend->channels = obtained.channels; backend->channels = spec.channels;
tmp = (obtained.samples * obtained.channels) * 10; tmp = (spec.samples * spec.channels) * 10;
if (tmp & (tmp - 1)) if (tmp & (tmp - 1))
{ /* make it a power of two */ { /* make it a power of two */
@ -1624,7 +1612,7 @@ SDL_BackendInit(void)
backend->samples = tmp; backend->samples = tmp;
backend->submission_chunk = 1; backend->submission_chunk = 1;
backend->speed = obtained.freq; backend->speed = spec.freq;
samplesize = (backend->samples * (backend->samplebits / 8)); samplesize = (backend->samples * (backend->samplebits / 8));
backend->buffer = calloc(1, samplesize); backend->buffer = calloc(1, samplesize);
s_numchannels = MAX_CHANNELS; s_numchannels = MAX_CHANNELS;