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