An implementation of DSD (sigma-delta modulation) for low sample rates
Find a file
2026-04-18 16:31:09 +08:00
src first commit 2026-04-18 16:31:09 +08:00
tests first commit 2026-04-18 16:31:09 +08:00
.gitignore first commit 2026-04-18 16:31:09 +08:00
CMakeLists.txt first commit 2026-04-18 16:31:09 +08:00
README.md first commit 2026-04-18 16:31:09 +08:00

dsd16

dsd16 is a small C++20 command-line experiment for round-tripping audio through an unusual DSD format:

  • Input: mono/stereo WAV with any sample rate and supported uncompressed sample format
  • Encoded output: 1-bit DSD in DSF at input_sample_rate * input_bits_per_sample
  • Decoded output: 16-bit PCM WAV at the original input sample rate

Examples:

  • 44.1 kHz / 16-bit WAV -> 705.6 kHz DSF
  • 48 kHz / 24-bit WAV -> 1.152 MHz DSF
  • 96 kHz / 32-bit float WAV -> 3.072 MHz DSF

The PCM resampling stages use libsoxr.

Why

I wanted to see what would happen if the same PCM audio was represented in delta-sigma at the exact same bitrate.

It turns out we just get a slightly (~60 dBFS for 16-bit) higher noise floor but beyond that, basically nothing else.

Notes

  • Supported WAV input subtypes for bitrate-matched conversion are 8/16/24/32-bit PCM plus 32/64-bit float.
  • The encoder uses libsoxr for bitrate-matched PCM upsampling followed by a conservative single-bit delta-sigma loop.
  • The written DSF stores the source PCM bit depth in its reserved fmt field so the tool can recover the original sample rate on decode.
  • The decoder reconstructs PCM with libsoxr, then adds TPDF dither before writing WAV.
  • ffprobe may report generated DSF files at an unexpected rate. That is a presentation quirk in FFmpeg's DSD handling for 1-bit DSF, not the stored DSF sampling-frequency field. The tool's own info command reports the actual stored DSD rate.

Build

cmake -S . -B build
cmake --build build

This requires libsoxr, libsndfile, and pkg-config to be available at configure time.

Test

ctest --test-dir build --output-on-failure

Usage

Encode WAV to DSF:

./build/dsd16 encode input.wav output.dsf

Decode DSF back to WAV:

./build/dsd16 decode input.dsf output.wav

Export raw DSD bits as unsigned 8-bit WAV samples (0x00 / 0xFF):

./build/dsd16 export-bits input.dsf output.wav

Both encode and decode print live progress updates to stderr, including the current stage and overall percentage.

Inspect a file:

./build/dsd16 info input.wav
./build/dsd16 info input.dsf