# HG changeset patch # User Giulio Moro # Date 1465222515 -3600 # Node ID 4823ee13bcac0d1d2a0e1694b8c2d4927a2e8b65 # Parent 860c42b3830e208b5e48858b2dcf016614f46af0 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. diff -r 860c42b3830e -r 4823ee13bcac .cproject --- a/.cproject Mon Jun 06 12:21:38 2016 +0100 +++ b/.cproject Mon Jun 06 15:15:15 2016 +0100 @@ -134,7 +134,8 @@ - + + @@ -262,7 +263,8 @@ - + + diff -r 860c42b3830e -r 4823ee13bcac examples/basic_libpd/render.cpp --- a/examples/basic_libpd/render.cpp Mon Jun 06 12:21:38 2016 +0100 +++ b/examples/basic_libpd/render.cpp Mon Jun 06 15:15:15 2016 +0100 @@ -17,16 +17,10 @@ #include #include - -// setup() is called once before the audio rendering starts. -// Use it to perform any initialisation and allocation which is dependent -// on the period size or sample rate. -// -// userData holds an opaque pointer to a data structure that was passed -// in from the call to initAudio(). -// -// Return true on success; returning false halts the program. -unsigned int gLibpdBlockSize; //make sure this matches the one used to compile libpd +// if you are 100% sure of what value that was used to compile libpd/puredata, then +// you could define this, instead of getting it at runtime. It has proved to give some 0.3% +// performance boost when it is 8 (thanks to vectorize optimizations I guess). +unsigned int gLibpdBlockSize; unsigned int gChannelsInUse = 10; int gBufLength; @@ -200,56 +194,67 @@ */ static unsigned int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels); static unsigned int numberOfPdBlocksToProcess = gBufLength / gLibpdBlockSize; - for(unsigned int j = 0; j < numberOfPdBlocksToProcess; ++j){ - unsigned int inW = 0; - unsigned int outR = 0; - - for(unsigned int n = 0; n < gLibpdBlockSize; ++n){ //pd buffers are interleaved - for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio - gInBuf[inW++] = audioRead(context, n, ch); + for(unsigned int tick = 0; tick < numberOfPdBlocksToProcess; ++tick){ + unsigned int audioOutFrameBase = gLibpdBlockSize * tick; + unsigned int j; + unsigned int k; + float* p0; + float* p1; + for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) { + for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) { + *p1 = audioRead(context, audioOutFrameBase + j, k); } - // then analogs - // this loop resamples by ZOH, as needed, using m - if(context->analogChannels == 8 ){ //hold the value for two frames - for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ - gInBuf[inW++] = analogRead(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even + } + // then analogs + // this loop resamples by ZOH, as needed, using m + if(context->analogChannels == 8 ){ //hold the value for two frames + for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) { + for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) { + unsigned int analogFrame = (audioOutFrameBase + j) / 2; + *p1 = analogRead(context, analogFrame, k); } - } else if(context->analogChannels == 4){ //write every frame - for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ - gInBuf[inW++] = analogRead(context, n, analogCh); + } + } else if(context->analogChannels == 4){ //write every frame + for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) { + for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) { + unsigned int analogFrame = audioOutFrameBase + j; + *p1 = analogRead(context, analogFrame, k); } - } else if(context->analogChannels == 2){ //drop every other frame - for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ - gInBuf[inW++] = analogRead(context, n*2, analogCh); + } + } else if(context->analogChannels == 2){ //drop every other frame + for (j = 0, p0 = gInBuf; j < gLibpdBlockSize; j++, p0++) { + for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) { + unsigned int analogFrame = (audioOutFrameBase + j) * 2; + *p1 = analogRead(context, analogFrame, k); } } } libpd_process_sys(); // process the block - for(unsigned int n = 0; n < gLibpdBlockSize; ++n){ //pd buffers are interleaved - unsigned int outAudioFrame = 0; - for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ - audioWrite(context, outAudioFrame, ch, gOutBuf[outR++]); + for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) { + for (k = 0, p1 = p0; k < context->audioChannels; k++, p1 += gLibpdBlockSize) { + audioWrite(context, audioOutFrameBase + j, k, *p1); } - //and analogs - if(context->analogChannels == 8){ - for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ - float analogOut = gOutBuf[outR++]; - if((n&1) == 0){//write every two frames - analogWrite(context, outAudioFrame/2, analogCh, analogOut); - } else { - // discard this sample - } + } + if(context->analogChannels == 8){ + for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j += 2, p0 += 2) { //write every two frames + unsigned int analogFrame = (audioOutFrameBase + j) / 2; + for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) { + analogWrite(context, analogFrame, k, *p1); } - } else if(context->analogChannels == 4){ //write every frame - for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ - float analogOut = gOutBuf[outR++]; - analogWrite(context, outAudioFrame, analogCh, analogOut); + } + } else if(context->analogChannels == 4){ //write every frame + for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; ++j, ++p0) { + unsigned int analogFrame = (audioOutFrameBase + j); + for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) { + analogWrite(context, analogFrame, k, *p1); } - } else if(context->analogChannels == 2){ //write twice every frame - for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ - float analogOut = gOutBuf[outR++]; - analogWrite(context, 2*outAudioFrame, analogCh, analogOut); - analogWrite(context, 2*outAudioFrame + 1, analogCh, analogOut); + } + } else if(context->analogChannels == 2){ //write every frame twice + for (j = 0, p0 = gOutBuf; j < gLibpdBlockSize; j++, p0++) { + for (k = 0, p1 = p0 + gLibpdBlockSize * context->audioChannels; k < analogChannelsInUse; k++, p1 += gLibpdBlockSize) { + int analogFrame = audioOutFrameBase * 2 + j * 2; + analogWrite(context, analogFrame, k, *p1); + analogWrite(context, analogFrame + 1, k, *p1); } } } @@ -264,6 +269,4 @@ void cleanup(BelaContext *context, void *userData) { libpd_queued_release(); -// free(gInBuf); -// free(gOutBuf); } diff -r 860c42b3830e -r 4823ee13bcac libpd.so Binary file libpd.so has changed