cyrinx

Open-source data over sound

Send data through the air with sound.

Cyrinx turns bytes into an audio waveform, plays it through a speaker, and recovers the bytes from microphone recordings. In one close-range bench setup, built-in MacBook Pro and Pixel 7a audio hardware delivered 65.9 kilobits per second of byte-verified payload—about 8.2 kilobytes per second.

Audible · near contact · one-way campaign · host-decoded

Verified payload rate
65.875 kbps
Blocks recovered
98.481%4,215 of 4,280 scheduled blocks, before retries
Audio hardware
Built in MacBook speaker → two Pixel microphones

What “verified payload” means

The 65.875 kbps clock includes synchronization, pilots, error correction, CRCs, and four 0.25-second gaps. Only payload blocks that passed CRC and matched the scheduled bytes count. It does not include retransmissions, app setup, or a preceding channel-sounding step. ADB coordinated the capture, but no payload traveled over USB or radio. The faster profile missed its reliability gate: 98.481% block recovery versus 99.967% for its paired control.

Performance

How fast is that?

Acoustic modems do not share one standard benchmark. Frequency band, distance, hardware, and rate accounting all change the result. These published reference points show the trade-offs instead of pretending they are identical experiments.

~2×

the highest rate in one review’s 2000–2022 commodity-device literature set

A 2026 systematic review examined 31 acoustic systems from that search window and listed a 32 kbps study at the top. Cyrinx reports 65.875 kbps using different, scheduled byte-level goodput accounting. This is useful context, not a universal speed-record claim. Read the review.

Published acoustic-modem reference points
System Reported rate Test setup What differs
Cyrinx 2.0 65.875 kbps Built-in MacBook speaker → Pixel microphones; near contact Audible; scheduled byte-verified goodput; 98.481% block recovery; host batch decode
Yamamoto & Kubo 32.38 kbps Yamaha speaker → Olympus PCM recorder; through 1.5 m Information rate including in-frame FEC, training, and guard intervals; 140 frames
BatComm 47.49 kbps Dedicated ultrasonic transmitter → built-in device microphone; centimeter range Inaudible rate at 4.3% BER; also 17.76 kbps at 2.3 m; specialized transmitter
Tabak, Lin & Singer 4 kbps Built-in laptop speakers and microphones; through 5 m Near-ultrasonic raw rate; longer range; BER rather than delivered-payload goodput

The plain-English takeaway: Cyrinx currently emphasizes close-range throughput. The other systems above reach farther or avoid audible sound. The measurements are not interchangeable, and Cyrinx has not established a world record across every acoustic-modem design.

Controlled open-source comparison

137× faster on the same MacBook-to-iPhone path

Cyrinx 1.0 delivered 36.47 kbps; the fastest ggwave mode recovered on the same path delivered 0.267 kbps. Both used the same placement and payload-airtime accounting. The newer Pixel result is deliberately not used to inflate this ratio.

See the controlled comparison
Cyrinx 1.0
36.47 kbps
ggwave Fastest
0.267 kbps

How it works

A modem that uses sound instead of radio.

Cyrinx uses the same broad idea as a radio modem, except the carrier is pressure in the air and the transducers are speakers and microphones.

01

Spread data across many tones

Hundreds of narrow frequency lanes carry small pieces of the message at the same time. Error correction adds redundancy before transmission.

02

Measure what the room changed

Known tones reveal timing, echoes, and frequency dead spots. If two microphones are available, the receiver can combine them per frequency.

03

Repair and verify each block

Soft decoding repairs damaged bits. A CRC flags blocks that do not validate, so the benchmark counts correctly recovered payload only.

Use Cyrinx

How can I use it in my own project?

Today, Cyrinx 2.0 is a frame codec library—not a drop-in AirDrop replacement. It gives your app bytes ↔ 48 kHz PCM conversion. Your app supplies audio playback, recording, message chunking, scheduling, session logic, and retries.

Swift · macOS 13+ and iOS 17+

Add the Swift package

dependencies: [
    .package(
        url: "https://github.com/dweekly/cyrinx.git",
        from: "2.0.0"
    )
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "Cyrinx", package: "cyrinx")
        ]
    )
]

Encode and decode a frame

import Cyrinx
import Foundation

let config = BulkPHY.Configuration
    .makePixel7aNearFieldFlagshipProfile(
        amplitude: 0.18
    )
let modem = BulkPHY(configuration: config)
let bytes = modem.geometry()!.payloadBytes
let payload = Data(repeating: 0xA5, count: bytes)

let pcm = modem.encode(payload)! // mono Float, 48 kHz
// Play pcm; record sample-aligned mic channels.
if let result = modem.decode(
        primaryCapture,
        automaticallyCombining: secondaryCapture
    ), result.isComplete {
    let verifiedPayload = result.payload
    // Consume verifiedPayload.
} else {
    // Reject or retry the incomplete frame.
}

The Pixel preset reproduces a measured bench profile; it is not a safe universal default. Validate amplitude, route, and reliability on your own devices. encode accepts exactly one frame of payload.

Portable C

Use the same codec without Swift

The canonical implementation is C. In SwiftPM, add .product(name: "CCyrinx", package: "cyrinx") to a C target and include <cyrinx/cyrinx_bulk.h>. Then fill a cyrinx_bulk_config, compute its geometry, modulate one frame, play and capture audio, then demodulate one or two aligned microphone channels.

  1. cyrinx_bulk_compute_geometry
  2. cyrinx_bulk_modulate
  3. Your 48 kHz playback and capture
  4. cyrinx_bulk_demodulate2_auto_v1

Accept the returned payload only when blocks_ok == blocks_total, or use a _with_block_validity entry point to handle blocks individually. Outside SwiftPM, compile cyrinx_bulk.c, cyrinx_fft.c, kiss_fft.c, and kiss_fftr.c with the public and KISS FFT include roots and kiss_fft_scalar=double. The repository does not yet provide CMake, pkg-config, an Android AAR, or JNI bindings.

The library provides

  • Portable byte-to-waveform and waveform-to-byte codec
  • Error correction and per-block CRC validation
  • Mono and sample-aligned two-microphone receivers
  • Measured Pixel and Moto profile factories
  • Golden vectors and deterministic codec tests

Your application provides

  • 48 kHz float PCM playback and microphone capture
  • Payload chunking, frame timing, and padding
  • Retries, session state, and user-facing progress
  • Device calibration and a safe output level
  • Testing across the distances and placements you support

Project status

What works today—and what does not.

The codec is real and tested. The product experience around it is still research work. These boundaries matter if you plan to embed Cyrinx.

Available now

  • Portable C bulk codec and Swift binding
  • Audible MacBook-to-Pixel frame profile
  • Two-microphone combining and automatic selection
  • CRC-block recovery counts and receiver diagnostics
  • Apache-2.0 source, tests, papers, and failure log

Still research

  • No turnkey cross-platform transfer app
  • No on-device Cyrinx 2 Android decoder or JNI/AAR
  • No automatic route calibration or volume selection
  • No integrated ultrasonic or pleasant-audible mode
  • No flagship throughput claim yet at 3 ft or in both directions

A one-way ultrasonic experiment reached about 9 kbps, but the phone-to-Mac coherent return path failed and the mode is not integrated. The pleasant audible mode is a roadmap item and has not been listener-tested. Read the ultrasonic findings .

Evidence

Inspect the work, including the setbacks.

The papers describe the bench geometry, accounting, receiver changes, rejected profiles, and limits of the claims. The repository includes the implementation, tests, measurement ledgers, and negative findings.