audio: Clean up some CloseDevice() interface details.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 05 Aug 2016 01:44:41 -0400
changeset 10237 9530fc07da6c
parent 10236 c2730130a448
child 10238 620329de23d4
audio: Clean up some CloseDevice() interface details. - It's now always called if device->hidden isn't NULL, even if OpenDevice() failed halfway through. This lets implementation code not have to clean up itself on every possible failure point; just return an error and SDL will handle it for you. - Implementations can assume this->hidden != NULL and not check for it. - implementations don't have to set this->hidden = NULL when done, because the caller is always about to free(this). - Don't reset other fields that are in a block of memory about to be free()'d. - Implementations all now free things like internal mix buffers last, after closing devices and such, to guarantee they definitely aren't in use anymore at the point of deallocation.
src/audio/SDL_audio.c
src/audio/SDL_sysaudio.h
src/audio/alsa/SDL_alsa_audio.c
src/audio/android/SDL_androidaudio.c
src/audio/arts/SDL_artsaudio.c
src/audio/bsd/SDL_bsdaudio.c
src/audio/coreaudio/SDL_coreaudio.c
src/audio/directsound/SDL_directsound.c
src/audio/disk/SDL_diskaudio.c
src/audio/dsp/SDL_dspaudio.c
src/audio/emscripten/SDL_emscriptenaudio.c
src/audio/esd/SDL_esdaudio.c
src/audio/fusionsound/SDL_fsaudio.c
src/audio/haiku/SDL_haikuaudio.cc
src/audio/nacl/SDL_naclaudio.c
src/audio/nas/SDL_nasaudio.c
src/audio/paudio/SDL_paudio.c
src/audio/psp/SDL_pspaudio.c
src/audio/pulseaudio/SDL_pulseaudio.c
src/audio/qsa/SDL_qsa_audio.c
src/audio/sndio/SDL_sndioaudio.c
src/audio/sun/SDL_sunaudio.c
src/audio/winmm/SDL_winmm.c
src/audio/xaudio2/SDL_xaudio2.c
--- a/src/audio/SDL_audio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/SDL_audio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -982,9 +982,8 @@
     if (device->convert.needed) {
         SDL_FreeAudioMem(device->convert.buf);
     }
-    if (device->opened) {
+    if (device->hidden != NULL) {
         current_audio.impl.CloseDevice(device);
-        device->opened = SDL_FALSE;
     }
 
     free_audio_queue(device->buffer_queue_head);
@@ -1193,7 +1192,10 @@
         close_audio_device(device);
         return 0;
     }
-    device->opened = SDL_TRUE;
+
+    /* if your target really doesn't need it, set it to 0x1 or something. */
+    /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
+    SDL_assert(device->hidden != NULL);
 
     /* See if we need to do any conversion */
     build_cvt = SDL_FALSE;
--- a/src/audio/SDL_sysaudio.h	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/SDL_sysaudio.h	Fri Aug 05 01:44:41 2016 -0400
@@ -162,7 +162,6 @@
     SDL_atomic_t shutdown; /* true if we are signaling the play thread to end. */
     SDL_atomic_t enabled;  /* true if device is functioning and connected. */
     SDL_atomic_t paused;
-    SDL_bool opened;
     SDL_bool iscapture;
 
     /* Fake audio buffer for when the audio hardware is busy */
--- a/src/audio/alsa/SDL_alsa_audio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/alsa/SDL_alsa_audio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -402,17 +402,12 @@
 static void
 ALSA_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->pcm_handle) {
-            ALSA_snd_pcm_drain(this->hidden->pcm_handle);
-            ALSA_snd_pcm_close(this->hidden->pcm_handle);
-            this->hidden->pcm_handle = NULL;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->pcm_handle) {
+        ALSA_snd_pcm_drain(this->hidden->pcm_handle);
+        ALSA_snd_pcm_close(this->hidden->pcm_handle);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -555,7 +550,6 @@
                 SND_PCM_NONBLOCK);
 
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't open audio device: %s",
                             ALSA_snd_strerror(status));
     }
@@ -566,7 +560,6 @@
     snd_pcm_hw_params_alloca(&hwparams);
     status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't get hardware config: %s",
                             ALSA_snd_strerror(status));
     }
@@ -575,7 +568,6 @@
     status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
                                                SND_PCM_ACCESS_RW_INTERLEAVED);
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't set interleaved access: %s",
                      ALSA_snd_strerror(status));
     }
@@ -629,7 +621,6 @@
         }
     }
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't find any hardware audio formats");
     }
     this->spec.format = test_format;
@@ -641,7 +632,6 @@
     if (status < 0) {
         status = ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels);
         if (status < 0) {
-            ALSA_CloseDevice(this);
             return SDL_SetError("ALSA: Couldn't set audio channels");
         }
         this->spec.channels = channels;
