Changed Qt sound underflow/overflow so that it better scales with changing running faster or slower than realtime.

This commit is contained in:
mjbudd77 2021-08-07 10:24:37 -04:00
parent 301fb99a8a
commit 896af76167
2 changed files with 227 additions and 121 deletions

View File

@ -1005,120 +1005,122 @@ FCEUD_Update(uint8 *XBuf,
int blitDone = 0; int blitDone = 0;
//extern int FCEUDnetplay; //extern int FCEUDnetplay;
#ifdef CREATE_AVI //#ifdef CREATE_AVI
if (LoggingEnabled == 2 || (eoptions&EO_NOTHROTTLE)) //if (LoggingEnabled == 2 || (eoptions&EO_NOTHROTTLE))
{ //{
if(LoggingEnabled == 2) // if(LoggingEnabled == 2)
{ // {
int16* MonoBuf = new int16[Count]; // int16* MonoBuf = new int16[Count];
int n; // int n;
for(n=0; n<Count; ++n) // for(n=0; n<Count; ++n)
{ // {
MonoBuf[n] = Buffer[n] & 0xFFFF; // MonoBuf[n] = Buffer[n] & 0xFFFF;
} // }
NESVideoLoggingAudio // NESVideoLoggingAudio
( // (
MonoBuf, // MonoBuf,
FSettings.SndRate, 16, 1, // FSettings.SndRate, 16, 1,
Count // Count
); // );
delete [] MonoBuf; // delete [] MonoBuf;
} // }
Count /= 2; // Count /= 2;
if (inited & 1) // if (inited & 1)
{ // {
if (Count > GetWriteSound()) Count = GetWriteSound(); // if (Count > GetWriteSound()) Count = GetWriteSound();
if (!mutecapture) // if (!mutecapture)
{ // {
if(Count > 0 && Buffer) WriteSound(Buffer,Count); // if(Count > 0 && Buffer) WriteSound(Buffer,Count);
} // }
} // }
//if (inited & 2) // //if (inited & 2)
// FCEUD_UpdateInput(); // // FCEUD_UpdateInput();
if(XBuf && (inited & 4)) BlitScreen(XBuf); // if(XBuf && (inited & 4)) BlitScreen(XBuf);
//
return; // return;
} //}
#endif //#endif
aviRecordAddAudioFrame( Buffer, Count ); aviRecordAddAudioFrame( Buffer, Count );
int ocount = Count; WriteSound(Buffer,Count);
//int ocount = Count;
// apply frame scaling to Count // apply frame scaling to Count
Count = (int)(Count / g_fpsScale); //Count = (int)(Count / g_fpsScale);
if (Count) //if (Count)
{ //{
int32 can=GetWriteSound(); // int32 can=GetWriteSound();
static int uflow=0; // static int uflow=0;
int32 tmpcan; // int32 tmpcan;
// don't underflow when scaling fps // // don't underflow when scaling fps
if(can >= GetMaxSound() && g_fpsScale==1.0) uflow=1; /* Go into massive underflow mode. */ // if(can >= GetMaxSound() && g_fpsScale==1.0) uflow=1; /* Go into massive underflow mode. */
if(can > Count) can=Count; // if(can > Count) can=Count;
else uflow=0; // else uflow=0;
#ifdef CREATE_AVI // #ifdef CREATE_AVI
if (!mutecapture) // if (!mutecapture)
#endif // #endif
WriteSound(Buffer,can); // WriteSound(Buffer,can);
//if(uflow) puts("Underflow"); // //if(uflow) puts("Underflow");
tmpcan = GetWriteSound(); // tmpcan = GetWriteSound();
// don't underflow when scaling fps // // don't underflow when scaling fps
if (g_fpsScale>1.0 || ((tmpcan < Count*0.90) && !uflow)) // if (g_fpsScale>1.0 || ((tmpcan < Count*0.90) && !uflow))
{ // {
if (XBuf && (inited&4) && !(NoWaiting & 2)) // if (XBuf && (inited&4) && !(NoWaiting & 2))
{ // {
BlitScreen(XBuf); blitDone = 1; // BlitScreen(XBuf); blitDone = 1;
} // }
Buffer+=can; // Buffer+=can;
Count-=can; // Count-=can;
if(Count) // if(Count)
{ // {
if(NoWaiting) // if(NoWaiting)
{ // {
can=GetWriteSound(); // can=GetWriteSound();
if(Count>can) Count=can; // if(Count>can) Count=can;
#ifdef CREATE_AVI // #ifdef CREATE_AVI
if (!mutecapture) // if (!mutecapture)
#endif // #endif
WriteSound(Buffer,Count); // WriteSound(Buffer,Count);
} // }
else // else
{ // {
while(Count>0) // while(Count>0)
{ // {
#ifdef CREATE_AVI // #ifdef CREATE_AVI
if (!mutecapture) // if (!mutecapture)
#endif // #endif
WriteSound(Buffer,(Count<ocount) ? Count : ocount); // WriteSound(Buffer,(Count<ocount) ? Count : ocount);
Count -= ocount; // Count -= ocount;
} // }
} // }
} // }
} //else puts("Skipped"); // } //else puts("Skipped");
//else if (!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8))) // //else if (!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8)))
//{ // //{
// if (Count > tmpcan) Count=tmpcan; // // if (Count > tmpcan) Count=tmpcan;
// while(tmpcan > 0) // // while(tmpcan > 0)
// { // // {
// // printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan); // // // printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
// #ifdef CREATE_AVI // // #ifdef CREATE_AVI
// if (!mutecapture) // // if (!mutecapture)
// #endif // // #endif
// WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan); // // WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan);
// tmpcan -= Count; // // tmpcan -= Count;
// } // // }
//} // //}
} //}
else //else
{ //{
if (XBuf && (inited&4)) // if (XBuf && (inited&4))
{ // {
BlitScreen(XBuf); blitDone = 1; // BlitScreen(XBuf); blitDone = 1;
} // }
} //}
if ( !blitDone ) if ( !blitDone )
{ {
if (XBuf && (inited&4)) if (XBuf && (inited&4))

View File

@ -48,6 +48,7 @@ static int s_mute = 0;
extern int EmulationPaused; extern int EmulationPaused;
extern double frmRateAdjRatio; extern double frmRateAdjRatio;
extern double g_fpsScale;
/** /**
* Callback from the SDL to get and play audio data. * Callback from the SDL to get and play audio data.
@ -261,33 +262,136 @@ void
WriteSound(int32 *buf, WriteSound(int32 *buf,
int Count) 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; extern int EmulationPaused;
if (EmulationPaused == 0) if (EmulationPaused == 0)
{ {
int waitCount = 0; int waitCount = 0;
while(Count) if ( uflowMode )
{ { // Underflow mode
while(s_BufferIn == s_BufferSize) while (Count)
{ {
SDL_Delay(1); waitCount++; while (s_BufferIn == s_BufferSize)
if ( waitCount > 1000 )
{ {
printf("Error: Sound sink is not draining... Breaking out of audio loop to prevent lockup.\n"); SDL_Delay(1); waitCount++;
return;
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; if ( waitCount > 1000 )
Count--; {
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize; 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(); SDL_LockAudio();
s_BufferIn++; s_BufferIn++;
SDL_UnlockAudio(); SDL_UnlockAudio();
}
skipCounter = (skipCounter+1) % ovrFlowSkip;
buf++; Count--;
buf++;
}
}
} }
} }
} }