changeset 120:cdd441a304a9 scope-refactoring

Added read to interleaved buffer
author Giulio Moro <giuliomoro@yahoo.it>
date Fri, 21 Aug 2015 15:52:37 +0100
parents c692827083e1
children 2197435e8fb4
files core/NetworkSend.cpp core/ReceiveAudioThread.cpp include/ReceiveAudioThread.h projects/scope/render.cpp
diffstat 4 files changed, 33 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/core/NetworkSend.cpp	Fri Aug 21 15:21:34 2015 +0100
+++ b/core/NetworkSend.cpp	Fri Aug 21 15:52:37 2015 +0100
@@ -47,7 +47,6 @@
 void NetworkSend::setup(float aSampleRate){
 	setup(aSampleRate, 0, 9999, "192.168.7.1");//channelNumber=0
 }
-
 void NetworkSend::setup(float aSampleRate, int aChannelNumber, int aPort, const char *aServer){
 	staticConstructor(); //FIXME: ideally this should be in the constructor, but this is not currently possible
 						//because of limitations in BeagleRT_createAuxiliaryTask()
@@ -59,7 +58,7 @@
 	setChannelNumber(aChannelNumber);
 	setPort(aPort);
 	setServer(aServer);
-	printf("Channel %d is sending messages to : %s:%d at %fHz\n", getChannelNumber(), aServer, aPort, aSampleRate);
+	printf("Channel %d is sending messages to: %s:%d at %fHz\n", getChannelNumber(), aServer, aPort, aSampleRate);
 }
 
 void NetworkSend::log(float value){ //TODO: add a vectorized version of this method
@@ -72,7 +71,12 @@
 		channel.activeBuffer=!channel.activeBuffer; //switch buffer
 		channel.doneOnTime=false;
 		BeagleRT_scheduleAuxiliaryTask(NetworkSend::sendDataTask); //send the buffer
-		//TODO: maybe we should have transmitAudioTask running in a loop instead of scheduling it multiple times?
+		// TODO: maybe we should have transmitAudioTask running in a loop instead of scheduling it multiple times?
+		// The current solution allows to minimize latency when a single channel is used, as there is no inherent
+		// rt_task_sleep in the thread, as we are signaling it every time.
+		// Although, there is a possible race condition: if the auxiliaryTask is scheduled by channel 0,
+		// it might still be executing when channel 1 schedules it. But if the AuxTask has already skipped
+		// over channel 1, then we are at risk that channel 1 never gets sent.
 	}
 	if(channel.index==channel.headerLength){
 		channel.buffers[channel.activeBuffer][0] = (float)channel.channelNumber; //TODO: this could actually be done just once in setup()
@@ -138,8 +142,9 @@
 		channels[n].setPort(port);
 	}
 }
-void Scope::setPort(int channel, int port){
-	channels[channel].setPort(port);
+void Scope::setPort(int channel, int aPort){
+	channels[channel].setPort(aPort);
+	printf("Channel %d is now sending to port %d\n", channel, aPort);
 }
 
 int Scope::getNumChannels(){
--- a/core/ReceiveAudioThread.cpp	Fri Aug 21 15:21:34 2015 +0100
+++ b/core/ReceiveAudioThread.cpp	Fri Aug 21 15:52:37 2015 +0100
@@ -132,6 +132,7 @@
 #endif
   bindToPort(aPort);
   channel=aChannel;
+  printf("Channel %d is receiving on port %d\n",aChannel, aPort);
   //  fd=fopen("output.m","w"); //DEBUG
   //  fprintf(fd,"var=["); //DEBUG
   headerLength=2;
@@ -147,7 +148,7 @@
   stackBuffer=(float*)malloc(sizeof(float)*headerLength);
   bytesToRead=sizeof(float)*(payloadLength + headerLength);
   writePointer=-1;
-  readPointer=0; //TODO: this *4 is sortof a security margin
+  readPointer=0;
   sleepTime=payloadLength/(float)44100 /4.0; //set sleepTime so that you do not check too often or too infrequently
 //JUCE    startThread(threadPriority);
 }
@@ -173,7 +174,10 @@
     }
     return buffer+(int)readPointer;
 };
