使用OpenSL ES開(kāi)發(fā)音頻播放功能

2024-02-16 13:53 更新

OpenSL ES全稱(chēng)為Open Sound Library for Embedded Systems,是一個(gè)嵌入式、跨平臺(tái)、免費(fèi)的音頻處理庫(kù)。為嵌入式移動(dòng)多媒體設(shè)備上的應(yīng)用開(kāi)發(fā)者提供標(biāo)準(zhǔn)化、高性能、低延遲的API。HarmonyOS的Native API基于Khronos Group開(kāi)發(fā)的OpenSL ES 1.0.1 API 規(guī)范實(shí)現(xiàn),開(kāi)發(fā)者可以通過(guò)<OpenSLES.h>和<OpenSLES_OpenHarmony.h>在HarmonyOS上使用相關(guān)API。

HarmonyOS上的OpenSL ES

OpenSL ES中提供了以下的接口,HarmonyOS當(dāng)前僅實(shí)現(xiàn)了部分OpenSL ES接口,可以實(shí)現(xiàn)音頻播放的基礎(chǔ)功能。

調(diào)用未實(shí)現(xiàn)接口后會(huì)返回SL_RESULT_FEATURE_UNSUPPORTED,當(dāng)前沒(méi)有相關(guān)擴(kuò)展可以使用。

以下列表列舉了HarmonyOS上已實(shí)現(xiàn)的OpenSL ES的接口,具體說(shuō)明請(qǐng)參考OpenSL ES規(guī)范:

  • HarmonyOS上支持的Engine接口
    • 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 (*CreateOutputMix) (SLEngineItf self, SLObjectItf * pMix, SLuint32 numInterfaces, const SLInterfaceID * pInterfaceIds, const SLboolean * pInterfaceRequired)
  • HarmonyOS上支持的Object接口:
    • SLresult (*Realize) (SLObjectItf self, SLboolean async)
    • SLresult (*GetState) (SLObjectItf self, SLuint32 * pState)
    • SLresult (*GetInterface) (SLObjectItf self, const SLInterfaceID iid, void * pInterface)
    • void (*Destroy) (SLObjectItf self)
  • HarmonyOS上支持的Playback接口:
    • SLresult (*SetPlayState) (SLPlayItf self, SLuint32 state)
    • SLresult (*GetPlayState) (SLPlayItf self, SLuint32 *pState)
  • HarmonyOS上支持的Volume控制接口
    • SLresult (*SetVolumeLevel) (SLVolumeItf self, SLmillibel level)
    • SLresult (*GetVolumeLevel) (SLVolumeItf self, SLmillibel *pLevel)
    • SLresult (*GetMaxVolumeLevel) (SLVolumeItf self, SLmillibel *pMaxLevel)
  • HarmonyOS上支持的BufferQueue接口
    以下接口需引入<OpenSLES_OpenHarmony.h>使用。

    接口

    說(shuō)明

    SLresult (*Enqueue) (SLOHBufferQueueItf self, const void *buffer, SLuint32 size)

    根據(jù)情況將buffer加到相應(yīng)隊(duì)列中。

    如果是播放操作,則將帶有音頻數(shù)據(jù)的buffer插入到filledBufferQ_隊(duì)列中;如果是錄音操作,則將錄音使用后的空閑buffer插入到freeBufferQ_隊(duì)列中。

    self:表示調(diào)用該函數(shù)的BufferQueue接口對(duì)象。

    buffer:播放時(shí)表示帶有音頻數(shù)據(jù)的buffer,錄音時(shí)表示已存儲(chǔ)完錄音數(shù)據(jù)后的空閑buffer。

    size:表示buffer的大小。

    SLresult (*Clear) (SLOHBufferQueueItf self)

    釋放BufferQueue接口對(duì)象。

    self:表示調(diào)用該函數(shù)的BufferQueue接口對(duì)象將被釋放。

    SLresult (*GetState) (SLOHBufferQueueItf self, SLOHBufferQueueState *state)

    獲取BufferQueue接口對(duì)象狀態(tài)。

    self:表示調(diào)用該函數(shù)的BufferQueue接口對(duì)象。

    state:BufferQueue的當(dāng)前狀態(tài)。

    SLresult (*RegisterCallback) (SLOHBufferQueueItf self, SlOHBufferQueueCallback callback, void* pContext)

    注冊(cè)回調(diào)函數(shù)。

    self:表示調(diào)用該函數(shù)的BufferQueue接口對(duì)象。

    callback:播放/錄音時(shí)注冊(cè)的回調(diào)函數(shù)。

    pContext:播放時(shí)傳入待播放音頻文件,錄音時(shí)傳入將要錄制的音頻文件。

    SLresult (*GetBuffer) (SLOHBufferQueueItf self, SLuint8** buffer, SLuint32* size)

    根據(jù)情況獲取相應(yīng)的buffer。

    如果是播放操作,則從freeBufferQ_隊(duì)列中獲取空閑buffer;如果是錄音操作,則從filledBufferQ_隊(duì)列中獲取攜帶錄音數(shù)據(jù)的buffer。

    self:表示調(diào)用該函數(shù)的BufferQueue接口對(duì)象。

    buffer:播放時(shí)表示空閑的buffer,錄音時(shí)表示攜帶錄音數(shù)據(jù)的buffer。

    size:表示buffer的大小。

