From 44aaec4f22412a2c7f34cd10fb5250ab25626c5e Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Mar 2007 01:44:46 +0000 Subject: [PATCH] make the cache/stream setup code common. --- include/snd_render.h | 45 ++++++++++++++++--- libs/audio/renderer/flac.c | 77 ++++---------------------------- libs/audio/renderer/midi.c | 11 +---- libs/audio/renderer/snd_sfx.c | 83 +++++++++++++++++++++++++++++++++++ libs/audio/renderer/vorbis.c | 76 +++++--------------------------- libs/audio/renderer/wav.c | 70 +++-------------------------- 6 files changed, 149 insertions(+), 213 deletions(-) diff --git a/include/snd_render.h b/include/snd_render.h index e89499c54..8cd34f044 100644 --- a/include/snd_render.h +++ b/include/snd_render.h @@ -127,16 +127,14 @@ struct sfxstream_s { void *file; //!< handle for "file" representing the stream wavinfo_t wavinfo; //!< description of sound data unsigned pos; //!< position of next sample within full stream - /** Seek to an absolute position within the stream, resetting the ring - buffer. + /** Resample raw data into internal format. \param sc buffer to write resampled sound (sfxstream_s::buffer) \param data raw sample data \param length number of raw samples to resample \param prev pointer to end of last resample for smoothing */ void (*resample)(sfxbuffer_t *, byte *, int, void *); - /** Seek to an absolute position within the stream, resetting the ring - buffer. + /** Read data from the stream. \param file handle for "file" representing the stream (sfxstream_s::file) \param data destination of read data @@ -164,7 +162,7 @@ struct sfxblock_s { cache_user_t cache; //!< cached sound buffer (::sfxbuffer_s) }; -/** Representation of a sound being played +/** Representation of a sound being played. */ struct channel_s { sfx_t *sfx; //!< sound played by this channel @@ -180,6 +178,14 @@ struct channel_s { int master_vol; //!< 0-255 master volume int phase; //!< phase shift between l-r in samples int oldphase; //!< phase shift between l-r in samples + /** signal between main program and mixer thread that the channel is to be + stopped. + - 0 normal operation + - 1 signal from main program to mixer the channel is to be stopped + - 2 signal from the mixer to the main program indicating the mixer is + done with the channel and the main program is free to clear it. + */ + int stopped; }; extern struct cvar_s *snd_loadas8bit; @@ -200,6 +206,35 @@ extern portable_samplepair_t snd_paintbuffer[PAINTBUFFER_SIZE * 2]; \ingroup sound_render_mix */ //@{ +/** Cache sound data. Initializes caching fields of sfx. + \param sfx + \param realname + \param info + \param loader +*/ +void SND_SFX_Cache (sfx_t *sfx, char *realname, wavinfo_t info, + cache_loader_t loader); + +/** Stream sound data. Initializes streaming fields of sfx. + \param sfx + \param realname + \param info + \param open +*/ +void SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info, + sfx_t *(*open) (sfx_t *sfx)); + +/** Open a stream for playback. + \param sfx + \param read + \param seek + \param close +*/ +sfx_t *SND_SFX_StreamOpen (sfx_t *sfx, void *file, + int (*read)(void *, byte *, int, wavinfo_t *), + int (*seek)(void *, int, wavinfo_t *), + void (*close) (sfx_t *)); + /** Pre-load a sound into the cache. \param sample name of sound to precache */ diff --git a/libs/audio/renderer/flac.c b/libs/audio/renderer/flac.c index 652f4a9b3..ce61607ba 100644 --- a/libs/audio/renderer/flac.c +++ b/libs/audio/renderer/flac.c @@ -314,21 +314,8 @@ flac_callback_load (void *object, cache_allocator_t allocator) static void flac_cache (sfx_t *sfx, char *realname, flacfile_t *ff, wavinfo_t info) { - sfxblock_t *block = calloc (1, sizeof (sfxblock_t)); - close_flac (ff); - - sfx->data = block; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = SND_CacheTouch; - sfx->retain = SND_CacheRetain; - sfx->release = SND_CacheRelease; - - block->sfx = sfx; - block->file = realname; - block->wavinfo = info; - - Cache_Add (&block->cache, block, flac_callback_load); + SND_SFX_Cache (sfx, realname, info, flac_callback_load); } static int @@ -357,78 +344,32 @@ flac_stream_close (sfx_t *sfx) } static sfx_t * -flac_stream_open (sfx_t *_sfx) +flac_stream_open (sfx_t *sfx) { - sfx_t *sfx; - sfxstream_t *stream = (sfxstream_t *) _sfx->data; - wavinfo_t *info = &stream->wavinfo; - int samples; - int size; + sfxstream_t *stream = (sfxstream_t *) sfx->data; QFile *file; + void *f; QFS_FOpenFile (stream->file, &file); if (!file) return 0; - sfx = calloc (1, sizeof (sfx_t)); - samples = snd_shm->speed * 0.3; - size = samples = (samples + 255) & ~255; - if (!snd_loadas8bit->int_val) - size *= 2; - if (info->channels == 2) - size *= 2; - stream = calloc (1, sizeof (sfxstream_t) + size); - memcpy (stream->buffer.data + size, "\xde\xad\xbe\xef", 4); - - sfx->name = _sfx->name; - sfx->data = stream; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->close = flac_stream_close; - - stream->sfx = sfx; - stream->file = open_flac (file); - if (!stream->file) { + f = open_flac (file); + if (!f) { Sys_Printf ("Input does not appear to be a flac bitstream.\n"); Qclose (file); - free (stream); - free (sfx); return 0; } - stream->resample = info->channels == 2 ? SND_ResampleStereo - : SND_ResampleMono; - stream->read = flac_stream_read; - stream->seek = flac_stream_seek; - stream->wavinfo = *info; - stream->buffer.length = samples; - stream->buffer.advance = SND_StreamAdvance; - stream->buffer.setpos = SND_StreamSetPos; - stream->buffer.sfx = sfx; - - stream->resample (&stream->buffer, 0, 0, 0); // get sfx setup properly - stream->seek (stream->file, 0, &stream->wavinfo); - - stream->buffer.advance (&stream->buffer, 0); - - return sfx; + return SND_SFX_StreamOpen (sfx, f, flac_stream_read, flac_stream_seek, + flac_stream_close); } static void flac_stream (sfx_t *sfx, char *realname, flacfile_t *ff, wavinfo_t info) { - sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); - close_flac (ff); - sfx->open = flac_stream_open; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->data = stream; - - stream->file = realname; - stream->wavinfo = info; + SND_SFX_Stream (sfx, realname, info, flac_stream_open); } static wavinfo_t diff --git a/libs/audio/renderer/midi.c b/libs/audio/renderer/midi.c index c29451b8f..ed92b38ca 100644 --- a/libs/audio/renderer/midi.c +++ b/libs/audio/renderer/midi.c @@ -191,7 +191,6 @@ void SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) { wavinfo_t info; - sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); midi *handle; unsigned char *local_buffer; unsigned long int local_buffer_size = Qfilesize (file); @@ -220,14 +219,6 @@ SND_LoadMidi (QFile *file, sfx_t *sfx, char *realname) Sys_DPrintf ("stream %s\n", realname); // we init stream here cause we will only ever stream - - sfx->open = midi_stream_open; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->data = stream; - - stream->file = realname; - stream->wavinfo = info; + SND_SFX_Stream (sfx, realname, info, midi_stream_open); } #endif // HAVE_WILDMIDI diff --git a/libs/audio/renderer/snd_sfx.c b/libs/audio/renderer/snd_sfx.c index 9820b3738..95dce81e7 100644 --- a/libs/audio/renderer/snd_sfx.c +++ b/libs/audio/renderer/snd_sfx.c @@ -72,6 +72,89 @@ snd_sfx_free (void *_sfx, void *unused) sfx->name = 0; } +void +SND_SFX_Cache (sfx_t *sfx, char *realname, wavinfo_t info, + cache_loader_t loader) +{ + sfxblock_t *block = calloc (1, sizeof (sfxblock_t)); + + sfx->data = block; + sfx->wavinfo = SND_CacheWavinfo; + sfx->touch = SND_CacheTouch; + sfx->retain = SND_CacheRetain; + sfx->release = SND_CacheRelease; + + block->sfx = sfx; + block->file = realname; + block->wavinfo = info; + + Cache_Add (&block->cache, block, loader); +} + +void +SND_SFX_Stream (sfx_t *sfx, char *realname, wavinfo_t info, + sfx_t *(*open) (sfx_t *sfx)) +{ + sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); + sfx->open = open; + sfx->wavinfo = SND_CacheWavinfo; + sfx->touch = sfx->retain = SND_StreamRetain; + sfx->release = SND_StreamRelease; + sfx->data = stream; + + stream->file = realname; + stream->wavinfo = info; +} + +sfx_t * +SND_SFX_StreamOpen (sfx_t *sfx, void *file, + int (*read)(void *, byte *, int, wavinfo_t *), + int (*seek)(void *, int, wavinfo_t *), + void (*close) (sfx_t *)) +{ + sfxstream_t *stream = (sfxstream_t *) sfx->data; + wavinfo_t *info = &stream->wavinfo; + int samples; + int size; + + sfx_t *new_sfx = calloc (1, sizeof (sfx_t)); + + new_sfx->name = sfx->name; + new_sfx->wavinfo = SND_CacheWavinfo; + new_sfx->touch = new_sfx->retain = SND_StreamRetain; + new_sfx->release = SND_StreamRelease; + new_sfx->close = close; + + samples = snd_shm->speed * 0.3; + size = samples = (samples + 255) & ~255; + if (!snd_loadas8bit->int_val) + size *= 2; + if (info->channels == 2) + size *= 2; + + stream = calloc (1, sizeof (sfxstream_t) + size); + new_sfx->data = stream; + memcpy (stream->buffer.data + size, "\xde\xad\xbe\xef", 4); + stream->file = file; + stream->sfx = new_sfx; + stream->resample = info->channels == 2 ? SND_ResampleStereo + : SND_ResampleMono; + stream->read = read; + stream->seek = seek; + + stream->buffer.length = samples; + stream->buffer.advance = SND_StreamAdvance; + stream->buffer.setpos = SND_StreamSetPos; + stream->buffer.sfx = new_sfx; + + stream->resample (&stream->buffer, 0, 0, 0); // get sfx setup properly + stream->seek (stream->file, 0, &stream->wavinfo); + + stream->buffer.advance (&stream->buffer, 0); + + return new_sfx; +} + sfx_t * SND_LoadSound (const char *name) { diff --git a/libs/audio/renderer/vorbis.c b/libs/audio/renderer/vorbis.c index 1b178c6e5..1e27e1a90 100644 --- a/libs/audio/renderer/vorbis.c +++ b/libs/audio/renderer/vorbis.c @@ -214,19 +214,8 @@ vorbis_callback_load (void *object, cache_allocator_t allocator) static void vorbis_cache (sfx_t *sfx, char *realname, OggVorbis_File *vf, wavinfo_t info) { - sfxblock_t *block = calloc (1, sizeof (sfxblock_t)); ov_clear (vf); - sfx->data = block; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = SND_CacheTouch; - sfx->retain = SND_CacheRetain; - sfx->release = SND_CacheRelease; - - block->sfx = sfx; - block->file = realname; - block->wavinfo = info; - - Cache_Add (&block->cache, block, vorbis_callback_load); + SND_SFX_Cache (sfx, realname, info, vorbis_callback_load); } static int @@ -252,78 +241,33 @@ vorbis_stream_close (sfx_t *sfx) } static sfx_t * -vorbis_stream_open (sfx_t *_sfx) +vorbis_stream_open (sfx_t *sfx) { - sfx_t *sfx; - sfxstream_t *stream = (sfxstream_t *) _sfx->data; - wavinfo_t *info = &stream->wavinfo; - int samples; - int size; + sfxstream_t *stream = (sfxstream_t *) sfx->data; QFile *file; + void *f; QFS_FOpenFile (stream->file, &file); if (!file) return 0; - sfx = calloc (1, sizeof (sfx_t)); - samples = snd_shm->speed * 0.3; - size = samples = (samples + 255) & ~255; - if (!snd_loadas8bit->int_val) - size *= 2; - if (info->channels == 2) - size *= 2; - stream = calloc (1, sizeof (sfxstream_t) + size); - memcpy (stream->buffer.data + size, "\xde\xad\xbe\xef", 4); - - sfx->name = _sfx->name; - sfx->data = stream; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->close = vorbis_stream_close; - - stream->sfx = sfx; - stream->file = malloc (sizeof (OggVorbis_File)); - if (ov_open_callbacks (file, stream->file, 0, 0, callbacks) < 0) { + f = malloc (sizeof (OggVorbis_File)); + if (ov_open_callbacks (file, f, 0, 0, callbacks) < 0) { Sys_Printf ("Input does not appear to be an Ogg bitstream.\n"); Qclose (file); - free (stream); - free (sfx); + free (f); return 0; } - stream->resample = info->channels == 2 ? SND_ResampleStereo - : SND_ResampleMono; - stream->read = vorbis_stream_read; - stream->seek = vorbis_stream_seek; - stream->wavinfo = *info; - stream->buffer.length = samples; - stream->buffer.advance = SND_StreamAdvance; - stream->buffer.setpos = SND_StreamSetPos; - stream->buffer.sfx = sfx; - - stream->resample (&stream->buffer, 0, 0, 0); // get sfx setup properly - stream->seek (stream->file, 0, &stream->wavinfo); - - stream->buffer.advance (&stream->buffer, 0); - - return sfx; + return SND_SFX_StreamOpen (sfx, f, vorbis_stream_read, vorbis_stream_seek, + vorbis_stream_close); } static void vorbis_stream (sfx_t *sfx, char *realname, OggVorbis_File *vf, wavinfo_t info) { - sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); - ov_clear (vf); - sfx->open = vorbis_stream_open; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->data = stream; - - stream->file = realname; - stream->wavinfo = info; + SND_SFX_Stream (sfx, realname, info, vorbis_stream_open); } void diff --git a/libs/audio/renderer/wav.c b/libs/audio/renderer/wav.c index 64addd88e..e1201ada1 100644 --- a/libs/audio/renderer/wav.c +++ b/libs/audio/renderer/wav.c @@ -82,19 +82,8 @@ wav_callback_load (void *object, cache_allocator_t allocator) static void wav_cache (sfx_t *sfx, char *realname, void *file, wavinfo_t info) { - sfxblock_t *block = calloc (1, sizeof (sfxblock_t)); Qclose (file); - sfx->data = block; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = SND_CacheTouch; - sfx->retain = SND_CacheRetain; - sfx->release = SND_CacheRelease; - - block->sfx = sfx; - block->file = realname; - block->wavinfo = info; - - Cache_Add (&block->cache, block, wav_callback_load); + SND_SFX_Cache (sfx, realname, info, wav_callback_load); } static int @@ -122,71 +111,24 @@ wav_stream_close (sfx_t *sfx) } static sfx_t * -wav_stream_open (sfx_t *_sfx) +wav_stream_open (sfx_t *sfx) { - sfx_t *sfx; - sfxstream_t *stream = (sfxstream_t *) _sfx->data; - wavinfo_t *info = &stream->wavinfo; - int samples; - int size; + sfxstream_t *stream = (sfxstream_t *) sfx->data; QFile *file; QFS_FOpenFile (stream->file, &file); if (!file) return 0; - sfx = calloc (1, sizeof (sfx_t)); - samples = snd_shm->speed * 0.3; - size = samples = (samples + 255) & ~255; - if (!snd_loadas8bit->int_val) - size *= 2; - if (info->channels == 2) - size *= 2; - stream = calloc (1, sizeof (sfxstream_t) + size); - memcpy (stream->buffer.data + size, "\xde\xad\xbe\xef", 4); - - sfx->name = _sfx->name; - sfx->data = stream; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->close = wav_stream_close; - - stream->sfx = sfx; - stream->file = file; - stream->resample = info->channels == 2 ? SND_ResampleStereo - : SND_ResampleMono; - stream->read = wav_stream_read; - stream->seek = wav_stream_seek; - stream->wavinfo = *info; - - stream->buffer.length = samples; - stream->buffer.advance = SND_StreamAdvance; - stream->buffer.setpos = SND_StreamSetPos; - stream->buffer.sfx = sfx; - - stream->resample (&stream->buffer, 0, 0, 0); // get sfx setup properly - stream->seek (stream->file, 0, &stream->wavinfo); - - stream->buffer.advance (&stream->buffer, 0); - - return sfx; + return SND_SFX_StreamOpen (sfx, file, wav_stream_read, wav_stream_seek, + wav_stream_close); } static void wav_stream (sfx_t *sfx, char *realname, void *file, wavinfo_t info) { - sfxstream_t *stream = calloc (1, sizeof (sfxstream_t)); - Qclose (file); - sfx->open = wav_stream_open; - sfx->wavinfo = SND_CacheWavinfo; - sfx->touch = sfx->retain = SND_StreamRetain; - sfx->release = SND_StreamRelease; - sfx->data = stream; - - stream->file = realname; - stream->wavinfo = info; + SND_SFX_Stream (sfx, realname, info, wav_stream_open); } static wavinfo_t