Mercurial > hg > beaglert
comparison examples/filter_IIR/render.cpp @ 300:dbeed520b014 prerelease
Renamed projects to examples
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Fri, 27 May 2016 13:58:20 +0100 |
parents | projects/filter_IIR/render.cpp@3c3a1357657d |
children | e4392164b458 |
comparison
equal
deleted
inserted
replaced
297:a3d83ebdf49b | 300:dbeed520b014 |
---|---|
1 /* | |
2 * render.cpp | |
3 * | |
4 * Created on: Oct 24, 2014 | |
5 * Author: Andrew McPherson and Victor Zappi | |
6 */ | |
7 | |
8 | |
9 #include <BeagleRT.h> // to schedule lower prio parallel process | |
10 #include <rtdk.h> | |
11 #include <cmath> | |
12 #include <stdio.h> | |
13 #include "SampleData.h" | |
14 | |
15 SampleData gSampleData; // User defined structure to get complex data from main | |
16 int gReadPtr; // Position of last read sample from file | |
17 | |
18 // filter vars | |
19 float gLastX[2]; | |
20 float gLastY[2]; | |
21 double lb0, lb1, lb2, la1, la2 = 0.0; | |
22 | |
23 // communication vars between the 2 auxiliary tasks | |
24 int gChangeCoeff = 0; | |
25 int gFreqDelta = 0; | |
26 | |
27 void initialise_filter(float freq); | |
28 | |
29 void calculate_coeff(float cutFreq); | |
30 | |
31 bool initialise_aux_tasks(); | |
32 | |
33 // Task for handling the update of the frequencies using the matrix | |
34 AuxiliaryTask gChangeCoeffTask; | |
35 | |
36 void check_coeff(); | |
37 | |
38 // Task for handling the update of the frequencies using the matrix | |
39 AuxiliaryTask gInputTask; | |
40 | |
41 void read_input(); | |
42 | |
43 | |
44 extern float gCutFreq; | |
45 | |
46 | |
47 // setup() is called once before the audio rendering starts. | |
48 // Use it to perform any initialisation and allocation which is dependent | |
49 // on the period size or sample rate. | |
50 // | |
51 // userData holds an opaque pointer to a data structure that was passed | |
52 // in from the call to initAudio(). | |
53 // | |
54 // Return true on success; returning false halts the program. | |
55 | |
56 bool setup(BeagleRTContext *context, void *userData) | |
57 { | |
58 | |
59 // Retrieve a parameter passed in from the initAudio() call | |
60 gSampleData = *(SampleData *)userData; | |
61 | |
62 gReadPtr = -1; | |
63 | |
64 initialise_filter(200); | |
65 | |
66 // Initialise auxiliary tasks | |
67 if(!initialise_aux_tasks()) | |
68 return false; | |
69 | |
70 return true; | |
71 } | |
72 | |
73 // render() is called regularly at the highest priority by the audio engine. | |
74 // Input and output are given from the audio hardware and the other | |
75 // ADCs and DACs (if available). If only audio is available, numMatrixFrames | |
76 // will be 0. | |
77 | |
78 void render(BeagleRTContext *context, void *userData) | |
79 { | |
80 for(unsigned int n = 0; n < context->audioFrames; n++) { | |
81 float sample = 0; | |
82 float out = 0; | |
83 | |
84 // If triggered... | |
85 if(gReadPtr != -1) | |
86 sample += gSampleData.samples[gReadPtr++]; // ...read each sample... | |
87 | |
88 if(gReadPtr >= gSampleData.sampleLen) | |
89 gReadPtr = -1; | |
90 | |
91 out = lb0*sample+lb1*gLastX[0]+lb2*gLastX[1]-la1*gLastY[0]-la2*gLastY[1]; | |
92 | |
93 gLastX[1] = gLastX[0]; | |
94 gLastX[0] = out; | |
95 gLastY[1] = gLastY[0]; | |
96 gLastY[0] = out; | |
97 | |
98 for(unsigned int channel = 0; channel < context->audioChannels; channel++) | |
99 context->audioOut[n * context->audioChannels + channel] = out; // ...and put it in both left and right channel | |
100 | |
101 } | |
102 | |
103 // Request that the lower-priority tasks run at next opportunity | |
104 BeagleRT_scheduleAuxiliaryTask(gChangeCoeffTask); | |
105 BeagleRT_scheduleAuxiliaryTask(gInputTask); | |
106 } | |
107 | |
108 // First calculation of coefficients | |
109 | |
110 void initialise_filter(float freq) | |
111 { | |
112 calculate_coeff(freq); | |
113 } | |
114 | |
115 | |
116 // Calculate the filter coefficients | |
117 // second order low pass butterworth filter | |
118 | |
119 void calculate_coeff(float cutFreq) | |
120 { | |
121 // Initialise any previous state (clearing buffers etc.) | |
122 // to prepare for calls to render() | |
123 float sampleRate = 44100; | |
124 double f = 2*M_PI*cutFreq/sampleRate; | |
125 double denom = 4+2*sqrt(2)*f+f*f; | |
126 lb0 = f*f/denom; | |
127 lb1 = 2*lb0; | |
128 lb2 = lb0; | |
129 la1 = (2*f*f-8)/denom; | |
130 la2 = (f*f+4-2*sqrt(2)*f)/denom; | |
131 gLastX[0] = gLastX [1] = 0; | |
132 gLastY[0] = gLastY[1] = 0; | |
133 | |
134 } | |
135 | |
136 | |
137 // Initialise the auxiliary tasks | |
138 // and print info | |
139 | |
140 bool initialise_aux_tasks() | |
141 { | |
142 if((gChangeCoeffTask = BeagleRT_createAuxiliaryTask(&check_coeff, 90, "beaglert-check-coeff")) == 0) | |
143 return false; | |
144 | |
145 if((gInputTask = BeagleRT_createAuxiliaryTask(&read_input, 50, "beaglert-read-input")) == 0) | |
146 return false; | |
147 | |
148 rt_printf("Press 'a' to trigger sample, 's' to stop\n"); | |
149 rt_printf("Press 'z' to low down cut-off freq of 100 Hz, 'x' to raise it up\n"); | |
150 rt_printf("Press 'q' to quit\n"); | |
151 | |
152 return true; | |
153 } | |
154 | |
155 // Check if cut-off freq has been changed | |
156 // and new coefficients are needed | |
157 | |
158 void check_coeff() | |
159 { | |
160 if(gChangeCoeff == 1) | |
161 { | |
162 gCutFreq += gFreqDelta; | |
163 gCutFreq = gCutFreq < 0 ? 0 : gCutFreq; | |
164 gCutFreq = gCutFreq > 22050 ? 22050 : gCutFreq; | |
165 | |
166 rt_printf("Cut-off frequency: %f\n", gCutFreq); | |
167 | |
168 calculate_coeff(gCutFreq); | |
169 gChangeCoeff = 0; | |
170 } | |
171 } | |
172 | |
173 // This is a lower-priority call to periodically read keyboard input | |
174 // and trigger samples. By placing it at a lower priority, | |
175 // it has minimal effect on the audio performance but it will take longer to | |
176 // complete if the system is under heavy audio load. | |
177 | |
178 void read_input() | |
179 { | |
180 // This is not a real-time task! | |
181 // Cos getchar is a system call, not handled by Xenomai. | |
182 // This task will be automatically down graded. | |
183 | |
184 char keyStroke = '.'; | |
185 | |
186 keyStroke = getchar(); | |
187 while(getchar()!='\n'); // to read the first stroke | |
188 | |
189 switch (keyStroke) | |
190 { | |
191 case 'a': | |
192 gReadPtr = 0; | |
193 break; | |
194 case 's': | |
195 gReadPtr = -1; | |
196 break; | |
197 case 'z': | |
198 gChangeCoeff = 1; | |
199 gFreqDelta = -100; | |
200 break; | |
201 case 'x': | |
202 gChangeCoeff = 1; | |
203 gFreqDelta = 100; | |
204 break; | |
205 case 'q': | |
206 gShouldStop = true; | |
207 break; | |
208 default: | |
209 break; | |
210 } | |
211 } | |
212 | |
213 | |
214 | |
215 // cleanup() is called once at the end, after the audio has stopped. | |
216 // Release any resources that were allocated in setup(). | |
217 | |
218 void cleanup(BeagleRTContext *context, void *userData) | |
219 { | |
220 delete[] gSampleData.samples; | |
221 } |