A modern, modular, and performance enhanced C/C++ decoder for digital voice. DMR, P25, NXDN, YSF, and more. https://github.com/arancormonk/dsd-neo
  • C 77.7%
  • C++ 18.8%
  • CMake 2.5%
  • Shell 0.9%
  • PowerShell 0.1%
Find a file
2026-04-13 22:02:48 -05:00
.githooks build(ci,cmake): require radio backends and validate install runtime destinations 2026-02-24 15:25:36 -06:00
.github build(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1 2026-04-12 00:42:24 +00:00
.vscode I know DSP(); load programs - scaffold repo. Initial commit. 2025-09-16 14:49:48 -05:00
apps core(vocoder,file,init),apps(cli): harden mbelib-neo integration 2026-02-21 22:05:07 -06:00
cmake protocol(p25): remove weak p25_sm_* wrapper attributes; protocol(p25p2): gate p25_sm_emit_active/on_release in DSD_NEO_P25P2_TEST_STUB builds; tests(p25): switch SM overrides to p25_sm_set_api; cmake(arch): forbid attribute((weak)) in src 2026-01-08 14:58:54 -06:00
docs feat: add RF baseband (I/Q) capture and replay 2026-04-12 17:36:58 -05:00
examples I know DSP(); load programs - scaffold repo. Initial commit. 2025-09-16 14:49:48 -05:00
images ci(linux-appimage): add ImageMagick and generate 256x256 icon from images/dsd-neo.png (fallback to screenshot) 2025-09-23 09:30:01 -05:00
include/dsd-neo core(audio,frames): fix .bin replay pacing drift and lag 2026-04-13 22:02:48 -05:00
packaging docs: continue to close documentation gaps 2026-02-21 10:43:53 -06:00
src core(audio,frames): fix .bin replay pacing drift and lag 2026-04-13 22:02:48 -05:00
tests dsp(core,io,nxdn): harden demod math and soft-metric scaling 2026-04-13 21:50:38 -05:00
tools tools(coverage): make default report project-wide and strict 2026-04-09 18:58:38 -05:00
vcpkg-ports windows(ci),io,vcpkg: eliminate MSVC/vcpkg warning noise without behavior changes 2026-02-24 16:06:56 -06:00
vcpkg-triplets build: fix debug builds 2025-12-13 20:48:28 -06:00
.clang-format I know DSP(); load programs - scaffold repo. Initial commit. 2025-09-16 14:49:48 -05:00
.clang-tidy clang-tidy: fix missing ci clang-tidy option 2025-12-19 23:03:50 -06:00
.clang-tidy.strict clang-tidy: fix missing ci clang-tidy option 2025-12-19 23:03:50 -06:00
.gitignore iwyu: add direct standard headers for strict mode 2026-02-21 19:38:41 -06:00
.vsconfig ci(windows): fix MinGW staging DLL search path for ncurses 2025-12-13 23:04:29 -06:00
CMakeLists.txt build(cmake): preserve C++14 around SoapySDR find_package 2026-02-24 15:49:33 -06:00
CMakePresets.json ci(mingw): fix dll search regex 2025-12-14 10:04:23 -06:00
COPYRIGHT docs: align docs with codebase 2025-12-26 08:38:20 -06:00
DSD_Author.pgp I know DSP(); load programs - scaffold repo. Initial commit. 2025-09-16 14:49:48 -05:00
LICENSE build/license: switch to GPL-3.0-or-later and rewrite D-STAR header utils under GPL-3.0 2025-11-19 23:26:03 -06:00
README.md feat: add RF baseband (I/Q) capture and replay 2026-04-12 17:36:58 -05:00
THIRD_PARTY.md fec(ezpwd): sync reed-solomon vendor to arancormonk/ezpwd-reed-solomon; fec(cmake): add rs_definitions TU; docs: update third-party notice 2025-12-29 13:10:55 -06:00
vcpkg-configuration.json ci: first attempt at native windows builds 2025-12-11 21:44:29 -06:00
vcpkg.json build(deps): bump github.com/microsoft/vcpkg from master to 2026.03.18 2026-03-22 00:42:26 +00:00

DSD-neo

A modular and performanceenhanced version of the well-known Digital Speech Decoder (DSD) with a modern CMake build, split into focused libraries (runtime, platform, dsp, io, engine, fec, crypto, protocol, core, ui) and a thin CLI.

Project homepage: https://github.com/arancormonk/dsd-neo

linux-ci windows-ci macos-ci

DSD-neo

Downloads

On Windows, the native MSVC ZIP is the preferred download for best integration with the Windows console and audio stack. The MinGW ZIP is a fully native alternative.

Project Status

This project is an active work in progress as we decouple from the upstream fork and continue modularization. Expect breaking changes to build presets, options, CLI flags, and internal library boundaries while this stabilization work proceeds. The main branch may be volatile; for deployments, prefer building a known commit. Issues and PRs are welcome—please include logs and reproduction details when reporting regressions.

Overview

  • A performanceenhanced fork of lwvmobile/dsd-fme, which is a fork of szechyjs/dsd
  • Modularized fork with clear boundaries: runtime, platform, dsp, io, engine, fec, crypto, protocol, core, plus ui and a CLI app.
  • Protocol coverage: DMR, dPMR, DSTAR, NXDN, P25 Phase 1/2, X2TDMA, EDACS, ProVoice, M17, YSF.
  • Requires arancormonk/mbelib-neo for IMBE/AMBE vocoder primitives.
  • Public headers live under include/dsd-neo/... and are included as #include <dsd-neo/<module>/<header>>.

How DSDneo Is Different

  • More input and streaming options

    • Direct RTLSDR USB, plus RTLTCP (-i rtltcp[:host:port]) and SoapySDR (-i soapy[:args]) for non-RTL radios (for example Airspy/SDRplay/HackRF/LimeSDR).
    • Generic TCP PCM16LE input (-i tcp[:host:port], SDR++/GRC 7355 audio streams).
    • UDP audio in/out: receive PCM16LE over UDP as an input, and send decoded audio to UDP sinks for easy piping to other apps or hosts (decoded voice is typically 8 kHz; see docs/network-audio.md).
    • M17 UDP/IP in/out: dedicated M17 frame input/output over UDP (-i m17udp[:bind:17000], -o m17udp[:host:17000]).
    • RF I/Q capture/replay workflow with metadata (--iq-capture, --iq-info, --iq-replay) for reproducible decode debugging and regression replay.
  • Builtin trunking workflow

    • Follow P25 and DMR trunked voice automatically using channel maps and group lists (-C ...csv, -G group.csv, -T, -N).
    • Onthefly retune control via rigctl (-U) for external SDR front-ends (e.g., SDR++). For RTL/RTLTCP input, DSD-neo retunes directly (optional external UDP retune control can be enabled with --rtl-udp-control <port>; see docs/udp-control.md).
  • RTLSDR qualityoflife features

    • Biastee control (when supported by your librtlsdr), manual or auto gain, power squelch, adjustable tuner bandwidth, and perrun PPM correction.
    • Optional spectrumbased autoPPM drift correction with SNR/power gating and short training/lock, for long unattended runs.
    • rtl_tcp niceties: configurable prebuffering to reduce dropouts and settings tuned for stable network use.
  • RTLSDR optimizations and diagnostics

    • Realtime visual aids in the terminal for faster setup and troubleshooting:
      • Constellation view with adjustable gating and normalization.
      • Eye diagram (Unicode/ASCII, optional color) with adaptive scales and level guides.
      • Spectrum analyzer with adjustable FFT size.
      • FSK 4level histogram and live permodulation SNR readouts.
    • Heavily optimized RTL path for smoother audio and fewer dropouts:
      • Onepass byte→I/Q widening with optional 90° rotation and DCspur fs/4 capture shift (configurable).
      • Cascaded decimation and an optional rational resampler to keep processing efficient and responsive.
      • Optional autoPPM correction from the timing error detector for long unattended runs.
    • Device control from the UI: toggle biastee, switch AGC/manual gain, adjust bandwidth and squelch, and retune quickly.
  • M17 encode tooling

    • Generate M17 signals for test/airgap workflows: stream voice (-fZ), packet (-fP), and BERT (-fB) encoders.
  • Expanded DSP controls for power users

    • Changes apply instantly from the UI and persist across retunes.
    • See docs/cli.md for environment variable reference.
  • Portable, readytorun builds

    • Linux AppImage, macOS DMG, and Windows portable ZIP releases.

How this compares at a glance

  • Versus DSDFME: similar protocol coverage and UI heritage, but DSDneo adds networkfriendly I/O (UDP audio in), refined RTLTCP handling (prebuffer, tuned defaults), optional autoPPM, and packaged crossplatform binaries.
  • Versus the original DSD: more protocols (notably P25 Phase 2, M17, YSF, EDACS), builtin trunking, network inputs, device control, and an interactive UI.

Build From Source

Requirements

  • C compiler with C11 and C++ compiler with C++14 support.
  • CMake ≥ 3.20.
  • Dependencies:
    • Required: libsndfile; a curses backend (ncursesw/PDCurses); and an audio backend (PulseAudio by default, PortAudio on Windows).
    • Optional: librtlsdr (RTLSDR support), SoapySDR (nonRTL SDR backends), Codec2 (additional vocoder paths), libcurl (rdio API uploads), help2man (man page generation).
    • Vocoder: mbelib-neo (mbe-neo CMake package) is required.

OS package hints

  • Ubuntu/Debian (apt):
    • sudo apt-get update && sudo apt-get install -y build-essential cmake ninja-build libsndfile1-dev libpulse-dev libncurses-dev librtlsdr-dev libsoapysdr-dev
  • macOS (Homebrew):
    • brew install cmake ninja libsndfile ncurses pulseaudio librtlsdr soapysdr codec2
  • Windows:
    • Preferred binary: the native MSVC ZIP. The MinGW ZIP is an alternative native build.
    • Source builds use CMake presets with vcpkg; set VCPKG_ROOT and use win-msvc-* or win-mingw-* presets in CMakePresets.json.

MBE vocoder dependency (mbelib-neo)

DSDneo requires the mbe-neo CMake package (from mbelib-neo). If CMake fails with “could not find mbe-neo”, install it and re-run configure.

Example (Linux/macOS):

# Build and install mbelib-neo (once)
git clone https://github.com/arancormonk/mbelib-neo
cmake -S mbelib-neo -B mbelib-neo/build -DCMAKE_BUILD_TYPE=Release
cmake --build mbelib-neo/build -j
cmake --install mbelib-neo/build --prefix "$HOME/.local"

# Then configure dsd-neo (point CMake to the install prefix)
cmake --preset dev-release -DCMAKE_PREFIX_PATH="$HOME/.local"

Build recipes (copy/paste)

# From the repository root.
#
# OS deps (examples):
# - Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y build-essential cmake ninja-build libsndfile1-dev libpulse-dev libncurses-dev librtlsdr-dev libsoapysdr-dev
# - macOS:         brew install cmake ninja libsndfile ncurses pulseaudio librtlsdr soapysdr codec2
#
# Install is optional; you can run directly from the build tree.

cmake --preset dev-release
cmake --build --preset dev-release -j

# Run (no install required)
build/dev-release/apps/dsd-cli/dsd-neo -h

# Install (optional; pick one)
cmake --install build/dev-release --prefix "$HOME/.local"
# sudo cmake --install build/dev-release

Linux/macOS — debug build + tests (preset dev-debug)

# OS deps (examples):
# - Ubuntu/Debian: sudo apt-get update && sudo apt-get install -y build-essential cmake ninja-build libsndfile1-dev libpulse-dev libncurses-dev librtlsdr-dev libsoapysdr-dev
# - macOS:         brew install cmake ninja libsndfile ncurses pulseaudio librtlsdr soapysdr codec2

cmake --preset dev-debug
cmake --build --preset dev-debug -j
ctest --preset dev-debug -V

# Run (no install required)
build/dev-debug/apps/dsd-cli/dsd-neo -h

Manual configure/build (no presets)

# Use a build directory that isn't a preset (so you don't expect build/dev-release to exist).
cmake -S . -B build/manual -DCMAKE_BUILD_TYPE=Release
cmake --build build/manual -j

# Run (no install required)
build/manual/apps/dsd-cli/dsd-neo -h

# Install (optional; pick one)
cmake --install build/manual --prefix "$HOME/.local"
# sudo cmake --install build/manual

Coverage (optional)

tools/coverage.sh  # generates build/coverage-debug/coverage_html

Notes

  • Presets live in CMakePresets.json.
  • Presets create outofsource builds under build/<preset>/. Run from the repo root.
  • The CLI binary outputs to build/<preset>/apps/dsd-cli/dsd-neo.
  • cmake --install <build_dir> only works if you configured that build directory. If you're inside the build directory, use cmake --install ..
  • If cmake --install build/dev-release fails and build/dev-release/ doesn't exist, you likely did a manual build (install from your actual build dir).

Install / Uninstall

# Preset builds (recommended)
# Single-config generators (Unix Makefiles/Ninja):
cmake --install build/dev-release --prefix "$HOME/.local"

# Multi-config generators (Visual Studio/Xcode):
cmake --install build/dev-release --config Release --prefix "$HOME/.local"

# Manual build directory (example above uses `build/manual/`):
cmake --install build/manual --prefix "$HOME/.local"
# cmake --install build --prefix "$HOME/.local"  # if you configured into `build/`

# Uninstall from the same build directory
cmake --build build/dev-release --target uninstall  # preset build
cmake --build build/manual --target uninstall       # manual build directory
# cmake --build build --target uninstall            # if you configured into `build/`

Build Options

These are CMake cache options (set at configure time via -D...).

  • Build hygiene and optimization:
    • -DDSD_ENABLE_WARNINGS=ON — Enable common warnings (default ON).
    • -DDSD_WARNINGS_AS_ERRORS=ON — Treat warnings as errors.
    • -DDSD_ENABLE_FAST_MATH=ON — Enable fastmath (-ffast-math//fp:fast) across targets.
    • -DDSD_ENABLE_LTO=ON — Enable IPO/LTO in Release builds (when supported).
    • -DDSD_ENABLE_NATIVE=ON — Enable -march=native -mtune=native (nonportable binaries).
    • -DDSD_ENABLE_ASAN=ON — AddressSanitizer in Debug builds.
    • -DDSD_ENABLE_UBSAN=ON — UndefinedBehaviorSanitizer in Debug builds.
  • Audio backend selection:
    • -DDSD_USE_PORTAUDIO=ON — Use PortAudio instead of PulseAudio (default on Windows).
  • Radio backend selection:
    • -DDSD_ENABLE_RTLSDR=ON|OFF — Enable/disable RTL-SDR backend discovery.
    • -DDSD_ENABLE_SOAPYSDR=ON|OFF — Enable/disable SoapySDR backend discovery.
    • -DDSD_REQUIRE_RTLSDR=ON|OFF — Fail configure when RTL-SDR is enabled but unavailable.
    • -DDSD_REQUIRE_SOAPYSDR=ON|OFF — Fail configure when SoapySDR is enabled but unavailable.
  • UI and behavior toggles:
    • -DCOLORS=OFF — Disable ncurses color output.
    • -DCOLORSLOGS=OFF — Disable colored terminal/log output.
  • Protocol and feature knobs:
    • -DPVC=ON — Enable ProVoice Conventional Frame Sync.
    • -DLZ=ON — Enable LimaZulurequested NXDN tweaks.
    • -DSID=ON — Enable experimental P25p1 Soft ID decoding.
  • Optional features (autodetected):
    • RTLSDR support is enabled when librtlsdr is found.
    • SoapySDR support is enabled when SoapySDR is found.
    • Codec2 support is enabled when codec2 is found.

CI Backend Policy

  • CI treats backend availability as a build contract, not a best-effort option.
  • Linux CI runs a backend matrix for both, soapy_only, rtl_only, and neither.
  • Release/packaging/static-analysis jobs that are expected to exercise radio backends configure with:
    • -DDSD_REQUIRE_RTLSDR=ON
    • -DDSD_REQUIRE_SOAPYSDR=ON
  • If either required backend is missing, configure fails fast.

Backend Matrix Reproduction (Local)

Run from repo root after installing deps (librtlsdr and SoapySDR when required):

# both backends required
cmake --preset dev-debug \
  -DDSD_ENABLE_RTLSDR=ON -DDSD_REQUIRE_RTLSDR=ON \
  -DDSD_ENABLE_SOAPYSDR=ON -DDSD_REQUIRE_SOAPYSDR=ON
cmake --build --preset dev-debug -j

# soapy_only
cmake --preset dev-debug \
  -DDSD_ENABLE_RTLSDR=OFF \
  -DDSD_ENABLE_SOAPYSDR=ON -DDSD_REQUIRE_SOAPYSDR=ON
cmake --build --preset dev-debug -j

# rtl_only
cmake --preset dev-debug \
  -DDSD_ENABLE_RTLSDR=ON -DDSD_REQUIRE_RTLSDR=ON \
  -DDSD_ENABLE_SOAPYSDR=OFF
cmake --build --preset dev-debug -j

# neither
cmake --preset dev-debug \
  -DDSD_ENABLE_RTLSDR=OFF \
  -DDSD_ENABLE_SOAPYSDR=OFF
cmake --build --preset dev-debug -j

CI-like strict scan-build run:

tools/scan_build.sh --strict \
  --cmake-arg -DDSD_REQUIRE_RTLSDR=ON \
  --cmake-arg -DDSD_REQUIRE_SOAPYSDR=ON

Runtime Tuning

Most users can run with defaults. For advanced tuning, see docs/cli.md.

Common options:

  • AutoPPM drift correction (RTLSDR): --auto-ppm
  • RTLTCP adaptive buffering: --rtltcp-autotune
  • Rig control (SDR++): -U 4532 (default port), -B <Hz> (bandwidth)

SoapySDR Quickstart

  • Use SoapySDR when your hardware is not accessed through librtlsdr directly.
  • Build with Soapy enabled (-DDSD_ENABLE_SOAPYSDR=ON) and optionally require it (-DDSD_REQUIRE_SOAPYSDR=ON).
  • Install SoapySDR tools and the Soapy module for your radio; verify with SoapySDRUtil --info and discover args with SoapySDRUtil --find.
  • Run with -i soapy[:args]. The soapy: string selects backend/device only; set tuning via rtl_* keys (at minimum rtl_freq; easiest via config). See the guide for a minimal config snippet.
  • Full guide: docs/soapysdr.md.

Using The CLI

  • See the friendly CLI guide: docs/cli.md
    • Or run dsd-neo -h for quick usage in your terminal.
    • Digital/analog output gain: -g <float> (digital; 0 = auto, 1 ≈ 2%, 50 = 100%) and -n <float> (analog 0100%).
    • DMR mono helpers:
      • Modern form: -fs -nm (DMR BS/MS simplex + mono audio).
      • Legacy alias: -fr (kept as a shorthand for the same DMRmono profile).
    • CSV formats (channel maps, group lists, key lists): docs/csv-formats.md (examples in examples/)

Quick examples

  • UDP in → Pulse out with UI: dsd-neo -i udp -o pulse -N
  • DMR trunking from TCP PCM input (with rigctl): dsd-neo -fs -i tcp -U 4532 -T -C dmr_t3_chan.csv -G group.csv -N
  • IQ capture + inspect + replay: dsd-neo -i rtl:0:851.375M:22:0:48:0:2 --iq-capture p25-control.iq -N then dsd-neo --iq-info p25-control.iq.json then dsd-neo --iq-replay p25-control.iq.json -f1 -N

Configuration

  • INIstyle user config is implemented for stable defaults (input/output/mode/trunking); see docs/config-system.md.
  • Config loading is opt-in: use --config to enable (optionally with a path), set DSD_NEO_CONFIG=<path>, or pass a single positional *.ini path (treated as --config <path>).
  • Default path (when --config is passed without a path): ${XDG_CONFIG_HOME:-$HOME/.config}/dsd-neo/config.ini.
  • --interactive-setup forces the bootstrap wizard even when a config exists; --print-config dumps the effective config as INI.
  • When config is enabled, the final settings are autosaved on exit.

Tests

  • Run all tests: ctest --preset dev-debug -V (or ctest --test-dir build/dev-debug -V).
  • Scope: unit tests cover runtime config parsing/validation, DSP primitives (filters/resampler/demod helpers), and FEC/crypto helpers.

Documentation

  • CLI usage and options: docs/cli.md
  • IQ capture/replay format and workflow: docs/iq-capture-replay.md
  • SoapySDR non-RTL setup and usage: docs/soapysdr.md
  • User config system (INI): docs/config-system.md
  • Trunking CSV formats: docs/csv-formats.md (examples in examples/)
  • Network audio I/O details (TCP/UDP/stdin/stdout): docs/network-audio.md
  • Terminal UI hotkeys and menus: docs/ui-terminal.md
  • RTL UDP retune control protocol: docs/udp-control.md
  • Module overview and build targets: docs/code_map.md

Project Layout

  • Apps: apps/dsd-cli — CLI entrypoint, target dsd-neo.
  • Core: src/core, headers <dsd-neo/core/...> — glue (audio, vocoder, frame dispatch, GPS, file import).
  • Engine: src/engine, headers <dsd-neo/engine/...> — top-level decode/encode runner and lifecycle.
  • Platform: src/platform, headers <dsd-neo/platform/...> — cross-platform primitives (audio backend, sockets, threading, timing, curses).
  • Runtime: src/runtime, headers <dsd-neo/runtime/...> — config, logging, aligned memory, rings, worker pool, RT scheduling, git version.
  • DSP: src/dsp, headers <dsd-neo/dsp/...> — demod pipeline, resampler, filters, FLL/TED, SIMD helpers.
  • IO: src/io, headers <dsd-neo/io/...> — radio (RTLSDR, RTLTCP, SoapySDR), audio (PulseAudio/PortAudio + UDP PCM input/output), control (UDP/rigctl/serial).
  • FEC: src/fec, headers <dsd-neo/fec/...> — BCH, Golay, Hamming, RS, BPTC, CRC/FCS.
  • Crypto: src/crypto, headers <dsd-neo/crypto/...> — RC2/RC4/DES/AES and helpers.
  • Protocols: src/protocol/<name>, headers <dsd-neo/protocol/<name>/...> — DMR, dPMR, DSTAR, NXDN, P25, X2TDMA, EDACS, ProVoice, M17, YSF.
  • Thirdparty: src/third_party/ezpwd (INTERFACE target dsd-neo_ezpwd), src/third_party/pffft (FFT helper).

Tooling

  • Format: tools/format.sh (requires clang-format; see .clang-format).
  • Static analysis:
    • tools/clang_tidy.sh (use --strict for extra checks).
    • tools/cppcheck.sh (use --strict for broader checks).
    • tools/iwyu.sh (include hygiene via include-what-you-use; excludes src/third_party).
    • tools/gcc_fanalyzer.sh (GCC -fanalyzer path-sensitive diagnostics; excludes src/third_party).
    • tools/scan_build.sh (Clang Static Analyzer via scan-build, heavier full-build pass; excludes src/third_party; supports repeatable --cmake-arg passthrough).
    • tools/semgrep.sh (additional SAST rules; use --strict to fail on findings; excludes src/third_party).
  • Git hooks: tools/install-git-hooks.sh enables autoformat on commit and a CI-aligned pre-push analysis pass (clang-format, clang-tidy, cppcheck, IWYU, GCC fanalyzer, Semgrep) on changed paths.
  • Optional full scan-build pre-push/preflight pass: set DSD_HOOK_RUN_SCAN_BUILD=1.
  • Manual preflight runner: tools/preflight_ci.sh runs the same CI-aligned checks as pre-push without pushing.

Contributing

  • Languages: C (C11) and C++ (C++14). Indent width 4 spaces; no tabs; brace all control statements; line length ≤ 120.
  • Use projectprefixed includes only: #include <dsd-neo/...>.
  • Prefer small, testable helpers and add focused tests under tests/<area>.
  • Before sending changes: build presets you touched, run tools/format.sh, address feasible clangtidy and cppcheck warnings.

License

  • Project license: GPL3.0orlater (see LICENSE).
  • Portions remain under ISC per the original DSD author (see COPYRIGHT).
  • Third-party notices live in THIRD_PARTY.md (installed license texts: share/doc/dsd-neo/licenses/).
  • Project-authored source files carry SPDX identifiers reflecting their license; vendored third-party files retain upstream license headers.