2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 typedef struct portable_samplepair_s
27 int sample[SND_LISTENERS];
28 } portable_sampleframe_t;
30 // LordHavoc: was 512, expanded to 2048
31 #define PAINTBUFFER_SIZE 2048
32 portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
35 // FIXME: this desyncs with the video too easily
36 extern void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate);
37 static void S_CaptureAVISound(size_t length)
40 unsigned char out[PAINTBUFFER_SIZE * 4];
41 unsigned char* out_ptr;
43 if (!cls.capturevideo_active)
46 // write the sound buffer as little endian 16bit interleaved stereo
47 for(i = 0, out_ptr = out; i < length; i++, out_ptr += 4)
51 n0 = paintbuffer[i].sample[0];
52 n0 = bound(-32768, n0, 32767);
53 out_ptr[0] = (unsigned char)n0;
54 out_ptr[1] = (unsigned char)(n0 >> 8);
56 n1 = paintbuffer[i].sample[1];
57 n1 = bound(-32768, n1, 32767);
58 out_ptr[2] = (unsigned char)n1;
59 out_ptr[3] = (unsigned char)(n1 >> 8);
61 SCR_CaptureVideo_SoundFrame(out, length, snd_renderbuffer->format.speed);
64 static unsigned int S_TransferPaintBuffer(snd_ringbuffer_t* rb, unsigned int starttime, unsigned int endtime)
66 unsigned int partialend;
69 if (!simsound && !SndSys_LockRenderBuffer())
72 partialend = starttime;
73 while (partialend < endtime) // handle recirculating buffer issues
75 unsigned int startoffset, maxframes, nbframes, i;
77 portable_sampleframe_t *painted_ptr;
80 startoffset = partialend % rb->maxframes;
81 maxframes = rb->maxframes - startoffset;
82 nbframes = endtime - partialend;
83 if (nbframes > maxframes)
86 rb_ptr = &rb->ring[startoffset * rb->format.width * rb->format.channels];
87 painted_ptr = &paintbuffer[partialend - starttime];
89 if (rb->format.width == 2) // 16bit
91 short *snd_out = (short*)rb_ptr;
92 if (rb->format.channels == 8) // 7.1 surround
94 if (snd_swapstereo.value)
96 for (i = 0; i < nbframes; i++, painted_ptr++)
98 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
99 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
100 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
101 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
102 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
103 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
104 *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
105 *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
110 for (i = 0;i < nbframes;i++, painted_ptr++)
112 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
113 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
114 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
115 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
116 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
117 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
118 *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
119 *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
123 else if (rb->format.channels == 6) // 5.1 surround
125 if (snd_swapstereo.value)
127 for (i = 0; i < nbframes; i++, painted_ptr++)
129 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
130 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
131 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
132 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
133 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
134 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
139 for (i = 0; i < nbframes; i++, painted_ptr++)
141 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
142 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
143 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
144 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
145 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
146 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
150 else if (rb->format.channels == 4) // 4.0 surround
152 if (snd_swapstereo.value)
154 for (i = 0; i < nbframes; i++, painted_ptr++)
156 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
157 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
158 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
159 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
164 for (i = 0; i < nbframes; i++, painted_ptr++)
166 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
167 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
168 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
169 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
173 else if (rb->format.channels == 2) // 2.0 stereo
175 if (snd_swapstereo.value)
177 for (i = 0; i < nbframes; i++, painted_ptr++)
179 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
180 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
185 for (i = 0; i < nbframes; i++, painted_ptr++)
187 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
188 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
192 else if (rb->format.channels == 1) // 1.0 mono
194 for (i = 0; i < nbframes; i++, painted_ptr++)
196 val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
197 *snd_out++ = bound(-32768, val, 32767);
203 unsigned char *snd_out = (unsigned char*)rb_ptr;
204 if (rb->format.channels == 8) // 7.1 surround
206 if (snd_swapstereo.value)
208 for (i = 0; i < nbframes; i++, painted_ptr++)
210 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
211 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
212 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
213 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
214 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
215 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
216 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
217 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
222 for (i = 0; i < nbframes; i++, painted_ptr++)
224 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
225 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
226 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
227 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
228 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
229 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
230 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
231 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
235 else if (rb->format.channels == 6) // 5.1 surround
237 if (snd_swapstereo.value)
239 for (i = 0; i < nbframes; i++, painted_ptr++)
241 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
242 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
243 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
244 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
245 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
246 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
251 for (i = 0; i < nbframes; i++, painted_ptr++)
253 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
254 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
255 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
256 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
257 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
258 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
262 else if (rb->format.channels == 4) // 4.0 surround
264 if (snd_swapstereo.value)
266 for (i = 0; i < nbframes; i++, painted_ptr++)
268 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
269 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
270 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
271 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
276 for (i = 0; i < nbframes; i++, painted_ptr++)
278 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
279 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
280 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
281 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
285 else if (rb->format.channels == 2) // 2.0 stereo
287 if (snd_swapstereo.value)
289 for (i = 0; i < nbframes; i++, painted_ptr++)
291 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
292 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
297 for (i = 0; i < nbframes; i++, painted_ptr++)
299 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
300 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
304 else if (rb->format.channels == 1) // 1.0 mono
306 for (i = 0;i < nbframes;i++, painted_ptr++)
308 val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
309 *snd_out++ = bound(0, val, 255);
314 partialend += nbframes;
317 rb->endframe = endtime;
319 // Remove outdated samples from the ring buffer, if any
320 if (rb->startframe < soundtime)
321 rb->startframe = soundtime;
324 SndSys_UnlockRenderBuffer();
326 return endtime - starttime;
331 ===============================================================================
335 ===============================================================================
338 static qboolean SND_PaintChannel (channel_t *ch, unsigned int count)
340 int snd_vol, vol[SND_LISTENERS];
341 const snd_buffer_t *sb;
342 unsigned int i, sb_offset;
344 // If this channel manages its own volume
345 if (ch->flags & CHANNELFLAG_FULLVOLUME)
348 snd_vol = (int)(volume.value * 256);
350 for (i = 0;i < SND_LISTENERS;i++)
351 vol[i] = ch->listener_volume[i] * snd_vol;
354 sb = ch->sfx->fetcher->getsb (ch, &sb_offset, count);
357 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
358 ch->sfx->name, count);
362 #if SND_LISTENERS != 8
363 # error the following code only supports up to 8 channels, update it
365 if (sb->format.width == 1)
367 const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
369 // Stereo sound support
370 if (sb->format.channels == 2)
372 if (vol[6] + vol[7] > 0)
374 for (i = 0;i < count;i++)
376 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
377 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
378 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
379 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
380 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
381 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
382 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 8;
383 paintbuffer[i].sample[7] += (samples[1] * vol[7]) >> 8;
387 else if (vol[4] + vol[5] > 0)
389 for (i = 0;i < count;i++)
391 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
392 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
393 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
394 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
395 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
396 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
400 else if (vol[2] + vol[3] > 0)
402 for (i = 0;i < count;i++)
404 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
405 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
406 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
407 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
411 else if (vol[0] + vol[1] > 0)
413 for (i = 0;i < count;i++)
415 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
416 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
421 else if (sb->format.channels == 1)
423 if (vol[6] + vol[7] > 0)
425 for (i = 0;i < count;i++)
427 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
428 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
429 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
430 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
431 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 8;
432 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 8;
433 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 8;
434 paintbuffer[i].sample[7] += (samples[0] * vol[7]) >> 8;
438 else if (vol[4] + vol[5] > 0)
440 for (i = 0;i < count;i++)
442 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
443 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
444 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
445 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
446 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 8;
447 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 8;
451 else if (vol[2] + vol[3] > 0)
453 for (i = 0;i < count;i++)
455 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
456 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
457 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
458 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
462 else if (vol[0] + vol[1] > 0)
464 for (i = 0;i < count;i++)
466 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
467 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
473 return false; // unsupported number of channels in sound
475 else if (sb->format.width == 2)
477 const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
479 // Stereo sound support
480 if (sb->format.channels == 2)
482 if (vol[6] + vol[7] > 0)
484 for (i = 0;i < count;i++)
486 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
487 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
488 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
489 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
490 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
491 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
492 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 16;
493 paintbuffer[i].sample[7] += (samples[1] * vol[7]) >> 16;
497 else if (vol[4] + vol[5] > 0)
499 for (i = 0;i < count;i++)
501 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
502 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
503 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
504 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
505 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
506 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
510 else if (vol[2] + vol[3] > 0)
512 for (i = 0;i < count;i++)
514 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
515 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
516 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
517 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
521 else if (vol[0] + vol[1] > 0)
523 for (i = 0;i < count;i++)
525 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
526 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
531 else if (sb->format.channels == 1)
533 if (vol[6] + vol[7] > 0)
535 for (i = 0;i < count;i++)
537 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
538 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
539 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
540 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
541 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 16;
542 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 16;
543 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 16;
544 paintbuffer[i].sample[7] += (samples[0] * vol[7]) >> 16;
548 else if (vol[4] + vol[5] > 0)
550 for (i = 0;i < count;i++)
552 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
553 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
554 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
555 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
556 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 16;
557 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 16;
561 else if (vol[2] + vol[3] > 0)
563 for (i = 0;i < count;i++)
565 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
566 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
567 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
568 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
572 else if (vol[0] + vol[1] > 0)
574 for (i = 0;i < count;i++)
576 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
577 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
583 return false; // unsupported number of channels in sound
591 void S_PaintChannels (snd_ringbuffer_t* rb, unsigned int starttime, unsigned int endtime)
593 unsigned int paintedtime;
595 paintedtime = starttime;
596 while (paintedtime < endtime)
598 unsigned int partialend, i, framecount;
601 // if paintbuffer is too small
602 if (endtime > paintedtime + PAINTBUFFER_SIZE)
603 partialend = paintedtime + PAINTBUFFER_SIZE;
605 partialend = endtime;
607 // clear the paint buffer
608 memset (paintbuffer, 0, (partialend - paintedtime) * sizeof (paintbuffer[0]));
610 // paint in the channels.
612 for (i = 0; i < total_channels ; i++, ch++)
615 unsigned int ltime, j;
620 for (j = 0;j < SND_LISTENERS;j++)
621 if (ch->listener_volume[j])
623 if (j == SND_LISTENERS)
625 if (!S_LoadSound (sfx, true))
628 // if the channel is paused
629 if (ch->flags & CHANNELFLAG_PAUSED)
631 int pausedtime = partialend - paintedtime;
632 ch->lastptime += pausedtime;
633 ch->end += pausedtime;
637 // if the sound hasn't been painted last time, update his position
638 if (ch->lastptime < paintedtime)
640 ch->pos += paintedtime - ch->lastptime;
642 // If the sound should have ended by then
643 if ((unsigned int)ch->pos > sfx->total_length)
647 if (sfx->loopstart >= 0)
648 loopstart = bound(0, sfx->loopstart, (int)sfx->total_length - 1);
651 if (ch->flags & CHANNELFLAG_FORCELOOP)
657 // If the sound is looped
659 ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart;
661 ch->pos = sfx->total_length;
662 ch->end = paintedtime + sfx->total_length - ch->pos;
667 while (ltime < partialend)
673 if (ch->end < partialend)
674 count = ch->end - ltime;
676 count = partialend - ltime;
680 for (j = 0; j < SND_LISTENERS; j++)
681 ch->listener_volume[j] = bound(0, ch->listener_volume[j], 255);
683 stop_paint = !SND_PaintChannel (ch, (unsigned int)count);
687 ch->lastptime = ltime;
693 if (ltime >= ch->end)
695 // if at end of loop, restart
696 if ((sfx->loopstart >= 0 || (ch->flags & CHANNELFLAG_FORCELOOP)) && !stop_paint)
698 ch->pos = bound(0, sfx->loopstart, (int)sfx->total_length - 1);
699 ch->end = ltime + sfx->total_length - ch->pos;
701 // channel just stopped
708 S_StopChannel (ch - channels);
714 S_CaptureAVISound (partialend - paintedtime);
715 framecount = S_TransferPaintBuffer (rb, paintedtime, partialend);
716 paintedtime += framecount;
718 // If there was not enough free space in the sound buffer, stop here
719 if (paintedtime != partialend)
721 Con_DPrintf(">> S_PaintChannels: Not enough free space in the sound buffer ( %u != %u)\n", paintedtime, partialend);