comparison projects/tank_wars/render.cpp @ 56:3c3a1357657d newapi

Further API update to name three primary functions setup(), render() and cleanup(). Changed include paths so now can #include <BeagleRT.h>. Removed stale pru_rtaudio.bin file as this is now done as pru_rtaudio_bin.h. Updated examples to new API and fixed minor compiler warnings along the way. Network example needs further attention to compile.
author andrewm
date Wed, 15 Jul 2015 12:10:51 +0100
parents fbfeb5895efd
children 8d80eda512cd
comparison
equal deleted inserted replaced
55:41d24dba6b74 56:3c3a1357657d
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 "game.h" 11 #include "game.h"
12 #include <rtdk.h> 12 #include <rtdk.h>
13 #include <cmath> 13 #include <cmath>
14 #include <cstdlib> 14 #include <cstdlib>
15 #include <time.h> 15 #include <time.h>
76 float gSoundProjectileOscillatorGain = 0.2; 76 float gSoundProjectileOscillatorGain = 0.2;
77 float gOscillatorPhaseScaler = 0; 77 float gOscillatorPhaseScaler = 0;
78 78
79 void screen_update(); 79 void screen_update();
80 80
81 // initialise_render() is called once before the audio rendering starts. 81 // setup() is called once before the audio rendering starts.
82 // Use it to perform any initialisation and allocation which is dependent 82 // Use it to perform any initialisation and allocation which is dependent
83 // on the period size or sample rate. 83 // on the period size or sample rate.
84 // 84 //
85 // userData holds an opaque pointer to a data structure that was passed 85 // userData holds an opaque pointer to a data structure that was passed
86 // in from the call to initAudio(). 86 // in from the call to initAudio().
87 // 87 //
88 // Return true on success; returning false halts the program. 88 // Return true on success; returning false halts the program.
89 89
90 bool initialise_render(int numAnalogChannels, int numDigitalChannels, int numAudioChannels, 90 bool setup(BeagleRTContext *context, void *userData)
91 int numAnalogFramesPerPeriod,
92 int numAudioFramesPerPeriod,
93 float analogSampleRate, float audioSampleRate,
94 void *userData)
95 { 91 {
96 srandom(time(NULL)); 92 srandom(time(NULL));
97 93
98 // Verify we are running with matrix enabled 94 // Verify we are running with matrix enabled
99 if(numAnalogFramesPerPeriod == 0 || numAnalogChannels < 4) { 95 if(context->analogFrames == 0 || context->analogChannels < 4) {
100 rt_printf("Error: this example needs the matrix enabled with at least 4 channels\n"); 96 rt_printf("Error: this example needs the matrix enabled with at least 4 channels\n");
101 return false; 97 return false;
102 } 98 }
103 99
104 // Initialise audio variables 100 // Initialise audio variables
105 gAudioFramesPerMatrixFrame = numAudioFramesPerPeriod / numAnalogFramesPerPeriod; 101 gAudioFramesPerMatrixFrame = context->audioFrames / context->analogFrames;
106 gOscillatorPhaseScaler = 2.0 * M_PI / audioSampleRate; 102 gOscillatorPhaseScaler = 2.0 * M_PI / context->audioSampleRate;
107 103
108 // Initialise the screen buffers 104 // Initialise the screen buffers
109 gScreenBufferMaxLength = 2 * analogSampleRate / gScreenFramesPerSecond; 105 gScreenBufferMaxLength = 2 * context->analogSampleRate / gScreenFramesPerSecond;
110 gScreenBuffer1 = new float[gScreenBufferMaxLength]; 106 gScreenBuffer1 = new float[gScreenBufferMaxLength];
111 gScreenBuffer2 = new float[gScreenBufferMaxLength]; 107 gScreenBuffer2 = new float[gScreenBufferMaxLength];
112 if(gScreenBuffer1 == 0 || gScreenBuffer2 == 0) { 108 if(gScreenBuffer1 == 0 || gScreenBuffer2 == 0) {
113 rt_printf("Error initialising screen buffers\n"); 109 rt_printf("Error initialising screen buffers\n");
114 return false; 110 return false;
121 gScreenBufferNextUpdateLocation = 0; 117 gScreenBufferNextUpdateLocation = 0;
122 gScreenNextBufferReady = false; 118 gScreenNextBufferReady = false;
123 119
124 // Initialise the game 120 // Initialise the game
125 setupGame(gScreenWidth, gScreenHeight); 121 setupGame(gScreenWidth, gScreenHeight);
126 gGameFrameInterval = analogSampleRate / gGameFramesPerSecond; 122 gGameFrameInterval = context->analogSampleRate / gGameFramesPerSecond;
127 gSamplesUntilNextFrame = gGameFrameInterval; 123 gSamplesUntilNextFrame = gGameFrameInterval;
128 124
129 // Initialise auxiliary tasks 125 // Initialise auxiliary tasks
130 if((gScreenUpdateTask = createAuxiliaryTaskLoop(&screen_update, 90, 126 if((gScreenUpdateTask = BeagleRT_createAuxiliaryTask(&screen_update, 90,
131 "beaglert-screen-update")) == 0) 127 "beaglert-screen-update")) == 0)
132 return false; 128 return false;
133 129
134 return true; 130 return true;
135 } 131 }
136 132
157 // render() is called regularly at the highest priority by the audio engine. 153 // render() is called regularly at the highest priority by the audio engine.
158 // Input and output are given from the audio hardware and the other 154 // Input and output are given from the audio hardware and the other
159 // ADCs and DACs (if available). If only audio is available, numMatrixFrames 155 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
160 // will be 0. 156 // will be 0.
161 157
162 void render(int numAnalogFrames, int numDigitalFrames, int numAudioFrames, float *audioIn, float *audioOut, 158 void render(BeagleRTContext *context, void *userData)
163 float *analogIn, float *analogOut, uint32_t *digital)
164 { 159 {
165 int audioIndex = 0; 160 int audioIndex = 0;
166 161
167 for(int n = 0; n < numAnalogFrames; n++) { 162 for(unsigned int n = 0; n < context->analogFrames; n++) {
168 for(int k = 0; k < gAudioFramesPerMatrixFrame; k++) { 163 for(int k = 0; k < gAudioFramesPerMatrixFrame; k++) {
169 // Render music and sound 164 // Render music and sound
170 float audioSample = 0; 165 float audioSample = 0;
171 166
172 // Music plays in a loop 167 // Music plays in a loop
191 1.0, 0, 300, 2000), 200, 6000); 186 1.0, 0, 300, 2000), 200, 6000);
192 if(gSoundProjectileOscillatorPhase > 2.0 * M_PI) 187 if(gSoundProjectileOscillatorPhase > 2.0 * M_PI)
193 gSoundProjectileOscillatorPhase -= 2.0 * M_PI; 188 gSoundProjectileOscillatorPhase -= 2.0 * M_PI;
194 } 189 }
195 190
196 audioOut[2*audioIndex] = audioOut[2*audioIndex + 1] = audioSample; 191 context->audioOut[2*audioIndex] = context->audioOut[2*audioIndex + 1] = audioSample;
197 audioIndex++; 192 audioIndex++;
198 } 193 }
199 194
200 // First-order lowpass filter to remove noise on launch FSR 195 // First-order lowpass filter to remove noise on launch FSR
201 float rawSample = AnalogRead(gInputLauncher, n); 196 float rawSample = analogReadFrame(context, n, gInputLauncher);
202 float launchSample = gLauncherFilterPole * gLauncherLastSample + 197 float launchSample = gLauncherFilterPole * gLauncherLastSample +
203 (1.0f - gLauncherFilterPole) * rawSample; 198 (1.0f - gLauncherFilterPole) * rawSample;
204 gLauncherLastSample = launchSample; 199 gLauncherLastSample = launchSample;
205 200
206 // Peak-detect on launch signal 201 // Peak-detect on launch signal
230 225
231 if(--gSamplesUntilNextFrame <= 0) { 226 if(--gSamplesUntilNextFrame <= 0) {
232 // Update game physics and cannon angles 227 // Update game physics and cannon angles
233 gSamplesUntilNextFrame = gGameFrameInterval; 228 gSamplesUntilNextFrame = gGameFrameInterval;
234 229
235 setTank1CannonAngle(map(AnalogRead(gInputTank1Angle, n), 230 setTank1CannonAngle(map(analogReadFrame(context, n, gInputTank1Angle),
236 0, 1.0, M_PI, 0)); 231 0, 1.0, M_PI, 0));
237 setTank2CannonAngle(map(AnalogRead(gInputTank2Angle, n), 232 setTank2CannonAngle(map(analogReadFrame(context, n, gInputTank2Angle),
238 0, 1.0, M_PI, 0)); 233 0, 1.0, M_PI, 0));
239 nextGameFrame(); 234 nextGameFrame();
240 235
241 // Check for collision and start sound accordingly 236 // Check for collision and start sound accordingly
242 if(gameStatusCollisionOccurred()) { 237 if(gameStatusCollisionOccurred()) {
255 float x = gScreenBufferRead[gScreenBufferReadPointer++]; 250 float x = gScreenBufferRead[gScreenBufferReadPointer++];
256 float y = gScreenBufferRead[gScreenBufferReadPointer++]; 251 float y = gScreenBufferRead[gScreenBufferReadPointer++];
257 252
258 // Rescale screen coordinates to matrix ranges; invert the Y 253 // Rescale screen coordinates to matrix ranges; invert the Y
259 // coordinate to go from normal screen coordinates to scope coordinates 254 // coordinate to go from normal screen coordinates to scope coordinates
260 AnalogWriteFrame(gOutputX, n, constrain(map(x, 0, gScreenWidth, 0, 1.0), 0, 1.0)); 255 analogWriteFrameOnce(context, n, gOutputX, constrain(map(x, 0, gScreenWidth, 0, 1.0), 0, 1.0));
261 AnalogWriteFrame(gOutputY, n, constrain(map(y, 0, gScreenHeight, 1.0, 0), 0, 1.0)); 256 analogWriteFrameOnce(context, n, gOutputY, constrain(map(y, 0, gScreenHeight, 1.0, 0), 0, 1.0));
262 } 257 }
263 else { 258 else {
264 // Still not ready! Write 0 until something happens 259 // Still not ready! Write 0 until something happens
265 AnalogWriteFrame(gOutputX, n, 0); 260 analogWriteFrameOnce(context, n, gOutputX, 0);
266 AnalogWriteFrame(gOutputY, n, 0); 261 analogWriteFrameOnce(context, n, gOutputY, 0);
267 } 262 }
268 263
269 if(gameStatusWinner() != 0) { 264 if(gameStatusWinner() != 0) {
270 // Blink one LED to show who won 265 // Blink one LED to show who won
271 // Blink both LEDs when projectile is in motion 266 // Blink both LEDs when projectile is in motion
272 float val = (gSampleCounter % 4000 > 2000) ? 1.0 : 0; 267 float val = (gSampleCounter % 4000 > 2000) ? 1.0 : 0;
273 AnalogWriteFrame(gOutputPlayer1LED, n, gameStatusWinner() == 1 ? val : 0); 268 analogWriteFrameOnce(context, n, gOutputPlayer1LED, gameStatusWinner() == 1 ? val : 0);
274 AnalogWriteFrame(gOutputPlayer2LED, n, gameStatusWinner() == 2 ? val : 0); 269 analogWriteFrameOnce(context, n, gOutputPlayer2LED, gameStatusWinner() == 2 ? val : 0);
275 270
276 // After 5 seconds, restart the game 271 // After 5 seconds, restart the game
277 gSamplesSinceFinish++; 272 gSamplesSinceFinish++;
278 if(gSamplesSinceFinish > 22050*5) 273 if(gSamplesSinceFinish > 22050*5)
279 gGameShouldRestart = true; 274 gGameShouldRestart = true;
280 } 275 }
281 else if(gameStatusProjectileInMotion()) { 276 else if(gameStatusProjectileInMotion()) {
282 // Blink both LEDs when projectile is in motion 277 // Blink both LEDs when projectile is in motion
283 float val = (gSampleCounter % 2000 > 1000) ? 1.0 : 0; 278 float val = (gSampleCounter % 2000 > 1000) ? 1.0 : 0;
284 AnalogWriteFrame(gOutputPlayer1LED, n, val); 279 analogWriteFrameOnce(context, n, gOutputPlayer1LED, val);
285 AnalogWriteFrame(gOutputPlayer2LED, n, val); 280 analogWriteFrameOnce(context, n, gOutputPlayer2LED, val);
286 } 281 }
287 else if(gameStatusPlayer1Turn()) { 282 else if(gameStatusPlayer1Turn()) {
288 AnalogWriteFrame(gOutputPlayer1LED, n, 1.0); 283 analogWriteFrameOnce(context, n, gOutputPlayer1LED, 1.0);
289 AnalogWriteFrame(gOutputPlayer2LED, n, 0); 284 analogWriteFrameOnce(context, n, gOutputPlayer2LED, 0);
290 } 285 }
291 else { 286 else {
292 AnalogWriteFrame(gOutputPlayer2LED, n, 1.0); 287 analogWriteFrameOnce(context, n, gOutputPlayer2LED, 1.0);
293 AnalogWriteFrame(gOutputPlayer1LED, n, 0); 288 analogWriteFrameOnce(context, n, gOutputPlayer1LED, 0);
294 } 289 }
295 290
296 // Check if we have reached the point where we should next update 291 // Check if we have reached the point where we should next update
297 if(gScreenBufferReadPointer >= gScreenBufferNextUpdateLocation && 292 if(gScreenBufferReadPointer >= gScreenBufferNextUpdateLocation &&
298 !gScreenNextBufferReady) { 293 !gScreenNextBufferReady) {
299 // Update the screen at lower priority than the audio thread 294 // Update the screen at lower priority than the audio thread
300 scheduleAuxiliaryTask(gScreenUpdateTask); 295 BeagleRT_scheduleAuxiliaryTask(gScreenUpdateTask);
301 } 296 }
302 297
303 gSampleCounter++; 298 gSampleCounter++;
304 } 299 }
305 } 300 }
318 313
319 // Flag it as ready to go 314 // Flag it as ready to go
320 gScreenNextBufferReady = true; 315 gScreenNextBufferReady = true;
321 } 316 }
322 317
323 // cleanup_render() is called once at the end, after the audio has stopped. 318 // cleanup() is called once at the end, after the audio has stopped.
324 // Release any resources that were allocated in initialise_render(). 319 // Release any resources that were allocated in setup().
325 320
326 void cleanup_render() 321 void cleanup(BeagleRTContext *context, void *userData)
327 { 322 {
328 // Clean up the game state 323 // Clean up the game state
329 cleanupGame(); 324 cleanupGame();
330 } 325 }