1 /*
2 * Copyright (c) 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 <cinttypes>
17 #include <condition_variable>
18 #include <cstdint>
19 #include <ctime>
20 #include <ostream>
21 #include <sstream>
22 #include <iostream>
23 #include <thread>
24 #include <mutex>
25 #include <map>
26 #include <securec.h>
27
28 #include <sys/time.h>
29
30 #include "audio_log.h"
31 #include "audio_errors.h"
32 #include "audio_utils.h"
33 #include "audio_process_in_client.h"
34 #include "parameter.h"
35 #include "pcm2wav.h"
36
37 using namespace std;
38 namespace OHOS {
39 namespace AudioStandard {
40 namespace {
41 static constexpr long WAV_HEADER_SIZE = 42;
42 static constexpr int64_t SECOND_TO_NANOSECOND = 1000000000;
43 constexpr int32_t SAMPLE_FORMAT_U8 = 8;
44 constexpr int32_t SAMPLE_FORMAT_S16LE = 16;
45 constexpr int32_t SAMPLE_FORMAT_S24LE = 24;
46 constexpr int32_t SAMPLE_FORMAT_S32LE = 32;
47 enum OperationCode : int32_t {
48 INVALID_OPERATION = -1,
49 INIT_LOCAL_SPK_PROCESS = 0,
50 INIT_REMOTE_SPK_PROCESS = 1,
51 START_SPK_PROCESS = 2,
52 PAUSE_SPK_PROCESS = 3,
53 RESUME_SPK_PROCESS = 4,
54 STOP_SPK_PROCESS = 5,
55 CHANGE_SPK_PROCESS_VOL = 6,
56 RELEASE_SPK_PROCESS = 7,
57
58 START_LOOP_TEST = 10,
59 END_LOOP_TEST = 11,
60
61 START_SIGNAL_TEST = 12,
62 END_SIGNAL_TEST = 13,
63
64 INIT_LOCAL_MIC_PROCESS = 20,
65 INIT_REMOTE_MIC_PROCESS = 21,
66 START_MIC_PROCESS = 22,
67 PAUSE_MIC_PROCESS = 23,
68 RESUME_MIC_PROCESS = 24,
69 STOP_MIC_PROCESS = 25,
70 CHANGE_MIC_PROCESS_VOL = 26,
71 RELEASE_MIC_PROCESS = 27,
72
73 EXIT_INTERACTIVE_TEST = 40,
74 };
75
76 enum AudioProcessTestType : int32_t {
77 INVALID_PROC_TEST = 0,
78 INTERACTIVE_RUN_SPK_TEST = 1,
79 AUTO_RUN_SPK_TEST = 2,
80 INTERACTIVE_RUN_MIC_TEST = 3,
81 AUTO_RUN_MIC_TEST = 4,
82 INTERACTIVE_RUN_LOOP = 5,
83 RENDER_SIGNAL_TEST = 6,
84 EXIT_PROC_TEST = 7,
85 };
86 enum TestMode : int32_t {
87 RENDER_FILE = 0,
88 RENDER_MIC_LOOP_DATA = 1,
89 RENDER_SIGNAL_DATA = 2,
90 };
91 static constexpr size_t CACHE_BUFFER_SIZE = 960;
92 TestMode g_testMode = RENDER_FILE;
93 bool g_renderSignal = false;
94 int64_t g_stampTime = 0;
95 }
96
97 class AudioProcessTest;
98 shared_ptr<AudioProcessTest> g_audioProcessTest = nullptr;
99 std::string g_spkfilePath = "";
100 const std::string MIC_FILE_PATH = "/data/data/mic.pcm";
101 FILE *g_spkWavFile = nullptr;
102 FILE *g_micPcmFile = nullptr;
103 mutex g_autoRunMutex;
104 condition_variable g_autoRunCV;
105
106 unique_ptr<uint8_t[]> g_byteBuffer = nullptr;
107 BufferDesc g_cacheBuffer = {nullptr, 0, 0};
108
109 string ConfigSpkTest(bool isRemote);
110 string CallStartSpk();
111 string CallPauseSpk();
112 string CallResumeSpk();
113 string CallStopSpk();
114 string SetSpkVolume();
115 string CallReleaseSpk();
116
117 string StartSignalTest();
118 string EndSignalTest();
119
120 string ConfigMicTest(bool isRemote);
121 string CallStartMic();
122 string CallPauseMic();
123 string CallResumeMic();
124 string CallStopMic();
125 string SetMicVolume();
126 string CallReleaseMic();
127 using CallTestOperationFunc = string (*)();
128
129 std::map<int32_t, std::string> g_audioProcessTestType = {
130 {INTERACTIVE_RUN_SPK_TEST, "Interactive run spk process test"},
131 {AUTO_RUN_SPK_TEST, "Auto run spk process test"},
132 {INTERACTIVE_RUN_MIC_TEST, "Interactive run mic process test"},
133 {AUTO_RUN_MIC_TEST, "Auto run mic process test"},
134 {INTERACTIVE_RUN_LOOP, "Roundtrip latency test"},
135 {RENDER_SIGNAL_TEST, "Render signal latency test"},
136 {EXIT_PROC_TEST, "Exit audio process test"},
137 };
138
139 std::map<int32_t, std::string> g_interactiveOptStrMap = {
140 {INIT_LOCAL_SPK_PROCESS, "call local spk init process"},
141 {INIT_REMOTE_SPK_PROCESS, "call remote spk init process"},
142 {START_SPK_PROCESS, "call start spk process"},
143 {PAUSE_SPK_PROCESS, "call pause spk process"},
144 {RESUME_SPK_PROCESS, "call resume spk process"},
145 {STOP_SPK_PROCESS, "call stop spk process"},
146 {CHANGE_SPK_PROCESS_VOL, "change spk process volume"},
147 {RELEASE_SPK_PROCESS, "release spk process"},
148
149 {START_LOOP_TEST, "start loop"},
150 {END_LOOP_TEST, "end loop"},
151
152 {START_SIGNAL_TEST, "start signal test"},
153 {END_SIGNAL_TEST, "end signal test"},
154
155 {INIT_LOCAL_MIC_PROCESS, "call local mic init process"},
156 {INIT_REMOTE_MIC_PROCESS, "call remote mic init process"},
157 {START_MIC_PROCESS, "call start mic process"},
158 {PAUSE_MIC_PROCESS, "call pause mic process"},
159 {RESUME_MIC_PROCESS, "call resume mic process"},
160 {STOP_MIC_PROCESS, "call stop mic process"},
161 {CHANGE_MIC_PROCESS_VOL, "change mic process volume"},
162 {RELEASE_MIC_PROCESS, "release mic process"},
163
164 {EXIT_INTERACTIVE_TEST, "exit interactive run test"},
165 };
166
167 std::map<int32_t, CallTestOperationFunc> g_interactiveOptFuncMap = {
168 {START_SPK_PROCESS, CallStartSpk},
169 {PAUSE_SPK_PROCESS, CallPauseSpk},
170 {RESUME_SPK_PROCESS, CallResumeSpk},
171 {STOP_SPK_PROCESS, CallStopSpk},
172 {CHANGE_SPK_PROCESS_VOL, SetSpkVolume},
173 {RELEASE_SPK_PROCESS, CallReleaseSpk},
174
175 {START_SIGNAL_TEST, StartSignalTest},
176 {END_SIGNAL_TEST, EndSignalTest},
177
178 {START_MIC_PROCESS, CallStartMic},
179 {PAUSE_MIC_PROCESS, CallPauseMic},
180 {RESUME_MIC_PROCESS, CallResumeMic},
181 {STOP_MIC_PROCESS, CallStopMic},
182 {CHANGE_MIC_PROCESS_VOL, SetMicVolume},
183 {RELEASE_MIC_PROCESS, CallReleaseMic}
184 };
185
186 class AudioProcessTestCallback : public AudioDataCallback {
187 public:
AudioProcessTestCallback(const std::shared_ptr<AudioProcessInClient> & procClient,int32_t spkLoopCnt,AudioMode clientMode)188 AudioProcessTestCallback(const std::shared_ptr<AudioProcessInClient> &procClient,
189 int32_t spkLoopCnt, AudioMode clientMode)
190 : procClient_(procClient), loopCount_(spkLoopCnt), clientMode_(clientMode) {};
191 ~AudioProcessTestCallback() = default;
192
193 void OnHandleData(size_t length) override;
InitSignalBuffer(const BufferDesc & signalSoundBuffer)194 void InitSignalBuffer(const BufferDesc &signalSoundBuffer)
195 {
196 int ret = memset_s(signalSoundBuffer.buffer, signalSoundBuffer.bufLength, 0, signalSoundBuffer.bufLength);
197 if (ret != EOK) {
198 return;
199 }
200 const int channels = 2; // 2 channels
201 const int samplePerChannel = 96 / channels; // 96 for 1ms
202 int16_t *signalData = static_cast<int16_t *>(static_cast<void *>(signalSoundBuffer.buffer));
203 int16_t bound = 10;
204 for (int idx = 0; idx < samplePerChannel; idx++) {
205 signalData[channels * idx] = bound + static_cast<int16_t>(sinf(2.0f * static_cast<float>(M_PI) * idx /
206 samplePerChannel) * (SHRT_MAX - bound));
207 for (int c = 1; c < channels; c++) {
208 signalData[channels * idx + c] = signalData[channels * idx];
209 }
210 }
211 };
212
213 private:
214 int32_t CaptureToFile(const BufferDesc &bufDesc);
215 int32_t RenderFromFile(const BufferDesc &bufDesc);
216
HandleWriteLoopData(const BufferDesc & bufDesc)217 void HandleWriteLoopData(const BufferDesc &bufDesc)
218 {
219 loopCount_++;
220 int32_t periodCount = loopCount_ % 400; // 400 * 0.005 = 2s
221
222 if (periodCount == 0) {
223 InitSignalBuffer(bufDesc); // set signal data
224 int64_t temp = ClockTime::GetCurNano() - g_stampTime;
225 std::cout << "client read-write latency:" << (temp / AUDIO_MS_PER_SECOND) << " us" << std::endl;
226 return;
227 }
228
229 int32_t keepQuiteHold = 50;
230 if (periodCount > keepQuiteHold) {
231 return;
232 }
233
234 // copy mic data in the cache buffer
235 int ret = memcpy_s(static_cast<void *>(bufDesc.buffer), bufDesc.bufLength,
236 static_cast<void *>(g_cacheBuffer.buffer), g_cacheBuffer.bufLength);
237 if (ret != EOK) {
238 AUDIO_WARNING_LOG("memcpy_s failed.");
239 }
240 };
241
GetCurTime()242 void GetCurTime()
243 {
244 struct timeval tv;
245 struct timezone tz;
246 struct tm *t;
247
248 gettimeofday(&tv, &tz);
249 t = localtime(&tv.tv_sec);
250 AUDIO_INFO_LOG("ClockTime::GetCurNano is %{public}" PRId64" Low-latency write first data start at"
251 ":%{public}04d-%{public}02d-%{public}02d %{public}02d:%{public}02d:%{public}02d.%{public}03" PRId64" ",
252 ClockTime::GetCurNano(), 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
253 static_cast<int64_t>(tv.tv_usec / AUDIO_MS_PER_SECOND));
254 }
255
HandleWriteSignalData(const BufferDesc & bufDesc)256 void HandleWriteSignalData(const BufferDesc &bufDesc)
257 {
258 if (g_renderSignal) {
259 InitSignalBuffer(bufDesc);
260 GetCurTime();
261 g_renderSignal = false;
262 }
263 }
264
265 private:
266 std::shared_ptr<AudioProcessInClient> procClient_ = nullptr;
267 int32_t loopCount_ = -1; // for loop
268 AudioMode clientMode_ = AUDIO_MODE_PLAYBACK;
269 bool renderFinish_ = false;
270 };
271
272 class AudioProcessTest {
273 public:
274 AudioProcessTest() = default;
275 ~AudioProcessTest() = default;
276
277 int32_t InitSpk(int32_t loopCount, bool isRemote);
278 bool IsInited();
279 bool StartSpk();
280 bool PauseSpk();
281 bool ResumeSpk();
282 bool SetSpkVolume(int32_t vol);
283 bool StopSpk();
284 bool ReleaseSpk();
285
286 int32_t InitMic(bool isRemote);
287 bool StartMic();
288 bool PauseMic();
289 bool ResumeMic();
290 bool SetMicVolume(int32_t vol);
291 bool StopMic();
292 bool ReleaseMic();
293
294 private:
295 std::shared_ptr<AudioProcessInClient> spkProcessClient_ = nullptr;
296 std::shared_ptr<AudioProcessInClient> micProcessClient_ = nullptr;
297 std::shared_ptr<AudioProcessTestCallback> spkProcClientCb_ = nullptr;
298 std::shared_ptr<AudioProcessTestCallback> micProcClientCb_ = nullptr;
299 int32_t loopCount_ = -1; // for loop
300 bool isInited_ = false;
301 };
302
CaptureToFile(const BufferDesc & bufDesc)303 int32_t AudioProcessTestCallback::CaptureToFile(const BufferDesc &bufDesc)
304 {
305 CHECK_AND_RETURN_RET_LOG(g_micPcmFile != nullptr, ERR_INVALID_HANDLE,
306 "%{public}s g_micPcmFile is null.", __func__);
307
308 size_t cnt = fwrite(bufDesc.buffer, 1, bufDesc.bufLength, g_micPcmFile);
309 CHECK_AND_RETURN_RET_LOG(cnt == bufDesc.bufLength, ERR_WRITE_FAILED,
310 "%{public}s fwrite fail, cnt %{public}zu, bufLength %{public}zu.", __func__, cnt, bufDesc.bufLength);
311 int ret = memcpy_s(static_cast<void *>(g_cacheBuffer.buffer), bufDesc.bufLength,
312 static_cast<void *>(bufDesc.buffer), bufDesc.bufLength);
313 if (ret != EOK) {
314 AUDIO_WARNING_LOG("memcpy_s failed.");
315 }
316 g_stampTime = ClockTime::GetCurNano();
317 return SUCCESS;
318 }
319
RenderFromFile(const BufferDesc & bufDesc)320 int32_t AudioProcessTestCallback::RenderFromFile(const BufferDesc &bufDesc)
321 {
322 CHECK_AND_RETURN_RET_LOG(g_spkWavFile != nullptr, ERR_INVALID_HANDLE,
323 "%{public}s g_spkWavFile is null.", __func__);
324
325 if (feof(g_spkWavFile)) {
326 if (loopCount_ < 0) {
327 fseek(g_spkWavFile, WAV_HEADER_SIZE, SEEK_SET); // infinite loop
328 } else if (loopCount_ == 0) {
329 renderFinish_ = true;
330 g_autoRunCV.notify_all();
331 } else {
332 loopCount_--;
333 fseek(g_spkWavFile, WAV_HEADER_SIZE, SEEK_SET);
334 }
335 }
336 if (renderFinish_) {
337 AUDIO_INFO_LOG("%{public}s render finish.", __func__);
338 return SUCCESS;
339 }
340 fread(bufDesc.buffer, 1, bufDesc.bufLength, g_spkWavFile);
341 return SUCCESS;
342 }
343
OnHandleData(size_t length)344 void AudioProcessTestCallback::OnHandleData(size_t length)
345 {
346 Trace callBack("client_n");
347 CHECK_AND_RETURN_LOG(procClient_ != nullptr, "%{public}s procClient is null.", __func__);
348
349 BufferDesc bufDesc = {nullptr, 0, 0};
350 int32_t ret = procClient_->GetBufferDesc(bufDesc);
351 if (ret != SUCCESS || bufDesc.buffer == nullptr || bufDesc.bufLength ==0) {
352 cout << "GetBufferDesc failed." << endl;
353 return;
354 }
355
356 if (clientMode_ == AUDIO_MODE_RECORD) {
357 ret = CaptureToFile(bufDesc);
358 CHECK_AND_RETURN_LOG(ret == SUCCESS, "%{public}s capture to file fail, ret %{public}d.",
359 __func__, ret);
360 } else {
361 if (g_testMode == TestMode::RENDER_FILE) {
362 ret = RenderFromFile(bufDesc);
363 CHECK_AND_RETURN_LOG(ret == SUCCESS, "%{public}s render from file fail, ret %{public}d.", __func__, ret);
364 } else if (g_testMode == TestMode::RENDER_MIC_LOOP_DATA) {
365 HandleWriteLoopData(bufDesc);
366 } else if (g_testMode == TestMode::RENDER_SIGNAL_DATA) {
367 HandleWriteSignalData(bufDesc);
368 }
369 }
370 ret = procClient_->Enqueue(bufDesc);
371 CHECK_AND_RETURN_LOG(ret == SUCCESS, "%{public}s enqueue buf fail, clientMode %{public}d, ret %{public}d.",
372 __func__, clientMode_, ret);
373
374 callBack.End();
375 }
376
GetSampleFormat(int32_t wavSampleFormat)377 inline AudioSampleFormat GetSampleFormat(int32_t wavSampleFormat)
378 {
379 switch (wavSampleFormat) {
380 case SAMPLE_FORMAT_U8:
381 return AudioSampleFormat::SAMPLE_U8;
382 case SAMPLE_FORMAT_S16LE:
383 return AudioSampleFormat::SAMPLE_S16LE;
384 case SAMPLE_FORMAT_S24LE:
385 return AudioSampleFormat::SAMPLE_S24LE;
386 case SAMPLE_FORMAT_S32LE:
387 return AudioSampleFormat::SAMPLE_S32LE;
388 default:
389 return AudioSampleFormat::INVALID_WIDTH;
390 }
391 }
392
InitSpk(int32_t loopCount,bool isRemote)393 int32_t AudioProcessTest::InitSpk(int32_t loopCount, bool isRemote)
394 {
395 if (loopCount < 0) {
396 loopCount_ = 1; // loop once
397 } else if (loopCount == 0) {
398 loopCount_ = -1; // infinite loop
399 } else {
400 loopCount_ = loopCount;
401 }
402
403 AudioProcessConfig config;
404 config.appInfo.appPid = getpid();
405 config.appInfo.appUid = getuid();
406
407 config.audioMode = AUDIO_MODE_PLAYBACK;
408
409 config.rendererInfo.contentType = CONTENT_TYPE_MUSIC;
410 config.rendererInfo.streamUsage = STREAM_USAGE_MEDIA;
411 config.rendererInfo.rendererFlags = STREAM_FLAG_FAST;
412
413 config.streamInfo.channels = STEREO;
414 config.streamInfo.encoding = ENCODING_PCM;
415 config.streamInfo.format = SAMPLE_S16LE;
416 config.streamInfo.samplingRate = SAMPLE_RATE_48000;
417
418 config.streamType = STREAM_MUSIC;
419
420 if (g_testMode == TestMode::RENDER_FILE) {
421 wav_hdr wavHeader;
422 size_t headerSize = sizeof(wav_hdr);
423 size_t bytesRead = fread(&wavHeader, 1, headerSize, g_spkWavFile);
424 if (bytesRead != headerSize) {
425 AUDIO_ERR_LOG("RenderCallbackTest: File header reading error");
426 }
427
428 config.streamInfo.samplingRate = static_cast<AudioSamplingRate>(wavHeader.SamplesPerSec);
429 config.streamInfo.format = GetSampleFormat(wavHeader.bitsPerSample);
430 config.streamInfo.channels = static_cast<AudioChannel>(wavHeader.NumOfChan);
431
432 cout << endl << "samplingRate:" << config.streamInfo.samplingRate << endl;
433 cout << "format:" << config.streamInfo.format << endl;
434 cout << "channels:" << config.streamInfo.channels << endl;
435 }
436
437 spkProcessClient_ = AudioProcessInClient::Create(config);
438 CHECK_AND_RETURN_RET_LOG(spkProcessClient_ != nullptr, ERR_INVALID_HANDLE,
439 "Client test creat process client fail.");
440
441 spkProcClientCb_ = std::make_shared<AudioProcessTestCallback>(spkProcessClient_, loopCount_, config.audioMode);
442 int32_t ret = spkProcessClient_->SaveDataCallback(spkProcClientCb_);
443 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Client test save data callback fail, ret %{public}d.", ret);
444 isInited_ = true;
445 return SUCCESS;
446 }
447
IsInited()448 bool AudioProcessTest::IsInited()
449 {
450 return isInited_;
451 }
452
StartSpk()453 bool AudioProcessTest::StartSpk()
454 {
455 CHECK_AND_RETURN_RET_LOG(spkProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
456 int32_t ret = spkProcessClient_->Start();
457 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
458 return true;
459 }
460
PauseSpk()461 bool AudioProcessTest::PauseSpk()
462 {
463 CHECK_AND_RETURN_RET_LOG(spkProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
464 int32_t ret = spkProcessClient_->Pause();
465 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
466 return true;
467 }
468
ResumeSpk()469 bool AudioProcessTest::ResumeSpk()
470 {
471 CHECK_AND_RETURN_RET_LOG(spkProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
472 int32_t ret = spkProcessClient_->Resume();
473 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
474 return true;
475 }
476
SetSpkVolume(int32_t vol)477 bool AudioProcessTest::SetSpkVolume(int32_t vol)
478 {
479 CHECK_AND_RETURN_RET_LOG(spkProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
480 int32_t ret = spkProcessClient_->SetVolume(vol);
481 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
482 return true;
483 }
484
StopSpk()485 bool AudioProcessTest::StopSpk()
486 {
487 CHECK_AND_RETURN_RET_LOG(spkProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
488 int32_t ret = spkProcessClient_->Stop();
489 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
490 return true;
491 }
492
ReleaseSpk()493 bool AudioProcessTest::ReleaseSpk()
494 {
495 if (spkProcessClient_ == nullptr) {
496 AUDIO_INFO_LOG("%{public}s process client is already released.", __func__);
497 return true;
498 }
499 int32_t ret = spkProcessClient_->Release();
500 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test release fail, ret %{public}d.", ret);
501 spkProcessClient_ = nullptr;
502 AUDIO_INFO_LOG("client test set nullptr!");
503 return true;
504 }
505
InitMic(bool isRemote)506 int32_t AudioProcessTest::InitMic(bool isRemote)
507 {
508 AudioProcessConfig config;
509 config.appInfo.appPid = getpid();
510 config.appInfo.appUid = getuid();
511
512 config.audioMode = AUDIO_MODE_RECORD;
513 config.capturerInfo.sourceType = SOURCE_TYPE_MIC;
514 config.capturerInfo.capturerFlags = STREAM_FLAG_FAST;
515
516 config.streamInfo.channels = STEREO;
517 config.streamInfo.encoding = ENCODING_PCM;
518 config.streamInfo.format = SAMPLE_S16LE;
519 config.streamInfo.samplingRate = SAMPLE_RATE_48000;
520
521 (void)isRemote;
522
523 micProcessClient_ = AudioProcessInClient::Create(config);
524 CHECK_AND_RETURN_RET_LOG(micProcessClient_ != nullptr, ERR_INVALID_HANDLE,
525 "Client test creat process client fail.");
526
527 micProcClientCb_ = std::make_shared<AudioProcessTestCallback>(micProcessClient_, 0, config.audioMode);
528 int32_t ret = micProcessClient_->SaveDataCallback(micProcClientCb_);
529 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Client test save data callback fail, ret %{public}d.", ret);
530 return SUCCESS;
531 }
532
StartMic()533 bool AudioProcessTest::StartMic()
534 {
535 CHECK_AND_RETURN_RET_LOG(micProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
536 int32_t ret = micProcessClient_->Start();
537 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
538 return true;
539 }
540
PauseMic()541 bool AudioProcessTest::PauseMic()
542 {
543 CHECK_AND_RETURN_RET_LOG(micProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
544 int32_t ret = micProcessClient_->Pause();
545 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
546 return true;
547 }
548
ResumeMic()549 bool AudioProcessTest::ResumeMic()
550 {
551 CHECK_AND_RETURN_RET_LOG(micProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
552 int32_t ret = micProcessClient_->Resume();
553 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
554 return true;
555 }
556
SetMicVolume(int32_t vol)557 bool AudioProcessTest::SetMicVolume(int32_t vol)
558 {
559 CHECK_AND_RETURN_RET_LOG(micProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
560 int32_t ret = micProcessClient_->SetVolume(vol);
561 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
562 return true;
563 }
564
StopMic()565 bool AudioProcessTest::StopMic()
566 {
567 CHECK_AND_RETURN_RET_LOG(micProcessClient_ != nullptr, false, "%{public}s process client is null.", __func__);
568 int32_t ret = micProcessClient_->Stop();
569 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test stop fail, ret %{public}d.", ret);
570 return true;
571 }
572
ReleaseMic()573 bool AudioProcessTest::ReleaseMic()
574 {
575 if (micProcessClient_ == nullptr) {
576 AUDIO_INFO_LOG("%{public}s process client is already released.", __func__);
577 return true;
578 }
579 int32_t ret = micProcessClient_->Release();
580 CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, false, "Client test release fail, ret %{public}d.", ret);
581 micProcessClient_ = nullptr;
582 AUDIO_INFO_LOG("client test set nullptr!");
583 return true;
584 }
585
OpenSpkFile()586 bool OpenSpkFile()
587 {
588 if (g_spkWavFile != nullptr) {
589 AUDIO_ERR_LOG("Spk file has been opened, g_spkfilePath %{public}s", g_spkfilePath.c_str());
590 return true;
591 }
592
593 char path[PATH_MAX] = { 0x00 };
594 if ((strlen(g_spkfilePath.c_str()) > PATH_MAX) || (realpath(g_spkfilePath.c_str(), path) == nullptr)) {
595 return false;
596 }
597 AUDIO_INFO_LOG("spk path = %{public}s", path);
598 g_spkWavFile = fopen(path, "rb");
599 if (g_spkWavFile == nullptr) {
600 AUDIO_ERR_LOG("Unable to open wave file");
601 return false;
602 }
603 return true;
604 }
605
CloseSpkFile()606 void CloseSpkFile()
607 {
608 if (g_spkWavFile != nullptr) {
609 fclose(g_spkWavFile);
610 g_spkWavFile = nullptr;
611 }
612 }
613
OpenMicFile()614 bool OpenMicFile()
615 {
616 if (g_micPcmFile != nullptr) {
617 AUDIO_ERR_LOG("Mic file has been opened, MIC_FILE_PATH %{public}s", MIC_FILE_PATH.c_str());
618 return true;
619 }
620
621 AUDIO_INFO_LOG("mic path = %{public}s", MIC_FILE_PATH.c_str());
622 g_micPcmFile = fopen(MIC_FILE_PATH.c_str(), "ab+");
623 if (g_micPcmFile == nullptr) {
624 AUDIO_ERR_LOG("Unable to open wave file");
625 return false;
626 }
627 return true;
628 }
629
CloseMicFile()630 void CloseMicFile()
631 {
632 if (g_micPcmFile != nullptr) {
633 fclose(g_micPcmFile);
634 g_micPcmFile = nullptr;
635 }
636 }
637
GetArgs(const std::string & args)638 inline int32_t GetArgs(const std::string &args)
639 {
640 int32_t value = 0;
641 stringstream valueStr;
642 valueStr << args;
643 valueStr >> value;
644 return value;
645 }
646
PrintInteractiveUsage()647 void PrintInteractiveUsage()
648 {
649 cout << endl << "======================= InteractiveRunTestSelect ============================" << endl;
650 cout << "You can respond to instructions for corresponding option:" << endl;
651 for (auto it = g_interactiveOptStrMap.begin(); it != g_interactiveOptStrMap.end(); it ++) {
652 cout << "\t enter " << it->first << " : " << it->second << endl;
653 }
654 }
655
PrintProcTestUsage()656 void PrintProcTestUsage()
657 {
658 cout << endl << "========================== ProcessTestSelect ================================" << endl;
659 cout << "You can respond to instructions for corresponding test:" << endl;
660 for (auto it = g_audioProcessTestType.begin(); it != g_audioProcessTestType.end(); it ++) {
661 cout << it->first << ". " << it->second << endl;
662 }
663 }
664
PrintUsage()665 void PrintUsage()
666 {
667 cout << "[Audio Process Client Test App]" << endl << endl;
668 cout << "Supported Functionalities:" << endl;
669 cout << " a) Auto run local spk test." << endl;
670 cout << " b) Interactive run local/remote spk test." << endl;
671 cout << " c) Auto run remote mic test." << endl;
672 cout << " d) Interactive run remote mic test." << endl;
673 cout << "================================Usage=======================================" << endl << endl;
674
675 cout << "-a\n\tAuto run local spk process test, pelese input the following after select." << endl;
676 cout << "\tUsage : <wav-file-path> <play-loop-count>" << endl;
677 cout << "\t if <play-loop-count> equals to 0, it will loop infinitely." << endl;
678 cout << "\tExample 1 : /data/data/48kHz_16bit.wav 0" << endl;
679 cout << "\tExample 2 : /data/data/48kHz_16bit.wav 2" << endl << endl;
680
681 cout << "-b\n\tInteractive run local/remote spk test, pelese input the following after select." << endl;
682 cout << "\tUsage : <wav-file-path>" << endl;
683
684 cout << "-c\n\tAuto run remote mic process test, pelese input the following after select." << endl;
685 cout << "\tUsage : <record-time-in-seconds>" << endl;
686 cout << "\tGenerate the specified time span record file, path : /data/data/mic.pcm" << endl;
687
688 cout << "-d\n\tInteractive run remote mic test." << endl;
689 cout << "\tGenerate record file from start to stop, path : /data/data/mic.pcm" << endl;
690 }
691
GetUserInput()692 int32_t GetUserInput()
693 {
694 int32_t res = -1; // result
695 size_t count = 3; // try three time
696 cout << ">>";
697 cin >> res;
698 while (cin.fail() && count-- > 0) {
699 cin.clear();
700 cin.ignore();
701 cout << "invalid input, not a number! Please retry with a number." << endl;
702 cout << ">>";
703 cin >> res;
704 }
705 return res;
706 }
707
AutoRunSpk()708 void AutoRunSpk()
709 {
710 cout << "Auto run spk process test enter, please input loopCount and path:" << endl;
711 int32_t loopCount = GetUserInput();
712 std::string palyFilePath;
713 cin >> palyFilePath;
714 g_spkfilePath = palyFilePath;
715
716 if (!OpenSpkFile()) {
717 cout << "open spk file path failed!" << g_spkfilePath << endl;
718 return;
719 }
720 if (g_audioProcessTest->InitSpk(loopCount, false) != SUCCESS) {
721 cout << "Spk init failed!" << endl;
722 return;
723 }
724
725 do {
726 if (!g_audioProcessTest->StartSpk()) {
727 cout << "Spk start failed!" << endl;
728 break;
729 }
730 int volShift = 15; // helf of 1 << 16
731 if (!g_audioProcessTest->SetSpkVolume(1 << volShift)) {
732 cout << "Spk set volume " << volShift << " failed!" << endl;
733 break;
734 }
735
736 unique_lock<mutex> lock(g_autoRunMutex);
737 g_autoRunCV.wait(lock);
738 cout << "AutoRunSpk end" << endl;
739
740 if (!g_audioProcessTest->StopSpk()) {
741 cout << "Spk stop failed!" << endl;
742 break;
743 }
744 } while (false);
745
746 if (!g_audioProcessTest->ReleaseSpk()) {
747 cout << "Spk release failed!" << endl;
748 }
749 CloseSpkFile();
750 }
751
AutoRunMic()752 void AutoRunMic()
753 {
754 cout << "Auto run mic process test enter, please input recordTimeS:" << endl;
755 int32_t recordTimeS = GetUserInput();
756 if (!OpenMicFile()) {
757 cout << "open mic file path failed!" << g_spkfilePath << endl;
758 return;
759 }
760
761 if (g_audioProcessTest->InitMic(false) != SUCCESS) {
762 cout << "Mic init failed!" << endl;
763 return;
764 }
765
766 do {
767 if (!g_audioProcessTest->StartMic()) {
768 cout << "Mic start failed!" << endl;
769 break;
770 }
771 int volShift = 15; // helf of 1 << 16
772 if (!g_audioProcessTest->SetMicVolume(1 << volShift)) {
773 cout << "Mic set volume " << volShift << " failed!" << endl;
774 break;
775 }
776
777 cout << "wait " << recordTimeS << "s for capture frame..." << endl;
778 ClockTime::RelativeSleep(recordTimeS * SECOND_TO_NANOSECOND);
779 cout << "AutoRunMic end" << endl;
780
781 if (!g_audioProcessTest->StopMic()) {
782 cout << "Mic stop failed!" << endl;
783 break;
784 }
785 } while (false);
786
787 if (!g_audioProcessTest->ReleaseMic()) {
788 cout << "Mic release failed!" << endl;
789 }
790 CloseMicFile();
791 }
792
ConfigSpkTest(bool isRemote)793 string ConfigSpkTest(bool isRemote)
794 {
795 cout << "Please input spk file path:" << endl;
796 std::string palyFilePath;
797 cin >> palyFilePath;
798 g_spkfilePath = palyFilePath;
799
800 if (!OpenSpkFile()) {
801 cout << "Open spk file path failed!" << g_spkfilePath << endl;
802 return "Open spk wav file fail";
803 }
804 int32_t ret = g_audioProcessTest->InitSpk(0, isRemote);
805 if (ret != SUCCESS) {
806 return "Spk init failed";
807 }
808 return "Spk init SUCCESS";
809 }
810
CallStartSpk()811 string CallStartSpk()
812 {
813 if (!g_audioProcessTest->StartSpk()) {
814 return "Spk start failed";
815 }
816 return "Spk start SUCCESS";
817 }
818
CallPauseSpk()819 string CallPauseSpk()
820 {
821 if (!g_audioProcessTest->PauseSpk()) {
822 return "Spk pause failed";
823 }
824 return "Spk pause SUCCESS";
825 }
826
CallResumeSpk()827 string CallResumeSpk()
828 {
829 if (!g_audioProcessTest->ResumeSpk()) {
830 return "Spk resume failed";
831 }
832 return "Spk resume SUCCESS";
833 }
834
CallStopSpk()835 string CallStopSpk()
836 {
837 if (!g_audioProcessTest->StopSpk()) {
838 return "Spk stop failed";
839 }
840 return "Spk stop SUCCESS";
841 }
842
SetSpkVolume()843 string SetSpkVolume()
844 {
845 int32_t vol = GetUserInput();
846 if (!g_audioProcessTest->SetSpkVolume(vol)) {
847 return "Spk set volume failed";
848 }
849 return "Spk set volume SUCCESS";
850 }
851
CallReleaseSpk()852 string CallReleaseSpk()
853 {
854 if (!g_audioProcessTest->ReleaseSpk()) {
855 return "Spk release failed";
856 }
857 CloseSpkFile();
858 return "Spk release SUCCESS";
859 }
860
ConfigMicTest(bool isRemote)861 string ConfigMicTest(bool isRemote)
862 {
863 if (!OpenMicFile()) {
864 cout << "Open mic file path failed!" << g_spkfilePath << endl;
865 return "Open mic pcm file fail";
866 }
867
868 int32_t ret = g_audioProcessTest->InitMic(isRemote);
869 if (ret != SUCCESS) {
870 return "Mic init failed";
871 }
872 return "Mic init SUCCESS";
873 }
874
CallStartMic()875 string CallStartMic()
876 {
877 if (!g_audioProcessTest->StartMic()) {
878 return "Mic start failed";
879 }
880 return "Mic start SUCCESS";
881 }
882
CallPauseMic()883 string CallPauseMic()
884 {
885 if (!g_audioProcessTest->PauseMic()) {
886 return "Mic pause failed";
887 }
888 return "Mic pause SUCCESS";
889 }
890
CallResumeMic()891 string CallResumeMic()
892 {
893 if (!g_audioProcessTest->ResumeMic()) {
894 return "Mic resume failed";
895 }
896 return "Mic resume SUCCESS";
897 }
898
CallStopMic()899 string CallStopMic()
900 {
901 if (!g_audioProcessTest->StopMic()) {
902 return "Mic stop failed";
903 }
904 return "Mic stop SUCCESS";
905 }
906
SetMicVolume()907 string SetMicVolume()
908 {
909 int32_t vol = GetUserInput();
910 if (!g_audioProcessTest->SetMicVolume(vol)) {
911 return "Mic set volume failed";
912 }
913 return "Mic set volume SUCCESS";
914 }
915
CallReleaseMic()916 string CallReleaseMic()
917 {
918 if (!g_audioProcessTest->ReleaseMic()) {
919 return "Mic release failed";
920 }
921 CloseMicFile();
922 return "Mic release SUCCESS";
923 }
924
StartLoopTest()925 string StartLoopTest()
926 {
927 std::cout << ConfigMicTest(false);
928 std::cout << CallStartMic();
929 std::cout << endl;
930
931 int32_t ret = g_audioProcessTest->InitSpk(0, false);
932 if (ret != SUCCESS) {
933 CallReleaseMic();
934 return "init spk failed";
935 } else {
936 std::cout << "init spk success" << endl;
937 }
938
939 std::cout << CallStartSpk();
940 std::cout << endl;
941 return "StartLoopTest success!";
942 }
943
EndLoopTest()944 string EndLoopTest()
945 {
946 std::cout << CallReleaseSpk();
947 std::cout << endl;
948 std::cout << CallStopMic();
949 std::cout << endl;
950 std::cout << CallReleaseMic();
951 std::cout << endl;
952 return "EndLooptest";
953 }
954
StartSignalTest()955 string StartSignalTest()
956 {
957 if (g_audioProcessTest == nullptr) {
958 return "StartSignalTest failed";
959 }
960
961 if (!g_audioProcessTest->IsInited()) {
962 if (g_audioProcessTest->InitSpk(0, false) != SUCCESS) {
963 return "init spk failed";
964 }
965 uint32_t tempSleep = 10000; // wait for 10ms
966 usleep(tempSleep);
967 CallStartSpk();
968 }
969 g_renderSignal = true;
970 return "call signal";
971 }
972
EndSignalTest()973 string EndSignalTest()
974 {
975 return CallReleaseSpk();
976 }
977
978
InitCachebuffer()979 void InitCachebuffer()
980 {
981 g_byteBuffer = std::make_unique<uint8_t []>(CACHE_BUFFER_SIZE);
982 g_cacheBuffer.buffer = g_byteBuffer.get();
983 g_cacheBuffer.bufLength = CACHE_BUFFER_SIZE;
984 g_cacheBuffer.dataLength = CACHE_BUFFER_SIZE;
985 }
986
InteractiveRun()987 void InteractiveRun()
988 {
989 if (g_testMode == TestMode::RENDER_MIC_LOOP_DATA) {
990 InitCachebuffer();
991 }
992 cout << "Interactive run process test enter." << endl;
993 bool isInteractiveRun = true;
994 while (isInteractiveRun) {
995 PrintInteractiveUsage();
996 OperationCode optCode = INVALID_OPERATION;
997 int32_t res = GetUserInput();
998 if (g_interactiveOptStrMap.count(res)) {
999 optCode = static_cast<OperationCode>(res);
1000 }
1001 switch (optCode) {
1002 case EXIT_INTERACTIVE_TEST:
1003 isInteractiveRun = false;
1004 break;
1005 case INIT_LOCAL_SPK_PROCESS:
1006 cout << ConfigSpkTest(false) << endl;
1007 break;
1008 case INIT_REMOTE_SPK_PROCESS:
1009 cout << ConfigSpkTest(true) << endl;
1010 break;
1011 case START_LOOP_TEST:
1012 cout << StartLoopTest() << endl;
1013 break;
1014 case END_LOOP_TEST:
1015 cout << EndLoopTest() << endl;
1016 break;
1017 case INIT_LOCAL_MIC_PROCESS:
1018 cout << ConfigMicTest(false) << endl;
1019 break;
1020 case INIT_REMOTE_MIC_PROCESS:
1021 cout << ConfigMicTest(true) << endl;
1022 break;
1023 default:
1024 auto it = g_interactiveOptFuncMap.find(optCode);
1025 if (it != g_interactiveOptFuncMap.end() && it->second != nullptr) {
1026 CallTestOperationFunc &func = it->second;
1027 cout << (*func)() << endl;
1028 break;
1029 }
1030 cout << "Invalid input :" << optCode << endl;
1031 break;
1032 }
1033 }
1034 cout << "Interactive run process test end." << endl;
1035 }
1036
SetSysPara(const std::string key,int32_t & value)1037 bool SetSysPara(const std::string key, int32_t &value)
1038 {
1039 auto res = SetParameter(key.c_str(), std::to_string(value).c_str());
1040 if (res < 0) {
1041 AUDIO_WARNING_LOG("SetSysPara fail, key:%{public}s res:%{public}d", key.c_str(), res);
1042 return false;
1043 }
1044 AUDIO_INFO_LOG("SetSysPara success.");
1045 return true;
1046 }
1047 } // namespace AudioStandard
1048 } // namespace OHOS
1049
1050 using namespace OHOS::AudioStandard;
main()1051 int main()
1052 {
1053 AUDIO_INFO_LOG("AudioProcessClientTest test enter.");
1054
1055 PrintUsage();
1056 g_audioProcessTest = make_shared<AudioProcessTest>();
1057
1058 bool isProcTestRun = true;
1059 while (isProcTestRun) {
1060 PrintProcTestUsage();
1061 AudioProcessTestType procTestType = INVALID_PROC_TEST;
1062 g_testMode = TestMode::RENDER_FILE;
1063 int32_t res = GetUserInput();
1064 if (g_audioProcessTestType.count(res)) {
1065 procTestType = static_cast<AudioProcessTestType>(res);
1066 }
1067 switch (procTestType) {
1068 case INTERACTIVE_RUN_SPK_TEST:
1069 case INTERACTIVE_RUN_MIC_TEST:
1070 InteractiveRun();
1071 break;
1072 case INTERACTIVE_RUN_LOOP:
1073 g_testMode = TestMode::RENDER_MIC_LOOP_DATA;
1074 InteractiveRun();
1075 break;
1076 case RENDER_SIGNAL_TEST:
1077 g_testMode = TestMode::RENDER_SIGNAL_DATA;
1078 InteractiveRun();
1079 break;
1080 case AUTO_RUN_SPK_TEST:
1081 AutoRunSpk();
1082 break;
1083 case AUTO_RUN_MIC_TEST:
1084 AutoRunMic();
1085 break;
1086 case EXIT_PROC_TEST:
1087 isProcTestRun = false;
1088 break;
1089 default:
1090 cout << "invalid input, procTestType: " << procTestType << endl;
1091 break;
1092 }
1093 }
1094 AUDIO_INFO_LOG("AudioProcessClientTest test end.");
1095 return 0;
1096 }
1097