当前位置:首页 > 话题广场 > 攻略专题 > 游戏问答

「Android 音频」“声音”从何而来

作者:jarrettYe

通过这篇文章,您可以对Android系统音频录制技术有一个整体的了解,并对王毅为什么一直没有录制环境音或声音有深入的了解。

一、音频量化

音频基座的文章数量很多,如果想知道更多,请到百度。(大卫亚设)。

这里重点关注 PCM 和采样率,因为目前遇到的音频问题都跟这两个有关。接下来看一张经典的音频采样流程图:

以上就是计算机系统中的音频文件的生成过程:采样、量化、编码。人耳所能听到的声音,最低的频率是 20Hz ~ 20KHZ,因此音频文件格式的最大带宽是 20KHZ。

根据奈奎斯特的理论,只有采样频率高于声音信号最高频率的两倍时,才能把数字信号表示的声音还原成为原来的声音,所以音频文件的采样率一般在 40~50KHZ,比如最常见的 CD 音质采样率 44.1KHZ。

对声音进行采样、量化过程被称为脉冲编码调制(Pulse Code Modulation),简称PCM。PCM 数据是最原始的音频数据完全无损,所以 PCM 数据虽然音质优秀但体积庞大,为了解决这个问题先后诞生了一系列的音频格式,这些音频格式运用不同的方法对音频数据进行压缩,其中有无损压缩(ALAC、APE、FLAC)和有损压缩(MP3、AAC、OGG、WMA)两种。


二、录音方式

1、系统内录

直接上 Google 官方的文档,大意就通过该接口可以进行实时字幕和游戏内录音。这里不准备深入,因为硬性要求 Android Q 及以上系统版本(文末有 AudioPlaybackCapture 使用实例可以参考):


2、麦克风录制

麦克风录制要特别注意的两个情况:

同时只能有一个实例存在,比如有 GVoice 在录音,那么其他都要歇菜了。官方文档 “共享音频输入” 有详细的说明。

另一种情况就是不可控(可能会录制到 ”黄、爆” 音频)。

2.1、基本概念

Android 系统提供的录制麦克风方式就两种:MediaRecorder 和 AudioRecord:

  • MediaRecorder:简易模式,调用简单,只有开始、结束,录音之后的文件也是指定编码格式,系统播放器可以直接播放。
  • AudioRecord:原始模式,可以暂停、继续,可以实时获取到 PCM 数据然后进行音视频的混合,也是录屏软件经常使用的接口。

2.2、麦克风内录的另类实现

通过上面的 AudioRecord 的代码可以发现,输入源是可以配置的,并且通过接口文档很快就发现 REMOTE_SUBMIX 这个输入源也可以实现内录功能,但是有两个必要条件:

  • 需要系统权限,就是需要在 Android 源码中进行编译的工程才可以获取系统签名权限
  • 会截走扬声器和耳机的声音,也就是说在录音时本地无法播放声音

3、Hook 内录

通过以下 Android 的音频系统架构图可以看出,Android 提供的唯二接口:MediaPlayer 和 AudioTrack,最终都是经过 AudioFlinger 的 AudioStreamOut::write(const void *buffer, size_t numBytes) 把数据传递到硬件层:

通过 inline hook 的形式可以导出音频数据,目前 KM 上已经有同事实践成功,具体可以参考链接:

但是,inline hook 需要操作寄存器并且方案通用性欠佳,所以不建议使用 inline hook。不过,在音频数据流转的过程中截取数据的形式是通用做法,引擎内录就是借鉴的这种做法。在更高的层级进行的获取行为,并且由于层级比较高,所以无法做到一个方案覆盖全的情况。几乎都是跟引擎密切相关,但是也有好的方面,就是稳定性得到了保证并且可以统一多端的获取逻辑。

4、引擎内录

引擎内录可以统一 Android、iOS、PC 多端音频获取逻辑


从上图可以看出,整个获取内音的逻辑很简单,但是,引擎这么多,引擎插件怎么写就成了一个难题

