attempt to compensate for scheduling jitter

This commit is contained in:
Glenn Maynard
2004-03-01 09:01:23 +00:00
parent 69f5527450
commit 3b14d5b8a5
+39 -1
View File
@@ -8,6 +8,7 @@
#include "TimingData.h"
#include "NotesLoaderSM.h"
#include "PrefsManager.h"
#include "RageDisplay.h"
RageSounds *SOUND = NULL;
@@ -308,6 +309,41 @@ RageSounds::~RageSounds()
delete g_Mutex;
}
static float GetFrameTimingAdjustment( float fDeltaTime )
{
/*
* We get one update per frame, and we're updated early, almost immediately after vsync,
* near the beginning of the game loop. However, it's very likely that we'll lose the
* scheduler while waiting for vsync, and some other thread will be working. Especially
* with a low-resolution scheduler (Linux 2.4, Win9x), we may not get the scheduler back
* immediately after the vsync; there may be up to a ~10ms delay. This can cause jitter
* in the rendered arrows.
*
* Compensate. If vsync is enabled, and we're maintaining the refresh rate consistently,
* we should have a very precise game loop interval. If we have that, but we're off by
* a small amount (less than the interval), adjust the time to line it up. As long as we
* adjust both the sound time and the timestamp, this won't adversely affect input timing.
* If we're off by more than that, we probably had a frame skip, in which case we have
* bigger skip problems, so don't adjust.
*/
static int iLastFPS = 0;
int iThisFPS = DISPLAY->GetFPS();
if( iThisFPS != DISPLAY->GetVideoModeParams().rate || iThisFPS != iLastFPS )
{
iLastFPS = iThisFPS;
return 0;
}
const float fExpectedDelay = 1.0f / iThisFPS;
const float fExtraDelay = fDeltaTime - fExpectedDelay;
if( fabsf(fExtraDelay) >= fExpectedDelay )
return 0;
/* Subtract the extra delay. (We might have delayed too little, in which case we'll return
* a positive number; this is normal.) */
return -fExtraDelay;
}
void RageSounds::Update( float fDeltaTime )
{
@@ -316,6 +352,8 @@ void RageSounds::Update( float fDeltaTime )
if( !g_UpdatingTimer )
return;
const float fAdjust = GetFrameTimingAdjustment( fDeltaTime );
if( !g_Playing->m_Music->IsPlaying() )
{
/* There's no song playing. Fake it. */
@@ -367,7 +405,7 @@ void RageSounds::Update( float fDeltaTime )
}
CHECKPOINT_M( ssprintf("%f", fSeconds) );
GAMESTATE->UpdateSongPosition( fSeconds, g_Playing->m_Timing, tm );
GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, g_Playing->m_Timing, tm+fAdjust );
}