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

1.1.1.3 ! root        1: /*
        !             2: Copyright (C) 1997-2001 Id Software, Inc.
        !             3: 
        !             4: This program is free software; you can redistribute it and/or
        !             5: modify it under the terms of the GNU General Public License
        !             6: as published by the Free Software Foundation; either version 2
        !             7: of the License, or (at your option) any later version.
        !             8: 
        !             9: This program is distributed in the hope that it will be useful,
        !            10: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
        !            12: 
        !            13: See the GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with this program; if not, write to the Free Software
        !            17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        !            18: 
        !            19: */
1.1       root       20: // snd_mem.c: sound caching
                     21: 
                     22: #include "client.h"
                     23: #include "snd_loc.h"
                     24: 
                     25: int                    cache_full_cycle;
                     26: 
                     27: byte *S_Alloc (int size);
                     28: 
                     29: /*
                     30: ================
                     31: ResampleSfx
                     32: ================
                     33: */
                     34: void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data)
                     35: {
                     36:        int             outcount;
                     37:        int             srcsample;
                     38:        float   stepscale;
                     39:        int             i;
                     40:        int             sample, samplefrac, fracstep;
                     41:        sfxcache_t      *sc;
                     42:        
                     43:        sc = sfx->cache;
                     44:        if (!sc)
                     45:                return;
                     46: 
                     47:        stepscale = (float)inrate / dma.speed;  // this is usually 0.5, 1, or 2
                     48: 
                     49:        outcount = sc->length / stepscale;
                     50:        sc->length = outcount;
                     51:        if (sc->loopstart != -1)
                     52:                sc->loopstart = sc->loopstart / stepscale;
                     53: 
                     54:        sc->speed = dma.speed;
                     55:        if (s_loadas8bit->value)
                     56:                sc->width = 1;
                     57:        else
                     58:                sc->width = inwidth;
                     59:        sc->stereo = 0;
                     60: 
                     61: // resample / decimate to the current source rate
                     62: 
                     63:        if (stepscale == 1 && inwidth == 1 && sc->width == 1)
                     64:        {
                     65: // fast special case
                     66:                for (i=0 ; i<outcount ; i++)
                     67:                        ((signed char *)sc->data)[i]
                     68:                        = (int)( (unsigned char)(data[i]) - 128);
                     69:        }
                     70:        else
                     71:        {
                     72: // general case
                     73:                samplefrac = 0;
                     74:                fracstep = stepscale*256;
                     75:                for (i=0 ; i<outcount ; i++)
                     76:                {
                     77:                        srcsample = samplefrac >> 8;
                     78:                        samplefrac += fracstep;
                     79:                        if (inwidth == 2)
                     80:                                sample = LittleShort ( ((short *)data)[srcsample] );
                     81:                        else
                     82:                                sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
                     83:                        if (sc->width == 2)
                     84:                                ((short *)sc->data)[i] = sample;
                     85:                        else
                     86:                                ((signed char *)sc->data)[i] = sample >> 8;
                     87:                }
                     88:        }
                     89: }
                     90: 
                     91: //=============================================================================
                     92: 
                     93: /*
                     94: ==============
                     95: S_LoadSound
                     96: ==============
                     97: */
                     98: sfxcache_t *S_LoadSound (sfx_t *s)
                     99: {
                    100:     char       namebuffer[MAX_QPATH];
                    101:        byte    *data;
                    102:        wavinfo_t       info;
                    103:        int             len;
                    104:        float   stepscale;
                    105:        sfxcache_t      *sc;
                    106:        int             size;
1.1.1.2   root      107:        char    *name;
1.1       root      108: 
                    109:        if (s->name[0] == '*')
                    110:                return NULL;
                    111: 
                    112: // see if still in memory
                    113:        sc = s->cache;
                    114:        if (sc)
                    115:                return sc;
                    116: 
                    117: //Com_Printf ("S_LoadSound: %x\n", (int)stackbuf);
                    118: // load it in
1.1.1.2   root      119:        if (s->truename)
                    120:                name = s->truename;
1.1       root      121:        else
1.1.1.2   root      122:                name = s->name;
                    123: 
                    124:        if (name[0] == '#')
                    125:                strcpy(namebuffer, &name[1]);
                    126:        else
                    127:                Com_sprintf (namebuffer, sizeof(namebuffer), "sound/%s", name);
1.1       root      128: 
                    129: //     Com_Printf ("loading %s\n",namebuffer);
                    130: 
                    131:        size = FS_LoadFile (namebuffer, (void **)&data);
                    132: 
                    133:        if (!data)
                    134:        {
1.1.1.2   root      135:                Com_DPrintf ("Couldn't load %s\n", namebuffer);
1.1       root      136:                return NULL;
                    137:        }
                    138: 
                    139:        info = GetWavinfo (s->name, data, size);
                    140:        if (info.channels != 1)
                    141:        {
                    142:                Com_Printf ("%s is a stereo sample\n",s->name);
                    143:                FS_FreeFile (data);
                    144:                return NULL;
                    145:        }
                    146: 
                    147:        stepscale = (float)info.rate / dma.speed;       
                    148:        len = info.samples / stepscale;
                    149: 
                    150:        len = len * info.width * info.channels;
                    151: 
                    152:        sc = s->cache = Z_Malloc (len + sizeof(sfxcache_t));
                    153:        if (!sc)
                    154:        {
                    155:                FS_FreeFile (data);
                    156:                return NULL;
                    157:        }
                    158:        
                    159:        sc->length = info.samples;
                    160:        sc->loopstart = info.loopstart;
                    161:        sc->speed = info.rate;
                    162:        sc->width = info.width;
                    163:        sc->stereo = info.channels;
                    164: 
                    165:        ResampleSfx (s, sc->speed, sc->width, data + info.dataofs);
                    166: 
                    167:        FS_FreeFile (data);
                    168: 
                    169:        return sc;
                    170: }
                    171: 
                    172: 
                    173: 
                    174: /*
                    175: ===============================================================================
                    176: 
                    177: WAV loading
                    178: 
                    179: ===============================================================================
                    180: */
                    181: 
                    182: 
                    183: byte   *data_p;
                    184: byte   *iff_end;
                    185: byte   *last_chunk;
                    186: byte   *iff_data;
                    187: int    iff_chunk_len;
                    188: 
                    189: 
                    190: short GetLittleShort(void)
                    191: {
                    192:        short val = 0;
                    193:        val = *data_p;
                    194:        val = val + (*(data_p+1)<<8);
                    195:        data_p += 2;
                    196:        return val;
                    197: }
                    198: 
                    199: int GetLittleLong(void)
                    200: {
                    201:        int val = 0;
                    202:        val = *data_p;
                    203:        val = val + (*(data_p+1)<<8);
                    204:        val = val + (*(data_p+2)<<16);
                    205:        val = val + (*(data_p+3)<<24);
                    206:        data_p += 4;
                    207:        return val;
                    208: }
                    209: 
                    210: void FindNextChunk(char *name)
                    211: {
                    212:        while (1)
                    213:        {
                    214:                data_p=last_chunk;
                    215: 
                    216:                if (data_p >= iff_end)
                    217:                {       // didn't find the chunk
                    218:                        data_p = NULL;
                    219:                        return;
                    220:                }
                    221:                
                    222:                data_p += 4;
                    223:                iff_chunk_len = GetLittleLong();
                    224:                if (iff_chunk_len < 0)
                    225:                {
                    226:                        data_p = NULL;
                    227:                        return;
                    228:                }
                    229: //             if (iff_chunk_len > 1024*1024)
                    230: //                     Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
                    231:                data_p -= 8;
                    232:                last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
                    233:                if (!strncmp(data_p, name, 4))
                    234:                        return;
                    235:        }
                    236: }
                    237: 
                    238: void FindChunk(char *name)
                    239: {
                    240:        last_chunk = iff_data;
                    241:        FindNextChunk (name);
                    242: }
                    243: 
                    244: 
                    245: void DumpChunks(void)
                    246: {
                    247:        char    str[5];
                    248:        
                    249:        str[4] = 0;
                    250:        data_p=iff_data;
                    251:        do
                    252:        {
                    253:                memcpy (str, data_p, 4);
                    254:                data_p += 4;
                    255:                iff_chunk_len = GetLittleLong();
                    256:                Com_Printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
                    257:                data_p += (iff_chunk_len + 1) & ~1;
                    258:        } while (data_p < iff_end);
                    259: }
                    260: 
                    261: /*
                    262: ============
                    263: GetWavinfo
                    264: ============
                    265: */
                    266: wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
                    267: {
                    268:        wavinfo_t       info;
                    269:        int     i;
                    270:        int     format;
                    271:        int             samples;
                    272: 
                    273:        memset (&info, 0, sizeof(info));
                    274: 
                    275:        if (!wav)
                    276:                return info;
                    277:                
                    278:        iff_data = wav;
                    279:        iff_end = wav + wavlength;
                    280: 
                    281: // find "RIFF" chunk
                    282:        FindChunk("RIFF");
                    283:        if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
                    284:        {
                    285:                Com_Printf("Missing RIFF/WAVE chunks\n");
                    286:                return info;
                    287:        }
                    288: 
                    289: // get "fmt " chunk
                    290:        iff_data = data_p + 12;
                    291: // DumpChunks ();
                    292: 
                    293:        FindChunk("fmt ");
                    294:        if (!data_p)
                    295:        {
                    296:                Com_Printf("Missing fmt chunk\n");
                    297:                return info;
                    298:        }
                    299:        data_p += 8;
                    300:        format = GetLittleShort();
                    301:        if (format != 1)
                    302:        {
                    303:                Com_Printf("Microsoft PCM format only\n");
                    304:                return info;
                    305:        }
                    306: 
                    307:        info.channels = GetLittleShort();
                    308:        info.rate = GetLittleLong();
                    309:        data_p += 4+2;
                    310:        info.width = GetLittleShort() / 8;
                    311: 
                    312: // get cue chunk
                    313:        FindChunk("cue ");
                    314:        if (data_p)
                    315:        {
                    316:                data_p += 32;
                    317:                info.loopstart = GetLittleLong();
                    318: //             Com_Printf("loopstart=%d\n", sfx->loopstart);
                    319: 
                    320:        // if the next chunk is a LIST chunk, look for a cue length marker
                    321:                FindNextChunk ("LIST");
                    322:                if (data_p)
                    323:                {
                    324:                        if (!strncmp (data_p + 28, "mark", 4))
                    325:                        {       // this is not a proper parse, but it works with cooledit...
                    326:                                data_p += 24;
                    327:                                i = GetLittleLong ();   // samples in loop
                    328:                                info.samples = info.loopstart + i;
                    329: //                             Com_Printf("looped length: %i\n", i);
                    330:                        }
                    331:                }
                    332:        }
                    333:        else
                    334:                info.loopstart = -1;
                    335: 
                    336: // find data chunk
                    337:        FindChunk("data");
                    338:        if (!data_p)
                    339:        {
                    340:                Com_Printf("Missing data chunk\n");
                    341:                return info;
                    342:        }
                    343: 
                    344:        data_p += 4;
                    345:        samples = GetLittleLong () / info.width;
                    346: 
                    347:        if (info.samples)
                    348:        {
                    349:                if (samples < info.samples)
                    350:                        Com_Error (ERR_DROP, "Sound %s has a bad loop length", name);
                    351:        }
                    352:        else
                    353:                info.samples = samples;
                    354: 
                    355:        info.dataofs = data_p - wav;
                    356:        
                    357:        return info;
                    358: }
                    359: 

unix.superglobalmegacorp.com

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