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

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: 

unix.superglobalmegacorp.com

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