我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

在阅读本文之前,建议您先阅读上一篇文章: 通过蓝牙的音频:有关配置文件、编解码器和设备的最大详细信息

一些无线耳机用户反映,在使用所有音频设备都支持的标准 SBC 蓝牙编解码器时,音质较差且缺乏高频。 改善音质的常见建议是购买支持 aptX 和 LDAC 编解码器的设备和耳机。 这些编解码器需要许可费用,因此支持它们的设备更加昂贵。

事实证明,SBC 的低质量是由于蓝牙堆栈和耳机设置的人为限制造成的,而通过对智能手机或计算机进行软件更改,可以在任何现有设备上绕过此限制。

编解码器SBC

SBC 编解码器具有许多在连接设置阶段协商的不同参数。 他们之中:

  • 通道数量和类型:联合立体声、立体声、双通道、单声道;
  • 频段数量:4或8;
  • 包装内块数:4、8、12、16;
  • 量化期间分配比特的算法:响度、SNR;
  • 量化期间使用的比特池(bitpool)的最大值和最小值:通常从 2 到 53。

解码设备必须支持这些参数的任意组合。 编码器可能无法实现所有功能。
现有的蓝牙堆栈通常同意以下配置文件:联合立体声、8 个频段、16 个块、响度、位池 2..53。 此配置文件以 44.1 kbps 的比特率对 328 kHz 音频进行编码。
位池参数直接影响一个配置文件中的比特率:该参数越高,比特率越高,因此质量也越高。
然而,位池参数并不依赖于特定的配置文件; 比特率也很大程度上受到其他参数的影响:通道类型、频带数量、块数量。 您可以通过同意非标准配置文件来间接提高比特率,而无需更改比特池。

我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

SBC码率计算公式

例如,双通道模式单独对通道进行编码,为每个通道使用整个位池。 通过强制设备使用双通道而不是联合立体声,我们在相同的最大位池值下获得几乎双倍的比特率:617 kbps。
在我看来,在协商阶段使用未与配置文件绑定的位池值是 A2DP 标准中的一个缺陷,这导致了 SBC 质量的人为限制。 协商比特率比协商比特池更有意义。

这些固定的比特池和比特率值源自包含用于高质量音频的推荐值的表。 但推荐并不是将自己限制在这些价值观的理由。

我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

A2DP v1.2 规范于 2007 年至 2015 年有效,要求所有解码设备在高达 512 kbps 的比特率下正常工作:

SNK 的解码器应支持不会导致超过最大比特率的所有可能的比特池值。 此配置文件将单声道模式的可用最大比特率限制为 320kb/s,双通道模式的可用最大比特率限制为 512kb/s。

在新版本的规范中,对比特率没有限制。 据估计,2015年后发布的支持EDR的现代耳机可以支持高达约730 kbps的比特率。

由于某种原因,我测试的 Linux (PulseAudio)、Android、Blackberry 和 macOS 蓝牙堆栈对位池参数的最大值进行了人为限制,这直接影响了最大比特率。 但这还不是最大的问题;几乎所有耳机也将最大位池值限制为 53。
正如我已经看到的,大多数设备在比特率为 551 kbps 的修改后的蓝牙堆栈上完美工作,没有中断或裂纹。 但在正常条件下,在常规蓝牙堆栈上,这样的比特率永远不会一致。

修改蓝牙堆栈

任何与 A2DP 标准兼容的蓝牙堆栈都支持双通道模式,但无法从接口激活它。

让我们在界面中添加一个切换开关! 我已经为 Android 8.1 和 Android 9 制作了补丁,为堆栈添加了完整的双通道支持,在开发工具中的模式切换菜单中添加了一个模式,并将支持双通道的 SBC 视为像 aptX 这样的附加编解码器、AAC 或 LDAC(Android 称之为 HD 音频),方法是在蓝牙设备设置中添加复选标记。 它看起来是这样的:

我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

安卓9补丁
安卓8.1补丁

当激活该复选框时,蓝牙音频开始以比特率传输 551kbps,如果耳机支持 3 Mbit/s 的连接速度,或者 452kbps,如果耳机仅支持 2 Mbit/s。

该补丁包含在以下替代固件中:

  • LineageOS
  • 复活混音
  • 机器人

551 和 452 kbit/s 从何而来?

蓝牙空中共享技术旨在高效传输大型固定大小的数据包。 数据传输发生在时隙中,一次传输中发送的最大时隙数为 5。也有使用 1 或 3 个时隙的传输模式,但不使用 2 或 4 个时隙。在 5 个时隙中,您可以以连接速度传输最多 679 字节速度为 2 Mbit/s 时,速度可达 1021 Mbit/s,高达 3 字节;速度分别为 3 - 367 字节和 552 字节。

我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

如果我们要传输的数据少于 679 或 1021 字节,但多于 367 或 552 字节,则传输仍然需要 5 个时隙,并且数据会同时传输,从而降低了传输效率。

我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

双通道模式下的 SBC,44100 Hz 音频,Bitpool 38 个参数,每帧 16 个块,8 个频率范围,将音频编码为 164 字节帧,比特率为 452 kbps。
音频必须封装在 L2CAP 和 AVDTP 传输协议中,这些协议从音频有效负载中占用 16 个字节。

我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

因此,一个具有 5 个插槽的蓝牙传输可以容纳 4 个音频帧:

679 (EDR 2 mbit/s DH5) - 4 (L2CAP) - 12 (AVDTP/RTP) - 1 (заголовок SBC) - (164*4) = 6

