4ed38a88b633fde65875389fb622340cc3d4b12a
[xonotic/darkplaces.git] / snd_mix.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 #include "quakedef.h"
22 #include "snd_main.h"
23
24 extern cvar_t snd_softclip;
25
26 static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
27 static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
28
29 extern speakerlayout_t snd_speakerlayout; // for querying the listeners
30
31 #ifdef CONFIG_VIDEO_CAPTURE
32 static void S_CaptureAVISound(const portable_sampleframe_t *sampleframes, size_t length)
33 {
34         size_t i;
35         unsigned int j;
36
37         if (!cls.capturevideo.active)
38                 return;
39
40         // undo whatever swapping the channel layout (swapstereo, ALSA) did
41         for(j = 0; j < snd_speakerlayout.channels; ++j)
42         {
43                 unsigned int j0 = snd_speakerlayout.listeners[j].channel_unswapped;
44                 for(i = 0; i < length; ++i)
45                         paintbuffer_unswapped[i].sample[j0] = sampleframes[i].sample[j];
46         }
47
48         SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
49 }
50 #endif
51
52 extern cvar_t snd_softclip;
53
54 static void S_SoftClipPaintBuffer(portable_sampleframe_t *painted_ptr, int nbframes, int width, int nchannels)
55 {
56         int i;
57
58         if((snd_softclip.integer == 1 && width <= 2) || snd_softclip.integer > 1)
59         {
60                 portable_sampleframe_t *p = painted_ptr;
61
62 #if 0
63 /* Soft clipping, the sound of a dream, thanks to Jon Wattes
64    post to Musicdsp.org */
65 #define SOFTCLIP(x) (x) = sin(bound(-M_PI/2, (x), M_PI/2)) * 0.25
66 #endif
67
68                 // let's do a simple limiter instead, seems to sound better
69                 static float maxvol = 0;
70                 maxvol = max(1.0f, maxvol * (1.0f - nbframes / (0.4f * snd_renderbuffer->format.speed)));
71 #define SOFTCLIP(x) if(fabs(x)>maxvol) maxvol=fabs(x); (x) /= maxvol;
72
73                 if (nchannels == 8)  // 7.1 surround
74                 {
75                         for (i = 0;i < nbframes;i++, p++)
76                         {
77                                 SOFTCLIP(p->sample[0]);
78                                 SOFTCLIP(p->sample[1]);
79                                 SOFTCLIP(p->sample[2]);
80                                 SOFTCLIP(p->sample[3]);
81                                 SOFTCLIP(p->sample[4]);
82                                 SOFTCLIP(p->sample[5]);
83                                 SOFTCLIP(p->sample[6]);
84                                 SOFTCLIP(p->sample[7]);
85                         }
86                 }
87                 else if (nchannels == 6)  // 5.1 surround
88                 {
89                         for (i = 0; i < nbframes; i++, p++)
90                         {
91                                 SOFTCLIP(p->sample[0]);
92                                 SOFTCLIP(p->sample[1]);
93                                 SOFTCLIP(p->sample[2]);
94                                 SOFTCLIP(p->sample[3]);
95                                 SOFTCLIP(p->sample[4]);
96                                 SOFTCLIP(p->sample[5]);
97                         }
98                 }
99                 else if (nchannels == 4)  // 4.0 surround
100                 {
101                         for (i = 0; i < nbframes; i++, p++)
102                         {
103                                 SOFTCLIP(p->sample[0]);
104                                 SOFTCLIP(p->sample[1]);
105                                 SOFTCLIP(p->sample[2]);
106                                 SOFTCLIP(p->sample[3]);
107                         }
108                 }
109                 else if (nchannels == 2)  // 2.0 stereo
110                 {
111                         for (i = 0; i < nbframes; i++, p++)
112                         {
113                                 SOFTCLIP(p->sample[0]);
114                                 SOFTCLIP(p->sample[1]);
115                         }
116                 }
117                 else if (nchannels == 1)  // 1.0 mono
118                 {
119                         for (i = 0; i < nbframes; i++, p++)
120                         {
121                                 SOFTCLIP(p->sample[0]);
122                         }
123                 }
124 #undef SOFTCLIP
125         }
126 }
127
128 static void S_ConvertPaintBuffer(portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int nchannels)
129 {
130         int i;
131         if (width == 4)  // 32bit float
132         {
133                 float *snd_out = (float*)rb_ptr;
134                 if (nchannels == 8)  // 7.1 surround
135                 {
136                         for (i = 0; i < nbframes; i++, painted_ptr++)
137                         {
138                                 *snd_out++ = painted_ptr->sample[0];
139                                 *snd_out++ = painted_ptr->sample[1];
140                                 *snd_out++ = painted_ptr->sample[2];
141                                 *snd_out++ = painted_ptr->sample[3];
142                                 *snd_out++ = painted_ptr->sample[4];
143                                 *snd_out++ = painted_ptr->sample[5];
144                                 *snd_out++ = painted_ptr->sample[6];
145                                 *snd_out++ = painted_ptr->sample[7];
146                         }
147                 }
148                 else if (nchannels == 6)  // 5.1 surround
149                 {
150                         for (i = 0; i < nbframes; i++, painted_ptr++)
151                         {
152                                 *snd_out++ = painted_ptr->sample[0];
153                                 *snd_out++ = painted_ptr->sample[1];
154                                 *snd_out++ = painted_ptr->sample[2];
155                                 *snd_out++ = painted_ptr->sample[3];
156                                 *snd_out++ = painted_ptr->sample[4];
157                                 *snd_out++ = painted_ptr->sample[5];
158                         }
159                 }
160                 else if (nchannels == 4)  // 4.0 surround
161                 {
162                         for (i = 0; i < nbframes; i++, painted_ptr++)
163                         {
164                                 *snd_out++ = painted_ptr->sample[0];
165                                 *snd_out++ = painted_ptr->sample[1];
166                                 *snd_out++ = painted_ptr->sample[2];
167                                 *snd_out++ = painted_ptr->sample[3];
168                         }
169                 }
170                 else if (nchannels == 2)  // 2.0 stereo
171                 {
172                         for (i = 0; i < nbframes; i++, painted_ptr++)
173                         {
174                                 *snd_out++ = painted_ptr->sample[0];
175                                 *snd_out++ = painted_ptr->sample[1];
176                         }
177                 }
178                 else if (nchannels == 1)  // 1.0 mono
179                 {
180                         for (i = 0; i < nbframes; i++, painted_ptr++)
181                         {
182                                 *snd_out++ = painted_ptr->sample[0];
183                         }
184                 }
185
186                 // noise is really really annoying
187                 if (cls.timedemo)
188                         memset(rb_ptr, 0, nbframes * nchannels * width);
189         }
190         else if (width == 2)  // 16bit
191         {
192                 short *snd_out = (short*)rb_ptr;
193                 if (nchannels == 8)  // 7.1 surround
194                 {
195                         for (i = 0;i < nbframes;i++, painted_ptr++)
196                         {
197                                 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
198                                 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
199                                 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
200                                 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
201                                 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
202                                 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
203                                 val = (int)(painted_ptr->sample[6] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
204                                 val = (int)(painted_ptr->sample[7] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
205                         }
206                 }
207                 else if (nchannels == 6)  // 5.1 surround
208                 {
209                         for (i = 0; i < nbframes; i++, painted_ptr++)
210                         {
211                                 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
212                                 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
213                                 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
214                                 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
215                                 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
216                                 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
217                         }
218                 }
219                 else if (nchannels == 4)  // 4.0 surround
220                 {
221                         for (i = 0; i < nbframes; i++, painted_ptr++)
222                         {
223                                 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
224                                 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
225                                 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
226                                 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
227                         }
228                 }
229                 else if (nchannels == 2)  // 2.0 stereo
230                 {
231                         for (i = 0; i < nbframes; i++, painted_ptr++)
232                         {
233                                 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
234                                 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
235                         }
236                 }
237                 else if (nchannels == 1)  // 1.0 mono
238                 {
239                         for (i = 0; i < nbframes; i++, painted_ptr++)
240                         {
241                                 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 16384.0f);*snd_out++ = bound(-32768, val, 32767);
242                         }
243                 }
244
245                 // noise is really really annoying
246                 if (cls.timedemo)
247                         memset(rb_ptr, 0, nbframes * nchannels * width);
248         }
249         else  // 8bit
250         {
251                 unsigned char *snd_out = (unsigned char*)rb_ptr;
252                 if (nchannels == 8)  // 7.1 surround
253                 {
254                         for (i = 0; i < nbframes; i++, painted_ptr++)
255                         {
256                                 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
257                                 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
258                                 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
259                                 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
260                                 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
261                                 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
262                                 val = (int)(painted_ptr->sample[6] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
263                                 val = (int)(painted_ptr->sample[7] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
264                         }
265                 }
266                 else if (nchannels == 6)  // 5.1 surround
267                 {
268                         for (i = 0; i < nbframes; i++, painted_ptr++)
269                         {
270                                 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
271                                 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
272                                 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
273                                 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
274                                 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
275                                 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
276                         }
277                 }
278                 else if (nchannels == 4)  // 4.0 surround
279                 {
280                         for (i = 0; i < nbframes; i++, painted_ptr++)
281                         {
282                                 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
283                                 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
284                                 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
285                                 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
286                         }
287                 }
288                 else if (nchannels == 2)  // 2.0 stereo
289                 {
290                         for (i = 0; i < nbframes; i++, painted_ptr++)
291                         {
292                                 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
293                                 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
294                         }
295                 }
296                 else if (nchannels == 1)  // 1.0 mono
297                 {
298                         for (i = 0;i < nbframes;i++, painted_ptr++)
299                         {
300                                 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 64.0f) + 128; *snd_out++ = bound(0, val, 255);
301                         }
302                 }
303
304                 // noise is really really annoying
305                 if (cls.timedemo)
306                         memset(rb_ptr, 128, nbframes * nchannels);
307         }
308 }
309
310
311 /*
312 ===============================================================================
313
314 CHANNEL MIXING
315
316 ===============================================================================
317 */
318
319 void S_MixToBuffer(void *stream, unsigned int bufferframes)
320 {
321         int channelindex;
322         channel_t *ch;
323         int totalmixframes;
324         unsigned char *outbytes = (unsigned char *) stream;
325         sfx_t *sfx;
326         portable_sampleframe_t *paint;
327         int wantframes;
328         int i;
329         int count;
330         int fetched;
331         int fetch;
332         int istartframe;
333         int iendframe;
334         int ilengthframes;
335         int totallength;
336         int loopstart;
337         int indexfrac;
338         int indexfracstep;
339 #define S_FETCHBUFFERSIZE 4096
340         float fetchsampleframes[S_FETCHBUFFERSIZE*2];
341         const float *fetchsampleframe;
342         float vol[SND_LISTENERS];
343         float lerp[2];
344         float sample[3];
345         double posd;
346         double speedd;
347         float maxvol;
348         qboolean looping;
349         qboolean silent;
350
351         // mix as many times as needed to fill the requested buffer
352         while (bufferframes)
353         {
354                 // limit to the size of the paint buffer
355                 totalmixframes = min(bufferframes, PAINTBUFFER_SIZE);
356
357                 // clear the paint buffer
358                 memset(paintbuffer, 0, totalmixframes * sizeof(paintbuffer[0]));
359
360                 // paint in the channels.
361                 // channels with zero volumes still advance in time but don't paint.
362                 ch = channels; // cppcheck complains here but it is wrong, channels is a channel_t[MAX_CHANNELS] and not an int
363                 for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
364                 {
365                         sfx = ch->sfx;
366                         if (sfx == NULL)
367                                 continue;
368                         if (!S_LoadSound (sfx, true))
369                                 continue;
370                         if (ch->flags & CHANNELFLAG_PAUSED)
371                                 continue;
372                         if (!sfx->total_length)
373                                 continue;
374
375                         // copy the channel information to the stack for reference, otherwise the
376                         // values might change during a mix if the spatializer is updating them
377                         // (note: this still may get some old and some new values!)
378                         posd = ch->position;
379                         speedd = ch->mixspeed * sfx->format.speed / snd_renderbuffer->format.speed;
380                         for (i = 0;i < SND_LISTENERS;i++)
381                                 vol[i] = ch->volume[i];
382
383                         // check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly)
384                         maxvol = 0;
385                         for (i = 0;i < SND_LISTENERS;i++)
386                                 if(vol[i] > maxvol)
387                                         maxvol = vol[i];
388                         switch(snd_renderbuffer->format.width)
389                         {
390                                 case 1: // 8bpp
391                                         silent = maxvol < (1.0f / (256.0f));
392                                         // so silent it has zero effect
393                                         break;
394                                 case 2: // 16bpp
395                                         silent = maxvol < (1.0f / (65536.0f));
396                                         // so silent it has zero effect
397                                         break;
398                                 default: // floating point
399                                         silent = maxvol < 1.0e-13f;
400                                         // 130 dB is difference between hearing
401                                         // threshold and a jackhammer from
402                                         // working distance.
403                                         // therefore, anyone who turns up
404                                         // volume so much they notice this
405                                         // cutoff, likely already has their
406                                         // ear-drums blown out anyway.
407                                         break;
408                         }
409
410                         // when doing prologic mixing, some channels invert one side
411                         if (ch->prologic_invert == -1)
412                                 vol[1] *= -1.0f;
413
414                         // get some sfx info in a consistent form
415                         totallength = sfx->total_length;
416                         loopstart = (int)sfx->loopstart < totallength ? (int)sfx->loopstart : ((ch->flags & CHANNELFLAG_FORCELOOP) ? 0 : totallength);
417                         looping = loopstart < totallength;
418
419                         // do the actual paint now (may skip work if silent)
420                         paint = paintbuffer;
421                         istartframe = 0;
422                         for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
423                         {
424                                 // check if this is a delayed sound
425                                 if (posd < 0)
426                                 {
427                                         // for a delayed sound we have to eat into the delay first
428                                         count = (int)floor(-posd / speedd) + 1;
429                                         count = bound(1, count, wantframes);
430                                         // let the for loop iterator apply the skip
431                                         continue;
432                                 }
433
434                                 // compute a fetch size that won't overflow our buffer
435                                 count = wantframes;
436                                 for (;;)
437                                 {
438                                         istartframe = (int)floor(posd);
439                                         iendframe = (int)floor(posd + (count-1) * speedd);
440                                         ilengthframes = count > 1 ? (iendframe - istartframe + 2) : 2;
441                                         if (ilengthframes <= S_FETCHBUFFERSIZE)
442                                                 break;
443                                         // reduce count by 25% and try again
444                                         count -= count >> 2;
445                                 }
446
447                                 // zero whole fetch buffer for safety
448                                 // (floating point noise from uninitialized memory = HORRIBLE)
449                                 // otherwise we would only need to clear the excess
450                                 if (!silent)
451                                         memset(fetchsampleframes, 0, ilengthframes*sfx->format.channels*sizeof(fetchsampleframes[0]));
452
453                                 // if looping, do multiple fetches
454                                 fetched = 0;
455                                 for (;;)
456                                 {
457                                         fetch = min(ilengthframes - fetched, totallength - istartframe);
458                                         if (fetch > 0)
459                                         {
460                                                 if (!silent)
461                                                         sfx->fetcher->getsamplesfloat(ch, sfx, istartframe, fetch, fetchsampleframes + fetched*sfx->format.channels);
462                                                 istartframe += fetch;
463                                                 fetched += fetch;
464                                         }
465                                         if (istartframe == totallength && looping && fetched < ilengthframes)
466                                         {
467                                                 // loop and fetch some more
468                                                 posd += loopstart - totallength;
469                                                 istartframe = loopstart;
470                                         }
471                                         else
472                                         {
473                                                 break;
474                                         }
475                                 }
476
477                                 // set up our fixedpoint resampling variables (float to int conversions are expensive so do not do one per sampleframe)
478                                 fetchsampleframe = fetchsampleframes;
479                                 indexfrac = (int)floor((posd - floor(posd)) * 65536.0);
480                                 indexfracstep = (int)floor(speedd * 65536.0);
481                                 if (!silent)
482                                 {
483                                         if (sfx->format.channels == 2)
484                                         {
485                                                 // music is stereo
486 #if SND_LISTENERS != 8
487 #error the following code only supports up to 8 channels, update it
488 #endif
489                                                 if (snd_speakerlayout.channels > 2)
490                                                 {
491                                                         // surround mixing
492                                                         for (i = 0;i < count;i++, paint++)
493                                                         {
494                                                                 lerp[1] = indexfrac * (1.0f / 65536.0f);
495                                                                 lerp[0] = 1.0f - lerp[1];
496                                                                 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
497                                                                 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
498                                                                 sample[2] = (sample[0] + sample[1]) * 0.5f;
499                                                                 paint->sample[0] += sample[0] * vol[0];
500                                                                 paint->sample[1] += sample[1] * vol[1];
501                                                                 paint->sample[2] += sample[0] * vol[2];
502                                                                 paint->sample[3] += sample[1] * vol[3];
503                                                                 paint->sample[4] += sample[2] * vol[4];
504                                                                 paint->sample[5] += sample[2] * vol[5];
505                                                                 paint->sample[6] += sample[0] * vol[6];
506                                                                 paint->sample[7] += sample[1] * vol[7];
507                                                                 indexfrac += indexfracstep;
508                                                                 fetchsampleframe += 2 * (indexfrac >> 16);
509                                                                 indexfrac &= 0xFFFF;
510                                                         }
511                                                 }
512                                                 else
513                                                 {
514                                                         // stereo mixing
515                                                         for (i = 0;i < count;i++, paint++)
516                                                         {
517                                                                 lerp[1] = indexfrac * (1.0f / 65536.0f);
518                                                                 lerp[0] = 1.0f - lerp[1];
519                                                                 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
520                                                                 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
521                                                                 paint->sample[0] += sample[0] * vol[0];
522                                                                 paint->sample[1] += sample[1] * vol[1];
523                                                                 indexfrac += indexfracstep;
524                                                                 fetchsampleframe += 2 * (indexfrac >> 16);
525                                                                 indexfrac &= 0xFFFF;
526                                                         }
527                                                 }
528                                         }
529                                         else if (sfx->format.channels == 1)
530                                         {
531                                                 // most sounds are mono
532 #if SND_LISTENERS != 8
533 #error the following code only supports up to 8 channels, update it
534 #endif
535                                                 if (snd_speakerlayout.channels > 2)
536                                                 {
537                                                         // surround mixing
538                                                         for (i = 0;i < count;i++, paint++)
539                                                         {
540                                                                 lerp[1] = indexfrac * (1.0f / 65536.0f);
541                                                                 lerp[0] = 1.0f - lerp[1];
542                                                                 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
543                                                                 paint->sample[0] += sample[0] * vol[0];
544                                                                 paint->sample[1] += sample[0] * vol[1];
545                                                                 paint->sample[2] += sample[0] * vol[2];
546                                                                 paint->sample[3] += sample[0] * vol[3];
547                                                                 paint->sample[4] += sample[0] * vol[4];
548                                                                 paint->sample[5] += sample[0] * vol[5];
549                                                                 paint->sample[6] += sample[0] * vol[6];
550                                                                 paint->sample[7] += sample[0] * vol[7];
551                                                                 indexfrac += indexfracstep;
552                                                                 fetchsampleframe += (indexfrac >> 16);
553                                                                 indexfrac &= 0xFFFF;
554                                                         }
555                                                 }
556                                                 else
557                                                 {
558                                                         // stereo mixing
559                                                         for (i = 0;i < count;i++, paint++)
560                                                         {
561                                                                 lerp[1] = indexfrac * (1.0f / 65536.0f);
562                                                                 lerp[0] = 1.0f - lerp[1];
563                                                                 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
564                                                                 paint->sample[0] += sample[0] * vol[0];
565                                                                 paint->sample[1] += sample[0] * vol[1];
566                                                                 indexfrac += indexfracstep;
567                                                                 fetchsampleframe += (indexfrac >> 16);
568                                                                 indexfrac &= 0xFFFF;
569                                                         }
570                                                 }
571                                         }
572                                 }
573                         }
574                         ch->position = posd;
575                         if (!looping && istartframe == totallength)
576                                 S_StopChannel(ch - channels, false, false);
577                 }
578
579                 S_SoftClipPaintBuffer(paintbuffer, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
580
581 #ifdef CONFIG_VIDEO_CAPTURE
582                 if (!snd_usethreadedmixing)
583                         S_CaptureAVISound(paintbuffer, totalmixframes);
584 #endif
585
586                 S_ConvertPaintBuffer(paintbuffer, outbytes, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
587
588                 // advance the output pointer
589                 outbytes += totalmixframes * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
590                 bufferframes -= totalmixframes;
591         }
592 }