在 Android 中重定向音频/创建备用声音路径

2024-03-14

有人有在 Android 中重定向音频或创建新声音路径的经验(使用 OpenSL ES、ALSA 等)吗?最终目标是创建一个虚拟麦克风来取代外部麦克风,人们可以播放音频文件,就像对着麦克风说话一样。访问麦克风的应用程序AudioSource.MIC应该使用这个备用流。它没有必要与语音通话一起工作,我相信实现这种功能更困难,因为这一切都是在收音机内完成的。

关于从哪里开始有什么想法吗?我已经对 OpenSL 和 ALSA 进行了一些研究,但看起来我需要打包新固件 (ROM) 才能定义自定义音频路径。如果可以避免,我想创建一个应用程序级解决方案。手机已“root”(具有 su 二进制文件)。其目标设备是 Samsung Galaxy S4 Google Edition (GT-i9505G)。具体来说,我正在寻找 i9505G 的音频驱动程序配置/源代码或任何参考。

提前致谢!

编辑 - 我已经检查了 CyanogenMod 10.2 源代码树,以及 jfltexx 驱动程序和内核。以下是 kernel/samsung/jf/sound 的内容:http://pastebin.com/7vK8THcZ http://pastebin.com/7vK8THcZ。这有记录在任何地方吗?


我曾经在一款基于高通 APQ8064 平台的手机上实现了您想要的功能(该平台似乎与您的目标设备中的平台几乎相同)。以下是我从中回忆起的内容的摘要,因为我不再能够访问我编写的代码,也无法再访问可以轻松进行此类修改的环境。因此,如果这个答案读起来像是一堆零碎的记忆,那是因为事实就是如此。

此信息也可能或多或少适用于其他 Qualcomm 平台(例如 MSM8960 或 MSM8974),但对于其他供应商(NVidia Tegra、Samsung Exynos、TI OMAP 等)的平台很可能完全无用。

简单说明:我使用的方法意味着录音应用程序获取的音频将在 Android 多媒体框架和/或平台的多媒体 DSP 中经过混音/音量控制。因此,如果您以 75% 的音量播放某些内容,录制它,然后以 75% 的音量播放录音,最终听起来可能会非常安静。如果你想获得未处理的 PCM 数据(解码后,但在混合/音量控制之前),你将不得不寻找其他方法,例如定制AudioFlinger,但这不是我尝试过或可以提供的信息。


几个感兴趣的地点:

该平台的音频驱动程序 https://www.codeaurora.org/cgit/quic/la/kernel/msm/tree/sound/soc/msm?h=kk_3.5_rb1.16。特别是msm-pcm-routing.c 文件 https://www.codeaurora.org/cgit/quic/la/kernel/msm/tree/sound/soc/msm/msm-pcm-routing.c?h=kk_3.5_rb1.16.

ALSA UCM(用例管理器)设置文件 https://android.googlesource.com/device/lge/mako/+/jb-mr1-dev/snd_soc_msm_2x_Fusion3。这只是 UCM 设置文件的示例。这些文件有许多变体,具体取决于所使用的具体平台,因此您的文件的名称可能略有不同(尽管它should从...开始snd_soc_msm_),其内容可能也与我链接的内容略有不同。
Kitkat 及更高版本的注意事项:UCM 设置文件用于 Jellybean(也可能是 ICS)。我的理解是这些设置已移至名为的文件中mixer_paths.xml https://android.googlesource.com/device/lge/mako/+/master/mixer_paths.xml关于奇巧。内容几乎相同,只是格式不同。

音频HAL代码 https://www.codeaurora.org/cgit/quic/la/platform/hardware/qcom/audio/tree/?h=jb_3.2_rb5.43。 ALSA UCM 存在于libalsa-intf,以及AudioHardware / AudioPolicyManager / ALSADevice代码存在于audio-alsa。请注意,此代码适用于 Jelly Bean,因为这是我熟悉的最新版本。 Kitkat 上的目录结构(可能还有一些文件/类)有所不同。

如果您打开 UCM 设置文件并搜索"HiFiPROXY Rx"你会发现这样的东西:

SectionVerb
Name "HiFiPROXY Rx"

EnableSequence
    'AFE_PCM_RX Audio Mixer MultiMedia1':1:1
EndSequence

DisableSequence
    'AFE_PCM_RX Audio Mixer MultiMedia1':1:0
EndSequence

# ALSA PCMs
CapturePCM 0
PlaybackPCM 0
EndSection

这定义了一个verb(本质上是音频用例的基础;还有修饰语可以应用于动词之上,例如同时播放和录音),名称为"HiFiPROXY Rx" (the HiFi绰号用于大多数非语音呼叫动词,PROXY指所使用的音频设备,并且Rx表示输出)并指定在应启用/禁用用例时要写入哪些 ALSA 控件以及写入内容。最后,它列出了在此用例中使用的 ALSA PCM 播放/捕获设备。例如,PlaybackPCM 0表示应使用播放设备 0(ALSA 卡隐含为代表内置硬件编解码器的卡,通常为卡 0)。这些动词由音频 HAL 根据用例(音乐播放、语音通话、录音……)、您连接的附件等进行选择。


如果你抬头看"AFE_PCM_RX Audio Mixer" in the msm_qdsp6_widgets 表 https://www.codeaurora.org/cgit/quic/la/kernel/msm/tree/sound/soc/msm/msm-pcm-routing.c?h=kk_3.5_rb1.16#n2719 in msm-pcm-routing.c你会看到它指的是名为的混音器控件列表afe_pcm_rx_mixer_controls https://www.codeaurora.org/cgit/quic/la/kernel/msm/tree/sound/soc/msm/msm-pcm-routing.c?h=kk_3.5_rb1.16#n1691看起来像这样:

static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
    SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_AFE_PCM_RX,
    MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
    msm_routing_put_audio_mixer),
    SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_AFE_PCM_RX,
    ... and so on...

这列出了允许您连接到后端 DAI 的前端 DAI(AFE_PCM_RX)。要了解它们之间的关系,请参阅这些图 https://www.kernel.org/doc/Documentation/sound/alsa/soc/DPCM.txt.
AFE_PCM_RX and AFE_PCM_TX是 Qualcomm 某些平台上的一对 DAI,它们实现了某种虚拟/代理设备。你所做的就是将音频输入AFE_PCM_RX然后由多媒体 DSP (QDSP) 处理,然后您可以通过AFE_PCM_TX。这用于实现 USB 和 WiFi 音频路由,以及 A2DP IIRC。

回到AFE_PCM_RX Audio Mixer MultiMedia1线路:这表示您正在喂食MultiMedia1进入AFE_PCM_RX Audio Mixer. MultiMedia1用于正常播放/录音,对应于pcmC0D0(您应该能够列出手机上的设备adb shell cat /proc/asound/devices)。还有其他前端 DAI,例如MultiMedia3 and MultiMedia5用于低延迟播放和低功耗音频播放等特殊情况。
当你喂食时MultiMedia1 to the AFE_PCM_RX Audio Mixer您写入卡 0 上的播放设备 0 的所有内容都将被送入AFE_PCM_RX后端 DAI。要读回它,您可以设置一个 UCM 动词,它的作用如下'MultiMedia1 Mixer AFE_PCM_TX':1:1,然后你会读到pcmC0D0c(这应该是默认的 ALSA 捕获设备)。


一个简单的测试是从您的手机中提取 UCM 设置文件(应位于/system/etc/)并修改"HiFi" verb's EnableSequence类似的东西:

'AFE_PCM_RX Audio Mixer MultiMedia1':1:1
'AFE_PCM_RX Audio Mixer MultiMedia3':1:1
'AFE_PCM_RX Audio Mixer MultiMedia5':1:1

(并且类似地在DisableSequence,但与:1:0在每行的末尾)。

然后前往"Capture Music"修饰符(这是正常录制时命名不佳的修饰符)并更改SLIM_0_TX to AFE_PCM_TX.

将修改后的 UCM 设置文件复制回手机(需要 root 权限),然后重新启动手机。然后开始一些播放(连接有线耳机/耳机,并禁用触摸声音,以便不会选择低延迟动词),并从AudioSource.MIC。然后,检查录音并查看是否能够录制播放音频。如果没有,那么可能选择了低功率音频动词,您必须修改"HiFi Low Power"动词类似于你对 the 所做的"HiFi"动词。如果您在音频 HAL 中启用了所有调试打印(即取消注释#define LOG_NDEBUG 0在所有可以找到它的 cpp 文件中),这样您就可以看到选择了哪些 UCM 动词/修饰语。


我上面描述的修改有点乏味,因为你必须涵盖所有MultiMedia所有相关动词和修饰语的前端 DAI。
IIRC,我能够将其简化为每个动词/修饰词仅一行:

'AFE_PCM_RX Port Mixer SLIM_0_RX':1:1

如果你看一下"HiFi", "HiFi Low Power", "HiFi Lowlatency"你会发现它们都使用动词SLIMBUS_0_RX后端 DAI,所以我通过使用AFE_PCM_RX Port Mixer它允许我建立从后端 DAI 到另一个后端 DAI 的连接。如果你看一下afe_pcm_rx_port_mixer_controls and intercon表在msm-pcm-routing.c你会注意到没有SLIM_0_RX条目为AFE_PCM_RX Port Mixer,因此您必须自己添加这些内容(只需复制粘贴一些现有行并更改名称即可)。


您可能需要进行的其他一些更改:

  • In 框架/基础 https://www.codeaurora.org/cgit/quic/la/platform/frameworks/base/tree/?h=aosp-new/master and 框架/AV https://www.codeaurora.org/cgit/quic/la/platform/frameworks/av/tree/?h=aosp-new/master (e.g. AudioManager, AudioService, AudioSystem)你必须添加一个新的AudioSource恒定并确保它在所有必要的地方得到认可。

  • 在 UCM 设置文件中,您必须添加一些新的动词/修饰符,以便在您的新版本时正确设置 ALSA 控件。AudioSource用来。

  • 在音频 HAL 中,您必须进行一些更改,以便在您的新动词/修饰语时选择您的新动词/修饰语。AudioSource用来。请注意,有一个基类AudioPolicyManagerALSA called AudioPolicyManagerBase您可能还需要修改它(它是位于源代码树的其他位置 https://www.codeaurora.org/cgit/quic/la/platform/hardware/libhardware_legacy/tree/audio?h=kk_2.7_rb1.21).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Android 中重定向音频/创建备用声音路径 的相关文章

随机推荐