]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_wav.c
Add an in_releaseall command for debugging/working around stuck keys.
[xonotic/darkplaces.git] / snd_wav.c
index d8af145438f82936a48b894b86bb201ec9b59a0d..6f861913335007bb2f155a68aa5b672c16cdaaee 100644 (file)
--- a/snd_wav.c
+++ b/snd_wav.c
@@ -27,7 +27,7 @@
 #include "snd_wav.h"
 
 
-typedef struct
+typedef struct wavinfo_s
 {
        int             rate;
        int             width;
@@ -38,10 +38,10 @@ typedef struct
 } wavinfo_t;
 
 
-static qbyte *data_p;
-static qbyte *iff_end;
-static qbyte *last_chunk;
-static qbyte *iff_data;
+static unsigned char *data_p;
+static unsigned char *iff_end;
+static unsigned char *last_chunk;
+static unsigned char *iff_data;
 static int iff_chunk_len;
 
 
@@ -65,7 +65,7 @@ static int GetLittleLong(void)
        return val;
 }
 
-static void FindNextChunk(char *name)
+static void FindNextChunk(const char *name)
 {
        while (1)
        {
@@ -84,14 +84,20 @@ static void FindNextChunk(char *name)
                        data_p = NULL;
                        return;
                }
+               if (data_p + iff_chunk_len > iff_end)
+               {
+                       // truncated chunk!
+                       data_p = NULL;
+                       return;
+               }
                data_p -= 8;
                last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
-               if (!strncmp(data_p, name, 4))
+               if (!strncmp((const char *)data_p, name, 4))
                        return;
        }
 }
 
