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
33 size_t ResampleSfx (const qbyte *in_data, size_t in_length, const snd_format_t* in_format, qbyte *out_data, const char* sfxname)
35 int samplefrac, fracstep;
36 size_t i, srcsample, srclength, outcount;
38 // this is usually 0.5 (128), 1 (256), or 2 (512)
39 fracstep = ((double) in_format->speed / (double) shm->format.speed) * 256.0;
41 srclength = in_length * in_format->channels;
43 outcount = (double) in_length * (double) shm->format.speed / (double) in_format->speed;
44 Con_DPrintf("ResampleSfx: resampling sound \"%s\" from %dHz to %dHz (%d samples to %d samples)\n",
45 sfxname, in_format->speed, shm->format.speed, in_length, outcount);
47 // resample / decimate to the current source rate
51 // fast case for direct transfer
52 if (in_format->width == 1) // 8bit
53 for (i = 0;i < srclength;i++)
54 ((signed char *)out_data)[i] = ((unsigned char *)in_data)[i] - 128;
55 else //if (sb->width == 2) // 16bit
56 for (i = 0;i < srclength;i++)
57 ((short *)out_data)[i] = ((short *)in_data)[i];
63 if ((fracstep & 255) == 0) // skipping points on perfect multiple
67 if (in_format->width == 2)
69 short *out = (short*)out_data;
70 const short *in = (const short*)in_data;
71 if (in_format->channels == 2) // LordHavoc: stereo sound support
74 for (i=0 ; i<outcount ; i++)
76 *out++ = in[srcsample ];
77 *out++ = in[srcsample+1];
78 srcsample += fracstep;
83 for (i=0 ; i<outcount ; i++)
85 *out++ = in[srcsample];
86 srcsample += fracstep;
92 signed char *out = out_data;
93 const unsigned char *in = in_data;
94 if (in_format->channels == 2)
97 for (i=0 ; i<outcount ; i++)
99 *out++ = in[srcsample ] - 128;
100 *out++ = in[srcsample+1] - 128;
101 srcsample += fracstep;
106 for (i=0 ; i<outcount ; i++)
108 *out++ = in[srcsample ] - 128;
109 srcsample += fracstep;
118 if (in_format->width == 2)
120 short *out = (short*)out_data;
121 const short *in = (const short*)in_data;
122 if (in_format->channels == 2)
124 for (i=0 ; i<outcount ; i++)
126 srcsample = (samplefrac >> 8) << 1;
128 if (srcsample+2 >= srclength)
132 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
133 *out++ = (short) sample;
135 if (srcsample+2 >= srclength)
139 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
140 *out++ = (short) sample;
141 samplefrac += fracstep;
146 for (i=0 ; i<outcount ; i++)
148 srcsample = samplefrac >> 8;
150 if (srcsample+1 >= srclength)
154 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
155 *out++ = (short) sample;
156 samplefrac += fracstep;
162 signed char *out = out_data;
163 const unsigned char *in = in_data;
164 if (in_format->channels == 2)
166 for (i=0 ; i<outcount ; i++)
168 srcsample = (samplefrac >> 8) << 1;
169 a = (int) in[srcsample ] - 128;
170 if (srcsample+2 >= srclength)
173 b = (int) in[srcsample+2] - 128;
174 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
175 *out++ = (signed char) sample;
176 a = (int) in[srcsample+1] - 128;
177 if (srcsample+2 >= srclength)
180 b = (int) in[srcsample+3] - 128;
181 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
182 *out++ = (signed char) sample;
183 samplefrac += fracstep;
188 for (i=0 ; i<outcount ; i++)
190 srcsample = samplefrac >> 8;
191 a = (int) in[srcsample ] - 128;
192 if (srcsample+1 >= srclength)
195 b = (int) in[srcsample+1] - 128;
196 sample = (((b - a) * (samplefrac & 255)) >> 8) + a;
197 *out++ = (signed char) sample;
198 samplefrac += fracstep;
208 //=============================================================================
215 qboolean S_LoadSound (sfx_t *s, int complain)
217 char namebuffer[MAX_QPATH];
219 qboolean modified_name = false;
221 // see if still in memory
222 if (!shm || !shm->format.speed)
224 if (s->fetcher != NULL)
226 if (s->format.speed != shm->format.speed)
227 Sys_Error ("S_LoadSound: sound %s hasn't been resampled (%uHz instead of %uHz)", s->name);
231 len = snprintf (namebuffer, sizeof (namebuffer), "sound/%s", s->name);
232 if (len >= sizeof (namebuffer))
235 // Try to load it as a WAV file
236 if (S_LoadWavFile (namebuffer, s))
239 // Else, try to load it as an Ogg Vorbis file
240 if (!strcasecmp (namebuffer + len - 4, ".wav"))
242 strcpy (namebuffer + len - 3, "ogg");
243 modified_name = true;
245 if (OGG_LoadVorbisFile (namebuffer, s))
248 // Can't load the sound!
250 s->flags |= SFXFLAG_SILENTLYMISSING;
252 s->flags &= ~SFXFLAG_SILENTLYMISSING;
256 strcpy (namebuffer + len - 3, "wav");
257 Con_Printf("Couldn't load %s\n", namebuffer);
262 void S_UnloadSound(sfx_t *s)
264 if (s->fetcher != NULL)
269 s->fetcher_data = NULL;
270 Mem_FreePool(&s->mempool);
272 // At this point, some per-channel data pointers may point to freed zones.
273 // Practically, it shouldn't be a problem; but it's wrong, so we fix that
274 for (i = 0; i < total_channels ; i++)
275 if (channels[i].sfx == s)
276 channels[i].fetcher_data = NULL;