shithub: choc

Download patch

ref: 204a03688d5e0b3b1779f26c065427f2b1652524
parent: 3a708aa7fb7577ad8fed6ee39705567dcdc4e97e
author: Simon Howard <fraggle@gmail.com>
date: Sun Sep 14 18:11:04 EDT 2008

Allocate sound chunks and their buffers together, so that they are freed
out as cache together.

Subversion-branch: /branches/raven-branch
Subversion-revision: 1230

--- a/src/i_sdlsound.c
+++ b/src/i_sdlsound.c
@@ -57,32 +57,13 @@
 static int mixer_freq;
 static Uint16 mixer_format;
 static int mixer_channels;
-static uint32_t (*ExpandSoundData)(byte *data, int samplerate, int length,
-                                   Mix_Chunk *destination) = NULL;
+static void (*ExpandSoundData)(sfxinfo_t *sfxinfo,
+                               byte *data,
+                               int samplerate,
+                               int length) = NULL;
 
 int use_libsamplerate = 0;
 
-// The driver_data field is used to point to a Mix_Chunk structure that
-// has data about the expanded version of the sound effect.  These are
-// allocated on demand.
-
-static Mix_Chunk *GetSoundChunk(sfxinfo_t *sfxinfo)
-{
-    Mix_Chunk *chunk;
-
-    // No chunk for this structure yet? Allocate it.
-
-    if (sfxinfo->driver_data == NULL)
-    {
-	chunk = Z_Malloc(sizeof(Mix_Chunk), PU_STATIC, NULL);
-	chunk->abuf = NULL;
-	chunk->allocated = 0;
-        sfxinfo->driver_data = chunk;
-    }
-
-    return sfxinfo->driver_data;
-}
-
 // When a sound stops, check if it is still playing.  If it is not, 
 // we can mark the sound data as CACHE to be freed back for other
 // means.
@@ -91,7 +72,6 @@
 {
     int i;
     sfxinfo_t *sfxinfo = channels_playing[channel];
-    Mix_Chunk *chunk;
 
     if (sfxinfo == NULL)
     {
@@ -110,10 +90,33 @@
 
     // Not used on any channel, and can be safely released
 
-    chunk = GetSoundChunk(sfxinfo);
-    Z_ChangeTag(chunk->abuf, PU_CACHE);
+    Z_ChangeTag(sfxinfo->driver_data, PU_CACHE);
 }
 
+// Allocate a new Mix_Chunk along with its data, storing
+// the result in the variable pointed to by variable
+
+static Mix_Chunk *AllocateChunk(sfxinfo_t *sfxinfo, uint32_t len)
+{
+    Mix_Chunk *chunk;
+
+    // Allocate the chunk and the audio buffer together
+
+    chunk = Z_Malloc(len + sizeof(Mix_Chunk),
+                     PU_STATIC,
+                     &sfxinfo->driver_data);
+    sfxinfo->driver_data = chunk;
+
+    // Skip past the chunk structure for the audio buffer
+
+    chunk->abuf = (byte *) (chunk + 1);
+    chunk->alen = len;
+    chunk->allocated = 1;
+    chunk->volume = MIX_MAX_VOLUME;
+
+    return chunk;
+}
+
 #ifdef HAVE_LIBSAMPLERATE
 
 // Returns the conversion mode for libsamplerate to use.
@@ -150,15 +153,17 @@
 // Returns number of clipped samples.
 // DWF 2008-02-10 with cleanups by Simon Howard.
 
-static uint32_t ExpandSoundData_SRC(byte *data,
-                                    int samplerate,
-                                    int length,
-                                    Mix_Chunk *destination)
+static void ExpandSoundData_SRC(sfxinfo_t *sfxinfo,
+                                byte *data,
+                                int samplerate,
+                                int length)
 {
     SRC_DATA src_data;
     uint32_t i, abuf_index=0, clipped=0;
+    uint32_t alen;
     int retn;
     int16_t *expanded;
+    Mix_Chunk *chunk;
 
     src_data.input_frames = length;
     src_data.data_in = malloc(length * sizeof(float));
@@ -185,13 +190,15 @@
     retn = src_simple(&src_data, SRC_ConversionMode(), 1);
     assert(retn == 0);
 
-    // Convert the result back into 16-bit integers.
+    // Allocate the new chunk.
 
-    destination->alen = src_data.output_frames_gen * 4;
-    destination->abuf = Z_Malloc(destination->alen, PU_STATIC, 
-                                 &destination->abuf);
-    expanded = (int16_t *) destination->abuf;
+    alen = src_data.output_frames_gen * 4;
 
+    chunk = AllocateChunk(sfxinfo, src_data.output_frames_gen * 4);
+    expanded = (int16_t *) chunk->abuf;
+
+    // Convert the result back into 16-bit integers.
+
     for (i=0; i<src_data.output_frames_gen; ++i)
     {
         // libsamplerate does not limit itself to the -1.0 .. 1.0 range on
@@ -219,13 +226,16 @@
         int32_t cvtval_i = cvtval_f + (cvtval_f < 0 ? -0.5 : 0.5);
 
         // Asymmetrical sound worries me, so we won't use -32768.
-        if (cvtval_i < -INT16_MAX) {
-          cvtval_i = -INT16_MAX;
-          ++clipped;
-        } else if (cvtval_i > INT16_MAX) {
-          cvtval_i = INT16_MAX;
-          ++clipped;
+        if (cvtval_i < -INT16_MAX)
+        {
+            cvtval_i = -INT16_MAX;
+            ++clipped;
         }
+        else if (cvtval_i > INT16_MAX)
+        {
+            cvtval_i = INT16_MAX;
+            ++clipped;
+        }
 
         // Left and right channels
 
@@ -235,7 +245,13 @@
 
     free(src_data.data_in);
     free(src_data.data_out);
-    return clipped;
+
+    if (clipped > 0)
+    {
+        fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", 
+                        sfxinfo->name, clipped,
+                        400.0 * clipped / chunk->alen);
+    }
 }
 
 #endif
@@ -272,12 +288,13 @@
 // Generic sound expansion function for any sample rate.
 // Returns number of clipped samples (always 0).
 
-static uint32_t ExpandSoundData_SDL(byte *data,
-                                    int samplerate,
-                                    int length,
-                                    Mix_Chunk *destination)
+static void ExpandSoundData_SDL(sfxinfo_t *sfxinfo,
+                                byte *data,
+                                int samplerate,
+                                int length)
 {
     SDL_AudioCVT convertor;
+    Mix_Chunk *chunk;
     uint32_t expanded_length;
  
     // Calculate the length of the expanded version of the sample.    
@@ -288,10 +305,10 @@
 
     expanded_length *= 4;
 
-    destination->alen = expanded_length;
-    destination->abuf 
-        = Z_Malloc(expanded_length, PU_STATIC, &destination->abuf);
+    // Allocate a chunk in which to expand the sound
 
+    chunk = AllocateChunk(sfxinfo, expanded_length);
+
     // If we can, use the standard / optimised SDL conversion routines.
     
     if (samplerate <= mixer_freq
@@ -300,7 +317,7 @@
                           AUDIO_U8, 1, samplerate,
                           mixer_format, mixer_channels, mixer_freq))
     {
-        convertor.buf = destination->abuf;
+        convertor.buf = chunk->abuf;
         convertor.len = length;
         memcpy(convertor.buf, data, length);
 
@@ -308,7 +325,7 @@
     }
     else
     {
-        Sint16 *expanded = (Sint16 *) destination->abuf;
+        Sint16 *expanded = (Sint16 *) chunk->abuf;
         int expanded_length;
         int expand_ratio;
         int i;
@@ -366,8 +383,6 @@
         }
 #endif /* #ifdef LOW_PASS_FILTER */
     }
-
-    return 0;
 }
 
 // Load and convert a sound effect
