1# Using OHAudio for Audio Playback (C/C++)
2
3**OHAudio** is a set of C APIs introduced in API version 10. These APIs are normalized in design and support both common and low-latency audio channels. They support the PCM format only. They are suitable for playback applications that implement audio output at the native layer.
4
5## Prerequisites
6
7To use the playback or recording capability of **OHAudio**, you must first import the corresponding header files.
8
9### Linking the Dynamic Library in the CMake Script
10
11``` cmake
12target_link_libraries(sample PUBLIC libohaudio.so)
13```
14
15### Adding Header Files
16
17To use APIs for audio playback, import <[native_audiostreambuilder.h](../../reference/apis-audio-kit/native__audiostreambuilder_8h.md)> and <[native_audiorenderer.h](../../reference/apis-audio-kit/native__audiorenderer_8h.md)>.
18
19```cpp
20#include <ohaudio/native_audiorenderer.h>
21#include <ohaudio/native_audiostreambuilder.h>
22```
23
24## Building Audio Streams
25
26**OHAudio** provides the **OH_AudioStreamBuilder** class, which complies with the builder design pattern and is used to build audio streams. You need to specify [OH_AudioStream_Type](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostream_type) based on your service scenarios.
27
28**OH_AudioStream_Type** can be set to either of the following:
29
30- AUDIOSTREAM_TYPE_RENDERER
31- AUDIOSTREAM_TYPE_CAPTURER
32
33The following code snippet shows how to use [OH_AudioStreamBuilder_Create](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_create) to create a builder:
34
35```
36OH_AudioStreamBuilder* builder;
37OH_AudioStreamBuilder_Create(&builder, streamType);
38```
39
40After the audio service is complete, call [OH_AudioStreamBuilder_Destroy](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_destroy) to destroy the builder.
41
42```
43OH_AudioStreamBuilder_Destroy(builder);
44```
45
46## How to Develop
47
48Read [OHAudio](../../reference/apis-audio-kit/_o_h_audio.md) for the API reference.
49
50The following walks you through how to implement simple playback:
51
521. Create an audio stream builder.
53
54    ```c++
55    OH_AudioStreamBuilder* builder;
56    OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
57    ```
58
592. Set audio stream parameters.
60
61    After creating the builder for audio playback, set the parameters required.
62
63    ```c++
64    // Set the audio sampling rate.
65    OH_AudioStreamBuilder_SetSamplingRate(builder, 48000);
66    // Set the number of audio channels.
67    OH_AudioStreamBuilder_SetChannelCount(builder, 2);
68    // Set the audio sampling format.
69    OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
70    // Set the encoding type of the audio stream.
71    OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
72    // Set the usage scenario of the audio renderer.
73    OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
74    ```
75
76    Note that the audio data to play is written through callbacks. You must call **OH_AudioStreamBuilder_SetRendererCallback** to implement the callbacks. For details about the declaration of the callback functions, see [OH_AudioRenderer_Callbacks](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiorenderer_callbacks).
77
78
793. Set the callback functions.
80
81    For details about concurrent processing of multiple audio streams, see [Processing Audio Interruption Events](audio-playback-concurrency.md). The procedure is similar, and the only difference is the API programming language in use.
82
83    ```c++
84    // Customize a data writing function.
85    int32_t MyOnWriteData(
86        OH_AudioRenderer* renderer,
87        void* userData,
88        void* buffer,
89        int32_t length)
90    {
91        // Write the data to be played to the buffer by length.
92        return 0;
93    }
94    // Customize an audio stream event function.
95    int32_t MyOnStreamEvent(
96        OH_AudioRenderer* renderer,
97        void* userData,
98        OH_AudioStream_Event event)
99    {
100        // Update the player status and UI based on the audio stream event information indicated by the event.
101        return 0;
102    }
103    // Customize an audio interruption event function.
104    int32_t MyOnInterruptEvent(
105        OH_AudioRenderer* renderer,
106        void* userData,
107        OH_AudioInterrupt_ForceType type,
108        OH_AudioInterrupt_Hint hint)
109    {
110        // Update the player status and UI based on the audio interruption information indicated by type and hint.
111        return 0;
112    }
113    // Customize an exception callback function.
114    int32_t MyOnError(
115        OH_AudioRenderer* renderer,
116        void* userData,
117        OH_AudioStream_Result error)
118    {
119        // Perform operations based on the audio exception information indicated by error.
120        return 0;
121    }
122
123    OH_AudioRenderer_Callbacks callbacks;
124    // Set the callbacks.
125    callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
126    callbacks.OH_AudioRenderer_OnStreamEvent = MyOnStreamEvent;
127    callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
128    callbacks.OH_AudioRenderer_OnError = MyOnError;
129
130    // Set callbacks for the audio renderer.
131    OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);
132    ```
133
134    To avoid unexpected behavior, ensure that each callback of [OH_AudioRenderer_Callbacks](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiorenderer_callbacks) is initialized by a custom callback method or null pointer when being set.
135
136    ```c++
137    // Customize a data writing function.
138    int32_t MyOnWriteData(
139        OH_AudioRenderer* renderer,
140        void* userData,
141        void* buffer,
142        int32_t length)
143    {
144        // Write the data to be played to the buffer by length.
145        return 0;
146    }
147    // Customize an audio interruption event function.
148    int32_t MyOnInterruptEvent(
149        OH_AudioRenderer* renderer,
150        void* userData,
151        OH_AudioInterrupt_ForceType type,
152        OH_AudioInterrupt_Hint hint)
153    {
154        // Update the player status and UI based on the audio interruption information indicated by type and hint.
155        return 0;
156    }
157    OH_AudioRenderer_Callbacks callbacks;
158
159    // Configure a callback function. If listening is required, assign a value.
160    callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
161    callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
162
163    // (Mandatory) If listening is not required, use a null pointer for initialization.
164    callbacks.OH_AudioRenderer_OnStreamEvent = nullptr;
165    callbacks.OH_AudioRenderer_OnError = nullptr;
166    ```
167
1684. Create an audio renderer instance.
169
170    ```c++
171    OH_AudioRenderer* audioRenderer;
172    OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
173    ```
174
1755. Use the audio renderer.
176
177    You can use the APIs listed below to control the audio streams.
178    
179    | API                                                        | Description        |
180    | ------------------------------------------------------------ | ------------ |
181    | OH_AudioStream_Result OH_AudioRenderer_Start(OH_AudioRenderer* renderer) | Starts the audio renderer.    |
182    | OH_AudioStream_Result OH_AudioRenderer_Pause(OH_AudioRenderer* renderer) | Pauses the audio renderer.    |
183    | OH_AudioStream_Result OH_AudioRenderer_Stop(OH_AudioRenderer* renderer) | Stops the audio renderer.    |
184    | OH_AudioStream_Result OH_AudioRenderer_Flush(OH_AudioRenderer* renderer) | Flushes written audio data.|
185    | OH_AudioStream_Result OH_AudioRenderer_Release(OH_AudioRenderer* renderer) | Releases the audio renderer instance.|
186
1876. Destroy the audio stream builder.
188
189    When the builder is no longer used, release related resources.
190
191    ```c++
192    OH_AudioStreamBuilder_Destroy(builder);
193    ```
194
195## Setting the Low Latency Mode
196
197If the device supports the low-latency channel, you can use the low-latency mode to create a player for a higher-quality audio experience.
198
199The development process is similar to that in the common playback scenario. The only difference is that you need to set the low delay mode by calling [OH_AudioStreamBuilder_SetLatencyMode()](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_setlatencymode) when creating an audio stream builder.
200
201The code snippet is as follows:
202
203```C
204OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST);
205```
206
207## Setting the Audio Channel Layout
208
209In the case of audio file playback, you can set the audio channel layout to specify the speaker position during rendering or playing for a better audio experience.
210
211The development process is similar to that in the common playback scenario. The only difference is that you need to set the audio channel layout by calling [OH_AudioStreamBuilder_SetChannelLayout()](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_setchannellayout) when creating an audio stream builder.
212
213If the audio channel layout does not match the number of audio channels, audio streams fail to be created. Therefore, you must ensure that the audio channel layout setting is correct.
214
215If you do not know the accurate audio channel layout or you want to use the default audio channel layout, do not call the API to set the audio channel layout. Alternatively, deliver **CH_LAYOUT_UNKNOWN** to use the default audio channel layout, which is specific to the number of audio channels.
216
217For audio in HOA format, to obtain the correct rendering and playback effect, you must specify the audio channel layout.
218
219The code snippet is as follows:
220
221```C
222OH_AudioStreamBuilder_SetChannelLayout(builder, CH_LAYOUT_STEREO);
223```
224
225## Playing Audio Files in AudioVivid Format
226
227In the case of audio file playback in AudioVivid format, the callback function used for writing data is different from that in the common playback scenario. This callback function can write PCM data and metadata at the same time.
228
229The development process is similar to that in the common playback scenario. The only difference is that you need to call [OH_AudioStreamBuilder_SetWriteDataWithMetadataCallback()](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_setwritedatawithmetadatacallback) to set the callback function and call [OH_AudioStreamBuilder_SetEncodingType()](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_setencodingtype) to set the encoding type to **AUDIOSTREAM_ENCODING_TYPE_AUDIOVIVID** when creating an audio stream builder.
230
231When an audio file in AudioVivid format is played, the frame size is fixed. Therefore, do not call [OH_AudioStreamBuilder_SetFrameSizeInCallback()](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_setframesizeincallback) to set the frame size in the callback. In addition, when setting the number of audio channels and the audio channel layout, use the sum of the number of sound beds written into the audio source and the number of objects.
232
233The code snippet is as follows:
234
235```C
236// Customize a callback function for simultaneously writing PCM data and metadata.
237int32_t MyOnWriteDataWithMetadata(
238    OH_AudioRenderer* renderer,
239    void* userData,
240    void* audioData,
241    int32_t audioDataSize,
242    void* metadata,
243    int32_t metadataSize)
244{
245    // Write the PCM data and metadata to be played to the buffer by audioDataSize and metadataSize, respectively.
246    return 0;
247}
248
249// Set the encoding type.
250OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_AUDIOVIVID);
251// Set the callbacks.
252OH_AudioRenderer_WriteDataWithMetadataCallback metadataCallback = MyOnWriteDataWithMetadata;
253// Set the callback function for writing both PCM data and metadata.
254OH_AudioStreamBuilder_SetWriteDataWithMetadataCallback(builder, metadataCallback, nullptr);
255```
256