翻译自Android Extensions

针对Android的OpenSL ES扩展了参考OpenSL ES规范,使其与Android兼容,并利用Android平台的强大功能和灵活性。

Android扩展的API定义在OpenSLES_Android.h和它包含的头文件中。查阅OpenSLES_Android.h了解这些扩展的详细信息。这个文件位于您的安装根目录下,在sysroot/usr/include/SLES目录下。除非另有说明,所有接口都是显式的。

这些扩展限制了应用程序到其他OpenSL ES实现的可移植性,因为它们是特定于android的。您可以通过避免使用扩展或使用#ifdef在编译时排除它们来缓解这个问题。

下表显示了Android特定的接口和数据定位器及Android OpenSL ES支持的每种对象类型。单元格中的Yes值表示对象类型都可用的接口和数据定位器data locators。

Feature Audio player Audio recorder Engine Output mix
Android buffer queue Yes: Source (decode) No No No
Android configuration Yes Yes No No
Android effect Yes No No Yes
Android effect capabilities No No Yes No
Android effect send Yes No No No
Android simple buffer queue Yes: Source (playback) or sink (decode) Yes No No
Android buffer queue data locator Yes: Source (decode) No No No
Android file descriptor data locator Yes: Source No No No
Android simple buffer queue data locator Yes: Source (playback) or sink (decode) Yes: Sink No No

Android配置接口

Android配置界面提供了一种为对象设置特定于平台的参数的方法。该接口不同于其他OpenSL ES 1.0.1接口,因为您的应用程序可以在实例化相应对象之前使用它;而且,您可以在实例化对象之前配置它。OpenSLES_AndroidConfiguration.h头文件,驻留在/sysroot/usr/include/SLES中,记录了以下可用的配置键值:

  • 音频播放器的流类型(默认SL_ANDROID_STREAM_MEDIA)。
  • 音频记录器的记录配置文件(默认SL_ANDROID_RECORDING_PRESET_GENERIC)。

下面的代码片段展示了如何在音频播放器上设置Android音频流类型的示例:

