giuliomoro@135
|
1 #include "VirtualClock.h"
|
giuliomoro@149
|
2 void VirtualClock::init(float initialValueUs){
|
giuliomoro@135
|
3 firstRun=true;
|
giuliomoro@141
|
4 movingAverage.setLength(101); //TODO: a better filtering algorithm ( Did you say Kalman?)
|
giuliomoro@149
|
5 blockPeriod=-1;
|
giuliomoro@141
|
6 elapsedPeriods=0;
|
giuliomoro@141
|
7 startTime=0;
|
giuliomoro@149
|
8 elapsedPeriodsOffset = 0;
|
giuliomoro@149
|
9 lastSyncEstimatedTime = 0;
|
giuliomoro@149
|
10 double coefficients[IIR_FILTER_STAGE_COEFFICIENTS] = {
|
giuliomoro@149
|
11 0.000241359049041961, 0.000482718098083923, 0.000241359049041961, -1.95557824031504, 0.956543676511203
|
giuliomoro@149
|
12 };
|
giuliomoro@150
|
13 double states[4];
|
giuliomoro@150
|
14 for(int n = 0; n < 4; n++){
|
giuliomoro@150
|
15 states[n] = initialValueUs;
|
giuliomoro@150
|
16 }
|
giuliomoro@150
|
17 iir.setNumberOfStages(2);
|
giuliomoro@149
|
18 iir.setCoefficients(coefficients);
|
giuliomoro@150
|
19 iir.setStates(states);
|
giuliomoro@150
|
20 // printf("kalmanInit=%f\n",initialValueUs);
|
giuliomoro@150
|
21 // kalman.init(0.01, 158575.715009816 /*measured var() */, initialValueUs);
|
giuliomoro@150
|
22 kalman.init(10, 1588.715009816 /*measured var() */, initialValueUs);
|
giuliomoro@135
|
23 }
|
giuliomoro@135
|
24
|
giuliomoro@149
|
25 VirtualClock::VirtualClock(){}
|
giuliomoro@135
|
26 void VirtualClock::sync(){
|
giuliomoro@135
|
27 sync(1);
|
giuliomoro@135
|
28 }
|
giuliomoro@150
|
29
|
giuliomoro@141
|
30 void VirtualClock::sync(double numPeriods){
|
giuliomoro@149
|
31 myClock_t currentTime = Clock::getTimeUs();
|
giuliomoro@149
|
32 elapsedPeriods += numPeriods;
|
giuliomoro@149
|
33 static int calls = 0;
|
giuliomoro@149
|
34 if(calls == 0){
|
giuliomoro@149
|
35 startTime = currentTime;
|
giuliomoro@149
|
36 lastSyncEstimatedTime = 0;
|
giuliomoro@149
|
37 } else {
|
giuliomoro@149
|
38 double newBlockPeriod = (currentTime - lastSyncTime);
|
giuliomoro@150
|
39 #ifdef USE_JUCE
|
giuliomoro@149
|
40 blockPeriod = iir.process(kalman.process(newBlockPeriod));
|
giuliomoro@150
|
41 #else
|
giuliomoro@150
|
42 // this leverages the fact that on the Beaglebone the audio clock
|
giuliomoro@150
|
43 // is synced to the xenomai clock.
|
giuliomoro@150
|
44 // CAVEAT: we are actually drifting by fractions of a sample everytime
|
giuliomoro@150
|
45 // there is a clock adjustment because we do not know exactly at what point
|
giuliomoro@150
|
46 // time the clock change actually takes place
|
giuliomoro@150
|
47 // Avoiding this would actually require a redesign and would anyhow produce overall
|
giuliomoro@150
|
48 // less accurate results.
|
giuliomoro@150
|
49 blockPeriod = numPeriods/gAudioCodec->getAudioSamplingRate()*1e6;
|
giuliomoro@150
|
50 #endif /* USE_JUCE */
|
giuliomoro@150
|
51 // printf("%f %f\n", blockPeriod, newBlockPeriod);
|
giuliomoro@149
|
52 period = blockPeriod / numPeriods;
|
giuliomoro@149
|
53 lastSyncEstimatedTime += (period * numPeriods);
|
giuliomoro@141
|
54 }
|
giuliomoro@149
|
55 lastSyncTime = currentTime;
|
giuliomoro@149
|
56 // printf("%lld\n", lastSyncTime);
|
giuliomoro@141
|
57 calls++;
|
giuliomoro@135
|
58 }
|
giuliomoro@135
|
59
|
giuliomoro@135
|
60 double VirtualClock::getNow(){
|
giuliomoro@139
|
61 myClock_t currentSystemTime=Clock::getTimeUs();
|
giuliomoro@149
|
62 if(blockPeriod<=0){
|
giuliomoro@141
|
63 return currentSystemTime; // TODO: this is not very meaningful.
|
giuliomoro@135
|
64 }
|
giuliomoro@149
|
65 double elapsed = (currentSystemTime - startTime) - lastSyncEstimatedTime;
|
giuliomoro@149
|
66 double now = elapsedPeriods + elapsed / (double)period;
|
giuliomoro@149
|
67 // if(now>currentSystemTime+10*1e6)
|
giuliomoro@149
|
68 // now=0;
|
giuliomoro@149
|
69 // static long long int pastSy=0;
|
giuliomoro@149
|
70 // printf("%lld\n", currentSystemTime-pastSy);
|
giuliomoro@149
|
71 // pastSy=currentSystemTime;
|
giuliomoro@149
|
72 static int count=0;
|
giuliomoro@149
|
73 count++;
|
giuliomoro@149
|
74 // if(count&1)
|
giuliomoro@149
|
75 #ifdef USE_JUCE
|
giuliomoro@149
|
76 #else
|
giuliomoro@149
|
77 // printf("%f %f %f\n", (currentSystemTime - startTime)/1e6*44100.0, blockPeriod, now);
|
giuliomoro@149
|
78 #endif
|
giuliomoro@139
|
79 return now;
|
giuliomoro@135
|
80 }
|
giuliomoro@135
|
81
|
giuliomoro@141
|
82 void VirtualClock::addOffset(double periodOffset){
|
giuliomoro@141
|
83 elapsedPeriods-=periodOffset;
|
giuliomoro@141
|
84 if(elapsedPeriods<0){
|
giuliomoro@141
|
85 printf("ERROR: periodOffset adjustment of %f resulted in elapsedPeriods=%f\n", periodOffset, elapsedPeriods);
|
giuliomoro@141
|
86 exit(1);
|
giuliomoro@141
|
87 }
|
giuliomoro@141
|
88 movingAverage.reset();
|
giuliomoro@141
|
89 }
|
giuliomoro@135
|
90 double VirtualClock::getPeriod(){
|
giuliomoro@149
|
91 return blockPeriod;
|
giuliomoro@135
|
92 }
|