Mercurial > hg > beaglert
comparison examples/basic_libpd/render.cpp @ 350:ebaeffa5d493 prerelease
Full implementation of libpd digitals (in and out at message rate). Still messy, needs cleanup, new utilites for setDataOut, clearDataOut, wrapping all this new digital stuff in a class which will be re-usable by Heavy
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Wed, 08 Jun 2016 01:58:35 +0100 |
parents | 6e454ebd9cc4 |
children | 749aa016fa16 |
comparison
equal
deleted
inserted
replaced
349:6e454ebd9cc4 | 350:ebaeffa5d493 |
---|---|
47 #define PARSE_MIDI | 47 #define PARSE_MIDI |
48 AuxiliaryTask libpdReadFilesTask; | 48 AuxiliaryTask libpdReadFilesTask; |
49 Midi midi; | 49 Midi midi; |
50 //UdpServer udpServer; | 50 //UdpServer udpServer; |
51 | 51 |
52 static uint32_t clearDataOut; | |
53 static uint32_t setDataOut; | |
52 void sendDigitalMessage(bool state, unsigned int delay, void* receiverName){ | 54 void sendDigitalMessage(bool state, unsigned int delay, void* receiverName){ |
53 libpd_float((char*)receiverName, (float)state); | 55 libpd_float((char*)receiverName, (float)state); |
54 // rt_printf("%s: %d\n", (char*)receiverName, state); | 56 // rt_printf("%s: %d\n", (char*)receiverName, state); |
55 } | 57 } |
58 | |
59 void Bela_floatHook(const char *source, float value){ | |
60 // rt_printf("received: %s %f\n", source, value); | |
61 // let's make this as optimized as possible for built-in digital Out parsing | |
62 // the built-in digital receivers are of the form "bela_digitalOutXX" where XX is between 11 and 26 | |
63 static int prefixLength = 15; // strlen("bela_digitalOut") | |
64 if(strncmp(source, "bela_digitalOut", prefixLength)==0){ | |
65 if(source[prefixLength] != 0){ //the two ifs are used instead of if(strlen(source) >= prefixLength+2) | |
66 if(source[prefixLength + 1] != 0){ | |
67 // quickly convert the suffix to integer, assuming they are numbers, avoiding to call atoi | |
68 int receiver = ((source[prefixLength] - 48) * 10); | |
69 receiver += (source[prefixLength+1] - 48); | |
70 // rt_printf("received on digital %d value %.0f\n", receiver, value); | |
71 unsigned int channel = receiver - 11; // go back to the actual Bela digital channel number | |
72 if(channel >= 0 && channel < 16){ //16 is the hardcoded value for the number of digital channels | |
73 //TODO: here we should check if this channel has been registered as message-rate output | |
74 if(value == 0){ | |
75 clearDataOut = setBit(clearDataOut, channel); | |
76 setDataOut = clearBit(setDataOut, channel); | |
77 } else { | |
78 setDataOut = setBit(setDataOut, channel); | |
79 clearDataOut = clearBit(clearDataOut, channel); | |
80 } | |
81 // rt_printf("clear 0x%x set 0x%x\n", clearDataOut, setDataOut); | |
82 } | |
83 } | |
84 } | |
85 } | |
86 } | |
87 | |
56 char receiverNames[16][21]={ | 88 char receiverNames[16][21]={ |
57 {"bela_digitalIn11"},{"bela_digitalIn12"},{"bela_digitalIn13"},{"bela_digitalIn14"},{"bela_digitalIn15"}, | 89 {"bela_digitalIn11"},{"bela_digitalIn12"},{"bela_digitalIn13"},{"bela_digitalIn14"},{"bela_digitalIn15"}, |
58 {"bela_digitalIn16"},{"bela_digitalIn17"},{"bela_digitalIn18"},{"bela_digitalIn19"},{"bela_digitalIn20"}, | 90 {"bela_digitalIn16"},{"bela_digitalIn17"},{"bela_digitalIn18"},{"bela_digitalIn19"},{"bela_digitalIn20"}, |
59 {"bela_digitalIn21"},{"bela_digitalIn22"},{"bela_digitalIn23"},{"bela_digitalIn24"},{"bela_digitalIn25"}, | 91 {"bela_digitalIn21"},{"bela_digitalIn22"},{"bela_digitalIn23"},{"bela_digitalIn24"},{"bela_digitalIn25"}, |
60 {"bela_digitalIn26"} | 92 {"bela_digitalIn26"} |
71 dtm = new DigitalToMessage* [context->digitalChannels]; | 103 dtm = new DigitalToMessage* [context->digitalChannels]; |
72 if(context->digitalChannels > 0){ | 104 if(context->digitalChannels > 0){ |
73 for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){ | 105 for(unsigned int ch = 0; ch < context->digitalChannels; ++ch){ |
74 dtm[ch] = new DigitalToMessage; | 106 dtm[ch] = new DigitalToMessage; |
75 dtm[ch]->setCallback(sendDigitalMessage, receiverNames[ch]); | 107 dtm[ch]->setCallback(sendDigitalMessage, receiverNames[ch]); |
76 pinMode(context, 0, ch, INPUT); | 108 if((ch%2) == 0 ) |
109 pinMode(context, 0, ch, INPUT); | |
110 else | |
111 pinMode(context, 0, ch, OUTPUT); | |
77 } | 112 } |
78 } | 113 } |
79 midi.readFrom(0); | 114 midi.readFrom(0); |
80 midi.writeTo(0); | 115 midi.writeTo(0); |
81 #ifdef PARSE_MIDI | 116 #ifdef PARSE_MIDI |
99 libpd_set_noteonhook(pdnoteon); | 134 libpd_set_noteonhook(pdnoteon); |
100 //TODO: add hooks for other midi events and generate MIDI output appropriately | 135 //TODO: add hooks for other midi events and generate MIDI output appropriately |
101 libpd_init(); | 136 libpd_init(); |
102 //TODO: ideally, we would analyse the ASCII of the patch file and find the in/outs to use | 137 //TODO: ideally, we would analyse the ASCII of the patch file and find the in/outs to use |
103 libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate); | 138 libpd_init_audio(gChannelsInUse, gChannelsInUse, context->audioSampleRate); |
139 gInBuf = libpd_get_sys_soundin(); | |
140 gOutBuf = libpd_get_sys_soundout(); | |
104 | 141 |
105 libpd_start_message(1); // one entry in list | 142 libpd_start_message(1); // one entry in list |
106 libpd_add_float(1.0f); | 143 libpd_add_float(1.0f); |
107 libpd_finish_message("pd", "dsp"); | 144 libpd_finish_message("pd", "dsp"); |
108 | 145 |
110 | 147 |
111 char file[] = "_main.pd"; | 148 char file[] = "_main.pd"; |
112 char folder[] = "./"; | 149 char folder[] = "./"; |
113 // open patch [; pd open file folder( | 150 // open patch [; pd open file folder( |
114 libpd_openfile(file, folder); | 151 libpd_openfile(file, folder); |
115 gInBuf = libpd_get_sys_soundin(); | 152 |
116 gOutBuf = libpd_get_sys_soundout(); | 153 // bind your receivers here |
154 libpd_bind("bela_digitalOut11"); | |
155 libpd_bind("bela_digitalOut12"); | |
156 libpd_bind("bela_digitalOut13"); | |
157 libpd_bind("bela_digitalOut14"); | |
158 libpd_bind("bela_digitalOut15"); | |
159 libpd_bind("bela_digitalOut16"); | |
160 libpd_bind("bela_digitalOut17"); | |
161 libpd_bind("bela_digitalOut18"); | |
162 libpd_bind("bela_digitalOut19"); | |
163 libpd_bind("bela_digitalOut20"); | |
164 libpd_bind("bela_digitalOut21"); | |
165 libpd_bind("bela_digitalOut22"); | |
166 libpd_bind("bela_digitalOut23"); | |
167 libpd_bind("bela_digitalOut24"); | |
168 libpd_bind("bela_digitalOut25"); | |
169 libpd_bind("bela_digitalOut26"); | |
170 | |
117 libpdReadFilesTask = Bela_createAuxiliaryTask(libpdReadFilesLoop, 60, "libpdReadFiles"); | 171 libpdReadFilesTask = Bela_createAuxiliaryTask(libpdReadFilesLoop, 60, "libpdReadFiles"); |
118 Bela_scheduleAuxiliaryTask(libpdReadFilesTask); | 172 Bela_scheduleAuxiliaryTask(libpdReadFilesTask); |
119 | 173 |
120 | 174 |
121 return true; | 175 return true; |
205 libpd_midibyte(0, input); | 259 libpd_midibyte(0, input); |
206 } | 260 } |
207 #endif /* PARSE_MIDI */ | 261 #endif /* PARSE_MIDI */ |
208 | 262 |
209 static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize; | 263 static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize; |
264 | |
265 // these are reset at every audio callback. Persistence across audio callbacks | |
266 // is handled by the core code. | |
267 // setDataOut = 0; | |
268 // clearDataOut = 0; | |
269 | |
210 for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick){ | 270 for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick){ |
211 unsigned int audioFrameBase = gLibpdBlockSize * tick; | 271 unsigned int audioFrameBase = gLibpdBlockSize * tick; |
212 unsigned int j; | 272 unsigned int j; |
213 unsigned int k; | 273 unsigned int k; |
214 float* p0; | 274 float* p0; |
266 } | 326 } |
267 | 327 |
268 libpd_process_sys(); // process the block | 328 libpd_process_sys(); // process the block |
269 | 329 |
270 //digital out | 330 //digital out |
271 // digital at message-rate | 331 // digital out at signal-rate |
272 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) { | 332 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) { |
273 unsigned int digitalFrame = (audioFrameBase + j); | 333 unsigned int digitalFrame = (audioFrameBase + j); |
274 for (k = 0, p1 = p0 + gLibpdBlockSize * (context->audioChannels + 8); | 334 for (k = 0, p1 = p0 + gLibpdBlockSize * (context->audioChannels + 8); |
275 k < context->digitalChannels; k++, p1 += gLibpdBlockSize) { | 335 k < context->digitalChannels; k++, p1 += gLibpdBlockSize) { |
276 // TODO: only process the channels marked as such | 336 // TODO: only process the channels marked as such |
277 digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5); | 337 digitalWriteOnce(context, digitalFrame, k, *p1 > 0.5); |
278 } | 338 } |
279 } | 339 } |
280 | 340 |
341 // digital out at message-rate | |
342 if(clearDataOut || setDataOut){ | |
343 for (unsigned int frame = audioFrameBase; frame < audioFrameBase + gLibpdBlockSize; ++frame) { | |
344 // TODO: only process the channels marked as such | |
345 uint32_t outWord = context->digital[frame]; | |
346 outWord = outWord | (setDataOut << 16); | |
347 outWord = outWord &~ (clearDataOut << 16); | |
348 context->digital[frame] = outWord; | |
349 } | |
350 } | |
351 | |
281 //audio | 352 //audio |
282 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) { | 353 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) { |
283 for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) { | 354 for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) { |
284 audioWrite(context, audioFrameBase + j, k, *p1); | 355 audioWrite(context, audioFrameBase + j, k, *p1); |
285 } | 356 } |