离线编辑(C/C++)
===========

从API version 22开始，[OHAudioSuite](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-ohaudiosuite)给开发者提供音频离线编辑能力，允许在非实时预览场景下对音频数据进行处理，开发者可以组合多个音频节点实现复杂的音频处理流程。

#### 开发基础配置

开发者使用[OHAudioSuite](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-ohaudiosuite)提供的离线编辑能力，添加对应的头文件。

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

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

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

开发者通过引入头文件<[native\_audio\_suite\_base.h](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-base-h)\>和<[native\_audio\_suite\_engine.h](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h)\>，使用音频编创相关API。

#include <ohaudiosuite/native\_audio\_suite\_base.h>
#include <ohaudiosuite/native\_audio\_suite\_engine.h>

#### 开发步骤

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

开发者参考本节内容实现音频离线编辑功能。

#### \[h2\]指定音频节点类型

开发者需要根据业务场景，调用[OH\_AudioSuiteNodeBuilder\_SetNodeType()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuitenodebuilder_setnodetype)接口，指定对应的[OH\_AudioNode\_Type](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-base-h#oh_audionode_type)。

#### \[h2\]指定音频节点格式

开发者需要根据业务场景，调用[OH\_AudioSuiteNodeBuilder\_SetFormat()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuitenodebuilder_setformat)或者[OH\_AudioSuiteEngine\_SetAudioFormat()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuiteengine_setaudioformat)接口，设置音频格式（位深（[OH\_Audio\_SampleFormat](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-base-h#oh_audio_sampleformat)）、采样率（[OH\_Audio\_SampleRate](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-base-h#oh_audio_samplerate)）、声道数（[OH\_AudioChannelLayout](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-channel-layout-h#oh_audiochannellayout)）等）。

#### \[h2\]基础离线编辑

使用效果节点（如均衡器效果节点）处理输入的PCM（Pulse Code Modulation）音频数据，输出带有该音效的PCM音频数据。

**图1**：基础离线编辑示意图

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ca/v3/9-MYcvLyQhOjocRExYp9pw/zh-cn_image_0000002625108305.png?HW-CC-KV=V1&HW-CC-Date=20260612T073506Z&HW-CC-Expire=86400&HW-CC-Sign=25861B00688A932C73520D0F1F44FA64A72D406766BFF73F792132C97DB9D60C)

1.  创建引擎和管线。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 创建引擎。
    OH\_AudioSuiteEngine \*audioSuiteEngine = nullptr;
    OH\_AudioSuiteEngine\_Create(&audioSuiteEngine);
    
    // 创建管线。
    OH\_AudioSuitePipeline \*audioSuitePipeline = nullptr;
    OH\_AudioSuiteEngine\_CreatePipeline(audioSuiteEngine, &audioSuitePipeline,
                                       OH\_AudioSuite\_PipelineWorkMode::AUDIOSUITE\_PIPELINE\_EDIT\_MODE);
    
2.  创建输入、输出、均衡器节点并连接组网。
    
    创建输入节点需要实现自定义回调函数InputNodeWriteDataCallBack，函数类型为[OH\_InputNode\_RequestDataCallback()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_inputnode_requestdatacallback)，调用[OH\_AudioSuiteNodeBuilder\_SetRequestDataCallback()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuitenodebuilder_setrequestdatacallback)接口设置回调函数。
    
    struct AudioDataInfo {
        uint8\_t \*buffer = nullptr;   // 音频数据。
        int32\_t bufferSize = 0;      // 音频数据总大小。
        int32\_t totalWriteSize = 0;  // 处理过的音频数据总大小。
        int32\_t totalReadSize = 0;  // 已读取的音频数据总大小。
    };
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 输入节点请求数据的回调函数。
    static int32\_t InputNodeWriteDataCallBack(OH\_AudioNode \*audioNode, void \*userData, void \*audioData,
                                              int32\_t audioDataSize, bool \*finished)
    {
        if ((audioNode == nullptr) || (userData == nullptr) || (audioData == nullptr) || (audioDataSize <= 0) ||
            (finished == nullptr)) {
            return -1;
        }
        struct AudioDataInfo \*info = static\_cast<struct AudioDataInfo \*>(userData);
        // 要处理的音频大小。
        int32\_t actualDataSize = std::min(audioDataSize, info->bufferSize - info->totalWriteSize);
        // 将PCM音频数据写入audioData。
        if (actualDataSize > 0) {
            std::copy(info->buffer + info->totalWriteSize, info->buffer + info->totalWriteSize + actualDataSize,
                      static\_cast<uint8\_t \*>(audioData));
        }
        info->totalWriteSize += actualDataSize;
        // 音频数据全部处理完。
        if (info->totalWriteSize >= info->bufferSize) {
            \*finished = true;
        }
        return actualDataSize;
    }
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 创建节点构造器。
    OH\_AudioNodeBuilder \*nodeBuilder = nullptr;
    OH\_AudioSuiteNodeBuilder\_Create(&nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::INPUT\_NODE\_TYPE\_DEFAULT);
    // 配置音频数据格式，开发者根据要处理的音频数据格式设置采样率、声道分布、声道数、位深、编码格式参数。
    OH\_AudioFormat audioFormatInput;
    audioFormatInput.samplingRate = OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000;
    audioFormatInput.channelLayout = OH\_AudioChannelLayout::CH\_LAYOUT\_STEREO;
    audioFormatInput.channelCount = CHANNEL\_COUNT;
    audioFormatInput.sampleFormat = OH\_Audio\_SampleFormat::AUDIO\_SAMPLE\_S16LE;
    audioFormatInput.encodingType = OH\_Audio\_EncodingType::AUDIO\_ENCODING\_TYPE\_RAW;
    OH\_AudioSuiteNodeBuilder\_SetFormat(nodeBuilder, audioFormatInput);
    // 设置音频流的回调。
    void \*userData = static\_cast<void \*>(audioInfo);
    OH\_AudioSuiteNodeBuilder\_SetRequestDataCallback(nodeBuilder, InputNodeWriteDataCallBack, userData);
    // 创建输入节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuiteEngine, nodeBuilder, &nodes.inputNode);
    
    // 重置构造器配置并设置为均衡器节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::EFFECT\_NODE\_TYPE\_EQUALIZER);
    // 创建均衡器节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuiteEngine, nodeBuilder, &nodes.eqNode);
    // 设置均衡器节点效果为默认。
    OH\_AudioSuiteEngine\_SetEqualizerFrequencyBandGains(nodes.eqNode, OH\_EQUALIZER\_PARAM\_DEFAULT);
    
    // 重置构造器配置并设置为输出节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::OUTPUT\_NODE\_TYPE\_DEFAULT);
    // 配置音频数据格式，开发者根据预期输出的音频格式设置采样率、声道分布、声道数、位深、编码格式参数。
    OH\_AudioFormat audioFormatOutput;
    audioFormatOutput.samplingRate = OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000;
    audioFormatOutput.channelLayout = OH\_AudioChannelLayout::CH\_LAYOUT\_STEREO;
    audioFormatOutput.channelCount = CHANNEL\_COUNT;
    audioFormatOutput.sampleFormat = OH\_Audio\_SampleFormat::AUDIO\_SAMPLE\_S16LE;
    audioFormatOutput.encodingType = OH\_Audio\_EncodingType::AUDIO\_ENCODING\_TYPE\_RAW;
    OH\_AudioSuiteNodeBuilder\_SetFormat(nodeBuilder, audioFormatOutput);
    // 创建输出节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuiteEngine, nodeBuilder, &nodes.outputNode);
    
    // 销毁节点构造器。
    OH\_AudioSuiteNodeBuilder\_Destroy(nodeBuilder);
    
    // 连接各个节点组成组网。
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.inputNode, nodes.eqNode);
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.eqNode, nodes.outputNode);
    
