在TWS耳机中,如果突然听不清楚对方的声音,是不是让你感到非常沮丧?或者当你在客厅喊一声“打开灯”,智能家居却迟迟没有反应——问题可能并不在于麦克风或算法,而是无线链路的带宽未能跟上语音的速度。
我们通常认为蓝牙连接要么“通”,要么“不通”,但实际上情况要复杂得多。信号强度如同海浪般起伏不定,当人们移动或墙壁阻挡时,信道质量会大幅波动。然而,语音数据却非常“急躁”:它不能等待长时间的重传(延迟敏感),也不能容忍丢包造成的卡顿(鲁棒性要求高),并且还需要节能(毕竟耳机使用的只是纽扣电池)。
那么,如何解决这个问题呢?始终使用高速率?在弱信号环境下,这会导致连接直接崩溃;一直使用低速率?音质只能勉强凑合。这就好比开车——在城市拥堵时强行加速至200公里/小时,不发生事故才怪;而在高速公路上限速60公里/小时,则显得过于浪费。
因此,最明智的做法是根据路况自动调整档位。在CH579这款国产小芯片上,我们实现了这样的“无线变速器”。CH579不仅仅是一款普通的BLE芯片,它集成了RISC-V E907内核、USB、以太网接口,并支持BLE 5.3的所有主流PHY模式:
- LE 1M:稳扎稳打,兼容性极佳
- LE 2M:速度翻倍,适合高清语音传输
- Coded PHY (S=2/S=8):穿透力强,即使在-100dBm的环境下也能保持通话
这意味着,设备可以在信号良好时以2Mbps的速度传输Opus 128kbps的高清音频,在信号不佳时切换到125kbps以确保通话不断,而不是简单地在整个过程中降低音质或断开连接。关键在于,这一切都可以在不中断连接的情况下完成,切换延迟通常低于10ms,用户几乎察觉不到。
小知识:BLE的PHY切换依赖于LL层控制帧(
→ LL_PHY_REQ
→ LL_PHY_RSP
),整个过程由硬件状态机驱动,无需重新配对或建立连接,非常适合动态场景。LL_PHY_UPDATE_IND
快速切换固然重要,但更重要的是“智能切换”。仅有切换能力是不够的,如何判断何时应该升档、何时应该降档?我们曾经尝试过几种方法,但都遇到了问题:
- 仅依赖RSSI(接收信号强度指示)?这可能导致在短暂干扰后错误地降速,恢复时又频繁调整,即所谓的“乒乓效应”。
- 仅依赖误包率(PER)?短期波动大,响应过慢,导致语音缓冲区溢出。
因此,我们最终开发了一个复合决策引擎,结合多个维度:
同时引入了迟滞机制(Hysteresis):降速容易提速难,避免频繁振荡。例如,从2M切换到1M后,不会因为一次RSSI回升就立刻切换回2M,而是需要连续三次达标。// 简化版速率决策逻辑
uint8_t DecideTargetPhy(int rssi, int per_last_5s, bool voice_active)
{
if (!voice_active) {
return LE_1M_PHY; // 静默期节能优先
}
if (rssi > -70 && per < 5) {
return LE_2M_PHY; // 强信号+低误码,冲!
}
if (rssi < -85 || per > 15) {
return LE_CODED_PHY_S8; // 危险区域,保命要紧
}
return LE_1M_PHY; // 中间地带,稳一手
}
更进一步,我们还引入了语音活跃检测(VAD)联动:在没有语音活动时,系统可以主动维持低速率甚至进入轻度睡眠,一旦检测到语音启动,立即预判并请求切换至高速PHY,抢占传输窗口。
经验之谈:不要等到第一包语音数据堆积后再切换速率!等到那时,FIFO已经快要满了。应当提前做好准备,利用VAD进行前瞻性触发。
带宽优化不仅仅是提高传输速率,端到端的协同才是关键。许多人认为提高带宽就是将PHY调到最高速度,但这并不是全部。真正的带宽优化是一整套软硬件协同的设计理念。
- 动态编码匹配:使音频“适应”信道。你试过用4G网络播放4K视频吗?缓冲条一直在转……同样的道理,如果编码器输出的比特率远高于当前无线净吞吐量,再好的PHY也无法解决问题。因此,每当PHY切换完成后,我们会立即通知编码器调整目标码率,以确保既不会“带宽过剩空跑”,也不会“小马拉大车”。
void UpdateAudioBitrate(uint8_t phy_mode) { int target_bitrate; switch(phy_mode) { case LE_2M_PHY: target_bitrate = 128000; // Opus 高清档 break; case LE_1M_PHY: target_bitrate = 64000; // 标准清晰度 break; case LE_CODED_PHY_S8: target_bitrate = 16000; // LC3 极简通话 break; default: target_bitrate = 32000; break; } opus_encoder_ctl(opus_enc, OPUS_SET_BITRATE(target_bitrate)); } - 包聚合 + 缓冲管理:减少协议开销。BLE每帧最多支持251字节的有效载荷,但加上头部、CRC、ACK等开销,实际效率可能只有70%左右。特别是在低速率下,这些“固定成本”所占比例更高。我们的解决方案包括:
- 在2M模式下启用多语音帧聚合发送,将3~4个Opus帧打包成一个PDU;
- 使用双缓冲队列,主缓冲接收编码数据,副缓冲专门供射频DMA读取,防止切换瞬间阻塞;
- 接收端根据时间戳做Jitter Buffer平滑播放,以抵抗抖动。
- 功耗平衡术:快≠费电,慢≠省心。你可能会认为2M PHY一定更耗电,但事实并非如此。虽然瞬时电流稍大,但由于传输时间较短,整体能耗可能更低。例如:
因此,在语音突发场景中,高速短时传输 + 快速进入低功耗监听,通常是最佳组合。这也是为什么我们在设计电源管理时特别注意以下几点:PHY模式 传输10kB数据所需时间 平均射频功耗 LE 1M 约80ms 持续升高 LE 2M 约40ms 瞬间爆发后快速休眠 - 配合DC-DC供电,应对2M发射时的电流尖峰;
- 利用CH579内置的低功耗模式,在非传输期间关闭RF前端;
- 主控CPU配合深度睡眠,仅保留RTC和VAD唤醒功能。
从实验室到真实世界的实战表现证明了这种方法的有效性。
此方案已在一款工业级别的语音对讲设备中得到应用验证,效果非常可靠:
- 场景
- 固定1M PHY
- 自适应切换方案
| 室内直线距离(信号强) | MOS 3.8(Opus 64k) | MOS 4.5(Opus 128k)? |
| 穿过两堵墙(信号弱) | 频繁卡顿,MOS 2.5 | 切换至S8保持通话,MOS 3.2? |
| 移动过程(信号动态变化) | 多次断开并重新连接 | 平滑切换,无感知? |
| 连续通话8小时 | 剩余电量40% | 剩余电量58%? |
最重要的是,用户反馈称“声音清晰多了”、“即使走远也不会断线”、“一整天无需充电”。这正是技术实际应用的核心价值。
设计建议:避免这些误区,节省开发时间
如果你正在进行类似的项目,以下几点建议或许对你有帮助:
- 不要盲目依赖制造商的默认设置。例如,CH579 SDK 默认使用1M PHY,许多开发者不愿更改。然而,只需添加几行HCI命令即可启用2M/Coded功能,从而显著提升性能。
- 确保测试时模拟真实的移动环境。静态测试无法揭示所有问题,必须在行走、穿过门或转弯等情况下进行测试,特别是当人体阻挡信号时。建议使用机器人携带设备沿预定路径移动,以获得更准确的数据。
- 关注“实际吞吐量”而非“理论速率”。虽然空中速率为2Mbps,但实际有效负载可能仅为1.6~1.8Mbps。务必测量真实语音流下的有效带宽,并考虑ACL调度、NACK重传等因素的影响。
- 预留回退机制。如果切换失败(例如对方设备不支持2M),应有备用策略以确保基本通话功能不受影响,而不是直接中断通信。
这只是开始,而非终点
目前的速率切换机制仍然是“响应式”的——即在信号恶化后才降低速度。然而,未来的方向可以更加先进:
- 引入AI预测模型:基于历史RSSI序列预测信道趋势,提前进行PHY切换,实现主动适应。
- 结合AoA/AoD定位信息:判断用户是否正在远离,提前准备足够的带宽。
- 融合LE Audio特性:利用同步通道构建更加稳定的语音传输管道。
像CH579这样的国产芯片正将高端平台的技术普及化。作为开发者,我们的目标不仅是使技术可用,还要最大限度地利用每一比特的带宽。
毕竟,让用户体验到清晰的世界,本身就是一件非常酷的事情,不是吗?


雷达卡


京公网安备 11010802022788号







