wsjtx-lib 1.2.5 → 2.0.1
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 +1 -1
- package/dist/src/index.d.ts +15 -163
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +89 -290
- package/dist/src/index.js.map +1 -1
- package/dist/src/types.d.ts +32 -170
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +3 -78
- package/dist/src/types.js.map +1 -1
- package/dist/test/wsjtx.basic.test.d.ts +3 -2
- package/dist/test/wsjtx.basic.test.d.ts.map +1 -1
- package/dist/test/wsjtx.basic.test.js +63 -200
- package/dist/test/wsjtx.basic.test.js.map +1 -1
- package/dist/test/wsjtx.test.d.ts +16 -7
- package/dist/test/wsjtx.test.d.ts.map +1 -1
- package/dist/test/wsjtx.test.js +297 -560
- package/dist/test/wsjtx.test.js.map +1 -1
- package/package.json +1 -1
- package/prebuilds/darwin-arm64/build-info.json +1 -1
- package/prebuilds/darwin-arm64/libfftw3f.3.dylib +0 -0
- package/prebuilds/darwin-arm64/libfftw3f_threads.3.dylib +0 -0
- package/prebuilds/darwin-arm64/libwsjtx_core.dylib +0 -0
- package/prebuilds/darwin-arm64/wsjtx_lib_nodejs.node +0 -0
- package/prebuilds/darwin-x64/build-info.json +1 -1
- package/prebuilds/darwin-x64/libfftw3f.3.dylib +0 -0
- package/prebuilds/darwin-x64/libfftw3f_threads.3.dylib +0 -0
- package/prebuilds/darwin-x64/libwsjtx_core.dylib +0 -0
- package/prebuilds/darwin-x64/wsjtx_lib_nodejs.node +0 -0
- package/prebuilds/linux-arm64/build-info.json +1 -1
- package/prebuilds/linux-arm64/libwsjtx_core.so +0 -0
- package/prebuilds/linux-arm64/wsjtx_lib_nodejs.node +0 -0
- package/prebuilds/linux-x64/build-info.json +1 -1
- package/prebuilds/linux-x64/libwsjtx_core.so +0 -0
- package/prebuilds/linux-x64/wsjtx_lib_nodejs.node +0 -0
- package/prebuilds/win32-x64/build-info.json +1 -1
- package/prebuilds/win32-x64/wsjtx_core.dll +0 -0
- package/prebuilds/win32-x64/wsjtx_lib_nodejs.node +0 -0
package/dist/src/index.js
CHANGED
|
@@ -1,370 +1,169 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* wsjtx-lib — Node.js binding for the WSJT-X 3.0.0 backend.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* import { WSJTXLib, WSJTXMode } from 'wsjtx-lib';
|
|
11
|
-
*
|
|
12
|
-
* const lib = new WSJTXLib();
|
|
13
|
-
*
|
|
14
|
-
* // Decode FT8 audio data
|
|
15
|
-
* const audioData = new Float32Array(48000 * 13); // 13 seconds at 48kHz
|
|
16
|
-
* const result = await lib.decode(WSJTXMode.FT8, audioData, 1500);
|
|
17
|
-
*
|
|
18
|
-
* // Get decoded messages
|
|
19
|
-
* const messages = lib.pullMessages();
|
|
20
|
-
* console.log('Decoded messages:', messages);
|
|
21
|
-
* ```
|
|
4
|
+
* Public surface:
|
|
5
|
+
* - WSJTXLib.encode(mode, message, frequency)
|
|
6
|
+
* - WSJTXLib.decode(mode, audio, options)
|
|
7
|
+
* - WSJTXLib.decodeWSPR(audio, options)
|
|
8
|
+
* - WSJTXLib.convertAudioFormat(audio, target)
|
|
9
|
+
* - capability/sample-rate query helpers
|
|
22
10
|
*/
|
|
23
|
-
import { WSJTXMode, WSJTXError } from './types.js';
|
|
11
|
+
import { WSJTXMode, WSJTXError, } from './types.js';
|
|
24
12
|
import { createRequire } from 'node:module';
|
|
25
13
|
import { fileURLToPath } from 'node:url';
|
|
26
14
|
import path from 'node:path';
|
|
27
|
-
// Create require function for ES modules
|
|
28
15
|
const require = createRequire(import.meta.url);
|
|
29
|
-
|
|
30
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
31
|
-
const __dirname = path.dirname(__filename);
|
|
32
|
-
// Load native module using node-gyp-build (prebuildify layout with build/Release fallback)
|
|
16
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
33
17
|
function loadNativeBinding() {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const binding = load(packageRoot);
|
|
37
|
-
if (binding && binding.WSJTXLib)
|
|
38
|
-
return binding;
|
|
39
|
-
throw new Error('Native module loaded but WSJTXLib export is missing. Please rebuild with "npm run build".');
|
|
18
|
+
const binding = require('node-gyp-build')(path.resolve(__dirname, '..', '..'));
|
|
19
|
+
return binding.WSJTXLib;
|
|
40
20
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
21
|
+
const NativeWSJTXLib = loadNativeBinding();
|
|
22
|
+
const DEFAULT_CONFIG = {
|
|
23
|
+
maxThreads: 4,
|
|
24
|
+
debug: false,
|
|
25
|
+
defaultLowFreq: 200,
|
|
26
|
+
defaultHighFreq: 4000,
|
|
27
|
+
defaultTolerance: 20,
|
|
28
|
+
};
|
|
29
|
+
const FREQ_MIN = 0;
|
|
30
|
+
const FREQ_MAX = 30_000_000;
|
|
31
|
+
const THREADS_MIN = 1;
|
|
32
|
+
const THREADS_MAX = 16;
|
|
33
|
+
const MESSAGE_MAX_LEN = 37;
|
|
51
34
|
export class WSJTXLib {
|
|
52
35
|
native;
|
|
53
36
|
config;
|
|
54
|
-
/**
|
|
55
|
-
* Create a new WSJTX library instance
|
|
56
|
-
*
|
|
57
|
-
* @param config Optional configuration options
|
|
58
|
-
* @throws {WSJTXError} If the native library fails to initialize
|
|
59
|
-
*/
|
|
60
37
|
constructor(config = {}) {
|
|
61
|
-
this.config = {
|
|
62
|
-
|
|
63
|
-
debug: false,
|
|
64
|
-
...config
|
|
65
|
-
};
|
|
66
|
-
try {
|
|
67
|
-
this.native = new NativeWSJTXLib();
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
throw new WSJTXError(`Failed to initialize WSJTX library: ${error instanceof Error ? error.message : String(error)}`, 'INIT_ERROR');
|
|
71
|
-
}
|
|
38
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
39
|
+
this.native = new NativeWSJTXLib();
|
|
72
40
|
}
|
|
73
|
-
|
|
74
|
-
* Decode digital radio signals from audio data
|
|
75
|
-
*
|
|
76
|
-
* This method processes audio samples and attempts to decode digital
|
|
77
|
-
* messages using the specified protocol mode. The operation is performed
|
|
78
|
-
* asynchronously to avoid blocking the Node.js event loop.
|
|
79
|
-
*
|
|
80
|
-
* @param mode The digital mode to use for decoding
|
|
81
|
-
* @param audioData Audio samples (Float32Array or Int16Array)
|
|
82
|
-
* @param frequency Center frequency in Hz
|
|
83
|
-
* @param threads Number of threads to use (1-16, default: 4)
|
|
84
|
-
* @returns Promise that resolves when decoding is complete
|
|
85
|
-
*
|
|
86
|
-
* @throws {WSJTXError} If parameters are invalid or decoding fails
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* ```typescript
|
|
90
|
-
* const audioData = new Float32Array(48000 * 13); // 13 seconds
|
|
91
|
-
* await lib.decode(WSJTXMode.FT8, audioData, 1500);
|
|
92
|
-
* const messages = lib.pullMessages();
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
async decode(mode, audioData, frequency, threads = this.config.maxThreads || 4) {
|
|
41
|
+
async decode(mode, audioData, options) {
|
|
96
42
|
this.validateMode(mode);
|
|
97
|
-
this.
|
|
98
|
-
this.
|
|
99
|
-
this.validateAudioData(audioData);
|
|
43
|
+
this.validateAudio(audioData);
|
|
44
|
+
this.validateFrequency(options.frequency);
|
|
100
45
|
if (!this.isDecodingSupported(mode)) {
|
|
101
|
-
throw new WSJTXError(
|
|
102
|
-
}
|
|
46
|
+
throw new WSJTXError('Decoding not supported for this mode', 'UNSUPPORTED');
|
|
47
|
+
}
|
|
48
|
+
const opts = {
|
|
49
|
+
frequency: options.frequency,
|
|
50
|
+
threads: options.threads ?? this.config.maxThreads,
|
|
51
|
+
lowFreq: options.lowFreq ?? this.config.defaultLowFreq,
|
|
52
|
+
highFreq: options.highFreq ?? this.config.defaultHighFreq,
|
|
53
|
+
tolerance: options.tolerance ?? this.config.defaultTolerance,
|
|
54
|
+
dxCall: options.dxCall ?? '',
|
|
55
|
+
dxGrid: options.dxGrid ?? '',
|
|
56
|
+
};
|
|
103
57
|
return new Promise((resolve, reject) => {
|
|
104
|
-
|
|
105
|
-
if (
|
|
106
|
-
reject(new WSJTXError(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
resolve({ success: result });
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
try {
|
|
114
|
-
this.native.decode(mode, audioData, frequency, threads, callback);
|
|
115
|
-
}
|
|
116
|
-
catch (error) {
|
|
117
|
-
reject(new WSJTXError(`Decode operation failed: ${error instanceof Error ? error.message : String(error)}`, 'DECODE_ERROR'));
|
|
118
|
-
}
|
|
58
|
+
this.native.decode(mode, audioData, opts, (err, result) => {
|
|
59
|
+
if (err)
|
|
60
|
+
reject(new WSJTXError(err.message, 'DECODE_ERROR'));
|
|
61
|
+
else
|
|
62
|
+
resolve(result);
|
|
63
|
+
});
|
|
119
64
|
});
|
|
120
65
|
}
|
|
121
|
-
|
|
122
|
-
* Encode a message into audio waveform for transmission
|
|
123
|
-
*
|
|
124
|
-
* Generates the audio waveform that represents the specified message
|
|
125
|
-
* using the given digital mode. The resulting audio can be fed to
|
|
126
|
-
* a radio transmitter or audio interface.
|
|
127
|
-
*
|
|
128
|
-
* @param mode The digital mode to use for encoding
|
|
129
|
-
* @param message The message text to encode (mode-specific format)
|
|
130
|
-
* @param frequency Center frequency in Hz
|
|
131
|
-
* @param threads Number of threads to use (1-16, default: 4)
|
|
132
|
-
* @returns Promise that resolves with encoded audio data and actual message sent
|
|
133
|
-
*
|
|
134
|
-
* @throws {WSJTXError} If parameters are invalid or encoding fails
|
|
135
|
-
*
|
|
136
|
-
* @example
|
|
137
|
-
* ```typescript
|
|
138
|
-
* const result = await lib.encode(WSJTXMode.FT8, 'CQ DX K1ABC FN20', 1500);
|
|
139
|
-
* console.log('Generated audio samples:', result.audioData.length);
|
|
140
|
-
* console.log('Actual message sent:', result.messageSent);
|
|
141
|
-
* ```
|
|
142
|
-
*/
|
|
143
|
-
async encode(mode, message, frequency, threads = this.config.maxThreads || 4) {
|
|
66
|
+
async encode(mode, message, frequency, threads = this.config.maxThreads) {
|
|
144
67
|
this.validateMode(mode);
|
|
145
68
|
this.validateMessage(message);
|
|
146
69
|
this.validateFrequency(frequency);
|
|
147
70
|
this.validateThreads(threads);
|
|
148
71
|
if (!this.isEncodingSupported(mode)) {
|
|
149
|
-
throw new WSJTXError(
|
|
72
|
+
throw new WSJTXError('Encoding not supported for this mode', 'UNSUPPORTED');
|
|
150
73
|
}
|
|
151
74
|
return new Promise((resolve, reject) => {
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
reject(new WSJTXError(
|
|
155
|
-
|
|
156
|
-
else {
|
|
75
|
+
this.native.encode(mode, message, frequency, threads, (err, result) => {
|
|
76
|
+
if (err)
|
|
77
|
+
reject(new WSJTXError(err.message, 'ENCODE_ERROR'));
|
|
78
|
+
else
|
|
157
79
|
resolve(result);
|
|
158
|
-
|
|
159
|
-
};
|
|
160
|
-
try {
|
|
161
|
-
this.native.encode(mode, message, frequency, threads, callback);
|
|
162
|
-
}
|
|
163
|
-
catch (error) {
|
|
164
|
-
reject(new WSJTXError(`Encode operation failed: ${error instanceof Error ? error.message : String(error)}`, 'ENCODE_ERROR'));
|
|
165
|
-
}
|
|
80
|
+
});
|
|
166
81
|
});
|
|
167
82
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
*
|
|
175
|
-
* @param iqData Interleaved I,Q samples as Float32Array
|
|
176
|
-
* @param options Decoder options (frequency, callsign, etc.)
|
|
177
|
-
* @returns Promise that resolves with array of decoded WSPR results
|
|
178
|
-
*
|
|
179
|
-
* @throws {WSJTXError} If parameters are invalid or decoding fails
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* ```typescript
|
|
183
|
-
* const iqData = new Float32Array(2 * 12000 * 111); // 2 minutes of IQ data
|
|
184
|
-
* const options = {
|
|
185
|
-
* dialFrequency: 14095600, // 20m WSPR frequency
|
|
186
|
-
* callsign: 'K1ABC',
|
|
187
|
-
* locator: 'FN20'
|
|
188
|
-
* };
|
|
189
|
-
* const results = await lib.decodeWSPR(iqData, options);
|
|
190
|
-
* ```
|
|
191
|
-
*/
|
|
192
|
-
async decodeWSPR(iqData, options = {}) {
|
|
193
|
-
this.validateIQData(iqData);
|
|
194
|
-
const defaultOptions = {
|
|
195
|
-
dialFrequency: 14095600, // 20m WSPR frequency
|
|
83
|
+
async decodeWSPR(audioData, options = {}) {
|
|
84
|
+
if (!(audioData instanceof Int16Array) || audioData.length === 0) {
|
|
85
|
+
throw new WSJTXError('audioData must be a non-empty Int16Array', 'INVALID');
|
|
86
|
+
}
|
|
87
|
+
const opts = {
|
|
88
|
+
dialFrequency: 14_095_600,
|
|
196
89
|
callsign: '',
|
|
197
90
|
locator: '',
|
|
198
91
|
quickMode: false,
|
|
199
92
|
useHashTable: true,
|
|
200
93
|
passes: 2,
|
|
201
94
|
subtraction: true,
|
|
202
|
-
...options
|
|
95
|
+
...options,
|
|
203
96
|
};
|
|
204
97
|
return new Promise((resolve, reject) => {
|
|
205
|
-
|
|
206
|
-
if (
|
|
207
|
-
reject(new WSJTXError(
|
|
208
|
-
|
|
209
|
-
else {
|
|
98
|
+
this.native.decodeWSPR(audioData, opts, (err, results) => {
|
|
99
|
+
if (err)
|
|
100
|
+
reject(new WSJTXError(err.message, 'WSPR_ERROR'));
|
|
101
|
+
else
|
|
210
102
|
resolve(results);
|
|
211
|
-
|
|
212
|
-
};
|
|
213
|
-
try {
|
|
214
|
-
this.native.decodeWSPR(iqData, defaultOptions, callback);
|
|
215
|
-
}
|
|
216
|
-
catch (error) {
|
|
217
|
-
reject(new WSJTXError(`WSPR decode failed: ${error instanceof Error ? error.message : String(error)}`, 'WSPR_DECODE_ERROR'));
|
|
218
|
-
}
|
|
103
|
+
});
|
|
219
104
|
});
|
|
220
105
|
}
|
|
221
|
-
/**
|
|
222
|
-
* Retrieve decoded messages from the internal queue
|
|
223
|
-
*
|
|
224
|
-
* Messages are added to an internal queue as they are decoded.
|
|
225
|
-
* This method retrieves and removes all pending messages from the queue.
|
|
226
|
-
*
|
|
227
|
-
* @returns Array of decoded messages
|
|
228
|
-
*
|
|
229
|
-
* @example
|
|
230
|
-
* ```typescript
|
|
231
|
-
* const messages = lib.pullMessages();
|
|
232
|
-
* messages.forEach(msg => {
|
|
233
|
-
* console.log(`${msg.text} (SNR: ${msg.snr} dB, ΔT: ${msg.deltaTime}s)`);
|
|
234
|
-
* });
|
|
235
|
-
* ```
|
|
236
|
-
*/
|
|
237
106
|
pullMessages() {
|
|
238
|
-
|
|
239
|
-
return this.native.pullMessages();
|
|
240
|
-
}
|
|
241
|
-
catch (error) {
|
|
242
|
-
throw new WSJTXError(`Failed to pull messages: ${error instanceof Error ? error.message : String(error)}`, 'PULL_ERROR');
|
|
243
|
-
}
|
|
107
|
+
return this.native.pullMessages();
|
|
244
108
|
}
|
|
245
|
-
/**
|
|
246
|
-
* Check if encoding is supported for a specific mode
|
|
247
|
-
*
|
|
248
|
-
* @param mode The mode to check
|
|
249
|
-
* @returns True if encoding is supported
|
|
250
|
-
*/
|
|
251
109
|
isEncodingSupported(mode) {
|
|
252
110
|
return this.native.isEncodingSupported(mode);
|
|
253
111
|
}
|
|
254
|
-
/**
|
|
255
|
-
* Check if decoding is supported for a specific mode
|
|
256
|
-
*
|
|
257
|
-
* @param mode The mode to check
|
|
258
|
-
* @returns True if decoding is supported
|
|
259
|
-
*/
|
|
260
112
|
isDecodingSupported(mode) {
|
|
261
113
|
return this.native.isDecodingSupported(mode);
|
|
262
114
|
}
|
|
263
|
-
/**
|
|
264
|
-
* Get the required sample rate for a specific mode
|
|
265
|
-
*
|
|
266
|
-
* @param mode The mode to query
|
|
267
|
-
* @returns Sample rate in Hz
|
|
268
|
-
*/
|
|
269
115
|
getSampleRate(mode) {
|
|
270
116
|
return this.native.getSampleRate(mode);
|
|
271
117
|
}
|
|
272
|
-
/**
|
|
273
|
-
* Get the transmission duration for a specific mode
|
|
274
|
-
*
|
|
275
|
-
* @param mode The mode to query
|
|
276
|
-
* @returns Duration in seconds
|
|
277
|
-
*/
|
|
278
118
|
getTransmissionDuration(mode) {
|
|
279
119
|
return this.native.getTransmissionDuration(mode);
|
|
280
120
|
}
|
|
281
|
-
/**
|
|
282
|
-
* Get capabilities for all supported modes
|
|
283
|
-
*
|
|
284
|
-
* @returns Array of mode capability information
|
|
285
|
-
*/
|
|
286
121
|
getAllModeCapabilities() {
|
|
287
|
-
const
|
|
288
|
-
return
|
|
289
|
-
mode,
|
|
122
|
+
const numericModes = Object.values(WSJTXMode).filter((v) => typeof v === 'number');
|
|
123
|
+
return numericModes.map((mode) => ({
|
|
124
|
+
mode: mode,
|
|
290
125
|
encodingSupported: this.isEncodingSupported(mode),
|
|
291
126
|
decodingSupported: this.isDecodingSupported(mode),
|
|
292
127
|
sampleRate: this.getSampleRate(mode),
|
|
293
|
-
duration: this.getTransmissionDuration(mode)
|
|
128
|
+
duration: this.getTransmissionDuration(mode),
|
|
294
129
|
}));
|
|
295
130
|
}
|
|
296
|
-
/**
|
|
297
|
-
* Convert audio format between Float32Array and Int16Array (async)
|
|
298
|
-
*
|
|
299
|
-
* Uses the native addon with Node's libuv 线程池执行,不阻塞主线程。
|
|
300
|
-
*
|
|
301
|
-
* @param audioData 输入音频数据
|
|
302
|
-
* @param targetFormat 目标格式 ('float32' | 'int16')
|
|
303
|
-
* @returns Promise 解析为转换后的数据
|
|
304
|
-
*/
|
|
305
131
|
async convertAudioFormat(audioData, targetFormat) {
|
|
306
|
-
if (targetFormat !== 'float32' && targetFormat !== 'int16') {
|
|
307
|
-
throw new Error(`Invalid target format: ${targetFormat}. Must be 'float32' or 'int16'`);
|
|
308
|
-
}
|
|
309
|
-
// 快速路径:已经是目标格式
|
|
310
|
-
if ((targetFormat === 'float32' && audioData instanceof Float32Array) ||
|
|
311
|
-
(targetFormat === 'int16' && audioData instanceof Int16Array)) {
|
|
312
|
-
return audioData;
|
|
313
|
-
}
|
|
314
132
|
return new Promise((resolve, reject) => {
|
|
315
|
-
|
|
316
|
-
if (
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
};
|
|
322
|
-
try {
|
|
323
|
-
this.native.convertAudioFormat(audioData, targetFormat, callback);
|
|
324
|
-
}
|
|
325
|
-
catch (error) {
|
|
326
|
-
reject(new WSJTXError(`Audio conversion failed: ${error instanceof Error ? error.message : String(error)}`, 'AUDIO_CONVERT_ERROR'));
|
|
327
|
-
}
|
|
133
|
+
this.native.convertAudioFormat(audioData, targetFormat, (err, result) => {
|
|
134
|
+
if (err)
|
|
135
|
+
reject(err);
|
|
136
|
+
else
|
|
137
|
+
resolve(result);
|
|
138
|
+
});
|
|
328
139
|
});
|
|
329
140
|
}
|
|
330
|
-
// Validation methods
|
|
331
141
|
validateMode(mode) {
|
|
332
142
|
if (!Object.values(WSJTXMode).includes(mode)) {
|
|
333
|
-
throw new WSJTXError(
|
|
143
|
+
throw new WSJTXError('Invalid mode', 'INVALID');
|
|
334
144
|
}
|
|
335
145
|
}
|
|
336
|
-
validateFrequency(
|
|
337
|
-
if (!Number.isInteger(
|
|
338
|
-
throw new WSJTXError(
|
|
146
|
+
validateFrequency(freq) {
|
|
147
|
+
if (!Number.isInteger(freq) || freq < FREQ_MIN || freq > FREQ_MAX) {
|
|
148
|
+
throw new WSJTXError('Invalid frequency', 'INVALID');
|
|
339
149
|
}
|
|
340
150
|
}
|
|
341
151
|
validateThreads(threads) {
|
|
342
|
-
if (!Number.isInteger(threads) || threads <
|
|
343
|
-
throw new WSJTXError(`
|
|
152
|
+
if (!Number.isInteger(threads) || threads < THREADS_MIN || threads > THREADS_MAX) {
|
|
153
|
+
throw new WSJTXError(`Threads must be ${THREADS_MIN}..${THREADS_MAX}`, 'INVALID');
|
|
344
154
|
}
|
|
345
155
|
}
|
|
346
156
|
validateMessage(message) {
|
|
347
|
-
if (typeof message !== 'string' || message.length === 0 || message.length >
|
|
348
|
-
throw new WSJTXError(`
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
validateAudioData(audioData) {
|
|
352
|
-
if (!(audioData instanceof Float32Array) && !(audioData instanceof Int16Array)) {
|
|
353
|
-
throw new WSJTXError('Invalid audio data: must be Float32Array or Int16Array', 'INVALID_AUDIO_DATA');
|
|
354
|
-
}
|
|
355
|
-
if (audioData.length === 0) {
|
|
356
|
-
throw new WSJTXError('Audio data cannot be empty', 'INVALID_AUDIO_DATA');
|
|
157
|
+
if (typeof message !== 'string' || message.length === 0 || message.length > MESSAGE_MAX_LEN) {
|
|
158
|
+
throw new WSJTXError(`Message must be 1..${MESSAGE_MAX_LEN} characters`, 'INVALID');
|
|
357
159
|
}
|
|
358
160
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (iqData.length === 0 || iqData.length % 2 !== 0) {
|
|
364
|
-
throw new WSJTXError('IQ data length must be even (interleaved I,Q samples)', 'INVALID_IQ_DATA');
|
|
161
|
+
validateAudio(audio) {
|
|
162
|
+
const isTyped = audio instanceof Float32Array || audio instanceof Int16Array;
|
|
163
|
+
if (!isTyped || audio.length === 0) {
|
|
164
|
+
throw new WSJTXError('audioData must be a non-empty Float32Array or Int16Array', 'INVALID');
|
|
365
165
|
}
|
|
366
166
|
}
|
|
367
167
|
}
|
|
368
|
-
|
|
369
|
-
export { WSJTXMode, WSJTXError, };
|
|
168
|
+
export { WSJTXMode, WSJTXError };
|
|
370
169
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|