Farrow arbitrary resampler¶
import numpy as np
import matplotlib.pyplot as plt
import sdr
%config InlineBackend.print_figure_kwargs = {"facecolor" : "w"}
# %matplotlib widget
Construct an input signal, ¶
Create a discrete-time signal
sample_rate = 1 # samples/s
N = 100 # samples
freq = 0.05 # Hz
tx = np.arange(N) / sample_rate # Time axis for the input signal
x = np.exp(1j * 2 * np.pi * freq * tx) # Complex exponential input signal
x *= np.exp(-np.arange(N) / 100) # Exponential decay
plt.figure(figsize=[10, 5])
plt.plot(tx, x.real, marker="o", fillstyle="none", label="real")
plt.plot(tx, x.imag, marker="o", fillstyle="none", label="imag")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.title("Original signal, $x(t)$")
plt.legend()
plt.grid(which="both", linestyle="--")
plt.show()

Resample the input signal with rate , ¶
Now, resample
In the sdr
library, the Farrow arbitrary resampler is implemented in sdr.FarrowResampler
.
def resample_signal(rate):
farrow = sdr.FarrowResampler()
y = farrow(x, rate)
new_sample_rate = rate * sample_rate
ty = np.arange(y.size) / new_sample_rate # Time axis for output signal
print(f"Input signal length: {x.size}")
print(f"Output signal length: {y.size}")
plt.figure(figsize=[10, 5])
plt.plot(tx, x.real, linestyle="none", marker="o", fillstyle="none", label="Input (real)")
plt.plot(tx, x.imag, linestyle="none", marker="o", fillstyle="none", label="Input (imag)")
plt.gca().set_prop_cycle(None)
plt.plot(ty, y.real, linestyle="none", marker=".", label="Output (real)")
plt.plot(ty, y.imag, linestyle="none", marker=".", label="Output (imag)")
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.title(f"Original $x(t)$ and resampled signal $y(t)$, rate = {rate}")
plt.legend()
plt.grid(which="both", linestyle="--")
plt.show()
Upsample the signal by an integer rate¶
When upsampling by 2, notice there are two output samples for every input sample.
resample_signal(2)
Input signal length: 100
Output signal length: 200

When upsampling by 4, notice there are four output samples for every input sample.
resample_signal(4)
Input signal length: 100
Output signal length: 400

Downsample the signal by an integer rate¶
When downsampling by 2, notice every other sample of the input appears at the output.
resample_signal(1 / 2)
Input signal length: 100
Output signal length: 50

When downsampling by 4, notice every fourth sample of the input appears at the output.
resample_signal(1 / 4)
Input signal length: 100
Output signal length: 25

Upsample by an irrational rate¶
When upsampling by
resample_signal(np.pi)
Input signal length: 100
Output signal length: 315

Downsample by an irrational rate¶
When downsampling by
resample_signal(1 / np.pi)
Input signal length: 100
Output signal length: 32
