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;
//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))

View File

@ -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++;
}
}
}
}
}