什么是OpenSL ES? openSL ES是一个专用于嵌入式系统的音频库,可以提供对音频的播放和录制等相关功能,在Android上Aduio Recoder都是基于此库实现的,同时,我们也可以在Android的JNI里面使用此库进行音频开发,官方介绍请点击
OpenSL ES几乎都是通过一个Object一个Interface成对来获取一项功能,比如OpenSL ES的全局引擎engineObject和engineInterface:
SLObjectItf engineObject; //引擎始祖对象
SLEngineItf engineInterface; //引擎接口
slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
(*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineInterface);
从上一步得知所有的功能都是先创建Object,在获取其interface,其内部大致有这么一个状态机制
使用OpenSL ES进行音频录制和播放时,我们都是和一个缓冲区(自己创建)打交道,录音时,触发回调函数后,说明缓存区数据填满了,我们可以从里面取出录好的数据;播放时,触发回调函数后,说明缓冲区数据播完了,我们往缓冲区添加音频数据
录音重点主要集中在初始化配置方面:
SLDataSource和SLDataSink
typedef struct SLDataSource_ {
void *pLocator; //输入数据类别
void *pFormat; //输入数据格式
} SLDataSource;
typedef struct SLDataSink_ {
void *pLocator;
void *pFormat;
} SLDataSink;
其中pLocator的类型可以是:
SLDataLocator_Address
SLDataLocator_BufferQueue
SLDataLocator_IODevice
SLDataLocator_MIDIBufferQueue
SLDataLocator_URI
针对录音的数据来源我们可以选择IODevice,以下是对IODevice的配置:
//录音源source
slHelper->ioDevice.locatorType = SL_DATALOCATOR_IODEVICE; //源头是io设备
slHelper->ioDevice.deviceType = SL_IODEVICE_AUDIOINPUT; //音频输入
slHelper->ioDevice.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
slHelper->ioDevice.device = NULL; //device ID生效的前提必须device NULL
配置录音的输出,我们选择SLDataLocator_BufferQueue类型,输出到缓冲区,还需要配置输出的数据给format
//输出
queue.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; //输出到缓冲队列
queue.numBuffers = 2; //2个缓冲队列
pcmFormat.formatType = SL_DATAFORMAT_PCM; //录音数据格式
pcmFormat.numChannels = channels;
pcmFormat.samplesPerSec = sampleRate;
pcmFormat.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16; //每个采样点bit
pcmFormat.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
pcmFormat.channelMask = getChannelMask(channels); //根据声道数确定掩码
pcmFormat.endianness = SL_BYTEORDER_LITTLEENDIAN; //字节小端模式
sink.pLocator = &(queue);
sink.pFormat = &(pcmFormat);
最后,就可以创建Recoder开始播放了:
///Recorder/////
SLInterfaceID id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE};
SLboolean required[] = {SL_BOOLEAN_TRUE};
(*engineInterface)->CreateAudioRecorder(engineInterface, &recorderObject
, &source, &sink, 1, id, required);
(*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
//Register
(*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
&(androidBufferQueueItf));
(*androidBufferQueueItf)->RegisterCallback(androidBufferQueueItf, openSLCallBack, NULL);
//start recorder
(*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderInterface);
(*recorderInterface)->SetRecordState(recorderInterface, SL_RECORDSTATE_RECORDING);
ok,以上就是楼主学习过程中的一点小小心得,如有不正,请指正; 以下是我的学习demo
参考的链接: https://juejin.im/post/5bda5ed85188257f3e09d6f5 https://zhuanlan.zhihu.com/p/20865418
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。