• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Using OHAudio for Audio Playback (C/C++)
2
3OHAudio 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
21Include the <[native_audiostreambuilder.h](../../reference/apis-audio-kit/capi-native-audiostreambuilder-h.md)> and <[native_audiorenderer.h](../../reference/apis-audio-kit/capi-native-audiorenderer-h.md)> header files so that the application can use the functions related to audio playback.
22
23```cpp
24#include <ohaudio/native_audiorenderer.h>
25#include <ohaudio/native_audiostreambuilder.h>
26```
27
28## Building Audio Streams
29
30OHAudio 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/capi-native-audiostream-base-h.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/capi-native-audiostreambuilder-h.md#oh_audiostreambuilder_create) to create a builder:
38
39```cpp
40OH_AudioStreamBuilder* builder;
41OH_AudioStreamBuilder_Create(&builder, streamType);
42```
43
44After the audio service is complete, call [OH_AudioStreamBuilder_Destroy](../../reference/apis-audio-kit/capi-native-audiostreambuilder-h.md#oh_audiostreambuilder_destroy) to destroy the builder.
45
46```cpp
47OH_AudioStreamBuilder_Destroy(builder);
48```
49
50## How to Develop
51
52Read [OHAudio](../../reference/apis-audio-kit/capi-ohaudio.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    ```cpp
59    OH_AudioStreamBuilder* builder;
60    OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
61    ```
62
632. Set audio stream parameters.
64
65    For details about the audio sampling rate, see [Configuring the Appropriate Audio Sampling Rate](using-audiorenderer-for-playback.md#configuring-the-appropriate-audio-sampling-rate).<br>
66    After creating the builder for audio playback, set the parameters required.
67
68    ```cpp
69    // Set the audio sampling rate.
70    OH_AudioStreamBuilder_SetSamplingRate(builder, 48000);
71    // Set the number of audio channels.
72    OH_AudioStreamBuilder_SetChannelCount(builder, 2);
73    // Set the audio sampling format.
74    OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
75    // Set the encoding type of the audio stream.
76    OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
77    // Set the usage scenario of the audio renderer.
78    OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
79    ```
80
81    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/capi-ohaudio-oh-audiorenderer-callbacks-struct.md).
82
833. Set the callback functions.
84
85    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.
86
87    The callback function [OH_AudioRenderer_OnWriteDataCallback](../../reference/apis-audio-kit/capi-native-audiostream-base-h.md#oh_audiorenderer_onwritedatacallback) is introduced in API version 12 for writing audio data.
88
89    - Since API version 12, you are advised to use [OH_AudioRenderer_OnWriteDataCallback](../../reference/apis-audio-kit/capi-native-audiostream-base-h.md#oh_audiorenderer_onwritedatacallback) instead of [OH_AudioRenderer_Callbacks_Struct.OH_AudioRenderer_OnWriteData](../../reference/apis-audio-kit/capi-ohaudio-oh-audiorenderer-callbacks-struct.md#oh_audiorenderer_onwritedata) to write audio data.
90
91      > **NOTE**
92      >
93      > - 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.
94      >
95      > - 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**.
96      >
97      > - 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.
98
99      Since API version 12, you can call [OH_AudioStreamBuilder_SetFrameSizeInCallback](../../reference/apis-audio-kit/capi-native-audiostreambuilder-h.md#oh_audiostreambuilder_setframesizeincallback) to set **audioDataSize**.
100
101      ```cpp
102      // Customize a data writing function.
103      static OH_AudioData_Callback_Result NewAudioRendererOnWriteData(
104          OH_AudioRenderer* renderer,
105          void* userData,
106          void* audioData,
107          int32_t audioDataSize)
108      {
109          // Write the data to be played to audioData by audioDataSize.
110          // If you do not want to play a segment of audioData, return AUDIO_DATA_CALLBACK_RESULT_INVALID.
111          return AUDIO_DATA_CALLBACK_RESULT_VALID;
112      }
113      // Customize an audio stream event function.
114      int32_t MyOnStreamEvent(
115          OH_AudioRenderer* renderer,
116          void* userData,
117          OH_AudioStream_Event event)
118      {
119          // Update the player status and UI based on the audio stream event information indicated by the event.
120          return 0;
121      }
122      // Customize an audio interruption event function.
123      int32_t MyOnInterruptEvent(
124          OH_AudioRenderer* renderer,
125          void* userData,
126          OH_AudioInterrupt_ForceType type,
127          OH_AudioInterrupt_Hint hint)
128      {
129          // Update the player status and UI based on the audio interruption information indicated by type and hint.
130          return 0;
131      }
132      // Customize an exception callback function.
133      int32_t MyOnError(
134          OH_AudioRenderer* renderer,
135          void* userData,
136          OH_AudioStream_Result error)
137      {
138          // Perform operations based on the audio exception information indicated by error.
139          return 0;
140      }
141
142      OH_AudioRenderer_Callbacks callbacks;
143
144      // Set the callbacks.
145      callbacks.OH_AudioRenderer_OnStreamEvent = MyOnStreamEvent;
146      callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
147      callbacks.OH_AudioRenderer_OnError = MyOnError;
148      callbacks.OH_AudioRenderer_OnWriteData = nullptr;
149
150      // Set callbacks for the audio renderer.
151      OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);
152
153      // Configure the callback function for writing audio data.
154      OH_AudioRenderer_OnWriteDataCallback writeDataCb = NewAudioRendererOnWriteData;
155      OH_AudioStreamBuilder_SetRendererWriteDataCallback(builder, writeDataCb, nullptr);
156      ```
157
158    - In API version 11, you can use the callback function [OH_AudioRenderer_Callbacks_Struct.OH_AudioRenderer_OnWriteData](../../reference/apis-audio-kit/capi-ohaudio-oh-audiorenderer-callbacks-struct.md#oh_audiorenderer_onwritedata) to write audio data.
159
160      > **NOTE**
161      >
162      > - 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.
163      >
164      > - 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.
165      >
166      > - 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).
167      >
168      > - 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.
169
170      ```cpp
171      // Customize a data writing function.
172      int32_t MyOnWriteData(
173          OH_AudioRenderer* renderer,
174          void* userData,
175          void* buffer,
176          int32_t length)
177      {
178          // Write the data to be played to the buffer by length.
179          // If you do not want to play a particular portion of the buffer, you can clear that specific section of the buffer.
180          return 0;
181      }
182      // Customize an audio stream event function.
183      int32_t MyOnStreamEvent(
184          OH_AudioRenderer* renderer,
185          void* userData,
186          OH_AudioStream_Event event)
187      {
188          // Update the player status and UI based on the audio stream event information indicated by the event.
189          return 0;
190      }
191      // Customize an audio interruption event function.
192      int32_t MyOnInterruptEvent(
193          OH_AudioRenderer* renderer,
194          void* userData,
195          OH_AudioInterrupt_ForceType type,
196          OH_AudioInterrupt_Hint hint)
197      {
198          // Update the player status and UI based on the audio interruption information indicated by type and hint.
199          return 0;
200      }
201      // Customize an exception callback function.
202      int32_t MyOnError(
203          OH_AudioRenderer* renderer,
204          void* userData,
205          OH_AudioStream_Result error)
206      {
207          // Perform operations based on the audio exception information indicated by error.
208          return 0;
209      }
210
211      OH_AudioRenderer_Callbacks callbacks;
212
213      // Set the callbacks.
214      callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
215      callbacks.OH_AudioRenderer_OnStreamEvent = MyOnStreamEvent;
216      callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
217      callbacks.OH_AudioRenderer_OnError = MyOnError;
218
219      // Set callbacks for the audio renderer.
220      OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);
221      ```
222
223   To avoid unexpected behavior, you can set the audio callback functions in either of the following ways:
224
225   - Initialize each callback in [OH_AudioRenderer_Callbacks](../../reference/apis-audio-kit/capi-ohaudio-oh-audiorenderer-callbacks-struct.md) by a custom callback method or a null pointer.
226
227     ```cpp
228     // Customize a data writing function.
229     int32_t MyOnWriteData(
230         OH_AudioRenderer* renderer,
231         void* userData,
232         void* buffer,
233         int32_t length)
234     {
235         // Write the data to be played to the buffer by length.
236         return 0;
237     }
238     // Customize an audio interruption event function.
239     int32_t MyOnInterruptEvent(
240         OH_AudioRenderer* renderer,
241         void* userData,
242         OH_AudioInterrupt_ForceType type,
243         OH_AudioInterrupt_Hint hint)
244     {
245         // Update the player status and UI based on the audio interruption information indicated by type and hint.
246         return 0;
247     }
248
249     OH_AudioRenderer_Callbacks callbacks;
250
251     // Configure a callback function. If listening is required, assign a value.
252     callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
253     callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
254
255     // (Mandatory) If listening is not required, use a null pointer for initialization.
256     callbacks.OH_AudioRenderer_OnStreamEvent = nullptr;
257     callbacks.OH_AudioRenderer_OnError = nullptr;
258     ```
259
260   - Initialize and clear the struct before using it.
261
262     ```cpp
263     // Customize a data writing function.
264     int32_t MyOnWriteData(
265         OH_AudioRenderer* renderer,
266         void* userData,
267         void* buffer,
268         int32_t length)
269     {
270         // Write the data to be played to the buffer by length.
271         return 0;
272     }
273     // Customize an audio interruption event function.
274     int32_t MyOnInterruptEvent(
275         OH_AudioRenderer* renderer,
276         void* userData,
277         OH_AudioInterrupt_ForceType type,
278         OH_AudioInterrupt_Hint hint)
279     {
280         // Update the player status and UI based on the audio interruption information indicated by type and hint.
281         return 0;
282     }
283     OH_AudioRenderer_Callbacks callbacks;
284
285     // Initialize and clear the struct before using it.
286     memset(&callbacks, 0, sizeof(OH_AudioRenderer_Callbacks));
287
288     // Configure the required callback functions.
289     callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
290     callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent;
291     ```
292
2934. Create an audio renderer instance.
294
295    ```cpp
296    OH_AudioRenderer* audioRenderer;
297    OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
298    ```
299
3005. Use the audio renderer.
301
302    You can use the APIs listed below to control the audio streams.
303
304    | API                                                        | Description        |
305    | ------------------------------------------------------------ | ------------ |
306    | OH_AudioStream_Result OH_AudioRenderer_Start(OH_AudioRenderer* renderer) | Starts the audio renderer.    |
307    | OH_AudioStream_Result OH_AudioRenderer_Pause(OH_AudioRenderer* renderer) | Pauses the audio renderer.    |
308    | OH_AudioStream_Result OH_AudioRenderer_Stop(OH_AudioRenderer* renderer) | Stops the audio renderer.    |
309    | OH_AudioStream_Result OH_AudioRenderer_Flush(OH_AudioRenderer* renderer) | Flushes obtained audio data.|
310    | OH_AudioStream_Result OH_AudioRenderer_Release(OH_AudioRenderer* renderer) | Releases the audio renderer instance.|
311
3126. Destroy the audio stream builder.
313
314    When the builder is no longer used, release related resources.
315
316    ```cpp
317    OH_AudioStreamBuilder_Destroy(builder);
318    ```
319
320## Setting the Volume for an Audio Stream
321
322You can use [OH_AudioRenderer_SetVolume](../../reference/apis-audio-kit/capi-native-audiorenderer-h.md#oh_audiorenderer_setvolume) to set the volume for the current audio stream.
323
324```cpp
325// Volume to set. The value range is [0.0, 1.0].
326float volume = 0.5f;
327
328// Set the volume for the audio stream.
329OH_AudioStream_Result OH_AudioRenderer_SetVolume(audioRenderer, volume);
330```
331
332## Setting the Low Latency Mode
333
334If the device supports the low-latency channel and the sampling rate is set to 48000, you can use the low-latency mode to create a player for a higher-quality audio experience.
335
336The development process is similar to that in the common playback scenario. The only difference is that you need to set the low-latency mode by calling [OH_AudioStreamBuilder_SetLatencyMode()](../../reference/apis-audio-kit/capi-native-audiostreambuilder-h.md#oh_audiostreambuilder_setlatencymode) when creating an audio stream builder.
337
338> **NOTE**
339> - In audio recording scenarios, if [OH_AudioStream_Usage](../../reference/apis-audio-kit/capi-native-audiostream-base-h.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.
340> - The low-latency mode requires robust data processing capabilities. If your application generates data slowly, it may lead to lag. Therefore, for typical music and video playback, this mode is not recommended. It is best suited for applications that are sensitive to latency, such as gaming and karaoke.
341
342The code snippet is as follows:
343
344```cpp
345OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST);
346```
347
348## Setting the Audio Channel Layout
349
350In 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.
351
352The 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/capi-native-audiostreambuilder-h.md#oh_audiostreambuilder_setchannellayout) when creating an audio stream builder.
353
354If 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.
355
356If 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.
357
358For audio in HOA format, to obtain the correct rendering and playback effect, you must specify the audio channel layout.
359
360The code snippet is as follows:
361
362```cpp
363OH_AudioStreamBuilder_SetChannelLayout(builder, CH_LAYOUT_STEREO);
364```
365
366## Playing Audio Files in Audio Vivid Format
367
368In the case of audio file playback in Audio Vivid 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.
369
370The 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/capi-native-audiostreambuilder-h.md#oh_audiostreambuilder_setwritedatawithmetadatacallback) to set the callback function and call [OH_AudioStreamBuilder_SetEncodingType()](../../reference/apis-audio-kit/capi-native-audiostreambuilder-h.md#oh_audiostreambuilder_setencodingtype) to set the encoding type to **AUDIOSTREAM_ENCODING_TYPE_AUDIOVIVID** when creating an audio stream builder.
371
372When an audio file in Audio Vivid format is played, the frame size is fixed. Therefore, do not call [OH_AudioStreamBuilder_SetFrameSizeInCallback()](../../reference/apis-audio-kit/capi-native-audiostreambuilder-h.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.
373
374```cpp
375// Customize a callback function for simultaneously writing PCM data and metadata.
376int32_t MyOnWriteDataWithMetadata(
377    OH_AudioRenderer* renderer,
378    void* userData,
379    void* audioData,
380    int32_t audioDataSize,
381    void* metadata,
382    int32_t metadataSize)
383{
384    // Write the PCM data and metadata to be played to the buffer by audioDataSize and metadataSize, respectively.
385    return 0;
386}
387
388// Set the encoding type.
389OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_AUDIOVIVID);
390// Set the callbacks.
391OH_AudioRenderer_WriteDataWithMetadataCallback metadataCallback = MyOnWriteDataWithMetadata;
392// Set the callback function for writing both PCM data and metadata.
393OH_AudioStreamBuilder_SetWriteDataWithMetadataCallback(builder, metadataCallback, nullptr);
394```
395
396<!--RP1-->
397<!--RP1End-->
398