• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 #ifndef LOG_TAG
16 #define LOG_TAG "OhAudioCapturerLowlatencyTest"
17 #endif
18 
19 #include <ostream>
20 #include <sstream>
21 #include <iostream>
22 #include <string>
23 #include <map>
24 #include <cstdint>
25 #include <cstdio>
26 #include <cstring>
27 #include "native_audiostreambuilder.h"
28 #include <native_audiocapturer.h>
29 #include <thread>
30 #include <chrono>
31 #include <securec.h>
32 #include "audio_info.h"
33 #include "audio_system_manager.h"
34 #include "audio_errors.h"
35 #include "audio_common_log.h"
36 using namespace std;
37 
38 namespace OHOS {
39 namespace AudioStandard {
40 namespace {
41 enum OperationCode : int32_t {
42     INVALID_OPERATION = -1,
43     RELEASE_SPK_OH = 1,
44     START_SPK_OH = 2,
45     STOP_SPK_OH  = 3,
46     START_LOOP_TEST = 4,
47     END_LOOP_TEST = 5,
48     INIT_LOCAL_MIC_OH = 6,
49     INIT_REMOTE_MIC_OH = 7,
50     START_MIC_OH = 8,
51     PAUSE_MIC_OH = 9,
52     STOP_MIC_OH = 10,
53     RELEASE_MIC_OH = 11,
54     EXIT_INTERACTIVE_TEST = 20,
55 };
56 
57 enum AudioOHTestType : int32_t {
58     INVALID_OH_TEST = 0,
59     INTERACTIVE_RUN_MIC_TEST = 1,
60     INTERACTIVE_RUN_LOOP = 2,
61     EXIT_OH_TEST = 7,
62 };
63 static constexpr size_t CACHE_BUFFER_SIZE = 960;
64 int64_t g_stampTime = 0;
65 OperationCode g_optCode = INVALID_OPERATION;
66 }
67 
68 class AudioNdkTest;
69 
70 shared_ptr<AudioNdkTest> g_audioNdkTest = nullptr;
71 string g_spkfilePath = "";
72 const string MIC_FILE_PATH = "/data/data/mic_oh.pcm";
73 FILE *g_spkWavFile = nullptr;
74 FILE *g_micPcmFile = nullptr;
75 OH_AudioStreamBuilder* builder;
76 OH_AudioCapturer* audioCapturer;
77 OH_AudioRenderer* audioRenderer;
78 OH_AudioStream_Result ret;
79 int32_t g_latencyMode = 1;
80 static constexpr int64_t SECOND_TO_NANOSECOND = 1000000000;
81 int32_t g_loopCount = -1; // for loop
82 unique_ptr<uint8_t[]> g_byteBuffer = nullptr;
83 BufferDesc g_cacheBuffer = {nullptr, 0, 0};
84 
85 string CallStartSpk();
86 string CallStopSpk();
87 string CallReleaseSpk();
88 string ConfigMicTest(bool isRemote);
89 string CallStartMic();
90 string CallPauseMic();
91 string CallStopMic();
92 string CallReleaseMic();
93 using CallTestOperationFunc = string (*)();
94 
95 map<int32_t, string> g_audioNdkTestType = {
96     {INTERACTIVE_RUN_MIC_TEST, "Interactive run mic oh test"},
97     {INTERACTIVE_RUN_LOOP, "Roundtrip latency test"},
98     {EXIT_OH_TEST, "Exit audio oh test"},
99 };
100 
101 map<int32_t, string> g_interactiveOptStrMap = {
102     {START_SPK_OH, "call start spk oh"},
103     {STOP_SPK_OH, "call stop spk oh"},
104     {RELEASE_SPK_OH, "release spk oh"},
105     {START_LOOP_TEST, "start loop"},
106     {END_LOOP_TEST, "end loop"},
107     {INIT_LOCAL_MIC_OH, "call local mic init oh"},
108     {INIT_REMOTE_MIC_OH, "call remote mic init oh"},
109     {START_MIC_OH, "call start mic oh"},
110     {PAUSE_MIC_OH, "call pause mic oh"},
111     {STOP_MIC_OH, "call stop mic oh"},
112     {RELEASE_MIC_OH, "release mic oh"},
113     {EXIT_INTERACTIVE_TEST, "exit interactive run test"},
114 };
115 
116 map<int32_t, CallTestOperationFunc> g_interactiveOptFuncMap = {
117     {START_SPK_OH, CallStartSpk},
118     {STOP_SPK_OH, CallStopSpk},
119     {RELEASE_SPK_OH, CallReleaseSpk},
120     {START_MIC_OH, CallStartMic},
121     {PAUSE_MIC_OH, CallPauseMic},
122     {STOP_MIC_OH, CallStopMic},
123     {RELEASE_MIC_OH, CallReleaseMic}
124 };
125 
126 class AudioNdkTest {
127 public:
128     AudioNdkTest() = default;
129     ~AudioNdkTest() = default;
130 
131     int32_t InitSpk(int32_t loopCount, bool isRemote);
132     bool StartSpk();
133     bool StopSpk();
134     bool ReleaseSpk();
135     int32_t InitMic(bool isRemote);
136     bool StartMic();
137     bool PauseMic();
138     bool StopMic();
139     bool ReleaseMic();
140     void SelectDevice(DeviceRole deviceRole);
141 };
142 
InitSignalBuffer(void * signalSoundBuffer,int32_t bufferLen)143 void InitSignalBuffer(void* signalSoundBuffer, int32_t bufferLen)
144 {
145     int ret = memset_s(signalSoundBuffer, bufferLen, 0, bufferLen);
146     if (ret != EOK) {
147         return;
148     }
149     const int channels = 2; // 2 channels
150     const int samplePerChannel = 96 / channels; // 96 for 1ms
151     int16_t *signalData = static_cast<int16_t *>(signalSoundBuffer);
152     int16_t bound = 10;
153     for (int idx = 0; idx < samplePerChannel; idx++) {
154         signalData[channels * idx] = bound + static_cast<int16_t>(sinf(2.0f * static_cast<float>(M_PI) * idx /
155             samplePerChannel) * (SHRT_MAX - bound));
156         for (int c = 1; c < channels; c++) {
157             signalData[channels * idx + c] = signalData[channels * idx];
158         }
159     }
160 }
161 
AudioRendererOnWriteData(OH_AudioRenderer * renderer,void * userData,void * buffer,int32_t bufferLen)162 static int32_t AudioRendererOnWriteData(OH_AudioRenderer* renderer,
163     void* userData,
164     void* buffer,
165     int32_t bufferLen)
166 {
167     g_loopCount++;
168     int32_t periodCount = g_loopCount % 400; // 400 * 0.005 = 2s
169     if (periodCount == 0) {
170         InitSignalBuffer(buffer, bufferLen); // set signal data
171         int64_t temp = ClockTime::GetCurNano() - g_stampTime;
172         std::cout << "client read-write latency:" << (temp / AUDIO_MS_PER_SECOND) << " us" << std::endl;
173         return 0;
174     }
175     int32_t keepQuiteHold = 50;
176     if (periodCount > keepQuiteHold) {
177         return 0;
178     }
179     // copy mic data in the cache buffer
180     int ret = memcpy_s(buffer, bufferLen, static_cast<void *>(g_cacheBuffer.buffer), g_cacheBuffer.bufLength);
181     if (ret != EOK) {
182         AUDIO_WARNING_LOG("memcpy_s failed.");
183     }
184     return 0;
185 }
186 
AudioCapturerOnReadData(OH_AudioCapturer * capturer,void * userData,void * buffer,int32_t bufferLen)187 static int32_t AudioCapturerOnReadData(OH_AudioCapturer* capturer,
188     void* userData,
189     void* buffer,
190     int32_t bufferLen)
191 {
192     if (g_optCode == START_LOOP_TEST) {
193         int32_t cnt = fwrite(buffer, 1, bufferLen, g_micPcmFile);
194         CHECK_AND_RETURN_RET_LOG(cnt == bufferLen, ERR_WRITE_FAILED,
195             "%{public}s fwrite fail, cnt %{public}d, bufLength %{public}d.", __func__, cnt, bufferLen);
196         int ret = memcpy_s(static_cast<void *>(g_cacheBuffer.buffer), bufferLen, buffer, bufferLen);
197         if (ret != EOK) {
198             AUDIO_WARNING_LOG("memcpy_s failed.");
199         }
200         g_stampTime = ClockTime::GetCurNano();
201         return 0;
202     }
203 
204     size_t count = 1;
205     if (fwrite(buffer, bufferLen, count, g_micPcmFile) != count) {
206         cout <<"buffer fwrite err";
207     }
208     return 0;
209 }
210 
211 
InitSpk(int32_t loopCount,bool isRemote)212 int32_t AudioNdkTest::InitSpk(int32_t loopCount, bool isRemote)
213 {
214     if (loopCount < 0) {
215         g_loopCount = 1; // loop once
216     } else if (loopCount == 0) {
217         g_loopCount = -1; // infinite loop
218     } else {
219         g_loopCount = loopCount;
220     }
221 
222     if (isRemote) {
223         SelectDevice(OUTPUT_DEVICE);
224     }
225 
226     OH_AudioStream_Type type = AUDIOSTREAM_TYPE_RENDERER;
227     ret = OH_AudioStreamBuilder_Create(&builder, type);
228     cout << "createcallback ret:  " << ret << endl;
229     // 2. set params and callbacks
230     OH_AudioStreamBuilder_SetSamplingRate(builder, SAMPLE_RATE_48000);
231     OH_AudioStreamBuilder_SetChannelCount(builder, STEREO);
232     OH_AudioStreamBuilder_SetLatencyMode(builder, (OH_AudioStream_LatencyMode)g_latencyMode);
233 
234     OH_AudioRenderer_Callbacks callbacks;
235     callbacks.OH_AudioRenderer_OnWriteData = AudioRendererOnWriteData;
236     ret = OH_AudioStreamBuilder_SetRendererCallback(builder, callbacks, nullptr);
237     cout << "setcallback ret: " << ret << endl;
238     // 3. create OH_AudioRenderer
239     ret = OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
240     cout << "create renderer client, ret: " << ret << endl;
241     return SUCCESS;
242 }
243 
ReleaseSpk()244 bool AudioNdkTest::ReleaseSpk()
245 {
246     if (!audioRenderer) {
247         ret = OH_AudioRenderer_Release(audioRenderer);
248         cout << "Renderer release ret: " << ret << endl;
249     }
250 
251     if (!builder) {
252         ret = OH_AudioStreamBuilder_Destroy(builder);
253         cout << "Renderer destroy builder ret: " << ret << endl;
254     }
255     return true;
256 }
257 
StartSpk()258 bool AudioNdkTest::StartSpk()
259 {
260     ret = OH_AudioRenderer_Start(audioRenderer);
261     cout << "Renderer start ret: " << ret << endl;
262     return true;
263 }
264 
StopSpk()265 bool AudioNdkTest::StopSpk()
266 {
267     ret = OH_AudioRenderer_Stop(audioRenderer);
268     cout << "Renderer stop ret: " << ret << endl;
269     return true;
270 }
271 
InitMic(bool isRemote)272 int32_t AudioNdkTest::InitMic(bool isRemote)
273 {
274     if (isRemote) {
275         SelectDevice(INPUT_DEVICE);
276     }
277     // 1. create
278     OH_AudioStream_Type type = AUDIOSTREAM_TYPE_CAPTURER;
279     ret = OH_AudioStreamBuilder_Create(&builder, type);
280     cout <<"create capturer builder: " << ret << endl;
281 
282     // 2. set params and callbacks
283     OH_AudioStreamBuilder_SetSamplingRate(builder, SAMPLE_RATE_48000);
284     OH_AudioStreamBuilder_SetChannelCount(builder, STEREO);
285     OH_AudioStreamBuilder_SetLatencyMode(builder, (OH_AudioStream_LatencyMode)g_latencyMode);
286 
287     OH_AudioCapturer_Callbacks callbacks;
288     callbacks.OH_AudioCapturer_OnReadData = AudioCapturerOnReadData;
289     ret = OH_AudioStreamBuilder_SetCapturerCallback(builder, callbacks, nullptr);
290     cout << "setcallback: " << ret << endl;
291 
292     // 3. create OH_AudioCapturer
293     ret = OH_AudioStreamBuilder_GenerateCapturer(builder, &audioCapturer);
294     cout << "create capturer client, ret: " << ret << endl;
295 
296     return SUCCESS;
297 }
298 
StartMic()299 bool AudioNdkTest::StartMic()
300 {
301     ret = OH_AudioCapturer_Start(audioCapturer);
302     cout << "start ret: " << ret << endl;
303     return true;
304 }
305 
PauseMic()306 bool AudioNdkTest::PauseMic()
307 {
308     ret = OH_AudioCapturer_Pause(audioCapturer);
309     cout << "pause ret: " << ret << endl;
310     return true;
311 }
312 
StopMic()313 bool AudioNdkTest::StopMic()
314 {
315     ret = OH_AudioCapturer_Stop(audioCapturer);
316     cout << "stop ret: " << ret << endl;
317     return true;
318 }
319 
ReleaseMic()320 bool AudioNdkTest::ReleaseMic()
321 {
322     if (!audioCapturer) {
323         ret = OH_AudioCapturer_Release(audioCapturer);
324         cout << "release ret: " << ret << endl;
325     }
326 
327     if (!builder) {
328         ret = OH_AudioStreamBuilder_Destroy(builder);
329         cout << "destroy builder ret: " << ret << endl;
330     }
331     return true;
332 }
333 
SelectDevice(DeviceRole deviceRole)334 void AudioNdkTest::SelectDevice(DeviceRole deviceRole)
335 {
336     AudioSystemManager *manager = AudioSystemManager::GetInstance();
337     if (manager == nullptr) {
338         cout << "Get AudioSystemManager failed" << endl;
339         return;
340     }
341 
342     vector<std::shared_ptr<AudioDeviceDescriptor>> devices;
343     if (deviceRole == OUTPUT_DEVICE) {
344         devices = manager->GetDevices(DISTRIBUTED_OUTPUT_DEVICES_FLAG);
345     } else {
346         devices = manager->GetDevices(DISTRIBUTED_INPUT_DEVICES_FLAG);
347     }
348     if (devices.size() != 1) {
349         cout << "GetDevices failed, unsupported size:" << devices.size() << endl;
350         return;
351     }
352     cout << "using device:" << devices[0]->networkId_ << endl;
353 
354     int32_t ret = 0;
355     if (deviceRole == OUTPUT_DEVICE) {
356         sptr<AudioRendererFilter> filter = new AudioRendererFilter();
357         filter->uid = getuid();
358         filter->rendererInfo.rendererFlags = STREAM_FLAG_FAST;
359         ret = manager->SelectOutputDevice(filter, devices);
360     } else {
361         sptr<AudioCapturerFilter> filter = new AudioCapturerFilter();
362         filter->uid = getuid();
363         filter->capturerInfo.sourceType = SOURCE_TYPE_MIC;
364         filter->capturerInfo.capturerFlags = STREAM_FLAG_FAST;
365         ret = manager->SelectInputDevice(filter, devices);
366     }
367 
368     if (ret == SUCCESS) {
369         cout << "SelectDevice seccess" << endl;
370     } else {
371         cout << "SelectDevice failed, ret:" << ret << endl;
372     }
373 }
374 
OpenSpkFile()375 bool OpenSpkFile()
376 {
377     if (g_spkWavFile != nullptr) {
378         AUDIO_ERR_LOG("Spk file has been opened, g_spkfilePath %{public}s", g_spkfilePath.c_str());
379         return true;
380     }
381 
382     char path[PATH_MAX] = { 0x00 };
383     if ((strlen(g_spkfilePath.c_str()) > PATH_MAX) || (realpath(g_spkfilePath.c_str(), path) == nullptr)) {
384         return false;
385     }
386     AUDIO_INFO_LOG("spk path = %{public}s", path);
387     g_spkWavFile = fopen(path, "rb");
388     if (g_spkWavFile == nullptr) {
389         AUDIO_ERR_LOG("Unable to open wave file");
390         return false;
391     }
392     return true;
393 }
394 
CloseSpkFile()395 void CloseSpkFile()
396 {
397     if (g_spkWavFile != nullptr) {
398         fclose(g_spkWavFile);
399         g_spkWavFile = nullptr;
400     }
401 }
402 
OpenMicFile()403 bool OpenMicFile()
404 {
405     if (g_micPcmFile != nullptr) {
406         AUDIO_ERR_LOG("Mic file has been opened, MIC_FILE_PATH %{public}s", MIC_FILE_PATH.c_str());
407         return true;
408     }
409 
410     AUDIO_INFO_LOG("mic path = %{public}s", MIC_FILE_PATH.c_str());
411     g_micPcmFile = fopen(MIC_FILE_PATH.c_str(), "ab+");
412     if (g_micPcmFile == nullptr) {
413         AUDIO_ERR_LOG("Unable to open wave file");
414         return false;
415     }
416     return true;
417 }
418 
CloseMicFile()419 void CloseMicFile()
420 {
421     if (g_micPcmFile != nullptr) {
422         fclose(g_micPcmFile);
423         g_micPcmFile = nullptr;
424     }
425 }
426 
PrintInteractiveUsage()427 void PrintInteractiveUsage()
428 {
429     cout << endl << "======================= InteractiveRunTestSelect ============================" << endl;
430     cout << "You can respond to instructions for corresponding option:" << endl;
431     for (auto it = g_interactiveOptStrMap.begin(); it != g_interactiveOptStrMap.end(); it ++) {
432         cout << "\t enter " << it->first << " : " << it->second << endl;
433     }
434 }
435 
PrintNdkTestUsage()436 void PrintNdkTestUsage()
437 {
438     cout << endl << "========================== NdkTestSelect ================================" << endl;
439     cout << "You can respond to instructions for corresponding test:" << endl;
440     for (auto it = g_audioNdkTestType.begin(); it != g_audioNdkTestType.end(); it ++) {
441         cout << it->first << ". " << it->second << endl;
442     }
443 }
444 
GetUserInput()445 int32_t GetUserInput()
446 {
447     int32_t res = -1;
448     size_t count = 3;
449     cout << ">>";
450     cin >> res;
451     while (cin.fail() && count-- > 0) {
452         cin.clear();
453         cin.ignore();
454         cout << "invalid input, not a number! Please retry with a number." << endl;
455         cout << ">>";
456         cin >> res;
457     }
458     return res;
459 }
460 
AutoRunMic()461 void AutoRunMic()
462 {
463     cout << "Auto run mic oh test enter, please input recordTimeS:" << endl;
464     int32_t recordTimeS = GetUserInput();
465     if (!OpenMicFile()) {
466         cout << "open mic file path failed!" << endl;
467         return;
468     }
469 
470     if (g_audioNdkTest->InitMic(false) != SUCCESS) {
471         cout << "Mic init failed!" << endl;
472         return;
473     }
474 
475     do {
476         if (!g_audioNdkTest->StartMic()) {
477             cout << "Mic start failed!" << endl;
478             break;
479         }
480 
481         cout << "wait " << recordTimeS << "s for capture frame..." << endl;
482         ClockTime::RelativeSleep(recordTimeS * SECOND_TO_NANOSECOND);
483         cout << "AutoRunMic end" << endl;
484 
485         if (!g_audioNdkTest->StopMic()) {
486             cout << "Mic stop failed!" << endl;
487             break;
488         }
489     } while (false);
490 
491     if (!g_audioNdkTest->ReleaseMic()) {
492         cout << "Mic release failed!" << endl;
493     }
494     CloseMicFile();
495 }
496 
ConfigMicTest(bool isRemote)497 string ConfigMicTest(bool isRemote)
498 {
499     if (!OpenMicFile()) {
500         cout << "Open mic file path failed!" << endl;
501         return "Open mic pcm file fail";
502     }
503 
504     int32_t ret = g_audioNdkTest->InitMic(isRemote);
505     if (ret != SUCCESS) {
506         return "Mic init failed";
507     }
508     return "Mic init SUCCESS";
509 }
510 
CallStartSpk()511 string CallStartSpk()
512 {
513     if (!g_audioNdkTest->StartSpk()) {
514         return "Spk start failed";
515     }
516     return "Spk start SUCCESS";
517 }
518 
CallStopSpk()519 string CallStopSpk()
520 {
521     if (!g_audioNdkTest->StopSpk()) {
522         return "Spk stop failed";
523     }
524     return "Spk stop SUCCESS";
525 }
526 
CallReleaseSpk()527 string CallReleaseSpk()
528 {
529     if (!g_audioNdkTest->ReleaseSpk()) {
530         return "Spk release failed";
531     }
532     CloseSpkFile();
533     return "Spk release SUCCESS";
534 }
535 
CallStartMic()536 string CallStartMic()
537 {
538     if (!g_audioNdkTest->StartMic()) {
539         return "Mic start failed";
540     }
541     return "Mic start SUCCESS";
542 }
543 
CallPauseMic()544 string CallPauseMic()
545 {
546     if (!g_audioNdkTest->PauseMic()) {
547         return "Mic pause failed";
548     }
549     return "Mic pause SUCCESS";
550 }
551 
CallStopMic()552 string CallStopMic()
553 {
554     if (!g_audioNdkTest->StopMic()) {
555         return "Mic stop failed";
556     }
557     return "Mic stop SUCCESS";
558 }
559 
CallReleaseMic()560 string CallReleaseMic()
561 {
562     if (!g_audioNdkTest->ReleaseMic()) {
563         return "Mic release failed";
564     }
565     CloseMicFile();
566     return "Mic release SUCCESS";
567 }
568 
StartLoopTest()569 string StartLoopTest()
570 {
571     cout << ConfigMicTest(false) << endl;
572     cout << CallStartMic() << endl;
573 
574     int32_t ret = g_audioNdkTest->InitSpk(0, false);
575     if (ret != SUCCESS) {
576         CallReleaseMic();
577         return "init spk failed";
578     } else {
579         std::cout << "init spk success" << endl;
580     }
581 
582     cout << CallStartSpk() << endl;
583     return "StartLoopTest success!";
584 }
585 
EndLoopTest()586 string EndLoopTest()
587 {
588     cout << CallStopSpk() << endl;
589     cout << CallReleaseSpk() << endl;
590     cout << CallStopMic() << endl;
591     cout << CallReleaseMic() << endl;
592     return "EndLooptest";
593 }
594 
InitCachebuffer()595 void InitCachebuffer()
596 {
597     g_byteBuffer = make_unique<uint8_t []>(CACHE_BUFFER_SIZE);
598     g_cacheBuffer.buffer = g_byteBuffer.get();
599     g_cacheBuffer.bufLength = CACHE_BUFFER_SIZE;
600     g_cacheBuffer.dataLength = CACHE_BUFFER_SIZE;
601 }
602 
InteractiveRun()603 void InteractiveRun()
604 {
605     InitCachebuffer();
606     cout << "Interactive run oh test enter." << endl;
607     bool isInteractiveRun = true;
608     while (isInteractiveRun) {
609         PrintInteractiveUsage();
610         int32_t res = GetUserInput();
611         if (g_interactiveOptStrMap.count(res)) {
612             g_optCode = static_cast<OperationCode>(res);
613         }
614         switch (g_optCode) {
615             case EXIT_INTERACTIVE_TEST:
616                 isInteractiveRun = false;
617                 break;
618             case START_LOOP_TEST:
619                 cout << StartLoopTest() << endl;
620                 break;
621             case END_LOOP_TEST:
622                 cout << EndLoopTest() << endl;
623                 break;
624             case INIT_LOCAL_MIC_OH:
625                 cout << ConfigMicTest(false) << endl;
626                 break;
627             case INIT_REMOTE_MIC_OH:
628                 cout << ConfigMicTest(true) << endl;
629                 break;
630             default:
631                 auto it = g_interactiveOptFuncMap.find(g_optCode);
632                 if (it != g_interactiveOptFuncMap.end() && it->second != nullptr) {
633                     CallTestOperationFunc &func = it->second;
634                     cout << (*func)() << endl;
635                     break;
636                 }
637                 cout << "Invalid input :" << g_optCode << endl;
638                 break;
639         }
640     }
641     cout << "Interactive run oh test end." << endl;
642 }
643 
644 } // namespace AudioStandard
645 } // namespace OHOS
646 
647 using namespace OHOS::AudioStandard;
main()648 int main()
649 {
650     cout << "Please input 1 or 0 (1 means low latency, 0 means ordinary): " << endl;
651     cin >> g_latencyMode;
652 
653     bool isNdkTestRun = true;
654     g_audioNdkTest = make_shared<AudioNdkTest>();
655 
656     while (isNdkTestRun) {
657         PrintNdkTestUsage();
658         AudioOHTestType ohTestType = INVALID_OH_TEST;
659         int32_t res = GetUserInput();
660         if (g_audioNdkTestType.count(res)) {
661             ohTestType = static_cast<AudioOHTestType>(res);
662         }
663         switch (ohTestType) {
664             case INTERACTIVE_RUN_MIC_TEST:
665                 cout << "OH run mic test, ohTestType: " << ohTestType << endl;
666                 InteractiveRun();
667                 break;
668             case INTERACTIVE_RUN_LOOP:
669                 cout << "OH run loop test, ohTestType: " << ohTestType << endl;
670                 InteractiveRun();
671                 break;
672             case EXIT_OH_TEST:
673                 isNdkTestRun = false;
674                 cout << "exit OH test, ohTestType: " << ohTestType << endl;
675                 break;
676             default:
677                 cout << "invalid input, ohTestType: " << ohTestType << endl;
678                 break;
679         }
680     }
681     cout << "Test end!" << endl;
682     return 0;
683 }
684