关于OpenSL ES
OpenSL ES 全称是Open Sound Library for Embedded Systems , 即嵌入式音频加速标准。OpenSL ES 是开源免费、跨平台、针对嵌入式系统优化的硬件音频加速API。它为开发者提供了标准化、高性能、低响应时间的音频功能实现方法。
在使用OpenSL ES前,需要对OpenSL ES中的对象和接口的概念有一定的了解。
- 对象:对象是对一组资源及其状态的抽象,每个对象都有一个在其创建时指定的类型,类型决定了对象可以执行的任务集,对象有点类似于C++中类的概念。
- 接口:接口是对象提供的一组特征的抽象,这些抽象会为开发者提供一组方法以及每个接口的类型功能,在代码中,接口的类型由接口ID来标识。
简单来说就是,对象在代码中是没有实际的表示形式的,对象的创建也是通过接口来完成的。通过获取对象的方法来获取对象,进而可以使用对象的方法和属性,使用步骤如下:
以创建引擎为例,分为三步create -> realize -> get
- 创建一个引擎对象接口slCreateEngine(&engineObject,0,NULL,0,NULL,NULL);
- 实例化引擎对象(*engineObject)->Realize(engineObject,SL_BOOLEAN_FALSE);
- 获取这个引擎对象的方法接口(*engineObject)->GetInterface(engineObject,SL_IID_ENGINE,&engineEngine);
下面使用OpenSL ES来播放PCM数据
使用流程如下图:
代码实现
1.创建接口对象,即引擎对象
//创建接口对象,即引擎对象
//Create engine
slCreateEngine(&engineObject,0,NULL,0,NULL,NULL);
//realize the engine
(*engineObject)->Realize(engineObject,SL_BOOLEAN_FALSE);
//get the engine interface ,which is needed in order to create other objects
(*engineObject)->GetInterface(engineObject,SL_IID_ENGINE,&engineEngine);
2.设置混音器
//c创建混音器
//create output mix, with environmental reverb specified as a non-required interface
const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
const SLboolean req[1] = {SL_BOOLEAN_FALSE};
(*engineEngine)->CreateOutputMix(engineEngine,&outputMixObject,1,ids,req);
//realize the output mix
(*outputMixObject)->Realize(outputMixObject,SL_BOOLEAN_FALSE);
//get the environmental reverb interface
// this could fail if the environmental reverb effect is not available,
// either because the feature is not present, excessive CPU load, or
// the required MODIFY_AUDIO_SETTINGS permission was not requested and granted
SLresult lresult =(*outputMixObject)->GetInterface(outputMixObject,SL_IID_ENVIRONMENTALREVERB,&outputMixEnvironmentalReverb);
if(SL_RESULT_SUCCESS == lresult) {
(*outputMixEnvironmentalReverb)->SetEnvironmentalReverbProperties(
outputMixEnvironmentalReverb,&reverbSettings);
}
3.创建播放器或录音器
//创建播放器(录音器)
//create buffer queue audio player
//configure audio source
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, 2,
(SLuint32) getCurSampleRateForOpenSLES(pCodecParam != NULL ? pCodecParam->sample_rate : 0),
SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, SL_BYTEORDER_LITTLEENDIAN};
SLDataSource audioSrc = {&loc_bufq,&format_pcm};
//configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX,outputMixObject};
SLDataSink audioSnk = {&loc_outmix,NULL};
const SLInterfaceID ids1[4] = {SL_IID_BUFFERQUEUE,SL_IID_VOLUME,SL_IID_PLAYBACKRATE,SL_IID_MUTESOLO};
const SLboolean req1[4] = {SL_BOOLEAN_TRUE,SL_BOOLEAN_TRUE,SL_BOOLEAN_TRUE,SL_BOOLEAN_TRUE};
(*engineEngine)->CreateAudioPlayer(engineEngine,&bqPlayerObject,&audioSrc,&audioSnk,
4,ids1,req1);
//realize the player
(*bqPlayerObject)->Realize(bqPlayerObject,SL_BOOLEAN_FALSE);
//get the play interface
(*bqPlayerObject)->GetInterface(bqPlayerObject,SL_IID_PLAY,&bqPlayerPlay);
4.设置缓冲队列和回调函数
//创建缓冲队列和回调函数
//get the buffer queque interface
(*bqPlayerObject)->GetInterface(bqPlayerObject,SL_IID_BUFFERQUEUE,&bqPlayerBufferQueue);
//register callback on the buffer queue
(*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue,bqPlayerCallback,this);
回调函数
//this callback handler is called every time a buffer finishes playing
void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context) {
int size = getPcmData(&buffer);
SLresult result;
// enqueue another buffer
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer, 44100 * 2 * 2);
}
5.设置播放状态
//设置播放状态
//set the player's state to playing
(*bqPlayerPlay)->SetPlayState(bqPlayerPlay,SL_PLAYSTATE_PLAYING);
6.调用回调函数,开始播放
//StartPlay
bqPlayerCallback(bqPlayerBufferQueue,NULL);
完整代码如下:
https://github.com/Huzhuwei1/MusicPlayer.git
https://download.csdn.net/download/memory_of_the_wind/10803709