changeset 474:efc9a9f8e63d prerelease

Libpd added scope support and example
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 20 Jun 2016 20:38:46 +0100
parents 2a0b468ce1dd
children faa5f58c71af
files core/OSCServer.cpp core/Scope.cpp core/default_libpd_render.cpp examples/08-PureData/scope/_main.pd
diffstat 4 files changed, 64 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/core/OSCServer.cpp	Mon Jun 20 18:35:47 2016 +0100
+++ b/core/OSCServer.cpp	Mon Jun 20 20:38:46 2016 +0100
@@ -20,13 +20,13 @@
 
 void OSCServer::createAuxTasks(){
     char name [30];
-    sprintf (name, "OSCRecieveTask %i", port);
-    OSCRecieveTask = Bela_createAuxiliaryTask(OSCServer::checkMessages, BELA_AUDIO_PRIORITY-5, name, this, true);
+    sprintf (name, "OSCReceiveTask %i", port);
+    OSCReceiveTask = Bela_createAuxiliaryTask(OSCServer::checkMessages, BELA_AUDIO_PRIORITY-5, name, this, true);
 }
 
 void OSCServer::messageCheck(){
-    if (socket.waitUntilReady(true, UDP_RECIEVE_TIMEOUT_MS)){
-        int msgLength = socket.read(&inBuffer, UDP_RECIEVE_MAX_LENGTH, false);
+    if (socket.waitUntilReady(true, UDP_RECEIVE_TIMEOUT_MS)){
+        int msgLength = socket.read(&inBuffer, UDP_RECEIVE_MAX_LENGTH, false);
         pr.init(inBuffer, msgLength);
         oscpkt::Message *inmsg;
         while (pr.isOk() && (inmsg = pr.popMessage()) != 0) {
@@ -49,9 +49,9 @@
     return poppedMessage;
 }
 
-void OSCServer::recieveMessageNow(int timeout){
+void OSCServer::receiveMessageNow(int timeout){
     if (socket.waitUntilReady(true, timeout)){
-        int msgLength = socket.read(&inBuffer, UDP_RECIEVE_MAX_LENGTH, false);
+        int msgLength = socket.read(&inBuffer, UDP_RECEIVE_MAX_LENGTH, false);
         pr.init(inBuffer, msgLength);
         oscpkt::Message *inmsg;
         while (pr.isOk() && (inmsg = pr.popMessage()) != 0) {
--- a/core/Scope.cpp	Mon Jun 20 18:35:47 2016 +0100
+++ b/core/Scope.cpp	Mon Jun 20 20:38:46 2016 +0100
@@ -20,9 +20,9 @@
     sampleRate = _sampleRate;
     
     // setup the OSC server && client
-    // used for sending / recieving settings
+    // used for sending / receiving settings
     // oscClient has it's send task turned off, as we only need to send one handshake message
-    oscServer.setup(OSC_RECIEVE_PORT);
+    oscServer.setup(OSC_RECEIVE_PORT);
     oscClient.setup(OSC_SEND_PORT, "127.0.0.1", false);
 
     // setup the udp socket
@@ -36,18 +36,18 @@
 
     // send an OSC message to address /scope-setup
     // then wait 1 second for a reply on /scope-setup-reply 
-    bool handshakeRecieved = false;
+    bool handshakeReceived = false;
     oscClient.sendMessageNow(oscClient.newMessage.to("/scope-setup").add((int)numChannels).add(sampleRate).end());
-    oscServer.recieveMessageNow(1000);
+    oscServer.receiveMessageNow(1000);
     while (oscServer.messageWaiting()){
-        if (handshakeRecieved){
+        if (handshakeReceived){
             parseMessage(oscServer.popMessage());
         } else if (oscServer.popMessage().match("/scope-setup-reply")){
-            handshakeRecieved = true;
+            handshakeReceived = true;
         }
     }
     
-    if (handshakeRecieved && connected)
+    if (handshakeReceived && connected)
         start();
     
 }
@@ -82,7 +82,7 @@
 
 void Scope::log(float chn1, ...){
 
-    // check for any recieved OSC messages
+    // check for any received OSC messages
     while (oscServer.messageWaiting()){
         parseMessage(oscServer.popMessage());
     }
--- a/core/default_libpd_render.cpp	Mon Jun 20 18:35:47 2016 +0100
+++ b/core/default_libpd_render.cpp	Mon Jun 20 20:38:46 2016 +0100
@@ -15,10 +15,10 @@
 #include <libpd/s_stuff.h>
 #include <UdpServer.h>
 #include <Midi.h>
-//extern t_sample* sys_soundin;
-//extern t_sample* sys_soundout;
+#include <Scope.h>
+
 // if you are 100% sure of what value 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%
+// you could #define gBufLength 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).
 int gBufLength;
 
@@ -33,6 +33,7 @@
 	rt_printf("%s", recv);
 }
 
+//TODO: remove this function
 void libpdReadFilesLoop(){
     while(!gShouldStop){
     	// check for modified sockets/file descriptors
@@ -106,7 +107,7 @@
 				int receiver = ((source[prefixLength] - 48) * 10);
 				receiver += (source[prefixLength+1] - 48);
 				unsigned int channel = receiver - 11; // go back to the actual Bela digital channel number
-				if(channel >= 0 && channel < 16){ //16 is the hardcoded value for the number of digital channels
+				if(channel < 16){ //16 is the hardcoded value for the number of digital channels
 					dcm.setValue(channel, value);
 				}
 			}
@@ -121,12 +122,21 @@
 	{"bela_digitalIn26"}
 };
 
-static unsigned int analogChannelsInUse;
+static unsigned int gAnalogChannelsInUse;
 static unsigned int gLibpdBlockSize;
-static unsigned int gChannelsInUse = 26;
+// 2 audio + (up to)8 analog + (up to) 16 digital + 4 scope outputs
+static const unsigned int gChannelsInUse = 30;
+static const unsigned int gFirstAudioChannel = 0;
+static const unsigned int gFirstAnalogChannel = 2;
+static const unsigned int gFirstDigitalChannel = 10;
+static const unsigned int gFirstScopeChannel = 26;
 
+Scope scope;
+unsigned int gScopeChannels = 4;
 bool setup(BelaContext *context, void *userData)
 {
+    scope.setup(gScopeChannels, context->audioSampleRate);
+
 	// Check first of all if file exists. Will actually open it later.
 	char file[] = "_main.pd";
 	char folder[] = "./";
@@ -138,7 +148,7 @@
 		return false;
 	}
 	dcm.setCallback(sendDigitalMessage);
-	analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels - context->digitalChannels);
+	gAnalogChannelsInUse = context->analogChannels;
 	if(context->digitalChannels > 0){
 		for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){
 			dcm.setCallbackArgument(ch, receiverNames[ch]);
@@ -151,12 +161,11 @@
 #else
 	midi.enableParser(false);
 #endif /* PARSE_MIDI */
-//	gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse);
 //	udpServer.bindToPort(1234);
 
 	gLibpdBlockSize = libpd_blocksize();
 	// check that we are not running with a blocksize smaller than gLibPdBlockSize
-	// it would still work, but the load would be executed unevenly between calls to render
+	// We could still make it work, but the load would be executed unevenly between calls to render
 	if(context->audioFrames < gLibpdBlockSize){
 		fprintf(stderr, "Error: minimum block size must be %d\n", gLibpdBlockSize);
 		return false;
@@ -299,11 +308,6 @@
 
 	static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize;
 
-	// these are reset at every audio callback. Persistence across audio callbacks
-	// is handled by the core code.
-//	setDataOut = 0;
-//	clearDataOut = 0;
-
 	for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick){
 		unsigned int audioFrameBase = gLibpdBlockSize * tick;
 		unsigned int j;
@@ -319,21 +323,21 @@
 		// 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) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstAnalogChannel; k < gAnalogChannelsInUse; ++k, p1 += gLibpdBlockSize) {
 					unsigned int analogFrame = (audioFrameBase + j) / 2;
 					*p1 = analogRead(context, analogFrame, k);
 				}
 			}
 		} 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) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstAnalogChannel; k < gAnalogChannelsInUse; ++k, p1 += gLibpdBlockSize) {
 					unsigned int analogFrame = audioFrameBase + j;
 					*p1 = analogRead(context, analogFrame, k);
 				}
 			}
 		} 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) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstAnalogChannel; k < gAnalogChannelsInUse; ++k, p1 += gLibpdBlockSize) {
 					unsigned int analogFrame = (audioFrameBase + j) * 2;
 					*p1 = analogRead(context, analogFrame, k);
 				}
