Mozzi  version v2.0
sound synthesis library for Arduino
RollingStat.h
1 /*
2  * RollingStat.h
3  *
4  * This file is part of Mozzi.
5  *
6  * Copyright 2013-2024 Tim Barrass and the Mozzi Team
7  *
8  * Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
9  *
10  * WARNING: this code is incomplete, it doesn't work yet
11  */
12 
13 #ifndef ROLLINGSTAT_H
14 #define ROLLINGSTAT_H
15 
16 #include "RollingAverage.h"
17 #include "mozzi_fixmath.h"
18 
19 // adapted from RunningStat, http://www.johndcook.com/standard_deviation.html
20 /** @ingroup sensortools
21 WARNING: this class is work in progress, don't use it yet.
22 Calculates an approximation of the variance and standard deviation for a window of recent inputs.
23 @tparam T the type of numbers to use. Choose unsigned int, int , uint8_t, int8_t, or float
24 @tparam WINDOW_LENGTH how many recent input values to include in the calculations.
25 */
26 template <class T, int WINDOW_LENGTH>
28 {
29 public:
30 
31  /** Constructor */
32  RollingStat() : _previous_mean(0), _mean(0), _variance(0), WINDOW_LENGTH_AS_RSHIFT(trailingZerosConst(WINDOW_LENGTH))
33  {}
34 
35 
36  /** Update the mean and variance given a new input value.
37  @param x the next input value
38  @note timing for unsigned int 10us, int 22us
39  */
40  void update(T x) {
41  _mean = rollingMean.next(x);
42  _variance = (((long)x - _previous_mean)*((long)x - _mean))>>WINDOW_LENGTH_AS_RSHIFT; // should really be div by (WINDOW_LENGTH-1), but exact values are not important for this application
43  _previous_mean = _mean;
44  }
45 
46 
47  /** Update the mean and variance given a new input value.
48  @param x the next input value
49  */
50  void update(int8_t x) {
51  _mean = rollingMean.next(x);
52  _variance = (((int)x - _previous_mean)*((int)x - _mean))>>WINDOW_LENGTH_AS_RSHIFT; // should really be div by (WINDOW_LENGTH-1), but exact values are not important for this application
53  _previous_mean = _mean;
54  }
55 
56 
57  /** Return the mean of the last WINDOW_LENGTH number of inputs.
58  @return mean
59  */
60  T getMean() const {
61  return _mean;
62  }
63 
64 
65  /** Return the approximate variance of the last WINDOW_LENGTH number of inputs.
66  @return variance
67  @note This should really be calculated using WINDOW_LENGTH-1, but sacrificing accuracy for speed
68  we use the power of two value of WINDOW_LENGTH.
69  */
70  T getVariance() const {
71  return _variance;
72  }
73 
74  /** Return the approximate standard deviation of the last WINDOW_LENGTH number of inputs.
75  @return standard deviation.
76  */
78  return isqrt16(_variance);
79  }
80 
81 
82 
83 private:
84  T _previous_mean, _mean, _variance;
85  RollingAverage <T, WINDOW_LENGTH> rollingMean;
86  const uint8_t WINDOW_LENGTH_AS_RSHIFT;
87 };
88 
89 // no need to show the specialisations
90 /** @cond */
91 
92 /** float specialisation of RollingStat template */
93 template <int WINDOW_LENGTH>
94 class RollingStat <float, WINDOW_LENGTH>
95 {
96 public:
97 
98  /** Constructor */
99  RollingStat() : _previous_mean(0), _mean(0), _variance(0), WINDOW_LENGTH_AS_RSHIFT(trailingZerosConst(WINDOW_LENGTH))
100  {}
101 
102 
103  /** Update the mean and variance given a new input value.
104  @param x the next input value
105  @note timing for float: 60 to 90us
106  */
107  void update(float x) {
108  _mean = rollingMean.next(x);
109  _variance = ((x - _previous_mean)*(x - _mean))/(WINDOW_LENGTH-1);
110  _previous_mean = _mean;
111  }
112 
113 
114  /** Return the mean of the last WINDOW_LENGTH number of inputs.
115  @return mean
116  */
117  float getMean() const {
118  return _mean;
119  }
120 
121 
122  /** Return the approximate variance of the last WINDOW_LENGTH number of inputs.
123  @return variance
124  */
125  float getVariance() const {
126  return _variance;
127  }
128 
129  /** Calculate and return the approximate standard deviation of the last WINDOW_LENGTH number of inputs.
130  @return standard deviation.
131  @note this is probably too slow to use!
132  */
133  float getStandardDeviation() const {
134  return sqrt(_variance);
135  }
136 
137 
138 
139 private:
140  float _previous_mean, _mean, _variance;
141  RollingAverage <float, WINDOW_LENGTH> rollingMean;
142  const uint8_t WINDOW_LENGTH_AS_RSHIFT;
143 };
144 
145 // no need to show the specialisations
146 /** @endcond */
147 
148 #endif // #ifndef ROLLINGSTAT_H