Mercurial > hg > beaglert
comparison projects/cape_test/render.cpp @ 55:41d24dba6b74 newapi
Add cape test project and make rt_printf (rtdk.h) part of standard BeagleRT.h include
author | andrewm |
---|---|
date | Mon, 15 Jun 2015 18:16:00 +0100 |
parents | |
children | 3c3a1357657d |
comparison
equal
deleted
inserted
replaced
52:a6d223473ea2 | 55:41d24dba6b74 |
---|---|
1 /* | |
2 * render.cpp | |
3 * | |
4 * Created on: Oct 24, 2014 | |
5 * Author: parallels | |
6 */ | |
7 | |
8 | |
9 #include "../../include/BeagleRT.h" | |
10 #include <cmath> | |
11 | |
12 #define ANALOG_LOW (2048.0 / 65536.0) | |
13 #define ANALOG_HIGH (50000.0 / 65536.0) | |
14 | |
15 const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7}; | |
16 | |
17 uint64_t gLastErrorFrame = 0; | |
18 uint32_t gEnvelopeSampleCount = 0; | |
19 float gEnvelopeValue = 0.5; | |
20 float gEnvelopeDecayRate = 0.9995; | |
21 | |
22 // initialise_render() is called once before the audio rendering starts. | |
23 // Use it to perform any initialisation and allocation which is dependent | |
24 // on the period size or sample rate. | |
25 // | |
26 // userData holds an opaque pointer to a data structure that was passed | |
27 // in from the call to initAudio(). | |
28 // | |
29 // Return true on success; returning false halts the program. | |
30 | |
31 bool initialise_render(BeagleRTContext *context, void *userData) | |
32 { | |
33 return true; | |
34 } | |
35 | |
36 // render() is called regularly at the highest priority by the audio engine. | |
37 // Input and output are given from the audio hardware and the other | |
38 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | |
39 // will be 0. | |
40 | |
41 void render(BeagleRTContext *context, void *userData) | |
42 { | |
43 static float phase = 0.0; | |
44 static int sampleCounter = 0; | |
45 static int invertChannel = 0; | |
46 float frequency = 0; | |
47 | |
48 // Play a sine wave on the audio output | |
49 for(unsigned int n = 0; n < context->audioFrames; n++) { | |
50 context->audioOut[2*n] = context->audioOut[2*n + 1] = gEnvelopeValue * sinf(phase); | |
51 | |
52 // If one second has gone by with no error, play one sound, else | |
53 // play another | |
54 if(context->audioSampleCount + n - gLastErrorFrame > 44100) { | |
55 gEnvelopeValue *= gEnvelopeDecayRate; | |
56 gEnvelopeSampleCount++; | |
57 if(gEnvelopeSampleCount > 22050) { | |
58 gEnvelopeValue = 0.5; | |
59 gEnvelopeSampleCount = 0; | |
60 } | |
61 frequency = 880.0; | |
62 } | |
63 else { | |
64 gEnvelopeValue = 0.5; | |
65 frequency = 220.0; | |
66 } | |
67 | |
68 phase += 2.0 * M_PI * frequency / 44100.0; | |
69 if(phase >= 2.0 * M_PI) | |
70 phase -= 2.0 * M_PI; | |
71 } | |
72 | |
73 for(unsigned int n = 0; n < context->analogFrames; n++) { | |
74 // Change outputs every 512 samples | |
75 if(sampleCounter < 512) { | |
76 for(int k = 0; k < 8; k++) { | |
77 if(k == invertChannel) | |
78 context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH; | |
79 else | |
80 context->analogOut[n*8 + gDACPinOrder[k]] = 0; | |
81 } | |
82 } | |
83 else { | |
84 for(int k = 0; k < 8; k++) { | |
85 if(k == invertChannel) | |
86 context->analogOut[n*8 + gDACPinOrder[k]] = 0; | |
87 else | |
88 context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH; | |
89 } | |
90 } | |
91 | |
92 // Read after 256 samples: input should be low | |
93 if(sampleCounter == 256) { | |
94 for(int k = 0; k < 8; k++) { | |
95 if(k == invertChannel) { | |
96 if(context->analogIn[n*8 + k] < ANALOG_HIGH) { | |
97 rt_printf("FAIL [output %d, input %d] -- output HIGH input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); | |
98 gLastErrorFrame = context->audioSampleCount + n; | |
99 } | |
100 } | |
101 else { | |
102 if(context->analogIn[n*8 + k] > ANALOG_LOW) { | |
103 rt_printf("FAIL [output %d, input %d] -- output LOW --> input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); | |
104 gLastErrorFrame = context->audioSampleCount + n; | |
105 } | |
106 } | |
107 } | |
108 } | |
109 else if(sampleCounter == 768) { | |
110 for(int k = 0; k < 8; k++) { | |
111 if(k == invertChannel) { | |
112 if(context->analogIn[n*8 + k] > ANALOG_LOW) { | |
113 rt_printf("FAIL [output %d, input %d] -- output LOW input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); | |
114 gLastErrorFrame = context->audioSampleCount + n; | |
115 } | |
116 } | |
117 else { | |
118 if(context->analogIn[n*8 + k] < ANALOG_HIGH) { | |
119 rt_printf("FAIL [output %d, input %d] -- output HIGH input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]); | |
120 gLastErrorFrame = context->audioSampleCount + n; | |
121 } | |
122 } | |
123 } | |
124 } | |
125 | |
126 if(++sampleCounter >= 1024) { | |
127 sampleCounter = 0; | |
128 invertChannel++; | |
129 if(invertChannel >= 8) | |
130 invertChannel = 0; | |
131 } | |
132 } | |
133 } | |
134 | |
135 // cleanup_render() is called once at the end, after the audio has stopped. | |
136 // Release any resources that were allocated in initialise_render(). | |
137 | |
138 void cleanup_render(BeagleRTContext *context, void *userData) | |
139 { | |
140 | |
141 } |