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

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

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

提前致谢!

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

我曾经在基于高通公司APQ8064平台的手机上实现了你所拥有的function(它似乎与目标设备中的平台几乎相同)。 下面是我可以从中回忆起的内容摘要,因为我不再能够访问我编写的代码,或者我可以轻松地进行这些修改的环境。 因此,如果这个答案看起来像一堆碎片般的记忆,那就是因为它正是它的本质。

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

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


一些感兴趣的地方:

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

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

音频HAL代码 。 ALSA UCM存在于libalsa-intfAudioHardware / AudioPolicyManager / ALSADevice代码存在于audio-alsa 。 请注意,此代码适用于Jellybean,因为这是我熟悉的最新版本。 目录结构(可能还有一些文件/类)在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 

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


如果你在msm-pcm-routing.c的msm_qdsp6_widgets表中查找"AFE_PCM_RX Audio Mixer" ,你会看到它引用一个名为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( AFE_PCM_RX )的前端DAI。 要了解这些如何相互关联,请参阅这些图表 。
AFE_PCM_RXAFE_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 MixerMultiMedia1用于正常播放/录制,对应于pcmC0D0 (您应该可以使用adb shell cat /proc/asound/devices列出手机上的adb shell cat /proc/asound/devices )。 还有其他前端DAI,如MultiMedia3MultiMedia5 ,用于特殊情况,如低延迟播放和低功耗音频播放。
当您将MultiMedia1 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"动词的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更改为AFE_PCM_TX

将修改后的UCM设置文件复制回手机(需要root权限),然后重新启动手机。 然后开始一些播放(连接有线耳机/耳机,并禁用触摸声音,以便不选择低延迟动词),并从AudioSource.MIC开始录制。 然后,检查录音并查看是否能够录制播放音频。 如果没有,那么可能选择了低功率音频动词,你必须修改"HiFi Low Power"动词,类似于你对"HiFi"动词所做的动词。 如果您在音频HAL中启用了所有调试打印( #define LOG_NDEBUG 0 ,在您可以find它的所有cpp文件中取消注释#define LOG_NDEBUG 0 ,它将对您有所帮助,以便您可以看到哪些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的连接。 如果你看一下msm-pcm-routing.c中的afe_pcm_rx_port_mixer_controlsintercon表,你会注意到AFE_PCM_RX Port Mixer没有SLIM_0_RX条目,所以你必须自己添加它们(这只是复制粘贴一些问题)现有的行和更改名称)。


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

  • 在frameworks / base和frameworks / av (例如AudioManagerAudioServiceAudioSystem )中,您必须添加一个新的AudioSource常量,并确保它在所有必要的位置被识别。

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

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