← Ordo Artificum

gfsk8-modem

JS8Call modem library

A standalone C++20 static library providing encode, modulate, and decode for all five JS8 submodes — extracted from the JS8Call-improved source tree and stripped of every heavyweight dependency.

Working & available now GitHub

What it is

gfsk8-modem is a C++20 static library that isolates the JS8 modem from the JS8Call-improved source tree. The original JS8Call codebase carries hard dependencies on Qt, FFTW3, Boost, and Eigen — making it impossible to use the modem in any application that doesn't also pull in Qt's entire stack. gfsk8-modem removes all of those dependencies and provides a clean, minimal API for encoding messages, modulating audio, and decoding received frames.

The only remaining external dependency is KissFFT, which is small enough to vendor directly into the library. The result is a library that compiles for Linux x86-64, aarch64 (Raspberry Pi), and Windows (MinGW cross-compile) with a single cmake command and no system packages required beyond a C++20 compiler.

The JS8 mode

JS8 is a weak-signal HF digital mode for keyboard-to-keyboard communication, designed by Jordan Sherer (KN4CRD). It is derived from FT8 — itself the creation of Joe Taylor (K1JT) and Steve Franke (K9AN) — and uses the same 8-GFSK modulation, 79-symbol frame structure, Costas array synchronization, and LDPC forward error correction that made FT8 the most-used HF digital mode in the world. JS8 extends FT8's fixed-format message structure to support free-text exchange, directed messaging, and relay forwarding.

The five JS8 submodes — Normal (15 s), Fast (10 s), Turbo (6 s), Slow (30 s), and Ultra (4 s) — trade throughput for sensitivity, allowing operation under varying propagation conditions. gfsk8-modem supports all five.

API surface

  • Encode — pack a callsign, grid, and free-text message into a JS8 frame payload.
  • Modulate — convert a frame payload to 12 kHz float32 PCM audio for any submode.
  • Decode — search a 12 kHz int16 audio buffer for all five submodes simultaneously; returns decoded frames with SNR and frequency offset.
  • Log callback — optional callback for internal decoder diagnostic messages.

The public API lives entirely in include/gfsk8modem.h under the gfsk8:: namespace. Internal implementation headers are not exposed.

Platform support

Linux x86-64
Native
Raspberry Pi
aarch64 cross-compile
Windows
MinGW cross-compile

Building

# clone and build
git clone https://github.com/jfrancis42/gfsk8-modem
cd gfsk8-modem
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -- -j2
# output: build/libgfsk8modem.a

No system packages required beyond a C++20 compiler and CMake 3.20+. KissFFT is vendored. Cross-compilation toolchains are included in the repository.

Credits & prior work

gfsk8-modem would not exist without the foundational work of the people who invented and implemented the modes it carries:

Joe Taylor (K1JT) & Steve Franke (K9AN)

Inventors of FT8, the mode at the heart of JS8. Their research paper "FT8, a Weak-Signal HF Propagation Mode" (QST, 2018) and the open-source WSJT-X implementation define the 8-GFSK modulation, Costas array synchronization, and LDPC coding that gfsk8-modem implements. The entire weak-signal digital mode ecosystem exists because of their work.

Jordan Sherer (KN4CRD) & the JS8Call-improved team

Creator of JS8Call and the JS8 protocol extension that turned FT8's structured-message format into a general-purpose free-text communication mode. The JS8Call-improved fork, maintained by the community after JS8Call development slowed, is the upstream source from which gfsk8-modem was extracted and refactored. Their protocol design, codec implementation, and varicode work are the direct predecessors of this library.

gfsk8-modem is a derivative work. It is licensed GPL-3.0, consistent with the upstream JS8Call and WSJT-X licenses.