@@ -652,7 +642,6 @@
     status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
                                                   &rate, NULL);
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't set audio frequency: %s",
                             ALSA_snd_strerror(status));
     }
@@ -664,7 +653,6 @@
         /* Failed to set desired buffer size, do the best you can... */
         status = ALSA_set_period_size(this, hwparams, 1);
         if (status < 0) {
-            ALSA_CloseDevice(this);
             return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
         }
     }
@@ -672,26 +660,22 @@
     snd_pcm_sw_params_alloca(&swparams);
     status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't get software config: %s",
                             ALSA_snd_strerror(status));
     }
     status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, this->spec.samples);
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("Couldn't set minimum available samples: %s",
                             ALSA_snd_strerror(status));
     }
     status =
         ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1);
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't set start threshold: %s",
                             ALSA_snd_strerror(status));
     }
     status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("Couldn't set software audio parameters: %s",
                             ALSA_snd_strerror(status));
     }
@@ -704,7 +688,6 @@
         this->hidden->mixlen = this->spec.size;
         this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
         if (this->hidden->mixbuf == NULL) {
-            ALSA_CloseDevice(this);
             return SDL_OutOfMemory();
         }
         SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
--- a/src/audio/android/SDL_androidaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/android/SDL_androidaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -44,6 +44,7 @@
         return SDL_SetError("Capture not supported on Android");
     }
 
+    /* !!! FIXME: higher level will prevent this now. Lose this check (and global?). */
     if (audioDevice != NULL) {
         return SDL_SetError("Only one audio device at a time please!");
     }
@@ -115,10 +116,7 @@
     Android_JNI_CloseAudioDevice();
 
     if (audioDevice == this) {
-        if (audioDevice->hidden != NULL) {
-            SDL_free(this->hidden);
-            this->hidden = NULL;
-        }
+        SDL_free(this->hidden);
         audioDevice = NULL;
     }
 }
--- a/src/audio/arts/SDL_artsaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/arts/SDL_artsaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -203,17 +203,12 @@
 static void
 ARTS_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->stream) {
-            SDL_NAME(arts_close_stream) (this->hidden->stream);
-            this->hidden->stream = 0;
-        }
-        SDL_NAME(arts_free) ();
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->stream) {
+        SDL_NAME(arts_close_stream) (this->hidden->stream);
     }
+    SDL_NAME(arts_free) ();
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -267,19 +262,16 @@
         }
     }
     if (format == 0) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     this->spec.format = test_format;
 
     if ((rc = SDL_NAME(arts_init) ()) != 0) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("Unable to initialize ARTS: %s",
                             SDL_NAME(arts_error_text) (rc));
     }
 
     if (!ARTS_Suspend()) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("ARTS can not open audio device");
     }
 
@@ -297,7 +289,6 @@
     /* Determine the power of two of the fragment size */
     for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
     if ((0x01 << frag_spec) != this->spec.size) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("Fragment size must be a power of two");
     }
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
@@ -318,7 +309,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        ARTS_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
--- a/src/audio/bsd/SDL_bsdaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/bsd/SDL_bsdaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -268,16 +268,11 @@
 static void
 BSDAUDIO_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -319,7 +314,6 @@
     /* Set to play mode */
     info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
     if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
-        BSDAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't put device into play mode");
     }
 
@@ -361,7 +355,6 @@
     }
 
     if (!format) {
-        BSDAUDIO_CloseDevice(this);
         return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
     }
 
@@ -386,7 +379,6 @@
         this->hidden->mixlen = this->spec.size;
         this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
         if (this->hidden->mixbuf == NULL) {
-            BSDAUDIO_CloseDevice(this);
             return SDL_OutOfMemory();
         }
         SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
--- a/src/audio/coreaudio/SDL_coreaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/coreaudio/SDL_coreaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -22,6 +22,8 @@
 
 #if SDL_AUDIO_DRIVER_COREAUDIO
 
+/* !!! FIXME: clean out some of the macro salsa in here. */
+
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_sysaudio.h"
@@ -30,11 +32,8 @@
 
 #define DEBUG_COREAUDIO 0
 
-static void COREAUDIO_CloseDevice(_THIS);
-
 #define CHECK_RESULT(msg) \
     if (result != noErr) { \
-        COREAUDIO_CloseDevice(this); \
         SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
         return 0; \
     }
@@ -436,45 +435,39 @@
 static void
 COREAUDIO_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        const int iscapture = this->iscapture;
