Inspiration

Every lecture I've been in has the same boring moment: the prof wants to share a link, so 200 people squint at a URL on a slide and type it out by hand, or someone puts up a QR code that half the room can't scan from the back. Meanwhile, every laptop in that room has a speaker and a microphone. I wondered if sound itself could carry the link. Turns out it can, and the fact that sound is naturally one-to-many means a single "chirp" can reach every device in the room at once, which is something AirDrop and Bluetooth fundamentally can't do.

What it does

ChirpDrop sends short texts and links between nearby devices using only sound. You type a message, hit Send, and your device plays a short audible chirp that encodes the text as audio tones. Any device with ChirpDrop open and listening decodes the message through its microphone and displays it instantly. Received links are clickable. There's no pairing, no accounts, no internet needed for the transfer itself. One sender can broadcast to unlimited listeners simultaneously.

How I built it

The app is React + Vite, deployed on Vercel. The acoustic modem underneath is ggwave, an open-source data-over-sound library that handles FSK modulation and Reed-Solomon error correction. Everything on top of that is mine: the Web Audio pipeline (encoding text to a waveform and playing it, capturing mic audio and feeding it to the decoder frame by frame), a reliability layer that auto-repeats each chirp 3 times while receivers deduplicate so exactly one copy shows up, a live waveform visualization built on AnalyserNode so you can actually see the data leaving the device, mic privacy controls, and the UI.

Challenges I ran into

I had many problems with audio in the browser. Browsers block AudioContext until a user gesture, so everything has to initialize inside a click handler. Furthermore, sample rates differ between devices, and hardcoding one means it works on your laptop and silently fails on your phone. The worst bug was that ggwave's encoder returns a typed array that's a view into WASM memory, so naively converting it gave me the same garbled thump for every message until I copied the bytes out properly.

Accomplishments that I'm proud of

Something that I'm proud of is that the whole thing works end to end on real hardware. I can type a message on my laptop and watch it appear on my phone across the room, carried by nothing but sound, and I built that solo in a weekend without ever having touched the Web Audio API before.

I'm also proud of the engineering underneath the demo. The reliability layer means the same chirp lands exactly once on every listener, even though it's transmitted three times. The failure mode is clean too: because of the checksum, a noisy room means you receive nothing rather than garbled text.

What I learned

I learned a ton about the Web Audio API: audio graphs, AnalyserNode, script processors, and how typed arrays actually work in JavaScript. I also learned that reliability engineering is a product feature. The auto-retry and dedupe layer took maybe 30 lines, but it's the difference between a demo that works once and a demo that works every time.

What's next for ChirpDrop

Password-protected chirps using the Web Crypto API, so a message broadcast to a whole room can only be decrypted by people who share the password. Everyone hears the chirp, but only your group can read it. Also, I'm thinking about adding message IDs so that identical texts sent back-to-back aren't filtered as duplicates, an ultrasonic mode for silent transfers, and testing broadcasts over room PA systems to reach genuinely large spaces.

Built With

Share this project:

Updates