蓝牙无线音频技术:哪个更好?


随着技术的发展,如此熟悉的“管”式模拟耳机已被载入史册-越来越多地被蓝牙无线同类产品取代。

为了防潮和防尘,现代智能手机被剥夺了通常的连接器。

开发人员发布了所有新版本的蓝牙协议和所有新版本的编解码器,承诺“更快,更高,更强”-减少播放延迟,提高质量。

一切都很好吗? 让我们看看。

引言


我不会深入研究协议的技术实现以及无聊的规范。 亲爱的ValdikSS ,他在很大程度上是本文的启发,甚至是科学顾问,他正在准备有关编解码器的综合材料-那里的所有内容都将更加详细和技术正确。

我想更多地谈谈个人经历。 好吧,有点娱乐性(无聊?)练习。

一年半以前,我对aptX的想法感到兴奋。 是的,我读了很多这样的评论,并且相信所有这些技术上的曲折。 一个孩子出生了-我真的很想在晚上和我的妻子一起戴着耳机看节目,而又不吵闹,也不吵醒屋里的任何人。

结果是什么?

质素


让我们从数字和事实开始(您好,维基百科!)

SBC是一种很好的旧编解码器,符合A2DP标准。 该编解码器是Frans de Bont (F.de Bont,M.Groenewegen和W.Oomen,“ 128 kb / s的高质量音频编码系统”,第98 AES公约,1995年2月25-28日)的工作和使用的结果。在专利EP-0400755B1中描述的算法。 值得注意的是,该专利的作者仅允许在蓝牙应用程序中免费使用SBC,但是该专利于2010年6月2日到期。 由于A2DP标准非常普遍,因此很难找到不支持SBC的耳机或扬声器。

编解码器提供16、32、44.1、48 kHz的采样频率,流速为10-1500 kbit / s。 是的,您没听错。 最高1500 kbps。 编解码器中根本没有比特率限制。 但是稍后会更多。

aptX编解码器于1988年在贝尔法斯特女王大学开发 。 是的,在蓝牙技术问世之前已有十几年了,因此编解码器被用于专业音频设备中。 高通公司目前拥有这些权利,因此使用需要许可和特许权使用费。 截至2014年,成本大致如下:一次性付款6,000美元,对于最多10,000个设备的参与者,每发布一台设备,≈1美元。 因此,许多具有Snapdragon 835、845、821、820、810、805、801、800、650、615、410芯片的设备都是很可能的,并支持aptX,但由于未购买许可证,该设备并未在那里激活。 关于它-也在下面。

编解码器具有16位的位深度和48 kHz的采样频率,可提供384 kbit / s(双通道)位速率。

正式支持aptX的产品列表 。 您可以在Aliexpress上找到许多支持aptX的未知系统,但要为事实做好准备,那就是实际上将有相同的旧SBC,而且仅此而已。

aptX HD-相同的编解码器,但具有不同的编码配置文件,流速度为576 kbit / s,支持高达48 kHz的采样频率和高达24位的位深。 有人称其为aptX无损编解码器-但这完全是胡说八道,仅是因为目前无法实现可以承载无损数据的流的价值。 该编解码器的一个特殊优势是可调整的编码延迟,在48 kHz的采样频率下可以将其降低到1 ms。 同样,从处理器加载的角度来看,编解码器是极其有利的,与MP3和AAS相比,它具有优势。

正式支持aptX HD的产品列表 。 他足够小。

aptX低延迟 (或LL)是编解码器的特殊版本,可让您将声音延迟时间减少到40毫秒以下。 正式支持aptX LL的产品列表

图片

她在那儿。 曾经是这张照片用细小东西给我买了。 延误! 毕竟,谁想听到某部动作片的爆炸声,恐怖片中怪物的尖叫声或足球比赛结束后人群的吼叫声?

但是,这真的是这样吗?

las,不。

与任何营销材料一样,数字牵强。 延迟在很大程度上取决于系统中的缓冲和编解码器的实现。 因此,SBC的延迟可能会小于40 ms,考虑到电视广播的标准(+40 ms ... -60 ms),这是完全可以接受的。