-        if (this->hidden->audioUnitOpened) {
-            #if MACOSX_COREAUDIO
-            /* Unregister our disconnect callback. */
-            AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
-            #endif
+    const int iscapture = this->iscapture;
+    if (this->hidden->audioUnitOpened) {
+        #if MACOSX_COREAUDIO
+        /* Unregister our disconnect callback. */
+        AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
+        #endif
 
-            AURenderCallbackStruct callback;
-            const AudioUnitElement output_bus = 0;
-            const AudioUnitElement input_bus = 1;
-            const AudioUnitElement bus =
-                ((iscapture) ? input_bus : output_bus);
+        AURenderCallbackStruct callback;
+        const AudioUnitElement output_bus = 0;
+        const AudioUnitElement input_bus = 1;
+        const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
 
-            /* stop processing the audio unit */
-            AudioOutputUnitStop(this->hidden->audioUnit);
+        /* stop processing the audio unit */
+        AudioOutputUnitStop(this->hidden->audioUnit);
 
-            /* Remove the input callback */
-            SDL_zero(callback);
-            AudioUnitSetProperty(this->hidden->audioUnit,
-                                 iscapture ? kAudioOutputUnitProperty_SetInputCallback : kAudioUnitProperty_SetRenderCallback,
-                                 kAudioUnitScope_Global, bus, &callback, sizeof(callback));
-            AudioComponentInstanceDispose(this->hidden->audioUnit);
-            this->hidden->audioUnitOpened = 0;
-
-            SDL_free(this->hidden->captureBufferList.mBuffers[0].mData);
+        /* Remove the input callback */
+        SDL_zero(callback);
+        AudioUnitSetProperty(this->hidden->audioUnit,
+                             iscapture ? kAudioOutputUnitProperty_SetInputCallback : kAudioUnitProperty_SetRenderCallback,
+                             kAudioUnitScope_Global, bus, &callback, sizeof(callback));
+        AudioComponentInstanceDispose(this->hidden->audioUnit);
+    }
 
-        }
-        SDL_free(this->hidden->buffer);
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    SDL_free(this->hidden->captureBufferList.mBuffers[0].mData);
+    SDL_free(this->hidden->buffer);
+    SDL_free(this->hidden);
 
-        if (iscapture) {
-            open_capture_devices--;
-        } else {
-            open_playback_devices--;
-        }
-        update_audio_session();
+    if (iscapture) {
+        open_capture_devices--;
+    } else {
+        open_playback_devices--;
     }
+    update_audio_session();
 }
 
 #if MACOSX_COREAUDIO
@@ -623,7 +616,6 @@
         framesize *= SDL_AUDIO_BITSIZE(this->spec.format) / 8;
         ptr = SDL_calloc(1, framesize);
         if (ptr == NULL) {
-            COREAUDIO_CloseDevice(this);
             SDL_OutOfMemory();
             return 0;
         }
@@ -655,7 +647,6 @@
 
     this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
     if (this->hidden->buffer == NULL) {
-        COREAUDIO_CloseDevice(this);
         SDL_OutOfMemory();
         return 0;
     }
@@ -737,7 +728,6 @@
     }
 
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
-        COREAUDIO_CloseDevice(this);
         return SDL_SetError("Unsupported audio format");
     }
 
@@ -747,7 +737,6 @@
         strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
 
     if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
-        COREAUDIO_CloseDevice(this);
         return -1;      /* prepare_audiounit() will call SDL_SetError()... */
     }
 
--- a/src/audio/directsound/SDL_directsound.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/directsound/SDL_directsound.c	Fri Aug 05 01:44:41 2016 -0400
@@ -322,20 +322,13 @@
 static void
 DSOUND_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        if (this->hidden->sound != NULL) {
-            if (this->hidden->mixbuf != NULL) {
-                /* Clean up the audio buffer */
-                IDirectSoundBuffer_Release(this->hidden->mixbuf);
-                this->hidden->mixbuf = NULL;
-            }
-            IDirectSound_Release(this->hidden->sound);
-            this->hidden->sound = NULL;
-        }
-
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->mixbuf != NULL) {
+        IDirectSoundBuffer_Release(this->hidden->mixbuf);
     }
+    if (this->hidden->sound != NULL) {
+        IDirectSound_Release(this->hidden->sound);
+    }
+    SDL_free(this->hidden);
 }
 
 /* This function tries to create a secondary audio buffer, and returns the
@@ -443,7 +436,6 @@
     /* Open the audio device */
     result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
     if (result != DS_OK) {
-        DSOUND_CloseDevice(this);
         return SetDSerror("DirectSoundCreate", result);
     }
 
