文档管理中心
您当前正在浏览新版开发者文档中心,目录分类和层级有所调整。点击左侧当前文档分类名称前的“☰”图标,可切换文档分类。 了解新版目录
指南与API参考指南媒体Audio Kit(音频服务)OpenSL ES开发指导(不再推荐)从OpenSL ES切换到OHAudio(C/C++)

从OpenSL ES切换到OHAudio(C/C++)

由于OpenSL ES无法满足音频系统的能力扩展,建议开发者使用OHAudio替代OpenSL ES开发音频业务。本文将介绍如何从使用OpenSL ES接口开发音频业务,切换为使用OHAudio接口。

支持的功能差异

两者支持的功能范围略有差异,OHAudio增加支持低时延播放/录制、监听业务变化等功能。

具体差异如下表所示。

展开
功能 OpenSL ES OHAudio
音频流式播放 √ √
音频流式录制 √ √
音频低时延播放 × √
音频低时延录制 × √
播放对象状态切换 √ √
录制对象状态切换 √ √
获取音频流对象状态 √ √
清理播放缓存 × √
监听音频打断事件 × √
监听音频流事件 × √
监听流异常事件 × √
监听播放设备变化事件 × √

开发模式差异

此小节将结合开发步骤,对比介绍OHAudio和OpenSL ES在开发模式上的差异。

音频播放和录制的实现类似,此处以音频播放为例说明。

构造实例

OpenSL ES:

通过全局接口获取到Engine对象,基于Engine结合不同输入输出配置参数,构造出不同音频播放对象。

收起
自动换行
深色代码主题
复制
  1. // 生成Engine Interface对象。
  2. SLEngineItf engine;
  3. // ...
  4. // 按需配置音频输入slSource。
  5. SLDataSource slSource;
  6. // ...
  7. // 按需配置音频输出slSink。
  8. SLDataSink slSink;
  9. // ...
  10. // 生成音频播放对象。
  11. SLObjectItf playerObject;
  12. (*engine)->CreateAudioPlayer(engine,
  13. &playerObject,
  14. &slSource,
  15. &slSink,
  16. 0,
  17. nullptr,
  18. nullptr);
  19. (*playerObject)->Realize(playerObject,
  20. SL_BOOLEAN_FALSE);

OHAudio:

采用建造器模式,通过建造器,配合自定义参数设置,生成音频播放对象。

收起
自动换行
深色代码主题
复制
  1. // 创建建造器。
  2. OH_AudioStreamBuilder *builder;
  3. OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
  4. // 设置自定义参数,否则会使用默认参数。
  5. OH_AudioStreamBuilder_SetSamplingRate(builder, 48000);
  6. OH_AudioStreamBuilder_SetChannelCount(builder, 2);
  7. OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
  8. OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
  9. // 关键参数,仅OHAudio支持,根据音频用途设置,系统会根据此参数实现音频策略自适应。
  10. OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
  11. // ...
  12. // 生成音频播放对象。
  13. OH_AudioRenderer *audioRenderer;
  14. OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);

状态切换

OpenSL ES:

基于Object获取状态切换Interface,使用该接口切换状态,只有SL_PLAYSTATE_STOPPED、SL_PLAYSTATE_PAUSED、SL_PLAYSTATE_PLAYING三种状态。

收起
自动换行
深色代码主题
复制
  1. // 基于播放对象,获取播放操作Interface。
  2. SLPlayItf playItf = nullptr;
  3. (*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playItf);
  4. // 状态切换。
  5. (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
  6. (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED);
  7. (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);

OHAudio:

有独立的状态切换接口,基于状态机进行状态切换,共6个OH_AudioStream_State状态,主要在AUDIOSTREAM_STATE_PREPARED、AUDIOSTREAM_STATE_RUNNING、AUDIOSTREAM_STATE_STOPPED、AUDIOSTREAM_STATE_PAUSED、AUDIOSTREAM_STATE_RELEASED状态间切换。

收起
自动换行
深色代码主题
复制
  1. // 状态切换。
  2. OH_AudioRenderer_Start(audioRenderer);
  3. OH_AudioRenderer_Pause(audioRenderer);
  4. OH_AudioRenderer_Stop(audioRenderer);

数据处理

OpenSL ES:

基于扩展的OHBufferQueue接口,通过注册自定义的Callback函数,根据数据请求时机,将待播放数据填入系统内提供的缓冲区中。

收起
自动换行
深色代码主题
复制
  1. static void MyBufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
  2. {
  3. SLuint8 *buffer = nullptr;
  4. SLuint32 bufferSize;
  5. // 获取系统内提供的buffer。
  6. (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &bufferSize);
  7. // 将待播放音频数据写入buffer。
  8. // ...
  9. // 将buffer输入系统。
  10. (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, bufferSize);
  11. }
  12. // 获取OHBufferQueue接口。
  13. SLOHBufferQueueItf bufferQueueItf;
  14. (*playerObject)->GetInterface(playerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
  15. // 可传入自定义的上下文信息,会在Callback内收到。
  16. void *pContext;
  17. (*bufferQueueItf)->RegisterCallback(bufferQueueItf, MyBufferQueueCallback, pContext);

OHAudio:

统一使用回调模式,在构造时注册数据写入回调,实现自定义的数据填充函数,在播放过程中会跟随系统调度和时延配置情况,自动在合适时机触发数据请求回调。

收起
自动换行
深色代码主题
复制
  1. static int32_t MyOnWriteData(
  2. OH_AudioRenderer *renderer,
  3. void *userData,
  4. void *buffer,
  5. int32_t bufferLen)
  6. {
  7. // 将待播放数据按照请求的bufferLen长度,填入buffer。
  8. // 函数返回后,系统会自动从buffer取出数据输出。
  9. }
  10. OH_AudioRenderer_Callbacks callbacks;
  11. callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
  12. // 设置输出音频流的回调,在生成音频播放对象时自动注册。
  13. void *userData = nullptr;
  14. OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, userData);

资源释放

OpenSL ES:

使用SLObjectItf接口实现对象资源释放。

收起
自动换行
深色代码主题
复制
  1. // 释放播放对象资源。
  2. (*playerObject)->Destroy(playerObject);

OHAudio:

使用对应模块的释放接口实现对象资源释放。

收起
自动换行
深色代码主题
复制
  1. // 释放建造器资源。
  2. OH_AudioStreamBuilder_Destroy(builder);
  3. // 释放播放对象资源。
  4. OH_AudioRenderer_Release(audioRenderer);