1. OpenSL ES 是什么

OpenSL ES (Open Sound Library for Embedded Systems)是无授权费、跨平台、针对嵌入式系统精心优化的硬件音频加速API。它为嵌入式移动多媒体设备上的本地应用程序开发者提供标准化, 高性能,低响应时间的音频功能实现方法,并实现软/硬件音频性能的直接跨平台部署,降低执行难度,促进高级音频市场的发展。简单来说OpenSL ES是一个嵌入式跨平台免费的音频处理库。
Android的OpenSL ES库是在NDK的platforms文件夹对应android平台先相应cpu类型里面,如:

2. OpenSL ES 与 Android的关系

Android 2.3 (API 9) 即开始支持 OpenSL ES 标准了,通过 NDK 提供相应的 API 开发接口,下图是 Android 官方给出的关系图(参考:https://source.android.com/devices/audio/latency_app.html):

由该图可以看出,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

3. 与Java层的AudioRecord, AudioTrack的关系

利用 Android 提供的 AudioRecord 采集音频,利用 AudioTrack 播放音频,利用 MediaCodec 来编解码,这些 API 均是 Android 提供的 Java 层 API,无论是采集、播放还是编解码,这些 API 接口都需要将音频数据从 Java 拷贝到 native 层,或者从 native 层拷贝到 Java,如果希望减少拷贝,开发更加高效的 Android 音频应用,则建议使用 Android NDK 提供的 OpenSL ES API 接口,它支持在 native 层直接处理音频数据。

4. OpenSL ES的特性以及优劣势

特性:

()C 语言接口,兼容 C++,需要在 NDK 下开发,能更好地集成在 native 应用中
()运行于 native 层,需要自己管理资源的申请与释放,没有 Dalvik 虚拟机的垃圾回收机制
()支持 PCM 数据的采集,支持的配置:16bit 位宽, Hz采样率,单通道。(其他的配置不能保证兼容所有平台)
()支持 PCM 数据的播放,支持的配置:8bit/16bit 位宽,单通道/双通道,小端模式,采样率(, , , , , , , , Hz)
()支持播放的音频数据来源:res 文件夹下的音频、assets 文件夹下的音频、sdcard 目录下的音频、在线网络音频、代码中定义的音频二进制数据等等

优势:

()避免音频数据频繁在 native 层和 Java 层拷贝,提高效率
()相比于 Java API,可以更灵活地控制参数
()由于是 C 代码,因此可以做深度优化,比如采用 NEON 优化
()代码细节更难被反编译

劣势:

()不支持版本低于 Android 2.3 (API ) 的设备
()没有全部实现 OpenSL ES 定义的特性和功能
()不支持 MIDI
()不支持直接播放 DRM 或者 加密的内容
()不支持音频数据的编解码,如需编解码,需要使用 MediaCodec API 或者第三方库
()在音频延时方面,相比于上层 API,并没有特别明显地改进

5. OpenSL ES的一些基本概念

Objects和Interfaces

OpenSL ES 有两个必须理解的概念,就是 Object 和 Interface,Object 可以想象成 Java 的 Object 类,Interface 可以想象成 Java 的 Interface,但它们并不完全相同,下面进一步解释他们的关系:
(1) 每个 Object 可能会存在一个或者多个 Interface,官方为每一种 Object 都定义了一系列的 Interface
(2)每个 Object 对象都提供了一些最基础的操作,比如:Realize,Resume,GetState,Destroy 等等,如果希望使用该对象支持的功能函数,则必须通过其 GetInterface 函数拿到 Interface 接口,然后通过 Interface 来访问功能函数
(3)并不是每个系统上都实现了 OpenSL ES 为 Object 定义的所有 Interface,所以在获取 Interface 的时候需要做一些选择和判断

所有的Object在OpenSL里面我们拿到的都是一个SLObjectItf:

struct SLObjectItf_ {
SLresult (*Realize) (SLObjectItf self,SLboolean async); SLresult (*Resume) (SLObjectItf self,SLboolean async); SLresult (*GetState) (SLObjectItf self,SLuint32 * pState); SLresult (*GetInterface) (SLObjectItf self, const SLInterfaceID iid, void * pInterface); SLresult (*RegisterCallback) (SLObjectItf self, slObjectCallback callback, void * pContext); void (*AbortAsyncOperation) (SLObjectItf self); void (*Destroy) (SLObjectItf self); SLresult (*SetPriority) (SLObjectItf self, SLint32 priority, SLboolean preemptable); SLresult (*GetPriority) (SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable); SLresult (*SetLossOfControlInterfaces) (SLObjectItf self, SLint16 numInterfaces, SLInterfaceID * pInterfaceIDs, SLboolean enabled);
}; typedef const struct SLObjectItf_ * const * SLObjectItf;

这里的SLObjectItf是一个二级指针,它指向的是一个结构体指针。任何创建出来的Object都必须调用 Realize 方法做初始化,在不需要的时候可以使用 Destroy 方法来释放资源。

Interface则是方法的集合,例如SLRecordItf里面包含了和录音相关的方法,SLPlayItf包含了和播放相关的方法。我们功能都是通过调用Interfaces的方法去实现的,如 SLEngineItf 这个interface,我们可以通过它去创建各种Object,例如播放器、录音器、混音器的Object,然后在用这些Object去获取各种Interface去实现各种功能。

struct SLEngineItf_ {
SLresult (*CreateAudioPlayer) (SLEngineItf self, SLObjectItf * pPlayer, SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, const SLInterfaceID * pInterfaceIds, const SLboolean * pInterfaceRequired); SLresult (*CreateAudioRecorder) (SLEngineItf self, SLObjectItf * pRecorder, SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, const SLInterfaceID * pInterfaceIds, const SLboolean * pInterfaceRequired); SLresult (*CreateOutputMix) (SLEngineItf self, SLObjectItf * pMix, SLuint32 numInterfaces, const SLInterfaceID * pInterfaceIds, const SLboolean * pInterfaceRequired); ...
};

6. OpenSL ES的基本开发流程

这里以使用OpenSL ES 来播放一个PCM文件为例,主要包括:

、 创建接口对象
、设置混音器
、创建播放器(录音器)
、设置缓冲队列和回调函数
、设置播放状态
、启动回调函数

由于OpenSL ES是Native层提供的API,在使用前须注意添加头文件和链接选项,在需要用到OpenSL ES API的C文件中添加:

#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>

链接库文件:

如果是:Android.mk

LOCAL_LDLIBS += -lOepnSLES

如果是:CMakeLists.txt

 在 target_link_libraries 括号中添加 OpenSLES

示例代码: 《OpenSL ES: 利用OpenSL ES播放一个存在于SDcard上的PCM文件

参考链接:

1. Android音频开发(7):使用 OpenSL ES API(下)

2. OpenSL ES 学习笔记

3.Android OpenSL ES 开发:Android OpenSL 介绍和开发流程说明

OpenSL ES: OpenSL ES 简介的更多相关文章

  1. Data Structures & js &ES 6 & ES next

    Data Structures & js &ES 6 & ES next Algorithm Singly-Linked List & Doubly-Linked Li ...

  2. es概念一句话简介和注意点

    1.elasticsearch是什么? 一个实时分布式搜索(全文or结构化)和分析引擎,面向文档(document oriented) 2.主节点(Master Node)职责? 负责集群中的操作(如 ...

  3. es 搜索功能简介

    DSL 语法介绍 语法 范围 /_search 集群上搜索所有的索引 /index1/_search index1 /index1,index2/_search index1和index2 /inde ...

  4. [ios][opengles]OpenGL ES基础知识简介

    参考: http://www.cnblogs.com/shangdahao/archive/2011/11/05/2233587.html 3D变换:模型,视图,投影与Viewport: http:/ ...

  5. ES(5): ES Cluster modules settings

    ES cluster 提供了针对不同模块的参数设置,可通过修改集群上各个节点的elasticsearch.yml文件,也可在集群运行时通过api接口来更新(https://www.elastic.co ...

  6. ES(4): ES Cluster Security Settings

    目录: ES安全事件回顾 ES集群安全建议 安全访问配置 license更新 ES安全事件回顾 下面是白帽汇监测到针对全球使用广泛的全文索引引擎Elasticsearch的勒索事件: 2017年1月1 ...

  7. ES(3): ES Cluster Extended Azure Storage

    Azure VM的磁盘空间远远不能满足ES集群存储需求(还需除掉VM的临时盘),同时也未找着ES配置 block blob storage 存储的组件,因此下文介绍通过挂载附加盘的方式增加ES集群存储 ...

  8. es篇-es基础

    点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. es基础知识 es和solr一样,都是基于Lucene的全文检索数据库 ...

  9. docker es and es cluster

    How to use this image You can run the default elasticsearch command simply: $ docker run -d elastics ...

随机推荐

  1. Android驱动之设备树简介

    目录 一.    设备树简介    2 1.    问题一:为什么需要设备树?    2 ①名词解释:    2 ②DT详细介绍:    2 ③DTS是DT的源文件,描述Device Tree中的设备 ...

  2. 理解ld-linux.so.2

    翻译自:Understanding ld-linux.so.2 前言 ld-linux.so.2是linux的动态加载器(dynamic loader).本文试图就ld-linux.so.2如何与Li ...

  3. 关于MySQL中的锁机制详解

    锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则. 最显著的特点是不同的存储引擎支持不同的锁机制,InnoDB支持行锁和表锁,MyISAM支持表锁. 表锁就是把 ...

  4. Oracle基础知识【1】

    目录: 1.Oracle创建库.表 2.Oracle数据怎删查改操作 3.Oracle数据约束条件 Oracle创建库.表: create user user05 identified by 1234 ...

  5. Kotlin编译器使用及反编译分析

    在上一次对Kotlin进行了一个入门的介绍,并用IntelliJ IDEA来编写了一个Kotlin的HelloWorld,记得我们在最初学习J2SE的时候在编译运行都是通过javac.java命令来进 ...

  6. plus代码闪光点

    1. 快速变成 String 格式: { stamp: +new Date() } 2. 封装axios请求: axios.get(this.URI, { params: { }, withCrede ...

  7. MVC框架和MTV框架

    MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller),具有耦合性低 ...

  8. 人们为什么在Python脚本的第一行上编写#!/ usr / bin / env python shebang?

    在我看来,如果没有该行,文件运行相同. #1楼 您可以使用virtualenv尝试此问题 这是test.py #! /usr/bin/env python import sys print(sys.v ...

  9. LOJ2823 三个朋友 ——查询字串的哈希值

    概念 查询字串的hash值 我们所说的哈希通常都是进制哈希,因为它具有一些很方便的性质,例如,具有和前缀和类似的性质. 假设一个字符串的前缀哈希值记为 $h[i]$,进制为 $base$,那么显然 $ ...

  10. 转,SqlServer 基础之(触发器)

    概念:   触发器(trigger)是SQL server 提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触 ...