From 5d9483b6329153f4e9924e332dc42ad835e77c83 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 15 Sep 2008 16:02:05 +0000 Subject: [PATCH] - Moved some more high level sound logic out of FMODSoundRenderer: The rolloff and channel ended callbacks now call functions in s_sound.cpp instead of working on the data itself and GSnd->StopSound has been replaced with S_StopChannel. SVN r1227 (trunk) --- docs/rh-log.txt | 10 +++ src/s_sound.cpp | 137 +++++++++++++++++++++++++++++++++++++--- src/s_sound.h | 1 + src/sound/fmodsound.cpp | 128 ++++++++----------------------------- src/sound/fmodsound.h | 3 +- src/sound/i_sound.cpp | 16 ++--- src/sound/i_sound.h | 5 +- 7 files changed, 177 insertions(+), 123 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a978e93e7..c6f253afd 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,13 @@ +September 15, 2008 (Changes by Graf Zahl) +- Moved some more high level sound logic out of FMODSoundRenderer: + The rolloff and channel ended callbacks now call functions in s_sound.cpp + instead of working on the data itself and GSnd->StopSound has been replaced + with S_StopChannel. +- Changed compilation for g_doom, g_heretic, g_hexen and g_strife folders so + that all files are included by a central one instead of compiling each one + separately. This speeds up the compilation process by 25% when doing a + complete rebuild in Visual C. + September 14, 2008 (Changes by Graf Zahl) - Cleaned up some include dependencies. - fixed: For Chex Quest some CVars were initialized to Heretic's default. diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 37f70c05f..2145a3c4d 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -320,7 +320,7 @@ void S_Shutdown () while (Channels != NULL) { - GSnd->StopSound(Channels); + S_StopChannel(Channels); } GSnd->UpdateSounds(); for (chan = FreeChannels; chan != NULL; chan = next) @@ -986,7 +986,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO } if (foundit) { - GSnd->StopSound(chan); + S_StopChannel(chan); break; } } @@ -1343,7 +1343,7 @@ void S_StopSound (int channel) if (chan->SourceType == SOURCE_None && (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) { - GSnd->StopSound(chan); + S_StopChannel(chan); } } } @@ -1367,7 +1367,7 @@ void S_StopSound (AActor *actor, int channel) chan->Actor == actor && (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) { - GSnd->StopSound(chan); + S_StopChannel(chan); } } } @@ -1389,7 +1389,7 @@ void S_StopSound (const sector_t *sec, int channel) chan->Sector == sec && (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) { - GSnd->StopSound(chan); + S_StopChannel(chan); } } } @@ -1410,7 +1410,7 @@ void S_StopSound (const FPolyObj *poly, int channel) chan->Poly == poly && (chan->EntChannel == channel || (i_compatflags & COMPATF_MAGICSILENCE))) { - GSnd->StopSound(chan); + S_StopChannel(chan); } } } @@ -1426,7 +1426,7 @@ void S_StopAllChannels () SN_StopAllSequences(); while (Channels != NULL) { - GSnd->StopSound(Channels); + S_StopChannel(Channels); } GSnd->UpdateSounds(); } @@ -1461,7 +1461,7 @@ void S_RelinkSound (AActor *from, AActor *to) } else { - GSnd->StopSound(chan); + S_StopChannel(chan); } } } @@ -1612,7 +1612,7 @@ void S_EvictAllChannels() chan->ChanFlags |= CHAN_EVICTED; if (chan->SysChannel != NULL) { - GSnd->StopSound(chan); + S_StopChannel(chan); } assert(chan->NextChan == next); } @@ -1755,6 +1755,125 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor) +//========================================================================== +// +// S_GetRolloff +// +//========================================================================== + +float S_GetRolloff(FRolloffInfo *rolloff, float distance) +{ + if (rolloff == NULL) + { + return 0; + } + + if (distance <= rolloff->MinDistance) + { + return 1; + } + if (rolloff->RolloffType == ROLLOFF_Log) + { // Logarithmic rolloff has no max distance where it goes silent. + return rolloff->MinDistance / (rolloff->MinDistance + rolloff->RolloffFactor * (distance - rolloff->MinDistance)); + } + if (distance >= rolloff->MaxDistance) + { + return 0; + } + + float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance); + if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve != NULL) + { + volume = S_SoundCurve[int(S_SoundCurveSize * (1 - volume))] / 127.f; + } + if (rolloff->RolloffType == ROLLOFF_Linear) + { + return volume; + } + else + { + return (powf(10.f, volume) - 1.f) / 9.f; + } +} + + +//========================================================================== +// +// S_ChannelEnded (callback for sound interface code) +// +//========================================================================== + +void S_ChannelEnded(FSoundChan *schan) +{ + bool evicted; + + if (schan != NULL) + { + // If the sound was stopped with GSnd->StopSound(), then we know + // it wasn't evicted. Otherwise, if it's looping, it must have + // been evicted. If it's not looping, then it was evicted if it + // didn't reach the end of its playback. + if (schan->ChanFlags & CHAN_FORGETTABLE) + { + evicted = false; + } + else if (schan->ChanFlags & (CHAN_LOOP | CHAN_EVICTED)) + { + evicted = true; + } + else + { + unsigned int pos = GSnd->GetPosition(schan); + unsigned int len = GSnd->GetSampleLength(schan->SfxInfo->data); + if (pos == 0) + { + evicted = !!(schan->ChanFlags & CHAN_JUSTSTARTED); + } + else if (pos < len) + { + evicted = true; + } + } + if (!evicted) + { + S_ReturnChannel(schan); + } + else + { + schan->ChanFlags |= CHAN_EVICTED; + schan->SysChannel = NULL; + } + } +} + +//========================================================================== +// +// S_StopChannel +// +//========================================================================== + +void S_StopChannel(FSoundChan *chan) +{ + if (chan == NULL) + return; + + if (chan->SysChannel != NULL) + { + // S_EvictAllChannels() will set the CHAN_EVICTED flag to indicate + // that it wants to keep all the channel information around. + if (!(chan->ChanFlags & CHAN_EVICTED)) + { + chan->ChanFlags |= CHAN_FORGETTABLE; + } + GSnd->StopChannel(chan); + } + else + { + S_ReturnChannel(chan); + } +} + + //========================================================================== // // (FArchive &) << (FSoundID &) diff --git a/src/s_sound.h b/src/s_sound.h index 7637c560c..6c84b0e07 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -210,6 +210,7 @@ FSoundChan *S_GetChannel(void *syschan); void S_ReturnChannel(FSoundChan *chan); void S_EvictAllChannels(); +void S_StopChannel(FSoundChan *chan); void S_LinkChannel(FSoundChan *chan, FSoundChan **head); void S_UnlinkChannel(FSoundChan *chan); diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 6b4882550..8286fe2c6 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -1616,25 +1616,12 @@ FSoundChan *FMODSoundRenderer::CommonChannelSetup(FMOD::Channel *chan, FSoundCha // //========================================================================== -void FMODSoundRenderer::StopSound(FSoundChan *chan) +void FMODSoundRenderer::StopChannel(FSoundChan *chan) { - if (chan == NULL) - return; - - if (chan->SysChannel != NULL) + if (chan != NULL && chan->SysChannel != NULL) { - // S_EvictAllChannels() will set the CHAN_EVICTED flag to indicate - // that it wants to keep all the channel information around. - if (!(chan->ChanFlags & CHAN_EVICTED)) - { - chan->ChanFlags |= CHAN_FORGETTABLE; - } ((FMOD::Channel *)chan->SysChannel)->stop(); } - else - { - S_ReturnChannel(chan); - } } //========================================================================== @@ -1995,6 +1982,26 @@ unsigned int FMODSoundRenderer::GetMSLength(SoundHandle sfx) } +//========================================================================== +// +// FMODSoundRenderer :: GetMSLength +// +//========================================================================== + +unsigned int FMODSoundRenderer::GetSampleLength(SoundHandle sfx) +{ + if (sfx.data != NULL) + { + unsigned int length; + + if (((FMOD::Sound *)sfx.data)->getLength(&length, FMOD_TIMEUNIT_PCM) == FMOD_OK) + { + return length; + } + } + return 0; // Don't know. +} + //========================================================================== // @@ -2014,58 +2021,7 @@ FMOD_RESULT F_CALLBACK FMODSoundRenderer::ChannelEndCallback if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL) { - bool evicted; - - // If the sound was stopped with GSnd->StopSound(), then we know - // it wasn't evicted. Otherwise, if it's looping, it must have - // been evicted. If it's not looping, then it was evicted if it - // didn't reach the end of its playback. - if (schan->ChanFlags & CHAN_FORGETTABLE) - { - evicted = false; - } - else if (schan->ChanFlags & (CHAN_LOOP | CHAN_EVICTED)) - { - evicted = true; - } - else - { - FMOD::Sound *sound; - unsigned int len, pos; - - evicted = false; // Assume not evicted - if (FMOD_OK == chan->getPosition(&pos, FMOD_TIMEUNIT_PCM)) - { - // If position is 0, then this sound either didn't have - // a chance to play at all, or it stopped normally. - if (pos == 0) - { - if (schan->ChanFlags & CHAN_JUSTSTARTED) - { - evicted = true; - } - } - else if (FMOD_OK == chan->getCurrentSound(&sound)) - { - if (FMOD_OK == sound->getLength(&len, FMOD_TIMEUNIT_PCM)) - { - if (pos < len) - { - evicted = true; - } - } - } - } - } - if (!evicted) - { - S_ReturnChannel(schan); - } - else - { - schan->ChanFlags |= CHAN_EVICTED; - schan->SysChannel = NULL; - } + S_ChannelEnded(schan); } return FMOD_OK; } @@ -2083,53 +2039,19 @@ float F_CALLBACK FMODSoundRenderer::RolloffCallback(FMOD_CHANNEL *channel, float { FMOD::Channel *chan = (FMOD::Channel *)channel; FSoundChan *schan; - FRolloffInfo *rolloff; if (GRolloff != NULL) { - rolloff = GRolloff; - distance *= GDistScale; + return S_GetRolloff(GRolloff, distance * GDistScale); } else if (chan->getUserData((void **)&schan) == FMOD_OK && schan != NULL) { - rolloff = &schan->Rolloff; - distance *= schan->DistanceScale; + return S_GetRolloff(&schan->Rolloff, distance * schan->DistanceScale); } else { return 0; } - if (rolloff == NULL) - { - return 0; - } - - if (distance <= rolloff->MinDistance) - { - return 1; - } - if (rolloff->RolloffType == ROLLOFF_Log) - { // Logarithmic rolloff has no max distance where it goes silent. - return rolloff->MinDistance / (rolloff->MinDistance + rolloff->RolloffFactor * (distance - rolloff->MinDistance)); - } - if (distance >= rolloff->MaxDistance) - { - return 0; - } - - float volume = (rolloff->MaxDistance - distance) / (rolloff->MaxDistance - rolloff->MinDistance); - if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve != NULL) - { - volume = S_SoundCurve[int(S_SoundCurveSize * (1 - volume))] / 127.f; - } - if (rolloff->RolloffType == ROLLOFF_Linear) - { - return volume; - } - else - { - return (powf(10.f, volume) - 1.f) / 9.f; - } } //========================================================================== diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 5c3061c1c..82d9cd733 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -17,6 +17,7 @@ public: SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits); void UnloadSound (SoundHandle sfx); unsigned int GetMSLength(SoundHandle sfx); + unsigned int GetSampleLength(SoundHandle sfx); float GetOutputRate(); // Streaming sounds. @@ -30,7 +31,7 @@ public: FSoundChan *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FSoundChan *reuse_chan); // Stops a sound channel. - void StopSound (FSoundChan *chan); + void StopChannel (FSoundChan *chan); // Returns position of sound on this channel, in samples. unsigned int GetPosition(FSoundChan *chan); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 7d5599769..84cd9a0ab 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -137,10 +137,17 @@ public: // ambient sounds to specify a default minimum period. return 250; } + unsigned int GetSampleLength(SoundHandle sfx) + { + return 0; + } float GetOutputRate() { return 11025; // Lies! } + void StopChannel(FSoundChan *chan) + { + } // Streaming sounds. SoundStream *CreateStream (SoundStreamCallback callback, int buffbytes, int flags, int samplerate, void *userdata) @@ -162,15 +169,6 @@ public: return NULL; } - // Stops a sound channel. - void StopSound (FSoundChan *chan) - { - if (chan != NULL) - { - S_ReturnChannel(chan); - } - } - // Returns position of sound on this channel, in samples. unsigned int GetPosition(FSoundChan *chan) { diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 3e5d6339c..e7fec1c32 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -96,6 +96,7 @@ public: virtual SoundHandle LoadSoundRaw(BYTE *sfxdata, int length, int frequency, int channels, int bits) = 0; virtual void UnloadSound (SoundHandle sfx) = 0; // unloads a sound from memory virtual unsigned int GetMSLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency + virtual unsigned int GetSampleLength(SoundHandle sfx) = 0; // Gets the length of a sound at its default frequency virtual float GetOutputRate() = 0; // Streaming sounds. @@ -107,7 +108,7 @@ public: virtual FSoundChan *StartSound3D (SoundHandle sfx, SoundListener *listener, float vol, FRolloffInfo *rolloff, float distscale, int pitch, int priority, const FVector3 &pos, const FVector3 &vel, int channum, int chanflags, FSoundChan *reuse_chan) = 0; // Stops a sound channel. - virtual void StopSound (FSoundChan *chan) = 0; + virtual void StopChannel (FSoundChan *chan) = 0; // Returns position of sound on this channel, in samples. virtual unsigned int GetPosition(FSoundChan *chan) = 0; @@ -141,4 +142,6 @@ extern SoundRenderer *GSnd; void I_InitSound (); void I_ShutdownSound (); +void S_ChannelEnded(FSoundChan *schan); +float S_GetRolloff(FRolloffInfo *rolloff, float distance); #endif