From 8fdf5c85d7ac0914e7241897c38c5caa1c88af6c Mon Sep 17 00:00:00 2001 From: avolkov Date: Tue, 11 Feb 2003 10:51:53 +0000 Subject: [PATCH] Fixes some sound <-> mixsdl interactions, in particular, same buffer getting queued on 2 sources (bug #146) git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@730 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/src/sc2code/libs/sound/mixsdl/mixer.c | 60 +++++++++++-------- sc2/src/sc2code/libs/sound/mixsdl/mixerint.h | 1 + .../sc2code/libs/sound/mixsdl/sound_mixsdl.h | 1 + sc2/src/sc2code/libs/sound/sfx.c | 27 ++++++++- sc2/src/sc2code/libs/sound/sound.c | 43 ++++++++++--- sc2/src/sc2code/libs/sound/sound.h | 1 + sc2/src/sc2code/libs/sound/sound_chooser.c | 3 + sc2/src/sc2code/libs/sound/sound_chooser.h | 1 + 8 files changed, 105 insertions(+), 32 deletions(-) diff --git a/sc2/src/sc2code/libs/sound/mixsdl/mixer.c b/sc2/src/sc2code/libs/sound/mixsdl/mixer.c index 4681f4fb8..9d13fae43 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/mixer.c +++ b/sc2/src/sc2code/libs/sound/mixsdl/mixer.c @@ -490,10 +490,15 @@ mixSDL_Sourcei (mixSDL_Object srcobj, mixSDL_SourceProp pname, } break; case MIX_SOURCE_STATE: -#ifdef DEBUG - fprintf (stderr, "mixSDL_Sourcei() called " - "with MIX_SOURCE_STATE. call ignored\n"); -#endif + if (value == MIX_INITIAL) + { + mixSDL_SourceRewind_internal (src); + } + else + { + fprintf (stderr, "mixSDL_Sourcei(MIX_SOURCE_STATE): " + "unsupported state, call ignored\n"); + } break; default: mixSDL_SetError (MIX_INVALID_ENUM); @@ -700,26 +705,7 @@ mixSDL_SourceRewind (mixSDL_Object srcobj) } else { - /* should change the processed buffers to queued */ - mixSDL_Buffer *buf; - - if (src->state >= MIX_PLAYING) - mixSDL_SourceDeactivate (src); - - mixSDL_LockMutex (buf_mutex); - - for (buf = src->firstqueued; - buf && buf->state != MIX_BUF_QUEUED; - buf = buf->next) - { - buf->state = MIX_BUF_QUEUED; - } - - mixSDL_UnlockMutex (buf_mutex); - - src->curbufofs = 0; - src->cprocessed = 0; - src->state = MIX_INITIAL; + mixSDL_SourceRewind_internal (src); } mixSDL_UnlockMutex (src_mutex); @@ -1104,6 +1090,32 @@ mixSDL_SourceStop_internal (mixSDL_Source *src) mixSDL_UnlockMutex (buf_mutex); } +static void +mixSDL_SourceRewind_internal (mixSDL_Source *src) +{ + /* should change the processed buffers to queued */ + mixSDL_Buffer *buf; + + if (src->state >= MIX_PLAYING) + mixSDL_SourceDeactivate (src); + + mixSDL_LockMutex (buf_mutex); + + for (buf = src->firstqueued; + buf && buf->state != MIX_BUF_QUEUED; + buf = buf->next) + { + buf->state = MIX_BUF_QUEUED; + } + + mixSDL_UnlockMutex (buf_mutex); + + src->curbufofs = 0; + src->cprocessed = 0; + src->nextqueued = src->firstqueued; + src->state = MIX_INITIAL; +} + /* get the sample next in queue in internal format */ static __inline__ bool mixSDL_SourceGetNextSample (mixSDL_Source *src, sint32* psamp) diff --git a/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h b/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h index 9d764cdc9..ec6e9a913 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/mixerint.h @@ -76,6 +76,7 @@ static __inline__ void mixSDL_PutSampleExt (void *dst, uint32 bpc, /* Source manipulation */ static void mixSDL_SourceUnqueueAll (mixSDL_Source *src); static void mixSDL_SourceStop_internal (mixSDL_Source *src); +static void mixSDL_SourceRewind_internal (mixSDL_Source *src); static void mixSDL_SourceActivate (mixSDL_Source* src); static void mixSDL_SourceDeactivate (mixSDL_Source* src); diff --git a/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h b/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h index 6ea932815..5db3e4d79 100644 --- a/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h +++ b/sc2/src/sc2code/libs/sound/mixsdl/sound_mixsdl.h @@ -61,6 +61,7 @@ #define TFBSOUND_SOURCE_STATE MIX_SOURCE_STATE #define TFBSOUND_PLAYING MIX_PLAYING #define TFBSOUND_PAUSED MIX_PAUSED +#define TFBSOUND_STOPPED MIX_STOPPED #define TFBSOUND_FORMAT_MONO16 MIX_FORMAT_MONO16 #define TFBSOUND_FORMAT_STEREO16 MIX_FORMAT_STEREO16 #define TFBSOUND_FORMAT_STEREO8 MIX_FORMAT_STEREO8 diff --git a/sc2/src/sc2code/libs/sound/sfx.c b/sc2/src/sc2code/libs/sound/sfx.c index d043a6c2a..aae5fef52 100644 --- a/sc2/src/sc2code/libs/sound/sfx.c +++ b/sc2/src/sc2code/libs/sound/sfx.c @@ -21,14 +21,19 @@ #include "sound.h" +static void CheckFinishedChannels (); + void PlayChannel (COUNT channel, PVOID sample, COUNT sample_length, COUNT loop_begin, COUNT loop_length, unsigned char priority) { TFB_SoundSample *tfb_sample = *(TFB_SoundSample**) sample; + StopSource (channel); + // all finished (stopped) channels can be cleaned up at this point + // since this is the only func that can initiate an sfx sound + CheckFinishedChannels (); soundSource[channel].sample = tfb_sample; - TFBSound_SourceStop (soundSource[channel].handle); TFBSound_Sourcei (soundSource[channel].handle, TFBSOUND_BUFFER, tfb_sample->buffer[0]); TFBSound_SourcePlay (soundSource[channel].handle); @@ -40,6 +45,26 @@ StopChannel (COUNT channel, unsigned char Priority) StopSource (channel); } +static void +CheckFinishedChannels () +{ + int i; + + for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i) + { + TFBSound_IntVal state; + + TFBSound_GetSourcei (soundSource[i].handle, TFBSOUND_SOURCE_STATE, + &state); + if (state == TFBSOUND_STOPPED) + { + CleanSource (i); + // and if it failed... we still dont care + TFBSound_GetError(); + } + } +} + BOOLEAN ChannelPlaying (COUNT WhichChannel) { diff --git a/sc2/src/sc2code/libs/sound/sound.c b/sc2/src/sc2code/libs/sound/sound.c index 4e661af7c..b70de971c 100644 --- a/sc2/src/sc2code/libs/sound/sound.c +++ b/sc2/src/sc2code/libs/sound/sound.c @@ -34,22 +34,39 @@ StopSound (void) } void -StopSource (int iSource) +CleanSource (int iSource) { +#define MAX_STACK_BUFFERS 64 TFBSound_IntVal processed; - TFBSound_SourceStop (soundSource[iSource].handle); TFBSound_GetSourcei (soundSource[iSource].handle, TFBSOUND_BUFFERS_PROCESSED, &processed); - if (processed != 0) { - TFBSound_Object *buffer = (TFBSound_Object *) - HMalloc (sizeof (TFBSound_Object) * processed); + TFBSound_Object stack_bufs[MAX_STACK_BUFFERS]; + TFBSound_Object *bufs; + + if (processed > MAX_STACK_BUFFERS) + bufs = (TFBSound_Object *) HMalloc ( + sizeof (TFBSound_Object) * processed); + else + bufs = stack_bufs; + TFBSound_SourceUnqueueBuffers (soundSource[iSource].handle, - processed, buffer); - HFree (buffer); + processed, bufs); + + if (processed > MAX_STACK_BUFFERS) + HFree (bufs); } + // set the source state to 'initial' + TFBSound_SourceRewind (soundSource[iSource].handle); +} + +void +StopSource (int iSource) +{ + TFBSound_SourceStop (soundSource[iSource].handle); + CleanSource (iSource); } BOOLEAN @@ -82,6 +99,18 @@ SoundPlaying (void) return FALSE; } +// for now just spin in a sleep() loop +// perhaps later change to condvar implementation +void +WaitForSoundEnd (COUNT Channel) +{ + while (Channel == TFBSOUND_WAIT_ALL ? + SoundPlaying () : ChannelPlaying (Channel)) + { + SleepThread (ONE_SECOND / 20); + } +} + TFB_SoundChain * create_soundchain (TFB_SoundDecoder *decoder, float startTime) { diff --git a/sc2/src/sc2code/libs/sound/sound.h b/sc2/src/sc2code/libs/sound/sound.h index ab55280a0..b9a89447f 100644 --- a/sc2/src/sc2code/libs/sound/sound.h +++ b/sc2/src/sc2code/libs/sound/sound.h @@ -90,6 +90,7 @@ typedef struct tfb_soundsource extern TFB_SoundSource soundSource[]; void StopSource (int iSource); +void CleanSource (int iSource); void SetSFXVolume (float volume); void SetSpeechVolume (float volume); diff --git a/sc2/src/sc2code/libs/sound/sound_chooser.c b/sc2/src/sc2code/libs/sound/sound_chooser.c index 3bb37d664..d01902fc7 100644 --- a/sc2/src/sc2code/libs/sound/sound_chooser.c +++ b/sc2/src/sc2code/libs/sound/sound_chooser.c @@ -27,6 +27,7 @@ static unsigned int tfb_enum_lookup[TFBSOUND_ENUMSIZE]; unsigned int TFBSOUND_NO_ERROR; int TFBSOUND_PAUSED; int TFBSOUND_PLAYING; +int TFBSOUND_STOPPED; unsigned int TFBSOUND_FORMAT_MONO16; unsigned int TFBSOUND_FORMAT_STEREO16; unsigned int TFBSOUND_FORMAT_STEREO8; @@ -262,6 +263,7 @@ TFB_choose_InitSound (int driver, int flags) TFBSOUND_NO_ERROR = AL_NO_ERROR; TFBSOUND_PAUSED = AL_PAUSED; TFBSOUND_PLAYING = AL_PLAYING; + TFBSOUND_STOPPED = AL_STOPPED; TFBSOUND_FORMAT_MONO16 = AL_FORMAT_MONO16; TFBSOUND_FORMAT_STEREO16 = AL_FORMAT_STEREO16; TFBSOUND_FORMAT_MONO8 = AL_FORMAT_MONO8; @@ -281,6 +283,7 @@ TFB_choose_InitSound (int driver, int flags) TFBSOUND_NO_ERROR = MIX_NO_ERROR; TFBSOUND_PAUSED = MIX_PAUSED; TFBSOUND_PLAYING = MIX_PLAYING; + TFBSOUND_STOPPED = MIX_STOPPED; TFBSOUND_FORMAT_MONO16 = MIX_FORMAT_MONO16; TFBSOUND_FORMAT_STEREO16 = MIX_FORMAT_STEREO16; TFBSOUND_FORMAT_MONO8 = MIX_FORMAT_MONO8; diff --git a/sc2/src/sc2code/libs/sound/sound_chooser.h b/sc2/src/sc2code/libs/sound/sound_chooser.h index fa73879ef..8aa351bda 100644 --- a/sc2/src/sc2code/libs/sound/sound_chooser.h +++ b/sc2/src/sc2code/libs/sound/sound_chooser.h @@ -101,6 +101,7 @@ enum extern int TFBSOUND_PAUSED; extern int TFBSOUND_PLAYING; +extern int TFBSOUND_STOPPED; extern unsigned int TFBSOUND_NO_ERROR; extern unsigned int TFBSOUND_FORMAT_MONO16; extern unsigned int TFBSOUND_FORMAT_STEREO16;