@@ -348,7 +352,7 @@
 		// digital in at signal-rate
 		for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
 			unsigned int digitalFrame = audioFrameBase + j;
-			for (k = 0, p1 = p0 + gLibpdBlockSize * (context->audioChannels + 8);
+			for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstDigitalChannel;
 					k < 16; ++k, p1 += gLibpdBlockSize) {
 				if(dcm.isSignalRate(k) && dcm.isInput(k)){ // only process input channels that are handled at signal rate
 					*p1 = digitalRead(context, digitalFrame, k);
@@ -362,7 +366,7 @@
 		// digital out at signal-rate
 		for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
 			unsigned int digitalFrame = (audioFrameBase + j);
-			for (k = 0, p1 = p0  + gLibpdBlockSize * (context->audioChannels + 8);
+			for (k = 0, p1 = p0  + gLibpdBlockSize * gFirstDigitalChannel;
 					k < context->digitalChannels; k++, p1 += gLibpdBlockSize) {
 				if(dcm.isSignalRate(k) && dcm.isOutput(k)){ // only process output channels that are handled at signal rate
 					digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5);
@@ -379,25 +383,34 @@
 				audioWrite(context, audioFrameBase + j, k, *p1);
 			}
 		}
+		//scope
+		for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
+			float scopeOut[gScopeChannels]={0};
+			for (k = 0, p1 = p0  + gLibpdBlockSize * gFirstScopeChannel; k < gScopeChannels; k++, p1 += gLibpdBlockSize) {
+				scopeOut[k] = *p1;
+			}
+			scope.log(scopeOut[0], scopeOut[1], scopeOut[2], scopeOut[3]);
+		}
+
 
 		//analog
 		if(context->analogChannels == 8){
 			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j += 2, p0 += 2) { //write every two frames
 				unsigned int analogFrame = (audioFrameBase + j) / 2;
-				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstAnalogChannel; k < gAnalogChannelsInUse; k++, p1 += gLibpdBlockSize) {
 					analogWriteOnce(context, analogFrame, k, *p1);
 				}
 			}
 		} else if(context->analogChannels == 4){ //write every frame
 			for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
 				unsigned int analogFrame = (audioFrameBase + j);
-				for (k = 0, p1 = p0  + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
+				for (k = 0, p1 = p0  + gLibpdBlockSize * context->audioChannels; k < gAnalogChannelsInUse; k++, p1 += gLibpdBlockSize) {
 					analogWriteOnce(context, analogFrame, k, *p1);
 				}
 			}
 		} 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) {
+				for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < gAnalogChannelsInUse; k++, p1 += gLibpdBlockSize) {
 					int analogFrame = audioFrameBase * 2 + j * 2;
 					analogWriteOnce(context, analogFrame, k, *p1);
 					analogWriteOnce(context, analogFrame + 1, k, *p1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/scope/_main.pd	Mon Jun 20 20:38:46 2016 +0100
@@ -0,0 +1,15 @@
+#N canvas 394 368 477 304 10;
+#X text 16 25 ============;
+#X obj 104 239 dac~ 27 28 29 30;
+#X obj 27 186 osc~ 2321;
+#X obj 123 175 osc~ 12;
+#X obj 267 175 noise~;
+#X obj 192 170 phasor~ 10;
+#X text 16 15 Bela Scope;
+#X text 116 15 Make sure the IDE is running and then bring up the scope
+in your browser http://192.168.7.2/scope/ You can log to the scope
+by sending to dac~ 27 to 30;
+#X connect 2 0 1 0;
+#X connect 3 0 1 1;
+#X connect 4 0 1 3;
+#X connect 5 0 1 2;