Skip to content

Commit

Permalink
Added Sound_NewSampleFromMem(), and implementation of RWops pooling.
Browse files Browse the repository at this point in the history
  • Loading branch information
icculus committed Feb 27, 2005
1 parent f24443b commit cd61d51
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 0 deletions.
25 changes: 25 additions & 0 deletions SDL_sound.c
Expand Up @@ -450,6 +450,10 @@ int __Sound_strcasecmp(const char *x, const char *y)
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))
Expand Down Expand Up @@ -693,6 +697,7 @@ Sound_Sample *Sound_NewSampleFromFile(const char *filename,

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)
Expand All @@ -702,6 +707,26 @@ Sound_Sample *Sound_NewSampleFromFile(const char *filename,
} /* 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;
Expand Down
36 changes: 36 additions & 0 deletions SDL_sound.h
Expand Up @@ -451,6 +451,39 @@ SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSample(SDL_RWops *rw,
Sound_AudioInfo *desired,
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.
Expand All @@ -462,6 +495,9 @@ SNDDECLSPEC Sound_Sample * SDLCALL Sound_NewSample(SDL_RWops *rw,
* 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.
Expand Down
11 changes: 11 additions & 0 deletions SDL_sound_internal.h
Expand Up @@ -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. */
Expand Down Expand Up @@ -240,6 +248,7 @@ extern SNDDECLSPEC int Sound_BuildAudioCVT(Sound_AudioCVT *cvt,
extern SNDDECLSPEC int Sound_ConvertAudio(Sound_AudioCVT *cvt);


typedef void (*MixFunc)(float *dst, void *src, Uint32 frames, float *gains);

typedef struct __SOUND_SAMPLEINTERNAL__
{
Expand All @@ -252,6 +261,8 @@ typedef struct __SOUND_SAMPLEINTERNAL__
Uint32 buffer_size;
void *decoder_private;
Sint32 total_time;
Uint32 mix_position;
MixFunc mix;
} Sound_SampleInternal;


Expand Down
2 changes: 2 additions & 0 deletions TODO
Expand Up @@ -15,6 +15,8 @@ General stuff TODO:
- 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)?
Expand Down
82 changes: 82 additions & 0 deletions extra_rwops.c
Expand Up @@ -130,6 +130,88 @@ SDL_RWops *RWops_RWRefCounter_new(SDL_RWops *rw)
} /* 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 ... */


18 changes: 18 additions & 0 deletions extra_rwops.h
Expand Up @@ -61,6 +61,24 @@ SDL_RWops *RWops_RWRefCounter_new(SDL_RWops *rw);
/* 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
Expand Down

0 comments on commit cd61d51

Please sign in to comment.