3.  渲染音频数据。
    
    开发者调用[OH\_AudioSuiteEngine\_RenderFrame()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuiteengine_renderframe)接口渲染并获取PCM音频数据。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 根据输出节点的格式计算单帧处理数据大小。如果samplingRate为11025请使用40ms来计算。
    int32\_t frameSize = RENDER\_FRAME\_DURATION\_MS \* OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000 \* CHANNEL\_COUNT \*
                        SAMPLE\_FORMAT\_S16LE\_BYTE\_SIZE / MS\_PER\_SECOND;
    // 用于接收渲染后的输出音频数据。
    uint8\_t \*audioData = (uint8\_t \*)malloc(frameSize);
    int32\_t responseSize = 0;
    bool finished = false;
    // 渲染。
    OH\_AudioSuiteEngine\_StartPipeline(audioSuitePipeline);
    // ...
    do {
        OH\_AudioSuite\_Result result = OH\_AudioSuiteEngine\_RenderFrame(
            audioSuitePipeline, static\_cast<void \*>(audioData), frameSize, &responseSize, &finished);
        if ((result != OH\_AudioSuite\_Result::AUDIOSUITE\_SUCCESS) || (responseSize <= 0)) {
            // 本次音频编创渲染失败。
            break;
        } else {
            // audioData是渲染过后的音频数据，音频数据长度为responseSize，开发者根据业务场景自行使用或者保存。
            // ...
        }
    } while (!finished);
    // ...
    OH\_AudioSuiteEngine\_StopPipeline(audioSuitePipeline);
    free(audioData);
    audioData = nullptr;
    
