annotate scripts/hvresources/render.cpp @ 329:9a2a5f14b587 prerelease

Updated build_pd_heavy to work with the latest makefile.
author Giulio Moro <giuliomoro@yahoo.it>
date Sat, 04 Jun 2016 14:10:45 +0100
parents 156e6955ccf6
children 9dc5a0ccad25
rev   line source
chris@160 1 /*
chris@160 2 * render.cpp
chris@160 3 *
chris@160 4 * Template render.cpp file for on-board heavy compiling
chris@160 5 *
chris@160 6 * N.B. this is currently *not* compatible with foleyDesigner source files!
chris@160 7 *
chris@160 8 * Created on: November 5, 2015
chris@160 9 *
chris@160 10 * Christian Heinrichs
chris@160 11 *
chris@160 12 */
chris@160 13
giuliomoro@329 14 #include <Bela.h>
giuliomoro@198 15 #include <Midi.h>
chris@160 16 #include <cmath>
chris@160 17 #include "../include/Utilities.h"
chris@160 18 #include "Heavy_bbb.h"
chris@190 19 #include <string.h>
chris@190 20 #include <stdlib.h>
chris@190 21 #include <string.h>
chris@160 22 /*
chris@160 23 * HEAVY CONTEXT & BUFFERS
chris@160 24 */
chris@160 25
chris@160 26 Hv_bbb *gHeavyContext;
chris@160 27 float *gHvInputBuffers = NULL, *gHvOutputBuffers = NULL;
chris@160 28 int gHvInputChannels = 0, gHvOutputChannels = 0;
chris@160 29
chris@160 30 float gInverseSampleRate;
chris@160 31
chris@160 32 /*
chris@160 33 * HEAVY FUNCTIONS
chris@160 34 */
chris@160 35
chris@160 36 void printHook(double timestampSecs, const char *printLabel, const char *msgString, void *userData) {
chris@160 37 printf("Message from Heavy patch: [@ %.3f] %s: %s\n", timestampSecs, printLabel, msgString);
chris@160 38 }
chris@160 39
chris@160 40 static void sendHook(
chris@160 41 double timestamp, // in milliseconds
chris@160 42 const char *receiverName,
chris@160 43 const HvMessage *const m,
chris@160 44 void *userData) {
chris@160 45
chris@160 46 // only react to messages sent to receivers named "hello"
chris@160 47 if (!strncmp(receiverName, "hello", 5)) {
chris@160 48 }
chris@160 49
chris@160 50 }
chris@160 51
chris@160 52 /*
chris@166 53 * SETUP, RENDER LOOP & CLEANUP
chris@160 54 */
chris@160 55
giuliomoro@198 56 Midi midi;
giuliomoro@329 57 bool setup(BelaContext *context, void *userData) {
chris@160 58
chris@160 59 /* HEAVY */
chris@160 60
chris@160 61 gHeavyContext = hv_bbb_new(context->audioSampleRate);
chris@160 62
chris@160 63 gHvInputChannels = hv_getNumInputChannels(gHeavyContext);
chris@160 64 gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext);
chris@160 65
chris@160 66 rt_printf("Starting Heavy context with %d input channels and %d output channels\n",
chris@160 67 gHvInputChannels, gHvOutputChannels);
chris@160 68
chris@160 69 if(gHvInputChannels != 0) {
chris@160 70 gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float));
chris@160 71 }
chris@160 72 if(gHvOutputChannels != 0) {
chris@160 73 gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float));
chris@160 74 }
chris@160 75
chris@160 76 gInverseSampleRate = 1.0 / context->audioSampleRate;
chris@160 77
chris@160 78 // Set heavy print hook
chris@160 79 hv_setPrintHook(gHeavyContext, &printHook);
chris@160 80 // Set heavy send hook
chris@160 81 hv_setSendHook(gHeavyContext, sendHook);
chris@160 82
giuliomoro@198 83 midi.readFrom(0);
giuliomoro@198 84 midi.writeTo(0);
giuliomoro@198 85 midi.enableParser(true);
chris@160 86 return true;
chris@160 87 }
chris@160 88
chris@160 89
giuliomoro@329 90 void render(BelaContext *context, void *userData)
chris@160 91 {
chris@160 92
chris@160 93 // De-interleave the data
chris@160 94 if(gHvInputBuffers != NULL) {
chris@160 95 for(int n = 0; n < context->audioFrames; n++) {
chris@160 96 for(int ch = 0; ch < gHvInputChannels; ch++) {
chris@160 97 if(ch >= context->audioChannels+context->analogChannels) {
chris@160 98 // THESE ARE PARAMETER INPUT 'CHANNELS' USED FOR ROUTING
chris@160 99 // 'sensor' outputs from routing channels of dac~ are passed through here
chris@160 100 break;
chris@160 101 } else {
chris@160 102 // If more than 2 ADC inputs are used in the pd patch, route the analog inputs
chris@160 103 // i.e. ADC3->analogIn0 etc. (first two are always audio inputs)
chris@160 104 if(ch >= context->audioChannels) {
chris@160 105 int m = n/2;
chris@160 106 float mIn = context->analogIn[m*context->analogChannels + (ch-context->audioChannels)];
chris@160 107 gHvInputBuffers[ch * context->audioFrames + n] = mIn;
chris@160 108 } else {
chris@160 109 gHvInputBuffers[ch * context->audioFrames + n] = context->audioIn[n * context->audioChannels + ch];
chris@160 110 }
chris@160 111 }
chris@160 112 }
chris@160 113 }
chris@160 114 }
chris@160 115
chris@160 116 // replacement for bang~ object
chris@160 117 //hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b");
giuliomoro@198 118 {
giuliomoro@198 119 int num;
giuliomoro@289 120 unsigned int hvHashes[3];
giuliomoro@289 121 hvHashes[0] = hv_stringToHash("bela_notein");
giuliomoro@289 122 hvHashes[1] = hv_stringToHash("bela_ctlin");
giuliomoro@289 123 hvHashes[2] = hv_stringToHash("bela_pgmin");
giuliomoro@198 124 while((num = midi.getParser()->numAvailableMessages()) > 0){
giuliomoro@198 125 static MidiChannelMessage message;
giuliomoro@198 126 message = midi.getParser()->getNextChannelMessage();
giuliomoro@198 127 switch(message.getType()){
giuliomoro@198 128 case kmmNoteOn: {
giuliomoro@198 129 // message.prettyPrint();
giuliomoro@198 130 float noteNumber = message.getDataByte(0);
giuliomoro@198 131 float velocity = message.getDataByte(1);
giuliomoro@198 132 float channel = message.getChannel();
giuliomoro@198 133 // rt_printf("message: noteNumber: %f, velocity: %f, channel: %f\n", noteNumber, velocity, channel);
giuliomoro@289 134 hv_vscheduleMessageForReceiver(gHeavyContext, hvHashes[0], 0, "fff", noteNumber, velocity, channel);
giuliomoro@198 135 }
giuliomoro@198 136 break;
giuliomoro@198 137 case kmmControlChange: {
giuliomoro@289 138 hv_vscheduleMessageForReceiver(gHeavyContext, hvHashes[1], 0, "fff",
giuliomoro@198 139 (float)message.getDataByte(1), (float)message.getDataByte(0), (float)message.getChannel());
giuliomoro@198 140 }
giuliomoro@198 141 break;
giuliomoro@198 142 case kmmProgramChange:
giuliomoro@289 143 hv_vscheduleMessageForReceiver(gHeavyContext, hvHashes[2], 0, "ff",
giuliomoro@198 144 (float)message.getDataByte(0), (float)message.getChannel());
giuliomoro@198 145 break;
giuliomoro@198 146 }
giuliomoro@198 147 }
giuliomoro@198 148 }
giuliomoro@198 149 // hv_sendFloatToReceiver(gHeavyContext, "notein", 1.123f);
giuliomoro@198 150
chris@160 151
chris@160 152 hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames);
chris@160 153
chris@160 154 // Interleave the output data
chris@160 155 if(gHvOutputBuffers != NULL) {
chris@160 156 for(int n = 0; n < context->audioFrames; n++) {
chris@160 157
chris@160 158 for(int ch = 0; ch < gHvOutputChannels; ch++) {
chris@160 159 if(ch >= context->audioChannels+context->analogChannels) {
chris@160 160 // THESE ARE SENSOR OUTPUT 'CHANNELS' USED FOR ROUTING
chris@160 161 // they are the content of the 'sensor output' dac~ channels
chris@160 162 } else {
chris@160 163 if(ch >= context->audioChannels) {
chris@160 164 int m = n/2;
chris@160 165 context->analogOut[m * context->analogFrames + (ch-context->audioChannels)] = constrain(gHvOutputBuffers[ch*context->audioFrames + n],0.0,1.0);
chris@160 166 } else {
chris@160 167 context->audioOut[n * context->audioChannels + ch] = gHvOutputBuffers[ch * context->audioFrames + n];
chris@160 168 }
chris@160 169 }
chris@160 170 }
chris@160 171 }
chris@160 172 }
chris@160 173
chris@160 174 }
chris@160 175
chris@160 176
giuliomoro@329 177 void cleanup(BelaContext *context, void *userData)
chris@160 178 {
chris@160 179
chris@160 180 hv_bbb_free(gHeavyContext);
chris@160 181 if(gHvInputBuffers != NULL)
chris@160 182 free(gHvInputBuffers);
chris@160 183 if(gHvOutputBuffers != NULL)
chris@160 184 free(gHvOutputBuffers);
chris@160 185
chris@160 186 }