我们先从最简单的 Unity FMOD 开始。

4.1、Unity FMOD 内录

Unity 內置的 Audio 內部使用的是 FMOD,但是没有导出接口,所以无法使用 FMOD 插件的方式。

通过查找 ,Unity 给出类似的接口,简单实现如下,具体的请查看附件 Ex 和 FmodSu。

集成的话,只需要把 Ex 挂载到 AudioListener 所在的主 Camera 就可以(保存成 PCM 文件是常用的调试技巧):

public class ExportAudioRes : MonoBehaviour { ... void OnAudioFilterRead(float[] data, int channels) { FmodSu(data, da, (uint)channels); if (DebugInGame) { // 把音频数据直接保存成 PCM 文件,这样就可以定位是否是音频本身的问题 (data); } } }

4.2、 FMOD Studio 内录

感觉这是废话:安装 FMOD Studio ,打开工程导入 FMOD for Unity

如果只是测试,可以直接使用 FMOD Studio 自带的样例的 bank 文件,FMOD 在 Unity 里面的配置也比较简单,如下动图所示,设置 bank 路径然后添加事件响应就可以:

接下来是 FMOD 插件实现的关键代码:

4.3、 Wwise 内录

安装 wwise Launcher 之后可以在本地路径下找到 AkDelay 的源码,通过改造源码添加转发器就可以实现自定义插件:

D:\Program Files (x86)\Audiokinetic\Wwise 2017.1.9.6501\SDK\samples\Plugins\AkDelay //通过修改上面的工程名,就可以得到一个自定义插件,有需要可以找我要工程源码

这里的关键就变成,如何在自定义插件里面把 “音频转发器” 这个库给拉起来?为了减少工程之间的依赖,Unity 里面可以通过 PInvoke 的形式动态拉起,但是在 wwise 插件里面就需要另辟蹊径,但是肯定还是想使用动态打开库的形式。直接上代码,大体如下:

另外需要注意的就是 wwise 插件需要挂载到 Master Audio Bus 上,并且不能同时挂载多个,否则录制出来的声音会叠加在一起:


前面只是抛砖引玉。

想要实现一个插件远比上面说的复杂。因为没有考虑版本兼容问题、插件的编译环境、动态获取库代码健壮性、不同平台差异兼容、插件集成等等问题。

5、思考扩展

既然引擎层面都有插件特效,那么 Android 原生应该也有对应的功能才对?是否可以利用呢?

//下面是摘抄于 Google 的文档,Google 早就料到会有人像我这样思考, 还特别提醒:这不是音频录制接口,别瞎用

最后在文章末尾分享一份Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料给大家

非常适合近期有面试和想在技术道路上继续精进的朋友。也是希望可以帮助到大家提升进阶

如果你觉得自己学习效率低,缺乏正确的指导,可以加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!

1.《「Android 音频」“声音”从何而来》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《「Android 音频」“声音”从何而来》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/gl/3173272.html

上一篇

a站手机uid怎么看?我来告诉你答案触乐夜话:B站喜敲钟,A站不轻松

bank格式音频怎么打开?总结很全面速看!1分钟记一个单词(第1782个)bank

  • bank格式音频怎么打开?总结很全面速看!1分钟记一个单词(第1782个)bank
  • bank格式音频怎么打开?总结很全面速看!1分钟记一个单词(第1782个)bank
  • bank格式音频怎么打开?总结很全面速看!1分钟记一个单词(第1782个)bank
bank格式音频怎么打开看这里!常见音频格式的任意切换方式,献给自媒体的小兄弟们

bank格式音频怎么打开看这里!常见音频格式的任意切换方式,献给自媒体的小兄弟们

bank格式音频怎么打开相关介绍,常见音频格式之间的转换方法 常见的声音格式有多种,包括WAV、MIDI、MP3、RA、MP4等。 我们该如何实现各种声音格式间的转换呢?如果你仔细看看每个音频之间的关系,你会发现,最常用的就是WAV文...