// CreateAudioPlayer and specify SL_IID_ANDROIDCONFIGURATION
// in the required interface ID array. Do not realize player yet.
// ...
SLAndroidConfigurationItf playerConfig;
result = (*playerObject)->GetInterface(playerObject,SL_IID_ANDROIDCONFIGURATION, &playerConfig);
assert(SL_RESULT_SUCCESS == result);
SLint32 streamType = SL_ANDROID_STREAM_ALARM;
result = (*playerConfig)->SetConfiguration(playerConfig,SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
assert(SL_RESULT_SUCCESS == result);
// ...
// Now realize the player here.
复制代码

可以使用类似的代码来配置音频记录器的预设:

// ... obtain the configuration interface as the first four lines above, then:
SLuint32 presetValue = SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
result = (*playerConfig)->SetConfiguration(playerConfig,RECORDING_PRESET, &presetValue, sizeof(SLuint32));
复制代码

Android effects interfaces 效果接口

Android的效果、效果发送和效果功能接口为应用程序查询和使用特定于设备的音频效果提供了通用机制。设备制造商应该记录他们提供的任一设备特定的音频效果。

便携应用应该使用OpenSL ES 1.0.1 api来实现音频效果,而不是Android效果扩展。

Android file descriptor data locator 文件描述符数据定位器

Android文件描述符数据定位器允许您将音频播放器的源指定为具有读权限的开放文件描述符。数据格式必须是MIME。

这个扩展与native asset manager结合使用特别有用,因为应用程序通过文件描述符从APK读取assets。

Android simple buffer queue data locator and interface 简单的缓冲队列数据定位器和接口

在OpenSL ES 1.0.1参考规范中,缓冲区队列只能用于音频播放器,它们与PCM和其他数据格式兼容。Android简单缓冲队列数据定位器和接口规范与参考规范相同,但有两个例外:

  • 您可以使用带有录音机和音频播放器的Android简单缓冲队列。
  • 您只能对这些队列使用PCM数据格式。

为了记录,您的应用程序应该排队空缓冲区。当一个注册回调发送一个通知,系统已经写完数据到缓冲区,应用程序可以从缓冲区读取。

回放以同样的方式工作。但是,为了将来的源代码兼容性,我们建议应用程序使用Android简单缓冲区队列,而不是OpenSL ES 1.0.1缓冲区队列。

buffer queue缓冲队列行为

Android实现不包括引用规范的要求,即当回放进入SL_PLAYSTATE_STOPPED状态时,播放cursor返回到当前播放缓冲区的开始位置。该实现可以顺应该行为,也可以保持播放cursor的位置不变。因此,您的应用程序不能假定这两种行为都发生了。因此,在转换到SL_PLAYSTATE_STOPPED之后,应该显式调用BufferQueue::Clear()方法。这样做将缓冲区队列设置为已知状态。

类似地,缓冲区队列回调的触发器是否必须转换为SL_PLAYSTATE_STOPPED或执行BufferQueue::Clear(),也没有规范来控制。因此,我们建议您不要对其中一个创建依赖关系;相反,你的应用程序应该能够同时处理这两种情况。

对象创建时的动态接口

为了方便起见,OpenSL ES 1.0.1的Android实现允许应用程序在实例化对象时指定动态接口。这是使用DynamicInterfaceManagement::AddInterface()的替代方案,以便在实例化后添加这些接口。

扩展报告 有三种方法可以查询平台是否支持Android扩展。如下:

  • Engine::QueryNumSupportedExtensions()
  • Engine::QuerySupportedExtension()
  • Engine::IsExtensionSupported()

这些方法都返回ANDROID_SDK_LEVEL_<API-level>,其中API-level是平台API级别;例如,ANDROID_SDK_LEVEL_23。平台API级别为9或更高意味着平台支持扩展。

解码音频为PCM格式

本节描述了OpenSL ES 1.0.1中一个不赞成使用的android专用扩展,用于将编码流解码到PCM,而无需立即回放。下表给出了使用此扩展和替代方案的建议。

API level Alternatives替代方案
15 及以下 一种具有适当许可证的开源编解码器
16 到 20 MediaCodec类或具有适当许可证的开源编解码器
21 以上 NDK MediaCodec在<media/NdkMedia*.>头文件,MediaCodec类,或具有适当许可证的开源编解码器

注意:目前没有关于MediaCodec API的NDK版本的文档。但是,您可以参考natvie-codec示例代码。

标准音频播放器回放音频设备,指定输出混合作为数据接收器。Android扩展的不同之处在于,如果应用程序将数据源指定为URI或使用MIME数据格式描述的Android文件描述符数据定位器,那么音频播放器将充当解码器。在这种情况下,数据接收器是一个使用PCM数据格式的Android简单缓冲队列数据定位器。

这个特性主要用于游戏在转换到新的游戏级别时预加载它们的音频assets,这与SoundPool类提供的功能类似。

应用程序最初应该在Android简单缓冲区队列中加入一组空缓冲区。然后,应用程序用PCM数据填充缓冲区。Android简单的缓冲区队列回调在每个缓冲区被填满后触发。回调处理程序处理PCM数据,重新装入现在为空的缓冲区,然后返回。应用程序负责跟踪解码缓冲区(buffer);回调参数列表不包含足够的信息来指示包含数据的缓冲区或接下来应该加入队列的缓冲区。

数据源通过在流的末尾传递SL_PLAYEVENT_HEADATEND事件隐式地报告流的结束(EOS)。当应用程序解码了它接收到的所有数据后,它就不再调用Android简单缓冲队列回调。

数据槽sink的PCM数据格式通常与编码的数据源在采样率、声道数和位深度方面匹配。但是,您可以解码到不同的采样率、声道数或位深度。有关检测实际PCM格式的规定的信息,请看下面的通过元数据确定解码PCM数据的格式部分

OpenSL ES为Android的PCM解码功能,支持暂停和初始搜索;它不支持音量控制、效果、循环或播放速率。

根据平台实现的不同,解码可能需要不能闲置的资源。因此,我们建议您确保提供足够数量的空PCM缓冲区;否则,解码器将挨饿。这可能发生,例如,如果您的应用程序从Android简单的缓冲区队列回调返回,而不排队另一个空缓冲区。解码器饿死的结果是未知的,但可能包括:删除解码PCM数据,暂停解码过程,或彻底终止解码器。

注意:对于运行在Android 4.x (API级别16-20)上的应用程序,解码一个编码流到PCM,但不立即回放,我们建议使用MediaCodec类。对于在Android 5.0 (API level 21)或更高版本上运行的新应用程序,我们建议使用NDK等效程序<NdkMedia*.h>。这些头文件驻留在安装根目录下的media/目录中。

解码流式ADTS AAC转为PCM

如果数据源是使用MIME数据格式的Android缓冲队列数据定位器,而数据接收器是使用PCM数据格式的Android简单缓冲队列数据定位器,则音频播放器充当流解码器。配置MIME数据格式如下:

  • 容器:SL_CONTAINERTYPE_RAW
  • MIME类型字符串:SL_ANDROID_MIME_AACADTS

该特性主要用于流媒体应用程序,这些应用程序处理AAC音频,但需要在回放之前执行定制的音频处理。大多数需要将音频解码到PCM的应用程序应该使用解码音频到PCM所描述的方法,因为该方法更简单,可以处理更多的音频格式。这里描述的技术是一种更专业的方法,只有在这两种条件都适用时才会使用:

  • 压缩音频源是包含在ADTS头文件中的AAC帧流。
  • 应用程序管理这个流。数据不位于标识符为URI的网络资源中,也不位于标识符为文件描述符的本地文件中。

应用程序最初应该在Android缓冲区队列中加入一组已填充的缓冲区。每个缓冲区包含一个或多个完整的ADTS AAC帧。每个缓冲区清空后,Android缓冲区队列回调会触发。回调处理程序应该重新填充缓冲区并重新排队,然后返回。应用程序不需要跟踪已编码的缓冲区;回调参数列表包含足够的信息来指示下一个应该加入队列的缓冲区。流的末尾通过对EOS项进行排队显式地标记。EOS后,不允许再排队。

我们建议您确保提供完整的ADTS AAC缓冲区,以避免使解码器挨饿。这可能发生,例如,如果您的应用程序从Android buffer queue回调返回,而不排队另一个完整的缓冲区。解码器饿死的结果是未知的。

除了数据源之外,流解码方法与解码音频到PCM的方法相同。

虽然名称相似,但Android缓冲队列与Android简单缓冲队列不同。流解码器使用两个缓冲队列:ADTS AAC数据源的Android缓冲队列和PCM数据槽的Android简单缓冲队列。有关Android缓冲队列API的更多信息,请参阅安装根目录下docs/Additional_library_docs/openmaxal/目录中的index.html文件。

通过元数据确定已解码的PCM数据的格式

SLMetadataExtractionItf接口是参考规范的一部分。但是,指示解码PCM数据的实际格式的元数据键是Android特有的。OpenSLES_AndroidMetadata.h头文件定义了这些元数据键。这个头文件驻留在安装根目录下/sysroot/usr/include/SLES目录中。

Object::Realize()方法执行完之后,元数据键索引立即可用。但是,在应用程序解码第一个编码数据之前,关联的值是不可用的。一个好的实践是,在调用Object::Realize方法后查询主线程中的键索引,在第一次调用时读取Android简单缓冲队列回调处理程序中的PCM格式元数据值。有关使用这个接口的示例,请参阅NDK包中的示例代码。

元数据键名是稳定的,但是键索引没有被记录,并且可能会发生更改。应用程序不应假定索引在不同的阶段运行中是持久的,也不应假定多个对象实例在同一过程运行中共享索引。

浮点型数据

在Android 5.0 (API level 21)及更高版本上运行的应用程序可以以单精度、浮点型向AudioPlayer提供数据。

在以下示例代码中,Engine::CreateAudioPlayer()方法创建一个使用浮点数据的音频播放器:

#include <SLES/OpenSLES_Android.h>
...
SLAndroidDataFormat_PCM_EX pcm;
pcm.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
pcm.numChannels = 2;
pcm.sampleRate = SL_SAMPLINGRATE_44_1;
pcm.bitsPerSample = 32;
pcm.containerSize = 32;
pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
pcm.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
...
SLDataSource audiosrc;
audiosrc.pLocator = ...
audiosrc.pFormat = &pcm;
复制代码

在音频采样页上阅读关于浮点音频的更多信息。


下一篇: 适用于android的OpenSL ES指南-编程注意事项

适用于Android的OpenSL ES指南-OpenSL ES的Android扩展相关推荐

  1. Android开发工程师面试指南

     Android开发工程师面试指南 功能介绍     给Android开发工程师的一份面试指南,包含面试题集与简历模板. 面试题集 面试题集里的答案大部分来源于我的博客,因此这个题集也相当于是我的博客 ...

  2. Android Apk瘦身指南大全

    Android Apk瘦身指南大全 前言 为什么Android应用Apk要瘦身?虽然安装包大小对应用使用没有影响,但应用的安装包越大,用户下载的门槛越高,安装等待时间也会越长,特别是在移动网络情况下, ...

  3. android开发导航sdk,Android导航SDK开发指南(26页)-原创力文档

    Android 导航SDK 开发指南 一.概述 Android 导航SDK 目前为V1.1 版本,以.jar 形式提供,请广大开发者使用SDK 前务必 在官网申请key,以便全部功能顺利使用. And ...

  4. android4.0 音频框架 opensl openmax,适用于android的OpenSL ES指南-面向Android的OpenSL ES

    本文将详细说明NDK中OpenSL ES™的实现与OpenSL ES 1.0.1参考规范的不同.在使用规范中的示例代码时,可能需要修改它以在Android上工作. 除非另有说明,所有功能都可以在And ...

  5. 在 Android* 平台上设置原生 OpenGL ES*

    Setting up Native OpenGL ES* on Android* Platforms final.docx BSD2.0.txt ParticleSystemNDK.zip READM ...

  6. Android Camera API 2使用OpenGL ES 2.0和GLSurfaceView对预览进行实时二次处理(黑白滤镜)

    这段时间有点忙,一直没时间写第三篇教程,其实代码很早之前就写好了.本系列教程会有三篇文章讲解Android平台滤镜的实现方式,希望在阅读本文之前先阅读前面两篇文档. 第一篇 Android Camer ...

  7. Android项目开发教程之OpenGL ES

    视频课:[免费]跨平台APP JQuery Mobile开发-1-初探移动开发-张晨光的在线视频教程-CSDN程序员研修院 学习内容 OpenGL ES的基本概念 Android下3D开发的基本知识 ...

  8. Android C/C++开发指南

    Android C/C++开发指南 1.Android C/C++简介 众所周知,Android作为目前主流的移动终端领域的开发平台,其主要的开发语言就是JAVA.Android借助于JAVA高效.灵 ...

  9. flutter 局部状态和全局状态区别_给 Android 开发者的 Flutter 指南

    这篇文档旨在帮助 Android 开发者利用既有的 Android 知识来通过 Flutter 开发移动应用.如果你了解 Android 框架的基本知识,你就可以使用这篇文档作为 Flutter 开发 ...

最新文章

  1. CSS中一些语法规范和代码风格
  2. Iframe自适应高度绝对好使的代码 兼容IE,遨游,火狐[转]
  3. smarty中如何统计数组的个数?
  4. linux用户简单指令操作
  5. 什么是SAP CRM的Custom Transaction Context
  6. import java.io 包下载_Go 包管理机制深入分析
  7. www.sirim-global.com
  8. java判断对象无数据_java 对象属性不能为空判断
  9. php 怎么输入php ini,PHP怎么找到php.ini配置文件?-php教程
  10. 百度分享代码_网销侠:网络营销百问百答之51,百度小程序是什么
  11. 自动化测试qq空间登录
  12. torch 矩阵运算
  13. linkedin python 领英技能 测评
  14. 服务器esn和文件esn不匹配,如何获取服务器ESN
  15. (重点)微服务核心研究之--编排
  16. 微型计算机硬件系统基本组成一般应用包括,计算机系统的基本组成,一般应包括哪些...
  17. 修復Windows無法存取指定的裝置路徑或檔案
  18. C++实现暴力筛、朴素素数筛、埃氏素数筛、欧拉素数筛的解法
  19. linux命令行看图工具,六个鲜为人知的超酷Unix/Linux命令
  20. 工作中遇到的IE6兼容性问题及解决办法

热门文章

  1. 根据矩阵变化实现基于 HTML5 的 WebGL 3D 自动布局
  2. 如何减少浏览器repaint和reflow(下)
  3. Vue 入门,Vue属性和指令
  4. Ubuntu 16.04安装NASM汇编IDE-SASM
  5. 51nod 1368:黑白棋 二分图最大匹配
  6. python 装饰器 二 (装饰带参数的函数)
  7. EBS服务重启脚本(应用和数据库)
  8. 修改mysql表结构语句
  9. 提高PHP编程效率的53个要点(转)
  10. debian---nano转VIM