changeset 133:04b1678614c9 scope-refactoring

Using moving average for clock detection during synchronization seems to be working better but audio gets worse and worse
author Giulio Moro <giuliomoro@yahoo.it>
date Thu, 27 Aug 2015 03:33:32 +0100
parents e24c531220ee
children e77e2e712fbc
files core/ClockSynchronizer.cpp core/ReceiveAudioThread.cpp projects/scope/render.cpp
diffstat 3 files changed, 43 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/core/ClockSynchronizer.cpp	Thu Aug 27 01:42:04 2015 +0100
+++ b/core/ClockSynchronizer.cpp	Thu Aug 27 03:33:32 2015 +0100
@@ -22,13 +22,13 @@
 }
 
 void ClockSynchronizer::setClock(){
-	rt_printf("Setting clock to %f\n",targetSamplingRate);
+//	rt_printf("Setting clock to %f\n",targetSamplingRate);
 	threadRunning=true;
 //I2C magic
 	gAudioCodec->setAudioSamplingRate(targetSamplingRate);
 	threadRunning=false;
-	threadWasRunning=3;
-	rt_printf("Exiting thread\n");
+	threadWasRunning=1;
+//	rt_printf("Exiting thread\n");
 };
 
 ClockSynchronizer::ClockSynchronizer() {
@@ -93,22 +93,44 @@
 	// Should also try to avoid drastic correction after a while that the program
 	// has started, so to avoid glitches. But this can maybe be handled by the thread itself.
 	// TODO: should keep a log and maybe compensate for (and prevent) overshoot according to previous changes
-	rt_printf("lastTime: %llu, remoteCounter: %d\n", lastTime, remoteCounter);
-
+	static RTIME lastlastTime=0;
+//	rt_printf("interval: %f, \n",(double)(remoteCounter*300.0)/lastTime*1000000000.0);
+	lastlastTime=lastTime;
 	currentSamplingRate=gAudioCodec->getAudioSamplingRate();
 	float T=1/currentSamplingRate;
 	int elapsedSamples=remoteCounter*(NetworkBuffer::bufferLength-NetworkBuffer::headerLength);
 	double expectedTimeUs=T*elapsedSamples*1000000;
+	double actualTimeS=lastTime/1000000000.0;
 	double actualTimeUs=lastTime/1000.0;
-	targetSamplingRate=expectedTimeUs/actualTimeUs*currentSamplingRate;
+	static float averageBuffer[101]={0};
+	static int averageBufferPointer=0;
+	static float average=0;
+	static int bufferFull=0;
+	average-=averageBuffer[averageBufferPointer];
+	averageBuffer[averageBufferPointer]=elapsedSamples/actualTimeS;
+	average+=averageBuffer[averageBufferPointer];
+	averageBufferPointer++;
+	if(averageBufferPointer==101){
+		averageBufferPointer=0;
+		bufferFull++;
+	}
+
 //	rt_printf("Fs: %f, expectedTimeUs: %f, lastTime: %ul\n", expectedTimeUs, lastTime);
-	rt_printf("Fs: %.1f, expectedTimeUs: %4.3f, actualTimeUs: %4.3f, targetFs_ %.3f\n",
-			gAudioCodec->getAudioSamplingRate(), expectedTimeUs/elapsedSamples, actualTimeUs/elapsedSamples, targetSamplingRate);
-	adjustClock();
+//	rt_printf("Fs: %.1f, actualTimeS: %4.6f, targetFs_ %.3f\n",
+	if((averageBufferPointer&3)==0){
+		static float oldTargetSamplingRate=0;
+		targetSamplingRate=average/101;
+		if(bufferFull>=3 && fabsf(targetSamplingRate-oldTargetSamplingRate) < 1){
+			rt_printf("%.1f, %4.6f, %.3f;\n",
+				gAudioCodec->getAudioSamplingRate(),  actualTimeS, targetSamplingRate, targetSamplingRate-oldTargetSamplingRate);
+			adjustClock();
+		}
+		oldTargetSamplingRate=targetSamplingRate;
+	}
 }
 
 void ClockSynchronizer::adjustClock(){
-	if(currentSamplingRate!= targetSamplingRate){ //TODO: actually check that the difference is less than the quantization error in the PLL
+	if(fabsf(currentSamplingRate-targetSamplingRate)>0.7){ //TODO: actually check that the difference is less than the quantization error in the PLL
 		BeagleRT_scheduleAuxiliaryTask(setClockTask);
 	}
 }
--- a/core/ReceiveAudioThread.cpp	Thu Aug 27 01:42:04 2015 +0100
+++ b/core/ReceiveAudioThread.cpp	Thu Aug 27 03:33:32 2015 +0100
@@ -202,11 +202,18 @@
         return -2;
     if(isListening()==false)
         return -1;
-    if(writePointer<0){ //if writePointer has not been initalized yet ...
+    static int numCalls=0;
+    if(writePointer<0 || (numCalls&16383)==0){ //if writePointer has not been initalized yet ...
+#ifdef USE_JUCE
+#else //debug
+    	rt_printf("reinit the writePointer, readPointer: %f;\n",readPointer);
+    	readPointer=0;
+#endif /* USE_JUCE */
         writePointer=2*length;  // do it, so that it starts writing at a safety margin from where we write.
                             // This will help keeping them in sync.
                             //TODO: handle what happens when the remote stream is interrupted and then restarted
     }
+    numCalls++;
     if(length>lastValidPointer) { 
         //not enough samples available, we fill the buffer with what is available, but the destination buffer will not be filled completely
         //at this very moment the other thread might be writing at most one payload into the buffer.
--- a/projects/scope/render.cpp	Thu Aug 27 01:42:04 2015 +0100
+++ b/projects/scope/render.cpp	Thu Aug 27 03:33:32 2015 +0100
@@ -54,7 +54,7 @@
 	static int count=0;
 //	if((count&262143)==0){
 //	static int nextCall=160000;
-	if( ((count&(16384-1))==0 /*&& count>200000*/)){
+	if( ((count&(2047-1))==0 /*&& count>200000*/)){
 //		rt_printf("b %d\n", count);
 		clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
 //		nextCall=count+100000;
@@ -64,8 +64,8 @@
 //		clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
 //	}
 	if(count==0){
-		gAudioCodec->setAudioSamplingRate(44080);
-		printf("startHread\n");
+		gAudioCodec->setAudioSamplingRate( 44101);
+		rt_printf("startHread\n");
 		ReceiveAudioThread::startThread();
 	}
 	for(unsigned int n = 0; n < context->audioFrames; n++) {