Skip to content

Python Polyphase API

Kaiser window filter-bank design tools and DPMFS polynomial coefficient fitting — used to generate the coefficient banks consumed by doppler.resample.

Source: python/dsp/doppler/polyphase/


polyphase

doppler.polyphase

Kaiser window design formulas for polyphase FIR filter banks, and DPMFS polynomial coefficient fitting.

DPMFSCoeffs dataclass

DPMFS polynomial coefficient bank.

c has shape (2, M+1, N), float32:

  • axis 0: j ∈ {0, 1} — polyphase component (j = ⌊2μ⌋)
  • axis 1: m ∈ {0..M} — polynomial order
  • axis 2: k ∈ {0..N-1} — tap index (inner, contiguous for C)

At a given fractional delay μ ∈ [0, 1)::

j    = int(2 * mu) & 1
mu_J = 2 * mu - j
h[k] = Horner(c[j, :, k], mu_J)

evaluate

evaluate(mu: float) -> np.ndarray

Return the N-tap coefficient vector for fractional delay μ.

Parameters:

Name Type Description Default
mu float

Fractional delay in [0, 1).

required

Returns:

Type Description
ndarray

float32 array of shape (N,).

validate

validate(polyphase: ndarray, verbose: bool = True) -> dict

Compare reconstructed coefficients against a reference bank.

Parameters:

Name Type Description Default
polyphase ndarray

Reference bank of shape (L, N) from kaiser_prototype.

required
verbose bool

Print a one-line summary when True.

True

Returns:

Type Description
dict

rms and max_abs coefficient errors.

to_c_header

to_c_header(name: str = 'dpmfs') -> str

Return a C header snippet with the coefficient arrays.

The arrays are named {name}_c{j}_m{m}[N], suitable for inclusion in a C source file.

kaiser_beta

kaiser_beta(attenuation_db: float) -> float

Return Kaiser window β for the given stopband attenuation (dB).

kaiser_taps

kaiser_taps(attenuation: float = 60.0, passband: float = 0.4, stopband: float = 0.6) -> int

Return prototype filter length for the given Kaiser spec.

kaiser_prototype

kaiser_prototype(attenuation: float = 60.0, passband: float = 0.4, stopband: float = 0.6, image_attenuation: float = 80.0, phases: int = None) -> np.ndarray

Return a Kaiser-windowed sinc prototype filter (float32).

fit_dpmfs

fit_dpmfs(polyphase: ndarray, M: int = 3, passband: float = 0.4, stopband: float = 0.6, attenuation: float = 60.0) -> DPMFSCoeffs

Fit DPMFS coefficients to a polyphase bank via least squares.

For each polyphase component j ∈ {0, 1} and each tap k, solves::

V @ c[j, :, k] ≈ polyphase[j*half : (j+1)*half, k]

where V is a Vandermonde matrix in μ_J ∈ [0, 1).

Parameters:

Name Type Description Default
polyphase ndarray

Float32 array of shape (L, N) — the polyphase output of :func:kaiser_prototype. L must be a power of two ≥ 2.

required
M int

Polynomial order (default 3). Order 3 (cubic) gives tight fits for smooth prototype filters with minimal overshoot.

3
passband float

Filter specifications stored in the result for reference. These do not affect the fit — they describe the input bank.

0.4
stopband float

Filter specifications stored in the result for reference. These do not affect the fit — they describe the input bank.

0.4
attenuation float

Filter specifications stored in the result for reference. These do not affect the fit — they describe the input bank.

0.4

Returns:

Type Description
DPMFSCoeffs

Polynomial coefficient bank c[j, m, k], float32.

optimize_dpmfs

optimize_dpmfs(passband: float = 0.4, stopband: float = 0.6, attenuation: float = 60.0, N: int = 6, M: int = 3, a: float = 1.0, b: float = -0.5, num_der: int = -1, K_pass: float = 10.0, K_stop: float = 1.0, n_pass: int = 100, n_stop: int = 500) -> DPMFSCoeffs

Design a DPMFS resampler via LP minimax optimization.

Wraps :func:optimize_pbf and converts the result to a :class:DPMFSCoeffs object compatible with the C runtime.

The polyphase decomposition uses J=2 (DPMFS): c[j, m, k] = C[2k + j, m]

Parameters:

Name Type Description Default
passband float

Normalised band edges (fraction of 2π, i.e. fraction of Fin).

0.4
stopband float

Normalised band edges (fraction of 2π, i.e. fraction of Fin).

0.4
attenuation float

Target stopband attenuation in dB (stored for reference only; the LP optimizer minimises the Chebyshev error directly).

60.0
N int

Number of polynomial pieces (even). Default 6.

6
M int

Polynomial order. Default 3 (cubic DPMFS).

3
a float

Basis function constants. Default a=1, b=-0.5.

1.0
b float

Basis function constants. Default a=1, b=-0.5.

1.0
num_der int

Continuity order (-1 = unconstrained).

-1
K_pass float

Passband / stopband LP weights.

10.0
K_stop float

Passband / stopband LP weights.

10.0
n_pass int

Frequency grid density.

100
n_stop int

Frequency grid density.

100

Returns:

Type Description
DPMFSCoeffs

Fitted coefficient bank, shape c[2, M+1, N//2], float32.

optimize_pbf

optimize_pbf(N: int, M: int, passband: float = 0.2, stopband: float = 0.8, a: float = 1.0, b: float = -0.5, K_pass: float = 10.0, K_stop: float = 1.0, n_pass: int = 100, n_stop: int = 500, num_der: int = -1) -> tuple[np.ndarray, float]

Minimax PBF optimization via linear programming.

Minimizes the weighted Chebyshev error between the PBF frequency response and the ideal lowpass response, subject to optional time-domain continuity constraints.

Parameters:

Name Type Description Default
N int

Number of polynomial pieces (must be even for symmetry).

required
M int

Polynomial order (e.g. 3 for cubic).

required
passband float

Normalised passband edge (fraction of 2π).

0.2
stopband float

Normalised stopband edge.

0.8
a float

Basis function constants. DPMFS default: a=1, b=-0.5.

1.0
b float

Basis function constants. DPMFS default: a=1, b=-0.5.

1.0
K_pass float

Passband / stopband weights.

10.0
K_stop float

Passband / stopband weights.

10.0
n_pass int

Number of frequency grid points in each band.

100
n_stop int

Number of frequency grid points in each band.

100
num_der int

Continuity order (-1 = none, 0 = continuous, k = k derivatives continuous).

-1

Returns:

Name Type Description
C ndarray

Coefficient matrix, shape (N, M+1).

delta float

Minimised maximum weighted error.