4.  资源销毁。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 销毁节点。
    OH\_AudioSuiteEngine\_DestroyNode(nodes.inputNode);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.eqNode);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.outputNode);
    
    // 销毁管线。
    OH\_AudioSuiteEngine\_DestroyPipeline(audioSuitePipeline);
    
    // 销毁引擎。
    OH\_AudioSuiteEngine\_Destroy(audioSuiteEngine);
    

#### \[h2\]音源分离场景

使用音源分离节点分离输入的PCM音频数据为人声和背景声，然后通过输出节点分别输出这两路数据。

**图2**：音源分离编辑示意图

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/7d/v3/NqDfBngwSS6kEz28gCfRSw/zh-cn_image_0000002594668788.png?HW-CC-KV=V1&HW-CC-Date=20260612T073506Z&HW-CC-Expire=86400&HW-CC-Sign=94532806D0109D428288AAE9D72DB6B8B18217536941E1C6D17551827D994139)

示例代码如下：

1.  创建引擎和管线。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 创建引擎。
    OH\_AudioSuiteEngine \*audioSuiteEngine = nullptr;
    OH\_AudioSuiteEngine\_Create(&audioSuiteEngine);
    
    // 创建管线。
    OH\_AudioSuitePipeline \*audioSuitePipeline = nullptr;
    OH\_AudioSuiteEngine\_CreatePipeline(audioSuiteEngine, &audioSuitePipeline,
                                       OH\_AudioSuite\_PipelineWorkMode::AUDIOSUITE\_PIPELINE\_EDIT\_MODE);
    
