- 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.
Polyphase 3/2 Resampling FIR Filter Block Diagram¶+------------------------+ +-->| 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 filterThe 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[tuple[int, ...], dtype[float64]], ndarray[tuple[int, ...], dtype[complex128]]]
- frequency_response(freqs: float, ...) complex
- frequency_response(...) ndarray[tuple[int, ...], dtype[complex128]]
Returns the frequency response \(H(\omega)\) of the FIR filter.
- group_delay(...) tuple[TypeAliasForwardRef('~numpy.typing.NDArray'), TypeAliasForwardRef('~numpy.typing.NDArray')]
Returns the group delay \(\tau_g(\omega)\) of the FIR filter.
- phase_delay(...) tuple[TypeAliasForwardRef('~numpy.typing.NDArray'), TypeAliasForwardRef('~numpy.typing.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\).