What is digital signal processing? Well, digital signal processing is a technique used to extract or modify data in a meaningful way within the digital realm. What exactly does that mean?
Let’s look at analog signal processing first. If you have a signal with low and high frequency components, and you’re only interested in the low frequency, then you can use an RC filter to get rid of the high frequency information. If that’s not enough, then you can use higher order filters, which typically require opamps. Analog signal processing is relatively straight forward: the circuit cleans up the signal so that whatever ultimately interprets the data doesn’t have to worry about filters.
But there are situations where analog signal processing isn’t viable:
- You buy a sensor and it only has a digital interface. For example, a temperature sensor could output the measured temperature as 16 bit data sent over a SPI bus.
- The PCB has already been designed, fabricated and assembled, and it’s too late to re-spin the board. Turns out the system had more noise than expected, so the filter that’s present on the board isn’t enough to get the job done.
- There’s not enough room on the PCB to add a filter. A simple RC filter is tiny, but what if you want to have a 5th order filter? That would require multiple opamps as well as a bunch of resistors and capacitors. Also, what if opamps require ±12V, and you only have 5 volts available?
- There are situations where the filter characteristic has to change on the fly. For example, a user may tell the system through a GUI what the cut-off frequency of a filter should be. How would you implement this in an analog filter?
The list above shows situations where digital signal processing would be useful. You can’t put an RC filter on a digital signal and expect it to clean up the data; you need something more complicated.
Digital signal processing, much like analog signal processing, is mostly about filters. The simplest possible filter you can have for a system is a moving average. If the filter length if 5, then the output of the filter is the average of the 5 most recent data readings. The longer the filter length, the greater the reduction in noise since averaging causes noise to cancel out. A drawback to a longer filter is slower response, though, since the newest data points tend to get swamped out by the older data points.
Another way to use averages in a filter is to take multiple samples and treat that as a single sample point. For example, take ten readings from a sensor, average the ten values, then just use the average in the algorithm. The key difference between this scheme and the previous moving average scheme is that you’ve changed your effective sampling rate; if you read data from the sensor 100 times a second, the software will only see it has 10 readings per second since it takes 10 samples to generate 1 piece of usable data. Meanwhile, for a moving average filter, 100 samples will yield 100 pieces of usable data. Signal processing involving multiple rates like this is called multirate signal processing.
Averaging is great for reducing noise and shaping signals in the time domain, but what if you’re trying to get rid of frequency components? How would you use digital signal processing to create a single pole low pass filter? Well, again, let’s see how an analog filter works.
An analog filter has an input, the filter, and the output. The output, y(t), can be calculated by convolving the filter’s impulse response, h(t), with the input signal, x(t). A filter’s impulse response is the filter’s output when the input is an infinitely short, infinitely large spike. Let’s take a look at a simple RC filter’s impulse response:

I used LTSpice to simulate an RC filter, and got the filter’s step response. Then, I took the derivative of this step response to calculate the function’s impulse response. I did this because, even in simulation, an impulse response is hard to create. As you can see, the filter’s impulse response is a decaying exponential; how quickly the waveform decays depends on the cutoff frequency, which is 20 kHz in this case.
So now we have the impulse response of an analog filter. How is this used in digital signal processing? Well, as it turns out, a digital filter can be very similar to an analog filter. In an analog filter, you have y(t) = x(t) * h(t). If you sample the input signal and digitize it, you’ll get x[n], which is a discrete signal. If you sample the impulse response of your filter, then you’ll get h[n]. Amazingly, filtering a digital signal is as simple as convolving x[n] and h[n]! So in the digital realm, you have y[n] = x[n] * h[n]. Make sure you’re sampling the impulse response at the same rate as the input signal.