总结:

  1. 现有的编解码器无法比有线技术更好,因为没有任何编解码器可以实现真正的无损压缩。
  2. 最受欢迎的编解码器是SBC。 他在设置上最灵活。 而且,尽管aptX发行得较早,但它无法击败SBC的流行,这显然是因为后者是免费的。
  3. 声音质量在很大程度上取决于编解码器的实施以及一般而言耳机/扬声器的硬件性能-如果扬声器本身较弱,则任何编解码器都无法提高质量。 因此,在将来,比较质量时,我们将讨论在相同的扬声器/耳机上使用相同的源,使用不同的编解码器播放相同内容的情况。

实际且非常主观的结果




这些信息基于已经提到的一年半的操作,比较和吸引外部听众经验。

体验的基础是在可以选择编解码器的SONY Walkman NWZ-A17播放器上收听无损音乐,以及观看通过Avantree Priva III输出音频的各种节目。

一共有三个耳机:Sennheiser PMX 60,Koss Porta Pro和Koss UR-20。

Jabra BT3030(SBC)和Avantree Clipper Pro(aptX)被用作无线信号接收器。

还使用了Voombox Outdoor(SBC)扬声器和Aftershokz Trekz Titanium(aptX)骨传导耳机。

所有均衡器和增强器均已关闭-这很重要。

总计:

  1. 有线连接播放的声音质量始终更好。 毫无疑问。
  2. SBC和aptX之间的区别很难听到-仅在某些类型的音乐中。 例如,文章的作者清楚地听到了古典乐曲中大提琴独奏的差异,而对于小提琴和低频乐器,这种差异不太明显。 在现代流派(流行,电子音乐和摇滚)中,听不到差异。 在某些情况下,主观上似乎SBC的声音传输要比aptX好。
  3. 仅当您连接到同一信号源并将不同的接收器插入不同的耳朵时,才能看到SBC与aptX之间的延迟(例如,左声道为SBC,右声道为aptX)。 几乎不可能看到图片的延迟,但是因为aptX用于动态场景和内容的故事是一个神话。
  4. 令人惊讶的是由相当便宜且“不出名”的Voombox Outdoor的音质引起的。 显然,这是上面提到的SBC的成功实施。
  5. aptX在具有骨骼传导功能的耳机中的实现是完全难以理解的-该技术非常具体,因此由于该技术本身,质量损失非常大。 考虑到设备操作的“范围”很小,与两个设备配对的实施效果非常差,我可以说Aftershokz是一家在营销方面投入更多资金而不是在开发方面投入资金的公司。


我并不是说,如果您连接各种光谱分析仪等等,您可以并且应该看到两者之间的区别。 但是人耳,甚至更糟的是普通人耳,不是频谱设备,因此不会听到所有这些细微差别。

实践:修复可以修复的问题


第1部分。打开aptX


如前所述,在某些设备中禁用了aptX的使用,可能是为了避免专利起诉。

通过滑动库设备以实现编解码器并在build.prop中编写使用此编解码器的功能,可以非常简单地解决此问题。

在Internet上,有许多这种性质的解决方案。 我自由地将它们组合为一个,同时将其实现为Magisk的模块。 是的,我真的很喜欢这个项目,我认为以Magisk模块的形式实现系统更改是一种更好,更安全的解决方案,它能够将系统保存为原始格式,并且可以轻松回滚。

该模块可从此处下载。 是的,我了解github。 不,直到我有时间把它放在那里。

该模块将自动模拟build.prop中的条目,包括aptX,如果可能的话,还包括aptX HD。



第2部分。提高SBC比特率


如先前报道,SBC编解码器基本上没有比特率限制。 但是,制造商通常将单声道设置为342 kbit / s,立体声设置为345 kbit / s,以确保在所有类型的接收设备上都能可靠运行。

同时,从2007年到2015年有效的A2DP v1.2规范要求所有解码设备以单声道最高320 kbit / s的比特率正常工作,而立体声信号则以512 kbit / s的比特率正常工作。

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

实际上,事实并非如此。 ValdikSS进行的一项广泛研究中,发现几乎所有接收设备都能以454 kbit / s的比特率可靠地工作,而相当数量的接收设备以507 kbit / s的比特率可靠地工作。

在研究中, ValdikSS还表明,与人们普遍认为aptX编解码器质量相反,在某些文件上,其结果可能比标准328 kbps的SBC产生更差的结果,而切换到高比特率的SBC所产生的声音通常会超过aptX,在任何耳机上。

