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 }