2.  创建输入、输出、音源分离节点并连接。
    
    创建输入节点需要实现自定义回调函数InputNodeWriteDataCallBack，函数类型为[OH\_InputNode\_RequestDataCallback()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_inputnode_requestdatacallback)，调用[OH\_AudioSuiteNodeBuilder\_SetRequestDataCallback()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuitenodebuilder_setrequestdatacallback)接口设置回调函数。
    
    struct AudioDataInfo {
        uint8\_t \*buffer = nullptr;   // 音频数据。
        int32\_t bufferSize = 0;      // 音频数据总大小。
        int32\_t totalWriteSize = 0;  // 处理过的音频数据总大小。
        int32\_t totalReadSize = 0;  // 已读取的音频数据总大小。
    };
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 输入节点请求数据的回调函数。
    static int32\_t InputNodeWriteDataCallBack(OH\_AudioNode \*audioNode, void \*userData, void \*audioData,
                                              int32\_t audioDataSize, bool \*finished)
    {
        if ((audioNode == nullptr) || (userData == nullptr) || (audioData == nullptr) || (audioDataSize <= 0) ||
            (finished == nullptr)) {
            return -1;
        }
        struct AudioDataInfo \*info = static\_cast<struct AudioDataInfo \*>(userData);
        // 要处理的音频大小。
        int32\_t actualDataSize = std::min(audioDataSize, info->bufferSize - info->totalWriteSize);
        // 将PCM音频数据写入audioData。
        if (actualDataSize > 0) {
            std::copy(info->buffer + info->totalWriteSize, info->buffer + info->totalWriteSize + actualDataSize,
                      static\_cast<uint8\_t \*>(audioData));
        }
        info->totalWriteSize += actualDataSize;
        // 音频数据全部处理完。
        if (info->totalWriteSize >= info->bufferSize) {
            \*finished = true;
        }
        return actualDataSize;
    }
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 创建节点构造器。
    OH\_AudioNodeBuilder \*nodeBuilder = nullptr;
    OH\_AudioSuiteNodeBuilder\_Create(&nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::INPUT\_NODE\_TYPE\_DEFAULT);
    
    // 配置音频数据格式，开发者根据要处理的音频数据格式设置采样率、声道分布、声道数、位深、编码格式参数。
    OH\_AudioFormat audioFormatInput;
    audioFormatInput.samplingRate = OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000;
    audioFormatInput.channelLayout = OH\_AudioChannelLayout::CH\_LAYOUT\_STEREO;
    audioFormatInput.channelCount = CHANNEL\_COUNT;
    audioFormatInput.sampleFormat = OH\_Audio\_SampleFormat::AUDIO\_SAMPLE\_S16LE;
    audioFormatInput.encodingType = OH\_Audio\_EncodingType::AUDIO\_ENCODING\_TYPE\_RAW;
    OH\_AudioSuiteNodeBuilder\_SetFormat(nodeBuilder, audioFormatInput);
    void \*userData = static\_cast<void \*>(audioInfo);
    // 设置音频流的回调。
    OH\_AudioSuiteNodeBuilder\_SetRequestDataCallback(nodeBuilder, InputNodeWriteDataCallBack, userData);
    
    // 创建输入节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.inputNode);
    
    // 重置构造器配置并设置为音源分离节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder,
                                         OH\_AudioNode\_Type::EFFECT\_MULTII\_OUTPUT\_NODE\_TYPE\_AUDIO\_SEPARATION);
    
    // 创建音源分离节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.aissNode);
    
    // 重置构造器配置并设置为输出节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::OUTPUT\_NODE\_TYPE\_DEFAULT);
    // 配置音频数据格式，开发者根据预期输出的音频格式设置采样率、声道分布、声道数、位深、编码格式参数。
    OH\_AudioFormat audioFormatOutput;
    audioFormatOutput.samplingRate = OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000;
    audioFormatOutput.channelLayout = OH\_AudioChannelLayout::CH\_LAYOUT\_STEREO;
    audioFormatOutput.channelCount = CHANNEL\_COUNT;
    audioFormatOutput.sampleFormat = OH\_Audio\_SampleFormat::AUDIO\_SAMPLE\_S16LE;
    audioFormatOutput.encodingType = OH\_Audio\_EncodingType::AUDIO\_ENCODING\_TYPE\_RAW;
    OH\_AudioSuiteNodeBuilder\_SetFormat(nodeBuilder, audioFormatOutput);
    
    // 创建输出节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.outputNode);
    
    // 销毁节点构造器。
    OH\_AudioSuiteNodeBuilder\_Destroy(nodeBuilder);
    
    // 连接各个节点组成组网。
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.inputNode, nodes.aissNode);
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.aissNode, nodes.outputNode);
    
