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 vol[SND_LISTENERS];
187 const snd_buffer_t *sb;
188 unsigned int i, sb_offset;
190 // move to the stack (do we need to?)
191 for (i = 0;i < SND_LISTENERS;i++)
192 vol[i] = ch->listener_volume[i];
194 // if volumes are all zero, just return
195 for (i = 0;i < SND_LISTENERS;i++)
198 if (i == SND_LISTENERS)
202 sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
205 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
206 ch->sfx->name); // , count); // or add this? FIXME
211 #if SND_LISTENERS != 8
212 # error the following code only supports up to 8 channels, update it
214 if (sb->format.width == 1)
216 const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
218 // Stereo sound support
219 if (sb->format.channels == 2)
221 if (vol[6] + vol[7] > 0)
223 for (i = 0;i < count;i++)
225 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
226 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
227 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
228 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
229 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
230 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
231 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
232 paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
236 else if (vol[4] + vol[5] > 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;
249 else if (vol[2] + vol[3] > 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;
255 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
256 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
260 else if (vol[0] + vol[1] > 0)
262 for (i = 0;i < count;i++)
264 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
265 paint[i].sample[1] += (samples[1] * vol[1] * ch->prologic_invert) >> 8;
270 else if (sb->format.channels == 1)
272 if (vol[6] + vol[7] > 0)
274 for (i = 0;i < count;i++)
276 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
277 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
278 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
279 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
280 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
281 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
282 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
283 paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
287 else if (vol[4] + vol[5] > 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;
300 else if (vol[2] + vol[3] > 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;
306 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
307 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
311 else if (vol[0] + vol[1] > 0)
313 for (i = 0;i < count;i++)
315 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
316 paint[i].sample[1] += (samples[0] * vol[1] * ch->prologic_invert) >> 8;
322 return false; // unsupported number of channels in sound
324 else if (sb->format.width == 2)
326 const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
328 // Stereo sound support
329 if (sb->format.channels == 2)
331 if (vol[6] + vol[7] > 0)
333 for (i = 0;i < count;i++)
335 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
336 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
337 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
338 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
339 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
340 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
341 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
342 paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
346 else if (vol[4] + vol[5] > 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;
359 else if (vol[2] + vol[3] > 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;
365 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
366 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
370 else if (vol[0] + vol[1] > 0)
372 for (i = 0;i < count;i++)
374 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
375 paint[i].sample[1] += (samples[1] * vol[1] * ch->prologic_invert) >> 16;
380 else if (sb->format.channels == 1)
382 if (vol[6] + vol[7] > 0)
384 for (i = 0;i < count;i++)
386 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
387 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
388 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
389 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
390 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
391 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
392 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
393 paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
397 else if (vol[4] + vol[5] > 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;
410 else if (vol[2] + vol[3] > 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;
416 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
417 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
421 else if (vol[0] + vol[1] > 0)
423 for (i = 0;i < count;i++)
425 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
426 paint[i].sample[1] += (samples[0] * vol[1] * ch->prologic_invert) >> 16;
432 return false; // unsupported number of channels in sound
438 void S_MixToBuffer(void *stream, unsigned int bufferframes)
443 unsigned char *outbytes = (unsigned char *) stream;
445 // mix as many times as needed to fill the requested buffer
448 // limit to the size of the paint buffer
449 frames = min(bufferframes, PAINTBUFFER_SIZE);
451 // clear the paint buffer
452 memset (paintbuffer, 0, frames * sizeof (paintbuffer[0]));
454 // paint in the channels.
455 // channels with zero volumes still advance in time but don't paint.
457 for (i = 0; i < total_channels ; i++, ch++)
466 if (!S_LoadSound (sfx, true))
468 if (ch->flags & CHANNELFLAG_PAUSED)
475 count = min(count, (int)frames - ltime);
480 while (ltime < (int)frames)
482 // paint up to end of buffer or of input, whichever is lower
483 count = sfx->total_length - ch->pos;
484 count = bound(0, count, (int)frames - ltime);
487 SND_PaintChannel (ch, paintbuffer + ltime, count);
492 // if at end of sfx, loop or stop the channel
493 if (ch->pos >= (int)sfx->total_length)
495 if (sfx->loopstart < sfx->total_length)
496 ch->pos = sfx->loopstart;
497 else if (ch->flags & CHANNELFLAG_FORCELOOP)
501 S_StopChannel (ch - channels, false);
508 if (!snd_usethreadedmixing)
509 S_CaptureAVISound(frames);
511 S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
513 // advance the output pointer
514 outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
515 bufferframes -= frames;