diff --git a/include/snd_internal.h b/include/snd_internal.h index 352138114..fc618c825 100644 --- a/include/snd_internal.h +++ b/include/snd_internal.h @@ -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 diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index 9868d12cd..4d8ed5a94 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -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; diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index bebb1f9f0..8185060e6 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -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; diff --git a/libs/audio/renderer/snd_channels.c b/libs/audio/renderer/snd_channels.c index 8b56415ff..d90b98e8a 100644 --- a/libs/audio/renderer/snd_channels.c +++ b/libs/audio/renderer/snd_channels.c @@ -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 diff --git a/libs/audio/renderer/snd_dma.c b/libs/audio/renderer/snd_dma.c index f8095688a..7e3fd427f 100644 --- a/libs/audio/renderer/snd_dma.c +++ b/libs/audio/renderer/snd_dma.c @@ -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) { diff --git a/libs/audio/renderer/snd_mem.c b/libs/audio/renderer/snd_mem.c index aa93b6bd0..05ee1d55a 100644 --- a/libs/audio/renderer/snd_mem.c +++ b/libs/audio/renderer/snd_mem.c @@ -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); diff --git a/libs/audio/renderer/snd_mix.c b/libs/audio/renderer/snd_mix.c index 92789aaa1..4453852a1 100644 --- a/libs/audio/renderer/snd_mix.c +++ b/libs/audio/renderer/snd_mix.c @@ -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]; } diff --git a/libs/audio/renderer/snd_resample.c b/libs/audio/renderer/snd_resample.c index 97f4acbc4..b11e1ed88 100644 --- a/libs/audio/renderer/snd_resample.c +++ b/libs/audio/renderer/snd_resample.c @@ -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); diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 79a7af51d..8a4e9f6c5 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -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; diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 8c51660df..e7b4565c1 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -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; diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index 68baae734..24dc27863 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -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;