BROWSER / ACOUSTIC MODEM

Airtext

4-FSK · 17.5–19.3 kHz · LOCAL ONLY

Enable audio on both devices, then send a short message. Keep their speakers and microphones close.

Transmit

Audio off

Automatic · starts Fast (30 ms), retries at 60 ms after a negative ACK.

Up to 3 attempts

Receive

Audio off
Incoming text · live
Waiting for a transmission…
0 bytes received
Symbols: —
Signal diagnostics appear after enabling audio.

Air monitor

Microphone inactive
16 kHz17.5 · 18.1 · 18.7 · 19.3 kHz21 kHz

Protocol log

How to test & protocol reference

On iPhone, open the page directly in Safari and disconnect Bluetooth audio for testing. Microphone access can change iOS audio routing and the volume indicator. The app requests a playback-and-recording session and uses media-stream output on iPhone/iPad to work around Web Audio routing issues. The browser and iOS still choose the physical output; a web page cannot guarantee the loudspeaker route.

Open this same file in two tabs or on two devices and enable audio in both. Use speakers, not headphones. Start with a few characters and moderate volume; some people can hear these frequencies. Keep both pages visible when possible. Send from one page at a time. Two tabs on one computer are a useful first test, but microphone sharing and background throttling depend on the browser.

Everything runs locally. No network, storage, libraries, or server is used. Microphone access requires permission and a supported secure context (local files normally qualify; use HTTPS for static hosting). Speaker and microphone response above 17 kHz varies widely; delivery is not guaranteed on every device.

Normal uses 60 ms slots (42 ms tone, 3 ms ramps, 18 ms guard). Fast uses 30 ms slots (21 ms tone, 1.5 ms ramps, 9 ms guard), doubling the raw byte rate from 4.17 to 8.33 bytes/second. The receiver detects either speed from the preamble and replies at the detected speed. Every new message starts Fast. A negative ACK switches its remaining attempts to Normal; no ACK still stops without retry. Output is fixed at the former slider maximum (gain 0.5). Symbols 0–3 map to 17,500 / 18,100 / 18,700 / 19,300 Hz. Bytes are four symbols, most significant pair first. Sync is 3 0 3 0 2 1 2 3. Frame: sync, type, ID, payload length, header XOR, payload, payload XOR. DATA type = D2; ACK type = A1. Each packet carries up to 128 bytes, including multipart metadata. Messages have no application-imposed total-length cap (available browser memory and transmission time still apply). DATA begins with START/END flags, an 8-byte random message ID and a base-128 part index, followed by UTF-8 text. Reload both pages for this protocol version. ACK payload contains success (1/0) and the receiver’s computed XOR. The header XOR protects type, ID, and length; ACK payload also has its own XOR.

AudioWorklet performs windowed Goertzel detection off the main thread, with ScriptProcessor fallback for browsers that reject local Blob worklets. The receiver correlates the preamble and samples the middle of fixed symbol slots; it does not need silence between tones. Missing or ambiguous slots become erasures. Invalid headers are discarded. A valid header followed by incomplete or damaged data produces a negative ACK. Retries keep the same ID; valid duplicate packets are acknowledged again.

The sender waits 3 seconds after transmission. A matching negative ACK or differing parity triggers a retry at 60 ms (3 total attempts). A successful matching ACK marks delivery. A detected reply with an unreadable header or a damaged matching ACK retries the same complete packet, including its preamble. True silence advances to the next part without retry; any unacknowledged part makes the final result “No ACK — delivery unconfirmed”. After three negative ACKs for a part, transmission pauses with a Resume button. Resume retries only that part, keeping the same message ID, packet ID and byte offset; earlier parts remain intact. Stop/Enable audio also preserves this checkpoint. Editing the message starts a new transfer. Checkpoints are kept in memory and are lost if the page is reloaded. Verified text is appended once; retries do not duplicate it. UTF-8 characters may cross part boundaries. Missing parts are visibly marked, and END is required for completion. XOR detects many errors but is not a CRC or security mechanism. Half-duplex suppresses local decoding during transmission and briefly afterward; it cannot prevent simultaneous senders from colliding.