1e41f4b71Sopenharmony_ci# Switching from OpenSL ES to OHAudio (C/C++)
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ciYou are advised to use **OHAudio** APIs instead of OpenSL ES APIs to develop audio services, since the latter may fail to provide extended audio capabilities. This topic describes how to switch the audio service code from the OpenSL ES APIs to the **OHAudio** APIs.
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci## Differences in Features Supported
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciDifferent from the OpenSL ES APIs, the **OHAudio** APIs support low-latency playback/recording and service change listening.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciThe table below lists the differences in the features supported by the APIs.
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci| | OpenSL ES| OHAudio |
12e41f4b71Sopenharmony_ci| --- | --- | --- |
13e41f4b71Sopenharmony_ci| Audio streaming playback| Supported| Supported|
14e41f4b71Sopenharmony_ci| Audio streaming recording| Supported| Supported|
15e41f4b71Sopenharmony_ci| Low-latency audio playback| Not supported| Supported|
16e41f4b71Sopenharmony_ci| Low-latency audio recording| Not supported| Supported|
17e41f4b71Sopenharmony_ci| Switching the state of a playback object| Supported| Supported|
18e41f4b71Sopenharmony_ci| Switching the state of a recording object| Supported| Supported|
19e41f4b71Sopenharmony_ci| Obtaining the state of an audio stream object| Supported| Supported|
20e41f4b71Sopenharmony_ci| Clearing the playback cache| Not supported| Supported|
21e41f4b71Sopenharmony_ci| Listening for audio interruption events| Not supported| Supported|
22e41f4b71Sopenharmony_ci| Listening for audio stream events| Not supported| Supported|
23e41f4b71Sopenharmony_ci| Listening for stream exception events| Not supported| Supported|
24e41f4b71Sopenharmony_ci| Listening for output device update events| Not supported| Supported|
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci## Differences in Development Modes
27e41f4b71Sopenharmony_ci
28e41f4b71Sopenharmony_ciThis section describes the differences between **OHAudio** and OpenSL ES APIs in development modes based on the development procedure of audio playback. The implementation of audio recording is similar.
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci### Constructing Instances
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ciOpenSL ES:
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ciObtain an **Engine** object through the global interface, and construct an audio playback object based on the **Engine** object and the input and output parameters.
35e41f4b71Sopenharmony_ci
36e41f4b71Sopenharmony_ci```c++
37e41f4b71Sopenharmony_ci// Generate an Engine object.
38e41f4b71Sopenharmony_ciSLEngineItf engine;
39e41f4b71Sopenharmony_ci// ...
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci// Configure audio input slSource as required.
42e41f4b71Sopenharmony_ciSLDataSource slSource;
43e41f4b71Sopenharmony_ci// ...
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ci// Configure audio output slSink as required.
46e41f4b71Sopenharmony_ciSLDataSink slSink;
47e41f4b71Sopenharmony_ci// ...
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ci// Generate an audio playback object.
50e41f4b71Sopenharmony_ciSLObjectItf playerObject;
51e41f4b71Sopenharmony_ci(*engine)->CreateAudioPlayer(engine,
52e41f4b71Sopenharmony_ci                             &playerObject,
53e41f4b71Sopenharmony_ci                             &slSource,
54e41f4b71Sopenharmony_ci                             &slSink,
55e41f4b71Sopenharmony_ci                             0,
56e41f4b71Sopenharmony_ci                             nullptr,
57e41f4b71Sopenharmony_ci                             nullptr);
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci(*playerObject)->Realize(playerObject,
60e41f4b71Sopenharmony_ci                         SL_BOOLEAN_FALSE);
61e41f4b71Sopenharmony_ci```
62e41f4b71Sopenharmony_ci
63e41f4b71Sopenharmony_ciOHAudio:
64e41f4b71Sopenharmony_ci
65e41f4b71Sopenharmony_ciUse the builder mode to generate an audio playback object based on custom parameters.
66e41f4b71Sopenharmony_ci
67e41f4b71Sopenharmony_ci```c++
68e41f4b71Sopenharmony_ci// Create a builder.
69e41f4b71Sopenharmony_ciOH_AudioStreamBuilder *builder;
70e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci// Set custom parameters. Otherwise, the default parameters will be used.
73e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_SetSamplingRate(builder, 48000);
74e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_SetChannelCount(builder, 2);
75e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
76e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
77e41f4b71Sopenharmony_ci// This parameter specifies the audio usage and is supported only by OHAudio. The system implements audio policy adaptation based on the parameter.
78e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
79e41f4b71Sopenharmony_ci// ...
80e41f4b71Sopenharmony_ci
81e41f4b71Sopenharmony_ci// Generate an audio playback object.
82e41f4b71Sopenharmony_ciOH_AudioRenderer *audioRenderer;
83e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
84e41f4b71Sopenharmony_ci```
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ci### State Switching
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ciOpenSL ES:
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ciObtain the state switching interface based on the audio playback object and use the interface to switch the state. There are three states: **SL_PLAYSTATE_STOPPED**, **SL_PLAYSTATE_PAUSED**, and **SL_PLAYSTATE_PLAYING**.
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci```c++
93e41f4b71Sopenharmony_ci// Obtain the playback operation interface based on the audio playback object.
94e41f4b71Sopenharmony_ciSLPlayItf playItf = nullptr;
95e41f4b71Sopenharmony_ci(*playerObject)->GetInterface(playerObject, SL_IID_PLAY, &playItf);
96e41f4b71Sopenharmony_ci// Switch the state.
97e41f4b71Sopenharmony_ci(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
98e41f4b71Sopenharmony_ci(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED);
99e41f4b71Sopenharmony_ci(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
100e41f4b71Sopenharmony_ci```
101e41f4b71Sopenharmony_ci
102e41f4b71Sopenharmony_ciOHAudio:
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ciThere are independent state switching interfaces. The state is switched based on the state machine. There are six states, which are mainly switched between **AUDIOSTREAM_STATE_PREPARED**, **AUDIOSTREAM_STATE_RUNNING**, **AUDIOSTREAM_STATE_STOPPED**, **AUDIOSTREAM_STATE_PAUSED**, and **AUDIOSTREAM_STATE_RELEASED**.
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci```c++
107e41f4b71Sopenharmony_ci// Switch the state.
108e41f4b71Sopenharmony_ciOH_AudioRenderer_Start(audioRenderer);
109e41f4b71Sopenharmony_ciOH_AudioRenderer_Pause(audioRenderer);
110e41f4b71Sopenharmony_ciOH_AudioRenderer_Stop(audioRenderer);
111e41f4b71Sopenharmony_ci```
112e41f4b71Sopenharmony_ci
113e41f4b71Sopenharmony_ci### Data Processing
114e41f4b71Sopenharmony_ci
115e41f4b71Sopenharmony_ciOpenSL ES:
116e41f4b71Sopenharmony_ci
117e41f4b71Sopenharmony_ciBased on the extended **OHBufferQueue** APIs, you can register a custom callback function to write audio data to be played to the system buffer.
118e41f4b71Sopenharmony_ci
119e41f4b71Sopenharmony_ci```c++
120e41f4b71Sopenharmony_cistatic void MyBufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
121e41f4b71Sopenharmony_ci{
122e41f4b71Sopenharmony_ci    SLuint8 *buffer = nullptr;
123e41f4b71Sopenharmony_ci    SLuint32 bufferSize;
124e41f4b71Sopenharmony_ci    // Obtain the buffer provided by the system.
125e41f4b71Sopenharmony_ci    (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &bufferSize);
126e41f4b71Sopenharmony_ci    // Write the audio data to be played to the buffer.
127e41f4b71Sopenharmony_ci    // ...
128e41f4b71Sopenharmony_ci    // Enqueue the buffer.
129e41f4b71Sopenharmony_ci    (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, bufferSize);
130e41f4b71Sopenharmony_ci}
131e41f4b71Sopenharmony_ci
132e41f4b71Sopenharmony_ci// Obtain the OHBufferQueue APIs.
133e41f4b71Sopenharmony_ciSLOHBufferQueueItf bufferQueueItf;
134e41f4b71Sopenharmony_ci(*playerObject)->GetInterface(playerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
135e41f4b71Sopenharmony_ci// This callback can be used to obtain the custom context information passed in.
136e41f4b71Sopenharmony_civoid *pContext;
137e41f4b71Sopenharmony_ci(*bufferQueueItf)->RegisterCallback(bufferQueueItf, MyBufferQueueCallback, pContext);
138e41f4b71Sopenharmony_ci```
139e41f4b71Sopenharmony_ci
140e41f4b71Sopenharmony_ciOHAudio:
141e41f4b71Sopenharmony_ci
142e41f4b71Sopenharmony_ciThe callback mode is used. When the audio playback object is constructed, a data input callback is registered to implement custom data filling. During playback, a data request callback is automatically triggered at a proper time based on the system scheduling and delay configuration.
143e41f4b71Sopenharmony_ci
144e41f4b71Sopenharmony_ci```c++
145e41f4b71Sopenharmony_cistatic int32_t MyOnWriteData(
146e41f4b71Sopenharmony_ci    OH_AudioRenderer *renderer,
147e41f4b71Sopenharmony_ci    void *userData,
148e41f4b71Sopenharmony_ci    void *buffer,
149e41f4b71Sopenharmony_ci    int32_t bufferLen)
150e41f4b71Sopenharmony_ci{
151e41f4b71Sopenharmony_ci    // Write the data to be played to the buffer based on the requested buffer length.
152e41f4b71Sopenharmony_ci    // After the function is returned, the system automatically fetches data from the buffer.
153e41f4b71Sopenharmony_ci}
154e41f4b71Sopenharmony_ci
155e41f4b71Sopenharmony_ciOH_AudioRenderer_Callbacks callbacks;
156e41f4b71Sopenharmony_cicallbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData;
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ci// Set the callback function for outputting audio streams. The callback function is automatically registered when the audio playback object is generated.
159e41f4b71Sopenharmony_civoid *userData = nullptr;
160e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, userData);
161e41f4b71Sopenharmony_ci```
162e41f4b71Sopenharmony_ci
163e41f4b71Sopenharmony_ci### Releasing Resources
164e41f4b71Sopenharmony_ci
165e41f4b71Sopenharmony_ciOpenSL ES:
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ciCall **SLObjectItf** to release object resources.
168e41f4b71Sopenharmony_ci
169e41f4b71Sopenharmony_ci```c++
170e41f4b71Sopenharmony_ci// Release the playback object resources.
171e41f4b71Sopenharmony_ci(*playerObject)->Destroy(playerObject);
172e41f4b71Sopenharmony_ci```
173e41f4b71Sopenharmony_ci
174e41f4b71Sopenharmony_ciOHAudio:
175e41f4b71Sopenharmony_ci
176e41f4b71Sopenharmony_ciCall the release interface of the module to release object resources.
177e41f4b71Sopenharmony_ci
178e41f4b71Sopenharmony_ci```c++
179e41f4b71Sopenharmony_ci// Release the builder resources.
180e41f4b71Sopenharmony_ciOH_AudioStreamBuilder_Destroy(builder);
181e41f4b71Sopenharmony_ci
182e41f4b71Sopenharmony_ci// Release the playback object resources.
183e41f4b71Sopenharmony_ciOH_AudioRenderer_Release(audioRenderer);
184e41f4b71Sopenharmony_ci```
185