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 and are suitable for playback applications that implement audio output at the native layer.
4
5OHAudio audio playback state transition
6
7![OHAudioRenderer status change](figures/ohaudiorenderer-status-change.png)
8
9## Prerequisites
10
11To use the playback capability of **OHAudio**, you must first import the corresponding header files.
12
13### Linking the Dynamic Library in the CMake Script
14
15``` cmake
16target_link_libraries(sample PUBLIC libohaudio.so)
17```
18
19### Adding Header Files
20
21To 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)>.
22
23```cpp
24#include <ohaudio/native_audiorenderer.h>
25#include <ohaudio/native_audiostreambuilder.h>
26```
27
28## Building Audio Streams
29
30**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.
31
32**OH_AudioStream_Type** can be set to either of the following:
33
34- AUDIOSTREAM_TYPE_RENDERER
35- AUDIOSTREAM_TYPE_CAPTURER
36
37The 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:
38
39```
40OH_AudioStreamBuilder* builder;
41OH_AudioStreamBuilder_Create(&builder, streamType);
42```
43
44After the audio service is complete, call [OH_AudioStreamBuilder_Destroy](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_destroy) to destroy the builder.
45
46```
47OH_AudioStreamBuilder_Destroy(builder);
48```
49
50## How to Develop
51
52Read [OHAudio](../../reference/apis-audio-kit/_o_h_audio.md) for the API reference.
53
54The following walks you through how to implement simple playback:
55
561. Create an audio stream builder.
57
58    ```c++
59    OH_AudioStreamBuilder* builder;
60    OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
61    ```
62
632. Set audio stream parameters.
64
65    After creating the builder for audio playback, set the parameters required.
66
67    ```c++
68    // Set the audio sampling rate.
69    OH_AudioStreamBuilder_SetSamplingRate(builder, 48000);
70    // Set the number of audio channels.
71    OH_AudioStreamBuilder_SetChannelCount(builder, 2);
72    // Set the audio sampling format.
73    OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
74    // Set the encoding type of the audio stream.
75    OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
76    // Set the usage scenario of the audio renderer.
77    OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
78    ```
79
80    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).
81
823. Set the callback functions.
83
84    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.
85
86    The callback function [OH_AudioRenderer_OnWriteDataCallback](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiorenderer_onwritedatacallback) is introduced in API version 12 for writing audio data.
87
88    - Since API version 12, you are advised to use [OH_AudioRenderer_OnWriteDataCallback](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiorenderer_onwritedatacallback) instead of [OH_AudioRenderer_Callbacks_Struct.OH_AudioRenderer_OnWriteData](../../reference/apis-audio-kit/_o_h___audio_renderer___callbacks___struct.md#oh_audiorenderer_onwritedata) to write audio data.
89
90      > **NOTE**
91      >
92      > - When the amount of data is sufficient to meet the required buffer length of the callback, you should return **AUDIO_DATA_CALLBACK_RESULT_VALID**, and the system uses the entire data buffer for playback. Do not return **AUDIO_DATA_CALLBACK_RESULT_VALID** in this case, as this leads to audio artifacts such as noise and playback stuttering.
93      >
94      > - When the amount of data is insufficient to meet the required buffer length of the callback, you are advised to return **AUDIO_DATA_CALLBACK_RESULT_INVALID**. In this case, the system does not process this portion of audio data but requests data from the application again. Once the buffer is adequately filled, you can return **AUDIO_DATA_CALLBACK_RESULT_VALID**.
95      >
96      > - Once the callback function finishes its execution, the audio service queues the data in the buffer for playback. Therefore, do not change the buffered data outside the callback. Regarding the last frame, if there is insufficient data to completely fill the buffer, you must concatenate the available data with padding to ensure that the buffer is full. This prevents any residual dirty data in the buffer from adversely affecting the playback effect.
97
98    - Since API version 12, you can call [OH_AudioStreamBuilder_SetFrameSizeInCallback](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostreambuilder_setframesizeincallback) to set **audioDataSize**.
99
100      ```c++
101      // Customize a data writing function.
102      static OH_AudioData_Callback_Result NewAudioRendererOnWriteData(
103          OH_AudioRenderer* renderer,
104          void* userData,
105          void* audioData,
106          int32_t audioDataSize)
107      {
108          // Write the data to be played to audioData by audioDataSize.
109          // If you do not want to play a segment of audioData, return AUDIO_DATA_CALLBACK_RESULT_INVALID.
110          return AUDIO_DATA_CALLBACK_RESULT_VALID;
111      }
112      // Customize an audio stream event function.
113      int32_t MyOnStreamEvent(
114          OH_AudioRenderer* renderer,
115          void* userData,
116          OH_AudioStream_Event event)
117      {
118          // Update the player status and UI based on the audio stream event information indicated by the event.
119          return 0;
120      }
121      // Customize an audio interruption event function.
122      int32_t MyOnInterruptEvent(
123          OH_AudioRenderer* renderer,
124          void* userData,
125          OH_AudioInterrupt_ForceType type,
126          OH_AudioInterrupt_Hint hint)
127      {
128          // Update the player status and UI based on the audio interruption information indicated by type and hint.
129          return 0;
130      }
131      // Customize an exception callback function.
132      int32_t MyOnError(
133          OH_AudioRenderer* renderer,
134          void* userData,
135          OH_AudioStream_Result error)
136      {
137          // Perform operations based on the audio exception information indicated by error.
138          return 0;
139      }
140
141      OH_AudioRenderer_Callbacks callbacks;
142
143      // Set the callbacks.
144      callbacks.OH_AudioRenderer_OnStreamEvent = MyOnStreamEvent;
145      callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
146      callbacks.OH_AudioRenderer_OnError = MyOnError;
147      callbacks.OH_AudioRenderer_OnWriteData = nullptr;
148
149      // Set callbacks for the audio renderer.
150      OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);
151
152      // Configure the callback function for writing audio data.
153      OH_AudioRenderer_OnWriteDataCallback writeDataCb = NewAudioRendererOnWriteData;
154      OH_AudioStreamBuilder_SetRendererWriteDataCallback(builder, writeDataCb, nullptr);
155      ```
156
157    - In API version 11, you can use the callback function [OH_AudioRenderer_Callbacks_Struct.OH_AudioRenderer_OnWriteData](../../reference/apis-audio-kit/_o_h___audio_renderer___callbacks___struct.md#oh_audiorenderer_onwritedata) to write audio data.
158
159      > **NOTE**
160      >
161      > - This callback function does not return a callback result, and the system treats all data in the callback as valid by default. Ensure that the callback's data buffer is completely filled to the necessary length to prevent issues such as audio noise and playback stuttering.
162      >
163      > - If the amount of data is insufficient to fill the data buffer, you are advised to temporarily halt data writing (without pausing the audio stream), block the callback function, and wait until enough data accumulates before resuming writing, thereby ensuring that the buffer is fully filled. If you need to call AudioRenderer APIs after the callback function is blocked, unblock the callback function first.
164      >
165      > - If you do not want to play the audio data in this callback function, you can nullify the data block in the callback function. (Once nullified, the system still regards this as part of the written data, leading to silent frames during playback).
166      >
167      > - Once the callback function finishes its execution, the audio service queues the data in the buffer for playback. Therefore, do not change the buffered data outside the callback. Regarding the last frame, if there is insufficient data to completely fill the buffer, you must concatenate the available data with padding to ensure that the buffer is full. This prevents any residual dirty data in the buffer from adversely affecting the playback effect.
168
169      ```c++
170      // Customize a data writing function.
171      int32_t MyOnWriteData(
172          OH_AudioRenderer* renderer,
173          void* userData,
174          void* buffer,
175          int32_t length)
176      {
177          // Write the data to be played to the buffer by length.
178          // If you do not want to play a particular portion of the buffer, you can clear that specific section of the buffer.
179          return 0;
180      }
181      // Customize an audio stream event function.
182      int32_t MyOnStreamEvent(
183          OH_AudioRenderer* renderer,
184          void* userData,
185          OH_AudioStream_Event event)
186      {
187          // Update the player status and UI based on the audio stream event information indicated by the event.
188          return 0;
189      }
190      // Customize an audio interruption event function.
191      int32_t MyOnInterruptEvent(
192          OH_AudioRenderer* renderer,
193          void* userData,
194          OH_AudioInterrupt_ForceType type,
195          OH_AudioInterrupt_Hint hint)
196      {
197          // Update the player status and UI based on the audio interruption information indicated by type and hint.
198          return 0;
199      }
200      // Customize an exception callback function.
201      int32_t MyOnError(
202          OH_AudioRenderer* renderer,
203          void* userData,
204          OH_AudioStream_Result error)
205      {
206          // Perform operations based on the audio exception information indicated by error.
207          return 0;
208      }
209
210      OH_AudioRenderer_Callbacks callbacks;
211
212      // Set the callbacks.
213      callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
214      callbacks.OH_AudioRenderer_OnStreamEvent = MyOnStreamEvent;
215      callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
216      callbacks.OH_AudioRenderer_OnError = MyOnError;
217
218      // Set callbacks for the audio renderer.
219      OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);
220      ```
221
222   To avoid unexpected behavior, you can set the audio callback functions in either of the following ways:
223
224   - Initialize each callback in [OH_AudioRenderer_Callbacks](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiorenderer_callbacks) by a custom callback method or a null pointer.
225
226     ```c++
227     // Customize a data writing function.
228     int32_t MyOnWriteData(
229         OH_AudioRenderer* renderer,
230         void* userData,
231         void* buffer,
232         int32_t length)
233     {
234         // Write the data to be played to the buffer by length.
235         return 0;
236     }
237     // Customize an audio interruption event function.
238     int32_t MyOnInterruptEvent(
239         OH_AudioRenderer* renderer,
240         void* userData,
241         OH_AudioInterrupt_ForceType type,
242         OH_AudioInterrupt_Hint hint)
243     {
244         // Update the player status and UI based on the audio interruption information indicated by type and hint.
245         return 0;
246     }
247
248     OH_AudioRenderer_Callbacks callbacks;
249
250     // Configure a callback function. If listening is required, assign a value.
251     callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
252     callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
253
254     // (Mandatory) If listening is not required, use a null pointer for initialization.
255     callbacks.OH_AudioRenderer_OnStreamEvent = nullptr;
256     callbacks.OH_AudioRenderer_OnError = nullptr;
257     ```
258
259   - Initialize and clear the struct before using it.
260
261     ```c++
262     // Customize a data writing function.
263     int32_t MyOnWriteData(
264         OH_AudioRenderer* renderer,
265         void* userData,
266         void* buffer,
267         int32_t length)
268     {
269         // Write the data to be played to the buffer by length.
270         return 0;
271     }
272     // Customize an audio interruption event function.
273     int32_t MyOnInterruptEvent(
274         OH_AudioRenderer* renderer,
275         void* userData,
276         OH_AudioInterrupt_ForceType type,
277         OH_AudioInterrupt_Hint hint)
278     {
279         // Update the player status and UI based on the audio interruption information indicated by type and hint.
280         return 0;
281     }
282     OH_AudioRenderer_Callbacks callbacks;
283
284     // Initialize and clear the struct before using it.
285     memset(&callbacks, 0, sizeof(OH_AudioRenderer_Callbacks));
286
287     // Configure the required callback functions.
288     callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
289     callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
290     ```
291
2924. Create an audio renderer instance.
293
294    ```c++
295    OH_AudioRenderer* audioRenderer;
296    OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
297    ```
298
2995. Use the audio renderer.
300
301    You can use the APIs listed below to control the audio streams.
302
303    | API                                                        | Description        |
304    | ------------------------------------------------------------ | ------------ |
305    | OH_AudioStream_Result OH_AudioRenderer_Start(OH_AudioRenderer* renderer) | Starts the audio renderer.    |
306    | OH_AudioStream_Result OH_AudioRenderer_Pause(OH_AudioRenderer* renderer) | Pauses the audio renderer.    |
307    | OH_AudioStream_Result OH_AudioRenderer_Stop(OH_AudioRenderer* renderer) | Stops the audio renderer.    |
308    | OH_AudioStream_Result OH_AudioRenderer_Flush(OH_AudioRenderer* renderer) | Flushes written audio data.|
309    | OH_AudioStream_Result OH_AudioRenderer_Release(OH_AudioRenderer* renderer) | Releases the audio renderer instance.|
310
3116. Destroy the audio stream builder.
312
313    When the builder is no longer used, release related resources.
314
315    ```c++
316    OH_AudioStreamBuilder_Destroy(builder);
317    ```
318
319## Setting the Low Latency Mode
320
321If the device supports the low-latency channel, you can use the low-latency mode to create a player for a higher-quality audio experience.
322
323The 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.
324
325> **NOTE**
326>
327> In audio recording scenarios, if [OH_AudioStream_Usage](../../reference/apis-audio-kit/_o_h_audio.md#oh_audiostream_usage) is set to **AUDIOSTREAM_USAGE_VOICE_COMMUNICATION** or **AUDIOSTREAM_USAGE_VIDEO_COMMUNICATION**, the low-latency mode cannot be set. The system determines the output audio channel based on the device capability.
328
329The code snippet is as follows:
330
331```C
332OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST);
333```
334
335## Setting the Audio Channel Layout
336
337In 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.
338
339The 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.
340
341If 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.
342
343If 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.
344
345For audio in HOA format, to obtain the correct rendering and playback effect, you must specify the audio channel layout.
346
347The code snippet is as follows:
348
349```C
350OH_AudioStreamBuilder_SetChannelLayout(builder, CH_LAYOUT_STEREO);
351```
352
353## Playing Audio Files in AudioVivid Format
354
355In 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.
356
357The 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.
358
359When 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.
360
361The code snippet is as follows:
362
363```C
364// Customize a callback function for simultaneously writing PCM data and metadata.
365int32_t MyOnWriteDataWithMetadata(
366    OH_AudioRenderer* renderer,
367    void* userData,
368    void* audioData,
369    int32_t audioDataSize,
370    void* metadata,
371    int32_t metadataSize)
372{
373    // Write the PCM data and metadata to be played to the buffer by audioDataSize and metadataSize, respectively.
374    return 0;
375}
376
377// Set the encoding type.
378OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_AUDIOVIVID);
379// Set the callbacks.
380OH_AudioRenderer_WriteDataWithMetadataCallback metadataCallback = MyOnWriteDataWithMetadata;
381// Set the callback function for writing both PCM data and metadata.
382OH_AudioStreamBuilder_SetWriteDataWithMetadataCallback(builder, metadataCallback, nullptr);
383```
384
385<!--RP1-->
386<!--RP1End-->
387