comparison examples/basic_libpd/render.cpp @ 343:4823ee13bcac prerelease

basic_libpd now populates pd's audio buffers directly. Updated libpd.so binary. This required an API change with respect to standard libpdAPI because for some strange reason, accessing sys_audioin and sys_audioout directly from the render.cpp file would return invalid values.
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 06 Jun 2016 15:15:15 +0100
parents 860c42b3830e
children 0e1e0dfe24c5
comparison
equal deleted inserted replaced
342:860c42b3830e 343:4823ee13bcac
15 #include "z_queued.h" 15 #include "z_queued.h"
16 #include "s_stuff.h" 16 #include "s_stuff.h"
17 #include <UdpServer.h> 17 #include <UdpServer.h>
18 #include <Midi.h> 18 #include <Midi.h>
19 19
20 20 // if you are 100% sure of what value that was used to compile libpd/puredata, then
21 // setup() is called once before the audio rendering starts. 21 // you could define this, instead of getting it at runtime. It has proved to give some 0.3%
22 // Use it to perform any initialisation and allocation which is dependent 22 // performance boost when it is 8 (thanks to vectorize optimizations I guess).
23 // on the period size or sample rate. 23 unsigned int gLibpdBlockSize;
24 //
25 // userData holds an opaque pointer to a data structure that was passed
26 // in from the call to initAudio().
27 //
28 // Return true on success; returning false halts the program.
29 unsigned int gLibpdBlockSize; //make sure this matches the one used to compile libpd
30 24
31 unsigned int gChannelsInUse = 10; 25 unsigned int gChannelsInUse = 10;
32 int gBufLength; 26 int gBufLength;
33 27
34 float* gInBuf; 28 float* gInBuf;
198 * 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
199 * memory operations. 193 * memory operations.
200 */ 194 */
201 static unsigned int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels); 195 static unsigned int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels);
202 static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize; 196 static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize;
203 for(unsigned int j = 0; j < numberOfPdBlocksToProcess; ++j){ 197 for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick){
204 unsigned int inW = 0; 198 unsigned int audioOutFrameBase = gLibpdBlockSize * tick;
205 unsigned int outR = 0; 199 unsigned int j;
206 200 unsigned int k;
207 for(unsigned int n = 0; n < gLibpdBlockSize; ++n){ //pd buffers are interleaved 201 float* p0;
208 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio 202 float* p1;
209 gInBuf[inW++] = audioRead(context, n, ch); 203 for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
210 } 204 for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) {
211 // then analogs 205 *p1 = audioRead(context, audioOutFrameBase + j, k);
212 // this loop resamples by ZOH, as needed, using m 206 }
213 if(context->analogChannels == 8 ){ //hold the value for two frames 207 }
214 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 208 // then analogs
215 gInBuf[inW++] = analogRead(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even 209 // this loop resamples by ZOH, as needed, using m
216 } 210 if(context->analogChannels == 8 ){ //hold the value for two frames
217 } else if(context->analogChannels == 4){ //write every frame 211 for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
218 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 212 for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
219 gInBuf[inW++] = analogRead(context, n, analogCh); 213 unsigned int analogFrame = (audioOutFrameBase + j) / 2;
220 } 214 *p1 = analogRead(context, analogFrame, k);
221 } else if(context->analogChannels == 2){ //drop every other frame 215 }
222 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 216 }
223 gInBuf[inW++] = analogRead(context, n*2, analogCh); 217 } else if(context->analogChannels == 4){ //write every frame
218 for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
219 for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
220 unsigned int analogFrame = audioOutFrameBase + j;
221 *p1 = analogRead(context, analogFrame, k);
222 }
223 }
224 } else if(context->analogChannels == 2){ //drop every other frame
225 for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) {
226 for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
227 unsigned int analogFrame = (audioOutFrameBase + j) * 2;
228 *p1 = analogRead(context, analogFrame, k);
224 } 229 }
225 } 230 }
226 } 231 }
227 libpd_process_sys(); // process the block 232 libpd_process_sys(); // process the block
228 for(unsigned int n = 0; n < gLibpdBlockSize; ++n){ //pd buffers are interleaved 233 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) {
229 unsigned int outAudioFrame = 0; 234 for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) {
230 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ 235 audioWrite(context, audioOutFrameBase + j, k, *p1);
231 audioWrite(context, outAudioFrame, ch, gOutBuf[outR++]); 236 }
232 } 237 }
233 //and analogs 238 if(context->analogChannels == 8){
234 if(context->analogChannels == 8){ 239 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j += 2, p0 += 2) { //write every two frames
235 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 240 unsigned int analogFrame = (audioOutFrameBase + j) / 2;
236 float analogOut = gOutBuf[outR++]; 241 for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
237 if((n&1) == 0){//write every two frames 242 analogWrite(context, analogFrame, k, *p1);
238 analogWrite(context, outAudioFrame/2, analogCh, analogOut); 243 }
239 } else { 244 }
240 // discard this sample 245 } else if(context->analogChannels == 4){ //write every frame
241 } 246 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) {
242 } 247 unsigned int analogFrame = (audioOutFrameBase + j);
243 } else if(context->analogChannels == 4){ //write every frame 248 for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
244 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 249 analogWrite(context, analogFrame, k, *p1);
245 float analogOut = gOutBuf[outR++]; 250 }
246 analogWrite(context, outAudioFrame, analogCh, analogOut); 251 }
247 } 252 } else if(context->analogChannels == 2){ //write every frame twice
248 } else if(context->analogChannels == 2){ //write twice every frame 253 for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) {
249 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ 254 for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) {
250 float analogOut = gOutBuf[outR++]; 255 int analogFrame = audioOutFrameBase * 2 + j * 2;
251 analogWrite(context, 2*outAudioFrame, analogCh, analogOut); 256 analogWrite(context, analogFrame, k, *p1);
252 analogWrite(context, 2*outAudioFrame + 1, analogCh, analogOut); 257 analogWrite(context, analogFrame + 1, k, *p1);
253 } 258 }
254 } 259 }
255 } 260 }
256 } 261 }
257 Bela_scheduleAuxiliaryTask(libpdProcessMidiQueueTask); 262 Bela_scheduleAuxiliaryTask(libpdProcessMidiQueueTask);
262 // Release any resources that were allocated in setup(). 267 // Release any resources that were allocated in setup().
263 268
264 void cleanup(BelaContext *context, void *userData) 269 void cleanup(BelaContext *context, void *userData)
265 { 270 {
266 libpd_queued_release(); 271 libpd_queued_release();
267 // free(gInBuf); 272 }
268 // free(gOutBuf);
269 }