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