蓝牙音乐静音

蓝牙音乐静音

在这里插入图片描述

大家想必对静音功能不陌生,相关场景下该功能很实用。现在的终端设备上有整个音频系统的静音,当然也有局部功能的静音,其中的蓝牙音乐也是提供静音操作的,本期和大家简单分享下蓝牙音乐静音在安卓系统中的实现。

蓝牙音乐的音频数据基本按照如下流程从 SRC 传送到 SNK:

在这里插入图片描述

蓝牙音乐静音的实现方案从上图也就非常明了,当前的安卓系统主要是在音频数据上报到 SNK 端的蓝牙协议栈时不进行保存,从而没有解码后的音频数据送入安卓多媒体系统 AudioTrack 来实现的。

上述方案的实现主要依赖协议栈 btif_a2dp_sink.cc 中定义的全局变量 btif_a2dp_sink_cb 中的两个基本变量:
在这里插入图片描述

rx_focus_state 变量受蓝牙服务层控制,变量含义顾名思义表示当前的蓝牙音乐是否具有音频焦点,而布尔值的 rx_flush 表示接收到的音频数据是否保存,其和 rx_focus_state 是一 一对应的关系:
在这里插入图片描述

这样蓝牙服务也就间接通过 rx_flush 在函数btif_a2dp_sink_enqueue_buf()中实现了蓝牙音乐静音。

蓝牙服务层中的接口为A2dpSinkStateMachine.informAudioFocusStateNative(),还需在framework层中添加接口函数才能打通应用层到蓝牙服务的调用,相信大家都可以轻松实现。

蓝牙音乐静音功能遇到的问题:
静音成功后再解除静音,重新播放蓝牙音乐往往会伴随着一声pop音

针对该问题首先需要分析下蓝牙协议栈将解码后的音频数据送入AudioTrack是否异常,打开宏变量 DUMP_PCM_DATA 记录蓝牙音乐音频数据PCM流,使用PCM流查看工具打开发现送给系统的PCM流很正常啊。

最后请教系统音频的同事后才了解其中的缘由,蓝牙协议栈在静音时是停止往系统AudioFlinger写数据,AudioFlinger会检测通道内是否有数据,这样超过一定时间没有数据后,AudioFlinger会关闭蓝牙协议栈对应的音频通道。然后再解除静音系统会重新打开音频通道,由于打开通道需要时间,但蓝牙协议栈是在解除静音后就开始往送AudioTrack中写数据了,由于存在这样的时序问题才会伴随着一声pop音。

基于AudioFlinger会检测是否有数据这一特性,理想的修复方案就是蓝牙协议栈在静音后往给AudioFlinger 写入空数据,从而避免 AudioFlinger 检测通道一定时间没有送数据后关闭通道。

解决方案:SNK 端的蓝牙协议栈还是正常接收音频数据加入 btif_a2dp_sink_cb.rx_audio_queue 队列保存,只需在音频数据解码完成的处理函数 btif_a2dp_sink_on_decode_complete()中加以判断,如果当前处于静音状态,则将解码后的数据直接memset重置为0的空数据即可。

蓝牙音乐静音的分享到这里就结束了,感兴趣的小伙伴欢迎私信留言一起讨论,共同学习,一起进步!

更多互联互通技术,欢迎关注微信公众号:Connectivity
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值