Ggwave
Tiny data-over-sound library
Install / Use
/learn @ggerganov/GgwaveREADME
ggwave
[![ggwave badge][changelog-badge]][changelog]
Tiny data-over-sound library.
Click on the images below to hear what it sounds like:
<a href="https://youtu.be/S2YdGefZiy4"><img width="100%" src="media/ggwave0.gif"></img></a>
<a href="https://user-images.githubusercontent.com/1991296/161401690-013023ba-1d21-4fb7-8d7f-9953f51c1e5b.mp4"><img width="100%" src="https://user-images.githubusercontent.com/1991296/109401710-d7d3d880-7958-11eb-9b7e-364be0b4cf55.gif"></img></a>
<a href="https://youtu.be/Zcgf77T71QM"><img width="100%" src="media/waver-preview1.gif"></img></a>
https://user-images.githubusercontent.com/1991296/166411509-5e1b9bcb-3655-40b1-9dc3-9bec72889dcf.mp4
https://user-images.githubusercontent.com/1991296/168469004-aeb9b9fe-cf81-4db7-b602-62e4ae659341.mp4
<a href="https://youtu.be/aj_GLBtU3Vw"><img width="100%" src="https://user-images.githubusercontent.com/1991296/177214041-26456254-d4b5-425b-bc57-48bcfc8f816e.png"></img></a>
Details
This library allows you to communicate small amounts of data between air-gapped devices using sound. It implements a simple FSK-based transmission protocol that can be easily integrated in various projects. The bandwidth rate is between 8-16 bytes/sec depending on the protocol parameters. Error correction codes (ECC) are used to improve demodulation robustness.
This library is used only to generate and analyze the RAW waveforms that are played and captured from your audio devices (speakers, microphones, etc.). You are free to use any audio backend (e.g. PulseAudio, ALSA, etc.) as long as you provide callbacks for queuing and dequeuing audio samples.
Here is a list of possible applications of ggwave with a few examples:
- Serverless, one-to-many broadcast
- wave-share - file sharing through sound
- Internet of Things
- esp32-rx, arduino-rx, rp2040-rx, arduino-tx - Send and receive sound data on microcontrollers
- r2t2 - Transmit data with the PC speaker
- buttons - Record and send commands via Talking buttons
- Audio QR codes
- [Twitter] - Broadcast your clipboard to nearby devices
- Device pairing / Contact exchange
- PairSonic - Exchange contact information and public keys with nearby devices
- Authorization
Try it out
You can easily test the library using the free waver application which is available on the following platforms:
<a href="https://apps.apple.com/us/app/waver-data-over-sound/id1543607865?itsct=apps_box&itscg=30200&ign-itsct=apps_box#?platform=iphone" style="display: inline-block; overflow: hidden; border-radius: 13px; width: 250px; height: 83px;"><img height="60px" src="https://tools.applemediaservices.com/api/badges/download-on-the-app-store/white/en-US?size=250x83&releaseDate=1607558400&h=8e5fafc57929918f684abc83ff8311ef" alt="Download on the App Store"></a> <a href='https://play.google.com/store/apps/details?id=com.ggerganov.Waver&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' src='https://i.imgur.com/BKDCbKv.png' height="60px"/></a> <a href="https://snapcraft.io/waver"> <img alt="Get it from the Snap Store" src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg" height="60px"/> </a>
Browser demos
- https://waver.ggerganov.com
- https://ggwave.ggerganov.com
- https://ggwave-js.ggerganov.com
HTTP service
# audible example
curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello%20world!' --output hello.wav
# ultrasound example
curl -sS 'https://ggwave-to-file.ggerganov.com/?m=Hello%20world!&p=4' --output hello.wav
Technical details
Below is a short summary of the modulation and demodulation algorithm used in ggwave for encoding and decoding data into sound.
Modulation (Tx)
The current approach uses a multi-frequency Frequency-Shift Keying (FSK) modulation scheme. The data to be transmitted is first split into 4-bit chunks. At each moment of time, 3 bytes are transmitted using 6 tones - one tone for each 4-bit chunk. The 6 tones are emitted in a 4.5kHz range divided in 96 equally-spaced frequencies:
| Freq, [Hz] | Value, [bits] | Freq, [Hz] | Value, [bits] | ... | Freq, [Hz] | Value, [bits] |
| ------------ | --------------- | ------------ | --------------- | --- | ------------ | --------------- |
| F0 + 00*dF | Chunk 0: 0000 | F0 + 16*dF | Chunk 1: 0000 | ... | F0 + 80*dF | Chunk 5: 0000 |
| F0 + 01*dF | Chunk 0: 0001 | F0 + 17*dF | Chunk 1: 0001 | ... | F0 + 81*dF | Chunk 5: 0001 |
| F0 + 02*dF | Chunk 0: 0010 | F0 + 18*dF | Chunk 1: 0010 | ... | F0 + 82*dF | Chunk 5: 0010 |
| ... | ... | ... | ... | ... | ... | ... |
| F0 + 14*dF | Chunk 0: 1110 | F0 + 30*dF | Chunk 1: 1110 | ... | F0 + 94*dF | Chunk 5: 1110 |
| F0 + 15*dF | Chunk 0: 1111 | F0 + 31*dF | Chunk 1: 1111 | ... | F0 + 95*dF | Chunk 5: 1111 |
For all protocols: dF = 46.875 Hz. For non-ultrasonic protocols: F0 = 1875.000 Hz. For ultrasonic protocols: F0 = 15000.000 Hz.
The original data is encoded using Reed-Solomon error codes. The number of ECC bytes is determined based on the length of the original data. The encoded data is the one being transmitted.
Demodulation (Rx)
Beginning and ending of the transmission are marked with special sound markers (#13). The receiver listens for these markers and records the in-between sound data. The recorded data is then Fourier transformed to obtain a frequency spectrum. The detected frequencies are decoded back to binary data in the same way they were encoded.
Reed-Solomon decoding is finally performed to obtain the original data.
Examples
The examples folder contains several sample applications of the library:
| Example | Description | Audio |
| ------- | ----------- | ----- |
| ggtag | Sound-programmable e-paper badge | PDM mic |
| ggwave-rx | Very basic receive-only program | SDL |
| ggwave-cli | Command line tool for sending/receiving data through sound | SDL |
| ggwave-wasm | WebAssembly module for web applications | SDL |
| ggwave-to-file | Output a generated waveform to an uncompressed WAV file | - |
| ggwave-from-file | Decode a waveform from an uncompressed WAV file | - |
| waver | GUI application for sending/receiving data through sound | SDL |
| ggwave-py | Python examples | PortAudio |
| ggwave-js | Javascript example | Web Audio API |
| spectrogram | Spectrogram tool | SDL |
| ggweb-spike | Android example using a WebView to wrap ggwave into a simple app | WebAudio |
| buttons | Record and send commands via Talking buttons | Web Audio API |
| r2t2 | Transmit data through the PC speaker | PC speaker |
| ggwave-objc | Minimal Objective-C iOS app using ggwave | AudioToolbox |
| ggwave-java | Minimal Java Android app using ggwave | android.media |
| ggwave-kmm | Kotlin Multiplatform Project using ggwave | android.media, javax.sound.sampled |
| ggwave-fm | Transmit ggwave messages with HackRF | Radio |
| esp32-rx | Transmit and receive messages using ESP32 | - |
| rp2040-rx | Transmit and receive messages using Raspberry Pi Pico (RP2040) | - |
| arduino-rx | Transmit and receive messages using Arduino RP2040 | - |
| [arduino-tx](https://github.com/ggerganov/ggwave/tre
Related Skills
node-connect
328.6kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
openai-image-gen
328.6kBatch-generate images via OpenAI Images API. Random prompt sampler + `index.html` gallery.
claude-opus-4-5-migration
80.9kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
80.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
