annotate core/VirtualClock.cpp @ 150:ebbfb154351a ClockSync

Now leveraging BBB's lock between xenomai clock and audio clock for ultra-accurate, low-latency clocking. CAVEAT: fractions of samples drifts will occurr every time the clock is changed
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 22 Sep 2015 04:09:13 +0100
parents 134bff10e561
children 8f98b32d0e23
rev   line source
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 }