16

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

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

提前致谢!

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

4

1 回答 1

36

我曾经在基于 Qualcomm 的 APQ8064 平台(这似乎与您的目标设备中的平台几乎相同)的手机上实现了您所追求的功能。下面是我可以从中回忆的摘要,因为我不再可以访问我编写的代码,或者我可以轻松进行此类修改的环境。所以如果这个答案读起来像是一堆零碎的记忆,那是因为它就是这样。

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

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


几个感兴趣的地方:

平台的音频驱动程序。特别是msm-pcm-routing.c 文件

ALSA UCM(用例管理器)设置文件。这只是一个示例 UCM 设置文件。根据所使用的确切平台,这些文件有许多变体,因此您的名称可能略有不同(尽管它应该以 开头snd_soc_msm_),其内容也可能与我链接的内容略有不同。
Kitkat 及更高版本的注意事项:UCM 设置文件用于 Jellybean(可能还有 ICS)。我的理解是这些设置已移至名为mixer_paths.xmlKitkat 的文件中。内容几乎相同,只是格式不同。

音频 HAL 代码。ALSA UCM 存在于 中, //libalsa-intf代码AudioHardware存在于. 请注意,此代码适用于 Jellybean,因为这是我熟悉的最新版本。Kitkat 的目录结构(可能还有一些文件/类)不同。AudioPolicyManagerALSADeviceaudio-alsa

如果您打开 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

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


如果您"AFE_PCM_RX Audio Mixer"msm_qdsp6_widgets 表中查找,msm-pcm-routing.c您会看到它引用了一个名为的混音器控件列表,afe_pcm_rx_mixer_controls如下所示:

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)。要了解它们之间的关系,请参阅这些图表
AFE_PCM_RX并且AFE_PCM_TX是高通公司某些平台上的一对 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。 当您向卡 0 上的播放设备 0 写入的所有内容馈入时,将被馈入后端 DAI。要回读它,您可以设置一个执行类似 的 UCM 动词,然后您将从(它应该是默认的 ALSA 捕获设备)中读取。MultiMedia5
MultiMedia1AFE_PCM_RX Audio MixerAFE_PCM_RX'MultiMedia1 Mixer AFE_PCM_TX':1:1pcmC0D0c


一个简单的测试是从您的手机中提取 UCM 设置文件(应该位于下面的某个位置/system/etc/),并使用以下内容修改"HiFi"动词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_TXAFE_PCM_TX.

将修改后的 UCM 设置文件复制回手机(需要 root 权限),然后重启手机。然后开始播放(连接有线耳机/耳机,并禁用触摸声音,以免选择低延迟动词),然后从AudioSource.MIC. 之后,检查录音,看看您是否能够录制播放音频。如果没有,那么可能选择了低功率音频动词,您必须修改"HiFi Low Power"动词,就像您对动词所做的那样"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 到另一个后端的连接戴。如果您查看afe_pcm_rx_port_mixer_controlsintercon表,msm-pcm-routing.c您会注意到没有 的SLIM_0_RX条目AFE_PCM_RX Port Mixer,因此您必须自己添加这些(只需复制粘贴一些现有行并更改名称)。


您可能必须进行的其他一些更改:

  • frameworks/baseframeworks/av(例如AudioManager, AudioService, AudioSystem)中,您必须添加一个新AudioSource常量并确保它在所有必要的地方都能被识别。

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

  • 在音频 HAL 中,您必须进行一些更改,以便在使用新动词/修饰语时选择您的新动词/修饰语AudioSource。请注意,有一个AudioPolicyManagerALSA被调用的基类AudioPolicyManagerBase,您可能还需要修改它(它位于源树的其他位置)。

于 2014-01-19T14:22:31.727 回答