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.
20 // snd_mix.c -- portable code to mix sounds
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];
34 // FIXME: this desyncs with the video too easily
35 extern qboolean cl_capturevideo_active;
36 extern void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate);
37 void S_CaptureAVISound(portable_sampleframe_t *buf, size_t length)
41 unsigned char out[PAINTBUFFER_SIZE * 4];
42 if (!cl_capturevideo_active)
44 // write the sound buffer as little endian 16bit interleaved stereo
45 for(i = 0;i < length;i++)
48 n = bound(-32768, n, 32767);
49 out[i*4+0] = n & 0xFF;
50 out[i*4+1] = (n >> 8) & 0xFF;
52 n = bound(-32768, n, 32767);
53 out[i*4+2] = n & 0xFF;
54 out[i*4+3] = (n >> 8) & 0xFF;
56 SCR_CaptureVideo_SoundFrame(out, length, shm->format.speed);
59 // TODO: rewrite this function
60 void S_TransferPaintBuffer(int endtime)
64 portable_sampleframe_t *snd_p;
68 if ((pbuf = S_LockBuffer()))
71 lpaintedtime = paintedtime;
72 for (lpaintedtime = paintedtime;lpaintedtime < endtime;lpaintedtime += snd_frames)
74 // handle recirculating buffer issues
75 i = lpaintedtime & (shm->sampleframes - 1);
76 snd_frames = shm->sampleframes - i;
77 if (snd_frames > endtime - lpaintedtime)
78 snd_frames = endtime - lpaintedtime;
79 if (shm->format.width == 2)
82 short *snd_out = (short *) pbuf + i * shm->format.channels;
83 if (shm->format.channels == 8)
86 if (snd_swapstereo.value)
88 for (i = 0;i < snd_frames;i++, snd_p++)
90 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
91 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
92 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
93 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
94 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
95 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
96 *snd_out++ = bound(-32768, snd_p->sample[6], 32767);
97 *snd_out++ = bound(-32768, snd_p->sample[7], 32767);
102 for (i = 0;i < snd_frames;i++, snd_p++)
104 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
105 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
106 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
107 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
108 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
109 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
110 *snd_out++ = bound(-32768, snd_p->sample[6], 32767);
111 *snd_out++ = bound(-32768, snd_p->sample[7], 32767);
115 else if (shm->format.channels == 6)
118 if (snd_swapstereo.value)
120 for (i = 0;i < snd_frames;i++, snd_p++)
122 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
123 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
124 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
125 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
126 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
127 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
132 for (i = 0;i < snd_frames;i++, snd_p++)
134 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
135 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
136 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
137 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
138 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
139 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
143 else if (shm->format.channels == 4)
146 if (snd_swapstereo.value)
148 for (i = 0;i < snd_frames;i++, snd_p++)
150 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
151 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
152 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
153 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
158 for (i = 0;i < snd_frames;i++, snd_p++)
160 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
161 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
162 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
163 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
167 else if (shm->format.channels == 2)
170 if (snd_swapstereo.value)
172 for (i = 0;i < snd_frames;i++, snd_p++)
174 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
175 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
180 for (i = 0;i < snd_frames;i++, snd_p++)
182 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
183 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
187 else if (shm->format.channels == 1)
190 for (i = 0;i < snd_frames;i++, snd_p++)
191 *snd_out++ = bound(-32768, (snd_p->sample[0] + snd_p->sample[1]) >> 1, 32767);
197 unsigned char *snd_out = (unsigned char *) pbuf + i * shm->format.channels;
198 if (shm->format.channels == 8)
201 if (snd_swapstereo.value)
203 for (i = 0;i < snd_frames;i++, snd_p++)
205 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
206 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
207 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
208 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
209 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
210 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
211 val = (snd_p->sample[6] >> 8) + 128;*snd_out++ = bound(0, val, 255);
212 val = (snd_p->sample[7] >> 8) + 128;*snd_out++ = bound(0, val, 255);
217 for (i = 0;i < snd_frames;i++, snd_p++)
219 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
220 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
221 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
222 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
223 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
224 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
225 val = (snd_p->sample[6] >> 8) + 128;*snd_out++ = bound(0, val, 255);
226 val = (snd_p->sample[7] >> 8) + 128;*snd_out++ = bound(0, val, 255);
230 else if (shm->format.channels == 6)
233 if (snd_swapstereo.value)
235 for (i = 0;i < snd_frames;i++, snd_p++)
237 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
238 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
239 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
240 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
241 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
242 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
247 for (i = 0;i < snd_frames;i++, snd_p++)
249 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
250 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
251 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
252 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
253 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
254 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
258 else if (shm->format.channels == 4)
261 if (snd_swapstereo.value)
263 for (i = 0;i < snd_frames;i++, snd_p++)
265 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
266 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
267 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
268 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
273 for (i = 0;i < snd_frames;i++, snd_p++)
275 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
276 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
277 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
278 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
282 else if (shm->format.channels == 2)
285 if (snd_swapstereo.value)
287 for (i = 0;i < snd_frames;i++, snd_p++)
289 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
290 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
295 for (i = 0;i < snd_frames;i++, snd_p++)
297 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
298 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
302 else if (shm->format.channels == 1)
305 for (i = 0;i < snd_frames;i++, snd_p++)
307 val = ((snd_p->sample[0]+snd_p->sample[1]) >> 9) + 128;*snd_out++ = bound(0, val, 255);
318 ===============================================================================
322 ===============================================================================
325 qboolean SND_PaintChannel (channel_t *ch, int endtime);
327 void S_PaintChannels(int endtime)
335 while (paintedtime < endtime)
337 // if paintbuffer is smaller than DMA buffer
339 if (endtime - paintedtime > PAINTBUFFER_SIZE)
340 end = paintedtime + PAINTBUFFER_SIZE;
342 // clear the paint buffer
343 memset (&paintbuffer, 0, (end - paintedtime) * sizeof (paintbuffer[0]));
345 // paint in the channels.
347 for (i=0; i<total_channels ; i++, ch++)
354 for (j = 0;j < SND_LISTENERS;j++)
355 if (ch->listener_volume[j])
357 if (j == SND_LISTENERS)
359 if (!S_LoadSound (sfx, true))
362 // if the channel is paused
363 if (ch->flags & CHANNELFLAG_PAUSED)
365 int pausedtime = end - paintedtime;
366 ch->lastptime += pausedtime;
367 ch->end += pausedtime;
371 // if the sound hasn't been painted last time, update his position
372 if (ch->lastptime < paintedtime)
374 ch->pos += paintedtime - ch->lastptime;
376 // If the sound should have ended by then
377 if ((unsigned int)ch->pos > sfx->total_length)
381 if (ch->flags & CHANNELFLAG_FORCELOOP)
385 if (sfx->loopstart >= 0)
386 loopstart = sfx->loopstart;
388 // If the sound is looped
390 ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart;
392 ch->pos = sfx->total_length;
393 ch->end = paintedtime + sfx->total_length - ch->pos;
404 count = (int)ch->end - ltime;
410 for (j = 0;j < SND_LISTENERS;j++)
411 ch->listener_volume[j] = bound(0, ch->listener_volume[j], 255);
413 stop_paint = !SND_PaintChannel (ch, count);
418 ch->lastptime = ltime;
424 if (ltime >= ch->end)
426 // if at end of loop, restart
427 if ((sfx->loopstart >= 0 || (ch->flags & CHANNELFLAG_FORCELOOP)) && !stop_paint)
429 ch->pos = bound(0, sfx->loopstart, (int)sfx->total_length - 1);
430 ch->end = ltime + sfx->total_length - ch->pos;
432 // channel just stopped
439 S_StopChannel (ch - channels);
445 // transfer out according to DMA format
446 S_CaptureAVISound (paintbuffer, end - paintedtime);
447 S_TransferPaintBuffer(end);
453 qboolean SND_PaintChannel (channel_t *ch, int count)
455 int snd_vol, vol[SND_LISTENERS];
456 const sfxbuffer_t *sb;
459 // If this channel manages its own volume
460 if (ch->flags & CHANNELFLAG_FULLVOLUME)
463 snd_vol = volume.value * 256;
465 for (i = 0;i < SND_LISTENERS;i++)
466 vol[i] = ch->listener_volume[i] * snd_vol;
468 sb = ch->sfx->fetcher->getsb (ch, ch->pos, count);
472 #if SND_LISTENERS != 8
473 #error this code only supports up to 8 channels, update it
476 if (ch->sfx->format.width == 1)
478 const signed char *sfx = (signed char *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
479 // Stereo sound support
480 if (ch->sfx->format.channels == 2)
482 if (vol[6] + vol[7] > 0)
484 for (i = 0;i < count;i++)
486 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
487 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
488 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
489 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
490 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
491 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
492 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
493 paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 8;
497 else if (vol[4] + vol[5] > 0)
499 for (i = 0;i < count;i++)
501 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
502 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
503 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
504 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
505 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
506 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
510 else if (vol[2] + vol[3] > 0)
512 for (i = 0;i < count;i++)
514 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
515 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
516 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
517 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
521 else if (vol[0] + vol[1] > 0)
523 for (i = 0;i < count;i++)
525 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
526 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
531 else if (ch->sfx->format.channels == 1)
533 if (vol[6] + vol[7] > 0)
535 for (i = 0;i < count;i++)
537 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
538 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
539 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
540 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
541 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
542 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
543 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
544 paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 8;
548 else if (vol[4] + vol[5] > 0)
550 for (i = 0;i < count;i++)
552 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
553 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
554 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
555 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
556 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
557 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
561 else if (vol[2] + vol[3] > 0)
563 for (i = 0;i < count;i++)
565 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
566 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
567 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
568 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
572 else if (vol[0] + vol[1] > 0)
574 for (i = 0;i < count;i++)
576 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
577 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
583 return true; // unsupported number of channels in sound
585 else if (ch->sfx->format.width == 2)
587 const signed short *sfx = (signed short *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
588 // Stereo sound support
589 if (ch->sfx->format.channels == 2)
591 if (vol[6] + vol[7] > 0)
593 for (i = 0;i < count;i++)
595 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
596 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
597 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
598 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
599 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
600 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
601 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
602 paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 16;
606 else if (vol[4] + vol[5] > 0)
608 for (i = 0;i < count;i++)
610 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
611 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
612 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
613 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
614 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
615 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
619 else if (vol[2] + vol[3] > 0)
621 for (i = 0;i < count;i++)
623 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
624 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
625 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
626 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
630 else if (vol[0] + vol[1] > 0)
632 for (i = 0;i < count;i++)
634 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
635 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
640 else if (ch->sfx->format.channels == 1)
642 if (vol[6] + vol[7] > 0)
644 for (i = 0;i < count;i++)
646 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
647 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
648 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
649 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
650 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
651 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
652 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
653 paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 16;
657 else if (vol[4] + vol[5] > 0)
659 for (i = 0;i < count;i++)
661 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
662 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
663 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
664 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
665 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
666 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
670 else if (vol[2] + vol[3] > 0)
672 for (i = 0;i < count;i++)
674 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
675 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
676 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
677 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
681 else if (vol[0] + vol[1] > 0)
683 for (i = 0;i < count;i++)
685 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
686 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
692 return true; // unsupported number of channels in sound