Nyquist Signal Expansion with Python
Filtering and Scaling
The real magic is the finite impulse response filter, or FIR filter. We are going to cheat and let the computer figure out what the filter coefficients need to be. To do this, we use the remez() function in the scipy.signals package. This function is similar to the firpm() function in MATLAB. We give the function our pass band and stop band. We want to pass all frequencies less than or equal to fmax. Since we expanded the signal, we need to compute what fmax is for the higher sample rate. To do this we divide by L. This gives us:
The magnitude of the filter is:
If you noticed I snuck a scaling factor into the filter coefficients. I scaled them by L.
Now we need to run the expanded signal through the filter:
Which gives us:
Now, this looks like it could be what we are looking for, but why is it shifted you ask? That has to do with the delay in the filter, which is directly related to the number of taps in the filter.
Calculating the Filter Delay
The filter delay is equal to the number of taps, minus 1, in the filter divided by 2. For this example it is [latex]n_s=\frac{\textrm{len}(h)-1}{2}[/latex]. That’s the delay in samples, but how does that relate back to the time shift?
. Now that we’ve figured this out, we will shift the input signal to match the delay coming out of the filter:
The calculated delay for this example is 1.66. Looking at Figure 5, we see that the points match up after that time.
Non-integer Resampling
So you say, this is great, but I need my signal resampled by a non-integer value. That’s great. We do the exact same thing as above and then slice the resulting data to take every Mth sample. Easy as
Next we put it all together.