4
$\begingroup$

I'm new to DSP, and I'm using this basic "1-pole LPF" Param Smooth filter which "smooth" param when I change it. The code is pretty simple:

class CParamSmooth
{
public:
    double a, b, z;

    CParamSmooth() { 
        a = 0.8; 
        b = 1. - a; 
        z = 0.; 
    }

    double Process(double in) { 
        z = (in * b) + (z * a); 
        return z; 
    }
};

If I try some values with "strong" a coefficients, I can see that it starts heavy on increment, then becomes smooth till "rounding" happen, setting z = in:

0 | 0.16
1 | 0.288
2 | 0.3904
3 | 0.47232
4 | 0.537856
5 | 0.590285
6 | 0.632228
7 | 0.665782
8 | 0.692626
9 | 0.714101
10 | 0.731281
11 | 0.745024
12 | 0.75602
13 | 0.764816
14 | 0.771853
15 | 0.777482
16 | 0.781986
17 | 0.785588
18 | 0.788471
19 | 0.790777
20 | 0.792621
21 | 0.794097
22 | 0.795278
23 | 0.796222
24 | 0.796978
25 | 0.797582
26 | 0.798066
27 | 0.798453
28 | 0.798762
29 | 0.79901
30 | 0.799208
31 | 0.799366
32 | 0.799493
33 | 0.799594
34 | 0.799675
35 | 0.79974
36 | 0.799792
37 | 0.799834
38 | 0.799867
39 | 0.799894
40 | 0.799915
41 | 0.799932
42 | 0.799946
43 | 0.799956
44 | 0.799965
45 | 0.799972
46 | 0.799978
47 | 0.799982
48 | 0.799986
49 | 0.799989
50 | 0.799991
51 | 0.799993
52 | 0.799994
53 | 0.799995
54 | 0.799996
55 | 0.799997
56 | 0.799998
57 | 0.799998
58 | 0.799998
59 | 0.799999
60 | 0.799999
61 | 0.799999
62 | 0.799999
63 | 0.799999
64 | 0.8
65 | 0.8
66 | 0.8
...

So, basically, each iteration is a sum of 0.16 + prev z * 0.8. And here is where I don't understand: why 0.16 + prev z * 0.8 can't go "over" 0.8?

In fact, this become stable when z = in. Without rounding, z will always be < in. Why it can't go > in?

It's a sum on each iteration... who limits it?

$\endgroup$
1
  • $\begingroup$ You might want to try to compute the values by hand, drawing them on an axis one by one. Each iteration is computing a weighted mean between the previous result and the input, and with constant input it can be easy to get why you can't cross it. $\endgroup$ Aug 24, 2016 at 12:56

1 Answer 1

8
$\begingroup$

In more standard DSP terms, you have the following filter:

$$ y[n] = (1-a) x[n] + a y[n-1] $$

where $x[n]$ and $y[n]$ are the input and output signals at time $n$ respectively.

The transfer function (which you didn't ask for) is:

$$ H(z) = \frac{1-a}{1 - az^{-1}} $$

so here is your single pole, at $z=a$ in the complex plane. This filter is also known as exponential smoothing, exponential moving average (EMA), or exponentially weighted moving average (EWMA).

The infinite impulse response is $h[n] = (1-a) u[n] a^n$. In layman terms, when the input signal is 0 except for $x[0]=1$, the output signal is an exponential $(1-a) \times a^n$ starting at $n=0$.

What you want is the step response (i.e. what happens if the input signal is a constant $K$ starting at time $n=0$).

In this case, the output signal is the convolution $h \star Ku$ of the impulse response and the step signal. This is (for time $n \ge 0$):

$$ y[n] = \sum_{k=0}^{k=n} K \times h[k] = K(1-a) \sum_{k=0}^{k=n} a^k = K(1-a)\frac{1-a^{n+1}}{1-a} = K (1-a^{n+1}) $$

As the time $n$ grows, $a^{n+1}$ vanishes, and the step response grows monotonically to its limit value $y = K$, which is the value of the input signal.

This is what you get in your simulation.

$\endgroup$
7
  • 1
    $\begingroup$ I dared to add a few more common names for this filter, to help find literature. Corrections welcome $\endgroup$ Aug 24, 2016 at 11:49
  • $\begingroup$ Beautiful answer ! $\endgroup$
    – Gilles
    Aug 24, 2016 at 12:27
  • $\begingroup$ Thanks for the answer! Well, for step: "This filter is also known as exponential smoothing, exponential moving average (EMA), or exponentially weighted moving average (EWMA)." The formula you have put (y[n] = (1−a)*x[n] + a*y[n−1]) is like my formula, but the one on the wiki is different: its y[n] = a*x[n] + (1-a)*y[n-1]. Why? $\endgroup$
    – markzzz
    Aug 24, 2016 at 12:30
  • 1
    $\begingroup$ @markzzz The difference is just in how you name your parameters. In the answer above, the exponent is a. In the wikipedia article notation, the exponent is (1-a_wiki). $\endgroup$
    – Juancho
    Aug 24, 2016 at 12:45
  • $\begingroup$ Right! Thanks! So basically, the formula become z = in - (in - z)*a and it subtracts from in (step by step) an amount smaller at each step, till at some points (due to computer rounding) (in - z)*a become 0, so in. Is it right? If it wasn't "rounding", it really was a "infinite response", without returning in...! Not sure if that's correct anyway hehehe $\endgroup$
    – markzzz
    Aug 24, 2016 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.