comparison projects/oscillator_bank/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 ac8eb07afcf5
comparison
equal deleted inserted replaced
54:d3f869b98147 108:3068421c0737
4 * Created on: Oct 24, 2014 4 * Created on: Oct 24, 2014
5 * Author: parallels 5 * Author: parallels
6 */ 6 */
7 7
8 8
9 #include "../../include/RTAudio.h" 9 #include <BeagleRT.h>
10 #include "../../include/Utilities.h" 10 #include <Utilities.h>
11 #include <rtdk.h> 11 #include <rtdk.h>
12 #include <cstdlib> 12 #include <cstdlib>
13 #include <cmath> 13 #include <cmath>
14 #include <cstring> 14 #include <cstring>
15 #include <time.h> 15 #include <time.h>
32 // Task for handling the update of the frequencies using the matrix 32 // Task for handling the update of the frequencies using the matrix
33 AuxiliaryTask gFrequencyUpdateTask; 33 AuxiliaryTask gFrequencyUpdateTask;
34 34
35 // These settings are carried over from main.cpp 35 // These settings are carried over from main.cpp
36 // Setting global variables is an alternative approach 36 // Setting global variables is an alternative approach
37 // to passing a structure to userData in initialise_render() 37 // to passing a structure to userData in setup()
38 38
39 extern int gNumOscillators; 39 extern int gNumOscillators;
40 extern int gWavetableLength; 40 extern int gWavetableLength;
41 41
42 void recalculate_frequencies(); 42 void recalculate_frequencies();
48 float *phases, float *frequencies, float *amplitudes, 48 float *phases, float *frequencies, float *amplitudes,
49 float *freqDerivatives, float *ampDerivatives, 49 float *freqDerivatives, float *ampDerivatives,
50 float *lookupTable); 50 float *lookupTable);
51 } 51 }
52 52
53 // initialise_render() is called once before the audio rendering starts. 53 // setup() is called once before the audio rendering starts.
54 // Use it to perform any initialisation and allocation which is dependent 54 // Use it to perform any initialisation and allocation which is dependent
55 // on the period size or sample rate. 55 // on the period size or sample rate.
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 setup(BeagleRTContext *context, void *userData)
62 int numMatrixFramesPerPeriod,
63 int numAudioFramesPerPeriod,
64 float matrixSampleRate, float audioSampleRate,
65 void *userData)
66 { 62 {
67 srandom(time(NULL)); 63 srandom(time(NULL));
68 64
69 if(numAudioChannels != 2) { 65 if(context->audioChannels != 2) {
70 rt_printf("Error: this example needs stereo audio enabled\n"); 66 rt_printf("Error: this example needs stereo audio enabled\n");
71 return false; 67 return false;
72 } 68 }
73 69
74 // Initialise the sine wavetable 70 // Initialise the sine wavetable
107 float increment = (kMaximumFrequency - kMinimumFrequency) / (float)gNumOscillators; 103 float increment = (kMaximumFrequency - kMinimumFrequency) / (float)gNumOscillators;
108 104
109 for(int n = 0; n < gNumOscillators; n++) { 105 for(int n = 0; n < gNumOscillators; n++) {
110 gPhases[n] = 0.0; 106 gPhases[n] = 0.0;
111 107
112 if(numMatrixFramesPerPeriod == 0) { 108 if(context->analogFrames == 0) {
113 // Random frequencies when used without matrix 109 // Random frequencies when used without matrix
114 gFrequencies[n] = kMinimumFrequency + (kMaximumFrequency - kMinimumFrequency) * ((float)random() / (float)RAND_MAX); 110 gFrequencies[n] = kMinimumFrequency + (kMaximumFrequency - kMinimumFrequency) * ((float)random() / (float)RAND_MAX);
115 } 111 }
116 else { 112 else {
117 // Constant spread of frequencies when used with matrix 113 // Constant spread of frequencies when used with matrix
118 gFrequencies[n] = freq; 114 gFrequencies[n] = freq;
119 freq += increment; 115 freq += increment;
120 } 116 }
121 117
122 // For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians 118 // For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
123 gFrequencies[n] *= (float)gWavetableLength / audioSampleRate; 119 gFrequencies[n] *= (float)gWavetableLength / context->audioSampleRate;
124 gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators; 120 gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators;
125 gDFrequencies[n] = gDAmplitudes[n] = 0.0; 121 gDFrequencies[n] = gDAmplitudes[n] = 0.0;
126 } 122 }
127 123
124 increment = 0;
125 freq = 440.0;
126
127 for(int n = 0; n < gNumOscillators; n++) {
128 // Update the frequencies to a regular spread, plus a small amount of randomness
129 // to avoid weird phase effects
130 float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
131 float newFreq = freq * randScale;
132
133 // For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
134 gFrequencies[n] = newFreq * (float)gWavetableLength / context->audioSampleRate;
135
136 freq += increment;
137 }
138
128 // Initialise auxiliary tasks 139 // Initialise auxiliary tasks
129 if((gFrequencyUpdateTask = createAuxiliaryTaskLoop(&recalculate_frequencies, 90, "beaglert-update-frequencies")) == 0) 140 if((gFrequencyUpdateTask = BeagleRT_createAuxiliaryTask(&recalculate_frequencies, 85, "beaglert-update-frequencies")) == 0)
130 return false; 141 return false;
131 142
132 gAudioSampleRate = audioSampleRate; 143 //for(int n = 0; n < gNumOscillators; n++)
144 // rt_printf("%f\n", gFrequencies[n]);
145
146 gAudioSampleRate = context->audioSampleRate;
133 gSampleCount = 0; 147 gSampleCount = 0;
134 148
135 return true; 149 return true;
136 } 150 }
137 151
138 // render() is called regularly at the highest priority by the audio engine. 152 // 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 153 // Input and output are given from the audio hardware and the other
140 // ADCs and DACs (if available). If only audio is available, numMatrixFrames 154 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
141 // will be 0. 155 // will be 0.
142 156
143 void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut, 157 void render(BeagleRTContext *context, void *userData)
144 uint16_t *matrixIn, uint16_t *matrixOut)
145 { 158 {
146 // Initialise buffer to 0 159 // Initialise buffer to 0
147 memset(audioOut, 0, 2 * numAudioFrames * sizeof(float)); 160 memset(context->audioOut, 0, 2 * context->audioFrames * sizeof(float));
148 161
149 // Render audio frames 162 // Render audio frames
150 oscillator_bank_neon(numAudioFrames, audioOut, 163 oscillator_bank_neon(context->audioFrames, context->audioOut,
151 gNumOscillators, gWavetableLength, 164 gNumOscillators, gWavetableLength,
152 gPhases, gFrequencies, gAmplitudes, 165 gPhases, gFrequencies, gAmplitudes,
153 gDFrequencies, gDAmplitudes, 166 gDFrequencies, gDAmplitudes,
154 gWavetable); 167 gWavetable);
155 168
156 if(numMatrixFrames != 0 && (gSampleCount += numAudioFrames) >= 128) { 169 if(context->analogFrames != 0 && (gSampleCount += context->audioFrames) >= 128) {
157 gSampleCount = 0; 170 gSampleCount = 0;
158 gNewMinFrequency = map(matrixIn[0], 0, MATRIX_MAX, 20.0f, 8000.0f); 171 gNewMinFrequency = map(context->analogIn[0], 0, 1.0, 1000.0f, 8000.0f);
159 gNewMaxFrequency = map(matrixIn[1], 0, MATRIX_MAX, 20.0f, 8000.0f); 172 gNewMaxFrequency = map(context->analogIn[1], 0, 1.0, 1000.0f, 8000.0f);
160 173
161 // Make sure max >= min 174 // Make sure max >= min
162 if(gNewMaxFrequency < gNewMinFrequency) { 175 if(gNewMaxFrequency < gNewMinFrequency) {
163 float temp = gNewMaxFrequency; 176 float temp = gNewMaxFrequency;
164 gNewMaxFrequency = gNewMinFrequency; 177 gNewMaxFrequency = gNewMinFrequency;
165 gNewMinFrequency = temp; 178 gNewMinFrequency = temp;
166 } 179 }
167 180
168 // Request that the lower-priority task run at next opportunity 181 // Request that the lower-priority task run at next opportunity
169 scheduleAuxiliaryTask(gFrequencyUpdateTask); 182 //BeagleRT_scheduleAuxiliaryTask(gFrequencyUpdateTask);
170 } 183 }
171 } 184 }
172 185
173 // This is a lower-priority call to update the frequencies which will happen 186 // 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, 187 // periodically when the matrix is enabled. By placing it at a lower priority,
192 freq += increment; 205 freq += increment;
193 } 206 }
194 } 207 }
195 208
196 209
197 // cleanup_render() is called once at the end, after the audio has stopped. 210 // cleanup() is called once at the end, after the audio has stopped.
198 // Release any resources that were allocated in initialise_render(). 211 // Release any resources that were allocated in setup().
199 212
200 void cleanup_render() 213 void cleanup(BeagleRTContext *context, void *userData)
201 { 214 {
202 free(gWavetable); 215 free(gWavetable);
203 free(gPhases); 216 free(gPhases);
204 free(gFrequencies); 217 free(gFrequencies);
205 free(gAmplitudes); 218 free(gAmplitudes);