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.
27 #include "snd_modplug.h"
29 unsigned char resampling_buffer [48000 * 2 * 2];
36 If "buffer" is NULL, the function allocates one buffer of "sampleframes" sample frames itself
37 (if "sampleframes" is 0, the function chooses the size).
40 snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int sampleframes, void* buffer)
42 snd_ringbuffer_t *ringbuffer;
44 // If the caller provides a buffer, it must give us its size
45 if (sampleframes == 0 && buffer != NULL)
48 ringbuffer = (snd_ringbuffer_t*)Mem_Alloc(snd_mempool, sizeof (*ringbuffer));
49 memset(ringbuffer, 0, sizeof(*ringbuffer));
50 memcpy(&ringbuffer->format, format, sizeof(ringbuffer->format));
52 // If we haven't been given a buffer
55 unsigned int maxframes;
58 if (sampleframes == 0)
59 maxframes = (format->speed + 1) / 2; // Make the sound buffer large enough for containing 0.5 sec of sound
61 maxframes = sampleframes;
63 memsize = maxframes * format->width * format->channels;
64 ringbuffer->ring = (unsigned char *) Mem_Alloc(snd_mempool, memsize);
65 ringbuffer->maxframes = maxframes;
69 ringbuffer->ring = (unsigned char *) buffer;
70 ringbuffer->maxframes = sampleframes;
82 snd_buffer_t *Snd_CreateSndBuffer (const unsigned char *samples, unsigned int sampleframes, const snd_format_t* in_format, unsigned int sb_speed)
84 size_t newsampleframes, memsize;
87 newsampleframes = (size_t) ceil((double)sampleframes * (double)sb_speed / (double)in_format->speed);
89 memsize = newsampleframes * in_format->channels * in_format->width;
90 memsize += sizeof (*sb) - sizeof (sb->samples);
92 sb = (snd_buffer_t*)Mem_Alloc (snd_mempool, memsize);
93 sb->format.channels = in_format->channels;
94 sb->format.width = in_format->width;
95 sb->format.speed = sb_speed;
96 sb->maxframes = newsampleframes;
99 if (!Snd_AppendToSndBuffer (sb, samples, sampleframes, in_format))
111 Snd_AppendToSndBuffer
114 qboolean Snd_AppendToSndBuffer (snd_buffer_t* sb, const unsigned char *samples, unsigned int sampleframes, const snd_format_t* format)
116 size_t srclength, outcount;
117 unsigned char *out_data;
119 //Con_DPrintf("ResampleSfx: %d samples @ %dHz -> %d samples @ %dHz\n",
120 // sampleframes, format->speed, outcount, sb->format.speed);
122 // If the formats are incompatible
123 if (sb->format.channels != format->channels || sb->format.width != format->width)
125 Con_Print("AppendToSndBuffer: incompatible sound formats!\n");
129 outcount = (size_t) ((double)sampleframes * (double)sb->format.speed / (double)format->speed);
131 // If the sound buffer is too short
132 if (outcount > sb->maxframes - sb->nbframes)
134 Con_Print("AppendToSndBuffer: sound buffer too short!\n");
138 out_data = &sb->samples[sb->nbframes * sb->format.width * sb->format.channels];
139 srclength = sampleframes * format->channels;
141 // Trivial case (direct transfer)
142 if (format->speed == sb->format.speed)
144 if (format->width == 1)
148 for (i = 0; i < srclength; i++)
149 ((signed char*)out_data)[i] = samples[i] - 128;
151 else // if (format->width == 2)
152 memcpy (out_data, samples, srclength * format->width);
155 // General case (linear interpolation with a fixed-point fractional
156 // step, 18-bit integer part and 14-bit fractional part)
157 // Can handle up to 2^18 (262144) samples per second (> 96KHz stereo)
158 # define FRACTIONAL_BITS 14
159 # define FRACTIONAL_MASK ((1 << FRACTIONAL_BITS) - 1)
160 # define INTEGER_BITS (sizeof(samplefrac)*8 - FRACTIONAL_BITS)
163 const unsigned int fracstep = (unsigned int)((double)format->speed / sb->format.speed * (1 << FRACTIONAL_BITS));
164 size_t remain_in = srclength, total_out = 0;
165 unsigned int samplefrac;
166 const unsigned char *in_ptr = samples;
167 unsigned char *out_ptr = out_data;
169 // Check that we can handle one second of that sound
170 if (format->speed * format->channels > (1 << INTEGER_BITS))
172 Con_Printf ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))\n",
173 format->speed, format->channels);
177 // We work 1 sec at a time to make sure we don't accumulate any
178 // significant error when adding "fracstep" over several seconds, and
179 // also to be able to handle very long sounds.
180 while (total_out < outcount)
182 size_t tmpcount, interpolation_limit, i, j;
183 unsigned int srcsample;
187 // If more than 1 sec of sound remains to be converted
188 if (outcount - total_out > sb->format.speed)
190 tmpcount = sb->format.speed;
191 interpolation_limit = tmpcount; // all samples can be interpolated
195 tmpcount = outcount - total_out;
196 interpolation_limit = (int)ceil((double)(((remain_in / format->channels) - 1) << FRACTIONAL_BITS) / fracstep);
197 if (interpolation_limit > tmpcount)
198 interpolation_limit = tmpcount;
202 if (format->width == 2)
204 const short* in_ptr_short;
207 for (i = 0; i < interpolation_limit; i++)
209 srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
210 in_ptr_short = &((const short*)in_ptr)[srcsample];
212 for (j = 0; j < format->channels; j++)
217 b = *(in_ptr_short + format->channels);
218 *((short*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
221 out_ptr += sizeof (short);
224 samplefrac += fracstep;
227 // Non-interpolated part
228 for (/* nothing */; i < tmpcount; i++)
230 srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
231 in_ptr_short = &((const short*)in_ptr)[srcsample];
233 for (j = 0; j < format->channels; j++)
235 *((short*)out_ptr) = *in_ptr_short;
238 out_ptr += sizeof (short);
241 samplefrac += fracstep;
245 else // if (format->width == 1)
247 const unsigned char* in_ptr_byte;
249 // Convert up to 1 sec of sound
250 for (i = 0; i < interpolation_limit; i++)
252 srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
253 in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
255 for (j = 0; j < format->channels; j++)
259 a = *in_ptr_byte - 128;
260 b = *(in_ptr_byte + format->channels) - 128;
261 *((signed char*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
264 out_ptr += sizeof (signed char);
267 samplefrac += fracstep;
270 // Non-interpolated part
271 for (/* nothing */; i < tmpcount; i++)
273 srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
274 in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
276 for (j = 0; j < format->channels; j++)
278 *((signed char*)out_ptr) = *in_ptr_byte - 128;
281 out_ptr += sizeof (signed char);
284 samplefrac += fracstep;
288 // Update the counters and the buffer position
289 remain_in -= format->speed * format->channels;
290 in_ptr += format->speed * format->channels * format->width;
291 total_out += tmpcount;
295 sb->nbframes += outcount;
300 //=============================================================================
307 qboolean S_LoadSound (sfx_t *sfx, qboolean complain)
309 char namebuffer[MAX_QPATH + 16];
312 // See if already loaded
313 if (sfx->fetcher != NULL)
316 // If we weren't able to load it previously, no need to retry
317 // Note: S_PrecacheSound clears this flag to cause a retry
318 if (sfx->flags & SFXFLAG_FILEMISSING)
322 if (snd_renderbuffer == NULL)
325 // Initialize volume peak to 0; if ReplayGain is supported, the loader will change this away
326 sfx->volume_peak = 0.0;
328 if (developer_loading.integer)
329 Con_Printf("loading sound %s\n", sfx->name);
331 SCR_PushLoadingScreen(true, sfx->name, 1);
333 // LordHavoc: if the sound filename does not begin with sound/, try adding it
334 if (strncasecmp(sfx->name, "sound/", 6))
336 dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", sfx->name);
337 len = strlen(namebuffer);
338 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
340 if (S_LoadWavFile (namebuffer, sfx))
342 memcpy (namebuffer + len - 3, "ogg", 4);
344 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
346 if (OGG_LoadVorbisFile (namebuffer, sfx))
351 if (ModPlug_LoadModPlugFile (namebuffer, sfx))
356 // LordHavoc: then try without the added sound/ as wav and ogg
357 dpsnprintf (namebuffer, sizeof(namebuffer), "%s", sfx->name);
358 len = strlen(namebuffer);
359 // request foo.wav: tries foo.wav, then foo.ogg
360 // request foo.ogg: tries foo.ogg only
361 // request foo.mod: tries foo.mod only
362 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
364 if (S_LoadWavFile (namebuffer, sfx))
366 memcpy (namebuffer + len - 3, "ogg", 4);
368 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
370 if (OGG_LoadVorbisFile (namebuffer, sfx))
375 if (ModPlug_LoadModPlugFile (namebuffer, sfx))
379 // Can't load the sound!
380 sfx->flags |= SFXFLAG_FILEMISSING;
382 Con_DPrintf("failed to load sound \"%s\"\n", sfx->name);
384 SCR_PopLoadingScreen(false);
388 SCR_PopLoadingScreen(false);