#include <boost/thread/lock_guard.hpp>
#include "time_postprocessor.h"
#include "api_config.h"
#include <cmath>
using namespace lsl;
time_postprocessor::time_postprocessor(const postproc_callback_t &query_correction, const postproc_callback_t &query_srate, const reset_callback_t &query_reset):
samples_seen_(0.0), query_srate_(query_srate), options_(proc_none), halftime_(api_config::get_instance()->smoothing_halftime()),
query_correction_(query_correction), query_reset_(query_reset), next_query_time_(0.0), last_offset_(0.0),
smoothing_initialized_(false), last_value_(-std::numeric_limits<double>::infinity())
{
}
double time_postprocessor::process_timestamp(double value) {
if (options_ & proc_threadsafe) {
lslboost::lock_guard<lslboost::mutex> lock(processing_mut_);
return process_internal(value);
} else
return process_internal(value);
}
double time_postprocessor::process_internal(double value) {
if (options_ & proc_clocksync) {
if ((fmod(samples_seen_,50.0) == 0.0) && lsl_clock() > next_query_time_) {
last_offset_ = query_correction_();
if (query_reset_()) {
last_offset_ = query_correction_();
last_value_ = -std::numeric_limits<double>::infinity();
samples_seen_ = 0;
smoothing_initialized_ = false;
}
next_query_time_ = lsl_clock()+0.5;
}
value += last_offset_;
}
if (options_ & proc_dejitter) {
if (!smoothing_initialized_) {
double srate = query_srate_();
smoothing_applicable_ = (srate > 0.0);
if (smoothing_applicable_) {
w0_ = 0.0;
w1_ = 1.0/srate;
lam_ = pow(2.0, -1.0/(srate*halftime_));
il_ = 1.0/lam_;
P00_ = P11_ = 1e10; P01_ = P10_ = 0.0;
baseline_value_ = value;
}
smoothing_initialized_ = true;
}
if (smoothing_applicable_) {
value -= baseline_value_;
double u1 = samples_seen_; double pi0 = P00_ + u1*P10_; double pi1 = P01_ + u1*P11_; double al = value - w0_ - w1_ * u1; double gam = lam_ + pi0 + pi1 * u1; P00_ = il_ * (P00_ - ((pi0*pi0)/gam)); P01_ = il_ * (P01_ - ((pi0*pi1)/gam)); P10_ = il_ * (P10_ - ((pi1*pi0)/gam)); P11_ = il_ * (P11_ - ((pi1*pi1)/gam)); w0_ += al * (P00_ + P10_ * u1); w1_ += al * (P01_ + P11_ * u1); value = w0_ + w1_*u1;
value += baseline_value_;
}
}
if (options_ & proc_monotonize) {
if (value < last_value_)
value = last_value_;
}
samples_seen_ += 1.0;
last_value_ = value;
return value;
}