]> icculus.org git repositories - divverent/darkplaces.git/blob - snd_mix.c
reworked default address cvars to be empty for default interfaces, this
[divverent/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(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         if (width == 2)  // 16bit
54         {
55                 short *snd_out = (short*)rb_ptr;
56                 if (channels == 8)  // 7.1 surround
57                 {
58                         for (i = 0;i < nbframes;i++, painted_ptr++)
59                         {
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);
68                         }
69                 }
70                 else if (channels == 6)  // 5.1 surround
71                 {
72                         for (i = 0; i < nbframes; i++, painted_ptr++)
73                         {
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);
80                         }
81                 }
82                 else if (channels == 4)  // 4.0 surround
83                 {
84                         for (i = 0; i < nbframes; i++, painted_ptr++)
85                         {
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);
90                         }
91                 }
92                 else if (channels == 2)  // 2.0 stereo
93                 {
94                         for (i = 0; i < nbframes; i++, painted_ptr++)
95                         {
96                                 *snd_out++ = bound(-32768, painted_ptr->sample[0], 32767);
97                                 *snd_out++ = bound(-32768, painted_ptr->sample[1], 32767);
98                         }
99                 }
100                 else if (channels == 1)  // 1.0 mono
101                 {
102                         for (i = 0; i < nbframes; i++, painted_ptr++)
103                         {
104                                 val = (painted_ptr->sample[0] + painted_ptr->sample[1]) >> 1;
105                                 *snd_out++ = bound(-32768, val, 32767);
106                         }
107                 }
108         }
109         else  // 8bit
110         {
111                 unsigned char *snd_out = (unsigned char*)rb_ptr;
112                 if (channels == 8)  // 7.1 surround
113                 {
114                         for (i = 0; i < nbframes; i++, painted_ptr++)
115                         {
116                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
117                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
118                                 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
119                                 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
120                                 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
121                                 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
122                                 val = (painted_ptr->sample[6] >> 8) + 128; *snd_out++ = bound(0, val, 255);
123                                 val = (painted_ptr->sample[7] >> 8) + 128; *snd_out++ = bound(0, val, 255);
124                         }
125                 }
126                 else if (channels == 6)  // 5.1 surround
127                 {
128                         for (i = 0; i < nbframes; i++, painted_ptr++)
129                         {
130                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
131                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
132                                 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
133                                 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
134                                 val = (painted_ptr->sample[4] >> 8) + 128; *snd_out++ = bound(0, val, 255);
135                                 val = (painted_ptr->sample[5] >> 8) + 128; *snd_out++ = bound(0, val, 255);
136                         }
137                 }
138                 else if (channels == 4)  // 4.0 surround
139                 {
140                         for (i = 0; i < nbframes; i++, painted_ptr++)
141                         {
142                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
143                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
144                                 val = (painted_ptr->sample[2] >> 8) + 128; *snd_out++ = bound(0, val, 255);
145                                 val = (painted_ptr->sample[3] >> 8) + 128; *snd_out++ = bound(0, val, 255);
146                         }
147                 }
148                 else if (channels == 2)  // 2.0 stereo
149                 {
150                         for (i = 0; i < nbframes; i++, painted_ptr++)
151                         {
152                                 val = (painted_ptr->sample[0] >> 8) + 128; *snd_out++ = bound(0, val, 255);
153                                 val = (painted_ptr->sample[1] >> 8) + 128; *snd_out++ = bound(0, val, 255);
154                         }
155                 }
156                 else if (channels == 1)  // 1.0 mono
157                 {
158                         for (i = 0;i < nbframes;i++, painted_ptr++)
159                         {
160                                 val = ((painted_ptr->sample[0] + painted_ptr->sample[1]) >> 9) + 128;
161                                 *snd_out++ = bound(0, val, 255);
162                         }
163                 }
164         }
165 }
166
167
168 /*
169 ===============================================================================
170
171 CHANNEL MIXING
172
173 ===============================================================================
174 */
175
176 static qboolean SND_PaintChannel (channel_t *ch, portable_sampleframe_t *paint, unsigned int count)
177 {
178         int snd_vol, vol[SND_LISTENERS];
179         const snd_buffer_t *sb;
180         unsigned int i, sb_offset;
181
182         // If this channel manages its own volume
183         if (ch->flags & CHANNELFLAG_FULLVOLUME)
184                 snd_vol = 256;
185         else
186                 snd_vol = (int)(volume.value * 256);
187
188         // calculate mixing volumes based on channel volumes and volume cvar
189         // also limit the volumes to values that won't clip
190         for (i = 0;i < SND_LISTENERS;i++)
191         {
192                 vol[i] = ch->listener_volume[i] * snd_vol;
193                 vol[i] = bound(0, vol[i], 65536);
194         }
195
196         // if volumes are all zero, just return
197         for (i = 0;i < SND_LISTENERS;i++)
198                 if (vol[i])
199                         break;
200         if (i == SND_LISTENERS)
201                 return false;
202
203         sb_offset = ch->pos;
204         sb = ch->sfx->fetcher->getsb (ch->sfx->fetcher_data, &ch->fetcher_data, &sb_offset, count);
205         if (sb == NULL)
206         {
207                 Con_DPrintf("SND_PaintChannel: ERROR: can't get sound buffer from sfx \"%s\"\n",
208                                         ch->sfx->name); // , count); // or add this? FIXME
209                 return false;
210         }
211         else
212         {
213 #if SND_LISTENERS != 8
214 #               error the following code only supports up to 8 channels, update it
215 #endif
216                 if (sb->format.width == 1)
217                 {
218                         const signed char *samples = (signed char*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
219
220                         // Stereo sound support
221                         if (sb->format.channels == 2)
222                         {
223                                 if (vol[6] + vol[7] > 0)
224                                 {
225                                         for (i = 0;i < count;i++)
226                                         {
227                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
228                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
229                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
230                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
231                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
232                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
233                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
234                                                 paint[i].sample[7] += (samples[1] * vol[7]) >> 8;
235                                                 samples += 2;
236                                         }
237                                 }
238                                 else if (vol[4] + vol[5] > 0)
239                                 {
240                                         for (i = 0;i < count;i++)
241                                         {
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;
246                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 9;
247                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 9;
248                                                 samples += 2;
249                                         }
250                                 }
251                                 else if (vol[2] + vol[3] > 0)
252                                 {
253                                         for (i = 0;i < count;i++)
254                                         {
255                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
256                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
257                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
258                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 8;
259                                                 samples += 2;
260                                         }
261                                 }
262                                 else if (vol[0] + vol[1] > 0)
263                                 {
264                                         for (i = 0;i < count;i++)
265                                         {
266                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
267                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 8;
268                                                 samples += 2;
269                                         }
270                                 }
271                         }
272                         else if (sb->format.channels == 1)
273                         {
274                                 if (vol[6] + vol[7] > 0)
275                                 {
276                                         for (i = 0;i < count;i++)
277                                         {
278                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
279                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
280                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
281                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
282                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
283                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
284                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 8;
285                                                 paint[i].sample[7] += (samples[0] * vol[7]) >> 8;
286                                                 samples += 1;
287                                         }
288                                 }
289                                 else if (vol[4] + vol[5] > 0)
290                                 {
291                                         for (i = 0;i < count;i++)
292                                         {
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;
297                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 8;
298                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 8;
299                                                 samples += 1;
300                                         }
301                                 }
302                                 else if (vol[2] + vol[3] > 0)
303                                 {
304                                         for (i = 0;i < count;i++)
305                                         {
306                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
307                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
308                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 8;
309                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 8;
310                                                 samples += 1;
311                                         }
312                                 }
313                                 else if (vol[0] + vol[1] > 0)
314                                 {
315                                         for (i = 0;i < count;i++)
316                                         {
317                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 8;
318                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 8;
319                                                 samples += 1;
320                                         }
321                                 }
322                         }
323                         else
324                                 return false; // unsupported number of channels in sound
325                 }
326                 else if (sb->format.width == 2)
327                 {
328                         const signed short *samples = (signed short*)sb->samples + (ch->pos - sb_offset) * sb->format.channels;
329
330                         // Stereo sound support
331                         if (sb->format.channels == 2)
332                         {
333                                 if (vol[6] + vol[7] > 0)
334                                 {
335                                         for (i = 0;i < count;i++)
336                                         {
337                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
338                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
339                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
340                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
341                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
342                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
343                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
344                                                 paint[i].sample[7] += (samples[1] * vol[7]) >> 16;
345                                                 samples += 2;
346                                         }
347                                 }
348                                 else if (vol[4] + vol[5] > 0)
349                                 {
350                                         for (i = 0;i < count;i++)
351                                         {
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;
356                                                 paint[i].sample[4] += ((samples[0] + samples[1]) * vol[4]) >> 17;
357                                                 paint[i].sample[5] += ((samples[0] + samples[1]) * vol[5]) >> 17;
358                                                 samples += 2;
359                                         }
360                                 }
361                                 else if (vol[2] + vol[3] > 0)
362                                 {
363                                         for (i = 0;i < count;i++)
364                                         {
365                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
366                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
367                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
368                                                 paint[i].sample[3] += (samples[1] * vol[3]) >> 16;
369                                                 samples += 2;
370                                         }
371                                 }
372                                 else if (vol[0] + vol[1] > 0)
373                                 {
374                                         for (i = 0;i < count;i++)
375                                         {
376                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
377                                                 paint[i].sample[1] += (samples[1] * vol[1]) >> 16;
378                                                 samples += 2;
379                                         }
380                                 }
381                         }
382                         else if (sb->format.channels == 1)
383                         {
384                                 if (vol[6] + vol[7] > 0)
385                                 {
386                                         for (i = 0;i < count;i++)
387                                         {
388                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
389                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
390                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
391                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
392                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
393                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
394                                                 paint[i].sample[6] += (samples[0] * vol[6]) >> 16;
395                                                 paint[i].sample[7] += (samples[0] * vol[7]) >> 16;
396                                                 samples += 1;
397                                         }
398                                 }
399                                 else if (vol[4] + vol[5] > 0)
400                                 {
401                                         for (i = 0;i < count;i++)
402                                         {
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;
407                                                 paint[i].sample[4] += (samples[0] * vol[4]) >> 16;
408                                                 paint[i].sample[5] += (samples[0] * vol[5]) >> 16;
409                                                 samples += 1;
410                                         }
411                                 }
412                                 else if (vol[2] + vol[3] > 0)
413                                 {
414                                         for (i = 0;i < count;i++)
415                                         {
416                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
417                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
418                                                 paint[i].sample[2] += (samples[0] * vol[2]) >> 16;
419                                                 paint[i].sample[3] += (samples[0] * vol[3]) >> 16;
420                                                 samples += 1;
421                                         }
422                                 }
423                                 else if (vol[0] + vol[1] > 0)
424                                 {
425                                         for (i = 0;i < count;i++)
426                                         {
427                                                 paint[i].sample[0] += (samples[0] * vol[0]) >> 16;
428                                                 paint[i].sample[1] += (samples[0] * vol[1]) >> 16;
429                                                 samples += 1;
430                                         }
431                                 }
432                         }
433                         else
434                                 return false; // unsupported number of channels in sound
435                 }
436         }
437         return true;
438 }
439
440 void S_MixToBuffer(void *stream, unsigned int bufferframes)
441 {
442         unsigned int i;
443         channel_t *ch;
444         unsigned int frames;
445         unsigned char *outbytes = (unsigned char *) stream;
446
447         // mix as many times as needed to fill the requested buffer
448         while (bufferframes)
449         {
450                 // limit to the size of the paint buffer
451                 frames = min(bufferframes, PAINTBUFFER_SIZE);
452
453                 // clear the paint buffer
454                 memset (paintbuffer, 0, frames * sizeof (paintbuffer[0]));
455
456                 // paint in the channels.
457                 // channels with zero volumes still advance in time but don't paint.
458                 ch = channels;
459                 for (i = 0; i < total_channels ; i++, ch++)
460                 {
461                         sfx_t *sfx;
462                         unsigned int ltime;
463                         unsigned int count;
464
465                         sfx = ch->sfx;
466                         if (sfx == NULL)
467                                 continue;
468                         if (!S_LoadSound (sfx, true))
469                                 continue;
470                         if (ch->flags & CHANNELFLAG_PAUSED)
471                                 continue;
472
473                         ltime = 0;
474                         if (ch->pos < 0)
475                         {
476                                 count = -ch->pos;
477                                 count = min(count, frames - ltime);
478                                 ch->pos += count;
479                                 ltime += count;
480                         }
481
482                         while (ltime < frames)
483                         {
484                                 // paint up to end of buffer or of input, whichever is lower
485                                 count = sfx->total_length - ch->pos;
486                                 count = bound(0, count, frames - ltime);
487                                 if (count)
488                                 {
489                                         SND_PaintChannel (ch, paintbuffer + ltime, count);
490                                         ch->pos += count;
491                                         ltime += count;
492                                 }
493
494                                 // if at end of sfx, loop or stop the channel
495                                 if (ch->pos >= (int)sfx->total_length)
496                                 {
497                                         if (sfx->loopstart < sfx->total_length)
498                                                 ch->pos = sfx->loopstart;
499                                         else if (ch->flags & CHANNELFLAG_FORCELOOP)
500                                                 ch->pos = 0;
501                                         else
502                                         {
503                                                 S_StopChannel (ch - channels, false);
504                                                 break;
505                                         }
506                                 }
507                         }
508                 }
509
510                 if (!snd_usethreadedmixing)
511                         S_CaptureAVISound(frames);
512
513                 S_ConvertPaintBuffer(paintbuffer, outbytes, frames, snd_renderbuffer->format.width, snd_renderbuffer->format.channels);
514
515                 // advance the output pointer
516                 outbytes += frames * snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
517                 bufferframes -= frames;
518         }
519 }