完整示例

參考以下示例代碼,播放一個(gè)音頻文件。

  1. 添加頭文件。
    1. #include <OpenSLES.h>
    2. #include <OpenSLES_OpenHarmony.h>
    3. #include <OpenSLES_Platform.h>
  2. 使用slCreateEngine接口和獲取engine實(shí)例。
    1. SLObjectItf engineObject = nullptr;
    2. slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
    3. (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
  3. 獲取接口SL_IID_ENGINE的engineEngine實(shí)例。
    1. SLEngineItf engineEngine = nullptr;
    2. (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
  4. 配置播放器信息,創(chuàng)建AudioPlayer。
    1. SLDataLocator_BufferQueue slBufferQueue = {
    2. SL_DATALOCATOR_BUFFERQUEUE,
    3. 0
    4. };
    5. // 具體參數(shù)需要根據(jù)音頻文件格式進(jìn)行適配
    6. SLDataFormat_PCM pcmFormat = {
    7. SL_DATAFORMAT_PCM,
    8. 2, // 通道數(shù)
    9. SL_SAMPLINGRATE_48, // 采樣率
    10. SL_PCMSAMPLEFORMAT_FIXED_16, // 音頻采樣格式
    11. 0,
    12. 0,
    13. 0
    14. };
    15. SLDataSource slSource = {&slBufferQueue, &pcmFormat};
    16. SLObjectItf pcmPlayerObject = nullptr;
    17. (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, nullptr, 0, nullptr, nullptr);
    18. (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
  5. 獲取接口SL_IID_OH_BUFFERQUEUE的bufferQueueItf實(shí)例。
    1. SLOHBufferQueueItf bufferQueueItf;
    2. (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
  6. 打開(kāi)音頻文件,注冊(cè)BufferQueueCallback回調(diào)。
    1. static void BufferQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
    2. {
    3. SLuint8 *buffer = nullptr;
    4. SLuint32 pSize;
    5. (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &pSize);
    6. // 將待播放音頻數(shù)據(jù)寫(xiě)入buffer
    7. (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
    8. }
    9. void *pContext; // 可傳入自定義的上下文信息,會(huì)在Callback內(nèi)收到
    10. (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, pContext);
  7. 獲取接口SL_PLAYSTATE_PLAYING的playItf實(shí)例,開(kāi)始播放。
    1. SLPlayItf playItf = nullptr;
    2. (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
    3. (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
  8. 結(jié)束音頻播放。
    1. (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
    2. (*pcmPlayerObject)->Destroy(pcmPlayerObject);
    3. (*engineObject)->Destroy(engineObject);
以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)