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];
26 static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
28 extern speakerlayout_t snd_speakerlayout; // for querying the listeners
30 extern void SCR_CaptureVideo_SoundFrame(const portable_sampleframe_t *paintbuffer, size_t length);
31 static void S_CaptureAVISound(size_t length)
36 if (!cls.capturevideo.active)
39 // undo whatever swapping the channel layout (swapstereo, ALSA) did
40 for(j = 0; j < snd_speakerlayout.channels; ++j)
42 unsigned int j0 = snd_speakerlayout.listeners[j].channel_unswapped;
43 for(i = 0; i < length; ++i)
44 paintbuffer_unswapped[i].sample[j0] = paintbuffer[i].sample[j];
47 SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
50 static void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
53 if (width == 2) // 16bit
55 short *snd_out = (short*)rb_ptr;
56 if (channels == 8) // 7.1 surround
58 for (i = 0;i < nbframes;i++, painted_ptr++)
60 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
61 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
62 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
63 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
64 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
65 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
66 *snd_out++ = bound(-32768, painted_ptr->sample[6], 32767);
67 *snd_out++ = bound(-32768, painted_ptr->sample[7], 32767);
70 else if (channels == 6) // 5.1 surround
72 for (i = 0; i < nbframes; i++, painted_ptr++)
74 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
75 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
76 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
77 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
78 *snd_out++ = bound(-32768, painted_ptr->sample[4], 32767);
79 *snd_out++ = bound(-32768, painted_ptr->sample[5], 32767);
82 else if (channels == 4) // 4.0 surround
84 for (i = 0; i < nbframes; i++, painted_ptr++)
86 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
87 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
88 *snd_out++ = bound(-32768, painted_ptr->sample[2], 32767);
89 *snd_out++ = bound(-32768, painted_ptr->sample[3], 32767);
92 else if (channels == 2) // 2.0 stereo
94 for (i = 0; i < nbframes; i++, painted_ptr++)
96 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
97 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
100 else if (channels == 1) // 1.0 mono
102 for (i = 0; i < nbframes; i++, painted_ptr++)
104 val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
105 *snd_out++ = bound(-32768, val, 32767);
109 // noise is really really annoying
111 memset(rb_ptr, 0, nbframes * channels * width);
115 unsigned char *snd_out = (unsigned char*)rb_ptr;
116 if (channels == 8) // 7.1 surround
118 for (i = 0; i < nbframes; i++, painted_ptr++)
120 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
121 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
122 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
123 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
124 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
125 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
126 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
127 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
130 else if (channels == 6) // 5.1 surround
132 for (i = 0; i < nbframes; i++, painted_ptr++)
134 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
135 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
136 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
137 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
138 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
139 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
142 else if (channels == 4) // 4.0 surround
144 for (i = 0; i < nbframes; i++, painted_ptr++)
146 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
147 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
148 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
149 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
152 else if (channels == 2) // 2.0 stereo
154 for (i = 0; i < nbframes; i++, painted_ptr++)
156 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
157 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
160 else if (channels == 1) // 1.0 mono
162 for (i = 0;i < nbframes;i++, painted_ptr++)
164 val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
165 *snd_out++ = bound(0, val, 255);
169 // noise is really really annoying
171 memset(rb_ptr, 128, nbframes * channels);
177 ===============================================================================
181 ===============================================================================
184 static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
186 int snd_vol, vol[SND_LISTENERS];
187 const snd_buffer_t *sb;
188 unsigned int i, sb_offset;
190 // If this channel manages its own volume
191 if (ch->flags & CHANNELFLAG_FULLVOLUME)
192 snd_vol = (int)(mastervolume.value * 256);
194 snd_vol = (int)(mastervolume.value * volume.value * 256);
196 // calculate mixing volumes based on channel volumes and volume cvar
197 // also limit the volumes to values that won't clip
198 for (i = 0;i < SND_LISTENERS;i++)
200 vol[i] = ch->listener_volume[i] * snd_vol;
201 vol[i] = bound(0, vol[i], 65536);
204 // if volumes are all zero, just return
205 for (i = 0;i < SND_LISTENERS;i++)
208 if (i == SND_LISTENERS)
212 sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
215 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
216 ch->sfx->name); // , count); // or add this? FIXME
221 #if SND_LISTENERS != 8
222 # error the following code only supports up to 8 channels, update it
224 if (sb->format.width == 1)
226 const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
228 // Stereo sound support
229 if (sb->format.channels == 2)
231 if (vol[6] + vol[7] > 0)
233 for (i = 0;i < count;i++)
235 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
236 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
237 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
238 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
239 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
240 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
241 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
242 paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
246 else if (vol[4] + vol[5] > 0)
248 for (i = 0;i < count;i++)
250 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
251 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
252 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
253 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
254 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
255 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
259 else if (vol[2] + vol[3] > 0)
261 for (i = 0;i < count;i++)
263 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
264 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
265 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
266 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
270 else if (vol[0] + vol[1] > 0)
272 for (i = 0;i < count;i++)
274 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
275 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
280 else if (sb->format.channels == 1)
282 if (vol[6] + vol[7] > 0)
284 for (i = 0;i < count;i++)
286 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
287 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
288 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
289 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
290 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
291 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
292 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
293 paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
297 else if (vol[4] + vol[5] > 0)
299 for (i = 0;i < count;i++)
301 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
302 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
303 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
304 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
305 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
306 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
310 else if (vol[2] + vol[3] > 0)
312 for (i = 0;i < count;i++)
314 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
315 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
316 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
317 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
321 else if (vol[0] + vol[1] > 0)
323 for (i = 0;i < count;i++)
325 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
326 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
332 return false; // unsupported number of channels in sound
334 else if (sb->format.width == 2)
336 const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
338 // Stereo sound support
339 if (sb->format.channels == 2)
341 if (vol[6] + vol[7] > 0)
343 for (i = 0;i < count;i++)
345 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
346 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
347 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
348 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
349 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
350 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
351 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
352 paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
356 else if (vol[4] + vol[5] > 0)
358 for (i = 0;i < count;i++)
360 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
361 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
362 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
363 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
364 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
365 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
369 else if (vol[2] + vol[3] > 0)
371 for (i = 0;i < count;i++)
373 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
374 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
375 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
376 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
380 else if (vol[0] + vol[1] > 0)
382 for (i = 0;i < count;i++)
384 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
385 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
390 else if (sb->format.channels == 1)
392 if (vol[6] + vol[7] > 0)
394 for (i = 0;i < count;i++)
396 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
397 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
398 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
399 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
400 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
401 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
402 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
403 paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
407 else if (vol[4] + vol[5] > 0)
409 for (i = 0;i < count;i++)
411 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
412 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
413 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
414 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
415 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
416 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
420 else if (vol[2] + vol[3] > 0)
422 for (i = 0;i < count;i++)
424 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
425 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
426 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
427 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
431 else if (vol[0] + vol[1] > 0)
433 for (i = 0;i < count;i++)
435 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
436 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
442 return false; // unsupported number of channels in sound
448 void S_MixToBuffer(void *stream, unsigned int bufferframes)
453 unsigned char *outbytes = (unsigned char *) stream;
455 // mix as many times as needed to fill the requested buffer
458 // limit to the size of the paint buffer
459 frames = min(bufferframes, PAINTBUFFER_SIZE);
461 // clear the paint buffer
462 memset (paintbuffer, 0, frames * sizeof (paintbuffer[0]));
464 // paint in the channels.
465 // channels with zero volumes still advance in time but don't paint.
467 for (i = 0; i < total_channels ; i++, ch++)
476 if (!S_LoadSound (sfx, true))
478 if (ch->flags & CHANNELFLAG_PAUSED)
485 count = min(count, (int)frames - ltime);
490 while (ltime < (int)frames)
492 // paint up to end of buffer or of input, whichever is lower
493 count = sfx->total_length - ch->pos;
494 count = bound(0, count, (int)frames - ltime);
497 SND_PaintChannel (ch, paintbuffer + ltime, count);
502 // if at end of sfx, loop or stop the channel
503 if (ch->pos >= (int)sfx->total_length)
505 if (sfx->loopstart < sfx->total_length)
506 ch->pos = sfx->loopstart;
507 else if (ch->flags & CHANNELFLAG_FORCELOOP)
511 S_StopChannel (ch - channels, false);
518 if (!snd_usethreadedmixing)
519 S_CaptureAVISound(frames);
521 S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
523 // advance the output pointer
524 outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
525 bufferframes -= frames;