shithub: qk1

Download patch

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;
+}