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