mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-30 20:50:42 +00:00
getting closer. wav's successfully load, but playback is always looped (?).
oggs hang
This commit is contained in:
parent
948c97a6a4
commit
e3f8c833ad
5 changed files with 141 additions and 130 deletions
|
@ -48,14 +48,12 @@ struct sfx_s
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
int loopstart;
|
int loopstart;
|
||||||
int speed;
|
|
||||||
int width;
|
|
||||||
int channels;
|
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
struct sfxbuffer_s *(*touch) (sfx_t *sfx);
|
struct sfxbuffer_s *(*touch) (sfx_t *sfx);
|
||||||
struct sfxbuffer_s *(*retain) (sfx_t *sfx);
|
struct sfxbuffer_s *(*retain) (sfx_t *sfx);
|
||||||
|
struct wavinfo_s *(*wavinfo) (sfx_t *sfx);
|
||||||
void (*release) (sfx_t *sfx);
|
void (*release) (sfx_t *sfx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,16 @@ typedef struct portable_samplepair_s {
|
||||||
int right;
|
int right;
|
||||||
} portable_samplepair_t;
|
} portable_samplepair_t;
|
||||||
|
|
||||||
|
typedef struct wavinfo_s {
|
||||||
|
int rate;
|
||||||
|
int width;
|
||||||
|
int channels;
|
||||||
|
int loopstart;
|
||||||
|
int samples;
|
||||||
|
int dataofs; // chunk starts this many bytes from file start
|
||||||
|
int datalen; // chunk bytes
|
||||||
|
} wavinfo_t;
|
||||||
|
|
||||||
typedef struct channel_s channel_t;
|
typedef struct channel_s channel_t;
|
||||||
typedef struct sfxbuffer_s sfxbuffer_t;
|
typedef struct sfxbuffer_s sfxbuffer_t;
|
||||||
struct sfxbuffer_s {
|
struct sfxbuffer_s {
|
||||||
|
@ -49,19 +59,21 @@ struct sfxbuffer_s {
|
||||||
int pos; // position of tail within full stream
|
int pos; // position of tail within full stream
|
||||||
void (*paint) (channel_t *ch, sfxbuffer_t *buffer, int count);
|
void (*paint) (channel_t *ch, sfxbuffer_t *buffer, int count);
|
||||||
void (*advance) (sfxbuffer_t *buffer, int count);
|
void (*advance) (sfxbuffer_t *buffer, int count);
|
||||||
|
sfx_t *sfx;
|
||||||
byte data[4];
|
byte data[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct sfxstream_s {
|
typedef struct sfxstream_s {
|
||||||
sfx_t *sfx;
|
sfx_t *sfx;
|
||||||
void *file;
|
void *file;
|
||||||
|
wavinfo_t wavinfo;
|
||||||
sfxbuffer_t buffer;
|
sfxbuffer_t buffer;
|
||||||
} sfxstream_t;
|
} sfxstream_t;
|
||||||
|
|
||||||
typedef struct sfxblock_s {
|
typedef struct sfxblock_s {
|
||||||
sfx_t *sfx;
|
sfx_t *sfx;
|
||||||
void *file;
|
void *file;
|
||||||
int bytes;
|
wavinfo_t wavinfo;
|
||||||
cache_user_t cache;
|
cache_user_t cache;
|
||||||
} sfxblock_t;
|
} sfxblock_t;
|
||||||
|
|
||||||
|
@ -82,15 +94,6 @@ struct channel_s {
|
||||||
int oldphase; // phase shift between l-r in samples
|
int oldphase; // phase shift between l-r in samples
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct wavinfo_s {
|
|
||||||
int rate;
|
|
||||||
int width;
|
|
||||||
int channels;
|
|
||||||
int loopstart;
|
|
||||||
int samples;
|
|
||||||
int dataofs; // chunk starts this many bytes from file start
|
|
||||||
} wavinfo_t;
|
|
||||||
|
|
||||||
void SND_PaintChannels(int endtime);
|
void SND_PaintChannels(int endtime);
|
||||||
void SND_Init (void);
|
void SND_Init (void);
|
||||||
void SND_Shutdown (void);
|
void SND_Shutdown (void);
|
||||||
|
@ -115,8 +118,8 @@ void SND_LocalSound (const char *s);
|
||||||
void SND_BlockSound (void);
|
void SND_BlockSound (void);
|
||||||
void SND_UnblockSound (void);
|
void SND_UnblockSound (void);
|
||||||
|
|
||||||
void SND_ResampleMono (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length);
|
void SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length);
|
||||||
void SND_ResampleStereo (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length);
|
void SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length);
|
||||||
sfxbuffer_t *SND_GetCache (long samples, int rate, int inwidth, int channels,
|
sfxbuffer_t *SND_GetCache (long samples, int rate, int inwidth, int channels,
|
||||||
sfxblock_t *block, cache_allocator_t allocator);
|
sfxblock_t *block, cache_allocator_t allocator);
|
||||||
|
|
||||||
|
@ -131,6 +134,8 @@ void SND_CallbackLoad (void *object, cache_allocator_t allocator);
|
||||||
void SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname);
|
void SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname);
|
||||||
void SND_LoadWav (QFile *file, sfx_t *sfx, char *realname);
|
void SND_LoadWav (QFile *file, sfx_t *sfx, char *realname);
|
||||||
|
|
||||||
|
wavinfo_t *SND_CacheWavinfo (sfx_t *sfx);
|
||||||
|
wavinfo_t *SND_StreamWavinfo (sfx_t *sfx);
|
||||||
sfxbuffer_t *SND_CacheTouch (sfx_t *sfx);
|
sfxbuffer_t *SND_CacheTouch (sfx_t *sfx);
|
||||||
sfxbuffer_t *SND_CacheRetain (sfx_t *sfx);
|
sfxbuffer_t *SND_CacheRetain (sfx_t *sfx);
|
||||||
void SND_CacheRelease (sfx_t *sfx);
|
void SND_CacheRelease (sfx_t *sfx);
|
||||||
|
@ -143,8 +148,6 @@ void SND_PaintChannelFrom16 (channel_t *ch, sfxbuffer_t *sc, int count);
|
||||||
void SND_PaintChannelStereo8 (channel_t *ch, sfxbuffer_t *sc, int count);
|
void SND_PaintChannelStereo8 (channel_t *ch, sfxbuffer_t *sc, int count);
|
||||||
void SND_PaintChannelStereo16 (channel_t *ch, sfxbuffer_t *sc, int count);
|
void SND_PaintChannelStereo16 (channel_t *ch, sfxbuffer_t *sc, int count);
|
||||||
|
|
||||||
wavinfo_t GetWavinfo (const char *name, byte *wav, int wavlength);
|
|
||||||
|
|
||||||
extern channel_t channels[MAX_CHANNELS];
|
extern channel_t channels[MAX_CHANNELS];
|
||||||
// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds
|
// 0 to MAX_DYNAMIC_CHANNELS-1 = normal entity sounds
|
||||||
// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc
|
// MAX_DYNAMIC_CHANNELS to MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS -1 = water, etc
|
||||||
|
|
|
@ -98,6 +98,18 @@ SND_StreamRelease (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wavinfo_t *
|
||||||
|
SND_CacheWavinfo (sfx_t *sfx)
|
||||||
|
{
|
||||||
|
return &((sfxblock_t *) sfx->data)->wavinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
wavinfo_t *
|
||||||
|
SND_StreamWavinfo (sfx_t *sfx)
|
||||||
|
{
|
||||||
|
return &((sfxstream_t *) sfx->data)->wavinfo;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_Load (sfx_t *sfx)
|
SND_Load (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
|
@ -157,23 +169,25 @@ SND_GetCache (long samples, int rate, int inwidth, int channels,
|
||||||
width = snd_loadas8bit->int_val ? 1 : 2;
|
width = snd_loadas8bit->int_val ? 1 : 2;
|
||||||
stepscale = (float) rate / shm->speed; // usually 0.5, 1, or 2
|
stepscale = (float) rate / shm->speed; // usually 0.5, 1, or 2
|
||||||
size = samples / stepscale;
|
size = samples / stepscale;
|
||||||
|
printf ("%ld %d\n", samples, size);
|
||||||
size *= width * channels;
|
size *= width * channels;
|
||||||
sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name);
|
sc = allocator (&block->cache, sizeof (sfxbuffer_t) + size, sfx->name);
|
||||||
if (!sc)
|
if (!sc)
|
||||||
return 0;
|
return 0;
|
||||||
block->bytes = size;
|
memcpy (sc->data + size, "\xde\xad\xbe\xef", 4);
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_ResampleMono (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length)
|
SND_ResampleMono (sfxbuffer_t *sc, byte *data, int length)
|
||||||
{
|
{
|
||||||
unsigned char *ib, *ob;
|
unsigned char *ib, *ob;
|
||||||
int fracstep, outcount, sample, samplefrac, srcsample, i;
|
int fracstep, outcount, sample, samplefrac, srcsample, i;
|
||||||
float stepscale;
|
float stepscale;
|
||||||
short *is, *os;
|
short *is, *os;
|
||||||
int inwidth = sfx->width;
|
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||||
int inrate = sfx->speed;
|
int inwidth = info->width;
|
||||||
|
int inrate = info->rate;
|
||||||
int outwidth;
|
int outwidth;
|
||||||
|
|
||||||
is = (short *) data;
|
is = (short *) data;
|
||||||
|
@ -184,6 +198,11 @@ SND_ResampleMono (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length)
|
||||||
stepscale = (float) inrate / shm->speed; // usually 0.5, 1, or 2
|
stepscale = (float) inrate / shm->speed; // usually 0.5, 1, or 2
|
||||||
|
|
||||||
outcount = length / stepscale;
|
outcount = length / stepscale;
|
||||||
|
printf ("%d %d\n", length, outcount);
|
||||||
|
|
||||||
|
sc->sfx->length = outcount;
|
||||||
|
if (info->loopstart != -1)
|
||||||
|
sc->sfx->loopstart = info->loopstart / stepscale;
|
||||||
|
|
||||||
if (snd_loadas8bit->int_val) {
|
if (snd_loadas8bit->int_val) {
|
||||||
outwidth = 1;
|
outwidth = 1;
|
||||||
|
@ -263,17 +282,24 @@ SND_ResampleMono (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
byte *x = sc->data + outcount * outwidth;
|
||||||
|
if (memcmp (x, "\xde\xad\xbe\xef", 4))
|
||||||
|
Sys_Error ("SND_ResampleMono screwed the pooch %02x%02x%02x%02x",
|
||||||
|
x[0], x[1], x[2], x[3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_ResampleStereo (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length)
|
SND_ResampleStereo (sfxbuffer_t *sc, byte *data, int length)
|
||||||
{
|
{
|
||||||
int fracstep, outcount, sl, sr, samplefrac, srcsample, i;
|
int fracstep, outcount, sl, sr, samplefrac, srcsample, i;
|
||||||
float stepscale;
|
float stepscale;
|
||||||
stereo8_t *ib, *ob;
|
stereo8_t *ib, *ob;
|
||||||
stereo16_t *is, *os;
|
stereo16_t *is, *os;
|
||||||
int inwidth = sfx->width;
|
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||||
int inrate = sfx->speed;
|
int inwidth = info->width;
|
||||||
|
int inrate = info->rate;
|
||||||
int outwidth;
|
int outwidth;
|
||||||
|
|
||||||
is = (stereo16_t *) data;
|
is = (stereo16_t *) data;
|
||||||
|
@ -285,6 +311,10 @@ SND_ResampleStereo (sfx_t *sfx, sfxbuffer_t *sc, byte *data, int length)
|
||||||
|
|
||||||
outcount = length / stepscale;
|
outcount = length / stepscale;
|
||||||
|
|
||||||
|
sc->sfx->length = outcount;
|
||||||
|
if (info->loopstart != -1)
|
||||||
|
sc->sfx->loopstart = info->loopstart / stepscale;
|
||||||
|
|
||||||
if (snd_loadas8bit->int_val) {
|
if (snd_loadas8bit->int_val) {
|
||||||
outwidth = 1;
|
outwidth = 1;
|
||||||
sc->paint = SND_PaintChannelStereo8;
|
sc->paint = SND_PaintChannelStereo8;
|
||||||
|
|
|
@ -85,37 +85,45 @@ static ov_callbacks callbacks = {
|
||||||
tell_func,
|
tell_func,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static wavinfo_t
|
||||||
get_info (OggVorbis_File *vf, sfx_t *sfx)
|
get_info (OggVorbis_File *vf)
|
||||||
{
|
{
|
||||||
|
wavinfo_t info;
|
||||||
vorbis_info *vi;
|
vorbis_info *vi;
|
||||||
int sample_start = -1, sample_count = 0;
|
int sample_start = -1, sample_count = 0;
|
||||||
|
int samples;
|
||||||
char **ptr;
|
char **ptr;
|
||||||
|
|
||||||
vi = ov_info (vf, -1);
|
vi = ov_info (vf, -1);
|
||||||
sfx->length = ov_pcm_total (vf, -1);
|
samples = ov_pcm_total (vf, -1);
|
||||||
sfx->channels = vi->channels;
|
|
||||||
sfx->speed = vi->rate;
|
|
||||||
|
|
||||||
for (ptr = ov_comment (vf, -1)->user_comments; *ptr; ptr++) {
|
for (ptr = ov_comment (vf, -1)->user_comments; *ptr; ptr++) {
|
||||||
Sys_DPrintf ("%s\n", *ptr);
|
Sys_DPrintf ("%s\n", *ptr);
|
||||||
if (strncmp ("CUEPOINT=", *ptr, 9) == 0) {
|
if (strncmp ("CUEPOINT=", *ptr, 9) == 0) {
|
||||||
sscanf (*ptr + 9, "%d %d", &sample_start, &sample_count);
|
sscanf (*ptr + 9, "%d %d", &sample_start, &sample_count);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (developer->int_val) {
|
|
||||||
Sys_Printf ("\nBitstream is %d channel, %dHz\n",
|
|
||||||
sfx->channels, sfx->speed);
|
|
||||||
Sys_Printf ("\nDecoded length: %d samples (%d bytes)\n",
|
|
||||||
sfx->length, sfx->length * sfx->channels * 2);
|
|
||||||
Sys_Printf ("Encoded by: %s\n\n", ov_comment (vf, -1)->vendor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sample_start != -1)
|
if (sample_start != -1)
|
||||||
sfx->length = sample_start + sample_count;
|
samples = sample_start + sample_count;
|
||||||
sfx->loopstart = sample_start;
|
|
||||||
|
info.rate = vi->rate;
|
||||||
|
info.width = 2;
|
||||||
|
info.channels = vi->channels;
|
||||||
|
info.loopstart = sample_start;
|
||||||
|
info.samples = samples;
|
||||||
|
info.dataofs = 0;
|
||||||
|
info.datalen = samples * 2;
|
||||||
|
|
||||||
|
if (developer->int_val) {
|
||||||
|
Sys_Printf ("\nBitstream is %d channel, %dHz\n",
|
||||||
|
info.channels, info.rate);
|
||||||
|
Sys_Printf ("\nDecoded length: %d samples (%d bytes)\n",
|
||||||
|
info.samples, info.samples * info.channels * 2);
|
||||||
|
Sys_Printf ("Encoded by: %s\n\n", ov_comment (vf, -1)->vendor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -144,16 +152,15 @@ read_ogg (OggVorbis_File *vf, byte *buf, int len)
|
||||||
static sfxbuffer_t *
|
static sfxbuffer_t *
|
||||||
load_ogg (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
|
load_ogg (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
|
||||||
{
|
{
|
||||||
long size;
|
|
||||||
byte *data;
|
byte *data;
|
||||||
sfxbuffer_t *sc = 0;
|
sfxbuffer_t *sc = 0;
|
||||||
sfx_t *sfx = block->sfx;
|
sfx_t *sfx = block->sfx;
|
||||||
int channels;
|
void (*resample)(sfxbuffer_t *, byte *, int);
|
||||||
void (*resample)(sfx_t *, sfxbuffer_t *, byte *, int);
|
wavinfo_t info;
|
||||||
|
|
||||||
get_info (vf, sfx);
|
info = get_info (vf);
|
||||||
|
|
||||||
switch (sfx->channels) {
|
switch (info.channels) {
|
||||||
case 1:
|
case 1:
|
||||||
resample = SND_ResampleMono;
|
resample = SND_ResampleMono;
|
||||||
break;
|
break;
|
||||||
|
@ -162,23 +169,22 @@ load_ogg (OggVorbis_File *vf, sfxblock_t *block, cache_allocator_t allocator)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Sys_Printf ("%s: unsupported channel count: %d\n",
|
Sys_Printf ("%s: unsupported channel count: %d\n",
|
||||||
sfx->name, sfx->channels);
|
sfx->name, info.channels);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
channels = sfx->channels;
|
data = malloc (info.datalen);
|
||||||
|
|
||||||
size = sfx->length * channels * 2;
|
|
||||||
|
|
||||||
data = malloc (size);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
goto bail;
|
goto bail;
|
||||||
sc = SND_GetCache (sfx->length, sfx->speed, 2, channels, block, allocator);
|
sc = SND_GetCache (info.samples, info.rate, info.width, info.channels,
|
||||||
|
block, allocator);
|
||||||
if (!sc)
|
if (!sc)
|
||||||
goto bail;
|
goto bail;
|
||||||
if (read_ogg (vf, data, size) < 0)
|
sc->sfx = sfx;
|
||||||
|
if (read_ogg (vf, data, info.datalen) < 0)
|
||||||
goto bail;
|
goto bail;
|
||||||
resample (sfx, sc, data, sfx->length);
|
block->wavinfo = info;
|
||||||
|
resample (sc, data, info.samples);
|
||||||
sc->length = sc->head = sfx->length;
|
sc->length = sc->head = sfx->length;
|
||||||
bail:
|
bail:
|
||||||
if (data)
|
if (data)
|
||||||
|
@ -207,47 +213,9 @@ ogg_callback_load (void *object, cache_allocator_t allocator)
|
||||||
load_ogg (&vf, block, allocator);
|
load_ogg (&vf, block, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
vorbis_advance (sfxbuffer_t *buffer, int count)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stream_ogg (sfx_t *sfx, OggVorbis_File *vf)
|
stream_ogg (sfx_t *sfx, OggVorbis_File *vf)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream;
|
|
||||||
int length, bytes;
|
|
||||||
void (*paint) (channel_t *ch, sfxbuffer_t *buffer, int count);
|
|
||||||
|
|
||||||
|
|
||||||
get_info (vf, sfx);
|
|
||||||
|
|
||||||
switch (sfx->channels) {
|
|
||||||
case 1:
|
|
||||||
paint = SND_PaintChannelFrom16;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
paint = SND_PaintChannelStereo16;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Sys_Printf ("%s: unsupported channel count: %d\n",
|
|
||||||
sfx->name, sfx->channels);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
length = shm->speed * snd_mixahead->value * 3;
|
|
||||||
bytes = sfx->channels * 2 * length;
|
|
||||||
|
|
||||||
stream = calloc (1, sizeof (sfxstream_t) + bytes);
|
|
||||||
|
|
||||||
stream->file = malloc (sizeof (OggVorbis_File));
|
|
||||||
memcpy (stream->file, vf, sizeof (OggVorbis_File));
|
|
||||||
|
|
||||||
stream->buffer.length = length;
|
|
||||||
stream->buffer.paint = paint;
|
|
||||||
stream->buffer.advance = vorbis_advance;
|
|
||||||
|
|
||||||
sfx->data = stream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -265,6 +233,7 @@ SND_LoadOgg (QFile *file, sfx_t *sfx, char *realname)
|
||||||
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
||||||
ov_clear (&vf);
|
ov_clear (&vf);
|
||||||
sfx->data = block;
|
sfx->data = block;
|
||||||
|
sfx->wavinfo = SND_CacheWavinfo;
|
||||||
sfx->touch = SND_CacheTouch;
|
sfx->touch = SND_CacheTouch;
|
||||||
sfx->retain = SND_CacheRetain;
|
sfx->retain = SND_CacheRetain;
|
||||||
sfx->release = SND_CacheRelease;
|
sfx->release = SND_CacheRelease;
|
||||||
|
|
|
@ -48,49 +48,44 @@ static __attribute__ ((unused)) const char rcsid[] =
|
||||||
|
|
||||||
#include "snd_render.h"
|
#include "snd_render.h"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *name;
|
|
||||||
int data_start;
|
|
||||||
int data_length;
|
|
||||||
int length;
|
|
||||||
} wavfile_t;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wav_callback_load (void *object, cache_allocator_t allocator)
|
wav_callback_load (void *object, cache_allocator_t allocator)
|
||||||
{
|
{
|
||||||
sfxblock_t *block = (sfxblock_t *) object;
|
sfxblock_t *block = (sfxblock_t *) object;
|
||||||
sfx_t *sfx = block->sfx;
|
sfx_t *sfx = block->sfx;
|
||||||
wavfile_t *wavfile = (wavfile_t *) block->file;
|
const char *name = (const char *) block->file;
|
||||||
QFile *file;
|
QFile *file;
|
||||||
byte *data;
|
byte *data;
|
||||||
sfxbuffer_t *buffer;
|
sfxbuffer_t *buffer;
|
||||||
|
wavinfo_t *info = &block->wavinfo;
|
||||||
|
|
||||||
QFS_FOpenFile (wavfile->name, &file);
|
QFS_FOpenFile (name, &file);
|
||||||
if (!file)
|
if (!file)
|
||||||
return; //FIXME Sys_Error?
|
return; //FIXME Sys_Error?
|
||||||
|
|
||||||
Qseek (file, wavfile->data_start, SEEK_SET);
|
Qseek (file, info->dataofs, SEEK_SET);
|
||||||
data = malloc (wavfile->data_length);
|
data = malloc (info->datalen);
|
||||||
Qread (file, data, wavfile->data_length);
|
Qread (file, data, info->datalen);
|
||||||
Qclose (file);
|
Qclose (file);
|
||||||
|
|
||||||
buffer = SND_GetCache (wavfile->length, sfx->speed, sfx->width,
|
buffer = SND_GetCache (info->samples, info->rate, info->width,
|
||||||
sfx->channels, block, allocator);
|
info->channels, block, allocator);
|
||||||
if (sfx->channels == 2)
|
buffer->sfx = sfx;
|
||||||
SND_ResampleStereo (sfx, buffer, data, wavfile->length);
|
if (info->channels == 2)
|
||||||
|
SND_ResampleStereo (buffer, data, info->samples);
|
||||||
else
|
else
|
||||||
SND_ResampleMono (sfx, buffer, data, wavfile->length);
|
SND_ResampleMono (buffer, data, info->samples);
|
||||||
buffer->length = buffer->head = sfx->length;
|
buffer->length = buffer->head = sfx->length;
|
||||||
free (data);
|
free (data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stream_wav (sfx_t *sfx, wavfile_t *wavfile)
|
stream_wav (sfx_t *sfx, wavinfo_t info)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static wavinfo_t
|
||||||
SND_LoadWav (QFile *file, sfx_t *sfx, char *realname)
|
get_info (QFile *file)
|
||||||
{
|
{
|
||||||
riff_t *riff;
|
riff_t *riff;
|
||||||
riff_d_chunk_t **ck;
|
riff_d_chunk_t **ck;
|
||||||
|
@ -110,13 +105,14 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname)
|
||||||
riff_ltxt_t *ltxt;
|
riff_ltxt_t *ltxt;
|
||||||
riff_d_ltxt_t *dltxt = 0;
|
riff_d_ltxt_t *dltxt = 0;
|
||||||
|
|
||||||
wavfile_t *wavfile;
|
wavinfo_t info;
|
||||||
|
|
||||||
int loop_start = -1, sample_count = -1;
|
|
||||||
|
info.rate = 0;
|
||||||
|
|
||||||
if (!(riff = riff_read (file))) {
|
if (!(riff = riff_read (file))) {
|
||||||
Sys_Printf ("bad riff file\n");
|
Sys_Printf ("bad riff file\n");
|
||||||
return;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ck = riff->chunks; *ck; ck++) {
|
for (ck = riff->chunks; *ck; ck++) {
|
||||||
|
@ -141,7 +137,7 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname)
|
||||||
for (lck = list->chunks; *lck; lck++) {
|
for (lck = list->chunks; *lck; lck++) {
|
||||||
RIFF_SWITCH ((*lck)->name) {
|
RIFF_SWITCH ((*lck)->name) {
|
||||||
case RIFF_CASE ('l','t','x','t'):
|
case RIFF_CASE ('l','t','x','t'):
|
||||||
ltxt = (riff_ltxt_t *) *ck;
|
ltxt = (riff_ltxt_t *) *lck;
|
||||||
dltxt = <xt->ltxt;
|
dltxt = <xt->ltxt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -167,39 +163,54 @@ SND_LoadWav (QFile *file, sfx_t *sfx, char *realname)
|
||||||
Sys_Printf ("unsupported channel count\n");
|
Sys_Printf ("unsupported channel count\n");
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
sfx->width = dfmt->bits_per_sample / 8;
|
|
||||||
sfx->length = data->ck.len / sfx->width;
|
|
||||||
sfx->speed = dfmt->samples_per_sec;
|
|
||||||
sfx->channels = dfmt->channels;
|
|
||||||
|
|
||||||
wavfile = malloc (sizeof (wavfile_t));
|
info.rate = dfmt->samples_per_sec;
|
||||||
wavfile->name = realname;
|
info.width = dfmt->bits_per_sample / 8;
|
||||||
wavfile->data_start = *(int *)data->data;
|
info.channels = dfmt->channels;
|
||||||
wavfile->data_length = data->ck.len;
|
if (cp) {
|
||||||
wavfile->length = sfx->length;
|
info.loopstart = cp->sample_offset;
|
||||||
|
if (dltxt)
|
||||||
|
info.samples = info.loopstart + dltxt->len;
|
||||||
|
else
|
||||||
|
info.samples = data->ck.len / info.width;
|
||||||
|
} else {
|
||||||
|
info.loopstart = -1;
|
||||||
|
info.samples = data->ck.len / info.width;
|
||||||
|
}
|
||||||
|
info.dataofs = *(int *)data->data;
|
||||||
|
info.datalen = data->ck.len;
|
||||||
|
|
||||||
|
bail:
|
||||||
|
Qclose (file);
|
||||||
|
riff_free (riff);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SND_LoadWav (QFile *file, sfx_t *sfx, char *realname)
|
||||||
|
{
|
||||||
|
wavinfo_t info;
|
||||||
|
|
||||||
|
info = get_info (file);
|
||||||
|
if (!info.rate)
|
||||||
|
return;
|
||||||
|
|
||||||
if (sfx->length < 8 * shm->speed) {
|
if (sfx->length < 8 * shm->speed) {
|
||||||
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
||||||
sfx->data = block;
|
sfx->data = block;
|
||||||
|
sfx->wavinfo = SND_CacheWavinfo;
|
||||||
sfx->touch = SND_CacheTouch;
|
sfx->touch = SND_CacheTouch;
|
||||||
sfx->retain = SND_CacheRetain;
|
sfx->retain = SND_CacheRetain;
|
||||||
sfx->release = SND_CacheRelease;
|
sfx->release = SND_CacheRelease;
|
||||||
sfx->data = block;
|
sfx->data = block;
|
||||||
block->sfx = sfx;
|
block->sfx = sfx;
|
||||||
block->file = wavfile;
|
block->file = realname;
|
||||||
|
block->wavinfo = info;
|
||||||
Cache_Add (&block->cache, block, wav_callback_load);
|
Cache_Add (&block->cache, block, wav_callback_load);
|
||||||
} else {
|
} else {
|
||||||
sfx->touch = sfx->retain = SND_StreamRetain;
|
sfx->touch = sfx->retain = SND_StreamRetain;
|
||||||
sfx->release = SND_StreamRelease;
|
sfx->release = SND_StreamRelease;
|
||||||
free (realname);
|
free (realname);
|
||||||
stream_wav (sfx, wavfile);
|
stream_wav (sfx, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dltxt)
|
|
||||||
sample_count = dltxt->len;
|
|
||||||
if (cp)
|
|
||||||
loop_start = cp->sample_offset;
|
|
||||||
bail:
|
|
||||||
Qclose (file);
|
|
||||||
riff_free (riff);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue