ggwave: data-over-sound for air-gapped devices, and what it actually costs you
Tiny data-over-sound library
At a glance
- What is it?
- ggwave is an MIT-licensed C++ library that moves small payloads between devices over an audio link at 8 to 16 bytes per second. It is a good fit for pairing, broadcast and microcontroller links, and a poor fit for anything that looks like throughput.
- Who is it for?
- Adopt ggwave when the link itself is the point: pairing two devices that share no network, broadcasting a short string to every microphone in a room, or moving a few bytes onto an Arduino, ESP32 or RP2040 that has no radio. Do not adopt it as a transport for files, telemetry streams or anything measured in kilobytes per second; the documented rate is 8 to 16 bytes/sec depending on protocol parameters, and that ceiling is the design, not a tuning problem.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 167 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem ggwave solves, and the people it is aimed at
Most short-range data transfer assumes a network exists. Bluetooth pairing, Wi-Fi Direct and NFC all require a radio, a driver and, usually, a handshake that both sides agree on. ggwave removes that assumption. The README describes it as a library that lets you communicate small amounts of data between air-gapped devices using sound, and it implements a simple FSK-based transmission protocol. The library generates and analyzes raw waveforms only. It does not open an audio device. The README is explicit that you provide callbacks for queuing and dequeuing audio samples, so PulseAudio, ALSA or any other backend is your decision.
The audience follows from that constraint. The README lists serverless one-to-many broadcast, Internet of Things, audio QR codes, device pairing and contact exchange, and authorization. The examples directory backs this up with concrete targets: esp32-rx, arduino-rx, rp2040-rx and arduino-tx for microcontrollers, r2t2 for transmitting through a PC speaker, and buttons for recording and sending commands. If you are wiring a sensor to a phone with no radio in between, or you want one device to address every listener in a room at once, this is the shape of tool you are looking for. If you want a general-purpose link, it is not.
How the FSK modulation and marker-based demodulation actually work
The transmit side is a multi-frequency Frequency-Shift Keying scheme. The README states that data is split into 4-bit chunks, and that at each moment of time 3 bytes are transmitted using 6 tones, one tone per chunk. Those six tones live in a 4.5 kHz range divided into 96 equally spaced frequencies. The spacing is fixed: dF = 46.875 Hz for all protocols. What changes between profiles is the base frequency. Non-ultrasonic protocols start at F0 = 1875.000 Hz; ultrasonic protocols start at F0 = 15000.000 Hz. That single constant is what separates an audible transmission from one most adults will not hear.
Before transmission, the payload goes through Reed-Solomon error codes, and the README notes that the number of ECC bytes is determined by the length of the original data. So the bytes on the wire are not the bytes you passed in. That matters when you estimate how long a message will take: the encoded stream is longer than the input, and the overhead grows as a proportion on short payloads.
The receive side is where the framing lives. The README says the beginning and ending of a transmission are marked with special sound markers, that the receiver listens for these markers and records the in-between sound data, and that the recording is then Fourier transformed to obtain a frequency spectrum. Detected frequencies are decoded back to binary. This is a record-then-analyze pipeline, not a streaming one. The receiver has to hear a complete marked segment before it can decode anything, which is the reason very short messages behave differently from very long ones in a noisy room.
Installing ggwave and sending your first message
The README does not give a CMake build walkthrough, but the repository layout does: there is a top-level CMakeLists.txt, a cmake/ directory, and an include/ directory alongside src/ and tests/. The language bindings live under bindings/, and the README carries PyPI and npm badges, so the Python and JavaScript packages are published under the name ggwave. The examples/ggwave-py and examples/ggwave-js directories are the reference points for each.
The lowest-friction first use does not require a build at all. The README documents an HTTP service that returns a WAV file for a given message, and it gives this audible example:
curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello%20world!' --output hello.wavThe reader should end up with hello.wav in the working directory. Playing it produces the audible FSK transmission. The same endpoint accepts a protocol parameter, and the README shows the ultrasonic variant:
curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello%20world!&p=4' --output hello.wavHere p=4 selects the ultrasonic profile, which corresponds to the F0 = 15000.000 Hz base described in the technical section. If you cannot hear the first file and can hear nothing from the second, that is expected behaviour rather than a failure.
For a local build, the examples are the entry point. The README points to the waver application under examples/waver as the easiest way to test the library, and lists ggwave-cli, ggwave-rx, ggwave-from-file and ggwave-to-file among the example targets. The ggwave-to-file example README is where the HTTP service is documented, so that directory is the place to look if you want to run the endpoint yourself rather than calling the public one.
The bandwidth ceiling is the honest limitation
The README states the bandwidth rate plainly: between 8 and 16 bytes/sec depending on the protocol parameters. That is not a figure that improves with a better microphone or a quieter room. It is set by the modulation, and the ECC layer adds bytes on top of whatever you want to send. A 100-byte payload is therefore in the neighbourhood of ten seconds of continuous sound, and the receiver must capture the whole marked segment before decoding begins.
This rules out several uses people might reach for. Streaming sensor telemetry, transferring a file, or replacing a low-rate radio link are all wrong fits. The wave-share example is described as file sharing through sound, but the mechanism is a URL or a short identifier carried acoustically, not the file itself. Treat ggwave as a channel for a few hundred bytes at most, and design the rest of your system around that.
The second limitation is environmental. The library analyzes raw waveforms from your audio hardware, so it inherits that hardware's frequency response, its noise floor and its automatic gain control. The README does not document any calibration step, retry policy or acknowledgement protocol, and it does not document rollback or error reporting behaviour when a marker is missed. In practice that means your application layer has to decide what to do when a message does not arrive, because the library gives you a demodulation result and not a delivery guarantee. The ultrasonic profile adds a further constraint the README does not quantify: at F0 = 15000.000 Hz, any speaker or microphone with a rolloff in that region will attenuate the signal, and there is no fallback documented for that case.
Where ggwave sits against QR codes and near-field radio
The closest comparison is an audio QR code, and the README itself uses that phrase. The difference is directional. A QR code is a visual one-to-one channel: one camera, one screen, aligned. ggwave is acoustic and the README frames one application as serverless, one-to-many broadcast, which a QR code cannot do. A single speaker can address every microphone in range simultaneously, with no line of sight and no pairing step. The cost is throughput, and it is a large cost: a QR code carries a URL in a single frame, while ggwave spends seconds on the same payload.
The other comparison is NFC or Bluetooth Low Energy pairing. Those give you a real link with acknowledgements, but they require a radio and, in the BLE case, a discovery and connection sequence. ggwave needs neither, which is exactly why the README lists device pairing and contact exchange, citing PairSonic for exchanging contact information and public keys between nearby devices. If your two devices are physically adjacent and both have working radios, BLE will be faster and more reliable. If one of them is an Arduino with no radio, or if you want to reach an unknown number of listeners at once, the acoustic path is the one that exists.
Maintenance, licence and upgrade cost
The repository is not archived, and the last push was on 2026-04-16. The most recent tagged release is ggwave v0.4.3 from 2026-03-21. The two prior tags, waver v1.5.2 and waver v1.5.1, date from 2022, which reflects that waver is the demo application and ggwave is the library; they version separately. There is a CHANGELOG.md at the repository root, so release-to-release changes are tracked in-tree rather than only in the GitHub releases list.
The licence is MIT, which is permissive and imposes no copyleft obligation on your own code. The repository also contains a reed-solomon directory under src/, and the README links to it as the source of the error correction implementation. If you vendor or modify that component, check its own licence header rather than assuming the top-level MIT file covers every file in the tree. That is a reading task for whoever handles your dependency review, not a legal conclusion.
Upgrade cost is likely to be low for most consumers. The public surface is the encode and decode entry points plus the audio callbacks, and the protocol parameters are the part most likely to shift between versions. The release cadence visible here is roughly one library tag per year, so pinning a version and reading CHANGELOG.md before moving is a reasonable posture. The bindings under bindings/, and the published PyPI and npm packages, are the parts to watch: a change there can affect you without any change to the C++ core.
Editorial conclusion
Adopt ggwave when the link itself is the point: pairing two devices that share no network, broadcasting a short string to every microphone in a room, or moving a few bytes onto an Arduino, ESP32 or RP2040 that has no radio. Do not adopt it as a transport for files, telemetry streams or anything measured in kilobytes per second; the documented rate is 8 to 16 bytes/sec depending on protocol parameters, and that ceiling is the design, not a tuning problem. Before committing, verify three things in your own setup: that your target platform is covered by the bindings/ or examples/ tree, that the acoustic path in your room actually carries the ultrasonic profile (p=4 in the HTTP service example) rather than the audible one, and that your receiver can honour the marker-based framing the README describes, since demodulation depends on detecting the start and end markers before any Fourier analysis happens.
Frequently asked questions
How does ggwave work?
It encodes data into sound using multi-frequency FSK. The payload is split into 4-bit chunks, three bytes are sent at a time using six tones spread across a 4.5 kHz range, and Reed-Solomon error codes are applied before transmission. The receiver detects start and end markers, records the audio in between, and Fourier transforms it to recover the frequencies.
What is ggwave?
ggwave is a tiny data-over-sound library, MIT licensed and written primarily in C++, that lets air-gapped devices exchange small amounts of data using sound. It generates and analyzes raw waveforms only; you supply the audio backend through callbacks.
Is ggwave real?
Yes. It is a published library with PyPI and npm packages, a CHANGELOG.md, a CI badge, and a set of example applications including waver, ggwave-cli and microcontroller receivers for ESP32, Arduino and RP2040.
What is the difference between gibberlink and ggwave?
The repository documents only ggwave itself: an FSK-based data-over-sound library with an MIT licence and bindings for Python, JavaScript and microcontrollers. It does not describe a separate mode or product called gibberlink, so the README gives no basis for a comparison.
What is the ggwave alternative?
The README does not name a competing library. The nearest documented comparison is the audio QR code, which the README lists as an application category, and the examples include a qrcode topic; the difference is that ggwave broadcasts acoustically to many listeners at once rather than requiring one aligned camera.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ggerganov-ggwave)