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(const portable_sampleframe_t *paintbuffer, 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 // FIXME: add 24bit and 32bit float formats
54 // FIXME: optimize with SSE intrinsics?
55 if (width == 2) // 16bit
57 short *snd_out = (short*)rb_ptr;
58 if (channels == 8) // 7.1 surround
60 for (i = 0;i < nbframes;i++, painted_ptr++)
62 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
63 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
64 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
65 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
66 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
67 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
68 val = (int)(painted_ptr->sample[6] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
69 val = (int)(painted_ptr->sample[7] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
72 else if (channels == 6) // 5.1 surround
74 for (i = 0; i < nbframes; i++, painted_ptr++)
76 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
77 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
78 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
79 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
80 val = (int)(painted_ptr->sample[4] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
81 val = (int)(painted_ptr->sample[5] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
84 else if (channels == 4) // 4.0 surround
86 for (i = 0; i < nbframes; i++, painted_ptr++)
88 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
89 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
90 val = (int)(painted_ptr->sample[2] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
91 val = (int)(painted_ptr->sample[3] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
94 else if (channels == 2) // 2.0 stereo
96 for (i = 0; i < nbframes; i++, painted_ptr++)
98 val = (int)(painted_ptr->sample[0] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
99 val = (int)(painted_ptr->sample[1] * 32768.0f);*snd_out++ = bound(-32768, val, 32767);
102 else if (channels == 1) // 1.0 mono
104 for (i = 0; i < nbframes; i++, painted_ptr++)
106 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 16384.0f);*snd_out++ = bound(-32768, val, 32767);
110 // noise is really really annoying
112 memset(rb_ptr, 0, nbframes * channels * width);
116 unsigned char *snd_out = (unsigned char*)rb_ptr;
117 if (channels == 8) // 7.1 surround
119 for (i = 0; i < nbframes; i++, painted_ptr++)
121 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
122 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
123 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
124 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
125 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
126 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
127 val = (int)(painted_ptr->sample[6] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
128 val = (int)(painted_ptr->sample[7] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
131 else if (channels == 6) // 5.1 surround
133 for (i = 0; i < nbframes; i++, painted_ptr++)
135 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
136 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
137 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
138 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
139 val = (int)(painted_ptr->sample[4] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
140 val = (int)(painted_ptr->sample[5] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
143 else if (channels == 4) // 4.0 surround
145 for (i = 0; i < nbframes; i++, painted_ptr++)
147 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
148 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
149 val = (int)(painted_ptr->sample[2] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
150 val = (int)(painted_ptr->sample[3] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
153 else if (channels == 2) // 2.0 stereo
155 for (i = 0; i < nbframes; i++, painted_ptr++)
157 val = (int)(painted_ptr->sample[0] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
158 val = (int)(painted_ptr->sample[1] * 128.0f) + 128; *snd_out++ = bound(0, val, 255);
161 else if (channels == 1) // 1.0 mono
163 for (i = 0;i < nbframes;i++, painted_ptr++)
165 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 64.0f) + 128; *snd_out++ = bound(0, val, 255);
169 // noise is really really annoying
171 memset(rb_ptr, 128, nbframes * channels);
177 ===============================================================================
181 ===============================================================================
184 void S_MixToBuffer(void *stream, unsigned int bufferframes)
189 unsigned char *outbytes = (unsigned char *) stream;
191 portable_sampleframe_t *paint;
204 #define S_FETCHBUFFERSIZE 4096
205 float fetchsampleframes[S_FETCHBUFFERSIZE*2];
206 const float *fetchsampleframe;
207 float vol[SND_LISTENERS];
216 // mix as many times as needed to fill the requested buffer
219 // limit to the size of the paint buffer
220 totalmixframes = min(bufferframes, PAINTBUFFER_SIZE);
222 // clear the paint buffer
223 memset(paintbuffer, 0, totalmixframes * sizeof(paintbuffer[0]));
225 // paint in the channels.
226 // channels with zero volumes still advance in time but don't paint.
228 for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
233 if (!S_LoadSound (sfx, true))
235 if (ch->flags & CHANNELFLAG_PAUSED)
237 if (!sfx->total_length)
240 // copy the channel information to the stack for reference, otherwise the
241 // values might change during a mix if the spatializer is updating them
242 // (note: this still may get some old and some new values!)
244 speedd = ch->mixspeed * sfx->format.speed / snd_renderbuffer->format.speed;
245 for (i = 0;i < SND_LISTENERS;i++)
246 vol[i] = ch->volume[i];
248 // check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly)
250 for (i = 0;i < SND_LISTENERS;i++)
253 switch(snd_renderbuffer->format.width)
256 silent = maxvol < (1.0f / (256.0f));
257 // so silent it has zero effect
260 silent = maxvol < (1.0f / (65536.0f));
261 // so silent it has zero effect
263 default: // floating point
264 silent = maxvol < 1.0e-13f;
265 // 130 dB is difference between hearing
266 // threshold and a jackhammer from
268 // therefore, anyone who turns up
269 // volume so much they notice this
270 // cutoff, likely already has their
271 // ear-drums blown out anyway.
275 // when doing prologic mixing, some channels invert one side
276 if (ch->prologic_invert == -1)
279 // get some sfx info in a consistent form
280 totallength = sfx->total_length;
281 loopstart = (int)sfx->loopstart < totallength ? (int)sfx->loopstart : ((ch->flags & CHANNELFLAG_FORCELOOP) ? 0 : totallength);
282 looping = loopstart < totallength;
284 // do the actual paint now (may skip work if silent)
286 wantframes = totalmixframes;
288 for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
290 // check if this is a delayed sound
293 // for a delayed sound we have to eat into the delay first
294 count = (int)floor(-posd / speedd) + 1;
295 count = bound(1, count, wantframes);
296 // let the for loop iterator apply the skip
300 // compute a fetch size that won't overflow our buffer
304 istartframe = (int)floor(posd);
305 iendframe = (int)floor(posd + (count-1) * speedd);
306 ilengthframes = count > 1 ? (iendframe - istartframe + 2) : 2;
307 if (ilengthframes <= S_FETCHBUFFERSIZE)
309 // reduce count by 25% and try again
313 // zero whole fetch buffer for safety
314 // (floating point noise from uninitialized memory = HORRIBLE)
315 // otherwise we would only need to clear the excess
317 memset(fetchsampleframes, 0, ilengthframes*sfx->format.channels*sizeof(fetchsampleframes[0]));
319 // if looping, do multiple fetches
323 fetch = min(ilengthframes - fetched, totallength - istartframe);
327 sfx->fetcher->getsamplesfloat(ch, sfx, istartframe, fetch, fetchsampleframes + fetched*sfx->format.channels);
328 istartframe += fetch;
331 if (istartframe == totallength && looping && fetched < ilengthframes)
333 // loop and fetch some more
334 posd += loopstart - totallength;
335 istartframe = loopstart;
343 // set up our fixedpoint resampling variables (float to int conversions are expensive so do not do one per sampleframe)
344 fetchsampleframe = fetchsampleframes;
345 indexfrac = (int)floor((posd - floor(posd)) * 65536.0);
346 indexfracstep = (int)floor(speedd * 65536.0);
349 if (sfx->format.channels == 2)
352 #if SND_LISTENERS != 8
353 #error the following code only supports up to 8 channels, update it
355 if (snd_speakerlayout.channels > 2)
358 for (i = 0;i < count;i++, paint++)
360 lerp[1] = indexfrac * (1.0f / 65536.0f);
361 lerp[0] = 1.0f - lerp[1];
362 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
363 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
364 sample[2] = (sample[0] + sample[1]) * 0.5f;
365 paint->sample[0] += sample[0] * vol[0];
366 paint->sample[1] += sample[1] * vol[1];
367 paint->sample[2] += sample[0] * vol[2];
368 paint->sample[3] += sample[1] * vol[3];
369 paint->sample[4] += sample[2] * vol[4];
370 paint->sample[5] += sample[2] * vol[5];
371 paint->sample[6] += sample[0] * vol[6];
372 paint->sample[7] += sample[1] * vol[7];
373 indexfrac += indexfracstep;
374 fetchsampleframe += 2 * (indexfrac >> 16);
381 for (i = 0;i < count;i++, paint++)
383 lerp[1] = indexfrac * (1.0f / 65536.0f);
384 lerp[0] = 1.0f - lerp[1];
385 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[2] * lerp[1];
386 sample[1] = fetchsampleframe[1] * lerp[0] + fetchsampleframe[3] * lerp[1];
387 paint->sample[0] += sample[0] * vol[0];
388 paint->sample[1] += sample[1] * vol[1];
389 indexfrac += indexfracstep;
390 fetchsampleframe += 2 * (indexfrac >> 16);
395 else if (sfx->format.channels == 1)
397 // most sounds are mono
398 #if SND_LISTENERS != 8
399 #error the following code only supports up to 8 channels, update it
401 if (snd_speakerlayout.channels > 2)
404 for (i = 0;i < count;i++, paint++)
406 lerp[1] = indexfrac * (1.0f / 65536.0f);
407 lerp[0] = 1.0f - lerp[1];
408 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
409 paint->sample[0] += sample[0] * vol[0];
410 paint->sample[1] += sample[0] * vol[1];
411 paint->sample[2] += sample[0] * vol[2];
412 paint->sample[3] += sample[0] * vol[3];
413 paint->sample[4] += sample[0] * vol[4];
414 paint->sample[5] += sample[0] * vol[5];
415 paint->sample[6] += sample[0] * vol[6];
416 paint->sample[7] += sample[0] * vol[7];
417 indexfrac += indexfracstep;
418 fetchsampleframe += (indexfrac >> 16);
425 for (i = 0;i < count;i++, paint++)
427 lerp[1] = indexfrac * (1.0f / 65536.0f);
428 lerp[0] = 1.0f - lerp[1];
429 sample[0] = fetchsampleframe[0] * lerp[0] + fetchsampleframe[1] * lerp[1];
430 paint->sample[0] += sample[0] * vol[0];
431 paint->sample[1] += sample[0] * vol[1];
432 indexfrac += indexfracstep;
433 fetchsampleframe += (indexfrac >> 16);
441 if (!looping && istartframe == totallength)
442 S_StopChannel(ch - channels, false, false);
445 if (!snd_usethreadedmixing)
446 S_CaptureAVISound(paintbuffer, totalmixframes);
448 S_ConvertPaintBuffer(paintbuffer, outbytes, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
450 // advance the output pointer
451 outbytes += totalmixframes * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
452 bufferframes -= totalmixframes;