]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_wav.c
Fix a missing newline in system vars mismatch warning.
[xonotic/darkplaces.git] / snd_wav.c
index 89bd6c6e4cd9f5ba45406507929aa235c883345d..6f861913335007bb2f155a68aa5b672c16cdaaee 100644 (file)
--- a/snd_wav.c
+++ b/snd_wav.c
@@ -65,7 +65,7 @@ static int GetLittleLong(void)
        return val;
 }
 
-static void FindNextChunk(char *name)
+static void FindNextChunk(const char *name)
 {
        while (1)
        {
@@ -84,6 +84,12 @@ 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((const char *)data_p, name, 4))
@@ -91,7 +97,7 @@ static void FindNextChunk(char *name)
        }
 }
 
-static void FindChunk(char *name)
+static void FindChunk(const char *name)
 {
        last_chunk = iff_data;
        FindNextChunk (name);
@@ -220,12 +226,24 @@ static wavinfo_t GetWavinfo (char *name, unsigned char *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 (sfxbuffer_t *)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 = (sfxbuffer_t *)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,17 +265,17 @@ 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)
 {
        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
@@ -278,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)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 = (sfxbuffer_t *)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 = (int)((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;
 }