We also need to initialize this memory cell before we use the filter for
the first time.
And in terms of computation, we see that we need two multiplications and
one addition per output sample.
Now we implement this in C.
But the language is really irrelevant when it comes to implementing a digital filter.
And this is really the power of the DSP paradigm.
So here is the same guy implemented in Python.
Python is an object-oriented programming language, so
we can do something a little bit more elegant that what we did before.
We can define a class that we can parametrize
with different values of lambda.
And therefore, we can instantiate different leaking integrators
with different values of the leaking factor.
So here, the initialization procedure gets its own lines of code.
And what we do is we initialize lambda to a value that we pass and
we initialize the memory cell that we need to have as well.
And then finally, we can compute the output of the filter.
Since we're in Python,
it's very easy to pass an array here rather than a single value.
And so we iterate over the array and compute the output for
each member of the array.
And what we produce in the end is another array that contains the output values.
So again, we can test this.
We instantiate a leaky integrator with a value of 0.95 for lambda.
And then we compute the leaky integrator for
a signal, which is again the delta signal.
And to show that we can place our origin wherever we want,
we actually provide a few zeros before the time n equal to zero.
And the output gives us exactly what we expect.
Some zero points before we hit one and
then the exponentially decaying impulse response that we expect.
We can try to do the same with another old friend,
the moving average, who's the CDE is this one.
And if we try to implement the moving average in C using the same paradigm as
before, we define a function that we call each time a new input sample arrives.
And then we do some initialization here.
So we have to decide on the length of the moving average, this will be a constant M.
Once we have decided on the length, we have to allocate an array of memory cells
that contains the input samples that we're going to use to compute the average.
And we also have to define an index on this array of memory cells.
We initialize this index at minus one,
this is a trick that will be clear in the second.
This is standard C bookkeeping and
this last year are still part of the initialization procedure.
So remember, ix is initialize to minus one, so the first and the first
time only that we call the function, we will enter this part of the code.
And this part of the code is simply sets the memory cells to zero for first use.
After which ix is initialize to zero and will never be minus one again.
This part here simply stores the current value into the memory buffer and
updates the index of the buffer, modulo capital M.
We will see how that works in the next slide.
And finally, this part computes the moving average
simply by summing all the elements in the array and normalizing by capital M.
The modulo M operation we saw before
implements what is called a circular buffer.
Which is a neat trick used in most DSP applications.
Suppose I need to store five values of the input.
So I define five memory cells like so, which I initialize to zero.
And then as the samples start coming in, I start putting them into the memory cells.
So I use an index ix to keep track of the next free cell for use.
And so I initialize the thing at 0 and the first sample will go in here.
At the next step, the sample will go on the next cell and
I will update the index to the next free cell and so on and so forth.
When I get to the last cell and I fill the buffer, I update ix modulo n,
so that it will point back to the first cell of the array.
And as you can see,
now my array is full with the first five samples that have come in.
In the next step, I will still need five samples, but
I can forget the oldest sample.
And so I will put x5 into the position number 0 and
start filling the array once again.
The implementation of the moving average teaches us a set of lessons
that are very close to what we'll learn with a leaky integrator.
In this case, we need M memory cells to implement the filter,
the memory requirements are higher for the moving average.
We need to initialize the cells once again before we first use them and for
each output sample, we'll need now M additions and one addition.
So when M grows,
you can see that both memory and computational requirements grow as well.