X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=snd_wav.c;h=d23a8b5126487ca3b01196c8c5c17ffc61492565;hp=ff4bb4069f3c56845ef279e8cdf3358a8433006b;hb=73f27d62983b6af1cb9a6971d0a4cb6275b91a07;hpb=75b340111c3e3199c1a7193f66dc8819d01ff655 diff --git a/snd_wav.c b/snd_wav.c index ff4bb406..d23a8b51 100644 --- a/snd_wav.c +++ b/snd_wav.c @@ -22,12 +22,12 @@ */ -#include "quakedef.h" +#include "darkplaces.h" #include "snd_main.h" #include "snd_wav.h" +#include "sound.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 @@ -204,7 +210,10 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength) if (info.samples) { if (samples < info.samples) - Host_Error ("Sound %s has a bad loop length", name); + { + Con_Printf ("Sound %s has a bad loop length\n", name); + info.samples = samples; + } } else info.samples = samples; @@ -217,16 +226,38 @@ 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); + } } +/* +==================== +WAV_FreeSfx +==================== +*/ +static void WAV_FreeSfx(sfx_t *sfx) +{ + // free the loaded sound data + Mem_Free(sfx->fetcher_data); +} -snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL }; +const snd_fetcher_t wav_fetcher = { WAV_GetSamplesFloat, NULL, WAV_FreeSfx }; /* @@ -234,87 +265,85 @@ snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL }; S_LoadWavFile ============== */ -qboolean S_LoadWavFile (const char *filename, sfx_t *s) +qbool S_LoadWavFile (const char *filename, sfx_t *sfx) { - qbyte *data; + fs_offset_t filesize; + unsigned char *data; wavinfo_t info; - int len; - sfxbuffer_t* sb; + int i, len; + const unsigned char *inb; + unsigned char *outb; - Mem_FreePool (&s->mempool); - s->mempool = Mem_AllocPool(s->name, 0, NULL); + // Already loaded? + if (sfx->fetcher != NULL) + return true; // Load the file - data = FS_LoadFile(filename, s->mempool, false); + data = FS_LoadFile(filename, snd_mempool, false, &filesize); 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; } - 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, 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); - Mem_FreePool (&s->mempool); + 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; - - sb = Mem_Alloc (s->mempool, len + sizeof (*sb) - sizeof (sb->data)); - 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_FreePool(&s->mempool); - 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->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 = 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); + Mem_Free(data); // we already got a copy of this in fetcher_data return true; }