根据这些数据, ValdikSS向Lineage OS和Google的开发人员发送了评论,但到目前为止还没有任何反应。

因此,我们只能手动修改蓝牙协议栈。

我们需要一个能够反编译ARM,任何HEX编辑器(我使用WinHEX)和我们设备中的bluetooth.default.so文件的IDA Pro。 通常,它位于路径/ system / lib / hw上,而且很少-路径/ system / lib64 / hw(肯定需要root访问)。

因此,打开bluetooth.default.so文件,下面描述的操作和修改仅适用于原始Android堆栈(bluedroid)。 如果您在IDA Pro中看到“需要的库'com.qualcomm.qti.bluetooth_audio@1.0.so'”之类的内容,则该说明很有可能对您没有帮助。



我们的首要任务是在标准配置中用双通道替代联合立体声。

我们将使用bta_av_build_src_cfg函数

要在IDA中找到此过程,我们将在调试日志“无法解析src cap ret =%d”中使用搜索查找特征消息





结果,很快我们就以代码形式找到了函数本身:



我们的任务是替换支票的原始结构

if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_JOINT) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_JOINT; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_STEREO) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_STEREO; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_MONO) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_MONO;</code>  <code> if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_STEREO) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_STEREO; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_DUAL) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_DUAL; else if (src_cap.ch_mode & A2D_SBC_IE_CH_MD_MONO) pref_cap.ch_mode = A2D_SBC_IE_CH_MD_MONO; 

有几种方法可以做到这一点。

首先是按照检查顺序将指令TST.W R0,#1替换为TST.W R0,#4并将MOVS R0,#1替换为MOVS R0,#4:



在字节码中,这是将x01替换为x04。 重要的是要注意字节的特征序列,通过该序列可以找到此模式。 在不深入细节的情况下,我会说本质上是对序列的搜索

 10 20 8D F8 04 00 9D F8 0D 00 10 F0 01 0F ?? ?? 10 F0 02 0F ?? ?? 10 F0 04 0F ?? ?? 10 F0 08 0F ?? ?? 08 20 ?? ?? 01 20 ?? ?? 02 20 ?? ?? 04 20 

及其替换

 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 04 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 04 ?? ?? ?? ?? ?? ?? ?? ?? ?? 

但是,该方法具有缺点。

许多编译器根据优化来更改命令的执行顺序。 并且在这种情况下,不可能找到所需的模式,有时将结构中的检查机制通常引入到内联代码中。 因此,更改常量btif_av_sbc_default_config更加可靠。

