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