diff options
Diffstat (limited to 'src/jake2/client/SND_MEM.java')
-rw-r--r-- | src/jake2/client/SND_MEM.java | 550 |
1 files changed, 270 insertions, 280 deletions
diff --git a/src/jake2/client/SND_MEM.java b/src/jake2/client/SND_MEM.java index a5f7671..85215d1 100644 --- a/src/jake2/client/SND_MEM.java +++ b/src/jake2/client/SND_MEM.java @@ -2,7 +2,7 @@ * SND_MEM.java * Copyright (C) 2004 * - * $Id: SND_MEM.java,v 1.1 2004-07-07 19:58:52 hzi Exp $ + * $Id: SND_MEM.java,v 1.2 2004-07-08 15:58:42 hzi Exp $ */ /* Copyright (C) 1997-2001 Id Software, Inc. @@ -25,6 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package jake2.client; +import jake2.qcommon.Com; +import jake2.qcommon.FS; + /** * SND_MEM */ @@ -39,52 +42,51 @@ public class SND_MEM extends SND_JAVA { // // byte *S_Alloc (int size); // -// /* -// ================ -// ResampleSfx -// ================ -// */ -// void ResampleSfx (sfx_t *sfx, int inrate, int inwidth, byte *data) -// { -// int outcount; -// int srcsample; -// float stepscale; -// int i; -// int sample, samplefrac, fracstep; -// sfxcache_t *sc; -// -// sc = sfx->cache; -// if (!sc) -// return; -// -// stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 -// -// outcount = sc->length / stepscale; -// sc->length = outcount; -// if (sc->loopstart != -1) -// sc->loopstart = sc->loopstart / stepscale; -// -// sc->speed = dma.speed; -// if (s_loadas8bit->value) -// sc->width = 1; -// else -// sc->width = inwidth; -// sc->stereo = 0; -// -//// resample / decimate to the current source rate -// -// if (stepscale == 1 && inwidth == 1 && sc->width == 1) -// { -//// fast special case -// for (i=0 ; i<outcount ; i++) -// ((signed char *)sc->data)[i] -// = (int)( (unsigned char)(data[i]) - 128); -// } -// else -// { -//// general case -// samplefrac = 0; -// fracstep = stepscale*256; + /* + ================ + ResampleSfx + ================ + */ + static void ResampleSfx (sfx_t sfx, int inrate, int inwidth, byte[] data, int ofs) + { + int outcount; + int srcsample; + float stepscale; + int i; + int sample, samplefrac, fracstep; + sfxcache_t sc; + + sc = sfx.cache; + if (sc == null) + return; + + stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2 + + outcount = (int)(sc.length / stepscale); + sc.length = outcount; + if (sc.loopstart != -1) + sc.loopstart = (int)(sc.loopstart / stepscale); + + sc.speed = dma.speed; + if (SND_DMA.s_loadas8bit.value != 0.0f) + sc.width = 1; + else + sc.width = inwidth; + sc.stereo = 0; + +// resample / decimate to the current source rate + + if (stepscale == 1 && inwidth == 1 && sc.width == 1) + { +// fast special case + for (i=0 ; i<outcount ; i++) + sc.data[i+ofs] = (byte)((data[i+ofs] & 0xFF) - 128); + } + else + { +// general case + samplefrac = 0; + fracstep = (int)(stepscale*256); // for (i=0 ; i<outcount ; i++) // { // srcsample = samplefrac >> 8; @@ -98,8 +100,8 @@ public class SND_MEM extends SND_JAVA { // else // ((signed char *)sc->data)[i] = sample >> 8; // } -// } -// } + } + } // //// ============================================================================= // @@ -108,77 +110,70 @@ public class SND_MEM extends SND_JAVA { S_LoadSound ============== */ - static sfxcache_t LoadSound (sfx_t s) - { -// char namebuffer[MAX_QPATH]; -// byte *data; -// wavinfo_t info; -// int len; -// float stepscale; - sfxcache_t sc = null; -// int size; -// char *name; -// -// if (s->name[0] == '*') -// return NULL; -// -//// see if still in memory -// sc = s->cache; -// if (sc) -// return sc; -// -//// Com_Printf ("S_LoadSound: %x\n", (int)stackbuf); -//// load it in -// if (s->truename) -// name = s->truename; -// else -// name = s->name; -// -// if (name[0] == '#') -// strcpy(namebuffer, &name[1]); -// else -// Com_sprintf (namebuffer, sizeof(namebuffer), "sound/%s", name); -// -//// Com_Printf ("loading %s\n",namebuffer); -// -// size = FS_LoadFile (namebuffer, (void **)&data); -// -// if (!data) -// { -// Com_DPrintf ("Couldn't load %s\n", namebuffer); -// return NULL; -// } -// -// info = GetWavinfo (s->name, data, size); -// if (info.channels != 1) -// { -// Com_Printf ("%s is a stereo sample\n",s->name); -// FS_FreeFile (data); -// return NULL; -// } -// -// stepscale = (float)info.rate / dma.speed; -// len = info.samples / stepscale; -// -// len = len * info.width * info.channels; -// -// sc = s->cache = Z_Malloc (len + sizeof(sfxcache_t)); -// if (!sc) -// { -// FS_FreeFile (data); -// return NULL; -// } -// -// sc->length = info.samples; -// sc->loopstart = info.loopstart; -// sc->speed = info.rate; -// sc->width = info.width; -// sc->stereo = info.channels; -// -// ResampleSfx (s, sc->speed, sc->width, data + info.dataofs); -// -// FS_FreeFile (data); -// + static sfxcache_t LoadSound(sfx_t s) { + String namebuffer; + byte[] data; + wavinfo_t info; + int len; + float stepscale; + sfxcache_t sc = null; + int size; + String name; + + if (s.name.charAt(0) == '*') + return null; + + // see if still in memory + sc = s.cache; + if (sc != null) + return sc; + + // load it in + if (s.truename != null) + name = s.truename; + else + name = s.name; + + if (name.charAt(0) == '#') + namebuffer = name.substring(1); + //strcpy(namebuffer, &name[1]); + else + namebuffer = "sound/" + name; + //Com_sprintf (namebuffer, sizeof(namebuffer), "sound/%s", name); + + data = FS.LoadFile(namebuffer); + + if (data == null) { + Com.DPrintf("Couldn't load " + namebuffer + "\n"); + return null; + } + size = data.length; + + info = GetWavinfo(s.name, data, size); + if (info.channels != 1) { + Com.Printf(s.name + " is a stereo sample\n"); + FS.FreeFile(data); + return null; + } + + stepscale = ((float)info.rate) / dma.speed; + len = (int) (info.samples / stepscale); + + len = len * info.width * info.channels; + + //sc = s.cache = Z_Malloc (len + sizeof(sfxcache_t)); + sc = s.cache = new sfxcache_t(len); + + sc.length = info.samples; + sc.loopstart = info.loopstart; + sc.speed = info.rate; + sc.width = info.width; + sc.stereo = info.channels; + + ResampleSfx(s, sc.speed, sc.width, data, info.dataofs); + + FS.FreeFile(data); + return sc; } // @@ -192,67 +187,65 @@ public class SND_MEM extends SND_JAVA { // =============================================================================== // */ // -// -// byte *data_p; -// byte *iff_end; -// byte *last_chunk; -// byte *iff_data; -// int iff_chunk_len; -// -// -// short GetLittleShort(void) -// { -// short val = 0; -// val = *data_p; -// val = val + (*(data_p+1)<<8); -// data_p += 2; -// return val; -// } -// -// int GetLittleLong(void) -// { -// int val = 0; -// val = *data_p; -// val = val + (*(data_p+1)<<8); -// val = val + (*(data_p+2)<<16); -// val = val + (*(data_p+3)<<24); -// data_p += 4; -// return val; -// } -// -// void FindNextChunk(char *name) -// { -// while (1) -// { -// data_p=last_chunk; -// -// if (data_p >= iff_end) -// { // didn't find the chunk -// data_p = NULL; -// return; -// } -// -// data_p += 4; -// iff_chunk_len = GetLittleLong(); -// if (iff_chunk_len < 0) -// { -// data_p = NULL; -// return; -// } -//// if (iff_chunk_len > 1024*1024) -//// Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); -// data_p -= 8; -// last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 ); -// if (!strncmp(data_p, name, 4)) -// return; -// } -// } -// -// void FindChunk(char *name) -// { -// last_chunk = iff_data; -// FindNextChunk (name); -// } + static byte[] data_b; + static int data_p; + static int iff_end; + static int last_chunk; + static int iff_data; + static int iff_chunk_len; + + + static short GetLittleShort() { + short val = 0; + val = data_b[data_p]; + data_p++; + val |= (data_b[data_p] << 8); + data_p++; + return val; + } + + static int GetLittleLong() { + int val = 0; + val = data_b[data_p]; + data_p++; + val |= (data_b[data_p] << 8); + data_p++; + val |= (data_b[data_p] << 16); + data_p++; + val |= (data_b[data_p] << 24); + data_p++; + return val; + } + + static void FindNextChunk(String name) { + while (true) { + data_p = last_chunk; + + if (data_p >= iff_end) { // didn't find the chunk + data_p = 0; + return; + } + + data_p += 4; + iff_chunk_len = GetLittleLong(); + if (iff_chunk_len < 0) { + data_p = 0; + return; + } + // if (iff_chunk_len > 1024*1024) + // Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len); + data_p -= 8; + last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1); + String s = new String(data_b, data_p, 4); + if (s.equals(name)) + return; + } + } + + static void FindChunk(String name) { + last_chunk = iff_data; + FindNextChunk(name); + } // // // void DumpChunks(void) @@ -271,104 +264,101 @@ public class SND_MEM extends SND_JAVA { // } while (data_p < iff_end); // } // -// /* -// ============ -// GetWavinfo -// ============ -// */ -// wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength) -// { -// wavinfo_t info; -// int i; -// int format; -// int samples; -// -// memset (&info, 0, sizeof(info)); -// -// if (!wav) -// return info; -// -// iff_data = wav; -// iff_end = wav + wavlength; -// -//// find "RIFF" chunk -// FindChunk("RIFF"); -// if (!(data_p && !strncmp(data_p+8, "WAVE", 4))) -// { -// Com_Printf("Missing RIFF/WAVE chunks\n"); -// return info; -// } -// -//// get "fmt " chunk -// iff_data = data_p + 12; -//// DumpChunks (); -// -// FindChunk("fmt "); -// if (!data_p) -// { -// Com_Printf("Missing fmt chunk\n"); -// return info; -// } -// data_p += 8; -// format = GetLittleShort(); -// if (format != 1) -// { -// Com_Printf("Microsoft PCM format only\n"); -// return info; -// } -// -// info.channels = GetLittleShort(); -// info.rate = GetLittleLong(); -// data_p += 4+2; -// info.width = GetLittleShort() / 8; -// -//// get cue chunk -// FindChunk("cue "); -// if (data_p) -// { -// data_p += 32; -// info.loopstart = GetLittleLong(); -//// Com_Printf("loopstart=%d\n", sfx->loopstart); -// -// // if the next chunk is a LIST chunk, look for a cue length marker -// FindNextChunk ("LIST"); -// if (data_p) -// { -// if (!strncmp (data_p + 28, "mark", 4)) -// { // this is not a proper parse, but it works with cooledit... -// data_p += 24; -// i = GetLittleLong (); // samples in loop -// info.samples = info.loopstart + i; -//// Com_Printf("looped length: %i\n", i); -// } -// } -// } -// else -// info.loopstart = -1; -// -//// find data chunk -// FindChunk("data"); -// if (!data_p) -// { -// Com_Printf("Missing data chunk\n"); -// return info; -// } -// -// data_p += 4; -// samples = GetLittleLong () / info.width; -// -// if (info.samples) -// { -// if (samples < info.samples) -// Com_Error (ERR_DROP, "Sound %s has a bad loop length", name); -// } -// else -// info.samples = samples; -// -// info.dataofs = data_p - wav; -// -// return info; -// } -// + /* + ============ + GetWavinfo + ============ + */ + static wavinfo_t GetWavinfo(String name, byte[] wav, int wavlength) { + wavinfo_t info = new wavinfo_t(); + int i; + int format; + int samples; + + if (wav == null) + return info; + + iff_data = 0; + iff_end = wavlength; + data_b = wav; + + // find "RIFF" chunk + FindChunk("RIFF"); + String s = new String(data_b, data_p + 8, 4); + if (!((data_p != 0) && s.equals("WAVE"))) { + Com.Printf("Missing RIFF/WAVE chunks\n"); + return info; + } + + // get "fmt " chunk + iff_data = data_p + 12; + // DumpChunks (); + + FindChunk("fmt "); + if (data_p == 0) { + Com.Printf("Missing fmt chunk\n"); + return info; + } + data_p += 8; + format = GetLittleShort(); + if (format != 1) { + Com.Printf("Microsoft PCM format only\n"); + return info; + } + + info.channels = GetLittleShort(); + info.rate = GetLittleLong(); + data_p += 4 + 2; + info.width = GetLittleShort() / 8; + + // get cue chunk + FindChunk("cue "); + if (data_p != 0) { + data_p += 32; + info.loopstart = GetLittleLong(); + // Com_Printf("loopstart=%d\n", sfx->loopstart); + // if the next chunk is a LIST chunk, look for a cue length marker + FindNextChunk("LIST"); + if (data_p != 0) { + s = new String(data_b, data_p + 28, 4); + if (s.equals("MARK")) { // this is not a proper parse, but it works with cooledit... + data_p += 24; + i = GetLittleLong(); // samples in loop + info.samples = info.loopstart + i; + // Com_Printf("looped length: %i\n", i); + } + } + } else + info.loopstart = -1; + + // find data chunk + FindChunk("data"); + if (data_p == 0) { + Com.Printf("Missing data chunk\n"); + return info; + } + + data_p += 4; + samples = GetLittleLong() / info.width; + + if (info.samples != 0) { + if (samples < info.samples) + Com.Error(ERR_DROP, "Sound " + name + " has a bad loop length"); + } else + info.samples = samples; + + info.dataofs = data_p; + + return info; + } + + static class wavinfo_t { + int rate; + int width; + int channels; + int loopstart; + int samples; + int dataofs; // chunk starts this many bytes from file start + } } |