2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // snd_mix.c -- portable code to mix sounds for snd_dma.c
27 #define DWORD unsigned long
30 #define PAINTBUFFER_SIZE 512
31 portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
32 int snd_scaletable[32][256];
33 int *snd_p, snd_linear_count, snd_vol;
36 void Snd_WriteLinearBlastStereo16 (void);
38 extern cvar_t snd_swapstereo;
40 void Snd_WriteLinearBlastStereo16 (void)
45 if (snd_swapstereo.value)
47 for (i=0 ; i<snd_linear_count ; i+=2)
49 val = (snd_p[i+1]*snd_vol)>>8;
52 else if (val < (short)0x8000)
53 snd_out[i] = (short)0x8000;
57 val = (snd_p[i]*snd_vol)>>8;
59 snd_out[i+1] = 0x7fff;
60 else if (val < (short)0x8000)
61 snd_out[i+1] = (short)0x8000;
68 for (i=0 ; i<snd_linear_count ; i+=2)
70 val = (snd_p[i]*snd_vol)>>8;
73 else if (val < (short)0x8000)
74 snd_out[i] = (short)0x8000;
78 val = (snd_p[i+1]*snd_vol)>>8;
80 snd_out[i+1] = 0x7fff;
81 else if (val < (short)0x8000)
82 snd_out[i+1] = (short)0x8000;
90 void S_TransferStereo16 (int endtime)
102 snd_vol = volume.value*256;
104 snd_p = (int *) paintbuffer;
105 lpaintedtime = paintedtime;
112 while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize,
113 &pbuf2, &dwSize2, 0)) != DS_OK)
115 if (hresult != DSERR_BUFFERLOST)
117 Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n");
125 Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n");
135 pbuf = (DWORD *)shm->buffer;
138 while (lpaintedtime < endtime)
140 // handle recirculating buffer issues
141 lpos = lpaintedtime & ((shm->samples>>1)-1);
143 snd_out = (short *) pbuf + (lpos<<1);
145 snd_linear_count = (shm->samples>>1) - lpos;
146 if (lpaintedtime + snd_linear_count > endtime)
147 snd_linear_count = endtime - lpaintedtime;
149 snd_linear_count <<= 1;
151 // write a linear blast of samples
152 Snd_WriteLinearBlastStereo16 ();
154 snd_p += snd_linear_count;
155 lpaintedtime += (snd_linear_count>>1);
160 pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
164 void S_TransferPaintBuffer(int endtime)
176 DWORD dwSize,dwSize2;
181 if (shm->samplebits == 16 && shm->channels == 2)
183 S_TransferStereo16 (endtime);
187 p = (int *) paintbuffer;
188 count = (endtime - paintedtime) * shm->channels;
189 out_mask = shm->samples - 1;
190 out_idx = paintedtime * shm->channels & out_mask;
191 step = 3 - shm->channels;
192 snd_vol = volume.value*256;
199 while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize,
200 &pbuf2,&dwSize2, 0)) != DS_OK)
202 if (hresult != DSERR_BUFFERLOST)
204 Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n");
212 Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n");
222 pbuf = (DWORD *)shm->buffer;
225 if (shm->samplebits == 16)
227 short *out = (short *) pbuf;
230 val = (*p * snd_vol) >> 8;
234 else if (val < (short)0x8000)
237 out_idx = (out_idx + 1) & out_mask;
240 else if (shm->samplebits == 8)
242 unsigned char *out = (unsigned char *) pbuf;
245 val = (*p * snd_vol) >> 8;
249 else if (val < (short)0x8000)
251 out[out_idx] = (val>>8) + 128;
252 out_idx = (out_idx + 1) & out_mask;
258 DWORD dwNewpos, dwWrite;
259 int il = paintedtime;
260 int ir = endtime - paintedtime;
264 pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
266 pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite);
268 // if ((dwNewpos >= il) && (dwNewpos <= ir))
269 // Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos);
276 ===============================================================================
280 ===============================================================================
283 void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
284 void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
286 void S_PaintChannels(int endtime)
294 while (paintedtime < endtime)
296 // if paintbuffer is smaller than DMA buffer
298 if (endtime - paintedtime > PAINTBUFFER_SIZE)
299 end = paintedtime + PAINTBUFFER_SIZE;
301 // clear the paint buffer
302 memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t));
304 // paint in the channels.
306 for (i=0; i<total_channels ; i++, ch++)
310 if (!ch->leftvol && !ch->rightvol)
312 sc = S_LoadSound (ch->sfx);
321 count = ch->end - ltime;
328 SND_PaintChannelFrom8(ch, sc, count);
330 SND_PaintChannelFrom16(ch, sc, count);
335 // if at end of loop, restart
336 if (ltime >= ch->end)
338 if (sc->loopstart >= 0)
340 ch->pos = sc->loopstart;
341 ch->end = ltime + sc->length - ch->pos;
344 { // channel just stopped
353 // transfer out according to DMA format
354 S_TransferPaintBuffer(end);
359 void SND_InitScaletable (void)
363 for (i=0 ; i<32 ; i++)
364 for (j=0 ; j<256 ; j++)
365 snd_scaletable[i][j] = ((signed char)j) * i * 8;
371 void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
374 int *lscale, *rscale;
378 if (ch->leftvol > 255)
380 if (ch->rightvol > 255)
383 lscale = snd_scaletable[ch->leftvol >> 3];
384 rscale = snd_scaletable[ch->rightvol >> 3];
385 if (sc->stereo) // LordHavoc: stereo sound support, and optimizations
387 sfx = (unsigned char *)sc->data + ch->pos * 2;
389 for (i=0 ; i<count ; i++)
391 paintbuffer[i].left += lscale[*sfx++];
392 paintbuffer[i].right += rscale[*sfx++];
398 sfx = (unsigned char *)sc->data + ch->pos;
400 for (i=0 ; i<count ; i++)
402 paintbuffer[i].left += lscale[*sfx];
403 paintbuffer[i].right += rscale[*sfx++];
413 void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
417 int leftvol, rightvol;
421 leftvol = ch->leftvol;
422 rightvol = ch->rightvol;
423 if (sc->stereo) // LordHavoc: stereo sound support, and optimizations
425 sfx = (signed short *)sc->data + ch->pos * 2;
427 for (i=0 ; i<count ; i++)
429 paintbuffer[i].left += (short) ((int) (*sfx++ * leftvol) >> 8);
430 paintbuffer[i].right += (short) ((int) (*sfx++ * rightvol) >> 8);
435 sfx = (signed short *)sc->data + ch->pos;
437 for (i=0 ; i<count ; i++)
439 paintbuffer[i].left += (short) ((int) (*sfx * leftvol) >> 8);
440 paintbuffer[i].right += (short) ((int) (*sfx++ * rightvol) >> 8);