1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <dlfcn.h>
17 #include <limits.h>
18 #include <pthread.h>
19 #include <securec.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include "framework_common.h"
28 #include "hdf_base.h"
29 #include "inttypes.h"
30 #include "osal_mem.h"
31 #include "v4_0/audio_types.h"
32 #include "v4_0/iaudio_manager.h"
33 
34 #define MAX_AUDIO_ADAPTER_DESC         5
35 #define BUFFER_LEN                     256
36 #define AUDIO_CHANNELCOUNT             2
37 #define AUDIO_SAMPLE_RATE_48K          48000
38 #define PATH_LEN                       256
39 #define DEEP_BUFFER_RENDER_PERIOD_SIZE 4096
40 #define INT_32_MAX                     0x7fffffff
41 #define EXT_PARAMS_MAXLEN              107
42 #define BITS_TO_FROMAT                 3
43 
44 struct StrPara {
45     struct IAudioRender *render;
46     FILE *file;
47     struct AudioSampleAttributes attrs;
48     uint64_t *replyBytes;
49     char *frame;
50     int32_t bufferSize;
51 };
52 
53 struct IAudioRender *g_render = NULL;
54 struct IAudioAdapter *g_adapter = NULL;
55 static struct IAudioManager *g_audioManager = NULL;
56 struct AudioDeviceDescriptor g_devDesc;
57 struct AudioSampleAttributes g_attrs;
58 struct AudioPort g_audioPort;
59 struct AudioHeadInfo g_wavHeadInfo;
60 static struct StrPara g_str;
61 uint32_t g_renderId = 0;
62 
63 pthread_t g_tids;
64 char *g_frame = NULL;
65 FILE *g_file;
66 
67 char g_path[256];
68 char g_adapterName[PATH_LEN] = {0};
69 static int32_t g_closeEnd = 0;
70 pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
71 pthread_cond_t g_functionCond = PTHREAD_COND_INITIALIZER;
72 bool g_waitSleep = false;
73 bool g_isDirect = true;
74 
75 enum RenderMenuId {
76     RENDER_START = 1,
77     RENDER_STOP,
78     RENDER_RESUME,
79     RENDER_PAUSE,
80     SET_RENDER_VOLUME,
81     SET_RENDER_GAIN,
82     SET_RENDER_MUTE,
83     SET_RENDER_ATTRIBUTES,
84     SET_RENDER_SLECET_SCENE,
85     GET_RENDER_EXT_PARAMS,
86     GET_RENDER_POSITION,
87 };
88 
89 enum RenderInputType {
90     INPUT_INT = 0,
91     INPUT_FLOAT,
92     INPUT_UINT32,
93 };
94 
95 typedef int32_t (*AudioRenderOperation)(struct IAudioRender **);
96 
97 struct ProcessRenderMenuSwitchList {
98     enum RenderMenuId cmd;
99     AudioRenderOperation operation;
100 };
101 
CheckInputName(int type,void * val)102 static int32_t CheckInputName(int type, void *val)
103 {
104     if (val == NULL) {
105         return HDF_FAILURE;
106     }
107 
108     int ret;
109     int inputInt = 0;
110     float inputFloat = 0.0;
111     uint32_t inputUint = 0;
112 
113     printf("\n");
114     switch (type) {
115         case INPUT_INT:
116             ret = scanf_s("%d", &inputInt);
117             if (inputInt < 0 || inputInt > GET_RENDER_POSITION + 1) {
118                 if (g_frame != NULL) {
119                     OsalMemFree(g_frame);
120                     g_frame = NULL;
121                 }
122                 AUDIO_FUNC_LOGE("Input failure");
123                 return HDF_FAILURE;
124             }
125 
126             *(int *)val = inputInt;
127             break;
128         case INPUT_FLOAT:
129             ret = scanf_s("%f", &inputFloat);
130 
131             *(float *)val = inputFloat;
132             break;
133         case INPUT_UINT32:
134             ret = scanf_s("%u", &inputUint);
135             if (inputUint > 0xFFFFFFFF) {
136                 return HDF_FAILURE;
137             }
138 
139             *(uint32_t *)val = inputUint;
140             break;
141         default:
142             ret = EOF;
143             break;
144     }
145 
146     if (ret == 0) {
147         CleanStdin();
148     } else if (ret == EOF) {
149         AUDIO_FUNC_LOGE("Input failure occurs!");
150         return HDF_FAILURE;
151     }
152     return HDF_SUCCESS;
153 }
154 
InitAttrs(struct AudioSampleAttributes * attrs)155 static int32_t InitAttrs(struct AudioSampleAttributes *attrs)
156 {
157     if (attrs == NULL) {
158         return HDF_FAILURE;
159     }
160     /* Initialization of audio parameters for playback */
161     attrs->format = AUDIO_FORMAT_TYPE_PCM_16_BIT;
162     attrs->channelCount = AUDIO_CHANNELCOUNT;
163     attrs->sampleRate = AUDIO_SAMPLE_RATE_48K;
164     attrs->interleaved = 0;
165     attrs->type = AUDIO_IN_MEDIA;
166     attrs->period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
167     attrs->frameSize = PCM_16_BIT * attrs->channelCount / PCM_8_BIT;
168     attrs->isBigEndian = false;
169     attrs->isSignedData = true;
170     attrs->startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs->frameSize);
171     attrs->stopThreshold = INT_32_MAX;
172     attrs->silenceThreshold = 0;
173     return HDF_SUCCESS;
174 }
175 
InitDevDesc(struct AudioDeviceDescriptor * devDesc,uint32_t portId)176 static int32_t InitDevDesc(struct AudioDeviceDescriptor *devDesc, uint32_t portId)
177 {
178     if (devDesc == NULL) {
179         return HDF_FAILURE;
180     }
181     /* Initialization of audio parameters for playback */
182     devDesc->portId = portId;
183     devDesc->pins = PIN_OUT_SPEAKER;
184     devDesc->desc = strdup("cardname");
185     return HDF_SUCCESS;
186 }
187 
StreamClose(int32_t sig)188 static void StreamClose(int32_t sig)
189 {
190     /* allow the stream to be closed gracefully */
191     (void)signal(sig, SIG_IGN);
192     g_closeEnd = 1;
193 }
194 
PcmFramesToBytes(const struct AudioSampleAttributes attrs)195 static uint32_t PcmFramesToBytes(const struct AudioSampleAttributes attrs)
196 {
197     return DEEP_BUFFER_RENDER_PERIOD_SIZE * attrs.channelCount * (PcmFormatToBits(attrs.format) >> BITS_TO_FROMAT);
198 }
199 
StopAudioFiles(struct IAudioRender ** renderS)200 static int32_t StopAudioFiles(struct IAudioRender **renderS)
201 {
202     if (renderS == NULL) {
203         return HDF_FAILURE;
204     }
205     if (g_waitSleep) {
206         pthread_mutex_lock(&g_mutex);
207         g_waitSleep = false;
208         pthread_cond_signal(&g_functionCond);
209         pthread_mutex_unlock(&g_mutex);
210     }
211     if (!g_closeEnd) {
212         g_closeEnd = true;
213         usleep(100000); // sleep 100000us
214     }
215 
216     struct IAudioRender *render = *renderS;
217     if (render == NULL) {
218         AUDIO_FUNC_LOGE("render is null");
219         return HDF_FAILURE;
220     }
221 
222     int32_t ret = render->Stop((void *)render);
223     if (ret < 0) {
224         AUDIO_FUNC_LOGE("Stop Render!");
225     }
226 
227     if (g_adapter == NULL || g_adapter->DestroyRender == NULL) {
228         return HDF_FAILURE;
229     }
230 
231     ret = g_adapter->DestroyRender(g_adapter, g_renderId);
232     if (ret < 0) {
233         AUDIO_FUNC_LOGE("Destroy Render!");
234     }
235 
236     IAudioRenderRelease(render, g_isDirect);
237 
238     *renderS = NULL;
239     g_render = NULL;
240     if (g_frame != NULL) {
241         OsalMemFree(g_frame);
242         g_frame = NULL;
243     }
244 
245     if (g_file != NULL) {
246         fclose(g_file);
247         g_file = NULL;
248     }
249     printf("Stop Successful\n");
250     return ret;
251 }
252 
FrameStartMmap(const struct StrPara * param)253 static int32_t FrameStartMmap(const struct StrPara *param)
254 {
255     if (param == NULL) {
256         return HDF_FAILURE;
257     }
258     const struct StrPara *strParam = param;
259     struct IAudioRender *render = strParam->render;
260     struct AudioMmapBufferDescriptor mmapDesc;
261 
262     (void)signal(SIGINT, StreamClose);
263 
264     // get file length
265     char pathBuf[PATH_MAX] = {'\0'};
266     if (realpath(g_path, pathBuf) == NULL) {
267         return HDF_FAILURE;
268     }
269 
270     // get fileSize
271     FILE *fp = fopen(pathBuf, "rb+");
272     if (fp == NULL) {
273         printf("Open file failed!\n");
274         return HDF_FAILURE;
275     }
276 
277     int32_t ret = fseek(fp, 0, SEEK_END);
278     if (ret != 0) {
279         fclose(fp);
280         return HDF_FAILURE;
281     }
282 
283     int32_t reqSize = (int32_t)ftell(fp);
284     if (reqSize < 0) {
285         fclose(fp);
286         return HDF_FAILURE;
287     }
288     (void)fclose(fp);
289     // Init param
290     mmapDesc.memoryFd = 0; // default 0
291     mmapDesc.filePath = strdup(pathBuf);
292     mmapDesc.isShareable = 1;                                        // 1:Shareable ,0:Don't share
293     mmapDesc.transferFrameSize = DEEP_BUFFER_RENDER_PERIOD_SIZE / 4; // One frame size 4 bit
294     mmapDesc.offset = sizeof(g_wavHeadInfo);
295 
296     // start
297     if (render == NULL || render->ReqMmapBuffer == NULL) {
298         free(mmapDesc.filePath);
299         return HDF_FAILURE;
300     }
301 
302     ret = render->ReqMmapBuffer(render, reqSize, &mmapDesc);
303     if (ret < 0 || reqSize <= 0) {
304         free(mmapDesc.filePath);
305         printf("Request map fail,please check.\n");
306         return HDF_FAILURE;
307     }
308 
309     if (g_render != NULL) {
310         ret = StopAudioFiles(&render);
311         if (ret < 0) {
312             free(mmapDesc.filePath);
313             AUDIO_FUNC_LOGE("StopAudioFiles File!");
314         }
315     }
316     free(mmapDesc.filePath);
317     return HDF_SUCCESS;
318 }
319 
FrameStart(const struct StrPara * param)320 static int32_t FrameStart(const struct StrPara *param)
321 {
322     if (param == NULL) {
323         return HDF_FAILURE;
324     }
325 
326     size_t numRead;
327     char *frame = param->frame;
328     int32_t bufferSize = param->bufferSize;
329     struct IAudioRender *render = param->render;
330     size_t remainingDataSize = g_wavHeadInfo.riffSize;
331 
332     (void)signal(SIGINT, StreamClose);
333     if (g_file == NULL) {
334         return HDF_FAILURE;
335     }
336 
337     if (render == NULL || render->RenderFrame == NULL || frame == NULL) {
338         return HDF_FAILURE;
339     }
340 
341     do {
342         uint64_t replyBytes = 0;
343         size_t readSize = (remainingDataSize > bufferSize) ? (size_t)bufferSize : remainingDataSize;
344         numRead = fread(frame, 1, readSize, g_file);
345         if (numRead > 0) {
346             int32_t ret = render->RenderFrame(render, (int8_t *)frame, numRead, &replyBytes);
347             if (ret == HDF_ERR_INVALID_OBJECT) {
348                 AUDIO_FUNC_LOGE("Render already stop!");
349                 break;
350             }
351             remainingDataSize -= numRead;
352         }
353 
354         while (g_waitSleep) {
355             printf("music pause now.\n");
356             pthread_cond_wait(&g_functionCond, &g_mutex);
357             printf("music resume now.\n");
358         }
359     } while (!g_closeEnd && numRead > 0 && remainingDataSize > 0);
360 
361     if (!g_closeEnd) {
362         printf("\nPlay complete, please select input again\n");
363         (void)StopAudioFiles(&render);
364     }
365     return HDF_SUCCESS;
366 }
367 
InitPlayingAudioParam(struct IAudioRender * render)368 static int32_t InitPlayingAudioParam(struct IAudioRender *render)
369 {
370     if (render == NULL) {
371         return HDF_FAILURE;
372     }
373     uint64_t frameSize = 0;
374     uint64_t frameCount = 0;
375     uint64_t bufferSize = 0;
376     if (render->GetFrameSize(render, &frameSize) != HDF_SUCCESS) {
377         AUDIO_FUNC_LOGE("get frame size failed");
378     }
379     if (render->GetFrameCount(render, &frameCount) != HDF_SUCCESS) {
380         AUDIO_FUNC_LOGE("get frame count failed");
381     }
382 
383     bufferSize = frameCount * frameSize;
384     if (bufferSize == 0) {
385         bufferSize = PcmFramesToBytes(g_attrs);
386         AUDIO_FUNC_LOGE("buffer size by calc is %" PRIu64 "", bufferSize);
387     }
388 
389     g_frame = (char *)OsalMemCalloc(bufferSize);
390     if (g_frame == NULL) {
391         return HDF_FAILURE;
392     }
393 
394     (void)memset_s(&g_str, sizeof(struct StrPara), 0, sizeof(struct StrPara));
395 
396     g_str.render = render;
397     g_str.bufferSize = (int32_t)bufferSize;
398     g_str.frame = g_frame;
399     return HDF_SUCCESS;
400 }
401 
PrintPlayMode(void)402 static void PrintPlayMode(void)
403 {
404     printf(" ============= Play Render Mode ==========\n");
405     printf("| 1. Render non-mmap                     |\n");
406     printf("| 2. Render mmap                         |\n");
407     printf(" ======================================== \n");
408 }
409 
SelectPlayMode(int32_t * palyModeFlag)410 static int32_t SelectPlayMode(int32_t *palyModeFlag)
411 {
412     if (palyModeFlag == NULL) {
413         AUDIO_FUNC_LOGE("palyModeFlag is null");
414         return HDF_FAILURE;
415     }
416 
417     int choice = 0;
418 
419     system("clear");
420 
421     PrintPlayMode();
422 
423     printf("Please enter your choice:");
424 
425     int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
426     if (ret < 0) {
427         AUDIO_FUNC_LOGE("CheckInputName Fail");
428         return HDF_FAILURE;
429     } else {
430         *palyModeFlag = choice;
431     }
432     return HDF_SUCCESS;
433 }
434 
StartPlayThread(int32_t palyModeFlag)435 static int32_t StartPlayThread(int32_t palyModeFlag)
436 {
437     pthread_attr_t tidsAttr;
438     pthread_attr_init(&tidsAttr);
439     pthread_attr_setdetachstate(&tidsAttr, PTHREAD_CREATE_DETACHED);
440     switch (palyModeFlag) {
441         case 1: // 1. Stander Loading
442             if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
443                 AUDIO_FUNC_LOGE("Create Thread Fail");
444                 return HDF_FAILURE;
445             }
446             break;
447         case 2: // 2. Low latency Loading
448             if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStartMmap), &g_str) != 0) {
449                 AUDIO_FUNC_LOGE("Create Thread Fail");
450                 return HDF_FAILURE;
451             }
452             break;
453         default:
454             printf("Input error,Switched to non-mmap Mode for you.\n");
455             SystemInputFail();
456 
457             if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
458                 AUDIO_FUNC_LOGE("Create Thread Fail");
459                 return HDF_FAILURE;
460             }
461             break;
462     }
463     return HDF_SUCCESS;
464 }
465 
PlayingAudioInitFile(void)466 static int32_t PlayingAudioInitFile(void)
467 {
468     if (g_file != NULL) {
469         AUDIO_FUNC_LOGE("the music is playing,please stop first");
470         return HDF_FAILURE;
471     }
472     g_closeEnd = false;
473 
474     char pathBuf[PATH_MAX] = {'\0'};
475     if (realpath(g_path, pathBuf) == NULL) {
476         return HDF_FAILURE;
477     }
478 
479     g_file = fopen(pathBuf, "rb");
480     if (g_file == NULL) {
481         printf("failed to open '%s'\n", g_path);
482         return HDF_FAILURE;
483     }
484 
485     if (CheckWavFileHeader(g_file, &g_wavHeadInfo, &g_attrs) < 0) {
486         FileClose(&g_file);
487         return HDF_FAILURE;
488     }
489 
490     (void)chmod(g_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
491 
492     return HDF_SUCCESS;
493 }
494 
PlayingAudioInitRender(struct IAudioRender ** renderTemp)495 static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp)
496 {
497     if (renderTemp == NULL) {
498         AUDIO_FUNC_LOGE("render is null");
499         return HDF_FAILURE;
500     }
501     struct IAudioRender *render = NULL;
502     if (g_adapter == NULL || g_adapter->CreateRender == NULL) {
503         return HDF_FAILURE;
504     }
505     int32_t ret = g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &render, &g_renderId);
506     if (render == NULL || ret < 0 || render->RenderFrame == NULL) {
507         AUDIO_FUNC_LOGE("AudioDeviceCreateRender failed or RenderFrame is null");
508         return HDF_FAILURE;
509     }
510 
511     // Playing audio files
512     if (render->Start((void *)render)) {
513         AUDIO_FUNC_LOGE("Start Bind Fail!");
514         g_adapter->DestroyRender(g_adapter, g_renderId);
515         IAudioRenderRelease(render, g_isDirect);
516         return HDF_FAILURE;
517     }
518 
519     if (InitPlayingAudioParam(render) < 0) {
520         g_adapter->DestroyRender(g_adapter, g_renderId);
521         IAudioRenderRelease(render, g_isDirect);
522         return HDF_FAILURE;
523     }
524     *renderTemp = render;
525     return HDF_SUCCESS;
526 }
527 
PlayingAudioFiles(struct IAudioRender ** renderS)528 static int32_t PlayingAudioFiles(struct IAudioRender **renderS)
529 {
530     if (renderS == NULL || g_adapter == NULL) {
531         return HDF_FAILURE;
532     }
533 
534     if (PlayingAudioInitFile() < 0) {
535         AUDIO_FUNC_LOGE("PlayingAudioInitFile Fail");
536         return HDF_FAILURE;
537     }
538 
539     int32_t palyModeFlag = 0;
540     if (SelectPlayMode(&palyModeFlag) < 0) {
541         AUDIO_FUNC_LOGE("SelectPlayMode Fail");
542         FileClose(&g_file);
543         return HDF_FAILURE;
544     }
545 
546     struct IAudioRender *render = NULL;
547     if (PlayingAudioInitRender(&render) < 0) {
548         AUDIO_FUNC_LOGE("PlayingAudioInitRender fail");
549         FileClose(&g_file);
550         return HDF_FAILURE;
551     }
552 
553     if (StartPlayThread(palyModeFlag) < 0) {
554         FileClose(&g_file);
555         if (g_adapter != NULL && g_adapter->DestroyRender != NULL) {
556             g_adapter->DestroyRender(g_adapter, g_renderId);
557         }
558         IAudioRenderRelease(render, g_isDirect);
559         return HDF_FAILURE;
560     }
561 
562     *renderS = render;
563     printf("Start Successful,Music is playing\n");
564     return HDF_SUCCESS;
565 }
566 
SelectLoadingMode(void)567 static int32_t SelectLoadingMode(void)
568 {
569     int choice = 0;
570 
571     system("clear");
572 
573     PrintLoadModeMenu();
574 
575     printf("Please enter your choice:");
576 
577     int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
578     if (ret < 0) {
579         return HDF_FAILURE;
580     }
581 
582     switch (choice) {
583         case 1: // 1 is Passthrough Loading
584             g_isDirect = true;
585             break;
586         case 2: // 2 is IPC Loading
587             g_isDirect = false;
588             break;
589         default:
590             printf("Input error,Switched to direct loading in for you.\n");
591             SystemInputFail();
592             g_isDirect = true;
593             break;
594     }
595 
596     return HDF_SUCCESS;
597 }
598 
AudioAdapterDescriptorFree(struct AudioAdapterDescriptor * dataBlock,bool freeSelf)599 void AudioAdapterDescriptorFree(struct AudioAdapterDescriptor *dataBlock, bool freeSelf)
600 {
601     if (dataBlock == NULL) {
602         return;
603     }
604 
605     if (dataBlock->adapterName != NULL) {
606         OsalMemFree(dataBlock->adapterName);
607         dataBlock->adapterName = NULL;
608     }
609 
610     if (dataBlock->ports != NULL) {
611         OsalMemFree(dataBlock->ports);
612     }
613 
614     if (freeSelf) {
615         OsalMemFree(dataBlock);
616     }
617 }
618 
ReleaseAdapterDescs(struct AudioAdapterDescriptor ** descs,uint32_t descsLen)619 static void ReleaseAdapterDescs(struct AudioAdapterDescriptor **descs, uint32_t descsLen)
620 {
621     if (descsLen > 0 && descs != NULL && (*descs) != NULL) {
622         for (uint32_t i = 0; i < descsLen; i++) {
623             AudioAdapterDescriptorFree(&(*descs)[i], false);
624         }
625         OsalMemFree(*descs);
626         *descs = NULL;
627     }
628 }
629 
GetManagerAndLoadAdapter(struct AudioPort * renderPort)630 static int32_t GetManagerAndLoadAdapter(struct AudioPort *renderPort)
631 {
632     int32_t adapterIndex = 0;
633 
634     if (renderPort == NULL) {
635         AUDIO_FUNC_LOGE("The Parameter is NULL");
636         return HDF_FAILURE;
637     }
638 
639     struct IAudioManager *audioManagerIns = IAudioManagerGet(g_isDirect);
640     if (audioManagerIns == NULL) {
641         AUDIO_FUNC_LOGE("Get audio Manager Fail");
642         return HDF_FAILURE;
643     }
644 
645     g_audioManager = audioManagerIns;
646 
647     struct AudioAdapterDescriptor *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc(
648         sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC));
649     if (descs == NULL) {
650         AUDIO_FUNC_LOGE("OsalMemCalloc for descs failed");
651         return HDF_FAILURE;
652     }
653 
654     uint32_t adapterNum = MAX_AUDIO_ADAPTER_DESC;
655 
656     int32_t ret = audioManagerIns->GetAllAdapters(audioManagerIns, descs, &adapterNum);
657     if (ret < 0 || adapterNum == 0) {
658         AUDIO_FUNC_LOGE("Get All Adapters Fail");
659         ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
660         return HDF_ERR_NOT_SUPPORT;
661     }
662     if (SelectAudioCard(descs, adapterNum, &adapterIndex) != HDF_SUCCESS) {
663         ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
664         return HDF_ERR_NOT_SUPPORT;
665     }
666     if (strcpy_s(g_adapterName, PATH_LEN, descs[adapterIndex - 1].adapterName) < 0) {
667         ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
668         return HDF_ERR_NOT_SUPPORT;
669     }
670     if (SwitchAudioPort(&descs[adapterIndex - 1], PORT_OUT, renderPort) != HDF_SUCCESS) {
671         ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
672         return HDF_ERR_NOT_SUPPORT;
673     }
674     if (audioManagerIns->LoadAdapter(audioManagerIns, &descs[adapterIndex - 1], &g_adapter)) {
675         AUDIO_FUNC_LOGE("Load Adapter Fail");
676         ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
677         return HDF_ERR_NOT_SUPPORT;
678     }
679 
680     ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
681 
682     return HDF_SUCCESS;
683 }
684 
InitRenderParam(uint32_t portId)685 static int32_t InitRenderParam(uint32_t portId)
686 {
687     if (g_adapter == NULL || g_adapter->InitAllPorts == NULL) {
688         return HDF_FAILURE;
689     }
690     // Initialization port information, can fill through mode and other parameters
691     (void)g_adapter->InitAllPorts(g_adapter);
692 
693     // User needs to set
694     if (InitAttrs(&g_attrs) < 0) {
695         AUDIO_FUNC_LOGE("InitAttrs failed");
696         return HDF_FAILURE;
697     }
698 
699     // Specify a hardware device
700     if (InitDevDesc(&g_devDesc, portId) < 0) {
701         AUDIO_FUNC_LOGE("InitDevDesc failed");
702         return HDF_FAILURE;
703     }
704     return HDF_SUCCESS;
705 }
706 
RenderGetAdapterAndInitEnvParams(void)707 static int32_t RenderGetAdapterAndInitEnvParams(void)
708 {
709     struct AudioPort renderPort;
710 
711     int32_t ret = GetManagerAndLoadAdapter(&renderPort);
712     if (ret < 0) {
713         return ret;
714     }
715 
716     if (InitRenderParam(renderPort.portId) < 0) {
717         g_audioManager->UnloadAdapter(g_audioManager, g_adapterName);
718         IAudioAdapterRelease(g_adapter, g_isDirect);
719         g_adapter = NULL;
720         return HDF_FAILURE;
721     }
722     return HDF_SUCCESS;
723 }
724 
InitParam(void)725 static int32_t InitParam(void)
726 {
727     if (SelectLoadingMode() < 0) {
728         return HDF_FAILURE;
729     }
730 
731     /* Select loading mode,end */
732     g_audioPort.dir = PORT_OUT;
733     g_audioPort.portId = 0;
734     g_audioPort.portName = "AOP";
735 
736     if (RenderGetAdapterAndInitEnvParams() < 0) {
737         AUDIO_FUNC_LOGE("GetProxyManagerFunc Fail");
738         if (g_audioManager != NULL) {
739             IAudioManagerRelease(g_audioManager, g_isDirect);
740             g_audioManager = NULL;
741         }
742         return HDF_FAILURE;
743     }
744     return HDF_SUCCESS;
745 }
746 
SetRenderMute(struct IAudioRender ** render)747 static int32_t SetRenderMute(struct IAudioRender **render)
748 {
749     (void)render;
750     if (g_render == NULL || g_render->GetMute == NULL) {
751         return HDF_FAILURE;
752     }
753 
754     int32_t val;
755     bool isMute = false;
756 
757     int32_t ret = g_render->GetMute((void *)g_render, &isMute);
758     if (ret < 0) {
759         AUDIO_FUNC_LOGE("The current mute state was not obtained!");
760     }
761 
762     printf("Now %s ,Do you need to set mute status(1/0):", isMute ? "mute" : "not mute");
763 
764     ret = CheckInputName(INPUT_INT, (void *)&val);
765     if (ret < 0) {
766         return HDF_FAILURE;
767     }
768 
769     if (g_render == NULL || g_render->SetMute == NULL) {
770         AUDIO_FUNC_LOGE("Music already stop!");
771         SystemInputFail();
772         return HDF_FAILURE;
773     }
774     if (val == 1) {
775         ret = g_render->SetMute((void *)g_render, !isMute);
776     }
777     return ret;
778 }
779 
SetRenderVolume(struct IAudioRender ** render)780 static int32_t SetRenderVolume(struct IAudioRender **render)
781 {
782     (void)render;
783     if (g_render == NULL || g_render->GetVolume == NULL) {
784         return HDF_FAILURE;
785     }
786 
787     int32_t ret;
788     float val = 0.0;
789 
790     ret = g_render->GetVolume((void *)g_render, &val);
791     if (ret < 0) {
792         AUDIO_FUNC_LOGE("Get current volume failed!");
793         SystemInputFail();
794         return ret;
795     }
796 
797     printf("Now the volume is %f ,Please enter the volume value you want to set (0.0-1.0):", val);
798 
799     ret = CheckInputName(INPUT_FLOAT, (void *)&val);
800     if (ret < 0) {
801         return HDF_FAILURE;
802     }
803 
804     if (val < 0.0 || val > 1.0) {
805         AUDIO_FUNC_LOGE("Invalid volume value!");
806         SystemInputFail();
807         return HDF_FAILURE;
808     }
809 
810     if (g_render == NULL || g_render->SetVolume == NULL) {
811         AUDIO_FUNC_LOGE("Music already stop!");
812         SystemInputFail();
813         return HDF_FAILURE;
814     }
815 
816     ret = g_render->SetVolume((void *)g_render, val);
817     if (ret < 0) {
818         AUDIO_FUNC_LOGE("set volume fail!");
819         SystemInputFail();
820     }
821     return ret;
822 }
823 
GetRenderGain(struct IAudioRender ** render)824 static int32_t GetRenderGain(struct IAudioRender **render)
825 {
826     (void)render;
827     if (g_render == NULL || g_render->GetGain == NULL) {
828         return HDF_FAILURE;
829     }
830 
831     float val = 1.0;
832 
833     int32_t ret = g_render->GetGain((void *)g_render, &val);
834     if (ret < 0) {
835         AUDIO_FUNC_LOGE("Get current gain failed!");
836         SystemInputFail();
837         return HDF_FAILURE;
838     }
839     printf("Now the gain is %f,", val);
840     SystemInputFail();
841     return HDF_SUCCESS;
842 }
843 
SetRenderPause(struct IAudioRender ** render)844 static int32_t SetRenderPause(struct IAudioRender **render)
845 {
846     (void)render;
847 
848     if (g_waitSleep) {
849         AUDIO_FUNC_LOGE("Already pause,not need pause again!");
850         SystemInputFail();
851         return HDF_FAILURE;
852     }
853 
854     if (g_render == NULL || g_render->Pause == NULL) {
855         return HDF_FAILURE;
856     }
857 
858     int32_t ret = g_render->Pause((void *)g_render);
859     if (ret != 0) {
860         return HDF_FAILURE;
861     }
862 
863     printf("Pause success!\n");
864     g_waitSleep = true;
865     return HDF_SUCCESS;
866 }
867 
SetRenderResume(struct IAudioRender ** render)868 static int32_t SetRenderResume(struct IAudioRender **render)
869 {
870     (void)render;
871 
872     if (!g_waitSleep) {
873         AUDIO_FUNC_LOGE("Now is Playing,not need resume!");
874         SystemInputFail();
875         return HDF_FAILURE;
876     }
877 
878     if (g_render == NULL || g_render->Resume == NULL) {
879         return HDF_FAILURE;
880     }
881 
882     int32_t ret = g_render->Resume((void *)g_render);
883     if (ret != 0) {
884         return HDF_FAILURE;
885     }
886     printf("resume success!\n");
887 
888     pthread_mutex_lock(&g_mutex);
889     g_waitSleep = false;
890     pthread_cond_signal(&g_functionCond);
891     pthread_mutex_unlock(&g_mutex);
892     return HDF_SUCCESS;
893 }
PrintAttributesFromat(void)894 static void PrintAttributesFromat(void)
895 {
896     printf(" ============= Render Sample Attributes Fromat =============== \n");
897     printf("| 1. Render AUDIO_FORMAT_TYPE_PCM_8_BIT                            |\n");
898     printf("| 2. Render AUDIO_FORMAT_TYPE_PCM_16_BIT                           |\n");
899     printf("| 3. Render AUDIO_FORMAT_TYPE_PCM_24_BIT                           |\n");
900     printf("| 4. Render AUDIO_FORMAT_TYPE_PCM_32_BIT                           |\n");
901     printf(" ============================================================= \n");
902 }
SelectAttributesFomat(uint32_t * pcmFomat)903 static int32_t SelectAttributesFomat(uint32_t *pcmFomat)
904 {
905     if (pcmFomat == NULL) {
906         AUDIO_FUNC_LOGE("fomat is null!");
907         return HDF_FAILURE;
908     }
909 
910     int val = 0;
911 
912     PrintAttributesFromat();
913 
914     printf("Please select audio format,If not selected, the default is 16bit:");
915 
916     int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
917     if (ret < 0) {
918         AUDIO_FUNC_LOGE("CheckInputName failed.");
919         return HDF_FAILURE;
920     }
921 
922     switch (val) {
923         case AUDIO_FORMAT_TYPE_PCM_8_BIT:
924             *pcmFomat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
925             break;
926         case AUDIO_FORMAT_TYPE_PCM_16_BIT:
927             *pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
928             break;
929         case AUDIO_FORMAT_TYPE_PCM_24_BIT:
930             *pcmFomat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
931             break;
932         case AUDIO_FORMAT_TYPE_PCM_32_BIT:
933             *pcmFomat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
934             break;
935         default:
936             *pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
937             break;
938     }
939     return HDF_SUCCESS;
940 }
941 
SetRenderAttributes(struct IAudioRender ** render)942 static int32_t SetRenderAttributes(struct IAudioRender **render)
943 {
944     (void)render;
945 
946     struct AudioSampleAttributes attrs;
947 
948     if (g_render == NULL || g_render->GetSampleAttributes == NULL) {
949         AUDIO_FUNC_LOGE("The pointer is null!");
950         return HDF_FAILURE;
951     }
952 
953     int32_t ret = g_render->GetSampleAttributes((void *)g_render, &attrs);
954     if (ret < 0) {
955         AUDIO_FUNC_LOGE("GetRenderAttributes failed!");
956     } else {
957         printf("Current sample attributes:\n");
958         printf("audioType is %u\nfomat is %u\nsampleRate is %u\nchannalCount is"
959                "%u\nperiod is %u\nframesize is %u\nbigEndian is %u\nSignedData is %u\n",
960             attrs.type, attrs.format, attrs.sampleRate, attrs.channelCount, attrs.period, attrs.frameSize,
961             attrs.isBigEndian, attrs.isSignedData);
962     }
963     printf("Set Sample Attributes,");
964     SystemInputFail();
965     system("clear");
966     printf("The sample attributes you want to set,Step by step, please.\n");
967 
968     ret = SelectAttributesFomat((uint32_t *)(&attrs.format));
969     if (ret < 0) {
970         AUDIO_FUNC_LOGE("SetRenderAttributes format failed!");
971         return HDF_FAILURE;
972     }
973 
974     printf("\nPlease input sample rate(48000,44100,32000...):");
975 
976     ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.sampleRate));
977     if (ret < 0) {
978         return HDF_FAILURE;
979     }
980 
981     printf("\nPlease input bigEndian(false=0/true=1):");
982 
983     ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.isBigEndian));
984     if (ret < 0) {
985         return HDF_FAILURE;
986     }
987     if (g_render == NULL || g_render->SetSampleAttributes == NULL) {
988         AUDIO_FUNC_LOGE("Music already complete,Please replay and set the attrbutes!");
989         SystemInputFail();
990         return HDF_FAILURE;
991     }
992 
993     ret = g_render->SetSampleAttributes((void *)g_render, &attrs);
994     if (ret < 0) {
995         AUDIO_FUNC_LOGE("Set render attributes failed!");
996         SystemInputFail();
997     }
998     return ret;
999 }
1000 
PrintRenderSelectPinFirst(struct AudioSceneDescriptor * scene)1001 static int32_t PrintRenderSelectPinFirst(struct AudioSceneDescriptor *scene)
1002 {
1003     system("clear");
1004     printf(" ==================== Select Pin =====================  \n");
1005     printf("| 0. Speaker                                           |\n");
1006     printf("| 1. HeadPhones                                        |\n");
1007     printf(" =====================================================  \n");
1008 
1009     printf("Please input your choice:\n");
1010     int32_t val = 0;
1011     int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1012     if (ret < 0) {
1013         AUDIO_FUNC_LOGE("Invalid value!");
1014         SystemInputFail();
1015         return HDF_FAILURE;
1016     }
1017 
1018     if (val == 1) {
1019         scene->desc.pins = PIN_OUT_HEADSET;
1020     } else {
1021         scene->desc.pins = PIN_OUT_SPEAKER;
1022     }
1023 
1024     return HDF_SUCCESS;
1025 }
1026 
PrintRenderSelectPinSecond(struct AudioSceneDescriptor * scene)1027 static int32_t PrintRenderSelectPinSecond(struct AudioSceneDescriptor *scene)
1028 {
1029     system("clear");
1030     printf(" ==================== Select Pin =====================  \n");
1031     printf("| 0. Speaker                                           |\n");
1032     printf("| 1. HeadPhones                                        |\n");
1033     printf("| 2. Speaker and HeadPhones                            |\n");
1034     printf(" =====================================================  \n");
1035 
1036     printf("Please input your choice:\n");
1037     int32_t val = 0;
1038     int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1039     if (ret < 0) {
1040         AUDIO_FUNC_LOGE("Invalid value!");
1041         SystemInputFail();
1042         return HDF_FAILURE;
1043     }
1044 
1045     if (val == 1) {
1046         scene->desc.pins = PIN_OUT_HEADSET;
1047     } else if (val == 0) {
1048         scene->desc.pins = PIN_OUT_SPEAKER;
1049     } else {
1050         scene->desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET;
1051     }
1052 
1053     return HDF_SUCCESS;
1054 }
1055 
PrintRenderSelectPinThird(struct AudioSceneDescriptor * scene)1056 static int32_t PrintRenderSelectPinThird(struct AudioSceneDescriptor *scene)
1057 {
1058     system("clear");
1059     printf(" ==================== Select Pin =====================  \n");
1060     printf("| 0. Speaker                                           |\n");
1061     printf("| 1. HeadPhones                                        |\n");
1062     printf(" =====================================================  \n");
1063 
1064     printf("Please input your choice:\n");
1065     int32_t val = 0;
1066     int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1067     if (ret < 0) {
1068         AUDIO_FUNC_LOGE("Invalid value!");
1069         SystemInputFail();
1070         return HDF_FAILURE;
1071     }
1072 
1073     if (val == 1) {
1074         scene->desc.pins = PIN_OUT_HEADSET;
1075     } else {
1076         scene->desc.pins = PIN_OUT_SPEAKER;
1077     }
1078 
1079     return HDF_SUCCESS;
1080 }
1081 
SelectSceneMenu(void)1082 static void SelectSceneMenu(void)
1083 {
1084     printf(" =================== Select Scene ======================== \n");
1085     printf("0 is Midea.                                               |\n");
1086     printf("1 is Communication.                                       |\n");
1087     printf("2 is Ring-Tone.                                           |\n");
1088     printf("3 is Voice-Call.                                          |\n");
1089     printf("4 is Mmap.                                                |\n");
1090     printf(" ========================================================= \n");
1091 }
1092 
SelectRenderScene(struct IAudioRender ** render)1093 static int32_t SelectRenderScene(struct IAudioRender **render)
1094 {
1095     (void)render;
1096 
1097     int32_t val = 0;
1098     struct AudioSceneDescriptor scene;
1099     system("clear");
1100     SelectSceneMenu();
1101     printf("Please input your choice:\n");
1102 
1103     int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1104     if (ret < 0) {
1105         AUDIO_FUNC_LOGE("Invalid value!");
1106         SystemInputFail();
1107         return HDF_FAILURE;
1108     }
1109 
1110     switch (val) {
1111         case AUDIO_IN_MEDIA:
1112             scene.scene.id = AUDIO_IN_MEDIA;
1113             PrintRenderSelectPinFirst(&scene);
1114             break;
1115         case AUDIO_IN_COMMUNICATION:
1116             scene.scene.id = AUDIO_IN_COMMUNICATION;
1117             PrintRenderSelectPinSecond(&scene);
1118             break;
1119         case AUDIO_IN_RINGTONE:
1120             scene.scene.id = AUDIO_IN_RINGTONE;
1121             scene.desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET;
1122             break;
1123         case AUDIO_IN_CALL:
1124             scene.scene.id = AUDIO_IN_CALL;
1125             PrintRenderSelectPinThird(&scene);
1126             break;
1127         case AUDIO_MMAP_NOIRQ:
1128             scene.scene.id = AUDIO_MMAP_NOIRQ;
1129             PrintRenderSelectPinFirst(&scene);
1130             break;
1131         default:
1132             break;
1133     }
1134 
1135     scene.desc.desc = "mic";
1136 
1137     if (g_render == NULL || g_render->SelectScene == NULL) {
1138         AUDIO_FUNC_LOGE("Music already stop,");
1139         SystemInputFail();
1140         return HDF_FAILURE;
1141     }
1142 
1143     ret = g_render->SelectScene((void *)g_render, &scene);
1144     if (ret < 0) {
1145         AUDIO_FUNC_LOGE("Select scene fail\n");
1146     }
1147     return ret;
1148 }
1149 
GetExtParams(struct IAudioRender ** render)1150 static int32_t GetExtParams(struct IAudioRender **render)
1151 {
1152     (void)render;
1153     if (g_render == NULL || g_render->GetExtraParams == NULL) {
1154         return HDF_FAILURE;
1155     }
1156 
1157     char keyValueList[BUFFER_LEN] = {0};
1158 
1159     int32_t ret = g_render->GetExtraParams((void *)g_render, keyValueList, EXT_PARAMS_MAXLEN);
1160     if (ret < 0) {
1161         AUDIO_FUNC_LOGE("Get EXT params failed!");
1162         SystemInputFail();
1163         return HDF_FAILURE;
1164     }
1165     printf("keyValueList = %s\n", keyValueList);
1166     return HDF_SUCCESS;
1167 }
1168 
GetRenderMmapPosition(struct IAudioRender ** render)1169 static int32_t GetRenderMmapPosition(struct IAudioRender **render)
1170 {
1171     (void)render;
1172 
1173     if (g_render == NULL || g_render->GetMmapPosition == NULL) {
1174         return HDF_FAILURE;
1175     }
1176 
1177     uint64_t frames = 0;
1178     struct AudioTimeStamp time;
1179     time.tvNSec = 0;
1180     time.tvSec = 0;
1181 
1182     int32_t ret = g_render->GetMmapPosition((void *)g_render, &frames, &time);
1183     if (ret < 0) {
1184         AUDIO_FUNC_LOGE("Get current Mmap frames Position failed!");
1185         SystemInputFail();
1186         return HDF_FAILURE;
1187     }
1188     printf("Now the Position is %" PRIu64 "\n", frames);
1189     return HDF_SUCCESS;
1190 }
1191 
PrintMenu2(void)1192 static void PrintMenu2(void)
1193 {
1194     printf(" ================== Play Render Menu ================== \n");
1195     printf("| 1. Render Start                                      |\n");
1196     printf("| 2. Render Stop                                       |\n");
1197     printf("| 3. Render Resume                                     |\n");
1198     printf("| 4. Render Pause                                      |\n");
1199     printf("| 5. Render SetVolume                                  |\n");
1200     printf("| 6. Render GetGain                                    |\n");
1201     printf("| 7. Render SetMute                                    |\n");
1202     printf("| 8. Render SetAttributes                              |\n");
1203     printf("| 9. Render SelectScene                                |\n");
1204     printf("| 10. Render getEXtParams                              |\n");
1205     printf("| 11. Render getMmapPosition                           |\n");
1206     printf("| 12.Exit                                              |\n");
1207     printf(" ====================================================== \n");
1208 }
1209 
1210 static struct ProcessRenderMenuSwitchList g_processRenderMenuSwitchList[] = {
1211     {RENDER_START,            PlayingAudioFiles    },
1212     {RENDER_STOP,             StopAudioFiles       },
1213     {RENDER_RESUME,           SetRenderResume      },
1214     {RENDER_PAUSE,            SetRenderPause       },
1215     {SET_RENDER_VOLUME,       SetRenderVolume      },
1216     {SET_RENDER_GAIN,         GetRenderGain        },
1217     {SET_RENDER_MUTE,         SetRenderMute        },
1218     {SET_RENDER_ATTRIBUTES,   SetRenderAttributes  },
1219     {SET_RENDER_SLECET_SCENE, SelectRenderScene    },
1220     {GET_RENDER_EXT_PARAMS,   GetExtParams         },
1221     {GET_RENDER_POSITION,     GetRenderMmapPosition},
1222 };
1223 
ProcessMenu(int32_t choice)1224 static void ProcessMenu(int32_t choice)
1225 {
1226     if (choice == GET_RENDER_POSITION + 1) {
1227         return;
1228     }
1229 
1230     if (g_render == NULL && choice != 1) {
1231         AUDIO_FUNC_LOGE("This render already release!");
1232         SystemInputFail();
1233         return;
1234     }
1235 
1236     for (int32_t i = RENDER_START; i <= GET_RENDER_POSITION; ++i) {
1237         if ((choice == (int32_t)g_processRenderMenuSwitchList[i - 1].cmd) &&
1238             (g_processRenderMenuSwitchList[i - 1].operation != NULL)) {
1239             g_processRenderMenuSwitchList[i - 1].operation(&g_render);
1240         }
1241     }
1242 }
1243 
Choice(void)1244 static void Choice(void)
1245 {
1246     int32_t choice = 0;
1247 
1248     while (choice < GET_RENDER_POSITION + 1 && choice >= 0) {
1249         system("clear");
1250         PrintMenu2();
1251         printf("your choice is:\n");
1252 
1253         int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
1254         if (ret < 0) {
1255             continue;
1256         }
1257 
1258         if (choice < RENDER_START || choice > GET_RENDER_POSITION + 1) {
1259             AUDIO_FUNC_LOGE("You input is wrong!");
1260             choice = 0;
1261             SystemInputFail();
1262             continue;
1263         }
1264         ProcessMenu(choice);
1265     }
1266 }
1267 
main(int32_t argc,char const * argv[])1268 int32_t main(int32_t argc, char const *argv[])
1269 {
1270     if (argc < 2 || argv == NULL || argv[0] == NULL) { // The parameter number is not greater than 2
1271         printf("usage:[1]sample [2]/data/test.wav\n");
1272         return 0;
1273     }
1274 
1275     if (argv[1] == NULL || strlen(argv[1]) == 0) {
1276         return HDF_FAILURE;
1277     }
1278 
1279     int32_t ret = strncpy_s(g_path, PATH_LEN - 1, argv[1], strlen(argv[1]) + 1);
1280     if (ret != 0) {
1281         AUDIO_FUNC_LOGE("strncpy_s Fail!");
1282         return HDF_FAILURE;
1283     }
1284 
1285     char pathBuf[PATH_MAX] = {'\0'};
1286     if (realpath(g_path, pathBuf) == NULL) {
1287         AUDIO_FUNC_LOGE("realpath Fail!");
1288         return HDF_FAILURE;
1289     }
1290 
1291     if (InitParam() != HDF_SUCCESS) { // init
1292         AUDIO_FUNC_LOGE("InitParam Fail!");
1293         return HDF_FAILURE;
1294     }
1295 
1296     Choice();
1297 
1298     if (g_render != NULL && g_adapter != NULL) {
1299         StopAudioFiles(&g_render);
1300     }
1301 
1302     if (g_audioManager != NULL && g_audioManager->UnloadAdapter != NULL) {
1303         g_audioManager->UnloadAdapter(g_audioManager, g_adapterName);
1304         IAudioAdapterRelease(g_adapter, g_isDirect);
1305         g_adapter = NULL;
1306         IAudioManagerRelease(g_audioManager, g_isDirect);
1307         g_audioManager = NULL;
1308     }
1309     return 0;
1310 }
1311