Annotation of quake2/client/snd_dma.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_dma.c -- main control for any streaming sound output device
                     21: 
                     22: #include "client.h"
                     23: #include "snd_loc.h"
                     24: 
                     25: void S_Play(void);
                     26: void S_SoundList(void);
                     27: void S_Update_();
                     28: void S_StopAllSounds(void);
                     29: 
                     30: 
                     31: // =======================================================================
                     32: // Internal sound data & structures
                     33: // =======================================================================
                     34: 
                     35: // only begin attenuating sound volumes when outside the FULLVOLUME range
                     36: #define                SOUND_FULLVOLUME        80
                     37: 
                     38: #define                SOUND_LOOPATTENUATE     0.003
                     39: 
                     40: int                    s_registration_sequence;
                     41: 
                     42: channel_t   channels[MAX_CHANNELS];
                     43: 
                     44: qboolean       snd_initialized = false;
                     45: int                    sound_started=0;
                     46: 
                     47: dma_t          dma;
                     48: 
                     49: vec3_t         listener_origin;
                     50: vec3_t         listener_forward;
                     51: vec3_t         listener_right;
                     52: vec3_t         listener_up;
                     53: 
                     54: qboolean       s_registering;
                     55: 
                     56: int                    soundtime;              // sample PAIRS
                     57: int            paintedtime;    // sample PAIRS
                     58: 
                     59: // during registration it is possible to have more sounds
                     60: // than could actually be referenced during gameplay,
                     61: // because we don't want to free anything until we are
                     62: // sure we won't need it.
                     63: #define                MAX_SFX         (MAX_SOUNDS*2)
                     64: sfx_t          known_sfx[MAX_SFX];
                     65: int                    num_sfx;
                     66: 
                     67: #define                MAX_PLAYSOUNDS  128
                     68: playsound_t    s_playsounds[MAX_PLAYSOUNDS];
                     69: playsound_t    s_freeplays;
                     70: playsound_t    s_pendingplays;
                     71: 
                     72: int                    s_beginofs;
                     73: 
                     74: cvar_t         *s_volume;
                     75: cvar_t         *s_testsound;
                     76: cvar_t         *s_loadas8bit;
                     77: cvar_t         *s_khz;
                     78: cvar_t         *s_show;
                     79: cvar_t         *s_mixahead;
                     80: cvar_t         *s_primary;
                     81: 
                     82: 
                     83: int            s_rawend;
                     84: portable_samplepair_t  s_rawsamples[MAX_RAW_SAMPLES];
                     85: 
                     86: 
                     87: // ====================================================================
                     88: // User-setable variables
                     89: // ====================================================================
                     90: 
                     91: 
                     92: void S_SoundInfo_f(void)
                     93: {
                     94:        if (!sound_started)
                     95:        {
                     96:                Com_Printf ("sound system not started\n");
                     97:                return;
                     98:        }
                     99:        
                    100:     Com_Printf("%5d stereo\n", dma.channels - 1);
                    101:     Com_Printf("%5d samples\n", dma.samples);
                    102:     Com_Printf("%5d samplepos\n", dma.samplepos);
                    103:     Com_Printf("%5d samplebits\n", dma.samplebits);
                    104:     Com_Printf("%5d submission_chunk\n", dma.submission_chunk);
                    105:     Com_Printf("%5d speed\n", dma.speed);
                    106:     Com_Printf("0x%x dma buffer\n", dma.buffer);
                    107: }
                    108: 
                    109: 
                    110: 
                    111: /*
                    112: ================
                    113: S_Init
                    114: ================
                    115: */
                    116: void S_Init (void)
                    117: {
                    118:        cvar_t  *cv;
                    119: 
                    120:        Com_Printf("\n------- sound initialization -------\n");
                    121: 
                    122:        cv = Cvar_Get ("s_initsound", "1", 0);
                    123:        if (!cv->value)
                    124:                Com_Printf ("not initializing.\n");
                    125:        else
                    126:        {
                    127:                s_volume = Cvar_Get ("s_volume", "0.7", CVAR_ARCHIVE);
                    128:                s_khz = Cvar_Get ("s_khz", "11", CVAR_ARCHIVE);
                    129:                s_loadas8bit = Cvar_Get ("s_loadas8bit", "1", CVAR_ARCHIVE);
                    130:                s_mixahead = Cvar_Get ("s_mixahead", "0.2", CVAR_ARCHIVE);
                    131:                s_show = Cvar_Get ("s_show", "0", 0);
                    132:                s_testsound = Cvar_Get ("s_testsound", "0", 0);
                    133:                s_primary = Cvar_Get ("s_primary", "0", CVAR_ARCHIVE);  // win32 specific
                    134: 
                    135:                Cmd_AddCommand("play", S_Play);
                    136:                Cmd_AddCommand("stopsound", S_StopAllSounds);
                    137:                Cmd_AddCommand("soundlist", S_SoundList);
                    138:                Cmd_AddCommand("soundinfo", S_SoundInfo_f);
                    139: 
                    140:                if (!SNDDMA_Init())
                    141:                        return;
                    142: 
                    143:                S_InitScaletable ();
                    144: 
                    145:                sound_started = 1;
                    146:                num_sfx = 0;
                    147: 
                    148:                soundtime = 0;
                    149:                paintedtime = 0;
                    150: 
                    151:                Com_Printf ("sound sampling rate: %i\n", dma.speed);
                    152: 
                    153:                S_StopAllSounds ();
                    154:        }
                    155: 
                    156:        Com_Printf("------------------------------------\n");
                    157: }
                    158: 
                    159: 
                    160: // =======================================================================
                    161: // Shutdown sound engine
                    162: // =======================================================================
                    163: 
                    164: void S_Shutdown(void)
                    165: {
                    166:        int             i;
                    167:        sfx_t   *sfx;
                    168: 
                    169:        if (!sound_started)
                    170:                return;
                    171: 
                    172:        SNDDMA_Shutdown();
                    173: 
                    174:        sound_started = 0;
                    175: 
                    176:        Cmd_RemoveCommand("play");
                    177:        Cmd_RemoveCommand("stopsound");
                    178:        Cmd_RemoveCommand("soundlist");
                    179:        Cmd_RemoveCommand("soundinfo");
                    180: 
                    181:        // free all sounds
                    182:        for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
                    183:        {
                    184:                if (!sfx->name[0])
                    185:                        continue;
                    186:                if (sfx->cache)
                    187:                        Z_Free (sfx->cache);
                    188:                memset (sfx, 0, sizeof(*sfx));
                    189:        }
                    190: 
                    191:        num_sfx = 0;
                    192: }
                    193: 
                    194: 
                    195: // =======================================================================
                    196: // Load a sound
                    197: // =======================================================================
                    198: 
                    199: /*
                    200: ==================
                    201: S_FindName
                    202: 
                    203: ==================
                    204: */
                    205: sfx_t *S_FindName (char *name, qboolean create)
                    206: {
                    207:        int             i;
                    208:        sfx_t   *sfx;
                    209: 
                    210:        if (!name)
                    211:                Com_Error (ERR_FATAL, "S_FindName: NULL\n");
                    212:        if (!name[0])
                    213:                Com_Error (ERR_FATAL, "S_FindName: empty name\n");
                    214: 
                    215:        if (strlen(name) >= MAX_QPATH)
                    216:                Com_Error (ERR_FATAL, "Sound name too long: %s", name);
                    217: 
                    218:        // see if already loaded
                    219:        for (i=0 ; i < num_sfx ; i++)
                    220:                if (!strcmp(known_sfx[i].name, name))
                    221:                {
                    222:                        return &known_sfx[i];
                    223:                }
                    224: 
                    225:        if (!create)
                    226:                return NULL;
                    227: 
                    228:        // find a free sfx
                    229:        for (i=0 ; i < num_sfx ; i++)
                    230:                if (!known_sfx[i].name[0])
                    231: //                     registration_sequence < s_registration_sequence)
                    232:                        break;
                    233: 
                    234:        if (i == num_sfx)
                    235:        {
                    236:                if (num_sfx == MAX_SFX)
                    237:                        Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
                    238:                num_sfx++;
                    239:        }
                    240:        
                    241:        sfx = &known_sfx[i];
                    242:        memset (sfx, 0, sizeof(*sfx));
                    243:        strcpy (sfx->name, name);
                    244:        sfx->registration_sequence = s_registration_sequence;
                    245:        
                    246:        return sfx;
                    247: }
                    248: 
                    249: 
                    250: /*
1.1.1.2   root      251: ==================
                    252: S_AliasName
                    253: 
                    254: ==================
                    255: */
                    256: sfx_t *S_AliasName (char *aliasname, char *truename)
                    257: {
                    258:        sfx_t   *sfx;
                    259:        char    *s;
                    260:        int             i;
                    261: 
                    262:        s = Z_Malloc (MAX_QPATH);
                    263:        strcpy (s, truename);
                    264: 
                    265:        // find a free sfx
                    266:        for (i=0 ; i < num_sfx ; i++)
                    267:                if (!known_sfx[i].name[0])
                    268:                        break;
                    269: 
                    270:        if (i == num_sfx)
                    271:        {
                    272:                if (num_sfx == MAX_SFX)
                    273:                        Com_Error (ERR_FATAL, "S_FindName: out of sfx_t");
                    274:                num_sfx++;
                    275:        }
                    276:        
                    277:        sfx = &known_sfx[i];
                    278:        memset (sfx, 0, sizeof(*sfx));
                    279:        strcpy (sfx->name, aliasname);
                    280:        sfx->registration_sequence = s_registration_sequence;
                    281:        sfx->truename = s;
                    282: 
                    283:        return sfx;
                    284: }
                    285: 
                    286: 
                    287: /*
1.1       root      288: =====================
                    289: S_BeginRegistration
                    290: 
                    291: =====================
                    292: */
                    293: void S_BeginRegistration (void)
                    294: {
                    295:        s_registration_sequence++;
                    296:        s_registering = true;
                    297: }
                    298: 
                    299: /*
                    300: ==================
                    301: S_RegisterSound
                    302: 
                    303: ==================
                    304: */
                    305: sfx_t *S_RegisterSound (char *name)
                    306: {
                    307:        sfx_t   *sfx;
                    308: 
                    309:        if (!sound_started)
                    310:                return NULL;
                    311: 
                    312:        sfx = S_FindName (name, true);
                    313:        sfx->registration_sequence = s_registration_sequence;
                    314: 
                    315:        if (!s_registering)
                    316:                S_LoadSound (sfx);
                    317: 
                    318:        return sfx;
                    319: }
                    320: 
                    321: 
                    322: /*
                    323: =====================
                    324: S_EndRegistration
                    325: 
                    326: =====================
                    327: */
                    328: void S_EndRegistration (void)
                    329: {
                    330:        int             i;
                    331:        sfx_t   *sfx;
                    332:        int             size;
                    333: 
                    334:        // free any sounds not from this registration sequence
                    335:        for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
                    336:        {
                    337:                if (!sfx->name[0])
                    338:                        continue;
                    339:                if (sfx->registration_sequence != s_registration_sequence)
                    340:                {       // don't need this sound
                    341:                        if (sfx->cache) // it is possible to have a leftover
                    342:                                Z_Free (sfx->cache);    // from a server that didn't finish loading
                    343:                        memset (sfx, 0, sizeof(*sfx));
                    344:                }
                    345:                else
                    346:                {       // make sure it is paged in
                    347:                        if (sfx->cache)
                    348:                        {
                    349:                                size = sfx->cache->length*sfx->cache->width;
                    350:                                Com_PageInMemory ((byte *)sfx->cache, size);
                    351:                        }
                    352:                }
                    353: 
                    354:        }
                    355: 
                    356:        // load everything in
                    357:        for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
                    358:        {
                    359:                if (!sfx->name[0])
                    360:                        continue;
                    361:                S_LoadSound (sfx);
                    362:        }
                    363: 
                    364:        s_registering = false;
                    365: }
                    366: 
                    367: 
                    368: //=============================================================================
                    369: 
                    370: /*
                    371: =================
                    372: S_PickChannel
                    373: =================
                    374: */
                    375: channel_t *S_PickChannel(int entnum, int entchannel)
                    376: {
                    377:     int                        ch_idx;
                    378:     int                        first_to_die;
                    379:     int                        life_left;
                    380:        channel_t       *ch;
                    381: 
                    382:        if (entchannel<0)
                    383:                Com_Error (ERR_DROP, "S_PickChannel: entchannel<0");
                    384: 
                    385: // Check for replacement sound, or find the best one to replace
                    386:     first_to_die = -1;
                    387:     life_left = 0x7fffffff;
                    388:     for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++)
                    389:     {
                    390:                if (entchannel != 0             // channel 0 never overrides
                    391:                && channels[ch_idx].entnum == entnum
                    392:                && channels[ch_idx].entchannel == entchannel)
                    393:                {       // always override sound from same entity
                    394:                        first_to_die = ch_idx;
                    395:                        break;
                    396:                }
                    397: 
                    398:                // don't let monster sounds override player sounds
                    399:                if (channels[ch_idx].entnum == cl.playernum+1 && entnum != cl.playernum+1 && channels[ch_idx].sfx)
                    400:                        continue;
                    401: 
                    402:                if (channels[ch_idx].end - paintedtime < life_left)
                    403:                {
                    404:                        life_left = channels[ch_idx].end - paintedtime;
                    405:                        first_to_die = ch_idx;
                    406:                }
                    407:    }
                    408: 
                    409:        if (first_to_die == -1)
                    410:                return NULL;
                    411: 
                    412:        ch = &channels[first_to_die];
                    413:        memset (ch, 0, sizeof(*ch));
                    414: 
                    415:     return ch;
                    416: }       
                    417: 
                    418: /*
                    419: =================
                    420: S_SpatializeOrigin
                    421: 
                    422: Used for spatializing channels and autosounds
                    423: =================
                    424: */
                    425: void S_SpatializeOrigin (vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol)
                    426: {
                    427:     vec_t              dot;
                    428:     vec_t              dist;
                    429:     vec_t              lscale, rscale, scale;
                    430:     vec3_t             source_vec;
                    431: 
                    432:        if (cls.state != ca_active)
                    433:        {
                    434:                *left_vol = *right_vol = 255;
                    435:                return;
                    436:        }
                    437: 
                    438: // calculate stereo seperation and distance attenuation
                    439:        VectorSubtract(origin, listener_origin, source_vec);
                    440: 
                    441:        dist = VectorNormalize(source_vec);
                    442:        dist -= SOUND_FULLVOLUME;
                    443:        if (dist < 0)
                    444:                dist = 0;                       // close enough to be at full volume
                    445:        dist *= dist_mult;              // different attenuation levels
                    446:        
                    447:        dot = DotProduct(listener_right, source_vec);
                    448: 
                    449:        if (dma.channels == 1 || !dist_mult)
                    450:        { // no attenuation = no spatialization
                    451:                rscale = 1.0;
                    452:                lscale = 1.0;
                    453:        }
                    454:        else
                    455:        {
                    456:                rscale = 0.5 * (1.0 + dot);
                    457:                lscale = 0.5*(1.0 - dot);
                    458:        }
                    459: 
                    460:        // add in distance effect
                    461:        scale = (1.0 - dist) * rscale;
                    462:        *right_vol = (int) (master_vol * scale);
                    463:        if (*right_vol < 0)
                    464:                *right_vol = 0;
                    465: 
                    466:        scale = (1.0 - dist) * lscale;
                    467:        *left_vol = (int) (master_vol * scale);
                    468:        if (*left_vol < 0)
                    469:                *left_vol = 0;
                    470: }
                    471: 
                    472: /*
                    473: =================
                    474: S_Spatialize
                    475: =================
                    476: */
                    477: void S_Spatialize(channel_t *ch)
                    478: {
                    479:        vec3_t          origin;
                    480: 
                    481:        // anything coming from the view entity will always be full volume
                    482:        if (ch->entnum == cl.playernum+1)
                    483:        {
                    484:                ch->leftvol = ch->master_vol;
                    485:                ch->rightvol = ch->master_vol;
                    486:                return;
                    487:        }
                    488: 
                    489:        if (ch->fixed_origin)
                    490:        {
                    491:                VectorCopy (ch->origin, origin);
                    492:        }
                    493:        else
                    494:                CL_GetEntitySoundOrigin (ch->entnum, origin);
                    495: 
                    496:        S_SpatializeOrigin (origin, ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol);
                    497: }           
                    498: 
                    499: 
                    500: /*
                    501: =================
                    502: S_AllocPlaysound
                    503: =================
                    504: */
                    505: playsound_t *S_AllocPlaysound (void)
                    506: {
                    507:        playsound_t     *ps;
                    508: 
                    509:        ps = s_freeplays.next;
                    510:        if (ps == &s_freeplays)
                    511:                return NULL;            // no free playsounds
                    512: 
                    513:        // unlink from freelist
                    514:        ps->prev->next = ps->next;
                    515:        ps->next->prev = ps->prev;
                    516:        
                    517:        return ps;
                    518: }
                    519: 
                    520: 
                    521: /*
                    522: =================
                    523: S_FreePlaysound
                    524: =================
                    525: */
                    526: void S_FreePlaysound (playsound_t *ps)
                    527: {
                    528:        // unlink from channel
                    529:        ps->prev->next = ps->next;
                    530:        ps->next->prev = ps->prev;
                    531: 
                    532:        // add to free list
                    533:        ps->next = s_freeplays.next;
                    534:        s_freeplays.next->prev = ps;
                    535:        ps->prev = &s_freeplays;
                    536:        s_freeplays.next = ps;
                    537: }
                    538: 
                    539: 
                    540: 
                    541: /*
                    542: ===============
                    543: S_IssuePlaysound
                    544: 
                    545: Take the next playsound and begin it on the channel
                    546: This is never called directly by S_Play*, but only
                    547: by the update loop.
                    548: ===============
                    549: */
                    550: void S_IssuePlaysound (playsound_t *ps)
                    551: {
                    552:        channel_t       *ch;
                    553:        sfxcache_t      *sc;
                    554: 
                    555:        if (s_show->value)
                    556:                Com_Printf ("Issue %i\n", ps->begin);
                    557:        // pick a channel to play on
                    558:        ch = S_PickChannel(ps->entnum, ps->entchannel);
                    559:        if (!ch)
                    560:        {
                    561:                S_FreePlaysound (ps);
                    562:                return;
                    563:        }
                    564: 
                    565:        // spatialize
                    566:        if (ps->attenuation == ATTN_STATIC)
                    567:                ch->dist_mult = ps->attenuation * 0.001;
                    568:        else
                    569:                ch->dist_mult = ps->attenuation * 0.0005;
                    570:        ch->master_vol = ps->volume;
                    571:        ch->entnum = ps->entnum;
                    572:        ch->entchannel = ps->entchannel;
                    573:        ch->sfx = ps->sfx;
                    574:        VectorCopy (ps->origin, ch->origin);
                    575:        ch->fixed_origin = ps->fixed_origin;
                    576: 
                    577:        S_Spatialize(ch);
                    578: 
                    579:        ch->pos = 0;
                    580:        sc = S_LoadSound (ch->sfx);
                    581:     ch->end = paintedtime + sc->length;
                    582: 
                    583:        // free the playsound
                    584:        S_FreePlaysound (ps);
                    585: }
                    586: 
                    587: struct sfx_s *S_RegisterSexedSound (entity_state_t *ent, char *base)
                    588: {
                    589:        int                             n;
                    590:        char                    *p;
                    591:        struct sfx_s    *sfx;
                    592:        FILE                    *f;
                    593:        char                    model[MAX_QPATH];
1.1.1.2   root      594:        char                    sexedFilename[MAX_QPATH];
                    595:        char                    maleFilename[MAX_QPATH];
1.1       root      596: 
                    597:        // determine what model the client is using
                    598:        model[0] = 0;
                    599:        n = CS_PLAYERSKINS + ent->number - 1;
                    600:        if (cl.configstrings[n][0])
                    601:        {
                    602:                p = strchr(cl.configstrings[n], '\\');
                    603:                if (p)
                    604:                {
                    605:                        p += 1;
                    606:                        strcpy(model, p);
                    607:                        p = strchr(model, '/');
                    608:                        if (p)
                    609:                                *p = 0;
                    610:                }
                    611:        }
                    612:        // if we can't figure it out, they're male
                    613:        if (!model[0])
                    614:                strcpy(model, "male");
                    615: 
                    616:        // see if we already know of the model specific sound
1.1.1.2   root      617:        Com_sprintf (sexedFilename, sizeof(sexedFilename), "#players/%s/%s", model, base+1);
                    618:        sfx = S_FindName (sexedFilename, false);
1.1       root      619: 
                    620:        if (!sfx)
                    621:        {
                    622:                // no, so see if it exists
1.1.1.2   root      623:                FS_FOpenFile (&sexedFilename[1], &f);
1.1       root      624:                if (f)
                    625:                {
                    626:                        // yes, close the file and register it
                    627:                        FS_FCloseFile (f);
1.1.1.2   root      628:                        sfx = S_RegisterSound (sexedFilename);
1.1       root      629:                }
                    630:                else
                    631:                {
                    632:                        // no, revert to the male sound in the pak0.pak
1.1.1.2   root      633:                        Com_sprintf (maleFilename, sizeof(maleFilename), "player/%s/%s", "male", base+1);
                    634:                        sfx = S_AliasName (sexedFilename, maleFilename);
1.1       root      635:                }
                    636:        }
                    637: 
                    638:        return sfx;
                    639: }
                    640: 
