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.
24 extern cvar_t snd_softclip;
26 static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
28 extern speakerlayout_t snd_speakerlayout; // for querying the listeners
30 #ifdef CONFIG_VIDEO_CAPTURE
31 static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
33 static void S_CaptureAVISound(const portable_sampleframe_t *sampleframes, size_t length)
38 if (!cls.capturevideo.active)
41 // undo whatever swapping the channel layout (swapstereo, ALSA) did
42 for(j = 0; j < snd_speakerlayout.channels; ++j)
44 unsigned int j0 = snd_speakerlayout.listeners[j].channel_unswapped;
45 for(i = 0; i < length; ++i)
46 paintbuffer_unswapped[i].sample[j0] = sampleframes[i].sample[j];
49 SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
53 extern cvar_t snd_softclip;
55 static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int nchannels)
59 if((snd_softclip.integer == 1 && width <= 2) || snd_softclip.integer > 1)
61 portable_sampleframe_t *p = painted_ptr;
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
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;
74 if (nchannels == 8) // 7.1 surround
76 for (i = 0;i < nbframes;i++, p++)
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]);
88 else if (nchannels == 6) // 5.1 surround
90 for (i = 0; i < nbframes; i++, p++)
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]);
100 else if (nchannels == 4) // 4.0 surround
102 for (i = 0; i < nbframes; i++, p++)
104 SOFTCLIP(p->sample[0]);
105 SOFTCLIP(p->sample[1]);
106 SOFTCLIP(p->sample[2]);
107 SOFTCLIP(p->sample[3]);
110 else if (nchannels == 2) // 2.0 stereo
112 for (i = 0; i < nbframes; i++, p++)
114 SOFTCLIP(p->sample[0]);
115 SOFTCLIP(p->sample[1]);
118 else if (nchannels == 1) // 1.0 mono
120 for (i = 0; i < nbframes; i++, p++)
122 SOFTCLIP(p->sample[0]);
129 static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int nchannels)
133 if (width == 4) // 32bit float
135 float *snd_out = (float*)rb_ptr;
136 if (nchannels == 8) // 7.1 surround
138 for (i = 0; i < nbframes; i++, painted_ptr++)
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];
150 else if (nchannels == 6) // 5.1 surround
152 for (i = 0; i < nbframes; i++, painted_ptr++)
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];
162 else if (nchannels == 4) // 4.0 surround
164 for (i = 0; i < nbframes; i++, painted_ptr++)
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];
172 else if (nchannels == 2) // 2.0 stereo
174 for (i = 0; i < nbframes; i++, painted_ptr++)
176 *snd_out++ = painted_ptr->sample[0];
177 *snd_out++ = painted_ptr->sample[1];
180 else if (nchannels == 1) // 1.0 mono
182 for (i = 0; i < nbframes; i++, painted_ptr++)
184 *snd_out++ = painted_ptr->sample[0];
188 // noise is really really annoying
190 memset(rb_ptr, 0, nbframes * nchannels * width);
192 else if (width == 2) // 16bit
194 short *snd_out = (short*)rb_ptr;
195 if (nchannels == 8) // 7.1 surround
197 for (i = 0;i < nbframes;i++, painted_ptr++)
199 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
200 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
201 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
202 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
203 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
204 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
205 val = (int)(painted_ptr->sample[6] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
206 val = (int)(painted_ptr->sample[7] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
209 else if (nchannels == 6) // 5.1 surround
211 for (i = 0; i < nbframes; i++, painted_ptr++)
213 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
214 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
215 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
216 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
217 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
218 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
221 else if (nchannels == 4) // 4.0 surround
223 for (i = 0; i < nbframes; i++, painted_ptr++)
225 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
226 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
227 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
228 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
231 else if (nchannels == 2) // 2.0 stereo
233 for (i = 0; i < nbframes; i++, painted_ptr++)
235 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
236 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
239 else if (nchannels == 1) // 1.0 mono
241 for (i = 0; i < nbframes; i++, painted_ptr++)
243 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 16384.0f);*snd_out++ = bound(-32768, val, 32767);
247 // noise is really really annoying
249 memset(rb_ptr, 0, nbframes * nchannels * width);
253 unsigned char *snd_out = (unsigned char*)rb_ptr;
254 if (nchannels == 8) // 7.1 surround
256 for (i = 0; i < nbframes; i++, painted_ptr++)
258 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
259 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
260 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
261 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
262 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
263 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
264 val = (int)(painted_ptr->sample[6] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
265 val = (int)(painted_ptr->sample[7] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
268 else if (nchannels == 6) // 5.1 surround
270 for (i = 0; i < nbframes; i++, painted_ptr++)
272 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
273 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
274 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
275 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
276 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
277 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
280 else if (nchannels == 4) // 4.0 surround
282 for (i = 0; i < nbframes; i++, painted_ptr++)
284 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
285 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
286 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
287 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
290 else if (nchannels == 2) // 2.0 stereo
292 for (i = 0; i < nbframes; i++, painted_ptr++)
294 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
295 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
298 else if (nchannels == 1) // 1.0 mono
300 for (i = 0;i < nbframes;i++, painted_ptr++)
302 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 64.0f) + 128; *snd_out++ = bound(0, val, 255);
306 // noise is really really annoying
308 memset(rb_ptr, 128, nbframes * nchannels);
313 ===============================================================================
317 ===============================================================================
323 float accum[SND_LISTENERS];
324 } underwater = {0.f, 1.f, {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f}};
326 void S_SetUnderwaterIntensity(void)
328 float host_frametime = cl.realframetime;
329 float target = cl.view_underwater ? 1.f : 0.f;
331 if (snd_waterfx.value < 0.f)
333 else if (snd_waterfx.value > 2.f)
336 target *= snd_waterfx.value;
338 if (underwater.intensity < target)
340 underwater.intensity += host_frametime * 4.f;
341 underwater.intensity = min(underwater.intensity, target);
343 else if (underwater.intensity > target)
345 underwater.intensity -= host_frametime * 4.f;
346 underwater.intensity = max(underwater.intensity, target);
349 underwater.alpha = exp(-underwater.intensity * log(12.f));
352 static void S_UnderwaterFilter(int endtime)
356 if (!underwater.intensity) {
358 for (sl = 0; sl < SND_LISTENERS; sl++) {
359 underwater.accum[sl] = paintbuffer[endtime-1].sample[sl];
364 for (i = 0; i < endtime; i++) {
365 for (sl = 0; sl < SND_LISTENERS; sl++) {
366 underwater.accum[sl] += underwater.alpha * (paintbuffer[i].sample[sl] - underwater.accum[sl]);
367 paintbuffer[i].sample[sl] = underwater.accum[sl];
373 ===============================================================================
377 ===============================================================================
380 void S_MixToBuffer(void *stream, unsigned int bufferframes)
385 unsigned char *outbytes = (unsigned char *) stream;
387 portable_sampleframe_t *paint;
400 #define S_FETCHBUFFERSIZE 4096
401 float fetchsampleframes[S_FETCHBUFFERSIZE*2];
402 const float *fetchsampleframe;
403 float vol[SND_LISTENERS];
412 // mix as many times as needed to fill the requested buffer
415 // limit to the size of the paint buffer
416 totalmixframes = min(bufferframes, PAINTBUFFER_SIZE);
418 // clear the paint buffer
419 memset(paintbuffer, 0, totalmixframes * sizeof(paintbuffer[0]));
421 // paint in the channels.
422 // channels with zero volumes still advance in time but don't paint.
423 ch = channels; // cppcheck complains here but it is wrong, channels is a channel_t[MAX_CHANNELS] and not an int
424 for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
429 if (!S_LoadSound (sfx, true))
431 if (ch->flags & CHANNELFLAG_PAUSED)
433 if (!sfx->total_length)
436 // copy the channel information to the stack for reference, otherwise the
437 // values might change during a mix if the spatializer is updating them
438 // (note: this still may get some old and some new values!)
440 speedd = ch->mixspeed * sfx->format.speed / snd_renderbuffer->format.speed;
441 for (i = 0;i < SND_LISTENERS;i++)
442 vol[i] = ch->volume[i];
444 // check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly)
446 for (i = 0;i < SND_LISTENERS;i++)
449 switch(snd_renderbuffer->format.width)
452 silent = maxvol < (1.0f / (256.0f));
453 // so silent it has zero effect
456 silent = maxvol < (1.0f / (65536.0f));
457 // so silent it has zero effect
459 default: // floating point
460 silent = maxvol < 1.0e-13f;
461 // 130 dB is difference between hearing
462 // threshold and a jackhammer from
464 // therefore, anyone who turns up
465 // volume so much they notice this
466 // cutoff, likely already has their
467 // ear-drums blown out anyway.
471 // when doing prologic mixing, some channels invert one side
472 if (ch->prologic_invert == -1)
475 // get some sfx info in a consistent form
476 totallength = sfx->total_length;
477 loopstart = (int)sfx->loopstart < totallength ? (int)sfx->loopstart : ((ch->flags & CHANNELFLAG_FORCELOOP) ? 0 : totallength);
478 looping = loopstart < totallength;
480 // do the actual paint now (may skip work if silent)
483 for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
485 // check if this is a delayed sound
488 // for a delayed sound we have to eat into the delay first
489 count = (int)floor(-posd / speedd) + 1;
490 count = bound(1, count, wantframes);
491 // let the for loop iterator apply the skip
495 // compute a fetch size that won't overflow our buffer
499 istartframe = (int)floor(posd);
500 iendframe = (int)floor(posd + (count-1) * speedd);
501 ilengthframes = count > 1 ? (iendframe - istartframe + 2) : 2;
502 if (ilengthframes <= S_FETCHBUFFERSIZE)
504 // reduce count by 25% and try again
508 // zero whole fetch buffer for safety
509 // (floating point noise from uninitialized memory = HORRIBLE)
510 // otherwise we would only need to clear the excess
512 memset(fetchsampleframes, 0, ilengthframes*sfx->format.channels*sizeof(fetchsampleframes[0]));
514 // if looping, do multiple fetches
518 fetch = min(ilengthframes - fetched, totallength - istartframe);
522 sfx->fetcher->getsamplesfloat(ch, sfx, istartframe, fetch, fetchsampleframes + fetched*sfx->format.channels);
523 istartframe += fetch;
526 if (istartframe == totallength && looping && fetched < ilengthframes)
528 // loop and fetch some more
529 posd += loopstart - totallength;
530 istartframe = loopstart;
538 // set up our fixedpoint resampling variables (float to int conversions are expensive so do not do one per sampleframe)
539 fetchsampleframe = fetchsampleframes;
540 indexfrac = (int)floor((posd - floor(posd)) * 65536.0);
541 indexfracstep = (int)floor(speedd * 65536.0);
544 if (sfx->format.channels == 2)
547 #if SND_LISTENERS != 8
548 #error the following code only supports up to 8 channels, update it
550 if (snd_speakerlayout.channels > 2)
553 for (i = 0;i < count;i++, paint++)
555 lerp[1] = indexfrac * (1.0f / 65536.0f);
556 lerp[0] = 1.0f - lerp[1];
557 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
558 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
559 sample[2] = (sample[0] + sample[1]) * 0.5f;
560 paint->sample[0] += sample[0] * vol[0];
561 paint->sample[1] += sample[1] * vol[1];
562 paint->sample[2] += sample[0] * vol[2];
563 paint->sample[3] += sample[1] * vol[3];
564 paint->sample[4] += sample[2] * vol[4];
565 paint->sample[5] += sample[2] * vol[5];
566 paint->sample[6] += sample[0] * vol[6];
567 paint->sample[7] += sample[1] * vol[7];
568 indexfrac += indexfracstep;
569 fetchsampleframe += 2 * (indexfrac >> 16);
576 for (i = 0;i < count;i++, paint++)
578 lerp[1] = indexfrac * (1.0f / 65536.0f);
579 lerp[0] = 1.0f - lerp[1];
580 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
581 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
582 paint->sample[0] += sample[0] * vol[0];
583 paint->sample[1] += sample[1] * vol[1];
584 indexfrac += indexfracstep;
585 fetchsampleframe += 2 * (indexfrac >> 16);
590 else if (sfx->format.channels == 1)
592 // most sounds are mono
593 #if SND_LISTENERS != 8
594 #error the following code only supports up to 8 channels, update it
596 if (snd_speakerlayout.channels > 2)
599 for (i = 0;i < count;i++, paint++)
601 lerp[1] = indexfrac * (1.0f / 65536.0f);
602 lerp[0] = 1.0f - lerp[1];
603 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
604 paint->sample[0] += sample[0] * vol[0];
605 paint->sample[1] += sample[0] * vol[1];
606 paint->sample[2] += sample[0] * vol[2];
607 paint->sample[3] += sample[0] * vol[3];
608 paint->sample[4] += sample[0] * vol[4];
609 paint->sample[5] += sample[0] * vol[5];
610 paint->sample[6] += sample[0] * vol[6];
611 paint->sample[7] += sample[0] * vol[7];
612 indexfrac += indexfracstep;
613 fetchsampleframe += (indexfrac >> 16);
620 for (i = 0;i < count;i++, paint++)
622 lerp[1] = indexfrac * (1.0f / 65536.0f);
623 lerp[0] = 1.0f - lerp[1];
624 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
625 paint->sample[0] += sample[0] * vol[0];
626 paint->sample[1] += sample[0] * vol[1];
627 indexfrac += indexfracstep;
628 fetchsampleframe += (indexfrac >> 16);
636 if (!looping && istartframe == totallength)
637 S_StopChannel(ch - channels, false, false);
640 S_SoftClipPaintBuffer(paintbuffer, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
642 S_UnderwaterFilter(totalmixframes);
645 #ifdef CONFIG_VIDEO_CAPTURE
646 if (!snd_usethreadedmixing)
647 S_CaptureAVISound(paintbuffer, totalmixframes);
650 S_ConvertPaintBuffer(paintbuffer, outbytes, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
652 // advance the output pointer
653 outbytes += totalmixframes * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
654 bufferframes -= totalmixframes;