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