chris@163
|
1 /*
|
chris@163
|
2 * render.cpp
|
chris@163
|
3 *
|
chris@163
|
4 * Template render.cpp file for on-board heavy compiling
|
chris@163
|
5 *
|
chris@163
|
6 * N.B. this is currently *not* compatible with foleyDesigner source files!
|
chris@163
|
7 *
|
chris@163
|
8 * Created on: November 5, 2015
|
chris@163
|
9 *
|
chris@163
|
10 * Christian Heinrichs
|
chris@163
|
11 *
|
chris@163
|
12 */
|
chris@163
|
13
|
chris@163
|
14 #include <BeagleRT.h>
|
chris@163
|
15 #include <cmath>
|
chris@163
|
16 #include "../include/Utilities.h"
|
chris@163
|
17 #include "Heavy_bbb.h"
|
chris@163
|
18
|
chris@163
|
19 // #include "I2c_TouchKey.h"
|
chris@163
|
20
|
chris@163
|
21 // #include "../include/UdpServer.h"
|
chris@163
|
22 // #include "../include/UdpClient.h"
|
chris@163
|
23 // #include <iostream>
|
chris@163
|
24 // #include <fstream>
|
chris@163
|
25 // #include "../include/ReceiveAudioThread.h"
|
chris@163
|
26
|
chris@163
|
27 // #include "../include/render.h"
|
chris@163
|
28 // #include <arm_neon.h>
|
chris@163
|
29 // #include <time.h>
|
chris@163
|
30 // #include <sndfile.h>
|
chris@163
|
31
|
chris@163
|
32 // #include "../include/RTAudio.h"
|
chris@163
|
33 // #include <rtdk.h>
|
chris@163
|
34
|
chris@163
|
35
|
chris@163
|
36 /*
|
chris@163
|
37 * HEAVY CONTEXT & BUFFERS
|
chris@163
|
38 */
|
chris@163
|
39
|
chris@163
|
40 Hv_bbb *gHeavyContext;
|
chris@163
|
41 float *gHvInputBuffers = NULL, *gHvOutputBuffers = NULL;
|
chris@163
|
42 int gHvInputChannels = 0, gHvOutputChannels = 0;
|
chris@163
|
43
|
chris@163
|
44 float gInverseSampleRate;
|
chris@163
|
45
|
chris@163
|
46 /*
|
chris@163
|
47 * HEAVY FUNCTIONS
|
chris@163
|
48 */
|
chris@163
|
49
|
chris@163
|
50 void printHook(double timestampSecs, const char *printLabel, const char *msgString, void *userData) {
|
chris@163
|
51 printf("Message from Heavy patch: [@ %.3f] %s: %s\n", timestampSecs, printLabel, msgString);
|
chris@163
|
52 }
|
chris@163
|
53
|
chris@163
|
54 static void sendHook(
|
chris@163
|
55 double timestamp, // in milliseconds
|
chris@163
|
56 const char *receiverName,
|
chris@163
|
57 const HvMessage *const m,
|
chris@163
|
58 void *userData) {
|
chris@163
|
59
|
chris@163
|
60 // only react to messages sent to receivers named "hello"
|
chris@163
|
61 if (!strncmp(receiverName, "hello", 5)) {
|
chris@163
|
62 }
|
chris@163
|
63
|
chris@163
|
64 }
|
chris@163
|
65
|
chris@163
|
66 /*
|
chris@163
|
67 * RENDER INITIALISATION, LOOP & CLEANUP
|
chris@163
|
68 */
|
chris@163
|
69
|
chris@163
|
70
|
chris@163
|
71 // bool initialise_render(int numMatrixChannels, int numAudioChannels,
|
chris@163
|
72 // int numMatrixFramesPerPeriod,
|
chris@163
|
73 // int numAudioFramesPerPeriod,
|
chris@163
|
74 // float matrixSampleRate, float audioSampleRate,
|
chris@163
|
75 // void *userData)
|
chris@163
|
76 // {
|
chris@163
|
77 bool setup(BeagleRTContext *context, void *userData) {
|
chris@163
|
78
|
chris@163
|
79 /* HEAVY */
|
chris@163
|
80
|
chris@163
|
81 gHeavyContext = hv_bbb_new(context->audioSampleRate);
|
chris@163
|
82
|
chris@163
|
83 gHvInputChannels = hv_getNumInputChannels(gHeavyContext);
|
chris@163
|
84 gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext);
|
chris@163
|
85
|
chris@163
|
86 // srand ( time(NULL) );
|
chris@163
|
87
|
chris@163
|
88 rt_printf("Starting Heavy context with %d input channels and %d output channels\n",
|
chris@163
|
89 gHvInputChannels, gHvOutputChannels);
|
chris@163
|
90
|
chris@163
|
91 if(gHvInputChannels != 0) {
|
chris@163
|
92 gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float));
|
chris@163
|
93 //memset(gHvInputBuffers,0,gHvInputChannels * numAudioFramesPerPeriod * sizeof(float));
|
chris@163
|
94 }
|
chris@163
|
95 if(gHvOutputChannels != 0) {
|
chris@163
|
96 gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float));
|
chris@163
|
97 }
|
chris@163
|
98
|
chris@163
|
99 gInverseSampleRate = 1.0 / context->audioSampleRate;
|
chris@163
|
100
|
chris@163
|
101 // Set heavy print hook
|
chris@163
|
102 hv_setPrintHook(gHeavyContext, &printHook);
|
chris@163
|
103 // Set heavy send hook
|
chris@163
|
104 hv_setSendHook(gHeavyContext, sendHook);
|
chris@163
|
105
|
chris@163
|
106 return true;
|
chris@163
|
107 }
|
chris@163
|
108
|
chris@163
|
109
|
chris@163
|
110 // void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
|
chris@163
|
111 // uint16_t *matrixIn, uint16_t *matrixOut)
|
chris@163
|
112 // {
|
chris@163
|
113 void render(BeagleRTContext *context, void *userData)
|
chris@163
|
114 {
|
chris@163
|
115 // use this for thread management
|
chris@163
|
116 // if(gCount == 0) {
|
chris@163
|
117 // } else {
|
chris@163
|
118 // }
|
chris@163
|
119 // gCount++;
|
chris@163
|
120
|
chris@163
|
121 // De-interleave the data
|
chris@163
|
122 if(gHvInputBuffers != NULL) {
|
chris@163
|
123 for(int n = 0; n < context->audioFrames; n++) {
|
chris@163
|
124 for(int ch = 0; ch < gHvInputChannels; ch++) {
|
chris@163
|
125 if(ch >= context->audioChannels+context->analogChannels) {
|
chris@163
|
126 // THESE ARE PARAMETER INPUT 'CHANNELS' USED FOR ROUTING
|
chris@163
|
127 // 'sensor' outputs from routing channels of dac~ are passed through here
|
chris@163
|
128 break;
|
chris@163
|
129 } else {
|
chris@163
|
130 // If more than 2 ADC inputs are used in the pd patch, route the analog inputs
|
chris@163
|
131 // i.e. ADC3->analogIn0 etc. (first two are always audio inputs)
|
chris@163
|
132 if(ch >= context->audioChannels) {
|
chris@163
|
133 int m = n/2;
|
chris@163
|
134 float mIn = context->analogIn[m*context->analogChannels + (ch-context->audioChannels)];
|
chris@163
|
135 gHvInputBuffers[ch * context->audioFrames + n] = mIn;
|
chris@163
|
136 } else {
|
chris@163
|
137 gHvInputBuffers[ch * context->audioFrames + n] = context->audioIn[n * context->audioChannels + ch];
|
chris@163
|
138 }
|
chris@163
|
139 }
|
chris@163
|
140 }
|
chris@163
|
141 }
|
chris@163
|
142 }
|
chris@163
|
143
|
chris@163
|
144 // replacement for bang~ object
|
chris@163
|
145 //hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b");
|
chris@163
|
146
|
chris@163
|
147 hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames);
|
chris@163
|
148
|
chris@163
|
149 // Interleave the output data
|
chris@163
|
150 if(gHvOutputBuffers != NULL) {
|
chris@163
|
151 for(int n = 0; n < context->audioFrames; n++) {
|
chris@163
|
152
|
chris@163
|
153 for(int ch = 0; ch < gHvOutputChannels; ch++) {
|
chris@163
|
154 if(ch >= context->audioChannels+context->analogChannels) {
|
chris@163
|
155 // THESE ARE SENSOR OUTPUT 'CHANNELS' USED FOR ROUTING
|
chris@163
|
156 // they are the content of the 'sensor output' dac~ channels
|
chris@163
|
157 } else {
|
chris@163
|
158 if(ch >= context->audioChannels) {
|
chris@163
|
159 int m = n/2;
|
chris@163
|
160 // float mOut = (float)gHvOutputBuffers[ch*numAudioFrames + n];
|
chris@163
|
161 // mOut = constrain(mOut,0.0,1.0);
|
chris@163
|
162 context->analogOut[m * context->analogFrames + (ch-context->audioChannels)] = constrain(gHvOutputBuffers[ch*context->audioFrames + n],0.0,1.0);
|
chris@163
|
163 } else {
|
chris@163
|
164 context->audioOut[n * context->audioChannels + ch] = gHvOutputBuffers[ch * context->audioFrames + n];
|
chris@163
|
165 }
|
chris@163
|
166 }
|
chris@163
|
167 }
|
chris@163
|
168 }
|
chris@163
|
169 }
|
chris@163
|
170
|
chris@163
|
171 }
|
chris@163
|
172
|
chris@163
|
173
|
chris@163
|
174 void cleanup(BeagleRTContext *context, void *userData)
|
chris@163
|
175 {
|
chris@163
|
176
|
chris@163
|
177 hv_bbb_free(gHeavyContext);
|
chris@163
|
178 if(gHvInputBuffers != NULL)
|
chris@163
|
179 free(gHvInputBuffers);
|
chris@163
|
180 if(gHvOutputBuffers != NULL)
|
chris@163
|
181 free(gHvOutputBuffers);
|
chris@163
|
182
|
chris@163
|
183 }
|