ref: bb5d36fa55021e81d20e8cd1309c6a163b4fe498
parent: 76563314d19e01997f1a03bf81c14ccdf6d86300
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Sat Dec 23 13:36:20 EST 2023
move GetWavinfo to its own file
--- a/Makefile
+++ b/Makefile
@@ -92,6 +92,7 @@
unix/snd_sdl.o\
unix/vid.o\
view.o\
+ wav.o\
world.o\
zone.o\
--- a/dat.h
+++ b/dat.h
@@ -12,11 +12,22 @@
};
typedef struct Sfx Sfx;
+typedef struct wavinfo_t wavinfo_t;
struct Sfx {char s[Npath];
int map;
mem_user_t cu;
+};
+
+struct wavinfo_t
+{+ int rate;
+ int width;
+ int channels;
+ int loopofs;
+ int samples;
+ int dataofs;
};
extern char *game;
--- a/fns.h
+++ b/fns.h
@@ -64,3 +64,5 @@
void sndwrite(uchar *buf, long sz);
void sndclose(void);
int sndopen(void);
+
+int wavinfo(byte *in, int len, wavinfo_t *info);
--- a/mkfile
+++ b/mkfile
@@ -85,6 +85,7 @@
sv_user.$O\
vid.$O\
view.$O\
+ wav.$O\
world.$O\
zone.$O\
--- a/snd.c
+++ b/snd.c
@@ -51,16 +51,6 @@
byte data[1]; // variable sized
} sfxcache_t;
-typedef struct
-{- int rate;
- int width;
- int channels;
- int loopofs;
- int samples;
- int dataofs;
-} wavinfo_t;
-
static vec3_t listener_origin;
static vec3_t listener_forward;
static vec3_t listener_right;
@@ -127,161 +117,6 @@
}
}
-static short
-GetLittleShort(void)
-{- short val;
-
- val = *data_p;
- val = val + (*(data_p+1)<<8);
- data_p += 2;
- return val;
-}
-
-static int
-GetLittleLong(void)
-{- int val;
-
- 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;
-}
-
-static void
-FindNextChunk(char *name)
-{- int iff_chunk_len;
-
- while (1)
- {- data_p=last_chunk;
-
- if (data_p >= iff_end)
- { // didn't find the chunk- data_p = nil;
- return;
- }
-
- data_p += 4;
- iff_chunk_len = GetLittleLong();
- if (iff_chunk_len < 0)
- {- data_p = nil;
- return;
- }
-// if (iff_chunk_len > 1024*1024)
-// fatal ("FindNextChunk: %d 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((char *)data_p, name, 4) == 0)
- return;
- }
-}
-
-static void
-FindChunk(char *name)
-{- last_chunk = iff_data;
- FindNextChunk (name);
-}
-
-static wavinfo_t
-GetWavinfo(char *name, byte *wav, vlong 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((char *)data_p+8, "WAVE", 4) == 0))
- {- Con_Printf("Missing RIFF/WAVE chunks\n");- return info;
- }
-
-// get "fmt " chunk
- iff_data = data_p + 12;
-
- FindChunk("fmt ");- if (!data_p)
- {- Con_Printf("Missing fmt chunk\n");- return info;
- }
- data_p += 8;
- format = GetLittleShort();
- if (format != 1)
- {- Con_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.loopofs = GetLittleLong();
-
- // if the next chunk is a LIST chunk, look for a cue length marker
- FindNextChunk ("LIST");- if (data_p)
- {- if(strncmp((char *)data_p+28, "mark", 4) == 0)
- { // this is not a proper parse, but it works with cooledit...- data_p += 24;
- i = GetLittleLong (); // samples in loop
- info.samples = info.loopofs + i;
-// Con_Printf("looped length: %d\n", i);- }
- }
- }
- else
- info.loopofs = -1;
-
-// find data chunk
- FindChunk("data");- if (!data_p)
- {- Con_Printf("Missing data chunk\n");- return info;
- }
-
- data_p += 4;
- samples = GetLittleLong () / info.width;
-
- if (info.samples)
- {- if (samples < info.samples)
- fatal ("Sound %s has a bad loop length", name);- }
- else
- info.samples = samples;
-
- info.dataofs = data_p - wav;
-
- return info;
-}
-
static sfxcache_t *
loadsfx(Sfx *sfx)
{@@ -298,7 +133,10 @@
Con_DPrintf("loadsfx: %r\n");return nil;
}
- info = GetWavinfo(sfx->s, u, len);
+ if(wavinfo(u, len, &info) != 0){+ Con_Printf("loadsfx: %s: %s\n", sfx->s, lerr());+ return nil;
+ }
if(info.channels != 1){ Con_DPrintf("loadsfx: non mono wave %s\n", sfx->s);return nil;
--- /dev/null
+++ b/wav.c
@@ -1,0 +1,92 @@
+#include "quakedef.h"
+
+int
+wavinfo(byte *in, int len, wavinfo_t *info)
+{+ int i, n, sz, fmt, loopsamples;
+ byte *p;
+
+ memset(info, 0, sizeof(*info));
+
+ p = in;
+ if(len < 36 || memcmp(p, "RIFF", 4) != 0){+ werrstr("not a RIFF");+ return -1;
+ }
+ p += 4; len -= 4;
+ sz = le32(p); len -= 4;
+ if(sz < 36 || sz > len){+ werrstr("trucated? sz=%d len=%d", sz, len);+ return -1;
+ }
+ if(memcmp(p, "WAVE", 4) != 0){+ werrstr("not a WAVE");+ return -1;
+ }
+ p += 4; sz -= 4;
+ if(memcmp(p, "fmt ", 4) != 0){+ werrstr("no \"fmt \" subchunk");+ return -1;
+ }
+ p += 4; sz -= 4;
+ n = le32(p); sz -= 4;
+
+ fmt = le16(p); sz -= 2; n -= 2;
+ if(fmt != 1){+ werrstr("not Microsoft PCM format: %d", fmt);+ return -1;
+ }
+ info->channels = le16(p); sz -= 2; n -= 2;
+ info->rate = le32(p); sz -= 4; n -= 4;
+ p += 4+2; sz -= 4+2; n -= 4+2; /* skip ByteRate + BlockAlign */
+ info->width = le16(p); sz -= 2; n -= 2;
+ if((info->width % 8) != 0){+ werrstr("invalid width: %d", info->width);+ return -1;
+ }
+ info->width /= 8;
+ info->loopofs = -1;
+ loopsamples = 0;
+ p += n; sz -= n;
+
+ for(; sz >= 8;){+ p += 4; sz -= 4;
+ n = le32(p); sz -= 4;
+ if(n > sz || n <= 0)
+ break;
+ if(n >= 4){+ if(memcmp(p-8, "cue ", 4) == 0){+ i = le32(p); sz -= 4; n -= 4; /* CuePoints - usually two of those */
+ if(i >= 1 && n >= i*6*4){+ p += 5*4; sz -= 5*4; n -= 5*4; /* Name+Position+Chunk+ChunkStart+BlockStart */
+ info->loopofs = le32(p); sz -= 4; n -= 4;
+ /* FIXME(sigrid): check if this is needed and whether it works at all */
+ if(i > 1){+ p += 5*4; sz -= 5*4; n -= 5*4; /* Name+Position+Chunk+ChunkStart+BlockStart */
+ loopsamples = info->loopofs + le32(p); sz -= 4; n -= 4;
+ }
+ }
+ }else if(memcmp(p-8, "data", 4) == 0 && info->dataofs == 0){+ info->samples = n / info->width;
+ info->dataofs = p - in;
+ }else if(memcmp(p-8, "LIST", 4) == 0 && info->loopofs >= 0 && loopsamples == 0){+ p += 4; sz -= 4; n -= 4; /* skip "adtl" */
+ if(n >= 20 && memcmp(p, "ltxt", 4) == 0 && memcmp(p+16, "mark", 4) == 0){+ p += 12; sz -= 12; n -= 12;
+ loopsamples = info->loopofs + le32(p); sz -= 4; n -= 4;
+ }
+ }
+ }
+ n = (n + 1) & ~1;
+ p += n; sz -= n;
+ }
+
+ if(loopsamples > info->samples || info->loopofs > info->samples){+ werrstr("invalid loop: (%d,%d) > %d", info->loopofs, loopsamples, info->samples);+ return -1;
+ }
+ if(loopsamples > 0)
+ info->samples = loopsamples;
+
+ return 0;
+}
--
⑨