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 // LordHavoc: was 512, expanded to 2048
31 #define PAINTBUFFER_SIZE 2048
32 portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
33 int snd_scaletable[32][256];
34 int *snd_p, snd_linear_count, snd_vol;
38 // LordHavoc: disabled this because it desyncs with the video too easily
39 extern cvar_t cl_avidemo;
40 static FILE *cl_avidemo_soundfile = NULL;
41 void S_CaptureAVISound(portable_samplepair_t *buf, int length)
44 qbyte out[PAINTBUFFER_SIZE * 4];
45 char filename[MAX_OSPATH];
47 if (cl_avidemo.value >= 0.1f)
49 if (cl_avidemo_soundfile == NULL)
51 sprintf (filename, "%s/dpavi.wav", com_gamedir);
52 cl_avidemo_soundfile = fopen(filename, "wb");
54 fwrite(out, 1, 44, cl_avidemo_soundfile);
55 // header will be filled out when file is closed
57 fseek(cl_avidemo_soundfile, 0, SEEK_END);
58 // write the sound buffer as little endian 16bit interleaved stereo
59 for(i = 0;i < length;i++)
61 n = buf[i].left >> 2; // quiet enough to prevent clipping most of the time
62 n = bound(-32768, n, 32767);
63 out[i*4+0] = n & 0xFF;
64 out[i*4+1] = (n >> 8) & 0xFF;
65 n = buf[i].right >> 2; // quiet enough to prevent clipping most of the time
66 n = bound(-32768, n, 32767);
67 out[i*4+2] = n & 0xFF;
68 out[i*4+3] = (n >> 8) & 0xFF;
70 if (fwrite(out, 4, length, cl_avidemo_soundfile) < length)
72 Cvar_SetValueQuick(&cl_avidemo, 0);
73 Con_Printf("avi saving sound failed, out of disk space? stopping avi demo capture.\n");
76 else if (cl_avidemo_soundfile)
78 // file has not been closed yet, close it
79 fseek(cl_avidemo_soundfile, 0, SEEK_END);
80 i = ftell(cl_avidemo_soundfile);
82 //"RIFF", (int) unknown (chunk size), "WAVE",
83 //"fmt ", (int) 16 (chunk size), (short) format 1 (uncompressed PCM), (short) 2 channels, (int) unknown rate, (int) unknown bytes per second, (short) 4 bytes per sample (channels * bytes per channel), (short) 16 bits per channel
84 //"data", (int) unknown (chunk size)
85 memcpy(out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\x00data****", 44);
86 // the length of the whole RIFF chunk
89 out[5] = (n >> 8) & 0xFF;
90 out[6] = (n >> 16) & 0xFF;
91 out[7] = (n >> 24) & 0xFF;
95 out[25] = (n >> 8) & 0xFF;
96 out[26] = (n >> 16) & 0xFF;
97 out[27] = (n >> 24) & 0xFF;
98 // bytes per second (rate * channels * bytes per channel)
100 out[28] = (n) & 0xFF;
101 out[29] = (n >> 8) & 0xFF;
102 out[30] = (n >> 16) & 0xFF;
103 out[31] = (n >> 24) & 0xFF;
104 // the length of the data chunk
106 out[40] = (n) & 0xFF;
107 out[41] = (n >> 8) & 0xFF;
108 out[42] = (n >> 16) & 0xFF;
109 out[43] = (n >> 24) & 0xFF;
111 fseek(cl_avidemo_soundfile, 0, SEEK_SET);
112 fwrite(out, 1, 44, cl_avidemo_soundfile);
113 fclose(cl_avidemo_soundfile);
114 cl_avidemo_soundfile = NULL;
119 void Snd_WriteLinearBlastStereo16 (void)
124 if (snd_swapstereo.value)
126 for (i=0 ; i<snd_linear_count ; i+=2)
128 val = (snd_p[i+1]*snd_vol)>>8;
129 snd_out[i ] = bound(-32768, val, 32767);
130 val = (snd_p[i ]*snd_vol)>>8;
131 snd_out[i+1] = bound(-32768, val, 32767);
136 for (i=0 ; i<snd_linear_count ; i+=2)
138 val = (snd_p[i]*snd_vol)>>8;
139 snd_out[i] = bound(-32768, val, 32767);
140 val = (snd_p[i+1]*snd_vol)>>8;
141 snd_out[i+1] = bound(-32768, val, 32767);
146 void S_TransferStereo16 (int endtime)
153 DWORD dwSize,dwSize2;
158 snd_vol = volume.value*256;
160 snd_p = (int *) paintbuffer;
161 lpaintedtime = paintedtime;
168 while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, &pbuf2, &dwSize2, 0)) != DS_OK)
170 if (hresult != DSERR_BUFFERLOST)
172 Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n");
180 Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n");
190 pbuf = (DWORD *)shm->buffer;
193 while (lpaintedtime < endtime)
195 // handle recirculating buffer issues
196 lpos = lpaintedtime & ((shm->samples>>1)-1);
198 snd_out = (short *) pbuf + (lpos<<1);
200 snd_linear_count = (shm->samples>>1) - lpos;
201 if (lpaintedtime + snd_linear_count > endtime)
202 snd_linear_count = endtime - lpaintedtime;
204 snd_linear_count <<= 1;
206 // write a linear blast of samples
207 Snd_WriteLinearBlastStereo16 ();
209 snd_p += snd_linear_count;
210 lpaintedtime += (snd_linear_count>>1);
215 pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
219 void S_TransferPaintBuffer(int endtime)
231 DWORD dwSize,dwSize2;
236 if (shm->samplebits == 16 && shm->channels == 2)
238 S_TransferStereo16 (endtime);
242 p = (int *) paintbuffer;
243 count = (endtime - paintedtime) * shm->channels;
244 out_mask = shm->samples - 1;
245 out_idx = paintedtime * shm->channels & out_mask;
246 step = 3 - shm->channels;
247 snd_vol = volume.value*256;
254 while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, &pbuf2,&dwSize2, 0)) != DS_OK)
256 if (hresult != DSERR_BUFFERLOST)
258 Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n");
266 Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n");
276 pbuf = (DWORD *)shm->buffer;
279 if (shm->samplebits == 16)
281 short *out = (short *) pbuf;
284 val = (*p * snd_vol) >> 8;
285 out[out_idx] = bound(-32768, val, 32767);
287 out_idx = (out_idx + 1) & out_mask;
290 else if (shm->samplebits == 8)
292 unsigned char *out = (unsigned char *) pbuf;
295 val = ((*p * snd_vol) >> 16) + 128;
296 out[out_idx] = bound(0, val, 255);
298 out_idx = (out_idx + 1) & out_mask;
305 DWORD dwNewpos, dwWrite;
306 int il = paintedtime;
307 int ir = endtime - paintedtime;
311 pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
313 pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite);
315 // if ((dwNewpos >= il) && (dwNewpos <= ir))
316 // Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos);
323 ===============================================================================
327 ===============================================================================
330 void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
331 void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
333 void S_PaintChannels(int endtime)
341 while (paintedtime < endtime)
343 // if paintbuffer is smaller than DMA buffer
345 if (endtime - paintedtime > PAINTBUFFER_SIZE)
346 end = paintedtime + PAINTBUFFER_SIZE;
348 // clear the paint buffer
349 memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t));
351 // paint in the channels.
353 for (i=0; i<total_channels ; i++, ch++)
357 if (!ch->leftvol && !ch->rightvol)
359 sc = S_LoadSound (ch->sfx);
369 count = ch->end - ltime;
376 SND_PaintChannelFrom8(ch, sc, count);
378 SND_PaintChannelFrom16(ch, sc, count);
383 // if at end of loop, restart
384 if (ltime >= ch->end)
386 if (sc->loopstart >= 0)
388 ch->pos = sc->loopstart;
389 ch->end = ltime + sc->length - ch->pos;
393 // channel just stopped
402 // transfer out according to DMA format
403 //S_CaptureAVISound(paintbuffer, end - paintedtime);
404 S_TransferPaintBuffer(end);
409 void SND_InitScaletable (void)
413 for (i=0 ; i<32 ; i++)
414 for (j=0 ; j<256 ; j++)
415 snd_scaletable[i][j] = ((signed char)j) * i * 8;
419 void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
422 int *lscale, *rscale;
426 if (ch->leftvol > 255)
428 if (ch->rightvol > 255)
431 lscale = snd_scaletable[ch->leftvol >> 3];
432 rscale = snd_scaletable[ch->rightvol >> 3];
435 // LordHavoc: stereo sound support, and optimizations
436 sfx = (unsigned char *)sc->data + ch->pos * 2;
438 for (i=0 ; i<count ; i++)
440 paintbuffer[i].left += lscale[*sfx++];
441 paintbuffer[i].right += rscale[*sfx++];
447 sfx = (unsigned char *)sc->data + ch->pos;
449 for (i=0 ; i<count ; i++)
451 paintbuffer[i].left += lscale[*sfx];
452 paintbuffer[i].right += rscale[*sfx++];
459 void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
463 int leftvol, rightvol;
467 leftvol = ch->leftvol;
468 rightvol = ch->rightvol;
471 // LordHavoc: stereo sound support, and optimizations
472 sfx = (signed short *)sc->data + ch->pos * 2;
474 for (i=0 ; i<count ; i++)
476 paintbuffer[i].left += (*sfx++ * leftvol) >> 8;
477 paintbuffer[i].right += (*sfx++ * rightvol) >> 8;
482 sfx = (signed short *)sc->data + ch->pos;
484 for (i=0 ; i<count ; i++)
486 paintbuffer[i].left += (*sfx * leftvol) >> 8;
487 paintbuffer[i].right += (*sfx++ * rightvol) >> 8;