|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.