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

标签 android audio alsa opensl

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

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

提前致谢!

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

最佳答案

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

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

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

几个感兴趣的地方:

The platform's audio drivers .特别是msm-pcm-routing.c file .

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

The audio HAL code . 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 PCM 播放/捕获设备。例如,PlaybackPCM 0意味着应该使用播放设备 0(ALSA 卡被暗示为代表内置硬件编解码器的卡,通常是卡 0)。这些动词由音频 HAL 根据用例(音乐播放、语音通话、录音等)、您附加的附件等选择。

如果您查找 "AFE_PCM_RX Audio Mixer"msm_qdsp6_widgets tablemsm-pcm-routing.c你会看到它指的是 list of mixer controls named 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。要了解这些之间的关系,请参阅 these diagrams . 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行:这表示您正在喂食 MultiMedia1AFE_PCM_RX Audio Mixer . MultiMedia1用于正常播放/录音,对应pcmC0D0 (您应该能够使用 adb shell cat /proc/asound/devices 列出手机上的设备)。还有其他前端 DAI,例如 MultiMedia3MultiMedia5用于低延迟播放和低功耗音频播放等特殊情况。
当您喂食时 MultiMedia1AFE_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_TXAFE_PCM_TX .

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

您可能需要进行的其他一些更改:
  • frameworks/baseframeworks/av (例如 AudioManagerAudioServiceAudioSystem )你必须添加一个新的 AudioSource不变,并确保它在所有必要的地方得到认可。
  • 在 UCM 设置文件中,您必须添加一些新的动词/修饰符,以便在您使用新 AudioSource 时正确设置 ALSA 控件。用来。
  • 在音频 HAL 中,您必须进行一些更改,以便在您的新 AudioSource 时选择您的新动词/修饰语。用来。请注意,有一个基类 AudioPolicyManagerALSAAudioPolicyManagerBase您可能还需要修改(它是 located elsewhere in the source tree )。
  • 关于android - 在 Android 中重定向音频/创建备用声音路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21024851/

    相关文章:

    android - 如何更改 eclipse 中的 minSDK 版本?

    linux - 如何从内核访问在用户空间中创建的节点?

    c - 运行 portaudio 示例时 Ubuntu 中的错误

    java - Gradle 从 lib 中排除 java 类,替换为自己的类以避免重复

    android - Calabash - start_test_server_in_background 未启动应用程序

    android - 有关如何执行延迟后台工作的即时应用建议

    c - 录制的声音比原来的慢

    ios - 以编程方式压缩录制的音频

    html - DOM之外的html5音频元素的多个来源

    google-chrome - Chromium --alsa-output-device 标志不起作用