From 4b76f849382616a62a29576bd7e7aca6cf5b9567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=B8=85?= Date: Mon, 9 May 2022 14:00:41 +0000 Subject: [PATCH] Signed-off-by: yangshuai --- .../media/opensles-playback.md | 185 +++++++++++------- 1 file changed, 112 insertions(+), 73 deletions(-) diff --git a/zh-cn/application-dev/media/opensles-playback.md b/zh-cn/application-dev/media/opensles-playback.md index 144c02e4f0..798caabbe0 100644 --- a/zh-cn/application-dev/media/opensles-playback.md +++ b/zh-cn/application-dev/media/opensles-playback.md @@ -1,84 +1,123 @@ -OpenSL ES音频播放开发指导 +# OpenSL ES音频播放开发指导 -场景介绍 +## 场景介绍 -开发者可以通过本文了解到在OpenHarmony如何使用OpenSL ES进行音频播放相关操作;当前仅实现了部分OpenSL ES接口,未实现接口调用后会返回SL_RESULT_FEATURE_UNSUPPORTED +开发者可以通过本文了解到在**OpenHarmony**如何使用**OpenSL ES**进行音频播放相关操作;当前仅实现了部分[**OpenSL ES**接口](https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h),未实现接口调用后会返回**SL_RESULT_FEATURE_UNSUPPORTED** -开发步骤 +## 开发步骤 -以下步骤描述了在OpenHarmony如何使用OpenSL ES开发音频播放功能: +以下步骤描述了在**OpenHarmony**如何使用**OpenSL ES**开发音频播放功能: 1. 添加头文件 - #include - #include - #include - -2. 使用 slCreateEngine 接口和获取 engine 实例。 - SLObjectItf engineObject = nullptr; - slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr); - (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); - -3. 获取接口 SL_IID_ENGINE 的 engineEngine 实例 - SLEngineItf engineEngine = nullptr; - (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); - -4. 配置播放器信息,创建 AudioPlayer 。 - SLDataLocator_BufferQueue slBufferQueue = { - SL_DATALOCATOR_BUFFERQUEUE, - 0 - }; - - //具体参数需要根据音频文件格式进行适配 - SLDataFormat_PCM pcmFormat = { - SL_DATAFORMAT_PCM, - 2, - 48000, - 16, - 0, - 0, - 0 - }; - SLDataSource slSource = {&slBufferQueue, &pcmFormat}; - - SLObjectItf pcmPlayerObject = nullptr; - (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, null, 0, nullptr, nullptr); - (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE); - -5. 获取接口 SL_IID_OH_BUFFERQUEUE 的 bufferQueueItf 实例 - SLOHBufferQueueItf bufferQueueItf; - (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf); - -6. 打开音频文件,注册 BuqqerQueueCallback 回调 - FILE *wavFile_ = nullptr; - - static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size) - { - FILE *wavFile = (FILE *)pContext; - if (!feof(wavFile)) { - SLuint8 *buffer = nullptr; - SLuint32 pSize = 0; - (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize); - //从文件读取数据 - fread(buffer, 1, size, wavFile); - (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size); - } - return; - } - - //wavFile_ 需要设置为用户想要播放的文件描述符 - wavFile_ = fopen(path, "rb"); - (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BuqqerQueueCallback, wavFile_); - -7. 获取接口 SL_PLAYSTATE_PLAYING 的 playItf 实例,开始播放 - SLPlayItf playItf = nullptr; - (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf); - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); - + + ```c++ + #include + #include + #include + ``` + + + +2. 使用 **slCreateEngine** 接口和获取 **engine** 实例。 + + ```c++ + SLObjectItf engineObject = nullptr; + slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr); + (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE); + ``` + + + +3. 获取接口 **SL_IID_ENGINE** 的 **engineEngine** 实例 + + ```c++ + SLEngineItf engineEngine = nullptr; + (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine); + ``` + + + +4. 配置播放器信息,创建 **AudioPlayer** 。 + + ```c++ + SLDataLocator_BufferQueue slBufferQueue = { + SL_DATALOCATOR_BUFFERQUEUE, + 0 + }; + + //具体参数需要根据音频文件格式进行适配 + SLDataFormat_PCM pcmFormat = { + SL_DATAFORMAT_PCM, + 2, + 48000, + 16, + 0, + 0, + 0 + }; + SLDataSource slSource = {&slBufferQueue, &pcmFormat}; + + SLObjectItf pcmPlayerObject = nullptr; + (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, null, 0, nullptr, nullptr); + (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE); + ``` + + + +5. 获取接口 **SL_IID_OH_BUFFERQUEUE** 的 **bufferQueueItf** 实例 + + ``` + SLOHBufferQueueItf bufferQueueItf; + (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf); + ``` + + + +6. 打开音频文件,注册 **BuqqerQueueCallback** 回调 + + ```c++ + FILE *wavFile_ = nullptr; + + static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size) + { + FILE *wavFile = (FILE *)pContext; + if (!feof(wavFile)) { + SLuint8 *buffer = nullptr; + SLuint32 pSize = 0; + (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize); + //从文件读取数据 + fread(buffer, 1, size, wavFile); + (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size); + } + return; + } + + //wavFile_ 需要设置为用户想要播放的文件描述符 + wavFile_ = fopen(path, "rb"); + (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BuqqerQueueCallback, wavFile_); + ``` + + + +7. 获取接口 **SL_PLAYSTATE_PLAYING** 的 **playItf** 实例,开始播放 + + ```c++ + SLPlayItf playItf = nullptr; + (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf); + (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING); + ``` + + + 8. 结束音频播放 - (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); - (*pcmPlayerObject)->Destroy(pcmPlayerObject); - (*engineObject)->Destroy(engineObject); + + ```c++ + (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED); + (*pcmPlayerObject)->Destroy(pcmPlayerObject); + (*engineObject)->Destroy(engineObject); + ``` + -- GitLab