mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
start of split-out wav loader. not done yet (probably doesn't compile) but
easier to keep track of here :)
This commit is contained in:
parent
b80357afda
commit
c9f0652a95
1 changed files with 226 additions and 0 deletions
226
libs/audio/renderer/wav.c
Normal file
226
libs/audio/renderer/wav.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
wav.c
|
||||
|
||||
wav file loading
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static __attribute__ ((unused)) const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/sound.h"
|
||||
#include "QF/sys.h"
|
||||
#include "QF/qendian.h"
|
||||
#include "QF/quakefs.h"
|
||||
|
||||
#include "snd_render.h"
|
||||
|
||||
static byte *data_p;
|
||||
static byte *iff_end;
|
||||
static byte *last_chunk;
|
||||
static byte *iff_data;
|
||||
static int iff_chunk_len;
|
||||
|
||||
static short
|
||||
SND_GetLittleShort (void)
|
||||
{
|
||||
short val = 0;
|
||||
|
||||
val = *data_p;
|
||||
val = val + (*(data_p + 1) << 8);
|
||||
data_p += 2;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int
|
||||
SND_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;
|
||||
}
|
||||
|
||||
static void
|
||||
SND_FindNexctChunk (const 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 = SND_GetLittleLong ();
|
||||
if (iff_chunk_len < 0) {
|
||||
data_p = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
data_p -= 8;
|
||||
last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1);
|
||||
if (!strncmp (data_p, name, 4))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
SND_FindChunk (const char *name)
|
||||
{
|
||||
last_chunk = iff_data;
|
||||
SND_FindNexctChunk (name);
|
||||
}
|
||||
|
||||
static wavinfo_t
|
||||
SND_GetWavinfo (const char *name, byte * wav, int wavlength)
|
||||
{
|
||||
int format, samples, i;
|
||||
wavinfo_t info;
|
||||
|
||||
memset (&info, 0, sizeof (info));
|
||||
|
||||
if (!wav)
|
||||
return info;
|
||||
|
||||
iff_data = wav;
|
||||
iff_end = wav + wavlength;
|
||||
|
||||
// find "RIFF" chunk
|
||||
SND_FindChunk ("RIFF");
|
||||
if (!(data_p && !strncmp (data_p + 8, "WAVE", 4))) {
|
||||
Sys_Printf ("Missing RIFF/WAVE chunks\n");
|
||||
return info;
|
||||
}
|
||||
// get "fmt " chunk
|
||||
iff_data = data_p + 12;
|
||||
// SND_DumpChunks ();
|
||||
|
||||
SND_FindChunk ("fmt ");
|
||||
if (!data_p) {
|
||||
Sys_Printf ("Missing fmt chunk\n");
|
||||
return info;
|
||||
}
|
||||
data_p += 8;
|
||||
format = SND_GetLittleShort ();
|
||||
if (format != 1) {
|
||||
Sys_Printf ("Microsoft PCM format only\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
info.channels = SND_GetLittleShort ();
|
||||
info.rate = SND_GetLittleLong ();
|
||||
data_p += 4 + 2;
|
||||
info.width = SND_GetLittleShort () / 8;
|
||||
|
||||
// get cue chunk
|
||||
SND_FindChunk ("cue ");
|
||||
if (data_p) {
|
||||
data_p += 32;
|
||||
info.loopstart = SND_GetLittleLong ();
|
||||
|
||||
// if the next chunk is a LIST chunk, look for a cue length marker
|
||||
SND_FindNexctChunk ("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 = SND_GetLittleLong (); // samples in loop
|
||||
info.samples = info.loopstart + i;
|
||||
}
|
||||
}
|
||||
} else
|
||||
info.loopstart = -1;
|
||||
|
||||
// find data chunk
|
||||
SND_FindChunk ("data");
|
||||
if (!data_p) {
|
||||
Sys_Printf ("Missing data chunk\n");
|
||||
return info;
|
||||
}
|
||||
|
||||
data_p += 4;
|
||||
samples = SND_GetLittleLong () / info.width;
|
||||
|
||||
if (info.samples) {
|
||||
if (samples < info.samples)
|
||||
Sys_Error ("Sound %s has a bad loop length", name);
|
||||
} else
|
||||
info.samples = samples;
|
||||
|
||||
info.dataofs = data_p - wav;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void
|
||||
SND_LoadWav (QFile *file)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = Qfilelen (file);
|
||||
data = Hunk_TempAlloc (size);
|
||||
Qread (file, data, size);
|
||||
|
||||
info = SND_GetWavinfo (sfx->name, data, qfs_filesize);
|
||||
if (info.channels != 1) {
|
||||
Sys_Printf ("%s is a stereo sample\n", sfx->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stepscale = (float) info.rate / shm->speed;
|
||||
len = info.samples / stepscale;
|
||||
|
||||
if (snd_loadas8bit->int_val) {
|
||||
len = len * info.channels;
|
||||
} else {
|
||||
len = len * 2 * info.channels;
|
||||
}
|
||||
|
||||
sc = SND_GetCache (info.samples, info.rate, info.width, info.channels,
|
||||
sfx, allocator);
|
||||
if (!sc)
|
||||
return NULL;
|
||||
|
||||
sfx->loopstart = info.loopstart;
|
||||
|
||||
SND_ResampleSfx (sc, data + info.dataofs);
|
||||
|
||||
return sc;
|
||||
}
|
Loading…
Reference in a new issue