-static void FindChunk(char *name)
+static void FindChunk(const char *name)
 {
        last_chunk = iff_data;
        FindNextChunk (name);
@@ -122,7 +128,7 @@ static void DumpChunks(void)
 GetWavinfo
 ============
 */
-static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
+static wavinfo_t GetWavinfo (char *name, unsigned char *wav, int wavlength)
 {
        wavinfo_t info;
        int i;
@@ -139,7 +145,7 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
 
        // find "RIFF" chunk
        FindChunk("RIFF");
-       if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
+       if (!(data_p && !strncmp((const char *)data_p+8, "WAVE", 4)))
        {
                Con_Print("Missing RIFF/WAVE chunks\n");
                return info;
@@ -179,7 +185,7 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
                FindNextChunk ("LIST");
                if (data_p)
                {
-                       if (!strncmp (data_p + 28, "mark", 4))
+                       if (!strncmp ((const char *)data_p + 28, "mark", 4))
                        {       // this is not a proper parse, but it works with cooledit...
                                data_p += 24;
                                i = GetLittleLong ();   // samples in loop
@@ -205,7 +211,7 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
        {
                if (samples < info.samples)
                {
-                       Con_Printf ("Sound %s has a bad loop length", name);
+                       Con_Printf ("Sound %s has a bad loop length\n", name);
                        info.samples = samples;
                }
        }
@@ -220,12 +226,24 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
 
 /*
 ====================
-WAV_FetchSound
+WAV_GetSamplesFloat
 ====================
 */
-static const sfxbuffer_t* WAV_FetchSound (channel_t* ch, unsigned int start, unsigned int nbsamples)
+static void WAV_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
 {
-       return ch->sfx->fetcher_data;
+       int i, len = numsampleframes * sfx->format.channels;
+       if (sfx->format.width == 2)
+       {
+               const short *bufs = (const short *)sfx->fetcher_data + firstsampleframe * sfx->format.channels;
+               for (i = 0;i < len;i++)
+                       outsamplesfloat[i] = bufs[i] * (1.0f / 32768.0f);
+       }
+       else
+       {
+               const signed char *bufb = (const signed char *)sfx->fetcher_data + firstsampleframe * sfx->format.channels;
+               for (i = 0;i < len;i++)
+                       outsamplesfloat[i] = bufb[i] * (1.0f / 128.0f);
+       }
 }
 
 /*
@@ -233,19 +251,13 @@ static const sfxbuffer_t* WAV_FetchSound (channel_t* ch, unsigned int start, uns
 WAV_FreeSfx
 ====================
 */
-static void WAV_FreeSfx (sfx_t* sfx)
+static void WAV_FreeSfx(sfx_t *sfx)
 {
-       sfxbuffer_t* sb = sfx->fetcher_data;
-
-       // 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;
+       // free the loaded sound data
+       Mem_Free(sfx->fetcher_data);
 }
 
-const snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL, WAV_FreeSfx };
+const snd_fetcher_t wav_fetcher = { WAV_GetSamplesFloat, NULL, WAV_FreeSfx };
 
 
 /*
@@ -253,20 +265,21 @@ const snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL, WAV_FreeSfx };
 S_LoadWavFile
 ==============
 */
-qboolean S_LoadWavFile (const char *filename, sfx_t *s)
+qboolean S_LoadWavFile (const char *filename, sfx_t *sfx)
 {
-       qbyte *data;
+       fs_offset_t filesize;
+       unsigned char *data;
        wavinfo_t info;
-       int len;
-       size_t memsize;
-       sfxbuffer_t* sb;
+       int i, len;
+       const unsigned char *inb;
+       unsigned char *outb;
 
        // Already loaded?
-       if (s->fetcher != NULL)
+       if (sfx->fetcher != NULL)
                return true;
 
        // Load the file
-       data = FS_LoadFile(filename, snd_mempool, false);
+       data = FS_LoadFile(filename, snd_mempool, false, &filesize);
        if (!data)
                return false;
 
@@ -277,64 +290,59 @@ qboolean S_LoadWavFile (const char *filename, sfx_t *s)
                return false;
        }
 
-       Con_DPrintf ("Loading WAV file \"%s\"\n", filename);
+       if (developer_loading.integer >= 2)
+               Con_Printf ("Loading WAV file \"%s\"\n", filename);
 
-       info = GetWavinfo (s->name, data, (int)fs_filesize);
-       // Stereo sounds are allowed (intended for music)
-       if (info.channels < 1 || info.channels > 2)
+       info = GetWavinfo (sfx->name, data, (int)filesize);
+       if (info.channels < 1 || info.channels > 2)  // Stereo sounds are allowed (intended for music)
        {
-               Con_Printf("%s has an unsupported number of channels (%i)\n",s->name, info.channels);
+               Con_Printf("%s has an unsupported number of channels (%i)\n",sfx->name, info.channels);
                Mem_Free(data);
                return false;
        }
        //if (info.channels == 2)
-       //      Log_Printf("stereosounds.log", "%s\n", s->name);
-
-       // calculate resampled length
-       len = (int) ((double) info.samples * (double) shm->format.speed / (double) info.rate);
-       len = len * info.width * info.channels;
-
-       memsize = len + sizeof (*sb) - sizeof (sb->data);
-       sb = Mem_Alloc (snd_mempool, memsize);
-       if (sb == NULL)
+       //      Log_Printf("stereosounds.log", "%s\n", sfx->name);
+
+       sfx->format.speed = info.rate;
+       sfx->format.width = info.width;
+       sfx->format.channels = info.channels;
+       sfx->fetcher = &wav_fetcher;
+       sfx->fetcher_data = Mem_Alloc(snd_mempool, info.samples * sfx->format.width * sfx->format.channels);
+       sfx->total_length = info.samples;
+       sfx->memsize += filesize;
+       len = info.samples * sfx->format.channels * sfx->format.width;
+       inb = data + info.dataofs;
+       outb = (unsigned char *)sfx->fetcher_data;
+       if (info.width == 2)
        {
-               Con_Printf("failed to allocate memory for sound \"%s\"\n", s->name);
-               Mem_Free(data);
-               return false;
+               if (mem_bigendian)
+               {
+                       // we have to byteswap the data at load (better than doing it while mixing)
+                       for (i = 0;i < len;i += 2)
+                       {
+                               outb[i] = inb[i+1];
+                               outb[i+1] = inb[i];
+                       }
+               }
+               else
+               {
+                       // we can just copy it straight
+                       memcpy(outb, inb, len);
+               }
        }
-       s->memsize += memsize;
-
-       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;
-       s->flags &= ~SFXFLAG_STREAMED;
-
-#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]);
+               // convert unsigned byte sound data to signed bytes for quicker mixing
+               for (i = 0;i < len;i++)
+                       outb[i] = inb[i] - 0x80;
        }
-#endif
 
-       sb->length = (int)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;
+       if (info.loopstart < 0)
+               sfx->loopstart = sfx->total_length;
+       else
+               sfx->loopstart = info.loopstart;
+       sfx->loopstart = min(sfx->loopstart, sfx->total_length);
+       sfx->flags &= ~SFXFLAG_STREAMED;
 
-       Mem_Free (data);
        return true;
 }