@@ -465,7 +457,6 @@
     }
 
     if (!valid_format) {
-        DSOUND_CloseDevice(this);
         if (tried_format) {
             return -1;  /* CreateSecondary() should have called SDL_SetError(). */
         }
--- a/src/audio/disk/SDL_diskaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/disk/SDL_diskaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -87,16 +87,11 @@
 static void
 DISKAUD_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->output != NULL) {
-            SDL_RWclose(this->hidden->output);
-            this->hidden->output = NULL;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->output != NULL) {
+        SDL_RWclose(this->hidden->output);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -120,14 +115,12 @@
     /* Open the audio device */
     this->hidden->output = SDL_RWFromFile(fname, "wb");
     if (this->hidden->output == NULL) {
-        DISKAUD_CloseDevice(this);
         return -1;
     }
 
     /* Allocate mixing buffer */
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        DISKAUD_CloseDevice(this);
         return -1;
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
--- a/src/audio/dsp/SDL_dspaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/dsp/SDL_dspaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -60,16 +60,11 @@
 static void
 DSP_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 
@@ -111,7 +106,6 @@
     /* Open the audio device */
     this->hidden->audio_fd = open(devname, flags, 0);
     if (this->hidden->audio_fd < 0) {
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
     }
     this->hidden->mixbuf = NULL;
@@ -122,7 +116,6 @@
         ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
         ctlflags &= ~O_NONBLOCK;
         if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
-            DSP_CloseDevice(this);
             return SDL_SetError("Couldn't set audio blocking mode");
         }
     }
@@ -130,7 +123,6 @@
     /* Get a list of supported hardware formats */
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
         perror("SNDCTL_DSP_GETFMTS");
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't get audio format list");
     }
 
@@ -187,7 +179,6 @@
         }
     }
     if (format == 0) {
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     this->spec.format = test_format;
@@ -197,7 +188,6 @@
     if ((ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
         (value != format)) {
         perror("SNDCTL_DSP_SETFMT");
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't set audio format");
     }
 
@@ -205,7 +195,6 @@
     value = this->spec.channels;
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
         perror("SNDCTL_DSP_CHANNELS");
-        DSP_CloseDevice(this);
         return SDL_SetError("Cannot set the number of channels");
     }
     this->spec.channels = value;
@@ -214,7 +203,6 @@
     value = this->spec.freq;
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
         perror("SNDCTL_DSP_SPEED");
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't set audio frequency");
     }
     this->spec.freq = value;
@@ -225,7 +213,6 @@
     /* Determine the power of two of the fragment size */
     for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
     if ((0x01U << frag_spec) != this->spec.size) {
-        DSP_CloseDevice(this);
         return SDL_SetError("Fragment size must be a power of two");
     }
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
@@ -253,7 +240,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        DSP_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
--- a/src/audio/emscripten/SDL_emscriptenaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/emscripten/SDL_emscriptenaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -136,16 +136,8 @@
 static void
 Emscripten_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            /* Clean up the audio buffer */
-            SDL_free(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
-
-        SDL_free(this->hidden);
-        this->hidden = NULL;
-    }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
--- a/src/audio/esd/SDL_esdaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/esd/SDL_esdaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -174,17 +174,11 @@
 static void
 ESD_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            SDL_NAME(esd_close) (this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_fd >= 0) {
+        SDL_NAME(esd_close) (this->hidden->audio_fd);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 /* Try to get the name of the program */
@@ -252,7 +246,6 @@
     }
 
     if (!found) {
-        ESD_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
 
@@ -271,7 +264,6 @@
                                    get_progname());
 
     if (this->hidden->audio_fd < 0) {
-        ESD_CloseDevice(this);
         return SDL_SetError("Couldn't open ESD connection");
     }
 
@@ -285,7 +277,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        ESD_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
--- a/src/audio/fusionsound/SDL_fsaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/fusionsound/SDL_fsaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -22,6 +22,8 @@
 
 #if SDL_AUDIO_DRIVER_FUSIONSOUND
 
+/* !!! FIXME: why is this is SDL_FS_* instead of FUSIONSOUND_*? */
+
 /* Allow access to a raw mixing buffer */
 
 #ifdef HAVE_SIGNAL_H
@@ -168,20 +170,14 @@
 static void
 SDL_FS_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->stream) {
-            this->hidden->stream->Release(this->hidden->stream);
-            this->hidden->stream = NULL;
-        }
-        if (this->hidden->fs) {
-            this->hidden->fs->Release(this->hidden->fs);
-            this->hidden->fs = NULL;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->stream) {
+        this->hidden->stream->Release(this->hidden->stream);
     }
