Changed Qt sound underflow/overflow so that it better scales with changing running faster or slower than realtime.
This commit is contained in:
parent
301fb99a8a
commit
896af76167
|
@ -1005,120 +1005,122 @@ FCEUD_Update(uint8 *XBuf,
|
|||
int blitDone = 0;
|
||||
//extern int FCEUDnetplay;
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
if (LoggingEnabled == 2 || (eoptions&EO_NOTHROTTLE))
|
||||
{
|
||||
if(LoggingEnabled == 2)
|
||||
{
|
||||
int16* MonoBuf = new int16[Count];
|
||||
int n;
|
||||
for(n=0; n<Count; ++n)
|
||||
{
|
||||
MonoBuf[n] = Buffer[n] & 0xFFFF;
|
||||
}
|
||||
NESVideoLoggingAudio
|
||||
(
|
||||
MonoBuf,
|
||||
FSettings.SndRate, 16, 1,
|
||||
Count
|
||||
);
|
||||
delete [] MonoBuf;
|
||||
}
|
||||
Count /= 2;
|
||||
if (inited & 1)
|
||||
{
|
||||
if (Count > GetWriteSound()) Count = GetWriteSound();
|
||||
//#ifdef CREATE_AVI
|
||||
//if (LoggingEnabled == 2 || (eoptions&EO_NOTHROTTLE))
|
||||
//{
|
||||
// if(LoggingEnabled == 2)
|
||||
// {
|
||||
// int16* MonoBuf = new int16[Count];
|
||||
// int n;
|
||||
// for(n=0; n<Count; ++n)
|
||||
// {
|
||||
// MonoBuf[n] = Buffer[n] & 0xFFFF;
|
||||
// }
|
||||
// NESVideoLoggingAudio
|
||||
// (
|
||||
// MonoBuf,
|
||||
// FSettings.SndRate, 16, 1,
|
||||
// Count
|
||||
// );
|
||||
// delete [] MonoBuf;
|
||||
// }
|
||||
// Count /= 2;
|
||||
// if (inited & 1)
|
||||
// {
|
||||
// if (Count > GetWriteSound()) Count = GetWriteSound();
|
||||
|
||||
if (!mutecapture)
|
||||
{
|
||||
if(Count > 0 && Buffer) WriteSound(Buffer,Count);
|
||||
}
|
||||
}
|
||||
//if (inited & 2)
|
||||
// FCEUD_UpdateInput();
|
||||
if(XBuf && (inited & 4)) BlitScreen(XBuf);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// if (!mutecapture)
|
||||
// {
|
||||
// if(Count > 0 && Buffer) WriteSound(Buffer,Count);
|
||||
// }
|
||||
// }
|
||||
// //if (inited & 2)
|
||||
// // FCEUD_UpdateInput();
|
||||
// if(XBuf && (inited & 4)) BlitScreen(XBuf);
|
||||
//
|
||||
// return;
|
||||
//}
|
||||
//#endif
|
||||
aviRecordAddAudioFrame( Buffer, Count );
|
||||
|
||||
int ocount = Count;
|
||||
WriteSound(Buffer,Count);
|
||||
|
||||
//int ocount = Count;
|
||||
// apply frame scaling to Count
|
||||
Count = (int)(Count / g_fpsScale);
|
||||
if (Count)
|
||||
{
|
||||
int32 can=GetWriteSound();
|
||||
static int uflow=0;
|
||||
int32 tmpcan;
|
||||
//Count = (int)(Count / g_fpsScale);
|
||||
//if (Count)
|
||||
//{
|
||||
// int32 can=GetWriteSound();
|
||||
// static int uflow=0;
|
||||
// int32 tmpcan;
|
||||
|
||||
// don't underflow when scaling fps
|
||||
if(can >= GetMaxSound() && g_fpsScale==1.0) uflow=1; /* Go into massive underflow mode. */
|
||||
// // don't underflow when scaling fps
|
||||
// if(can >= GetMaxSound() && g_fpsScale==1.0) uflow=1; /* Go into massive underflow mode. */
|
||||
|
||||
if(can > Count) can=Count;
|
||||
else uflow=0;
|
||||
// if(can > Count) can=Count;
|
||||
// else uflow=0;
|
||||
|
||||
#ifdef CREATE_AVI
|
||||
if (!mutecapture)
|
||||
#endif
|
||||
WriteSound(Buffer,can);
|
||||
// #ifdef CREATE_AVI
|
||||
// if (!mutecapture)
|
||||
// #endif
|
||||
// WriteSound(Buffer,can);
|
||||
|
||||
//if(uflow) puts("Underflow");
|
||||
tmpcan = GetWriteSound();
|
||||
// don't underflow when scaling fps
|
||||
if (g_fpsScale>1.0 || ((tmpcan < Count*0.90) && !uflow))
|
||||
{
|
||||
if (XBuf && (inited&4) && !(NoWaiting & 2))
|
||||
{
|
||||
BlitScreen(XBuf); blitDone = 1;
|
||||
}
|
||||
Buffer+=can;
|
||||
Count-=can;
|
||||
if(Count)
|
||||
{
|
||||
if(NoWaiting)
|
||||
{
|
||||
can=GetWriteSound();
|
||||
if(Count>can) Count=can;
|
||||
#ifdef CREATE_AVI
|
||||
if (!mutecapture)
|
||||
#endif
|
||||
WriteSound(Buffer,Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
while(Count>0)
|
||||
{
|
||||
#ifdef CREATE_AVI
|
||||
if (!mutecapture)
|
||||
#endif
|
||||
WriteSound(Buffer,(Count<ocount) ? Count : ocount);
|
||||
Count -= ocount;
|
||||
}
|
||||
}
|
||||
}
|
||||
} //else puts("Skipped");
|
||||
//else if (!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8)))
|
||||
//{
|
||||
// if (Count > tmpcan) Count=tmpcan;
|
||||
// while(tmpcan > 0)
|
||||
// {
|
||||
// // printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
|
||||
// #ifdef CREATE_AVI
|
||||
// if (!mutecapture)
|
||||
// #endif
|
||||
// WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan);
|
||||
// tmpcan -= Count;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (XBuf && (inited&4))
|
||||
{
|
||||
BlitScreen(XBuf); blitDone = 1;
|
||||
}
|
||||
}
|
||||
// //if(uflow) puts("Underflow");
|
||||
// tmpcan = GetWriteSound();
|
||||
// // don't underflow when scaling fps
|
||||
// if (g_fpsScale>1.0 || ((tmpcan < Count*0.90) && !uflow))
|
||||
// {
|
||||
// if (XBuf && (inited&4) && !(NoWaiting & 2))
|
||||
// {
|
||||
// BlitScreen(XBuf); blitDone = 1;
|
||||
// }
|
||||
// Buffer+=can;
|
||||
// Count-=can;
|
||||
// if(Count)
|
||||
// {
|
||||
// if(NoWaiting)
|
||||
// {
|
||||
// can=GetWriteSound();
|
||||
// if(Count>can) Count=can;
|
||||
// #ifdef CREATE_AVI
|
||||
// if (!mutecapture)
|
||||
// #endif
|
||||
// WriteSound(Buffer,Count);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// while(Count>0)
|
||||
// {
|
||||
// #ifdef CREATE_AVI
|
||||
// if (!mutecapture)
|
||||
// #endif
|
||||
// WriteSound(Buffer,(Count<ocount) ? Count : ocount);
|
||||
// Count -= ocount;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } //else puts("Skipped");
|
||||
// //else if (!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8)))
|
||||
// //{
|
||||
// // if (Count > tmpcan) Count=tmpcan;
|
||||
// // while(tmpcan > 0)
|
||||
// // {
|
||||
// // // printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
|
||||
// // #ifdef CREATE_AVI
|
||||
// // if (!mutecapture)
|
||||
// // #endif
|
||||
// // WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan);
|
||||
// // tmpcan -= Count;
|
||||
// // }
|
||||
// //}
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// if (XBuf && (inited&4))
|
||||
// {
|
||||
// BlitScreen(XBuf); blitDone = 1;
|
||||
// }
|
||||
//}
|
||||
if ( !blitDone )
|
||||
{
|
||||
if (XBuf && (inited&4))
|
||||
|
|
|
@ -48,6 +48,7 @@ static int s_mute = 0;
|
|||
|
||||
extern int EmulationPaused;
|
||||
extern double frmRateAdjRatio;
|
||||
extern double g_fpsScale;
|
||||
|
||||
/**
|
||||
* Callback from the SDL to get and play audio data.
|
||||
|
@ -261,33 +262,136 @@ void
|
|||
WriteSound(int32 *buf,
|
||||
int Count)
|
||||
{
|
||||
|
||||
int uflowMode = 0;
|
||||
int ovrFlowSkip = 1;
|
||||
int udrFlowDup = 1;
|
||||
static int skipCounter = 0;
|
||||
|
||||
if ( g_fpsScale >= 0.90 )
|
||||
{
|
||||
uflowMode = 0;
|
||||
ovrFlowSkip = (int)(g_fpsScale);
|
||||
|
||||
if ( ovrFlowSkip < 1 )
|
||||
{
|
||||
ovrFlowSkip = 1;
|
||||
}
|
||||
if ( s_BufferIn >= (s_BufferSize/2) )
|
||||
{
|
||||
ovrFlowSkip++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
udrFlowDup = (int)(1.0 / g_fpsScale);
|
||||
|
||||
if ( udrFlowDup < 1 )
|
||||
{
|
||||
udrFlowDup = 1;
|
||||
}
|
||||
if ( s_BufferIn <= (s_BufferSize/2) )
|
||||
{
|
||||
udrFlowDup++;
|
||||
}
|
||||
uflowMode = (udrFlowDup > 1);
|
||||
}
|
||||
extern int EmulationPaused;
|
||||
if (EmulationPaused == 0)
|
||||
{
|
||||
int waitCount = 0;
|
||||
|
||||
while(Count)
|
||||
{
|
||||
while(s_BufferIn == s_BufferSize)
|
||||
if ( uflowMode )
|
||||
{ // Underflow mode
|
||||
while (Count)
|
||||
{
|
||||
SDL_Delay(1); waitCount++;
|
||||
|
||||
if ( waitCount > 1000 )
|
||||
while (s_BufferIn == s_BufferSize)
|
||||
{
|
||||
printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n");
|
||||
return;
|
||||
SDL_Delay(1); waitCount++;
|
||||
|
||||
if ( waitCount > 1000 )
|
||||
{
|
||||
printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<udrFlowDup; i++)
|
||||
{
|
||||
s_Buffer[s_BufferWrite] = *buf;
|
||||
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
|
||||
|
||||
SDL_LockAudio();
|
||||
s_BufferIn++;
|
||||
SDL_UnlockAudio();
|
||||
}
|
||||
|
||||
Count--;
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ovrFlowSkip == 1 )
|
||||
{ // Perfect one to one realtime
|
||||
skipCounter = 0;
|
||||
|
||||
while (Count)
|
||||
{
|
||||
while (s_BufferIn == s_BufferSize)
|
||||
{
|
||||
SDL_Delay(1); waitCount++;
|
||||
|
||||
if ( waitCount > 1000 )
|
||||
{
|
||||
printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
s_Buffer[s_BufferWrite] = *buf;
|
||||
Count--;
|
||||
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
|
||||
|
||||
SDL_LockAudio();
|
||||
s_BufferIn++;
|
||||
SDL_UnlockAudio();
|
||||
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Overflow mode
|
||||
while (Count)
|
||||
{
|
||||
while (s_BufferIn == s_BufferSize)
|
||||
{
|
||||
SDL_Delay(1); waitCount++;
|
||||
|
||||
s_Buffer[s_BufferWrite] = *buf;
|
||||
Count--;
|
||||
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
|
||||
if ( waitCount > 1000 )
|
||||
{
|
||||
printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( skipCounter == 0 )
|
||||
{
|
||||
s_Buffer[s_BufferWrite] = *buf;
|
||||
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
|
||||
|
||||
SDL_LockAudio();
|
||||
s_BufferIn++;
|
||||
SDL_UnlockAudio();
|
||||
SDL_LockAudio();
|
||||
s_BufferIn++;
|
||||
SDL_UnlockAudio();
|
||||
}
|
||||
skipCounter = (skipCounter+1) % ovrFlowSkip;
|
||||
|
||||
buf++;
|
||||
Count--;
|
||||
buf++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue