如何零基础用 ggwave 让两台设备用声音传数据:完整实操指南
【免费下载链接】ggwaveTiny>项目地址: https://gitcode.com/GitHub_Trending/gg/ggwave
没有网、没有线、没有蓝牙,一台电脑怎么把一小段数据交给旁边的 ESP32?ggwave 声波传输库就是干这个的:发送端把数据编码成一段声波,从扬声器播出去;接收端用麦克风录下这段声音,做频谱分析后还原成数据。它基于 FSK 频移键控调制,传输速率 8-16 字节/秒,Python 几行代码就能跑起来,Arduino、ESP32 这类小单片机也带得动。
📻 它是什么、凭什么工作
一句话:ggwave 把数据变成一个"声学二维码"。
- 发送时,数据被切成 4-bit 小块,用 6 个同时播放的音调承载,落在一段 4.5kHz 宽的频率带里(可听声协议基频 1875Hz,超声波协议 15kHz)
- 原始数据先经过 Reed-Solomon 纠错编码,接收端有轻微误码也能自行修复
- 接收端先监听专门的起止标记声,确认传输边界后再对录音做 FFT 频谱分析,逐帧还原出数据
- 库本身只负责"数据 ↔ 原始波形"这一层,音频设备(ALSA、PortAudio、Web Audio)由你自己接
所有协议常量和参数含义都在 include/ggwave/ggwave.h 的注释里,读一遍就清楚每个字段的用途。
能力全景:先选对"调"再动手
库内置 4 组、共 12 个预置协议(加 10 个可自定义的空位):
| 协议族 | 常量(示例) | 每块字节数 | 特点 | 适合场景 |
|---|---|---|---|---|
| 可听声 | GGWAVE_PROTOCOL_AUDIBLE_NORMAL/_FAST/_FASTEST | 3 | 人耳可闻,基频 1875Hz;档位越高速率越高、抗噪越差 | 演示、近距离传文件 |
| 超声波 | GGWAVE_PROTOCOL_ULTRASOUND_NORMAL/_FAST/_FASTEST | 3 | 基频 15kHz 起,人听不见、不扰人 | 自动配对、后台静默传输 |
| DT 多音 | GGWAVE_PROTOCOL_DT_NORMAL/_FAST/_FASTEST | 1 | 多音调直传,速率最慢但更稳 | 信道条件差的远距离 |
| MT 单音 | GGWAVE_PROTOCOL_MT_NORMAL/_FAST/_FASTEST | 1 | 单音调、内存占用最低 | 只有无源蜂鸣器的 Arduino 等 MCU |
怎么选,记住三条就够:
- 要"听得见、能演示":
AUDIBLE_FAST - 要"听不见、不碍事":
ULTRASOUND_NORMAL - 设备只有一个蜂鸣器:MT 族 +
GGWAVE_OPERATING_MODE_TX_ONLY_TONES(只生成音调列表,不合成完整波形,省内存)
🚀 从零跑起来:三步收到第一句话
步骤 1:获取代码并构建
git clone https://gitcode.com/GitHub_Trending/gg/ggwave --recursive cd ggwave && mkdir build && cd build cmake .. make如果不想编译 C 代码,也可以直接pip install ggwave装 Python 包,配合 PortAudio 就能收发。
步骤 2:最小发送示例
import ggwave, pyaudio p = pyaudio.PyAudio() waveform = ggwave.encode("hello ggwave", protocolId=1, volume=20) # 1=AUDIBLE_FAST stream = p.open(format=pyaudio.paFloat32, channels=1, rate=48000, output=True, frames_per_buffer=4096) stream.write(waveform, len(waveform)//4) # 扬声器播放这段声波 stream.stop_stream(); stream.close(); p.terminate()步骤 3:另一台机器上接收
import ggwave, pyaudio p = pyaudio.PyAudio() inst = ggwave.init() # 默认参数:48kHz、1024 帧 stream = p.open(format=pyaudio.paFloat32, channels=1, rate=48000, input=True, frames_per_buffer=1024) while True: data = stream.read(1024, exception_on_overflow=False) res = ggwave.decode(inst, data) # 每帧喂一次,收到才返回内容 if res is not None: print("Received:", res.decode("utf-8")); break跑通这两段,你手里就是一个"空气传数据"的收发系统了。
硬件准备(接单片机时)
用 Arduino 当发送端的话,硬件极简:无源蜂鸣器接数字引脚(示例用 10),两个按键控制发送内容,5V 供电即可:
对应代码在examples/arduino-tx/arduino-tx.ino,接收侧的 ESP32 / RP2040 接麦克风电路在examples/esp32-rx/和examples/rp2040-rx/。
两个真实用法演示
场景 1:给 IoT 设备配网
手机或电脑把 WiFi 的 SSID+密码用声音播出去,ESP32 用模拟麦克风(MAX9814、KY-037 等)听音解码,拿到凭据直接连网,省掉串口手输的步骤:
uint8_t buf[256]; int n = ggwave_decode(inst, micData, nBytes, buf); // 麦克风音频喂进去 if (n > 0) { buf[n] = '\0'; // 解码结果不带结束符,手动补 connectWiFi((char*)buf); // 解析 SSID/密码并连接 }价值在于:设备出厂不用预置任何配置,"靠近手机听一下"就完成了配网,且凭据走的是人耳听不太懂的超声波频段。
场景 2:浏览器之间传小文件
把 ggwave 编译成 WebAssembly(examples/ggwave-wasm/),两个网页各开一个标签页,一个用 Web Audio API 播放波形、一个用麦克风解码,中间没有任何服务器和插件:
char payload[256]; while (running) { // 接收标签页的主循环 int n = ggwave_decode(inst, micBuf, nBytes, payload); if (n > 0) { payload[n] = 0; saveToFile(payload); } // 文件还原 }几百字节的文件、密钥片段、剪贴板内容,播个一两秒就过去了。
🛠 调优与避坑:4 个常见状况的处理
- 发了没反应:多半是背景噪声太大或音量太小。把 volume 保持在 15-30(头文件注释建议 25,别超过 50),协议从 FAST 档退回 NORMAL 档,或开启 DSS 直接序列扩展模式提升鲁棒性。
ggwave_decode频繁返回 -1:表示解码失败,通常就是噪声。缩短设备间距、避开大音量声源;另外确认麦克风的采样率设置(sampleRateInp)与实际一致,不一致时库会自动重采样,但误差太大照样解不出。- Arduino Uno 蜂鸣器发不出声:无源蜂鸣器在 1-2kHz 低段可能物理发不出来。用 MT 单音协议,并用
ggwave_txProtocolSetFreqStart把基频上移(arduino-tx 示例移了 48 个 bin ≈ 2250Hz),接收端记得移相同的量。 - 数据超过 140 字节发不出去:变长载荷上限 140 字节、固定长度模式上限 64 字节。大文件要自己分片:加序号、逐片发送、接收端重组,失败重传。
❓ 常见疑问
Q:一次到底能发多少数据? A:变长模式每包最大 140 字节,固定长度模式 64 字节;更大的数据靠分片。
Q:采样率必须是 48000Hz 吗? A:默认工作速率 48kHz。设备实际采样率不同时,把sampleRateInp/sampleRateOut设成设备值,ggwave 会内部重采样。
Q:接收端要不要全协议都开着? A:默认全部启用。收发协议已知时,用ggwave_rxToggleProtocol只留目标协议,误报更少、内存更省。
Q:笔记本自带的扬声器和麦克风能用吗? A:能。examples/r2t2/甚至演示了直接用 PC 板载喇叭发数据。
延伸资源
- examples/ggwave-py/send.py 与 examples/ggwave-py/receive.py:Python 收发对的最小实现,逐行对应本文步骤 2/3
- examples/arduino-tx/arduino-tx.ino:MCU 上用蜂鸣器发文本的完整示例,含频率偏移处理
- src/ggwave.cpp:调制、Reed-Solomon 编解码与频谱分析的完整实现,想深挖协议细节看这里
【免费下载链接】ggwaveTiny>项目地址: https://gitcode.com/GitHub_Trending/gg/ggwave
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考