+    if (this->hidden->fs) {
+        this->hidden->fs->Release(this->hidden->fs);
+    }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 
@@ -239,7 +235,6 @@
     }
 
     if (format == 0) {
-        SDL_FS_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     this->spec.format = test_format;
@@ -247,7 +242,6 @@
     /* Retrieve the main sound interface. */
     ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
     if (ret) {
-        SDL_FS_CloseDevice(this);
         return SDL_SetError("Unable to initialize FusionSound: %d", ret);
     }
 
@@ -266,7 +260,6 @@
         this->hidden->fs->CreateStream(this->hidden->fs, &desc,
                                        &this->hidden->stream);
     if (ret) {
-        SDL_FS_CloseDevice(this);
         return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
     }
 
@@ -287,7 +280,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        SDL_FS_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
--- a/src/audio/haiku/SDL_haikuaudio.cc	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/haiku/SDL_haikuaudio.cc	Fri Aug 05 01:44:41 2016 -0400
@@ -74,16 +74,11 @@
 static void
 HAIKUAUDIO_CloseDevice(_THIS)
 {
-    if (_this->hidden != NULL) {
-        if (_this->hidden->audio_obj) {
-            _this->hidden->audio_obj->Stop();
-            delete _this->hidden->audio_obj;
-            _this->hidden->audio_obj = NULL;
-        }
-
-        delete _this->hidden;
-        _this->hidden = NULL;
+    if (_this->hidden->audio_obj) {
+        _this->hidden->audio_obj->Stop();
+        delete _this->hidden->audio_obj;
     }
+    delete _this->hidden;
 }
 
 
@@ -177,7 +172,6 @@
     }
 
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
-        HAIKUAUDIO_CloseDevice(_this);
         return SDL_SetError("Unsupported audio format");
     }
 
@@ -196,7 +190,6 @@
     if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
         _this->hidden->audio_obj->SetHasData(true);
     } else {
-        HAIKUAUDIO_CloseDevice(_this);
         return SDL_SetError("Unable to start Be audio");
     }
 
--- a/src/audio/nacl/SDL_naclaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/nacl/SDL_naclaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -43,8 +43,6 @@
 #define SAMPLE_FRAME_COUNT 4096
 
 /* Audio driver functions */
-static int NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture);
-static void NACLAUD_CloseDevice(_THIS);
 static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
 
 /* FIXME: Make use of latency if needed */
--- a/src/audio/nas/SDL_nasaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/nas/SDL_nasaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -190,16 +190,11 @@
 static void
 NAS_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->aud) {
-            NAS_AuCloseServer(this->hidden->aud);
-            this->hidden->aud = 0;
-        }
-        SDL_free(this->hidden);
-        this2 = this->hidden = NULL;
+    if (this->hidden->aud) {
+        NAS_AuCloseServer(this->hidden->aud);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static unsigned char
@@ -300,21 +295,18 @@
         }
     }
     if (format == 0) {
-        NAS_CloseDevice(this);
         return SDL_SetError("NAS: Couldn't find any hardware audio formats");
     }
     this->spec.format = test_format;
 
     this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
     if (this->hidden->aud == 0) {
-        NAS_CloseDevice(this);
         return SDL_SetError("NAS: Couldn't open connection to NAS server");
     }
 
     this->hidden->dev = find_device(this, this->spec.channels);
     if ((this->hidden->dev == AuNone)
         || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
-        NAS_CloseDevice(this);
         return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
     }
 
@@ -347,7 +339,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        NAS_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
--- a/src/audio/paudio/SDL_paudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/paudio/SDL_paudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -228,16 +228,11 @@
 static void
 PAUDIO_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -268,7 +263,6 @@
     fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
     this->hidden->audio_fd = fd;
     if (fd < 0) {
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
     }
 
@@ -277,7 +271,6 @@
      * that we can have.
      */
     if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't get audio buffer information");
     }
 
@@ -391,7 +384,6 @@
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Couldn't find any hardware audio formats\n");
 #endif
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     this->spec.format = test_format;
@@ -449,7 +441,6 @@
     }
 
     if (err != NULL) {
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Paudio: %s", err);
     }
 
@@ -457,7 +448,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        PAUDIO_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
@@ -492,7 +482,6 @@
     paud_control.ioctl_request = AUDIO_START;
     paud_control.position = 0;
     if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
-        PAUDIO_CloseDevice(this);
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Can't start audio play\n");
 #endif
--- a/src/audio/psp/SDL_pspaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/psp/SDL_pspaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -126,14 +126,11 @@
 {
     if (this->hidden->channel >= 0) {
         sceAudioChRelease(this->hidden->channel);
-        this->hidden->channel = -1;
     }
+    free(this->hidden->rawbuf);  /* this uses memalign(), not SDL_malloc(). */
+    SDL_free(this->hidden);
+}
 
