- 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:
parent
d9edc2e78d
commit
351359802b
@ -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;
|
||||
}
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user