return *sum = *sum - (*sum + n - 1) / n + v;
}
+/* Adds sample value <v> spanning <s> samples to sliding window sum <sum>
+ * configured for <n> samples, where <n> is supposed to be "much larger" than
+ * <s>. The sample is returned. Better if <n> is a power of two. Note that this
+ * is only an approximate. Indeed, as can be seen with two samples only over a
+ * 8-sample window, the original function would return :
+ * sum1 = sum - (sum + 7) / 8 + v
+ * sum2 = sum1 - (sum1 + 7) / 8 + v
+ * = (sum - (sum + 7) / 8 + v) - (sum - (sum + 7) / 8 + v + 7) / 8 + v
+ * ~= 7sum/8 - 7/8 + v - sum/8 + sum/64 - 7/64 - v/8 - 7/8 + v
+ * ~= (3sum/4 + sum/64) - (7/4 + 7/64) + 15v/8
+ *
+ * while the function below would return :
+ * sum = sum + 2*v - (sum + 8) * 2 / 8
+ * = 3sum/4 + 2v - 2
+ *
+ * this presents an error of ~ (sum/64 + 9/64 + v/8) = (sum+n+1)/(n^s) + v/n
+ *
+ * Thus the simplified function effectively replaces a part of the history with
+ * a linear sum instead of applying the exponential one. But as long as s/n is
+ * "small enough", the error fades away and remains small for both small and
+ * large values of n and s (typically < 0.2% measured).
+ */
+static inline unsigned int swrate_add_scaled(unsigned int *sum, unsigned int n, unsigned int v, unsigned int s)
+{
+ return *sum = *sum + v * s - div64_32((unsigned long long)(*sum + n) * s, n);
+}
+
/* Returns the average sample value for the sum <sum> over a sliding window of
* <n> samples. Better if <n> is a power of two. It must be the same <n> as the
* one used above in all additions.