-    if (this->hidden->rawbuf != NULL) {
-        free(this->hidden->rawbuf);
-        this->hidden->rawbuf = NULL;
-    }
-}
 static void PSPAUD_ThreadInit(_THIS)
 {
     /* Increase the priority of this audio thread by 1 to put it
@@ -151,7 +148,6 @@
 static int
 PSPAUD_Init(SDL_AudioDriverImpl * impl)
 {
-
     /* Set the function pointers */
     impl->OpenDevice = PSPAUD_OpenDevice;
     impl->PlayDevice = PSPAUD_PlayDevice;
--- a/src/audio/pulseaudio/SDL_pulseaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/pulseaudio/SDL_pulseaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -463,20 +463,18 @@
 static void
 PULSEAUDIO_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
+    if (this->hidden->stream) {
         if (this->hidden->capturebuf != NULL) {
             PULSEAUDIO_pa_stream_drop(this->hidden->stream);
         }
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        SDL_free(this->hidden->device_name);
-        if (this->hidden->stream) {
-            PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
-            PULSEAUDIO_pa_stream_unref(this->hidden->stream);
-        }
-        DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+        PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
+        PULSEAUDIO_pa_stream_unref(this->hidden->stream);
     }
+
+    DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden->device_name);
+    SDL_free(this->hidden);
 }
 
 static void
@@ -579,7 +577,6 @@
         }
     }
     if (paspec.format == PA_SAMPLE_INVALID) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     this->spec.format = test_format;
@@ -595,7 +592,6 @@
         h->mixlen = this->spec.size;
         h->mixbuf = (Uint8 *) SDL_AllocAudioMem(h->mixlen);
         if (h->mixbuf == NULL) {
-            PULSEAUDIO_CloseDevice(this);
             return SDL_OutOfMemory();
         }
         SDL_memset(h->mixbuf, this->spec.silence, this->spec.size);
@@ -621,12 +617,10 @@
 #endif
 
     if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Could not connect to PulseAudio server");
     }
 
     if (!FindDeviceName(h, iscapture, handle)) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Requested PulseAudio sink/source missing?");
     }
 
@@ -643,7 +637,6 @@
         );
 
     if (h->stream == NULL) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Could not set up PulseAudio stream");
     }
 
@@ -660,18 +653,15 @@
     }
 
     if (rc < 0) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Could not connect PulseAudio stream");
     }
 
     do {
         if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
-            PULSEAUDIO_CloseDevice(this);
             return SDL_SetError("pa_mainloop_iterate() failed");
         }
         state = PULSEAUDIO_pa_stream_get_state(h->stream);
         if (!PA_STREAM_IS_GOOD(state)) {
-            PULSEAUDIO_CloseDevice(this);
             return SDL_SetError("Could not connect PulseAudio stream");
         }
     } while (state != PA_STREAM_READY);
--- a/src/audio/qsa/SDL_qsa_audio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/qsa/SDL_qsa_audio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -322,27 +322,21 @@
 static void
 QSA_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        if (this->hidden->audio_handle != NULL) {
-            if (!this->hidden->iscapture) {
-                /* Finish playing available samples */
-                snd_pcm_plugin_flush(this->hidden->audio_handle,
-                                     SND_PCM_CHANNEL_PLAYBACK);
-            } else {
-                /* Cancel unread samples during capture */
-                snd_pcm_plugin_flush(this->hidden->audio_handle,
-                                     SND_PCM_CHANNEL_CAPTURE);
-            }
-            snd_pcm_close(this->hidden->audio_handle);
-            this->hidden->audio_handle = NULL;
+    if (this->hidden->audio_handle != NULL) {
+        if (!this->hidden->iscapture) {
+            /* Finish playing available samples */
+            snd_pcm_plugin_flush(this->hidden->audio_handle,
+                                 SND_PCM_CHANNEL_PLAYBACK);
+        } else {
+            /* Cancel unread samples during capture */
+            snd_pcm_plugin_flush(this->hidden->audio_handle,
+                                 SND_PCM_CHANNEL_CAPTURE);
         }
-
-        SDL_FreeAudioMem(this->hidden->pcm_buf);
-        this->hidden->pcm_buf = NULL;
+        snd_pcm_close(this->hidden->audio_handle);
+    }
 
-        SDL_free(this->hidden);
-        this->hidden = NULL;
-    }
+    SDL_FreeAudioMem(this->hidden->pcm_buf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -391,7 +385,6 @@
     /* Check if requested device is opened */
     if (status < 0) {
         this->hidden->audio_handle = NULL;
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_open", status);
     }
 
@@ -401,7 +394,6 @@
             snd_pcm_plugin_set_disable(this->hidden->audio_handle,
                                        PLUGIN_DISABLE_MMAP);
         if (status < 0) {
-            QSA_CloseDevice(this);
             return QSA_SetError("snd_pcm_plugin_set_disable", status);
         }
     }
@@ -487,7 +479,6 @@
 
     /* assumes test_format not 0 on success */
     if (test_format == 0) {
-        QSA_CloseDevice(this);
         return SDL_SetError("QSA: Couldn't find any hardware audio formats");
     }
 
@@ -505,7 +496,6 @@
     /* Setup the transfer parameters according to cparams */
     status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
     if (status < 0) {
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_channel_params", status);
     }
 
@@ -519,7 +509,6 @@
 
     /* Setup an audio channel */
     if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