1.1.1.2   root      641: 
1.1       root      642: // =======================================================================
                    643: // Start a sound effect
                    644: // =======================================================================
                    645: 
                    646: /*
                    647: ====================
                    648: S_StartSound
                    649: 
                    650: Validates the parms and ques the sound up
                    651: if pos is NULL, the sound will be dynamically sourced from the entity
                    652: Entchannel 0 will never override a playing sound
                    653: ====================
                    654: */
                    655: void S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
                    656: {
                    657:        sfxcache_t      *sc;
                    658:        int                     vol;
                    659:        playsound_t     *ps, *sort;
                    660:        int                     start;
                    661: 
                    662:        if (!sound_started)
                    663:                return;
                    664: 
                    665:        if (!sfx)
                    666:                return;
                    667: 
                    668:        if (sfx->name[0] == '*')
                    669:                sfx = S_RegisterSexedSound(&cl_entities[entnum].current, sfx->name);
                    670: 
                    671:        // make sure the sound is loaded
                    672:        sc = S_LoadSound (sfx);
                    673:        if (!sc)
                    674:                return;         // couldn't load the sound's data
                    675: 
                    676:        vol = fvol*255;
                    677: 
                    678:        // make the playsound_t
                    679:        ps = S_AllocPlaysound ();
                    680:        if (!ps)
                    681:                return;
                    682: 
                    683:        if (origin)
                    684:        {
                    685:                VectorCopy (origin, ps->origin);
                    686:                ps->fixed_origin = true;
                    687:        }
                    688:        else
                    689:                ps->fixed_origin = false;
                    690: 
                    691:        ps->entnum = entnum;
                    692:        ps->entchannel = entchannel;
                    693:        ps->attenuation = attenuation;
                    694:        ps->volume = vol;
                    695:        ps->sfx = sfx;
                    696: 
                    697:        // drift s_beginofs
                    698:        start = cl.frame.servertime * 0.001 * dma.speed + s_beginofs;
                    699:        if (start < paintedtime)
                    700:        {
                    701:                start = paintedtime;
                    702:                s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
                    703:        }
                    704:        else if (start > paintedtime + 0.3 * dma.speed)
                    705:        {
                    706:                start = paintedtime + 0.1 * dma.speed;
                    707:                s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
                    708:        }
                    709:        else
                    710:        {
                    711:                s_beginofs-=10;
                    712:        }
                    713: 
                    714:        if (!timeofs)
                    715:                ps->begin = paintedtime;
                    716:        else
                    717:                ps->begin = start + timeofs * dma.speed;
                    718: 
                    719:        // sort into the pending sound list
                    720:        for (sort = s_pendingplays.next ; 
                    721:                sort != &s_pendingplays && sort->begin < ps->begin ;
                    722:                sort = sort->next)
                    723:                        ;
                    724: 
                    725:        ps->next = sort;
                    726:        ps->prev = sort->prev;
                    727: 
                    728:        ps->next->prev = ps;
                    729:        ps->prev->next = ps;
                    730: }
                    731: 
                    732: 
                    733: /*
                    734: ==================
                    735: S_StartLocalSound
                    736: ==================
                    737: */
                    738: void S_StartLocalSound (char *sound)
                    739: {
                    740:        sfx_t   *sfx;
                    741: 
                    742:        if (!sound_started)
                    743:                return;
                    744:                
                    745:        sfx = S_RegisterSound (sound);
                    746:        if (!sfx)
                    747:        {
                    748:                Com_Printf ("S_StartLocalSound: can't cache %s\n", sound);
                    749:                return;
                    750:        }
                    751:        S_StartSound (NULL, cl.playernum+1, 0, sfx, 1, 1, 0);
                    752: }
                    753: 
                    754: 
                    755: /*
                    756: ==================
                    757: S_ClearBuffer
                    758: ==================
                    759: */
                    760: void S_ClearBuffer (void)
                    761: {
                    762:        int             clear;
                    763:                
                    764:        if (!sound_started)
                    765:                return;
                    766: 
                    767:        s_rawend = 0;
                    768: 
                    769:        if (dma.samplebits == 8)
                    770:                clear = 0x80;
                    771:        else
                    772:                clear = 0;
                    773: 
                    774:        SNDDMA_BeginPainting ();
                    775:        if (dma.buffer)
                    776:                memset(dma.buffer, clear, dma.samples * dma.samplebits/8);
                    777:        SNDDMA_Submit ();
                    778: }
                    779: 
                    780: /*
                    781: ==================
                    782: S_StopAllSounds
                    783: ==================
                    784: */
                    785: void S_StopAllSounds(void)
                    786: {
                    787:        int             i;
                    788: 
                    789:        if (!sound_started)
                    790:                return;
                    791: 
                    792:        // clear all the playsounds
                    793:        memset(s_playsounds, 0, sizeof(s_playsounds));
                    794:        s_freeplays.next = s_freeplays.prev = &s_freeplays;
                    795:        s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
                    796: 
                    797:        for (i=0 ; i<MAX_PLAYSOUNDS ; i++)
                    798:        {
                    799:                s_playsounds[i].prev = &s_freeplays;
                    800:                s_playsounds[i].next = s_freeplays.next;
                    801:                s_playsounds[i].prev->next = &s_playsounds[i];
                    802:                s_playsounds[i].next->prev = &s_playsounds[i];
                    803:        }
                    804: 
                    805:        // clear all the channels
                    806:        memset(channels, 0, sizeof(channels));
                    807: 
                    808:        S_ClearBuffer ();
                    809: }
                    810: 
                    811: /*
                    812: ==================
                    813: S_AddLoopSounds
                    814: 
                    815: Entities with a ->sound field will generated looped sounds
                    816: that are automatically started, stopped, and merged together
                    817: as the entities are sent to the client
                    818: ==================
                    819: */
                    820: void S_AddLoopSounds (void)
                    821: {
                    822:        int                     i, j;
                    823:        int                     sounds[MAX_EDICTS];
                    824:        int                     left, right, left_total, right_total;
                    825:        channel_t       *ch;
                    826:        sfx_t           *sfx;
                    827:        sfxcache_t      *sc;
                    828:        int                     num;
                    829:        entity_state_t  *ent;
                    830: 
                    831:        if (cl_paused->value)
                    832:                return;
                    833: 
                    834:        if (cls.state != ca_active)
                    835:                return;
                    836: 
                    837:        if (!cl.sound_prepped)
                    838:                return;
                    839: 
                    840:        for (i=0 ; i<cl.frame.num_entities ; i++)
                    841:        {
                    842:                num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
                    843:                ent = &cl_parse_entities[num];
                    844:                sounds[i] = ent->sound;
                    845:        }
                    846: 
                    847:        for (i=0 ; i<cl.frame.num_entities ; i++)
                    848:        {
                    849:                if (!sounds[i])
                    850:                        continue;
                    851: 
                    852:                sfx = cl.sound_precache[sounds[i]];
                    853:                if (!sfx)
                    854:                        continue;               // bad sound effect
                    855:                sc = sfx->cache;
                    856:                if (!sc)
                    857:                        continue;
                    858: 
                    859:                num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
                    860:                ent = &cl_parse_entities[num];
                    861: 
                    862:                // find the total contribution of all sounds of this type
                    863:                S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE,
                    864:                        &left_total, &right_total);
                    865:                for (j=i+1 ; j<cl.frame.num_entities ; j++)
                    866:                {
                    867:                        if (sounds[j] != sounds[i])
                    868:                                continue;
                    869:                        sounds[j] = 0;  // don't check this again later
                    870: 
                    871:                        num = (cl.frame.parse_entities + j)&(MAX_PARSE_ENTITIES-1);
                    872:                        ent = &cl_parse_entities[num];
                    873: 
                    874:                        S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE, 
                    875:                                &left, &right);
                    876:                        left_total += left;
                    877:                        right_total += right;
                    878:                }
                    879: 
                    880:                if (left_total == 0 && right_total == 0)
                    881:                        continue;               // not audible
                    882: 
                    883:                // allocate a channel
                    884:                ch = S_PickChannel(0, 0);
                    885:                if (!ch)
                    886:                        return;
                    887: 
                    888:                if (left_total > 255)
                    889:                        left_total = 255;
                    890:                if (right_total > 255)
                    891:                        right_total = 255;
                    892:                ch->leftvol = left_total;
                    893:                ch->rightvol = right_total;
                    894:                ch->autosound = true;   // remove next frame
                    895:                ch->sfx = sfx;
                    896:                ch->pos = paintedtime % sc->length;
                    897:                ch->end = paintedtime + sc->length - ch->pos;
                    898:        }
                    899: }
                    900: 
                    901: //=============================================================================
                    902: 
                    903: /*
                    904: ============
                    905: S_RawSamples
                    906: 
                    907: Cinematic streaming and voice over network
                    908: ============
                    909: */
                    910: void S_RawSamples (int samples, int rate, int width, int channels, byte *data)
                    911: {
                    912:        int             i;
                    913:        int             src, dst;
                    914:        float   scale;
                    915: 
                    916:        if (!sound_started)
                    917:                return;
                    918: 
                    919:        if (s_rawend < paintedtime)
                    920:                s_rawend = paintedtime;
                    921:        scale = (float)rate / dma.speed;
                    922: 
                    923: //Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend);
                    924:        if (channels == 2 && width == 2)
                    925:        {
                    926:                if (scale == 1.0)
                    927:                {       // optimized case
                    928:                        for (i=0 ; i<samples ; i++)
                    929:                        {
                    930:                                dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    931:                                s_rawend++;
1.1.1.2   root      932:                                s_rawsamples[dst].left =
                    933:                                    LittleShort(((short *)data)[i*2]) << 8;
                    934:                                s_rawsamples[dst].right =
                    935:                                    LittleShort(((short *)data)[i*2+1]) << 8;
1.1       root      936:                        }
                    937:                }
                    938:                else
                    939:                {
                    940:                        for (i=0 ; ; i++)
                    941:                        {
                    942:                                src = i*scale;
                    943:                                if (src >= samples)
                    944:                                        break;
                    945:                                dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    946:                                s_rawend++;
1.1.1.2   root      947:                                s_rawsamples[dst].left =
                    948:                                    LittleShort(((short *)data)[src*2]) << 8;
                    949:                                s_rawsamples[dst].right =
                    950:                                    LittleShort(((short *)data)[src*2+1]) << 8;
1.1       root      951:                        }
                    952:                }
                    953:        }
                    954:        else if (channels == 1 && width == 2)
                    955:        {
                    956:                for (i=0 ; ; i++)
                    957:                {
                    958:                        src = i*scale;
                    959:                        if (src >= samples)
                    960:                                break;
                    961:                        dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    962:                        s_rawend++;
1.1.1.2   root      963:                        s_rawsamples[dst].left =
                    964:                            LittleShort(((short *)data)[src]) << 8;
                    965:                        s_rawsamples[dst].right =
                    966:                            LittleShort(((short *)data)[src]) << 8;
1.1       root      967:                }
                    968:        }
                    969:        else if (channels == 2 && width == 1)
                    970:        {
                    971:                for (i=0 ; ; i++)
                    972:                {
                    973:                        src = i*scale;
                    974:                        if (src >= samples)
                    975:                                break;
                    976:                        dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    977:                        s_rawend++;
1.1.1.2   root      978:                        s_rawsamples[dst].left =
                    979:                            ((char *)data)[src*2] << 16;
                    980:                        s_rawsamples[dst].right =
                    981:                            ((char *)data)[src*2+1] << 16;
1.1       root      982:                }
                    983:        }
                    984:        else if (channels == 1 && width == 1)
                    985:        {
                    986:                for (i=0 ; ; i++)
                    987:                {
                    988:                        src = i*scale;
                    989:                        if (src >= samples)
                    990:                                break;
                    991:                        dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    992:                        s_rawend++;
1.1.1.2   root      993:                        s_rawsamples[dst].left =
                    994:                            (((byte *)data)[src]-128) << 16;
1.1       root      995:                        s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
                    996:                }
                    997:        }
                    998: }
                    999: 
                   1000: //=============================================================================
                   1001: 
                   1002: /*
                   1003: ============
                   1004: S_Update
                   1005: 
                   1006: Called once each time through the main loop
                   1007: ============
                   1008: */
                   1009: void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
                   1010: {
                   1011:        int                     i;
                   1012:        int                     total;
                   1013:        channel_t       *ch;
                   1014:        channel_t       *combine;
                   1015: 
                   1016:        if (!sound_started)
                   1017:                return;
                   1018: 
                   1019:        // if the laoding plaque is up, clear everything
                   1020:        // out to make sure we aren't looping a dirty
                   1021:        // dma buffer while loading
                   1022:        if (cls.disable_screen)
                   1023:        {
                   1024:                S_ClearBuffer ();
                   1025:                return;
                   1026:        }
                   1027: 
                   1028:        // rebuild scale tables if volume is modified
                   1029:        if (s_volume->modified)
                   1030:                S_InitScaletable ();
                   1031: 
                   1032:        VectorCopy(origin, listener_origin);
                   1033:        VectorCopy(forward, listener_forward);
                   1034:        VectorCopy(right, listener_right);
                   1035:        VectorCopy(up, listener_up);
                   1036: 
                   1037:        combine = NULL;
                   1038: 
                   1039:        // update spatialization for dynamic sounds     
                   1040:        ch = channels;
                   1041:        for (i=0 ; i<MAX_CHANNELS; i++, ch++)
                   1042:        {
                   1043:                if (!ch->sfx)
                   1044:                        continue;
                   1045:                if (ch->autosound)
                   1046:                {       // autosounds are regenerated fresh each frame
                   1047:                        memset (ch, 0, sizeof(*ch));
                   1048:                        continue;
                   1049:                }
                   1050:                S_Spatialize(ch);         // respatialize channel
                   1051:                if (!ch->leftvol && !ch->rightvol)
                   1052:                {
                   1053:                        memset (ch, 0, sizeof(*ch));
                   1054:                        continue;
                   1055:                }
                   1056:        }
                   1057: 
                   1058:        // add loopsounds
                   1059:        S_AddLoopSounds ();
                   1060: 
                   1061:        //
                   1062:        // debugging output
                   1063:        //
                   1064:        if (s_show->value)
                   1065:        {
                   1066:                total = 0;
                   1067:                ch = channels;
                   1068:                for (i=0 ; i<MAX_CHANNELS; i++, ch++)
                   1069:                        if (ch->sfx && (ch->leftvol || ch->rightvol) )
                   1070:                        {
                   1071:                                Com_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
                   1072:                                total++;
                   1073:                        }
                   1074:                
                   1075:                Com_Printf ("----(%i)---- painted: %i\n", total, paintedtime);
                   1076:        }
                   1077: 
                   1078: // mix some sound
                   1079:        S_Update_();
                   1080: }
                   1081: 
                   1082: void GetSoundtime(void)
                   1083: {
                   1084:        int             samplepos;
                   1085:        static  int             buffers;
                   1086:        static  int             oldsamplepos;
                   1087:        int             fullsamples;
                   1088:        
                   1089:        fullsamples = dma.samples / dma.channels;
                   1090: 
                   1091: // it is possible to miscount buffers if it has wrapped twice between
                   1092: // calls to S_Update.  Oh well.
                   1093:        samplepos = SNDDMA_GetDMAPos();
                   1094: 
                   1095:        if (samplepos < oldsamplepos)
                   1096:        {
                   1097:                buffers++;                                      // buffer wrapped
                   1098:                
                   1099:                if (paintedtime > 0x40000000)
                   1100:                {       // time to chop things off to avoid 32 bit limits
                   1101:                        buffers = 0;
                   1102:                        paintedtime = fullsamples;
                   1103:                        S_StopAllSounds ();
                   1104:                }
                   1105:        }
                   1106:        oldsamplepos = samplepos;
                   1107: 
                   1108:        soundtime = buffers*fullsamples + samplepos/dma.channels;
                   1109: }
                   1110: 
                   1111: 
                   1112: void S_Update_(void)
                   1113: {
                   1114:        unsigned        endtime;
                   1115:        int                             samps;
                   1116: 
                   1117:        if (!sound_started)
                   1118:                return;
                   1119: 
                   1120:        SNDDMA_BeginPainting ();
                   1121: 
                   1122:        if (!dma.buffer)
                   1123:                return;
                   1124: 
                   1125: // Updates DMA time
                   1126:        GetSoundtime();
                   1127: 
                   1128: // check to make sure that we haven't overshot
                   1129:        if (paintedtime < soundtime)
                   1130:        {
                   1131:                Com_DPrintf ("S_Update_ : overflow\n");
                   1132:                paintedtime = soundtime;
                   1133:        }
                   1134: 
                   1135: // mix ahead of current position
                   1136:        endtime = soundtime + s_mixahead->value * dma.speed;
                   1137: //endtime = (soundtime + 4096) & ~4095;
                   1138: 
                   1139:        // mix to an even submission block size
                   1140:        endtime = (endtime + dma.submission_chunk-1)
                   1141:                & ~(dma.submission_chunk-1);
                   1142:        samps = dma.samples >> (dma.channels-1);
                   1143:        if (endtime - soundtime > samps)
                   1144:                endtime = soundtime + samps;
                   1145: 
                   1146:        S_PaintChannels (endtime);
                   1147: 
                   1148:        SNDDMA_Submit ();
                   1149: }
                   1150: 
                   1151: /*
                   1152: ===============================================================================
                   1153: 
                   1154: console functions
                   1155: 
                   1156: ===============================================================================
                   1157: */
                   1158: 
                   1159: void S_Play(void)
                   1160: {
                   1161:        int     i;
                   1162:        char name[256];
                   1163:        sfx_t   *sfx;
                   1164:        
                   1165:        i = 1;
                   1166:        while (i<Cmd_Argc())
                   1167:        {
                   1168:                if (!strrchr(Cmd_Argv(i), '.'))
                   1169:                {
                   1170:                        strcpy(name, Cmd_Argv(i));
                   1171:                        strcat(name, ".wav");
                   1172:                }
                   1173:                else
                   1174:                        strcpy(name, Cmd_Argv(i));
                   1175:                sfx = S_RegisterSound(name);
                   1176:                S_StartSound(NULL, cl.playernum+1, 0, sfx, 1.0, 1.0, 0);
                   1177:                i++;
                   1178:        }
                   1179: }
                   1180: 
                   1181: void S_SoundList(void)
                   1182: {
                   1183:        int             i;
                   1184:        sfx_t   *sfx;
                   1185:        sfxcache_t      *sc;
                   1186:        int             size, total;
                   1187: 
                   1188:        total = 0;
                   1189:        for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
                   1190:        {
                   1191:                if (!sfx->registration_sequence)
                   1192:                        continue;
                   1193:                sc = sfx->cache;
                   1194:                if (sc)
                   1195:                {
                   1196:                        size = sc->length*sc->width*(sc->stereo+1);
                   1197:                        total += size;
                   1198:                        if (sc->loopstart >= 0)
                   1199:                                Com_Printf ("L");
                   1200:                        else
                   1201:                                Com_Printf (" ");
                   1202:                        Com_Printf("(%2db) %6i : %s\n",sc->width*8,  size, sfx->name);
                   1203:                }
                   1204:                else
                   1205:                {
                   1206:                        if (sfx->name[0] == '*')
                   1207:                                Com_Printf("  placeholder : %s\n", sfx->name);
                   1208:                        else
                   1209:                                Com_Printf("  not loaded  : %s\n", sfx->name);
                   1210:                }
                   1211:        }
                   1212:        Com_Printf ("Total resident: %i\n", total);
                   1213: }
                   1214: 

unix.superglobalmegacorp.com

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