1# Using OpenSL ES for Audio Playback (C/C++)
2
3OpenSL ES, short for Open Sound Library for Embedded Systems, is an embedded, cross-platform audio processing library that is free of charge. It provides high-performance and low-latency APIs for you to develop applications running on embedded mobile multimedia devices. OpenHarmony has implemented certain native APIs based on [OpenSL ES](https://www.khronos.org/opensles/) 1.0.1 API specifications developed by the [Khronos Group](https://www.khronos.org/). You can use these APIs through <OpenSLES.h\> and <OpenSLES_OpenHarmony.h\>.
4
5## Using OHAudio to Replace OpenSL ES
6
7OpenHarmony provides the OpenSL ES APIs for audio development at the native layer since SDK8. As the version evolves, these APIs fail to meet the capability expansion requirements of the audio system and therefore are no longer recommended.
8
9In SDK 10, OpenHarmony provides the **OHAudio** APIs, which open up all audio functions of the system. The **OHAudio** APIs cover all the capabilities provided by OpenSL ES in OpenHarmony. They also support new features such as audio focus events and low latency.
10
11For details about how to use the **OHAudio** APIs for audio development, see [Using OHAudio for Audio Playback (C/C++)](using-ohaudio-for-playback.md).
12
13If you have used the OpenSL ES APIs in your code, you can switch them to the **OHAudio** APIs. For details, see [Switching from OpenSL ES to OHAudio (C/C++)](replace-opensles-by-ohaudio.md).
14
15## OpenSL ES on OpenHarmony
16
17Currently, OpenHarmony implements parts of [OpenSL ES APIs](https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h) to implement basic audio playback functionalities.
18
19If an API that has not been implemented on OpenHarmony is called, **SL_RESULT_FEATURE_UNSUPPORTED** is returned.
20
21The following lists the OpenSL ES APIs that have been implemented on OpenHarmony. For details, see the [OpenSL ES](https://www.khronos.org/opensles/) specifications.
22
23- **SLInterfaceID implemented on OpenHarmony**
24
25  | SLInterfaceID | Description |
26  | -------- | -------- |
27  | SL_IID_ENGINE | Universal engine, which provides the interface for creating player objects. |
28  | SL_IID_PLAY | Provides the player status interface. |
29  | SL_IID_VOLUME | Provides interfaces for adjusting and reading the volume of audio playback streams. |
30  | SL_IID_OH_BUFFERQUEUE | Provides the callback registration interface for audio playback stream data. |
31
32- **Engine APIs implemented on OpenHarmony**
33  - SLresult (\*CreateAudioPlayer) (SLEngineItf self, SLObjectItf \* pPlayer, SLDataSource \*pAudioSrc, SLDataSink \*pAudioSnk, SLuint32 numInterfaces, const SLInterfaceID \* pInterfaceIds, const SLboolean \* pInterfaceRequired)
34  - SLresult (\*CreateAudioRecorder) (SLEngineItf self, SLObjectItf \* pRecorder, SLDataSource \*pAudioSrc, SLDataSink \*pAudioSnk, SLuint32 numInterfaces, const SLInterfaceID \* pInterfaceIds, const SLboolean \* pInterfaceRequired)
35  - SLresult (\*CreateOutputMix) (SLEngineItf self, SLObjectItf \* pMix, SLuint32 numInterfaces, const SLInterfaceID \* pInterfaceIds, const SLboolean \* pInterfaceRequired)
36
37- **Object APIs implemented on OpenHarmony**
38  - SLresult (\*Realize) (SLObjectItf self, SLboolean async)
39  - SLresult (\*GetState) (SLObjectItf self, SLuint32 \* pState)
40  - SLresult (\*GetInterface) (SLObjectItf self, const SLInterfaceID iid, void \* pInterface)
41  - void (\*Destroy) (SLObjectItf self)
42
43- **Playback APIs implemented on OpenHarmony**
44  - SLresult (\*SetPlayState) (SLPlayItf self, SLuint32 state)
45  - SLresult (\*GetPlayState) (SLPlayItf self, SLuint32 \*pState)
46
47- **Volume control APIs implemented on OpenHarmony**
48  - SLresult (\*SetVolumeLevel) (SLVolumeItf self, SLmillibel level)
49  - SLresult (\*GetVolumeLevel) (SLVolumeItf self, SLmillibel \*pLevel)
50  - SLresult (\*GetMaxVolumeLevel) (SLVolumeItf  self, SLmillibel \*pMaxLevel)
51
52- **BufferQueue APIs implemented on OpenHarmony**
53
54   The APIs listed below can be used only after <OpenSLES_OpenHarmony.h\> is introduced.
55
56  | API | Description |
57  | -------- | -------- |
58  | SLresult (\*Enqueue) (SLOHBufferQueueItf self, const void \*buffer, SLuint32 size) | Adds a buffer to the corresponding queue.<br>For an audio playback operation, this API adds the buffer with audio data to the **filledBufferQ_** queue. For an audio recording operation, this API adds the idle buffer after recording data storage to the **freeBufferQ_** queue.<br>The **self** parameter indicates the **BufferQueue** object that calls this API.<br>The **buffer** parameter indicates the pointer to the buffer with audio data or the pointer to the idle buffer after the recording data is stored.<br>The **size** parameter indicates the size of the buffer. |
59  | SLresult (\*Clear) (SLOHBufferQueueItf self) | Releases a **BufferQueue** object.<br>The **self** parameter indicates the **BufferQueue** object that calls this API. |
60  | SLresult (\*GetState) (SLOHBufferQueueItf self, SLOHBufferQueueState \*state) | Obtains the state of a **BufferQueue** object.<br>The **self** parameter indicates the **BufferQueue** object that calls this API.<br>The **state** parameter indicates the pointer to the state of the **BufferQueue** object. |
61  | SLresult (\*RegisterCallback) (SLOHBufferQueueItf self, SlOHBufferQueueCallback callback, void\* pContext) | Registers a callback.<br>The **self** parameter indicates the **BufferQueue** object that calls this API.<br>The **callback** parameter indicates the callback to be registered for the audio playback or recording operation.<br>The **pContext** parameter indicates the pointer to the audio file to be played for an audio playback operation or the pointer to the audio file to be recorded for an audio recording operation. |
62  | SLresult (\*GetBuffer) (SLOHBufferQueueItf self, SLuint8\*\* buffer, SLuint32\* size) | Obtains a buffer.<br>For an audio playback operation, this API obtains an idle buffer from the **freeBufferQ_** queue. For an audio recording operation, this API obtains the buffer that carries recording data from the **filledBufferQ_** queue.<br>The **self** parameter indicates the **BufferQueue** object that calls this API.<br>The **buffer** parameter indicates the double pointer to the idle buffer or the buffer carrying recording data.<br>The **size** parameter indicates the size of the buffer. |
63
64## Sample Code
65
66### Linking the Dynamic Library in the CMake Script
67
68``` cmake
69target_link_libraries(sample PUBLIC libOpenSLES.so)
70```
71
72Refer to the sample code below to play an audio file.
73
741. Add the header files.
75
76   ```c++
77   #include "SLES/OpenSLES.h"
78   #include "SLES/OpenSLES_OpenHarmony.h"
79   #include "SLES/OpenSLES_Platform.h"
80   ```
81
822. Use the **slCreateEngine** API to obtain an **engine** instance.
83
84   ```c++
85   SLObjectItf engineObject = nullptr;
86   slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
87   (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
88   ```
89
903. Obtain the **engineEngine** instance of the **SL_IID_ENGINE** API.
91
92   ```c++
93   SLEngineItf engineEngine = nullptr;
94   (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
95   ```
96
974. Configure the player and create an **AudioPlayer** instance.
98
99   ```c++
100   SLDataLocator_BufferQueue slBufferQueue = {
101       SL_DATALOCATOR_BUFFERQUEUE,
102       1
103   };
104
105   // Configure the parameters based on the audio file format.
106   SLDataFormat_PCM pcmFormat = {
107       SL_DATAFORMAT_PCM,
108       2,                           // Number of channels.
109       SL_SAMPLINGRATE_48,          // Sampling rate.
110       SL_PCMSAMPLEFORMAT_FIXED_16, // Audio sample format.
111       16,
112       SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
113       SL_BYTEORDER_LITTLEENDIAN
114   };
115   SLDataSource slSource = {
116      &slBufferQueue,
117      &pcmFormat
118   };
119   SLObjectItf pcmPlayerObject = nullptr;
120   (*engineEngine)->CreateAudioPlayer(engineEngine,
121                                      &pcmPlayerObject,
122                                      &slSource,
123                                      &slSink,
124                                      0,
125                                      nullptr,
126                                      nullptr);
127   (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
128   ```
129
1305. Obtain the **bufferQueueItf** instance of the **SL_IID_OH_BUFFERQUEUE** API.
131
132   ```c++
133   SLOHBufferQueueItf bufferQueueItf;
134   (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
135   ```
136
1376. Open an audio file and register the **BufferQueueCallback** function.
138
139   ```c++
140   static void BufferQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
141   {
142       SLuint8 *buffer = nullptr;
143       SLuint32 pSize;
144       (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &pSize);
145       // Write the audio data to be played to the buffer.
146       (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
147   }
148   void *pContext; // This callback can be used to obtain the custom context information passed in.
149   (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, pContext);
150   ```
151
1527. Obtain the **playItf** instance of the **SL_PLAYSTATE_PLAYING** API and start playing.
153
154   ```c++
155   SLPlayItf playItf = nullptr;
156   (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
157   (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
158   ```
159
1608. Stop playing.
161
162   ```c++
163   (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
164   (*pcmPlayerObject)->Destroy(pcmPlayerObject);
165   (*engineObject)->Destroy(engineObject);
166   ```
167