Skip to main content

dtmb-sdr

A minimal, vendor-neutral DTMB receiver. It accepts interleaved signed 8-bit complex samples (CI8) from a file or standard input and emits MPEG transport stream packets to a file or standard output.

CI8 file/stdin
  -> sample-rate conversion
  -> PN420/PN595/PN945 synchronization and C=3780 equalization
  -> 16QAM/32QAM/64QAM deinterleaving and soft demapping
  -> LDPC, BCH, and descrambling
  -> MPEG-TS file/stdout

Hardware acquisition is intentionally outside this repository. Any application that can produce CI8 bytes at a known sample rate can feed the receiver.

Build

Requirements are CMake 3.20+, a C++20 compiler, and Python 3.10+.

For a released platform wheel, installation is simply:

pip install dtmb-sdr

The wheel contains the native receiver executables and required LDPC data; no separate source checkout or CMake build is required.

Version 0.4.0 adds the 16QAM, 32QAM, PN420 and PN595 receive paths. These paths have synthetic regression coverage; their over-the-air validation remains pending.

To build from a source checkout:

python -m pip install -e ".[dev]"
cmake -S core/cpp -B build/core-cpp -DDTMB_CORE_BUILD_TESTS=ON
cmake --build build/core-cpp --config Release
ctest --test-dir build/core-cpp -C Release --output-on-failure
pytest

Build a distributable wheel with:

python -m build --wheel

Prebuilt wheels use the portable CPU decoder. CUDA requires a source build with a supported NVIDIA toolkit.

Decode a CI8 file

dtmb-decode \
  --input capture.ci8 \
  --input-rate 16000000 \
  --output recovered.ts \
  --acceleration cpu \
  --error-policy continue

The default profile is QAM64, FEC rate 0.6, interleaver mode 2 (--system-info-index 22). Select the modulation, FEC rate and interleaver with an explicit system-information profile:

FEC rate Interleaver 16QAM profile 32QAM profile 64QAM profile
0.4 (rate 1) mode1 11 — 19
0.4 (rate 1) mode2 12 — 20
0.6 (rate 2) mode1 13 — 21
0.6 (rate 2) mode2 14 — 22
0.8 (rate 3) mode1 15 17 23
0.8 (rate 3) mode2 16 18 24

Each 16QAM, 32QAM, and 64QAM symbol carries 4, 5, or 6 soft bits. The native frontend and demappers accept --qam 16qam|32qam|64qam, and --normalization qam uses the selected alphabet. The existing 64QAM API and dtmb_core_deinterleave_qam64 executable remain compatible; the generic executable is dtmb_core_deinterleave_qam.

Synthetic regressions cover all six 16QAM profiles, continuous interleaving, noisy natural LDPC/BCH recovery and exact transport bytes. They do not establish over-the-air validation.

32QAM profiles 17/18 group two signal frames into five rate-3 LDPC codewords.

--qam32-frame-phase auto detects packing alignment from two naturally LDPC/BCH-clean codewords at exactly one of two possible phases in a bounded prefix. The prefix is replayed and any one-frame startup discard is reported. Use 0 for a known group boundary or 1 to skip the first signal frame. An ambiguous prefix or incomplete terminal group is an error. FEC frame counters and --decode-batch-frames count two-signal-frame groups for 32QAM; diagnostics also report signal-frame counts and the grouping factor. All five codewords must pass the clean gates before the group is emitted. Synthetic tests cover both packing phases, both interleavers, noise and exact CI8-to-TS recovery.

Select the known frame header explicitly with --pn-mode pn420|pn595|pn945. The default remains pn945; PN mode is independent of the system-information profile. Automatic PN-mode selection is not implemented.

Mode Header symbols Frame symbols Frames per superframe Header/body power
PN420 420 4200 225 2
PN595 595 4375 216 1
PN945 945 4725 200 2

For example, a known PN595/16QAM rate-2, mode2 signal uses:

