修改了蓝牙堆栈,以改善没有AAC,aptX或LDAC编解码器的耳机上的音频质量

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

一些无线耳机用户注意到,使用标准的蓝牙SBC编解码器时,声音质量较低且缺少高频,所有耳机和其他蓝牙音频设备均支持该编码。 获得更好音质的常见建议是购买支持aptX或LDAC编解码器的设备和耳机。 这些编解码器需要支付许可费用,这就是与它们一起使用的设备更昂贵的原因。

事实证明,SBC的质量低下是由目前所有蓝牙堆栈和耳机配置的人为限制引起的,而这种限制只能在任何经过​​软件修改的现有设备上才能克服。

SBC编解码器

SBC具有许多在连接建立阶段协商的不同参数:

  • 音频通道类型和编号:联合立体声,立体声,双通道,单声道;
  • 频带数:4或8;
  • 一个数据包中的音频块数:4、8、12、16;
  • 量化比特分配算法:响度,SNR;
  • 量化过程中使用的最大和最小位池:通常为2-53。


要求解码器支持这些参数的任何组合。 编码器可能仅实现其中的一部分。
现有的蓝牙协议栈通常会协商以下我称为“配置文件”的选项集:联合立体声,8频段,16块,响度,比特池2..53。 此配置文件以328 kbps的比特率编码44.1 kHz立体声音频。
比特池是改变编码比特率的参数:比特率越高,比特率越高,因此质量也越高。 但是确切的位池值仅在准确的配置文件内对应于准确的比特率。
比特率还受到其他参数的显着影响:音频通道类型,频带数,音频块数。 您可以通过协商非标准配置文件来间接提高比特率,而无需更改比特池。

bitrate= frac8\次 length\次 rate\次


比特率计算公式


例如,与立体声或联合立体声不同,“双通道”模式对每个通道使用单独的位池分别对通道进行编码,而“立体声”或“联合立体声”对两个通道都使用位池。 强制设备使用双通道而不是联合立体声,将使我们获得几乎两倍的617 kbps比特率,而相同的比特池值为53。
在我看来,位池应该是一个内部变量。 我假定位池值未绑定到其他编解码器参数,而仅将其定义为独立的协商变量是A2DP规范设计错误。

固定比特池和比特率值源自高质量音频的推荐配置文件。 但建议不应成为设置这些参数限制的理由。

蓝牙SBC配置文件表

A2DP规范v1.2(于2007年至2015年生效)要求所有解码器以最高512 kbps的比特率正常工作:

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


在规范的新版本中没有规定比特率限制。 假定2015年后发布的具有EDR支持的现代耳机可以支持高达730 kbps的比特率。

由于某些原因,所有当前测试的蓝牙协议栈(Linux(PulseAudio),Android,Blackberry和macOS)都具有最大比特池参数的人为限制,这直接影响最大比特率。 但这不是最大的问题,几乎所有耳机都将最大位池值限制为53。
正如我在测试中已经看到的那样,大多数设备在修改后的蓝牙协议栈(比特率为551 kbps)下都可以正常工作,没有中断和and啪声。 但是,在正常情况下,使用现有的蓝牙堆栈无法协商这样的比特率。

蓝牙堆栈修改

每个兼容A2DP的蓝牙堆栈都应支持双通道模式,但是没有办法强制使用此模式。

让我们向用户界面添加一个开关! 我为Android 8.1和Android 9制作了补丁程序,这些补丁程序在堆栈中和开发人员菜单中添加了对双通道的完全支持,并通过在双通道模式上添加一个勾号来作为附加的“高清音频”编解码器(如aptX,AAC或LDAC)来处理双通道模式。蓝牙设备设置如下所示:

图片

Android 9补丁
Android 8.1补丁

此复选框切换双通道模式,该模式配置为对EDR 3 Mb / s设备使用551 kbps,对EDR 2 Mb / s设备使用452 kbps

此补丁集已合并到以下备用固件中:
  • LineageOS 15.1 (自2019年3月31日起)和16.0 (自2019年5月13日起)
  • 复活混音 (自2019年5月14日起)
  • crDroid (自2019年5月13日起)


551和452 kbps来自哪里?

蓝牙时分技术旨在有效传输大型固定大小的数据包。 数据传输发生在插槽中,一次传输中发送的插槽数量最多为5。还有一些传输模式使用1或3个插槽,但不使用2或4。您可以以连接速度在5个插槽中传输多达679个字节。最高2 Mbps,最高1021字节,速度3 Mbps。 在3个插槽中,最大数据量分别为367和552字节。

图片

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

图片

在位通道= 38的双通道模式下使用SBC编码的44100 Hz音频,在一个帧中有16个块,8个频带,可产生164字节的音频帧,并具有452 kb / s的比特率。
音频有效负载应封装到L2CAP和AVDTP传输协议中,以从音频有效负载中减去16个字节的开销。

