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

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: /*
                    232: =====================
                    233: S_BeginRegistration
                    234: 
                    235: =====================
                    236: */
                    237: void S_BeginRegistration (void)
                    238: {
                    239:        s_registration_sequence++;
                    240:        s_registering = true;
                    241: }
                    242: 
                    243: /*
                    244: ==================
                    245: S_RegisterSound
                    246: 
                    247: ==================
                    248: */
                    249: sfx_t *S_RegisterSound (char *name)
                    250: {
                    251:        sfx_t   *sfx;
                    252: 
                    253:        if (!sound_started)
                    254:                return NULL;
                    255: 
                    256:        sfx = S_FindName (name, true);
                    257:        sfx->registration_sequence = s_registration_sequence;
                    258: 
                    259:        if (!s_registering)
                    260:                S_LoadSound (sfx);
                    261: 
                    262:        return sfx;
                    263: }
                    264: 
                    265: 
                    266: /*
                    267: =====================
                    268: S_EndRegistration
                    269: 
                    270: =====================
                    271: */
                    272: void S_EndRegistration (void)
                    273: {
                    274:        int             i;
                    275:        sfx_t   *sfx;
                    276:        int             size;
                    277: 
                    278:        // free any sounds not from this registration sequence
                    279:        for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
                    280:        {
                    281:                if (!sfx->name[0])
                    282:                        continue;
                    283:                if (sfx->registration_sequence != s_registration_sequence)
                    284:                {       // don't need this sound
                    285:                        if (sfx->cache) // it is possible to have a leftover
                    286:                                Z_Free (sfx->cache);    // from a server that didn't finish loading
                    287:                        memset (sfx, 0, sizeof(*sfx));
                    288:                }
                    289:                else
                    290:                {       // make sure it is paged in
                    291:                        if (sfx->cache)
                    292:                        {
                    293:                                size = sfx->cache->length*sfx->cache->width;
                    294:                                Com_PageInMemory ((byte *)sfx->cache, size);
                    295:                        }
                    296:                }
                    297: 
                    298:        }
                    299: 
                    300:        // load everything in
                    301:        for (i=0, sfx=known_sfx ; i < num_sfx ; i++,sfx++)
                    302:        {
                    303:                if (!sfx->name[0])
                    304:                        continue;
                    305:                S_LoadSound (sfx);
                    306:        }
                    307: 
                    308:        s_registering = false;
                    309: }
                    310: 
                    311: 
                    312: //=============================================================================
                    313: 
                    314: /*
                    315: =================
                    316: S_PickChannel
                    317: =================
                    318: */
                    319: channel_t *S_PickChannel(int entnum, int entchannel)
                    320: {
                    321:     int                        ch_idx;
                    322:     int                        first_to_die;
                    323:     int                        life_left;
                    324:        channel_t       *ch;
                    325: 
                    326:        if (entchannel<0)
                    327:                Com_Error (ERR_DROP, "S_PickChannel: entchannel<0");
                    328: 
                    329: // Check for replacement sound, or find the best one to replace
                    330:     first_to_die = -1;
                    331:     life_left = 0x7fffffff;
                    332:     for (ch_idx=0 ; ch_idx < MAX_CHANNELS ; ch_idx++)
                    333:     {
                    334:                if (entchannel != 0             // channel 0 never overrides
                    335:                && channels[ch_idx].entnum == entnum
                    336:                && channels[ch_idx].entchannel == entchannel)
                    337:                {       // always override sound from same entity
                    338:                        first_to_die = ch_idx;
                    339:                        break;
                    340:                }
                    341: 
                    342:                // don't let monster sounds override player sounds
                    343:                if (channels[ch_idx].entnum == cl.playernum+1 && entnum != cl.playernum+1 && channels[ch_idx].sfx)
                    344:                        continue;
                    345: 
                    346:                if (channels[ch_idx].end - paintedtime < life_left)
                    347:                {
                    348:                        life_left = channels[ch_idx].end - paintedtime;
                    349:                        first_to_die = ch_idx;
                    350:                }
                    351:    }
                    352: 
                    353:        if (first_to_die == -1)
                    354:                return NULL;
                    355: 
                    356:        ch = &channels[first_to_die];
                    357:        memset (ch, 0, sizeof(*ch));
                    358: 
                    359:     return ch;
                    360: }       
                    361: 
                    362: /*
                    363: =================
                    364: S_SpatializeOrigin
                    365: 
                    366: Used for spatializing channels and autosounds
                    367: =================
                    368: */
                    369: void S_SpatializeOrigin (vec3_t origin, float master_vol, float dist_mult, int *left_vol, int *right_vol)
                    370: {
                    371:     vec_t              dot;
                    372:     vec_t              dist;
                    373:     vec_t              lscale, rscale, scale;
                    374:     vec3_t             source_vec;
                    375: 
                    376:        if (cls.state != ca_active)
                    377:        {
                    378:                *left_vol = *right_vol = 255;
                    379:                return;
                    380:        }
                    381: 
                    382: // calculate stereo seperation and distance attenuation
                    383:        VectorSubtract(origin, listener_origin, source_vec);
                    384: 
                    385:        dist = VectorNormalize(source_vec);
                    386:        dist -= SOUND_FULLVOLUME;
                    387:        if (dist < 0)
                    388:                dist = 0;                       // close enough to be at full volume
                    389:        dist *= dist_mult;              // different attenuation levels
                    390:        
                    391:        dot = DotProduct(listener_right, source_vec);
                    392: 
                    393:        if (dma.channels == 1 || !dist_mult)
                    394:        { // no attenuation = no spatialization
                    395:                rscale = 1.0;
                    396:                lscale = 1.0;
                    397:        }
                    398:        else
                    399:        {
                    400:                rscale = 0.5 * (1.0 + dot);
                    401:                lscale = 0.5*(1.0 - dot);
                    402:        }
                    403: 
                    404:        // add in distance effect
                    405:        scale = (1.0 - dist) * rscale;
                    406:        *right_vol = (int) (master_vol * scale);
                    407:        if (*right_vol < 0)
                    408:                *right_vol = 0;
                    409: 
                    410:        scale = (1.0 - dist) * lscale;
                    411:        *left_vol = (int) (master_vol * scale);
                    412:        if (*left_vol < 0)
                    413:                *left_vol = 0;
                    414: }
                    415: 
                    416: /*
                    417: =================
                    418: S_Spatialize
                    419: =================
                    420: */
                    421: void S_Spatialize(channel_t *ch)
                    422: {
                    423:        vec3_t          origin;
                    424: 
                    425:        // anything coming from the view entity will always be full volume
                    426:        if (ch->entnum == cl.playernum+1)
                    427:        {
                    428:                ch->leftvol = ch->master_vol;
                    429:                ch->rightvol = ch->master_vol;
                    430:                return;
                    431:        }
                    432: 
                    433:        if (ch->fixed_origin)
                    434:        {
                    435:                VectorCopy (ch->origin, origin);
                    436:        }
                    437:        else
                    438:                CL_GetEntitySoundOrigin (ch->entnum, origin);
                    439: 
                    440:        S_SpatializeOrigin (origin, ch->master_vol, ch->dist_mult, &ch->leftvol, &ch->rightvol);
                    441: }           
                    442: 
                    443: 
                    444: /*
                    445: =================
                    446: S_AllocPlaysound
                    447: =================
                    448: */
                    449: playsound_t *S_AllocPlaysound (void)
                    450: {
                    451:        playsound_t     *ps;
                    452: 
                    453:        ps = s_freeplays.next;
                    454:        if (ps == &s_freeplays)
                    455:                return NULL;            // no free playsounds
                    456: 
                    457:        // unlink from freelist
                    458:        ps->prev->next = ps->next;
                    459:        ps->next->prev = ps->prev;
                    460:        
                    461:        return ps;
                    462: }
                    463: 
                    464: 
                    465: /*
                    466: =================
                    467: S_FreePlaysound
                    468: =================
                    469: */
                    470: void S_FreePlaysound (playsound_t *ps)
                    471: {
                    472:        // unlink from channel
                    473:        ps->prev->next = ps->next;
                    474:        ps->next->prev = ps->prev;
                    475: 
                    476:        // add to free list
                    477:        ps->next = s_freeplays.next;
                    478:        s_freeplays.next->prev = ps;
                    479:        ps->prev = &s_freeplays;
                    480:        s_freeplays.next = ps;
                    481: }
                    482: 
                    483: 
                    484: 
                    485: /*
                    486: ===============
                    487: S_IssuePlaysound
                    488: 
                    489: Take the next playsound and begin it on the channel
                    490: This is never called directly by S_Play*, but only
                    491: by the update loop.
                    492: ===============
                    493: */
                    494: void S_IssuePlaysound (playsound_t *ps)
                    495: {
                    496:        channel_t       *ch;
                    497:        sfxcache_t      *sc;
                    498: 
                    499:        if (s_show->value)
                    500:                Com_Printf ("Issue %i\n", ps->begin);
                    501:        // pick a channel to play on
                    502:        ch = S_PickChannel(ps->entnum, ps->entchannel);
                    503:        if (!ch)
                    504:        {
                    505:                S_FreePlaysound (ps);
                    506:                return;
                    507:        }
                    508: 
                    509:        // spatialize
                    510:        if (ps->attenuation == ATTN_STATIC)
                    511:                ch->dist_mult = ps->attenuation * 0.001;
                    512:        else
                    513:                ch->dist_mult = ps->attenuation * 0.0005;
                    514:        ch->master_vol = ps->volume;
                    515:        ch->entnum = ps->entnum;
                    516:        ch->entchannel = ps->entchannel;
                    517:        ch->sfx = ps->sfx;
                    518:        VectorCopy (ps->origin, ch->origin);
                    519:        ch->fixed_origin = ps->fixed_origin;
                    520: 
                    521:        S_Spatialize(ch);
                    522: 
                    523:        ch->pos = 0;
                    524:        sc = S_LoadSound (ch->sfx);
                    525:     ch->end = paintedtime + sc->length;
                    526: 
                    527:        // free the playsound
                    528:        S_FreePlaysound (ps);
                    529: }
                    530: 
                    531: 
                    532: struct sfx_s *S_RegisterSexedSound (entity_state_t *ent, char *base)
                    533: {
                    534:        int                             n;
                    535:        char                    *p;
                    536:        struct sfx_s    *sfx;
                    537:        FILE                    *f;
                    538:        char                    model[MAX_QPATH];
                    539:        char                    buffer[MAX_QPATH];
                    540: 
                    541:        // determine what model the client is using
                    542:        model[0] = 0;
                    543:        n = CS_PLAYERSKINS + ent->number - 1;
                    544:        if (cl.configstrings[n][0])
                    545:        {
                    546:                p = strchr(cl.configstrings[n], '\\');
                    547:                if (p)
                    548:                {
                    549:                        p += 1;
                    550:                        strcpy(model, p);
                    551:                        p = strchr(model, '/');
                    552:                        if (p)
                    553:                                *p = 0;
                    554:                }
                    555:        }
                    556:        // if we can't figure it out, they're male
                    557:        if (!model[0])
                    558:                strcpy(model, "male");
                    559: 
                    560:        // see if we already know of the model specific sound
                    561:        Com_sprintf (buffer, sizeof(buffer), "#players/%s/%s", model, base+1);
                    562:        sfx = S_FindName (buffer, false);
                    563: 
                    564:        if (!sfx)
                    565:        {
                    566:                // no, so see if it exists
                    567:                FS_FOpenFile (&buffer[1], &f);
                    568:                if (f)
                    569:                {
                    570:                        // yes, close the file and register it
                    571:                        FS_FCloseFile (f);
                    572:                        sfx = S_RegisterSound (buffer);
                    573:                }
                    574:                else
                    575:                {
                    576:                        // no, revert to the male sound in the pak0.pak
                    577:                        Com_sprintf (buffer, sizeof(buffer), "player/%s/%s", "male", base+1);
                    578:                        sfx = S_FindName (buffer, true);
                    579:                }
                    580:        }
                    581: 
                    582:        return sfx;
                    583: }
                    584: 
                    585: // =======================================================================
                    586: // Start a sound effect
                    587: // =======================================================================
                    588: 
                    589: /*
                    590: ====================
                    591: S_StartSound
                    592: 
                    593: Validates the parms and ques the sound up
                    594: if pos is NULL, the sound will be dynamically sourced from the entity
                    595: Entchannel 0 will never override a playing sound
                    596: ====================
                    597: */
                    598: void S_StartSound(vec3_t origin, int entnum, int entchannel, sfx_t *sfx, float fvol, float attenuation, float timeofs)
                    599: {
                    600:        sfxcache_t      *sc;
                    601:        int                     vol;
                    602:        playsound_t     *ps, *sort;
                    603:        int                     start;
                    604: 
                    605:        if (!sound_started)
                    606:                return;
                    607: 
                    608:        if (!sfx)
                    609:                return;
                    610: 
                    611:        if (sfx->name[0] == '*')
                    612:                sfx = S_RegisterSexedSound(&cl_entities[entnum].current, sfx->name);
                    613: 
                    614:        // make sure the sound is loaded
                    615:        sc = S_LoadSound (sfx);
                    616:        if (!sc)
                    617:                return;         // couldn't load the sound's data
                    618: 
                    619:        vol = fvol*255;
                    620: 
                    621:        // make the playsound_t
                    622:        ps = S_AllocPlaysound ();
                    623:        if (!ps)
                    624:                return;
                    625: 
                    626:        if (origin)
                    627:        {
                    628:                VectorCopy (origin, ps->origin);
                    629:                ps->fixed_origin = true;
                    630:        }
                    631:        else
                    632:                ps->fixed_origin = false;
                    633: 
                    634:        ps->entnum = entnum;
                    635:        ps->entchannel = entchannel;
                    636:        ps->attenuation = attenuation;
                    637:        ps->volume = vol;
                    638:        ps->sfx = sfx;
                    639: 
                    640:        // drift s_beginofs
                    641:        start = cl.frame.servertime * 0.001 * dma.speed + s_beginofs;
                    642:        if (start < paintedtime)
                    643:        {
                    644:                start = paintedtime;
                    645:                s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
                    646:        }
                    647:        else if (start > paintedtime + 0.3 * dma.speed)
                    648:        {
                    649:                start = paintedtime + 0.1 * dma.speed;
                    650:                s_beginofs = start - (cl.frame.servertime * 0.001 * dma.speed);
                    651:        }
                    652:        else
                    653:        {
                    654:                s_beginofs-=10;
                    655:        }
                    656: 
                    657:        if (!timeofs)
                    658:                ps->begin = paintedtime;
                    659:        else
                    660:                ps->begin = start + timeofs * dma.speed;
                    661: 
                    662:        // sort into the pending sound list
                    663:        for (sort = s_pendingplays.next ; 
                    664:                sort != &s_pendingplays && sort->begin < ps->begin ;
                    665:                sort = sort->next)
                    666:                        ;
                    667: 
                    668:        ps->next = sort;
                    669:        ps->prev = sort->prev;
                    670: 
                    671:        ps->next->prev = ps;
                    672:        ps->prev->next = ps;
                    673: }
                    674: 
                    675: 
                    676: /*
                    677: ==================
                    678: S_StartLocalSound
                    679: ==================
                    680: */
                    681: void S_StartLocalSound (char *sound)
                    682: {
                    683:        sfx_t   *sfx;
                    684: 
                    685:        if (!sound_started)
                    686:                return;
                    687:                
                    688:        sfx = S_RegisterSound (sound);
                    689:        if (!sfx)
                    690:        {
                    691:                Com_Printf ("S_StartLocalSound: can't cache %s\n", sound);
                    692:                return;
                    693:        }
                    694:        S_StartSound (NULL, cl.playernum+1, 0, sfx, 1, 1, 0);
                    695: }
                    696: 
                    697: 
                    698: /*
                    699: ==================
                    700: S_ClearBuffer
                    701: ==================
                    702: */
                    703: void S_ClearBuffer (void)
                    704: {
                    705:        int             clear;
                    706:                
                    707:        if (!sound_started)
                    708:                return;
                    709: 
                    710:        s_rawend = 0;
                    711: 
                    712:        if (dma.samplebits == 8)
                    713:                clear = 0x80;
                    714:        else
                    715:                clear = 0;
                    716: 
                    717:        SNDDMA_BeginPainting ();
                    718:        if (dma.buffer)
                    719:                memset(dma.buffer, clear, dma.samples * dma.samplebits/8);
                    720:        SNDDMA_Submit ();
                    721: }
                    722: 
                    723: /*
                    724: ==================
                    725: S_StopAllSounds
                    726: ==================
                    727: */
                    728: void S_StopAllSounds(void)
                    729: {
                    730:        int             i;
                    731: 
                    732:        if (!sound_started)
                    733:                return;
                    734: 
                    735:        // clear all the playsounds
                    736:        memset(s_playsounds, 0, sizeof(s_playsounds));
                    737:        s_freeplays.next = s_freeplays.prev = &s_freeplays;
                    738:        s_pendingplays.next = s_pendingplays.prev = &s_pendingplays;
                    739: 
                    740:        for (i=0 ; i<MAX_PLAYSOUNDS ; i++)
                    741:        {
                    742:                s_playsounds[i].prev = &s_freeplays;
                    743:                s_playsounds[i].next = s_freeplays.next;
                    744:                s_playsounds[i].prev->next = &s_playsounds[i];
                    745:                s_playsounds[i].next->prev = &s_playsounds[i];
                    746:        }
                    747: 
                    748:        // clear all the channels
                    749:        memset(channels, 0, sizeof(channels));
                    750: 
                    751:        S_ClearBuffer ();
                    752: }
                    753: 
                    754: /*
                    755: ==================
                    756: S_AddLoopSounds
                    757: 
                    758: Entities with a ->sound field will generated looped sounds
                    759: that are automatically started, stopped, and merged together
                    760: as the entities are sent to the client
                    761: ==================
                    762: */
                    763: void S_AddLoopSounds (void)
                    764: {
                    765:        int                     i, j;
                    766:        int                     sounds[MAX_EDICTS];
                    767:        int                     left, right, left_total, right_total;
                    768:        channel_t       *ch;
                    769:        sfx_t           *sfx;
                    770:        sfxcache_t      *sc;
                    771:        int                     num;
                    772:        entity_state_t  *ent;
                    773: 
                    774:        if (cl_paused->value)
                    775:                return;
                    776: 
                    777:        if (cls.state != ca_active)
                    778:                return;
                    779: 
                    780:        if (!cl.sound_prepped)
                    781:                return;
                    782: 
                    783:        for (i=0 ; i<cl.frame.num_entities ; i++)
                    784:        {
                    785:                num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
                    786:                ent = &cl_parse_entities[num];
                    787:                sounds[i] = ent->sound;
                    788:        }
                    789: 
                    790:        for (i=0 ; i<cl.frame.num_entities ; i++)
                    791:        {
                    792:                if (!sounds[i])
                    793:                        continue;
                    794: 
                    795:                sfx = cl.sound_precache[sounds[i]];
                    796:                if (!sfx)
                    797:                        continue;               // bad sound effect
                    798:                sc = sfx->cache;
                    799:                if (!sc)
                    800:                        continue;
                    801: 
                    802:                num = (cl.frame.parse_entities + i)&(MAX_PARSE_ENTITIES-1);
                    803:                ent = &cl_parse_entities[num];
                    804: 
                    805:                // find the total contribution of all sounds of this type
                    806:                S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE,
                    807:                        &left_total, &right_total);
                    808:                for (j=i+1 ; j<cl.frame.num_entities ; j++)
                    809:                {
                    810:                        if (sounds[j] != sounds[i])
                    811:                                continue;
                    812:                        sounds[j] = 0;  // don't check this again later
                    813: 
                    814:                        num = (cl.frame.parse_entities + j)&(MAX_PARSE_ENTITIES-1);
                    815:                        ent = &cl_parse_entities[num];
                    816: 
                    817:                        S_SpatializeOrigin (ent->origin, 255.0, SOUND_LOOPATTENUATE, 
                    818:                                &left, &right);
                    819:                        left_total += left;
                    820:                        right_total += right;
                    821:                }
                    822: 
                    823:                if (left_total == 0 && right_total == 0)
                    824:                        continue;               // not audible
                    825: 
                    826:                // allocate a channel
                    827:                ch = S_PickChannel(0, 0);
                    828:                if (!ch)
                    829:                        return;
                    830: 
                    831:                if (left_total > 255)
                    832:                        left_total = 255;
                    833:                if (right_total > 255)
                    834:                        right_total = 255;
                    835:                ch->leftvol = left_total;
                    836:                ch->rightvol = right_total;
                    837:                ch->autosound = true;   // remove next frame
                    838:                ch->sfx = sfx;
                    839:                ch->pos = paintedtime % sc->length;
                    840:                ch->end = paintedtime + sc->length - ch->pos;
                    841:        }
                    842: }
                    843: 
                    844: //=============================================================================
                    845: 
                    846: /*
                    847: ============
                    848: S_RawSamples
                    849: 
                    850: Cinematic streaming and voice over network
                    851: ============
                    852: */
                    853: void S_RawSamples (int samples, int rate, int width, int channels, byte *data)
                    854: {
                    855:        int             i;
                    856:        int             src, dst;
                    857:        float   scale;
                    858: 
                    859:        if (!sound_started)
                    860:                return;
                    861: 
                    862:        if (s_rawend < paintedtime)
                    863:                s_rawend = paintedtime;
                    864:        scale = (float)rate / dma.speed;
                    865: 
                    866: //Com_Printf ("%i < %i < %i\n", soundtime, paintedtime, s_rawend);
                    867:        if (channels == 2 && width == 2)
                    868:        {
                    869:                if (scale == 1.0)
                    870:                {       // optimized case
                    871:                        for (i=0 ; i<samples ; i++)
                    872:                        {
                    873:                                dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    874:                                s_rawend++;
                    875:                                s_rawsamples[dst].left = ((short *)data)[i*2] << 8;
                    876:                                s_rawsamples[dst].right = ((short *)data)[i*2+1] << 8;
                    877:                        }
                    878:                }
                    879:                else
                    880:                {
                    881:                        for (i=0 ; ; i++)
                    882:                        {
                    883:                                src = i*scale;
                    884:                                if (src >= samples)
                    885:                                        break;
                    886:                                dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    887:                                s_rawend++;
                    888:                                s_rawsamples[dst].left = ((short *)data)[src*2] << 8;
                    889:                                s_rawsamples[dst].right = ((short *)data)[src*2+1] << 8;
                    890:                        }
                    891:                }
                    892:        }
                    893:        else if (channels == 1 && width == 2)
                    894:        {
                    895:                for (i=0 ; ; i++)
                    896:                {
                    897:                        src = i*scale;
                    898:                        if (src >= samples)
                    899:                                break;
                    900:                        dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    901:                        s_rawend++;
                    902:                        s_rawsamples[dst].left = ((short *)data)[src] << 8;
                    903:                        s_rawsamples[dst].right = ((short *)data)[src] << 8;
                    904:                }
                    905:        }
                    906:        else if (channels == 2 && width == 1)
                    907:        {
                    908:                for (i=0 ; ; i++)
                    909:                {
                    910:                        src = i*scale;
                    911:                        if (src >= samples)
                    912:                                break;
                    913:                        dst = s_rawend&(MAX_RAW_SAMPLES-1);
                    914:                        s_rawend++;
                    915:                        s_rawsamples[dst].left = ((char *)data)[src*2] << 16;
                    916:                        s_rawsamples[dst].right = ((char *)data)[src*2+1] << 16;
                    917:                }
                    918:        }
                    919:        else if (channels == 1 && width == 1)
                    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++;
                    928:                        s_rawsamples[dst].left = (((byte *)data)[src]-128) << 16;
                    929:                        s_rawsamples[dst].right = (((byte *)data)[src]-128) << 16;
                    930:                }
                    931:        }
                    932: }
                    933: 
                    934: //=============================================================================
                    935: 
                    936: /*
                    937: ============
                    938: S_Update
                    939: 
                    940: Called once each time through the main loop
                    941: ============
                    942: */
                    943: void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up)
                    944: {
                    945:        int                     i;
                    946:        int                     total;
                    947:        channel_t       *ch;
                    948:        channel_t       *combine;
                    949: 
                    950:        if (!sound_started)
                    951:                return;
                    952: 
                    953:        // if the laoding plaque is up, clear everything
                    954:        // out to make sure we aren't looping a dirty
                    955:        // dma buffer while loading
                    956:        if (cls.disable_screen)
                    957:        {
                    958:                S_ClearBuffer ();
                    959:                return;
                    960:        }
                    961: 
                    962:        // rebuild scale tables if volume is modified
                    963:        if (s_volume->modified)
                    964:                S_InitScaletable ();
                    965: 
                    966:        VectorCopy(origin, listener_origin);
                    967:        VectorCopy(forward, listener_forward);
                    968:        VectorCopy(right, listener_right);
                    969:        VectorCopy(up, listener_up);
                    970: 
                    971:        combine = NULL;
                    972: 
                    973:        // update spatialization for dynamic sounds     
                    974:        ch = channels;
                    975:        for (i=0 ; i<MAX_CHANNELS; i++, ch++)
                    976:        {
                    977:                if (!ch->sfx)
                    978:                        continue;
                    979:                if (ch->autosound)
                    980:                {       // autosounds are regenerated fresh each frame
                    981:                        memset (ch, 0, sizeof(*ch));
                    982:                        continue;
                    983:                }
                    984:                S_Spatialize(ch);         // respatialize channel
                    985:                if (!ch->leftvol && !ch->rightvol)
                    986:                {
                    987:                        memset (ch, 0, sizeof(*ch));
                    988:                        continue;
                    989:                }
                    990:        }
                    991: 
                    992:        // add loopsounds
                    993:        S_AddLoopSounds ();
                    994: 
                    995:        //
                    996:        // debugging output
                    997:        //
                    998:        if (s_show->value)
                    999:        {
                   1000:                total = 0;
                   1001:                ch = channels;
                   1002:                for (i=0 ; i<MAX_CHANNELS; i++, ch++)
                   1003:                        if (ch->sfx && (ch->leftvol || ch->rightvol) )
                   1004:                        {
                   1005:                                Com_Printf ("%3i %3i %s\n", ch->leftvol, ch->rightvol, ch->sfx->name);
                   1006:                                total++;
                   1007:                        }
                   1008:                
                   1009:                Com_Printf ("----(%i)---- painted: %i\n", total, paintedtime);
                   1010:        }
                   1011: 
                   1012: // mix some sound
                   1013:        S_Update_();
                   1014: }
                   1015: 
                   1016: void GetSoundtime(void)
                   1017: {
                   1018:        int             samplepos;
                   1019:        static  int             buffers;
                   1020:        static  int             oldsamplepos;
                   1021:        int             fullsamples;
                   1022:        
                   1023:        fullsamples = dma.samples / dma.channels;
                   1024: 
                   1025: // it is possible to miscount buffers if it has wrapped twice between
                   1026: // calls to S_Update.  Oh well.
                   1027:        samplepos = SNDDMA_GetDMAPos();
                   1028: 
                   1029:        if (samplepos < oldsamplepos)
                   1030:        {
                   1031:                buffers++;                                      // buffer wrapped
                   1032:                
                   1033:                if (paintedtime > 0x40000000)
                   1034:                {       // time to chop things off to avoid 32 bit limits
                   1035:                        buffers = 0;
                   1036:                        paintedtime = fullsamples;
                   1037:                        S_StopAllSounds ();
                   1038:                }
                   1039:        }
                   1040:        oldsamplepos = samplepos;
                   1041: 
                   1042:        soundtime = buffers*fullsamples + samplepos/dma.channels;
                   1043: }
                   1044: 
                   1045: 
                   1046: void S_Update_(void)
                   1047: {
                   1048:        unsigned        endtime;
                   1049:        int                             samps;
                   1050: 
                   1051:        if (!sound_started)
                   1052:                return;
                   1053: 
                   1054:        SNDDMA_BeginPainting ();
                   1055: 
                   1056:        if (!dma.buffer)
                   1057:                return;
                   1058: 
                   1059: // Updates DMA time
                   1060:        GetSoundtime();
                   1061: 
                   1062: // check to make sure that we haven't overshot
                   1063:        if (paintedtime < soundtime)
                   1064:        {
                   1065:                Com_DPrintf ("S_Update_ : overflow\n");
                   1066:                paintedtime = soundtime;
                   1067:        }
                   1068: 
                   1069: // mix ahead of current position
                   1070:        endtime = soundtime + s_mixahead->value * dma.speed;
                   1071: //endtime = (soundtime + 4096) & ~4095;
                   1072: 
                   1073:        // mix to an even submission block size
                   1074:        endtime = (endtime + dma.submission_chunk-1)
                   1075:                & ~(dma.submission_chunk-1);
                   1076:        samps = dma.samples >> (dma.channels-1);
                   1077:        if (endtime - soundtime > samps)
                   1078:                endtime = soundtime + samps;
                   1079: 
                   1080:        S_PaintChannels (endtime);
                   1081: 
                   1082:        SNDDMA_Submit ();
                   1083: }
                   1084: 
                   1085: /*
                   1086: ===============================================================================
                   1087: 
                   1088: console functions
                   1089: 
                   1090: ===============================================================================
                   1091: */
                   1092: 
                   1093: void S_Play(void)
                   1094: {
                   1095:        int     i;
                   1096:        char name[256];
                   1097:        sfx_t   *sfx;
                   1098:        
                   1099:        i = 1;
                   1100:        while (i<Cmd_Argc())
                   1101:        {
                   1102:                if (!strrchr(Cmd_Argv(i), '.'))
                   1103:                {
                   1104:                        strcpy(name, Cmd_Argv(i));
                   1105:                        strcat(name, ".wav");
                   1106:                }
                   1107:                else
                   1108:                        strcpy(name, Cmd_Argv(i));
                   1109:                sfx = S_RegisterSound(name);
                   1110:                S_StartSound(NULL, cl.playernum+1, 0, sfx, 1.0, 1.0, 0);
                   1111:                i++;
                   1112:        }
                   1113: }
                   1114: 
                   1115: void S_SoundList(void)
                   1116: {
                   1117:        int             i;
                   1118:        sfx_t   *sfx;
                   1119:        sfxcache_t      *sc;
                   1120:        int             size, total;
                   1121: 
                   1122:        total = 0;
                   1123:        for (sfx=known_sfx, i=0 ; i<num_sfx ; i++, sfx++)
                   1124:        {
                   1125:                if (!sfx->registration_sequence)
                   1126:                        continue;
                   1127:                sc = sfx->cache;
                   1128:                if (sc)
                   1129:                {
                   1130:                        size = sc->length*sc->width*(sc->stereo+1);
                   1131:                        total += size;
                   1132:                        if (sc->loopstart >= 0)
                   1133:                                Com_Printf ("L");
                   1134:                        else
                   1135:                                Com_Printf (" ");
                   1136:                        Com_Printf("(%2db) %6i : %s\n",sc->width*8,  size, sfx->name);
                   1137:                }
                   1138:                else
                   1139:                {
                   1140:                        if (sfx->name[0] == '*')
                   1141:                                Com_Printf("  placeholder : %s\n", sfx->name);
                   1142:                        else
                   1143:                                Com_Printf("  not loaded  : %s\n", sfx->name);
                   1144:                }
                   1145:        }
                   1146:        Com_Printf ("Total resident: %i\n", total);
                   1147: }
                   1148: 

unix.superglobalmegacorp.com

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