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

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: 

unix.superglobalmegacorp.com

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