comparison core/ClockSync.cpp @ 152:8f98b32d0e23 ClockSync

Last commit on this branch for a while. Overall not very succesful
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 05 Oct 2015 13:06:14 +0100
parents e9c9404e3d1f
children
comparison
equal deleted inserted replaced
151:e9c9404e3d1f 152:8f98b32d0e23
1 #include "ClockSync.h" 1 #include "ClockSync.h"
2 2
3 void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){ 3 void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){
4 virtualClock=&aVirtualClock; 4 virtualClock=&aVirtualClock;
5 } 5 }
6 Pid* gClockSyncPid;
6 void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){ 7 void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){
7 setVirtualClock(aVirtualClock); 8 setVirtualClock(aVirtualClock);
8 slave=thisIsSlave; 9 slave=thisIsSlave;
9 setPort(aPort); 10 setPort(aPort);
10 // isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1"); 11 // isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1");
13 resetTs(); 14 resetTs();
14 receiveLoopSleepUs=100; 15 receiveLoopSleepUs=100;
15 receiveLoopTimeout=1e5; 16 receiveLoopTimeout=1e5;
16 movingAverage.setLength(31); 17 movingAverage.setLength(31);
17 expectedClockSyncType=isSlave() ? kSync : kNone; 18 expectedClockSyncType=isSlave() ? kSync : kNone;
19 gClockSyncPid = &pid;
18 } 20 }
19 void ClockSync::resetTs(){ 21 void ClockSync::resetTs(){
20 T1=-1; 22 T1=-1;
21 T1p=-1; 23 T1p=-1;
22 T2=-1; 24 T2=-1;
213 expectedClockSyncType=kDelayResp; 215 expectedClockSyncType=kDelayResp;
214 break; 216 break;
215 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless 217 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless
216 T2p=clockSyncTimestamp; 218 T2p=clockSyncTimestamp;
217 //TODO: evaluate things 219 //TODO: evaluate things
218 double offset=(T1p-T1-T2p+T2)/2.0d;
219 if(areTsValid()){ 220 if(areTsValid()){
220 processOffset(offset); 221 offset = (T1p-T1-T2p+T2)/2.0d;
221 222 processOffset();
222 /*
223 static int calls=0;
224 static double referenceOffset=0;
225
226 if(calls<100){ // start by averaging everything
227 movingAverage.add(offset);
228 } else { //once we get an estimate, start discarding outliers
229 float maxOffsetDeviation=20;
230 float deviation=fabsf(movingAverage.getAverage()-offset);
231 if(deviation<maxOffsetDeviation){
232 movingAverage.add(offset);
233 printf("w(end+1)=%4.1f;\n", movingAverage.getAverage());
234 } else {
235 // printf("Out of range: %f \n", deviation);
236 }
237 }
238 printf("offset(end+1)=%f;\n", offset);
239 if (calls==100){
240 // printf("Update reference\n");
241 referenceOffset=movingAverage.getAverage();
242 } else if (calls==200){
243 calls=99;
244 }
245 calls++;
246 */
247
248 // printf("%lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p);
249 // if(T2-T1p<0){
250 // printf("Negative: %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p);
251 // }
252 } else { 223 } else {
253 printf("InvalidTs:\n %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); 224 printf("InvalidTs:\n %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p);
254 } 225 }
255 expectedClockSyncType=kSync; //end of the cycle, wait for next sync. 226 expectedClockSyncType=kSync; //end of the cycle, wait for next sync.
256 break; 227 break;
259 //printf("Unexpected message type\n"); // we should never get here 230 //printf("Unexpected message type\n"); // we should never get here
260 return -1; 231 return -1;
261 } 232 }
262 return 1; 233 return 1;
263 } 234 }
264 void ClockSync::processOffset(double offset){ 235 void ClockSync::processOffset(){
265 static int calls=0; 236 static int calls=0;
266 // TODO: change the flow control below so that it can happen multiple times 237 // TODO: change the flow control below so that it can happen multiple times
267 //(base it upon the length of movingAverage rather than the number of calls) 238 //(base it upon the length of movingAverage rather than the number of calls)
268 if(calls<30){ 239 if(calls<30){
269 // wait for the VirtualClock to stabilize and produce meaningful outputs 240 // wait for the VirtualClock to stabilize and produce meaningful outputs
278 } else if (calls>50){ //use IIR filter from now on 249 } else if (calls>50){ //use IIR filter from now on
279 //filter coefficients obtained from Matlab : [B,A]=butter(2,0.005); 250 //filter coefficients obtained from Matlab : [B,A]=butter(2,0.005);
280 static IirFilter iir(1); 251 static IirFilter iir(1);
281 static bool init = false; 252 static bool init = false;
282 if(init == false){ 253 if(init == false){
254 //cutoff 0.05
283 // double coeffs[5]={0.00554271721028068, 0.0110854344205614, 0.00554271721028068, 255 // double coeffs[5]={0.00554271721028068, 0.0110854344205614, 0.00554271721028068,
284 // -1.77863177782459, 0.800802646665708}; 256 // -1.77863177782459, 0.800802646665708};
285 double coeffs[5]={0.0200833655642113, 0.0401667311284225, 0.0200833655642113, 257 //cutoff 0.015
286 -1.56101807580072, 0.641351538057563}; 258 double coeffs[5]={0.000537169774812052, 0.0010743395496241, 0.000537169774812052,
259 -1.93338022587993, 0.935528904979178};
260 // double coeffs[5]={0.0200833655642113, 0.0401667311284225, 0.0200833655642113,
261 // -1.56101807580072, 0.641351538057563};
287 iir.setCoefficients(coeffs); 262 iir.setCoefficients(coeffs);
288 init = true; 263 init = true;
289 } 264 }
290 float expectedOffsetDifferenceMean = 0.2432; 265 float expectedOffsetDifferenceMean = 0.2432;
291 float expectedOffsetDifferenceStd = 6.487; 266 float expectedOffsetDifference = 3.5;
292 float nlOffset; 267 static float pastNlOffset = 0;
293 static float pastOffset = 0; 268 static float pastIncrement = 0;
294 float offsetIncrement = offset-pastOffset; 269 float offsetIncrement = offset-pastNlOffset;
295 if ( fabsf(offsetIncrement) > 1*expectedOffsetDifferenceStd && calls>51){ 270 static int filteredOut=0;
271 if (calls>51 && (fabsf(offsetIncrement) > expectedOffsetDifference && filteredOut < 8)){
296 // non-linear filtering: remove outliers 272 // non-linear filtering: remove outliers
297 nlOffset = pastOffset; 273 nlOffset = pastNlOffset;
274 // printf("this actually happened\n");
275 //nlOffset=offset; // BYPASS non linear filter
298 // printf("%f %f 0,0,0,0,0,0\n", offset,pastOffset); 276 // printf("%f %f 0,0,0,0,0,0\n", offset,pastOffset);
277 filteredOut++;
299 } else { 278 } else {
300 nlOffset=offset; 279 nlOffset=offset;
301 } 280 filteredOut = 0;
302 pastOffset=nlOffset; 281 }
303 float iirOffset = iir.process(nlOffset); 282 pastIncrement = nlOffset - pastNlOffset;
283 pastNlOffset = nlOffset;
284 iirOffset = iir.process(nlOffset);
304 static float maxOffset=0; 285 static float maxOffset=0;
305 static float pastIirOffset=0; 286 static float pastIirOffset=0;
306 if( calls > 0 ) { 287 if( calls > 0 ) {
307 maxOffset=fabsf(iirOffset) > fabsf(maxOffset) ? iirOffset : maxOffset; 288 maxOffset=fabsf(iirOffset) > fabsf(maxOffset) ? iirOffset : maxOffset;
308 pid.setError(iirOffset); 289 pid.setError(iirOffset);
309 float correction=pid.getOutput()*0.0001; 290 float correction=pid.getOutput();
310 static float oldSamplingRate=44100; 291 static float oldSamplingRate=44100;
311 printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n", 292 if( (calls&0) == 0){
312 offset, nlOffset, iirOffset, iirOffset - pastIirOffset, correction, oldSamplingRate); //unfiltered, filtered 293 printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n",
294 offset, nlOffset, iirOffset, iirOffset - pastIirOffset,
295 pid.getProportionalGain(), pid.getIntegralGain(), pid.getDerivativeGain(), pid.getGlobalGain(),
296 correction, pid.getIntegralError(), oldSamplingRate); //unfiltered, filtered
297 }
313 pastIirOffset = iirOffset; 298 pastIirOffset = iirOffset;
314 float targetSamplingRate; 299 float targetSamplingRate;
300 // Applit PID
301 targetSamplingRate = oldSamplingRate - correction;
302 if(targetSamplingRate> 44110) //clip the Pid !
303 targetSamplingRate = 44110;
304 if (targetSamplingRate < 44090)
305 targetSamplingRate = 44090;
306
307 // or use a naive hysteresis comparator
315 static int direction=1; 308 static int direction=1;
316 float thresholdL = -1; 309 float thresholdL = -1;
317 // targetSamplingRate = oldSamplingRate - correction;
318 float thresholdH = 3; 310 float thresholdH = 3;
319
320 targetSamplingRate = 44100; 311 targetSamplingRate = 44100;
321 if( 312 if(
322 (iirOffset > thresholdH && direction == 1) || 313 (iirOffset > thresholdH && direction == 1) ||
323 (iirOffset > thresholdL && direction == -1) 314 (iirOffset > thresholdL && direction == -1)
324 ){ 315 ){
328 else if ( 319 else if (
329 (iirOffset < -thresholdH && direction == -1) || 320 (iirOffset < -thresholdH && direction == -1) ||
330 (iirOffset < -thresholdL && direction == 1) 321 (iirOffset < -thresholdL && direction == 1)
331 ) 322 )
332 { 323 {
333 iirOffset = 44102; 324 iirOffset = 44103;
334 direction = 1; 325 direction = 1;
335 } 326 }
336 #ifndef USE_JUCE 327 #ifndef USE_JUCE
337 if(oldSamplingRate != targetSamplingRate){ 328 if(oldSamplingRate != targetSamplingRate){
338 gAudioCodec->setAudioSamplingRate(targetSamplingRate); 329 gAudioCodec->setAudioSamplingRate(targetSamplingRate);
360 351
361 int ClockSync::sendReceiveLoop(){ 352 int ClockSync::sendReceiveLoop(){
362 if(isSlave()==true){ 353 if(isSlave()==true){
363 //printf("Waiting for a sync clockSync\n"); 354 //printf("Waiting for a sync clockSync\n");
364 } else { //if this is master 355 } else { //if this is master
365 usleep(30000); //this times (roughly) how often sync clockSyncs are being sent. 356 usleep(10000); //this times (roughly) how often sync clockSyncs are being sent.
366 int ret=masterSendSync(); 357 int ret=masterSendSync();
367 if(ret<=0) 358 if(ret<=0)
368 return -1; 359 return -1;
369 } 360 }
370 int ret=receiveLoop(); 361 int ret=receiveLoop();
371 if(ret<=0) 362 if(ret<=0)
372 return -2; 363 return -2;
373 return 1; 364 return 1;
374 } 365 }
375 366
376 367 float ClockSync::getOffset(){
368 return offset;
369 }
370 float ClockSync::getIirOffset(){
371 return iirOffset;
372 }