Substantially improved rate estimation averaging.

git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@204 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
sinamas 2008-12-25 23:45:53 +00:00
parent cbf173e0a8
commit c69e48ac80
5 changed files with 48 additions and 41 deletions

View File

@ -36,26 +36,27 @@ void RateEst::init(long srate, long reference) {
this->srate.var = srate >> 12;
last = 0;
this->reference = reference;
samples = 0;
count = 1;
samples = ((this->srate.est >> UPSHIFT) * 12) << 5;
usecs = 12000000 << 5;
}
void RateEst::feed(const long samplesIn) {
samples += samplesIn;
if (--count == 0) {
count = 32;
const usec_t now = getusecs();
if (last) {
long est = samples * (1000000.0f * UP) / (now - last) + 0.5f;
est = limit((srate.est * 31 + est + 16) >> 5, reference);
srate.var = (srate.var * 15 + std::abs(est - srate.est) + 8) >> 4;
srate.est = est;
const usec_t now = getusecs();
if (last) {
samples += samplesIn << 5;
usecs += (now - last) << 5;
long est = samples * (1000000.0f * UP) / usecs + 0.5f;
est = limit((srate.est * 31 + est + 16) >> 5, reference);
srate.var = (srate.var * 15 + std::abs(est - srate.est) + 8) >> 4;
srate.est = est;
if (usecs > 16000000 << 5) {
samples = (samples * 3 + 2) >> 2;
usecs = (usecs * 3 + 2) >> 2;
}
last = now;
samples = 0;
}
last = now;
}

View File

@ -34,16 +34,16 @@ private:
Result srate;
usec_t last;
usec_t usecs;
long reference;
long samples;
unsigned count;
public:
RateEst(long srate = 0) { init(srate); }
RateEst(long srate, long reference) { init(srate, reference); }
void init(long srate) { init(srate, srate); }
void init(long srate, long reference);
void reset() { count = 1; last = 0; }
void reset() { last = 0; }
void feed(long samples);
const Result result() const { const Result res = { (srate.est + UP / 2) >> UPSHIFT, (srate.var + UP / 2) >> UPSHIFT }; return res; }
};

View File

@ -20,31 +20,37 @@
#include <adaptivesleep.h>
#include <cstdlib>
static long limit(long est, const long ref) {
if (est > ref + (ref >> 5))
est = ref + (ref >> 5);
else if (est < ref - (ref >> 5))
est = ref - (ref >> 5);
return est;
}
void FtEst::init(const long frameTime) {
this->frameTime = frameTime;
ft = 0;
ftAvg = frameTime << COUNT_LOG2;
ft = 4500000 << 6;
ftAvg = frameTime << UPSHIFT;
ftVar = ftAvg >> 12;
last = 0;
count = COUNT;
count = (ft + (frameTime >> 1)) / (frameTime ? frameTime : 1);
}
void FtEst::update(const usec_t t) {
if (t - last < static_cast<unsigned long>(frameTime + (frameTime >> 3))) {
ft += t - last;
if (--count == 0) {
count = COUNT;
long oldFtAvg = ftAvg;
ftAvg = (ftAvg * 15 + ft + 8) >> 4;
if (ftAvg > ((frameTime + (frameTime >> 5)) << COUNT_LOG2))
ftAvg = (frameTime + (frameTime >> 5)) << COUNT_LOG2;
else if (ftAvg < ((frameTime - (frameTime >> 5)) << COUNT_LOG2))
ftAvg = (frameTime - (frameTime >> 5)) << COUNT_LOG2;
ftVar = (ftVar * 15 + std::abs(ftAvg - oldFtAvg) + 8) >> 4;
ft = 0;
ft += (t - last) << 6;
count += 1 << 6;
long ftAvgNew = static_cast<long>(static_cast<float>(ft) * UP / count + 0.5f);
ftAvgNew = limit((ftAvg * 31 + ftAvgNew + 16) >> 5, frameTime << UPSHIFT);
ftVar = (ftVar * 15 + std::abs(ftAvgNew - ftAvg) + 8) >> 4;
ftAvg = ftAvgNew;
if (ft > (6000000 << 6)) {
ft = (ft * 3 + 2) >> 2;
count = (count * 3 + 2) >> 2;
}
}

View File

@ -28,8 +28,8 @@
class QHBoxLayout;
class FtEst {
enum { COUNT_LOG2 = 4 };
enum { COUNT = 1 << COUNT_LOG2 };
enum { UPSHIFT= 5 };
enum { UP = 1 << UPSHIFT };
long frameTime;
long ft;
@ -42,8 +42,8 @@ public:
FtEst(long frameTime = 0) { init(frameTime); }
void init(long frameTime);
void update(usec_t t);
long est() const { return (ftAvg + COUNT / 2) >> COUNT_LOG2; }
long var() const { return (ftVar + COUNT / 2) >> COUNT_LOG2; }
long est() const { return (ftAvg + UP / 2) >> UPSHIFT; }
long var() const { return (ftVar + UP / 2) >> UPSHIFT; }
};
class BlitterWidget : public QWidget {

View File

@ -552,7 +552,7 @@ void MainWindow::timerEvent(QTimerEvent */*event*/) {
if (estft.est) {
float est = static_cast<float>(rsrate.est) * estft.est;
const float var = static_cast<float>(rsrate.est + rsrate.var) * (estft.est + estft.var) - est;
const float var = static_cast<float>(rsrate.est + (rsrate.var ? rsrate.var : 1)) * (estft.est + (estft.var ? estft.var : 1)) - est;
est += var;
if (std::fabs(est - resampler->outRate() * static_cast<float>(usecft - (usecft >> 11))) > var * 2)