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
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  */
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(trailingZerosConst(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
Calculates a running average over a specified number of the most recent readings. ...
T next(T input)
Give the average of the last WINDOW_LENGTH.
RollingAverage()
Constructor.