h[n] is called the filter kernel. Just like how an analog filter’s impulse response defines the filter, the filter kernel defines the digital filter. Note that the impulse response and the filter kernel have been normalized; the area under the curve of the impulse response and the sum of data points in the filter kernel are 1. This property is desirable if you want a DC gain of 1.
In our example, we have a system that samples the input at 3 MHz and the filter’s cutoff frequency is 20 kHz. To test the filter, let’s have the inputs be sinusoids that are equal to, one decade below and one decade above the cutoff frequency.

In the figure above, note the change in x-axis scale; all three signals are sampled at the same rate, but because the bottom graph is far more zoomed in than the others, it looks more discrete.
The filter kernel we’re using is for a single order low pass filter. Therefore, we would expect the 2 kHz signal to be unaffected by the filter, the 20 kHz to be -3dB of the original signal (around 71%), and the 200 kHz signal to be -20 dB (about 10%). And the results are…

The amplitude of all three signals were 1 before the filter. Now, the amplitudes are 1, 0.708 and 0.1 for 2 kHz, 20 kHz and 200 kHz, respectively. We’ve implemented a purely digital filter! Without using an RC filter, we’ve successfully attenuated a high frequency signal without significantly affecting the lower frequencies. The filter also produces the phase shift that you’d expect from an analog low pass filter; note that the 20 KHz signal is out of phase with the 2 kHz signal (200 kHz is also out of phase, but its small amplitude makes it less noticeable).
Digital signal processing is a very powerful tool. The example above uses a filter kernel based off of an RC filter, but you can use more powerful filter kernels. For example, you can sample the impulse response of a 6th order Chebyshev filter and get the same performance as an analog filter. In addition, you can use filter kernels that don’t have any basis in analog filters, allowing you to create filters that work for your specific application.
Digital signal processing isn’t all roses, though. It has several drawbacks:
- Since you don’t have a circuit that performs filtering, the microcontroller or microprocessor will have to do that. This means the code becomes more complex, you lose processor cycles, and the microprocessor consumes more power.
- If you skimp out on analog filters, then you’ll usually find you have to sample at a much higher rate. This is because of the Nyquist theorem: the sampling rate of your system must be at least twice the highest frequency component in the signal. An analog filter can reduce the frequency range of the signal of interest, allowing you to sample at a lower rate. By increasing your sampling rate, you force more work onto the microprocessor, increasing overhead, power consumption, etc.
- Converting an analog signal to a digital one will always result in the loss of data. Not only are you sampling, which results in data lost in terms of time, but you’re also quantizing the data, typically by an ADC. The infinite number of values the analog waveform can take has been reduced to 65535 by a 16 bit ADC. Granted, you have to sample the data even if you have an analog filter, but by using digital signal processing, you lose data earlier in the signal chain which might be detrimental to the system.
The main drawback to the filter I’ve shown here is the computationally intense nature of convolution. If the kernel is a thousand samples long, then convolution requires at least 1000 multiplications and 999 additions to produce a single output sample, which will then needed to be repeated each time you want a new output sample. A shortcut around this is taking the FFT of x[n] and h[n], multiplying the results together, and then performing the IFFT to get y[n], but that’s also computationally intense.
Another shortcoming of DSP is its inability to truly replicate analog filters. If I wanted the filter kernel to completely replicate the RC filter’s impulse response, then the filter kernel would be infinitely long since the impulse response of an RC filter never reaches zero. You typically want to capture 5 to 10 time constants of the filter, or make the kernel long enough that round-off errors create more problems than a truncated kernel, but the point is the digital filter isn’t a 100% accurate representation of the analog filter.
The example filter we’ve discussed here is an FIR (Finite Impulse Response) filter, so called because the filter kernel produces an impulse response that is finite length. The other filter type used in DSP is the IIR (Infinite Impulse Response) filter, which are filters that have infinitely long impulse responses by using recursion. That is, the output of an IIR filter depend not only on the current and past values of the input signal, but also on the past values of the output. By feeding the past output values back into the filter, you can have impulse responses that never reach zero, just like analog filters. IIR filters are significantly less computationally intense than FIR filters, but they also do not replicate analog filter characteristics as well as FIR filters.