Annotation of quake2/client/snd_mix.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.