| Mozzi version v1.1.0 sound synthesis library for Arduino |

Smooth.h
1 /*
2 * Smooth.h
3 *
4 * Copyright 2012 Tim Barrass.
5 *
6 * This file is part of Mozzi.
7 *
8 * Mozzi is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
9 *
10 */
11
12 #ifndef SMOOTH_H_
13 #define SMOOTH_H_
14
15 #include "Arduino.h"
16 #include "mozzi_fixmath.h"
17
18 /** A simple infinite impulse response low pass filter for smoothing control or audio signals.
19 This algorithm comes from http://en.wikipedia.org/wiki/Low-pass_filter:
20 y[i] := y[i-1] + α * (x[i] - y[i-1]),
21 translated as
22 out = last_out + a * (in - last_out).
23 It's not calibrated to any real-world update rate, so if you use it at
24 CONTROL_RATE and you change CONTROL_RATE, you'll need to adjust the smoothness
25 value to suit.
26 @tparam T the type of numbers being smoothed. Watch out for numbers overflowing the
27 internal calculations. Some experimentation is recommended.
28 @note Timing: ~5us for 16 bit types, ~1us for 8 bit types.
29 @todo Check if 8 bit templates can work efficiently with a higher res smoothness -
30 as is they don't have enough resolution to work well at audio rate. See if Line might be
31 more useful in most cases.
32 */
33
34 template <class T>
35 class Smooth
36 {
37 private:
38 long last_out;
39 Q0n16 a;
40
41 public:
42 /** Constructor.
43 @param smoothness sets how much smoothing the filter will apply to
44 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
45 very smooth.
46 */
47 Smooth(float smoothness)
48 {
49 setSmoothness(smoothness);
50 }
51
52 /** Constructor.
53 This constructor which doesn't take a smoothness parameter is useful when you incorporate Smooth into another class definition.
54 You need to call setSmoothness(float) for your object before using Smooth.
55 @note there's probably a better way to do this...
56 */
57 Smooth()
58 {}
59
60
61 /** Filters the input and returns the filtered value. You can also use the operator() function, eg. something like mySmoother(input-value).
62 @param in the signal to be smoothed.
63 @return the filtered signal.
64 */
65 inline
66 T next(T in)
67 {
68 long out = ((((((long)in - (last_out>>8)) * a))>>8) + last_out);
69 last_out = out;
70 return (T)(out>>8);
71 }
72
73
74 /** Filters the input and returns the filtered value. Same as next(input-value).
75 @param in the signal to be smoothed.
76 @return the filtered signal.
77 */
78 inline
79 T operator()(T n) {
80 return next(n);
81 }
82
83
84 /** Sets how much smoothing the filter will apply to its input.
85 @param smoothness sets how much smoothing the filter will apply to
86 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
87 very smooth.
88 */
89 inline
90 void setSmoothness(float smoothness)
91 {
92 a=float_to_Q0n16(1.f-smoothness);
93 }
94
95 };
96
97
98 /** @cond */ // doxygen can ignore the specialisations
99
100 /** uint8_t specialisation of Smooth template*/
101 template <>
102 class Smooth <uint8_t>
103 {
104 private:
105 unsigned int last_out;
106 Q0n8 a;
107
108 public:
109 /** Constructor.
110 @param smoothness sets how much smoothing the filter will apply to
111 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
112 very smooth.
113 */
114 Smooth(float smoothness)
115 {
116 setSmoothness(smoothness);
117 }
118
119 /** Filters the input and returns the filtered value. You can also use the operator() function, eg. something like mySmoother(input-value).
120 @param in the signal to be smoothed.
121 @return the filtered signal.
122 */
123 inline
124 uint8_t next(uint8_t in)
125 {
126 unsigned int out = (((((int)in - (last_out>>8)) * a)) + last_out);
127 last_out = out;
128 return (uint8_t)(out>>8);
129 }
130
131
132 /** Filters the input and returns the filtered value. Same as next(input-value).
133 @param in the signal to be smoothed.
134 @return the filtered signal.
135 */
136 inline
137 uint8_t operator()(uint8_t n) {
138 return next(n);
139 }
140
141
142 /** Sets how much smoothing the filter will apply to its input.
143 @param smoothness sets how much smoothing the filter will apply to
144 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
145 very smooth.
146 */
147 inline
148 void setSmoothness(float smoothness)
149 {
150 a=float_to_Q0n8(1.f-smoothness);
151 }
152
153 };
154
155
156 /** int8_t specialisation of Smooth template*/
157 template <>
158 class Smooth <int8_t>
159 {
160 private:
161 int last_out;
162 Q0n8 a;
163
164 public:
165 /** Constructor.
166 @param smoothness sets how much smoothing the filter will apply to
167 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
168 very smooth.
169 */
170 Smooth(float smoothness)
171 {
172 setSmoothness(smoothness);
173 }
174
175
176 /** Filters the input and returns the filtered value. You can also use the operator() function, eg. something like mySmoother(input-value).
177 @param in the signal to be smoothed.
178 @return the filtered signal.
179 */
180 inline
181 int8_t next(int8_t in)
182 {
183 int out = (((((int)in - (last_out>>8)) * a)) + last_out);
184 last_out = out;
185 return (int8_t)(out>>8);
186 }
187
188
189 /** Filters the input and returns the filtered value. Same as next(input-value).
190 @param in the signal to be smoothed.
191 @return the filtered signal.
192 */
193 inline
194 int8_t operator()(int8_t n) {
195 return next(n);
196 }
197
198
199 /** Sets how much smoothing the filter will apply to its input.
200 @param smoothness sets how much smoothing the filter will apply to
201 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
202 very smooth.
203 */
204 inline
205 void setSmoothness(float smoothness)
206 {
207 a=float_to_Q0n8(1.f-smoothness);
208 }
209
210 };
211
212 /** float specialisation of Smooth template*/
213 template <>
214 class Smooth <float>
215 {
216 private:
217 float last_out;
218 float a;
219
220 public:
221 /** Constructor.
222 @param smoothness sets how much smoothing the filter will apply to
223 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
224 very smooth.
225 */
226 Smooth(float smoothness)
227 {
228 setSmoothness(smoothness);
229 }
230
231 /** Filters the input and returns the filtered value. You can also use the operator() function, eg. something like mySmoother(input-value).
232 @param in the signal to be smoothed.
233 @return the filtered signal.
234 */
235 inline
236 float next(float in)
237 {
238 float out = last_out + a * (in - last_out);
239 //float out = (in - last_out * a) + last_out;
240 last_out = out;
241 return out;
242 }
243
244
245 /** Filters the input and returns the filtered value. Same as next(input-value).
246 @param in the signal to be smoothed.
247 @return the filtered signal.
248 */
249 inline
250 float operator()(float n) {
251 return next(n);
252 }
253
254
255 /** Sets how much smoothing the filter will apply to its input.
256 @param smoothness sets how much smoothing the filter will apply to
257 its input. Use a float in the range 0~1, where 0 is not very smooth and 0.99 is
258 very smooth.
259 */
260 inline
261 void setSmoothness(float smoothness)
262 {
263 a=1.f-smoothness;
264 }
265
266 };
267
268
269 /** @endcond */
270
271 /**
272 @example 05.Control_Filters/Smooth/Smooth.ino
273 This example demonstrates the Smooth class.
274 */
275
276 #endif /* SMOOTH_H_ */
Smooth::setSmoothness
void setSmoothness(float smoothness)
Sets how much smoothing the filter will apply to its input.
Definition: Smooth.h:90
Smooth::Smooth
Smooth(float smoothness)
Constructor.
Definition: Smooth.h:47
Q0n16
uint16_t Q0n16
unsigned fractional number using 16 fractional bits, represents 0.0 to 0.999
Definition: mozzi_fixmath.h:29
Smooth
A simple infinite impulse response low pass filter for smoothing control or audio signals...
Definition: Smooth.h:35
Smooth::operator()
T operator()(T n)
Filters the input and returns the filtered value.
Definition: Smooth.h:79
float_to_Q0n16
Q0n16 float_to_Q0n16(float a)
Convert float to Q0n16 fix.
Definition: mozzi_fixmath.h:124
Smooth::next
T next(T in)
Filters the input and returns the filtered value.
Definition: Smooth.h:66
Smooth::Smooth
Smooth()
Constructor.
Definition: Smooth.h:57