]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - snd_mix.c
don't hexdump png images while reading them (why did it do this??)
[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 // snd_mix.c -- portable code to mix sounds
21
22 #include "quakedef.h"
23 #include "snd_main.h"
24
25 typedef struct portable_samplepair_s
26 {
27         int sample[SND_LISTENERS];
28 } portable_sampleframe_t;
29
30 // LordHavoc: was 512, expanded to 2048
31 #define PAINTBUFFER_SIZE 2048
32 portable_sampleframe_t paintbuffer[PAINTBUFFER_SIZE];
33
34 // FIXME: this desyncs with the video too easily
35 extern void SCR_CaptureVideo_SoundFrame(unsigned char *bufstereo16le, size_t length, int rate);
36 void S_CaptureAVISound(portable_sampleframe_t *buf, size_t length)
37 {
38         int n;
39         size_t i;
40         unsigned char out[PAINTBUFFER_SIZE * 4];
41         if (!cls.capturevideo_active)
42                 return;
43         // write the sound buffer as little endian 16bit interleaved stereo
44         for(i = 0;i < length;i++)
45         {
46                 n = buf[i].sample[0];
47                 n = bound(-32768, n, 32767);
48                 out[i*4+0] = n & 0xFF;
49                 out[i*4+1] = (n >> 8) & 0xFF;
50                 n = buf[i].sample[1];
51                 n = bound(-32768, n, 32767);
52                 out[i*4+2] = n & 0xFF;
53                 out[i*4+3] = (n >> 8) & 0xFF;
54         }
55         SCR_CaptureVideo_SoundFrame(out, length, shm->format.speed);
56 }
57
58 // TODO: rewrite this function
59 void S_TransferPaintBuffer(int endtime)
60 {
61         void *pbuf;
62         int i;
63         portable_sampleframe_t *snd_p;
64         int lpaintedtime;
65         int snd_frames;
66         int val;
67         if ((pbuf = S_LockBuffer()))
68         {
69                 snd_p = paintbuffer;
70                 lpaintedtime = paintedtime;
71                 for (lpaintedtime = paintedtime;lpaintedtime < endtime;lpaintedtime += snd_frames)
72                 {
73                         // handle recirculating buffer issues
74                         i = lpaintedtime & (shm->sampleframes - 1);
75                         snd_frames = shm->sampleframes - i;
76                         if (snd_frames > endtime - lpaintedtime)
77                                 snd_frames = endtime - lpaintedtime;
78                         if (shm->format.width == 2)
79                         {
80                                 // 16bit
81                                 short *snd_out = (short *) pbuf + i * shm->format.channels;
82                                 if (shm->format.channels == 8)
83                                 {
84                                         // 7.1 surround
85                                         if (snd_swapstereo.value)
86                                         {
87                                                 for (i = 0;i < snd_frames;i++, snd_p++)
88                                                 {
89                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
90                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
91                                                         *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
92                                                         *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
93                                                         *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
94                                                         *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
95                                                         *snd_out++ = bound(-32768, snd_p->sample[6], 32767);
96                                                         *snd_out++ = bound(-32768, snd_p->sample[7], 32767);
97                                                 }
98                                         }
99                                         else
100                                         {
101                                                 for (i = 0;i < snd_frames;i++, snd_p++)
102                                                 {
103                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
104                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
105                                                         *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
106                                                         *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
107                                                         *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
108                                                         *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
109                                                         *snd_out++ = bound(-32768, snd_p->sample[6], 32767);
110                                                         *snd_out++ = bound(-32768, snd_p->sample[7], 32767);
111                                                 }
112                                         }
113                                 }
114                                 else if (shm->format.channels == 6)
115                                 {
116                                         // 5.1 surround
117                                         if (snd_swapstereo.value)
118                                         {
119                                                 for (i = 0;i < snd_frames;i++, snd_p++)
120                                                 {
121                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
122                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
123                                                         *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
124                                                         *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
125                                                         *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
126                                                         *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
127                                                 }
128                                         }
129                                         else
130                                         {
131                                                 for (i = 0;i < snd_frames;i++, snd_p++)
132                                                 {
133                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
134                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
135                                                         *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
136                                                         *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
137                                                         *snd_out++ = bound(-32768, snd_p->sample[4], 32767);
138                                                         *snd_out++ = bound(-32768, snd_p->sample[5], 32767);
139                                                 }
140                                         }
141                                 }
142                                 else if (shm->format.channels == 4)
143                                 {
144                                         // 4.0 surround
145                                         if (snd_swapstereo.value)
146                                         {
147                                                 for (i = 0;i < snd_frames;i++, snd_p++)
148                                                 {
149                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
150                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
151                                                         *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
152                                                         *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
153                                                 }
154                                         }
155                                         else
156                                         {
157                                                 for (i = 0;i < snd_frames;i++, snd_p++)
158                                                 {
159                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
160                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
161                                                         *snd_out++ = bound(-32768, snd_p->sample[2], 32767);
162                                                         *snd_out++ = bound(-32768, snd_p->sample[3], 32767);
163                                                 }
164                                         }
165                                 }
166                                 else if (shm->format.channels == 2)
167                                 {
168                                         // 2.0 stereo
169                                         if (snd_swapstereo.value)
170                                         {
171                                                 for (i = 0;i < snd_frames;i++, snd_p++)
172                                                 {
173                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
174                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
175                                                 }
176                                         }
177                                         else
178                                         {
179                                                 for (i = 0;i < snd_frames;i++, snd_p++)
180                                                 {
181                                                         *snd_out++ = bound(-32768, snd_p->sample[0], 32767);
182                                                         *snd_out++ = bound(-32768, snd_p->sample[1], 32767);
183                                                 }
184                                         }
185                                 }
186                                 else if (shm->format.channels == 1)
187                                 {
188                                         // 1.0 mono
189                                         for (i = 0;i < snd_frames;i++, snd_p++)
190                                                 *snd_out++ = bound(-32768, (snd_p->sample[0] + snd_p->sample[1]) >> 1, 32767);
191                                 }
192                         }
193                         else
194                         {
195                                 // 8bit
196                                 unsigned char *snd_out = (unsigned char *) pbuf + i * shm->format.channels;
197                                 if (shm->format.channels == 8)
198                                 {
199                                         // 7.1 surround
200                                         if (snd_swapstereo.value)
201                                         {
202                                                 for (i = 0;i < snd_frames;i++, snd_p++)
203                                                 {
204                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
205                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
206                                                         val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
207                                                         val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
208                                                         val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
209                                                         val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
210                                                         val = (snd_p->sample[6] >> 8) + 128;*snd_out++ = bound(0, val, 255);
211                                                         val = (snd_p->sample[7] >> 8) + 128;*snd_out++ = bound(0, val, 255);
212                                                 }
213                                         }
214                                         else
215                                         {
216                                                 for (i = 0;i < snd_frames;i++, snd_p++)
217                                                 {
218                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
219                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
220                                                         val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
221                                                         val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
222                                                         val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
223                                                         val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
224                                                         val = (snd_p->sample[6] >> 8) + 128;*snd_out++ = bound(0, val, 255);
225                                                         val = (snd_p->sample[7] >> 8) + 128;*snd_out++ = bound(0, val, 255);
226                                                 }
227                                         }
228                                 }
229                                 else if (shm->format.channels == 6)
230                                 {
231                                         // 5.1 surround
232                                         if (snd_swapstereo.value)
233                                         {
234                                                 for (i = 0;i < snd_frames;i++, snd_p++)
235                                                 {
236                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
237                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
238                                                         val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
239                                                         val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
240                                                         val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
241                                                         val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
242                                                 }
243                                         }
244                                         else
245                                         {
246                                                 for (i = 0;i < snd_frames;i++, snd_p++)
247                                                 {
248                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
249                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
250                                                         val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
251                                                         val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
252                                                         val = (snd_p->sample[4] >> 8) + 128;*snd_out++ = bound(0, val, 255);
253                                                         val = (snd_p->sample[5] >> 8) + 128;*snd_out++ = bound(0, val, 255);
254                                                 }
255                                         }
256                                 }
257                                 else if (shm->format.channels == 4)
258                                 {
259                                         // 4.0 surround
260                                         if (snd_swapstereo.value)
261                                         {
262                                                 for (i = 0;i < snd_frames;i++, snd_p++)
263                                                 {
264                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
265                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
266                                                         val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
267                                                         val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
268                                                 }
269                                         }
270                                         else
271                                         {
272                                                 for (i = 0;i < snd_frames;i++, snd_p++)
273                                                 {
274                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
275                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
276                                                         val = (snd_p->sample[2] >> 8) + 128;*snd_out++ = bound(0, val, 255);
277                                                         val = (snd_p->sample[3] >> 8) + 128;*snd_out++ = bound(0, val, 255);
278                                                 }
279                                         }
280                                 }
281                                 else if (shm->format.channels == 2)
282                                 {
283                                         // 2.0 stereo
284                                         if (snd_swapstereo.value)
285                                         {
286                                                 for (i = 0;i < snd_frames;i++, snd_p++)
287                                                 {
288                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
289                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
290                                                 }
291                                         }
292                                         else
293                                         {
294                                                 for (i = 0;i < snd_frames;i++, snd_p++)
295                                                 {
296                                                         val = (snd_p->sample[0] >> 8) + 128;*snd_out++ = bound(0, val, 255);
297                                                         val = (snd_p->sample[1] >> 8) + 128;*snd_out++ = bound(0, val, 255);
298                                                 }
299                                         }
300                                 }
301                                 else if (shm->format.channels == 1)
302                                 {
303                                         // 1.0 mono
304                                         for (i = 0;i < snd_frames;i++, snd_p++)
305                                         {
306                                                 val = ((snd_p->sample[0]+snd_p->sample[1]) >> 9) + 128;*snd_out++ = bound(0, val, 255);
307                                         }
308                                 }
309                         }
310                 }
311                 S_UnlockBuffer();
312         }
313 }
314
315
316 /*
317 ===============================================================================
318
319 CHANNEL MIXING
320
321 ===============================================================================
322 */
323
324 qboolean SND_PaintChannel (channel_t *ch, int endtime);
325
326 void S_PaintChannels(int endtime)
327 {
328         unsigned int i, j;
329         int end;
330         channel_t *ch;
331         sfx_t *sfx;
332         int ltime, count;
333
334         while (paintedtime < endtime)
335         {
336                 // if paintbuffer is smaller than DMA buffer
337                 end = endtime;
338                 if (endtime - paintedtime > PAINTBUFFER_SIZE)
339                         end = paintedtime + PAINTBUFFER_SIZE;
340
341                 // clear the paint buffer
342                 memset (&paintbuffer, 0, (end - paintedtime) * sizeof (paintbuffer[0]));
343
344                 // paint in the channels.
345                 ch = channels;
346                 for (i=0; i<total_channels ; i++, ch++)
347                 {
348                         sfx = ch->sfx;
349                         if (!sfx)
350                                 continue;
351                         for (j = 0;j < SND_LISTENERS;j++)
352                                 if (ch->listener_volume[j])
353                                         break;
354                         if (j == SND_LISTENERS)
355                                 continue;
356                         if (!S_LoadSound (sfx, true))
357                                 continue;
358
359                         // if the channel is paused
360                         if (ch->flags & CHANNELFLAG_PAUSED)
361                         {
362                                 int pausedtime = end - paintedtime;
363                                 ch->lastptime += pausedtime;
364                                 ch->end += pausedtime;
365                                 continue;
366                         }
367
368                         // if the sound hasn't been painted last time, update his position
369                         if (ch->lastptime < paintedtime)
370                         {
371                                 ch->pos += paintedtime - ch->lastptime;
372
373                                 // If the sound should have ended by then
374                                 if ((unsigned int)ch->pos > sfx->total_length)
375                                 {
376                                         int loopstart;
377
378                                         if (ch->flags & CHANNELFLAG_FORCELOOP)
379                                                 loopstart = 0;
380                                         else
381                                                 loopstart = -1;
382                                         if (sfx->loopstart >= 0)
383                                                 loopstart = sfx->loopstart;
384
385                                         // If the sound is looped
386                                         if (loopstart >= 0)
387                                                 ch->pos = (ch->pos - sfx->total_length) % (sfx->total_length - loopstart) + loopstart;
388                                         else
389                                                 ch->pos = sfx->total_length;
390                                         ch->end = paintedtime + sfx->total_length - ch->pos;
391                                 }
392                         }
393
394                         ltime = paintedtime;
395                         while (ltime < end)
396                         {
397                                 qboolean stop_paint;
398
399                                 // paint up to end
400                                 if (ch->end < end)
401                                         count = (int)ch->end - ltime;
402                                 else
403                                         count = end - ltime;
404
405                                 if (count > 0)
406                                 {
407                                         for (j = 0;j < SND_LISTENERS;j++)
408                                                 ch->listener_volume[j] = bound(0, ch->listener_volume[j], 255);
409
410                                         stop_paint = !SND_PaintChannel (ch, count);
411
412                                         if (!stop_paint)
413                                         {
414                                                 ltime += count;
415                                                 ch->lastptime = ltime;
416                                         }
417                                 }
418                                 else
419                                         stop_paint = false;
420
421                                 if (ltime >= ch->end)
422                                 {
423                                         // if at end of loop, restart
424                                         if ((sfx->loopstart >= 0 || (ch->flags & CHANNELFLAG_FORCELOOP)) && !stop_paint)
425                                         {
426                                                 ch->pos = bound(0, sfx->loopstart, (int)sfx->total_length - 1);
427                                                 ch->end = ltime + sfx->total_length - ch->pos;
428                                         }
429                                         // channel just stopped
430                                         else
431                                                 stop_paint = true;
432                                 }
433
434                                 if (stop_paint)
435                                 {
436                                         S_StopChannel (ch - channels);
437                                         break;
438                                 }
439                         }
440                 }
441
442                 // transfer out according to DMA format
443                 S_CaptureAVISound (paintbuffer, end - paintedtime);
444                 S_TransferPaintBuffer(end);
445                 paintedtime = end;
446         }
447 }
448
449
450 qboolean SND_PaintChannel (channel_t *ch, int count)
451 {
452         int snd_vol, vol[SND_LISTENERS];
453         const sfxbuffer_t *sb;
454         int i;
455
456         // If this channel manages its own volume
457         if (ch->flags & CHANNELFLAG_FULLVOLUME)
458                 snd_vol = 256;
459         else
460                 snd_vol = (int)(volume.value * 256);
461
462         for (i = 0;i < SND_LISTENERS;i++)
463                 vol[i] = ch->listener_volume[i] * snd_vol;
464
465         sb = ch->sfx->fetcher->getsb (ch, ch->pos, count);
466         if (sb == NULL)
467                 return false;
468
469 #if SND_LISTENERS != 8
470 #error this code only supports up to 8 channels, update it
471 #endif
472
473         if (ch->sfx->format.width == 1)
474         {
475                 const signed char *sfx = (signed char *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
476                 // Stereo sound support
477                 if (ch->sfx->format.channels == 2)
478                 {
479                         if (vol[6] + vol[7] > 0)
480                         {
481                                 for (i = 0;i < count;i++)
482                                 {
483                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
484                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
485                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
486                                         paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
487                                         paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
488                                         paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
489                                         paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
490                                         paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 8;
491                                         sfx += 2;
492                                 }
493                         }
494                         else if (vol[4] + vol[5] > 0)
495                         {
496                                 for (i = 0;i < count;i++)
497                                 {
498                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
499                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
500                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
501                                         paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
502                                         paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 9;
503                                         paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 9;
504                                         sfx += 2;
505                                 }
506                         }
507                         else if (vol[2] + vol[3] > 0)
508                         {
509                                 for (i = 0;i < count;i++)
510                                 {
511                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
512                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
513                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
514                                         paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 8;
515                                         sfx += 2;
516                                 }
517                         }
518                         else if (vol[0] + vol[1] > 0)
519                         {
520                                 for (i = 0;i < count;i++)
521                                 {
522                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
523                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 8;
524                                         sfx += 2;
525                                 }
526                         }
527                 }
528                 else if (ch->sfx->format.channels == 1)
529                 {
530                         if (vol[6] + vol[7] > 0)
531                         {
532                                 for (i = 0;i < count;i++)
533                                 {
534                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
535                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
536                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
537                                         paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
538                                         paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
539                                         paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
540                                         paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 8;
541                                         paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 8;
542                                         sfx += 1;
543                                 }
544                         }
545                         else if (vol[4] + vol[5] > 0)
546                         {
547                                 for (i = 0;i < count;i++)
548                                 {
549                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
550                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
551                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
552                                         paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
553                                         paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 8;
554                                         paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 8;
555                                         sfx += 1;
556                                 }
557                         }
558                         else if (vol[2] + vol[3] > 0)
559                         {
560                                 for (i = 0;i < count;i++)
561                                 {
562                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
563                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
564                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 8;
565                                         paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 8;
566                                         sfx += 1;
567                                 }
568                         }
569                         else if (vol[0] + vol[1] > 0)
570                         {
571                                 for (i = 0;i < count;i++)
572                                 {
573                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 8;
574                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 8;
575                                         sfx += 1;
576                                 }
577                         }
578                 }
579                 else
580                         return true; // unsupported number of channels in sound
581         }
582         else if (ch->sfx->format.width == 2)
583         {
584                 const signed short *sfx = (signed short *)sb->data + (ch->pos - sb->offset) * ch->sfx->format.channels;
585                 // Stereo sound support
586                 if (ch->sfx->format.channels == 2)
587                 {
588                         if (vol[6] + vol[7] > 0)
589                         {
590                                 for (i = 0;i < count;i++)
591                                 {
592                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
593                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
594                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
595                                         paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
596                                         paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
597                                         paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
598                                         paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
599                                         paintbuffer[i].sample[7] += (sfx[1] * vol[7]) >> 16;
600                                         sfx += 2;
601                                 }
602                         }
603                         else if (vol[4] + vol[5] > 0)
604                         {
605                                 for (i = 0;i < count;i++)
606                                 {
607                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
608                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
609                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
610                                         paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
611                                         paintbuffer[i].sample[4] += ((sfx[0]+sfx[1]) * vol[4]) >> 17;
612                                         paintbuffer[i].sample[5] += ((sfx[0]+sfx[1]) * vol[5]) >> 17;
613                                         sfx += 2;
614                                 }
615                         }
616                         else if (vol[2] + vol[3] > 0)
617                         {
618                                 for (i = 0;i < count;i++)
619                                 {
620                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
621                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
622                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
623                                         paintbuffer[i].sample[3] += (sfx[1] * vol[3]) >> 16;
624                                         sfx += 2;
625                                 }
626                         }
627                         else if (vol[0] + vol[1] > 0)
628                         {
629                                 for (i = 0;i < count;i++)
630                                 {
631                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
632                                         paintbuffer[i].sample[1] += (sfx[1] * vol[1]) >> 16;
633                                         sfx += 2;
634                                 }
635                         }
636                 }
637                 else if (ch->sfx->format.channels == 1)
638                 {
639                         if (vol[6] + vol[7] > 0)
640                         {
641                                 for (i = 0;i < count;i++)
642                                 {
643                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
644                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
645                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
646                                         paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
647                                         paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
648                                         paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
649                                         paintbuffer[i].sample[6] += (sfx[0] * vol[6]) >> 16;
650                                         paintbuffer[i].sample[7] += (sfx[0] * vol[7]) >> 16;
651                                         sfx += 1;
652                                 }
653                         }
654                         else if (vol[4] + vol[5] > 0)
655                         {
656                                 for (i = 0;i < count;i++)
657                                 {
658                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
659                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
660                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
661                                         paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
662                                         paintbuffer[i].sample[4] += (sfx[0] * vol[4]) >> 16;
663                                         paintbuffer[i].sample[5] += (sfx[0] * vol[5]) >> 16;
664                                         sfx += 1;
665                                 }
666                         }
667                         else if (vol[2] + vol[3] > 0)
668                         {
669                                 for (i = 0;i < count;i++)
670                                 {
671                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
672                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
673                                         paintbuffer[i].sample[2] += (sfx[0] * vol[2]) >> 16;
674                                         paintbuffer[i].sample[3] += (sfx[0] * vol[3]) >> 16;
675                                         sfx += 1;
676                                 }
677                         }
678                         else if (vol[0] + vol[1] > 0)
679                         {
680                                 for (i = 0;i < count;i++)
681                                 {
682                                         paintbuffer[i].sample[0] += (sfx[0] * vol[0]) >> 16;
683                                         paintbuffer[i].sample[1] += (sfx[0] * vol[1]) >> 16;
684                                         sfx += 1;
685                                 }
686                         }
687                 }
688                 else
689                         return true; // unsupported number of channels in sound
690         }
691         ch->pos += count;
692         return true;
693 }
694