DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
snd_mix.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20
21#include "quakedef.h"
22#include "snd_main.h"
23
24extern cvar_t snd_softclip;
25
27
28extern speakerlayout_t snd_speakerlayout; // for querying the listeners
29
30#ifdef CONFIG_VIDEO_CAPTURE
31static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
32
33static void S_CaptureAVISound(const portable_sampleframe_t *sampleframes, size_t length)
34{
35 size_t i;
36 unsigned int j;
37
38 if (!cls.capturevideo.active)
39 return;
40
41 // undo whatever swapping the channel layout (swapstereo, ALSA) did
42 for(j = 0; j < snd_speakerlayout.channels; ++j)
43 {
45 for(i = 0; i < length; ++i)
46 paintbuffer_unswapped[i].sample[j0] = sampleframes[i].sample[j];
47 }
48
49 SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
50}
51#endif
52
54
55static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int nchannels)
56{
57 int i;
58
59 if((snd_softclip.integer == 1 && width <= 2) || snd_softclip.integer > 1)
60 {
61 portable_sampleframe_t *p = painted_ptr;
62
63#if 0
64/* Soft clipping, the sound of a dream, thanks to Jon Wattes
65 post to Musicdsp.org */
66#define SOFTCLIP(x) (x) = sin(bound(-M_PI/2, (x), M_PI/2)) * 0.25
67#endif
68
69 // let's do a simple limiter instead, seems to sound better
70 static float maxvol = 0;
71 maxvol = max(1.0f, maxvol * (1.0f - nbframes / (0.4f * snd_renderbuffer->format.speed)));
72#define SOFTCLIP(x) if(fabs(x)>maxvol) maxvol=fabs(x); (x) /= maxvol;
73
74 if (nchannels == 8) // 7.1 surround
75 {
76 for (i = 0;i < nbframes;i++, p++)
77 {
78 SOFTCLIP(p->sample[0]);
79 SOFTCLIP(p->sample[1]);
80 SOFTCLIP(p->sample[2]);
81 SOFTCLIP(p->sample[3]);
82 SOFTCLIP(p->sample[4]);
83 SOFTCLIP(p->sample[5]);
84 SOFTCLIP(p->sample[6]);
85 SOFTCLIP(p->sample[7]);
86 }
87 }
88 else if (nchannels == 6) // 5.1 surround
89 {
90 for (i = 0; i < nbframes; i++, p++)
91 {
92 SOFTCLIP(p->sample[0]);
93 SOFTCLIP(p->sample[1]);
94 SOFTCLIP(p->sample[2]);
95 SOFTCLIP(p->sample[3]);
96 SOFTCLIP(p->sample[4]);
97 SOFTCLIP(p->sample[5]);
98 }
99 }
100 else if (nchannels == 4) // 4.0 surround
101 {
102 for (i = 0; i < nbframes; i++, p++)
103 {
104 SOFTCLIP(p->sample[0]);
105 SOFTCLIP(p->sample[1]);
106 SOFTCLIP(p->sample[2]);
107 SOFTCLIP(p->sample[3]);
108 }
109 }
110 else if (nchannels == 2) // 2.0 stereo
111 {
112 for (i = 0; i < nbframes; i++, p++)
113 {
114 SOFTCLIP(p->sample[0]);
115 SOFTCLIP(p->sample[1]);
116 }
117 }
118 else if (nchannels == 1) // 1.0 mono
119 {
120 for (i = 0; i < nbframes; i++, p++)
121 {
122 SOFTCLIP(p->sample[0]);
123 }
124 }
125#undef SOFTCLIP
126 }
127}
128
129static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int nchannels)
130{
131 int i;
132 float val;
133 if (width == 4) // 32bit float
134 {
135 float *snd_out = (float*)rb_ptr;
136 if (nchannels == 8) // 7.1 surround
137 {
138 for (i = 0; i < nbframes; i++, painted_ptr++)
139 {
140 *snd_out++ = painted_ptr->sample[0];
141 *snd_out++ = painted_ptr->sample[1];
142 *snd_out++ = painted_ptr->sample[2];
143 *snd_out++ = painted_ptr->sample[3];
144 *snd_out++ = painted_ptr->sample[4];
145 *snd_out++ = painted_ptr->sample[5];
146 *snd_out++ = painted_ptr->sample[6];
147 *snd_out++ = painted_ptr->sample[7];
148 }
149 }
150 else if (nchannels == 6) // 5.1 surround
151 {
152 for (i = 0; i < nbframes; i++, painted_ptr++)
153 {
154 *snd_out++ = painted_ptr->sample[0];
155 *snd_out++ = painted_ptr->sample[1];
156 *snd_out++ = painted_ptr->sample[2];
157 *snd_out++ = painted_ptr->sample[3];
158 *snd_out++ = painted_ptr->sample[4];
159 *snd_out++ = painted_ptr->sample[5];
160 }
161 }
162 else if (nchannels == 4) // 4.0 surround
163 {
164 for (i = 0; i < nbframes; i++, painted_ptr++)
165 {
166 *snd_out++ = painted_ptr->sample[0];
167 *snd_out++ = painted_ptr->sample[1];
168 *snd_out++ = painted_ptr->sample[2];
169 *snd_out++ = painted_ptr->sample[3];
170 }
171 }
172 else if (nchannels == 2) // 2.0 stereo
173 {
174 for (i = 0; i < nbframes; i++, painted_ptr++)
175 {
176 *snd_out++ = painted_ptr->sample[0];
177 *snd_out++ = painted_ptr->sample[1];
178 }
179 }
180 else if (nchannels == 1) // 1.0 mono
181 {
182 for (i = 0; i < nbframes; i++, painted_ptr++)
183 {
184 *snd_out++ = painted_ptr->sample[0];
185 }
186 }
187 }
188 else if (width == 2) // 16bit
189 {
190 short *snd_out = (short*)rb_ptr;
191 if (nchannels == 8) // 7.1 surround
192 {
193 for (i = 0;i < nbframes;i++, painted_ptr++)
194 {
195 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
196 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
197 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
198 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
199 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
200 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
201 val = (int)(painted_ptr->sample[6] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
202 val = (int)(painted_ptr->sample[7] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
203 }
204 }
205 else if (nchannels == 6) // 5.1 surround
206 {
207 for (i = 0; i < nbframes; i++, painted_ptr++)
208 {
209 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
210 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
211 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
212 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
213 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
214 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
215 }
216 }
217 else if (nchannels == 4) // 4.0 surround
218 {
219 for (i = 0; i < nbframes; i++, painted_ptr++)
220 {
221 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
222 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
223 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
224 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
225 }
226 }
227 else if (nchannels == 2) // 2.0 stereo
228 {
229 for (i = 0; i < nbframes; i++, painted_ptr++)
230 {
231 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
232 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
233 }
234 }
235 else if (nchannels == 1) // 1.0 mono
236 {
237 for (i = 0; i < nbframes; i++, painted_ptr++)
238 {
239 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 16384.0f);*snd_out++ = bound(-32768, val, 32767);
240 }
241 }
242 }
243 else // 8bit
244 {
245 unsigned char *snd_out = (unsigned char*)rb_ptr;
246 if (nchannels == 8) // 7.1 surround
247 {
248 for (i = 0; i < nbframes; i++, painted_ptr++)
249 {
250 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
251 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
252 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
253 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
254 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
255 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
256 val = (int)(painted_ptr->sample[6] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
257 val = (int)(painted_ptr->sample[7] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
258 }
259 }
260 else if (nchannels == 6) // 5.1 surround
261 {
262 for (i = 0; i < nbframes; i++, painted_ptr++)
263 {
264 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
265 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
266 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
267 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
268 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
269 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
270 }
271 }
272 else if (nchannels == 4) // 4.0 surround
273 {
274 for (i = 0; i < nbframes; i++, painted_ptr++)
275 {
276 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
277 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
278 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
279 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
280 }
281 }
282 else if (nchannels == 2) // 2.0 stereo
283 {
284 for (i = 0; i < nbframes; i++, painted_ptr++)
285 {
286 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
287 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
288 }
289 }
290 else if (nchannels == 1) // 1.0 mono
291 {
292 for (i = 0;i < nbframes;i++, painted_ptr++)
293 {
294 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 64.0f) + 128; *snd_out++ = bound(0, val, 255);
295 }
296 }
297 }
298}
299
300
301
302/*
303===============================================================================
304
305UNDERWATER EFFECT
306
307Muffles the intensity of sounds when the player is underwater
308
309===============================================================================
310*/
311
312static struct
313{
315 float alpha;
317}
318underwater = {0.f, 1.f, {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}};
319
321{
322 float target = cl.view_underwater ? bound(0.f, snd_waterfx.value, 2.f) : 0.f;
323
324 if (underwater.intensity < target)
325 {
326 underwater.intensity += cl.realframetime * 4.f;
327 underwater.intensity = min(underwater.intensity, target);
328 }
329 else if (underwater.intensity > target)
330 {
331 underwater.intensity -= cl.realframetime * 4.f;
332 underwater.intensity = max(underwater.intensity, target);
333 }
334
335 underwater.alpha = underwater.intensity ? exp(-underwater.intensity * log(12.f)) : 1.f;
336}
337
338static void S_UnderwaterFilter(int endtime)
339{
340 int i;
341 int sl;
342
343 if (!underwater.intensity)
344 {
345 if (endtime > 0)
346 for (sl = 0; sl < SND_LISTENERS; sl++)
347 underwater.accum[sl] = paintbuffer[endtime-1].sample[sl];
348 return;
349 }
350
351 for (i = 0; i < endtime; i++)
352 for (sl = 0; sl < SND_LISTENERS; sl++)
353 {
354 underwater.accum[sl] += underwater.alpha * (paintbuffer[i].sample[sl] - underwater.accum[sl]);
355 paintbuffer[i].sample[sl] = underwater.accum[sl];
356 }
357}
358
359
360
361/*
362===============================================================================
363
364CHANNEL MIXING
365
366===============================================================================
367*/
368
369void S_MixToBuffer(void *stream, unsigned int bufferframes)
370{
371 int channelindex;
372 channel_t *ch;
373 int totalmixframes;
374 unsigned char *outbytes = (unsigned char *) stream;
375 sfx_t *sfx;
377 int wantframes;
378 int i;
379 int count;
380 int fetched;
381 int fetch;
382 int istartframe;
383 int iendframe;
384 int ilengthframes;
385 int totallength;
386 int loopstart;
387 int indexfrac;
388 int indexfracstep;
389#define S_FETCHBUFFERSIZE 4096
390 float fetchsampleframes[S_FETCHBUFFERSIZE*2];
391 const float *fetchsampleframe;
392 float vol[SND_LISTENERS];
393 float lerp[2];
394 float sample[3];
395 double posd;
396 double speedd;
397 float maxvol;
398 qbool looping;
399 qbool silent;
400
401 // mix as many times as needed to fill the requested buffer
402 while (bufferframes)
403 {
404 // limit to the size of the paint buffer
405 totalmixframes = min(bufferframes, PAINTBUFFER_SIZE);
406
407 // clear the paint buffer
408 memset(paintbuffer, 0, totalmixframes * sizeof(paintbuffer[0]));
409
410 // paint in the channels.
411 // channels with zero volumes still advance in time but don't paint.
412 ch = channels; // cppcheck complains here but it is wrong, channels is a channel_t[MAX_CHANNELS] and not an int
413 for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
414 {
415 sfx = ch->sfx;
416 if (sfx == NULL)
417 continue;
418 if (!S_LoadSound (sfx, true))
419 continue;
420 if (ch->flags & CHANNELFLAG_PAUSED)
421 continue;
422 if (!sfx->total_length)
423 continue;
424
425 // copy the channel information to the stack for reference, otherwise the
426 // values might change during a mix if the spatializer is updating them
427 // (note: this still may get some old and some new values!)
428 posd = ch->position;
429 speedd = ch->mixspeed * sfx->format.speed / snd_renderbuffer->format.speed;
430 for (i = 0;i < SND_LISTENERS;i++)
431 vol[i] = ch->volume[i];
432
433 // check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly)
434 maxvol = 0;
435 for (i = 0;i < SND_LISTENERS;i++)
436 if(vol[i] > maxvol)
437 maxvol = vol[i];
439 {
440 case 1: // 8bpp
441 silent = maxvol < (1.0f / (256.0f));
442 // so silent it has zero effect
443 break;
444 case 2: // 16bpp
445 silent = maxvol < (1.0f / (65536.0f));
446 // so silent it has zero effect
447 break;
448 default: // floating point
449 silent = maxvol < 1.0e-13f;
450 // 130 dB is difference between hearing
451 // threshold and a jackhammer from
452 // working distance.
453 // therefore, anyone who turns up
454 // volume so much they notice this
455 // cutoff, likely already has their
456 // ear-drums blown out anyway.
457 break;
458 }
459
460 // when doing prologic mixing, some channels invert one side
461 if (ch->prologic_invert == -1)
462 vol[1] *= -1.0f;
463
464 // get some sfx info in a consistent form
465 totallength = sfx->total_length;
466 loopstart = (int)sfx->loopstart < totallength ? (int)sfx->loopstart : ((ch->flags & CHANNELFLAG_FORCELOOP) ? 0 : totallength);
467 looping = loopstart < totallength;
468
469 // do the actual paint now (may skip work if silent)
470 paint = paintbuffer;
471 istartframe = 0;
472 for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
473 {
474 // check if this is a delayed sound
475 if (posd < 0)
476 {
477 // for a delayed sound we have to eat into the delay first
478 count = (int)floor(-posd / speedd) + 1;
479 count = bound(1, count, wantframes);
480 // let the for loop iterator apply the skip
481 continue;
482 }
483
484 // compute a fetch size that won't overflow our buffer
485 count = wantframes;
486 for (;;)
487 {
488 istartframe = (int)floor(posd);
489 iendframe = (int)floor(posd + (count-1) * speedd);
490 ilengthframes = count > 1 ? (iendframe - istartframe + 2) : 2;
491 if (ilengthframes <= S_FETCHBUFFERSIZE)
492 break;
493 // reduce count by 25% and try again
494 count -= count >> 2;
495 }
496
497 // zero whole fetch buffer for safety
498 // (floating point noise from uninitialized memory = HORRIBLE)
499 // otherwise we would only need to clear the excess
500 if (!silent)
501 memset(fetchsampleframes, 0, ilengthframes*sfx->format.channels*sizeof(fetchsampleframes[0]));
502
503 // if looping, do multiple fetches
504 fetched = 0;
505 for (;;)
506 {
507 fetch = min(ilengthframes - fetched, totallength - istartframe);
508 if (fetch > 0)
509 {
510 if (!silent)
511 sfx->fetcher->getsamplesfloat(ch, sfx, istartframe, fetch, fetchsampleframes + fetched*sfx->format.channels);
512 istartframe += fetch;
513 fetched += fetch;
514 }
515 if (istartframe == totallength && looping && fetched < ilengthframes)
516 {
517 // loop and fetch some more
518 posd += loopstart - totallength;
519 istartframe = loopstart;
520 }
521 else
522 {
523 break;
524 }
525 }
526
527 // set up our fixedpoint resampling variables (float to int conversions are expensive so do not do one per sampleframe)
528 fetchsampleframe = fetchsampleframes;
529 indexfrac = (int)floor((posd - floor(posd)) * 65536.0);
530 indexfracstep = (int)floor(speedd * 65536.0);
531 if (!silent)
532 {
533 if (sfx->format.channels == 2)
534 {
535 // music is stereo
536#if SND_LISTENERS != 8
537#error the following code only supports up to 8 channels, update it
538#endif
540 {
541 // surround mixing
542 for (i = 0;i < count;i++, paint++)
543 {
544 lerp[1] = indexfrac * (1.0f / 65536.0f);
545 lerp[0] = 1.0f - lerp[1];
546 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
547 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
548 sample[2] = (sample[0] + sample[1]) * 0.5f;
549 paint->sample[0] += sample[0] * vol[0];
550 paint->sample[1] += sample[1] * vol[1];
551 paint->sample[2] += sample[0] * vol[2];
552 paint->sample[3] += sample[1] * vol[3];
553 paint->sample[4] += sample[2] * vol[4];
554 paint->sample[5] += sample[2] * vol[5];
555 paint->sample[6] += sample[0] * vol[6];
556 paint->sample[7] += sample[1] * vol[7];
557 indexfrac += indexfracstep;
558 fetchsampleframe += 2 * (indexfrac >> 16);
559 indexfrac &= 0xFFFF;
560 }
561 }
562 else
563 {
564 // stereo mixing
565 for (i = 0;i < count;i++, paint++)
566 {
567 lerp[1] = indexfrac * (1.0f / 65536.0f);
568 lerp[0] = 1.0f - lerp[1];
569 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
570 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
571 paint->sample[0] += sample[0] * vol[0];
572 paint->sample[1] += sample[1] * vol[1];
573 indexfrac += indexfracstep;
574 fetchsampleframe += 2 * (indexfrac >> 16);
575 indexfrac &= 0xFFFF;
576 }
577 }
578 }
579 else if (sfx->format.channels == 1)
580 {
581 // most sounds are mono
582#if SND_LISTENERS != 8
583#error the following code only supports up to 8 channels, update it
584#endif
586 {
587 // surround mixing
588 for (i = 0;i < count;i++, paint++)
589 {
590 lerp[1] = indexfrac * (1.0f / 65536.0f);
591 lerp[0] = 1.0f - lerp[1];
592 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
593 paint->sample[0] += sample[0] * vol[0];
594 paint->sample[1] += sample[0] * vol[1];
595 paint->sample[2] += sample[0] * vol[2];
596 paint->sample[3] += sample[0] * vol[3];
597 paint->sample[4] += sample[0] * vol[4];
598 paint->sample[5] += sample[0] * vol[5];
599 paint->sample[6] += sample[0] * vol[6];
600 paint->sample[7] += sample[0] * vol[7];
601 indexfrac += indexfracstep;
602 fetchsampleframe += (indexfrac >> 16);
603 indexfrac &= 0xFFFF;
604 }
605 }
606 else
607 {
608 // stereo mixing
609 for (i = 0;i < count;i++, paint++)
610 {
611 lerp[1] = indexfrac * (1.0f / 65536.0f);
612 lerp[0] = 1.0f - lerp[1];
613 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
614 paint->sample[0] += sample[0] * vol[0];
615 paint->sample[1] += sample[0] * vol[1];
616 indexfrac += indexfracstep;
617 fetchsampleframe += (indexfrac >> 16);
618 indexfrac &= 0xFFFF;
619 }
620 }
621 }
622 }
623 }
624 ch->position = posd;
625 if (!looping && istartframe == totallength)
626 S_StopChannel(ch - channels, false, false);
627 }
628
630
631 S_UnderwaterFilter(totalmixframes);
632
633
634#ifdef CONFIG_VIDEO_CAPTURE
636 S_CaptureAVISound(paintbuffer, totalmixframes);
637#endif
638
640
641 // advance the output pointer
642 outbytes += totalmixframes * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
643 bufferframes -= totalmixframes;
644 }
645}
client_state_t cl
Definition cl_main.c:117
client_static_t cls
Definition cl_main.c:116
float log(float f)
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLenum GLsizei width
Definition glquake.h:622
GLenum GLuint GLenum GLsizei length
Definition glquake.h:657
GLenum GLenum GLsizei count
Definition glquake.h:656
#define max(A, B)
Definition mathlib.h:38
#define min(A, B)
Definition mathlib.h:37
#define bound(min, num, max)
Definition mathlib.h:34
float floor(float f)
string target
Definition progsdefs.qc:193
int i
#define PAINTBUFFER_SIZE
Definition qdefs.h:151
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
void SCR_CaptureVideo_SoundFrame(const struct portable_samplepair_s *paintbuffer, size_t length)
cvar_t snd_waterfx
Definition snd_main.c:173
unsigned int total_channels
Definition snd_main.c:129
void S_StopChannel(unsigned int channel_ind, qbool lockmutex, qbool freesfx)
Definition snd_main.c:1648
channel_t channels[MAX_CHANNELS]
Definition snd_main.c:128
snd_ringbuffer_t * snd_renderbuffer
Definition snd_main.c:131
qbool snd_usethreadedmixing
if true, the main thread does not mix sound, soundtime does not advance, and neither does snd_renderb...
Definition snd_main.c:137
qbool S_LoadSound(struct sfx_s *sfx, qbool complain)
#define SND_LISTENERS
Definition snd_main.h:84
float accum[SND_LISTENERS]
Definition snd_mix.c:316
static struct @33 underwater
void S_MixToBuffer(void *stream, unsigned int bufferframes)
Definition snd_mix.c:369
float intensity
Definition snd_mix.c:314
static void S_UnderwaterFilter(int endtime)
Definition snd_mix.c:338
static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int nchannels)
Definition snd_mix.c:55
void S_SetUnderwaterIntensity(void)
Definition snd_mix.c:320
#define S_FETCHBUFFERSIZE
static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE]
Definition snd_mix.c:26
speakerlayout_t snd_speakerlayout
Definition snd_main.c:44
static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int nchannels)
Definition snd_mix.c:129
float alpha
Definition snd_mix.c:315
cvar_t snd_softclip
Definition snd_mix.c:53
#define SOFTCLIP(x)
#define CHANNELFLAG_FORCELOOP
Definition sound.h:39
#define CHANNELFLAG_PAUSED
Definition sound.h:41
unsigned int flags
cf CHANNELFLAG_* defines
Definition snd_main.h:91
int prologic_invert
whether a sound is played on the surround channels in prologic
Definition snd_main.h:97
float volume[SND_LISTENERS]
spatialized volume per speaker (mastervol * distanceattenuation * channelvolume cvars)
Definition snd_main.h:104
double position
updated ONLY by mixer position in sfx, starts at 0, loops or stops at sfx->total_length
Definition snd_main.h:108
struct sfx_s * sfx
pointer to sound sample being used
Definition snd_main.h:89
float mixspeed
these are often updated while mixer is running, glitching should be minimized (mismatched channel vol...
Definition snd_main.h:102
double realframetime
Definition client.h:871
qbool view_underwater
Definition client.h:1139
Definition cvar.h:66
float value
Definition cvar.h:74
int integer
Definition cvar.h:73
int channel_unswapped
for un-swapping
Definition snd_main.h:202
exported for capturevideo so ogg can see all channels
Definition snd_main.h:196
float sample[SND_LISTENERS]
Definition snd_main.h:197
unsigned int speed
Definition snd_main.h:32
unsigned short channels
Definition snd_main.h:34
unsigned short width
Definition snd_main.h:33
snd_format_t format
Definition snd_main.h:47
unsigned int channels
Definition snd_main.h:212
listener_t listeners[SND_LISTENERS]
Definition snd_main.h:213