• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 
19 #include <cstdio>
20 #include <climits>
21 #include <cstdlib>
22 #include <cstring>
23 #include <unistd.h>
24 
25 #include "audio_log.h"
26 #include "pcm2wav.h"
27 
28 using namespace std;
29 
30 static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size);
31 
32 static void PlayerStart(SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile);
33 
34 static void PlayerStop(SLPlayItf playItf, SLOHBufferQueueItf bufferQueueItf);
35 
36 static void OpenSlTest();
37 
38 static void OpenSlTestConcurrent();
39 
40 const SLuint32 number = 3;
41 FILE *wavFile_ = nullptr;
42 FILE *wavFile1_ = nullptr;
43 FILE *wavFile2_ = nullptr;
44 wav_hdr wavHeader_;
45 wav_hdr wavHeader1_;
46 wav_hdr wavHeader2_;
47 SLObjectItf engineObject = nullptr;
48 SLObjectItf outputMixObject = nullptr;
49 SLPlayItf playItf;
50 SLPlayItf playItf1;
51 SLPlayItf playItf2;
52 SLVolumeItf volumeItf1;
53 SLVolumeItf volumeItf2;
54 SLOHBufferQueueItf bufferQueueItf;
55 SLOHBufferQueueItf bufferQueueItf1;
56 SLOHBufferQueueItf bufferQueueItf2;
57 SLObjectItf pcmPlayerObject = nullptr;
58 SLObjectItf pcmPlayerObject1 = nullptr;
59 SLObjectItf pcmPlayerObject2 = nullptr;
60 
main(int argc,char * argv[])61 int main(int argc, char *argv[])
62 {
63     if (argc == 4) {
64         size_t headerSize = sizeof(wav_hdr);
65         char *inputPath = argv[1];
66         char path[PATH_MAX + 1] = {0x00};
67         if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
68             AUDIO_ERR_LOG("Invalid path");
69             return -1;
70         }
71         wavFile1_ = fopen(path, "rb");
72         if (wavFile1_ == nullptr) {
73             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
74             return -1;
75         }
76         fread(&wavHeader1_, 1, headerSize, wavFile1_);
77 
78         headerSize = sizeof(wav_hdr);
79         inputPath = argv[2];
80         if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
81             AUDIO_ERR_LOG("Invalid path");
82             return -1;
83         }
84         wavFile2_ = fopen(path, "rb");
85         if (wavFile2_ == nullptr) {
86             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
87             return -1;
88         }
89         fread(&wavHeader2_, 1, headerSize, wavFile2_);
90 
91         OpenSlTestConcurrent();
92 
93         while (!feof(wavFile1_) || !feof(wavFile2_)) {
94             sleep(1);
95         }
96 
97         PlayerStop(playItf1, bufferQueueItf1);
98         PlayerStop(playItf2, bufferQueueItf2);
99         (*pcmPlayerObject1)->Destroy(pcmPlayerObject1);
100         (*pcmPlayerObject2)->Destroy(pcmPlayerObject2);
101         (*engineObject)->Destroy(engineObject);
102         (*outputMixObject)->Destroy(outputMixObject);
103         return 0;
104     } else {
105         if (argc < 2) {
106             return -1;
107         }
108         size_t headerSize = sizeof(wav_hdr);
109         char *inputPath = argv[1];
110         char path[PATH_MAX + 1] = {0x00};
111         if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
112             AUDIO_ERR_LOG("Invalid path");
113             return -1;
114         }
115         wavFile_ = fopen(path, "rb");
116         if (wavFile_ == nullptr) {
117             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
118             return -1;
119         }
120         fread(&wavHeader_, 1, headerSize, wavFile_);
121 
122         OpenSlTest();
123 
124         while (!feof(wavFile_)) {
125             sleep(1);
126         }
127         PlayerStop(playItf, bufferQueueItf);
128         (*pcmPlayerObject)->Destroy(pcmPlayerObject);
129 
130         if (argc < 3) {
131             return 0;
132         }
133         char *inputPath2 = argv[2];
134         char path2[PATH_MAX + 1] = {0x00};
135         if ((strlen(inputPath2) > PATH_MAX) || (realpath(inputPath2, path2) == nullptr)) {
136             AUDIO_ERR_LOG("Invalid path");
137             return -1;
138         }
139         wavFile_ = fopen(path2, "rb");
140         if (wavFile_ == nullptr) {
141             AUDIO_INFO_LOG("AudioRendererTest: Unable to open wave file");
142             return -1;
143         }
144         fread(&wavHeader_, 1, headerSize, wavFile_);
145 
146         OpenSlTest();
147 
148         while (!feof(wavFile_)) {
149             sleep(1);
150         }
151         PlayerStop(playItf, bufferQueueItf);
152         (*pcmPlayerObject)->Destroy(pcmPlayerObject);
153         return 0;
154     }
155 }
156 
OpenSlTest()157 static void OpenSlTest()
158 {
159     AUDIO_INFO_LOG("OpenSlTest");
160     engineObject = nullptr;
161     SLEngineItf engineEngine = nullptr;
162     slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
163     (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
164     (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
165 
166     outputMixObject = nullptr;
167     (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
168     (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
169 
170     SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
171     SLDataSink slSink = {&slOutputMix, nullptr};
172     SLDataLocator_BufferQueue slBufferQueue = {
173         SL_DATALOCATOR_BUFFERQUEUE,
174         0
175     };
176     SLDataFormat_PCM pcmFormat = {
177         SL_DATAFORMAT_PCM,
178         wavHeader_.NumOfChan,
179         wavHeader_.SamplesPerSec * 1000,
180         wavHeader_.bitsPerSample,
181         0,
182         0,
183         0
184     };
185     SLDataSource slSource = {&slBufferQueue, &pcmFormat};
186     (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject, &slSource, &slSink, number, nullptr, nullptr);
187     (*pcmPlayerObject)->Realize(pcmPlayerObject, SL_BOOLEAN_FALSE);
188 
189     (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_PLAY, &playItf);
190     SLVolumeItf volumeItf;
191     (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_VOLUME, &volumeItf);
192     SLmillibel pLevel = 0;
193     (*volumeItf)->GetVolumeLevel(volumeItf, &pLevel);
194     (*pcmPlayerObject)->GetInterface(pcmPlayerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
195     (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, wavFile_);
196 
197     PlayerStart(playItf, bufferQueueItf, wavFile_);
198 }
199 
OpenSlTestConcurrent()200 static void OpenSlTestConcurrent()
201 {
202     AUDIO_INFO_LOG("OpenSlTestConcurrent");
203     engineObject = nullptr;
204     SLEngineItf engineEngine = nullptr;
205 
206     slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
207     (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
208     (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
209 
210     outputMixObject = nullptr;
211     (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, nullptr, nullptr);
212     (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
213 
214     SLDataLocator_OutputMix slOutputMix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
215     SLDataSink slSink = {&slOutputMix, nullptr};
216     SLDataLocator_BufferQueue slBufferQueue = {
217         SL_DATALOCATOR_BUFFERQUEUE,
218         0
219     };
220     SLDataFormat_PCM pcmFormat1 = {
221         SL_DATAFORMAT_PCM,
222         wavHeader1_.NumOfChan,
223         wavHeader1_.SamplesPerSec * 1000,
224         wavHeader1_.bitsPerSample,
225         0,
226         0,
227         0
228     };
229     SLDataFormat_PCM pcmFormat2 = {
230         SL_DATAFORMAT_PCM,
231         wavHeader2_.NumOfChan,
232         wavHeader2_.SamplesPerSec * 1000,
233         wavHeader2_.bitsPerSample,
234         0,
235         0,
236         0
237     };
238     SLDataSource slSource1 = {&slBufferQueue, &pcmFormat1};
239     SLDataSource slSource2 = {&slBufferQueue, &pcmFormat2};
240 
241     (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject1, &slSource1, &slSink, number, nullptr, nullptr);
242     (*pcmPlayerObject1)->Realize(pcmPlayerObject1, SL_BOOLEAN_FALSE);
243 
244     (*engineEngine)->CreateAudioPlayer(engineEngine, &pcmPlayerObject2, &slSource2, &slSink, number, nullptr, nullptr);
245     (*pcmPlayerObject2)->Realize(pcmPlayerObject2, SL_BOOLEAN_FALSE);
246 
247     (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_PLAY, &playItf1);
248     (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_PLAY, &playItf2);
249     (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_VOLUME, &volumeItf1);
250 
251     SLmillibel level1 = 0;
252     (*volumeItf1)->GetMaxVolumeLevel(volumeItf1, &level1);
253     SLmillibel temp = 2;
254     level1 = (SLmillibel) (level1 / temp);
255     (*volumeItf1)->SetVolumeLevel(volumeItf1, level1);
256     (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_VOLUME, &volumeItf2);
257     SLmillibel level2 = 0;
258     (*volumeItf2)->GetMaxVolumeLevel(volumeItf2, &level2);
259     temp = 15;
260     level2 = (SLmillibel) (level2 / temp);
261     (*volumeItf2)->SetVolumeLevel(volumeItf2, level2);
262 
263     (*pcmPlayerObject1)->GetInterface(pcmPlayerObject1, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf1);
264     (*pcmPlayerObject2)->GetInterface(pcmPlayerObject2, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf2);
265     (*bufferQueueItf1)->RegisterCallback(bufferQueueItf1, BufferQueueCallback, wavFile1_);
266     (*bufferQueueItf2)->RegisterCallback(bufferQueueItf2, BufferQueueCallback, wavFile2_);
267     PlayerStart(playItf1, bufferQueueItf1, wavFile1_);
268     PlayerStart(playItf2, bufferQueueItf2, wavFile2_);
269 }
270 
BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf,void * pContext,SLuint32 size)271 static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
272 {
273     FILE *wavFile = (FILE *)pContext;
274     if (!feof(wavFile)) {
275         SLuint8 *buffer = nullptr;
276         SLuint32 bufferSize = 0;
277         (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, &bufferSize);
278         if (buffer != nullptr) {
279             fread(buffer, 1, size, wavFile);
280             (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
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