mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-04-20 09:55:38 +00:00
port loop support to wave codec
This commit is contained in:
parent
273c024aec
commit
aa5a838d95
3 changed files with 73 additions and 18 deletions
|
@ -246,6 +246,7 @@ snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
|
|||
stream->fh.pos = 0;
|
||||
stream->fh.length = length;
|
||||
stream->fh.pak = stream->pak = pak;
|
||||
stream->info.loopstart = -1;
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct snd_info_s
|
|||
int samples;
|
||||
int size;
|
||||
int dataofs;
|
||||
int loopstart; // -1 if not looped
|
||||
} snd_info_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -62,7 +62,7 @@ static short FGetLittleShort(FILE *f)
|
|||
WAV_ReadChunkInfo
|
||||
=================
|
||||
*/
|
||||
static int WAV_ReadChunkInfo(FILE *f, char *name)
|
||||
static int WAV_ReadChunkInfo(const fshandle_t *fh, char *name)
|
||||
{
|
||||
int len, r;
|
||||
|
||||
|
@ -73,9 +73,8 @@ static int WAV_ReadChunkInfo(FILE *f, char *name)
|
|||
return -1;
|
||||
|
||||
len = FGetLittleLong(f);
|
||||
if (len < 0)
|
||||
if (len < 0 || (ftell(fh->file) + len) > (fh->start + fh->length))
|
||||
{
|
||||
Con_Printf("WAV: Negative chunk length\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -84,17 +83,17 @@ static int WAV_ReadChunkInfo(FILE *f, char *name)
|
|||
|
||||
/*
|
||||
=================
|
||||
WAV_FindRIFFChunk
|
||||
WAV_FindNextRIFFChunk
|
||||
|
||||
Returns the length of the data in the chunk, or -1 if not found
|
||||
=================
|
||||
*/
|
||||
static int WAV_FindRIFFChunk(FILE *f, const char *chunk)
|
||||
static int WAV_FindNextRIFFChunk(const fshandle_t *fh, const char *chunk)
|
||||
{
|
||||
char name[5];
|
||||
int len;
|
||||
|
||||
while ((len = WAV_ReadChunkInfo(f, name)) >= 0)
|
||||
while ((len = WAV_ReadChunkInfo(fh, name)) >= 0)
|
||||
{
|
||||
/* If this is the right chunk, return */
|
||||
if (!strncmp(name, chunk, 4))
|
||||
|
@ -102,25 +101,47 @@ static int WAV_FindRIFFChunk(FILE *f, const char *chunk)
|
|||
len = ((len + 1) & ~1); /* pad by 2 . */
|
||||
|
||||
/* Not the right chunk - skip it */
|
||||
fseek(f, len, SEEK_CUR);
|
||||
fseek(fh->file, len, SEEK_CUR);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
WAV_FindRIFFChunk
|
||||
|
||||
Returns the length of the data in the chunk, or -1 if not found
|
||||
=================
|
||||
*/
|
||||
static int WAV_FindRIFFChunk(const fshandle_t *fh, const char *chunk)
|
||||
{
|
||||
int length;
|
||||
int last = ftell(fh->file);
|
||||
|
||||
fseek(fh->file, fh->start + 12, SEEK_SET);
|
||||
|
||||
if ((length = WAV_FindNextRIFFChunk(fh, chunk)) < 0)
|
||||
{
|
||||
fseek(fh->file, last, SEEK_SET);
|
||||
return length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
WAV_ReadRIFFHeader
|
||||
=================
|
||||
*/
|
||||
static qboolean WAV_ReadRIFFHeader(const char *name, FILE *file, snd_info_t *info)
|
||||
static qboolean WAV_ReadRIFFHeader(const char *name, const fshandle_t *fh, snd_info_t *info)
|
||||
{
|
||||
char dump[16];
|
||||
int wav_format;
|
||||
int bits;
|
||||
int fmtlen = 0;
|
||||
|
||||
if (fread(dump, 1, 12, file) < 12 ||
|
||||
if (fread(dump, 1, 12, fh->file) < 12 ||
|
||||
strncmp(dump, "RIFF", 4) != 0 ||
|
||||
strncmp(&dump[8], "WAVE", 4) != 0)
|
||||
{
|
||||
|
@ -129,7 +150,7 @@ static qboolean WAV_ReadRIFFHeader(const char *name, FILE *file, snd_info_t *inf
|
|||
}
|
||||
|
||||
/* Scan for the format chunk */
|
||||
if ((fmtlen = WAV_FindRIFFChunk(file, "fmt ")) < 0)
|
||||
if ((fmtlen = WAV_FindRIFFChunk(fh, "fmt ")) < 0)
|
||||
{
|
||||
Con_Printf("%s is missing fmt chunk\n", name);
|
||||
return false;
|
||||
|
@ -158,21 +179,53 @@ static qboolean WAV_ReadRIFFHeader(const char *name, FILE *file, snd_info_t *inf
|
|||
info->width = bits / 8;
|
||||
info->dataofs = 0;
|
||||
|
||||
/* Skip the rest of the format chunk if required */
|
||||
if (fmtlen > 16)
|
||||
/* Scan for the cue chunk */
|
||||
if ((info->size = WAV_FindRIFFChunk(fh, "cue ")) < 0)
|
||||
{
|
||||
fmtlen -= 16;
|
||||
fseek(file, fmtlen, SEEK_CUR);
|
||||
info->loopstart = -1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
fseek(fh->file, 24, SEEK_CUR);
|
||||
info->loopstart = GetLittleLong();
|
||||
// Con_Printf("loopstart=%d\n", info->loopstart);
|
||||
|
||||
// if the next chunk is a LIST chunk, look for a cue length marker
|
||||
if (WAV_FindNextRIFFChunk ("LIST") >= 0)
|
||||
{
|
||||
fseek(fh->file, 20, SEEK_CUR);
|
||||
char marker[4];
|
||||
memset(marker, 0, 4);
|
||||
fread(marker, 4, 4, fh->file);
|
||||
|
||||
if (!strncmp(marker, "mark", 4))
|
||||
{ // this is not a proper parse, but it works with cooledit...
|
||||
fseek(fh->file, -8, SEEK_CUR);
|
||||
int i = GetLittleLong(); // samples in loop
|
||||
info->samples = info->loopstart + i;
|
||||
// Con_Printf("looped length: %i\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan for the data chunk */
|
||||
if ((info->size = WAV_FindRIFFChunk(file, "data")) < 0)
|
||||
if ((info->size = WAV_FindRIFFChunk(fh, "data")) < 0)
|
||||
{
|
||||
Con_Printf("%s is missing data chunk\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
info->samples = (info->size / info->width) / info->channels;
|
||||
int samples = (info->size / info->width) / info->channels;
|
||||
if (info->samples)
|
||||
{
|
||||
if (samples < info.samples)
|
||||
Sys_Error ("%s has a bad loop length", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->samples = samples;
|
||||
}
|
||||
|
||||
if (info->samples == 0)
|
||||
{
|
||||
Con_Printf("%s has zero samples\n", name);
|
||||
|
@ -202,7 +255,7 @@ snd_stream_t *S_WAV_CodecOpenStream(const char *filename)
|
|||
/* The file reads are sequential, therefore no need
|
||||
* for the FS_*() functions: We will manipulate the
|
||||
* file by ourselves from now on. */
|
||||
if (!WAV_ReadRIFFHeader(filename, stream->fh.file, &stream->info))
|
||||
if (!WAV_ReadRIFFHeader(filename, &stream->fh, &stream->info))
|
||||
{
|
||||
S_CodecUtilClose(&stream);
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in a new issue