|
|
1.1 root 1: // snd_mix.c -- portable code to mix sounds for snd_dma.c
2:
3: #include "client.h"
4: #include "snd_loc.h"
5:
6: #define PAINTBUFFER_SIZE 2048
7: portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
8: int snd_scaletable[32][256];
9: int *snd_p, snd_linear_count, snd_vol;
10: short *snd_out;
11:
12: void S_WriteLinearBlastStereo16 (void);
13:
1.1.1.2 ! root 14: #if !(defined __linux__ && defined __i386__)
1.1 root 15: #if !id386
16:
17: void S_WriteLinearBlastStereo16 (void)
18: {
19: int i;
20: int val;
21:
22: for (i=0 ; i<snd_linear_count ; i+=2)
23: {
24: val = snd_p[i]>>8;
25: if (val > 0x7fff)
26: snd_out[i] = 0x7fff;
27: else if (val < (short)0x8000)
28: snd_out[i] = (short)0x8000;
29: else
30: snd_out[i] = val;
31:
32: val = snd_p[i+1]>>8;
33: if (val > 0x7fff)
34: snd_out[i+1] = 0x7fff;
35: else if (val < (short)0x8000)
36: snd_out[i+1] = (short)0x8000;
37: else
38: snd_out[i+1] = val;
39: }
40: }
41: #else
42: __declspec( naked ) void S_WriteLinearBlastStereo16 (void)
43: {
44: __asm {
45:
46: push edi
47: push ebx
48: mov ecx,ds:dword ptr[snd_linear_count]
49: mov ebx,ds:dword ptr[snd_p]
50: mov edi,ds:dword ptr[snd_out]
51: LWLBLoopTop:
52: mov eax,ds:dword ptr[-8+ebx+ecx*4]
53: sar eax,8
54: cmp eax,07FFFh
55: jg LClampHigh
56: cmp eax,0FFFF8000h
57: jnl LClampDone
58: mov eax,0FFFF8000h
59: jmp LClampDone
60: LClampHigh:
61: mov eax,07FFFh
62: LClampDone:
63: mov edx,ds:dword ptr[-4+ebx+ecx*4]
64: sar edx,8
65: cmp edx,07FFFh
66: jg LClampHigh2
67: cmp edx,0FFFF8000h
68: jnl LClampDone2
69: mov edx,0FFFF8000h
70: jmp LClampDone2
71: LClampHigh2:
72: mov edx,07FFFh
73: LClampDone2:
74: shl edx,16
75: and eax,0FFFFh
76: or edx,eax
77: mov ds:dword ptr[-4+edi+ecx*2],edx
78: sub ecx,2
79: jnz LWLBLoopTop
80: pop ebx
81: pop edi
82: ret
83: }
84: }
85:
86: #endif
1.1.1.2 ! root 87: #endif
1.1 root 88:
89: void S_TransferStereo16 (unsigned long *pbuf, int endtime)
90: {
91: int lpos;
92: int lpaintedtime;
93:
94: snd_p = (int *) paintbuffer;
95: lpaintedtime = paintedtime;
96:
97: while (lpaintedtime < endtime)
98: {
99: // handle recirculating buffer issues
100: lpos = lpaintedtime & ((dma.samples>>1)-1);
101:
102: snd_out = (short *) pbuf + (lpos<<1);
103:
104: snd_linear_count = (dma.samples>>1) - lpos;
105: if (lpaintedtime + snd_linear_count > endtime)
106: snd_linear_count = endtime - lpaintedtime;
107:
108: snd_linear_count <<= 1;
109:
110: // write a linear blast of samples
111: S_WriteLinearBlastStereo16 ();
112:
113: snd_p += snd_linear_count;
114: lpaintedtime += (snd_linear_count>>1);
115: }
116: }
117:
118: /*
119: ===================
120: S_TransferPaintBuffer
121:
122: ===================
123: */
124: void S_TransferPaintBuffer(int endtime)
125: {
126: int out_idx;
127: int count;
128: int out_mask;
129: int *p;
130: int step;
131: int val;
132: unsigned long *pbuf;
133:
134: pbuf = (unsigned long *)dma.buffer;
135:
136: if (s_testsound->value)
137: {
138: int i;
139: int count;
140:
141: // write a fixed sine wave
142: count = (endtime - paintedtime);
143: for (i=0 ; i<count ; i++)
144: paintbuffer[i].left = paintbuffer[i].right = sin((paintedtime+i)*0.1)*20000*256;
145: }
146:
147:
148: if (dma.samplebits == 16 && dma.channels == 2)
149: { // optimized case
150: S_TransferStereo16 (pbuf, endtime);
151: }
152: else
153: { // general case
154: p = (int *) paintbuffer;
155: count = (endtime - paintedtime) * dma.channels;
156: out_mask = dma.samples - 1;
157: out_idx = paintedtime * dma.channels & out_mask;
158: step = 3 - dma.channels;
159:
160: if (dma.samplebits == 16)
161: {
162: short *out = (short *) pbuf;
163: while (count--)
164: {
165: val = *p >> 8;
166: p+= step;
167: if (val > 0x7fff)
168: val = 0x7fff;
169: else if (val < (short)0x8000)
170: val = (short)0x8000;
171: out[out_idx] = val;
172: out_idx = (out_idx + 1) & out_mask;
173: }
174: }
175: else if (dma.samplebits == 8)
176: {
177: unsigned char *out = (unsigned char *) pbuf;
178: while (count--)
179: {
180: val = *p >> 8;
181: p+= step;
182: if (val > 0x7fff)
183: val = 0x7fff;
184: else if (val < (short)0x8000)
185: val = (short)0x8000;
186: out[out_idx] = (val>>8) + 128;
187: out_idx = (out_idx + 1) & out_mask;
188: }
189: }
190: }
191: }
192:
193:
194: /*
195: ===============================================================================
196:
197: CHANNEL MIXING
198:
199: ===============================================================================
200: */
201:
202: void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime, int offset);
203: void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime, int offset);
204:
205: void S_PaintChannels(int endtime)
206: {
207: int i;
208: int end;
209: channel_t *ch;
210: sfxcache_t *sc;
211: int ltime, count;
212: playsound_t *ps;
213:
214: snd_vol = s_volume->value*256;
215:
216: //Com_Printf ("%i to %i\n", paintedtime, endtime);
217: while (paintedtime < endtime)
218: {
219: // if paintbuffer is smaller than DMA buffer
220: end = endtime;
221: if (endtime - paintedtime > PAINTBUFFER_SIZE)
222: end = paintedtime + PAINTBUFFER_SIZE;
223:
224: // start any playsounds
225: while (1)
226: {
227: ps = s_pendingplays.next;
228: if (ps == &s_pendingplays)
229: break; // no more pending sounds
230: if (ps->begin <= paintedtime)
231: {
232: S_IssuePlaysound (ps);
233: continue;
234: }
235:
236: if (ps->begin < end)
237: end = ps->begin; // stop here
238: break;
239: }
240:
241: // clear the paint buffer
242: if (s_rawend < paintedtime)
243: {
244: // Com_Printf ("clear\n");
245: memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t));
246: }
247: else
248: { // copy from the streaming sound source
249: int s;
250: int stop;
251:
252: stop = (end < s_rawend) ? end : s_rawend;
253:
254: for (i=paintedtime ; i<stop ; i++)
255: {
256: s = i&(MAX_RAW_SAMPLES-1);
257: paintbuffer[i-paintedtime] = s_rawsamples[s];
258: }
259: // if (i != end)
260: // Com_Printf ("partial stream\n");
261: // else
262: // Com_Printf ("full stream\n");
263: for ( ; i<end ; i++)
264: {
265: paintbuffer[i-paintedtime].left =
266: paintbuffer[i-paintedtime].right = 0;
267: }
268: }
269:
270:
271: // paint in the channels.
272: ch = channels;
273: for (i=0; i<MAX_CHANNELS ; i++, ch++)
274: {
275: ltime = paintedtime;
276:
277: while (ltime < end)
278: {
279: if (!ch->sfx || (!ch->leftvol && !ch->rightvol) )
280: break;
281:
282: // max painting is to the end of the buffer
283: count = end - ltime;
284:
285: // might be stopped by running out of data
286: if (ch->end - ltime < count)
287: count = ch->end - ltime;
288:
289: sc = S_LoadSound (ch->sfx);
290: if (!sc)
291: break;
292:
293: if (count > 0 && ch->sfx)
294: {
295: if (sc->width == 1)// FIXME; 8 bit asm is wrong now
296: S_PaintChannelFrom8(ch, sc, count, ltime - paintedtime);
297: else
298: S_PaintChannelFrom16(ch, sc, count, ltime - paintedtime);
299:
300: ltime += count;
301: }
302:
303: // if at end of loop, restart
304: if (ltime >= ch->end)
305: {
306: if (ch->autosound)
307: { // autolooping sounds always go back to start
308: ch->pos = 0;
309: ch->end = ltime + sc->length;
310: }
311: else if (sc->loopstart >= 0)
312: {
313: ch->pos = sc->loopstart;
314: ch->end = ltime + sc->length - ch->pos;
315: }
316: else
317: { // channel just stopped
318: ch->sfx = NULL;
319: }
320: }
321: }
322:
323: }
324:
325: // transfer out according to DMA format
326: S_TransferPaintBuffer(end);
327: paintedtime = end;
328: }
329: }
330:
331: void S_InitScaletable (void)
332: {
333: int i, j;
334: int scale;
335:
336: s_volume->modified = false;
337: for (i=0 ; i<32 ; i++)
338: {
339: scale = i * 8 * 256 * s_volume->value;
340: for (j=0 ; j<256 ; j++)
341: snd_scaletable[i][j] = ((signed char)j) * scale;
342: }
343: }
344:
345:
1.1.1.2 ! root 346: #if !(defined __linux__ && defined __i386__)
1.1 root 347: #if !id386
348:
349: void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count, int offset)
350: {
351: int data;
352: int *lscale, *rscale;
353: unsigned char *sfx;
354: int i;
355: portable_samplepair_t *samp;
356:
357: if (ch->leftvol > 255)
358: ch->leftvol = 255;
359: if (ch->rightvol > 255)
360: ch->rightvol = 255;
361:
362: lscale = snd_scaletable[ ch->leftvol >> 11];
363: rscale = snd_scaletable[ ch->rightvol >> 11];
364: sfx = (signed char *)sc->data + ch->pos;
365:
366: samp = &paintbuffer[offset];
367:
368: for (i=0 ; i<count ; i++, samp++)
369: {
370: data = sfx[i];
371: samp->left += lscale[data];
372: samp->right += rscale[data];
373: }
374:
375: ch->pos += count;
376: }
377:
378: #else
379:
380: __declspec( naked ) void S_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count, int offset)
381: {
382: __asm {
383: push esi
384: push edi
385: push ebx
386: push ebp
387: mov ebx,ds:dword ptr[4+16+esp]
388: mov esi,ds:dword ptr[8+16+esp]
389: mov eax,ds:dword ptr[4+ebx]
390: mov edx,ds:dword ptr[8+ebx]
391: cmp eax,255
392: jna LLeftSet
393: mov eax,255
394: LLeftSet:
395: cmp edx,255
396: jna LRightSet
397: mov edx,255
398: LRightSet:
399: and eax,0F8h
400: add esi,20
401: and edx,0F8h
402: mov edi,ds:dword ptr[16+ebx]
403: mov ecx,ds:dword ptr[12+16+esp]
404: add esi,edi
405: shl eax,7
406: add edi,ecx
407: shl edx,7
408: mov ds:dword ptr[16+ebx],edi
409: add eax,offset snd_scaletable
410: add edx,offset snd_scaletable
411: sub ebx,ebx
412: mov bl,ds:byte ptr[-1+esi+ecx*1]
413: test ecx,1
414: jz LMix8Loop
415: mov edi,ds:dword ptr[eax+ebx*4]
416: mov ebp,ds:dword ptr[edx+ebx*4]
417: add edi,ds:dword ptr[paintbuffer+0-8+ecx*8]
418: add ebp,ds:dword ptr[paintbuffer+4-8+ecx*8]
419: mov ds:dword ptr[paintbuffer+0-8+ecx*8],edi
420: mov ds:dword ptr[paintbuffer+4-8+ecx*8],ebp
421: mov bl,ds:byte ptr[-2+esi+ecx*1]
422: dec ecx
423: jz LDone
424: LMix8Loop:
425: mov edi,ds:dword ptr[eax+ebx*4]
426: mov ebp,ds:dword ptr[edx+ebx*4]
427: add edi,ds:dword ptr[paintbuffer+0-8+ecx*8]
428: add ebp,ds:dword ptr[paintbuffer+4-8+ecx*8]
429: mov bl,ds:byte ptr[-2+esi+ecx*1]
430: mov ds:dword ptr[paintbuffer+0-8+ecx*8],edi
431: mov ds:dword ptr[paintbuffer+4-8+ecx*8],ebp
432: mov edi,ds:dword ptr[eax+ebx*4]
433: mov ebp,ds:dword ptr[edx+ebx*4]
434: mov bl,ds:byte ptr[-3+esi+ecx*1]
435: add edi,ds:dword ptr[paintbuffer+0-8*2+ecx*8]
436: add ebp,ds:dword ptr[paintbuffer+4-8*2+ecx*8]
437: mov ds:dword ptr[paintbuffer+0-8*2+ecx*8],edi
438: mov ds:dword ptr[paintbuffer+4-8*2+ecx*8],ebp
439: sub ecx,2
440: jnz LMix8Loop
441: LDone:
442: pop ebp
443: pop ebx
444: pop edi
445: pop esi
446: ret
447: }
448: }
449:
450: #endif
1.1.1.2 ! root 451: #endif
1.1 root 452:
453: void S_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count, int offset)
454: {
455: int data;
456: int left, right;
457: int leftvol, rightvol;
458: signed short *sfx;
459: int i;
460: portable_samplepair_t *samp;
461:
462: leftvol = ch->leftvol*snd_vol;
463: rightvol = ch->rightvol*snd_vol;
464: sfx = (signed short *)sc->data + ch->pos;
465:
466: samp = &paintbuffer[offset];
467: for (i=0 ; i<count ; i++, samp++)
468: {
469: data = sfx[i];
470: left = (data * leftvol)>>8;
471: right = (data * rightvol)>>8;
472: samp->left += left;
473: samp->right += right;
474: }
475:
476: ch->pos += count;
477: }
478:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.