@e04/ft8ts 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,13 +2,13 @@
2
2
 
3
3
  [![Tests](https://github.com/e04/ft8ts/actions/workflows/test.yml/badge.svg)](https://github.com/e04/ft8ts/actions/workflows/test.yml)
4
4
 
5
- FT8 encoder and decoder in TypeScript. A port of the Fortran implementation from [WSJT-X](https://wsjt.sourceforge.io/wsjtx.html) v2.7.0.
5
+ FT8/FT4 encoder and decoder in pure TypeScript. A port of the Fortran implementation from [WSJT-X](https://wsjt.sourceforge.io/wsjtx.html) v2.7.0.
6
6
 
7
7
  ## Overview
8
8
 
9
- FT8 is a digital amateur radio mode designed for weak-signal communication, developed by Joe Taylor (K1JT) and Steve Franke (K9AN).
9
+ FT8/FT4 are digital amateur radio modes designed for weak-signal communication, developed by Joe Taylor (K1JT) and Steve Franke (K9AN).
10
10
 
11
- This library provides pure TypeScript implementations of both encoding and decoding, suitable for use in Node.js or the browser.
11
+ This library provides pure TypeScript implementations of both encoding and decoding for FT8/FT4, suitable for use in Node.js or the browser.
12
12
 
13
13
  ## Demo
14
14
 
@@ -19,8 +19,8 @@ https://e04.github.io/ft8ts/example/browser/index.html
19
19
  ### CLI
20
20
 
21
21
  ```bash
22
- # Decode WAV file
23
- npx @e04/ft8ts decode foo.wav [--low 200] [--high 3000] [--depth 2]
22
+ # Decode WAV file (FT8 or FT4)
23
+ npx @e04/ft8ts decode foo.wav [--mode ft8|ft4] [--low 200] [--high 3000] [--depth 2]
24
24
 
25
25
  # Encode message to WAV file
26
26
  npx @e04/ft8ts encode "CQ JK1IFA PM95" [--out output.wav] [--df 1000]
@@ -30,29 +30,30 @@ npx @e04/ft8ts encode "CQ JK1IFA PM95" [--out output.wav] [--df 1000]
30
30
 
31
31
  The benchmark below was compiled with reference to [Comparing PyFT8 with WSJT-x and FT8_lib](https://www.reddit.com/r/amateurradio/comments/1qt27ss/comparing_pyft8_with_wsjtx_and_ft8_lib/).
32
32
 
33
- | Call a | Call b | Message | WSJT-x(default) | WSJT-x (fast) | [PyFT8](https://github.com/G1OJS/PyFT8) | [ft8_lib](https://github.com/kgoba/ft8_lib) | ft8ts (depth=1) | ft8ts (depth=2) | ft8ts (depth=3) |
34
- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
35
- | W1FC | F5BZB | -8 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
36
- | WM3PEN | EA6VQ | -9 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
37
- | CQ | F5RXL | IN94 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
38
- | N1JFU | EA6EE | R-07 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
39
- | A92EE | F5PSR | -14 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
40
- | K1BZM | EA3GP | -9 | ☑️ | ☑️ | ☑️ | | ☑️ | ☑️ | ☑️ |
41
- | W0RSJ | EA3BMU | RR73 | ☑️ | ☑️ | ☑️ | | ☑️ | ☑️ | ☑️ |
42
- | K1JT | HA0DU | KN07 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
43
- | W1DIG | SV9CVY | -14 | ☑️ | ☑️ | ☑️ | | ☑️ | ☑️ | ☑️ |
44
- | K1JT | EA3AGB | -15 | ☑️ | ☑️ | ☑️ | | ☑️ | ☑️ | ☑️ |
45
- | XE2X | HA2NP | RR73 | ☑️ | ☑️ | ☑️ | ☑️ | | | ☑️ |
46
- | N1PJT | HB9CQK | -10 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
47
- | K1BZM | EA3CJ | JN01 | ☑️ | ☑️ | | | | | |
48
- | KD2UGC | F6GCP | R-23 | ☑️ | ☑️ | | | | | |
49
- | WA2FZW | DL5AXX | RR73 | ☑️ | | | | | | |
50
- | N1API | HA6FQ | -23 | ☑️ | | | | | ☑️ | ☑️ |
51
- | N1API | F2VX | 73 | ☑️ | | | | | | |
52
- | K1JT | HA5WA | 73 | ☑️ | | | | | ☑️ | ☑️ |
53
- | CQ | EA2BFM | IN83 | ☑️ | | | | | | |
54
-
55
- At its maximum depth mode (Depth 3), it successfully decodes 14 messages, outperforming both `PyFT8` (12) and `FT8_lib` (8), and matching the total message count of `WSJT-x FAST mode`.
33
+ | Call a | Call b | Message | WSJT-x(default) | WSJT-x (fast) | [PyFT8](https://github.com/G1OJS/PyFT8) | [ft8_lib](https://github.com/kgoba/ft8_lib) | ft8ts (depth=3) |
34
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
35
+ | W1FC | F5BZB | -8 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
36
+ | WM3PEN | EA6VQ | -9 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
37
+ | CQ | F5RXL | IN94 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
38
+ | N1JFU | EA6EE | R-07 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
39
+ | A92EE | F5PSR | -14 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
40
+ | K1BZM | EA3GP | -9 | ☑️ | ☑️ | ☑️ | | ☑️ |
41
+ | W0RSJ | EA3BMU | RR73 | ☑️ | ☑️ | ☑️ | | ☑️ |
42
+ | K1JT | HA0DU | KN07 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
43
+ | W1DIG | SV9CVY | -14 | ☑️ | ☑️ | ☑️ | | ☑️ |
44
+ | K1JT | EA3AGB | -15 | ☑️ | ☑️ | ☑️ | | ☑️ |
45
+ | XE2X | HA2NP | RR73 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
46
+ | N1PJT | HB9CQK | -10 | ☑️ | ☑️ | ☑️ | ☑️ | ☑️ |
47
+ | K1BZM | EA3CJ | JN01 | ☑️ | ☑️ | | | |
48
+ | KD2UGC | F6GCP | R-23 | ☑️ | ☑️ | | | |
49
+ | WA2FZW | DL5AXX | RR73 | ☑️ | | | | |
50
+ | N1API | HA6FQ | -23 | ☑️ | | | | ☑️ |
51
+ | N1API | F2VX | 73 | ☑️ | | | | ☑️ |
52
+ | K1JT | HA5WA | 73 | ☑️ | | | | ☑️ |
53
+ | CQ | EA2BFM | IN83 | ☑️ | | | | |
54
+ | K1BZM | DK8NE | -10 | | | | | ☑️ |
55
+
56
+ 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).
56
57
 
57
58
  ## Installation
58
59
 
@@ -63,7 +64,7 @@ At its maximum depth mode (Depth 3), it successfully decodes 14 messages, outper
63
64
  ### API
64
65
 
65
66
  ```typescript
66
- import { encodeFT8, decodeFT8, HashCallBook } from "@e04/ft8ts";
67
+ import { encodeFT8, decodeFT8, encodeFT4, decodeFT4, HashCallBook } from "@e04/ft8ts";
67
68
 
68
69
  // Encode a message to audio samples (Float32Array)
69
70
  const samples = encodeFT8("CQ JK1IFA PM95", {
@@ -90,6 +91,28 @@ for (const d of decoded) {
90
91
  }
91
92
  ```
92
93
 
94
+ ### FT4
95
+
96
+ ```typescript
97
+ import { encodeFT4, decodeFT4, HashCallBook } from "@e04/ft8ts";
98
+
99
+ // Encode FT4 message
100
+ const samples = encodeFT4("CQ JK1IFA PM95", {
101
+ sampleRate: 12000,
102
+ baseFrequency: 1000,
103
+ });
104
+
105
+ // Decode FT4
106
+ const book = new HashCallBook();
107
+ const decoded = decodeFT4(samples, {
108
+ sampleRate: 12000,
109
+ freqLow: 200,
110
+ freqHigh: 3000,
111
+ depth: 2,
112
+ hashCallBook: book,
113
+ });
114
+ ```
115
+
93
116
  ### Decode Options
94
117
 
95
118
  | Option | Default | Description |
@@ -99,13 +122,9 @@ for (const d of decoded) {
99
122
  | `freqHigh` | 3000 | Upper frequency bound (Hz) |
100
123
  | `syncMin` | 1.2 | Minimum sync threshold |
101
124
  | `depth` | 2 | Decoding depth: 1=fast BP only, 2=BP+OSD, 3=deep |
102
- | `maxCandidates` | 300 | Maximum candidates to process |
125
+ | `maxCandidates` | 300 (FT8) / 100 (FT4) | Maximum candidates to process |
103
126
  | `hashCallBook` | — | `HashCallBook` instance for resolving hashed callsigns |
104
127
 
105
- ## ToDo
106
-
107
- - [ ] FT4 Support
108
-
109
128
  ## Build
110
129
 
111
130
  ```bash