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