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