]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - snd_mix.c
add cvars: snd_attenuation_exponent, snd_attenuation_decibel
[xonotic/darkplaces.git] / snd_mix.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20
21 #include "quakedef.h"
22 #include "snd_main.h"
23
24
25 static portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
26 static portable_sampleframe_t paintbuffer_unswapped[PAINTBUFFER_SIZE];
27
28 extern speakerlayout_t snd_speakerlayout; // for querying the listeners
29
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)
32 {
33         size_t i;
34         unsigned int j;
35
36         if (!cls.capturevideo.active)
37                 return;
38
39         // undo whatever swapping the channel layout (swapstereo, ALSA) did
40         for(j = 0; j < snd_speakerlayout.channels; ++j)
41         {
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];
45         }
46
47         SCR_CaptureVideo_SoundFrame(paintbuffer_unswapped, length);
48 }
49
50 static void S_ConvertPaintBuffer(const portable_sampleframe_t *painted_ptr, void *rb_ptr, int nbframes, int width, int channels)
51 {
52         int i, val;
53         // FIXME: add 24bit and 32bit float formats
54         // FIXME: optimize with SSE intrinsics?
55         if (width == 2)  // 16bit
56         {
57                 short *snd_out = (short*)rb_ptr;
58                 if (channels == 8)  // 7.1 surround
59                 {
60                         for (i = 0;i < nbframes;i++, painted_ptr++)
61                         {
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);
70                         }
71                 }
72                 else if (channels == 6)  // 5.1 surround
73                 {
74                         for (i = 0; i < nbframes; i++, painted_ptr++)
75                         {
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);
82                         }
83                 }
84                 else if (channels == 4)  // 4.0 surround
85                 {
86                         for (i = 0; i < nbframes; i++, painted_ptr++)
87                         {
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);
92                         }
93                 }
94                 else if (channels == 2)  // 2.0 stereo
95                 {
96                         for (i = 0; i < nbframes; i++, painted_ptr++)
97                         {
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);
100                         }
101                 }
102                 else if (channels == 1)  // 1.0 mono
103                 {
104                         for (i = 0; i < nbframes; i++, painted_ptr++)
105                         {
106                                 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 16384.0f);*snd_out++ = bound(-32768, val, 32767);
107                         }
108                 }
109
110                 // noise is really really annoying
111                 if (cls.timedemo)
112                         memset(rb_ptr, 0, nbframes * channels * width);
113         }
114         else  // 8bit
115         {
116                 unsigned char *snd_out = (unsigned char*)rb_ptr;
117                 if (channels == 8)  // 7.1 surround
118                 {
119                         for (i = 0; i < nbframes; i++, painted_ptr++)
120                         {
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);
129                         }
130                 }
131                 else if (channels == 6)  // 5.1 surround
132                 {
133                         for (i = 0; i < nbframes; i++, painted_ptr++)
134                         {
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);
141                         }
142                 }
143                 else if (channels == 4)  // 4.0 surround
144                 {
145                         for (i = 0; i < nbframes; i++, painted_ptr++)
146                         {
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);
151                         }
152                 }
153                 else if (channels == 2)  // 2.0 stereo
154                 {
155                         for (i = 0; i < nbframes; i++, painted_ptr++)
156                         {
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);
159                         }
160                 }
161                 else if (channels == 1)  // 1.0 mono
162                 {
163                         for (i = 0;i < nbframes;i++, painted_ptr++)
164                         {
165                                 val = (int)((painted_ptr->sample[0] + painted_ptr->sample[1]) * 64.0f) + 128; *snd_out++ = bound(0, val, 255);
166                         }
167                 }
168
169                 // noise is really really annoying
170                 if (cls.timedemo)
171                         memset(rb_ptr, 128, nbframes * channels);
172         }
173 }
174
175
176 /*
177 ===============================================================================
178
179 CHANNEL MIXING
180
181 ===============================================================================
182 */
183
184 void S_MixToBuffer(void *stream, unsigned int bufferframes)
185 {
186         int channelindex;
187         channel_t *ch;
188         int totalmixframes;
189         unsigned char *outbytes = (unsigned char *) stream;
190         sfx_t *sfx;
191         portable_sampleframe_t *paint;
192         int wantframes;
193         int i;
194         int count;
195         int fetched;
196         int fetch;
197         int istartframe;
198         int iendframe;
199         int ilengthframes;
200         int totallength;
201         int loopstart;
202         int indexfrac;
203         int indexfracstep;
204 #define S_FETCHBUFFERSIZE 4096
205         float fetchsampleframes[S_FETCHBUFFERSIZE*2];
206         const float *fetchsampleframe;
207         float vol[SND_LISTENERS];
208         float lerp[2];
209         float sample[3];
210         double posd;
211         double speedd;
212         float maxvol;
213         qboolean looping;
214         qboolean silent;
215
216         // mix as many times as needed to fill the requested buffer
217         while (bufferframes)
218         {
219                 // limit to the size of the paint buffer
220                 totalmixframes = min(bufferframes, PAINTBUFFER_SIZE);
221
222                 // clear the paint buffer
223                 memset(paintbuffer, 0, totalmixframes * sizeof(paintbuffer[0]));
224
225                 // paint in the channels.
226                 // channels with zero volumes still advance in time but don't paint.
227                 ch = channels;
228                 for (channelindex = 0;channelindex < (int)total_channels;channelindex++, ch++)
229                 {
230                         sfx = ch->sfx;
231                         if (sfx == NULL)
232                                 continue;
233                         if (!S_LoadSound (sfx, true))
234                                 continue;
235                         if (ch->flags & CHANNELFLAG_PAUSED)
236                                 continue;
237                         if (!sfx->total_length)
238                                 continue;
239
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!)
243                         posd = ch->position;
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];
247
248                         // check total volume level, because we can skip some code on silent sounds but other code must still run (position updates mainly)
249                         maxvol = 0;
250                         for (i = 0;i < SND_LISTENERS;i++)
251                                 if(vol[i] > maxvol)
252                                         maxvol = vol[i];
253                         switch(snd_renderbuffer->format.width)
254                         {
255                                 case 1: // 8bpp
256                                         silent = maxvol < (1.0f / (256.0f));
257                                         // so silent it has zero effect
258                                         break;
259                                 case 2: // 16bpp
260                                         silent = maxvol < (1.0f / (65536.0f));
261                                         // so silent it has zero effect
262                                         break;
263                                 default: // floating point
264                                         silent = maxvol < 1.0e-13f;
265                                         // 130 dB is difference between hearing
266                                         // threshold and a jackhammer from
267                                         // working distance.
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.
272                                         break;
273                         }
274
275                         // when doing prologic mixing, some channels invert one side
276                         if (ch->prologic_invert == -1)
277                                 vol[1] *= -1.0f;
278
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;
283
284                         // do the actual paint now (may skip work if silent)
285                         paint = paintbuffer;
286                         wantframes = totalmixframes;
287                         istartframe = 0;
288                         for (wantframes = totalmixframes;wantframes > 0;posd += count * speedd, wantframes -= count)
289                         {
290                                 // check if this is a delayed sound
291                                 if (posd < 0)
292                                 {
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
297                                         continue;
298                                 }
299
300                                 // compute a fetch size that won't overflow our buffer
301                                 count = wantframes;
302                                 for (;;)
303                                 {
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)
308                                                 break;
309                                         // reduce count by 25% and try again
310                                         count -= count >> 2;
311                                 }
312
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
316                                 if (!silent)
317                                         memset(fetchsampleframes, 0, ilengthframes*sfx->format.channels*sizeof(fetchsampleframes[0]));
318
319                                 // if looping, do multiple fetches
320                                 fetched = 0;
321                                 for (;;)
322                                 {
323                                         fetch = min(ilengthframes - fetched, totallength - istartframe);
324                                         if (fetch > 0)
325                                         {
326                                                 if (!silent)
327                                                         sfx->fetcher->getsamplesfloat(ch, sfx, istartframe, fetch, fetchsampleframes + fetched*sfx->format.channels);
328                                                 istartframe += fetch;
329                                                 fetched += fetch;
330                                         }
331                                         if (istartframe == totallength && looping && fetched < ilengthframes)
332                                         {
333                                                 // loop and fetch some more
334                                                 posd += loopstart - totallength;
335                                                 istartframe = loopstart;
336                                         }
337                                         else
338                                         {
339                                                 break;
340                                         }
341                                 }
342
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);
347                                 if (!silent)
348                                 {
349                                         if (sfx->format.channels == 2)
350                                         {
351                                                 // music is stereo
352 #if SND_LISTENERS != 8
353 #error the following code only supports up to 8 channels, update it
354 #endif
355                                                 if (snd_speakerlayout.channels > 2)
356                                                 {
357                                                         // surround mixing
358                                                         for (i = 0;i < count;i++, paint++)
359                                                         {
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);
375                                                                 indexfrac &= 0xFFFF;
376                                                         }
377                                                 }
378                                                 else
379                                                 {
380                                                         // stereo mixing
381                                                         for (i = 0;i < count;i++, paint++)
382                                                         {
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);
391                                                                 indexfrac &= 0xFFFF;
392                                                         }
393                                                 }
394                                         }
395                                         else if (sfx->format.channels == 1)
396                                         {
397                                                 // most sounds are mono
398 #if SND_LISTENERS != 8
399 #error the following code only supports up to 8 channels, update it
400 #endif
401                                                 if (snd_speakerlayout.channels > 2)
402                                                 {
403                                                         // surround mixing
404                                                         for (i = 0;i < count;i++, paint++)
405                                                         {
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);
419                                                                 indexfrac &= 0xFFFF;
420                                                         }
421                                                 }
422                                                 else
423                                                 {
424                                                         // stereo mixing
425                                                         for (i = 0;i < count;i++, paint++)
426                                                         {
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);
434                                                                 indexfrac &= 0xFFFF;
435                                                         }
436                                                 }
437                                         }
438                                 }
439                         }
440                         ch->position = posd;
441                         if (!looping && istartframe == totallength)
442                                 S_StopChannel(ch - channels, false, false);
443                 }
444
445                 if (!snd_usethreadedmixing)
446                         S_CaptureAVISound(paintbuffer, totalmixframes);
447
448                 S_ConvertPaintBuffer(paintbuffer, outbytes, totalmixframes, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
449
450                 // advance the output pointer
451                 outbytes += totalmixframes * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
452                 bufferframes -= totalmixframes;
453         }
454 }