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 the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // snd_mem.c: sound caching
32 size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* in_format, qbyte *out_data, const char* sfxname)
34 int samplefrac, fracstep;
35 size_t i, srcsample, srclength, outcount;
37 // this is usually 0.5 (128), 1 (256), or 2 (512)
38 fracstep = ((double) in_format->speed / (double) shm->format.speed) * 256.0;
40 srclength = in_length * in_format->channels;
42 outcount = (double) in_length * (double) shm->format.speed / (double) in_format->speed;
43 Con_DPrintf("ResampleSfx: resampling sound \"%s\" from %dHz to %dHz (%d samples to %d samples)\n",
44 sfxname, in_format->speed, shm->format.speed, in_length, outcount);
46 // resample / decimate to the current source rate
50 // fast case for direct transfer
51 if (in_format->width == 1) // 8bit
52 for (i = 0;i < srclength;i++)
53 ((signed char *)out_data)[i] = ((unsigned char *)in_data)[i] - 128;
54 else //if (sb->width == 2) // 16bit
55 for (i = 0;i < srclength;i++)
56 ((short *)out_data)[i] = ((short *)in_data)[i];
62 if ((fracstep & 255) == 0) // skipping points on perfect multiple
66 if (in_format->width == 2)
68 short *out = (short*)out_data;
69 const short *in = (const short*)in_data;
70 if (in_format->channels == 2) // LordHavoc: stereo sound support
73 for (i=0 ; i<outcount ; i++)
75 *out++ = in[srcsample ];
76 *out++ = in[srcsample+1];
77 srcsample += fracstep;
82 for (i=0 ; i<outcount ; i++)
84 *out++ = in[srcsample];
85 srcsample += fracstep;
91 signed char *out = out_data;
92 const unsigned char *in = in_data;
93 if (in_format->channels == 2)
96 for (i=0 ; i<outcount ; i++)
98 *out++ = in[srcsample ] - 128;
99 *out++ = in[srcsample+1] - 128;
100 srcsample += fracstep;
105 for (i=0 ; i<outcount ; i++)
107 *out++ = in[srcsample ] - 128;
108 srcsample += fracstep;
117 if (in_format->width == 2)
119 short *out = (short*)out_data;
120 const short *in = (const short*)in_data;
121 if (in_format->channels == 2)
123 for (i=0 ; i<outcount ; i++)
125 srcsample = (samplefrac >> 8) << 1;
127 if (srcsample+2 >= srclength)
131 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
132 *out++ = (short) sample;
134 if (srcsample+2 >= srclength)
138 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
139 *out++ = (short) sample;
140 samplefrac += fracstep;
145 for (i=0 ; i<outcount ; i++)
147 srcsample = samplefrac >> 8;
149 if (srcsample+1 >= srclength)
153 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
154 *out++ = (short) sample;
155 samplefrac += fracstep;
161 signed char *out = out_data;
162 const unsigned char *in = in_data;
163 if (in_format->channels == 2)
165 for (i=0 ; i<outcount ; i++)
167 srcsample = (samplefrac >> 8) << 1;
168 a = (int) in[srcsample ] - 128;
169 if (srcsample+2 >= srclength)
172 b = (int) in[srcsample+2] - 128;
173 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
174 *out++ = (signed char) sample;
175 a = (int) in[srcsample+1] - 128;
176 if (srcsample+2 >= srclength)
179 b = (int) in[srcsample+3] - 128;
180 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
181 *out++ = (signed char) sample;
182 samplefrac += fracstep;
187 for (i=0 ; i<outcount ; i++)
189 srcsample = samplefrac >> 8;
190 a = (int) in[srcsample ] - 128;
191 if (srcsample+1 >= srclength)
194 b = (int) in[srcsample+1] - 128;
195 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
196 *out++ = (signed char) sample;
197 samplefrac += fracstep;
207 //=============================================================================
209 wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength);
216 static const sfxbuffer_t* WAV_FetchSound (channel_t* ch, unsigned int start, unsigned int nbsamples)
218 return ch->sfx->fetcher_data;
222 snd_fetcher_t wav_fetcher = { WAV_FetchSound, NULL };
230 qboolean S_LoadWavFile (const char *filename, sfx_t *s)
237 Mem_FreePool (&s->mempool);
238 s->mempool = Mem_AllocPool(s->name);
241 data = FS_LoadFile(filename, s->mempool, false);
244 Mem_FreePool (&s->mempool);
248 // Don't try to load it if it's not a WAV file
249 if (memcmp (data, "RIFF", 4) || memcmp (data + 8, "WAVE", 4))
251 Mem_FreePool (&s->mempool);
255 Con_DPrintf ("Loading WAV file \"%s\"\n", filename);
257 info = GetWavinfo (s->name, data, fs_filesize);
258 // Stereo sounds are allowed (intended for music)
259 if (info.channels < 1 || info.channels > 2)
261 Con_Printf("%s has an unsupported number of channels (%i)\n",s->name, info.channels);
262 Mem_FreePool (&s->mempool);
266 // calculate resampled length
267 len = (int) ((double) info.samples * (double) shm->format.speed / (double) info.rate);
268 len = len * info.width * info.channels;
270 sb = Mem_Alloc (s->mempool, len + sizeof (*sb) - sizeof (sb->data));
273 Con_Printf("failed to allocate memory for sound \"%s\"\n", s->name);
274 Mem_FreePool(&s->mempool);
278 s->fetcher = &wav_fetcher;
279 s->fetcher_data = sb;
280 s->format.speed = info.rate;
281 s->format.width = info.width;
282 s->format.channels = info.channels;
283 if (info.loopstart < 0)
286 s->loopstart = (double)info.loopstart * (double)shm->format.speed / (double)s->format.speed;
288 #if BYTE_ORDER != LITTLE_ENDIAN
289 // We must convert the WAV data from little endian
290 // to the machine endianess before resampling it
296 len = info.samples * info.channels;
297 ptr = (short*)(data + info.dataofs);
298 for (i = 0; i < len; i++)
299 ptr[i] = LittleShort (ptr[i]);
303 sb->length = ResampleSfx (data + info.dataofs, info.samples, &s->format, sb->data, s->name);
304 s->format.speed = shm->format.speed;
305 s->total_length = sb->length;
318 qboolean S_LoadSound (sfx_t *s, int complain)
320 char namebuffer[MAX_QPATH];
322 qboolean modified_name = false;
324 // see if still in memory
325 if (!shm || !shm->format.speed)
327 if (s->fetcher != NULL)
329 if (s->format.speed != shm->format.speed)
330 Sys_Error ("S_LoadSound: sound %s hasn't been resampled (%uHz instead of %uHz)", s->name);
334 len = snprintf (namebuffer, sizeof (namebuffer), "sound/%s", s->name);
335 if (len >= sizeof (namebuffer))
338 // Try to load it as a WAV file
339 if (S_LoadWavFile (namebuffer, s))
342 // Else, try to load it as an Ogg Vorbis file
343 if (!strcasecmp (namebuffer + len - 4, ".wav"))
345 strcpy (namebuffer + len - 3, "ogg");
346 modified_name = true;
348 if (OGG_LoadVorbisFile (namebuffer, s))
351 // Can't load the sound!
353 s->flags |= SFXFLAG_SILENTLYMISSING;
355 s->flags &= ~SFXFLAG_SILENTLYMISSING;
359 strcpy (namebuffer + len - 3, "wav");
360 Con_Printf("Couldn't load %s\n", namebuffer);
365 void S_UnloadSound(sfx_t *s)
367 if (s->fetcher != NULL)
372 s->fetcher_data = NULL;
373 Mem_FreePool(&s->mempool);
375 // At this point, some per-channel data pointers may point to freed zones.
376 // Practically, it shouldn't be a problem; but it's wrong, so we fix that
377 for (i = 0; i < total_channels ; i++)
378 if (channels[i].sfx == s)
379 channels[i].fetcher_data = NULL;
385 ===============================================================================
389 ===============================================================================
393 static qbyte *data_p;
394 static qbyte *iff_end;
395 static qbyte *last_chunk;
396 static qbyte *iff_data;
397 static int iff_chunk_len;
400 short GetLittleShort(void)
404 val = BuffLittleShort (data_p);
410 int GetLittleLong(void)
414 val = BuffLittleLong (data_p);
420 void FindNextChunk(char *name)
426 if (data_p >= iff_end)
427 { // didn't find the chunk
433 iff_chunk_len = GetLittleLong();
434 if (iff_chunk_len < 0)
440 last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
441 if (!strncmp(data_p, name, 4))
446 void FindChunk(char *name)
448 last_chunk = iff_data;
449 FindNextChunk (name);
453 void DumpChunks(void)
461 memcpy (str, data_p, 4);
463 iff_chunk_len = GetLittleLong();
464 Con_Printf("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
465 data_p += (iff_chunk_len + 1) & ~1;
466 } while (data_p < iff_end);
474 wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
481 memset (&info, 0, sizeof(info));
487 iff_end = wav + wavlength;
491 if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
493 Con_Print("Missing RIFF/WAVE chunks\n");
498 iff_data = data_p + 12;
504 Con_Print("Missing fmt chunk\n");
508 format = GetLittleShort();
511 Con_Print("Microsoft PCM format only\n");
515 info.channels = GetLittleShort();
516 info.rate = GetLittleLong();
518 info.width = GetLittleShort() / 8;
525 info.loopstart = GetLittleLong();
527 // if the next chunk is a LIST chunk, look for a cue length marker
528 FindNextChunk ("LIST");
531 if (!strncmp (data_p + 28, "mark", 4))
532 { // this is not a proper parse, but it works with cooledit...
534 i = GetLittleLong (); // samples in loop
535 info.samples = info.loopstart + i;
546 Con_Print("Missing data chunk\n");
551 samples = GetLittleLong () / info.width / info.channels;
555 if (samples < info.samples)
556 Host_Error ("Sound %s has a bad loop length", name);
559 info.samples = samples;
561 info.dataofs = data_p - wav;