@@ -375,11 +390,9 @@
 
 static boolean CacheSFX(sfxinfo_t *sfxinfo)
 {
-    Mix_Chunk *chunk;
     int lumpnum;
     unsigned int lumplen;
     int samplerate;
-    int clipped;
     unsigned int length;
     byte *data;
 
@@ -413,22 +426,9 @@
     }
 
     // Sample rate conversion
-    // DWF 2008-02-10:  chunk->alen and abuf are determined
-    // by ExpandSoundData.
 
-    chunk = GetSoundChunk(sfxinfo);
-    chunk->allocated = 1;
-    chunk->volume = MIX_MAX_VOLUME;
+    ExpandSoundData(sfxinfo, data + 8, samplerate, length);
 
-    clipped = ExpandSoundData(data + 8, samplerate, length, chunk);
-
-    if (clipped)
-    {
-        fprintf(stderr, "Sound '%s': clipped %u samples (%0.2f %%)\n", 
-                        sfxinfo->name, clipped,
-                        400.0 * clipped / chunk->alen);
-    }
-
     // don't need the original lump any more
   
     W_ReleaseLumpNum(lumpnum);
@@ -442,7 +442,6 @@
 
 static void I_SDL_PrecacheSounds(sfxinfo_t *sounds, int num_sounds)
 {
-    Mix_Chunk *chunk;
     char namebuf[9];
     int i;
 
@@ -469,12 +468,11 @@
 
         if (sounds[i].lumpnum != -1)
         {
-            CacheSFX(&sounds[i]);
-	    chunk = GetSoundChunk(&sounds[i]);
+            // Try to cache the sound and then release it as cache
 
-            if (chunk->abuf != NULL)
+            if (CacheSFX(&sounds[i])) 
             {
-                Z_ChangeTag(chunk->abuf, PU_CACHE);
+                Z_ChangeTag(sounds[i].driver_data, PU_CACHE);
             }
         }
     }
@@ -495,24 +493,20 @@
 
 static boolean LockSound(sfxinfo_t *sfxinfo)
 {
-    Mix_Chunk *chunk;
+    // If the sound isn't loaded, load it now
 
-    chunk = GetSoundChunk(sfxinfo);
-
-    if (chunk->abuf == NULL)
+    if (sfxinfo->driver_data == NULL)
     {
-        // Not yet loaded, or has been freed.  Load the sound data.
-
         if (!CacheSFX(sfxinfo))
-	{
+        {
             return false;
-	}
+        }
     }
     else
     {
-        // don't free the sound while it is playing!
+        // Lock the sound effect into memory
    
-        Z_ChangeTag(chunk->abuf, PU_STATIC);
+        Z_ChangeTag(sfxinfo->driver_data, PU_STATIC);
     }
 
     return true;
@@ -583,7 +577,7 @@
 	return -1;
     }
 
-    chunk = GetSoundChunk(sfxinfo);
+    chunk = (Mix_Chunk *) sfxinfo->driver_data;
 
     // play sound