2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to:
18 Free Software Foundation, Inc.
19 59 Temple Place - Suite 330
20 Boston, MA 02111-1307, USA
36 int dataofs; // chunk starts this many bytes from file start
41 static qbyte *iff_end;
42 static qbyte *last_chunk;
43 static qbyte *iff_data;
44 static int iff_chunk_len;
47 static short GetLittleShort(void)
51 val = BuffLittleShort (data_p);
57 static int GetLittleLong(void)
61 val = BuffLittleLong (data_p);
67 static void FindNextChunk(char *name)
73 if (data_p >= iff_end)
74 { // didn't find the chunk
80 iff_chunk_len = GetLittleLong();
81 if (iff_chunk_len < 0)
87 last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
88 if (!strncmp(data_p, name, 4))
93 static void FindChunk(char *name)
95 last_chunk = iff_data;
101 static void DumpChunks(void)
109 memcpy (str, data_p, 4);
111 iff_chunk_len = GetLittleLong();
112 Con_Printf("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
113 data_p += (iff_chunk_len + 1) & ~1;
114 } while (data_p < iff_end);
124 static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
131 memset (&info, 0, sizeof(info));
137 iff_end = wav + wavlength;
141 if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
143 Con_Print("Missing RIFF/WAVE chunks\n");
148 iff_data = data_p + 12;
154 Con_Print("Missing fmt chunk\n");
158 format = GetLittleShort();
161 Con_Print("Microsoft PCM format only\n");
165 info.channels = GetLittleShort();
166 info.rate = GetLittleLong();
168 info.width = GetLittleShort() / 8;
175 info.loopstart = GetLittleLong();
177 // if the next chunk is a LIST chunk, look for a cue length marker
178 FindNextChunk ("LIST");
181 if (!strncmp (data_p + 28, "mark", 4))
182 { // this is not a proper parse, but it works with cooledit...
184 i = GetLittleLong (); // samples in loop
185 info.samples = info.loopstart + i;
196 Con_Print("Missing data chunk\n");
201 samples = GetLittleLong () / info.width / info.channels;
205 if (samples < info.samples)
206 Host_Error ("Sound %s has a bad loop length", name);
209 info.samples = samples;
211 info.dataofs = data_p - wav;
222 static const sfxbuffer_t* WAV_FetchSound (channel_t* ch, unsigned int start, unsigned int nbsamples)
224 return ch->sfx->fetcher_data;
228 snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL };
236 qboolean S_LoadWavFile (const char *filename, sfx_t *s)
243 Mem_FreePool (&s->mempool);
244 s->mempool = Mem_AllocPool(s->name);
247 data = FS_LoadFile(filename, s->mempool, false);
250 Mem_FreePool (&s->mempool);
254 // Don't try to load it if it's not a WAV file
255 if (memcmp (data, "RIFF", 4) || memcmp (data + 8, "WAVE", 4))
257 Mem_FreePool (&s->mempool);
261 Con_DPrintf ("Loading WAV file \"%s\"\n", filename);
263 info = GetWavinfo (s->name, data, fs_filesize);
264 // Stereo sounds are allowed (intended for music)
265 if (info.channels < 1 || info.channels > 2)
267 Con_Printf("%s has an unsupported number of channels (%i)\n",s->name, info.channels);
268 Mem_FreePool (&s->mempool);
272 // calculate resampled length
273 len = (int) ((double) info.samples * (double) shm->format.speed / (double) info.rate);
274 len = len * info.width * info.channels;
276 sb = Mem_Alloc (s->mempool, len + sizeof (*sb) - sizeof (sb->data));
279 Con_Printf("failed to allocate memory for sound \"%s\"\n", s->name);
280 Mem_FreePool(&s->mempool);
284 s->fetcher = &wav_fetcher;
285 s->fetcher_data = sb;
286 s->format.speed = info.rate;
287 s->format.width = info.width;
288 s->format.channels = info.channels;
289 if (info.loopstart < 0)
292 s->loopstart = (double)info.loopstart * (double)shm->format.speed / (double)s->format.speed;
294 #if BYTE_ORDER != LITTLE_ENDIAN
295 // We must convert the WAV data from little endian
296 // to the machine endianess before resampling it
302 len = info.samples * info.channels;
303 ptr = (short*)(data + info.dataofs);
304 for (i = 0; i < len; i++)
305 ptr[i] = LittleShort (ptr[i]);
309 sb->length = ResampleSfx (data + info.dataofs, info.samples, &s->format, sb->data, s->name);
310 s->format.speed = shm->format.speed;
311 s->total_length = sb->length;