]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
Implement SDL2 AUDIO_F32 format and use it as the default, since it has become the...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 26 May 2019 03:04:36 +0000 (03:04 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Sun, 26 May 2019 03:04:36 +0000 (03:04 +0000)
Improved the fallback mechanism on SDL2 audio setup - by removing it; SDL2 will tell us what changes it makes for the format, and it will convert the rest automatically.

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@12476 d7cf8633-e32d-0410-b094-e92efae38249

snd_main.c
snd_main.h
snd_mem.c
snd_mix.c
snd_sdl.c

index 53e63d5202eb4344b138c639231a32385fdb7f92..b61a9d3cee365fc351b42ab298b8d3988c3dce64 100644 (file)
@@ -237,10 +237,10 @@ static cvar_t ambient_fade = {0, "ambient_fade", "100", "rate of volume fading w
 static cvar_t snd_noextraupdate = {0, "snd_noextraupdate", "0", "disables extra sound mixer calls that are meant to reduce the chance of sound breakup at very low framerates"};
 static cvar_t snd_show = {0, "snd_show", "0", "shows some statistics about sound mixing"};
 
-// Default sound format is 48KHz, 16-bit, stereo
+// Default sound format is 48KHz, 32bit float, stereo
 // (48KHz because a lot of onboard sound cards sucks at any other speed)
 static cvar_t snd_speed = {CVAR_SAVE, "snd_speed", "48000", "sound output frequency, in hertz"};
-static cvar_t snd_width = {CVAR_SAVE, "snd_width", "2", "sound output precision, in bytes (1 and 2 supported)"};
+static cvar_t snd_width = {CVAR_SAVE, "snd_width", "4", "sound output precision, in bytes - 1 = 8bit, 2 = 16bit, 4 = 32bit float"};
 static cvar_t snd_channels = {CVAR_SAVE, "snd_channels", "2", "number of channels for the sound output (2 for stereo; up to 8 supported for 3D sound)"};
 
 static cvar_t snd_startloopingsounds = {0, "snd_startloopingsounds", "1", "whether to start sounds that would loop (you want this to be 1); existing sounds are not affected"};
@@ -371,77 +371,6 @@ int S_GetSoundChannels(void)
 }
 
 
-static qboolean S_ChooseCheaperFormat (snd_format_t* format, qboolean fixed_speed, qboolean fixed_width, qboolean fixed_channels)
-{
-       static const snd_format_t thresholds [] =
-       {
-               // speed                        width                   channels
-               { SND_MIN_SPEED,        SND_MIN_WIDTH,  SND_MIN_CHANNELS },
-               { 11025,                        1,                              2 },
-               { 22050,                        2,                              2 },
-               { 44100,                        2,                              2 },
-               { 48000,                        2,                              6 },
-               { 96000,                        2,                              6 },
-               { SND_MAX_SPEED,        SND_MAX_WIDTH,  SND_MAX_CHANNELS },
-       };
-       const unsigned int nb_thresholds = sizeof(thresholds) / sizeof(thresholds[0]);
-       unsigned int speed_level, width_level, channels_level;
-
-       // If we have reached the minimum values, there's nothing more we can do
-       if ((format->speed == thresholds[0].speed || fixed_speed) &&
-               (format->width == thresholds[0].width || fixed_width) &&
-               (format->channels == thresholds[0].channels || fixed_channels))
-               return false;
-
-       // Check the min and max values
-       #define CHECK_BOUNDARIES(param)                                                         \
-       if (format->param < thresholds[0].param)                                        \
-       {                                                                                                                       \
-               format->param = thresholds[0].param;                                    \
-               return true;                                                                                    \
-       }                                                                                                                       \
-       if (format->param > thresholds[nb_thresholds - 1].param)        \
-       {                                                                                                                       \
-               format->param = thresholds[nb_thresholds - 1].param;    \
-               return true;                                                                                    \
-       }
-       CHECK_BOUNDARIES(speed);
-       CHECK_BOUNDARIES(width);
-       CHECK_BOUNDARIES(channels);
-       #undef CHECK_BOUNDARIES
-
-       // Find the level of each parameter
-       #define FIND_LEVEL(param)                                                                       \
-       param##_level = 0;                                                                                      \
-       while (param##_level < nb_thresholds - 1)                                       \
-       {                                                                                                                       \
-               if (format->param <= thresholds[param##_level].param)   \
-                       break;                                                                                          \
-                                                                                                                               \
-               param##_level++;                                                                                \
-       }
-       FIND_LEVEL(speed);
-       FIND_LEVEL(width);
-       FIND_LEVEL(channels);
-       #undef FIND_LEVEL
-
-       // Decrease the parameter with the highest level to the previous level
-       if (channels_level >= speed_level && channels_level >= width_level && !fixed_channels)
-       {
-               format->channels = thresholds[channels_level - 1].channels;
-               return true;
-       }
-       if (speed_level >= width_level && !fixed_speed)
-       {
-               format->speed = thresholds[speed_level - 1].speed;
-               return true;
-       }
-
-       format->width = thresholds[width_level - 1].width;
-       return true;
-}
-
-
 #define SWAP_LISTENERS(l1, l2, tmpl) { tmpl = (l1); (l1) = (l2); (l2) = tmpl; }
 
 static void S_SetChannelLayout (void)
@@ -615,7 +544,7 @@ void S_Startup (void)
                chosen_fmt.speed = atoi (com_argv[i + 1]);
                fixed_speed = true;
        }
-// COMMANDLINEOPTION: Sound: -sndbits <bits> chooses 8 bit or 16 bit sound output
+// COMMANDLINEOPTION: Sound: -sndbits <bits> chooses 8 bit or 16 bit or 32bit float sound output
        i = COM_CheckParm ("-sndbits");
        if (0 < i && i < com_argc - 1)
        {
@@ -655,6 +584,11 @@ void S_Startup (void)
                chosen_fmt.width = SND_MIN_WIDTH;
                fixed_width = false;
        }
+    else if (chosen_fmt.width == 3)
+       {
+               chosen_fmt.width = 4;
+               fixed_width = false;
+       }
        else if (chosen_fmt.width > SND_MAX_WIDTH)
        {
                chosen_fmt.width = SND_MAX_WIDTH;
@@ -675,39 +609,12 @@ void S_Startup (void)
        // create the sound buffer used for sumitting the samples to the plaform-dependent module
        if (!simsound)
        {
-               snd_format_t suggest_fmt;
-               qboolean accepted;
-
-               accepted = false;
-               do
-               {
-                       Con_Printf("S_Startup: initializing sound output format: %dHz, %d bit, %d channels...\n",
-                                               chosen_fmt.speed, chosen_fmt.width * 8,
-                                               chosen_fmt.channels);
-
-                       memset(&suggest_fmt, 0, sizeof(suggest_fmt));
-                       accepted = SndSys_Init(&chosen_fmt, &suggest_fmt);
-
-                       if (!accepted)
-                       {
-                               Con_Printf("S_Startup: sound output initialization FAILED\n");
-
-                               // If the module is suggesting another one
-                               if (suggest_fmt.speed != 0)
-                               {
-                                       memcpy(&chosen_fmt, &suggest_fmt, sizeof(chosen_fmt));
-                                       Con_Printf ("           Driver has suggested %dHz, %d bit, %d channels. Retrying...\n",
-                                                               suggest_fmt.speed, suggest_fmt.width * 8,
-                                                               suggest_fmt.channels);
-                               }
-                               // Else, try to find a less resource-demanding format
-                               else if (!S_ChooseCheaperFormat (&chosen_fmt, fixed_speed, fixed_width, fixed_channels))
-                                       break;
-                       }
-               } while (!accepted);
+               Con_Printf("S_Startup: initializing sound output format: %dHz, %d bit, %d channels...\n",
+                                       chosen_fmt.speed,
+                                       chosen_fmt.width,
+                                       chosen_fmt.channels);
 
-               // If we haven't found a suitable format
-               if (!accepted)
+               if (!SndSys_Init(&chosen_fmt))
                {
                        Con_Print("S_Startup: SndSys_Init failed.\n");
                        sound_spatialized = false;
index 527ce49fc4241b5c6b1343dd1ac247af56a56fcf..5a07d72b8483dbc3ca0be8e3d4b6411806b97997 100644 (file)
@@ -153,9 +153,6 @@ void S_MixToBuffer(void *stream, unsigned int frames);
 
 qboolean S_LoadSound (sfx_t *sfx, qboolean complain);
 
-snd_buffer_t *Snd_CreateSndBuffer (const unsigned char *samples, unsigned int sampleframes, const snd_format_t* in_format, unsigned int sb_speed);
-qboolean Snd_AppendToSndBuffer (snd_buffer_t* sb, const unsigned char *samples, unsigned int sampleframes, const snd_format_t* format);
-
 // If "buffer" is NULL, the function allocates one buffer of "sampleframes" sample frames itself
 // (if "sampleframes" is 0, the function chooses the size).
 snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int sampleframes, void* buffer);
@@ -165,9 +162,9 @@ snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int
 //         Architecture-dependent functions
 // ====================================================================
 
-// Create "snd_renderbuffer" with the proper sound format if the call is successful
-// May return a suggested format if the requested format isn't available
-qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested);
+// Create "snd_renderbuffer", attempting to use the chosen sound format, but accepting if the driver wants to change it (e.g. 7.1 to stereo or lowering the speed)
+// Note: SDL automatically converts all formats, so this only fails if there is no audio
+qboolean SndSys_Init (snd_format_t* fmt);
 
 // Stop the sound card, delete "snd_renderbuffer" and free its other resources
 void SndSys_Shutdown (void);
index f6f9c145d85c073cf9aa2421f5cdab6d3dc17068..1098c2b67a817b0ec09c139b636ad42449b7590e 100644 (file)
--- a/snd_mem.c
+++ b/snd_mem.c
@@ -71,229 +71,6 @@ snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int
 }
 
 
-/*
-====================
-Snd_CreateSndBuffer
-====================
-*/
-snd_buffer_t *Snd_CreateSndBuffer (const unsigned char *samples, unsigned int sampleframes, const snd_format_t* in_format, unsigned int sb_speed)
-{
-       size_t newsampleframes, memsize;
-       snd_buffer_t* sb;
-
-       newsampleframes = (size_t) ceil((double)sampleframes * (double)sb_speed / (double)in_format->speed);
-
-       memsize = newsampleframes * in_format->channels * in_format->width;
-       memsize += sizeof (*sb) - sizeof (sb->samples);
-
-       sb = (snd_buffer_t*)Mem_Alloc (snd_mempool, memsize);
-       sb->format.channels = in_format->channels;
-       sb->format.width = in_format->width;
-       sb->format.speed = sb_speed;
-       sb->maxframes = (unsigned int)newsampleframes;
-       sb->nbframes = 0;
-
-       if (!Snd_AppendToSndBuffer (sb, samples, sampleframes, in_format))
-       {
-               Mem_Free (sb);
-               return NULL;
-       }
-
-       return sb;
-}
-
-
-/*
-====================
-Snd_AppendToSndBuffer
-====================
-*/
-qboolean Snd_AppendToSndBuffer (snd_buffer_t* sb, const unsigned char *samples, unsigned int sampleframes, const snd_format_t* format)
-{
-       size_t srclength, outcount;
-       unsigned char *out_data;
-
-       //Con_DPrintf("ResampleSfx: %d samples @ %dHz -> %d samples @ %dHz\n",
-       //                      sampleframes, format->speed, outcount, sb->format.speed);
-
-       // If the formats are incompatible
-       if (sb->format.channels != format->channels || sb->format.width != format->width)
-       {
-               Con_Print("AppendToSndBuffer: incompatible sound formats!\n");
-               return false;
-       }
-
-       outcount = (size_t) ((double)sampleframes * (double)sb->format.speed / (double)format->speed);
-
-       // If the sound buffer is too short
-       if (outcount > sb->maxframes - sb->nbframes)
-       {
-               Con_Print("AppendToSndBuffer: sound buffer too short!\n");
-               return false;
-       }
-
-       out_data = &sb->samples[sb->nbframes * sb->format.width * sb->format.channels];
-       srclength = sampleframes * format->channels;
-
-       // Trivial case (direct transfer)
-       if (format->speed == sb->format.speed)
-       {
-               if (format->width == 1)
-               {
-                       size_t i;
-
-                       for (i = 0; i < srclength; i++)
-                               ((signed char*)out_data)[i] = samples[i] - 128;
-               }
-               else  // if (format->width == 2)
-                       memcpy (out_data, samples, srclength * format->width);
-       }
-
-       // General case (linear interpolation with a fixed-point fractional
-       // step, 18-bit integer part and 14-bit fractional part)
-       // Can handle up to 2^18 (262144) samples per second (> 96KHz stereo)
-#      define FRACTIONAL_BITS 14
-#      define FRACTIONAL_MASK ((1 << FRACTIONAL_BITS) - 1)
-#      define INTEGER_BITS (sizeof(samplefrac)*8 - FRACTIONAL_BITS)
-       else
-       {
-               const unsigned int fracstep = (unsigned int)((double)format->speed / sb->format.speed * (1 << FRACTIONAL_BITS));
-               size_t remain_in = srclength, total_out = 0;
-               unsigned int samplefrac;
-               const unsigned char *in_ptr = samples;
-               unsigned char *out_ptr = out_data;
-
-               // Check that we can handle one second of that sound
-               if (format->speed * format->channels > (1 << INTEGER_BITS))
-               {
-                       Con_Printf ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))\n",
-                                          format->speed, format->channels);
-                       return 0;
-               }
-
-               // We work 1 sec at a time to make sure we don't accumulate any
-               // significant error when adding "fracstep" over several seconds, and
-               // also to be able to handle very long sounds.
-               while (total_out < outcount)
-               {
-                       size_t tmpcount, interpolation_limit, i, j;
-                       unsigned int srcsample;
-
-                       samplefrac = 0;
-
-                       // If more than 1 sec of sound remains to be converted
-                       if (outcount - total_out > sb->format.speed)
-                       {
-                               tmpcount = sb->format.speed;
-                               interpolation_limit = tmpcount;  // all samples can be interpolated
-                       }
-                       else
-                       {
-                               tmpcount = outcount - total_out;
-                               interpolation_limit = (int)ceil((double)(((remain_in / format->channels) - 1) << FRACTIONAL_BITS) / fracstep);
-                               if (interpolation_limit > tmpcount)
-                                       interpolation_limit = tmpcount;
-                       }
-
-                       // 16 bit samples
-                       if (format->width == 2)
-                       {
-                               const short* in_ptr_short;
-
-                               // Interpolated part
-                               for (i = 0; i < interpolation_limit; i++)
-                               {
-                                       srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
-                                       in_ptr_short = &((const short*)in_ptr)[srcsample];
-
-                                       for (j = 0; j < format->channels; j++)
-                                       {
-                                               int a, b;
-
-                                               a = *in_ptr_short;
-                                               b = *(in_ptr_short + format->channels);
-                                               *((short*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
-
-                                               in_ptr_short++;
-                                               out_ptr += sizeof (short);
-                                       }
-
-                                       samplefrac += fracstep;
-                               }
-
-                               // Non-interpolated part
-                               for (/* nothing */; i < tmpcount; i++)
-                               {
-                                       srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
-                                       in_ptr_short = &((const short*)in_ptr)[srcsample];
-
-                                       for (j = 0; j < format->channels; j++)
-                                       {
-                                               *((short*)out_ptr) = *in_ptr_short;
-
-                                               in_ptr_short++;
-                                               out_ptr += sizeof (short);
-                                       }
-
-                                       samplefrac += fracstep;
-                               }
-                       }
-                       // 8 bit samples
-                       else  // if (format->width == 1)
-                       {
-                               const unsigned char* in_ptr_byte;
-
-                               // Convert up to 1 sec of sound
-                               for (i = 0; i < interpolation_limit; i++)
-                               {
-                                       srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
-                                       in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
-
-                                       for (j = 0; j < format->channels; j++)
-                                       {
-                                               int a, b;
-
-                                               a = *in_ptr_byte - 128;
-                                               b = *(in_ptr_byte + format->channels) - 128;
-                                               *((signed char*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
-
-                                               in_ptr_byte++;
-                                               out_ptr += sizeof (signed char);
-                                       }
-
-                                       samplefrac += fracstep;
-                               }
-
-                               // Non-interpolated part
-                               for (/* nothing */; i < tmpcount; i++)
-                               {
-                                       srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
-                                       in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
-
-                                       for (j = 0; j < format->channels; j++)
-                                       {
-                                               *((signed char*)out_ptr) = *in_ptr_byte - 128;
-
-                                               in_ptr_byte++;
-                                               out_ptr += sizeof (signed char);
-                                       }
-
-                                       samplefrac += fracstep;
-                               }
-                       }
-
-                       // Update the counters and the buffer position
-                       remain_in -= format->speed * format->channels;
-                       in_ptr += format->speed * format->channels * format->width;
-                       total_out += tmpcount;
-               }
-       }
-
-       sb->nbframes += (unsigned int)outcount;
-       return true;
-}
-
-
 //=============================================================================
 
 /*
index 10da40047ec05355f7ccf85eff87d7b1a115344f..4ed38a88b633fde65875389fb622340cc3d4b12a 100644 (file)
--- a/snd_mix.c
+++ b/snd_mix.c
@@ -29,7 +29,7 @@ static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
 extern speakerlayout_t snd_speakerlayout; // for querying the listeners
 
 #ifdef CONFIG_VIDEO_CAPTURE
-static void S_CaptureAVISound(const portable_sampleframe_t *paintbuffer, size_t length)
+static void S_CaptureAVISound(const portable_sampleframe_t *sampleframes, size_t length)
 {
        size_t i;
        unsigned int j;
@@ -42,7 +42,7 @@ static void S_CaptureAVISound(const portable_sampleframe_t *paintbuffer, size_t
        {
                unsigned int j0 = snd_speakerlayout.listeners[j].channel_unswapped;
                for(i = 0; i < length; ++i)
-                       paintbuffer_unswapped[i].sample[j0] = paintbuffer[i].sample[j];
+                       paintbuffer_unswapped[i].sample[j0] = sampleframes[i].sample[j];
        }
 
        SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
@@ -127,11 +127,67 @@ static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbfra
 
 static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int nchannels)
 {
-       int i, val;
+       int i;
+       if (width == 4)  // 32bit float
+       {
+               float *snd_out = (float*)rb_ptr;
+               if (nchannels == 8)  // 7.1 surround
+               {
+                       for (i = 0; i < nbframes; i++, painted_ptr++)
+                       {
+                               *snd_out++ = painted_ptr->sample[0];
+                               *snd_out++ = painted_ptr->sample[1];
+                               *snd_out++ = painted_ptr->sample[2];
+                               *snd_out++ = painted_ptr->sample[3];
+                               *snd_out++ = painted_ptr->sample[4];
+                               *snd_out++ = painted_ptr->sample[5];
+                               *snd_out++ = painted_ptr->sample[6];
+                               *snd_out++ = painted_ptr->sample[7];
+                       }
+               }
+               else if (nchannels == 6)  // 5.1 surround
+               {
+                       for (i = 0; i < nbframes; i++, painted_ptr++)
+                       {
+                               *snd_out++ = painted_ptr->sample[0];
+                               *snd_out++ = painted_ptr->sample[1];
+                               *snd_out++ = painted_ptr->sample[2];
+                               *snd_out++ = painted_ptr->sample[3];
+                               *snd_out++ = painted_ptr->sample[4];
+                               *snd_out++ = painted_ptr->sample[5];
+                       }
+               }
+               else if (nchannels == 4)  // 4.0 surround
+               {
+                       for (i = 0; i < nbframes; i++, painted_ptr++)
+                       {
+                               *snd_out++ = painted_ptr->sample[0];
+                               *snd_out++ = painted_ptr->sample[1];
+                               *snd_out++ = painted_ptr->sample[2];
+                               *snd_out++ = painted_ptr->sample[3];
+                       }
+               }
+               else if (nchannels == 2)  // 2.0 stereo
+               {
+                       for (i = 0; i < nbframes; i++, painted_ptr++)
+                       {
+                               *snd_out++ = painted_ptr->sample[0];
+                               *snd_out++ = painted_ptr->sample[1];
+                       }
+               }
+               else if (nchannels == 1)  // 1.0 mono
+               {
+                       for (i = 0; i < nbframes; i++, painted_ptr++)
+                       {
+                               *snd_out++ = painted_ptr->sample[0];
+                       }
+               }
 
-       // FIXME: add 24bit and 32bit float formats
-       // FIXME: optimize with SSE intrinsics?
-       if (width == 2)  // 16bit
+               // noise is really really annoying
+               if (cls.timedemo)
+                       memset(rb_ptr, 0, nbframes * nchannels * width);
+       }
+       else if (width == 2)  // 16bit
        {
                short *snd_out = (short*)rb_ptr;
                if (nchannels == 8)  // 7.1 surround
index 21341dce883a6c111b502a2a91113ce9a13b99e8..850ca773e4d4054ecdb56bc94e15401ce2d11a55 100644 (file)
--- a/snd_sdl.c
+++ b/snd_sdl.c
@@ -92,7 +92,7 @@ Create "snd_renderbuffer" with the proper sound format if the call is successful
 May return a suggested format if the requested format isn't available
 ====================
 */
-qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
+qboolean SndSys_Init (snd_format_t* fmt)
 {
        unsigned int buffersize;
        SDL_AudioSpec wantspec;
@@ -108,14 +108,15 @@ qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
                return false;
        }
 
-       buffersize = (unsigned int)ceil((double)requested->speed / 25.0); // 2048 bytes on 24kHz to 48kHz
+       buffersize = (unsigned int)ceil((double)fmt->speed / 25.0); // 2048 bytes on 24kHz to 48kHz
 
        // Init the SDL Audio subsystem
+       memset(&wantspec, 0, sizeof(wantspec));
        wantspec.callback = Buffer_Callback;
        wantspec.userdata = NULL;
-       wantspec.freq = requested->speed;
-       wantspec.format = ((requested->width == 1) ? AUDIO_U8 : AUDIO_S16SYS);
-       wantspec.channels = requested->channels;
+       wantspec.freq = fmt->speed;
+       wantspec.format = fmt->width == 1 ? AUDIO_U8 : (fmt->width == 2 ? AUDIO_S16SYS : AUDIO_F32);
+       wantspec.channels = fmt->channels;
        wantspec.samples = CeilPowerOf2(buffersize);  // needs to be a power of 2 on some platforms.
 
        Con_Printf("Wanted audio Specification:\n"
@@ -125,7 +126,7 @@ qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
                                "\tSamples   : %i\n",
                                wantspec.channels, wantspec.format, wantspec.freq, wantspec.samples);
 
-       if ((audio_device = SDL_OpenAudioDevice(NULL, 0, &wantspec, &obtainspec, 0)) == 0)
+       if ((audio_device = SDL_OpenAudioDevice(NULL, 0, &wantspec, &obtainspec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE)) == 0)
        {
                Con_Printf( "Failed to open the audio device! (%s)\n", SDL_GetError() );
                return false;
@@ -138,28 +139,12 @@ qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
                                "\tSamples   : %i\n",
                                obtainspec.channels, obtainspec.format, obtainspec.freq, obtainspec.samples);
 
-       // If we haven't obtained what we wanted
-       if (wantspec.freq != obtainspec.freq ||
-               wantspec.format != obtainspec.format ||
-               wantspec.channels != obtainspec.channels)
-       {
-               SDL_CloseAudioDevice(audio_device);
-
-               // Pass the obtained format as a suggested format
-               if (suggested != NULL)
-               {
-                       suggested->speed = obtainspec.freq;
-                       // FIXME: check the format more carefully. There are plenty of unsupported cases
-                       suggested->width = ((obtainspec.format == AUDIO_U8) ? 1 : 2);
-                       suggested->channels = obtainspec.channels;
-               }
-
-               return false;
-       }
+       fmt->speed = obtainspec.freq;
+       fmt->channels = obtainspec.channels;
 
        snd_threaded = true;
 
-       snd_renderbuffer = Snd_CreateRingBuffer(requested, 0, NULL);
+       snd_renderbuffer = Snd_CreateRingBuffer(fmt, 0, NULL);
        if (snd_channellayout.integer == SND_CHANNELLAYOUT_AUTO)
                Cvar_SetValueQuick (&snd_channellayout, SND_CHANNELLAYOUT_STANDARD);