# Low pass filtering of an upsampled(zero inserted) signal

I have been working on interpolation in python from quite some time. The input signal is a sinusoid signal sampled at 933KHz. I am upsampling the signal by a factor of 5 and later using an FIR lowpass filter with Kaiser window.

I am observing two issues here:

1. The output of the FIR filter is attenuated by the interpolation factor. In my case, by a factor of 5. Multiplying the FIR co-efficients by interpolation factor is fixing it. But, I would like to find out why is it so.
2. Also the cut-off frequency seems to be shifted by a factor of 5 too. The FIR filter had a cutoff frequency of around 25KHz. But the upsampled signal seems to be attenuated only after 125Khz. I verified if the FIR design is fine or not by filtering the original signal(without upsampling) and it seems to be fine. When the sinusoid's frequency is above 25Khz i see the attenuation and zero attenuation if the frequency is less than 25Khz.

I am bit of novice in this and any pointers for further study would also really help.

Code snippet:

Fin = 25 * 10 ** 3
Fs = 933.0 * 10 ** 3

N = 100
L = 7

### input signal
n = np.linspace(0, N, num=N)
x_input = np.sin(2 * np.pi * Fin * 1/Fs * n)

## upsampling
x_input_upsampled = up_sample(x_input, N, L)  ===> just a module written by me. does simple matrix multiplication to achieve upsampling.

##### Kaiser window
# The Nyquist rate of the signal.
nyq_rate = Fs / 2.0
# The desired width of the transition from pass to stop,
# relative to the Nyquist rate.  We'll design the filter
# with a 5 Hz transition width.
width = 5.0/nyq_rate
# The desired attenuation in the stop band, in dB.
ripple_db = 100.0
# Compute the order and Kaiser parameter for the FIR filter.
from scipy.signal import kaiserord
numtaps, beta = kaiserord(ripple_db, width)
window = ('kaiser', beta)

#### FIR filter
cutoff = 25 * 10 ** 3
cutoff_normalized = cutoff/nyq_rate
## firwin
h_windowed = signal.firwin(numtaps, cutoff_normalized, window=window)

interpolated_y = np.convolve(x_input_upsampled, h_windowed)


• Zero padding and upsampling are two different things—- upsampling involves inserting zeros between samples while zero padding is appending or prepending zeros to the entire sequence – Dan Boschen Oct 15 '18 at 19:01
• (I think you mean “zero-insert” instead of “zero-pad” so this is simply a suggestion to fix your title for clarity) – Dan Boschen Oct 15 '18 at 21:02
• thanks for the pointing it out. I have edited the title. – pradeepmcp Oct 16 '18 at 3:38

I did not review your entire code, but from your description I believe what you are seeing is expected and explained with the following graphic.

The upper portion shows an example digital spectrum in the unique frequency span of DC to $$F_s$$ where $$F_s$$ is the sampling rate. (If we considered the frequency span to go from $$-\infty$$ to $$+\infty$$ we would see that this spectrum would replicate, thus we typically only show it over this range, or alternatively from $$-F_s/2$$ to $$+F_s/2$$.

The replication that occurs however is handy to help understand what occurs when we insert zeros to upsample by a factor N. This simple shifts the frequency to $$N F_s$$ while leaving the spectrum completely intact. (Hence the reason to upsample by inserting zeros rather than do a zero-order hold, meaning hold the same value, as that has a low pass filtering effect). When we change the sampling rate to $$N F_s$$ by inserting $$N-1$$ zeros in between each sample, the sampling rate is higher as expected, but the entire spectrum remains intact and now as part of our primary sampling frequency spectrum from 0 to our new sampling rate of $$N F_s$$ and thus are undesired images that must be filtered out to complete the interpolation. This is shown in the lower plot where $$N=5$$ as in your case. In the time domain the magnitude of the signal is unchanged after the zero insert, yet it's energy is distributed in frequency thus after filtering out the images the magnitude is reduced as you are seeing.

This is very clear to see if you consider a DC signal of all ones:

1 1 1 ...

After zero insert for $$N=5$$ this becomes

1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 ...

Prior to zero insert the peak amplitude was 1 and the average was also 1. After zero insert we have the same peak amplitude, but the average (which is a low pass filter, in this case estimate of the DC value) is now only 1/5!

Continuing that example in the frequency domain, below is the absolute value of the FFT of one hundred ones [1 1 1 1 ....1], as expected the result is in the first bin (DC) and is the summation of the samples as expressed in the formula for the FFT: Below is the same result after a zero insert for an interpolation factor of 5. Here we see the replication in frequency that occurs, but notice that the result is still 100, even though we have a 500 samples instead of 100, and importantly that this is replicated 5 times. The low pass filter would probably remove the higher frequencies leaving a mangitude of 100 result in the FFT for a 500 sample FFT. (The FFT is often normalized by the number of samples in order for the FFT magnitude to be equivalent to the magnitude of the time domain signal; and the normalized FFT for the first case would be $$100/100 =1$$ , and $$100/500 = 0.2$$ for the interpolated case.

To answer your second question, know that digital filters will scale with the sampling rate. So whatever results you have at $$F_s$$ will scale when you run the filter as $$N F_s$$. This is one reason why it is convenient to describe digital systems using a fractional frequency axis (either 0 to 1 corresponding to 0 to $$F_s$$ or 0 to $$2\pi$$ corresponding to the equivalent angular frequency.