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

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

unix.superglobalmegacorp.com

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