comparison examples/basic_libpd/render.cpp @ 337:5e2780bfbfed prerelease

Clean up of basic_libpd
author Giulio Moro <giuliomoro@yahoo.it>
date Sun, 05 Jun 2016 20:28:43 +0100
parents a9905703219d
children 1802f99cd77f
comparison
equal deleted inserted replaced
336:6599a9978ac4 337:5e2780bfbfed
22 // 22 //
23 // userData holds an opaque pointer to a data structure that was passed 23 // userData holds an opaque pointer to a data structure that was passed
24 // in from the call to initAudio(). 24 // in from the call to initAudio().
25 // 25 //
26 // Return true on success; returning false halts the program. 26 // Return true on success; returning false halts the program.
27 #define DEFDACBLKSIZE 8u //make sure this matches the one used to compile libpd 27 unsigned int gLibPdBlockSize; //make sure this matches the one used to compile libpd
28 28
29 int gChannelsInUse = 10; 29 unsigned int gChannelsInUse = 10;
30 int gBufLength; 30 int gBufLength;
31 31
32 float* gInBuf; 32 float* gInBuf;
33 float* gOutBuf; 33 float* gOutBuf;
34 34
41 } 41 }
42 42
43 UdpServer udpServer; 43 UdpServer udpServer;
44 44
45 void udpRead(){ 45 void udpRead(){
46 char dest[100] = {0};
47 while(!gShouldStop){ 46 while(!gShouldStop){
47 // check for modified sockets/file descriptors
48 // (libpd would normally do this every block WITHIN the audio thread)
49 // not sure if this is thread-safe at the moment
48 libpd_sys_microsleep(0); 50 libpd_sys_microsleep(0);
49 usleep(1000); 51 usleep(1000);
50 } 52 }
51 } 53 }
52 #define PARSE_MIDI 54 #define PARSE_MIDI
53 AuxiliaryTask udpReadTask; 55 AuxiliaryTask udpReadTask;
54 Midi midi; 56 Midi midi;
57
55 bool setup(BelaContext *context, void *userData) 58 bool setup(BelaContext *context, void *userData)
56 { 59 {
57 midi.readFrom(0); 60 midi.readFrom(0);
58 midi.writeTo(0); 61 midi.writeTo(0);
59 #ifdef PARSE_MIDI 62 #ifdef PARSE_MIDI
62 midi.enableParser(false); 65 midi.enableParser(false);
63 #endif /* PARSE_MIDI */ 66 #endif /* PARSE_MIDI */
64 gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse); 67 gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse);
65 udpServer.bindToPort(1234); 68 udpServer.bindToPort(1234);
66 69
67 // check that we are not running with a blocksize smaller than DEFDACBLKSIZE 70 gLibPdBlockSize = libpd_blocksize();
71 // check that we are not running with a blocksize smaller than gLibPdBlockSize
68 // it would still work, but the load would be executed unevenly between calls to render 72 // it would still work, but the load would be executed unevenly between calls to render
69 if(context->audioFrames < DEFDACBLKSIZE){ 73 if(context->audioFrames < gLibPdBlockSize){
70 fprintf(stderr, "Error: minimum block size must be %d\n", DEFDACBLKSIZE); 74 fprintf(stderr, "Error: minimum block size must be %d\n", gLibPdBlockSize);
71 return false; 75 return false;
72 } 76 }
73
74 // check that the sampling rate of the analogs is the same as audio if running with
75 // more than 2 channels (that is with analog). If we fix the TODO in render, then
76 // this test is not needed.
77 // if(context->analogFrames != context->audioFrames){
78 // fprintf(stderr, "Error: analog and audio sampling rates must be the same\n");
79 // return false;
80 // }
81 //following lines borrowed from libpd/samples/c/pdtest/pdtest.c
82 // init pd 77 // init pd
83 libpd_set_printhook(Bela_printHook); // set this before calling libpd_init 78 libpd_set_printhook(Bela_printHook); // set this before calling libpd_init
84 libpd_set_noteonhook(pdnoteon); 79 libpd_set_noteonhook(pdnoteon);
85 libpd_init(); 80 libpd_init();
86 //TODO: analyse the ASCII of the patch file and find the in/outs to use 81 //TODO: analyse the ASCII of the patch file and find the in/outs to use
88 83
89 libpd_start_message(1); // one entry in list 84 libpd_start_message(1); // one entry in list
90 libpd_add_float(1.0f); 85 libpd_add_float(1.0f);
91 libpd_finish_message("pd", "dsp"); 86 libpd_finish_message("pd", "dsp");
92 87
93 gBufLength = max(DEFDACBLKSIZE, context->audioFrames); 88 gBufLength = max((uint32_t)gLibPdBlockSize, context->audioFrames);
94 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength; 89 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength;
95 gInBuf = (float*)malloc(bufferSize); 90 gInBuf = (float*)malloc(bufferSize);
96 gOutBuf = (float*)malloc(bufferSize); 91 gOutBuf = (float*)malloc(bufferSize);
97 // no need to memset to zero 92 // no need to memset to zero
98 93
175 int channel = message.getChannel(); 170 int channel = message.getChannel();
176 int value = (message.getDataByte(1) << 7)| message.getDataByte(0); 171 int value = (message.getDataByte(1) << 7)| message.getDataByte(0);
177 libpd_pitchbend(channel, value); 172 libpd_pitchbend(channel, value);
178 break; 173 break;
179 } 174 }
175 case kmmNone:
176 case kmmAny:
177 break;
180 } 178 }
181 } 179 }
182 #else 180 #else
183 int input; 181 int input;
184 while((input = midi.getInput()) >= 0){ 182 while((input = midi.getInput()) >= 0){
185 libpd_midibyte(0, input); 183 libpd_midibyte(0, input);
186 rt_printf("input: %d\n", input); 184 rt_printf("input: %d\n", input);
187 } 185 }
188 #endif /* PARSE_MIDI */ 186 #endif /* PARSE_MIDI */
189 static int inW = 0; 187 static unsigned int inW = 0;
190 static int outR = 0; 188 static unsigned int outR = 0;
191 /* 189 /*
192 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers 190 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers
193 * and the blocksize of Bela is the same as DEFDACBLKSIZE, then you probably 191 * and the blocksize of Bela is the same as gLibPdBlockSize, then you probably
194 * do not need the for loops before and after libpd_process_float, so you can save quite some 192 * do not need the for loops before and after libpd_process_float, so you can save quite some
195 * memory operations. 193 * memory operations.
196 */ 194 */
197 static int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels); 195 static unsigned int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels);
198 // rt_printf("channelsInUse: %d, analogChannels in Use: %d\n", gChannelsInUse, analogChannelsInUse); 196 // rt_printf("channelsInUse: %d, analogChannels in Use: %d\n", gChannelsInUse, analogChannelsInUse);
199 for(unsigned int n = 0; n < context->audioFrames; ++n){ //pd buffers are interleaved 197 for(unsigned int n = 0; n < context->audioFrames; ++n){ //pd buffers are interleaved
200 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio 198 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio
201 gInBuf[inW++] = audioRead(context, n, ch); 199 gInBuf[inW++] = audioRead(context, n, ch);
202 } 200 }
203 // then analogs 201 // then analogs
204 // this loop resamples by ZOH, as needed, using m 202 // this loop resamples by ZOH, as needed, using m
205 if(context->analogChannels == 8 ){ //hold the value for two frames 203 if(context->analogChannels == 8 ){ //hold the value for two frames
206 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 204 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
207 gInBuf[inW++] = analogRead(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even 205 gInBuf[inW++] = analogRead(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even
208 } 206 }
209 } else if(context->analogChannels == 4){ //write every frame 207 } else if(context->analogChannels == 4){ //write every frame
210 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 208 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
211 gInBuf[inW++] = analogRead(context, n, analogCh); 209 gInBuf[inW++] = analogRead(context, n, analogCh);
212 } 210 }
213 } else if(context->analogChannels == 2){ //drop every other frame 211 } else if(context->analogChannels == 2){ //drop every other frame
214 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 212 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
215 gInBuf[inW++] = analogRead(context, n*2, analogCh); 213 gInBuf[inW++] = analogRead(context, n*2, analogCh);
216 } 214 }
217 } 215 }
218 if(inW == gBufLength * gChannelsInUse){ 216 if(inW == gBufLength * gChannelsInUse){
219 inW = 0; 217 inW = 0;
220 } 218 }
221 } 219 }
222 // rt_printf("inW %d\n", inW); 220 // rt_printf("inW %d\n", inW);
223 if(inW == 0){ //if the buffer is full, process it 221 if(inW == 0){ //if the buffer is full, process it
224 static int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE; 222 static int numberOfPdBlocksToProcess = gBufLength/gLibPdBlockSize;
225 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf); 223 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf);
226 outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time 224 outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time
227 } 225 }
228 226
229 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved 227 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved
239 } else { 237 } else {
240 // discard this sample 238 // discard this sample
241 } 239 }
242 } 240 }
243 } else if(context->analogChannels == 4){ //write every frame 241 } else if(context->analogChannels == 4){ //write every frame
244 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 242 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){
245 float analogOut = gOutBuf[outR++]; 243 float analogOut = gOutBuf[outR++];
246 analogWrite(context, n, analogCh, analogOut); 244 analogWrite(context, n, analogCh, analogOut);
247 } 245 }
248 } else if(context->analogChannels == 2){ //write twice every frame 246 } else if(context->analogChannels == 2){ //write twice every frame
249 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 247 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){