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 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