1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <OpenSLES.h>
17 #include <OpenSLES_OpenHarmony.h>
18 #include <cstdio>
19 #include <climits>
20 #include <cstdlib>
21 #include <cstring>
22 #include <unistd.h>
23 #include "audio_log.h"
24 #include "pcm2wav.h"
25
26 using namespace std;
27
28 static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size);
29
30 static void PlayerStart (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile);
31
32 static void PlayerStop (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf);
33
34 static void OpenSlTest();
35
36 static void OpenSlTestConcurrent();
37
38 const SLuint32 number = 3;
39 FILE *wavFile_ = nullptr;
40 FILE *wavFile1_ = nullptr;
41 FILE *wavFile2_ = nullptr;
42 wav_hdr wavHeader_;
43 wav_hdr wavHeader1_;
44 wav_hdr wavHeader2_;
45 SLObjectItf engineObject = nullptr;
46 SLObjectItf outputMixObject = nullptr;
47 SLPlayItf playItf;
48 SLPlayItf playItf1;
49 SLPlayItf playItf2;
50 SLVolumeItf volumeItf1;
51 SLVolumeItf volumeItf2;
52 SLOHBufferQueueItf bufferQueueItf;
53 SLOHBufferQueueItf bufferQueueItf1;
54 SLOHBufferQueueItf bufferQueueItf2;
55 SLObjectItf pcmPlayerObject = nullptr;
56 SLObjectItf pcmPlayerObject1 = nullptr;
57 SLObjectItf pcmPlayerObject2 = nullptr;
58
main(int argc,char * argv[])59 int main(int argc, char *argv[])
60 {
61 if (argc == 4) {
62 size_t headerSize = sizeof(wav_hdr);
63 char *inputPath = argv[1];
64 char path[PATH_MAX + 1] = {0x00};
65 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
66 AUDIO_ERR_LOG("Invalid path");
67 return -1;
68 }
69 wavFile1_ = fopen(path, "rb");
70 if (wavFile1_ == nullptr) {
71 AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
72 return -1;
73 }
74 fread(&wavHeader1_, 1, headerSize, wavFile1_);
75
76 headerSize = sizeof(wav_hdr);
77 inputPath = argv[2];
78 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
79 AUDIO_ERR_LOG("Invalid path");
80 return -1;
81 }
82 wavFile2_ = fopen(path, "rb");
83 if (wavFile2_ == nullptr) {
84 AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
85 return -1;
86 }
87 fread(&wavHeader2_, 1, headerSize, wavFile2_);
88
89 OpenSlTestConcurrent();
90
91 while (!feof(wavFile1_) || !feof(wavFile2_)) {
92 sleep(1);
93 }
94
95 PlayerStop(playItf1, bufferQueueItf1);
96 PlayerStop(playItf2, bufferQueueItf2);
97 (*pcmPlayerObject1)->Destroy(pcmPlayerObject1);
98 (*pcmPlayerObject2)->Destroy(pcmPlayerObject2);
99 (*engineObject)->Destroy(engineObject);
100 (*outputMixObject)->Destroy(outputMixObject);
101 return 0;
102 } else {
103 if (argc < 2) {
104 return -1;
105 }
106 size_t headerSize = sizeof(wav_hdr);
107 char *inputPath = argv[1];
108 char path[PATH_MAX + 1] = {0x00};
109 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
110 AUDIO_ERR_LOG("Invalid path");
111 return -1;
112 }
113 wavFile_ = fopen(path, "rb");
114 if (wavFile_ == nullptr) {
115 AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
116 return -1;
117 }
118 fread(&wavHeader_, 1, headerSize, wavFile_);
119
120 OpenSlTest();
121
122 while (!feof(wavFile_)) {
123 sleep(1);
124 }
125 PlayerStop(playItf, bufferQueueItf);
126 (*pcmPlayerObject)->Destroy(pcmPlayerObject);
127
128 if (argc < 3) {
129 return 0;
130 }
131 char *inputPath2 = argv[2];
132 char path2[PATH_MAX + 1] = {0x00};
133 if ((strlen(inputPath2) > PATH_MAX) || (realpath(inputPath2, path2) == nullptr)) {
134 AUDIO_ERR_LOG("Invalid path");
135 return -1;
136 }
137 wavFile_ = fopen(path2, "rb");
138 if (wavFile_ == nullptr) {
139 AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
140 return -1;
141 }
142 fread(&wavHeader_, 1, headerSize, wavFile_);
143
144 OpenSlTest();
145
146 while (!feof(wavFile_)) {
147 sleep(1);
148 }
149 PlayerStop(playItf, bufferQueueItf);
150 (*pcmPlayerObject)->Destroy(pcmPlayerObject);
151 return 0;
152 }
153 }
154
OpenSlTest()155 static void OpenSlTest()
156 {
157 AUDIO_INFO_LOG("OpenSlTest");
158 engineObject = nullptr;
159 SLEngineItf engineEngine = nullptr;
160 slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
161 (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
162 (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
163
164 outputMixObject = nullptr;
165 (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
166 (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
167
168 SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
169 SLDataSink slSink = {&slOutputMix, nullptr};
170 SLDataLocator_BufferQueue slBufferQueue = {
171 SL_DATALOCATOR_BUFFERQUEUE,
172 0
173 };
174 SLDataFormat_PCM pcmFormat = {
175 SL_DATAFORMAT_PCM,
176 wavHeader_.NumOfChan,
177 wavHeader_.SamplesPerSec * 1000,
178 wavHeader_.bitsPerSample,
179 0,
180 0,
181 0
182 };
183 SLDataSource slSource = {&slBufferQueue, &pcmFormat};
184 (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, &slSink, number, nullptr, nullptr);
185 (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
186
187 (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
188 SLVolumeItf volumeItf;
189 (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_VOLUME, &volumeItf);
190 SLmillibel pLevel = 0;
191 (*volumeItf)->GetVolumeLevel(volumeItf, &pLevel);
192 (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
193 (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BuqqerQueueCallback, wavFile_);
194
195 PlayerStart(playItf, bufferQueueItf, wavFile_);
196 }
197
OpenSlTestConcurrent()198 static void OpenSlTestConcurrent()
199 {
200 AUDIO_INFO_LOG("OpenSlTestConcurrent");
201 engineObject = nullptr;
202 SLEngineItf engineEngine = nullptr;
203
204 slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
205 (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
206 (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
207
208 outputMixObject = nullptr;
209 (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
210 (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
211
212 SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
213 SLDataSink slSink = {&slOutputMix, nullptr};
214 SLDataLocator_BufferQueue slBufferQueue = {
215 SL_DATALOCATOR_BUFFERQUEUE,
216 0
217 };
218 SLDataFormat_PCM pcmFormat1 = {
219 SL_DATAFORMAT_PCM,
220 wavHeader1_.NumOfChan,
221 wavHeader1_.SamplesPerSec * 1000,
222 wavHeader1_.bitsPerSample,
223 0,
224 0,
225 0
226 };
227 SLDataFormat_PCM pcmFormat2 = {
228 SL_DATAFORMAT_PCM,
229 wavHeader2_.NumOfChan,
230 wavHeader2_.SamplesPerSec * 1000,
231 wavHeader2_.bitsPerSample,
232 0,
233 0,
234 0
235 };
236 SLDataSource slSource1 = {&slBufferQueue, &pcmFormat1};
237 SLDataSource slSource2 = {&slBufferQueue, &pcmFormat2};
238
239 (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject1, &slSource1, &slSink, number, nullptr, nullptr);
240 (*pcmPlayerObject1)->Realize(pcmPlayerObject1, SL_BOOLEAN_FALSE);
241
242 (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject2, &slSource2, &slSink, number, nullptr, nullptr);
243 (*pcmPlayerObject2)->Realize(pcmPlayerObject2, SL_BOOLEAN_FALSE);
244
245 (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_PLAY, &playItf1);
246 (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_PLAY, &playItf2);
247 (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_VOLUME, &volumeItf1);
248
249 SLmillibel level1 = 0;
250 (*volumeItf1)->GetMaxVolumeLevel(volumeItf1, &level1);
251 SLmillibel temp = 2;
252 level1 = (SLmillibel) (level1 / temp);
253 (*volumeItf1)->SetVolumeLevel(volumeItf1, level1);
254 (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_VOLUME, &volumeItf2);
255 SLmillibel level2 = 0;
256 (*volumeItf2)->GetMaxVolumeLevel(volumeItf2, &level2);
257 temp = 15;
258 level2 = (SLmillibel) (level2 / temp);
259 (*volumeItf2)->SetVolumeLevel(volumeItf2, level2);
260
261 (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf1);
262 (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf2);
263 (*bufferQueueItf1)->RegisterCallback(bufferQueueItf1, BuqqerQueueCallback, wavFile1_);
264 (*bufferQueueItf2)->RegisterCallback(bufferQueueItf2, BuqqerQueueCallback, wavFile2_);
265 PlayerStart(playItf1, bufferQueueItf1, wavFile1_);
266 PlayerStart(playItf2, bufferQueueItf2, wavFile2_);
267 }
268
BuqqerQueueCallback(SLOHBufferQueueItf bufferQueueItf,void * pContext,SLuint32 size)269 static void BuqqerQueueCallback (SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
270 {
271 FILE *wavFile = (FILE *)pContext;
272 if (!feof(wavFile)) {
273 SLuint8 *buffer = nullptr;
274 SLuint32 pSize = 0;
275 (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
276 if (buffer != nullptr) {
277 fread(buffer, 1, size, wavFile);
278 (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
279 } else {
280 AUDIO_ERR_LOG("BuqqerQueueCallback, get buffer is null.");
281 }
282 }
283 return;
284 }
285
PlayerStart(SLPlayItf playItf,SLOHBufferQueueItf bufferQueueItf,FILE * wavFile)286 static void PlayerStart (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile)
287 {
288 AUDIO_INFO_LOG("PlayerStart");
289 (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
290 return;
291 }
292
PlayerStop(SLPlayItf playItf,SLOHBufferQueueItf bufferQueueItf)293 static void PlayerStop (SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf)
294 {
295 AUDIO_INFO_LOG("PlayerStop");
296 (*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
297 return;
298 }
299