00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "libavutil/mem.h"
00026 #include "config.h"
00027 #include "timefilter.h"
00028
00029 struct TimeFilter {
00032 double cycle_time;
00033 double feedback2_factor;
00034 double feedback3_factor;
00035 double clock_period;
00036 int count;
00037 };
00038
00039
00040 static double qexpneg(double x)
00041 {
00042 return 1 - 1 / (1 + x * (1 + x / 2 * (1 + x / 3)));
00043 }
00044
00045 TimeFilter *ff_timefilter_new(double time_base,
00046 double period,
00047 double bandwidth)
00048 {
00049 TimeFilter *self = av_mallocz(sizeof(TimeFilter));
00050 double o = 2 * M_PI * bandwidth * period * time_base;
00051 self->clock_period = time_base;
00052 self->feedback2_factor = qexpneg(M_SQRT2 * o);
00053 self->feedback3_factor = qexpneg(o * o) / period;
00054 return self;
00055 }
00056
00057 void ff_timefilter_destroy(TimeFilter *self)
00058 {
00059 av_freep(&self);
00060 }
00061
00062 void ff_timefilter_reset(TimeFilter *self)
00063 {
00064 self->count = 0;
00065 }
00066
00067 double ff_timefilter_update(TimeFilter *self, double system_time, double period)
00068 {
00069 self->count++;
00070 if (self->count == 1) {
00072 self->cycle_time = system_time;
00073 } else {
00074 double loop_error;
00075 self->cycle_time += self->clock_period * period;
00077 loop_error = system_time - self->cycle_time;
00078
00080 self->cycle_time += FFMAX(self->feedback2_factor, 1.0 / self->count) * loop_error;
00081 self->clock_period += self->feedback3_factor * loop_error;
00082 }
00083 return self->cycle_time;
00084 }
00085
00086 double ff_timefilter_eval(TimeFilter *self, double delta)
00087 {
00088 return self->cycle_time + self->clock_period * delta;
00089 }
00090
00091 #ifdef TEST
00092 #include "libavutil/lfg.h"
00093 #define LFG_MAX ((1LL << 32) - 1)
00094
00095 #undef printf
00096
00097 int main(void)
00098 {
00099 AVLFG prng;
00100 double n0, n1;
00101 #define SAMPLES 1000
00102 double ideal[SAMPLES];
00103 double samples[SAMPLES];
00104 double samplet[SAMPLES];
00105 #if 1
00106 for (n0 = 0; n0 < 40; n0 = 2 * n0 + 1) {
00107 for (n1 = 0; n1 < 10; n1 = 2 * n1 + 1) {
00108 #else
00109 {
00110 {
00111 n0 = 7;
00112 n1 = 1;
00113 #endif
00114 double best_error = 1000000000;
00115 double bestpar0 = 1;
00116 double bestpar1 = 1;
00117 int better, i;
00118
00119 av_lfg_init(&prng, 123);
00120 for (i = 0; i < SAMPLES; i++) {
00121 samplet[i] = 10 + i + (av_lfg_get(&prng) < LFG_MAX/2 ? 0 : 0.999);
00122 ideal[i] = samplet[i] + n1 * i / (1000);
00123 samples[i] = ideal[i] + n0 * (av_lfg_get(&prng) - LFG_MAX / 2) / (LFG_MAX * 10LL);
00124 if(i && samples[i]<samples[i-1])
00125 samples[i]=samples[i-1]+0.001;
00126 }
00127
00128 do {
00129 double par0, par1;
00130 better = 0;
00131 for (par0 = bestpar0 * 0.8; par0 <= bestpar0 * 1.21; par0 += bestpar0 * 0.05) {
00132 for (par1 = bestpar1 * 0.8; par1 <= bestpar1 * 1.21; par1 += bestpar1 * 0.05) {
00133 double error = 0;
00134 TimeFilter *tf = ff_timefilter_new(1, par0, par1);
00135 for (i = 0; i < SAMPLES; i++) {
00136 double filtered;
00137 filtered = ff_timefilter_update(tf, samples[i], i ? (samplet[i] - samplet[i-1]) : 1);
00138 if(filtered < 0 || filtered > 1000000000)
00139 printf("filter is unstable\n");
00140 error += (filtered - ideal[i]) * (filtered - ideal[i]);
00141 }
00142 ff_timefilter_destroy(tf);
00143 if (error < best_error) {
00144 best_error = error;
00145 bestpar0 = par0;
00146 bestpar1 = par1;
00147 better = 1;
00148 }
00149 }
00150 }
00151 } while (better);
00152 #if 0
00153 double lastfil = 9;
00154 TimeFilter *tf = ff_timefilter_new(1, bestpar0, bestpar1);
00155 for (i = 0; i < SAMPLES; i++) {
00156 double filtered;
00157 filtered = ff_timefilter_update(tf, samples[i], 1);
00158 printf("%f %f %f %f\n", i - samples[i] + 10, filtered - samples[i],
00159 samples[FFMAX(i, 1)] - samples[FFMAX(i - 1, 0)], filtered - lastfil);
00160 lastfil = filtered;
00161 }
00162 ff_timefilter_destroy(tf);
00163 #else
00164 printf(" [%f %f %9f]", bestpar0, bestpar1, best_error);
00165 #endif
00166 }
00167 printf("\n");
00168 }
00169 return 0;
00170 }
00171 #endif