changeset 232:600355cf4ed5 mergingClockSync

libpd taking care of different numbers of analog channels
author Giulio Moro <giuliomoro@yahoo.it>
date Sun, 10 Apr 2016 03:14:33 +0200
parents c0bf6157f67e
children 18d03901f866
files projects/basic_libpd/render.cpp
diffstat 1 files changed, 54 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/projects/basic_libpd/render.cpp	Sun Apr 10 02:38:16 2016 +0200
+++ b/projects/basic_libpd/render.cpp	Sun Apr 10 03:14:33 2016 +0200
@@ -24,7 +24,7 @@
 // Return true on success; returning false halts the program.
 #define DEFDACBLKSIZE 8u  //make sure this matches the one used to compile libpd
 
-const int gChannelsInUse = 6;
+int gChannelsInUse = 10;
 int gBufLength;
 
 float* gInBuf;
@@ -51,6 +51,7 @@
 AuxiliaryTask  udpReadTask;
 bool setup(BeagleRTContext *context, void *userData)
 {
+	gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse);
 	udpServer.bindToPort(1234);
 
 	// check that we are not running with a blocksize smaller than DEFDACBLKSIZE
@@ -63,10 +64,10 @@
 	// check that the sampling rate of the analogs is the same as audio if running with
 	// more than 2 channels (that is with analog). If we fix the TODO in render, then
 	// this test is not needed.
-	if(context->analogFrames != context->audioFrames){
-		fprintf(stderr, "Error: analog and audio sampling rates must be the same\n");
-		return false;
-	}
+//	if(context->analogFrames != context->audioFrames){
+//		fprintf(stderr, "Error: analog and audio sampling rates must be the same\n");
+//		return false;
+//	}
 	//following lines borrowed from libpd/samples/c/pdtest/pdtest.c
 	// init pd
 	libpd_set_printhook(BeagleRT_printHook); // set this before calling libpd_init
@@ -85,7 +86,6 @@
 	gOutBuf = (float*)malloc(bufferSize);
 	// no need to memset to zero
 
-
 	char file[] = "_main.pd";
 	char folder[] = "./";
 	// open patch       [; pd open file folder(
@@ -111,40 +111,72 @@
  *	 do not need the for loops before and after libpd_process_float, so you can save quite some
  *	 memory operations.
  */
-
-	for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved
-		for(unsigned int k = 0; k < context->audioChannels; k++){
-			gInBuf[inW++] = audioReadFrame(context, n, k);
+	static int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels);
+	// rt_printf("channelsInUse: %d, analogChannels in Use: %d\n", gChannelsInUse, analogChannelsInUse);
+	for(unsigned int n = 0; n < context->audioFrames; ++n){ //pd buffers are interleaved
+		for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio
+			gInBuf[inW++] = audioReadFrame(context, n, ch);
 		}
-		for(unsigned int k = 0; k < gChannelsInUse - context->audioChannels; k ++){ // add analogs
-			gInBuf[inW++] = analogReadFrame(context, n, k);
-			// TODO: Apply here sampling rate conversion from analogs to audio
+		// then analogs
+		// this loop resamples by ZOH, as needed, using m
+		if(context->analogChannels == 8 ){ //hold the value for two frames
+			for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+				gInBuf[inW++] = analogReadFrame(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even
+			}
+		} else if(context->analogChannels == 4){ //write every frame
+			for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+				gInBuf[inW++] = analogReadFrame(context, n, analogCh);
+			}
+		} else if(context->analogChannels == 2){ //drop every other frame
+			for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+				gInBuf[inW++] = analogReadFrame(context, n*2, analogCh);
+			}
 		}
 		if(inW == gBufLength * gChannelsInUse){
 			inW = 0;
 		}
 	}
-
+	// rt_printf("inW %d\n", inW);
 	if(inW == 0){ //if the buffer is full, process it
-		int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE;
+		static int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE;
 		libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf);
-		outR = 0; // reset the read pointer. NOTE: hopefully this is not needed EXCEPT the first time
+		outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time
 	}
 
 	for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved
-		for(unsigned int k = 0; k < context->audioChannels; k++){
-			audioWriteFrame(context, n, k, gOutBuf[outR++]);
+		for(unsigned int ch = 0; ch < context->audioChannels; ++ch){
+			audioWriteFrame(context, n, ch, gOutBuf[outR++]);
 		}
-		//add analogs here, limit them to channelsInUse
-		for(unsigned int k = 0; k < gChannelsInUse - context->audioChannels; k ++){ // add analogs
-			analogWriteFrame(context, n, k, gOutBuf[outR++]);
-			// TODO: Apply here sampling rate conversion from analogs to audio
+		//and analogs
+		if(context->analogChannels == 8){
+			for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+				float analogOut = gOutBuf[outR++];				
+				if((n&1) == 0){//write every two frames
+					analogWriteFrame(context, n/2, analogCh, analogOut);
+				} else {
+					// discard this sample
+				}
+			}
+		} else if(context->analogChannels == 4){ //write every frame
+			for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+				float analogOut = gOutBuf[outR++];
+				analogWriteFrame(context, n, analogCh, analogOut);
+			}
+		} else if(context->analogChannels == 2){ //write twice every frame
+			for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+				float analogOut = gOutBuf[outR++];
+				analogWriteFrame(context, 2*n, analogCh, analogOut);
+				analogWriteFrame(context, 2*n + 1, analogCh, analogOut);
+			}
 		}
 		if(outR == gBufLength * gChannelsInUse){
 			outR = 0;
 		}
 	}
+	// rt_printf("outR %d, analogChannelsInUse %d, channelsInUse %d\n", 
+	// 	outR , analogChannelsInUse, gChannelsInUse);
 }
+
 // cleanup() is called once at the end, after the audio has stopped.
 // Release any resources that were allocated in setup().