dtmb-decode --input input.ci8 --input-rate 7560000 --output recovered.ts \
  --pn-mode pn595 --system-info-index 14 --acceleration cpu

Use the actual input sample rate. Synthetic CI8 tests cover all three PN modes, all six 16QAM profiles, multipath, CFO, sample displacement and exact TS recovery. PN420/PN595 and 32QAM over-the-air validation is still pending. PN595/32QAM is supported by the same native stages and has synthetic coverage. For a known rate-3, mode2 transmission:

dtmb-decode --input input.ci8 --input-rate 7560000 --output recovered.ts \
  --pn-mode pn595 --system-info-index 18 --acceleration cpu

Strict mode is the default. --error-policy continue omits unclean frames and adds MPEG-TS discontinuity indications before later clean output. The runtime fails when no transport bytes are recovered. Validate nonempty output with dtmb-ts-analyze; video claims additionally require an actual codec decode, not only stream identification.

Optional CUDA LDPC acceleration

CPU decoding is the portable baseline. Build the optional CUDA LDPC backend when a supported NVIDIA toolchain is available:

cmake -S core/cpp -B build/core-cpp-cuda \
  -DDTMB_CORE_ENABLE_CUDA_LDPC=ON \
  -DDTMB_CORE_BUILD_TESTS=ON
cmake --build build/core-cpp-cuda --config Release

Then select it explicitly:

dtmb-decode \
  --bin-dir build/core-cpp-cuda \
  --input capture.ci8 \
  --input-rate 16000000 \
  --output recovered.ts \
  --acceleration cuda

The CUDA backend batches LDPC codewords and reports host-to-device, kernel, device-to-host, and total timing metrics. CPU remains available as the correctness and portability reference.

Decode a pipe

Use - for stdin or stdout:

ci8-producing-command |
  dtmb-decode --input - --input-rate 16000000 --output recovered.ts

The source command is deliberately unspecified: the receiver depends only on the byte-stream contract, not an SDR vendor or device API.

Play while decoding

With ffplay:

ci8-producing-command |
  dtmb-decode --input - --input-rate 16000000 --output - --error-policy continue |
  ffplay -fflags nobuffer -flags low_delay -f mpegts -

With VLC:

ci8-producing-command |
  dtmb-decode --input - --input-rate 16000000 --output - \
    --error-policy continue |
  vlc - --demux=ts

The producer owns the SDR device, tuning and capture policy. dtmb-decode only consumes CI8 bytes, so the same receiver command works with a hardware adapter, a vendor utility or another SDR framework on any platform. Keep diagnostics on stderr; stdout is binary MPEG-TS.

Long-running receiver controls are explicit and off by default. A deployment that has independently validated them for its RF environment can enable:

ci8-producing-command |
  dtmb-decode --input - --input-rate 16000000 --output - \
    --pn-schedule-tracking \
    --source-frame-confidence inverse-mse \
    --resample-headroom-db 6 \
    --error-policy continue |
  vlc - --demux=ts

The receiver inserts bounded 64 MiB queues after bulk stages by default so capture, frontend, demapping and FEC can progress concurrently. Use --pipeline-buffer-mib 0 only for controlled diagnostics. These options are not universal RF defaults and do not replace transport or codec validation.

PN schedule options apply to PN420 and PN945. PN595 has a fixed header and uses direct correlation for timing tracking; cyclic schedule and cyclic header averaging options are rejected. In the native frontend, --pn-estimator wideband selects the appropriate cyclic or direct channel estimator for the chosen mode. For PN595, use --pn-wideband-header-observation direct (or core). Its default linear fit spans 149 signed delays; --pn-wideband-max-span-symbols controls that span, up to 298 taps. The existing PN945 API and command defaults remain available.

Playback quality depends on RF quality and FEC cleanliness. A player detecting a service is not evidence that the complete stream is error-free.

Inspect MPEG-TS output

dtmb-ts-analyze recovered.ts
ffprobe -v error -show_programs -show_streams recovered.ts

Scope

