- class sdr.Resampler(sdr.PolyphaseFIR)
Implements a polyphase rational resampling FIR filter.
Notes
The polyphase rational resampling filter is equivalent to first upsampling the input signal \(x[n]\) by \(P\) (by inserting \(P-1\) zeros between each sample), filtering the upsampled signal with the prototype FIR filter with feedforward coefficients \(h[n]\), and then downsampling the filtered signal by \(Q\) (by discarding \(Q-1\) samples every \(Q\) samples).
Instead, the polyphase rational resampling filter first decomposes the prototype FIR filter into \(P\) polyphase filters with feedforward coefficients \(h_i[n]\). The polyphase filters are then applied to the input signal \(x[n]\) in parallel. The output of the polyphase filters are then commutated by \(Q\) to produce the output signal \(y[n]\). This prevents the need to multiply with zeros in the upsampled input, as is needed in the first case.
+------------------------+ +-->| h[0], h[3], h[6], h[9] |--> ..., ____, y[0] | +------------------------+ | +------------------------+ ..., x[1], x[0] --+-->| h[1], h[4], h[7], 0 |--> ..., y[2], ____ | +------------------------+ | +------------------------+ +-->| h[2], h[5], h[8], 0 |--> ..., ____, y[1] +------------------------+ Input Hold Output Commutator by 2 (top-to-bottom) x[n] = Input signal with sample rate fs y[n] = Output signal with sample rate fs * P / Q h[n] = Prototype FIR filter
The polyphase feedforward taps \(h_i[n]\) are related to the prototype feedforward taps \(h[n]\) by
\[h_i[j] = h[i + j P] .\]If the interpolation rate \(P\) is 1, then the polyphase rational resampling filter is equivalent to the polyphase decimating filter. See
Decimator
.References
fred harris, Multirate Signal Processing for Communication Systems, Chapter 7: Resampling Filters.
Examples
Create an input signal to resample.
In [1]: x = np.cos(np.pi / 4 * np.arange(40))
Create a polyphase filter that resamples by 7/3 using the Kaiser window method.
In [2]: fir = sdr.Resampler(7, 3); fir Out[2]: sdr.Resampler(7, 3, 'kaiser', streaming=False) In [3]: y = fir(x) In [4]: plt.figure(); \ ...: sdr.plot.time_domain(x, marker="o", label="Input"); \ ...: sdr.plot.time_domain(y, sample_rate=fir.rate, marker=".", label="Resampled"); \ ...: plt.title("Resampling by 7/3 with the Kaiser window method"); ...:
Create a streaming polyphase filter that resamples by 7/3 using the Kaiser window method. This filter preserves state between calls.
In [5]: fir = sdr.Resampler(7, 3, streaming=True); fir Out[5]: sdr.Resampler(7, 3, 'kaiser', streaming=True) In [6]: y1 = fir(x[0:10]); \ ...: y2 = fir(x[10:20]); \ ...: y3 = fir(x[20:30]); \ ...: y4 = fir(x[30:40]); \ ...: y5 = fir.flush() ...: In [7]: plt.figure(); \ ...: sdr.plot.time_domain(x, marker="o", label="Input"); \ ...: sdr.plot.time_domain(y1, sample_rate=fir.rate, offset=-fir.delay/fir.rate + 0, marker=".", label="Resampled $y_1[n]$"); \ ...: sdr.plot.time_domain(y2, sample_rate=fir.rate, offset=-fir.delay/fir.rate + 10, marker=".", label="Resampled $y_2[n]$"); \ ...: sdr.plot.time_domain(y3, sample_rate=fir.rate, offset=-fir.delay/fir.rate + 20, marker=".", label="Resampled $y_3[n]$"); \ ...: sdr.plot.time_domain(y4, sample_rate=fir.rate, offset=-fir.delay/fir.rate + 30, marker=".", label="Resampled $y_4[n]$"); \ ...: sdr.plot.time_domain(y5, sample_rate=fir.rate, offset=-fir.delay/fir.rate + 40, marker=".", label="Resampled $y_5[n]$"); \ ...: plt.title("Streaming resampling by 7/3 with the Kaiser window method"); ...:
Create a polyphase filter that resamples by 5/7 using linear method.
In [8]: fir = sdr.Resampler(5, 7); fir Out[8]: sdr.Resampler(5, 7, 'kaiser', streaming=False) In [9]: y = fir(x) In [10]: plt.figure(); \ ....: sdr.plot.time_domain(x, marker=".", label="Input"); \ ....: sdr.plot.time_domain(y, sample_rate=fir.rate, marker="o", label="Resampled"); \ ....: plt.title("Resampling by 5/7 with the Kaiser window method"); ....:
Constructors¶
- Resampler(interpolation: int, decimation: int, ...)
Creates a polyphase FIR rational resampling filter.
Special methods¶
-
__call__(x: ArrayLike, mode: 'rate' | 'full' =
'rate'
) NDArray Filters the input signal \(x[n]\) with the polyphase FIR filter.
Streaming mode only¶
- reset()
Resets the filter state. Only useful when using streaming mode.
- flush() NDArray
Flushes the filter state by passing zeros through the filter. Only useful when using streaming mode.
- property state : NDArray
The filter state consisting of the previous \(N\) inputs.
Methods¶
-
impulse_response(N: int | None =
None
) NDArray Returns the impulse response \(h[n]\) of the FIR filter.
-
step_response(N: int | None =
None
) NDArray Returns the step response \(s[n]\) of the FIR filter.
- frequency_response(...) tuple[ndarray[Any, dtype[float64]], ndarray[Any, dtype[complex128]]]
- frequency_response(freqs: float, ...) complex
- frequency_response(freqs, ...) ndarray[Any, dtype[complex128]]
Returns the frequency response \(H(\omega)\) of the FIR filter.
- group_delay(...) tuple[NDArray, NDArray]
Returns the group delay \(\tau_g(\omega)\) of the FIR filter.
- phase_delay(...) tuple[NDArray, NDArray]
Returns the phase delay \(\tau_{\phi}(\omega)\) of the FIR filter.
-
noise_bandwidth(sample_rate: float =
1.0
) float Returns the noise bandwidth \(B_n\) of the FIR filter.
Properties¶
- property method : 'kaiser' | 'linear' | 'linear-matlab' | 'zoh' | 'custom'
The method used to design the polyphase resampling filter.
- property taps : NDArray
The prototype feedforward taps \(h[n]\).
- property polyphase_taps : NDArray
The polyphase feedforward taps \(h_i[n]\).
- property polyphase_order : int
The order \(M = (N + 1)/B - 1\) of each FIR polyphase filter \(h_i[n]\).
- property input : 'hold' | 'top-to-bottom' | 'bottom-to-top'
The input connection method.
- property output : 'sum' | 'top-to-bottom' | 'bottom-to-top' | 'all'
The output connection method.
- property interpolation : int
The integer interpolation rate \(P\).
- property decimation : int
The integer decimation rate \(Q\).
- property rate : float
The fractional resampling rate \(r = P/Q\). The output sample rate is \(f_{s,out} = f_{s,in} \cdot r\).