From 56a3c771e738f95464663eff324789b647ef7481 Mon Sep 17 00:00:00 2001 From: molivier Date: Sun, 18 Sep 2005 16:43:45 +0000 Subject: [PATCH] - SFXs no longer allocate mempools, they use the sound mempool directly. It saved 21KB and 129 mempools (from 191 to 62) in my quick test. - removed unused function S_UnloadSound - changed an endian test in the Ogg Vorbis code to look more coherent git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5725 d7cf8633-e32d-0410-b094-e92efae38249 --- snd_coreaudio.c | 2 -- snd_main.c | 19 +++++++++---- snd_main.h | 13 +++++---- snd_mem.c | 17 ------------ snd_ogg.c | 74 +++++++++++++++++++++++++++++++++++++------------ snd_sdl.c | 1 - snd_wav.c | 39 ++++++++++++++++++-------- snd_wav.h | 2 +- 8 files changed, 106 insertions(+), 61 deletions(-) diff --git a/snd_coreaudio.c b/snd_coreaudio.c index 899ccf6d..3a132f98 100644 --- a/snd_coreaudio.c +++ b/snd_coreaudio.c @@ -43,8 +43,6 @@ static qboolean s_isRunning; static AudioDeviceID outputDeviceID; static AudioStreamBasicDescription outputStreamBasicDescription; -extern mempool_t *snd_mempool; - /* =============== diff --git a/snd_main.c b/snd_main.c index bf0bc3da..fafb23c1 100644 --- a/snd_main.c +++ b/snd_main.c @@ -272,6 +272,7 @@ sfx_t *S_FindName (const char *name) sfx = Mem_Alloc (snd_mempool, sizeof (*sfx)); memset (sfx, 0, sizeof(*sfx)); strlcpy (sfx->name, name, sizeof (sfx->name)); + sfx->memsize = sizeof(*sfx); sfx->next = known_sfx; known_sfx = sfx; @@ -287,6 +288,8 @@ S_FreeSfx */ void S_FreeSfx (sfx_t *sfx, qboolean force) { + unsigned int i; + // Never free a locked sfx unless forced if (!force && (sfx->locks > 0 || (sfx->flags & SFXFLAG_PERMANENTLOCK))) return; @@ -313,8 +316,14 @@ void S_FreeSfx (sfx_t *sfx, qboolean force) } } + // Stop all channels using this sfx + for (i = 0; i < total_channels; i++) + if (channels[i].sfx == sfx) + S_StopChannel (i); + // Free it - Mem_FreePool (&sfx->mempool); + if (sfx->fetcher != NULL && sfx->fetcher->free != NULL) + sfx->fetcher->free (sfx); Mem_Free (sfx); } @@ -631,9 +640,9 @@ void S_StopChannel (unsigned int channel_ind) if (sfx->fetcher != NULL) { - snd_fetcher_end_t fetcher_end = sfx->fetcher->end; - if (fetcher_end != NULL) - fetcher_end (ch); + snd_fetcher_endsb_t fetcher_endsb = sfx->fetcher->endsb; + if (fetcher_endsb != NULL) + fetcher_endsb (ch); } // Remove the lock it holds @@ -1024,7 +1033,7 @@ void S_SoundList(void) { if (sfx->fetcher != NULL) { - size = (int)sfx->mempool->totalsize; + size = (int)sfx->memsize; total += size; Con_Printf ("%c%c%c%c(%2db, %6s) %8i : %s\n", (sfx->loopstart >= 0) ? 'L' : ' ', diff --git a/snd_main.h b/snd_main.h index 0248a92c..0eea61ad 100644 --- a/snd_main.h +++ b/snd_main.h @@ -50,7 +50,7 @@ struct sfx_s { char name[MAX_QPATH]; sfx_t *next; - mempool_t *mempool; + size_t memsize; // total memory used (including sfx_t and fetcher data) int locks; // One lock is automatically granted while the sfx is // playing (and removed when stopped). Locks can also be // added by S_PrecacheSound and S_ServerSounds. @@ -91,11 +91,13 @@ typedef struct } channel_t; typedef const sfxbuffer_t* (*snd_fetcher_getsb_t) (channel_t* ch, unsigned int start, unsigned int nbsamples); -typedef void (*snd_fetcher_end_t) (channel_t* ch); +typedef void (*snd_fetcher_endsb_t) (channel_t* ch); +typedef void (*snd_fetcher_free_t) (sfx_t* sfx); struct snd_fetcher_s { snd_fetcher_getsb_t getsb; - snd_fetcher_end_t end; + snd_fetcher_endsb_t endsb; + snd_fetcher_free_t free; }; void S_PaintChannels(int endtime); @@ -112,7 +114,6 @@ void SNDDMA_Submit(void); void SNDDMA_Shutdown(void); qboolean S_LoadSound (sfx_t *s, qboolean complain); -void S_UnloadSound(sfx_t *s); void S_LockSfx (sfx_t *sfx); void S_UnlockSfx (sfx_t *sfx); @@ -122,8 +123,6 @@ void S_UnlockBuffer(void); extern size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* in_format, qbyte *out_data, const char* sfxname); -// ==================================================================== -// User-setable variables // ==================================================================== // 0 to NUM_AMBIENTS - 1 = water, etc @@ -145,5 +144,7 @@ extern cvar_t snd_streaming; extern int snd_blocked; +extern mempool_t *snd_mempool; + #endif diff --git a/snd_mem.c b/snd_mem.c index 281e513a..1e94c270 100644 --- a/snd_mem.c +++ b/snd_mem.c @@ -213,20 +213,3 @@ qboolean S_LoadSound (sfx_t *s, qboolean complain) Con_Printf("S_LoadSound: Couldn't load \"%s\"\n", s->name); return false; } - -void S_UnloadSound (sfx_t *s) -{ - if (s->fetcher != NULL) - { - unsigned int i; - - // Stop all channels that use this sound - for (i = 0; i < total_channels ; i++) - if (channels[i].sfx == s) - S_StopChannel (i); - - s->fetcher = NULL; - s->fetcher_data = NULL; - Mem_FreePool(&s->mempool); - } -} diff --git a/snd_ogg.c b/snd_ogg.c index a342f4a8..a95ce231 100644 --- a/snd_ogg.c +++ b/snd_ogg.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2003-2004 Mathieu Olivier + Copyright (C) 2003-2005 Mathieu Olivier This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -370,6 +370,7 @@ void OGG_CloseLibrary (void) */ #define STREAM_BUFFER_DURATION 1.5f // 1.5 sec +#define STREAM_BUFFER_SIZE(format_ptr) (ceil (STREAM_BUFFER_DURATION * ((format_ptr)->speed * (format_ptr)->width * (format_ptr)->channels))) // We work with 1 sec sequences, so this buffer must be able to contain // 1 sec of sound of the highest quality (48 KHz, 16 bit samples, stereo) @@ -406,6 +407,7 @@ static const sfxbuffer_t* OGG_FetchSound (channel_t* ch, unsigned int start, uns ogg_stream_perchannel_t* per_ch; sfxbuffer_t* sb; sfx_t* sfx; + snd_format_t* format; ogg_stream_persfx_t* per_sfx; int newlength, done, ret, bigendian; unsigned int factor; @@ -414,14 +416,18 @@ static const sfxbuffer_t* OGG_FetchSound (channel_t* ch, unsigned int start, uns per_ch = ch->fetcher_data; sfx = ch->sfx; per_sfx = sfx->fetcher_data; - buff_len = ceil (STREAM_BUFFER_DURATION * (sfx->format.speed * sfx->format.width * sfx->format.channels)); + format = &sfx->format; + buff_len = STREAM_BUFFER_SIZE(format); // If there's no fetcher structure attached to the channel yet if (per_ch == NULL) { + size_t memsize; ogg_stream_persfx_t* per_sfx; - per_ch = Mem_Alloc (sfx->mempool, sizeof (*per_ch) - sizeof (per_ch->sb.data) + buff_len); + memsize = sizeof (*per_ch) - sizeof (per_ch->sb.data) + buff_len; + per_ch = Mem_Alloc (snd_mempool, memsize); + sfx->memsize += memsize; per_sfx = sfx->fetcher_data; // Open it with the VorbisFile API @@ -486,10 +492,10 @@ static const sfxbuffer_t* OGG_FetchSound (channel_t* ch, unsigned int start, uns newlength = per_sfx->format.speed * factor; // -> 1 sec of sound before resampling // Decompress in the resampling_buffer -#if BYTE_ORDER == LITTLE_ENDIAN - bigendian = 0; -#else +#if BYTE_ORDER == BIG_ENDIAN bigendian = 1; +#else + bigendian = 0; #endif done = 0; while ((ret = qov_read (&per_ch->vf, &resampling_buffer[done], (int)(newlength - done), bigendian, 2, 1, &per_ch->bs)) > 0) @@ -515,15 +521,44 @@ static void OGG_FetchEnd (channel_t* ch) per_ch = ch->fetcher_data; if (per_ch != NULL) { + size_t buff_len; + snd_format_t* format; + // Free the ogg vorbis decoder qov_clear (&per_ch->vf); Mem_Free (per_ch); ch->fetcher_data = NULL; + + format = &ch->sfx->format; + buff_len = STREAM_BUFFER_SIZE(format); + ch->sfx->memsize -= sizeof (*per_ch) - sizeof (per_ch->sb.data) + buff_len; } } -static const snd_fetcher_t ogg_fetcher = { OGG_FetchSound, OGG_FetchEnd }; + +/* +==================== +OGG_FreeSfx +==================== +*/ +static void OGG_FreeSfx (sfx_t* sfx) +{ + ogg_stream_persfx_t* per_sfx = sfx->fetcher_data; + + // Free the Ogg Vorbis file + Mem_Free(per_sfx->file); + sfx->memsize -= per_sfx->filesize; + + // Free the stream structure + Mem_Free(per_sfx); + sfx->memsize -= sizeof (*per_sfx); + + sfx->fetcher_data = NULL; + sfx->fetcher = NULL; +} + +static const snd_fetcher_t ogg_fetcher = { OGG_FetchSound, OGG_FetchEnd, OGG_FreeSfx }; /* @@ -544,16 +579,14 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *s) if (!vf_dll) return false; - Mem_FreePool (&s->mempool); - s->mempool = Mem_AllocPool (s->name, 0, NULL); + // Already loaded? + if (s->fetcher != NULL) + return true; // Load the file - data = FS_LoadFile (filename, s->mempool, false); + data = FS_LoadFile (filename, snd_mempool, false); if (data == NULL) - { - Mem_FreePool (&s->mempool); return false; - } Con_DPrintf ("Loading Ogg Vorbis file \"%s\"\n", filename); @@ -564,7 +597,7 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *s) if (qov_open_callbacks (&ov_decode, &vf, NULL, 0, callbacks) < 0) { Con_Printf ("error while opening Ogg Vorbis file \"%s\"\n", filename); - Mem_FreePool (&s->mempool); + Mem_Free(data); return false; } @@ -575,7 +608,7 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *s) Con_Printf("%s has an unsupported number of channels (%i)\n", s->name, vi->channels); qov_clear (&vf); - Mem_FreePool (&s->mempool); + Mem_Free(data); return false; } @@ -588,9 +621,11 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *s) ogg_stream_persfx_t* per_sfx; Con_DPrintf ("\"%s\" will be streamed\n", filename); - per_sfx = Mem_Alloc (s->mempool, sizeof (*per_sfx)); + per_sfx = Mem_Alloc (snd_mempool, sizeof (*per_sfx)); + s->memsize += sizeof (*per_sfx); per_sfx->file = data; per_sfx->filesize = fs_filesize; + s->memsize += fs_filesize; per_sfx->format.speed = vi->rate; per_sfx->format.width = 2; // We always work with 16 bits samples @@ -612,11 +647,12 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *s) int bs, bigendian; long ret; sfxbuffer_t *sb; + size_t memsize; Con_DPrintf ("\"%s\" will be cached\n", filename); // Decode it - buff = Mem_Alloc (s->mempool, (int)len); + buff = Mem_Alloc (snd_mempool, (int)len); done = 0; bs = 0; #if BYTE_ORDER == LITTLE_ENDIAN @@ -631,7 +667,9 @@ qboolean OGG_LoadVorbisFile (const char *filename, sfx_t *s) len = (double)done * (double)shm->format.speed / (double)vi->rate; // Resample it - sb = Mem_Alloc (s->mempool, (size_t)len + sizeof (*sb) - sizeof (sb->data)); + memsize = (size_t)len + sizeof (*sb) - sizeof (sb->data); + sb = Mem_Alloc (snd_mempool, memsize); + s->memsize += memsize; s->fetcher_data = sb; s->fetcher = &wav_fetcher; s->format.speed = vi->rate; diff --git a/snd_sdl.c b/snd_sdl.c index 38fb2053..ddd87fe1 100644 --- a/snd_sdl.c +++ b/snd_sdl.c @@ -39,7 +39,6 @@ typedef struct AudioState_s } AudioState; -extern mempool_t *snd_mempool; static AudioState as; static void Buffer_Callback(void *userdata, Uint8 *stream, int len); diff --git a/snd_wav.c b/snd_wav.c index 439ec73c..d8af1454 100644 --- a/snd_wav.c +++ b/snd_wav.c @@ -228,8 +228,24 @@ static const sfxbuffer_t* WAV_FetchSound (channel_t* ch, unsigned int start, uns return ch->sfx->fetcher_data; } +/* +==================== +WAV_FreeSfx +==================== +*/ +static void WAV_FreeSfx (sfx_t* sfx) +{ + sfxbuffer_t* sb = sfx->fetcher_data; -snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL }; + // Free the sound buffer + sfx->memsize -= (sb->length * sfx->format.channels * sfx->format.width) + sizeof (*sb) - sizeof (sb->data); + Mem_Free(sb); + + sfx->fetcher_data = NULL; + sfx->fetcher = NULL; +} + +const snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL, WAV_FreeSfx }; /* @@ -242,23 +258,22 @@ qboolean S_LoadWavFile (const char *filename, sfx_t *s) qbyte *data; wavinfo_t info; int len; + size_t memsize; sfxbuffer_t* sb; - Mem_FreePool (&s->mempool); - s->mempool = Mem_AllocPool(s->name, 0, NULL); + // Already loaded? + if (s->fetcher != NULL) + return true; // Load the file - data = FS_LoadFile(filename, s->mempool, false); + data = FS_LoadFile(filename, snd_mempool, false); if (!data) - { - Mem_FreePool (&s->mempool); return false; - } // Don't try to load it if it's not a WAV file if (memcmp (data, "RIFF", 4) || memcmp (data + 8, "WAVE", 4)) { - Mem_FreePool (&s->mempool); + Mem_Free(data); return false; } @@ -269,7 +284,7 @@ qboolean S_LoadWavFile (const char *filename, sfx_t *s) if (info.channels < 1 || info.channels > 2) { Con_Printf("%s has an unsupported number of channels (%i)\n",s->name, info.channels); - Mem_FreePool (&s->mempool); + Mem_Free(data); return false; } //if (info.channels == 2) @@ -279,13 +294,15 @@ qboolean S_LoadWavFile (const char *filename, sfx_t *s) len = (int) ((double) info.samples * (double) shm->format.speed / (double) info.rate); len = len * info.width * info.channels; - sb = Mem_Alloc (s->mempool, len + sizeof (*sb) - sizeof (sb->data)); + memsize = len + sizeof (*sb) - sizeof (sb->data); + sb = Mem_Alloc (snd_mempool, memsize); if (sb == NULL) { Con_Printf("failed to allocate memory for sound \"%s\"\n", s->name); - Mem_FreePool(&s->mempool); + Mem_Free(data); return false; } + s->memsize += memsize; s->fetcher = &wav_fetcher; s->fetcher_data = sb; diff --git a/snd_wav.h b/snd_wav.h index 638d1d3f..ae471620 100644 --- a/snd_wav.h +++ b/snd_wav.h @@ -26,7 +26,7 @@ #define SND_WAV_H -extern snd_fetcher_t wav_fetcher; +extern const snd_fetcher_t wav_fetcher; qboolean S_LoadWavFile (const char *filename, sfx_t *s); -- 2.39.2