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 void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate);
36 void S_CaptureAVISound(portable_sampleframe_t *buf, size_t length)
40 unsigned char out[PAINTBUFFER_SIZE * 4];
41 if (!cls.capturevideo_active)
43 // write the sound buffer as little endian 16bit interleaved stereo
44 for(i = 0;i < length;i++)
47 n = bound(-32768, n, 32767);
48 out[i*4+0] = n & 0xFF;
49 out[i*4+1] = (n >> 8) & 0xFF;
51 n = bound(-32768, n, 32767);
52 out[i*4+2] = n & 0xFF;
53 out[i*4+3] = (n >> 8) & 0xFF;
55 SCR_CaptureVideo_SoundFrame(out, length, shm->format.speed);
58 // TODO: rewrite this function
59 void S_TransferPaintBuffer(int endtime)
63 portable_sampleframe_t *snd_p;
67 if ((pbuf = S_LockBuffer()))
70 lpaintedtime = paintedtime;
71 for (lpaintedtime = paintedtime;lpaintedtime < endtime;lpaintedtime += snd_frames)
73 // handle recirculating buffer issues
74 i = lpaintedtime & (shm->sampleframes - 1);
75 snd_frames = shm->sampleframes - i;
76 if (snd_frames > endtime - lpaintedtime)
77 snd_frames = endtime - lpaintedtime;
78 if (shm->format.width == 2)
81 short *snd_out = (short *) pbuf + i * shm->format.channels;
82 if (shm->format.channels == 8)
85 if (snd_swapstereo.value)
87 for (i = 0;i < snd_frames;i++, snd_p++)
89 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
90 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
91 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
92 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
93 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
94 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
95 *snd_out++ = bound(-32768, snd_p->sample[6], 32767);
96 *snd_out++ = bound(-32768, snd_p->sample[7], 32767);
101 for (i = 0;i < snd_frames;i++, snd_p++)
103 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
104 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
105 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
106 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
107 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
108 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
109 *snd_out++ = bound(-32768, snd_p->sample[6], 32767);
110 *snd_out++ = bound(-32768, snd_p->sample[7], 32767);
114 else if (shm->format.channels == 6)
117 if (snd_swapstereo.value)
119 for (i = 0;i < snd_frames;i++, snd_p++)
121 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
122 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
123 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
124 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
125 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
126 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
131 for (i = 0;i < snd_frames;i++, snd_p++)
133 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
134 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
135 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
136 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
137 *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
138 *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
142 else if (shm->format.channels == 4)
145 if (snd_swapstereo.value)
147 for (i = 0;i < snd_frames;i++, snd_p++)
149 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
150 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
151 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
152 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
157 for (i = 0;i < snd_frames;i++, snd_p++)
159 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
160 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
161 *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
162 *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
166 else if (shm->format.channels == 2)
169 if (snd_swapstereo.value)
171 for (i = 0;i < snd_frames;i++, snd_p++)
173 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
174 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
179 for (i = 0;i < snd_frames;i++, snd_p++)
181 *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
182 *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
186 else if (shm->format.channels == 1)
189 for (i = 0;i < snd_frames;i++, snd_p++)
190 *snd_out++ = bound(-32768, (snd_p->sample[0] + snd_p->sample[1]) >> 1, 32767);
196 unsigned char *snd_out = (unsigned char *) pbuf + i * shm->format.channels;
197 if (shm->format.channels == 8)
200 if (snd_swapstereo.value)
202 for (i = 0;i < snd_frames;i++, snd_p++)
204 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
205 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
206 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
207 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
208 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
209 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
210 val = (snd_p->sample[6] >> 8) + 128;*snd_out++ = bound(0, val, 255);
211 val = (snd_p->sample[7] >> 8) + 128;*snd_out++ = bound(0, val, 255);
216 for (i = 0;i < snd_frames;i++, snd_p++)
218 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
219 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
220 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
221 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
222 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
223 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
224 val = (snd_p->sample[6] >> 8) + 128;*snd_out++ = bound(0, val, 255);
225 val = (snd_p->sample[7] >> 8) + 128;*snd_out++ = bound(0, val, 255);
229 else if (shm->format.channels == 6)
232 if (snd_swapstereo.value)
234 for (i = 0;i < snd_frames;i++, snd_p++)
236 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
237 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
238 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
239 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
240 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
241 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
246 for (i = 0;i < snd_frames;i++, snd_p++)
248 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
249 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
250 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
251 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
252 val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
253 val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
257 else if (shm->format.channels == 4)
260 if (snd_swapstereo.value)
262 for (i = 0;i < snd_frames;i++, snd_p++)
264 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
265 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
266 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
267 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
272 for (i = 0;i < snd_frames;i++, snd_p++)
274 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
275 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
276 val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
277 val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
281 else if (shm->format.channels == 2)
284 if (snd_swapstereo.value)
286 for (i = 0;i < snd_frames;i++, snd_p++)
288 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
289 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
294 for (i = 0;i < snd_frames;i++, snd_p++)
296 val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
297 val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
301 else if (shm->format.channels == 1)
304 for (i = 0;i < snd_frames;i++, snd_p++)
306 val = ((snd_p->sample[0]+snd_p->sample[1]) >> 9) + 128;*snd_out++ = bound(0, val, 255);
317 ===============================================================================
321 ===============================================================================
324 qboolean SND_PaintChannel (channel_t *ch, int endtime);
326 void S_PaintChannels(int endtime)
334 while (paintedtime < endtime)
336 // if paintbuffer is smaller than DMA buffer
338 if (endtime - paintedtime > PAINTBUFFER_SIZE)
339 end = paintedtime + PAINTBUFFER_SIZE;
341 // clear the paint buffer
342 memset (&paintbuffer, 0, (end - paintedtime) * sizeof (paintbuffer[0]));
344 // paint in the channels.
346 for (i=0; i<total_channels ; i++, ch++)
351 for (j = 0;j < SND_LISTENERS;j++)
352 if (ch->listener_volume[j])
354 if (j == SND_LISTENERS)
356 if (!S_LoadSound (sfx, true))
359 // if the channel is paused
360 if (ch->flags & CHANNELFLAG_PAUSED)
362 int pausedtime = end - paintedtime;
363 ch->lastptime += pausedtime;
364 ch->end += pausedtime;
368 // if the sound hasn't been painted last time, update his position
369 if (ch->lastptime < paintedtime)
371 ch->pos += paintedtime - ch->lastptime;
373 // If the sound should have ended by then
374 if ((unsigned int)ch->pos > sfx->total_length)
378 if (ch->flags & CHANNELFLAG_FORCELOOP)
382 if (sfx->loopstart >= 0)
383 loopstart = sfx->loopstart;
385 // If the sound is looped
387 ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart;
389 ch->pos = sfx->total_length;
390 ch->end = paintedtime + sfx->total_length - ch->pos;
401 count = (int)ch->end - ltime;
407 for (j = 0;j < SND_LISTENERS;j++)
408 ch->listener_volume[j] = bound(0, ch->listener_volume[j], 255);
410 stop_paint = !SND_PaintChannel (ch, count);
415 ch->lastptime = ltime;
421 if (ltime >= ch->end)
423 // if at end of loop, restart
424 if ((sfx->loopstart >= 0 || (ch->flags & CHANNELFLAG_FORCELOOP)) && !stop_paint)
426 ch->pos = bound(0, sfx->loopstart, (int)sfx->total_length - 1);
427 ch->end = ltime + sfx->total_length - ch->pos;
429 // channel just stopped
436 S_StopChannel (ch - channels);
442 // transfer out according to DMA format
443 S_CaptureAVISound (paintbuffer, end - paintedtime);
444 S_TransferPaintBuffer(end);
450 qboolean SND_PaintChannel (channel_t *ch, int count)
452 int snd_vol, vol[SND_LISTENERS];
453 const sfxbuffer_t *sb;
456 // If this channel manages its own volume
457 if (ch->flags & CHANNELFLAG_FULLVOLUME)
460 snd_vol = (int)(volume.value * 256);
462 for (i = 0;i < SND_LISTENERS;i++)
463 vol[i] = ch->listener_volume[i] * snd_vol;
465 sb = ch->sfx->fetcher->getsb (ch, ch->pos, count);
469 #if SND_LISTENERS != 8
470 #error this code only supports up to 8 channels, update it
473 if (ch->sfx->format.width == 1)
475 const signed char *sfx = (signed char *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
476 // Stereo sound support
477 if (ch->sfx->format.channels == 2)
479 if (vol[6] + vol[7] > 0)
481 for (i = 0;i < count;i++)
483 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
484 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
485 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
486 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
487 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
488 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
489 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
490 paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 8;
494 else if (vol[4] + vol[5] > 0)
496 for (i = 0;i < count;i++)
498 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
499 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
500 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
501 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
502 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
503 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
507 else if (vol[2] + vol[3] > 0)
509 for (i = 0;i < count;i++)
511 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
512 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
513 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
514 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
518 else if (vol[0] + vol[1] > 0)
520 for (i = 0;i < count;i++)
522 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
523 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
528 else if (ch->sfx->format.channels == 1)
530 if (vol[6] + vol[7] > 0)
532 for (i = 0;i < count;i++)
534 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
535 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
536 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
537 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
538 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
539 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
540 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
541 paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 8;
545 else if (vol[4] + vol[5] > 0)
547 for (i = 0;i < count;i++)
549 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
550 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
551 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
552 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
553 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
554 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
558 else if (vol[2] + vol[3] > 0)
560 for (i = 0;i < count;i++)
562 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
563 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
564 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
565 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
569 else if (vol[0] + vol[1] > 0)
571 for (i = 0;i < count;i++)
573 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
574 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
580 return true; // unsupported number of channels in sound
582 else if (ch->sfx->format.width == 2)
584 const signed short *sfx = (signed short *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
585 // Stereo sound support
586 if (ch->sfx->format.channels == 2)
588 if (vol[6] + vol[7] > 0)
590 for (i = 0;i < count;i++)
592 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
593 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
594 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
595 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
596 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
597 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
598 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
599 paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 16;
603 else if (vol[4] + vol[5] > 0)
605 for (i = 0;i < count;i++)
607 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
608 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
609 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
610 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
611 paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
612 paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
616 else if (vol[2] + vol[3] > 0)
618 for (i = 0;i < count;i++)
620 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
621 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
622 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
623 paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
627 else if (vol[0] + vol[1] > 0)
629 for (i = 0;i < count;i++)
631 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
632 paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
637 else if (ch->sfx->format.channels == 1)
639 if (vol[6] + vol[7] > 0)
641 for (i = 0;i < count;i++)
643 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
644 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
645 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
646 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
647 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
648 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
649 paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
650 paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 16;
654 else if (vol[4] + vol[5] > 0)
656 for (i = 0;i < count;i++)
658 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
659 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
660 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
661 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
662 paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
663 paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
667 else if (vol[2] + vol[3] > 0)
669 for (i = 0;i < count;i++)
671 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
672 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
673 paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
674 paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
678 else if (vol[0] + vol[1] > 0)
680 for (i = 0;i < count;i++)
682 paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
683 paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
689 return true; // unsupported number of channels in sound