- 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)
This commit is contained in:
Randy Heit 2009-11-18 04:45:20 +00:00
parent 424c6e8963
commit 51eb6465a2
7 changed files with 61 additions and 5 deletions

View file

@ -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.

View file

@ -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)

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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)
{

View file

@ -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;

View file

@ -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;
};