Qt sound fix for integer frame rates. Now computes the proper expected number of samples per frame.
This commit is contained in:
parent
728a7c3580
commit
ebec5422bf
|
@ -131,6 +131,13 @@ ConsoleSndConfDialog_t::ConsoleSndConfDialog_t(QWidget *parent)
|
|||
|
||||
connect(bufSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(bufSizeChanged(int)));
|
||||
|
||||
bufUsage = new QProgressBar();
|
||||
bufUsage->setOrientation( Qt::Horizontal );
|
||||
bufUsage->setMinimum( 0 );
|
||||
bufUsage->setMaximum( 100 );
|
||||
bufUsage->setValue( 0 );
|
||||
vbox1->addWidget(bufUsage);
|
||||
|
||||
// Use Global Focus
|
||||
useGlobalFocus = new QCheckBox(tr("Use Global Focus"));
|
||||
useGlobalFocus->setToolTip( tr("Mute sound when window is not in focus") );
|
||||
|
@ -262,11 +269,16 @@ ConsoleSndConfDialog_t::ConsoleSndConfDialog_t(QWidget *parent)
|
|||
setLayout(mainLayout);
|
||||
|
||||
setSliderEnables();
|
||||
|
||||
updateTimer = new QTimer(this);
|
||||
connect( updateTimer, &QTimer::timeout, this, &ConsoleSndConfDialog_t::periodicUpdate );
|
||||
updateTimer->start(1000);
|
||||
}
|
||||
//----------------------------------------------------
|
||||
ConsoleSndConfDialog_t::~ConsoleSndConfDialog_t(void)
|
||||
{
|
||||
printf("Destroy Sound Config Window\n");
|
||||
updateTimer->stop();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
void ConsoleSndConfDialog_t::closeEvent(QCloseEvent *event)
|
||||
|
@ -284,6 +296,20 @@ void ConsoleSndConfDialog_t::closeWindow(void)
|
|||
deleteLater();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ConsoleSndConfDialog_t::periodicUpdate(void)
|
||||
{
|
||||
uint32_t c, m;
|
||||
double percBufUse;
|
||||
|
||||
c = GetWriteSound();
|
||||
m = GetMaxSound();
|
||||
|
||||
percBufUse = 100.0f - (100.0f * (double)c / (double)m );
|
||||
|
||||
bufUsage->setValue( (int)(percBufUse) );
|
||||
|
||||
}
|
||||
//----------------------------------------------------
|
||||
void ConsoleSndConfDialog_t::setSliderEnables(void)
|
||||
{
|
||||
// For now, always leave all sliders enabled.
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <QSlider>
|
||||
#include <QFrame>
|
||||
#include <QGroupBox>
|
||||
#include <QProgressBar>
|
||||
#include <QTimer>
|
||||
|
||||
class ConsoleSndConfDialog_t : public QDialog
|
||||
{
|
||||
|
@ -45,6 +47,8 @@ protected:
|
|||
QSlider *sqr2Slider;
|
||||
QSlider *nseSlider;
|
||||
QSlider *pcmSlider;
|
||||
QProgressBar *bufUsage;
|
||||
QTimer *updateTimer;
|
||||
|
||||
void setCheckBoxFromProperty(QCheckBox *cbx, const char *property);
|
||||
void setComboBoxFromProperty(QComboBox *cbx, const char *property);
|
||||
|
@ -53,6 +57,7 @@ protected:
|
|||
|
||||
private slots:
|
||||
void closeWindow(void);
|
||||
void periodicUpdate(void);
|
||||
void bufSizeChanged(int value);
|
||||
void volumeChanged(int value);
|
||||
void triangleChanged(int value);
|
||||
|
|
|
@ -721,6 +721,8 @@ void ConsoleVideoConfDialog_t::intFrameRate_changed( int value )
|
|||
|
||||
fceuWrapperLock();
|
||||
RefreshThrottleFPS();
|
||||
KillSound();
|
||||
InitSound();
|
||||
fceuWrapperUnLock();
|
||||
}
|
||||
//----------------------------------------------------
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
#include "common/configSys.h"
|
||||
#include "utils/memory.h"
|
||||
#include "nes_shm.h"
|
||||
#include "Qt/nes_shm.h"
|
||||
#include "Qt/throttle.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
@ -38,47 +39,106 @@ static unsigned int s_BufferSize;
|
|||
static unsigned int s_BufferRead;
|
||||
static unsigned int s_BufferWrite;
|
||||
static volatile unsigned int s_BufferIn;
|
||||
static unsigned int s_SampleRate = 44100;
|
||||
static double noiseGate = 0.0;
|
||||
static double noiseGateRate = 0.010;
|
||||
static bool noiseGateActive = true;
|
||||
|
||||
static int s_mute = 0;
|
||||
|
||||
extern int EmulationPaused;
|
||||
extern double frmRateAdjRatio;
|
||||
|
||||
/**
|
||||
* Callback from the SDL to get and play audio data.
|
||||
*/
|
||||
static void
|
||||
fillaudio(void *udata,
|
||||
uint8 *stream,
|
||||
int len)
|
||||
uint8 *stream,
|
||||
int len)
|
||||
{
|
||||
char bufStarveDetected = 0;
|
||||
static int16_t sample = 0;
|
||||
//unsigned int starve_lp = nes_shm->sndBuf.starveCounter;
|
||||
int16 *tmps = (int16*)stream;
|
||||
len >>= 1;
|
||||
while (len)
|
||||
|
||||
if ( EmulationPaused || noiseGateActive )
|
||||
{
|
||||
//int16 sample = 0;
|
||||
if (s_BufferIn)
|
||||
// This noise gate helps avoid abrupt snaps in audio
|
||||
// when pausing emulation.
|
||||
while (len)
|
||||
{
|
||||
sample = s_Buffer[s_BufferRead];
|
||||
s_BufferRead = (s_BufferRead + 1) % s_BufferSize;
|
||||
s_BufferIn--;
|
||||
} else {
|
||||
// Retain last known sample value, helps avoid clicking
|
||||
// noise when sound system is starved of audio data.
|
||||
//sample = 0;
|
||||
bufStarveDetected = 1;
|
||||
nes_shm->sndBuf.starveCounter++;
|
||||
if (EmulationPaused)
|
||||
{
|
||||
noiseGate -= noiseGateRate;
|
||||
|
||||
if ( noiseGate < 0.0 )
|
||||
{
|
||||
noiseGate = 0.0;
|
||||
}
|
||||
noiseGateActive = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( s_BufferIn )
|
||||
{
|
||||
noiseGate += noiseGateRate;
|
||||
|
||||
if ( noiseGate > 1.0 )
|
||||
{
|
||||
noiseGate = 1.0;
|
||||
noiseGateActive = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s_BufferIn)
|
||||
{
|
||||
sample = s_Buffer[s_BufferRead] * noiseGate;
|
||||
s_BufferRead = (s_BufferRead + 1) % s_BufferSize;
|
||||
s_BufferIn--;
|
||||
|
||||
*tmps = sample;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Retain last known sample value, helps avoid clicking
|
||||
// noise when sound system is starved of audio data.
|
||||
*tmps = sample * noiseGate;
|
||||
}
|
||||
|
||||
tmps++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len)
|
||||
{
|
||||
if (s_BufferIn)
|
||||
{
|
||||
sample = s_Buffer[s_BufferRead];
|
||||
s_BufferRead = (s_BufferRead + 1) % s_BufferSize;
|
||||
s_BufferIn--;
|
||||
} else {
|
||||
// Retain last known sample value, helps avoid clicking
|
||||
// noise when sound system is starved of audio data.
|
||||
//sample = 0;
|
||||
bufStarveDetected = 1;
|
||||
nes_shm->sndBuf.starveCounter++;
|
||||
}
|
||||
|
||||
nes_shm->push_sound_sample( sample );
|
||||
nes_shm->push_sound_sample( sample );
|
||||
|
||||
*tmps = sample;
|
||||
tmps++;
|
||||
len--;
|
||||
*tmps = sample;
|
||||
tmps++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
if ( bufStarveDetected )
|
||||
{
|
||||
//printf("Starve:%u\n", nes_shm->sndBuf.starveCounter );
|
||||
//s_StarveCounter = nes_shm->sndBuf.starveCounter - starve_lp;
|
||||
//printf("Starve:%u\n", s_StarveCounter );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,6 +151,7 @@ InitSound()
|
|||
int sound, soundrate, soundbufsize, soundvolume, soundtrianglevolume, soundsquare1volume, soundsquare2volume, soundnoisevolume, soundpcmvolume, soundq;
|
||||
SDL_AudioSpec spec;
|
||||
const char *driverName;
|
||||
int frmRateSampleAdj = 0;
|
||||
|
||||
g_config->getOption("SDL.Sound", &sound);
|
||||
if (!sound)
|
||||
|
@ -117,10 +178,11 @@ InitSound()
|
|||
g_config->getOption("SDL.Sound.NoiseVolume", &soundnoisevolume);
|
||||
g_config->getOption("SDL.Sound.PCMVolume", &soundpcmvolume);
|
||||
|
||||
spec.freq = soundrate;
|
||||
spec.freq = s_SampleRate = soundrate;
|
||||
spec.format = AUDIO_S16SYS;
|
||||
spec.channels = 1;
|
||||
spec.samples = 512;
|
||||
//spec.samples = 512;
|
||||
spec.samples = (int)( ( (double)s_SampleRate / getBaseFrameRate() ) );
|
||||
spec.callback = fillaudio;
|
||||
spec.userdata = 0;
|
||||
|
||||
|
@ -131,6 +193,9 @@ InitSound()
|
|||
{
|
||||
s_BufferSize = spec.samples * 2;
|
||||
}
|
||||
noiseGate = 0.0;
|
||||
noiseGateRate = 1.0 / (double)spec.samples;
|
||||
noiseGateActive = true;
|
||||
|
||||
s_Buffer = (int *)FCEU_dmalloc(sizeof(int) * s_BufferSize);
|
||||
|
||||
|
@ -145,7 +210,7 @@ InitSound()
|
|||
puts(SDL_GetError());
|
||||
KillSound();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
driverName = SDL_GetCurrentAudioDriver();
|
||||
|
@ -155,9 +220,13 @@ InitSound()
|
|||
fprintf(stderr, "Loading SDL sound with %s driver...\n", driverName);
|
||||
}
|
||||
|
||||
frmRateSampleAdj = (int)( ( ((double)soundrate) * getFrameRateAdjustmentRatio()) - ((double)soundrate) );
|
||||
//frmRateSampleAdj = 0;
|
||||
//printf("Sample Rate Adjustment: %+i\n", frmRateSampleAdj );
|
||||
|
||||
FCEUI_SetSoundVolume(soundvolume);
|
||||
FCEUI_SetSoundQuality(soundq);
|
||||
FCEUI_Sound(soundrate);
|
||||
FCEUI_Sound(soundrate + frmRateSampleAdj);
|
||||
FCEUI_SetTriangleVolume(soundtrianglevolume);
|
||||
FCEUI_SetSquare1Volume(soundsquare1volume);
|
||||
FCEUI_SetSquare2Volume(soundsquare2volume);
|
||||
|
|
|
@ -38,6 +38,8 @@ static const double Normal = 1.0; // 1x speed (around 60 fps on NTSC)
|
|||
static uint32 frameLateCounter = 0;
|
||||
static double Lasttime=0, Nexttime=0, Latetime=0;
|
||||
static double desired_frametime = (1.0 / 60.099823);
|
||||
static double desired_frameRate = (60.099823);
|
||||
static double baseframeRate = (60.099823);
|
||||
static double frameDeltaCur = 0.0;
|
||||
static double frameDeltaMin = 1.0;
|
||||
static double frameDeltaMax = 0.0;
|
||||
|
@ -53,6 +55,7 @@ static int InFrame = 0;
|
|||
double g_fpsScale = Normal; // used by sdl.cpp
|
||||
bool MaxSpeed = false;
|
||||
bool useIntFrameRate = false;
|
||||
static double frmRateAdjRatio = 1.000000f; // Frame Rate Adjustment Ratio
|
||||
|
||||
double getHighPrecTimeStamp(void)
|
||||
{
|
||||
|
@ -242,11 +245,23 @@ RefreshThrottleFPS(void)
|
|||
|
||||
hz = ( ((double)fps) / 16777216.0 );
|
||||
|
||||
desired_frametime = 1.0 / ( hz * g_fpsScale );
|
||||
|
||||
if ( useIntFrameRate )
|
||||
{
|
||||
hz = (double)( (int)(hz) );
|
||||
|
||||
frmRateAdjRatio = (1.0 / ( hz * g_fpsScale )) / desired_frametime;
|
||||
|
||||
printf("frameAdjRatio:%f \n", frmRateAdjRatio );
|
||||
}
|
||||
else
|
||||
{
|
||||
frmRateAdjRatio = 1.000000f;
|
||||
}
|
||||
desired_frametime = 1.0 / ( hz * g_fpsScale );
|
||||
desired_frameRate = ( hz * g_fpsScale );
|
||||
baseframeRate = hz;
|
||||
|
||||
T = (int32_t)( desired_frametime * 1000.0 );
|
||||
|
||||
|
@ -264,6 +279,21 @@ RefreshThrottleFPS(void)
|
|||
|
||||
}
|
||||
|
||||
double getBaseFrameRate(void)
|
||||
{
|
||||
return baseframeRate;
|
||||
}
|
||||
|
||||
double getFrameRate(void)
|
||||
{
|
||||
return desired_frameRate;
|
||||
}
|
||||
|
||||
double getFrameRateAdjustmentRatio(void)
|
||||
{
|
||||
return frmRateAdjRatio;
|
||||
}
|
||||
|
||||
int highPrecSleep( double timeSeconds )
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
|
@ -53,5 +53,8 @@ void setFrameTimingEnable( bool enable );
|
|||
int getFrameTimingStats( struct frameTimingStat_t *stats );
|
||||
void videoBufferSwapMark(void);
|
||||
double getHighPrecTimeStamp(void);
|
||||
double getFrameRate(void);
|
||||
double getFrameRateAdjustmentRatio(void);
|
||||
double getBaseFrameRate(void);
|
||||
|
||||
extern bool useIntFrameRate;
|
||||
|
|
Loading…
Reference in New Issue