-        QSA_CloseDevice(this);
         return SDL_SetError("QSA: Unable to setup channel");
     }
 
@@ -542,7 +531,6 @@
     this->hidden->pcm_buf =
         (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
     if (this->hidden->pcm_buf == NULL) {
-        QSA_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->pcm_buf, this->spec.silence,
@@ -560,7 +548,6 @@
     }
 
     if (this->hidden->audio_fd < 0) {
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_file_descriptor", status);
     }
 
@@ -578,7 +565,6 @@
     }
 
     if (status < 0) {
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_plugin_prepare", status);
     }
 
--- a/src/audio/sndio/SDL_sndioaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/sndio/SDL_sndioaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -180,16 +180,11 @@
 static void
 SNDIO_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if ( this->hidden->dev != NULL ) {
-            SNDIO_sio_close(this->hidden->dev);
-            this->hidden->dev = NULL;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if ( this->hidden->dev != NULL ) {
+        SNDIO_sio_close(this->hidden->dev);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -210,7 +205,6 @@
 
     /* !!! FIXME: SIO_DEVANY can be a specific device... */
     if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) {
-        SNDIO_CloseDevice(this);
         return SDL_SetError("sio_open() failed");
     }
 
@@ -233,7 +227,6 @@
                 continue;
             }
             if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
-                SNDIO_CloseDevice(this);
                 return SDL_SetError("sio_getpar() failed");
             }
             if (par.bps != SIO_BPS(par.bits)) {
@@ -248,7 +241,6 @@
     }
 
     if (status < 0) {
-        SNDIO_CloseDevice(this);
         return SDL_SetError("sndio: Couldn't find any hardware audio formats");
     }
 
@@ -269,7 +261,6 @@
     else if ((par.bps == 1) && (!par.sig))
         this->spec.format = AUDIO_U8;
     else {
-        SNDIO_CloseDevice(this);
         return SDL_SetError("sndio: Got unsupported hardware audio format.");
     }
 
@@ -284,7 +275,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        SNDIO_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
--- a/src/audio/sun/SDL_sunaudio.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/sun/SDL_sunaudio.c	Fri Aug 05 01:44:41 2016 -0400
@@ -183,18 +183,12 @@
 static void
 SUNAUDIO_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        SDL_free(this->hidden->ulaw_buf);
-        this->hidden->ulaw_buf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    SDL_free(this->hidden->ulaw_buf);
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
     }
+    SDL_FreeAudioMem(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
--- a/src/audio/winmm/SDL_winmm.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/winmm/SDL_winmm.c	Fri Aug 05 01:44:41 2016 -0400
@@ -155,42 +155,31 @@
 static void
 WINMM_CloseDevice(_THIS)
 {
-    /* Close up audio */
-    if (this->hidden != NULL) {
-        int i;
+    int i;
 
-        if (this->hidden->audio_sem) {
-            CloseHandle(this->hidden->audio_sem);
-            this->hidden->audio_sem = 0;
-        }
+    if (this->hidden->audio_sem) {
+        CloseHandle(this->hidden->audio_sem);
+    }
 
-        /* Clean up mixing buffers */
-        for (i = 0; i < NUM_BUFFERS; ++i) {
-            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
-                waveOutUnprepareHeader(this->hidden->hout,
-                                       &this->hidden->wavebuf[i],
-                                       sizeof(this->hidden->wavebuf[i]));
-                this->hidden->wavebuf[i].dwUser = 0xFFFF;
-            }
+    /* Clean up mixing buffers */
+    for (i = 0; i < NUM_BUFFERS; ++i) {
+        if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
+            waveOutUnprepareHeader(this->hidden->hout,
+                                   &this->hidden->wavebuf[i],
+                                   sizeof (this->hidden->wavebuf[i]));
         }
+    }
 
-        /* Free raw mixing buffer */
-        SDL_free(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
+    if (this->hidden->hin) {
+        waveInClose(this->hidden->hin);
+    }
 
-        if (this->hidden->hin) {
-            waveInClose(this->hidden->hin);
-            this->hidden->hin = 0;
-        }
+    if (this->hidden->hout) {
+        waveOutClose(this->hidden->hout);
+    }
 
-        if (this->hidden->hout) {
-            waveOutClose(this->hidden->hout);
-            this->hidden->hout = 0;
-        }
-
-        SDL_free(this->hidden);
-        this->hidden = NULL;
-    }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static SDL_bool
@@ -269,7 +258,6 @@
     }
 
     if (!valid_datatype) {
-        WINMM_CloseDevice(this);
         return SDL_SetError("Unsupported audio format");
     }
 
@@ -288,7 +276,6 @@
     }
 
     if (result != MMSYSERR_NOERROR) {
-        WINMM_CloseDevice(this);
         return SetMMerror("waveOutOpen()", result);
     }
 #ifdef SOUND_DEBUG
