opensl(opensll)

http://www.itjxue.com  2023-02-17 04:38  来源:未知  点击次数: 

音频开发中常用到的概念

在音频开发中,下面的这几个概念经常会遇到。

(1) 采样率(samplerate)

采样率,注意,目前44100Hz是唯一可以保证兼容所有Android手机的采样率。

采样就是把模拟信号数字化的过程,不仅仅是音频需要采样,所有的模拟信号都需要通过采样转换为可以用0101来表示的数字信号,示意图如下所示:

蓝色代表模拟音频信号,红色的点代表采样得到的量化数值。

采样频率越高,红色的间隔就越密集,记录这一段音频信号所用的数据量就越大,同时音频质量也就越高。

根据奈奎斯特理论,采样频率只要不低于音频信号最高频率的两倍,就可以无损失地还原原始的声音。

通常人耳能听到频率范围大约在20Hz~20kHz之间的声音,为了保证声音不失真,采样频率应在40kHz以上。常用的音频采样频率有:8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz、96kHz、192kHz等。

(2) 量化精度(位宽)

上图中,每一个红色的采样点,都需要用一个数值来表示大小,这个数值的数据类型大小可以是:4bit、8bit、16bit、32bit等等,位数越多,表示得就越精细,声音质量自然就越好,当然,数据量也会成倍增大。

常见的位宽是:8bit 或者 16bit

(3) 声道数(channels)

由于音频的采集和播放是可以叠加的,因此,可以同时从多个音频源采集声音,并分别输出到不同的扬声器,故声道数一般表示声音录制时的音源数量或回放时相应的扬声器数量。

单声道(Mono)和双声道(Stereo)比较常见,顾名思义,前者的声道数为1,后者为2

(4) 音频帧(frame)

这个概念在应用开发中非常重要,网上很多文章都没有专门介绍这个概念。

音频跟视频很不一样,视频每一帧就是一张图像,而从上面的正玄波可以看出,音频数据是流式的,本身没有明确的一帧帧的概念,在实际的应用中,为了音频算法处理/传输的方便,一般约定俗成取2.5ms~60ms为单位的数据量为一帧音频。

这个时间被称之为“采样时间”,其长度没有特别的标准,它是根据编解码器和具体应用的需求来决定的,我们可以计算一下一帧音频帧的大小:

假设某通道的音频信号是采样率为8kHz,位宽为16bit,20ms一帧,双通道,则一帧音频数据的大小为:

int size = 8000 x 16bit x 0.02s x 2 = 5120 bit = 640 byte

5. 常见的音频编码方式有哪些?

上面提到过,模拟的音频信号转换为数字信号需要经过采样和量化,量化的过程被称之为编码,根据不同的量化策略,产生了许多不同的编码方式,常见的编码方式有:PCM 和 ADPCM,这些数据代表着无损的原始数字音频信号,添加一些文件头信息,就可以存储为WAV文件了,它是一种由微软和IBM联合开发的用于音频数字存储的标准,可以很容易地被解析和播放。

我们在音频开发过程中,会经常涉及到WAV文件的读写,以验证采集、传输、接收的音频数据的正确性。

6. 常见的音频压缩格式有哪些?

首先简单介绍一下音频数据压缩的最基本的原理:因为有冗余信息,所以可以压缩。

(1) 频谱掩蔽效应: 人耳所能察觉的声音信号的频率范围为20Hz~20KHz,在这个频率范围以外的音频信号属于冗余信号。

(2) 时域掩蔽效应: 当强音信号和弱音信号同时出现时,弱信号会听不到,因此,弱音信号也属于冗余信号。

下面简单列出常见的音频压缩格式:

MP3,AAC,OGG,WMA,Opus,FLAC,APE,m4a,AMR,等等

7. Adndroid VoIP相关的开源应用有哪些 ?

imsdroid,sipdroid,csipsimple,linphone,WebRTC 等等

8. 音频算法处理的开源库有哪些 ?

speex、ffmpeg,webrtc audio module(NS、VAD、AECM、AGC),等等

10. Android提供了哪些音频开发相关的API?

音频采集: MediaRecoder,AudioRecord

音频播放: SoundPool,MediaPlayer,AudioTrack (它们之间的区别可以参考 这篇 文章)

音频编解码: MediaCodec

NDK API: OpenSL ES

11. 音频开发的延时标准是什么?

ITU-TG.114规定,对于高质量语音可接受的时延是300ms。一般来说,如果时延在300~400ms,通话的交互性比较差,但还可以接受。时延大于400ms时,则交互通信非常困难

如何使用OpenSL ES在c4droid中进行声音编程

使用opensl es 的前提条件是在源代码中:

#include SLES/OpenSLES.h, 包含 opensl es的头文件

在gcc中:

-lOpenSLES 链接 opensl es的库文件

大休步骤如下:

1.创建声音引擎

2.创建声音播放器

3.设置播放缓冲

opensl es 主要操作的是 介面(interface),大体来说有如下几个介面:

SLObjectItf : 对象介面,

SLEngineItf :引擎介面

SLPlayItf:播放介面

SLBufferQueueItf :缓冲队列介面

SLEffectSendItf:音效发送介面

SLMuteSoloItf : 声道关闭 /单声道介面

SLVolumeItf : 声量介面

除了 slCreateEngine 这一条函数是用来创建声音引擎对象介面以外,其它的所有操作都是通过介面的成员函数完成的,现在我们来研究如何初始化声音引擎

初始化声音引擎需要3个介面,我们要将它们声明为全局变量:

