Mercurial > hg > beaglert
comparison projects/basic_libpd/render.cpp @ 232:600355cf4ed5 mergingClockSync
libpd taking care of different numbers of analog channels
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Sun, 10 Apr 2016 03:14:33 +0200 |
parents | af211ee57867 |
children |
comparison
equal
deleted
inserted
replaced
231:c0bf6157f67e | 232:600355cf4ed5 |
---|---|
22 // in from the call to initAudio(). | 22 // in from the call to initAudio(). |
23 // | 23 // |
24 // Return true on success; returning false halts the program. | 24 // Return true on success; returning false halts the program. |
25 #define DEFDACBLKSIZE 8u //make sure this matches the one used to compile libpd | 25 #define DEFDACBLKSIZE 8u //make sure this matches the one used to compile libpd |
26 | 26 |
27 const int gChannelsInUse = 6; | 27 int gChannelsInUse = 10; |
28 int gBufLength; | 28 int gBufLength; |
29 | 29 |
30 float* gInBuf; | 30 float* gInBuf; |
31 float* gOutBuf; | 31 float* gOutBuf; |
32 | 32 |
49 } | 49 } |
50 | 50 |
51 AuxiliaryTask udpReadTask; | 51 AuxiliaryTask udpReadTask; |
52 bool setup(BeagleRTContext *context, void *userData) | 52 bool setup(BeagleRTContext *context, void *userData) |
53 { | 53 { |
54 gChannelsInUse = min((int)(context->analogChannels+context->audioChannels), (int)gChannelsInUse); | |
54 udpServer.bindToPort(1234); | 55 udpServer.bindToPort(1234); |
55 | 56 |
56 // check that we are not running with a blocksize smaller than DEFDACBLKSIZE | 57 // check that we are not running with a blocksize smaller than DEFDACBLKSIZE |
57 // it would still work, but the load would be executed unevenly between calls to render | 58 // it would still work, but the load would be executed unevenly between calls to render |
58 if(context->audioFrames < DEFDACBLKSIZE){ | 59 if(context->audioFrames < DEFDACBLKSIZE){ |
61 } | 62 } |
62 | 63 |
63 // check that the sampling rate of the analogs is the same as audio if running with | 64 // check that the sampling rate of the analogs is the same as audio if running with |
64 // more than 2 channels (that is with analog). If we fix the TODO in render, then | 65 // more than 2 channels (that is with analog). If we fix the TODO in render, then |
65 // this test is not needed. | 66 // this test is not needed. |
66 if(context->analogFrames != context->audioFrames){ | 67 // if(context->analogFrames != context->audioFrames){ |
67 fprintf(stderr, "Error: analog and audio sampling rates must be the same\n"); | 68 // fprintf(stderr, "Error: analog and audio sampling rates must be the same\n"); |
68 return false; | 69 // return false; |
69 } | 70 // } |
70 //following lines borrowed from libpd/samples/c/pdtest/pdtest.c | 71 //following lines borrowed from libpd/samples/c/pdtest/pdtest.c |
71 // init pd | 72 // init pd |
72 libpd_set_printhook(BeagleRT_printHook); // set this before calling libpd_init | 73 libpd_set_printhook(BeagleRT_printHook); // set this before calling libpd_init |
73 libpd_set_noteonhook(pdnoteon); | 74 libpd_set_noteonhook(pdnoteon); |
74 libpd_init(); | 75 libpd_init(); |
82 gBufLength = max(DEFDACBLKSIZE, context->audioFrames); | 83 gBufLength = max(DEFDACBLKSIZE, context->audioFrames); |
83 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength; | 84 unsigned int bufferSize = sizeof(float)*gChannelsInUse*gBufLength; |
84 gInBuf = (float*)malloc(bufferSize); | 85 gInBuf = (float*)malloc(bufferSize); |
85 gOutBuf = (float*)malloc(bufferSize); | 86 gOutBuf = (float*)malloc(bufferSize); |
86 // no need to memset to zero | 87 // no need to memset to zero |
87 | |
88 | 88 |
89 char file[] = "_main.pd"; | 89 char file[] = "_main.pd"; |
90 char folder[] = "./"; | 90 char folder[] = "./"; |
91 // open patch [; pd open file folder( | 91 // open patch [; pd open file folder( |
92 libpd_openfile(file, folder); | 92 libpd_openfile(file, folder); |
109 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers | 109 * NOTE: if you are only using audio (or only analogs) and you are using interleaved buffers |
110 * and the blocksize of Bela is the same as DEFDACBLKSIZE, then you probably | 110 * and the blocksize of Bela is the same as DEFDACBLKSIZE, then you probably |
111 * do not need the for loops before and after libpd_process_float, so you can save quite some | 111 * do not need the for loops before and after libpd_process_float, so you can save quite some |
112 * memory operations. | 112 * memory operations. |
113 */ | 113 */ |
114 | 114 static int analogChannelsInUse = min(context->analogChannels, gChannelsInUse - context->audioChannels); |
115 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved | 115 // rt_printf("channelsInUse: %d, analogChannels in Use: %d\n", gChannelsInUse, analogChannelsInUse); |
116 for(unsigned int k = 0; k < context->audioChannels; k++){ | 116 for(unsigned int n = 0; n < context->audioFrames; ++n){ //pd buffers are interleaved |
117 gInBuf[inW++] = audioReadFrame(context, n, k); | 117 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ //first two channels are audio |
118 gInBuf[inW++] = audioReadFrame(context, n, ch); | |
118 } | 119 } |
119 for(unsigned int k = 0; k < gChannelsInUse - context->audioChannels; k ++){ // add analogs | 120 // then analogs |
120 gInBuf[inW++] = analogReadFrame(context, n, k); | 121 // this loop resamples by ZOH, as needed, using m |
121 // TODO: Apply here sampling rate conversion from analogs to audio | 122 if(context->analogChannels == 8 ){ //hold the value for two frames |
123 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ | |
124 gInBuf[inW++] = analogReadFrame(context, n/2, analogCh); // n/2 wil be the same for n and n+1 when n is even | |
125 } | |
126 } else if(context->analogChannels == 4){ //write every frame | |
127 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ | |
128 gInBuf[inW++] = analogReadFrame(context, n, analogCh); | |
129 } | |
130 } else if(context->analogChannels == 2){ //drop every other frame | |
131 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ | |
132 gInBuf[inW++] = analogReadFrame(context, n*2, analogCh); | |
133 } | |
122 } | 134 } |
123 if(inW == gBufLength * gChannelsInUse){ | 135 if(inW == gBufLength * gChannelsInUse){ |
124 inW = 0; | 136 inW = 0; |
125 } | 137 } |
126 } | 138 } |
127 | 139 // rt_printf("inW %d\n", inW); |
128 if(inW == 0){ //if the buffer is full, process it | 140 if(inW == 0){ //if the buffer is full, process it |
129 int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE; | 141 static int numberOfPdBlocksToProcess = gBufLength/DEFDACBLKSIZE; |
130 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf); | 142 libpd_process_float(numberOfPdBlocksToProcess, gInBuf, gOutBuf); |
131 outR = 0; // reset the read pointer. NOTE: hopefully this is not needed EXCEPT the first time | 143 outR = 0; // reset the read pointer. NOTE: hopefully this is needed only the first time |
132 } | 144 } |
133 | 145 |
134 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved | 146 for(unsigned int n = 0; n < context->audioFrames; n++){ //pd buffers are interleaved |
135 for(unsigned int k = 0; k < context->audioChannels; k++){ | 147 for(unsigned int ch = 0; ch < context->audioChannels; ++ch){ |
136 audioWriteFrame(context, n, k, gOutBuf[outR++]); | 148 audioWriteFrame(context, n, ch, gOutBuf[outR++]); |
137 } | 149 } |
138 //add analogs here, limit them to channelsInUse | 150 //and analogs |
139 for(unsigned int k = 0; k < gChannelsInUse - context->audioChannels; k ++){ // add analogs | 151 if(context->analogChannels == 8){ |
140 analogWriteFrame(context, n, k, gOutBuf[outR++]); | 152 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ |
141 // TODO: Apply here sampling rate conversion from analogs to audio | 153 float analogOut = gOutBuf[outR++]; |
154 if((n&1) == 0){//write every two frames | |
155 analogWriteFrame(context, n/2, analogCh, analogOut); | |
156 } else { | |
157 // discard this sample | |
158 } | |
159 } | |
160 } else if(context->analogChannels == 4){ //write every frame | |
161 for(int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ | |
162 float analogOut = gOutBuf[outR++]; | |
163 analogWriteFrame(context, n, analogCh, analogOut); | |
164 } | |
165 } else if(context->analogChannels == 2){ //write twice every frame | |
166 for(unsigned int analogCh = 0; analogCh < analogChannelsInUse; ++analogCh){ | |
167 float analogOut = gOutBuf[outR++]; | |
168 analogWriteFrame(context, 2*n, analogCh, analogOut); | |
169 analogWriteFrame(context, 2*n + 1, analogCh, analogOut); | |
170 } | |
142 } | 171 } |
143 if(outR == gBufLength * gChannelsInUse){ | 172 if(outR == gBufLength * gChannelsInUse){ |
144 outR = 0; | 173 outR = 0; |
145 } | 174 } |
146 } | 175 } |
176 // rt_printf("outR %d, analogChannelsInUse %d, channelsInUse %d\n", | |
177 // outR , analogChannelsInUse, gChannelsInUse); | |
147 } | 178 } |
179 | |
148 // cleanup() is called once at the end, after the audio has stopped. | 180 // cleanup() is called once at the end, after the audio has stopped. |
149 // Release any resources that were allocated in setup(). | 181 // Release any resources that were allocated in setup(). |
150 | 182 |
151 void cleanup(BeagleRTContext *context, void *userData) | 183 void cleanup(BeagleRTContext *context, void *userData) |
152 { | 184 { |