mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-05-31 00:30:57 +00:00
[sound] Access the buffer directly from the channel
This improves the locality of reference when mixing and removes the proxy sfx for streamed sounds. The buffer for streamed sounds is allocated when the stream is opened (since streamed sounds can't share buffers), and freed when the stream is closed. For block sounds, the buffer is reference counted (with the sfx holding one reference, so currently block buffers never get freed), with their reference count getting incremented on open and decremented on close. That the reference counts get to 1 has been confirmed, so all that should be needed is proper destruction of the sfx instances. Still need to sort out just why channels leak across level changes.
This commit is contained in:
parent
11fee8571c
commit
91140acfee
11 changed files with 240 additions and 205 deletions
|
@ -56,28 +56,29 @@ struct sfx_s
|
||||||
{
|
{
|
||||||
struct snd_s *snd; //!< ownding snd_t instance
|
struct snd_s *snd; //!< ownding snd_t instance
|
||||||
const char *name;
|
const char *name;
|
||||||
sfx_t *owner;
|
|
||||||
|
|
||||||
unsigned int length;
|
unsigned length;
|
||||||
unsigned int loopstart;
|
unsigned loopstart;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
sfxstream_t *stream;
|
sfxstream_t *stream;
|
||||||
sfxblock_t *block;
|
sfxblock_t *block;
|
||||||
} data;
|
};
|
||||||
|
|
||||||
sfxbuffer_t *(*touch) (sfx_t *sfx);
|
sfxbuffer_t *(*touch) (sfx_t *sfx);
|
||||||
sfxbuffer_t *(*retain) (sfx_t *sfx);
|
sfxbuffer_t *(*retain) (sfx_t *sfx);
|
||||||
void (*release) (sfx_t *sfx);
|
void (*release) (sfx_t *sfx);
|
||||||
|
|
||||||
sfxbuffer_t *(*getbuffer) (sfx_t *sfx);
|
sfxbuffer_t *(*getbuffer) (sfx_t *sfx);
|
||||||
struct wavinfo_s *(*wavinfo) (sfx_t *sfx);
|
struct wavinfo_s *(*wavinfo) (const sfx_t *sfx);
|
||||||
|
|
||||||
sfx_t *(*open) (sfx_t *sfx);
|
sfxbuffer_t *(*open) (sfx_t *sfx);
|
||||||
void (*close) (sfx_t *sfx);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** paint samples into the mix buffer
|
/** paint samples into the mix buffer
|
||||||
|
|
||||||
|
This is currently used for channel-count specific mixing
|
||||||
|
|
||||||
\param offset offset into the mix buffer at which to start mixing
|
\param offset offset into the mix buffer at which to start mixing
|
||||||
the channel
|
the channel
|
||||||
\param ch sound channel
|
\param ch sound channel
|
||||||
|
@ -87,7 +88,7 @@ struct sfx_s
|
||||||
typedef void sfxpaint_t (int offset, channel_t *ch, float *buffer,
|
typedef void sfxpaint_t (int offset, channel_t *ch, float *buffer,
|
||||||
unsigned count);
|
unsigned count);
|
||||||
|
|
||||||
/** Represent a sound sample in the mixer.
|
/** Represent a single output frame in the mixer.
|
||||||
*/
|
*/
|
||||||
struct portable_samplepair_s {
|
struct portable_samplepair_s {
|
||||||
float left; //!< left sample
|
float left; //!< left sample
|
||||||
|
@ -146,6 +147,14 @@ struct sfxbuffer_s {
|
||||||
unsigned size; //!< size of buffer in frames
|
unsigned size; //!< size of buffer in frames
|
||||||
unsigned pos; //!< position of tail within full stream
|
unsigned pos; //!< position of tail within full stream
|
||||||
unsigned channels; //!< number of channels per frame
|
unsigned channels; //!< number of channels per frame
|
||||||
|
unsigned sfx_length; //!< total length of sfx
|
||||||
|
union { // owning instance
|
||||||
|
// the first field of both sfxstream_t and sfxblock_t is a pointer
|
||||||
|
// to sfx_t
|
||||||
|
sfx_t const * const * const sfx;
|
||||||
|
sfxstream_t *stream;
|
||||||
|
sfxblock_t *block;
|
||||||
|
};
|
||||||
sfxpaint_t *paint; //!< channel count specific paint function
|
sfxpaint_t *paint; //!< channel count specific paint function
|
||||||
/** Advance the position with the stream, updating the ring buffer as
|
/** Advance the position with the stream, updating the ring buffer as
|
||||||
necessary. Null for chached sounds.
|
necessary. Null for chached sounds.
|
||||||
|
@ -160,7 +169,7 @@ struct sfxbuffer_s {
|
||||||
\param pos frame position with the stream
|
\param pos frame position with the stream
|
||||||
*/
|
*/
|
||||||
void (*setpos) (sfxbuffer_t *buffer, unsigned int pos);
|
void (*setpos) (sfxbuffer_t *buffer, unsigned int pos);
|
||||||
sfx_t *sfx; //!< owning sfx_t instance
|
void (*close) (sfxbuffer_t *buffer);
|
||||||
/** Sample data. The block at the beginning of the buffer (size depends on
|
/** Sample data. The block at the beginning of the buffer (size depends on
|
||||||
sample size)
|
sample size)
|
||||||
*/
|
*/
|
||||||
|
@ -170,7 +179,7 @@ struct sfxbuffer_s {
|
||||||
/** Representation of sound loaded that is streamed in as needed.
|
/** Representation of sound loaded that is streamed in as needed.
|
||||||
*/
|
*/
|
||||||
struct sfxstream_s {
|
struct sfxstream_s {
|
||||||
sfx_t *sfx; //!< owning sfx_t instance
|
const sfx_t *sfx; //!< owning sfx_t instance
|
||||||
void *file; //!< handle for "file" representing the stream
|
void *file; //!< handle for "file" representing the stream
|
||||||
wavinfo_t wavinfo; //!< description of sound data
|
wavinfo_t wavinfo; //!< description of sound data
|
||||||
unsigned pos; //!< position of next frame full stream
|
unsigned pos; //!< position of next frame full stream
|
||||||
|
@ -213,25 +222,24 @@ struct sfxstream_s {
|
||||||
/** Representation of sound loaded into memory as a full block.
|
/** Representation of sound loaded into memory as a full block.
|
||||||
*/
|
*/
|
||||||
struct sfxblock_s {
|
struct sfxblock_s {
|
||||||
sfx_t *sfx; //!< owning sfx_t instance
|
const sfx_t *sfx; //!< owning sfx_t instance
|
||||||
void *file; //!< handle for "file" representing the block
|
void *file; //!< handle for "file" representing the block
|
||||||
wavinfo_t wavinfo; //!< description of sound data
|
wavinfo_t wavinfo; //!< description of sound data
|
||||||
cache_user_t cache; //!< cached sound buffer (::sfxbuffer_s)
|
|
||||||
sfxbuffer_t *buffer; //!< pointer to cached buffer
|
sfxbuffer_t *buffer; //!< pointer to cached buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Representation of a sound being played.
|
/** Representation of a sound being played.
|
||||||
*/
|
*/
|
||||||
struct channel_s {
|
struct channel_s {
|
||||||
sfx_t *sfx; //!< sound played by this channel
|
sfxbuffer_t *buffer; //!< sound played by this channel
|
||||||
float leftvol; //!< 0-1 volume
|
float leftvol; //!< 0-1 volume
|
||||||
float rightvol; //!< 0-1 volume
|
float rightvol; //!< 0-1 volume
|
||||||
unsigned end; //!< end time in global paintsamples
|
unsigned end; //!< end time in global paintsamples
|
||||||
unsigned pos; //!< sample position in sfx
|
unsigned pos; //!< sample position in sfx
|
||||||
unsigned looping; //!< where to loop, -1 = no looping
|
unsigned loopstart; //!< where to loop, -1 = no looping
|
||||||
int pause; //!< don't update the channel at all
|
|
||||||
int phase; //!< phase shift between l-r in samples
|
int phase; //!< phase shift between l-r in samples
|
||||||
int oldphase; //!< phase shift between l-r in samples
|
int oldphase; //!< phase shift between l-r in samples
|
||||||
|
byte pause; //!< don't update the channel at all
|
||||||
/** signal between main program and mixer thread that the channel is to be
|
/** signal between main program and mixer thread that the channel is to be
|
||||||
stopped.
|
stopped.
|
||||||
- both \c stop and \c done are zero: normal operation
|
- both \c stop and \c done are zero: normal operation
|
||||||
|
@ -243,8 +251,8 @@ struct channel_s {
|
||||||
can be reused at any time.
|
can be reused at any time.
|
||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
int stop;
|
byte stop;
|
||||||
int done;
|
byte done;
|
||||||
//@}
|
//@}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -259,7 +267,11 @@ extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2];
|
||||||
void SND_Memory_Init_Cvars (void);
|
void SND_Memory_Init_Cvars (void);
|
||||||
int SND_Memory_Init (void);
|
int SND_Memory_Init (void);
|
||||||
sfxbuffer_t *SND_Memory_AllocBuffer (unsigned samples);
|
sfxbuffer_t *SND_Memory_AllocBuffer (unsigned samples);
|
||||||
void SND_Memory_FreeBuffer (sfxbuffer_t *buffer);
|
void SND_Memory_Free (void *ptr);
|
||||||
|
void SND_Memory_SetTag (void *ptr, int tag);
|
||||||
|
int SND_Memory_Retain (void *ptr);
|
||||||
|
int SND_Memory_Release (void *ptr);
|
||||||
|
int SND_Memory_GetRetainCount (void *ptr) __attribute__((pure));
|
||||||
|
|
||||||
/** \defgroup sound_render_sfx Sound sfx
|
/** \defgroup sound_render_sfx Sound sfx
|
||||||
\ingroup sound_render_mix
|
\ingroup sound_render_mix
|
||||||
|
@ -281,7 +293,7 @@ void SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
\param open
|
\param open
|
||||||
*/
|
*/
|
||||||
void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
sfx_t *(*open) (sfx_t *sfx));
|
sfxbuffer_t *(*open) (sfx_t *sfx));
|
||||||
|
|
||||||
/** Open a stream for playback.
|
/** Open a stream for playback.
|
||||||
\param sfx
|
\param sfx
|
||||||
|
@ -290,15 +302,15 @@ void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
\param seek
|
\param seek
|
||||||
\param close
|
\param close
|
||||||
*/
|
*/
|
||||||
sfx_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
sfxbuffer_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||||
long (*read)(void *, float **),
|
long (*read)(void *, float **),
|
||||||
int (*seek)(sfxstream_t *, int),
|
int (*seek)(sfxstream_t *, int),
|
||||||
void (*close) (sfx_t *));
|
void (*close) (sfxbuffer_t *));
|
||||||
|
|
||||||
/** Close a stream.
|
/** Close a stream.
|
||||||
\param sfx
|
\param sfx
|
||||||
*/
|
*/
|
||||||
void SND_SFX_StreamClose (sfx_t *sfx);
|
void SND_SFX_StreamClose (sfxstream_t *stream);
|
||||||
|
|
||||||
/** Pre-load a sound into the cache.
|
/** Pre-load a sound into the cache.
|
||||||
\param snd sound system state
|
\param snd sound system state
|
||||||
|
@ -466,7 +478,7 @@ void SND_SetPaint (sfxbuffer_t *sb);
|
||||||
*/
|
*/
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
unsigned SND_ResamplerFrames (sfx_t *sfx);
|
unsigned SND_ResamplerFrames (const sfx_t *sfx, unsigned frames);
|
||||||
|
|
||||||
/** Set up the various parameters that depend on the actual sample rate.
|
/** Set up the various parameters that depend on the actual sample rate.
|
||||||
\param sb buffer to setup
|
\param sb buffer to setup
|
||||||
|
@ -549,13 +561,13 @@ int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname);
|
||||||
\param sfx sound reference
|
\param sfx sound reference
|
||||||
\return pointer to sound's wavinfo
|
\return pointer to sound's wavinfo
|
||||||
*/
|
*/
|
||||||
wavinfo_t *SND_CacheWavinfo (sfx_t *sfx) __attribute__((pure));
|
wavinfo_t *SND_CacheWavinfo (const sfx_t *sfx) __attribute__((pure));
|
||||||
|
|
||||||
/** Retrieve wavinfo from a streamed sound.
|
/** Retrieve wavinfo from a streamed sound.
|
||||||
\param sfx sound reference
|
\param sfx sound reference
|
||||||
\return pointer to sound's wavinfo
|
\return pointer to sound's wavinfo
|
||||||
*/
|
*/
|
||||||
wavinfo_t *SND_StreamWavinfo (sfx_t *sfx) __attribute__((pure));
|
wavinfo_t *SND_StreamWavinfo (const sfx_t *sfx) __attribute__((pure));
|
||||||
|
|
||||||
/** Ensure a cached sound is in memory.
|
/** Ensure a cached sound is in memory.
|
||||||
\param sfx sound reference
|
\param sfx sound reference
|
||||||
|
|
|
@ -283,18 +283,20 @@ flac_load (flacfile_t *ff, sfxblock_t *block)
|
||||||
{
|
{
|
||||||
float *data;
|
float *data;
|
||||||
sfxbuffer_t *sb = 0;
|
sfxbuffer_t *sb = 0;
|
||||||
sfx_t *sfx = block->sfx;
|
const sfx_t *sfx = block->sfx;
|
||||||
wavinfo_t *info = &block->wavinfo;
|
wavinfo_t *info = &block->wavinfo;
|
||||||
|
|
||||||
data = malloc (info->datalen);
|
data = malloc (info->datalen);
|
||||||
if (!data)
|
if (!data)
|
||||||
goto bail;
|
goto bail;
|
||||||
unsigned buffer_frames = SND_ResamplerFrames (sfx);
|
unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames);
|
||||||
sb = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
sb = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
||||||
if (!sb)
|
if (!sb)
|
||||||
goto bail;
|
goto bail;
|
||||||
sb->size = buffer_frames * info->channels;
|
sb->size = buffer_frames * info->channels;
|
||||||
sb->sfx = sfx;
|
sb->channels = info->channels;
|
||||||
|
sb->sfx_length = info->frames;
|
||||||
|
sb->block = sfx->block;
|
||||||
if (flac_read (ff, data, info->frames) < 0)
|
if (flac_read (ff, data, info->frames) < 0)
|
||||||
goto bail;
|
goto bail;
|
||||||
SND_SetPaint (sb);
|
SND_SetPaint (sb);
|
||||||
|
@ -358,18 +360,18 @@ flac_stream_seek (sfxstream_t *stream, int pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
flac_stream_close (sfx_t *sfx)
|
flac_stream_close (sfxbuffer_t *buffer)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = buffer->stream;
|
||||||
|
|
||||||
flac_close (stream->file);
|
flac_close (stream->file);
|
||||||
SND_SFX_StreamClose (sfx);
|
SND_SFX_StreamClose (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfx_t *
|
static sfxbuffer_t *
|
||||||
flac_stream_open (sfx_t *sfx)
|
flac_stream_open (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = sfx->stream;
|
||||||
QFile *file;
|
QFile *file;
|
||||||
void *f;
|
void *f;
|
||||||
|
|
||||||
|
|
|
@ -143,20 +143,20 @@ midi_stream_seek (sfxstream_t *stream, int pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
midi_stream_close (sfx_t *sfx)
|
midi_stream_close (sfxbuffer_t *buffer)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = buffer->stream;
|
||||||
midi_file_t *mf = (midi_file_t *) stream->file;
|
midi_file_t *mf = (midi_file_t *) stream->file;
|
||||||
|
|
||||||
WildMidi_Close (mf->handle);
|
WildMidi_Close (mf->handle);
|
||||||
free (mf);
|
free (mf);
|
||||||
SND_SFX_StreamClose (sfx);
|
SND_SFX_StreamClose (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfx_t *
|
static sfxbuffer_t *
|
||||||
midi_stream_open (sfx_t *sfx)
|
midi_stream_open (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = sfx->stream;
|
||||||
QFile *file;
|
QFile *file;
|
||||||
midi *handle;
|
midi *handle;
|
||||||
unsigned char *local_buffer;
|
unsigned char *local_buffer;
|
||||||
|
|
|
@ -148,7 +148,8 @@ static cvar_t ambient_level_cvar = {
|
||||||
static void
|
static void
|
||||||
snd_free_channel (channel_t *ch)
|
snd_free_channel (channel_t *ch)
|
||||||
{
|
{
|
||||||
ch->sfx = 0;
|
sfxbuffer_t *buffer = ch->buffer;
|
||||||
|
ch->buffer = 0;
|
||||||
ch->stop = 0;
|
ch->stop = 0;
|
||||||
ch->done = 0;
|
ch->done = 0;
|
||||||
int chan_ind = ch - snd_channels;
|
int chan_ind = ch - snd_channels;
|
||||||
|
@ -157,6 +158,10 @@ snd_free_channel (channel_t *ch)
|
||||||
}
|
}
|
||||||
snd_free_channels[snd_num_free_channels++] = chan_ind;
|
snd_free_channels[snd_num_free_channels++] = chan_ind;
|
||||||
snd_entity_channels[chan_ind] = (entchan_t) {};
|
snd_entity_channels[chan_ind] = (entchan_t) {};
|
||||||
|
|
||||||
|
if (buffer) {
|
||||||
|
buffer->close (buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_t *
|
channel_t *
|
||||||
|
@ -164,8 +169,8 @@ SND_AllocChannel (snd_t *snd)
|
||||||
{
|
{
|
||||||
channel_t *chan;
|
channel_t *chan;
|
||||||
|
|
||||||
//Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n",
|
Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n",
|
||||||
// snd_num_free_channels);
|
snd_num_free_channels);
|
||||||
if (!snd_num_free_channels) {
|
if (!snd_num_free_channels) {
|
||||||
Sys_MaskPrintf (SYS_warn, "SND_AllocChannel: out of channels.\n");
|
Sys_MaskPrintf (SYS_warn, "SND_AllocChannel: out of channels.\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -181,7 +186,7 @@ SND_AllocChannel (snd_t *snd)
|
||||||
void
|
void
|
||||||
SND_ChannelStop (snd_t *snd, channel_t *chan)
|
SND_ChannelStop (snd_t *snd, channel_t *chan)
|
||||||
{
|
{
|
||||||
if (!chan->sfx) {
|
if (!chan->buffer) {
|
||||||
Sys_MaskPrintf (SYS_warn, "Sound: stop called on invalid channel\n");
|
Sys_MaskPrintf (SYS_warn, "Sound: stop called on invalid channel\n");
|
||||||
}
|
}
|
||||||
chan->stop = 1;
|
chan->stop = 1;
|
||||||
|
@ -207,7 +212,7 @@ SND_ScanChannels (snd_t *snd, int wait)
|
||||||
count = 0;
|
count = 0;
|
||||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||||
ch = &snd_channels[i];
|
ch = &snd_channels[i];
|
||||||
if (!ch->sfx || ch->done)
|
if (!ch->buffer || ch->done)
|
||||||
continue;
|
continue;
|
||||||
ch->stop = 1;
|
ch->stop = 1;
|
||||||
count++;
|
count++;
|
||||||
|
@ -221,7 +226,7 @@ SND_ScanChannels (snd_t *snd, int wait)
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||||
ch = &snd_channels[i];
|
ch = &snd_channels[i];
|
||||||
if (ch->sfx && ch->stop && !ch->done) {
|
if (ch->buffer && ch->stop && !ch->done) {
|
||||||
ch->done = 1;
|
ch->done = 1;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -230,11 +235,11 @@ SND_ScanChannels (snd_t *snd, int wait)
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||||
ch = &snd_channels[i];
|
ch = &snd_channels[i];
|
||||||
if (!ch->sfx || !ch->done)
|
if (!ch->buffer || !ch->done)
|
||||||
continue;
|
continue;
|
||||||
ch->sfx->release (ch->sfx);
|
sfxbuffer_t *buffer = ch->buffer;
|
||||||
ch->sfx->close (ch->sfx);
|
ch->buffer = 0;
|
||||||
ch->sfx = 0;
|
buffer->close (buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,8 +424,6 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level)
|
||||||
{
|
{
|
||||||
float vol;
|
float vol;
|
||||||
int ambient_channel;
|
int ambient_channel;
|
||||||
channel_t *chan;
|
|
||||||
sfx_t *sfx;
|
|
||||||
|
|
||||||
if (!snd_ambient)
|
if (!snd_ambient)
|
||||||
return;
|
return;
|
||||||
|
@ -430,7 +433,7 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level)
|
||||||
// stop all ambient channels.
|
// stop all ambient channels.
|
||||||
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
||||||
ambient_channel++) {
|
ambient_channel++) {
|
||||||
chan = ambient_channels[ambient_channel];
|
channel_t *chan = ambient_channels[ambient_channel];
|
||||||
if (chan) {
|
if (chan) {
|
||||||
int chan_ind = chan - snd_channels;
|
int chan_ind = chan - snd_channels;
|
||||||
spacial_t *spacial = &snd_spacialization[chan_ind];
|
spacial_t *spacial = &snd_spacialization[chan_ind];
|
||||||
|
@ -443,28 +446,28 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level)
|
||||||
|
|
||||||
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
||||||
ambient_channel++) {
|
ambient_channel++) {
|
||||||
sfx = ambient_sfx[ambient_channel];
|
sfx_t *sfx = ambient_sfx[ambient_channel];
|
||||||
if (!sfx)
|
if (!sfx)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
chan = ambient_channels[ambient_channel];
|
channel_t *chan = ambient_channels[ambient_channel];
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
chan = ambient_channels[ambient_channel] = SND_AllocChannel (snd);
|
chan = ambient_channels[ambient_channel] = SND_AllocChannel (snd);
|
||||||
if (!chan)
|
if (!chan)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chan->sfx) {
|
sfxbuffer_t *buffer;
|
||||||
sfx = sfx->open (sfx);
|
if (!chan->buffer) {
|
||||||
if (!sfx)
|
buffer = sfx->open (sfx);
|
||||||
|
if (!buffer)
|
||||||
continue;
|
continue;
|
||||||
sfx->retain (sfx);
|
|
||||||
} else {
|
} else {
|
||||||
sfx = chan->sfx;
|
buffer = chan->buffer;
|
||||||
//sfx->retain (sfx); //FIXME why is this necessary?
|
//sfx->retain (sfx); //FIXME why is this necessary?
|
||||||
}
|
}
|
||||||
// sfx will be written to chan->sfx later to ensure mixer doesn't use
|
// buffer will be written to chan->buffer later to ensure mixer
|
||||||
// channel prematurely.
|
// doesn't use channel prematurely.
|
||||||
|
|
||||||
int chan_ind = chan - snd_channels;
|
int chan_ind = chan - snd_channels;
|
||||||
spacial_t *spacial = &snd_spacialization[chan_ind];
|
spacial_t *spacial = &snd_spacialization[chan_ind];
|
||||||
|
@ -486,7 +489,8 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level)
|
||||||
}
|
}
|
||||||
|
|
||||||
chan->leftvol = chan->rightvol = spacial->volume;
|
chan->leftvol = chan->rightvol = spacial->volume;
|
||||||
chan->sfx = sfx;
|
chan->loopstart = sfx->loopstart;
|
||||||
|
chan->buffer = buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,7 +552,7 @@ s_spatialize (snd_t *snd, channel_t *ch)
|
||||||
static inline int
|
static inline int
|
||||||
s_update_channel (snd_t *snd, channel_t *ch)
|
s_update_channel (snd_t *snd, channel_t *ch)
|
||||||
{
|
{
|
||||||
if (!ch->sfx)
|
if (!ch->buffer)
|
||||||
return 0;
|
return 0;
|
||||||
s_spatialize (snd, ch);
|
s_spatialize (snd, ch);
|
||||||
if (!ch->leftvol && !ch->rightvol)
|
if (!ch->leftvol && !ch->rightvol)
|
||||||
|
@ -585,7 +589,7 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level)
|
||||||
channel_t *combine = 0;
|
channel_t *combine = 0;
|
||||||
for (int i = 0; i < MAX_CHANNELS; i++) {
|
for (int i = 0; i < MAX_CHANNELS; i++) {
|
||||||
channel_t *ch = &snd_channels[i];
|
channel_t *ch = &snd_channels[i];
|
||||||
if (!ch->sfx || ch->done) {
|
if (!ch->buffer || ch->done) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (set_is_member (&dynamic_channels, i)
|
if (set_is_member (&dynamic_channels, i)
|
||||||
|
@ -597,10 +601,13 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level)
|
||||||
// too quiet
|
// too quiet
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
//FIXME does this even work? probably better just to give
|
||||||
|
//static sounds random offsets (I suspect it worked just fine
|
||||||
|
//before streams were implemented)
|
||||||
// try to combine static sounds with a previous channel of
|
// try to combine static sounds with a previous channel of
|
||||||
// the same sound effect so we don't mix five torches every
|
// the same sound effect so we don't mix five torches every
|
||||||
// frame see if it can just use the last one
|
// frame see if it can just use the last one
|
||||||
if (combine && combine->sfx == ch->sfx) {
|
if (combine && combine->buffer == ch->buffer) {
|
||||||
s_combine_channel (combine, ch);
|
s_combine_channel (combine, ch);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -608,7 +615,7 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level)
|
||||||
channel_t *c = 0;
|
channel_t *c = 0;
|
||||||
for (int j = 0; j < i; j++) {
|
for (int j = 0; j < i; j++) {
|
||||||
if (set_is_member (&static_channels, j)) {
|
if (set_is_member (&static_channels, j)) {
|
||||||
if (snd_channels[j].sfx == ch->sfx) {
|
if (snd_channels[j].buffer == ch->buffer) {
|
||||||
c = &snd_channels[j];
|
c = &snd_channels[j];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -623,11 +630,11 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check,
|
snd_check_channels (snd_t *snd, channel_t *target_chan, const channel_t *check,
|
||||||
const sfx_t *osfx)
|
const sfx_t *sfx)
|
||||||
{
|
{
|
||||||
if (!check || !check->sfx || check == target_chan)
|
if (!check || !check->buffer || check == target_chan)
|
||||||
return 0;
|
return 0;
|
||||||
if (check->sfx->owner == osfx->owner && !check->pos) {
|
if (*check->buffer->sfx == sfx && !check->pos) {
|
||||||
int skip = rand () % (int) (0.01 * snd->speed);
|
int skip = rand () % (int) (0.01 * snd->speed);
|
||||||
target_chan->pos = -skip;
|
target_chan->pos = -skip;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -639,15 +646,11 @@ void
|
||||||
SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
||||||
vec4f_t origin, float vol, float attenuation)
|
vec4f_t origin, float vol, float attenuation)
|
||||||
{
|
{
|
||||||
int looped;
|
|
||||||
channel_t *target_chan;
|
|
||||||
sfx_t *osfx;
|
|
||||||
|
|
||||||
if (!sfx || !snd->speed)
|
if (!sfx || !snd->speed)
|
||||||
return;
|
return;
|
||||||
// pick a channel to play on
|
// pick a channel to play on
|
||||||
looped = sfx->loopstart != (unsigned) -1;
|
int looped = sfx->loopstart != (unsigned) -1;
|
||||||
target_chan = s_pick_channel (snd, entnum, entchannel, looped);
|
channel_t *target_chan = s_pick_channel (snd, entnum, entchannel, looped);
|
||||||
if (!target_chan)
|
if (!target_chan)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -663,7 +666,8 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
||||||
};
|
};
|
||||||
s_spatialize (snd, target_chan);
|
s_spatialize (snd, target_chan);
|
||||||
|
|
||||||
if (!(osfx = sfx->open (sfx))) {
|
sfxbuffer_t *buffer;
|
||||||
|
if (!(buffer = sfx->open (sfx))) {
|
||||||
// because the channel was never started, it's safe to directly free it
|
// because the channel was never started, it's safe to directly free it
|
||||||
snd_free_channel (target_chan);
|
snd_free_channel (target_chan);
|
||||||
return;
|
return;
|
||||||
|
@ -677,16 +681,12 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
||||||
if (set_is_member (&dynamic_channels, i)
|
if (set_is_member (&dynamic_channels, i)
|
||||||
|| set_is_member (&looped_channels, i)) {
|
|| set_is_member (&looped_channels, i)) {
|
||||||
channel_t *check = &snd_channels[i];
|
channel_t *check = &snd_channels[i];
|
||||||
if (snd_check_channels (snd, target_chan, check, osfx))
|
if (snd_check_channels (snd, target_chan, check, sfx))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!osfx->retain (osfx)) {
|
target_chan->loopstart = sfx->loopstart;
|
||||||
// because the channel was never started, it's safe to directly free it
|
target_chan->buffer = buffer;
|
||||||
snd_free_channel (target_chan);
|
|
||||||
return; // couldn't load the sound's data
|
|
||||||
}
|
|
||||||
target_chan->sfx = osfx;
|
|
||||||
set_add (looped ? &looped_channels : &dynamic_channels, chan_ind);
|
set_add (looped ? &looped_channels : &dynamic_channels, chan_ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,9 +716,6 @@ void
|
||||||
SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol,
|
SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol,
|
||||||
float attenuation)
|
float attenuation)
|
||||||
{
|
{
|
||||||
channel_t *ss;
|
|
||||||
sfx_t *osfx;
|
|
||||||
|
|
||||||
if (!sfx)
|
if (!sfx)
|
||||||
return;
|
return;
|
||||||
if (sfx->loopstart == (unsigned int) -1) {
|
if (sfx->loopstart == (unsigned int) -1) {
|
||||||
|
@ -726,13 +723,15 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
channel_t *ss;
|
||||||
if (!(ss = SND_AllocChannel (snd))) {
|
if (!(ss = SND_AllocChannel (snd))) {
|
||||||
Sys_Printf ("ran out of channels\n");
|
Sys_Printf ("ran out of channels\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int ss_ind = ss - snd_channels;
|
int ss_ind = ss - snd_channels;
|
||||||
|
|
||||||
if (!(osfx = sfx->open (sfx)))
|
sfxbuffer_t *buffer;
|
||||||
|
if (!(buffer = sfx->open (sfx)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spacial_t *spacial = &snd_spacialization[ss_ind];
|
spacial_t *spacial = &snd_spacialization[ss_ind];
|
||||||
|
@ -744,15 +743,13 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol,
|
||||||
s_spatialize (snd, ss);
|
s_spatialize (snd, ss);
|
||||||
ss->oldphase = ss->phase;
|
ss->oldphase = ss->phase;
|
||||||
|
|
||||||
if (!osfx->retain (osfx))
|
|
||||||
return;
|
|
||||||
|
|
||||||
set_add (&static_channels, ss_ind);
|
set_add (&static_channels, ss_ind);
|
||||||
snd_entity_channels[ss_ind] = (entchan_t) {
|
snd_entity_channels[ss_ind] = (entchan_t) {
|
||||||
.id = SND_STATIC_ID,
|
.id = SND_STATIC_ID,
|
||||||
.channel = 0,
|
.channel = 0,
|
||||||
};
|
};
|
||||||
ss->sfx = osfx;
|
ss->loopstart = sfx->loopstart;
|
||||||
|
ss->buffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -473,11 +473,11 @@ s_channel_free (channel_t *chan)
|
||||||
static int
|
static int
|
||||||
s_channel_set_sfx (channel_t *chan, sfx_t *sfx)
|
s_channel_set_sfx (channel_t *chan, sfx_t *sfx)
|
||||||
{
|
{
|
||||||
sfx_t *s = sfx->open (sfx);
|
sfxbuffer_t *buffer = sfx->open (sfx);
|
||||||
if (!s) {
|
if (!buffer) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
chan->sfx = s;
|
chan->buffer = buffer;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,8 +505,8 @@ s_channel_get_state (channel_t *chan)
|
||||||
// The mixer has finished mixing the channel (come to the end).
|
// The mixer has finished mixing the channel (come to the end).
|
||||||
return chan_done;
|
return chan_done;
|
||||||
}
|
}
|
||||||
if (!chan->sfx) {
|
if (!chan->buffer) {
|
||||||
// channel requires initialization
|
// channel has not been started yet
|
||||||
return chan_pending;
|
return chan_pending;
|
||||||
}
|
}
|
||||||
if (chan->pause) {
|
if (chan->pause) {
|
||||||
|
|
|
@ -126,9 +126,37 @@ SND_Memory_AllocBuffer (unsigned samples)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_Memory_FreeBuffer (sfxbuffer_t *buffer)
|
SND_Memory_Free (void *ptr)
|
||||||
{
|
{
|
||||||
Z_Free (snd_zone, buffer);
|
Z_Free (snd_zone, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SND_Memory_SetTag (void *ptr, int tag)
|
||||||
|
{
|
||||||
|
Z_SetTag (snd_zone, ptr, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SND_Memory_Retain (void *ptr)
|
||||||
|
{
|
||||||
|
return Z_IncRetainCount (snd_zone, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SND_Memory_Release (void *ptr)
|
||||||
|
{
|
||||||
|
int retain = Z_DecRetainCount (snd_zone, ptr);
|
||||||
|
if (!retain) {
|
||||||
|
Z_Free (snd_zone, ptr);
|
||||||
|
}
|
||||||
|
return retain;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SND_Memory_GetRetainCount (void *ptr)
|
||||||
|
{
|
||||||
|
return Z_GetRetainCount (snd_zone, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfxbuffer_t *
|
static sfxbuffer_t *
|
||||||
|
@ -142,34 +170,36 @@ snd_noop (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfx_t *
|
static sfxbuffer_t *
|
||||||
snd_open (sfx_t *sfx)
|
snd_open (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return sfx;
|
sfxbuffer_t *buffer = sfx->block->buffer;
|
||||||
|
SND_Memory_Retain (buffer);
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfx_t *
|
static sfxbuffer_t *
|
||||||
snd_open_fail (sfx_t *sfx)
|
snd_open_fail (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfxbuffer_t *
|
sfxbuffer_t * __attribute__((pure))
|
||||||
SND_CacheTouch (sfx_t *sfx)
|
SND_CacheTouch (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return sfx->data.block->buffer;
|
return sfx->block->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfxbuffer_t *
|
sfxbuffer_t *
|
||||||
SND_CacheGetBuffer (sfx_t *sfx)
|
SND_CacheGetBuffer (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return sfx->data.block->buffer;
|
return sfx->block->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfxbuffer_t *
|
sfxbuffer_t * __attribute__((pure))
|
||||||
SND_CacheRetain (sfx_t *sfx)
|
SND_CacheRetain (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return sfx->data.block->buffer;
|
return sfx->block->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -180,13 +210,13 @@ SND_CacheRelease (sfx_t *sfx)
|
||||||
sfxbuffer_t *
|
sfxbuffer_t *
|
||||||
SND_StreamGetBuffer (sfx_t *sfx)
|
SND_StreamGetBuffer (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return sfx->data.stream->buffer;
|
return sfx->stream->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfxbuffer_t *
|
sfxbuffer_t *
|
||||||
SND_StreamRetain (sfx_t *sfx)
|
SND_StreamRetain (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return sfx->data.stream->buffer;
|
return sfx->stream->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -195,15 +225,15 @@ SND_StreamRelease (sfx_t *sfx)
|
||||||
}
|
}
|
||||||
|
|
||||||
wavinfo_t *
|
wavinfo_t *
|
||||||
SND_CacheWavinfo (sfx_t *sfx)
|
SND_CacheWavinfo (const sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return &sfx->data.block->wavinfo;
|
return &sfx->block->wavinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
wavinfo_t *
|
wavinfo_t *
|
||||||
SND_StreamWavinfo (sfx_t *sfx)
|
SND_StreamWavinfo (const sfx_t *sfx)
|
||||||
{
|
{
|
||||||
return &sfx->data.stream->wavinfo;
|
return &sfx->stream->wavinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -215,8 +245,8 @@ read_samples (sfxbuffer_t *buffer, int count)
|
||||||
read_samples (buffer, buffer->size - buffer->head);
|
read_samples (buffer, buffer->size - buffer->head);
|
||||||
read_samples (buffer, count);
|
read_samples (buffer, count);
|
||||||
} else {
|
} else {
|
||||||
sfx_t *sfx = buffer->sfx;
|
sfxstream_t *stream = buffer->stream;
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
const sfx_t *sfx = stream->sfx;
|
||||||
wavinfo_t *info = &stream->wavinfo;
|
wavinfo_t *info = &stream->wavinfo;
|
||||||
float *data = buffer->data + buffer->head * info->channels;
|
float *data = buffer->data + buffer->head * info->channels;
|
||||||
int c;
|
int c;
|
||||||
|
@ -233,7 +263,7 @@ read_samples (sfxbuffer_t *buffer, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
|
fill_buffer (const sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
|
||||||
wavinfo_t *info, unsigned int headpos)
|
wavinfo_t *info, unsigned int headpos)
|
||||||
{
|
{
|
||||||
unsigned int samples;
|
unsigned int samples;
|
||||||
|
@ -244,11 +274,11 @@ fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
|
||||||
if (buffer->tail <= buffer->head)
|
if (buffer->tail <= buffer->head)
|
||||||
samples += buffer->size;
|
samples += buffer->size;
|
||||||
|
|
||||||
if (headpos + samples > sfx->length) {
|
if (headpos + samples > buffer->sfx_length) {
|
||||||
if (sfx->loopstart == (unsigned int)-1) {
|
if (sfx->loopstart == (unsigned int)-1) {
|
||||||
samples = sfx->length - headpos;
|
samples = buffer->sfx_length - headpos;
|
||||||
} else {
|
} else {
|
||||||
loop_samples = headpos + samples - sfx->length;
|
loop_samples = headpos + samples - buffer->sfx_length;
|
||||||
samples -= loop_samples;
|
samples -= loop_samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,8 +294,8 @@ void
|
||||||
SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos)
|
SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos)
|
||||||
{
|
{
|
||||||
float stepscale;
|
float stepscale;
|
||||||
sfx_t *sfx = buffer->sfx;
|
sfxstream_t *stream = buffer->stream;
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
const sfx_t *sfx = stream->sfx;
|
||||||
wavinfo_t *info = &stream->wavinfo;
|
wavinfo_t *info = &stream->wavinfo;
|
||||||
|
|
||||||
stepscale = (float) info->rate / sfx->snd->speed;
|
stepscale = (float) info->rate / sfx->snd->speed;
|
||||||
|
@ -282,8 +312,8 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
||||||
{
|
{
|
||||||
float stepscale;
|
float stepscale;
|
||||||
unsigned int headpos, samples;
|
unsigned int headpos, samples;
|
||||||
sfx_t *sfx = buffer->sfx;
|
sfxstream_t *stream = buffer->stream;
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
const sfx_t *sfx = stream->sfx;
|
||||||
wavinfo_t *info = &stream->wavinfo;
|
wavinfo_t *info = &stream->wavinfo;
|
||||||
|
|
||||||
stream->pos += count;
|
stream->pos += count;
|
||||||
|
@ -300,23 +330,23 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
||||||
|
|
||||||
// find out where head points to in the stream
|
// find out where head points to in the stream
|
||||||
headpos = buffer->pos + samples;
|
headpos = buffer->pos + samples;
|
||||||
if (headpos >= sfx->length) {
|
if (headpos >= buffer->sfx_length) {
|
||||||
if (sfx->loopstart == (unsigned int)-1)
|
if (sfx->loopstart == (unsigned int)-1)
|
||||||
headpos = sfx->length;
|
headpos = buffer->sfx_length;
|
||||||
else
|
else
|
||||||
headpos -= sfx->length - sfx->loopstart;
|
headpos -= buffer->sfx_length - sfx->loopstart;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (samples < count) {
|
if (samples < count) {
|
||||||
buffer->head = buffer->tail = 0;
|
buffer->head = buffer->tail = 0;
|
||||||
buffer->pos += count;
|
buffer->pos += count;
|
||||||
if (buffer->pos > sfx->length) {
|
if (buffer->pos > buffer->sfx_length) {
|
||||||
if (sfx->loopstart == (unsigned int)-1) {
|
if (sfx->loopstart == (unsigned int)-1) {
|
||||||
// reset the buffer and fill it incase it's needed again
|
// reset the buffer and fill it incase it's needed again
|
||||||
buffer->pos = 0;
|
buffer->pos = 0;
|
||||||
} else {
|
} else {
|
||||||
buffer->pos -= sfx->loopstart;
|
buffer->pos -= sfx->loopstart;
|
||||||
buffer->pos %= sfx->length - sfx->loopstart;
|
buffer->pos %= buffer->sfx_length - sfx->loopstart;
|
||||||
buffer->pos += sfx->loopstart;
|
buffer->pos += sfx->loopstart;
|
||||||
}
|
}
|
||||||
stream->pos = buffer->pos;
|
stream->pos = buffer->pos;
|
||||||
|
@ -325,7 +355,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
||||||
stream->seek (stream, buffer->pos * stepscale);
|
stream->seek (stream, buffer->pos * stepscale);
|
||||||
} else {
|
} else {
|
||||||
buffer->pos += count;
|
buffer->pos += count;
|
||||||
if (buffer->pos >= sfx->length) {
|
if (buffer->pos >= buffer->sfx_length) {
|
||||||
if (sfx->loopstart == (unsigned int)-1) {
|
if (sfx->loopstart == (unsigned int)-1) {
|
||||||
// reset the buffer and fill it in case it's needed again
|
// reset the buffer and fill it in case it's needed again
|
||||||
headpos = buffer->pos = 0;
|
headpos = buffer->pos = 0;
|
||||||
|
@ -333,7 +363,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
||||||
count = 0;
|
count = 0;
|
||||||
stream->seek (stream, buffer->pos * stepscale);
|
stream->seek (stream, buffer->pos * stepscale);
|
||||||
} else {
|
} else {
|
||||||
buffer->pos -= sfx->length - sfx->loopstart;
|
buffer->pos -= buffer->sfx_length - sfx->loopstart;
|
||||||
}
|
}
|
||||||
stream->pos = buffer->pos;
|
stream->pos = buffer->pos;
|
||||||
}
|
}
|
||||||
|
@ -355,7 +385,6 @@ SND_Load (sfx_t *sfx)
|
||||||
|
|
||||||
sfx->touch = sfx->retain = snd_fail;
|
sfx->touch = sfx->retain = snd_fail;
|
||||||
sfx->release = snd_noop;
|
sfx->release = snd_noop;
|
||||||
sfx->close = snd_noop;
|
|
||||||
sfx->open = snd_open_fail;
|
sfx->open = snd_open_fail;
|
||||||
|
|
||||||
file = QFS_FOpenFile (sfx->name);
|
file = QFS_FOpenFile (sfx->name);
|
||||||
|
|
|
@ -53,12 +53,12 @@ static int max_overpaint; // number of extra samples painted
|
||||||
/* CHANNEL MIXING */
|
/* CHANNEL MIXING */
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
check_channel_end (channel_t *ch, sfx_t *sfx, int count, unsigned ltime)
|
check_channel_end (channel_t *ch, sfxbuffer_t *sb, int count, unsigned ltime)
|
||||||
{
|
{
|
||||||
if (count <= 0 || ltime >= ch->end) {
|
if (count <= 0 || ltime >= ch->end) {
|
||||||
if (sfx->loopstart != (unsigned) -1) {
|
if (ch->loopstart != (unsigned) -1) {
|
||||||
ch->pos = sfx->loopstart;
|
ch->pos = ch->loopstart;
|
||||||
ch->end = ltime + sfx->length - ch->pos;
|
ch->end = ltime + sb->sfx_length - ch->pos;
|
||||||
} else { // channel just stopped
|
} else { // channel just stopped
|
||||||
ch->done = 1;
|
ch->done = 1;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -103,7 +103,6 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
||||||
unsigned end, ltime;
|
unsigned end, ltime;
|
||||||
int i, count;
|
int i, count;
|
||||||
channel_t *ch;
|
channel_t *ch;
|
||||||
sfx_t *sfx;
|
|
||||||
sfxbuffer_t *sb;
|
sfxbuffer_t *sb;
|
||||||
|
|
||||||
// clear the paint buffer
|
// clear the paint buffer
|
||||||
|
@ -123,7 +122,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
||||||
// paint in the channels.
|
// paint in the channels.
|
||||||
ch = snd_channels;
|
ch = snd_channels;
|
||||||
for (i = 0; i < snd_total_channels; i++, ch++) {
|
for (i = 0; i < snd_total_channels; i++, ch++) {
|
||||||
if (!(sfx = ch->sfx)) {
|
if (!(sb = ch->buffer)) {
|
||||||
// channel is inactive
|
// channel is inactive
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -133,14 +132,9 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
||||||
}
|
}
|
||||||
if (ch->pause)
|
if (ch->pause)
|
||||||
continue;
|
continue;
|
||||||
sb = sfx->getbuffer (sfx);
|
|
||||||
if (!sb) { // something went wrong with the sfx
|
|
||||||
printf ("XXXX sfx blew up!!!!\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ch->end)
|
if (!ch->end)
|
||||||
ch->end = snd->paintedtime + sfx->length - ch->pos;
|
ch->end = snd->paintedtime + sb->sfx_length - ch->pos;
|
||||||
|
|
||||||
ltime = snd->paintedtime;
|
ltime = snd->paintedtime;
|
||||||
|
|
||||||
|
@ -161,7 +155,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
||||||
ltime += count;
|
ltime += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_channel_end (ch, sfx, count, ltime))
|
if (check_channel_end (ch, sb, count, ltime))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,8 +467,7 @@ SND_SetPaint (sfxbuffer_t *sb)
|
||||||
snd_paint_8,
|
snd_paint_8,
|
||||||
};
|
};
|
||||||
|
|
||||||
wavinfo_t *info = sb->sfx->wavinfo (sb->sfx);
|
if (sb->channels > 8 || !sb->channels)
|
||||||
if (info->channels > 8)
|
Sys_Error ("invaliid channel count %d", sb->channels);
|
||||||
Sys_Error ("illegal channel count %d", info->channels);
|
sb->paint = painters[sb->channels];
|
||||||
sb->paint = painters[info->channels];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,13 +63,16 @@ check_buffer_integrity (sfxbuffer_t *sb, int width, const char *func)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
SND_ResamplerFrames (sfx_t *sfx)
|
SND_ResamplerFrames (const sfx_t *sfx, unsigned frames)
|
||||||
{
|
{
|
||||||
|
if (frames == ~0u) {
|
||||||
|
return frames;
|
||||||
|
}
|
||||||
wavinfo_t *info = sfx->wavinfo (sfx);
|
wavinfo_t *info = sfx->wavinfo (sfx);
|
||||||
snd_t *snd = sfx->snd;
|
snd_t *snd = sfx->snd;
|
||||||
int inrate = info->rate;
|
int inrate = info->rate;
|
||||||
double stepscale = (double) snd->speed / inrate;
|
double stepscale = (double) snd->speed / inrate;
|
||||||
return info->frames * stepscale;
|
return frames * stepscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -77,8 +80,8 @@ SND_Resample (sfxbuffer_t *sb, float *data, int length)
|
||||||
{
|
{
|
||||||
int outcount;
|
int outcount;
|
||||||
double stepscale;
|
double stepscale;
|
||||||
wavinfo_t *info = sb->sfx->wavinfo (sb->sfx);
|
wavinfo_t *info = (*sb->sfx)->wavinfo (*sb->sfx);
|
||||||
snd_t *snd = sb->sfx->snd;
|
snd_t *snd = (*sb->sfx)->snd;
|
||||||
int inrate = info->rate;
|
int inrate = info->rate;
|
||||||
int outwidth;
|
int outwidth;
|
||||||
SRC_DATA src_data;
|
SRC_DATA src_data;
|
||||||
|
@ -153,23 +156,19 @@ void
|
||||||
SND_SetupResampler (sfxbuffer_t *sb, int streamed)
|
SND_SetupResampler (sfxbuffer_t *sb, int streamed)
|
||||||
{
|
{
|
||||||
double stepscale;
|
double stepscale;
|
||||||
wavinfo_t *info = sb->sfx->wavinfo (sb->sfx);
|
wavinfo_t *info = (*sb->sfx)->wavinfo (*sb->sfx);
|
||||||
snd_t *snd = sb->sfx->snd;
|
snd_t *snd = (*sb->sfx)->snd;
|
||||||
int inrate = info->rate;
|
int inrate = info->rate;
|
||||||
|
|
||||||
stepscale = (double) snd->speed / inrate;
|
stepscale = (double) snd->speed / inrate;
|
||||||
|
|
||||||
sb->sfx->length = info->frames * stepscale;
|
sb->sfx_length = info->frames * stepscale;
|
||||||
if (info->loopstart != (unsigned int)-1)
|
|
||||||
sb->sfx->loopstart = info->loopstart * stepscale;
|
|
||||||
else
|
|
||||||
sb->sfx->loopstart = (unsigned int)-1;
|
|
||||||
|
|
||||||
sb->channels = info->channels;
|
sb->channels = info->channels;
|
||||||
|
|
||||||
if (streamed) {
|
if (streamed) {
|
||||||
int err;
|
int err;
|
||||||
sfxstream_t *stream = sb->sfx->data.stream;
|
sfxstream_t *stream = sb->stream;
|
||||||
|
|
||||||
if (snd->speed == inrate) {
|
if (snd->speed == inrate) {
|
||||||
stream->state = calloc (sizeof (snd_null_state_t), 1);
|
stream->state = calloc (sizeof (snd_null_state_t), 1);
|
||||||
|
|
|
@ -75,7 +75,12 @@ snd_sfx_free (void *_sfx, void *unused)
|
||||||
sfx_t *sfx = (sfx_t *) _sfx;
|
sfx_t *sfx = (sfx_t *) _sfx;
|
||||||
free ((char *) sfx->name);
|
free ((char *) sfx->name);
|
||||||
sfx->name = 0;
|
sfx->name = 0;
|
||||||
sfx->owner = 0;
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
snd_block_close (sfxbuffer_t *buffer)
|
||||||
|
{
|
||||||
|
SND_Memory_Release (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -84,22 +89,26 @@ SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
{
|
{
|
||||||
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
||||||
|
|
||||||
sfx->data.block = block;
|
sfx->block = block;
|
||||||
sfx->wavinfo = SND_CacheWavinfo;
|
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->getbuffer = SND_CacheGetBuffer;
|
sfx->getbuffer = SND_CacheGetBuffer;
|
||||||
|
sfx->loopstart = SND_ResamplerFrames (sfx, info.loopstart);
|
||||||
|
sfx->length = SND_ResamplerFrames (sfx, info.frames);
|
||||||
|
|
||||||
block->sfx = sfx;
|
block->sfx = sfx;
|
||||||
block->file = realname;
|
block->file = realname;
|
||||||
block->wavinfo = info;
|
block->wavinfo = info;
|
||||||
block->buffer = load (block);
|
block->buffer = load (block);
|
||||||
|
SND_Memory_Retain (block->buffer);
|
||||||
|
block->buffer->close = snd_block_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
sfx_t *(*open) (sfx_t *sfx))
|
sfxbuffer_t *(*open) (sfx_t *sfx))
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = calloc (1, sizeof (sfxstream_t));
|
sfxstream_t *stream = calloc (1, sizeof (sfxstream_t));
|
||||||
sfx->open = open;
|
sfx->open = open;
|
||||||
|
@ -107,20 +116,22 @@ SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
||||||
sfx->touch = sfx->retain = SND_StreamRetain;
|
sfx->touch = sfx->retain = SND_StreamRetain;
|
||||||
sfx->release = SND_StreamRelease;
|
sfx->release = SND_StreamRelease;
|
||||||
sfx->getbuffer = SND_StreamGetBuffer;
|
sfx->getbuffer = SND_StreamGetBuffer;
|
||||||
sfx->data.stream = stream;
|
sfx->stream = stream;
|
||||||
|
sfx->loopstart = SND_ResamplerFrames (sfx, info.loopstart);
|
||||||
|
sfx->length = SND_ResamplerFrames (sfx, info.frames);
|
||||||
|
|
||||||
stream->file = realname;
|
stream->file = realname;
|
||||||
stream->wavinfo = info;
|
stream->wavinfo = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
sfx_t *
|
sfxbuffer_t *
|
||||||
SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||||
long (*read)(void *, float **),
|
long (*read)(void *, float **),
|
||||||
int (*seek)(sfxstream_t *, int),
|
int (*seek)(sfxstream_t *, int),
|
||||||
void (*close) (sfx_t *))
|
void (*close) (sfxbuffer_t *))
|
||||||
{
|
{
|
||||||
snd_t *snd = sfx->snd;
|
snd_t *snd = sfx->snd;
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = sfx->stream;
|
||||||
wavinfo_t *info = &stream->wavinfo;
|
wavinfo_t *info = &stream->wavinfo;
|
||||||
int frames;
|
int frames;
|
||||||
|
|
||||||
|
@ -129,55 +140,44 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||||
if (!snd->speed)
|
if (!snd->speed)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
sfx_t *new_sfx = calloc (1, sizeof (sfx_t));
|
|
||||||
|
|
||||||
new_sfx->snd = sfx->snd;
|
|
||||||
new_sfx->name = sfx->name;
|
|
||||||
new_sfx->owner = sfx;
|
|
||||||
new_sfx->wavinfo = SND_CacheWavinfo;
|
|
||||||
new_sfx->touch = new_sfx->retain = SND_StreamRetain;
|
|
||||||
new_sfx->release = SND_StreamRelease;
|
|
||||||
new_sfx->getbuffer = SND_StreamGetBuffer;
|
|
||||||
new_sfx->close = close;
|
|
||||||
|
|
||||||
frames = snd->speed * 0.3;
|
frames = snd->speed * 0.3;
|
||||||
frames = (frames + 255) & ~255;
|
frames = (frames + 255) & ~255;
|
||||||
|
|
||||||
stream = calloc (1, sizeof (sfxstream_t));
|
stream = calloc (1, sizeof (sfxstream_t));
|
||||||
new_sfx->data.stream = stream;
|
|
||||||
stream->buffer = SND_Memory_AllocBuffer (frames * info->channels);
|
stream->buffer = SND_Memory_AllocBuffer (frames * info->channels);
|
||||||
if (!stream->buffer) {
|
if (!stream->buffer) {
|
||||||
free (stream);
|
free (stream);
|
||||||
free (new_sfx);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->file = file;
|
stream->file = file;
|
||||||
stream->sfx = new_sfx;
|
stream->sfx = sfx;
|
||||||
stream->ll_read = read;
|
stream->ll_read = read;
|
||||||
stream->ll_seek = seek;
|
stream->ll_seek = seek;
|
||||||
|
|
||||||
stream->wavinfo = *sfx->wavinfo (sfx);
|
stream->wavinfo = *sfx->wavinfo (sfx);
|
||||||
|
|
||||||
|
stream->buffer->stream = stream;
|
||||||
stream->buffer->size = frames;
|
stream->buffer->size = frames;
|
||||||
stream->buffer->advance = SND_StreamAdvance;
|
stream->buffer->advance = SND_StreamAdvance;
|
||||||
stream->buffer->setpos = SND_StreamSetPos;
|
stream->buffer->setpos = SND_StreamSetPos;
|
||||||
stream->buffer->sfx = new_sfx;
|
stream->buffer->sfx_length = info->frames;
|
||||||
|
stream->buffer->channels = info->channels;
|
||||||
|
stream->buffer->close = close;
|
||||||
SND_SetPaint (stream->buffer);
|
SND_SetPaint (stream->buffer);
|
||||||
|
|
||||||
SND_SetupResampler (stream->buffer, 1); // get sfx setup properly
|
SND_SetupResampler (stream->buffer, 1); // get sfx setup properly
|
||||||
stream->buffer->setpos (stream->buffer, 0); // pre-fill the buffer
|
stream->buffer->setpos (stream->buffer, 0); // pre-fill the buffer
|
||||||
|
|
||||||
return new_sfx;
|
return stream->buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SND_SFX_StreamClose (sfx_t *sfx)
|
SND_SFX_StreamClose (sfxstream_t *stream)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
|
||||||
SND_PulldownResampler (stream);
|
SND_PulldownResampler (stream);
|
||||||
SND_Memory_FreeBuffer (stream->buffer);
|
SND_Memory_Free (stream->buffer);
|
||||||
free (stream);
|
free (stream);
|
||||||
free (sfx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sfx_t *
|
sfx_t *
|
||||||
|
@ -196,7 +196,6 @@ SND_LoadSound (snd_t *snd, const char *name)
|
||||||
sfx = &snd_sfx[snd_num_sfx++];
|
sfx = &snd_sfx[snd_num_sfx++];
|
||||||
sfx->snd = snd;
|
sfx->snd = snd;
|
||||||
sfx->name = strdup (name);
|
sfx->name = strdup (name);
|
||||||
sfx->owner = sfx;
|
|
||||||
if (SND_Load (sfx) == -1) {
|
if (SND_Load (sfx) == -1) {
|
||||||
snd_num_sfx--;
|
snd_num_sfx--;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -164,18 +164,20 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block)
|
||||||
{
|
{
|
||||||
float *data;
|
float *data;
|
||||||
sfxbuffer_t *sb = 0;
|
sfxbuffer_t *sb = 0;
|
||||||
sfx_t *sfx = block->sfx;
|
const sfx_t *sfx = block->sfx;
|
||||||
wavinfo_t *info = &block->wavinfo;
|
wavinfo_t *info = &block->wavinfo;
|
||||||
|
|
||||||
data = malloc (info->datalen);
|
data = malloc (info->datalen);
|
||||||
if (!data)
|
if (!data)
|
||||||
goto bail;
|
goto bail;
|
||||||
unsigned buffer_frames = SND_ResamplerFrames (sfx);
|
unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames);
|
||||||
sb = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
sb = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
||||||
if (!sb)
|
if (!sb)
|
||||||
goto bail;
|
goto bail;
|
||||||
sb->size = buffer_frames * info->channels;
|
sb->size = buffer_frames * info->channels;
|
||||||
sb->sfx = sfx;
|
sb->channels = info->channels;
|
||||||
|
sb->sfx_length = info->frames;
|
||||||
|
sb->block = block;
|
||||||
if (vorbis_read (vf, data, info->frames, info) < 0)
|
if (vorbis_read (vf, data, info->frames, info) < 0)
|
||||||
goto bail;
|
goto bail;
|
||||||
SND_SetPaint (sb);
|
SND_SetPaint (sb);
|
||||||
|
@ -240,9 +242,9 @@ vorbis_stream_seek (sfxstream_t *stream, int pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vorbis_stream_close (sfx_t *sfx)
|
vorbis_stream_close (sfxbuffer_t *buffer)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = buffer->stream;
|
||||||
vorbis_file_t *vf = (vorbis_file_t *) stream->file;
|
vorbis_file_t *vf = (vorbis_file_t *) stream->file;
|
||||||
|
|
||||||
if (vf->data)
|
if (vf->data)
|
||||||
|
@ -250,13 +252,13 @@ vorbis_stream_close (sfx_t *sfx)
|
||||||
ov_clear (vf->vf);
|
ov_clear (vf->vf);
|
||||||
free (vf->vf);
|
free (vf->vf);
|
||||||
free (vf);
|
free (vf);
|
||||||
SND_SFX_StreamClose (sfx);
|
SND_SFX_StreamClose (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfx_t *
|
static sfxbuffer_t *
|
||||||
vorbis_stream_open (sfx_t *sfx)
|
vorbis_stream_open (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = sfx->stream;
|
||||||
QFile *file;
|
QFile *file;
|
||||||
vorbis_file_t *f;
|
vorbis_file_t *f;
|
||||||
|
|
||||||
|
|
|
@ -57,13 +57,13 @@ typedef struct {
|
||||||
static sfxbuffer_t *
|
static sfxbuffer_t *
|
||||||
wav_callback_load (sfxblock_t *block)
|
wav_callback_load (sfxblock_t *block)
|
||||||
{
|
{
|
||||||
sfx_t *sfx = block->sfx;
|
const sfx_t *sfx = block->sfx;
|
||||||
const char *name = (const char *) block->file;
|
const char *name = (const char *) block->file;
|
||||||
QFile *file;
|
QFile *file;
|
||||||
int len, fdata_ofs;
|
int len, fdata_ofs;
|
||||||
byte *data;
|
byte *data;
|
||||||
float *fdata;
|
float *fdata;
|
||||||
sfxbuffer_t *buffer;
|
sfxbuffer_t *buffer = 0;
|
||||||
wavinfo_t *info = &block->wavinfo;
|
wavinfo_t *info = &block->wavinfo;
|
||||||
|
|
||||||
file = QFS_FOpenFile (name);
|
file = QFS_FOpenFile (name);
|
||||||
|
@ -81,12 +81,14 @@ wav_callback_load (sfxblock_t *block)
|
||||||
|
|
||||||
SND_Convert (data, fdata, info->frames, info->channels, info->width);
|
SND_Convert (data, fdata, info->frames, info->channels, info->width);
|
||||||
|
|
||||||
unsigned buffer_frames = SND_ResamplerFrames (sfx);
|
unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames);
|
||||||
buffer = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
buffer = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
goto bail;
|
goto bail;
|
||||||
buffer->size = buffer_frames * info->channels;
|
buffer->size = buffer_frames * info->channels;
|
||||||
buffer->sfx = sfx;
|
buffer->channels = info->channels;
|
||||||
|
buffer->sfx_length = info->frames;
|
||||||
|
buffer->block = block;
|
||||||
SND_SetPaint (buffer);
|
SND_SetPaint (buffer);
|
||||||
SND_SetupResampler (buffer, 0);
|
SND_SetupResampler (buffer, 0);
|
||||||
SND_Resample (buffer, fdata, info->frames);
|
SND_Resample (buffer, fdata, info->frames);
|
||||||
|
@ -139,22 +141,22 @@ wav_stream_seek (sfxstream_t *stream, int pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wav_stream_close (sfx_t *sfx)
|
wav_stream_close (sfxbuffer_t *buffer)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = buffer->stream;
|
||||||
wav_file_t *wf = (wav_file_t *) stream->file;
|
wav_file_t *wf = (wav_file_t *) stream->file;
|
||||||
|
|
||||||
Qclose (wf->file);
|
Qclose (wf->file);
|
||||||
if (wf->data)
|
if (wf->data)
|
||||||
free (wf->data);
|
free (wf->data);
|
||||||
free (wf);
|
free (wf);
|
||||||
SND_SFX_StreamClose (sfx);
|
SND_SFX_StreamClose (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfx_t *
|
static sfxbuffer_t *
|
||||||
wav_stream_open (sfx_t *sfx)
|
wav_stream_open (sfx_t *sfx)
|
||||||
{
|
{
|
||||||
sfxstream_t *stream = sfx->data.stream;
|
sfxstream_t *stream = sfx->stream;
|
||||||
QFile *file;
|
QFile *file;
|
||||||
wav_file_t *wf;
|
wav_file_t *wf;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue