RK Android平台音频调试指南:从基础到实战,解决多设备输出、声卡异常等核心问题

电子说

1.4w人已加入

描述

 

 

 Android 开发中,音频模块的调试往往是 老大难”—— 多声卡无法区分、多设备同时输出没声音、HDMI 录音崩溃… 这些问题不仅影响用户体验,还会消耗大量开发时间。

 

 

瑞芯微(Rockchip)针对 RK 平台推出的 MultiAudio 方案,专门解决 Android 原生音频框架的局限,同时提供了一套清晰的调试方法论。今天这篇文章,就从实战角度出发,带大家搞定 RK Android 平台的音频调试,覆盖基础操作、常见 Bug 解决、多设备控制等核心场景。

Android

 

 

 

一、先搞懂:Android 原生音频的 痛点” 与 MultiAudio 解决方案

 

在聊调试前,我们得先明白为什么需要调试”——Android 原生音频框架存在不少局限,这也是 RK MultiAudio 方案的出发点:

 

 

1.多声卡认不出、用不了:即使设备支持多个声卡(比如双 HDMISPDIF),原生系统会按 AudioPolicy 优先级选最高的,无法让不同声卡同时输出不同声音;多个同类型声卡(如双 HDMI)更是无法区分。

 

 

2.多设备录音需适配Android 12 虽支持多设备同时录音,但原生代码默认不支持,需要厂商针对性开发。

 

 

3. APP 音频冲突:系统音频焦点机制会导致多屏同时播放视频时出现暂停,影响多场景使用(如会议投屏 + 本地播放)。

 

 

 RK MultiAudio 方案正好补上这些短板,核心能力包括:

 

 

 HDMI/DP 插拔识别 声音分离(HDMI_0/HDMI_1DP_0/DP_1 独立输出);

 

 

第三方 APP 按包名指定声卡(如 MX Player 走扬声器、RockVideoPlayer 走 HDMI);

 

 

JAVA 层通过接口直接控制声卡;

 

 

 HDMI IN 同时录音(HDMIIN_0/HDMIIN_1 独立录音);

 

 

多设备音量同步调节与保存。

 

 

二、基础调试:先搞定声卡识别” 与 驱动验证

 

调试的第一步,是确认硬件通路是否正常”—— 也就是声卡是否被正确识别、驱动是否能工作。这两步操作简单,但却是排查问题的基础。

 

 

1. 查看声卡:确认设备是否被系统识别

 

通过 adb 执行命令,查看当前系统已注册的声卡:

 

 

  •  
cat /proc/asound/cards

 RK3588 为例,正常输出会类似这样(能看到扬声器、HDMI INHDMI 0/1 等声卡):

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
0 [rockchipes8388 ]: rockchip-es8388 - rockchip-es8388                     rockchip-es83881 [rockchiphdmiin ]: rockchip_hdmiin - rockchip,hdmiin                     rockchip,hdmiin2 [rockchiphdmi0 ]: rockchip-hdmi0 - rockchip-hdmi0                     rockchip-hdmi03 [rockchiphdmi1 ]: rockchip-hdmi1 - rockchip-hdmi1                     rockchip-hdmi1

如果某块声卡没出现(比如 HDMI 0 缺失),先排查硬件连接(如 HDMI 线是否插好),再检查 DTS 配置是否正确。

 

 

2. 测试驱动:验证声卡能否正常出声

 

确认声卡识别后,用tinyplay 工具测试驱动是否正常(需系统集成 tinyalsa 工具集)。

 

 

以测试 HDMI 0 声卡(对应上述输出中的索引 “2”)为例:

 

 

1.准备一个 WAV 格式的音频文件(如 test.wav),推到设备的 /data 目录;

 

 

2.执行命令播放:

 

 

  •  
tinyplay /data/test.wav -D 2 -d 0

-D:指定声卡索引(这里“2” 对应 rockchiphdmi0);

 

 

-d:指定设备编号(通常为 0)。

 

 

如果能正常听到声音,说明 HDMI 0 声卡驱动没问题;若没声音,优先排查驱动配置(如 DTS 中声卡节点是否启用)。

 

 

三、实战:大常见音频 Bug 及解决方案

 

调试中最头疼的是明明配置了,却出问题”—— 我们整理了 RK 平台最常遇到的 类音频 Bug,附详细解决步骤。

 

 

1. 问题 1:更新代码后,HDMI 突然没声音(之前正常)

 

现象:代码同步到最新后,HDMI 无音频输出,查看声卡却能识别到。

 

 

原因:新框架支持多 HDMI 识别,若系统只有 路 HDMI,上层会默认调用 “hdmi0” 声卡,但 DTS 中声卡名可能配置成了 “hdmi1”,导致匹配失败。

 

 

解决:修改 DTS 文件,将声卡名改为 “rockchip-hdmi0”

 

 

  •  
  •  
  •  
  •  
  •  
# 找到 DTS 中 HDMI 声卡节点rockchiphdmi1: rockchip-hdmi1 {-   rockchip,card-name = "rockchip-hdmi1"+   rockchip,card-name = "rockchip-hdmi0"};

2. 问题 2UBoot 开 Logo 后,HDMI 没声音(插拔线后恢复)

 

现象:开启 UBoot Logo 显示后,HDMI 开机无声音,手动插拔一次 HDMI 线才正常。

 

 

原因HDMI 的 extcon(外部连接状态控制器)状态更新不及时,系统误以为 HDMI 未连接。

 

 

解决:修改 DRM 驱动代码,强制同步 extcon 状态:

 

 

drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c 中添加状态同步逻辑:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
mutex_lock(&hdmi->mutex);if (result != hdmi->last_connector_result) {    dev_dbg(hdmi->dev, "read_hpd result: %d", result);    // 同步 extcon 状态    extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, result == connector_status_connected);    handle_plugged_change(hdmi, result == connector_status_connected);    hdmi->last_connector_result = result;}mutex_unlock(&hdmi->mutex);

3. 问题 3SPDIF 与其他声卡同时出声,声音断断续续

 

现象SPDIF(光纤 同轴)与扬声器 / HDMI 同时播放时,音频卡顿、断连。

 

 

原因1DMA 音频流位置计算错误;2)声卡 MCLK 配置不合理。

 

 

解决:两步操作:

 

 

a.集成 3 个关键 Kernel 补丁(修复 DMA 与 PM 问题):

 

 

修复 DMA 流位置计算:ALSA: pcm_dmaengine: always get stream position from DMA driver

 

 

修复 DMA  runtime PM 失衡:dmaengine: pl330: Fix unbalanced runtime PM

 

 

提升 DMA 循环传输效率:dmaengine: pl330: Improve dma cyclic transfers efficiency

 

 

a.修改 DTS 中 SPDIF 声卡节点,添加 MCLK 配置:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
spdif_tx0_sound: spdif-tx0-sound {    status = "okay";    compatible = "simple-audio-card";+   simple-audio-card,mclk-fs = <128>; // 添加这行    simple-audio-card,name = "rockchip,spdif-tx0";    // 其他配置...};

4. 问题 4HDMI IN 录音时,偶尔出现 Audio 服务崩溃

 

现象:用 HDMI IN 录制外部音频(如机顶盒信号)时,Audio 服务突然崩溃,日志提示 “TimeCheck 超时

 

 

原因HDMI IN 录音的等待时间过短,导致超时触发服务重启。

 

 

解决:修改 I2S-TDM 驱动,延长录音等待时间:

 

 

sound/soc/rockchip/rockchip_i2s_tdm.c 中添加超时配置:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream, int cmd) {    // 其他逻辑...    break;+   // 针对录音流,延长等待时间到 500ms+   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {+       substream->wait_time = msecs_to_jiffies(500);+   }    return ret;}

5. 问题 5:更新代码后,声卡完全没声音(优先级冲突)

 

现象:同步代码后,所有声卡都没声音,查看proc/asound/cards 能识别到声卡。

 

 

原因RK 默认代码基于多声卡设备(如 RK3588 EVB1 支持 路声卡),优先级为 HDMI0 > HDMI1 > DP0 > DP1;若实际设备只有 路 HDMI1,系统仍优先调用 HDMI0(但无对应声卡),导致所有声音无输出。

 

 

解决:修改WiredAccessoryManager.java,屏蔽 HDMI0 的优先级判断:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
# 文件路径:frameworks/base/services/core/java/com/android/server/WiredAccessoryManager.javaelse if (headset == BIT_HDMI_AUDIO) {-   Slog.d(TAG"hdmi_0 plug");-   outDevice = AudioManager.DEVICE_OUT_HDMI;+   // 屏蔽 HDMI0 识别,避免优先级冲突+   // Slog.d(TAG, "hdmi_0 plug");+   // outDevice = AudioManager.DEVICE_OUT_HDMI;else if (headset == BIT_HDMI_AUDIO_1) {    Slog.d(TAG"hdmi_1 plug");    outDevice = AudioManager.DEVICE_OUT_HDMI_1;

四、实用技巧:多设备输出与 HDMI IN 录音的调用方法

 

除了调试,掌握 MultiAudio 的核心调用方式,能让开发更高效。

 

 

1. 多设备输出:指定声卡的 种方式

 

1JAVA 层通过 AudioSessionId 控制

 

MediaPlayer 初始化时,通过setAudioSessionId 指定声卡,必须在 setDataSource 前调用

 

 

  •  
  •  
  •  
  •  
  •  
  •  
MediaPlayer mp = new MediaPlayer();// 指定声卡:PRIMARY(57)=扬声器,HDMI0(65),DP0(73),HDMI1(81),DP1(89)mp.setAudioSessionId(65); // 声音从 HDMI0 输出mp.setDataSource("/data/test.mp4");mp.prepare();mp.start();

2)按 APP 包名绑定声卡

 

