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 static 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 void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
66 if (width == 2) // 16bit
68 short *snd_out = (short*)rb_ptr;
69 if (channels == 8) // 7.1 surround
71 for (i = 0;i < nbframes;i++, painted_ptr++)
73 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
74 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
75 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
76 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
77 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
78 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
79 *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
80 *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
83 else if (channels == 6) // 5.1 surround
85 for (i = 0; i < nbframes; i++, painted_ptr++)
87 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
88 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
89 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
90 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
91 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
92 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
95 else if (channels == 4) // 4.0 surround
97 for (i = 0; i < nbframes; i++, painted_ptr++)
99 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
100 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
101 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
102 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
105 else if (channels == 2) // 2.0 stereo
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);
113 else if (channels == 1) // 1.0 mono
115 for (i = 0; i < nbframes; i++, painted_ptr++)
117 val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
118 *snd_out++ = bound(-32768, val, 32767);
124 unsigned char *snd_out = (unsigned char*)rb_ptr;
125 if (channels == 8) // 7.1 surround
127 for (i = 0; i < nbframes; i++, painted_ptr++)
129 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
130 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
131 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
132 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
133 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
134 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
135 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
136 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
139 else if (channels == 6) // 5.1 surround
141 for (i = 0; i < nbframes; i++, painted_ptr++)
143 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
144 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
145 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
146 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
147 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
148 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
151 else if (channels == 4) // 4.0 surround
153 for (i = 0; i < nbframes; i++, painted_ptr++)
155 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
156 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
157 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
158 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
161 else if (channels == 2) // 2.0 stereo
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);
169 else if (channels == 1) // 1.0 mono
171 for (i = 0;i < nbframes;i++, painted_ptr++)
173 val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
174 *snd_out++ = bound(0, val, 255);
182 ===============================================================================
186 ===============================================================================
189 static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
191 int snd_vol, vol[SND_LISTENERS];
192 const snd_buffer_t *sb;
193 unsigned int i, sb_offset;
195 // If this channel manages its own volume
196 if (ch->flags & CHANNELFLAG_FULLVOLUME)
199 snd_vol = (int)(volume.value * 256);
201 // calculate mixing volumes based on channel volumes and volume cvar
202 // also limit the volumes to values that won't clip
203 for (i = 0;i < SND_LISTENERS;i++)
205 vol[i] = ch->listener_volume[i] * snd_vol;
206 vol[i] = bound(0, vol[i], 65536);
209 // if volumes are all zero, just return
210 for (i = 0;i < SND_LISTENERS;i++)
213 if (i == SND_LISTENERS)
217 sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
220 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
221 ch->sfx->name); // , count); // or add this? FIXME
226 #if SND_LISTENERS != 8
227 # error the following code only supports up to 8 channels, update it
229 if (sb->format.width == 1)
231 const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
233 // Stereo sound support
234 if (sb->format.channels == 2)
236 if (vol[6] + vol[7] > 0)
238 for (i = 0;i < count;i++)
240 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
241 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
242 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
243 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
244 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
245 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
246 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
247 paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
251 else if (vol[4] + vol[5] > 0)
253 for (i = 0;i < count;i++)
255 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
256 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
257 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
258 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
259 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
260 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
264 else if (vol[2] + vol[3] > 0)
266 for (i = 0;i < count;i++)
268 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
269 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
270 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
271 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
275 else if (vol[0] + vol[1] > 0)
277 for (i = 0;i < count;i++)
279 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
280 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
285 else if (sb->format.channels == 1)
287 if (vol[6] + vol[7] > 0)
289 for (i = 0;i < count;i++)
291 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
292 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
293 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
294 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
295 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
296 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
297 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
298 paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
302 else if (vol[4] + vol[5] > 0)
304 for (i = 0;i < count;i++)
306 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
307 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
308 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
309 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
310 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
311 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
315 else if (vol[2] + vol[3] > 0)
317 for (i = 0;i < count;i++)
319 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
320 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
321 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
322 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
326 else if (vol[0] + vol[1] > 0)
328 for (i = 0;i < count;i++)
330 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
331 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
337 return false; // unsupported number of channels in sound
339 else if (sb->format.width == 2)
341 const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
343 // Stereo sound support
344 if (sb->format.channels == 2)
346 if (vol[6] + vol[7] > 0)
348 for (i = 0;i < count;i++)
350 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
351 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
352 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
353 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
354 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
355 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
356 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
357 paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
361 else if (vol[4] + vol[5] > 0)
363 for (i = 0;i < count;i++)
365 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
366 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
367 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
368 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
369 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
370 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
374 else if (vol[2] + vol[3] > 0)
376 for (i = 0;i < count;i++)
378 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
379 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
380 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
381 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
385 else if (vol[0] + vol[1] > 0)
387 for (i = 0;i < count;i++)
389 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
390 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
395 else if (sb->format.channels == 1)
397 if (vol[6] + vol[7] > 0)
399 for (i = 0;i < count;i++)
401 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
402 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
403 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
404 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
405 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
406 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
407 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
408 paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
412 else if (vol[4] + vol[5] > 0)
414 for (i = 0;i < count;i++)
416 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
417 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
418 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
419 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
420 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
421 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
425 else if (vol[2] + vol[3] > 0)
427 for (i = 0;i < count;i++)
429 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
430 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
431 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
432 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
436 else if (vol[0] + vol[1] > 0)
438 for (i = 0;i < count;i++)
440 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
441 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
447 return false; // unsupported number of channels in sound
453 void S_MixToBuffer(void *stream, unsigned int bufferframes)
458 unsigned char *outbytes = stream;
460 // mix as many times as needed to fill the requested buffer
463 // limit to the size of the paint buffer
464 frames = min(bufferframes, PAINTBUFFER_SIZE);
466 // clear the paint buffer
467 memset (paintbuffer, 0, frames * sizeof (paintbuffer[0]));
469 // paint in the channels.
470 // channels with zero volumes still advance in time but don't paint.
472 for (i = 0; i < total_channels ; i++, ch++)
481 if (!S_LoadSound (sfx, true))
483 if (ch->flags & CHANNELFLAG_PAUSED)
490 count = min(count, frames - ltime);
495 while (ltime < frames)
497 // paint up to end of buffer or of input, whichever is lower
498 count = sfx->total_length - ch->pos;
499 count = bound(0, count, frames - ltime);
502 SND_PaintChannel (ch, paintbuffer + ltime, count);
507 // if at end of sfx, loop or stop the channel
508 if (ch->pos >= (int)sfx->total_length)
510 if (sfx->loopstart < sfx->total_length)
511 ch->pos = sfx->loopstart;
512 else if (ch->flags & CHANNELFLAG_FORCELOOP)
516 S_StopChannel (ch - channels, false);
523 if (!snd_usethreadedmixing)
524 S_CaptureAVISound(frames);
526 S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
528 // advance the output pointer
529 outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
530 bufferframes -= frames;