有没有人有经验(使用OpenSL ES,ALSA等)在Android中重定向音频或创建新的声音路径?最终目标是创建一个虚拟麦克风来替换外部麦克风,在那里可以播放音频文件,就好像他们正在对着麦克风讲话一样.访问麦克风的应用程序AudioSource.MIC
应使用此备用流.它没有必要使用语音呼叫,我相信实现这种功能更难,因为它都是在无线电中完成的.
关于从哪里开始的任何想法?我已经用OpenSL和ALSA做了一些研究,但看起来我需要打包新固件(ROM)才能定义自定义音频路径.如果可以避免,我想创建一个应用程序级解决方案.电话是"扎根"(有su二进制文件).目标设备是三星Galaxy S4谷歌版(GT-i9505G).具体来说,我正在寻找音频驱动程序配置/源代码或i9505G的任何参考.
提前致谢!
编辑 - 我已经检查了CyanogenMod 10.2源代码树,以及jfltexx驱动程序和内核.以下是kernel/samsung/jf/sound的内容:http://pastebin.com/7vK8THcZ.这记录在哪里?
我曾经在基于高通公司APQ8064平台的手机上实现了你所追求的功能(它似乎与目标设备中的平台几乎相同).下面是我可以从中回忆起的内容摘要,因为我不再能够访问我编写的代码,或者我可以轻松地进行这些修改的环境.因此,如果这个答案看起来像一堆零碎的记忆,那就是因为它正是它的本质.
此信息也可能适用于其他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).我的理解是这些设置已被移动到mixer_paths.xml
Kitkat上命名的文件.内容几乎相同,只是格式不同.
音频HAL代码.ALSA UCM存在于libalsa-intf
,AudioHardware
/ 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控件.最后,它列出了在此用例中使用的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(AFE_PCM_RX
)的前端DAI .要了解这些如何相互关联,请参阅这些图表.AFE_PCM_RX
并且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
).还有其他前端讲台,就像MultiMedia3
和MultiMedia5
那些在特殊情况下,如低延时播放和低功耗的音频播放使用.
当你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
在所有可以找到它的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
和intercon
表中msm-pcm-routing.c
你会注意到没有SLIM_0_RX
条目AFE_PCM_RX Port Mixer
,所以你必须自己添加(这只是复制粘贴一些现有的行和更改名称的问题).
您可能需要进行的其他一些更改:
在框架/基础和框架/ AV(例如AudioManager
,AudioService
,AudioSystem
)你就必须添加一个新的AudioSource
常数,确保它在所有必要的地方得到认可.
在UCM设置文件中,您必须添加一些新的动词/修饰符,以便在AudioSource
使用新的时正确设置ALSA控件.
在音频HAL中,您必须进行一些更改,以便在使用新音色时选择新的动词/修饰符AudioSource
.请注意,有一个AudioPolicyManagerALSA
被调用的基类AudioPolicyManagerBase
,您也可能需要修改它(它位于源树中的其他位置).