适合需要固定 APP 输出设备的场景(如会议软件固定走 HDMI),修改 AudioTrack.cpp

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
#if MultiAudioTestString8 appPackage = String8(mPackageName);// RockVideoPlayer 走 HDMI0,gallery3d 走 HDMI1,MX Player 走扬声器if (strstr(appPackage.string(), "RockVideoPlayer")) {    sessionid = (audio_session_t)65else if (strstr(appPackage.string(), "gallery3d")) {    sessionid = (audio_session_t)81;else if (strstr(appPackage.string(), "mxtech")) { // MX Player 包名含 mxtech    sessionid = (audio_session_t)57;}#endif

同时需要:

 

 

  •  
  •  
打开MultiAudioTest 宏(在frameworks/av/media/libaudioclient/include/media/AudioTrack.h中设为1);解决音频焦点冲突:在MediaFocusControl.java 中添加focusChangeHint = 3,避免多APP 同时播放时暂停

 

 

 

2. HDMI IN 录音:调用 HDMIIN 音频源

 

通过AudioRecord 初始化时指定MediaRecorder.AudioSource.HDMIIN,即可录制 HDMI 外部输入的声音:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 参数:音频源(HDMIIN)、采样率、声道配置、格式、缓冲区大小AudioRecord audioRecord = new AudioRecord(    MediaRecorder.AudioSource.HDMIIN,    44100// 采样率 44.1kHz    AudioFormat.CHANNEL_IN_STEREO, // 立体声    AudioFormat.ENCODING_PCM_16BIT, // 16bit PCM    4096 // 缓冲区大小);// 开始录音audioRecord.startRecording();

五、扩展:用 AudioPatch 优化 TvInput 音频延时

 

如果开发 TvInput 相关功能(如电视信号输入),可以用 AudioPatch 替代传统的AudioStream,进一步降低音频延时(但录屏无法捕获 TvInput 预览声音,需根据需求选择)。

 

 

核心修改:在TvInputHardwareManager.java 中屏蔽AudioStream 调用,启用AudioPatch

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
// 屏蔽原 AudioStream 逻辑// mAudioStream.start(6);// mAudioStream.stop();// 启用 AudioPatchif (mAudioPatch != null) {    mAudioManager.releaseAudioPatch(mAudioPatch);}// 创建 AudioPatch 连接 HDMI IN 音频源mAudioManager.createAudioPatch(    audioPatchArray,    new AudioPortConfig[] { sourceConfig },    new AudioPortConfig[] { sinkConfig });

六、总结与支持

 

RK Android 平台的音频调试,核心是 先确认基础通路(声卡 驱动),再定位上层逻辑(优先级、状态同步)MultiAudio 方案不仅解决了原生框架的局限,其配套的调试方法也能覆盖大部分场景。

 

 

希望这篇指南能帮你少踩坑,高效搞定音频调试!如果觉得有用,欢迎点赞、转发,也欢迎在评论区分享你的调试经验~

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分