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