Bind sw::dsp::sdr::OversampledChannelizer and OversampledSynthesizer — the
analysis/synthesis pair.
Upstream source: include/sw/dsp/sdr/channelizer.hpp (closes upstream #102).
Upstream tests: tests/test_sdr_channelizer.cpp.
Surface
OversampledChannelizer<CoeffScalar, StateScalar, SampleScalar> —
process(block) -> M complex channel outputs per hop, reset()
OversampledSynthesizer<CoeffScalar, StateScalar, SampleScalar> — the
inverse, M channels -> hop_ real samples, reset()
- Prototype-bank design helper (the
h(N) / denom(hop) construction near
the top of the header)
Binding notes
- This is not the same class as
mpdsp.Channelizer. That one binds
sw::dsp::multirate::Channelizer — critically sampled, hop = M. This one is
oversampled: hop < M, so channels overlap and the analysis/synthesis pair
reconstructs. Two classes with near-identical names in one namespace is a
usability trap. Decide the Python names deliberately — OversampledChannelizer
/ OversampledSynthesizer mirrors upstream and is unambiguous; a bare
Channelizer alias would collide with the existing binding.
- Also cross-link the two in the docstrings. Upstream's own docs added a
pointer from multirate/channelizer.md to the synthesis half for exactly
this reason (upstream 287584c).
- Three scalar axes —
<CoeffScalar, StateScalar, SampleScalar>. This is
the worst case for the dispatch decision in the foundations issue; at 18
configs an independent-axis scheme is 5832 instantiations. If the foundations
issue picked curated pairs, this class needs the triple form of that scheme.
- The prototype bank is designed once at construction. Like the RRC designer,
CoeffScalar is design-time and narrows back to double for storage — so it
may be expressible as coeff_dtype= at no runtime instantiation cost, which
would reduce the live axes to two. Confirm against the header before
assuming.
- Complex outputs go through
complex_split_to_numpy; the 2-D (blocks, channels) shape follows the pattern already established in
src/multirate_bindings.cpp::process_block.
- Note the upstream test lesson: a real input tone appears in two channels,
the wanted one and its conjugate mirror at M - c. Upstream had to fix its
own test for this (31a2ddb), and so did this repo's multirate channelizer
tests. Write the Python test knowing it.
Depends on
Foundations issue (both decisions).
Deliverables
Part of the SDR binding epic #130.
Bind
sw::dsp::sdr::OversampledChannelizerandOversampledSynthesizer— theanalysis/synthesis pair.
Upstream source:
include/sw/dsp/sdr/channelizer.hpp(closes upstream #102).Upstream tests:
tests/test_sdr_channelizer.cpp.Surface
OversampledChannelizer<CoeffScalar, StateScalar, SampleScalar>—process(block)-> M complex channel outputs per hop,reset()OversampledSynthesizer<CoeffScalar, StateScalar, SampleScalar>— theinverse, M channels ->
hop_real samples,reset()h(N)/denom(hop)construction nearthe top of the header)
Binding notes
mpdsp.Channelizer. That one bindssw::dsp::multirate::Channelizer— critically sampled, hop = M. This one isoversampled: hop < M, so channels overlap and the analysis/synthesis pair
reconstructs. Two classes with near-identical names in one namespace is a
usability trap. Decide the Python names deliberately —
OversampledChannelizer/
OversampledSynthesizermirrors upstream and is unambiguous; a bareChannelizeralias would collide with the existing binding.pointer from
multirate/channelizer.mdto the synthesis half for exactlythis reason (upstream
287584c).<CoeffScalar, StateScalar, SampleScalar>. This isthe worst case for the dispatch decision in the foundations issue; at 18
configs an independent-axis scheme is 5832 instantiations. If the foundations
issue picked curated pairs, this class needs the triple form of that scheme.
CoeffScalaris design-time and narrows back to double for storage — so itmay be expressible as
coeff_dtype=at no runtime instantiation cost, whichwould reduce the live axes to two. Confirm against the header before
assuming.
complex_split_to_numpy; the 2-D(blocks, channels)shape follows the pattern already established insrc/multirate_bindings.cpp::process_block.the wanted one and its conjugate mirror at
M - c. Upstream had to fix itsown test for this (
31a2ddb), and so did this repo's multirate channelizertests. Write the Python test knowing it.
Depends on
Foundations issue (both decisions).
Deliverables
src/sdr_bindings.cpp.python/mpdsp/__init__.py.tests/test_sdr_channelizer.py— tone lands in the expected channel andits conjugate mirror; analysis -> synthesis round trip reconstructs
within tolerance; behaviour across the dtype table.
scripts/build_api_ref.pytables updated,docs/api_reference.mdregenerated.
Part of the SDR binding epic #130.