Mercurial > hg > beaglert
comparison examples/basic_libpd/render.cpp @ 340:69d86429a1cf prerelease
More on libpd support for threads
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Mon, 06 Jun 2016 02:37:30 +0100 |
parents | 1802f99cd77f |
children | 7af9c5be3434 |
comparison
equal
deleted
inserted
replaced
339:02e6f96466f8 | 340:69d86429a1cf |
---|---|
23 // | 23 // |
24 // userData holds an opaque pointer to a data structure that was passed | 24 // userData holds an opaque pointer to a data structure that was passed |
25 // in from the call to initAudio(). | 25 // in from the call to initAudio(). |
26 // | 26 // |
27 // Return true on success; returning false halts the program. | 27 // Return true on success; returning false halts the program. |
28 unsigned int gLibPdBlockSize; //make sure this matches the one used to compile libpd | 28 unsigned int gLibpdBlockSize; //make sure this matches the one used to compile libpd |
29 | 29 |
30 unsigned int gChannelsInUse = 10; | 30 unsigned int gChannelsInUse = 10; |
31 int gBufLength; | 31 int gBufLength; |
32 | 32 |
33 float* gInBuf; | 33 float* gInBuf; |
41 rt_printf("%s", recv); | 41 rt_printf("%s", recv); |
42 } | 42 } |
43 | 43 |
44 UdpServer udpServer; | 44 UdpServer udpServer; |
45 | 45 |
46 void udpRead(){ | 46 void libpdReadFilesLoop(){ |
47 while(!gShouldStop){ | 47 while(!gShouldStop){ |
48 // check for modified sockets/file descriptors | 48 // check for modified sockets/file descriptors |
49 // (libpd would normally do this every block WITHIN the audio thread) | 49 // (libpd would normally do this every block WITHIN the audio thread) |
50 // not sure if this is thread-safe at the moment | 50 // not sure if this is thread-safe at the moment |
51 libpd_sys_microsleep(0); | 51 libpd_sys_microsleep(0); |
52 usleep(1000); | 52 usleep(1000); |
53 } | 53 } |
54 } | 54 } |
55 | |
55 #define PARSE_MIDI | 56 #define PARSE_MIDI |
56 AuxiliaryTask udpReadTask; | 57 AuxiliaryTask libpdReadFilesTask; |
58 AuxiliaryTask libpdProcessMessageQueueTask; | |
59 AuxiliaryTask libpdProcessMidiQueueTask; | |
57 Midi midi; | 60 Midi midi; |
58 | 61 |
59 bool setup(BelaContext *context, void *userData) | 62 bool setup(BelaContext *context, void *userData) |
60 { | 63 { |
61 midi.readFrom(0); | 64 midi.readFrom(0); |
66 midi.enableParser(false); | 69 midi.enableParser(false); |
67 #endif /* PARSE_MIDI */ | 70 #endif /* PARSE_MIDI */ |
68 gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse); | 71 gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse); |
69 udpServer.bindToPort(1234); | 72 udpServer.bindToPort(1234); |
70 | 73 |
71 gLibPdBlockSize = libpd_blocksize(); | 74 gLibpdBlockSize = libpd_blocksize(); |
72 // check that we are not running with a blocksize smaller than gLibPdBlockSize | 75 // check that we are not running with a blocksize smaller than gLibPdBlockSize |
73 // it would still work, but the load would be executed unevenly between calls to render | 76 // it would still work, but the load would be executed unevenly between calls to render |
74 if(context->audioFrames < gLibPdBlockSize){ | 77 if(context->audioFrames < gLibpdBlockSize){ |
75 fprintf(stderr, "Error: minimum block size must be %d\n", gLibPdBlockSize); | 78 fprintf(stderr, "Error: minimum block size must be %d\n", gLibpdBlockSize); |
76 return false; | 79 return false; |
77 } | 80 } |
78 // init pd | 81 // init pd |
79 libpd_set_queued_printhook(Bela_printHook); // set this before calling libpd_init | 82 libpd_set_queued_printhook(Bela_printHook); // set this before calling libpd_init |
80 libpd_set_queued_noteonhook(pdnoteon); | 83 libpd_set_queued_noteonhook(pdnoteon); |
84 //TODO: add hooks for other midi events and generate MIDI output appropriately | |
81 libpd_queued_init(); | 85 libpd_queued_init(); |
82 //TODO: analyse the ASCII of the patch file and find the in/outs to use | 86 //TODO: ideally, we would analyse the ASCII of the patch file and find the in/outs to use |
83 libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate); | 87 libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate); |
84 | 88 |
85 libpd_start_message(1); // one entry in list | 89 libpd_start_message(1); // one entry in list |
86 libpd_add_float(1.0f); | 90 libpd_add_float(1.0f); |
87 libpd_finish_message("pd", "dsp"); | 91 libpd_finish_message("pd", "dsp"); |
88 | 92 |
89 gBufLength = max((uint32_t)gLibPdBlockSize, context->audioFrames); | 93 gBufLength = max(gLibpdBlockSize, context->audioFrames); |
90 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength; | 94 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength; |
91 gInBuf = (float*)malloc(bufferSize); | 95 gInBuf = (float*)malloc(bufferSize); |
92 gOutBuf = (float*)malloc(bufferSize); | 96 gOutBuf = (float*)malloc(bufferSize); |
93 // no need to memset to zero | 97 // no need to memset to zero |
94 | 98 |
95 char file[] = "_main.pd"; | 99 char file[] = "_main.pd"; |
96 char folder[] = "./"; | 100 char folder[] = "./"; |
97 // open patch [; pd open file folder( | 101 // open patch [; pd open file folder( |
98 libpd_openfile(file, folder); | 102 libpd_openfile(file, folder); |
99 | 103 |
100 udpReadTask = Bela_createAuxiliaryTask(udpRead, 60, "udpReadTask"); | 104 libpdReadFilesTask = Bela_createAuxiliaryTask(libpdReadFilesLoop, 60, "libpdReadFiles"); |
101 Bela_scheduleAuxiliaryTask(udpReadTask); | 105 Bela_scheduleAuxiliaryTask(libpdReadFilesTask); |
106 | |
107 // Higher priority for the midi queue and lower priority for the message queue. Adjust to taste | |
108 libpdProcessMidiQueueTask = Bela_createAuxiliaryTask(libpd_queued_receive_midi_messages, 80, "libpdProcessMidiQueue"); | |
109 libpdProcessMessageQueueTask = Bela_createAuxiliaryTask(libpd_queued_receive_pd_messages, 70, "libpdProcessMessageQueue"); | |
102 return true; | 110 return true; |
103 } | 111 } |
104 | 112 |
105 // render() is called regularly at the highest priority by the audio engine. | 113 // render() is called regularly at the highest priority by the audio engine. |
106 // Input and output are given from the audio hardware and the other | 114 // Input and output are given from the audio hardware and the other |
180 } | 188 } |
181 #else | 189 #else |
182 int input; | 190 int input; |
183 while((input = midi.getInput()) >= 0){ | 191 while((input = midi.getInput()) >= 0){ |
184 libpd_midibyte(0, input); | 192 libpd_midibyte(0, input); |
185 rt_printf("input: %d\n", input); | |
186 } | 193 } |
187 #endif /* PARSE_MIDI */ | 194 #endif /* PARSE_MIDI */ |
195 | |
188 static unsigned int inW = 0; | 196 static unsigned int inW = 0; |
189 static unsigned int outR = 0; | 197 static unsigned int outR = 0; |
190 /* | 198 /* |
191 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers | 199 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers |
192 * and the blocksize of Bela is the same as gLibPdBlockSize, then you probably | 200 * and the blocksize of Bela is the same as gLibPdBlockSize, then you probably |
218 inW = 0; | 226 inW = 0; |
219 } | 227 } |
220 } | 228 } |
221 // rt_printf("inW %d\n", inW); | 229 // rt_printf("inW %d\n", inW); |
222 if(inW == 0){ //if the buffer is full, process it | 230 if(inW == 0){ //if the buffer is full, process it |
223 static int numberOfPdBlocksToProcess = gBufLength/gLibPdBlockSize; | 231 static int numberOfPdBlocksToProcess = gBufLength/gLibpdBlockSize; |
224 // TODO: see if we can rewrite libpd_process_float so that it takes a buffer | 232 // TODO: see if we can rewrite libpd_process_float so that it takes a buffer |
225 // of interleaved channels of arbitrary length channels rather than a series of | 233 // of interleaved channels of arbitrary length rather than a series of |
226 // stacked buffers of size gLibPdBlockSize as it currently does. | 234 // stacked buffers of size gLibPdBlockSize as it currently does. |
227 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf); | 235 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf); |
228 outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time | 236 outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time |
229 } | 237 } |
230 | 238 |
258 outR = 0; | 266 outR = 0; |
259 } | 267 } |
260 } | 268 } |
261 // rt_printf("outR %d, analogChannelsInUse %d, channelsInUse %d\n", | 269 // rt_printf("outR %d, analogChannelsInUse %d, channelsInUse %d\n", |
262 // outR , analogChannelsInUse, gChannelsInUse); | 270 // outR , analogChannelsInUse, gChannelsInUse); |
271 Bela_scheduleAuxiliaryTask(libpdProcessMidiQueueTask); | |
272 Bela_scheduleAuxiliaryTask(libpdProcessMessageQueueTask); | |
263 } | 273 } |
264 | 274 |
265 // cleanup() is called once at the end, after the audio has stopped. | 275 // cleanup() is called once at the end, after the audio has stopped. |
266 // Release any resources that were allocated in setup(). | 276 // Release any resources that were allocated in setup(). |
267 | 277 |