推荐使用OHAudio开发音频播放功能(C/C++)
==========================

OHAudio是系统在API version 10中引入的一套C API，此API在设计上实现归一，同时支持普通音频通路和低时延通路。仅支持PCM格式，适用于依赖Native层实现音频输出功能的场景。

OHAudio音频播放状态变化示意图：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/3f/v3/fknhRkwLQYyWw7WkKit_rA/zh-cn_image_0000002594668778.png?HW-CC-KV=V1&HW-CC-Date=20260612T073504Z&HW-CC-Expire=86400&HW-CC-Sign=ED57395AD0281CFCD737273DF39F745F16035FA216644B73D61CABAA9004F536)

当音频流处于工作状态（非released状态）时，需要占用系统的音频流资源。由于系统对音频流数量有限制，所以当客户端暂时不使用音频流时，调用OH\_AudioRenderer\_Release()回收音频资源，做好资源利用，避免后续创建音频流失败。

#### 使用入门

开发者要使用OHAudio提供的播放能力，需要添加对应的头文件。

以下各步骤示例为片段代码，可通过示例代码右下方链接获取[完整示例](https://gitcode.com/openharmony/applications_app_samples/blob/master/code/DocsSample/Media/Audio/AudioRendererSampleC)。

#### \[h2\]在 CMake 脚本中链接动态库

target\_link\_libraries(sample PUBLIC libohaudio.so)

#### \[h2\]添加头文件

开发者通过引入<[native\_audiostreambuilder.h](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h)\>和<[native\_audiorenderer.h](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiorenderer-h)\>头文件，使用音频播放相关API。

#include <ohaudio/native\_audiorenderer.h>
#include <ohaudio/native\_audiostreambuilder.h>

#### 开发步骤

详细的API说明请参考[OHAudio](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-ohaudio)。

#### \[h2\]音频流构造器

OHAudio提供OH\_AudioStreamBuilder接口，遵循构造器设计模式，用于构建音频流。开发者需要根据业务场景，指定对应的[OH\_AudioStream\_Type](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostream-base-h#oh_audiostream_type)。

OH\_AudioStream\_Type包含两种类型：

*   AUDIOSTREAM\_TYPE\_RENDERER
*   AUDIOSTREAM\_TYPE\_CAPTURER

使用[OH\_AudioStreamBuilder\_Create](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_create)创建构造器示例：

OH\_AudioStreamBuilder\* builder;
// ...
    OH\_AudioStreamBuilder\_Create(&builder, AUDIOSTREAM\_TYPE\_RENDERER);

在音频业务结束之后，开发者应该执行[OH\_AudioStreamBuilder\_Destroy](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_destroy)接口来销毁构造器。

OH\_AudioStreamBuilder\_Destroy(builder);

开发者可以通过以下几个步骤来实现一个简单的播放功能。

#### \[h2\]实现音频播放

1.  创建构造器。
    
    OH\_AudioStreamBuilder\* builder;
    // ...
        OH\_AudioStreamBuilder\_Create(&builder, AUDIOSTREAM\_TYPE\_RENDERER);
    
2.  配置音频流参数。
    
    关于音频采样率可参考[配置合适的音频采样率](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/using-audiorenderer-for-playback#配置合适的音频采样率)。
    
    创建音频播放构造器后，可以设置音频流所需要的参数，可以参考下面的案例。
    
    // 设置音频采样率。
    // 从API版本26.0.0开始：音频渲染扩展支持8000Hz到384000Hz范围内以10Hz为步长的采样率值。具体设备支持的采样率规格会存在差异。
    const int SAMPLING\_RATE\_48K = 48000;
    OH\_AudioStreamBuilder\_SetSamplingRate(builder, SAMPLING\_RATE\_48K);
    // 设置音频声道。
    const int channelCount = 2;
    OH\_AudioStreamBuilder\_SetChannelCount(builder, channelCount);
    // 设置音频采样格式。
    OH\_AudioStreamBuilder\_SetSampleFormat(builder, AUDIOSTREAM\_SAMPLE\_S16LE);
    // 设置音频流的编码类型。
    OH\_AudioStreamBuilder\_SetEncodingType(builder, AUDIOSTREAM\_ENCODING\_TYPE\_RAW);
    // 设置输出音频流的工作场景。
    OH\_AudioStreamBuilder\_SetRendererInfo(builder, AUDIOSTREAM\_USAGE\_MUSIC);
    
    注意，播放的音频数据要通过回调接口写入，开发者要实现回调接口，从API version 12开始支持使用[OH\_AudioStreamBuilder\_SetRendererWriteDataCallback](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_setrendererwritedatacallback)设置数据回调函数。数据回调函数的声明请查看[OH\_AudioRenderer\_OnWriteDataCallback](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostream-base-h#oh_audiorenderer_onwritedatacallback)。
    
3.  设置音频回调函数。
    
    多音频并发处理可参考文档[处理音频焦点事件](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/audio-playback-concurrency)，仅接口语言差异。
    
    *   从API version 12开始**推荐**使用[OH\_AudioRenderer\_OnWriteDataCallback](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostream-base-h#oh_audiorenderer_onwritedatacallback)用于写入音频数据。
        
        ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/b3/v3/b13hP7SHQUqYKEUC6R2eAQ/caution_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073504Z&HW-CC-Expire=86400&HW-CC-Sign=7EADCBFD651A8EDB84F637E72F0B3D18E8CFD2E535835313984121A95FCB76B1)
        
        *   能填满回调所需长度数据的情况下，返回AUDIO\_DATA\_CALLBACK\_RESULT\_VALID，系统会取用完整长度的数据缓冲进行播放。请不要在未填满数据的情况下返回AUDIO\_DATA\_CALLBACK\_RESULT\_VALID，否则会导致杂音、卡顿等现象。
            
        *   在无法填满回调所需长度数据的情况下，建议开发者返回AUDIO\_DATA\_CALLBACK\_RESULT\_INVALID，系统不会处理该段音频数据，然后会再次向应用请求数据，确认数据填满后返回AUDIO\_DATA\_CALLBACK\_RESULT\_VALID。
            
        *   回调函数结束后，音频服务会把缓冲中数据放入队列里等待播放，因此请勿在回调外再次更改缓冲中的数据。对于最后一帧，如果数据不够填满缓冲长度，开发者需要使用剩余数据拼接空数据的方式，将缓冲填满，避免缓冲内的历史脏数据对播放效果产生不良的影响。
            
        
    *   从API version 12开始可通过[OH\_AudioStreamBuilder\_SetFrameSizeInCallback](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_setframesizeincallback)设置audioDataSize的大小。
        
    
    // 自定义写入数据函数。
    static OH\_AudioData\_Callback\_Result MyOnWriteData\_New(
        OH\_AudioRenderer\* renderer,
        void\* userData,
        void\* audioData,
        int32\_t audioDataSize)
    {
        // 将待播放的数据，按audioDataSize长度写入audioData。
        // 如果开发者不希望播放某段audioData，返回AUDIO\_DATA\_CALLBACK\_RESULT\_INVALID即可。
        int32\_t readCount = fread(audioData, audioDataSize, 1, g\_fp);
        if (readCount < 0) {
            return AUDIO\_DATA\_CALLBACK\_RESULT\_INVALID;
        }
        if (feof(g\_fp)) {
            fseek(g\_fp, 0, SEEK\_SET);
        }
        return AUDIO\_DATA\_CALLBACK\_RESULT\_VALID;
    }
    
    // 自定义音频中断事件函数。
    void MyOnInterruptEvent\_New(
        OH\_AudioRenderer\* renderer,
        void\* userData,
        OH\_AudioInterrupt\_ForceType type,
        OH\_AudioInterrupt\_Hint hint)
    {
        // 根据type和hint表示的音频中断信息，更新播放器状态和界面。
    }
    
    // 自定义异常回调函数。
    void MyOnError\_New(
        OH\_AudioRenderer\* renderer,
        void\* userData,
        OH\_AudioStream\_Result error)
    {
        // 根据error表示的音频异常信息，做出相应的处理。
    }
    // ...
        // 配置音频中断事件回调函数。
        OH\_AudioRenderer\_OnInterruptCallback OnInterruptCb = MyOnInterruptEvent\_New;
        OH\_AudioStreamBuilder\_SetRendererInterruptCallback(builder, OnInterruptCb, nullptr);
        
        // 配置音频异常回调函数。
        OH\_AudioRenderer\_OnErrorCallback OnErrorCb = MyOnError\_New;
        OH\_AudioStreamBuilder\_SetRendererErrorCallback(builder, OnErrorCb, nullptr);
        
        // 配置写入音频数据回调函数。
        OH\_AudioRenderer\_OnWriteDataCallback writeDataCb = MyOnWriteData\_New;
        OH\_AudioStreamBuilder\_SetRendererWriteDataCallback(builder, writeDataCb, nullptr);
    
4.  构造播放音频流。
    
    OH\_AudioRenderer\* audioRenderer;
    // ...
        OH\_AudioStreamBuilder\_GenerateRenderer(builder, &audioRenderer);
    
5.  使用音频流。
    
    音频流中包含以下接口，用来实现对音频流的控制。
    
    | 接口 | 说明 |
    | :-- | :-- |
    | OH\_AudioStream\_Result OH\_AudioRenderer\_Start(OH\_AudioRenderer\* renderer) | 开始播放。 |
    | OH\_AudioStream\_Result OH\_AudioRenderer\_Pause(OH\_AudioRenderer\* renderer) | 暂停播放。 |
    | OH\_AudioStream\_Result OH\_AudioRenderer\_Stop(OH\_AudioRenderer\* renderer) | 停止播放。 |
    | OH\_AudioStream\_Result OH\_AudioRenderer\_Flush(OH\_AudioRenderer\* renderer) | 释放缓存数据。 |
    | OH\_AudioStream\_Result OH\_AudioRenderer\_Release(OH\_AudioRenderer\* renderer) | 释放播放实例。 |
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ae/v3/R9FXQRhxThSMC48roF73iA/caution_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073504Z&HW-CC-Expire=86400&HW-CC-Sign=0E43938DE579C70805339ADB8D5C448FA931EA0894D8259B192280AFE71DF58A)
    
    音频流控制接口执行会有耗时（例如OH\_AudioRenderer\_Stop接口需要播完缓存，单次执行普遍超过50ms），应避免在主线程中直接调用，以免造成界面显示卡顿。
    
6.  释放构造器。
    
    构造器不再使用时，需要释放相关资源。
    
    应用需根据实际业务需求合理使用构造器，按需创建并及时释放，避免占用过多音频资源导致异常。
    
    OH\_AudioStreamBuilder\_Destroy(builder);
    

#### \[h2\]设置音频流音量

开发者可使用[OH\_AudioRenderer\_SetVolume](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiorenderer-h#oh_audiorenderer_setvolume)接口设置当前音频流音量值。

float volume = 0.5f;

// 设置当前音频流音量值。
OH\_AudioRenderer\_SetVolume(audioRenderer, volume);

#### \[h2\]设置低时延模式

当设备支持低时延通路且采样率设置为48000Hz时，开发者可以使用低时延模式创建播放器，获得更高质量的音频体验。

开发流程与普通播放（[实现音频播放](#实现音频播放)）场景一致，仅需要在步骤1创建音频流构造器时，调用[OH\_AudioStreamBuilder\_SetLatencyMode()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_setlatencymode)设置低时延模式。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e8/v3/ERms701WT_Su3OLk7Nj00A/caution_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073504Z&HW-CC-Expire=86400&HW-CC-Sign=56B65F00BD75C56E2F7D6B51C0F9635A5517B6611BD272329816F67C8BD2ED74)

*   当音频播放场景[OH\_AudioStream\_Usage](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostream-base-h#oh_audiostream_usage)为AUDIOSTREAM\_USAGE\_VOICE\_COMMUNICATION和AUDIOSTREAM\_USAGE\_VIDEO\_COMMUNICATION时，不支持主动设置低时延模式，系统会根据设备的能力，决策输出的音频通路。
*   低时延通路对于数据处理性能要求较高，应用数据生成缓慢时容易导致卡顿。普通音乐、视频播放场景下不建议设置该模式，仅推荐游戏、K歌等对时延敏感的应用设置低时延模式。

OH\_AudioStreamBuilder\_SetLatencyMode(builder, AUDIOSTREAM\_LATENCY\_MODE\_FAST);

#### \[h2\]设置音频声道布局

播放音频文件时，可以通过设置音频的声道布局信息，指定渲染或播放时的扬声器摆位，使得渲染和播放效果更佳，获得更高质量的音频体验。

开发流程与普通播放（[实现音频播放](#实现音频播放)）场景一致，仅需要在步骤1创建音频流构造器时，调用[OH\_AudioStreamBuilder\_SetChannelLayout()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_setchannellayout)设置声道布局信息。

当声道布局与声道数不匹配时，创建音频流会失败。建议在设置声道布局时，确认下发的声道布局信息是否正确。

如果不知道准确的声道布局信息，或者开发者需要使用默认声道布局，可以不调用设置声道布局接口，或者下发CH\_LAYOUT\_UNKNOWN，以使用基于声道数的默认声道布局。

对于HOA（高阶立体环绕声）格式的音频，想要获得正确的渲染和播放效果，必须指定声道布局信息。

OH\_AudioStreamBuilder\_SetChannelLayout(builder, CH\_LAYOUT\_STEREO);

#### \[h2\]播放Audio Vivid格式音源

播放Audio Vivid（菁彩三维声）格式音频文件时，需要使用与普通播放不同的数据写入回调函数，该回调可以同时写入PCM（脉冲编码调制）数据与元数据。

开发流程与普通播放（[实现音频播放](#实现音频播放)）场景一致，仅需要在步骤1创建音频流构造器时，调用[OH\_AudioStreamBuilder\_SetWriteDataWithMetadataCallback()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_setwritedatawithmetadatacallback)设置PCM数据与元数据同时写入的回调函数，同时调用[OH\_AudioStreamBuilder\_SetEncodingType()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_setencodingtype)设置编码类型为AUDIOSTREAM\_ENCODING\_TYPE\_AUDIOVIVID。

在播放Audio Vivid时，帧长是固定的，不可通过[OH\_AudioStreamBuilder\_SetFrameSizeInCallback()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audiostreambuilder-h#oh_audiostreambuilder_setframesizeincallback)设置回调帧长。同时，在设置播放声道数和声道布局时，需要将写入音源的声床数和对象数相加后进行设置。

// 自定义同时写入PCM数据和元数据函数。
int32\_t MyOnWriteDataWithMetadata\_New(
    OH\_AudioRenderer\* renderer,
    void\* userData,
    void\* audioData,
    int32\_t audioDataSize,
    void\* metadata,
    int32\_t metadataSize)
{
    // 将待播放的PCM数据和元数据，分别按audioDataSize和metadataSize写入buffer。
    return 0;
}
// ...
    // 设置编码类型。
    OH\_AudioStreamBuilder\_SetEncodingType(builder, AUDIOSTREAM\_ENCODING\_TYPE\_AUDIOVIVID);
    // 配置回调函数。
    OH\_AudioRenderer\_WriteDataWithMetadataCallback metadataCallback = MyOnWriteDataWithMetadata\_New;
    // 设置同时写入PCM数据和元数据的回调。
    OH\_AudioStreamBuilder\_SetWriteDataWithMetadataCallback(builder, metadataCallback, nullptr);

#### 注意事项

从API version 12开始**不再推荐**使用[OH\_AudioRenderer\_Callbacks](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-ohaudio-oh-audiorenderer-callbacks-struct)的方式设置音频回调函数。若必须使用，需要注意在设置音频回调函数时，通过下面两种方式中的任意一种来设置音频回调函数，避免不可预期的行为。

*   方式1：请确保[OH\_AudioRenderer\_Callbacks](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-ohaudio-oh-audiorenderer-callbacks-struct)的每一个回调都被**自定义的回调方法**或**空指针**初始化。
    
    OH\_AudioRenderer\_Callbacks callbacks;
    // ...
    // 自定义写入数据函数。
    int32\_t MyOnWriteData\_Legacy(
        OH\_AudioRenderer\* renderer,
        void\* userData,
        void\* buffer,
        int32\_t length)
    {
        // 将待播放的数据，按length长度写入buffer。
        return 0;
    }
    
    // 自定义音频中断事件函数。
    int32\_t MyOnInterruptEvent\_Legacy(
        OH\_AudioRenderer\* renderer,
        void\* userData,
        OH\_AudioInterrupt\_ForceType type,
        OH\_AudioInterrupt\_Hint hint)
    {
        // 根据type和hint表示的音频中断信息，更新播放器状态和界面。
        return 0;
    }
    // ...
        // 配置回调函数，如果需要监听，则赋值。
        callbacks.OH\_AudioRenderer\_OnWriteData = MyOnWriteData\_Legacy;
        callbacks.OH\_AudioRenderer\_OnInterruptEvent = MyOnInterruptEvent\_Legacy;
    
        // （必选）无触发回调场景，使用空指针初始化。从API version 11开始，开发者如果需要监听设备变化，
        // 可直接使用OH\_AudioRenderer\_OutputDeviceChangeCallback替代。
        callbacks.OH\_AudioRenderer\_OnStreamEvent = nullptr;
        // （必选）如果不需要监听，使用空指针初始化。
        callbacks.OH\_AudioRenderer\_OnError = nullptr;
    
*   方式2：使用前，初始化并清零结构体。
    
    OH\_AudioRenderer\_Callbacks callbacks;
    // ...
    // 自定义写入数据函数。
    int32\_t MyOnWriteData\_Legacy(
        OH\_AudioRenderer\* renderer,
        void\* userData,
        void\* buffer,
        int32\_t length)
    {
        // 将待播放的数据，按length长度写入buffer。
        return 0;
    }
    
    // 自定义音频中断事件函数。
    int32\_t MyOnInterruptEvent\_Legacy(
        OH\_AudioRenderer\* renderer,
        void\* userData,
        OH\_AudioInterrupt\_ForceType type,
        OH\_AudioInterrupt\_Hint hint)
    {
        // 根据type和hint表示的音频中断信息，更新播放器状态和界面。
        return 0;
    }
    // ...
        // 使用前，初始化并清零结构体。
        OH\_AudioRenderer\_Callbacks callbacks = {0};
    
        // 配置需要的回调函数。
        callbacks.OH\_AudioRenderer\_OnWriteData = MyOnWriteData\_Legacy;
        callbacks.OH\_AudioRenderer\_OnInterruptEvent = MyOnInterruptEvent\_Legacy;
    

#### 示例代码

*   [音频低时延录制与播放](https://gitcode.com/HarmonyOS_Samples/audio-native)