SLObjectItf _aud;/* 声音引擎的对象介面 */

SLEngineItf _aud_eng;/* 声音引擎 */

SLObjectItf _aud_mix;/* 混音器对象介面 */

首先我们创建声音引擎的对象介面 :

slCreateEngine(_aud, 0, NULL, 0, NULL, NULL);

创建之后的介面并不能立即使用,我们首先要通过介面的子函数实现(Realize)它:

(*_aud)-Realize(_aud, SL_BOOLEAN_FALSE);/* 通过_aud的Realize子函数实现声音引擎的对象介面 */

实现之后,我们从声音引擎的对象中抓取声音引擎,在这里我们通过介面的子函数抓取介面 (GetInterface),抓取对像是 _aud, 抓取类型是引擎,抓取后存放的内存位置是我们先前声明的引擎介面_aud_eng的指针位置。指令如下:

(*_aud)-GetInterface(_aud, SL_IID_ENGINE, _aud_eng);

这样声音引擎就初始化了

第三步我们要做的是从声音引擎中创建 "输出混音器" 对象,这样我们才可以将声音播放出来。

注意,同 声音引擎的对象一样, 由于 "输出混音器" 是对象,我们必须创建后在实现(Realize)它。

由于"输出混音器"创建的同时需要两个音效参数,所以我们先准备好这两个参数:第一个参数类型是声音介面编号(SLInterfaceID),是一个数组,我们可以将其看成一个音效配置列表,在其中放置不同的音效编号。第二个参数是一个逻辑数组:是否强制实现声音介面编号中对应音效,如果某个音效的逻辑为真(SL_BOOLEAN_TRUE),则在无法实现该音效时视为"输出混音器"创建失败,否则将忽略该音效。因为安卓的声硬件对音效的支持不同,所以最好不要强制实现,所以我们在第二个数组中全部填写SL_BOOLEAN_FALSE 。

现在我们开始创建"输出混音器",环境回响(SL_IID_ENVIRONMENTALREVERB )是比较常见的音效,我们将非强制性的使用该音效。

SLInterfaceID effect[1] = {SL_IID_ENVIRONMENTALREVERB}; /*环境回响音效 */

SLboolean effect_bool[1] = {SL_BOOLEAN_FALSE}; /* 回响音效强制实现逻辑 */

(*_aud_eng)-CreateOutputMix(_aud_eng, _aud_mix, 1, effect, effect_bool);/* 从声音引擎中创建“输出混音器” */

(*_aud_mix)-Realize(_aud_mix, SL_BOOLEAN_FALSE); /* 实现刚创建的“输出混音器” */

样一来,所有的初始化工作就全部完成了。我们获得如下完整代码:

SLObjectItf _aud;/* 声音引擎对象 */

SLEngineItf _aud_eng;/* 声音引擎 */

SLObjectItf _aud_mix;/* 输出混音器对象 */

/* audio_init: 初始化opensl es */

int audio_init ()

{

SLInterfaceID effect[1] = {SL_IID_ENVIRONMENTALREVERB}; /* 音效 */

SLboolean effect_bool[1] = {SL_BOOLEAN_FALSE}; /*音效强制实现逻辑 */

slCreateEngine(_aud, 0, NULL, 0, NULL, NULL);/* 创建声音引擎对象 */

(*_aud)-Realize(_aud, SL_BOOLEAN_FALSE);/* 实现声音引擎对象 */

(*_aud)-GetInterface(_aud, SL_IID_ENGINE, _aud_eng);/* 从声音引擎对象中抓取声音引擎 */

(*_aud_eng)-CreateOutputMix(_aud_eng, _aud_mix, 1, effect, effect_bool);/* 通过声音引擎创建输出混音器对象,并且非强制性的开启环境混响效果 */

(*_aud_mix)-Realize(_aud_mix, SL_BOOLEAN_FALSE);/* 实现混音器对象 */

}

初始化引擎之后, 我们还要创建一个播放器对象,就可以在播放器中输出声音了

播放器对象和输出混音器一样,是对象,创建后需要进行实现:

SLObjectItf _aud_plyobj; /*播放器对象 */

(*_aud_eng)-CreateAudioPlayer(_aud_eng, _aud_plyobj, sndsrc, sndsnk, 3, ids, req);

/* 这是创建声音播放器对象aud_plyobj的函数 */

前两个参数分别把 声音引擎 和 播放器引擎的指针位置填上就可以了

我们真正需要填写的是后面4个参数 :

sndsrc: 声音数据源

sndsnk:声音输出池(data sink),也就是声音输出设备

3:功能清单数目,我们要让播放器支持3种功能

ids: 功能清单,我们要让播放器支持的功能

req:功能强制实现逻辑

opensl和audiotrack区别

1、管理不同。AudioTrack是在Android系统中管理,OpenSL是针对嵌入式管理。

2、音频类型不同。AudioTrack播放单一音频资源,OpenSL是平台的音频标准。

opensl音频输出是什么

8.OpenSL ES全称为Open Sound Library for EmbeddedSystems,即嵌入式音频加速标准。OpenSL ES是无授权费、跨平台、针对嵌入式系统精心优化的硬件音频加速API。它为嵌入式移动多媒体设备上的本地应用程序开发者提供了标准化、高性能、低响应时间的音频功能实现方法,同时还实现了软/硬件音频性能的直接跨平台部署,不仅降低了执行难度,而且促进了高级音频市场的发展。简单来说OpenSL ES是-一个嵌入式跨平台免费的音频处理库。所以它不是Android特有的。

(责任编辑:IT教学网)

更多