前面几篇文章介绍了如何在 Java 层,利用 Android 提供的 AudioRecord 采集音频,利用 AudioTrack 播放音频,利用 MediaCodec 来编解码,这些 API 均是 Android 提供的 Java 层 API,无论是采集、播放还是编解码,这些 API 接口都需要将音频数据从 Java 拷贝到 native 层,或者从 native 层拷贝到 Java,如果希望减少拷贝,开发更加高效的 Android 音频应用,则建议使用 Android NDK 提供的 OpenSL ES API 接口,它支持在 native 层直接处理音频数据。
OpenSL ES 从 Android 2.3 开始就提供了,但是 Android 官方关于 OpenSL ES 的文档非常少,网上资料也相对贫乏,再加上它的接口采用的是面向对象的 C 接口,不是特别简单易懂,因此学习起来不是那么容易,我计划通过两篇文章来介绍一下这套框架,希望能对初学者有所帮助。
本文不准备介绍 OpenSL ES 的工作原理和函数使用(这些将会在下一篇文章中介绍),而是从宏观的角度简单介绍一下 OpenSL ES 概况,让初学者了解这套 API 是干什么的,可以做哪些事,不能做哪些事,最后给出一些参考示例代码和资源链接。
OpenSL ES 全称是:Open Sound Library for Embedded Systems,是一套无授权费、跨平台、针对嵌入式系统精心优化的硬件音频加速API。它为嵌入式移动多媒体设备上的本地应用程序开发者提供标准化, 高性能, 低响应时间的音频功能实现方法,并实现软硬件音频性能的直接跨平台部署,降低执行难度,促进高级音频市场的发展。(来自 百度百科 )
一句话概述:OpenSL ES 是一套针对嵌入式平台的音频标准。
Android 2.3 (API 9) 即开始支持 OpenSL ES 标准了,通过 NDK 提供相应的 API 开发接口,下图是 Android 官方给出的关系图(出处: 这里 ):
由该图可以看出,Android 实现的 OpenSL ES 只是 OpenSL 1.0.1 的子集,并且进行了扩展,因此,对于 OpenSL ES API 的使用,我们还需要特别留意哪些是 Android 支持的,哪些是不支持的,具体相关文档的地址位于 NDK docs 目录下:
NDKroot/docs/Additional_library_docs/opensles/index.html NDKroot/docs/Additional_library_docs/opensles/OpenSL_ES_Specification_1.0.1.pdf
下面总结一下 Android OpenSL ES 的特点以及不支持的功能。
- C 语言接口,兼容 C++,需要在 NDK 下开发,能更好地集成在 native 应用中
- 运行于 native 层,需要自己管理资源的申请与释放,没有 Dalvik 虚拟机的垃圾回收机制
- 支持 PCM 数据的采集,支持的配置:16bit 位宽,16000 Hz采样率,单通道。(其他的配置不能保证兼容所有平台)
- 支持 PCM 数据的播放,支持的配置:8bit/16bit 位宽,单通道/双通道,小端模式,采样率(8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 Hz)
- 支持播放的音频数据来源:res 文件夹下的音频、assets 文件夹下的音频、sdcard 目录下的音频、在线网络音频、代码中定义的音频二进制数据等等
- 不支持版本低于 Android 2.3 (API 9) 的设备
- 没有全部实现 OpenSL ES 定义的特性和功能
- 不支持 MIDI
- 不支持直接播放 DRM 或者 加密的内容
- 不支持音频数据的编解码,如需编解码,需要使用 MediaCodec API 或者第三方库
- 在音频延时方面,相比于上层 API,并没有特别明显地改进
- 避免音频数据频繁在 native 层和 Java 层拷贝,提高效率
- 相比于 Java API,可以更灵活地控制参数
- 由于是 C 代码,因此可以做深度优化,比如采用 NEON 优化
- 代码细节更难被反编译
- 其他,待添加
有个老外(Victor Lazzarini)为 Android OpenSL ES API 写了一篇不错的介绍,并给出了一些示例代码,链接如下:
https://audioprograming.wordpress.com/2012/03/03/android-audio-streaming-with-opensl-es-and-the-ndk/
我提取了其中的两个文件,修改了一下,整理到我的 AudioDemo 示例中了,个人觉得有更好地演示效果,地址如下:
https://github.com/Jhuster/AudioDemo
《OpenSL ES Basics》
《Native Audio: OpenSL ES for Android》
《Android Audio Architecture》
《OpenSL ES for Android》
《Tutorials for OpenSL ES for Android》
《Android.NDK.Beginner's.Guide.pdf》
《Getting Started with OpenSL on Android》
《Android audio streaming with OpenSL ES and the NDK》
关于如何 Android OpenSL ES API 就介绍到这儿了,文章中有不清楚的地方欢迎留言或者来信 lujun.hust@gmail.com 交流,或者关注我的新浪微博@卢_俊或者 微信公众号 @Jhuster 获取最新的文章和资讯。