OpenSLES

文章详细介绍了OpenSLES在Android中播放声音的流程,包括创建和初始化SL引擎,创建混音器,设置播放器,利用回调函数写入缓冲队列以及播放。关键接口如slCreateEngine、Realize、GetInterface和CreateAudioPlayer等在过程中起到重要作用。
摘要由CSDN通过智能技术生成

OpenSLES

OpenSLES 播放声音流程

创建并设置 SL 引擎
创建并设置混音器
创建并设置播放器
设置回调并写入缓冲队列

播放队列

只要往播放队列中压入数据, 就会播放. 采用的是回调函数, 当取出的 buffer 数据播放完毕, 就会清理 buffer, 让队列空出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HnqeTGvV-1688353498902)(C:\Users\Administrator\Desktop\readme\opensles_queue.png)]在这里插入图片描述

SLObjectItf 的定义

typedef const struct SLObjectItf_ * const * SLObjectItf;

结构体 SLObjectItf_ 里面全是函数指针

struct SLObjectItf_ {
	SLresult (*Realize) (
		SLObjectItf self,
		SLboolean async
	);
	SLresult (*Resume) (
		SLObjectItf self,
		SLboolean async
	);
	SLresult (*GetState) (
		SLObjectItf self,
		SLuint32 * pState
	);
	SLresult (*GetInterface) (
		SLObjectItf self,
		const SLInterfaceID iid,//获取的结构功能id
		void * pInterface//存储接口功能的对象,即接口对象
	);
	SLresult (*RegisterCallback) (
		SLObjectItf self,
		slObjectCallback callback,
		void * pContext
	);
	void (*AbortAsyncOperation) (
		SLObjectItf self
	);
	void (*Destroy) (
		SLObjectItf self
	);
	SLresult (*SetPriority) (
		SLObjectItf self,
		SLint32 priority,
		SLboolean preemptable
	);
	SLresult (*GetPriority) (
		SLObjectItf self,
		SLint32 *pPriority,
		SLboolean *pPreemptable
	);
	SLresult (*SetLossOfControlInterfaces) (
		SLObjectItf self,
		SLint16 numInterfaces,
		SLInterfaceID * pInterfaceIDs,
		SLboolean enabled
	);
};

SLEngineItf 的定义

typedef const struct SLEngineItf_ * const * SLEngineItf;

结构体 SLEngineItf_ 里面全是函数指针

struct SLEngineItf_ {

