]> icculus.org git repositories - divverent/darkplaces.git/blob - snd_mem.c
fix dedicated server crashes caused by new lightmap merging
[divverent/darkplaces.git] / snd_mem.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20
21
22 #include "quakedef.h"
23
24 #include "snd_main.h"
25 #include "snd_ogg.h"
26 #include "snd_wav.h"
27
28
29 /*
30 ====================
31 Snd_CreateRingBuffer
32
33 If "buffer" is NULL, the function allocates one buffer of "sampleframes" sample frames itself
34 (if "sampleframes" is 0, the function chooses the size).
35 ====================
36 */
37 snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int sampleframes, void* buffer)
38 {
39         snd_ringbuffer_t *ringbuffer;
40
41         // If the caller provides a buffer, it must give us its size
42         if (sampleframes == 0 && buffer != NULL)
43                 return NULL;
44
45         ringbuffer = (snd_ringbuffer_t*)Mem_Alloc(snd_mempool, sizeof (*ringbuffer));
46         memset(ringbuffer, 0, sizeof(*ringbuffer));
47         memcpy(&ringbuffer->format, format, sizeof(ringbuffer->format));
48
49         // If we haven't been given a buffer
50         if (buffer == NULL)
51         {
52                 unsigned int maxframes;
53                 size_t memsize;
54
55                 if (sampleframes == 0)
56                         maxframes = (format->speed + 1) / 2;  // Make the sound buffer large enough for containing 0.5 sec of sound
57                 else
58                         maxframes = sampleframes;
59
60                 memsize = maxframes * format->width * format->channels;
61                 ringbuffer->ring = Mem_Alloc(snd_mempool, memsize);
62                 ringbuffer->maxframes = maxframes;
63         }
64         else
65         {
66                 ringbuffer->ring = buffer;
67                 ringbuffer->maxframes = sampleframes;
68         }
69
70         return ringbuffer;
71 }
72
73
74 /*
75 ====================
76 Snd_CreateSndBuffer
77 ====================
78 */
79 snd_buffer_t *Snd_CreateSndBuffer (const unsigned char *samples, unsigned int sampleframes, const snd_format_t* in_format, unsigned int sb_speed)
80 {
81         size_t newsampleframes, memsize;
82         snd_buffer_t* sb;
83
84         newsampleframes = (double)sampleframes * (double)sb_speed / (double)in_format->speed;
85
86         memsize = newsampleframes * in_format->channels * in_format->width;
87         memsize += sizeof (*sb) - sizeof (sb->samples);
88
89         sb = (snd_buffer_t*)Mem_Alloc (snd_mempool, memsize);
90         sb->format.channels = in_format->channels;
91         sb->format.width = in_format->width;
92         sb->format.speed = sb_speed;
93         sb->maxframes = newsampleframes;
94         sb->nbframes = 0;
95
96         if (!Snd_AppendToSndBuffer (sb, samples, sampleframes, in_format))
97         {
98                 Mem_Free (sb);
99                 return NULL;
100         }
101
102         return sb;
103 }
104
105
106 /*
107 ====================
108 Snd_AppendToSndBuffer
109 ====================
110 */
111 qboolean Snd_AppendToSndBuffer (snd_buffer_t* sb, const unsigned char *samples, unsigned int sampleframes, const snd_format_t* format)
112 {
113         size_t srclength, outcount;
114         unsigned char *out_data;
115
116         //Con_DPrintf("ResampleSfx: %d samples @ %dHz -> %d samples @ %dHz\n",
117         //                      sampleframes, format->speed, outcount, sb->format.speed);
118
119         // If the formats are incompatible
120         if (sb->format.channels != format->channels || sb->format.width != format->width)
121         {
122                 Con_Print("AppendToSndBuffer: incompatible sound formats!\n");
123                 return false;
124         }
125
126         outcount = (double)sampleframes * (double)sb->format.speed / (double)format->speed;
127
128         // If the sound buffer is too short
129         if (outcount > sb->maxframes - sb->nbframes)
130         {
131                 Con_Print("AppendToSndBuffer: sound buffer too short!\n");
132                 return false;
133         }
134
135         out_data = &sb->samples[sb->nbframes * sb->format.width * sb->format.channels];
136         srclength = sampleframes * format->channels;
137
138         // Trivial case (direct transfer)
139         if (format->speed == sb->format.speed)
140         {
141                 if (format->width == 1)
142                 {
143                         size_t i;
144
145                         for (i = 0; i < srclength; i++)
146                                 ((signed char*)out_data)[i] = samples[i] - 128;
147                 }
148                 else  // if (format->width == 2)
149                         memcpy (out_data, samples, srclength * format->width);
150         }
151
152         // General case (linear interpolation with a fixed-point fractional
153         // step, 18-bit integer part and 14-bit fractional part)
154         // Can handle up to 2^18 (262144) samples per second (> 96KHz stereo)
155 #       define FRACTIONAL_BITS 14
156 #       define FRACTIONAL_MASK ((1 << FRACTIONAL_BITS) - 1)
157 #       define INTEGER_BITS (sizeof(samplefrac)*8 - FRACTIONAL_BITS)
158         else
159         {
160                 const unsigned int fracstep = (unsigned int)((double)format->speed / sb->format.speed * (1 << FRACTIONAL_BITS));
161                 size_t remain_in = srclength, total_out = 0;
162                 unsigned int samplefrac;
163                 const unsigned char *in_ptr = samples;
164                 unsigned char *out_ptr = out_data;
165
166                 // Check that we can handle one second of that sound
167                 if (format->speed * format->channels > (1 << INTEGER_BITS))
168                 {
169                         Con_Printf ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))\n",
170                                            format->speed, format->channels);
171                         return 0;
172                 }
173
174                 // We work 1 sec at a time to make sure we don't accumulate any
175                 // significant error when adding "fracstep" over several seconds, and
176                 // also to be able to handle very long sounds.
177                 while (total_out < outcount)
178                 {
179                         size_t tmpcount, interpolation_limit, i, j;
180                         unsigned int srcsample;
181
182                         samplefrac = 0;
183
184                         // If more than 1 sec of sound remains to be converted
185                         if (outcount - total_out > sb->format.speed)
186                         {
187                                 tmpcount = sb->format.speed;
188                                 interpolation_limit = tmpcount;  // all samples can be interpolated
189                         }
190                         else
191                         {
192                                 tmpcount = outcount - total_out;
193                                 interpolation_limit = (int)ceil((double)(((remain_in / format->channels) - 1) << FRACTIONAL_BITS) / fracstep);
194                                 if (interpolation_limit > tmpcount)
195                                         interpolation_limit = tmpcount;
196                         }
197
198                         // 16 bit samples
199                         if (format->width == 2)
200                         {
201                                 const short* in_ptr_short;
202
203                                 // Interpolated part
204                                 for (i = 0; i < interpolation_limit; i++)
205                                 {
206                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
207                                         in_ptr_short = &((const short*)in_ptr)[srcsample];
208
209                                         for (j = 0; j < format->channels; j++)
210                                         {
211                                                 int a, b;
212
213                                                 a = *in_ptr_short;
214                                                 b = *(in_ptr_short + format->channels);
215                                                 *((short*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
216
217                                                 in_ptr_short++;
218                                                 out_ptr += sizeof (short);
219                                         }
220
221                                         samplefrac += fracstep;
222                                 }
223
224                                 // Non-interpolated part
225                                 for (/* nothing */; i < tmpcount; i++)
226                                 {
227                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
228                                         in_ptr_short = &((const short*)in_ptr)[srcsample];
229
230                                         for (j = 0; j < format->channels; j++)
231                                         {
232                                                 *((short*)out_ptr) = *in_ptr_short;
233
234                                                 in_ptr_short++;
235                                                 out_ptr += sizeof (short);
236                                         }
237
238                                         samplefrac += fracstep;
239                                 }
240                         }
241                         // 8 bit samples
242                         else  // if (format->width == 1)
243                         {
244                                 const unsigned char* in_ptr_byte;
245
246                                 // Convert up to 1 sec of sound
247                                 for (i = 0; i < interpolation_limit; i++)
248                                 {
249                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
250                                         in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
251
252                                         for (j = 0; j < format->channels; j++)
253                                         {
254                                                 int a, b;
255
256                                                 a = *in_ptr_byte - 128;
257                                                 b = *(in_ptr_byte + format->channels) - 128;
258                                                 *((signed char*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
259
260                                                 in_ptr_byte++;
261                                                 out_ptr += sizeof (signed char);
262                                         }
263
264                                         samplefrac += fracstep;
265                                 }
266
267                                 // Non-interpolated part
268                                 for (/* nothing */; i < tmpcount; i++)
269                                 {
270                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
271                                         in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
272
273                                         for (j = 0; j < format->channels; j++)
274                                         {
275                                                 *((signed char*)out_ptr) = *in_ptr_byte - 128;
276
277                                                 in_ptr_byte++;
278                                                 out_ptr += sizeof (signed char);
279                                         }
280
281                                         samplefrac += fracstep;
282                                 }
283                         }
284
285                         // Update the counters and the buffer position
286                         remain_in -= format->speed * format->channels;
287                         in_ptr += format->speed * format->channels * format->width;
288                         total_out += tmpcount;
289                 }
290         }
291
292         sb->nbframes += outcount;
293         return true;
294 }
295
296
297 //=============================================================================
298
299 /*
300 ==============
301 S_LoadSound
302 ==============
303 */
304 qboolean S_LoadSound (sfx_t *sfx, qboolean complain)
305 {
306         char namebuffer[MAX_QPATH + 16];
307         size_t len;
308
309         // See if already loaded
310         if (sfx->fetcher != NULL)
311                 return true;
312
313         // If we weren't able to load it previously, no need to retry
314         // Note: S_PrecacheSound clears this flag to cause a retry
315         if (sfx->flags & SFXFLAG_FILEMISSING)
316                 return false;
317
318         // No sound?
319         if (snd_renderbuffer == NULL)
320                 return false;
321
322         // LordHavoc: if the sound filename does not begin with sound/, try adding it
323         if (strncasecmp(sfx->name, "sound/", 6))
324         {
325                 len = dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", sfx->name);
326                 if (len < 0)
327                 {
328                         // name too long
329                         Con_Printf("S_LoadSound: name \"%s\" is too long\n", sfx->name);
330                         return false;
331                 }
332                 if (S_LoadWavFile (namebuffer, sfx))
333                         return true;
334                 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
335                         memcpy (namebuffer + len - 3, "ogg", 4);
336                 if (OGG_LoadVorbisFile (namebuffer, sfx))
337                         return true;
338         }
339
340         // LordHavoc: then try without the added sound/ as wav and ogg
341         len = dpsnprintf (namebuffer, sizeof(namebuffer), "%s", sfx->name);
342         if (len < 0)
343         {
344                 // name too long
345                 Con_Printf("S_LoadSound: name \"%s\" is too long\n", sfx->name);
346                 return false;
347         }
348         if (S_LoadWavFile (namebuffer, sfx))
349                 return true;
350         if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
351                 memcpy (namebuffer + len - 3, "ogg", 4);
352         if (OGG_LoadVorbisFile (namebuffer, sfx))
353                 return true;
354
355         // Can't load the sound!
356         sfx->flags |= SFXFLAG_FILEMISSING;
357         if (complain)
358                 Con_Printf("S_LoadSound: Couldn't load \"%s\"\n", sfx->name);
359         return false;
360 }