• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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