]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - snd_mem.c
IQM loading fixes and optimizations
[xonotic/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 #include "snd_modplug.h"
28
29 unsigned char resampling_buffer [48000 * 2 * 2];
30
31
32 /*
33 ====================
34 Snd_CreateRingBuffer
35
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).
38 ====================
39 */
40 snd_ringbuffer_t *Snd_CreateRingBuffer (const snd_format_t* format, unsigned int sampleframes, void* buffer)
41 {
42         snd_ringbuffer_t *ringbuffer;
43
44         // If the caller provides a buffer, it must give us its size
45         if (sampleframes == 0 && buffer != NULL)
46                 return NULL;
47
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));
51
52         // If we haven't been given a buffer
53         if (buffer == NULL)
54         {
55                 unsigned int maxframes;
56                 size_t memsize;
57
58                 if (sampleframes == 0)
59                         maxframes = (format->speed + 1) / 2;  // Make the sound buffer large enough for containing 0.5 sec of sound
60                 else
61                         maxframes = sampleframes;
62
63                 memsize = maxframes * format->width * format->channels;
64                 ringbuffer->ring = (unsigned char *) Mem_Alloc(snd_mempool, memsize);
65                 ringbuffer->maxframes = maxframes;
66         }
67         else
68         {
69                 ringbuffer->ring = (unsigned char *) buffer;
70                 ringbuffer->maxframes = sampleframes;
71         }
72
73         return ringbuffer;
74 }
75
76
77 /*
78 ====================
79 Snd_CreateSndBuffer
80 ====================
81 */
82 snd_buffer_t *Snd_CreateSndBuffer (const unsigned char *samples, unsigned int sampleframes, const snd_format_t* in_format, unsigned int sb_speed)
83 {
84         size_t newsampleframes, memsize;
85         snd_buffer_t* sb;
86
87         newsampleframes = (size_t) ceil((double)sampleframes * (double)sb_speed / (double)in_format->speed);
88
89         memsize = newsampleframes * in_format->channels * in_format->width;
90         memsize += sizeof (*sb) - sizeof (sb->samples);
91
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;
97         sb->nbframes = 0;
98
99         if (!Snd_AppendToSndBuffer (sb, samples, sampleframes, in_format))
100         {
101                 Mem_Free (sb);
102                 return NULL;
103         }
104
105         return sb;
106 }
107
108
109 /*
110 ====================
111 Snd_AppendToSndBuffer
112 ====================
113 */
114 qboolean Snd_AppendToSndBuffer (snd_buffer_t* sb, const unsigned char *samples, unsigned int sampleframes, const snd_format_t* format)
115 {
116         size_t srclength, outcount;
117         unsigned char *out_data;
118
119         //Con_DPrintf("ResampleSfx: %d samples @ %dHz -> %d samples @ %dHz\n",
120         //                      sampleframes, format->speed, outcount, sb->format.speed);
121
122         // If the formats are incompatible
123         if (sb->format.channels != format->channels || sb->format.width != format->width)
124         {
125                 Con_Print("AppendToSndBuffer: incompatible sound formats!\n");
126                 return false;
127         }
128
129         outcount = (size_t) ((double)sampleframes * (double)sb->format.speed / (double)format->speed);
130
131         // If the sound buffer is too short
132         if (outcount > sb->maxframes - sb->nbframes)
133         {
134                 Con_Print("AppendToSndBuffer: sound buffer too short!\n");
135                 return false;
136         }
137
138         out_data = &sb->samples[sb->nbframes * sb->format.width * sb->format.channels];
139         srclength = sampleframes * format->channels;
140
141         // Trivial case (direct transfer)
142         if (format->speed == sb->format.speed)
143         {
144                 if (format->width == 1)
145                 {
146                         size_t i;
147
148                         for (i = 0; i < srclength; i++)
149                                 ((signed char*)out_data)[i] = samples[i] - 128;
150                 }
151                 else  // if (format->width == 2)
152                         memcpy (out_data, samples, srclength * format->width);
153         }
154
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)
161         else
162         {
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;
168
169                 // Check that we can handle one second of that sound
170                 if (format->speed * format->channels > (1 << INTEGER_BITS))
171                 {
172                         Con_Printf ("ResampleSfx: sound quality too high for resampling (%uHz, %u channel(s))\n",
173                                            format->speed, format->channels);
174                         return 0;
175                 }
176
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)
181                 {
182                         size_t tmpcount, interpolation_limit, i, j;
183                         unsigned int srcsample;
184
185                         samplefrac = 0;
186
187                         // If more than 1 sec of sound remains to be converted
188                         if (outcount - total_out > sb->format.speed)
189                         {
190                                 tmpcount = sb->format.speed;
191                                 interpolation_limit = tmpcount;  // all samples can be interpolated
192                         }
193                         else
194                         {
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;
199                         }
200
201                         // 16 bit samples
202                         if (format->width == 2)
203                         {
204                                 const short* in_ptr_short;
205
206                                 // Interpolated part
207                                 for (i = 0; i < interpolation_limit; i++)
208                                 {
209                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
210                                         in_ptr_short = &((const short*)in_ptr)[srcsample];
211
212                                         for (j = 0; j < format->channels; j++)
213                                         {
214                                                 int a, b;
215
216                                                 a = *in_ptr_short;
217                                                 b = *(in_ptr_short + format->channels);
218                                                 *((short*)out_ptr) = (((b - a) * (samplefrac & FRACTIONAL_MASK)) >> FRACTIONAL_BITS) + a;
219
220                                                 in_ptr_short++;
221                                                 out_ptr += sizeof (short);
222                                         }
223
224                                         samplefrac += fracstep;
225                                 }
226
227                                 // Non-interpolated part
228                                 for (/* nothing */; i < tmpcount; i++)
229                                 {
230                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
231                                         in_ptr_short = &((const short*)in_ptr)[srcsample];
232
233                                         for (j = 0; j < format->channels; j++)
234                                         {
235                                                 *((short*)out_ptr) = *in_ptr_short;
236
237                                                 in_ptr_short++;
238                                                 out_ptr += sizeof (short);
239                                         }
240
241                                         samplefrac += fracstep;
242                                 }
243                         }
244                         // 8 bit samples
245                         else  // if (format->width == 1)
246                         {
247                                 const unsigned char* in_ptr_byte;
248
249                                 // Convert up to 1 sec of sound
250                                 for (i = 0; i < interpolation_limit; i++)
251                                 {
252                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
253                                         in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
254
255                                         for (j = 0; j < format->channels; j++)
256                                         {
257                                                 int a, b;
258
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;
262
263                                                 in_ptr_byte++;
264                                                 out_ptr += sizeof (signed char);
265                                         }
266
267                                         samplefrac += fracstep;
268                                 }
269
270                                 // Non-interpolated part
271                                 for (/* nothing */; i < tmpcount; i++)
272                                 {
273                                         srcsample = (samplefrac >> FRACTIONAL_BITS) * format->channels;
274                                         in_ptr_byte = &((const unsigned char*)in_ptr)[srcsample];
275
276                                         for (j = 0; j < format->channels; j++)
277                                         {
278                                                 *((signed char*)out_ptr) = *in_ptr_byte - 128;
279
280                                                 in_ptr_byte++;
281                                                 out_ptr += sizeof (signed char);
282                                         }
283
284                                         samplefrac += fracstep;
285                                 }
286                         }
287
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;
292                 }
293         }
294
295         sb->nbframes += outcount;
296         return true;
297 }
298
299
300 //=============================================================================
301
302 /*
303 ==============
304 S_LoadSound
305 ==============
306 */
307 qboolean S_LoadSound (sfx_t *sfx, qboolean complain)
308 {
309         char namebuffer[MAX_QPATH + 16];
310         size_t len;
311
312         // See if already loaded
313         if (sfx->fetcher != NULL)
314                 return true;
315
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)
319                 return false;
320
321         // No sound?
322         if (snd_renderbuffer == NULL)
323                 return false;
324
325         // Initialize volume peak to 0; if ReplayGain is supported, the loader will change this away
326         sfx->volume_peak = 0.0;
327
328         if (developer_loading.integer)
329                 Con_Printf("loading sound %s\n", sfx->name);
330
331         SCR_PushLoadingScreen(true, sfx->name, 1);
332
333         // LordHavoc: if the sound filename does not begin with sound/, try adding it
334         if (strncasecmp(sfx->name, "sound/", 6))
335         {
336                 dpsnprintf (namebuffer, sizeof(namebuffer), "sound/%s", sfx->name);
337                 len = strlen(namebuffer);
338                 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".wav"))
339                 {
340                         if (S_LoadWavFile (namebuffer, sfx))
341                                 goto loaded;
342                         memcpy (namebuffer + len - 3, "ogg", 4);
343                 }
344                 if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
345                 {
346                         if (OGG_LoadVorbisFile (namebuffer, sfx))
347                                 goto loaded;
348                 }
349                 else
350                 {
351                         if (ModPlug_LoadModPlugFile (namebuffer, sfx))
352                                 goto loaded;
353                 }
354         }
355
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"))
363         {
364                 if (S_LoadWavFile (namebuffer, sfx))
365                         goto loaded;
366                 memcpy (namebuffer + len - 3, "ogg", 4);
367         }
368         if (len >= 4 && !strcasecmp (namebuffer + len - 4, ".ogg"))
369         {
370                 if (OGG_LoadVorbisFile (namebuffer, sfx))
371                         goto loaded;
372         }
373         else
374         {
375                 if (ModPlug_LoadModPlugFile (namebuffer, sfx))
376                         goto loaded;
377         }
378
379         // Can't load the sound!
380         sfx->flags |= SFXFLAG_FILEMISSING;
381         if (complain)
382                 Con_DPrintf("failed to load sound \"%s\"\n", sfx->name);
383
384         SCR_PopLoadingScreen(false);
385         return false;
386
387 loaded:
388         SCR_PopLoadingScreen(false);
389         return true;
390 }