Mercurial > hg > beaglert
comparison scripts/hvresources/heavy_render.cpp @ 482:4d5edf7ee953 prerelease
heavy: support for signal-rate digitals and Scope.
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Tue, 21 Jun 2016 14:27:26 +0100 |
parents | 4ff80956c27a |
children | 7f8d1a3e4cef |
comparison
equal
deleted
inserted
replaced
481:def3b8cf9749 | 482:4d5edf7ee953 |
---|---|
11 * | 11 * |
12 */ | 12 */ |
13 | 13 |
14 #include <Bela.h> | 14 #include <Bela.h> |
15 #include <Midi.h> | 15 #include <Midi.h> |
16 #include <Scope.h> | |
16 #include <cmath> | 17 #include <cmath> |
17 #include "Heavy_bbb.h" | 18 #include <Heavy_bbb.h> |
18 #include <string.h> | 19 #include <string.h> |
19 #include <stdlib.h> | 20 #include <stdlib.h> |
20 #include <string.h> | 21 #include <string.h> |
21 #include <DigitalChannelManager.h> | 22 #include <DigitalChannelManager.h> |
22 | 23 |
131 | 132 |
132 /* | 133 /* |
133 * SETUP, RENDER LOOP & CLEANUP | 134 * SETUP, RENDER LOOP & CLEANUP |
134 */ | 135 */ |
135 | 136 |
136 | 137 // 2 audio + (up to)8 analog + (up to) 16 digital + 4 scope outputs |
137 | 138 static const unsigned int gChannelsInUse = 30; |
138 // Midi | 139 static unsigned int gAnalogChannelsInUse = 8; // hard-coded for the moment, TODO: get it at run-time from hv_context |
140 //static const unsigned int gFirstAudioChannel = 0; | |
141 static const unsigned int gFirstAnalogChannel = 2; | |
142 static const unsigned int gFirstDigitalChannel = 10; | |
143 static const unsigned int gFirstScopeChannel = 26; | |
144 static unsigned int gDigitalSigInChannelsInUse; | |
145 static unsigned int gDigitalSigOutChannelsInUse; | |
146 | |
147 // Bela Midi | |
139 Midi midi; | 148 Midi midi; |
140 unsigned int hvMidiHashes[7]; | 149 unsigned int hvMidiHashes[7]; |
150 // Bela Scope | |
151 Scope scope; | |
152 const unsigned int gMaxScopeChannels = 4; | |
153 unsigned int gScopeChannelsInUse; | |
154 float* gScopeOut; | |
141 | 155 |
142 | 156 |
143 bool setup(BelaContext *context, void *userData) { | 157 bool setup(BelaContext *context, void *userData) { |
144 | |
145 printf("top o setup\n"); | |
146 /* HEAVY */ | 158 /* HEAVY */ |
147 hvMidiHashes[kmmNoteOn] = hv_stringToHash("__hv_notein"); | 159 hvMidiHashes[kmmNoteOn] = hv_stringToHash("__hv_notein"); |
148 hvMidiHashes[kmmNoteOff] = hv_stringToHash("noteoff"); // this is handled differently, see the render function | 160 hvMidiHashes[kmmNoteOff] = hv_stringToHash("noteoff"); // this is handled differently, see the render function |
149 hvMidiHashes[kmmControlChange] = hv_stringToHash("__hv_ctlin"); | 161 hvMidiHashes[kmmControlChange] = hv_stringToHash("__hv_ctlin"); |
150 hvMidiHashes[kmmProgramChange] = hv_stringToHash("pgmin"); | 162 hvMidiHashes[kmmProgramChange] = hv_stringToHash("pgmin"); |
151 hvMidiHashes[kmmPolyphonicKeyPressure] = hv_stringToHash("polytouchin"); | 163 hvMidiHashes[kmmPolyphonicKeyPressure] = hv_stringToHash("polytouchin"); |
152 hvMidiHashes[kmmChannelPressure] = hv_stringToHash("touchin"); | 164 hvMidiHashes[kmmChannelPressure] = hv_stringToHash("touchin"); |
153 hvMidiHashes[kmmPitchBend] = hv_stringToHash("bendin"); | 165 hvMidiHashes[kmmPitchBend] = hv_stringToHash("bendin"); |
154 | 166 |
155 printf("after midi o setup\n"); | |
156 gHeavyContext = hv_bbb_new(context->audioSampleRate); | 167 gHeavyContext = hv_bbb_new(context->audioSampleRate); |
157 | 168 |
158 printf("aftet new o setup\n"); | |
159 gHvInputChannels = hv_getNumInputChannels(gHeavyContext); | 169 gHvInputChannels = hv_getNumInputChannels(gHeavyContext); |
160 gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext); | 170 gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext); |
161 | 171 |
162 rt_printf("Starting Heavy context with %d input channels and %d output channels\n", | 172 gScopeChannelsInUse = gHvOutputChannels > gFirstScopeChannel ? |
173 gHvOutputChannels - gFirstScopeChannel : 0; | |
174 gDigitalSigInChannelsInUse = gHvInputChannels > gFirstDigitalChannel ? | |
175 gHvInputChannels - gFirstDigitalChannel : 0; | |
176 gDigitalSigOutChannelsInUse = gHvOutputChannels > gFirstDigitalChannel ? | |
177 gHvOutputChannels - gFirstDigitalChannel - gScopeChannelsInUse: 0; | |
178 | |
179 printf("Starting Heavy context with %d input channels and %d output channels\n", | |
163 gHvInputChannels, gHvOutputChannels); | 180 gHvInputChannels, gHvOutputChannels); |
181 printf("Channels in use:\n"); | |
182 printf("Digital in : %u, Digital out: %u\n", gDigitalSigInChannelsInUse, gDigitalSigOutChannelsInUse); | |
183 printf("Scope out: %u\n", gScopeChannelsInUse); | |
164 | 184 |
165 if(gHvInputChannels != 0) { | 185 if(gHvInputChannels != 0) { |
166 gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float)); | 186 gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float)); |
167 } | 187 } |
168 if(gHvOutputChannels != 0) { | 188 if(gHvOutputChannels != 0) { |
169 gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float)); | 189 gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float)); |
170 } | 190 } |
171 printf("mid o setup\n"); | |
172 | 191 |
173 gInverseSampleRate = 1.0 / context->audioSampleRate; | 192 gInverseSampleRate = 1.0 / context->audioSampleRate; |
174 | 193 |
175 // Set heavy print hook | 194 // Set heavy print hook |
176 hv_setPrintHook(gHeavyContext, printHook); | 195 hv_setPrintHook(gHeavyContext, printHook); |
180 // TODO: change these hardcoded port values and actually change them in the Midi class | 199 // TODO: change these hardcoded port values and actually change them in the Midi class |
181 midi.readFrom(0); | 200 midi.readFrom(0); |
182 midi.writeTo(0); | 201 midi.writeTo(0); |
183 midi.enableParser(true); | 202 midi.enableParser(true); |
184 | 203 |
204 if(gScopeChannelsInUse > 0){ | |
205 // block below copy/pasted from libpd, except | |
206 scope.setup(gScopeChannelsInUse, context->audioSampleRate); | |
207 gScopeOut = new float[gScopeChannelsInUse]; | |
208 } | |
185 // Bela digital | 209 // Bela digital |
186 dcm.setCallback(sendDigitalMessage); | 210 dcm.setCallback(sendDigitalMessage); |
187 if(context->digitalChannels > 0){ | 211 if(context->digitalChannels > 0){ |
188 for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){ | 212 for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){ |
189 dcm.setCallbackArgument(ch, hvDigitalInHashes[ch]); | 213 dcm.setCallbackArgument(ch, hvDigitalInHashes[ch]); |
190 } | 214 } |
191 } | 215 } |
192 // unlike libpd, no need here to bind the bela_digitalOut.. receivers | 216 // unlike libpd, no need here to bind the bela_digitalOut.. receivers |
193 | 217 |
194 printf("end o setup\n"); | |
195 return true; | 218 return true; |
196 } | 219 } |
197 | 220 |
198 | 221 |
199 void render(BelaContext *context, void *userData) | 222 void render(BelaContext *context, void *userData) |
301 } | 324 } |
302 } | 325 } |
303 | 326 |
304 // Bela digital in | 327 // Bela digital in |
305 // note: in multiple places below we assume that the number of digital frames is same as number of audio | 328 // note: in multiple places below we assume that the number of digital frames is same as number of audio |
306 // digital in at message-rate | 329 // Bela digital in at message-rate |
307 dcm.processInput(context->digital, context->digitalFrames); | 330 dcm.processInput(context->digital, context->digitalFrames); |
308 | 331 |
309 // Bela digital in at signal-rate | 332 // Bela digital in at signal-rate |
310 // TODO: not really straightforward to implement as Heavy determines the number of channels in use at compile time | 333 if(gDigitalSigInChannelsInUse > 0) |
311 // on the basis of the number of adc~ / dac~ of the patch ... Maybe we should always include | 334 { |
312 // a dummy [adc~ 27] [dac~ 27] to make sure all channels are always allocated and then leave them all unprocessed ? | 335 unsigned int j, k; |
336 float *p0, *p1; | |
337 const unsigned int gLibpdBlockSize = context->audioFrames; | |
338 const unsigned int audioFrameBase = 0; | |
339 float* gInBuf = gHvInputBuffers; | |
340 // block below copy/pasted from libpd, except | |
341 // 16 has been replaced with gDigitalSigInChannelsInUse | |
342 for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) { | |
343 unsigned int digitalFrame = audioFrameBase + j; | |
344 for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstDigitalChannel; | |
345 k < gDigitalSigInChannelsInUse; ++k, p1 += gLibpdBlockSize) { | |
346 if(dcm.isSignalRate(k) && dcm.isInput(k)){ // only process input channels that are handled at signal rate | |
347 *p1 = digitalRead(context, digitalFrame, k); | |
348 } | |
349 } | |
350 } | |
351 } | |
352 | |
313 | 353 |
314 // replacement for bang~ object | 354 // replacement for bang~ object |
315 //hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b"); | 355 //hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b"); |
316 | 356 |
317 hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames); | 357 hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames); |
318 | 358 |
319 // Bela digital out | 359 // Bela digital out |
320 // digital out at signal-rate | 360 // Bela digital out at signal-rate |
321 // TODO: see note above. | 361 if(gDigitalSigOutChannelsInUse > 0) |
322 | 362 { |
323 // digital out at message-rate | 363 unsigned int j, k; |
364 float *p0, *p1; | |
365 const unsigned int gLibpdBlockSize = context->audioFrames; | |
366 const unsigned int audioFrameBase = 0; | |
367 float* gOutBuf = gHvOutputBuffers; | |
368 // block below copy/pasted from libpd, except | |
369 // context->digitalChannels has been replaced with gDigitalSigOutChannelsInUse | |
370 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) { | |
371 unsigned int digitalFrame = (audioFrameBase + j); | |
372 for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstDigitalChannel; | |
373 k < gDigitalSigOutChannelsInUse; k++, p1 += gLibpdBlockSize) { | |
374 if(dcm.isSignalRate(k) && dcm.isOutput(k)){ // only process output channels that are handled at signal rate | |
375 digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5); | |
376 } | |
377 } | |
378 } | |
379 } | |
380 // Bela digital out at message-rate | |
324 dcm.processOutput(context->digital, context->digitalFrames); | 381 dcm.processOutput(context->digital, context->digitalFrames); |
382 | |
383 // Bela scope | |
384 if(gScopeChannelsInUse > 0) | |
385 { | |
386 unsigned int j, k; | |
387 float *p0, *p1; | |
388 const unsigned int gLibpdBlockSize = context->audioFrames; | |
389 const unsigned int audioFrameBase = 0; | |
390 float* gOutBuf = gHvOutputBuffers; | |
391 | |
392 // block below copy/pasted from libpd | |
393 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) { | |
394 for (k = 0, p1 = p0 + gLibpdBlockSize * gFirstScopeChannel; k < gScopeChannelsInUse; k++, p1 += gLibpdBlockSize) { | |
395 gScopeOut[k] = *p1; | |
396 } | |
397 scope.log(gScopeOut[0], gScopeOut[1], gScopeOut[2], gScopeOut[3]); | |
398 } | |
399 } | |
325 | 400 |
326 // Interleave the output data | 401 // Interleave the output data |
327 if(gHvOutputBuffers != NULL) { | 402 if(gHvOutputBuffers != NULL) { |
328 for(unsigned int n = 0; n < context->audioFrames; n++) { | 403 for(unsigned int n = 0; n < context->audioFrames; n++) { |
329 | 404 |
352 hv_bbb_free(gHeavyContext); | 427 hv_bbb_free(gHeavyContext); |
353 if(gHvInputBuffers != NULL) | 428 if(gHvInputBuffers != NULL) |
354 free(gHvInputBuffers); | 429 free(gHvInputBuffers); |
355 if(gHvOutputBuffers != NULL) | 430 if(gHvOutputBuffers != NULL) |
356 free(gHvOutputBuffers); | 431 free(gHvOutputBuffers); |
357 | 432 delete[] gScopeOut; |
358 } | 433 } |