diff scripts/hvresources/heavy_render.cpp @ 442:6462d0cc8906 prerelease

build_pd_heavy.sh: major refactoring. Safer, nicer, cleaner
author Giulio Moro <giuliomoro@yahoo.it>
date Sun, 19 Jun 2016 00:35:41 +0100
parents scripts/hvresources/render.cpp@9dc5a0ccad25
children 4ff80956c27a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/hvresources/heavy_render.cpp	Sun Jun 19 00:35:41 2016 +0100
@@ -0,0 +1,185 @@
+/*
+ * render.cpp
+ *
+ *  Template render.cpp file for on-board heavy compiling
+ *
+ *  N.B. this is currently *not* compatible with foleyDesigner source files!
+ *
+ *  Created on: November 5, 2015
+ *
+ *  Christian Heinrichs
+ *
+ */
+
+#include <Bela.h>
+#include <Midi.h>
+#include <cmath>
+#include "Heavy_bbb.h"
+#include <string.h>
+#include <stdlib.h>
+#include <string.h>
+/*
+ *	HEAVY CONTEXT & BUFFERS
+ */
+
+Hv_bbb *gHeavyContext;
+float *gHvInputBuffers = NULL, *gHvOutputBuffers = NULL;
+int gHvInputChannels = 0, gHvOutputChannels = 0;
+
+float gInverseSampleRate;
+
+/*
+ *	HEAVY FUNCTIONS
+ */
+
+void printHook(double timestampSecs, const char *printLabel, const char *msgString, void *userData) {
+  printf("Message from Heavy patch: [@ %.3f] %s: %s\n", timestampSecs, printLabel, msgString);
+}
+
+static void sendHook(
+    double timestamp, // in milliseconds
+    const char *receiverName,
+    const HvMessage *const m,
+    void *userData) {
+
+  // only react to messages sent to receivers named "hello"
+  if (!strncmp(receiverName, "hello", 5)) {
+  }
+
+}
+
+/*
+ * SETUP, RENDER LOOP & CLEANUP
+ */
+
+Midi midi;
+bool setup(BelaContext *context, void *userData)	{
+
+	/* HEAVY */
+
+	gHeavyContext = hv_bbb_new(context->audioSampleRate);
+
+	gHvInputChannels = hv_getNumInputChannels(gHeavyContext);
+	gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext);
+
+	rt_printf("Starting Heavy context with %d input channels and %d output channels\n",
+			  gHvInputChannels, gHvOutputChannels);
+
+	if(gHvInputChannels != 0) {
+		gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float));
+	}
+	if(gHvOutputChannels != 0) {
+		gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float));
+	}
+
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+
+	// Set heavy print hook
+	hv_setPrintHook(gHeavyContext, &printHook);
+	// Set heavy send hook
+	hv_setSendHook(gHeavyContext, sendHook);
+
+	midi.readFrom(0);
+	midi.writeTo(0);
+	midi.enableParser(true);
+	return true;
+}
+
+
+void render(BelaContext *context, void *userData)
+{
+
+	// De-interleave the data
+	if(gHvInputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+			for(int ch = 0; ch < gHvInputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE PARAMETER INPUT 'CHANNELS' USED FOR ROUTING
+					// 'sensor' outputs from routing channels of dac~ are passed through here
+					break;
+				} else {
+					// If more than 2 ADC inputs are used in the pd patch, route the analog inputs
+					// i.e. ADC3->analogIn0 etc. (first two are always audio inputs)
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						float mIn = context->analogIn[m*context->analogChannels + (ch-context->audioChannels)];
+						gHvInputBuffers[ch * context->audioFrames + n] = mIn;
+					} else {
+						gHvInputBuffers[ch * context->audioFrames + n] = context->audioIn[n * context->audioChannels + ch];
+					}
+				}
+			}
+		}
+	}
+
+	// replacement for bang~ object
+	//hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b");
+	{
+		int num;
+		unsigned int hvHashes[3];
+		hvHashes[0] = hv_stringToHash("bela_notein");
+		hvHashes[1] = hv_stringToHash("bela_ctlin");
+		hvHashes[2] = hv_stringToHash("bela_pgmin"); 
+		while((num = midi.getParser()->numAvailableMessages()) > 0){
+			static MidiChannelMessage message;
+			message = midi.getParser()->getNextChannelMessage();
+			switch(message.getType()){
+			case kmmNoteOn: {
+//					message.prettyPrint();
+					float noteNumber = message.getDataByte(0);
+					float velocity = message.getDataByte(1);
+					float channel = message.getChannel();
+//					rt_printf("message: noteNumber: %f, velocity: %f, channel: %f\n", noteNumber, velocity, channel);
+					hv_vscheduleMessageForReceiver(gHeavyContext, hvHashes[0], 0, "fff", noteNumber, velocity, channel);
+				}
+				break;
+			case kmmControlChange: {
+				hv_vscheduleMessageForReceiver(gHeavyContext, hvHashes[1], 0, "fff",
+						(float)message.getDataByte(1), (float)message.getDataByte(0), (float)message.getChannel());
+				}
+				break;
+			case kmmProgramChange:
+				hv_vscheduleMessageForReceiver(gHeavyContext, hvHashes[2], 0, "ff",
+						(float)message.getDataByte(0), (float)message.getChannel());
+				break;
+			}
+		}
+	}
+//	hv_sendFloatToReceiver(gHeavyContext, "notein", 1.123f);
+
+
+	hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames);
+
+	// Interleave the output data
+	if(gHvOutputBuffers != NULL) {
+		for(int n = 0; n < context->audioFrames; n++) {
+
+			for(int ch = 0; ch < gHvOutputChannels; ch++) {
+				if(ch >= context->audioChannels+context->analogChannels) {
+					// THESE ARE SENSOR OUTPUT 'CHANNELS' USED FOR ROUTING
+					// they are the content of the 'sensor output' dac~ channels
+				} else {
+					if(ch >= context->audioChannels)	{
+						int m = n/2;
+						context->analogOut[m * context->analogFrames + (ch-context->audioChannels)] = constrain(gHvOutputBuffers[ch*context->audioFrames + n],0.0,1.0);
+					} else {
+						context->audioOut[n * context->audioChannels + ch] = gHvOutputBuffers[ch * context->audioFrames + n];
+					}
+				}
+			}
+		}
+	}
+
+}
+
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+	hv_bbb_free(gHeavyContext);
+	if(gHvInputBuffers != NULL)
+		free(gHvInputBuffers);
+	if(gHvOutputBuffers != NULL)
+		free(gHvOutputBuffers);
+
+}