- RateEst: Add a convenient way of filtering measures that extend beyond a buffer time, and are as such

probably invalid.
- RateEst: Allow using a custom timestamp in feed().
- RateEst: Keep a queue of the last ~100 msec worth of samples and duration, and filter out collective
  samples that give a pre-estimate that seems way off.


git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@215 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
sinamas 2009-01-09 02:07:33 +00:00
parent d9edc2e78d
commit 351359802b
2 changed files with 75 additions and 19 deletions

View File

@ -19,6 +19,28 @@
#include "rateest.h"
#include <cstdlib>
void RateEst::SumQueue::reset() {
q.clear();
samples_ = usecs_ = 0;
}
void RateEst::SumQueue::push(const long samples, const usec_t usecs) {
q.push_back(pair_t(samples, usecs));
samples_ += samples;
usecs_ += usecs;
}
void RateEst::SumQueue::pop() {
const pair_t &f = q.front();
samples_ -= f.first;
usecs_ -= f.second;
q.pop_front();
}
static usec_t sampleUsecs(long samples, long rate) {
return static_cast<usec_t>((samples * 1000000.0f) / (rate ? rate : 1) + 0.5f);
}
static long limit(long est, const long reference) {
if (est > reference + (reference >> 6))
est = reference + (reference >> 6);
@ -28,7 +50,9 @@ static long limit(long est, const long reference) {
return est;
}
void RateEst::init(long srate, long reference) {
void RateEst::init(long srate, long reference, const long maxSamplePeriod) {
maxPeriod = sampleUsecs(maxSamplePeriod, reference);
srate <<= UPSHIFT;
reference <<= UPSHIFT;
@ -38,25 +62,35 @@ void RateEst::init(long srate, long reference) {
this->reference = reference;
samples = ((this->srate.est >> UPSHIFT) * 12) << 5;
usecs = 12000000 << 5;
sumq.reset();
}
void RateEst::feed(const long samplesIn) {
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;
void RateEst::feed(long samplesIn, const usec_t now) {
usec_t usecsIn = now - last;
if (last && usecsIn < maxPeriod) {
sumq.push(samplesIn, usecsIn);
while ((usecsIn = sumq.usecs()) > 100000) {
samplesIn = sumq.samples();
sumq.pop();
if (std::abs(static_cast<long>(samplesIn * (1000000.0f * UP) / usecsIn) - reference) < reference >> 1) {
samples += (samplesIn - sumq.samples()) << 5;
usecs += (usecsIn - sumq.usecs()) << 5;
long est = static_cast<long>(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;
}

View File

@ -20,6 +20,8 @@
#define RATEEST_H
#include "usec.h"
#include <deque>
#include <utility>
class RateEst {
public:
@ -29,12 +31,31 @@ public:
};
private:
class SumQueue {
typedef std::pair<long, usec_t> pair_t;
typedef std::deque<pair_t> q_t;
q_t q;
long samples_;
usec_t usecs_;
public:
SumQueue() : samples_(0), usecs_(0) {}
void reset();
long samples() const { return samples_; }
usec_t usecs() const { return usecs_; }
void push(long samples, usec_t usecs);
void pop();
};
enum { UPSHIFT = 5 };
enum { UP = 1 << UPSHIFT };
Result srate;
SumQueue sumq;
usec_t last;
usec_t usecs;
usec_t maxPeriod;
long reference;
long samples;
@ -42,9 +63,10 @@ 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 init(long srate, long reference) { init(srate, reference, reference); }
void init(long srate, long reference, long maxSamplePeriod);
void reset() { last = 0; }
void feed(long samples);
void feed(long samples, usec_t usecs = getusecs());
const Result result() const { const Result res = { (srate.est + UP / 2) >> UPSHIFT, (srate.var + UP / 2) >> UPSHIFT }; return res; }
};