From a1e05a11f1c94c609e55a1a25d72e5ed2eaf5ecb Mon Sep 17 00:00:00 2001 From: molivier Date: Thu, 25 Mar 2004 09:47:01 +0000 Subject: [PATCH] Moved the WAV loading code out of "snd_mem.c". Removed a couple of useless definitions in "sound.h". git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@4057 d7cf8633-e32d-0410-b094-e92efae38249 --- darkplaces.dsp | 8 ++ makefile.inc | 2 +- snd_dma.c | 4 + snd_mem.c | 289 +------------------------------------------- snd_ogg.c | 2 +- snd_wav.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++++ snd_wav.h | 34 ++++++ sound.h | 16 --- 8 files changed, 365 insertions(+), 306 deletions(-) create mode 100644 snd_wav.c create mode 100644 snd_wav.h diff --git a/darkplaces.dsp b/darkplaces.dsp index 271e44db..6a06fac7 100644 --- a/darkplaces.dsp +++ b/darkplaces.dsp @@ -372,6 +372,10 @@ SOURCE=.\snd_ogg.c # End Source File # Begin Source File +SOURCE=.\snd_wav.c +# End Source File +# Begin Source File + SOURCE=.\snd_win.c # End Source File # Begin Source File @@ -672,6 +676,10 @@ SOURCE=.\snd_ogg.h # End Source File # Begin Source File +SOURCE=.\snd_wav.h +# End Source File +# Begin Source File + SOURCE=.\sound.h # End Source File # Begin Source File diff --git a/makefile.inc b/makefile.inc index 4ae92164..e790de9b 100644 --- a/makefile.inc +++ b/makefile.inc @@ -18,7 +18,7 @@ CPUOPTIMIZATIONS= ##### Variables that you shouldn't care about ##### # Sound objects -OBJ_COMMONSOUND=snd_dma.o snd_mem.o snd_mix.o snd_ogg.o +OBJ_COMMONSOUND=snd_dma.o snd_mem.o snd_mix.o snd_ogg.o snd_wav.o OBJ_NOSOUND=snd_null.o # CD objects diff --git a/snd_dma.c b/snd_dma.c index ed1de728..6dbc1ea2 100644 --- a/snd_dma.c +++ b/snd_dma.c @@ -418,6 +418,8 @@ sfx_t *S_PrecacheSound (char *name, int complain) /* ================= SND_PickChannel + +Picks a channel based on priorities, empty slots, number of channels ================= */ channel_t *SND_PickChannel(int entnum, int entchannel) @@ -468,6 +470,8 @@ channel_t *SND_PickChannel(int entnum, int entchannel) /* ================= SND_Spatialize + +Spatializes a channel ================= */ void SND_Spatialize(channel_t *ch, int isstatic) diff --git a/snd_mem.c b/snd_mem.c index 5e1ea8f9..a10b2631 100644 --- a/snd_mem.c +++ b/snd_mem.c @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "snd_ogg.h" +#include "snd_wav.h" /* @@ -206,110 +207,6 @@ size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* //============================================================================= -wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength); - -/* -==================== -WAV_FetchSound -==================== -*/ -static const sfxbuffer_t* WAV_FetchSound (channel_t* ch, unsigned int start, unsigned int nbsamples) -{ - return ch->sfx->fetcher_data; -} - - -snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL }; - - -/* -============== -S_LoadWavFile -============== -*/ -qboolean S_LoadWavFile (const char *filename, sfx_t *s) -{ - qbyte *data; - wavinfo_t info; - int len; - sfxbuffer_t* sb; - - Mem_FreePool (&s->mempool); - s->mempool = Mem_AllocPool(s->name); - - // Load the file - data = FS_LoadFile(filename, s->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); - return false; - } - - Con_DPrintf ("Loading WAV file \"%s\"\n", filename); - - info = GetWavinfo (s->name, data, fs_filesize); - // Stereo sounds are allowed (intended for music) - 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); - return false; - } - - // calculate resampled length - 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)); - if (sb == NULL) - { - Con_Printf("failed to allocate memory for sound \"%s\"\n", s->name); - Mem_FreePool(&s->mempool); - return false; - } - - s->fetcher = &wav_fetcher; - s->fetcher_data = sb; - s->format.speed = info.rate; - s->format.width = info.width; - s->format.channels = info.channels; - if (info.loopstart < 0) - s->loopstart = -1; - else - s->loopstart = (double)info.loopstart * (double)shm->format.speed / (double)s->format.speed; - -#if BYTE_ORDER != LITTLE_ENDIAN - // We must convert the WAV data from little endian - // to the machine endianess before resampling it - if (info.width == 2) - { - int i; - short* ptr; - - len = info.samples * info.channels; - ptr = (short*)(data + info.dataofs); - for (i = 0; i < len; i++) - ptr[i] = LittleShort (ptr[i]); - } -#endif - - sb->length = ResampleSfx (data + info.dataofs, info.samples, &s->format, sb->data, s->name); - s->format.speed = shm->format.speed; - s->total_length = sb->length; - sb->offset = 0; - - Mem_Free (data); - return true; -} - - /* ============== S_LoadSound @@ -379,187 +276,3 @@ void S_UnloadSound(sfx_t *s) channels[i].fetcher_data = NULL; } } - - -/* -=============================================================================== - -WAV loading - -=============================================================================== -*/ - - -static qbyte *data_p; -static qbyte *iff_end; -static qbyte *last_chunk; -static qbyte *iff_data; -static int iff_chunk_len; - - -short GetLittleShort(void) -{ - short val; - - val = BuffLittleShort (data_p); - data_p += 2; - - return val; -} - -int GetLittleLong(void) -{ - int val = 0; - - val = BuffLittleLong (data_p); - data_p += 4; - - return val; -} - -void FindNextChunk(char *name) -{ - while (1) - { - data_p=last_chunk; - - if (data_p >= iff_end) - { // didn't find the chunk - data_p = NULL; - return; - } - - data_p += 4; - iff_chunk_len = GetLittleLong(); - if (iff_chunk_len < 0) - { - data_p = NULL; - return; - } - data_p -= 8; - last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); - if (!strncmp(data_p, name, 4)) - return; - } -} - -void FindChunk(char *name) -{ - last_chunk = iff_data; - FindNextChunk (name); -} - - -void DumpChunks(void) -{ - char str[5]; - - str[4] = 0; - data_p=iff_data; - do - { - memcpy (str, data_p, 4); - data_p += 4; - iff_chunk_len = GetLittleLong(); - Con_Printf("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); - data_p += (iff_chunk_len + 1) & ~1; - } while (data_p < iff_end); -} - -/* -============ -GetWavinfo -============ -*/ -wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength) -{ - wavinfo_t info; - int i; - int format; - int samples; - - memset (&info, 0, sizeof(info)); - - if (!wav) - return info; - - iff_data = wav; - iff_end = wav + wavlength; - - // find "RIFF" chunk - FindChunk("RIFF"); - if (!(data_p && !strncmp(data_p+8, "WAVE", 4))) - { - Con_Print("Missing RIFF/WAVE chunks\n"); - return info; - } - - // get "fmt " chunk - iff_data = data_p + 12; - //DumpChunks (); - - FindChunk("fmt "); - if (!data_p) - { - Con_Print("Missing fmt chunk\n"); - return info; - } - data_p += 8; - format = GetLittleShort(); - if (format != 1) - { - Con_Print("Microsoft PCM format only\n"); - return info; - } - - info.channels = GetLittleShort(); - info.rate = GetLittleLong(); - data_p += 4+2; - info.width = GetLittleShort() / 8; - - // get cue chunk - FindChunk("cue "); - if (data_p) - { - data_p += 32; - info.loopstart = GetLittleLong(); - - // if the next chunk is a LIST chunk, look for a cue length marker - FindNextChunk ("LIST"); - if (data_p) - { - if (!strncmp (data_p + 28, "mark", 4)) - { // this is not a proper parse, but it works with cooledit... - data_p += 24; - i = GetLittleLong (); // samples in loop - info.samples = info.loopstart + i; - } - } - } - else - info.loopstart = -1; - - // find data chunk - FindChunk("data"); - if (!data_p) - { - Con_Print("Missing data chunk\n"); - return info; - } - - data_p += 4; - samples = GetLittleLong () / info.width / info.channels; - - if (info.samples) - { - if (samples < info.samples) - Host_Error ("Sound %s has a bad loop length", name); - } - else - info.samples = samples; - - info.dataofs = data_p - wav; - - return info; -} - diff --git a/snd_ogg.c b/snd_ogg.c index c8eae942..18c500f7 100644 --- a/snd_ogg.c +++ b/snd_ogg.c @@ -24,6 +24,7 @@ #include "quakedef.h" #include "snd_ogg.h" +#include "snd_wav.h" /* @@ -482,7 +483,6 @@ static void OGG_FetchEnd (channel_t* ch) } static const snd_fetcher_t ogg_fetcher = { OGG_FetchSound, OGG_FetchEnd }; -extern snd_fetcher_t wav_fetcher; /* diff --git a/snd_wav.c b/snd_wav.c new file mode 100644 index 00000000..e11c2456 --- /dev/null +++ b/snd_wav.c @@ -0,0 +1,316 @@ +/* + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + + +#include "quakedef.h" +#include "snd_wav.h" + + +typedef struct +{ + int rate; + int width; + int channels; + int loopstart; + int samples; + int dataofs; // chunk starts this many bytes from file start +} wavinfo_t; + + +static qbyte *data_p; +static qbyte *iff_end; +static qbyte *last_chunk; +static qbyte *iff_data; +static int iff_chunk_len; + + +static short GetLittleShort(void) +{ + short val; + + val = BuffLittleShort (data_p); + data_p += 2; + + return val; +} + +static int GetLittleLong(void) +{ + int val = 0; + + val = BuffLittleLong (data_p); + data_p += 4; + + return val; +} + +static void FindNextChunk(char *name) +{ + while (1) + { + data_p=last_chunk; + + if (data_p >= iff_end) + { // didn't find the chunk + data_p = NULL; + return; + } + + data_p += 4; + iff_chunk_len = GetLittleLong(); + if (iff_chunk_len < 0) + { + data_p = NULL; + return; + } + data_p -= 8; + last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); + if (!strncmp(data_p, name, 4)) + return; + } +} + +static void FindChunk(char *name) +{ + last_chunk = iff_data; + FindNextChunk (name); +} + + +/* +static void DumpChunks(void) +{ + char str[5]; + + str[4] = 0; + data_p=iff_data; + do + { + memcpy (str, data_p, 4); + data_p += 4; + iff_chunk_len = GetLittleLong(); + Con_Printf("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len); + data_p += (iff_chunk_len + 1) & ~1; + } while (data_p < iff_end); +} +*/ + + +/* +============ +GetWavinfo +============ +*/ +static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength) +{ + wavinfo_t info; + int i; + int format; + int samples; + + memset (&info, 0, sizeof(info)); + + if (!wav) + return info; + + iff_data = wav; + iff_end = wav + wavlength; + + // find "RIFF" chunk + FindChunk("RIFF"); + if (!(data_p && !strncmp(data_p+8, "WAVE", 4))) + { + Con_Print("Missing RIFF/WAVE chunks\n"); + return info; + } + + // get "fmt " chunk + iff_data = data_p + 12; + //DumpChunks (); + + FindChunk("fmt "); + if (!data_p) + { + Con_Print("Missing fmt chunk\n"); + return info; + } + data_p += 8; + format = GetLittleShort(); + if (format != 1) + { + Con_Print("Microsoft PCM format only\n"); + return info; + } + + info.channels = GetLittleShort(); + info.rate = GetLittleLong(); + data_p += 4+2; + info.width = GetLittleShort() / 8; + + // get cue chunk + FindChunk("cue "); + if (data_p) + { + data_p += 32; + info.loopstart = GetLittleLong(); + + // if the next chunk is a LIST chunk, look for a cue length marker + FindNextChunk ("LIST"); + if (data_p) + { + if (!strncmp (data_p + 28, "mark", 4)) + { // this is not a proper parse, but it works with cooledit... + data_p += 24; + i = GetLittleLong (); // samples in loop + info.samples = info.loopstart + i; + } + } + } + else + info.loopstart = -1; + + // find data chunk + FindChunk("data"); + if (!data_p) + { + Con_Print("Missing data chunk\n"); + return info; + } + + data_p += 4; + samples = GetLittleLong () / info.width / info.channels; + + if (info.samples) + { + if (samples < info.samples) + Host_Error ("Sound %s has a bad loop length", name); + } + else + info.samples = samples; + + info.dataofs = data_p - wav; + + return info; +} + + +/* +==================== +WAV_FetchSound +==================== +*/ +static const sfxbuffer_t* WAV_FetchSound (channel_t* ch, unsigned int start, unsigned int nbsamples) +{ + return ch->sfx->fetcher_data; +} + + +snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL }; + + +/* +============== +S_LoadWavFile +============== +*/ +qboolean S_LoadWavFile (const char *filename, sfx_t *s) +{ + qbyte *data; + wavinfo_t info; + int len; + sfxbuffer_t* sb; + + Mem_FreePool (&s->mempool); + s->mempool = Mem_AllocPool(s->name); + + // Load the file + data = FS_LoadFile(filename, s->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); + return false; + } + + Con_DPrintf ("Loading WAV file \"%s\"\n", filename); + + info = GetWavinfo (s->name, data, fs_filesize); + // Stereo sounds are allowed (intended for music) + 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); + return false; + } + + // calculate resampled length + 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)); + if (sb == NULL) + { + Con_Printf("failed to allocate memory for sound \"%s\"\n", s->name); + Mem_FreePool(&s->mempool); + return false; + } + + s->fetcher = &wav_fetcher; + s->fetcher_data = sb; + s->format.speed = info.rate; + s->format.width = info.width; + s->format.channels = info.channels; + if (info.loopstart < 0) + s->loopstart = -1; + else + s->loopstart = (double)info.loopstart * (double)shm->format.speed / (double)s->format.speed; + +#if BYTE_ORDER != LITTLE_ENDIAN + // We must convert the WAV data from little endian + // to the machine endianess before resampling it + if (info.width == 2) + { + int i; + short* ptr; + + len = info.samples * info.channels; + ptr = (short*)(data + info.dataofs); + for (i = 0; i < len; i++) + ptr[i] = LittleShort (ptr[i]); + } +#endif + + sb->length = ResampleSfx (data + info.dataofs, info.samples, &s->format, sb->data, s->name); + s->format.speed = shm->format.speed; + s->total_length = sb->length; + sb->offset = 0; + + Mem_Free (data); + return true; +} diff --git a/snd_wav.h b/snd_wav.h new file mode 100644 index 00000000..638d1d3f --- /dev/null +++ b/snd_wav.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + + +#ifndef SND_WAV_H +#define SND_WAV_H + + +extern snd_fetcher_t wav_fetcher; + +qboolean S_LoadWavFile (const char *filename, sfx_t *s); + + +#endif diff --git a/sound.h b/sound.h index c25ef15c..ada3b519 100644 --- a/sound.h +++ b/sound.h @@ -97,16 +97,6 @@ struct snd_fetcher_s snd_fetcher_end_t end; }; -typedef struct -{ - int rate; - int width; - int channels; - int loopstart; - int samples; - int dataofs; // chunk starts this many bytes from file start -} wavinfo_t; - void S_Init (void); void S_Startup (void); void S_Shutdown (void); @@ -126,12 +116,6 @@ void S_PurgeUnused (void); void S_PaintChannels(int endtime); void S_InitPaintChannels (void); -// picks a channel based on priorities, empty slots, number of channels -channel_t *SND_PickChannel(int entnum, int entchannel); - -// spatializes a channel -void SND_Spatialize(channel_t *ch, int isstatic); - // initializes cycling through a DMA buffer and returns information on it qboolean SNDDMA_Init(void); -- 2.39.2