comparison projects/d-box/render.cpp @ 108:3068421c0737 ultra-staging

Merged default into ultra-staging
author Giulio Moro <giuliomoro@yahoo.it>
date Tue, 18 Aug 2015 00:35:15 +0100
parents 3c3a1357657d
children
comparison
equal deleted inserted replaced
54:d3f869b98147 108:3068421c0737
3 * 3 *
4 * Created on: May 28, 2014 4 * Created on: May 28, 2014
5 * Author: Victor Zappi 5 * Author: Victor Zappi
6 */ 6 */
7 7
8 #include "../../include/RTAudio.h" 8 #include <BeagleRT.h>
9 #include "../../include/PRU.h" 9 #include <PRU.h>
10
10 #include "StatusLED.h" 11 #include "StatusLED.h"
11 #include "config.h" 12 #include "config.h"
12 #include "OscillatorBank.h" 13 #include "OscillatorBank.h"
13 #include "FeedbackOscillator.h" 14 #include "FeedbackOscillator.h"
14 #include "ADSR.h" 15 #include "ADSR.h"
17 #include <cmath> 18 #include <cmath>
18 #include <vector> 19 #include <vector>
19 20
20 #undef DBOX_CAPE_TEST 21 #undef DBOX_CAPE_TEST
21 22
23 // Mappings from pin numbers on PCB to actual DAC channels
24 // This gives the DAC and ADC connectors the same effective pinout
25 #define DAC_PIN0 6
26 #define DAC_PIN1 4
27 #define DAC_PIN2 2
28 #define DAC_PIN3 0
29 #define DAC_PIN4 1
30 #define DAC_PIN5 3
31 #define DAC_PIN6 5
32 #define DAC_PIN7 7
33
34 #define ADC_PIN0 0
35 #define ADC_PIN1 1
36 #define ADC_PIN2 2
37 #define ADC_PIN3 3
38 #define ADC_PIN4 4
39 #define ADC_PIN5 5
40 #define ADC_PIN6 6
41 #define ADC_PIN7 7
42
22 #define N_OCT 4.0 // maximum number of octaves on sensor 1 43 #define N_OCT 4.0 // maximum number of octaves on sensor 1
23 44
24 extern vector<OscillatorBank*> gOscBanks; 45 extern vector<OscillatorBank*> gOscBanks;
25 extern int gCurrentOscBank; 46 extern int gCurrentOscBank;
26 extern int gNextOscBank; 47 extern int gNextOscBank;
27 extern PRU *gPRU; 48 extern PRU *gPRU;
28 extern StatusLED gStatusLED; 49 extern StatusLED gStatusLED;
29 extern bool gIsLoading; 50 extern bool gIsLoading;
30 extern bool gAudioIn; 51 extern bool gAudioIn;
31 extern int gPeriodSize;
32 52
33 float *gOscillatorBuffer1, *gOscillatorBuffer2; 53 float *gOscillatorBuffer1, *gOscillatorBuffer2;
34 float *gOscillatorBufferRead, *gOscillatorBufferWrite; 54 float *gOscillatorBufferRead, *gOscillatorBufferWrite;
35 int gOscillatorBufferReadPointer = 0; 55 int gOscillatorBufferReadPointer = 0;
36 int gOscillatorBufferReadCurrentSize = 0; 56 int gOscillatorBufferReadCurrentSize = 0;
55 75
56 // This comes from sensor.cpp where it records the most recent touch location on 76 // This comes from sensor.cpp where it records the most recent touch location on
57 // sensor 0. 77 // sensor 0.
58 extern float gSensor0LatestTouchPos; 78 extern float gSensor0LatestTouchPos;
59 extern int gSensor0LatestTouchNum; 79 extern int gSensor0LatestTouchNum;
60 uint16_t gPitchLatestInput = 0; 80 float gPitchLatestInput = 0;
61 81
62 extern float gSensor1LatestTouchPos[]; 82 extern float gSensor1LatestTouchPos[];
63 //extern float gSensor1LatestTouchSizes[]; 83 //extern float gSensor1LatestTouchSizes[];
64 extern int gSensor1LatestTouchCount; 84 extern int gSensor1LatestTouchCount;
65 extern int gSensor1LatestTouchIndex; 85 extern int gSensor1LatestTouchIndex;
71 // FSR value from matrix input 91 // FSR value from matrix input
72 extern int gLastFSRValue; 92 extern int gLastFSRValue;
73 93
74 // Loop points from matrix input 4 94 // Loop points from matrix input 4
75 const int gLoopPointsInputBufferSize = 256; 95 const int gLoopPointsInputBufferSize = 256;
76 uint16_t gLoopPointsInputBuffer[gLoopPointsInputBufferSize]; 96 float gLoopPointsInputBuffer[gLoopPointsInputBufferSize];
77 int gLoopPointsInputBufferPointer = 0; 97 int gLoopPointsInputBufferPointer = 0;
78 int gLoopPointMin = 0, gLoopPointMax = 0; 98 float gLoopPointMin = 0, gLoopPointMax = 0;
79 99
80 // multiplier to activate or mute audio in 100 // multiplier to activate or mute audio in
81 int audioInStatus = 0; 101 int audioInStatus = 0;
82 102
83 // xenomai timer 103 // xenomai timer
84 SRTIME prevChangeNs = 0; 104 SRTIME prevChangeNs = 0;
85 105
86 // pitch vars 106 // pitch vars
87 float octaveSplitter; 107 float octaveSplitter;
88 u_int16_t semitones[((int)N_OCT*12)+1]; 108 float semitones[((int)N_OCT*12)+1];
89 float deltaTouch = 0; 109 float deltaTouch = 0;
90 float deltaWeightP = 0.5; 110 float deltaWeightP = 0.5 / 65536.0;
91 float deltaWeightI = 0.0005; 111 float deltaWeightI = 0.0005 / 65536.0;
92 112
93 // filter vars 113 // filter vars
94 ne10_fir_instance_f32_t filter[2]; 114 ne10_fir_instance_f32_t filter[2];
95 ne10_float32_t *filterIn[2]; 115 ne10_float32_t *filterIn[2];
96 ne10_float32_t *filterOut[2]; 116 ne10_float32_t *filterOut[2];
120 140
121 void wavetable_interpolate(int numSamplesIn, int numSamplesOut, 141 void wavetable_interpolate(int numSamplesIn, int numSamplesOut,
122 float *tableIn, float *tableOut, 142 float *tableIn, float *tableOut,
123 float *sineTable, float sineMix); 143 float *sineTable, float sineMix);
124 144
125 inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold, 145 inline float hysteresis_oscillator(float input, float risingThreshold,
126 uint16_t fallingThreshold, bool *rising); 146 float fallingThreshold, bool *rising);
147
148 void render_medium_prio();
149 void render_low_prio();
127 150
128 #ifdef DBOX_CAPE_TEST 151 #ifdef DBOX_CAPE_TEST
129 void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, 152 void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
130 uint16_t *matrixIn, uint16_t *matrixOut); 153 uint16_t *matrixIn, uint16_t *matrixOut);
131 #endif 154 #endif
132 155
133 bool initialise_render(int numMatrixChannels, int numAudioChannels, 156 bool setup(BeagleRTContext *context, void *userData) {
134 int numMatrixFramesPerPeriod,
135 int numAudioFramesPerPeriod,
136 float matrixSampleRate, float audioSampleRate,
137 void *userData) {
138 int oscBankHopSize = *(int *)userData; 157 int oscBankHopSize = *(int *)userData;
139 158
140 if(numMatrixChannels != 8) { 159 if(context->analogChannels != 8) {
141 printf("Error: D-Box needs matrix enabled with 8 channels.\n"); 160 printf("Error: D-Box needs matrix enabled with 8 channels.\n");
142 return false; 161 return false;
143 } 162 }
144 163
145 // Allocate two buffers for rendering oscillator bank samples 164 // Allocate two buffers for rendering oscillator bank samples
146 // One will be used for writing in the background while the other is used for reading 165 // One will be used for writing in the background while the other is used for reading
147 // on the audio thread. 8-byte alignment needed for the NEON code. 166 // on the audio thread. 8-byte alignment needed for the NEON code.
148 if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * gNumAudioChannels * sizeof(float))) { 167 if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * context->audioChannels * sizeof(float))) {
149 printf("Error allocating render buffers\n"); 168 printf("Error allocating render buffers\n");
150 return false; 169 return false;
151 } 170 }
152 if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * gNumAudioChannels * sizeof(float))) { 171 if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * context->audioChannels * sizeof(float))) {
153 printf("Error allocating render buffers\n"); 172 printf("Error allocating render buffers\n");
154 return false; 173 return false;
155 } 174 }
156 gOscillatorBufferWrite = gOscillatorBuffer1; 175 gOscillatorBufferWrite = gOscillatorBuffer1;
157 gOscillatorBufferRead = gOscillatorBuffer2; 176 gOscillatorBufferRead = gOscillatorBuffer2;
158 177
159 memset(gOscillatorBuffer1, 0, oscBankHopSize * gNumAudioChannels * sizeof(float)); 178 memset(gOscillatorBuffer1, 0, oscBankHopSize * context->audioChannels * sizeof(float));
160 memset(gOscillatorBuffer2, 0, oscBankHopSize * gNumAudioChannels * sizeof(float)); 179 memset(gOscillatorBuffer2, 0, oscBankHopSize * context->audioChannels * sizeof(float));
161 180
162 // Initialise the dynamic wavetable used by the oscillator bank 181 // Initialise the dynamic wavetable used by the oscillator bank
163 // It should match the size of the static one already allocated in the OscillatorBank object 182 // It should match the size of the static one already allocated in the OscillatorBank object
164 // Don't forget a guard point at the end of the table 183 // Don't forget a guard point at the end of the table
165 gDynamicWavetableLength = gOscBanks[gCurrentOscBank]->lookupTableSize; 184 gDynamicWavetableLength = gOscBanks[gCurrentOscBank]->lookupTableSize;
166 if(posix_memalign((void **)&gDynamicWavetable, 8, (gDynamicWavetableLength + 1) * sizeof(float))) { 185 if(posix_memalign((void **)&gDynamicWavetable, 8, (gDynamicWavetableLength + 1) * sizeof(float))) {
167 printf("Error allocating wavetable\n"); 186 printf("Error allocating wavetable\n");
168 return false; 187 return false;
169 } 188 }
170 189
171 gFeedbackOscillator.initialise(8192, 10.0, matrixSampleRate); 190 gFeedbackOscillator.initialise(8192, 10.0, context->analogSampleRate);
172 191
173 for(int n = 0; n < gDynamicWavetableLength + 1; n++) 192 for(int n = 0; n < gDynamicWavetableLength + 1; n++)
174 gDynamicWavetable[n] = 0; 193 gDynamicWavetable[n] = 0;
175 194
176 // pitch 195 // pitch
177 float midPos = (float)65535/2.0; 196 float midPos = 0.5;
178 octaveSplitter = round((float)65535/(N_OCT)); 197 octaveSplitter = 1.0 / N_OCT;
179 int numOfSemi = 12*N_OCT; 198 int numOfSemi = 12*N_OCT;
180 int middleSemitone = 12*N_OCT/2; 199 int middleSemitone = 12*N_OCT/2;
181 int lastSemitone = middleSemitone+numOfSemi/2; 200 int lastSemitone = middleSemitone+numOfSemi/2;
182 float inc = (float)65535/(N_OCT*12.0); 201 float inc = 1.0 / (N_OCT*12.0);
183 int i = -1; 202 int i = -1;
184 for(int semi=middleSemitone; semi<=lastSemitone; semi++) 203 for(int semi=middleSemitone; semi<=lastSemitone; semi++)
185 semitones[semi] = ( midPos + (++i)*inc) + 0.5; 204 semitones[semi] = ( midPos + (++i)*inc) + 0.5;
186 i = 0; 205 i = 0;
187 for(int semi=middleSemitone-1; semi>=0; semi--) 206 for(int semi=middleSemitone-1; semi>=0; semi--)
189 208
190 if(gAudioIn) 209 if(gAudioIn)
191 audioInStatus = 1; 210 audioInStatus = 1;
192 211
193 // filter 212 // filter
194 blockSize = 2*gPeriodSize; 213 blockSize = context->audioFrames;
195 filterState[0] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t)); 214 filterState[0] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
196 filterState[1] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t)); 215 filterState[1] = (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
197 filterIn[0] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); 216 filterIn[0] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
198 filterIn[1] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); 217 filterIn[1] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
199 filterOut[0] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); 218 filterOut[0] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
200 filterOut[1] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t)); 219 filterOut[1] = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
201 ne10_fir_init_float(&filter[0], FILTER_TAP_NUM, filterTaps, filterState[0], blockSize); 220 ne10_fir_init_float(&filter[0], FILTER_TAP_NUM, filterTaps, filterState[0], blockSize);
202 ne10_fir_init_float(&filter[1], FILTER_TAP_NUM, filterTaps, filterState[1], blockSize); 221 ne10_fir_init_float(&filter[1], FILTER_TAP_NUM, filterTaps, filterState[1], blockSize);
203 222
204 // peak outputs 223 // peak outputs
205 PeakBurst[0].setAttackRate(.00001 * matrixSampleRate); 224 PeakBurst[0].setAttackRate(.00001 * context->analogSampleRate);
206 PeakBurst[1].setAttackRate(.00001 * matrixSampleRate); 225 PeakBurst[1].setAttackRate(.00001 * context->analogSampleRate);
207 PeakBurst[0].setDecayRate(.5 * matrixSampleRate); 226 PeakBurst[0].setDecayRate(.5 * context->analogSampleRate);
208 PeakBurst[1].setDecayRate(.5 * matrixSampleRate); 227 PeakBurst[1].setDecayRate(.5 * context->analogSampleRate);
209 PeakBurst[0].setSustainLevel(0.0); 228 PeakBurst[0].setSustainLevel(0.0);
210 PeakBurst[1].setSustainLevel(0.0); 229 PeakBurst[1].setSustainLevel(0.0);
211 230
212 // Initialise auxiliary tasks 231 // Initialise auxiliary tasks
213 if((gMediumPriorityRender = createAuxiliaryTaskLoop(&render_medium_prio, 90, "dbox-calculation-medium")) == 0) 232 if((gMediumPriorityRender = BeagleRT_createAuxiliaryTask(&render_medium_prio, BEAGLERT_AUDIO_PRIORITY - 10, "dbox-calculation-medium")) == 0)
214 return false; 233 return false;
215 if((gLowPriorityRender = createAuxiliaryTaskLoop(&render_low_prio, 85, "dbox-calculation-low")) == 0) 234 if((gLowPriorityRender = BeagleRT_createAuxiliaryTask(&render_low_prio, BEAGLERT_AUDIO_PRIORITY - 15, "dbox-calculation-low")) == 0)
216 return false; 235 return false;
217 236
218 return true; 237 return true;
219 } 238 }
220 239
221 void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, 240 void render(BeagleRTContext *context, void *userData)
222 uint16_t *matrixIn, uint16_t *matrixOut)
223 { 241 {
224 #ifdef DBOX_CAPE_TEST 242 #ifdef DBOX_CAPE_TEST
225 render_capetest(numMatrixFrames, numAudioFrames, audioIn, audioOut, matrixIn, matrixOut); 243 render_capetest(numMatrixFrames, numAudioFrames, audioIn, audioOut, matrixIn, matrixOut);
226 #else 244 #else
227 if(gOscBanks[gCurrentOscBank]->state==bank_toreset) 245 if(gOscBanks[gCurrentOscBank]->state==bank_toreset)
228 gOscBanks[gCurrentOscBank]->resetOscillators(); 246 gOscBanks[gCurrentOscBank]->resetOscillators();
229 247
230 if(gOscBanks[gCurrentOscBank]->state==bank_playing) 248 if(gOscBanks[gCurrentOscBank]->state==bank_playing)
231 { 249 {
232 assert(gNumAudioChannels == 2); 250 assert(context->audioChannels == 2);
233 251
234 #ifdef OLD_OSCBANK 252 #ifdef OLD_OSCBANK
235 memset(audioOut, 0, numAudioFrames * gNumAudioChannels * sizeof(float)); 253 memset(audioOut, 0, numAudioFrames * * sizeof(float));
236 254
237 /* Render the oscillator bank. The oscillator bank function is written in NEON assembly 255 /* Render the oscillator bank. The oscillator bank function is written in NEON assembly
238 * and it strips out all extra checks, so find out in advance whether we can render a whole 256 * and it strips out all extra checks, so find out in advance whether we can render a whole
239 * block or whether the frame will increment in the middle of this buffer. 257 * block or whether the frame will increment in the middle of this buffer.
240 */ 258 */
267 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes, 285 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
268 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives, 286 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
269 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives, 287 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
270 gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/); 288 gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/);
271 framesRemaining -= gOscBanks[gCurrentOscBank]->hopCounter; 289 framesRemaining -= gOscBanks[gCurrentOscBank]->hopCounter;
272 audioOutWithOffset += gNumAudioChannels * gOscBanks[gCurrentOscBank]->hopCounter; 290 audioOutWithOffset += * gOscBanks[gCurrentOscBank]->hopCounter;
273 gOscBanks[gCurrentOscBank]->sampleCount += gOscBanks[gCurrentOscBank]->hopCounter; 291 gOscBanks[gCurrentOscBank]->sampleCount += gOscBanks[gCurrentOscBank]->hopCounter;
274 gOscBanks[gCurrentOscBank]->nextHop(); 292 gOscBanks[gCurrentOscBank]->nextHop();
275 } 293 }
276 } 294 }
277 #else 295 #else
278 for(int n = 0; n < numAudioFrames; n++) { 296 for(unsigned int n = 0; n < context->audioFrames; n++) {
279 audioOut[2*n] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n]*audioInStatus; 297 context->audioOut[2*n] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n]*audioInStatus;
280 audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n+1]*audioInStatus; 298 context->audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n+1]*audioInStatus;
281 299
282 filterIn[0][n] = fabs(audioIn[2*n]); // rectify for peak detection in 1 300 filterIn[0][n] = fabs(context->audioIn[2*n]); // rectify for peak detection in 1
283 filterIn[1][n] = fabs(audioIn[2*n+1]); // rectify for peak detection in 2 301 filterIn[1][n] = fabs(context->audioIn[2*n+1]); // rectify for peak detection in 2
284 302
285 /* FIXME why doesn't this work? */ 303 /* FIXME why doesn't this work? */
286 /* 304 /*
287 if(gOscillatorBufferReadPointer == gOscillatorBufferCurrentSize/2) { 305 if(gOscillatorBufferReadPointer == gOscillatorBufferCurrentSize/2) {
288 gOscillatorNeedsRender = true; 306 gOscillatorNeedsRender = true;
303 // New buffer size is whatever finished writing last hop 321 // New buffer size is whatever finished writing last hop
304 gOscillatorBufferReadCurrentSize = gOscillatorBufferWriteCurrentSize; 322 gOscillatorBufferReadCurrentSize = gOscillatorBufferWriteCurrentSize;
305 gOscillatorBufferReadPointer = 0; 323 gOscillatorBufferReadPointer = 0;
306 324
307 gOscillatorNeedsRender = true; 325 gOscillatorNeedsRender = true;
308 scheduleAuxiliaryTask(gMediumPriorityRender); 326 BeagleRT_scheduleAuxiliaryTask(gMediumPriorityRender);
309 } 327 }
310 } 328 }
311 #endif 329 #endif
312 } 330 }
313 else 331 else
314 { 332 {
315 for(int n = 0; n < numAudioFrames; n++) { 333 for(unsigned int n = 0; n < context->audioFrames; n++) {
316 audioOut[2*n] = audioIn[2*n]*audioInStatus; 334 context->audioOut[2*n] = context->audioIn[2*n]*audioInStatus;
317 audioOut[2*n + 1] = audioIn[2*n+1]*audioInStatus; 335 context->audioOut[2*n + 1] = context->audioIn[2*n+1]*audioInStatus;
318 336
319 filterIn[0][n] = fabs(audioIn[2*n]); // rectify for peak detection in 1 337 filterIn[0][n] = fabs(context->audioIn[2*n]); // rectify for peak detection in 1
320 filterIn[1][n] = fabs(audioIn[2*n+1]); // rectify for peak detection in 2 338 filterIn[1][n] = fabs(context->audioIn[2*n+1]); // rectify for peak detection in 2
321 } 339 }
322 } 340 }
323 341
324 // low pass filter audio in 1 and 2 for peak detection 342 // low pass filter audio in 1 and 2 for peak detection
325 ne10_fir_float_neon(&filter[0], filterIn[0], filterOut[0], blockSize); 343 ne10_fir_float_neon(&filter[0], filterIn[0], filterOut[0], blockSize);
326 ne10_fir_float_neon(&filter[1], filterIn[1], filterOut[1], blockSize); 344 ne10_fir_float_neon(&filter[1], filterIn[1], filterOut[1], blockSize);
327 345
328 for(int n = 0; n < numMatrixFrames; n++) { 346 for(unsigned int n = 0; n < context->analogFrames; n++) {
329 347
330 348
331 /* Matrix Out 0, In 0 349 /* Matrix Out 0, In 0
332 * 350 *
333 * CV loop 351 * CV loop
334 * Controls pitch of sound 352 * Controls pitch of sound
335 */ 353 */
336 int touchPosInt = gSensor0LatestTouchPos * 65536.0; 354 float touchPosInt = gSensor0LatestTouchPos;
337 if(touchPosInt < 0) touchPosInt = 0; 355 if(touchPosInt < 0) touchPosInt = 0;
338 if(touchPosInt > 65535) touchPosInt = 65535; 356 if(touchPosInt > 1.0) touchPosInt = 1.0;
339 matrixOut[n*8 + DAC_PIN0] = touchPosInt; 357 context->analogOut[n*8 + DAC_PIN0] = touchPosInt;
340 358
341 gPitchLatestInput = matrixIn[n*8 + ADC_PIN0]; 359 gPitchLatestInput = context->analogIn[n*8 + ADC_PIN0];
342 360
343 361
344 /* Matrix Out 7 362 /* Matrix Out 7
345 * 363 *
346 * Loop feedback with Matrix In 0 364 * Loop feedback with Matrix In 0
349 float deltaTarget = 0; 367 float deltaTarget = 0;
350 int semitoneIndex = 0; 368 int semitoneIndex = 0;
351 if(gSensor0LatestTouchNum>0) 369 if(gSensor0LatestTouchNum>0)
352 { 370 {
353 // current pitch is gPitchLatestInput, already retrieved 371 // current pitch is gPitchLatestInput, already retrieved
354 semitoneIndex = ( ( (float)gPitchLatestInput / 65535)*12*N_OCT )+0.5; // closest semitone 372 semitoneIndex = ( gPitchLatestInput * 12 * N_OCT )+0.5; // closest semitone
355 deltaTarget = (semitones[semitoneIndex]-gPitchLatestInput); // delta between pitch and target 373 deltaTarget = (semitones[semitoneIndex]-gPitchLatestInput); // delta between pitch and target
356 deltaTouch += deltaTarget*deltaWeightI; // update feedback [previous + current] 374 deltaTouch += deltaTarget*(deltaWeightI); // update feedback [previous + current]
357 } 375 }
358 else 376 else
359 deltaTouch = 0; 377 deltaTouch = 0;
360 378
361 int nextOut = touchPosInt + deltaTarget*deltaWeightP + deltaTouch; // add feedback to touch -> next out 379 float nextOut = touchPosInt + deltaTarget*deltaWeightP + deltaTouch; // add feedback to touch -> next out
362 if(nextOut < 0) nextOut = 0; // clamp 380 if(nextOut < 0) nextOut = 0; // clamp
363 if(nextOut > 65535) nextOut = 65535; // clamp 381 if(nextOut > 1.0) nextOut = 1.0; // clamp
364 matrixOut[n*8 + DAC_PIN7] = nextOut; // send next nextOut 382 context->analogOut[n*8 + DAC_PIN7] = nextOut; // send next nextOut
365 383
366 384
367 /* 385 /*
368 * Matrix Out 1, In 1 386 * Matrix Out 1, In 1
369 * 387 *
370 * Hysteresis (comparator) oscillator 388 * Hysteresis (comparator) oscillator
371 * Controls speed of playback 389 * Controls speed of playback
372 */ 390 */
373 bool wasRising = gSpeedHysteresisOscillatorRising; 391 bool wasRising = gSpeedHysteresisOscillatorRising;
374 matrixOut[n*8 + DAC_PIN1] = hysteresis_oscillator(matrixIn[n*8 + ADC_PIN1], 48000, 16000, &gSpeedHysteresisOscillatorRising); 392 context->analogOut[n*8 + DAC_PIN1] = hysteresis_oscillator(context->analogIn[n*8 + ADC_PIN1], 48000.0/65536.0,
393 16000.0/65536.0, &gSpeedHysteresisOscillatorRising);
375 394
376 // Find interval of zero crossing 395 // Find interval of zero crossing
377 if(wasRising && !gSpeedHysteresisOscillatorRising) { 396 if(wasRising && !gSpeedHysteresisOscillatorRising) {
378 int interval = gMatrixSampleCount - gSpeedHysteresisLastTrigger; 397 int interval = gMatrixSampleCount - gSpeedHysteresisLastTrigger;
379 398
392 * 411 *
393 * Feedback (phase shift) oscillator 412 * Feedback (phase shift) oscillator
394 * Controls wavetable used for oscillator bank 413 * Controls wavetable used for oscillator bank
395 */ 414 */
396 415
397 int tableLength = gFeedbackOscillator.process(matrixIn[n*8 + ADC_PIN2], &matrixOut[n*8 + DAC_PIN2]); 416 int tableLength = gFeedbackOscillator.process(context->analogIn[n*8 + ADC_PIN2], &context->analogOut[n*8 + DAC_PIN2]);
398 if(tableLength != 0) { 417 if(tableLength != 0) {
399 gFeedbackOscillatorTableLength = tableLength; 418 gFeedbackOscillatorTableLength = tableLength;
400 gFeedbackOscillatorTable = gFeedbackOscillator.wavetable(); 419 gFeedbackOscillatorTable = gFeedbackOscillator.wavetable();
401 gDynamicWavetableNeedsRender = true; 420 gDynamicWavetableNeedsRender = true;
402 scheduleAuxiliaryTask(gLowPriorityRender); 421 BeagleRT_scheduleAuxiliaryTask(gLowPriorityRender);
403 } 422 }
404 423
405 /* 424 /*
406 * Matrix Out 3, In 3 425 * Matrix Out 3, In 3
407 * 426 *
409 * Touch positions from sensor 1 428 * Touch positions from sensor 1
410 * Change every 32 samples (ca. 1.5 ms) 429 * Change every 32 samples (ca. 1.5 ms)
411 */ 430 */
412 volatile int touchCount = gSensor1LatestTouchCount; 431 volatile int touchCount = gSensor1LatestTouchCount;
413 if(touchCount == 0) 432 if(touchCount == 0)
414 matrixOut[n*8 + DAC_PIN3] = 0; 433 context->analogOut[n*8 + DAC_PIN3] = 0;
415 else { 434 else {
416 int touchIndex = (gMatrixSampleCount >> 5) % touchCount; 435 int touchIndex = (gMatrixSampleCount >> 5) % touchCount;
417 matrixOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f; 436 context->analogOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f / 65536.0f;
418 if(touchIndex != gSensor1LastTouchIndex) { 437 if(touchIndex != gSensor1LastTouchIndex) {
419 // Just changed to a new touch output. Reset the counter. 438 // Just changed to a new touch output. Reset the counter.
420 // It will take 2*matrixFrames samples for this output to come back to the 439 // It will take 2*matrixFrames samples for this output to come back to the
421 // ADC input. But we also want to read near the end of the 32 sample block; 440 // ADC input. But we also want to read near the end of the 32 sample block;
422 // let's say 24 samples into it. 441 // let's say 24 samples into it.
423 442
424 // FIXME this won't work for p > 2 443 // FIXME this won't work for p > 2
425 gSensor1InputDelayCounter = 24 + 2*numMatrixFrames; 444 gSensor1InputDelayCounter = 24 + 2*context->analogFrames;
426 gSensor1InputIndex = touchIndex; 445 gSensor1InputIndex = touchIndex;
427 } 446 }
428 gSensor1LastTouchIndex = touchIndex; 447 gSensor1LastTouchIndex = touchIndex;
429 } 448 }
430 449
431 if(gSensor1InputDelayCounter-- >= 0 && touchCount > 0) { 450 if(gSensor1InputDelayCounter-- >= 0 && touchCount > 0) {
432 gSensor1MatrixTouchPos[gSensor1InputIndex] = (float)matrixIn[n*8 + ADC_PIN3] / 65536.0f; 451 gSensor1MatrixTouchPos[gSensor1InputIndex] = context->analogIn[n*8 + ADC_PIN3];
433 } 452 }
434 453
435 /* Matrix Out 4 454 /* Matrix Out 4
436 * 455 *
437 * Sensor 1 last pos 456 * Sensor 1 last pos
438 */ 457 */
439 touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex] * 65536.0; 458 touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex];
440 if(touchPosInt < 0) touchPosInt = 0; 459 if(touchPosInt < 0) touchPosInt = 0;
441 if(touchPosInt > 65535) touchPosInt = 65535; 460 if(touchPosInt > 1.0) touchPosInt = 1.0;
442 matrixOut[n*8 + DAC_PIN4] = touchPosInt; 461 context->analogOut[n*8 + DAC_PIN4] = touchPosInt;
443 462
444 /* Matrix In 4 463 /* Matrix In 4
445 * 464 *
446 * Loop points selector 465 * Loop points selector
447 */ 466 */
448 gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = matrixIn[n*8 + ADC_PIN4]; 467 gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = context->analogIn[n*8 + ADC_PIN4];
449 if(gLoopPointsInputBufferPointer >= gLoopPointsInputBufferSize) { 468 if(gLoopPointsInputBufferPointer >= gLoopPointsInputBufferSize) {
450 // Find min and max values 469 // Find min and max values
451 uint16_t loopMax = 0, loopMin = 65535; 470 float loopMax = 0, loopMin = 1.0;
452 for(int i = 0; i < gLoopPointsInputBufferSize; i++) { 471 for(int i = 0; i < gLoopPointsInputBufferSize; i++) {
453 if(gLoopPointsInputBuffer[i] < loopMin) 472 if(gLoopPointsInputBuffer[i] < loopMin)
454 loopMin = gLoopPointsInputBuffer[i]; 473 loopMin = gLoopPointsInputBuffer[i];
455 if(gLoopPointsInputBuffer[i] > loopMax/* && gLoopPointsInputBuffer[i] != 65535*/) 474 if(gLoopPointsInputBuffer[i] > loopMax/* && gLoopPointsInputBuffer[i] != 65535*/)
456 loopMax = gLoopPointsInputBuffer[i]; 475 loopMax = gLoopPointsInputBuffer[i];
480 } 499 }
481 } 500 }
482 501
483 PeakBurst[0].process(1); 502 PeakBurst[0].process(1);
484 503
485 int convAudio = burstOut*peak[0]*65535; 504 float convAudio = burstOut*peak[0];
486 matrixOut[n*8 + DAC_PIN5] = convAudio; 505 context->analogOut[n*8 + DAC_PIN5] = convAudio;
487 prevFiltered[0] = filterOut[0][n*2+1]; 506 prevFiltered[0] = filterOut[0][n*2+1];
488 if(prevFiltered[0]>1) 507 if(prevFiltered[0]>1)
489 prevFiltered[0] = 1; 508 prevFiltered[0] = 1;
490 509
491 /* Matrix In 5 510 /* Matrix In 5
492 * 511 *
493 * Dissonance, via changing frequency motion of partials 512 * Dissonance, via changing frequency motion of partials
494 */ 513 */
495 float amount = (float)matrixIn[n*8 + ADC_PIN5] / 65536.0f; 514 float amount = (float)context->analogIn[n*8 + ADC_PIN5];
496 gOscBanks[gCurrentOscBank]->freqMovement = 1-amount; 515 gOscBanks[gCurrentOscBank]->freqMovement = 1.0 - amount;
497 516
498 517
499 518
500 519
501 /* Matrix Out 6 520 /* Matrix Out 6
514 } 533 }
515 } 534 }
516 535
517 PeakBurst[1].process(1); 536 PeakBurst[1].process(1);
518 537
519 convAudio = burstOut*peak[1]*65535; 538 convAudio = burstOut*peak[1];
520 matrixOut[n*8 + DAC_PIN6] = convAudio; 539 context->analogOut[n*8 + DAC_PIN6] = convAudio;
521 prevFiltered[1] = filterOut[1][n*2+1]; 540 prevFiltered[1] = filterOut[1][n*2+1];
522 if(prevFiltered[1]>1) 541 if(prevFiltered[1]>1)
523 prevFiltered[1] = 1; 542 prevFiltered[1] = 1;
524 543
525 /* Matrix In 6 544 /* Matrix In 6
527 * Sound selector 546 * Sound selector
528 */ 547 */
529 if(!gIsLoading) { 548 if(!gIsLoading) {
530 // Use hysteresis to avoid jumping back and forth between sounds 549 // Use hysteresis to avoid jumping back and forth between sounds
531 if(gOscBanks.size() > 1) { 550 if(gOscBanks.size() > 1) {
532 int input = matrixIn[n*8 + ADC_PIN6]; 551 float input = context->analogIn[n*8 + ADC_PIN6];
533 const int hystValue = 16000; 552 const float hystValue = 16000.0 / 65536.0;
534 553
535 int upHysteresisValue = ((gCurrentOscBank + 1) * 65536 + hystValue) / gOscBanks.size(); 554 float upHysteresisValue = ((gCurrentOscBank + 1) + hystValue) / gOscBanks.size();
536 int downHysteresisValue = (gCurrentOscBank * 65536 - hystValue) / gOscBanks.size(); 555 float downHysteresisValue = (gCurrentOscBank - hystValue) / gOscBanks.size();
537 556
538 if(input > upHysteresisValue || input < downHysteresisValue) { 557 if(input > upHysteresisValue || input < downHysteresisValue) {
539 gNextOscBank = input * gOscBanks.size() / 65536; 558 gNextOscBank = input * gOscBanks.size();
540 if(gNextOscBank < 0) 559 if(gNextOscBank < 0)
541 gNextOscBank = 0; 560 gNextOscBank = 0;
542 if((unsigned)gNextOscBank >= gOscBanks.size()) 561 if((unsigned)gNextOscBank >= gOscBanks.size())
543 gNextOscBank = gOscBanks.size() - 1; 562 gNextOscBank = gOscBanks.size() - 1;
544 } 563 }
549 * Matrix In 7 568 * Matrix In 7
550 * 569 *
551 * FSR from primary touch sensor 570 * FSR from primary touch sensor
552 * Value ranges from 0-1799 571 * Value ranges from 0-1799
553 */ 572 */
554 gLastFSRValue = matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); 573 gLastFSRValue = context->analogIn[n*8 + ADC_PIN7] * 1799.0;
555 //gLastFSRValue = 1799 - matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0); 574 //gLastFSRValue = 1799 - context->analogIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0);
556 //dbox_printf("%i\n",gLastFSRValue); 575 //dbox_printf("%i\n",gLastFSRValue);
557 576
558 gMatrixSampleCount++; 577 gMatrixSampleCount++;
559 } 578 }
560 579
567 586
568 if(gOscillatorNeedsRender) { 587 if(gOscillatorNeedsRender) {
569 gOscillatorNeedsRender = false; 588 gOscillatorNeedsRender = false;
570 589
571 /* Render one frame into the write buffer */ 590 /* Render one frame into the write buffer */
572 memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels * sizeof(float)); 591 memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * 2 * sizeof(float)); /* assumes 2 audio channels */
573 592
574 oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, gOscillatorBufferWrite, 593 oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, gOscillatorBufferWrite,
575 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize, 594 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize,
576 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies, 595 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies,
577 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes, 596 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
578 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives, 597 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
579 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives, 598 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
580 /*gOscBanks[gCurrentOscBank]->lookupTable*/gDynamicWavetable); 599 /*gOscBanks[gCurrentOscBank]->lookupTable*/gDynamicWavetable);
581 600
582 gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels; 601 gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * 2;
583 602
584 /* Update the pitch right before the hop 603 /* Update the pitch right before the hop
585 * Total CV range +/- N_OCT octaves 604 * Total CV range +/- N_OCT octaves
586 */ 605 */
587 float pitch = (float)gPitchLatestInput / octaveSplitter - N_OCT/2; 606 float pitch = (float)gPitchLatestInput / octaveSplitter - N_OCT/2;
658 wavetable_interpolate(gFeedbackOscillatorTableLength, gDynamicWavetableLength, 677 wavetable_interpolate(gFeedbackOscillatorTableLength, gDynamicWavetableLength,
659 gFeedbackOscillatorTable, gDynamicWavetable, 678 gFeedbackOscillatorTable, gDynamicWavetable,
660 gOscBanks[gCurrentOscBank]->lookupTable, sineMix); 679 gOscBanks[gCurrentOscBank]->lookupTable, sineMix);
661 } 680 }
662 681
663 if(gLoopPointMin >= 60000 && gLoopPointMax >= 60000) { 682 if(gLoopPointMin >= 60000.0/65536.0 && gLoopPointMax >= 60000.0/65536.0) {
664 // KLUDGE! 683 // KLUDGE!
665 if(gCurrentOscBank == 0) 684 if(gCurrentOscBank == 0)
666 gOscBanks[gCurrentOscBank]->setLoopHops(50, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.6) - 1); 685 gOscBanks[gCurrentOscBank]->setLoopHops(50, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.6) - 1);
667 else 686 else
668 gOscBanks[gCurrentOscBank]->setLoopHops(5, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.7) - 1); 687 gOscBanks[gCurrentOscBank]->setLoopHops(5, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.7) - 1);
669 } 688 }
670 else { 689 else {
671 float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0; 690 float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop();
672 float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0; 691 float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop();
673 692
674 int intLoopPointMin = normLoopPointMin; 693 int intLoopPointMin = normLoopPointMin;
675 if(intLoopPointMin < 1) 694 if(intLoopPointMin < 1)
676 intLoopPointMin = 1; 695 intLoopPointMin = 1;
677 int intLoopPointMax = normLoopPointMax; 696 int intLoopPointMax = normLoopPointMax;
710 729
711 //dbox_printf("min %d max %d\n", gLoopPointMin, gLoopPointMax); 730 //dbox_printf("min %d max %d\n", gLoopPointMin, gLoopPointMax);
712 } 731 }
713 732
714 // Clean up at the end of render 733 // Clean up at the end of render
715 void cleanup_render() 734 void cleanup(BeagleRTContext *context, void *userData)
716 { 735 {
717 free(gOscillatorBuffer1); 736 free(gOscillatorBuffer1);
718 free(gOscillatorBuffer2); 737 free(gOscillatorBuffer2);
719 free(gDynamicWavetable); 738 free(gDynamicWavetable);
720 } 739 }
742 761
743 tableOut[numSamplesOut] = tableOut[0]; 762 tableOut[numSamplesOut] = tableOut[0];
744 } 763 }
745 764
746 // Create a hysteresis oscillator with a matrix input and output 765 // Create a hysteresis oscillator with a matrix input and output
747 inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold, uint16_t fallingThreshold, bool *rising) 766 inline float hysteresis_oscillator(float input, float risingThreshold, float fallingThreshold, bool *rising)
748 { 767 {
749 uint16_t value; 768 float value;
750 769
751 if(*rising) { 770 if(*rising) {
752 if(input > risingThreshold) { 771 if(input > risingThreshold) {
753 *rising = false; 772 *rising = false;
754 value = 0; 773 value = 0;
755 } 774 }
756 else 775 else
757 value = 65535; 776 value = 1.0;
758 } 777 }
759 else { 778 else {
760 if(input < fallingThreshold) { 779 if(input < fallingThreshold) {
761 *rising = true; 780 *rising = true;
762 value = 65535; 781 value = 1.0;
763 } 782 }
764 else 783 else
765 value = 0; 784 value = 0;
766 } 785 }
767 786