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
|
chris@160
|
14 #include <BeagleRT.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;
|
chris@160
|
57 bool setup(BeagleRTContext *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
|
chris@160
|
90 void render(BeagleRTContext *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
|
chris@160
|
177 void cleanup(BeagleRTContext *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 }
|