Included:

  • portable C++20 receive stages;
  • CI8 file and stdin integration;
  • MPEG-TS file and stdout output;
  • required LDPC matrices;
  • core and pipeline-construction tests.

Not included:

  • SDR drivers or hardware-control code;
  • capture recipes, device identifiers, frequencies, gains, or locations;
  • signal-generation, scanning, UI, visualization, sweep, or research tooling;
  • real broadcast captures or derived analysis artifacts.

License

MIT. See LICENSE and THIRD_PARTY.md.

Metadata

Release files for dtmb-sdr 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dtmb-sdr 0.4.0
File Size Uploaded
dtmb_sdr-0.4.0.tar.gz 665.4 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for dtmb-sdr 0.4.0
File
dtmb_sdr-0.4.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
dtmb_sdr-0.4.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
dtmb_sdr-0.4.0-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64, Linux glibc 2.24+ x86-64 Details
dtmb_sdr-0.4.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
dtmb_sdr-0.4.0-py3-none-macosx_10_9_x86_64.whl Python 3 none macOS 10.9+ x86-64 Details

Total release size: 7.6 MB

Release files / dtmb_sdr-0.4.0.tar.gz

Download URL dtmb_sdr-0.4.0.tar.gz
Size 665.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d2f39184a45d27263e71dd9a9fa5f3db76529c7b967ce9bc5b47101a572fd7ec
BLAKE2b-256 checksum
How to use checksums
b2cf705da843bbec96631686acaaaec80003cb1c2cf4cf293612dd5578b2a1cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / dtmb_sdr-0.4.0-py3-none-win_amd64.whl

Download URL dtmb_sdr-0.4.0-py3-none-win_amd64.whl
Size 1.1 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
41f3709eefb5d8501646f24a568e661dee51640197439028a625af2e9ae4fc0e
BLAKE2b-256 checksum
How to use checksums
f3e306e7a82e95d06e8ca879994616ebcd5fd980d25f96b0dab8ec1c6696e539
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / dtmb_sdr-0.4.0-py3-none-musllinux_1_2_x86_64.whl

Download URL dtmb_sdr-0.4.0-py3-none-musllinux_1_2_x86_64.whl
Size 2.3 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
ba624d2439040ccc6588019b544c7553318e6109ecc7bad9ecaf945d71e37015
BLAKE2b-256 checksum
How to use checksums
e285a1f41bdd87753ffceeb649be991362b8d609cab1c7e88ca18216f124a4b7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / dtmb_sdr-0.4.0-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl

Download URL dtmb_sdr-0.4.0-py3-none-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
Size 1.2 MB
Tags Linux glibc 2.24+ x86-64 Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
8f930a041e1f83743952685f0d932d6c2cead79e8dadd50ef3a483fac34b2aba
BLAKE2b-256 checksum
How to use checksums
759335da412962ec67eb18f5aaf3412d3468090f9074944c1a050004003d75d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / dtmb_sdr-0.4.0-py3-none-macosx_11_0_arm64.whl

Download URL dtmb_sdr-0.4.0-py3-none-macosx_11_0_arm64.whl
Size 1.1 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
3ce83abf34558894aa32ce4c4550c3b2a23fb237c638dbfb5ccbb2be8b308a60
BLAKE2b-256 checksum
How to use checksums
34981699918fe44c987c6f5bcd5c4e444cc14d86713f480f2d275317ea5add2c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / dtmb_sdr-0.4.0-py3-none-macosx_10_9_x86_64.whl

Download URL dtmb_sdr-0.4.0-py3-none-macosx_10_9_x86_64.whl
Size 1.1 MB
Tags Python 3 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
cf3bca131457aab3e413afe7e522b4b517a0837a8ee820197aeef7cf6db87d68
BLAKE2b-256 checksum
How to use checksums
54700c08c5e1abd4e2a631b15dd504f11dd75a694ab9a933736f8771cde3af22
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.3

5 release files

0.4.2

5 release files

0.4.1

6 release files

This release

0.4.0 This release

6 release files

0.3.0

6 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page