changeset 485:137c0b00ea4c

Added Sound_NewSampleFromMem(), and implementation of RWops pooling.
author Ryan C. Gordon <icculus@icculus.org>
date Sun, 27 Feb 2005 19:53:25 +0000
parents 1c09756bc038
children 859dd2ef3197
files SDL_sound.c SDL_sound.h SDL_sound_internal.h TODO extra_rwops.c extra_rwops.h
diffstat 6 files changed, 174 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/SDL_sound.c	Sun Feb 27 19:50:54 2005 +0000
+++ b/SDL_sound.c	Sun Feb 27 19:53:25 2005 +0000
@@ -450,6 +450,10 @@
 static Sound_Sample *alloc_sample(SDL_RWops *rw, Sound_AudioInfo *desired,
                                     Uint32 bufferSize)
 {
+    /*
+     * !!! FIXME: We're going to need to pool samples, since the mixer
+     * !!! FIXME:  might be allocating tons of these on a regular basis.
+     */
     Sound_Sample *retval = malloc(sizeof (Sound_Sample));
     Sound_SampleInternal *internal = malloc(sizeof (Sound_SampleInternal));
     if ((retval == NULL) || (internal == NULL))
@@ -693,6 +697,7 @@
 
     ext = strrchr(filename, '.');
     rw = SDL_RWFromFile(filename, "rb");
+    /* !!! FIXME: rw = RWops_FromFile(filename, "rb");*/
     BAIL_IF_MACRO(rw == NULL, SDL_GetError(), NULL);
 
     if (ext != NULL)
@@ -702,6 +707,26 @@
 } /* Sound_NewSampleFromFile */
 
 
+Sound_Sample *Sound_NewSampleFromMem(const Uint8 *data,
+                                     Uint32 size,
+                                     const char *ext,
+                                     Sound_AudioInfo *desired,
+                                     Uint32 bufferSize);
+{
+    SDL_RWops *rw;
+
+    BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, NULL);
+    BAIL_IF_MACRO(data == NULL, ERR_INVALID_ARGUMENT, NULL);
+    BAIL_IF_MACRO(size == 0, ERR_INVALID_ARGUMENT, NULL);
+
+    rw = SDL_RWFromMem(data, size);
+    /* !!! FIXME: rw = RWops_FromMem(data, size);*/
+    BAIL_IF_MACRO(rw == NULL, SDL_GetError(), NULL);
+
+    return(Sound_NewSample(rw, ext, desired, bufferSize));
+} /* Sound_NewSampleFromMem */
+
+
 void Sound_FreeSample(Sound_Sample *sample)
 {
     Sound_SampleInternal *internal;
--- a/SDL_sound.h	Sun Feb 27 19:50:54 2005 +0000
+++ b/SDL_sound.h	Sun Feb 27 19:53:25 2005 +0000
@@ -452,6 +452,39 @@
                                                    Uint32 bufferSize);
 
 /**
+ * \fn Sound_Sample *Sound_NewSampleFromMem(const Uint8 *data, Sound_AudioInfo *desired, Uint32 bufferSize)
+ * \brief Start decoding a new sound sample from a file on disk.
+ *
+ * This is identical to Sound_NewSample(), but it creates an SDL_RWops for you
+ *  from the (size) bytes of memory referenced by (data).
+ *
+ * This can pool RWops structures, so it may fragment the heap less over time
+ *  than using SDL_RWFromMem().
+ *
+ *    \param filename file containing sound data.
+ *    \param desired Format to convert sound data into. Can usually be NULL,
+ *                   if you don't need conversion.
+ *    \param bufferSize size, in bytes, of initial read buffer.
+ *   \return Sound_Sample pointer, which is used as a handle to several other
+ *           SDL_sound APIs. NULL on error. If error, use
+ *           Sound_GetError() to see what went wrong.
+ *
+ * \sa Sound_NewSample
+ * \sa Sound_SetBufferSize
+ * \sa Sound_Decode
+ * \sa Sound_DecodeAll
+ * \sa Sound_Seek
+ * \sa Sound_Rewind
+ * \sa Sound_FreeSample
+ */
+SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSampleFromMem(const Uint8 *data,
+                                                      Uint32 size,
+                                                      const char *ext,
+                                                      Sound_AudioInfo *desired,
+                                                      Uint32 bufferSize);
+
+
+/**
  * \fn Sound_Sample *Sound_NewSampleFromFile(const char *filename, Sound_AudioInfo *desired, Uint32 bufferSize)
  * \brief Start decoding a new sound sample from a file on disk.
  *
@@ -462,6 +495,9 @@
  * Sound_NewSample()'s "ext" parameter is gleaned from the contents of
  *  (filename).
  *
+ * This can pool RWops structures, so it may fragment the heap less over time
+ *  than using SDL_RWFromFile().
+ *
  *    \param filename file containing sound data.
  *    \param desired Format to convert sound data into. Can usually be NULL,
  *                   if you don't need conversion.
--- a/SDL_sound_internal.h	Sun Feb 27 19:50:54 2005 +0000
+++ b/SDL_sound_internal.h	Sun Feb 27 19:53:25 2005 +0000
@@ -65,6 +65,14 @@
 #endif
 
 
+/*
+ * SDL itself only supports mono and stereo output, but hopefully we can
+ *  raise this value someday...there's probably a lot of assumptions in
+ *  SDL_sound that rely on it, though.
+ */
+#define MAX_CHANNELS 2
+
+
 typedef struct __SOUND_DECODERFUNCTIONS__
 {
         /* This is a block of info about your decoder. See SDL_sound.h. */
@@ -240,6 +248,7 @@
 extern SNDDECLSPEC int Sound_ConvertAudio(Sound_AudioCVT *cvt);
 
 
+typedef void (*MixFunc)(float *dst, void *src, Uint32 frames, float *gains);
 
 typedef struct __SOUND_SAMPLEINTERNAL__
 {
@@ -252,6 +261,8 @@
     Uint32 buffer_size;
     void *decoder_private;
     Sint32 total_time;
+    Uint32 mix_position;
+    MixFunc mix;
 } Sound_SampleInternal;
 
 
--- a/TODO	Sun Feb 27 19:50:54 2005 +0000
+++ b/TODO	Sun Feb 27 19:53:25 2005 +0000
@@ -15,6 +15,8 @@
 - Hack on the experimental audio conversion routines.
 - Handle compression and other chunks in WAV files.
 - Handle compression and other chunks in AIFF-C files.
+- Reduce malloc() pressure.
+- Maybe allow an external allocator?
 
 Quicktime stuff that'd be cool, but isn't crucial:
 - Integrate decoders/quicktime.c with build system (for OS X)?
--- a/extra_rwops.c	Sun Feb 27 19:50:54 2005 +0000
+++ b/extra_rwops.c	Sun Feb 27 19:53:25 2005 +0000
@@ -130,6 +130,88 @@
 } /* RWops_RWRefCounter_new */
 
 
