changeset 343:4823ee13bcac prerelease

basic_libpd now populates pd's audio buffers directly. Updated libpd.so binary. This required an API change with respect to standard libpdAPI because for some strange reason, accessing sys_audioin and sys_audioout directly from the render.cpp file would return invalid values.
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 06 Jun 2016 15:15:15 +0100
parents 860c42b3830e
children 1c35a5d0ce32
files .cproject examples/basic_libpd/render.cpp libpd.so
diffstat 3 files changed, 59 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/.cproject	Mon Jun 06 12:21:38 2016 +0100
+++ b/.cproject	Mon Jun 06 15:15:15 2016 +0100
@@ -134,7 +134,8 @@
 						</toolChain>
 					</folderInfo>
 					<sourceEntries>
-						<entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
+						<entry excluding="default_main.cpp|audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="examples/basic_libpd"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_button"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/>
@@ -262,7 +263,8 @@
 						</toolChain>
 					</folderInfo>
 					<sourceEntries>
-						<entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
+						<entry excluding="default_main.cpp|audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="examples/basic_libpd"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic_button"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/>
--- a/examples/basic_libpd/render.cpp	Mon Jun 06 12:21:38 2016 +0100
+++ b/examples/basic_libpd/render.cpp	Mon Jun 06 15:15:15 2016 +0100
@@ -17,16 +17,10 @@
 #include <UdpServer.h>
 #include <Midi.h>
 
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-unsigned int gLibpdBlockSize;  //make sure this matches the one used to compile libpd
+// if you are 100% sure of what value that was used to compile libpd/puredata, then
+// you could define this, instead of getting it at runtime. It has proved to give some 0.3%
+// performance boost when it is 8 (thanks to vectorize optimizations I guess).
+unsigned int gLibpdBlockSize;
 
 unsigned int gChannelsInUse = 10;
 int gBufLength;
@@ -200,56 +194,67 @@
  */
 	static unsigned int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels);
 	static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize;
-	for(unsigned int j = 0; j < numberOfPdBlocksToProcess; ++j){
-		unsigned int inW = 0;
-		unsigned int outR = 0;
-
-		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);
+	for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick){
+		unsigned int audioOutFrameBase = gLibpdBlockSize * tick;
+		unsigned int j;
+		unsigned int k;
+		float* p0;
+		float* p1;
+		for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
+			for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) {
+				*p1 = audioRead(context, audioOutFrameBase + j, k);
 			}
-			// 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
+		}
+		// then analogs
+		// this loop resamples by ZOH, as needed, using m
+		if(context->analogChannels == 8 ){ //hold the value for two frames
+			for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+					unsigned int analogFrame = (audioOutFrameBase + j) / 2;
+					*p1 = analogRead(context, analogFrame, k);
 				}
-			} 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 == 4){ //write every frame
+			for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+					unsigned int analogFrame = audioOutFrameBase + j;
+					*p1 = analogRead(context, analogFrame, k);
 				}
-			} else if(context->analogChannels == 2){ //drop every other frame
-				for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
-					gInBuf[inW++] = analogRead(context, n*2, analogCh);
+			}
+		} else if(context->analogChannels == 2){ //drop every other frame
+			for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+					unsigned int analogFrame = (audioOutFrameBase + j) * 2;
+					*p1 = analogRead(context, analogFrame, k);
 				}
 			}
 		}
 		libpd_process_sys(); // process the block
-		for(unsigned int n = 0; n < gLibpdBlockSize; ++n){ //pd buffers are interleaved
-			unsigned int outAudioFrame = 0;
-			for(unsigned int ch = 0; ch < context->audioChannels; ++ch){
-				audioWrite(context, outAudioFrame, ch, gOutBuf[outR++]);
+		for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) {
+			for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) {
+				audioWrite(context, audioOutFrameBase + j, k, *p1);
 			}
-			//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
-					}
+		}
+		if(context->analogChannels == 8){
+			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j += 2, p0 += 2) { //write every two frames
+				unsigned int analogFrame = (audioOutFrameBase + j) / 2;
+				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+					analogWrite(context, analogFrame, k, *p1);
 				}
-			} 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 == 4){ //write every frame
+			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
+				unsigned int analogFrame = (audioOutFrameBase + j);
+				for (k = 0, p1 = p0  + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+					analogWrite(context, analogFrame, k, *p1);
 				}
-			} 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 == 2){ //write every frame twice
+			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+					int analogFrame = audioOutFrameBase * 2 + j * 2;
+					analogWrite(context, analogFrame, k, *p1);
+					analogWrite(context, analogFrame + 1, k, *p1);
 				}
 			}
 		}
@@ -264,6 +269,4 @@
 void cleanup(BelaContext *context, void *userData)
 {
 	libpd_queued_release();
-//	free(gInBuf);
-//	free(gOutBuf);
 }
Binary file libpd.so has changed