From 51eb6465a2b87645ac39e7431aaa82adfb546bc1 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 18 Nov 2009 04:45:20 +0000 Subject: [PATCH] - Fixed two bugs in FMODSoundRenderer::HandleChannelDelay(): * Looping sounds that have been playing for a very long time, were evicted, and then were restarted need to have their positions clamped to lie within the bounds of the sounds. If we try to set a start position very far beyond the end, it will overflow inside FMOD and not work. * A start time of 0 is not actually valid and means the sound was never assigned a start time. - The latter bug also reveals a problem with starting looped sounds evicted: They need to be assigned a start time so if they should have the opportunity to start later, they will be properly synchronized. SVN r1987 (trunk) --- docs/rh-log.txt | 12 ++++++++++++ src/s_sound.cpp | 1 + src/sound/fmodsound.cpp | 34 +++++++++++++++++++++++++++++++++- src/sound/fmodsound.h | 3 +++ src/sound/i_sound.cpp | 7 ++++++- src/sound/i_sound.h | 3 +++ src/v_video.h | 6 +++--- 7 files changed, 61 insertions(+), 5 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 48abfcc2c..79ea15408 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,15 @@ +November 17, 2009 +- Fixed two bugs in FMODSoundRenderer::HandleChannelDelay(): + * Looping sounds that have been playing for a very long time, were evicted, + and then were restarted need to have their positions clamped to lie + within the bounds of the sounds. If we try to set a start position very + far beyond the end, it will overflow inside FMOD and not work. + * A start time of 0 is not actually valid and means the sound was never + assigned a start time. +- The latter bug also reveals a problem with starting looped sounds evicted: + They need to be assigned a start time so if they should have the opportunity + to start later, they will be properly synchronized. + November 17, 2009 (Changes by Graf Zahl) - fixed: P_NowayTraverse was called with a trace distance of 128 instead of the 64 that should have been used. diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 1287873a5..4fbef6ae1 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1053,6 +1053,7 @@ static FSoundChan *S_StartSound(AActor *actor, const sector_t *sec, const FPolyO if (chan == NULL && (chanflags & CHAN_LOOP)) { chan = (FSoundChan*)S_GetChannel(NULL); + GSnd->MarkStartTime(chan); chanflags |= CHAN_EVICTED; } if (attenuation > 0) diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 724d701fe..e278563a6 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -1650,6 +1650,10 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener * } if (!HandleChannelDelay(chan, reuse_chan, flags & (SNDF_ABSTIME | SNDF_LOOP), freq)) { + // FMOD seems to get confused if you stop a channel right after + // starting it, so hopefully this function will never fail. + // (Presumably you need an update between them, but I haven't + // tested this hypothesis.) chan->stop(); return NULL; } @@ -1674,6 +1678,19 @@ FISoundChannel *FMODSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener * return 0; } +//========================================================================== +// +// FMODSoundRenderer :: MarkStartTime +// +// Marks a channel's start time without actually playing it. +// +//========================================================================== + +void FMODSoundRenderer::MarkStartTime(FISoundChannel *chan) +{ + Sys->getDSPClock(&chan->StartTime.Hi, &chan->StartTime.Lo); +} + //========================================================================== // // FMODSoundRenderer :: HandleChannelDelay @@ -1704,11 +1721,26 @@ bool FMODSoundRenderer::HandleChannelDelay(FMOD::Channel *chan, FISoundChannel * } reuse_chan->StartTime.AsOne = QWORD(nowtime.AsOne - seekpos * OutputRate / freq); } - else + else if (reuse_chan->StartTime.AsOne != 0) { QWORD difftime = nowtime.AsOne - reuse_chan->StartTime.AsOne; if (difftime > 0) { + // Clamp the position of looping sounds to be within the sound. + // If we try to start it several minutes past its normal end, + // FMOD doesn't like that. + if (flags & SNDF_LOOP) + { + FMOD::Sound *sound; + if (FMOD_OK == chan->getCurrentSound(&sound)) + { + unsigned int len; + if (FMOD_OK == sound->getLength(&len, FMOD_TIMEUNIT_MS)) + { + difftime %= len; + } + } + } return chan->setPosition((unsigned int)(difftime / OutputRate), FMOD_TIMEUNIT_MS) == FMOD_OK; } } diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 78ba8aa86..3f31481bf 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -33,6 +33,9 @@ public: // Stops a sound channel. void StopChannel (FISoundChannel *chan); + // Marks a channel's start time without actually playing it. + void MarkStartTime (FISoundChannel *chan); + // Returns position of sound on this channel, in samples. unsigned int GetPosition(FISoundChannel *chan); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index c4b0c63e0..0009b48e2 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -159,7 +159,7 @@ public: return NULL; } - // Starts a sound. (No, not really.) + // Starts a sound. FISoundChannel *StartSound (SoundHandle sfx, float vol, int pitch, int chanflags, FISoundChannel *reuse_chan) { return NULL; @@ -169,6 +169,11 @@ public: return NULL; } + // Marks a channel's start time without actually playing it. + void MarkStartTime (FISoundChannel *chan) + { + } + // Returns position of sound on this channel, in samples. unsigned int GetPosition(FISoundChannel *chan) { diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index 1ff535d93..31f401093 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -109,6 +109,9 @@ public: // Stops a sound channel. virtual void StopChannel (FISoundChannel *chan) = 0; + // Marks a channel's start time without actually playing it. + virtual void MarkStartTime (FISoundChannel *chan) = 0; + // Returns position of sound on this channel, in samples. virtual unsigned int GetPosition(FISoundChannel *chan) = 0; diff --git a/src/v_video.h b/src/v_video.h index 69af12ada..e722c62db 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -232,7 +232,7 @@ public: uint32 fillcolor; FRemapTable *remap; const BYTE *translation; - DWORD colorOverlay; + uint32 colorOverlay; INTBOOL alphaChannel; INTBOOL flipX; fixed_t shadowAlpha; @@ -404,7 +404,7 @@ public: virtual bool WipeDo(int ticks); virtual void WipeCleanup(); - DWORD GetLastFPS() const { return LastCount; } + uint32 GetLastFPS() const { return LastCount; } #ifdef _WIN32 virtual void PaletteChanged () = 0; @@ -418,7 +418,7 @@ protected: DFrameBuffer () {} private: - DWORD LastMS, LastSec, FrameCount, LastCount, LastTic; + uint32 LastMS, LastSec, FrameCount, LastCount, LastTic; };