annotate projects/basic_libpd/render.cpp @ 269:ac8eb07afcf5

Oxygen text added to each render.cpp file for the default projects. Text includes project explanation from Wiki, edited in places. Empty project added as a default project. Doxyfile updated. Each of the project locations added to INPUT configuration option. Consider just watching the whole project file so all new projects are automatically pulled through.
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:40:16 +0100
parents 600355cf4ed5
children
rev   line source
giuliomoro@230 1 /*
giuliomoro@230 2 * render.cpp
giuliomoro@230 3 *
giuliomoro@230 4 * Created on: Oct 24, 2014
giuliomoro@230 5 * Author: parallels
giuliomoro@230 6 */
giuliomoro@230 7
giuliomoro@230 8 #include <BeagleRT.h>
giuliomoro@230 9 #include <cmath>
giuliomoro@230 10 #include <Utilities.h>
giuliomoro@230 11 #include <I2c_Codec.h>
giuliomoro@230 12 #include <PRU.h>
giuliomoro@230 13 #include <stdio.h>
giuliomoro@230 14 #include "z_libpd.h"
giuliomoro@230 15 #include <UdpServer.h>
giuliomoro@230 16
giuliomoro@230 17 // setup() is called once before the audio rendering starts.
giuliomoro@230 18 // Use it to perform any initialisation and allocation which is dependent
giuliomoro@230 19 // on the period size or sample rate.
giuliomoro@230 20 //
giuliomoro@230 21 // userData holds an opaque pointer to a data structure that was passed
giuliomoro@230 22 // in from the call to initAudio().
giuliomoro@230 23 //
giuliomoro@230 24 // Return true on success; returning false halts the program.
giuliomoro@230 25 #define DEFDACBLKSIZE 8u //make sure this matches the one used to compile libpd
giuliomoro@230 26
giuliomoro@232 27 int gChannelsInUse = 10;
giuliomoro@230 28 int gBufLength;
giuliomoro@230 29
giuliomoro@230 30 float* gInBuf;
giuliomoro@230 31 float* gOutBuf;
giuliomoro@230 32
giuliomoro@230 33 void pdnoteon(int ch, int pitch, int vel) {
giuliomoro@230 34 printf("noteon: %d %d %d\n", ch, pitch, vel);
giuliomoro@230 35 }
giuliomoro@230 36
giuliomoro@230 37 void BeagleRT_printHook(const char *recv){
giuliomoro@230 38 rt_printf("%s", recv);
giuliomoro@230 39 }
giuliomoro@230 40
giuliomoro@230 41 UdpServer udpServer;
giuliomoro@230 42
giuliomoro@230 43 void udpRead(){
giuliomoro@230 44 char dest[100] = {0};
giuliomoro@230 45 while(!gShouldStop){
giuliomoro@230 46 libpd_sys_microsleep(0);
giuliomoro@230 47 usleep(1000);
giuliomoro@230 48 }
giuliomoro@230 49 }
giuliomoro@230 50
giuliomoro@230 51 AuxiliaryTask udpReadTask;
giuliomoro@230 52 bool setup(BeagleRTContext *context, void *userData)
giuliomoro@230 53 {
giuliomoro@232 54 gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse);
giuliomoro@230 55 udpServer.bindToPort(1234);
giuliomoro@230 56
giuliomoro@230 57 // check that we are not running with a blocksize smaller than DEFDACBLKSIZE
giuliomoro@230 58 // it would still work, but the load would be executed unevenly between calls to render
giuliomoro@230 59 if(context->audioFrames < DEFDACBLKSIZE){
giuliomoro@230 60 fprintf(stderr, "Error: minimum block size must be %d\n", DEFDACBLKSIZE);
giuliomoro@230 61 return false;
giuliomoro@230 62 }
giuliomoro@230 63
giuliomoro@230 64 // check that the sampling rate of the analogs is the same as audio if running with
giuliomoro@230 65 // more than 2 channels (that is with analog). If we fix the TODO in render, then
giuliomoro@230 66 // this test is not needed.
giuliomoro@232 67 // if(context->analogFrames != context->audioFrames){
giuliomoro@232 68 // fprintf(stderr, "Error: analog and audio sampling rates must be the same\n");
giuliomoro@232 69 // return false;
giuliomoro@232 70 // }
giuliomoro@230 71 //following lines borrowed from libpd/samples/c/pdtest/pdtest.c
giuliomoro@230 72 // init pd
giuliomoro@230 73 libpd_set_printhook(BeagleRT_printHook); // set this before calling libpd_init
giuliomoro@230 74 libpd_set_noteonhook(pdnoteon);
giuliomoro@230 75 libpd_init();
giuliomoro@230 76 //TODO: analyse the ASCII of the patch file and find the in/outs to use
giuliomoro@230 77 libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate);
giuliomoro@230 78
giuliomoro@230 79 libpd_start_message(1); // one entry in list
giuliomoro@230 80 libpd_add_float(1.0f);
giuliomoro@230 81 libpd_finish_message("pd", "dsp");
giuliomoro@230 82
giuliomoro@230 83 gBufLength = max(DEFDACBLKSIZE, context->audioFrames);
giuliomoro@230 84 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength;
giuliomoro@230 85 gInBuf = (float*)malloc(bufferSize);
giuliomoro@230 86 gOutBuf = (float*)malloc(bufferSize);
giuliomoro@230 87 // no need to memset to zero
giuliomoro@230 88
giuliomoro@230 89 char file[] = "_main.pd";
giuliomoro@230 90 char folder[] = "./";
giuliomoro@230 91 // open patch [; pd open file folder(
giuliomoro@230 92 libpd_openfile(file, folder);
giuliomoro@230 93
giuliomoro@230 94 udpReadTask = BeagleRT_createAuxiliaryTask(udpRead, 60, "udpReadTask");
giuliomoro@230 95 BeagleRT_scheduleAuxiliaryTask(udpReadTask);
giuliomoro@230 96 return true;
giuliomoro@230 97 }
giuliomoro@230 98
giuliomoro@230 99 // render() is called regularly at the highest priority by the audio engine.
giuliomoro@230 100 // Input and output are given from the audio hardware and the other
giuliomoro@230 101 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
giuliomoro@230 102 // will be 0.
giuliomoro@230 103 BeagleRTContext *c;
giuliomoro@230 104 void render(BeagleRTContext *context, void *userData)
giuliomoro@230 105 {
giuliomoro@230 106 static int inW = 0;
giuliomoro@230 107 static int outR = 0;
giuliomoro@230 108 /*
giuliomoro@230 109 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers
giuliomoro@230 110 * and the blocksize of Bela is the same as DEFDACBLKSIZE, then you probably
giuliomoro@230 111 * do not need the for loops before and after libpd_process_float, so you can save quite some
giuliomoro@230 112 * memory operations.
giuliomoro@230 113 */
giuliomoro@232 114 static int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels);
giuliomoro@232 115 // rt_printf("channelsInUse: %d, analogChannels in Use: %d\n", gChannelsInUse, analogChannelsInUse);
giuliomoro@232 116 for(unsigned int n = 0; n < context->audioFrames; ++n){ //pd buffers are interleaved
giuliomoro@232 117 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio
giuliomoro@232 118 gInBuf[inW++] = audioReadFrame(context, n, ch);
giuliomoro@230 119 }
giuliomoro@232 120 // then analogs
giuliomoro@232 121 // this loop resamples by ZOH, as needed, using m
giuliomoro@232 122 if(context->analogChannels == 8 ){ //hold the value for two frames
giuliomoro@232 123 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
giuliomoro@232 124 gInBuf[inW++] = analogReadFrame(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even
giuliomoro@232 125 }
giuliomoro@232 126 } else if(context->analogChannels == 4){ //write every frame
giuliomoro@232 127 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
giuliomoro@232 128 gInBuf[inW++] = analogReadFrame(context, n, analogCh);
giuliomoro@232 129 }
giuliomoro@232 130 } else if(context->analogChannels == 2){ //drop every other frame
giuliomoro@232 131 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
giuliomoro@232 132 gInBuf[inW++] = analogReadFrame(context, n*2, analogCh);
giuliomoro@232 133 }
giuliomoro@230 134 }
giuliomoro@230 135 if(inW == gBufLength * gChannelsInUse){
giuliomoro@230 136 inW = 0;
giuliomoro@230 137 }
giuliomoro@230 138 }
giuliomoro@232 139 // rt_printf("inW %d\n", inW);
giuliomoro@230 140 if(inW == 0){ //if the buffer is full, process it
giuliomoro@232 141 static int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE;
giuliomoro@230 142 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf);
giuliomoro@232 143 outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time
giuliomoro@230 144 }
giuliomoro@230 145
giuliomoro@230 146 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved
giuliomoro@232 147 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){
giuliomoro@232 148 audioWriteFrame(context, n, ch, gOutBuf[outR++]);
giuliomoro@230 149 }
giuliomoro@232 150 //and analogs
giuliomoro@232 151 if(context->analogChannels == 8){
giuliomoro@232 152 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
giuliomoro@232 153 float analogOut = gOutBuf[outR++];
giuliomoro@232 154 if((n&1) == 0){//write every two frames
giuliomoro@232 155 analogWriteFrame(context, n/2, analogCh, analogOut);
giuliomoro@232 156 } else {
giuliomoro@232 157 // discard this sample
giuliomoro@232 158 }
giuliomoro@232 159 }
giuliomoro@232 160 } else if(context->analogChannels == 4){ //write every frame
giuliomoro@232 161 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
giuliomoro@232 162 float analogOut = gOutBuf[outR++];
giuliomoro@232 163 analogWriteFrame(context, n, analogCh, analogOut);
giuliomoro@232 164 }
giuliomoro@232 165 } else if(context->analogChannels == 2){ //write twice every frame
giuliomoro@232 166 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
giuliomoro@232 167 float analogOut = gOutBuf[outR++];
giuliomoro@232 168 analogWriteFrame(context, 2*n, analogCh, analogOut);
giuliomoro@232 169 analogWriteFrame(context, 2*n + 1, analogCh, analogOut);
giuliomoro@232 170 }
giuliomoro@230 171 }
giuliomoro@230 172 if(outR == gBufLength * gChannelsInUse){
giuliomoro@230 173 outR = 0;
giuliomoro@230 174 }
giuliomoro@230 175 }
giuliomoro@232 176 // rt_printf("outR %d, analogChannelsInUse %d, channelsInUse %d\n",
giuliomoro@232 177 // outR , analogChannelsInUse, gChannelsInUse);
giuliomoro@230 178 }
giuliomoro@232 179
giuliomoro@230 180 // cleanup() is called once at the end, after the audio has stopped.
giuliomoro@230 181 // Release any resources that were allocated in setup().
giuliomoro@230 182
giuliomoro@230 183 void cleanup(BeagleRTContext *context, void *userData)
giuliomoro@230 184 {
giuliomoro@230 185 free(gInBuf);
giuliomoro@230 186 free(gOutBuf);
giuliomoro@230 187 }