+
+    /*
+     * RWops pooling...
+     */
+
+static SDL_RWops *rwops_pool = NULL;
+static SDL_mutex *rwops_pool_mutex = NULL;
+
+int RWops_pooled_init(void)
+{
+    const int preallocate = 50;
+    int i;
+
+    rwops_pool_mutex = SDL_CreateMutex();
+    if (rwops_pool_mutex == NULL)
+        return(0);
+
+    for (i = 0; i < preallocate; i++)
+        free_pooled_rwops(alloc_pooled_rwops());
+
+    return(1);
+} /* RWops_pooled_init */
+
+
+void RWops_pooled_deinit(void)
+{
+    SDL_RWops *cur;
+    SDL_RWops *next;
+
+    if (rwops_pool_mutex == NULL)
+        return;  /* never initialized. */
+
+    SDL_LockMutex(rwops_pool_mutex);
+    /* all allocated rwops must be in the pool now, or the memory leaks. */
+    cur = rwops_pool;
+    rwops_pool = NULL;
+    SDL_UnlockMutex(rwops_pool_mutex);
+    SDL_DestroyMutex(rwops_pool_mutex);
+    rwops_pool_mutex = NULL;
+
+    while (cur)
+    {
+        next = (SDL_RWops *) (cur->hidden.unknown.data1);
+        free(cur);
+        cur = next;
+    } /* while */
+} /* RWops_pooled_deinit */
+
+
+SDL_RWops *RWops_pooled_alloc(void)
+{
+    SDL_RWops *rw;
+    if (rwops_pool_mutex == NULL)
+        return(NULL);  /* never initialized. */
+
+    SDL_LockMutex(rwops_pool_mutex);
+    rw = rwops_pool;
+    if (rw)
+        rwops_pool = (SDL_RWops *) (rw->hidden.unknown.data1);
+    SDL_UnlockMutex(rwops_pool_mutex);
+
+    if (!rw)
+        rw = (SDL_RWops *) malloc(sizeof (SDL_RWops));
+
+    return(rw);
+} /* RWops_pooled_alloc */
+
+
+void RWops_pooled_free(SDL_RWops *rw)
+{
+    if (rwops_pool_mutex == NULL)
+        return;  /* never initialized...why are we here? */
+
+    if (rw == NULL)
+        return;
+
+    SDL_LockMutex(rwops_pool_mutex);
+    rw->hidden.unknown.data1 = rwops_pool;
+    rwops_pool = rw;
+    SDL_UnlockMutex(rwops_pool_mutex);
+} /* RWops_pooled_free */
+
 /* end of extra_rwops.c ... */
 
 
--- a/extra_rwops.h	Sun Feb 27 19:50:54 2005 +0000
+++ b/extra_rwops.h	Sun Feb 27 19:53:25 2005 +0000
@@ -61,6 +61,24 @@
 /* Increment a reference counting RWops's refcount by one. */
 void RWops_RWRefCounter_addRef(SDL_RWops *rw);
 
+
+/*
+ * RWops pooling. This is to reduce malloc() pressure for audio that is
+ *  placed into Sound_Samples over and over again.
+ */
+
+/* Call this first. */
+int RWops_pooled_init(void);
+
+/* Call this last. */
+int RWops_pooled_deinit(void);
+
+/* Get a new RWops, allocating if needed. */
+SDL_RWops *RWops_pooled_alloc(void);
+
+/* Return a RWops to the pool for reuse. */
+void RWops_pooled_free(SDL_RWops *rw)
+
 #ifdef __cplusplus
 }
 #endif