]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - snd_mix.c
d497578129dedf92fd98506d4b416e26324ab95c
[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
25 static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
26 static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
27
28 extern speakerlayout_t snd_speakerlayout; // for querying the listeners
29
30 extern void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length);
31 static void S_CaptureAVISound(size_t length)
32 {
33         size_t i;
34         unsigned int j;
35
36         if (!cls.capturevideo.active)
37                 return;
38
39         // undo whatever swapping the channel layout (swapstereo, ALSA) did
40         for(j = 0; j < snd_speakerlayout.channels; ++j)
41         {
42                 unsigned int j0 = snd_speakerlayout.listeners[j].channel_unswapped;
43                 for(i = 0; i < length; ++i)
44                         paintbuffer_unswapped[i].sample[j0] = paintbuffer[i].sample[j];
45         }
46
47         SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
48 }
49
50 static void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
51 {
52         int i, val;
53         if (width == 2)  // 16bit
54         {
55                 short *snd_out = (short*)rb_ptr;
56                 if (channels == 8)  // 7.1 surround
57                 {
58                         for (i = 0;i < nbframes;i++, painted_ptr++)
59                         {
60                                 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
61                                 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
62                                 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
63                                 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
64                                 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
65                                 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
66                                 *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
67                                 *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
68                         }
69                 }
70                 else if (channels == 6)  // 5.1 surround
71                 {
72                         for (i = 0; i < nbframes; i++, painted_ptr++)
73                         {
74                                 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
75                                 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
76                                 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
77                                 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
78                                 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
79                                 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
80                         }
81                 }
82                 else if (channels == 4)  // 4.0 surround
83                 {
84                         for (i = 0; i < nbframes; i++, painted_ptr++)
85                         {
86                                 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
87                                 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
88                                 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
89                                 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
90                         }
91                 }
92                 else if (channels == 2)  // 2.0 stereo
93                 {
94                         for (i = 0; i < nbframes; i++, painted_ptr++)
95                         {
96                                 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
97                                 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
98                         }
99                 }
100                 else if (channels == 1)  // 1.0 mono
101                 {
102                         for (i = 0; i < nbframes; i++, painted_ptr++)
103                         {
104                                 val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
105                                 *snd_out++ = bound(-32768, val, 32767);
106                         }
107                 }
108
109                 // noise is really really annoying
110                 if (cls.timedemo)
111                         memset(rb_ptr, 0, nbframes * channels * width);
112         }
113         else  // 8bit
114         {
115                 unsigned char *snd_out = (unsigned char*)rb_ptr;
116                 if (channels == 8)  // 7.1 surround
117                 {
118                         for (i = 0; i < nbframes; i++, painted_ptr++)
119                         {
120                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
121                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
122                                 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
123                                 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
124                                 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
125                                 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
126                                 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
127                                 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
128                         }
129                 }
130                 else if (channels == 6)  // 5.1 surround
131                 {
132                         for (i = 0; i < nbframes; i++, painted_ptr++)
133                         {
134                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
135                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
136                                 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
137                                 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
138                                 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
139                                 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
140                         }
141                 }
142                 else if (channels == 4)  // 4.0 surround
143                 {
144                         for (i = 0; i < nbframes; i++, painted_ptr++)
145                         {
146                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
147                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
148                                 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
149                                 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
150                         }
151                 }
152                 else if (channels == 2)  // 2.0 stereo
153                 {
154                         for (i = 0; i < nbframes; i++, painted_ptr++)
155                         {
156                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
157                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
158                         }
159                 }
160                 else if (channels == 1)  // 1.0 mono
161                 {
162                         for (i = 0;i < nbframes;i++, painted_ptr++)
163                         {
164                                 val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
165                                 *snd_out++ = bound(0, val, 255);
166                         }
167                 }
168
169                 // noise is really really annoying
170                 if (cls.timedemo)
171                         memset(rb_ptr, 128, nbframes * channels);
172         }
173 }
174
175
176 /*
177 ===============================================================================
178
179 CHANNEL MIXING
180
181 ===============================================================================
182 */
183
184 static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
185 {
186         int vol[SND_LISTENERS];
187         const snd_buffer_t *sb;
188         unsigned int i, sb_offset;
189         sfx_t *sfx;
190
191         sfx = ch->sfx; // fetch the volatile variable
192         if (!sfx) // given that this is called by the mixer thread, this never happens, but...
193                 return false;
194
195         // move to the stack (do we need to?)
196         for (i = 0;i < SND_LISTENERS;i++)
197                 vol[i] = ch->listener_volume[i];
198
199         // if volumes are all zero, just return
200         for (i = 0;i < SND_LISTENERS;i++)
201                 if (vol[i])
202                         break;
203         if (i == SND_LISTENERS)
204                 return false;
205
206         sb_offset = ch->pos;
207         sb = sfx->fetcher->getsb (sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
208         if (sb == NULL)
209         {
210                 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
211                                         sfx->name); // , count); // or add this? FIXME
212                 return false;
213         }
214         else
215         {
216 #if SND_LISTENERS != 8
217 #               error the following code only supports up to 8 channels, update it
218 #endif
219                 if (sb->format.width == 1)
220                 {
221                         const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
222
223                         // Stereo sound support
224                         if (sb->format.channels == 2)
225                         {
226                                 if (vol[6] + vol[7] > 0)
227                                 {
228                                         for (i = 0;i < count;i++)
229                                         {
230                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
231                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
232                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
233                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
234                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
235                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
236                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
237                                                 paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
238                                                 samples += 2;
239                                         }
240                                 }
241                                 else if (vol[4] + vol[5] > 0)
242                                 {
243                                         for (i = 0;i < count;i++)
244                                         {
245                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
246                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
247                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
248                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
249                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
250                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
251                                                 samples += 2;
252                                         }
253                                 }
254                                 else if (vol[2] + vol[3] > 0)
255                                 {
256                                         for (i = 0;i < count;i++)
257                                         {
258                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
259                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
260                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
261                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
262                                                 samples += 2;
263                                         }
264                                 }
265                                 else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
266                                 {
267                                         for (i = 0;i < count;i++)
268                                         {
269                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
270                                                 paint[i].sample[1] -= (samples[1] * vol[1]) >> 8;
271                                                 samples += 2;
272                                         }
273                                 }
274                                 else if (vol[0] + vol[1] > 0)
275                                 {
276                                         for (i = 0;i < count;i++)
277                                         {
278                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
279                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
280                                                 samples += 2;
281                                         }
282                                 }
283                         }
284                         else if (sb->format.channels == 1)
285                         {
286                                 if (vol[6] + vol[7] > 0)
287                                 {
288                                         for (i = 0;i < count;i++)
289                                         {
290                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
291                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
292                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
293                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
294                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
295                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
296                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
297                                                 paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
298                                                 samples += 1;
299                                         }
300                                 }
301                                 else if (vol[4] + vol[5] > 0)
302                                 {
303                                         for (i = 0;i < count;i++)
304                                         {
305                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
306                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
307                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
308                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
309                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
310                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
311                                                 samples += 1;
312                                         }
313                                 }
314                                 else if (vol[2] + vol[3] > 0)
315                                 {
316                                         for (i = 0;i < count;i++)
317                                         {
318                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
319                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
320                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
321                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
322                                                 samples += 1;
323                                         }
324                                 }
325                                 else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
326                                 {
327                                         for (i = 0;i < count;i++)
328                                         {
329                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
330                                                 paint[i].sample[1] -= (samples[0] * vol[1]) >> 8;
331                                                 samples += 1;
332                                         }
333                                 }
334                                 else if (vol[0] + vol[1] > 0)
335                                 {
336                                         for (i = 0;i < count;i++)
337                                         {
338                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
339                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
340                                                 samples += 1;
341                                         }
342                                 }
343                         }
344                         else
345                                 return false; // unsupported number of channels in sound
346                 }
347                 else if (sb->format.width == 2)
348                 {
349                         const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
350
351                         // Stereo sound support
352                         if (sb->format.channels == 2)
353                         {
354                                 if (vol[6] + vol[7] > 0)
355                                 {
356                                         for (i = 0;i < count;i++)
357                                         {
358                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
359                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
360                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
361                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
362                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
363                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
364                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
365                                                 paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
366                                                 samples += 2;
367                                         }
368                                 }
369                                 else if (vol[4] + vol[5] > 0)
370                                 {
371                                         for (i = 0;i < count;i++)
372                                         {
373                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
374                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
375                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
376                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
377                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
378                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
379                                                 samples += 2;
380                                         }
381                                 }
382                                 else if (vol[2] + vol[3] > 0)
383                                 {
384                                         for (i = 0;i < count;i++)
385                                         {
386                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
387                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
388                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
389                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
390                                                 samples += 2;
391                                         }
392                                 }
393                                 else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
394                                 {
395                                         for (i = 0;i < count;i++)
396                                         {
397                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
398                                                 paint[i].sample[1] -= (samples[1] * vol[1]) >> 16;
399                                                 samples += 2;
400                                         }
401                                 }
402                                 else if (vol[0] + vol[1] > 0)
403                                 {
404                                         for (i = 0;i < count;i++)
405                                         {
406                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
407                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
408                                                 samples += 2;
409                                         }
410                                 }
411                         }
412                         else if (sb->format.channels == 1)
413                         {
414                                 if (vol[6] + vol[7] > 0)
415                                 {
416                                         for (i = 0;i < count;i++)
417                                         {
418                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
419                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
420                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
421                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
422                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
423                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
424                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
425                                                 paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
426                                                 samples += 1;
427                                         }
428                                 }
429                                 else if (vol[4] + vol[5] > 0)
430                                 {
431                                         for (i = 0;i < count;i++)
432                                         {
433                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
434                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
435                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
436                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
437                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
438                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
439                                                 samples += 1;
440                                         }
441                                 }
442                                 else if (vol[2] + vol[3] > 0)
443                                 {
444                                         for (i = 0;i < count;i++)
445                                         {
446                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
447                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
448                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
449                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
450                                                 samples += 1;
451                                         }
452                                 }
453                                 else if (vol[0] + vol[1] > 0 && ch->prologic_invert == -1)
454                                 {
455                                         for (i = 0;i < count;i++)
456                                         {
457                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
458                                                 paint[i].sample[1] -= (samples[0] * vol[1]) >> 16;
459                                                 samples += 1;
460                                         }
461                                 }
462                                 else if (vol[0] + vol[1] > 0)
463                                 {
464                                         for (i = 0;i < count;i++)
465                                         {
466                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
467                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
468                                                 samples += 1;
469                                         }
470                                 }
471                         }
472                         else
473                                 return false; // unsupported number of channels in sound
474                 }
475         }
476         return true;
477 }
478
479 void S_MixToBuffer(void *stream, unsigned int bufferframes)
480 {
481         unsigned int i;
482         channel_t *ch;
483         unsigned int frames;
484         unsigned char *outbytes = (unsigned char *) stream;
485
486         // mix as many times as needed to fill the requested buffer
487         while (bufferframes)
488         {
489                 // limit to the size of the paint buffer
490                 frames = min(bufferframes, PAINTBUFFER_SIZE);
491
492                 // clear the paint buffer
493                 memset (paintbuffer, 0, frames * sizeof (paintbuffer[0]));
494
495                 // paint in the channels.
496                 // channels with zero volumes still advance in time but don't paint.
497                 ch = channels;
498                 for (i = 0; i < total_channels ; i++, ch++)
499                 {
500                         sfx_t *sfx;
501                         int ltime;
502                         int count;
503
504                         sfx = ch->sfx;
505                         if (sfx == NULL)
506                                 continue;
507                         if (!S_LoadSound (sfx, true))
508                                 continue;
509                         if (ch->flags & CHANNELFLAG_PAUSED)
510                                 continue;
511                         if (!sfx->total_length)
512                                 continue;
513                         if (sfx->total_length < 0 || sfx->total_length > 1<<30)
514                                 Sys_Error("S_MixToBuffer: sfx corrupt\n");
515
516                         ltime = 0;
517                         if (ch->pos < 0)
518                         {
519                                 count = -ch->pos;
520                                 count = min(count, (int)frames - ltime);
521                                 ch->pos += count;
522                                 ltime += count;
523                         }
524
525                         while (ltime < (int)frames)
526                         {
527                                 // paint up to end of buffer or of input, whichever is lower
528                                 count = sfx->total_length - ch->pos;
529                                 count = bound(0, count, (int)frames - ltime);
530                                 // mix the remaining samples
531                                 if (count)
532                                 {
533                                         SND_PaintChannel (ch, paintbuffer + ltime, count);
534                                         ch->pos += count;
535                                         ltime += count;
536                                 }
537                                 // if at end of sfx, loop or stop the channel
538                                 else
539                                 {
540                                         if (sfx->loopstart < sfx->total_length)
541                                                 ch->pos = sfx->loopstart;
542                                         else if (ch->flags & CHANNELFLAG_FORCELOOP)
543                                                 ch->pos = 0;
544                                         else
545                                         {
546                                                 S_StopChannel (ch - channels, false, false);
547                                                 break;
548                                         }
549                                 }
550                         }
551                 }
552
553                 if (!snd_usethreadedmixing)
554                         S_CaptureAVISound(frames);
555
556                 S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
557
558                 // advance the output pointer
559                 outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
560                 bufferframes -= frames;
561         }
562 }