@@ -299,7 +286,6 @@
         result = waveOutGetDevCaps((UINT) this->hidden->hout,
                                    &caps, sizeof(caps));
         if (result != MMSYSERR_NOERROR) {
-            WINMM_CloseDevice(this);
             return SetMMerror("waveOutGetDevCaps()", result);
         }
         printf("Audio device: %s\n", caps.szPname);
@@ -310,7 +296,6 @@
     this->hidden->audio_sem =
         CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
     if (this->hidden->audio_sem == NULL) {
-        WINMM_CloseDevice(this);
         return SDL_SetError("Couldn't create semaphore");
     }
 
@@ -318,7 +303,6 @@
     this->hidden->mixbuf =
         (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
     if (this->hidden->mixbuf == NULL) {
-        WINMM_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     for (i = 0; i < NUM_BUFFERS; ++i) {
@@ -332,7 +316,6 @@
                                       &this->hidden->wavebuf[i],
                                       sizeof(this->hidden->wavebuf[i]));
         if (result != MMSYSERR_NOERROR) {
-            WINMM_CloseDevice(this);
             return SetMMerror("waveOutPrepareHeader()", result);
         }
     }
--- a/src/audio/xaudio2/SDL_xaudio2.c	Thu Aug 04 11:51:17 2016 -0400
+++ b/src/audio/xaudio2/SDL_xaudio2.c	Fri Aug 05 01:44:41 2016 -0400
@@ -257,33 +257,30 @@
 static void
 XAUDIO2_CloseDevice(_THIS)
 {
-    if (this->hidden != NULL) {
-        IXAudio2 *ixa2 = this->hidden->ixa2;
-        IXAudio2SourceVoice *source = this->hidden->source;
-        IXAudio2MasteringVoice *mastering = this->hidden->mastering;
+    IXAudio2 *ixa2 = this->hidden->ixa2;
+    IXAudio2SourceVoice *source = this->hidden->source;
+    IXAudio2MasteringVoice *mastering = this->hidden->mastering;
 
-        if (source != NULL) {
-            IXAudio2SourceVoice_Stop(source, 0, XAUDIO2_COMMIT_NOW);
-            IXAudio2SourceVoice_FlushSourceBuffers(source);
-            IXAudio2SourceVoice_DestroyVoice(source);
-        }
-        if (ixa2 != NULL) {
-            IXAudio2_StopEngine(ixa2);
-        }
-        if (mastering != NULL) {
-            IXAudio2MasteringVoice_DestroyVoice(mastering);
-        }
-        if (ixa2 != NULL) {
-            IXAudio2_Release(ixa2);
-        }
-        SDL_free(this->hidden->mixbuf);
-        if (this->hidden->semaphore != NULL) {
-            SDL_DestroySemaphore(this->hidden->semaphore);
-        }
+    if (source != NULL) {
+        IXAudio2SourceVoice_Stop(source, 0, XAUDIO2_COMMIT_NOW);
+        IXAudio2SourceVoice_FlushSourceBuffers(source);
+        IXAudio2SourceVoice_DestroyVoice(source);
+    }
+    if (ixa2 != NULL) {
+        IXAudio2_StopEngine(ixa2);
+    }
+    if (mastering != NULL) {
+        IXAudio2MasteringVoice_DestroyVoice(mastering);
+    }
+    if (ixa2 != NULL) {
+        IXAudio2_Release(ixa2);
+    }
+    if (this->hidden->semaphore != NULL) {
+        SDL_DestroySemaphore(this->hidden->semaphore);
+    }
 
-        SDL_free(this->hidden);
-        this->hidden = NULL;
-    }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 
 static int
@@ -350,7 +347,6 @@
     this->hidden->ixa2 = ixa2;
     this->hidden->semaphore = SDL_CreateSemaphore(1);
     if (this->hidden->semaphore == NULL) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: CreateSemaphore() failed!");
     }
 
@@ -368,7 +364,6 @@
     }
 
     if (!valid_format) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Unsupported audio format");
     }
 
@@ -379,7 +374,6 @@
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
-        XAUDIO2_CloseDevice(this);
         return SDL_OutOfMemory();
     }
     this->hidden->nextbuf = this->hidden->mixbuf;
@@ -401,7 +395,6 @@
                                            this->spec.freq, 0, devId, NULL);
 #endif
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't create mastering voice");
     }
 
@@ -436,7 +429,6 @@
 
 #endif
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't create source voice");
     }
     this->hidden->source = source;
@@ -444,13 +436,11 @@
     /* Start everything playing! */
     result = IXAudio2_StartEngine(ixa2);
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't start engine");
     }
 
     result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW);
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't start source voice");
     }