3.  渲染音频数据。
    
    包含音源分离节点的管线使用[OH\_AudioSuiteEngine\_MultiRenderFrame()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuiteengine_multirenderframe)接口渲染并获取两路PCM音频数据。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 根据输出节点的格式计算单帧处理数据大小。如果samplingRate为11025请使用40ms来计算。
    int32\_t frameSize = RENDER\_FRAME\_DURATION\_MS \* OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000 \* CHANNEL\_COUNT \*
                        SAMPLE\_FORMAT\_S16LE\_BYTE\_SIZE / MS\_PER\_SECOND;
    // 用于接收渲染后的输出音频数据。
    OH\_AudioDataArray audioDataArray;
    int32\_t outputNum = 2;
    audioDataArray.audioDataArray = (void \*\*)malloc(outputNum \* sizeof(void \*));
    for (int32\_t i = 0; i < outputNum; i++) {
        audioDataArray.audioDataArray\[i\] = (void \*)malloc(frameSize);
    }
    audioDataArray.arraySize = outputNum;
    audioDataArray.requestFrameSize = frameSize;
    int32\_t responseSize = 0;
    bool finished = false;
    
    // 渲染。
    OH\_AudioSuiteEngine\_StartPipeline(audioSuitePipeline);
    // ...
    do {
        OH\_AudioSuite\_Result result =
            OH\_AudioSuiteEngine\_MultiRenderFrame(audioSuitePipeline, &audioDataArray, &responseSize, &finished);
        if ((result != OH\_AudioSuite\_Result::AUDIOSUITE\_SUCCESS) || (responseSize <= 0)) {
            // 本次音频编创渲染失败。
            break;
        } else {
            // audioDataArray.audioDataArray\[0\]是提取的人声。
            // audioDataArray.audioDataArray\[1\]是提取的背景声。
            // 音频数据长度为responseSize，开发者根据业务场景自行使用或者保存。
            // ...
        }
    } while (!finished);
    // ...
    OH\_AudioSuiteEngine\_StopPipeline(audioSuitePipeline);
    
    for (int32\_t i = 0; i < outputNum; i++) {
        free(audioDataArray.audioDataArray\[i\]);
        audioDataArray.audioDataArray\[i\] = nullptr;
    }
    free(audioDataArray.audioDataArray);
    audioDataArray.audioDataArray = nullptr;
    
4.  资源销毁。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 销毁节点。
    OH\_AudioSuiteEngine\_DestroyNode(nodes.inputNode);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.aissNode);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.outputNode);
    
    // 销毁管线。
    OH\_AudioSuiteEngine\_DestroyPipeline(audioSuitePipeline);
    
    // 销毁引擎。
    OH\_AudioSuiteEngine\_Destroy(audioSuiteEngine);
    

#### \[h2\]混音与级联

输入多路PCM音频数据，使用混音节点进行混音，输出混音后的PCM音频数据。

**图3**：级联编辑示意图

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/11/v3/3w4Ak2E-TU6XHIQA8QlWng/zh-cn_image_0000002594828716.png?HW-CC-KV=V1&HW-CC-Date=20260612T073506Z&HW-CC-Expire=86400&HW-CC-Sign=B40935328DF1DE46ADAD8F938B21ED07D8114875C9BA016091A2E1E596EB3FC6)

示例代码如下：

1.  创建引擎和管线。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 创建引擎。
    OH\_AudioSuiteEngine \*audioSuiteEngine = nullptr;
    OH\_AudioSuiteEngine\_Create(&audioSuiteEngine);
    
    // 创建管线。
    OH\_AudioSuitePipeline \*audioSuitePipeline = nullptr;
    OH\_AudioSuiteEngine\_CreatePipeline(audioSuiteEngine, &audioSuitePipeline,
                                       OH\_AudioSuite\_PipelineWorkMode::AUDIOSUITE\_PIPELINE\_EDIT\_MODE);
    
