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

RollingAverage.h
1 #ifndef ROLLINGAVERAGE_H
2 #define ROLLINGAVERAGE_H
3
4 /*
5 * RollingAverage.h
6 *
7 * Copyright 2013 Tim Barrass.
8 *
9 * This file is part of Mozzi.
10 *
11 * Mozzi is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
12 *
13 */
14 /*
15 Draws on Arduino Smoothing example,
16 Created 22 April 2007
17 By David A. Mellis <dam@mellis.org>
18 modified 9 Apr 2012
19 by Tom Igoe
20 http://www.arduino.cc/en/Tutorial/Smoothing
21 */
22
23 #include "mozzi_utils.h" // for trailingZeros()
24
25
26 /** @ingroup sensortools
27 Calculates a running average over a
28 specified number of the most recent readings.
29 Like Smooth(), this is good for smoothing analog inputs in updateControl().
30 @tparam WINDOW_LENGTH the number of readings to include in the rolling average.
31 It must be a power of two (unless you're averaging floats). The higher the
32 number, the more the readings will be smoothed, but the slower the output
33 will respond to the input.
34 */
35
36 template <class T, int WINDOW_LENGTH>
37 class
38 RollingAverage {
39
40 public:
41
42 /** Constructor.
43 @tparam T the type of numbers to average, eg. int, unsigned int, float etc. It will be relatively slow with
44 floating point numbers, as it will use a divide operation for the averaging.
45 Nevertheless, there might be a time when it's useful.
46 @tparam WINDOW_LENGTH the number of readings to keep track of. It must be a power of two (unless
47 you're averaging floats). The higher the number, the more the readings will be
48 smoothed, but the slower the output will respond to the input.
49 @note Watch out for overflows!
50 */
51 RollingAverage():index(0),total(0), WINDOW_LENGTH_AS_RSHIFT((uint8_t)trailingZeros((unsigned long)WINDOW_LENGTH))
52 {
53 // initialize all the readings to 0:
54 for (int thisReading = 0; thisReading < WINDOW_LENGTH; thisReading++)
55 readings[thisReading] = 0;
56 }
57
58
59 /** Give the average of the last WINDOW_LENGTH.
60 @param input a control signal such as an analog input which needs smoothing.
61 @return the smoothed result.
62 @note unsigned int timing 5.7us
63 */
64 T next(T input)
65 {
66 return add(input)>>WINDOW_LENGTH_AS_RSHIFT;
67 }
68
69
70 protected:
71
72 inline
73 T add(T input){
74 // out with the old
75 total -= readings[index];
76 // in with the new
77 total += input;
78 readings[index] = input;
79
80 // advance and wrap index
81 ++index &= WINDOW_LENGTH -1;
82 return total;
83 }
84
85
86 private:
87 T readings[WINDOW_LENGTH]; // the readings from the analog input
88 unsigned int index; // the index of the current reading
89 long total; // the running total
90 const uint8_t WINDOW_LENGTH_AS_RSHIFT;
91
92 };
93
94 // no need to show the specialisations
95 /** @cond */
96
97 /** unsigned int partial specialisation of RollingAverage template.
98 This is needed because unsigned types need to remind (unsigned) for rshift.
99 */
100 template <int WINDOW_LENGTH>
101 class RollingAverage <unsigned int, WINDOW_LENGTH>
102 {
103 public:
104 /** Constructor.
105 @tparam WINDOW_LENGTH A power of two, the number of readings to keep track of.
106 The higher the number, the more the readings will be smoothed, but the slower the output will
107 respond to the input.
108 @note The internal total of all the values being averaged is held in a long (4 uint8_t) integer, to avoid overflowing.
109 However, watch out for overflows if you are averaging a long number types!
110 */
111 RollingAverage():index(0),total(0), WINDOW_LENGTH_AS_RSHIFT((uint8_t)trailingZeros((unsigned long)WINDOW_LENGTH))
112 {
113 // initialize all the readings to 0:
114 for (int thisReading = 0; thisReading < WINDOW_LENGTH; thisReading++)
115 readings[thisReading] = 0;
116 }
117
118 /** Give the average of the last WINDOW_LENGTH.
119 @param a control signal such as an analog input which needs smoothing.
120 @return the smoothed result.
121 @note timing for int 6us
122 */
123 unsigned int next(unsigned int input)
124 {
125 // calculate the average:
126 // this unsigned cast is the only difference between the int and unsigned int specialisations
127 // it tells the shift not to sign extend in from the left
128 return (unsigned)add(input)>>WINDOW_LENGTH_AS_RSHIFT;
129 }
130
131 protected:
132
133
134 inline
135 unsigned int add(unsigned int input){
136 // out with the old
137 total -= readings[index];
138 // in with the new
139 total += input;
140 readings[index] = input;
141
142 // advance and wrap index
143 ++index &= WINDOW_LENGTH -1;
144 return total;
145 }
146
147
148 private:
149 unsigned int readings[WINDOW_LENGTH]; // the readings from the analog input
150 unsigned int index; // the index of the current reading
151 long total; // the running total
152 const uint8_t WINDOW_LENGTH_AS_RSHIFT;
153
154 };
155
156
157
158 /** float partial specialisation of RollingAverage template*/
159 template <int WINDOW_LENGTH>
160 class RollingAverage <float, WINDOW_LENGTH>
161 {
162 public:
163 /** Constructor.
164 @tparam WINDOW_LENGTH A power of two, the number of readings to keep track of.
165 The higher the number, the more the readings will be smoothed, but the slower the output will
166 respond to the input.
167 @note The internal total of all the values being averaged is held in a long (4 uint8_t) integer, to avoid overflowing.
168 However, watch out for overflows if you are averaging a long number types!
169 */
170 RollingAverage():index(0),total(0.0)
171 {
172 // initialize all the readings to 0:
173 for (int thisReading = 0; thisReading < WINDOW_LENGTH; thisReading++)
174 readings[thisReading] = 0.0;
175 }
176
177 /** Give the average of the last WINDOW_LENGTH.
178 @param a control signal such as an analog input which needs smoothing.
179 @return the smoothed result.
180 @note timing for float 37us
181 */
182 float next(float input)
183 {
184 // out with the old
185 total -= readings[index];
186 // in with the new
187 total += input;
188 readings[index] = input;
189
190 // advance and wrap index
191 ++index &= WINDOW_LENGTH -1;
192
193 // calculate the average:
194 return total/WINDOW_LENGTH;
195 }
196
197 private:
198 float readings[WINDOW_LENGTH]; // the readings from the analog input
199 unsigned int index; // the index of the current reading
200 float total; // the running total
201
202 };
203
204
205 // no need to show the specialisations
206 /** @endcond
207 */
208
209 /**
210 @example 03.Sensors/Knob_LDR_x2_WavePacket/Knob_LDR_x2_WavePacket.ino
211 This example demonstrates the RollingAverage class.
212 */
213
214 #endif // #ifndef ROLLINGAVERAGE_H
RollingAverage
Calculates a running average over a specified number of the most recent readings. ...
Definition: RollingAverage.h:37
RollingAverage::next
T next(T input)
Give the average of the last WINDOW_LENGTH.
Definition: RollingAverage.h:64
RollingAverage::RollingAverage
RollingAverage()
Constructor.
Definition: RollingAverage.h:51