Annotation of quake2/client/snd_mix.c, revision 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.