2.  创建输入、输出、效果类节点并连接。
    
    由于混音功能有多个输入节点，需单独设置回调函数InputNodeWriteDataCallBack中的userData参数来区分多个输入节点，从而实现多个PCM音频数据的输入。InputNodeWriteDataCallBack函数类型为[OH\_InputNode\_RequestDataCallback()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_inputnode_requestdatacallback)。
    
    struct AudioDataInfo {
        uint8\_t \*buffer = nullptr;   // 音频数据。
        int32\_t bufferSize = 0;      // 音频数据总大小。
        int32\_t totalWriteSize = 0;  // 处理过的音频数据总大小。
        int32\_t totalReadSize = 0;  // 已读取的音频数据总大小。
    };
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 输入节点请求数据的回调函数。
    static int32\_t InputNodeWriteDataCallBack(OH\_AudioNode \*audioNode, void \*userData, void \*audioData,
                                              int32\_t audioDataSize, bool \*finished)
    {
        if ((audioNode == nullptr) || (userData == nullptr) || (audioData == nullptr) || (audioDataSize <= 0) ||
            (finished == nullptr)) {
            return -1;
        }
        struct AudioDataInfo \*info = static\_cast<struct AudioDataInfo \*>(userData);
        // 要处理的音频大小。
        int32\_t actualDataSize = std::min(audioDataSize, info->bufferSize - info->totalWriteSize);
        // 将PCM音频数据写入audioData。
        if (actualDataSize > 0) {
            std::copy(info->buffer + info->totalWriteSize, info->buffer + info->totalWriteSize + actualDataSize,
                      static\_cast<uint8\_t \*>(audioData));
        }
        info->totalWriteSize += actualDataSize;
        // 音频数据全部处理完。
        if (info->totalWriteSize >= info->bufferSize) {
            \*finished = true;
        }
        return actualDataSize;
    }
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 创建节点构造器。
    OH\_AudioNodeBuilder \*nodeBuilder = nullptr;
    OH\_AudioSuiteNodeBuilder\_Create(&nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::INPUT\_NODE\_TYPE\_DEFAULT);
    // 配置音频数据格式，开发者根据要处理的音频数据格式设置采样率、声道分布、声道数、位深、编码格式参数。
    OH\_AudioFormat audioFormatInput;
    audioFormatInput.samplingRate = OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000;
    audioFormatInput.channelLayout = OH\_AudioChannelLayout::CH\_LAYOUT\_STEREO;
    audioFormatInput.channelCount = CHANNEL\_COUNT;
    audioFormatInput.sampleFormat = OH\_Audio\_SampleFormat::AUDIO\_SAMPLE\_S16LE;
    audioFormatInput.encodingType = OH\_Audio\_EncodingType::AUDIO\_ENCODING\_TYPE\_RAW;
    OH\_AudioSuiteNodeBuilder\_SetFormat(nodeBuilder, audioFormatInput);
    // 设置第一个音频流的回调。
    void \*userData = static\_cast<void \*>(audioInfoForField);
    OH\_AudioSuiteNodeBuilder\_SetRequestDataCallback(nodeBuilder, InputNodeWriteDataCallBack, userData);
    // 创建第一个输入节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.inputNodeForField);
    
    // 重置构造器配置并设置为输入节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::INPUT\_NODE\_TYPE\_DEFAULT);
    OH\_AudioSuiteNodeBuilder\_SetFormat(nodeBuilder, audioFormatInput);
    // 设置第二个音频流的回调。
    userData = static\_cast<void \*>(audioInfoForMix);
    OH\_AudioSuiteNodeBuilder\_SetRequestDataCallback(nodeBuilder, InputNodeWriteDataCallBack, userData);
    // 创建第二个输入节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.inputNodeForMix);
    
    // 重置构造器配置并设置为声场节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::EFFECT\_NODE\_TYPE\_SOUND\_FIELD);
    // 创建声场节点并设置声场模式为聆听。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.fieldNode);
    OH\_AudioSuiteEngine\_SetSoundFieldType(nodes.fieldNode, SOUND\_FIELD\_FRONT\_FACING);
    
    // 重置构造器配置并设置为混音节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::EFFECT\_NODE\_TYPE\_AUDIO\_MIXER);
    // 创建混音节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.mixerNode);
    
    // 重置构造器配置并设置为输出节点类型。
    OH\_AudioSuiteNodeBuilder\_Reset(nodeBuilder);
    OH\_AudioSuiteNodeBuilder\_SetNodeType(nodeBuilder, OH\_AudioNode\_Type::OUTPUT\_NODE\_TYPE\_DEFAULT);
    // 配置音频数据格式，开发者根据预期输出的音频格式设置采样率、声道分布、声道数、位深、编码格式参数。
    OH\_AudioFormat audioFormatOutput;
    audioFormatOutput.samplingRate = OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000;
    audioFormatOutput.channelLayout = OH\_AudioChannelLayout::CH\_LAYOUT\_STEREO;
    audioFormatOutput.channelCount = CHANNEL\_COUNT;
    audioFormatOutput.sampleFormat = OH\_Audio\_SampleFormat::AUDIO\_SAMPLE\_S16LE;
    audioFormatOutput.encodingType = OH\_Audio\_EncodingType::AUDIO\_ENCODING\_TYPE\_RAW;
    OH\_AudioSuiteNodeBuilder\_SetFormat(nodeBuilder, audioFormatOutput);
    // 创建输出节点。
    OH\_AudioSuiteEngine\_CreateNode(audioSuitePipeline, nodeBuilder, &nodes.outputNode);
    
    // 销毁输出节点构造器。
    OH\_AudioSuiteNodeBuilder\_Destroy(nodeBuilder);
    
    // 连接各个节点组成组网。
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.inputNodeForField, nodes.fieldNode);
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.fieldNode, nodes.mixerNode);
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.inputNodeForMix, nodes.mixerNode);
    OH\_AudioSuiteEngine\_ConnectNodes(nodes.mixerNode, nodes.outputNode);
    
