comparison examples/04-Audio/filter-IIR/render.cpp @ 464:8fcfbfb32aa0 prerelease

Examples reorder with subdirectories. Added header to each project. Moved Doxygen to bottom of render.cpp.
author Robert Jack <robert.h.jack@gmail.com>
date Mon, 20 Jun 2016 16:20:38 +0100
parents
children b935f890e512
comparison
equal deleted inserted replaced
463:c47709e8b5c9 464:8fcfbfb32aa0
1 /*
2 ____ _____ _ _
3 | __ )| ____| | / \
4 | _ \| _| | | / _ \
5 | |_) | |___| |___ / ___ \
6 |____/|_____|_____/_/ \_\
7
8 The platform for ultra-low latency audio and sensor processing
9
10 http://bela.io
11
12 A project of the Augmented Instruments Laboratory within the
13 Centre for Digital Music at Queen Mary University of London.
14 http://www.eecs.qmul.ac.uk/~andrewm
15
16 (c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
17 Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
18 Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
19
20 The Bela software is distributed under the GNU Lesser General Public License
21 (LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
22 */
23
24
25 #include <Bela.h> // to schedule lower prio parallel process
26 #include <rtdk.h>
27 #include <cmath>
28 #include <stdio.h>
29 #include "SampleData.h"
30
31 SampleData gSampleData; // User defined structure to get complex data from main
32 int gReadPtr; // Position of last read sample from file
33
34 // filter vars
35 float gLastX[2];
36 float gLastY[2];
37 double lb0, lb1, lb2, la1, la2 = 0.0;
38
39 // communication vars between the 2 auxiliary tasks
40 int gChangeCoeff = 0;
41 int gFreqDelta = 0;
42
43 void initialise_filter(float freq);
44
45 void calculate_coeff(float cutFreq);
46
47 bool initialise_aux_tasks();
48
49 // Task for handling the update of the frequencies using the matrix
50 AuxiliaryTask gChangeCoeffTask;
51
52 void check_coeff();
53
54 // Task for handling the update of the frequencies using the matrix
55 AuxiliaryTask gInputTask;
56
57 void read_input();
58
59
60 extern float gCutFreq;
61
62
63 bool setup(BelaContext *context, void *userData)
64 {
65
66 // Retrieve a parameter passed in from the initAudio() call
67 gSampleData = *(SampleData *)userData;
68
69 gReadPtr = -1;
70
71 initialise_filter(200);
72
73 // Initialise auxiliary tasks
74 if(!initialise_aux_tasks())
75 return false;
76
77 return true;
78 }
79
80 void render(BelaContext *context, void *userData)
81 {
82 for(unsigned int n = 0; n < context->audioFrames; n++) {
83 float sample = 0;
84 float out = 0;
85
86 // If triggered...
87 if(gReadPtr != -1)
88 sample += gSampleData.samples[gReadPtr++]; // ...read each sample...
89
90 if(gReadPtr >= gSampleData.sampleLen)
91 gReadPtr = -1;
92
93 out = lb0*sample+lb1*gLastX[0]+lb2*gLastX[1]-la1*gLastY[0]-la2*gLastY[1];
94
95 gLastX[1] = gLastX[0];
96 gLastX[0] = out;
97 gLastY[1] = gLastY[0];
98 gLastY[0] = out;
99
100 for(unsigned int channel = 0; channel < context->audioChannels; channel++)
101 context->audioOut[n * context->audioChannels + channel] = out; // ...and put it in both left and right channel
102
103 }
104
105 // Request that the lower-priority tasks run at next opportunity
106 Bela_scheduleAuxiliaryTask(gChangeCoeffTask);
107 Bela_scheduleAuxiliaryTask(gInputTask);
108 }
109
110 // First calculation of coefficients
111
112 void initialise_filter(float freq)
113 {
114 calculate_coeff(freq);
115 }
116
117
118 // Calculate the filter coefficients
119 // second order low pass butterworth filter
120
121 void calculate_coeff(float cutFreq)
122 {
123 // Initialise any previous state (clearing buffers etc.)
124 // to prepare for calls to render()
125 float sampleRate = 44100;
126 double f = 2*M_PI*cutFreq/sampleRate;
127 double denom = 4+2*sqrt(2)*f+f*f;
128 lb0 = f*f/denom;
129 lb1 = 2*lb0;
130 lb2 = lb0;
131 la1 = (2*f*f-8)/denom;
132 la2 = (f*f+4-2*sqrt(2)*f)/denom;
133 gLastX[0] = gLastX [1] = 0;
134 gLastY[0] = gLastY[1] = 0;
135
136 }
137
138
139 // Initialise the auxiliary tasks
140 // and print info
141
142 bool initialise_aux_tasks()
143 {
144 if((gChangeCoeffTask = Bela_createAuxiliaryTask(&check_coeff, 90, "bela-check-coeff")) == 0)
145 return false;
146
147 if((gInputTask = Bela_createAuxiliaryTask(&read_input, 50, "bela-read-input")) == 0)
148 return false;
149
150 rt_printf("Press 'a' to trigger sample, 's' to stop\n");
151 rt_printf("Press 'z' to low down cut-off freq of 100 Hz, 'x' to raise it up\n");
152 rt_printf("Press 'q' to quit\n");
153
154 return true;
155 }
156
157 // Check if cut-off freq has been changed
158 // and new coefficients are needed
159
160 void check_coeff()
161 {
162 if(gChangeCoeff == 1)
163 {
164 gCutFreq += gFreqDelta;
165 gCutFreq = gCutFreq < 0 ? 0 : gCutFreq;
166 gCutFreq = gCutFreq > 22050 ? 22050 : gCutFreq;
167
168 rt_printf("Cut-off frequency: %f\n", gCutFreq);
169
170 calculate_coeff(gCutFreq);
171 gChangeCoeff = 0;
172 }
173 }
174
175 // This is a lower-priority call to periodically read keyboard input
176 // and trigger samples. By placing it at a lower priority,
177 // it has minimal effect on the audio performance but it will take longer to
178 // complete if the system is under heavy audio load.
179
180 void read_input()
181 {
182 // This is not a real-time task!
183 // Cos getchar is a system call, not handled by Xenomai.
184 // This task will be automatically down graded.
185
186 char keyStroke = '.';
187
188 keyStroke = getchar();
189 while(getchar()!='\n'); // to read the first stroke
190
191 switch (keyStroke)
192 {
193 case 'a':
194 gReadPtr = 0;
195 break;
196 case 's':
197 gReadPtr = -1;
198 break;
199 case 'z':
200 gChangeCoeff = 1;
201 gFreqDelta = -100;
202 break;
203 case 'x':
204 gChangeCoeff = 1;
205 gFreqDelta = 100;
206 break;
207 case 'q':
208 gShouldStop = true;
209 break;
210 default:
211 break;
212 }
213 }
214
215
216 void cleanup(BelaContext *context, void *userData)
217 {
218 delete[] gSampleData.samples;
219 }
220
221 /* ------------ Project Explantation ------------ */
222
223 /**
224 \example 04-filter-IIR
225
226 Infinite Impulse Response Filter
227 ------------------------------
228
229 This is an example of a infinite impulse response filter implementation.
230 */