Skip to content

Bind sdr::OversampledChannelizer and OversampledSynthesizer #126

Description

@Ravenwater

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

  • Bindings in src/sdr_bindings.cpp.
  • Exported by explicit name in python/mpdsp/__init__.py.
  • tests/test_sdr_channelizer.py — tone lands in the expected channel and
    its conjugate mirror; analysis -> synthesis round trip reconstructs
    within tolerance; behaviour across the dtype table.
  • scripts/build_api_ref.py tables updated, docs/api_reference.md
    regenerated.

Part of the SDR binding epic #130.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions