changeset 341:7af9c5be3434 prerelease

libpd: using smaller blocksizes for processing, so that events can be scheduled more accurately
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 06 Jun 2016 03:31:22 +0100
parents 69d86429a1cf
children 860c42b3830e
files examples/basic_libpd/render.cpp
diffstat 1 files changed, 52 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/examples/basic_libpd/render.cpp	Mon Jun 06 02:37:30 2016 +0100
+++ b/examples/basic_libpd/render.cpp	Mon Jun 06 03:31:22 2016 +0100
@@ -118,11 +118,13 @@
 void render(BelaContext *context, void *userData)
 {
 	int num;
+	// the safest thread-safe option to handle MIDI input is to process the MIDI buffer
+	// from the audio thread.
 #ifdef PARSE_MIDI
 	while((num = midi.getParser()->numAvailableMessages()) > 0){
 		static MidiChannelMessage message;
 		message = midi.getParser()->getNextChannelMessage();
-//		message.prettyPrint(); // use this to print beautified message (channel, data bytes)
+		//message.prettyPrint(); // use this to print beautified message (channel, data bytes)
 		switch(message.getType()){
 			case kmmNoteOn:
 			{
@@ -193,8 +195,8 @@
 	}
 #endif /* PARSE_MIDI */
 
-	static unsigned int inW = 0;
-	static unsigned int outR = 0;
+	unsigned int inW = 0;
+	unsigned int outR = 0;
 /*
  *	NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers
  *	 and the blocksize of Bela is the same as gLibPdBlockSize, then you probably
@@ -202,72 +204,64 @@
  *	 memory operations.
  */
 	static unsigned int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels);
+	static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize;
 	// 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++] = audioRead(context, n, ch);
-		}
-		// then analogs
-		// this loop resamples by ZOH, as needed, using m
-		if(context->analogChannels == 8 ){ //hold the value for two frames
-			for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
-				gInBuf[inW++] = analogRead(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even
+	for(unsigned int j = 0; j < numberOfPdBlocksToProcess; ++j){
+		int oldInW = inW;
+		for(unsigned int n = 0; n < gLibpdBlockSize; ++n){ //pd buffers are interleaved
+			for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio
+				gInBuf[inW++] = audioRead(context, n, ch);
 			}
-		} else if(context->analogChannels == 4){ //write every frame
-			for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
-				gInBuf[inW++] = analogRead(context, n, analogCh);
-			}
-		} else if(context->analogChannels == 2){ //drop every other frame
-			for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
-				gInBuf[inW++] = analogRead(context, n*2, analogCh);
+			// then analogs
+			// this loop resamples by ZOH, as needed, using m
+			if(context->analogChannels == 8 ){ //hold the value for two frames
+				for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+					gInBuf[inW++] = analogRead(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(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+					gInBuf[inW++] = analogRead(context, n, analogCh);
+				}
+			} else if(context->analogChannels == 2){ //drop every other frame
+				for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+					gInBuf[inW++] = analogRead(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
-		static int numberOfPdBlocksToProcess = gBufLength/gLibpdBlockSize;
 		// TODO: see if we can rewrite libpd_process_float so that it takes a buffer
 		// of interleaved channels of arbitrary length rather than a series of
 		// stacked buffers of size gLibPdBlockSize as it currently does.
-		libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf);
-		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 ch = 0; ch < context->audioChannels; ++ch){
-			audioWrite(context, n, ch, gOutBuf[outR++]);
-		}
-		//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
-					analogWrite(context, n/2, analogCh, analogOut);
-				} else {
-					// discard this sample
+		// This would allow to use the buffers as they are rather than having to copy them
+		libpd_process_float(1, &gInBuf[oldInW], &gOutBuf[oldInW]);
+		for(unsigned int n = 0; n < gLibpdBlockSize; ++n){ //pd buffers are interleaved
+			unsigned int outAudioFrame = n + j * gLibpdBlockSize;
+			for(unsigned int ch = 0; ch < context->audioChannels; ++ch){
+				audioWrite(context, outAudioFrame, ch, gOutBuf[outR++]);
+			}
+			//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
+						analogWrite(context, outAudioFrame/2, analogCh, analogOut);
+					} else {
+						// discard this sample
+					}
+				}
+			} else if(context->analogChannels == 4){ //write every frame
+				for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+					float analogOut = gOutBuf[outR++];
+					analogWrite(context, outAudioFrame, analogCh, analogOut);
+				}
+			} else if(context->analogChannels == 2){ //write twice every frame
+				for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
+					float analogOut = gOutBuf[outR++];
+					analogWrite(context, 2*outAudioFrame, analogCh, analogOut);
+					analogWrite(context, 2*outAudioFrame + 1, analogCh, analogOut);
 				}
 			}
-		} else if(context->analogChannels == 4){ //write every frame
-			for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
-				float analogOut = gOutBuf[outR++];
-				analogWrite(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++];
-				analogWrite(context, 2*n, analogCh, analogOut);
-				analogWrite(context, 2*n + 1, analogCh, analogOut);
-			}
-		}
-		if(outR == gBufLength * gChannelsInUse){
-			outR = 0;
 		}
 	}
-	// rt_printf("outR %d, analogChannelsInUse %d, channelsInUse %d\n", 
-	// 	outR , analogChannelsInUse, gChannelsInUse);
 	Bela_scheduleAuxiliaryTask(libpdProcessMidiQueueTask);
 	Bela_scheduleAuxiliaryTask(libpdProcessMessageQueueTask);
 }