	SLresult (*CreateLEDDevice) (
		SLEngineItf self,
		SLObjectItf * pDevice,
		SLuint32 deviceID,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
	SLresult (*CreateVibraDevice) (
		SLEngineItf self,
		SLObjectItf * pDevice,
		SLuint32 deviceID,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
	SLresult (*CreateAudioPlayer) (
		SLEngineItf self,//声音引擎
		SLObjectItf * pPlayer,//声音播放器
		SLDataSource *pAudioSrc,//声音数据源
		SLDataSink *pAudioSnk,//声音输出池, 声音输出设备
		SLuint32 numInterfaces,//功能清单数目
		const SLInterfaceID * pInterfaceIds,//功能清单, 要让播放器支持的功能
		const SLboolean * pInterfaceRequired//功能强制实现逻辑
	);
	SLresult (*CreateAudioRecorder) (
		SLEngineItf self,
		SLObjectItf * pRecorder,
		SLDataSource *pAudioSrc,
		SLDataSink *pAudioSnk,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
	SLresult (*CreateMidiPlayer) (
		SLEngineItf self,
		SLObjectItf * pPlayer,
		SLDataSource *pMIDISrc,
		SLDataSource *pBankSrc,
		SLDataSink *pAudioOutput,
		SLDataSink *pVibra,
		SLDataSink *pLEDArray,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
	SLresult (*CreateListener) (
		SLEngineItf self,
		SLObjectItf * pListener,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
	SLresult (*Create3DGroup) (
		SLEngineItf self,
		SLObjectItf * pGroup,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
	SLresult (*CreateOutputMix) (
		SLEngineItf self,
		SLObjectItf * pMix,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
	SLresult (*CreateMetadataExtractor) (
		SLEngineItf self,
		SLObjectItf * pMetadataExtractor,
		SLDataSource * pDataSource,
		SLuint32 numInterfaces,
		const SLInterfaceID * pInterfaceIds,
		const SLboolean * pInterfaceRequired
	);
    SLresult (*CreateExtensionObject) (
        SLEngineItf self,
        SLObjectItf * pObject,
        void * pParameters,
        SLuint32 objectID,
        SLuint32 numInterfaces,
        const SLInterfaceID * pInterfaceIds,
        const SLboolean * pInterfaceRequired
    );
	SLresult (*QueryNumSupportedInterfaces) (
		SLEngineItf self,
		SLuint32 objectID,
		SLuint32 * pNumSupportedInterfaces
	);
	SLresult (*QuerySupportedInterfaces) (
		SLEngineItf self,
		SLuint32 objectID,
		SLuint32 index,
		SLInterfaceID * pInterfaceId
	);
    SLresult (*QueryNumSupportedExtensions) (
        SLEngineItf self,
        SLuint32 * pNumExtensions
    );
    SLresult (*QuerySupportedExtension) (
        SLEngineItf self,
        SLuint32 index,
        SLchar * pExtensionName,
        SLint16 * pNameLength
    );
    SLresult (*IsExtensionSupported) (
        SLEngineItf self,
        const SLchar * pExtensionName,
        SLboolean * pSupported
    );
};

播放引擎创建与初始化

slCreateEngine(创建引擎)

**创建播放 engine **

SL_API SLresult SLAPIENTRY slCreateEngine(
	SLObjectItf             *pEngine,
	SLuint32                numOptions,
	const SLEngineOption    *pEngineOptions,
	SLuint32                numInterfaces,
	const SLInterfaceID     *pInterfaceIds,
	const SLboolean         * pInterfaceRequired
);
  • pEngine 引擎指针

  • numOptions 选择项数量

  • pEngineOptions 具体的选择项

  • numInterfaces 支持的接口数量

  • pInterfaceIds 支持的接口

  • pInterfaceRequired 接口是关闭还是开启

SLObjectItf engineObject;
slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);

Realize(初始化引擎)

初始化化上一步创建的引擎结构体

(*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);

GetInterface(获取引擎接口)

获取引擎接口

SLEngineItf engineInterface;//引擎接口
(*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineInterface);

创建输出设备

CreateOutputMix(创建混音器)

SLObjectItf outputMixObject;//混音器
(*engineInterface)->CreateOutputMix(
            engineInterface, &outputMixObject,
            SL_BOOLEAN_FALSE, nullptr, nullptr);

Realize(初始化混音器)

初始化化上一步创建的结构体

(*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);

GetInterface(获取混音器接口)

获取混音器接口, 不启用混响, 可以不用获取此接口

SLEngineItf outputMixEnvironmentalReverb;//混音器接口
(*outputMixObject)->GetInterface(
    outputMixObject, SL_IID_ENVIRONMENTALREVERB,
    &outputMixEnvironmentalReverb);

定义输出接口

  • 创建混音器 mix
  • 创建一个混音器输出对象 audioSink, 而混音的输出对象 outmix,就存在audioSink中初始化的。
//设置混音器
SLDataLocator_OutputMix outputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
//声音输出数据
SLDataSink audioSink = {&outputMix, nullptr};

配置 PCM 音频格式信息

//创建 Buffer 缓冲队列, 大小为 10
SLDataLocator_AndroidSimpleBufferQueue simpleBufferQueue = {
    SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 10};
// PCM数据格式
SLDataFormat_PCM formatPcm = {
    SL_DATAFORMAT_PCM,//数据格式
    2,//声道数
    SL_SAMPLINGRATE_44_1,//采样率 44100(每秒采集44100个点)
    SL_PCMSAMPLEFORMAT_FIXED_16,//每秒采样样本 存放大小 16bit
    SL_PCMSAMPLEFORMAT_FIXED_16,//每个样本 存放大小 16bit
    SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, // 前左声道  前右声道
    SL_BYTEORDER_LITTLEENDIAN//字节序(小端) 例如:int类型四个字节(到底是 高位在前 还是 低位在前 的排序方式,一般我们都是小端)
};
//音频数据源
SLDataSource audioSrc = {&simpleBufferQueue, &formatPcm};

创建播放器

const SLInterfaceID ids[1] = {SL_IID_BUFFERQUEUE};// 播放队列接口参数
const SLboolean req[1] = {SL_BOOLEAN_TRUE};//表示接口是否开放
SLObjectItf bpPlayerObject;//播放器
SLPlayItf bpPlayerInterface;//播放器接口
SLAndroidSimpleBufferQueueItf bpPlayerBufferQueue;//播放器采样缓冲队列
//创建播放器
int result = (*engineInterface)->CreateAudioPlayer(
    engineInterface,
    &bpPlayerObject,
    &audioSrc,
    &audioSink,
    //工作队列
    1,
    ids,
    req);
if (result != SL_RESULT_SUCCESS) {
    return;
}
//初始化播放器
result = (*bpPlayerObject)->Realize(bpPlayerObject, SL_BOOLEAN_FALSE);
if (result != SL_RESULT_SUCCESS) {
    return;
}
//获取播放器接口
result = (*bpPlayerObject)->GetInterface(bpPlayerObject, SL_IID_PLAY, &bpPlayerInterface);
if (result != SL_RESULT_SUCCESS) {
    return;
}
//获取播放器队列接口
    result = (*bpPlayerObject)->GetInterface(bpPlayerObject, SL_IID_BUFFERQUEUE, &bpPlayerBufferQueue);
    if (result != SL_RESULT_SUCCESS) {
        LOGE("获取播放器队列接口 error")
        return;
    }

设置回调函数,启动引擎播放

//回调函数
void bpPlayerCallback(SLAndroidSimpleBufferQueueItf caller,
                      void *pContext) {
    auto *audio_channel = static_cast<AudioChannel *>(pContext);
    int pcm_size = audio_channel->getPcm();//这里是从ffmpeg里面获取重采样后的 PCM 数据
    (*caller)->Enqueue(caller, audio_channel->out_buffers, pcm_size);
}


SLAndroidSimpleBufferQueueItf bpPlayerBufferQueue;//播放器采样缓冲队列
//设置回调函数
(*bpPlayerBufferQueue)->RegisterCallback(bpPlayerBufferQueue, bpPlayerCallback, this);
//设置播放器播放状态
(*bpPlayerInterface)->SetPlayState(bpPlayerInterface, SL_PLAYSTATE_PLAYING);
//手动调用一次回调函数
bpPlayerCallback(bpPlayerBufferQueue, this);

在 android 中使用

  1. 链接 OpenSLES 库

    target_link_libraries(OpenSLES )

  2. 导入头文件

    #include <SLES/OpenSLES.h>

    #include <SLES/OpenSLES_Android.h>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值