mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-23 04:42:32 +00:00
resampling now works
However, no fallback for when libsamplerate is missing.
This commit is contained in:
parent
1c985bc925
commit
22e8698827
8 changed files with 216 additions and 129 deletions
|
@ -134,31 +134,33 @@ struct sfxstream_s {
|
|||
void *file; //!< handle for "file" representing the stream
|
||||
wavinfo_t wavinfo; //!< description of sound data
|
||||
unsigned pos; //!< position of next frame full stream
|
||||
/** resampler state information */
|
||||
void *state;
|
||||
/** Resample raw data into internal format.
|
||||
\param sc buffer to write resampled sound (sfxstream_s::buffer)
|
||||
\param data raw sample data
|
||||
\param length number of frames to resample
|
||||
\param prev pointer to end of last resample for smoothing
|
||||
*/
|
||||
int (*resample)(sfxbuffer_t *, float *, int);
|
||||
|
||||
void *state; //!< resampler state information
|
||||
/** Read data from the stream.
|
||||
\param file handle for "file" representing the stream
|
||||
(sfxstream_s::file)
|
||||
This is a low-level function used by sfxstream_t::read. The read
|
||||
samples will be at the sample rate of the underlying stream.
|
||||
\param cb_data stream relevant infomation (actually ::sfxstream_t
|
||||
("this"), but this signature is used for compatibility
|
||||
with libsamplerate
|
||||
\param data address of pointer to be set to point to the buffer
|
||||
holding the samples
|
||||
*/
|
||||
long (*ll_read)(void *cb_data, float **data);
|
||||
/** Read data from the stream.
|
||||
This is a high-level function for use in the mixer. The read samples
|
||||
will always at be the correct sample rate for the mixer, reguardless
|
||||
of the sample rate in the underlying stream.
|
||||
\param stream "this"
|
||||
\param data destination of read data
|
||||
\param frames number of frames to read from stream
|
||||
\param info description of sound data (sfxstream_s::wavinfo)
|
||||
\param frames maximum number of frames to read from stream
|
||||
\return number of frames read from stream
|
||||
*/
|
||||
int (*read)(void *file, float *data, int frames, wavinfo_t *info);
|
||||
int (*read)(sfxstream_t *stream, float *data, int frames);
|
||||
/** Seek to an absolute position within the stream.
|
||||
\param file handle for "file" representing the stream
|
||||
(sfxstream_s::file)
|
||||
\param stream "this"
|
||||
\param pos frame position with the stream
|
||||
\param info description of sound data (sfxstream_s::wavinfo)
|
||||
*/
|
||||
int (*seek)(void *file, int pos, wavinfo_t *info);
|
||||
int (*seek)(sfxstream_t *stream, int pos);
|
||||
sfxbuffer_t buffer; //<! stream's ring buffer
|
||||
};
|
||||
|
||||
|
@ -250,10 +252,15 @@ void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
|||
\param close
|
||||
*/
|
||||
sfx_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||
int (*read)(void *, float *, int, wavinfo_t *),
|
||||
int (*seek)(void *, int, wavinfo_t *),
|
||||
long (*read)(void *, float **),
|
||||
int (*seek)(sfxstream_t *, int),
|
||||
void (*close) (sfx_t *));
|
||||
|
||||
/** Close a stream.
|
||||
\param sfx
|
||||
*/
|
||||
void SND_SFX_StreamClose (sfx_t *sfx);
|
||||
|
||||
/** Pre-load a sound into the cache.
|
||||
\param sample name of sound to precache
|
||||
*/
|
||||
|
@ -403,6 +410,11 @@ void SND_SetPaint (sfxbuffer_t *sc);
|
|||
*/
|
||||
void SND_SetupResampler (sfxbuffer_t *sc, int streamed);
|
||||
|
||||
/** Free memory allocated for the resampler.
|
||||
\param stream stream to pulldown
|
||||
*/
|
||||
void SND_PulldownResampler (sfxstream_t *stream);
|
||||
|
||||
/** Copy/resample data into buffer, resampling as necessary.
|
||||
\param sc buffer to write resampled sound
|
||||
\param data raw sample data
|
||||
|
@ -543,7 +555,6 @@ void SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos);
|
|||
/** Allocate a sound buffer from cache for cached sounds.
|
||||
\param samples size in samples
|
||||
\param rate sample rate
|
||||
\param inwidth bits per sample of input data
|
||||
\param channels number of channels in input data
|
||||
\param block cached sound descriptor to initialize
|
||||
\param allocator cache allocator function
|
||||
|
|
|
@ -335,16 +335,20 @@ flac_cache (sfx_t *sfx, char *realname, flacfile_t *ff, wavinfo_t info)
|
|||
SND_SFX_Cache (sfx, realname, info, flac_callback_load);
|
||||
}
|
||||
|
||||
static int
|
||||
flac_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
static long
|
||||
flac_stream_read (void *file, float **buf)
|
||||
{
|
||||
return flac_read (file, buf, count);
|
||||
sfxstream_t *stream = (sfxstream_t *) file;
|
||||
flacfile_t *ff = (flacfile_t *) stream->file;
|
||||
FLAC__stream_decoder_process_single (ff->decoder);
|
||||
*buf = ff->buffer;
|
||||
return ff->size;
|
||||
}
|
||||
|
||||
static int
|
||||
flac_stream_seek (void *file, int pos, wavinfo_t *info)
|
||||
flac_stream_seek (sfxstream_t *stream, int pos)
|
||||
{
|
||||
flacfile_t *ff = file;
|
||||
flacfile_t *ff = stream->file;
|
||||
|
||||
ff->pos = ff->size = 0;
|
||||
return FLAC__stream_decoder_seek_absolute (ff->decoder, pos);
|
||||
|
@ -356,8 +360,7 @@ flac_stream_close (sfx_t *sfx)
|
|||
sfxstream_t *stream = sfx->data.stream;
|
||||
|
||||
flac_close (stream->file);
|
||||
free (stream);
|
||||
free (sfx);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
|
|
|
@ -47,6 +47,15 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
|
||||
#include "snd_render.h"
|
||||
|
||||
#define FRAMES 1024
|
||||
#define CHANNELS 2
|
||||
#define WIDTH 2
|
||||
|
||||
typedef struct {
|
||||
float data[FRAMES * CHANNELS];
|
||||
midi *handle;
|
||||
} midi_file_t;
|
||||
|
||||
static int midi_intiialized = 0;
|
||||
|
||||
static cvar_t *wildmidi_volume;
|
||||
|
@ -88,48 +97,46 @@ midi_get_info (void * handle) {
|
|||
return info;
|
||||
}
|
||||
|
||||
static int
|
||||
midi_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
static long
|
||||
midi_stream_read (void *file, float **buf)
|
||||
{
|
||||
int size = count * info->channels * info->width;
|
||||
sfxstream_t *stream = (sfxstream_t *) file;
|
||||
midi_file_t *mf = (midi_file_t *) stream->file;
|
||||
int size = FRAMES * CHANNELS * WIDTH;
|
||||
int res;
|
||||
byte *data = alloca (size);
|
||||
|
||||
res = WildMidi_GetOutput (file, (char *)data, size);
|
||||
if (res > 0) {
|
||||
res /= info->channels * info->width;
|
||||
SND_Convert (data, buf, res, info->channels, info->width);
|
||||
}
|
||||
res = WildMidi_GetOutput (mf->handle, (char *)data, size);
|
||||
if (res < 0)
|
||||
return res;
|
||||
res /= CHANNELS * WIDTH;
|
||||
SND_Convert (data, mf->data, res, CHANNELS, WIDTH);
|
||||
*buf = mf->data;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
midi_stream_seek (void *file, int pos, wavinfo_t *info)
|
||||
midi_stream_seek (sfxstream_t *stream, int pos)
|
||||
{
|
||||
unsigned long int new_pos;
|
||||
pos *= info->width * info->channels;
|
||||
pos += info->dataofs;
|
||||
pos *= stream->wavinfo.width * stream->wavinfo.channels;
|
||||
pos += stream->wavinfo.dataofs;
|
||||
new_pos = pos;
|
||||
|
||||
return WildMidi_SampledSeek(file, &new_pos);
|
||||
return WildMidi_SampledSeek(stream->file, &new_pos);
|
||||
}
|
||||
|
||||
static void
|
||||
midi_stream_close (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
midi_file_t *mf = (midi_file_t *) stream->file;
|
||||
|
||||
WildMidi_Close (stream->file);
|
||||
free (stream);
|
||||
free (sfx);
|
||||
WildMidi_Close (mf->handle);
|
||||
free (mf);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: we set up only the QF stream here.
|
||||
* The WildMidi stream was setup when SND_OpenMidi was called
|
||||
* so stream->file contains the WildMidi handle for the midi
|
||||
*/
|
||||
|
||||
static sfx_t *
|
||||
midi_stream_open (sfx_t *sfx)
|
||||
{
|
||||
|
@ -138,6 +145,7 @@ midi_stream_open (sfx_t *sfx)
|
|||
midi *handle;
|
||||
unsigned char *local_buffer;
|
||||
unsigned long int local_buffer_size;
|
||||
midi_file_t *mf;
|
||||
|
||||
QFS_FOpenFile (stream->file, &file);
|
||||
|
||||
|
@ -152,7 +160,10 @@ midi_stream_open (sfx_t *sfx)
|
|||
if (handle == NULL)
|
||||
return NULL;
|
||||
|
||||
return SND_SFX_StreamOpen (sfx, handle, midi_stream_read, midi_stream_seek,
|
||||
mf = calloc (sizeof (midi_file_t), 1);
|
||||
mf->handle = handle;
|
||||
|
||||
return SND_SFX_StreamOpen (sfx, mf, midi_stream_read, midi_stream_seek,
|
||||
midi_stream_close);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,36 +165,15 @@ read_samples (sfxbuffer_t *buffer, int count)
|
|||
read_samples (buffer, buffer->length - buffer->head);
|
||||
read_samples (buffer, count);
|
||||
} else {
|
||||
float stepscale;
|
||||
int frames, size;
|
||||
sfx_t *sfx = buffer->sfx;
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
float *data = buffer->data + buffer->head * info->channels;
|
||||
int c;
|
||||
|
||||
stepscale = (float) info->rate / snd_shm->speed;
|
||||
if ((c = stream->read (stream, data, count)) != count)
|
||||
Sys_Printf ("%s nr %d %d\n", sfx->name, count, c);
|
||||
|
||||
frames = count * stepscale;
|
||||
size = frames * info->channels * sizeof (float);
|
||||
|
||||
if (stream->resample) {
|
||||
float *data = alloca (size);
|
||||
int c;
|
||||
|
||||
if (stream->read (stream->file, data, frames, info) != frames)
|
||||
Sys_Printf ("%s r\n", sfx->name);
|
||||
c = stream->resample (buffer, data, frames);
|
||||
if (c < count) {
|
||||
data = buffer->data + (buffer->head + c - 1) * info->channels;
|
||||
while (c++ < count) {
|
||||
memcpy (data + info->channels, data,
|
||||
info->channels * sizeof (float));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
float *data = buffer->data + buffer->head * info->channels;
|
||||
if (stream->read (stream->file, data, frames, info) != frames)
|
||||
Sys_Printf ("%s nr\n", sfx->name);
|
||||
}
|
||||
buffer->head += count;
|
||||
if (buffer->head >= buffer->length)
|
||||
buffer->head -= buffer->length;
|
||||
|
@ -224,7 +203,7 @@ fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
|
|||
if (samples)
|
||||
read_samples (buffer, samples);
|
||||
if (loop_samples) {
|
||||
stream->seek (stream->file, info->loopstart, info);
|
||||
stream->seek (stream, info->loopstart);
|
||||
read_samples (buffer, loop_samples);
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +221,7 @@ SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos)
|
|||
buffer->head = buffer->tail = 0;
|
||||
buffer->pos = pos;
|
||||
stream->pos = pos;
|
||||
stream->seek (stream->file, buffer->pos * stepscale, info);
|
||||
stream->seek (stream, buffer->pos * stepscale);
|
||||
fill_buffer (sfx, stream, buffer, info, pos);
|
||||
}
|
||||
|
||||
|
@ -291,7 +270,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
stream->pos = buffer->pos;
|
||||
}
|
||||
headpos = buffer->pos;
|
||||
stream->seek (stream->file, buffer->pos * stepscale, info);
|
||||
stream->seek (stream, buffer->pos * stepscale);
|
||||
} else {
|
||||
buffer->pos += count;
|
||||
if (buffer->pos >= sfx->length) {
|
||||
|
@ -300,7 +279,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
headpos = buffer->pos = 0;
|
||||
buffer->head = buffer->tail = 0;
|
||||
count = 0;
|
||||
stream->seek (stream->file, buffer->pos * stepscale, info);
|
||||
stream->seek (stream, buffer->pos * stepscale);
|
||||
} else {
|
||||
buffer->pos -= sfx->length - sfx->loopstart;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,12 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
#include "compat.h"
|
||||
#include "snd_render.h"
|
||||
|
||||
typedef struct {
|
||||
float *data;
|
||||
int size;
|
||||
int pos;
|
||||
} snd_null_state_t;
|
||||
|
||||
static void
|
||||
check_buffer_integrity (sfxbuffer_t *sc, int width, const char *func)
|
||||
{
|
||||
|
@ -85,28 +91,40 @@ SND_Resample (sfxbuffer_t *sc, float *data, int length)
|
|||
}
|
||||
|
||||
static int
|
||||
SND_ResampleStream (sfxbuffer_t *sc, float *data, int length)
|
||||
snd_read (sfxstream_t *stream, float *data, int frames)
|
||||
{
|
||||
SRC_DATA src_data;
|
||||
SRC_STATE *state = (SRC_STATE *) sc->sfx->data.stream->state;
|
||||
snd_null_state_t *state = (snd_null_state_t *) stream->state;
|
||||
int channels = stream->buffer.channels;
|
||||
int framesize = channels * sizeof (float);
|
||||
int count;
|
||||
int read = 0;
|
||||
|
||||
int outcount;
|
||||
double stepscale;
|
||||
wavinfo_t *info = sc->sfx->wavinfo (sc->sfx);
|
||||
int inrate = info->rate;
|
||||
while (frames) {
|
||||
if (state->pos == state->size) {
|
||||
state->size = stream->ll_read (stream, &state->data);
|
||||
if (state->size <= 0)
|
||||
return state->size;
|
||||
state->pos = 0;
|
||||
}
|
||||
count = frames;
|
||||
if (count > state->size - state->pos)
|
||||
count = state->size - state->pos;
|
||||
memcpy (data, state->data + state->pos * channels, count * framesize);
|
||||
state->pos += count;
|
||||
frames -= count;
|
||||
read += count;
|
||||
data += count * channels;
|
||||
}
|
||||
return read;
|
||||
}
|
||||
|
||||
stepscale = (double) snd_shm->speed / inrate;
|
||||
outcount = length * stepscale;
|
||||
static int
|
||||
snd_resample_read (sfxstream_t *stream, float *data, int frames)
|
||||
{
|
||||
int inrate = stream->wavinfo.rate;
|
||||
double ratio = (double) snd_shm->speed / inrate;
|
||||
|
||||
src_data.data_in = data;
|
||||
src_data.data_out = sc->data + sc->head * sc->channels;
|
||||
src_data.input_frames = length;
|
||||
src_data.output_frames = outcount;
|
||||
src_data.src_ratio = stepscale;
|
||||
src_data.end_of_input = 0; //XXX
|
||||
|
||||
src_process (state, &src_data);
|
||||
return src_data.output_frames_gen;
|
||||
return src_callback_read (stream->state, ratio, frames, data);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -131,15 +149,27 @@ SND_SetupResampler (sfxbuffer_t *sc, int streamed)
|
|||
sfxstream_t *stream = sc->sfx->data.stream;
|
||||
|
||||
if (snd_shm->speed == inrate) {
|
||||
stream->state = 0;
|
||||
stream->resample = 0;
|
||||
stream->state = calloc (sizeof (snd_null_state_t), 1);
|
||||
stream->read = snd_read;
|
||||
} else {
|
||||
stream->state = src_new (SRC_LINEAR, info->channels, &err);
|
||||
stream->resample = SND_ResampleStream;
|
||||
stream->state = src_callback_new (stream->ll_read,
|
||||
SRC_LINEAR, info->channels,
|
||||
&err, stream);
|
||||
stream->read = snd_resample_read;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SND_PulldownResampler (sfxstream_t *stream)
|
||||
{
|
||||
if (stream->read == snd_resample_read) {
|
||||
src_delete (stream->state);
|
||||
} else {
|
||||
free (stream->state);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SND_Convert (byte *idata, float *fdata, int frames, int channels, int width)
|
||||
{
|
||||
|
|
|
@ -111,8 +111,8 @@ SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
|||
|
||||
sfx_t *
|
||||
SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||
int (*read)(void *, float *, int, wavinfo_t *),
|
||||
int (*seek)(void *, int, wavinfo_t *),
|
||||
long (*read)(void *, float **),
|
||||
int (*seek)(sfxstream_t *, int),
|
||||
void (*close) (sfx_t *))
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
|
@ -139,7 +139,7 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
memcpy ((byte *) stream->buffer.data + size, "\xde\xad\xbe\xef", 4);
|
||||
stream->file = file;
|
||||
stream->sfx = new_sfx;
|
||||
stream->read = read;
|
||||
stream->ll_read = read;
|
||||
stream->seek = seek;
|
||||
|
||||
stream->wavinfo = *sfx->wavinfo (sfx);
|
||||
|
@ -156,6 +156,15 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
return new_sfx;
|
||||
}
|
||||
|
||||
void
|
||||
SND_SFX_StreamClose (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
SND_PulldownResampler (stream);
|
||||
free (stream);
|
||||
free (sfx);
|
||||
}
|
||||
|
||||
sfx_t *
|
||||
SND_LoadSound (const char *name)
|
||||
{
|
||||
|
|
|
@ -51,6 +51,13 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
|
||||
#include "snd_render.h"
|
||||
|
||||
#define FRAMES 1024
|
||||
|
||||
typedef struct {
|
||||
float *data;
|
||||
OggVorbis_File *vf;
|
||||
} vorbis_file_t;
|
||||
|
||||
static size_t
|
||||
vorbis_read_func (void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
{
|
||||
|
@ -211,26 +218,40 @@ vorbis_cache (sfx_t *sfx, char *realname, OggVorbis_File *vf, wavinfo_t info)
|
|||
SND_SFX_Cache (sfx, realname, info, vorbis_callback_load);
|
||||
}
|
||||
|
||||
static int
|
||||
vorbis_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
static long
|
||||
vorbis_stream_read (void *file, float **buf)
|
||||
{
|
||||
return vorbis_read (file, buf, count, info);
|
||||
sfxstream_t *stream = (sfxstream_t *) file;
|
||||
vorbis_file_t *vf = (vorbis_file_t *) stream->file;
|
||||
int res;
|
||||
|
||||
if (!vf->data)
|
||||
vf->data = malloc (FRAMES * stream->wavinfo.channels * sizeof (float));
|
||||
res = vorbis_read (vf->vf, vf->data, FRAMES, &stream->wavinfo);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
*buf = vf->data;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
vorbis_stream_seek (void *file, int pos, wavinfo_t *info)
|
||||
vorbis_stream_seek (sfxstream_t *stream, int pos)
|
||||
{
|
||||
return ov_pcm_seek (file, pos);
|
||||
vorbis_file_t *vf = (vorbis_file_t *) stream->file;
|
||||
return ov_pcm_seek (vf->vf, pos);
|
||||
}
|
||||
|
||||
static void
|
||||
vorbis_stream_close (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
vorbis_file_t *vf = (vorbis_file_t *) stream->file;
|
||||
|
||||
ov_clear (stream->file);
|
||||
free (stream);
|
||||
free (sfx);
|
||||
if (vf->data)
|
||||
free (vf->data);
|
||||
ov_clear (vf->vf);
|
||||
free (vf);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
|
@ -238,14 +259,15 @@ vorbis_stream_open (sfx_t *sfx)
|
|||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
QFile *file;
|
||||
void *f;
|
||||
vorbis_file_t *f;
|
||||
|
||||
QFS_FOpenFile (stream->file, &file);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
f = malloc (sizeof (OggVorbis_File));
|
||||
if (ov_open_callbacks (file, f, 0, 0, callbacks) < 0) {
|
||||
f = calloc (sizeof (vorbis_file_t), 1);
|
||||
f->vf = malloc (sizeof (OggVorbis_File));
|
||||
if (ov_open_callbacks (file, f->vf, 0, 0, callbacks) < 0) {
|
||||
Sys_Printf ("Input does not appear to be an Ogg bitstream.\n");
|
||||
Qclose (file);
|
||||
free (f);
|
||||
|
|
|
@ -48,6 +48,13 @@ static __attribute__ ((used)) const char rcsid[] =
|
|||
|
||||
#include "snd_render.h"
|
||||
|
||||
#define FRAMES 1024
|
||||
|
||||
typedef struct {
|
||||
float *data;
|
||||
QFile *file;
|
||||
} wav_file_t;
|
||||
|
||||
static void
|
||||
wav_callback_load (void *object, cache_allocator_t allocator)
|
||||
{
|
||||
|
@ -91,37 +98,49 @@ wav_cache (sfx_t *sfx, char *realname, void *file, wavinfo_t info)
|
|||
SND_SFX_Cache (sfx, realname, info, wav_callback_load);
|
||||
}
|
||||
|
||||
static int
|
||||
wav_stream_read (void *file, float *buf, int count, wavinfo_t *info)
|
||||
static long
|
||||
wav_stream_read (void *file, float **buf)
|
||||
{
|
||||
sfxstream_t *stream = (sfxstream_t *) file;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
wav_file_t *wf = (wav_file_t *) stream->file;
|
||||
int res;
|
||||
int len = count * info->channels * info->width;
|
||||
int len = FRAMES * info->channels * info->width;
|
||||
byte *data = alloca (len);
|
||||
|
||||
res = Qread (file, data, len);
|
||||
if (res > 0) {
|
||||
res /= (info->channels * info->width);
|
||||
SND_Convert (data, buf, res, info->channels, info->width);
|
||||
}
|
||||
if (!wf->data)
|
||||
wf->data = malloc (FRAMES * info->channels * sizeof (float));
|
||||
|
||||
res = Qread (wf->file, data, len);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
res /= (info->channels * info->width);
|
||||
SND_Convert (data, wf->data, res, info->channels, info->width);
|
||||
*buf = wf->data;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
wav_stream_seek (void *file, int pos, wavinfo_t *info)
|
||||
wav_stream_seek (sfxstream_t *stream, int pos)
|
||||
{
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
wav_file_t *wf = (wav_file_t *) stream->file;
|
||||
pos *= info->width * info->channels;
|
||||
pos += info->dataofs;
|
||||
return Qseek (file, pos, SEEK_SET);
|
||||
return Qseek (wf->file, pos, SEEK_SET);
|
||||
}
|
||||
|
||||
static void
|
||||
wav_stream_close (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
wav_file_t *wf = (wav_file_t *) stream->file;
|
||||
|
||||
Qclose (stream->file);
|
||||
free (stream);
|
||||
free (sfx);
|
||||
Qclose (wf->file);
|
||||
if (wf->data)
|
||||
free (wf->data);
|
||||
free (wf);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
|
@ -129,12 +148,15 @@ wav_stream_open (sfx_t *sfx)
|
|||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
QFile *file;
|
||||
wav_file_t *wf;
|
||||
|
||||
QFS_FOpenFile (stream->file, &file);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
return SND_SFX_StreamOpen (sfx, file, wav_stream_read, wav_stream_seek,
|
||||
wf = calloc (sizeof (wav_file_t), 1);
|
||||
wf->file = file;
|
||||
return SND_SFX_StreamOpen (sfx, wf, wav_stream_read, wav_stream_seek,
|
||||
wav_stream_close);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue