mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-23 19:01:06 +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
|
||||
const char *name;
|
||||
sfx_t *owner;
|
||||
|
||||
unsigned int length;
|
||||
unsigned int loopstart;
|
||||
unsigned length;
|
||||
unsigned loopstart;
|
||||
|
||||
union {
|
||||
sfxstream_t *stream;
|
||||
sfxblock_t *block;
|
||||
} data;
|
||||
};
|
||||
|
||||
sfxbuffer_t *(*touch) (sfx_t *sfx);
|
||||
sfxbuffer_t *(*retain) (sfx_t *sfx);
|
||||
void (*release) (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);
|
||||
void (*close) (sfx_t *sfx);
|
||||
sfxbuffer_t *(*open) (sfx_t *sfx);
|
||||
};
|
||||
|
||||
/** 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
|
||||
the channel
|
||||
\param ch sound channel
|
||||
|
@ -87,7 +88,7 @@ struct sfx_s
|
|||
typedef void sfxpaint_t (int offset, channel_t *ch, float *buffer,
|
||||
unsigned count);
|
||||
|
||||
/** Represent a sound sample in the mixer.
|
||||
/** Represent a single output frame in the mixer.
|
||||
*/
|
||||
struct portable_samplepair_s {
|
||||
float left; //!< left sample
|
||||
|
@ -146,6 +147,14 @@ struct sfxbuffer_s {
|
|||
unsigned size; //!< size of buffer in frames
|
||||
unsigned pos; //!< position of tail within full stream
|
||||
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
|
||||
/** Advance the position with the stream, updating the ring buffer as
|
||||
necessary. Null for chached sounds.
|
||||
|
@ -160,7 +169,7 @@ struct sfxbuffer_s {
|
|||
\param pos frame position with the stream
|
||||
*/
|
||||
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 size)
|
||||
*/
|
||||
|
@ -170,7 +179,7 @@ struct sfxbuffer_s {
|
|||
/** Representation of sound loaded that is streamed in as needed.
|
||||
*/
|
||||
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
|
||||
wavinfo_t wavinfo; //!< description of sound data
|
||||
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.
|
||||
*/
|
||||
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
|
||||
wavinfo_t wavinfo; //!< description of sound data
|
||||
cache_user_t cache; //!< cached sound buffer (::sfxbuffer_s)
|
||||
sfxbuffer_t *buffer; //!< pointer to cached buffer
|
||||
};
|
||||
|
||||
/** Representation of a sound being played.
|
||||
*/
|
||||
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 rightvol; //!< 0-1 volume
|
||||
unsigned end; //!< end time in global paintsamples
|
||||
unsigned pos; //!< sample position in sfx
|
||||
unsigned looping; //!< where to loop, -1 = no looping
|
||||
int pause; //!< don't update the channel at all
|
||||
unsigned loopstart; //!< where to loop, -1 = no looping
|
||||
int phase; //!< 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
|
||||
stopped.
|
||||
- both \c stop and \c done are zero: normal operation
|
||||
|
@ -243,8 +251,8 @@ struct channel_s {
|
|||
can be reused at any time.
|
||||
*/
|
||||
//@{
|
||||
int stop;
|
||||
int done;
|
||||
byte stop;
|
||||
byte done;
|
||||
//@}
|
||||
};
|
||||
|
||||
|
@ -259,7 +267,11 @@ extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2];
|
|||
void SND_Memory_Init_Cvars (void);
|
||||
int SND_Memory_Init (void);
|
||||
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
|
||||
\ingroup sound_render_mix
|
||||
|
@ -281,7 +293,7 @@ void SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info,
|
|||
\param open
|
||||
*/
|
||||
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.
|
||||
\param sfx
|
||||
|
@ -290,15 +302,15 @@ void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info,
|
|||
\param seek
|
||||
\param close
|
||||
*/
|
||||
sfx_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||
long (*read)(void *, float **),
|
||||
int (*seek)(sfxstream_t *, int),
|
||||
void (*close) (sfx_t *));
|
||||
sfxbuffer_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||
long (*read)(void *, float **),
|
||||
int (*seek)(sfxstream_t *, int),
|
||||
void (*close) (sfxbuffer_t *));
|
||||
|
||||
/** Close a stream.
|
||||
\param sfx
|
||||
*/
|
||||
void SND_SFX_StreamClose (sfx_t *sfx);
|
||||
void SND_SFX_StreamClose (sfxstream_t *stream);
|
||||
|
||||
/** Pre-load a sound into the cache.
|
||||
\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.
|
||||
\param sb buffer to setup
|
||||
|
@ -549,13 +561,13 @@ int SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname);
|
|||
\param sfx sound reference
|
||||
\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.
|
||||
\param sfx sound reference
|
||||
\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.
|
||||
\param sfx sound reference
|
||||
|
|
|
@ -283,18 +283,20 @@ flac_load (flacfile_t *ff, sfxblock_t *block)
|
|||
{
|
||||
float *data;
|
||||
sfxbuffer_t *sb = 0;
|
||||
sfx_t *sfx = block->sfx;
|
||||
const sfx_t *sfx = block->sfx;
|
||||
wavinfo_t *info = &block->wavinfo;
|
||||
|
||||
data = malloc (info->datalen);
|
||||
if (!data)
|
||||
goto bail;
|
||||
unsigned buffer_frames = SND_ResamplerFrames (sfx);
|
||||
unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames);
|
||||
sb = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
||||
if (!sb)
|
||||
goto bail;
|
||||
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)
|
||||
goto bail;
|
||||
SND_SetPaint (sb);
|
||||
|
@ -358,18 +360,18 @@ flac_stream_seek (sfxstream_t *stream, int pos)
|
|||
}
|
||||
|
||||
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);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
SND_SFX_StreamClose (stream);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
static sfxbuffer_t *
|
||||
flac_stream_open (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = sfx->stream;
|
||||
QFile *file;
|
||||
void *f;
|
||||
|
||||
|
|
|
@ -143,20 +143,20 @@ midi_stream_seek (sfxstream_t *stream, int pos)
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
WildMidi_Close (mf->handle);
|
||||
free (mf);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
SND_SFX_StreamClose (stream);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
static sfxbuffer_t *
|
||||
midi_stream_open (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = sfx->stream;
|
||||
QFile *file;
|
||||
midi *handle;
|
||||
unsigned char *local_buffer;
|
||||
|
|
|
@ -148,7 +148,8 @@ static cvar_t ambient_level_cvar = {
|
|||
static void
|
||||
snd_free_channel (channel_t *ch)
|
||||
{
|
||||
ch->sfx = 0;
|
||||
sfxbuffer_t *buffer = ch->buffer;
|
||||
ch->buffer = 0;
|
||||
ch->stop = 0;
|
||||
ch->done = 0;
|
||||
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_entity_channels[chan_ind] = (entchan_t) {};
|
||||
|
||||
if (buffer) {
|
||||
buffer->close (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
channel_t *
|
||||
|
@ -164,8 +169,8 @@ SND_AllocChannel (snd_t *snd)
|
|||
{
|
||||
channel_t *chan;
|
||||
|
||||
//Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n",
|
||||
// snd_num_free_channels);
|
||||
Sys_MaskPrintf (SYS_snd, "SND_AllocChannel: free channels: %d\n",
|
||||
snd_num_free_channels);
|
||||
if (!snd_num_free_channels) {
|
||||
Sys_MaskPrintf (SYS_warn, "SND_AllocChannel: out of channels.\n");
|
||||
return 0;
|
||||
|
@ -181,7 +186,7 @@ SND_AllocChannel (snd_t *snd)
|
|||
void
|
||||
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");
|
||||
}
|
||||
chan->stop = 1;
|
||||
|
@ -207,7 +212,7 @@ SND_ScanChannels (snd_t *snd, int wait)
|
|||
count = 0;
|
||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||
ch = &snd_channels[i];
|
||||
if (!ch->sfx || ch->done)
|
||||
if (!ch->buffer || ch->done)
|
||||
continue;
|
||||
ch->stop = 1;
|
||||
count++;
|
||||
|
@ -221,7 +226,7 @@ SND_ScanChannels (snd_t *snd, int wait)
|
|||
} else {
|
||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||
ch = &snd_channels[i];
|
||||
if (ch->sfx && ch->stop && !ch->done) {
|
||||
if (ch->buffer && ch->stop && !ch->done) {
|
||||
ch->done = 1;
|
||||
count++;
|
||||
}
|
||||
|
@ -230,11 +235,11 @@ SND_ScanChannels (snd_t *snd, int wait)
|
|||
}
|
||||
for (i = 0; i < MAX_CHANNELS; i++) {
|
||||
ch = &snd_channels[i];
|
||||
if (!ch->sfx || !ch->done)
|
||||
if (!ch->buffer || !ch->done)
|
||||
continue;
|
||||
ch->sfx->release (ch->sfx);
|
||||
ch->sfx->close (ch->sfx);
|
||||
ch->sfx = 0;
|
||||
sfxbuffer_t *buffer = ch->buffer;
|
||||
ch->buffer = 0;
|
||||
buffer->close (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -419,8 +424,6 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level)
|
|||
{
|
||||
float vol;
|
||||
int ambient_channel;
|
||||
channel_t *chan;
|
||||
sfx_t *sfx;
|
||||
|
||||
if (!snd_ambient)
|
||||
return;
|
||||
|
@ -430,7 +433,7 @@ s_updateAmbientSounds (snd_t *snd, const byte *ambient_sound_level)
|
|||
// stop all ambient channels.
|
||||
for (ambient_channel = 0; ambient_channel < NUM_AMBIENTS;
|
||||
ambient_channel++) {
|
||||
chan = ambient_channels[ambient_channel];
|
||||
channel_t *chan = ambient_channels[ambient_channel];
|
||||
if (chan) {
|
||||
int chan_ind = chan - snd_channels;
|
||||
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;
|
||||
ambient_channel++) {
|
||||
sfx = ambient_sfx[ambient_channel];
|
||||
sfx_t *sfx = ambient_sfx[ambient_channel];
|
||||
if (!sfx)
|
||||
continue;
|
||||
|
||||
chan = ambient_channels[ambient_channel];
|
||||
channel_t *chan = ambient_channels[ambient_channel];
|
||||
if (!chan) {
|
||||
chan = ambient_channels[ambient_channel] = SND_AllocChannel (snd);
|
||||
if (!chan)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!chan->sfx) {
|
||||
sfx = sfx->open (sfx);
|
||||
if (!sfx)
|
||||
sfxbuffer_t *buffer;
|
||||
if (!chan->buffer) {
|
||||
buffer = sfx->open (sfx);
|
||||
if (!buffer)
|
||||
continue;
|
||||
sfx->retain (sfx);
|
||||
} else {
|
||||
sfx = chan->sfx;
|
||||
buffer = chan->buffer;
|
||||
//sfx->retain (sfx); //FIXME why is this necessary?
|
||||
}
|
||||
// sfx will be written to chan->sfx later to ensure mixer doesn't use
|
||||
// channel prematurely.
|
||||
// buffer will be written to chan->buffer later to ensure mixer
|
||||
// doesn't use channel prematurely.
|
||||
|
||||
int chan_ind = chan - snd_channels;
|
||||
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->sfx = sfx;
|
||||
chan->loopstart = sfx->loopstart;
|
||||
chan->buffer = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -548,7 +552,7 @@ s_spatialize (snd_t *snd, channel_t *ch)
|
|||
static inline int
|
||||
s_update_channel (snd_t *snd, channel_t *ch)
|
||||
{
|
||||
if (!ch->sfx)
|
||||
if (!ch->buffer)
|
||||
return 0;
|
||||
s_spatialize (snd, ch);
|
||||
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;
|
||||
for (int i = 0; i < MAX_CHANNELS; i++) {
|
||||
channel_t *ch = &snd_channels[i];
|
||||
if (!ch->sfx || ch->done) {
|
||||
if (!ch->buffer || ch->done) {
|
||||
continue;
|
||||
}
|
||||
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
|
||||
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
|
||||
// the same sound effect so we don't mix five torches every
|
||||
// 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);
|
||||
continue;
|
||||
}
|
||||
|
@ -608,7 +615,7 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level)
|
|||
channel_t *c = 0;
|
||||
for (int j = 0; j < i; 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];
|
||||
break;
|
||||
}
|
||||
|
@ -623,11 +630,11 @@ SND_SetListener (snd_t *snd, transform_t *ear, const byte *ambient_sound_level)
|
|||
|
||||
static int
|
||||
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;
|
||||
if (check->sfx->owner == osfx->owner && !check->pos) {
|
||||
if (*check->buffer->sfx == sfx && !check->pos) {
|
||||
int skip = rand () % (int) (0.01 * snd->speed);
|
||||
target_chan->pos = -skip;
|
||||
return 1;
|
||||
|
@ -639,15 +646,11 @@ void
|
|||
SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
||||
vec4f_t origin, float vol, float attenuation)
|
||||
{
|
||||
int looped;
|
||||
channel_t *target_chan;
|
||||
sfx_t *osfx;
|
||||
|
||||
if (!sfx || !snd->speed)
|
||||
return;
|
||||
// pick a channel to play on
|
||||
looped = sfx->loopstart != (unsigned) -1;
|
||||
target_chan = s_pick_channel (snd, entnum, entchannel, looped);
|
||||
int looped = sfx->loopstart != (unsigned) -1;
|
||||
channel_t *target_chan = s_pick_channel (snd, entnum, entchannel, looped);
|
||||
if (!target_chan)
|
||||
return;
|
||||
|
||||
|
@ -663,7 +666,8 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
|||
};
|
||||
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
|
||||
snd_free_channel (target_chan);
|
||||
return;
|
||||
|
@ -677,16 +681,12 @@ SND_StartSound (snd_t *snd, int entnum, int entchannel, sfx_t *sfx,
|
|||
if (set_is_member (&dynamic_channels, i)
|
||||
|| set_is_member (&looped_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;
|
||||
}
|
||||
}
|
||||
if (!osfx->retain (osfx)) {
|
||||
// because the channel was never started, it's safe to directly free it
|
||||
snd_free_channel (target_chan);
|
||||
return; // couldn't load the sound's data
|
||||
}
|
||||
target_chan->sfx = osfx;
|
||||
target_chan->loopstart = sfx->loopstart;
|
||||
target_chan->buffer = buffer;
|
||||
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,
|
||||
float attenuation)
|
||||
{
|
||||
channel_t *ss;
|
||||
sfx_t *osfx;
|
||||
|
||||
if (!sfx)
|
||||
return;
|
||||
if (sfx->loopstart == (unsigned int) -1) {
|
||||
|
@ -726,13 +723,15 @@ SND_StaticSound (snd_t *snd, sfx_t *sfx, vec4f_t origin, float vol,
|
|||
return;
|
||||
}
|
||||
|
||||
channel_t *ss;
|
||||
if (!(ss = SND_AllocChannel (snd))) {
|
||||
Sys_Printf ("ran out of channels\n");
|
||||
return;
|
||||
}
|
||||
int ss_ind = ss - snd_channels;
|
||||
|
||||
if (!(osfx = sfx->open (sfx)))
|
||||
sfxbuffer_t *buffer;
|
||||
if (!(buffer = sfx->open (sfx)))
|
||||
return;
|
||||
|
||||
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);
|
||||
ss->oldphase = ss->phase;
|
||||
|
||||
if (!osfx->retain (osfx))
|
||||
return;
|
||||
|
||||
set_add (&static_channels, ss_ind);
|
||||
snd_entity_channels[ss_ind] = (entchan_t) {
|
||||
.id = SND_STATIC_ID,
|
||||
.channel = 0,
|
||||
};
|
||||
ss->sfx = osfx;
|
||||
ss->loopstart = sfx->loopstart;
|
||||
ss->buffer = buffer;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -473,11 +473,11 @@ s_channel_free (channel_t *chan)
|
|||
static int
|
||||
s_channel_set_sfx (channel_t *chan, sfx_t *sfx)
|
||||
{
|
||||
sfx_t *s = sfx->open (sfx);
|
||||
if (!s) {
|
||||
sfxbuffer_t *buffer = sfx->open (sfx);
|
||||
if (!buffer) {
|
||||
return 0;
|
||||
}
|
||||
chan->sfx = s;
|
||||
chan->buffer = buffer;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -505,8 +505,8 @@ s_channel_get_state (channel_t *chan)
|
|||
// The mixer has finished mixing the channel (come to the end).
|
||||
return chan_done;
|
||||
}
|
||||
if (!chan->sfx) {
|
||||
// channel requires initialization
|
||||
if (!chan->buffer) {
|
||||
// channel has not been started yet
|
||||
return chan_pending;
|
||||
}
|
||||
if (chan->pause) {
|
||||
|
|
|
@ -126,9 +126,37 @@ SND_Memory_AllocBuffer (unsigned samples)
|
|||
}
|
||||
|
||||
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 *
|
||||
|
@ -142,34 +170,36 @@ snd_noop (sfx_t *sfx)
|
|||
{
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
static sfxbuffer_t *
|
||||
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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sfxbuffer_t *
|
||||
sfxbuffer_t * __attribute__((pure))
|
||||
SND_CacheTouch (sfx_t *sfx)
|
||||
{
|
||||
return sfx->data.block->buffer;
|
||||
return sfx->block->buffer;
|
||||
}
|
||||
|
||||
sfxbuffer_t *
|
||||
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)
|
||||
{
|
||||
return sfx->data.block->buffer;
|
||||
return sfx->block->buffer;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -180,13 +210,13 @@ SND_CacheRelease (sfx_t *sfx)
|
|||
sfxbuffer_t *
|
||||
SND_StreamGetBuffer (sfx_t *sfx)
|
||||
{
|
||||
return sfx->data.stream->buffer;
|
||||
return sfx->stream->buffer;
|
||||
}
|
||||
|
||||
sfxbuffer_t *
|
||||
SND_StreamRetain (sfx_t *sfx)
|
||||
{
|
||||
return sfx->data.stream->buffer;
|
||||
return sfx->stream->buffer;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -195,15 +225,15 @@ SND_StreamRelease (sfx_t *sfx)
|
|||
}
|
||||
|
||||
wavinfo_t *
|
||||
SND_CacheWavinfo (sfx_t *sfx)
|
||||
SND_CacheWavinfo (const sfx_t *sfx)
|
||||
{
|
||||
return &sfx->data.block->wavinfo;
|
||||
return &sfx->block->wavinfo;
|
||||
}
|
||||
|
||||
wavinfo_t *
|
||||
SND_StreamWavinfo (sfx_t *sfx)
|
||||
SND_StreamWavinfo (const sfx_t *sfx)
|
||||
{
|
||||
return &sfx->data.stream->wavinfo;
|
||||
return &sfx->stream->wavinfo;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -215,8 +245,8 @@ read_samples (sfxbuffer_t *buffer, int count)
|
|||
read_samples (buffer, buffer->size - buffer->head);
|
||||
read_samples (buffer, count);
|
||||
} else {
|
||||
sfx_t *sfx = buffer->sfx;
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = buffer->stream;
|
||||
const sfx_t *sfx = stream->sfx;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
float *data = buffer->data + buffer->head * info->channels;
|
||||
int c;
|
||||
|
@ -233,7 +263,7 @@ read_samples (sfxbuffer_t *buffer, int count)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
unsigned int samples;
|
||||
|
@ -244,11 +274,11 @@ fill_buffer (sfx_t *sfx, sfxstream_t *stream, sfxbuffer_t *buffer,
|
|||
if (buffer->tail <= buffer->head)
|
||||
samples += buffer->size;
|
||||
|
||||
if (headpos + samples > sfx->length) {
|
||||
if (headpos + samples > buffer->sfx_length) {
|
||||
if (sfx->loopstart == (unsigned int)-1) {
|
||||
samples = sfx->length - headpos;
|
||||
samples = buffer->sfx_length - headpos;
|
||||
} else {
|
||||
loop_samples = headpos + samples - sfx->length;
|
||||
loop_samples = headpos + samples - buffer->sfx_length;
|
||||
samples -= loop_samples;
|
||||
}
|
||||
}
|
||||
|
@ -264,8 +294,8 @@ void
|
|||
SND_StreamSetPos (sfxbuffer_t *buffer, unsigned int pos)
|
||||
{
|
||||
float stepscale;
|
||||
sfx_t *sfx = buffer->sfx;
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = buffer->stream;
|
||||
const sfx_t *sfx = stream->sfx;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
|
||||
stepscale = (float) info->rate / sfx->snd->speed;
|
||||
|
@ -282,8 +312,8 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
{
|
||||
float stepscale;
|
||||
unsigned int headpos, samples;
|
||||
sfx_t *sfx = buffer->sfx;
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = buffer->stream;
|
||||
const sfx_t *sfx = stream->sfx;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
|
||||
stream->pos += count;
|
||||
|
@ -300,23 +330,23 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
|
||||
// find out where head points to in the stream
|
||||
headpos = buffer->pos + samples;
|
||||
if (headpos >= sfx->length) {
|
||||
if (headpos >= buffer->sfx_length) {
|
||||
if (sfx->loopstart == (unsigned int)-1)
|
||||
headpos = sfx->length;
|
||||
headpos = buffer->sfx_length;
|
||||
else
|
||||
headpos -= sfx->length - sfx->loopstart;
|
||||
headpos -= buffer->sfx_length - sfx->loopstart;
|
||||
}
|
||||
|
||||
if (samples < count) {
|
||||
buffer->head = buffer->tail = 0;
|
||||
buffer->pos += count;
|
||||
if (buffer->pos > sfx->length) {
|
||||
if (buffer->pos > buffer->sfx_length) {
|
||||
if (sfx->loopstart == (unsigned int)-1) {
|
||||
// reset the buffer and fill it incase it's needed again
|
||||
buffer->pos = 0;
|
||||
} else {
|
||||
buffer->pos -= sfx->loopstart;
|
||||
buffer->pos %= sfx->length - sfx->loopstart;
|
||||
buffer->pos %= buffer->sfx_length - sfx->loopstart;
|
||||
buffer->pos += sfx->loopstart;
|
||||
}
|
||||
stream->pos = buffer->pos;
|
||||
|
@ -325,7 +355,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
stream->seek (stream, buffer->pos * stepscale);
|
||||
} else {
|
||||
buffer->pos += count;
|
||||
if (buffer->pos >= sfx->length) {
|
||||
if (buffer->pos >= buffer->sfx_length) {
|
||||
if (sfx->loopstart == (unsigned int)-1) {
|
||||
// reset the buffer and fill it in case it's needed again
|
||||
headpos = buffer->pos = 0;
|
||||
|
@ -333,7 +363,7 @@ SND_StreamAdvance (sfxbuffer_t *buffer, unsigned int count)
|
|||
count = 0;
|
||||
stream->seek (stream, buffer->pos * stepscale);
|
||||
} else {
|
||||
buffer->pos -= sfx->length - sfx->loopstart;
|
||||
buffer->pos -= buffer->sfx_length - sfx->loopstart;
|
||||
}
|
||||
stream->pos = buffer->pos;
|
||||
}
|
||||
|
@ -355,7 +385,6 @@ SND_Load (sfx_t *sfx)
|
|||
|
||||
sfx->touch = sfx->retain = snd_fail;
|
||||
sfx->release = snd_noop;
|
||||
sfx->close = snd_noop;
|
||||
sfx->open = snd_open_fail;
|
||||
|
||||
file = QFS_FOpenFile (sfx->name);
|
||||
|
|
|
@ -53,12 +53,12 @@ static int max_overpaint; // number of extra samples painted
|
|||
/* CHANNEL MIXING */
|
||||
|
||||
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 (sfx->loopstart != (unsigned) -1) {
|
||||
ch->pos = sfx->loopstart;
|
||||
ch->end = ltime + sfx->length - ch->pos;
|
||||
if (ch->loopstart != (unsigned) -1) {
|
||||
ch->pos = ch->loopstart;
|
||||
ch->end = ltime + sb->sfx_length - ch->pos;
|
||||
} else { // channel just stopped
|
||||
ch->done = 1;
|
||||
return 1;
|
||||
|
@ -103,7 +103,6 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
|||
unsigned end, ltime;
|
||||
int i, count;
|
||||
channel_t *ch;
|
||||
sfx_t *sfx;
|
||||
sfxbuffer_t *sb;
|
||||
|
||||
// clear the paint buffer
|
||||
|
@ -123,7 +122,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
|||
// paint in the channels.
|
||||
ch = snd_channels;
|
||||
for (i = 0; i < snd_total_channels; i++, ch++) {
|
||||
if (!(sfx = ch->sfx)) {
|
||||
if (!(sb = ch->buffer)) {
|
||||
// channel is inactive
|
||||
continue;
|
||||
}
|
||||
|
@ -133,14 +132,9 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
|||
}
|
||||
if (ch->pause)
|
||||
continue;
|
||||
sb = sfx->getbuffer (sfx);
|
||||
if (!sb) { // something went wrong with the sfx
|
||||
printf ("XXXX sfx blew up!!!!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ch->end)
|
||||
ch->end = snd->paintedtime + sfx->length - ch->pos;
|
||||
ch->end = snd->paintedtime + sb->sfx_length - ch->pos;
|
||||
|
||||
ltime = snd->paintedtime;
|
||||
|
||||
|
@ -161,7 +155,7 @@ SND_PaintChannels (snd_t *snd, unsigned endtime)
|
|||
ltime += count;
|
||||
}
|
||||
|
||||
if (check_channel_end (ch, sfx, count, ltime))
|
||||
if (check_channel_end (ch, sb, count, ltime))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -473,8 +467,7 @@ SND_SetPaint (sfxbuffer_t *sb)
|
|||
snd_paint_8,
|
||||
};
|
||||
|
||||
wavinfo_t *info = sb->sfx->wavinfo (sb->sfx);
|
||||
if (info->channels > 8)
|
||||
Sys_Error ("illegal channel count %d", info->channels);
|
||||
sb->paint = painters[info->channels];
|
||||
if (sb->channels > 8 || !sb->channels)
|
||||
Sys_Error ("invaliid channel count %d", sb->channels);
|
||||
sb->paint = painters[sb->channels];
|
||||
}
|
||||
|
|
|
@ -63,13 +63,16 @@ check_buffer_integrity (sfxbuffer_t *sb, int width, const char *func)
|
|||
}
|
||||
|
||||
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);
|
||||
snd_t *snd = sfx->snd;
|
||||
int inrate = info->rate;
|
||||
double stepscale = (double) snd->speed / inrate;
|
||||
return info->frames * stepscale;
|
||||
return frames * stepscale;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -77,8 +80,8 @@ SND_Resample (sfxbuffer_t *sb, float *data, int length)
|
|||
{
|
||||
int outcount;
|
||||
double stepscale;
|
||||
wavinfo_t *info = sb->sfx->wavinfo (sb->sfx);
|
||||
snd_t *snd = sb->sfx->snd;
|
||||
wavinfo_t *info = (*sb->sfx)->wavinfo (*sb->sfx);
|
||||
snd_t *snd = (*sb->sfx)->snd;
|
||||
int inrate = info->rate;
|
||||
int outwidth;
|
||||
SRC_DATA src_data;
|
||||
|
@ -153,23 +156,19 @@ void
|
|||
SND_SetupResampler (sfxbuffer_t *sb, int streamed)
|
||||
{
|
||||
double stepscale;
|
||||
wavinfo_t *info = sb->sfx->wavinfo (sb->sfx);
|
||||
snd_t *snd = sb->sfx->snd;
|
||||
wavinfo_t *info = (*sb->sfx)->wavinfo (*sb->sfx);
|
||||
snd_t *snd = (*sb->sfx)->snd;
|
||||
int inrate = info->rate;
|
||||
|
||||
stepscale = (double) snd->speed / inrate;
|
||||
|
||||
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->sfx_length = info->frames * stepscale;
|
||||
|
||||
sb->channels = info->channels;
|
||||
|
||||
if (streamed) {
|
||||
int err;
|
||||
sfxstream_t *stream = sb->sfx->data.stream;
|
||||
sfxstream_t *stream = sb->stream;
|
||||
|
||||
if (snd->speed == inrate) {
|
||||
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;
|
||||
free ((char *) sfx->name);
|
||||
sfx->name = 0;
|
||||
sfx->owner = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
snd_block_close (sfxbuffer_t *buffer)
|
||||
{
|
||||
SND_Memory_Release (buffer);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -84,22 +89,26 @@ SND_SFX_Block (sfx_t *sfx, char *realname, wavinfo_t info,
|
|||
{
|
||||
sfxblock_t *block = calloc (1, sizeof (sfxblock_t));
|
||||
|
||||
sfx->data.block = block;
|
||||
sfx->block = block;
|
||||
sfx->wavinfo = SND_CacheWavinfo;
|
||||
sfx->touch = SND_CacheTouch;
|
||||
sfx->retain = SND_CacheRetain;
|
||||
sfx->release = SND_CacheRelease;
|
||||
sfx->getbuffer = SND_CacheGetBuffer;
|
||||
sfx->loopstart = SND_ResamplerFrames (sfx, info.loopstart);
|
||||
sfx->length = SND_ResamplerFrames (sfx, info.frames);
|
||||
|
||||
block->sfx = sfx;
|
||||
block->file = realname;
|
||||
block->wavinfo = info;
|
||||
block->buffer = load (block);
|
||||
SND_Memory_Retain (block->buffer);
|
||||
block->buffer->close = snd_block_close;
|
||||
}
|
||||
|
||||
void
|
||||
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));
|
||||
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->release = SND_StreamRelease;
|
||||
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->wavinfo = info;
|
||||
}
|
||||
|
||||
sfx_t *
|
||||
sfxbuffer_t *
|
||||
SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
||||
long (*read)(void *, float **),
|
||||
int (*seek)(sfxstream_t *, int),
|
||||
void (*close) (sfx_t *))
|
||||
void (*close) (sfxbuffer_t *))
|
||||
{
|
||||
snd_t *snd = sfx->snd;
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = sfx->stream;
|
||||
wavinfo_t *info = &stream->wavinfo;
|
||||
int frames;
|
||||
|
||||
|
@ -129,55 +140,44 @@ SND_SFX_StreamOpen (sfx_t *sfx, void *file,
|
|||
if (!snd->speed)
|
||||
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 = (frames + 255) & ~255;
|
||||
|
||||
stream = calloc (1, sizeof (sfxstream_t));
|
||||
new_sfx->data.stream = stream;
|
||||
stream->buffer = SND_Memory_AllocBuffer (frames * info->channels);
|
||||
if (!stream->buffer) {
|
||||
free (stream);
|
||||
free (new_sfx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream->file = file;
|
||||
stream->sfx = new_sfx;
|
||||
stream->sfx = sfx;
|
||||
stream->ll_read = read;
|
||||
stream->ll_seek = seek;
|
||||
|
||||
stream->wavinfo = *sfx->wavinfo (sfx);
|
||||
|
||||
stream->buffer->stream = stream;
|
||||
stream->buffer->size = frames;
|
||||
stream->buffer->advance = SND_StreamAdvance;
|
||||
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_SetupResampler (stream->buffer, 1); // get sfx setup properly
|
||||
stream->buffer->setpos (stream->buffer, 0); // pre-fill the buffer
|
||||
|
||||
return new_sfx;
|
||||
return stream->buffer;
|
||||
}
|
||||
|
||||
void
|
||||
SND_SFX_StreamClose (sfx_t *sfx)
|
||||
SND_SFX_StreamClose (sfxstream_t *stream)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
SND_PulldownResampler (stream);
|
||||
SND_Memory_FreeBuffer (stream->buffer);
|
||||
SND_Memory_Free (stream->buffer);
|
||||
free (stream);
|
||||
free (sfx);
|
||||
}
|
||||
|
||||
sfx_t *
|
||||
|
@ -196,7 +196,6 @@ SND_LoadSound (snd_t *snd, const char *name)
|
|||
sfx = &snd_sfx[snd_num_sfx++];
|
||||
sfx->snd = snd;
|
||||
sfx->name = strdup (name);
|
||||
sfx->owner = sfx;
|
||||
if (SND_Load (sfx) == -1) {
|
||||
snd_num_sfx--;
|
||||
return 0;
|
||||
|
|
|
@ -164,18 +164,20 @@ vorbis_load (OggVorbis_File *vf, sfxblock_t *block)
|
|||
{
|
||||
float *data;
|
||||
sfxbuffer_t *sb = 0;
|
||||
sfx_t *sfx = block->sfx;
|
||||
const sfx_t *sfx = block->sfx;
|
||||
wavinfo_t *info = &block->wavinfo;
|
||||
|
||||
data = malloc (info->datalen);
|
||||
if (!data)
|
||||
goto bail;
|
||||
unsigned buffer_frames = SND_ResamplerFrames (sfx);
|
||||
unsigned buffer_frames = SND_ResamplerFrames (sfx, info->frames);
|
||||
sb = SND_Memory_AllocBuffer (buffer_frames * info->channels);
|
||||
if (!sb)
|
||||
goto bail;
|
||||
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)
|
||||
goto bail;
|
||||
SND_SetPaint (sb);
|
||||
|
@ -240,9 +242,9 @@ vorbis_stream_seek (sfxstream_t *stream, int pos)
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
if (vf->data)
|
||||
|
@ -250,13 +252,13 @@ vorbis_stream_close (sfx_t *sfx)
|
|||
ov_clear (vf->vf);
|
||||
free (vf->vf);
|
||||
free (vf);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
SND_SFX_StreamClose (stream);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
static sfxbuffer_t *
|
||||
vorbis_stream_open (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = sfx->stream;
|
||||
QFile *file;
|
||||
vorbis_file_t *f;
|
||||
|
||||
|
|
|
@ -57,13 +57,13 @@ typedef struct {
|
|||
static sfxbuffer_t *
|
||||
wav_callback_load (sfxblock_t *block)
|
||||
{
|
||||
sfx_t *sfx = block->sfx;
|
||||
const sfx_t *sfx = block->sfx;
|
||||
const char *name = (const char *) block->file;
|
||||
QFile *file;
|
||||
int len, fdata_ofs;
|
||||
byte *data;
|
||||
float *fdata;
|
||||
sfxbuffer_t *buffer;
|
||||
sfxbuffer_t *buffer = 0;
|
||||
wavinfo_t *info = &block->wavinfo;
|
||||
|
||||
file = QFS_FOpenFile (name);
|
||||
|
@ -81,12 +81,14 @@ wav_callback_load (sfxblock_t *block)
|
|||
|
||||
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);
|
||||
if (!buffer)
|
||||
goto bail;
|
||||
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_SetupResampler (buffer, 0);
|
||||
SND_Resample (buffer, fdata, info->frames);
|
||||
|
@ -139,22 +141,22 @@ wav_stream_seek (sfxstream_t *stream, int pos)
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
Qclose (wf->file);
|
||||
if (wf->data)
|
||||
free (wf->data);
|
||||
free (wf);
|
||||
SND_SFX_StreamClose (sfx);
|
||||
SND_SFX_StreamClose (stream);
|
||||
}
|
||||
|
||||
static sfx_t *
|
||||
static sfxbuffer_t *
|
||||
wav_stream_open (sfx_t *sfx)
|
||||
{
|
||||
sfxstream_t *stream = sfx->data.stream;
|
||||
sfxstream_t *stream = sfx->stream;
|
||||
QFile *file;
|
||||
wav_file_t *wf;
|
||||
|
||||
|
|
Loading…
Reference in a new issue