chris@160: /* chris@160: * render.cpp chris@160: * chris@160: * Template render.cpp file for on-board heavy compiling chris@160: * chris@160: * N.B. this is currently *not* compatible with foleyDesigner source files! chris@160: * chris@160: * Created on: November 5, 2015 chris@160: * chris@160: * Christian Heinrichs chris@160: * chris@160: */ chris@160: chris@160: #include chris@160: #include chris@160: #include "../include/Utilities.h" chris@160: #include "Heavy_bbb.h" chris@160: chris@160: /* chris@160: * HEAVY CONTEXT & BUFFERS chris@160: */ chris@160: chris@160: Hv_bbb *gHeavyContext; chris@160: float *gHvInputBuffers = NULL, *gHvOutputBuffers = NULL; chris@160: int gHvInputChannels = 0, gHvOutputChannels = 0; chris@160: chris@160: float gInverseSampleRate; chris@160: chris@160: /* chris@160: * HEAVY FUNCTIONS chris@160: */ chris@160: chris@160: void printHook(double timestampSecs, const char *printLabel, const char *msgString, void *userData) { chris@160: printf("Message from Heavy patch: [@ %.3f] %s: %s\n", timestampSecs, printLabel, msgString); chris@160: } chris@160: chris@160: static void sendHook( chris@160: double timestamp, // in milliseconds chris@160: const char *receiverName, chris@160: const HvMessage *const m, chris@160: void *userData) { chris@160: chris@160: // only react to messages sent to receivers named "hello" chris@160: if (!strncmp(receiverName, "hello", 5)) { chris@160: } chris@160: chris@160: } chris@160: chris@160: /* chris@166: * SETUP, RENDER LOOP & CLEANUP chris@160: */ chris@160: chris@160: bool setup(BeagleRTContext *context, void *userData) { chris@160: chris@160: /* HEAVY */ chris@160: chris@160: gHeavyContext = hv_bbb_new(context->audioSampleRate); chris@160: chris@160: gHvInputChannels = hv_getNumInputChannels(gHeavyContext); chris@160: gHvOutputChannels = hv_getNumOutputChannels(gHeavyContext); chris@160: chris@160: rt_printf("Starting Heavy context with %d input channels and %d output channels\n", chris@160: gHvInputChannels, gHvOutputChannels); chris@160: chris@160: if(gHvInputChannels != 0) { chris@160: gHvInputBuffers = (float *)calloc(gHvInputChannels * context->audioFrames,sizeof(float)); chris@160: } chris@160: if(gHvOutputChannels != 0) { chris@160: gHvOutputBuffers = (float *)calloc(gHvOutputChannels * context->audioFrames,sizeof(float)); chris@160: } chris@160: chris@160: gInverseSampleRate = 1.0 / context->audioSampleRate; chris@160: chris@160: // Set heavy print hook chris@160: hv_setPrintHook(gHeavyContext, &printHook); chris@160: // Set heavy send hook chris@160: hv_setSendHook(gHeavyContext, sendHook); chris@160: chris@160: return true; chris@160: } chris@160: chris@160: chris@160: void render(BeagleRTContext *context, void *userData) chris@160: { chris@160: chris@160: // De-interleave the data chris@160: if(gHvInputBuffers != NULL) { chris@160: for(int n = 0; n < context->audioFrames; n++) { chris@160: for(int ch = 0; ch < gHvInputChannels; ch++) { chris@160: if(ch >= context->audioChannels+context->analogChannels) { chris@160: // THESE ARE PARAMETER INPUT 'CHANNELS' USED FOR ROUTING chris@160: // 'sensor' outputs from routing channels of dac~ are passed through here chris@160: break; chris@160: } else { chris@160: // If more than 2 ADC inputs are used in the pd patch, route the analog inputs chris@160: // i.e. ADC3->analogIn0 etc. (first two are always audio inputs) chris@160: if(ch >= context->audioChannels) { chris@160: int m = n/2; chris@160: float mIn = context->analogIn[m*context->analogChannels + (ch-context->audioChannels)]; chris@160: gHvInputBuffers[ch * context->audioFrames + n] = mIn; chris@160: } else { chris@160: gHvInputBuffers[ch * context->audioFrames + n] = context->audioIn[n * context->audioChannels + ch]; chris@160: } chris@160: } chris@160: } chris@160: } chris@160: } chris@160: chris@160: // replacement for bang~ object chris@160: //hv_vscheduleMessageForReceiver(gHeavyContext, "bbb_bang", 0.0f, "b"); chris@160: chris@160: hv_bbb_process_inline(gHeavyContext, gHvInputBuffers, gHvOutputBuffers, context->audioFrames); chris@160: chris@160: // Interleave the output data chris@160: if(gHvOutputBuffers != NULL) { chris@160: for(int n = 0; n < context->audioFrames; n++) { chris@160: chris@160: for(int ch = 0; ch < gHvOutputChannels; ch++) { chris@160: if(ch >= context->audioChannels+context->analogChannels) { chris@160: // THESE ARE SENSOR OUTPUT 'CHANNELS' USED FOR ROUTING chris@160: // they are the content of the 'sensor output' dac~ channels chris@160: } else { chris@160: if(ch >= context->audioChannels) { chris@160: int m = n/2; chris@160: context->analogOut[m * context->analogFrames + (ch-context->audioChannels)] = constrain(gHvOutputBuffers[ch*context->audioFrames + n],0.0,1.0); chris@160: } else { chris@160: context->audioOut[n * context->audioChannels + ch] = gHvOutputBuffers[ch * context->audioFrames + n]; chris@160: } chris@160: } chris@160: } chris@160: } chris@160: } chris@160: chris@160: } chris@160: chris@160: chris@160: void cleanup(BeagleRTContext *context, void *userData) chris@160: { chris@160: chris@160: hv_bbb_free(gHeavyContext); chris@160: if(gHvInputBuffers != NULL) chris@160: free(gHvInputBuffers); chris@160: if(gHvOutputBuffers != NULL) chris@160: free(gHvOutputBuffers); chris@160: chris@160: }