我曾经在基于 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.xml
Kitkat 的文件中。内容几乎相同,只是格式不同。
音频 HAL 代码。ALSA UCM 存在于 中, //libalsa-intf
代码AudioHardware
存在于. 请注意,此代码适用于 Jellybean,因为这是我熟悉的最新版本。Kitkat 的目录结构(可能还有一些文件/类)不同。AudioPolicyManager
ALSADevice
audio-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
MultiMedia1
AFE_PCM_RX Audio Mixer
AFE_PCM_RX
'MultiMedia1 Mixer AFE_PCM_TX':1:1
pcmC0D0c
一个简单的测试是从您的手机中提取 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 到另一个后端的连接戴。如果您查看afe_pcm_rx_port_mixer_controls
和intercon
表,msm-pcm-routing.c
您会注意到没有 的SLIM_0_RX
条目AFE_PCM_RX Port Mixer
,因此您必须自己添加这些(只需复制粘贴一些现有行并更改名称)。
您可能必须进行的其他一些更改:
在frameworks/base和frameworks/av(例如AudioManager
, AudioService
, AudioSystem
)中,您必须添加一个新AudioSource
常量并确保它在所有必要的地方都能被识别。
在 UCM 设置文件中,您必须添加一些新的动词/修饰符,以便在使用新AudioSource
的时正确设置 ALSA 控件。
在音频 HAL 中,您必须进行一些更改,以便在使用新动词/修饰语时选择您的新动词/修饰语AudioSource
。请注意,有一个AudioPolicyManagerALSA
被调用的基类AudioPolicyManagerBase
,您可能还需要修改它(它位于源树的其他位置)。