我们将 11.7 毫秒的音频数据放入正在发送的数据包中,该数据包将在 3.75 毫秒内传输,并且数据包中还剩下 6 个未使用的字节。
如果稍微提高位池,将不再可能将 4 个音频帧打包到一个包中。 您必须一次发送 3 帧,这会降低传输效率,减少每帧传输的音频量,并且在无线电条件较差的情况下更快导致音频卡顿。

同样,为 EDR 551 Mbit/s 选择 3 kbit/s 的比特率:使用 Bitpool 47,每帧 16 个块,8 个频率范围,帧大小为 200 字节,比特率为 551 kbit/s。 一包包含 5 帧或 14.6 毫秒的音乐。

计算所有SBC参数的算法相当复杂,如果手动计算很容易混淆,所以我做了一个交互式计算器来帮助有兴趣的人: btcodecs.valdikss.org.ru/sbc-比特率计算器

为什么需要这一切?

与人们对 aptX 编解码器音质的普遍看法相反,在某些文件上,它产生的结果比标准比特率为 328 kbps 的 SBC 还要差。

SBC 按照从低到高的方式将量化位动态分配到频带。 如果所有比特率都用于低频和中频,则高频将被“切断”(反而会出现静音)。
aptX 始终使用相同位数量化频段,这就是它具有恒定比特率的原因:352 kHz 为 44.1 kbps,384 kHz 为 48 kbps,并且它无法“位移”到最需要它们的频率。 与 SBC 不同,aptX 不会“削减”频率,而是会向频率添加量化噪声,从而降低音频的动态范围,有时还会引入特有的爆裂声。 SBC“吃掉细节”——丢弃最安静的区域。
平均而言,与SBC 328k相比,aptX在宽频率范围的音乐中引入的失真较少,但在窄频率范围和宽动态范围的音乐中,SBC 328k有时会胜出。

让我们考虑一个特殊情况。 钢琴演奏录音的频谱图:
我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

主要能量位于 0 至 4 kHz 的频率,并持续到 10 kHz。
在 aptX 中压缩的文件的频谱图如下所示:
我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

这就是 SBC 328k 的样子。
我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

可以看出,SBC 328k 周期性地完全关闭 16 kHz 以上的范围,并将所有可用比特率花在低于该值的范围上。 然而,aptX 在人耳可听的频谱中引入了更多的失真,从 aptX 频谱图减去原始频谱图中可以看出(越亮,失真越大):
我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

而 SBC 328k 在 0 至 10 kHz 范围内对信号的破坏较小,并切断其余部分:
我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

SBC 的 485k 比特率足以保留整个频率范围,而无需禁用频段。
我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

在该轨道上,SBC 485k 在 0-15 kHz 范围内明显领先于 aptX,15-22 kHz 的差异较小但仍然明显(越暗失真越少):
我们修改蓝牙堆栈以改善不使用 AAC、aptX 和 LDAC 编解码器的耳机的声音

原始音频、SBC 和 aptX 存档.

通过切换到高比特率 SBC,您将获得在任何耳机上都优于 aptX 的音频。 在支持 3 Mbps EDR 连接的耳机上,551 kbps 的比特率可产生与 aptX HD 相当的声音。

你还能做得更多吗?

Android 补丁还包括进一步提高 2 Mbps EDR 设备比特率的选项。 您可以将比特率从 452 kbit/s 增加到 595 kbit/s,但代价是在困难的无线电条件下降低传输稳定性。
将 persist.bluetooth.sbc_hd_higher_bitrate 变量设置为 1 就足够了:

# setprop persist.bluetooth.sbc_hd_higher_bitrate 1

目前,极限比特率补丁仅在 LineageOS 15.1 中采用,在 16.0 中尚未采用。

设备兼容性

几乎所有耳机、扬声器和汽车音响主机都支持 SBC 双通道。 这并不奇怪 - 该标准需要任何解码设备的支持。 此模式会在少数设备上导致问题,但这些都是孤立的实例。
有关兼容设备的更多详细信息,请访问 4pda или XDA开发.

声音差异比较

我制作了一个 Web 服务,可以在浏览器中实时将音频编码为 SBC(以及 aptX 和 aptX HD)。 有了它,您可以在任何有线耳机、扬声器和您喜爱的音乐上比较不同 SBC 配置文件和其他编解码器的声音,而无需实际通过蓝牙传输音频,还可以在播放音频时直接更改编码参数。
btcodecs.valdikss.org.ru/sbc-encoder

联系 Android 开发者

我写信给 Google 的许多蓝牙堆栈开发人员,要求他们考虑在 Android 主分支 - AOSP 中添加补丁,但没有收到任何回复。 我的补丁在 适用于 Android 的 Gerrit 补丁系统 任何相关人员也没有发表评论。
如果我能得到一些帮助来联系 Google 的开发人员并将 SBC HD 引入 Android,我会很高兴。 gerrit中的补丁已经过时了(这是早期的修订之一),如果开发者对我的更改感兴趣我会更新它(对我来说更新它并不容易,我没有兼容Android Q的设备)。

结论

使用 LineageOS、Resurrection Remix 和 crDroid 固件的智能手机用户现在只需激活蓝牙设备设置中的选项即可享受改进的音质。 Linux 用户还可以通过安装来获得更高的 SBC 比特率 巴利·罗哈尔的补丁,其中增加了对 aptX、aptX HD 和 FastStream 编解码器的支持。

来源: habr.com

添加评论