3.  渲染音频数据。
    
    开发者调用[OH\_AudioSuiteEngine\_RenderFrame()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-native-audio-suite-engine-h#oh_audiosuiteengine_renderframe)接口渲染并获取PCM音频数据。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 根据输出节点的格式计算单帧处理数据大小。如果samplingRate为11025请使用40ms来计算。
    int32\_t frameSize = RENDER\_FRAME\_DURATION\_MS \* OH\_Audio\_SampleRate::SAMPLE\_RATE\_48000 \* CHANNEL\_COUNT \*
                        SAMPLE\_FORMAT\_S16LE\_BYTE\_SIZE / MS\_PER\_SECOND;
    // 用于接收渲染后的输出音频数据。
    uint8\_t \*audioData = (uint8\_t \*)malloc(frameSize);
    int32\_t responseSize = 0;
    bool finished = false;
    
    // 渲染。
    OH\_AudioSuiteEngine\_StartPipeline(audioSuitePipeline);
    // ...
    do {
        OH\_AudioSuite\_Result result = OH\_AudioSuiteEngine\_RenderFrame(
            audioSuitePipeline, static\_cast<void \*>(audioData), frameSize, &responseSize, &finished);
        if ((result != OH\_AudioSuite\_Result::AUDIOSUITE\_SUCCESS) || (responseSize <= 0)) {
            // 本次音频编创渲染失败。
            break;
        } else {
            // audioData是渲染过后的音频数据，音频数据长度为responseSize，开发者根据业务场景自行使用或者保存。
            // ...
        }
    } while (!finished);
    // ...
    OH\_AudioSuiteEngine\_StopPipeline(audioSuitePipeline);
    free(audioData);
    audioData = nullptr;
    
4.  资源销毁。
    
    // 示例接口未包含返回值校验，实际使用时请务必添加校验逻辑。
    // 销毁节点。
    OH\_AudioSuiteEngine\_DestroyNode(nodes.inputNodeForMix);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.inputNodeForField);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.fieldNode);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.mixerNode);
    OH\_AudioSuiteEngine\_DestroyNode(nodes.outputNode);
    
    // 销毁管线。
    OH\_AudioSuiteEngine\_DestroyPipeline(audioSuitePipeline);
    
    // 销毁引擎。
    OH\_AudioSuiteEngine\_Destroy(audioSuiteEngine);
    

#### 完整示例代码

*   [音频编创示例代码](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/DocsSample/Media/Audio/AudioSuiteSample)