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 static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
28 extern void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length);
29 static void S_CaptureAVISound(size_t length)
31 if (!cls.capturevideo.active)
34 SCR_CaptureVideo_SoundFrame(paintbuffer, length);
37 static void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
40 if (width == 2) // 16bit
42 short *snd_out = (short*)rb_ptr;
43 if (channels == 8) // 7.1 surround
45 for (i = 0;i < nbframes;i++, painted_ptr++)
47 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
48 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
49 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
50 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
51 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
52 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
53 *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
54 *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
57 else if (channels == 6) // 5.1 surround
59 for (i = 0; i < nbframes; i++, painted_ptr++)
61 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
62 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
63 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
64 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
65 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
66 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
69 else if (channels == 4) // 4.0 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);
79 else if (channels == 2) // 2.0 stereo
81 for (i = 0; i < nbframes; i++, painted_ptr++)
83 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
84 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
87 else if (channels == 1) // 1.0 mono
89 for (i = 0; i < nbframes; i++, painted_ptr++)
91 val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
92 *snd_out++ = bound(-32768, val, 32767);
98 unsigned char *snd_out = (unsigned char*)rb_ptr;
99 if (channels == 8) // 7.1 surround
101 for (i = 0; i < nbframes; i++, painted_ptr++)
103 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
104 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
105 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
106 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
107 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
108 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
109 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
110 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
113 else if (channels == 6) // 5.1 surround
115 for (i = 0; i < nbframes; i++, painted_ptr++)
117 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
118 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
119 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
120 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
121 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
122 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
125 else if (channels == 4) // 4.0 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);
135 else if (channels == 2) // 2.0 stereo
137 for (i = 0; i < nbframes; i++, painted_ptr++)
139 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
140 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
143 else if (channels == 1) // 1.0 mono
145 for (i = 0;i < nbframes;i++, painted_ptr++)
147 val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
148 *snd_out++ = bound(0, val, 255);
156 ===============================================================================
160 ===============================================================================
163 static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
165 int snd_vol, vol[SND_LISTENERS];
166 const snd_buffer_t *sb;
167 unsigned int i, sb_offset;
169 // If this channel manages its own volume
170 if (ch->flags & CHANNELFLAG_FULLVOLUME)
173 snd_vol = (int)(volume.value * 256);
175 // calculate mixing volumes based on channel volumes and volume cvar
176 // also limit the volumes to values that won't clip
177 for (i = 0;i < SND_LISTENERS;i++)
179 vol[i] = ch->listener_volume[i] * snd_vol;
180 vol[i] = bound(0, vol[i], 65536);
183 // if volumes are all zero, just return
184 for (i = 0;i < SND_LISTENERS;i++)
187 if (i == SND_LISTENERS)
191 sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
194 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
195 ch->sfx->name); // , count); // or add this? FIXME
200 #if SND_LISTENERS != 8
201 # error the following code only supports up to 8 channels, update it
203 if (sb->format.width == 1)
205 const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
207 // Stereo sound support
208 if (sb->format.channels == 2)
210 if (vol[6] + vol[7] > 0)
212 for (i = 0;i < count;i++)
214 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
215 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
216 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
217 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
218 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
219 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
220 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
221 paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
225 else if (vol[4] + vol[5] > 0)
227 for (i = 0;i < count;i++)
229 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
230 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
231 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
232 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
233 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
234 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
238 else if (vol[2] + vol[3] > 0)
240 for (i = 0;i < count;i++)
242 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
243 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
244 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
245 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
249 else if (vol[0] + vol[1] > 0)
251 for (i = 0;i < count;i++)
253 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
254 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
259 else if (sb->format.channels == 1)
261 if (vol[6] + vol[7] > 0)
263 for (i = 0;i < count;i++)
265 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
266 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
267 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
268 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
269 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
270 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
271 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
272 paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
276 else if (vol[4] + vol[5] > 0)
278 for (i = 0;i < count;i++)
280 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
281 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
282 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
283 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
284 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
285 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
289 else if (vol[2] + vol[3] > 0)
291 for (i = 0;i < count;i++)
293 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
294 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
295 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
296 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
300 else if (vol[0] + vol[1] > 0)
302 for (i = 0;i < count;i++)
304 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
305 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
311 return false; // unsupported number of channels in sound
313 else if (sb->format.width == 2)
315 const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
317 // Stereo sound support
318 if (sb->format.channels == 2)
320 if (vol[6] + vol[7] > 0)
322 for (i = 0;i < count;i++)
324 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
325 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
326 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
327 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
328 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
329 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
330 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
331 paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
335 else if (vol[4] + vol[5] > 0)
337 for (i = 0;i < count;i++)
339 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
340 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
341 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
342 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
343 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
344 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
348 else if (vol[2] + vol[3] > 0)
350 for (i = 0;i < count;i++)
352 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
353 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
354 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
355 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
359 else if (vol[0] + vol[1] > 0)
361 for (i = 0;i < count;i++)
363 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
364 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
369 else if (sb->format.channels == 1)
371 if (vol[6] + vol[7] > 0)
373 for (i = 0;i < count;i++)
375 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
376 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
377 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
378 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
379 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
380 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
381 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
382 paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
386 else if (vol[4] + vol[5] > 0)
388 for (i = 0;i < count;i++)
390 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
391 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
392 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
393 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
394 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
395 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
399 else if (vol[2] + vol[3] > 0)
401 for (i = 0;i < count;i++)
403 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
404 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
405 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
406 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
410 else if (vol[0] + vol[1] > 0)
412 for (i = 0;i < count;i++)
414 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
415 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
421 return false; // unsupported number of channels in sound
427 void S_MixToBuffer(void *stream, unsigned int bufferframes)
432 unsigned char *outbytes = (unsigned char *) stream;
434 // mix as many times as needed to fill the requested buffer
437 // limit to the size of the paint buffer
438 frames = min(bufferframes, PAINTBUFFER_SIZE);
440 // clear the paint buffer
441 memset (paintbuffer, 0, frames * sizeof (paintbuffer[0]));
443 // paint in the channels.
444 // channels with zero volumes still advance in time but don't paint.
446 for (i = 0; i < total_channels ; i++, ch++)
455 if (!S_LoadSound (sfx, true))
457 if (ch->flags & CHANNELFLAG_PAUSED)
464 count = min(count, frames - ltime);
469 while (ltime < frames)
471 // paint up to end of buffer or of input, whichever is lower
472 count = sfx->total_length - ch->pos;
473 count = bound(0, count, frames - ltime);
476 SND_PaintChannel (ch, paintbuffer + ltime, count);
481 // if at end of sfx, loop or stop the channel
482 if (ch->pos >= (int)sfx->total_length)
484 if (sfx->loopstart < sfx->total_length)
485 ch->pos = sfx->loopstart;
486 else if (ch->flags & CHANNELFLAG_FORCELOOP)
490 S_StopChannel (ch - channels, false);
497 if (!snd_usethreadedmixing)
498 S_CaptureAVISound(frames);
500 S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
502 // advance the output pointer
503 outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
504 bufferframes -= frames;