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