The Ribbit WebAssembly API provides a simple, promise-based interface for encoding and decoding digital radio messages. This replaces the complex manual memory management with an easy-to-use API that handles everything automatically.
import { RibbitWASM } from './scripts/ribbit-wasm.js';
// One-line initialization
const ribbit = await RibbitWASM.load();
// Encode a message
const audioBuffer = await ribbit.encodeMessage("Hello World!");
// Decode audio (if you have received audio)
const decoded = await ribbit.decodeAudio(audioBuffer);
if (decoded) {
console.log("Received:", decoded.text);
}
RibbitWASM.load()Loads and initializes the WebAssembly module.
Promise<RibbitWASM> - Ready-to-use instanceencodeMessage(text, options)Encodes a text message into audio.
text (string): Message to encodeoptions (EncodeOptions, optional): Encoding optionsPromise<Float32Array> - Audio bufferdecodeAudio(audioBuffer)Decodes audio data into a message.
audioBuffer (Float32Array |
ArrayBuffer): Audio data to decode |
Promise<DecodeResult|null> - Decoded message or nulldecodeStream(stream)Starts real-time decoding from an audio stream.
stream (MediaStream): Audio stream to decodePromise<EventTarget> - Event emitter with ‘message’ and ‘error’ eventsgetMemoryUsage()Gets current memory usage statistics.
MemoryUsage objectdestroy()Cleans up resources and frees memory.
interface EncodeOptions {
callsign?: string; // Default: "NOCALL"
gridsquare?: string; // Default: "AA00aa"
name?: string; // Default: ""
emergency?: boolean; // Default: false
ntp?: boolean; // Default: false
gps?: boolean; // Default: false
messageType?: number; // Default: 1 (chat)
}
interface DecodeResult {
text: string; // Decoded message text
callsign: string; // Sender's callsign
gridsquare: string; // Sender's gridsquare
name: string; // Sender's name
timestamp: Date; // Message timestamp
emergency: boolean; // Emergency flag
ntp: boolean; // NTP flag
gps: boolean; // GPS flag
confidence: number; // Decoding confidence (0-1)
}
const ribbit = await RibbitWASM.load();
const audio = await ribbit.encodeMessage("CQ CQ DE TESTCALL");
console.log("Encoded", audio.length, "audio samples");
const audio = await ribbit.encodeMessage("Weather report: 72°F, clear skies", {
callsign: "WX0ABC",
gridsquare: "DM43jk",
name: "Weather Station",
emergency: false,
messageType: 2 // Might be weather type
});
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const decoder = await ribbit.decodeStream(stream);
decoder.addEventListener('message', (event) => {
const msg = event.detail;
console.log(`${msg.callsign}: ${msg.text}`);
});
decoder.addEventListener('error', (event) => {
console.error('Decoding error:', event.detail);
});
// Stop after 5 minutes
setTimeout(() => decoder.stop(), 5 * 60 * 1000);
const ribbit = await RibbitWASM.load();
// Check memory usage
console.log(ribbit.getMemoryUsage());
// ... use the API ...
// Clean up when done
ribbit.destroy();
The API throws descriptive errors for common issues:
try {
const ribbit = await RibbitWASM.load();
await ribbit.encodeMessage(""); // Empty message
} catch (error) {
console.log(error.message); // "Message text must be a string"
}
ribbit-wasm.js - Main API implementationribbit-wasm.d.ts - TypeScript definitionstest_wasm_api.html - API test pageexample_usage.js - Usage examples// Manual WASM loading
const module = await Module();
module._createEncoder();
module._initEncoder(messagePtr, messageLength);
// Manual memory management required
const ptr = module._malloc(size);
module._free(ptr);
// One-line loading
const ribbit = await RibbitWASM.load();
// Automatic memory management
const audio = await ribbit.encodeMessage("Hello!");
Run the test suite:
# Open in browser
open test_wasm_api.html
Or run individual examples:
import './example_usage.js';
// Then call RibbitExamples.basicExample()