对于初学者-找到她。 她刚开始担任我们的职务,因为

 void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap) { tA2D_SBC_CIE src_cap; tA2D_SBC_CIE pref_cap; UINT8 status = 0; /* initialize it to default SBC configuration */ A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &btif_av_sbc_default_config, p_pref_cfg); /* now try to build a preferred one */ /* parse configuration */ if ((status = A2D_ParsSbcInfo(&src_cap, p_src_cap, TRUE)) != 0) { APPL_TRACE_DEBUG(" Cant parse src cap ret = %d", status); 

她在这里:





可以看出btif_av_sbc_default_config本身是一个字节序列20 01 10 04 01 35 02,而第一个字节编码采样频率,可以是10(48 kHz)和20(44 kHz),因此不具体。 因此,我们的任务是替换序列
01 10 04 01 35 02

04 ?? ?? ?? ?? ??

这将允许您以类似的方式更改结构的逻辑,但是同时优化编译器不会引起问题。

在某些情况下,耳机或扬声器本身会启动连接。 在这种情况下,模式由bta_av_co_audio_init函数确定。

该函数的特点是“ bta_av_co_audio_init:%d”行 ,可以在代码中轻松地进行搜索:


在以下命令中枚举可能的连接模式:

  switch (index) { case BTIF_SV_AV_AA_SBC_INDEX: /* Set up for SBC codec for SRC*/ *p_codec_type = BTA_AV_CODEC_SBC; /* This should not fail because we are using constants for parameters */ A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info); /* Codec is valid */ return TRUE; 

常量bta_av_co_sbc_caps具有以下结构

 const tA2D_SBC_CIE bta_av_co_sbc_caps = { (A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */ (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL), /* ch_mode */ (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */ (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */ (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S), /* alloc_mthd */ BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */ A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */ }; 

该常数很容易在代码中找到,在我的情况下为20 0F F0 0C 03 35 02:



注意字节0F-它提供了与任何有效模式连接的能力,因为

 x0F = A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL = x08 | x02 | x01 | x04 

我们的任务是如下更改此值:

 x0F = A2D_SBC_IE_CH_MD_DUAL = x04 

因此,有必要更换

?? 0F F0 0C 03 35 02

?? 04 ?? ?? ?? ?? ??

因此,在通过设备启动连接的情况下以及在信号接收端启动连接的情况下,我们都强制堆栈以双通道模式进行连接。

现在,您需要删除比特率限制或提高其上限。

需要处理btif_media_task_get_sbc_rate 。 同样,要搜索特征线“检测到非edr a2dp接收器,将速率限制为%d”,我们在代码中查找函数:


比特率限制以字符串表示
UINT16速率= DEFAULT_SBC_BITRATE(依次为328 kbps

在代码中,是这样的:



将此值更改为454 kbit / s-高于标准值,并且适用于绝大多数接收器。 为此,请替换字节

B1 4F F4 A4 74 ?? E0

?? ?? ?? E3 ?? ?? ??

您还应该按模式搜索。

E0 4F F4 A4 74 ?? E0
并替换为
?? ?? ?? E3 ?? ?? ??
-这是许多设备所必需的。

E3的值可能会有所不同,具体取决于所需的最大比特率:

  • E3-454 kbps
  • F1-482 kbps
  • F3-486 kbps
  • 10-576 kbps
  • 48-无限制

通常,这由操作MOV.W R4,XXX的字节码确定。

实际上,值得尝试并选择所有接收设备都能稳定接收信号的最大值,而不会出现破裂,中断或失真。

在实验中的所有接收器上(我在上面指出),该值为576 kbit / s,小米Redmi 4x MIUI10 Android 7.1手机是信号源。

根据描述的操作,创建了一个通用补丁程序,该补丁程序可在Bluetooth.default.so中找到指定的模式并将其替换? 包括强制双通道模式,并将比特率限制设置为454 kbps。 如有必要,可以根据对相应字节的搜索和替换轻松更改限值-细心的阅读器将轻松完成此操作。

我强调:该修补程序仅在bluedroid堆栈的情况下有效,而在Fluoride堆栈和Android 8及更高版本的情况下很可能不会成功。

可以从这里下载补丁。

强烈建议您将原始文件替换为Magisk模块,对于我自己,我这样做如下请注意 :这些模块是我为小米Redmi 4x 3/32 GB手机由我制作的,撰写本文时使用的是当前全局稳定的MIUI 10固件。对于您而言,如上所述,bluetooth.default.so文件必须替换为您自己的补丁补丁。 也有可能必须沿着路径/ system / lib64 / hw复制该文件-这取决于手机的型号和固件版本。

如果发现某些接收设备不支持双通道,则使用Magisk模块的这种方法可以轻松更改最大比特率,并且通常禁止更改。

结论


目前,为了追求销售,许多公司都提出了一些技术创新作为更高价格的理由。

实际上,事实证明,现有的廉价技术没有得到充分开发,并且技术创新没有得到充分实施,这极大地影响了质量。

很多时候,用户会体验到“安慰剂效应”,仅凭产品更新或更丰富的色彩就可以说服自己达到完美。 实际上,这种质量是虚构的。

尽管与有线版本相比,无线音频传输的质量明显下降,但现代设备制造商似乎正致力于向无线技术的完全过渡。 同时,使用营销技巧来证明价格上涨是合理的:防止电话浸入水中(如何在水下说话?为什么将设备掉入水中?),使用更昂贵的编解码器等。 同时,现有流行的SBC编解码器的潜力没有得到充分利用。

Google无法获得有关328 kbps比特率限制的任何澄清,也无法消除该限制,因此无法从Lineage OS的开发人员的蓝牙菜单中添加启用双通道的选项。

感谢所有读完本书的人!

注释中的讨论和有关LDAC编解码器的空格引起了一些延续。

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


All Articles