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.
* **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
driver is forced, regardless if supported by SDL or the platform or
not. By default set to `directsound` under Windows and `auto` on all
other platforms.
to `auto` (the defailt), SDL chooses the driver. If set to anything
else the given driver is forced, regardless if supported by SDL or the
platform or not.
* **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 sndfreq = (Cvar_Get("s_khz", "44", 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));
#endif
if (strcmp(s_sdldriver->string, "auto") != 0)
{
@ -1502,8 +1497,7 @@ qboolean
SDL_BackendInit(void)
{
char reqdriver[128];
SDL_AudioSpec desired;
SDL_AudioSpec obtained;
SDL_AudioSpec spec;
int tmp, val;
/* This should never happen,
@ -1516,12 +1510,7 @@ SDL_BackendInit(void)
int sndbits = (Cvar_Get("sndbits", "16", CVAR_ARCHIVE))->value;
int sndfreq = (Cvar_Get("s_khz", "44", 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));
#endif
if (strcmp(s_sdldriver->string, "auto") != 0)
{
@ -1547,8 +1536,7 @@ SDL_BackendInit(void)
Com_Printf("SDL audio driver is \"%s\".\n", drivername);
memset(&desired, '\0', sizeof(desired));
memset(&obtained, '\0', sizeof(obtained));
memset(&spec, '\0', sizeof(spec));
/* Users are stupid */
if ((sndbits != 16) && (sndbits != 8))
@ -1558,45 +1546,45 @@ SDL_BackendInit(void)
if (sndfreq == 48)
{
desired.freq = 48000;
spec.freq = 48000;
}
else if (sndfreq == 44)
{
desired.freq = 44100;
spec.freq = 44100;
}
else if (sndfreq == 22)
{
desired.freq = 22050;
spec.freq = 22050;
}
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
{
desired.samples = 2048;
spec.samples = 2048;
}
desired.channels = sndchans;
desired.callback = SDL_Callback;
spec.channels = sndchans;
spec.callback = SDL_Callback;
/* 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());
SDL_QuitSubSystem(SDL_INIT_AUDIO);
@ -1607,10 +1595,10 @@ SDL_BackendInit(void)
backend = &sound;
playpos = 0;
backend->samplebits = obtained.format & 0xFF;
backend->channels = obtained.channels;
backend->samplebits = spec.format & 0xFF;
backend->channels = spec.channels;
tmp = (obtained.samples * obtained.channels) * 10;
tmp = (spec.samples * spec.channels) * 10;
if (tmp & (tmp - 1))
{ /* make it a power of two */
@ -1624,7 +1612,7 @@ SDL_BackendInit(void)
backend->samples = tmp;
backend->submission_chunk = 1;
backend->speed = obtained.freq;
backend->speed = spec.freq;
samplesize = (backend->samples * (backend->samplebits / 8));
backend->buffer = calloc(1, samplesize);
s_numchannels = MAX_CHANNELS;