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;
// apply frame scaling to Count
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. */
if(can > Count) can=Count;
else uflow=0;
#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); WriteSound(Buffer,Count);
}
else //int ocount = Count;
{ // apply frame scaling to Count
while(Count>0) //Count = (int)(Count / g_fpsScale);
{ //if (Count)
#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; // int32 can=GetWriteSound();
// while(tmpcan > 0) // static int uflow=0;
// { // int32 tmpcan;
// // printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
// // 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;
// #ifdef CREATE_AVI // #ifdef CREATE_AVI
// if (!mutecapture) // if (!mutecapture)
// #endif // #endif
// WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan); // WriteSound(Buffer,can);
// tmpcan -= Count;
// //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;
// } // }
//} //}
}
else
{
if (XBuf && (inited&4))
{
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,11 +262,80 @@ 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;
if ( uflowMode )
{ // Underflow mode
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;
}
}
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 (Count)
{ {
while (s_BufferIn == s_BufferSize) while (s_BufferIn == s_BufferSize)
@ -290,6 +360,40 @@ WriteSound(int32 *buf,
buf++; buf++;
} }
} }
else
{ // Overflow mode
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;
}
}
if ( skipCounter == 0 )
{
s_Buffer[s_BufferWrite] = *buf;
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
SDL_LockAudio();
s_BufferIn++;
SDL_UnlockAudio();
}
skipCounter = (skipCounter+1) % ovrFlowSkip;
Count--;
buf++;
}
}
}
}
} }
/** /**