banner
NEWS LETTER

RK 平台 AOSP 支持第三方应用绕过 48kHz 重采样直出原采样率音频

Scroll down

在 RK 平台上,第三方应用播放音频时,常见现象是系统最终把音频统一拉到 48kHz 再送入混音链路。这样做方便系统混音,但会让 44.1kHz、96kHz、192kHz 这类原始采样率在设备侧被二次处理。

如果目标是音乐播放、专业音频、采集回放一致性验证,或者对时钟抖动和重采样损耗比较敏感,就需要让应用走直出链路,尽量按原采样率输出,而不是默认进入 48kHz mixer。

本文给出的方案核心是:在 AOSP 音频策略里把“可直出”的输出能力暴露出来,在 HAL 侧保证该采样率真的能打开设备通路,再让第三方应用用 AudioTrack 走 direct / offload 路径。这样才能把“看起来支持”变成“实际能出声”。

一、问题背景

RK 平台上的 AOSP 音频框架通常会经过 AudioPolicyAudioFlinger、HAL、Codec/AMP 这几层。默认混音路径为了兼容性和多应用共享,往往会把 PCM 统一到一个主工作采样率,最常见就是 48kHz。

这个机制本身没有问题,但它不适合所有场景。第三方播放器、离线测试工具、无损播放 App、采样率校验工具,往往希望设备按文件原始采样率输出,减少系统侧重采样和不必要的格式转换。

讨论范围要收窄:这里不讨论 DRM、平台私有播放器、独占式专业音频 API 的定制,也不讨论蓝牙和 USB Audio 的外设链路,只聚焦 RK Android 设备本地扬声器或耳机口的直出能力。

二、核心思路

  • 不是“关闭 48kHz”,而是“补齐直出通路”。系统混音仍然可以保留,关键是让满足条件的流有机会绕开 mixer。
  • 直出成立的前提有三个:应用侧请求正确,策略层暴露 direct profile,HAL 侧真的支持该采样率和格式。
  • 只改 Java 层没用。AudioTrack 申请直出但策略文件没有对应 profile,最后仍然会被回落到 mixer。
  • 只改策略也不够。audio_policy_configuration.xml 写了 96kHz,如果 HAL 打不开这个采样率,最终还是失败或回退。
  • 最稳妥的办法是把“支持的采样率、声道、格式、输出标志”做成一条闭环链路,按设备能力逐项打通。

常见判断逻辑可以概括成一句话:应用请求的参数必须和 direct profile 一致,并且该输出设备要允许独占/直出打开。

三、落地步骤

  1. 先确认硬件链路是否真支持目标采样率。

    查看 codec、I2S、PA、DSP 或声卡驱动能力,确认目标文件的采样率不是只在软件层“声明支持”。

    1
    2
    3
    tinymix
    cat /proc/asound/cards
    cat /proc/asound/pcm
  2. audio_policy_configuration.xml 中为直出链路增加对应 profile。

    重点不是只写一个大列表,而是让 direct output profile 明确匹配目标采样率、声道和 PCM 格式。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <module name="primary" halVersion="7.0">
    <mixPorts>
    <mixPort name="primary output" role="source">
    <profile name="primary pcm"
    format="AUDIO_FORMAT_PCM_16_BIT"
    samplingRates="44100,48000,96000"
    channelMasks="AUDIO_CHANNEL_OUT_STEREO" />
    </mixPort>

    <mixPort name="direct pcm" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT">
    <profile name="direct pcm 96k"
    format="AUDIO_FORMAT_PCM_16_BIT"
    samplingRates="96000"
    channelMasks="AUDIO_CHANNEL_OUT_STEREO" />
    </mixPort>
    </mixPorts>
    </module>
  3. 让 HAL 的 open_output_stream 能按目标采样率建流。

    如果框架请求 96kHz,HAL 不要悄悄改回 48kHz。应该在参数不支持时明确失败,避免上层误判为直出成功。

  4. 在应用侧显式申请 direct 路径。

    纯普通 AudioTrack 很容易走混音器。第三方 App 需要按能力申请低延迟或 direct 输出,并确保播放参数和设备能力一致。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    AudioAttributes attrs = new AudioAttributes.Builder()
    .setUsage(AudioAttributes.USAGE_MEDIA)
    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
    .build();

    AudioFormat format = new AudioFormat.Builder()
    .setSampleRate(96000)
    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
    .build();

    AudioTrack track = new AudioTrack.Builder()
    .setAudioAttributes(attrs)
    .setAudioFormat(format)
    .setTransferMode(AudioTrack.MODE_STREAM)
    .build();
  5. 用日志验证是否真的绕开了 48kHz。

    重点看 AudioFlingerAudioPolicyManager 和 HAL 日志,确认输出轨道的采样率没有被重写,且没有回落到 mixer track。

    1
    adb logcat | grep -iE "AudioFlinger|AudioPolicy|primary output|direct"
  6. 做回归测试。

    分别测试 44.1kHz、48kHz、96kHz 三类文件,确认:

    • 48kHz 仍可正常播放
    • 目标采样率能直出
    • 非支持参数会明确失败,而不是静默重采样

四、常见坑

  • 只在 XML 里增加采样率,不改 HAL,最后会出现“策略支持、设备不支持”。
  • AudioTrack 申请了目标采样率,但没有匹配 direct profile,系统仍会回落到 mixer。
  • 设备同时挂了多个输出端口,策略优先级不清晰时,容易把直出流导到错误端口。
  • 厂商做了内部重采样,表面上看是 96kHz 输出,实际上 DAC 前还是被转成 48kHz。
  • 仅验证单个文件不够。不同编码、不同声道数、不同 buffer size 都可能触发不同路径。
  • 如果系统启用了音效、均衡器、音量增强,直出链路可能被迫回到可混音路径。

五、检查清单

  • 已确认目标采样率在硬件和驱动层可打开
  • audio_policy_configuration.xml 已为 direct 输出补齐 profile
  • HAL 不会把目标采样率静默改写成 48kHz
  • 第三方应用能显式创建目标采样率的 AudioTrack
  • AudioFlinger 日志确认没有进入混音重采样路径
  • 44.1kHz、48kHz、96kHz 文件都做过实机回归
  • 音效和增强链路已评估对直出路径的影响

六、小结

RK 平台上让第三方应用绕过 48kHz 重采样,关键不是某一个开关,而是策略层、HAL 层和应用层一起配合,把直出链路真正打通。

如果只改其中一层,最后大概率还是会回到默认 mixer。把支持能力做成闭环,才能让“原采样率输出”在工程上稳定成立。

其他文章
目录导航 置顶
  1. 1. 一、问题背景
  2. 2. 二、核心思路
  3. 3. 三、落地步骤
  4. 4. 四、常见坑
  5. 5. 五、检查清单
  6. 6. 六、小结
请输入关键词进行搜索