npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@e04/ft8ts

v0.0.12

Published

FT8 encoder/decoder in pure TypeScript

Downloads

770

Readme

ft8ts

Tests

FT8/FT4 encoder and decoder in pure TypeScript. A port of the Fortran implementation from WSJT-X v2.7.0.

Overview

FT8/FT4 are digital amateur radio modes designed for weak-signal communication, developed by Joe Taylor (K1JT) and Steve Franke (K9AN).

This library provides pure TypeScript implementations of both encoding and decoding for FT8/FT4, suitable for use in Node.js or the browser.

Demo

Browser

https://e04.github.io/ft8ts/example/browser/index.html

CLI

# Decode WAV file (FT8 or FT4)
npx @e04/ft8ts decode foo.wav [--mode ft8|ft4] [--low 200] [--high 3000] [--depth 2]

# Encode message to WAV file
npx @e04/ft8ts encode "CQ JK1IFA PM95" [--out output.wav] [--df 1000]

Benchmark

The benchmark below was compiled with reference to Comparing PyFT8 with WSJT-x and FT8_lib.

| Call a | Call b | Message | WSJT-x(default) | WSJT-x (fast) | PyFT8 | ft8_lib | ft8ts (depth=3) | | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | | W1FC | F5BZB | -8 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | WM3PEN | EA6VQ | -9 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | CQ | F5RXL | IN94 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | N1JFU | EA6EE | R-07 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | A92EE | F5PSR | -14 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | K1BZM | EA3GP | -9 | ☑️ | ☑️ | ☑️ | | ☑️ | | W0RSJ | EA3BMU | RR73 | ☑️ | ☑️ | ☑️ | | ☑️ | | K1JT | HA0DU | KN07 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | W1DIG | SV9CVY | -14 | ☑️ | ☑️ | ☑️ | | ☑️ | | K1JT | EA3AGB | -15 | ☑️ | ☑️ | ☑️ | | ☑️ | | XE2X | HA2NP | RR73 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | N1PJT | HB9CQK | -10 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | | K1BZM | EA3CJ | JN01 | ☑️ | ☑️ | | | | | KD2UGC | F6GCP | R-23 | ☑️ | ☑️ | | | | | WA2FZW | DL5AXX | RR73 | ☑️ | | | | | | N1API | HA6FQ | -23 | ☑️ | | | | ☑️ | | N1API | F2VX | 73 | ☑️ | | | | ☑️ | | K1JT | HA5WA | 73 | ☑️ | | | | ☑️ | | CQ | EA2BFM | IN83 | ☑️ | | | | | | K1BZM | DK8NE | -10 | | | | | ☑️ |

At its maximum depth mode (Depth 3), it successfully decodes 16 messages on this sample (including 16/20 rows in the table above), outperforming both PyFT8 (12), FT8_lib (8), and WSJT-x FAST mode (14).

Installation

npm i @e04/ft8ts

Usage

API

import { encodeFT8, decodeFT8, encodeFT4, decodeFT4, HashCallBook } from "@e04/ft8ts";

// Encode a message to audio samples (Float32Array)
const samples = encodeFT8("CQ JK1IFA PM95", {
  sampleRate: 12000,
  baseFrequency: 1000,
});

// Create a HashCallBook to resolve hashed callsigns.
// Reuse the same instance across multiple decode calls so that
// callsigns learned from earlier frames can resolve hashes in later ones.
const book = new HashCallBook();

// Decode audio samples to messages
const decoded = decodeFT8(samples, {
  sampleRate: 12000,
  freqLow: 200,
  freqHigh: 3000,
  depth: 2,
  hashCallBook: book,
});

for (const d of decoded) {
  console.log(`${d.freq} Hz  SNR ${d.snr} dB  ${d.msg}`);
}

FT4

import { encodeFT4, decodeFT4, HashCallBook } from "@e04/ft8ts";

// Encode FT4 message
const samples = encodeFT4("CQ JK1IFA PM95", {
  sampleRate: 12000,
  baseFrequency: 1000,
});

// Decode FT4
const book = new HashCallBook();
const decoded = decodeFT4(samples, {
  sampleRate: 12000,
  freqLow: 200,
  freqHigh: 3000,
  depth: 2,
  hashCallBook: book,
});

Decode Options

| Option | Default | Description | |--------|---------|-------------| | sampleRate | 12000 | Input audio sample rate (Hz) | | freqLow | 200 | Lower frequency bound (Hz) | | freqHigh | 3000 | Upper frequency bound (Hz) | | syncMin | 1.2 | Minimum sync threshold | | depth | 2 | Decoding depth: 1=fast BP only, 2=BP+OSD, 3=deep | | maxCandidates | 300 (FT8) / 100 (FT4) | Maximum candidates to process | | hashCallBook | — | HashCallBook instance for resolving hashed callsigns |

Build

npm run build

License

GPL-3.0

References

  • WSJT-X — Original Fortran implementation (v2.7.0), licensed under GPL v3

Related Projects

  • PyFT8 — Python implementation.
  • ft8_lib — C++ implementation.
  • ft8js - My previous experimental project using WebAssembly (WASM) with ft8_lib.