\开始{align *}帧长&= 4 + \ frac {子带\次通道} {2} + \\&\开始{cases} \ frac {块\次通道\次位池} {8}&\ text {如果是单通道或双通道模式,则\\ \ frac {子带+块\次比特池} {8}&\文本{如果是联合立体声模式} \\ \ frac {块\次比特池} {8}&\文本{如果是立体声模式} \\ \结束{cases} \结束{align *}





一个5插槽音频传输最多可以包含4个音频帧:
679 (EDR 2 mbit/s DH5) - 4 (L2CAP) - 12 (AVDTP/RTP) - 1 (SBC header) - (164*4) = 6 

单个数据包最多可传输11.7 ms的音频数据,这些数据将在3.75 ms内传输,并且数据包中还有6个未使用的字节。
如果稍微提高比特池,则无法再将4个音频帧打包到一个传输中。 您必须一次发送3帧,这会降低传输效率,减少在一个数据包中传输的音频量,并且会增加在恶劣无线电条件下出现音频卡顿的机会。

使用相同的原理选择EDR 3 Mbps的551 kbps比特率:对于Bitpool 47,每帧16个块,8个频段,帧大小为200字节,比特率为551 kbps。 单次传输最多可以捆绑5帧或14.6 ms的音乐。

计算所有SBC参数的算法非常复杂,如果尝试手动计算所有参数,您很容易犯错,所以我制作了一个交互式计算器来帮助有兴趣的人:
btcodecs.valdikss.org.ru/sbc-bitrate-calculator

那是为了什么?

与aptX声音质量的普遍看法相反,在某些情况下,它可以产生比标准328k比特率的SBC差的音频质量。

SBC以“从下到上”的方式为频段动态分配量化位。 如果整个比特率都用于较低和中频,则“最高频率”被“切断”(静音)。
aptX不断地量化具有相同位数的频带,这使其成为恒定的比特率编解码器:44.1 kHz为352 kbps,48 kHz为384 kbps。 它无法将“位”“转移”到最需要它们的频率。 与SBC不同,aptX不会“削减”频率,但会向其添加量化噪声,从而减小音频的动态范围,并有时会产生裂纹。 相反,SBC“吃细节”-丢弃最安静的区域。
平均而言,与SBC 328k相比,aptX在较宽频率范围的音乐中产生的失真较小,但在较窄频率范围和较宽动态范围的音乐中,SBC 328k有时会获胜。

让我们考虑一个特殊情况,钢琴录音。 这是一个频谱图:
图片

大部分能量位于0-4 kHz频率内,并持续高达10 kHz。
aptX文件的频谱图如下所示:
图片

这是SBC 328k:
图片

可以看出,SBC 328k定期完全切断16 kHz以上的范围,并对低于此值的频率范围使用了所有可用的比特率。 但是,aptX在人耳可听的频谱中引入了更多的失真,这可以从aptX频谱图减去原始音频频谱图中看到(失真越亮,失真越大):
图片

SBC 328k在0到10 kHz范围内对信号引入的失真较小,并且剩余的频率已被削减:
图片

485k比特率足以让SBC保存整个频率范围,而不会切断频段。
图片

在此样本上,SBC 485k在0-15 kHz范围内比aptX产生更好的结果,并且在15-22 kHz时,差异较小但仍然很明显(越暗,失真越小):
图片

使用原始音频和SBC / aptX编码的文件进行存档

通过切换到高比特率SBC,您可以在任何耳机上获得大部分时间优于aptX的声音。 在支持EDR 3 Mb / s的耳机上,551 kb / s SBC产生的声音非常接近aptX HD。

我们可以走得更远吗?

Android补丁集还有一个附加选项,可以进一步提高EDR 2 mbps设备的比特率。 您可以将比特率从452 kbps提高到595 kbps,以降低在无线电拥塞情况下传输的稳定性为代价。
只需将persist.bluetooth.sbc_hd_higher_bitrate变量设置为1:
 # setprop persist.bluetooth.sbc_hd_higher_bitrate 1 

极限比特率补丁当前仅在LineageOS 15.1中合并,而在16.0中不合并。

与设备的兼容性

几乎所有耳机,扬声器和车载音响系统都支持SBC双通道。 这也就不足为奇了-该标准要求其在任何解码设备中都必须支持。 在少数设备上,此模式会导致问题,但是这种情况很少见。
有关兼容设备的更多详细信息,请访问w3bsit3-dns.comxda-developers

声音差异比较

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

与Android开发人员联系

我试图与Google的许多蓝牙堆栈开发人员联系,请他们考虑将我的补丁包括在主要的Android分支AOSP中,但没有得到一个答案。 我在适用于Android的Gerrit代码检查系统中的补丁也没有收到开发人员的任何评论。
如果有人能告诉Google开发人员有关SBC HD for Android的实现,我将感到非常高兴。 gerrit补丁集已经过时(这是最早的修订版之一),但是如果开发人员对我的更改感兴趣,我将对其进行更新(更新起来不容易,因为我没有与Android Q兼容的设备) 。

结论

LineageOS,Resurrection Remix和crDroid固件的用户可以通过选中蓝牙设备设置中的复选框来增强蓝牙音频质量。 Linux用户还可以通过安装PaliRohár的补丁来获得更高的SBC比特率,其中包括添加对aptXaptX HD和FastStream编解码器的支持。

Source: https://habr.com/ru/post/zh-CN456476/


All Articles