How to approximate a moving RMS without iterating over N samples for each required output?

I have a signal with a sampling rate of F Hertz.

From it I want to produce an RMS signal, also with F samples per second with a window size of N samples.

Using a standard moving RMS algorithm I must iterate over the N most recent samples F times a second resulting in F*N operations a second.

Is there a way to approximate a moving RMS signal that only uses F operations per second (or close to it)?

I know that for other processes, like iteration, there are 'leaky' algorithms that can approximate the output. Instead of a leaky iterator, is there such thing as a 'leaky RMS'?

• you got your answer, but i just wanted to add that the trick comes from the notion of the Moving Average Filter. Feb 19 '20 at 22:57

1 Answer

There is a way to do it, it is really similar to a moving average

$$N$$ : number of samples per period

$$Z$$ : Accumulator

$$x[n]$$ : current sample

$$Z[n] = Z[n-1]+ x[n]^2 - x[n-N]^2$$

$$x_{RMS}[n] = \sqrt{\frac{1}{N}Z[n]}$$

Basically, you need a delay line to store the previous $$x[n]$$ samples or better yet the previous $$x[n]^2$$ samples and you need an accumulator. Both the accumulator and delay line should be set to 0 prior to starting the moving-RMS.

Basically you need need 1 multiplication, 2 additions, 1 division (by a constant, so it is equivalent to multiply by another constant) and 1 square root operation per sample.

Edit : The number of samples per period should be an integer. There are ways to do it with a non-integer number of samples per period, but it takes more work.

Edit 2 : This scheme will work only if the accumulator is an integer and if the accumulator never wraps around as Robert Bristow-Johnson pointed out. If the accumulator is floating-point, you might be stuck with some value in the accumulator you cannot get rid of, because floating-point arithmetic is not guaranteed to be associative in all conditions. See R-B-J solution in the comments when using floating-point arithmetic.

• 1 - I think you need to square the incoming signal. That being said, the delay line should use x^2[n] instead of x[n] so that you don't need 2 multiplications per sample. 2 - If we lose the square root, we get a moving-variance, don't we?
– Ben
Feb 19 '20 at 22:13
• Ben, if the accumulator is floating point, or if the number of bits in the accumulator cannot handle the summation at full precision, it is possible that the number subtracted from the accumulator will not be exactly the number earlier added. then you get a turd stuck in the accumulator that doesn't go away. one way to deal with this is to have a stable exponential averaging filter. $$Z[n] = \alpha Z[n-1]+ (x[n])^2 - \alpha^N (x[n-N])^2$$ where $0 < 1-\alpha \ll 1$ Feb 19 '20 at 23:03
• It might be good to define "wraps around" as one may confuse it with a simple overflow with appropriate result to roll over on overflow. The accumulator CAN overflow, it just can't overflow and go past the original value. Feb 20 '20 at 12:14
• I picture 2 cases : First case, delay line, then you feed the $x[n]^2 - x[n-N]^2$ to the accumulator. In that case the accumulator should not wrap around. Second case, accumulator first $acc[n] = acc[n-1] + x[n]^2$, then a delay line $$z[n] = \sqrt{\frac{acc[n] - acc[n-N]}{N}}$$ In the second case, the accumulator can wrap around without problem as long it does not go past the original value like you said.
– Ben
Feb 20 '20 at 14:11
• @Ben ah yes that is a good clarification. I now need to look at my moving average answer elsewhere to see if I covered that case with the comb filter placed first. Thanks Feb 20 '20 at 14:38