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 extern void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate);
36 static void S_CaptureAVISound(size_t length)
39 unsigned char out[PAINTBUFFER_SIZE * 4];
40 unsigned char* out_ptr;
42 if (!cls.capturevideo.active)
45 // write the sound buffer as little endian 16bit interleaved stereo
46 for(i = 0, out_ptr = out; i < length; i++, out_ptr += 4)
50 n0 = paintbuffer[i].sample[0];
51 n0 = bound(-32768, n0, 32767);
52 out_ptr[0] = (unsigned char)n0;
53 out_ptr[1] = (unsigned char)(n0 >> 8);
55 n1 = paintbuffer[i].sample[1];
56 n1 = bound(-32768, n1, 32767);
57 out_ptr[2] = (unsigned char)n1;
58 out_ptr[3] = (unsigned char)(n1 >> 8);
60 SCR_CaptureVideo_SoundFrame(out, length, snd_renderbuffer->format.speed);
63 static unsigned int S_TransferPaintBuffer(snd_ringbuffer_t* rb, unsigned int starttime, unsigned int endtime)
65 unsigned int partialend;
68 if (!simsound && !SndSys_LockRenderBuffer())
71 partialend = starttime;
72 while (partialend < endtime) // handle recirculating buffer issues
74 unsigned int startoffset, maxframes, nbframes, i;
76 portable_sampleframe_t *painted_ptr;
79 startoffset = partialend % rb->maxframes;
80 maxframes = rb->maxframes - startoffset;
81 nbframes = endtime - partialend;
82 if (nbframes > maxframes)
85 rb_ptr = &rb->ring[startoffset * rb->format.width * rb->format.channels];
86 painted_ptr = &paintbuffer[partialend - starttime];
88 if (rb->format.width == 2) // 16bit
90 short *snd_out = (short*)rb_ptr;
91 if (rb->format.channels == 8) // 7.1 surround
93 for (i = 0;i < nbframes;i++, painted_ptr++)
95 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
96 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
97 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
98 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
99 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
100 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
101 *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
102 *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
105 else if (rb->format.channels == 6) // 5.1 surround
107 for (i = 0; i < nbframes; i++, painted_ptr++)
109 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
110 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
111 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
112 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
113 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
114 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
117 else if (rb->format.channels == 4) // 4.0 surround
119 for (i = 0; i < nbframes; i++, painted_ptr++)
121 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
122 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
123 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
124 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
127 else if (rb->format.channels == 2) // 2.0 stereo
129 for (i = 0; i < nbframes; i++, painted_ptr++)
131 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
132 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
135 else if (rb->format.channels == 1) // 1.0 mono
137 for (i = 0; i < nbframes; i++, painted_ptr++)
139 val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
140 *snd_out++ = bound(-32768, val, 32767);
146 unsigned char *snd_out = (unsigned char*)rb_ptr;
147 if (rb->format.channels == 8) // 7.1 surround
149 for (i = 0; i < nbframes; i++, painted_ptr++)
151 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
152 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
153 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
154 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
155 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
156 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
157 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
158 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
161 else if (rb->format.channels == 6) // 5.1 surround
163 for (i = 0; i < nbframes; i++, painted_ptr++)
165 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
166 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
167 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
168 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
169 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
170 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
173 else if (rb->format.channels == 4) // 4.0 surround
175 for (i = 0; i < nbframes; i++, painted_ptr++)
177 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
178 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
179 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
180 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
183 else if (rb->format.channels == 2) // 2.0 stereo
185 for (i = 0; i < nbframes; i++, painted_ptr++)
187 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
188 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
191 else if (rb->format.channels == 1) // 1.0 mono
193 for (i = 0;i < nbframes;i++, painted_ptr++)
195 val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
196 *snd_out++ = bound(0, val, 255);
201 partialend += nbframes;
204 rb->endframe = endtime;
206 // Remove outdated samples from the ring buffer, if any
207 if (rb->startframe < soundtime)
208 rb->startframe = soundtime;
211 SndSys_UnlockRenderBuffer();
213 return endtime - starttime;
218 ===============================================================================
222 ===============================================================================
225 static qboolean SND_PaintChannel (channel_t *ch, unsigned int count)
227 int snd_vol, vol[SND_LISTENERS];
228 const snd_buffer_t *sb;
229 unsigned int i, sb_offset;
231 // If this channel manages its own volume
232 if (ch->flags & CHANNELFLAG_FULLVOLUME)
235 snd_vol = (int)(volume.value * 256);
237 // calculate mixing volumes based on channel volumes and volume cvar
238 // also limit the volumes to values that won't clip
239 for (i = 0;i < SND_LISTENERS;i++)
241 vol[i] = ch->listener_volume[i] * snd_vol;
242 vol[i] = bound(0, vol[i], 65536);
245 // if volumes are all zero, just return
246 for (i = 0;i < SND_LISTENERS;i++)
249 if (i == SND_LISTENERS)
253 sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
256 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
257 ch->sfx->name); // , count); // or add this? FIXME
262 #if SND_LISTENERS != 8
263 # error the following code only supports up to 8 channels, update it
265 if (sb->format.width == 1)
267 const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
269 // Stereo sound support
270 if (sb->format.channels == 2)
272 if (vol[6] + vol[7] > 0)
274 for (i = 0;i < count;i++)
276 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
277 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
278 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
279 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
280 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
281 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
282 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 8;
283 paintbuffer[i].sample[7] += (samples[1] * vol[7]) >> 8;
287 else if (vol[4] + vol[5] > 0)
289 for (i = 0;i < count;i++)
291 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
292 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
293 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
294 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
295 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
296 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
300 else if (vol[2] + vol[3] > 0)
302 for (i = 0;i < count;i++)
304 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
305 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
306 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
307 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 8;
311 else if (vol[0] + vol[1] > 0)
313 for (i = 0;i < count;i++)
315 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
316 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 8;
321 else if (sb->format.channels == 1)
323 if (vol[6] + vol[7] > 0)
325 for (i = 0;i < count;i++)
327 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
328 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
329 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
330 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
331 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 8;
332 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 8;
333 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 8;
334 paintbuffer[i].sample[7] += (samples[0] * vol[7]) >> 8;
338 else if (vol[4] + vol[5] > 0)
340 for (i = 0;i < count;i++)
342 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
343 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
344 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
345 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
346 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 8;
347 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 8;
351 else if (vol[2] + vol[3] > 0)
353 for (i = 0;i < count;i++)
355 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
356 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
357 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 8;
358 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 8;
362 else if (vol[0] + vol[1] > 0)
364 for (i = 0;i < count;i++)
366 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 8;
367 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 8;
373 return false; // unsupported number of channels in sound
375 else if (sb->format.width == 2)
377 const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
379 // Stereo sound support
380 if (sb->format.channels == 2)
382 if (vol[6] + vol[7] > 0)
384 for (i = 0;i < count;i++)
386 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
387 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
388 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
389 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
390 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
391 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
392 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 16;
393 paintbuffer[i].sample[7] += (samples[1] * vol[7]) >> 16;
397 else if (vol[4] + vol[5] > 0)
399 for (i = 0;i < count;i++)
401 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
402 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
403 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
404 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
405 paintbuffer[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
406 paintbuffer[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
410 else if (vol[2] + vol[3] > 0)
412 for (i = 0;i < count;i++)
414 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
415 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
416 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
417 paintbuffer[i].sample[3] += (samples[1] * vol[3]) >> 16;
421 else if (vol[0] + vol[1] > 0)
423 for (i = 0;i < count;i++)
425 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
426 paintbuffer[i].sample[1] += (samples[1] * vol[1]) >> 16;
431 else if (sb->format.channels == 1)
433 if (vol[6] + vol[7] > 0)
435 for (i = 0;i < count;i++)
437 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
438 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
439 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
440 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
441 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 16;
442 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 16;
443 paintbuffer[i].sample[6] += (samples[0] * vol[6]) >> 16;
444 paintbuffer[i].sample[7] += (samples[0] * vol[7]) >> 16;
448 else if (vol[4] + vol[5] > 0)
450 for (i = 0;i < count;i++)
452 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
453 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
454 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
455 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
456 paintbuffer[i].sample[4] += (samples[0] * vol[4]) >> 16;
457 paintbuffer[i].sample[5] += (samples[0] * vol[5]) >> 16;
461 else if (vol[2] + vol[3] > 0)
463 for (i = 0;i < count;i++)
465 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
466 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
467 paintbuffer[i].sample[2] += (samples[0] * vol[2]) >> 16;
468 paintbuffer[i].sample[3] += (samples[0] * vol[3]) >> 16;
472 else if (vol[0] + vol[1] > 0)
474 for (i = 0;i < count;i++)
476 paintbuffer[i].sample[0] += (samples[0] * vol[0]) >> 16;
477 paintbuffer[i].sample[1] += (samples[0] * vol[1]) >> 16;
483 return false; // unsupported number of channels in sound
489 void S_PaintChannels (snd_ringbuffer_t* rb, unsigned int starttime, unsigned int endtime)
491 unsigned int paintedtime;
493 paintedtime = starttime;
494 while (paintedtime < endtime)
496 unsigned int partialend, i, framecount;
499 // if paintbuffer is too small
500 if (endtime > paintedtime + PAINTBUFFER_SIZE)
501 partialend = paintedtime + PAINTBUFFER_SIZE;
503 partialend = endtime;
505 // clear the paint buffer
506 memset (paintbuffer, 0, (partialend - paintedtime) * sizeof (paintbuffer[0]));
508 // paint in the channels.
509 // channels with zero volumes still advance in time but don't paint.
511 for (i = 0; i < total_channels ; i++, ch++)
520 if (!S_LoadSound (sfx, true))
522 if (ch->flags & CHANNELFLAG_PAUSED)
529 count = min(count, partialend - ltime);
534 while (ltime < partialend)
536 // paint up to end of buffer or of input, whichever is lower
537 count = sfx->total_length - ch->pos;
538 count = bound(0, count, partialend - ltime);
541 SND_PaintChannel (ch, count);
546 // if at end of sfx, loop or stop the channel
547 if (ch->pos >= (int)sfx->total_length)
549 if (sfx->loopstart < sfx->total_length)
550 ch->pos = sfx->loopstart;
551 else if (ch->flags & CHANNELFLAG_FORCELOOP)
555 S_StopChannel (ch - channels);
562 S_CaptureAVISound (partialend - paintedtime);
563 framecount = S_TransferPaintBuffer (rb, paintedtime, partialend);
564 paintedtime += framecount;
566 // If there was not enough free space in the sound buffer, stop here
567 if (paintedtime != partialend)
569 Con_DPrintf(">> S_PaintChannels: Not enough free space in the sound buffer ( %u != %u)\n", paintedtime, partialend);