-int ReceiveAudioThread::getSamplesSrc(float *destination, int length, float samplingRateRatio){//TODO: add interleaved version
+int ReceiveAudioThread::getSamplesSrc(float *destination, int length,
+		float samplingRateRatio, int numChannelsInDestination,
+		int channelToWriteTo)
+{
     if (!(samplingRateRatio>0 && samplingRateRatio<=2))
         return -2;
     if(isListening()==false)
@@ -194,7 +198,7 @@
             return 0;
     }
     for(int n=0; n<length; n++){
-        destination[n]=buffer[(int)(0.5+readPointer)];//simple ZOH non-interpolation (nearest neighbour)
+        destination[n*numChannelsInDestination+channelToWriteTo]=buffer[(int)(0.5+readPointer)];//simple ZOH non-interpolation (nearest neighbour)
         //  fprintf(fd,"%f, %d, %f;\n",readPointer,writePointer,destination[n]); //DEBUG
         readPointer+=samplingRateRatio;
         if((int)(0.5+readPointer)>=lastValidPointer){
@@ -203,7 +207,11 @@
     }
     return readPointer; 
 }
-
+int ReceiveAudioThread::getSamplesSrc(float *destination, int length, float samplingRateRatio){
+	return getSamplesSrc(destination, length, samplingRateRatio, 1,0);
+	// TODO: rewriting this so that it does not call the override method we can save a multiply and add
+	// for each sample.
+}
 bool ReceiveAudioThread::isBufferReady(){
     return bufferReady;
 }
--- a/include/ReceiveAudioThread.h	Fri Aug 21 15:21:34 2015 +0100
+++ b/include/ReceiveAudioThread.h	Fri Aug 21 15:52:37 2015 +0100
@@ -58,7 +58,16 @@
     void bindToPort(int aPort);
     bool isListening();
     float* getCurrentBuffer(int length);
+    /**
+     * Copies the samples to a non-interleaved buffer.
+     */
     int getSamplesSrc(float *destination, int length, float samplingRateRatio);
+    /**
+     * Copies the samples to an interleaved buffer.
+     */
+    int getSamplesSrc(float *destination, int length,
+    		float samplingRateRatio, int numChannelsInDestination,
+    		int channelToWriteTo);
     bool isBufferReady();
 #ifdef JUCE // if we are in Juce, then we run a separate thread for each receiver
     		// (as each of them are typically receiving on a mono or stereo track)
--- a/projects/scope/render.cpp	Fri Aug 21 15:21:34 2015 +0100
+++ b/projects/scope/render.cpp	Fri Aug 21 15:52:37 2015 +0100
@@ -84,17 +84,9 @@
 			gPhase2 -= 2.0 * M_PI;
 		
 	}
-	static float buffer[2][32]; //this should be context->audioFrames
-	if(count==0){
-		memset(buffer,2*32*sizeof(float),0);
-	}
 	if(count>0){
-		int readPointer0=receiveAudio0.getSamplesSrc(buffer[0], context->audioFrames, 1);
-		int readPointer1=receiveAudio1.getSamplesSrc(buffer[1], context->audioFrames, 1);
-		for(unsigned int n=0; n<context->audioFrames; n++){
-			context->audioOut[n*2]=buffer[0][n];
-			context->audioOut[n*2+1]=buffer[1][n];
-		}
+		int readPointer0=receiveAudio0.getSamplesSrc(context->audioOut, context->audioFrames, 1, 2, 0);
+		int readPointer1=receiveAudio1.getSamplesSrc(context->audioOut, context->audioFrames, 1, 2, 1);
 	}
 	count++;
 }