comparison projects/oscillator_bank/render.cpp @ 45:579c86316008 newapi

Major API overhaul. Moved to a single data structure for handling render functions. Functionally, generally similar except for scheduling within PRU loop function, which now uses interrupts from the PRU rather than polling. This requires an updated kernel.
author andrewm
date Thu, 28 May 2015 14:35:55 -0400
parents 06f93bef7dd2
children 643cbee74eda
comparison
equal deleted inserted replaced
40:419ce4ebfc4c 45:579c86316008
56 // 56 //
57 // userData holds an opaque pointer to a data structure that was passed 57 // userData holds an opaque pointer to a data structure that was passed
58 // in from the call to initAudio(). 58 // in from the call to initAudio().
59 // 59 //
60 // Return true on success; returning false halts the program. 60 // Return true on success; returning false halts the program.
61 bool initialise_render(int numMatrixChannels, int numAudioChannels, 61 bool initialise_render(int numMatrixChannels, int numDigitalChannels, int numAudioChannels,
62 int numMatrixFramesPerPeriod, 62 int numMatrixFramesPerPeriod,
63 int numAudioFramesPerPeriod, 63 int numAudioFramesPerPeriod,
64 float matrixSampleRate, float audioSampleRate, 64 float matrixSampleRate, float audioSampleRate,
65 void *userData) 65 void *userData, RTAudioSettings* settings)
66 { 66 {
67 srandom(time(NULL)); 67 srandom(time(NULL));
68 68
69 if(numAudioChannels != 2) { 69 if(numAudioChannels != 2) {
70 rt_printf("Error: this example needs stereo audio enabled\n"); 70 rt_printf("Error: this example needs stereo audio enabled\n");
123 gFrequencies[n] *= (float)gWavetableLength / audioSampleRate; 123 gFrequencies[n] *= (float)gWavetableLength / audioSampleRate;
124 gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators; 124 gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators;
125 gDFrequencies[n] = gDAmplitudes[n] = 0.0; 125 gDFrequencies[n] = gDAmplitudes[n] = 0.0;
126 } 126 }
127 127
128 increment = 0;
129 freq = 440.0;
130
131 for(int n = 0; n < gNumOscillators; n++) {
132 // Update the frequencies to a regular spread, plus a small amount of randomness
133 // to avoid weird phase effects
134 float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
135 float newFreq = freq * randScale;
136
137 // For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
138 gFrequencies[n] = newFreq * (float)gWavetableLength / audioSampleRate;
139
140 freq += increment;
141 }
142
128 // Initialise auxiliary tasks 143 // Initialise auxiliary tasks
129 if((gFrequencyUpdateTask = createAuxiliaryTaskLoop(&recalculate_frequencies, 90, "beaglert-update-frequencies")) == 0) 144 if((gFrequencyUpdateTask = createAuxiliaryTaskLoop(&recalculate_frequencies, 90, "beaglert-update-frequencies")) == 0)
130 return false; 145 return false;
146
147 for(int n = 0; n < gNumOscillators; n++)
148 rt_printf("%f\n", gFrequencies[n]);
131 149
132 gAudioSampleRate = audioSampleRate; 150 gAudioSampleRate = audioSampleRate;
133 gSampleCount = 0; 151 gSampleCount = 0;
134 152
135 return true; 153 return true;
138 // render() is called regularly at the highest priority by the audio engine. 156 // render() is called regularly at the highest priority by the audio engine.
139 // Input and output are given from the audio hardware and the other 157 // Input and output are given from the audio hardware and the other
140 // ADCs and DACs (if available). If only audio is available, numMatrixFrames 158 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
141 // will be 0. 159 // will be 0.
142 160
143 void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, 161 void render(int numAnalogFrames, int numAudioFrames, int numDigitalFrames, float *audioIn, float *audioOut,
144 uint16_t *matrixIn, uint16_t *matrixOut) 162 float *analogIn, float *analogOut, uint32_t *digital)
145 { 163 {
146 // Initialise buffer to 0 164 // Initialise buffer to 0
147 memset(audioOut, 0, 2 * numAudioFrames * sizeof(float)); 165 memset(audioOut, 0, 2 * numAudioFrames * sizeof(float));
148 166
149 // Render audio frames 167 // Render audio frames
151 gNumOscillators, gWavetableLength, 169 gNumOscillators, gWavetableLength,
152 gPhases, gFrequencies, gAmplitudes, 170 gPhases, gFrequencies, gAmplitudes,
153 gDFrequencies, gDAmplitudes, 171 gDFrequencies, gDAmplitudes,
154 gWavetable); 172 gWavetable);
155 173
156 if(numMatrixFrames != 0 && (gSampleCount += numAudioFrames) >= 128) { 174 if(numAnalogFrames != 0 && (gSampleCount += numAudioFrames) >= 128) {
157 gSampleCount = 0; 175 gSampleCount = 0;
158 gNewMinFrequency = map(matrixIn[0], 0, MATRIX_MAX, 20.0f, 8000.0f); 176 gNewMinFrequency = map(analogIn[0], 0, 1.0, 1000.0f, 8000.0f);
159 gNewMaxFrequency = map(matrixIn[1], 0, MATRIX_MAX, 20.0f, 8000.0f); 177 gNewMaxFrequency = map(analogIn[1], 0, 1.0, 1000.0f, 8000.0f);
160 178
161 // Make sure max >= min 179 // Make sure max >= min
162 if(gNewMaxFrequency < gNewMinFrequency) { 180 if(gNewMaxFrequency < gNewMinFrequency) {
163 float temp = gNewMaxFrequency; 181 float temp = gNewMaxFrequency;
164 gNewMaxFrequency = gNewMinFrequency; 182 gNewMaxFrequency = gNewMinFrequency;
165 gNewMinFrequency = temp; 183 gNewMinFrequency = temp;
166 } 184 }
167 185
168 // Request that the lower-priority task run at next opportunity 186 // Request that the lower-priority task run at next opportunity
169 scheduleAuxiliaryTask(gFrequencyUpdateTask); 187 //scheduleAuxiliaryTask(gFrequencyUpdateTask);
170 } 188 }
171 } 189 }
172 190
173 // This is a lower-priority call to update the frequencies which will happen 191 // This is a lower-priority call to update the frequencies which will happen
174 // periodically when the matrix is enabled. By placing it at a lower priority, 192 // periodically when the matrix is enabled. By placing it at a lower priority,