attempt to compensate for scheduling jitter
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include "TimingData.h"
|
#include "TimingData.h"
|
||||||
#include "NotesLoaderSM.h"
|
#include "NotesLoaderSM.h"
|
||||||
#include "PrefsManager.h"
|
#include "PrefsManager.h"
|
||||||
|
#include "RageDisplay.h"
|
||||||
|
|
||||||
RageSounds *SOUND = NULL;
|
RageSounds *SOUND = NULL;
|
||||||
|
|
||||||
@@ -308,6 +309,41 @@ RageSounds::~RageSounds()
|
|||||||
delete g_Mutex;
|
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 )
|
void RageSounds::Update( float fDeltaTime )
|
||||||
{
|
{
|
||||||
@@ -316,6 +352,8 @@ void RageSounds::Update( float fDeltaTime )
|
|||||||
if( !g_UpdatingTimer )
|
if( !g_UpdatingTimer )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const float fAdjust = GetFrameTimingAdjustment( fDeltaTime );
|
||||||
|
|
||||||
if( !g_Playing->m_Music->IsPlaying() )
|
if( !g_Playing->m_Music->IsPlaying() )
|
||||||
{
|
{
|
||||||
/* There's no song playing. Fake it. */
|
/* There's no song playing. Fake it. */
|
||||||
@@ -367,7 +405,7 @@ void RageSounds::Update( float fDeltaTime )
|
|||||||
}
|
}
|
||||||
|
|
||||||
CHECKPOINT_M( ssprintf("%f", fSeconds) );
|
CHECKPOINT_M( ssprintf("%f", fSeconds) );
|
||||||
GAMESTATE->UpdateSongPosition( fSeconds, g_Playing->m_Timing, tm );
|
GAMESTATE->UpdateSongPosition( fSeconds+fAdjust, g_Playing->m_Timing, tm+fAdjust );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user