DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
snd_mix.c File Reference
#include "quakedef.h"
#include "snd_main.h"
+ Include dependency graph for snd_mix.c:

Go to the source code of this file.

Macros

#define S_FETCHBUFFERSIZE   4096
 
#define SOFTCLIP(x)
 

Functions

static void S_ConvertPaintBuffer (portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int nchannels)
 
void S_MixToBuffer (void *stream, unsigned int bufferframes)
 
void S_SetUnderwaterIntensity (void)
 
static void S_SoftClipPaintBuffer (portable_sampleframe_t *painted_ptr, int nbframes, int width, int nchannels)
 
static void S_UnderwaterFilter (int endtime)
 

Variables

static portable_sampleframe_t paintbuffer [PAINTBUFFER_SIZE]
 
cvar_t snd_softclip
 
speakerlayout_t snd_speakerlayout
 
struct { 
 
   float   accum [SND_LISTENERS
 
   float   alpha 
 
   float   intensity 
 
underwater = {0.f, 1.f, {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}} 
 

Macro Definition Documentation

◆ S_FETCHBUFFERSIZE

#define S_FETCHBUFFERSIZE   4096

Referenced by S_MixToBuffer().

◆ SOFTCLIP

#define SOFTCLIP ( x)
Value:
if(fabs(x)>maxvol) maxvol=fabs(x); (x) /= maxvol;
GLint GLenum GLint x
Definition glquake.h:651
float fabs(float f)

Referenced by S_SoftClipPaintBuffer().

Function Documentation

◆ S_ConvertPaintBuffer()

static void S_ConvertPaintBuffer ( portable_sampleframe_t * painted_ptr,
void * rb_ptr,
int nbframes,
int width,
int nchannels )
static

Definition at line 129 of file snd_mix.c.

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}
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLenum GLsizei width
Definition glquake.h:622
#define bound(min, num, max)
Definition mathlib.h:34
int i
float sample[SND_LISTENERS]
Definition snd_main.h:197

References bound, i, int(), portable_sampleframe_t::sample, and width.

Referenced by S_MixToBuffer().

◆ S_MixToBuffer()

void S_MixToBuffer ( void * stream,
unsigned int bufferframes )

Definition at line 369 of file snd_mix.c.

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}
GLenum GLenum GLsizei count
Definition glquake.h:656
#define min(A, B)
Definition mathlib.h:37
float floor(float f)
#define PAINTBUFFER_SIZE
Definition qdefs.h:151
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
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
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
#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
#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
exported for capturevideo so ogg can see all channels
Definition snd_main.h:196
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

References bound, CHANNELFLAG_FORCELOOP, CHANNELFLAG_PAUSED, channels, snd_format_t::channels, speakerlayout_t::channels, count, channel_t::flags, floor(), snd_ringbuffer_t::format, i, int(), min, channel_t::mixspeed, NULL, paintbuffer, PAINTBUFFER_SIZE, channel_t::position, channel_t::prologic_invert, S_ConvertPaintBuffer(), S_FETCHBUFFERSIZE, S_LoadSound(), S_SoftClipPaintBuffer(), S_StopChannel(), S_UnderwaterFilter(), portable_sampleframe_t::sample, channel_t::sfx, SND_LISTENERS, snd_renderbuffer, snd_speakerlayout, snd_usethreadedmixing, snd_format_t::speed, total_channels, channel_t::volume, and snd_format_t::width.

Referenced by Buffer_Callback(), and S_PaintAndSubmit().

◆ S_SetUnderwaterIntensity()

void S_SetUnderwaterIntensity ( void )

Definition at line 320 of file snd_mix.c.

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}
client_state_t cl
Definition cl_main.c:117
float log(float f)
#define max(A, B)
Definition mathlib.h:38
string target
Definition progsdefs.qc:193
cvar_t snd_waterfx
Definition snd_main.c:173
static struct @33 underwater
double realframetime
Definition client.h:871
qbool view_underwater
Definition client.h:1139
float value
Definition cvar.h:74

References bound, cl, log(), max, min, client_state_t::realframetime, snd_waterfx, target, underwater, cvar_t::value, and client_state_t::view_underwater.

Referenced by S_UpdateAmbientSounds().

◆ S_SoftClipPaintBuffer()

static void S_SoftClipPaintBuffer ( portable_sampleframe_t * painted_ptr,
int nbframes,
int width,
int nchannels )
static

Definition at line 55 of file snd_mix.c.

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}
cvar_t snd_softclip
Definition snd_mix.c:53
#define SOFTCLIP(x)
int integer
Definition cvar.h:73

References snd_ringbuffer_t::format, i, cvar_t::integer, max, portable_sampleframe_t::sample, snd_renderbuffer, snd_softclip, SOFTCLIP, snd_format_t::speed, and width.

Referenced by S_MixToBuffer().

◆ S_UnderwaterFilter()

static void S_UnderwaterFilter ( int endtime)
static

Definition at line 338 of file snd_mix.c.

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}

References i, paintbuffer, portable_sampleframe_t::sample, SND_LISTENERS, and underwater.

Referenced by S_MixToBuffer().

Variable Documentation

◆ accum

Definition at line 316 of file snd_mix.c.

◆ alpha

float alpha

Definition at line 315 of file snd_mix.c.

◆ intensity

◆ paintbuffer

◆ snd_softclip

cvar_t snd_softclip
extern

Definition at line 53 of file snd_mix.c.

Referenced by S_Init(), and S_SoftClipPaintBuffer().

◆ snd_speakerlayout

speakerlayout_t snd_speakerlayout
extern

◆ [struct]