避免安卓流媒体音乐App输出到USB音频设备时的PCM重采样
本帖最后由 R.I.P 于 2023-2-8 00:25 编辑玄学归数码区。这个也算是一个很有年头的比较棘手的问题了。当然很大程度上这是一个伪需求,折腾多半不会带来什么可闻的变化,主要是带来心理上的满足。。
一般来说对于这个需求我们会希望找到一个比较通用的办法,使得它在大部分的设备上都能直接奏效,不需要特别的适配。但是如果你琢磨过Android在音频服务上的整套设计的话,就会发现这实际上是个很难完美解决的事情。在一个USB DAC设备的mixer thread第一次被创建的时候,Android就会根据当前的audio policy配置选择一种采样率以及bit depth组合,与该设备协商,除非audio server重启或者你的设备被拔出等情况发生,这个设备上之后发生的音频回放都会使用这个采样率+bit depth组合。一个比较彻底的改法是修改audio server(AudioFlinger)的相关代码,在一个mixer thread上如果只有一个audio session在跑,且这一路输入的采样率和当前与USB设备协商的采样率不同的话,就手动协商成这(唯一)一路输入的采样率+bit depth。遗憾的是,这个调用路径上的相关方法的符号在Android大版本更新的时候总会有些或大或小的变化,要做一个通用的binary patch会很麻烦,而且这个操作也依赖USB Audio HAL到底长什么样子。所以这个想法基本只对几家开源做得相对好的品牌的设备有可行性,并且最方便的办法还是你改完audio server的相关代码以后自己编译出完整的系统镜像刷上。
不过我们还是有看起来丑陋但是实际效果很好的替代方法。半个月前我发现了一个github项目 https://github.com/yzyhk904/USB_SampleRate_Changer,这套脚本能够实现在不重启系统的前提下修改audio policy给USB设备默认匹配到的采样率设置,然后自动重启audioserver。经过测试,可以确认使用主流的音频API(如AudioTrack)的流媒体App(如Apple Music)在使用该脚本切换采样率时当前的播放并不会暂停,仅会有非常短的静音。于是我们可以采用这样的办法:在你要用的流媒体App调用AudioTrack这样的API的时候按需调用这个外部脚本来切换采样率。我写了一个简单的Xposed模块(https://wwxa.lanzouy.com/b02e7avgb 密码:5ayu)来对Apple Music实现这件事。使用前先把USB_SampleRate_Changer这个项目的代码放到/sdcard,确保/sdcard/USB_SampleRate_Changer/USB_SampleRate_Changer.sh文件存在,并把magisk设置中的"root name space mount mode"调整为global即可。
遗憾的是,在保证USB DAC工作在与唯一的input stream一致的采样率和PCM bit depth下仍然不能保证播放是bit-perfect的,原因是即使mixer只有一路输入,mixer也会进行一些处理,详见USB_SampleRate_Changer的readme中关于change_resampling_quality.sh的解释。在上面的xposed模块里,我在每次AM启动的时候调用change_resampling_quality.sh,使用的是readme的表格中"This script's A12 general purpose"这组参数。如果要做到bit-perfect,应该可以通过选择更加激进的重采样参数(来保证mixer算出的东西和输入足够接近,在round到输出的bit depth以后没有变化。readme中已经演示了对于44k 16bit的输出是可以做到的,对24bit和32bit原则上也可以,不过可能就会需要很长的buffer,增加耗电和播放延迟了),或者对audio server里mixer的实现做一些修改(这个玩意要做个通用patch的难度比最开始说的修改就低太多了)。
我不懂安卓,但是略微了解过解决SRC问题的方法。首先很多本地APP都支持独占,比如海贝,viper。不过这个答案没有意义。那么其实苹果、蓝厂和小米的大部分机型都支持自动切换采样率,比较拉跨的只有绿厂和华子。如果你不幸是这两家的用户,那么QQ音乐可以拯救你,它的手机端已经支持独占了,真是感人。另外拉跨这部分手机也无非是锁48的倍数或者44.1的倍数,而你很容易判断自己听的是48还是44.1从而避开不利局面。
我只相信 android.hardware.usb API 和它的最佳实现 USB Audio Player Pro 了 千本blur 发表于 2023-2-8 01:16
我不懂安卓,但是略微了解过解决SRC问题的方法。首先很多本地APP都支持独占,比如海贝,viper。不过这个答 ...
你对不幸一无所知
—— 来自 Unihertz Titan Slim, Android 11上的 S1Next-鹅版 v2.5.2-play R.I.P 发表于 2023-2-8 01:30
你对不幸一无所知
—— 来自 Unihertz Titan Slim, Android 11上的 S1Next-鹅版 v2.5.2-play ...
此话怎讲? 千本blur 发表于 2023-2-8 01:35
此话怎讲?
刚刚那层拿我的主力机发的,是个全键盘mtk的山寨机
页:
[1]