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.
34 size_t ResampleSfx (const unsigned char *in_data, size_t in_length, const snd_format_t* in_format, unsigned char *out_data, const char* sfxname)
36 size_t srclength, outcount;
38 srclength = in_length * in_format->channels;
39 outcount = (double)in_length * shm->format.speed / in_format->speed;
41 //Con_DPrintf("ResampleSfx(%s): %d samples @ %dHz -> %d samples @ %dHz\n",
42 // sfxname, in_length, in_format->speed, outcount, shm->format.speed);
44 // Trivial case (direct transfer)
45 if (in_format->speed == shm->format.speed)
47 if (in_format->width == 1)
51 for (i = 0; i < srclength; i++)
52 ((signed char*)out_data)[i] = in_data[i] - 128;
54 else // if (in_format->width == 2)
55 memcpy (out_data, in_data, srclength * in_format->width);
58 // General case (linear interpolation with a fixed-point fractional
59 // step, 18-bit integer part and 14-bit fractional part)
60 // Can handle up to 2^18 (262144) samples per second (> 96KHz stereo)
61 # define FRACTIONAL_BITS 14
62 # define FRACTIONAL_MASK ((1 << FRACTIONAL_BITS) - 1)
63 # define INTEGER_BITS (sizeof(samplefrac)*8 - FRACTIONAL_BITS)
66 const unsigned int fracstep = (double)in_format->speed / shm->format.speed * (1 << FRACTIONAL_BITS);
67 size_t remain_in = srclength, total_out = 0;
68 unsigned int samplefrac;
69 const unsigned char *in_ptr = in_data;
70 unsigned char *out_ptr = out_data;
72 // Check that we can handle one second of that sound
73 if (in_format->speed * in_format->channels > (1 << INTEGER_BITS))
75 Con_Printf ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))\n",
76 in_format->speed, in_format->channels);
80 // We work 1 sec at a time to make sure we don't accumulate any
81 // significant error when adding "fracstep" over several seconds, and
82 // also to be able to handle very long sounds.
83 while (total_out < outcount)
85 size_t tmpcount, interpolation_limit, i, j;
86 unsigned int srcsample;
90 // If more than 1 sec of sound remains to be converted
91 if (outcount - total_out > shm->format.speed)
93 tmpcount = shm->format.speed;
94 interpolation_limit = tmpcount; // all samples can be interpolated
98 tmpcount = outcount - total_out;
99 interpolation_limit = ceil((double)(((remain_in / in_format->channels) - 1) << FRACTIONAL_BITS) / fracstep);
100 if (interpolation_limit > tmpcount)
101 interpolation_limit = tmpcount;
105 if (in_format->width == 2)
107 const short* in_ptr_short;
110 for (i = 0; i < interpolation_limit; i++)
112 srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
113 in_ptr_short = &((const short*)in_ptr)[srcsample];
115 for (j = 0; j < in_format->channels; j++)
120 b = *(in_ptr_short + in_format->channels);
121 *((short*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
124 out_ptr += sizeof (short);
127 samplefrac += fracstep;
130 // Non-interpolated part
131 for (/* nothing */; i < tmpcount; i++)
133 srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
134 in_ptr_short = &((const short*)in_ptr)[srcsample];
136 for (j = 0; j < in_format->channels; j++)
138 *((short*)out_ptr) = *in_ptr_short;
141 out_ptr += sizeof (short);
144 samplefrac += fracstep;
148 else // if (in_format->width == 1)
150 const unsigned char* in_ptr_byte;
152 // Convert up to 1 sec of sound
153 for (i = 0; i < interpolation_limit; i++)
155 srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
156 in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
158 for (j = 0; j < in_format->channels; j++)
162 a = *in_ptr_byte - 128;
163 b = *(in_ptr_byte + in_format->channels) - 128;
164 *((signed char*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
167 out_ptr += sizeof (signed char);
170 samplefrac += fracstep;
173 // Non-interpolated part
174 for (/* nothing */; i < tmpcount; i++)
176 srcsample = (samplefrac >> FRACTIONAL_BITS) * in_format->channels;
177 in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
179 for (j = 0; j < in_format->channels; j++)
181 *((signed char*)out_ptr) = *in_ptr_byte - 128;
184 out_ptr += sizeof (signed char);
187 samplefrac += fracstep;
191 // Update the counters and the buffer position
192 remain_in -= in_format->speed * in_format->channels;
193 in_ptr += in_format->speed * in_format->channels * in_format->width;
194 total_out += tmpcount;
201 //=============================================================================
208 qboolean S_LoadSound (sfx_t *s, qboolean complain)
210 char namebuffer[MAX_QPATH + 16];
213 if (!shm || !shm->format.speed)
216 // If we weren't able to load it previously, no need to retry
217 if (s->flags & SFXFLAG_FILEMISSING)
221 if (s->fetcher != NULL)
223 if (s->format.speed != shm->format.speed)
224 Con_Printf ("S_LoadSound: sound %s hasn't been resampled (%uHz instead of %uHz)\n", s->name);
228 // LordHavoc: if the sound filename does not begin with sound/, try adding it
229 if (strncasecmp(s->name, "sound/", 6))
231 len = dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", s->name);
235 Con_Printf("S_LoadSound: name \"%s\" is too long\n", s->name);
238 if (S_LoadWavFile (namebuffer, s))
240 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
241 strcpy (namebuffer + len - 3, "ogg");
242 if (OGG_LoadVorbisFile (namebuffer, s))
246 // LordHavoc: then try without the added sound/ as wav and ogg
247 len = dpsnprintf (namebuffer, sizeof(namebuffer), "%s", s->name);
251 Con_Printf("S_LoadSound: name \"%s\" is too long\n", s->name);
254 if (S_LoadWavFile (namebuffer, s))
256 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
257 strcpy (namebuffer + len - 3, "ogg");
258 if (OGG_LoadVorbisFile (namebuffer, s))
261 // Can't load the sound!
262 s->flags |= SFXFLAG_FILEMISSING;
264 Con_Printf("S_LoadSound: Couldn't load \"%s\"\n", s->name);