随着科技的不断发展,越来越多的人在学习、娱乐、生产等方面使用移动设备。而其中至关重要的一个因素就是移动设备的音频系统。Android音频系统位于Android操作系统底层,负责从音频设备(如扬声器和麦克风)捕获和提供音频流。除了这个基本功能外,Android音频系统还可以进行降噪、音效处理、多媒体播放等工作,使得移动设备的音效变得更好,用户体验更加出色。
而在音频系统背后,深入的技术实现也是必不可少的。在Android音频系统中,Opensl就是其中一大重要组成部分。本文将从底层源码角度出发,深入剖析Android音频系统中的Opensl,让读者更好的了解该技术,从中寻找技术难点,探究技术创新。
一、Opensl基本架构
Opensl即Open Sound Library,是一种能够在音频和视频应用中实现低延迟、多通道、高质量音效效果的音频库。它是OpenSL ES API的实现,可以用移动设备的硬件来执行音频处理,并提供调用硬件加速的音频引擎处理。
Opensl的基本架构由以下三个组成部分:
1. Engine
-引擎的作用是为一组对象提供资源和管理能力,需要在应用层先创建一个引擎,然后再用这个引擎来创建他的子对象。
-引擎包含一个或多个输出混合器、输入源和效果器。
2. Object
-(1)输入源
-输入源是一个物理设备,如麦克风、附加到设备上的相机、蓝牙耳机等。
-(2)输出混音器
-输出混音器是所有的音频信号混合在一起并连接到音频输出端口的混音器。
-(3)效果器
-效果器是可以用于增强音频效果,如混响、均衡器等。
3. Interface
-Interface指定Object之间的连接方式。
其中,引擎和Object通过Interface进行通信交互,实现对系统资源的获取和使用。而在以上三个组成部分中,Object是最为核心的部分,其中又以输出混音器最为重要。输出混音器负责对多个播放器对象的音频数据进行混淆,并把结果播放到外部音频设备上。
二、Opensl工作流程
Opensl主要的工作流程分为两部分:引擎创建和Object创建。
1. 引擎创建
在应用层中,创建一个引擎对象的操作分别为:
slCreateEngine(&engineObj, 0, NULL, 0, NULL, NULL);
该操作创建了一个名为“engineObj”的Opensl引擎对象。
其中,第一个参数为创建的对象名,第二个参数为虚拟机实例,第三个参数为可选的引擎属性,第四个参数为可选的引擎特性,第五个参数为可选的调试配置,第六个参数为可选的结果回调。
引擎创建完成后,需要通过以下两个步骤初始化引擎。
1.1 Realize
通过以下操作对引擎进行初始化:
(*engineObj)->Realize(engineObj, SL_BOOLEAN_FALSE);
1.2 GetInterface
通过以下操作获取引擎对象的接口:
(*engineObj)->GetInterface(engineObj, SL_IID_ENGINE, (void*)&engineInterface);
在获得引擎接口的情况下,引擎的初始化工作即完成。
2. Object创建
Object在引擎之下工作,主要分为两个类型:输出混音器和输入源。
2.1 创建输出混音器
在创建对象之前需要先定义用于创建对象的数据结构。创建输出混合器的数据结构和操作如下:
SLObjectItf outputMixObj; // 全局静态变量
SLresult result;
result = (*engineInterface)->CreateOutputMix(engineInterface, &outputMixObj, 0, NULL, NULL);
if (SL_RESULT_SUCCESS != result) return NULL;
result = (*outputMixObj)->Realize(outputMixObj, SL_BOOLEAN_FALSE);
if (SL_RESULT_SUCCESS != result) return NULL;
其中,CreateOutputMix函数创建了一个基于输出混音器的新对象,Realize则是初始化此新对象,同样需要在此之后调用GetInterface获取此对象的接口。
2.2 创建输入源
在创建对象之前需要先定义用于创建对象的数据结构。创建输入源的数据结构和操作如下:
SLDataLocator_IODevice locDev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT,
SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
SLDataSource audioSrc = {&locDev, NULL};
SLDataLocator_AndroidSimpleBufferQueue locBufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1};
SLDataFormat_PCM formatPcm = {SL_DATAFORMAT_PCM, 1, SL_SAMPLINGRATE_44_1,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
SLDataSink audioSnk = {&locBufq, &formatPcm};
const SLInterfaceID input_interfaces[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
const SLboolean input_req[] = {SL_BOOLEAN_TRUE};
(*engineInterface)->CreateAudioRecorder(engineInterface, &inputObj, &audioSrc, &audioSnk,
1, input_interfaces, input_req);
(*inputObj)->Realize(inputObj, SL_BOOLEAN_FALSE);
其中,CreateAudioRecorder函数创建了一个包含录音器对象的新对象,Realize初始化此新对象。在Realize执行完毕后,通过GetInterface获取此对象的接口。
三、Opensl的优势
通过对Opensl的基本架构和工作流程的了解,可以发现,该技术具有以下几个优势:
1. 低延迟
Opensl支持本地处理音频数据、内部数据缓存和回放功能,使之的音频播放和处理更加快速,可以大幅降低音频传输延迟。
2. 质量高
通过Opensl的高效率处理,可以获得高质量音频处理效果。声音效果更加真实、清晰,同时也消除了播放过程中的杂音。
3. 多通道
此技术支持多通道音频,可处理多种类型、多路的音频播放。
4. 硬件加速
Opensl保留对硬件的访问接口,可以调用硬件加速的音频引擎处理,以实现更高效的音频处理。
总之,Android音频系统Opensl对于移动设备的音频处理和播放扮演着非常重要的角色。通过对其工作流程和优势的分析,可以更好地了解该技术,有助于使用者更加深入的研究和优化使用,提升音频质量和用户体验。