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++)
352 for (j = 0;j < SND_LISTENERS;j++)
353 if (ch->listener_volume[j])
355 if (j == SND_LISTENERS)
357 if (!S_LoadSound (sfx, true))
360 // if the channel is paused
361 if (ch->flags & CHANNELFLAG_PAUSED)
363 int pausedtime = end - paintedtime;
364 ch->lastptime += pausedtime;
365 ch->end += pausedtime;
369 // if the sound hasn't been painted last time, update his position
370 if (ch->lastptime < paintedtime)
372 ch->pos += paintedtime - ch->lastptime;
374 // If the sound should have ended by then
375 if ((unsigned int)ch->pos > sfx->total_length)
379 if (ch->flags & CHANNELFLAG_FORCELOOP)
383 if (sfx->loopstart >= 0)
384 loopstart = sfx->loopstart;
386 // If the sound is looped
388 ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart;
390 ch->pos = sfx->total_length;
391 ch->end = paintedtime + sfx->total_length - ch->pos;
402 count = (int)ch->end - ltime;
408 for (j = 0;j < SND_LISTENERS;j++)
409 ch->listener_volume[j] = bound(0, ch->listener_volume[j], 255);
411 stop_paint = !SND_PaintChannel (ch, count);
416 ch->lastptime = ltime;
422 if (ltime >= ch->end)
424 // if at end of loop, restart
425 if ((sfx->loopstart >= 0 || (ch->flags & CHANNELFLAG_FORCELOOP)) && !stop_paint)
427 ch->pos = bound(0, sfx->loopstart, (int)sfx->total_length - 1);
428 ch->end = ltime + sfx->total_length - ch->pos;
430 // channel just stopped
437 S_StopChannel (ch - channels);
443 // transfer out according to DMA format
444 S_CaptureAVISound (paintbuffer, end - paintedtime);
445 S_TransferPaintBuffer(end);
451 qboolean SND_PaintChannel (channel_t *ch, int count)
453 int snd_vol, vol[SND_LISTENERS];
454 const sfxbuffer_t *sb;
457 // If this channel manages its own volume
458 if (ch->flags & CHANNELFLAG_FULLVOLUME)
461 snd_vol = volume.value * 256;
463 for (i = 0;i < SND_LISTENERS;i++)
464 vol[i] = ch->listener_volume[i] * snd_vol;
466 sb = ch->sfx->fetcher->getsb (ch, ch->pos, count);
470 #if SND_LISTENERS != 8
471 #error this code only supports up to 8 channels, update it
474 if (ch->sfx->format.width == 1)
476 const signed char *sfx = (signed char *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
477 // Stereo sound support
478 if (ch->sfx->format.channels == 2)
480 if (vol[6] + vol[7] > 0)
482 for (i = 0;i < count;i++)
484 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
485 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
486 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
487 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
488 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
489 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
490 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
491 paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 8;
495 else if (vol[4] + vol[5] > 0)
497 for (i = 0;i < count;i++)
499 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
500 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
501 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
502 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
503 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
504 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
508 else if (vol[2] + vol[3] > 0)
510 for (i = 0;i < count;i++)
512 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
513 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
514 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
515 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
519 else if (vol[0] + vol[1] > 0)
521 for (i = 0;i < count;i++)
523 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
524 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
529 else if (ch->sfx->format.channels == 1)
531 if (vol[6] + vol[7] > 0)
533 for (i = 0;i < count;i++)
535 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
536 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
537 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
538 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
539 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
540 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
541 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
542 paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 8;
546 else if (vol[4] + vol[5] > 0)
548 for (i = 0;i < count;i++)
550 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
551 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
552 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
553 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
554 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
555 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
559 else if (vol[2] + vol[3] > 0)
561 for (i = 0;i < count;i++)
563 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
564 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
565 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
566 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
570 else if (vol[0] + vol[1] > 0)
572 for (i = 0;i < count;i++)
574 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
575 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
581 return true; // unsupported number of channels in sound
583 else if (ch->sfx->format.width == 2)
585 const signed short *sfx = (signed short *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
586 // Stereo sound support
587 if (ch->sfx->format.channels == 2)
589 if (vol[6] + vol[7] > 0)
591 for (i = 0;i < count;i++)
593 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
594 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
595 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
596 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
597 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
598 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
599 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
600 paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 16;
604 else if (vol[4] + vol[5] > 0)
606 for (i = 0;i < count;i++)
608 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
609 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
610 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
611 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
612 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
613 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
617 else if (vol[2] + vol[3] > 0)
619 for (i = 0;i < count;i++)
621 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
622 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
623 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
624 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
628 else if (vol[0] + vol[1] > 0)
630 for (i = 0;i < count;i++)
632 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
633 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
638 else if (ch->sfx->format.channels == 1)
640 if (vol[6] + vol[7] > 0)
642 for (i = 0;i < count;i++)
644 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
645 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
646 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
647 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
648 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
649 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
650 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
651 paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 16;
655 else if (vol[4] + vol[5] > 0)
657 for (i = 0;i < count;i++)
659 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
660 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
661 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
662 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
663 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
664 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
668 else if (vol[2] + vol[3] > 0)
670 for (i = 0;i < count;i++)
672 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
673 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
674 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
675 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
679 else if (vol[0] + vol[1] > 0)
681 for (i = 0;i < count;i++)
683 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
684 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
690 return true; // unsupported number of channels in sound