Mercurial > hg > beaglert
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){ |