/* * Copyright (c) 2022-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include "framework_common.h" #include "hdf_base.h" #include "inttypes.h" #include "osal_mem.h" #include "v4_0/audio_types.h" #include "v4_0/iaudio_manager.h" #define MAX_AUDIO_ADAPTER_DESC 5 #define BUFFER_LEN 256 #define AUDIO_CHANNELCOUNT 2 #define AUDIO_SAMPLE_RATE_48K 48000 #define PATH_LEN 256 #define DEEP_BUFFER_RENDER_PERIOD_SIZE 4096 #define INT_32_MAX 0x7fffffff #define EXT_PARAMS_MAXLEN 107 #define BITS_TO_FROMAT 3 struct StrPara { struct IAudioRender *render; FILE *file; struct AudioSampleAttributes attrs; uint64_t *replyBytes; char *frame; int32_t bufferSize; }; struct IAudioRender *g_render = NULL; struct IAudioAdapter *g_adapter = NULL; static struct IAudioManager *g_audioManager = NULL; struct AudioDeviceDescriptor g_devDesc; struct AudioSampleAttributes g_attrs; struct AudioPort g_audioPort; struct AudioHeadInfo g_wavHeadInfo; static struct StrPara g_str; uint32_t g_renderId = 0; pthread_t g_tids; char *g_frame = NULL; FILE *g_file; char g_path[256]; char g_adapterName[PATH_LEN] = {0}; static int32_t g_closeEnd = 0; pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t g_functionCond = PTHREAD_COND_INITIALIZER; bool g_waitSleep = false; bool g_isDirect = true; enum RenderMenuId { RENDER_START = 1, RENDER_STOP, RENDER_RESUME, RENDER_PAUSE, SET_RENDER_VOLUME, SET_RENDER_GAIN, SET_RENDER_MUTE, SET_RENDER_ATTRIBUTES, SET_RENDER_SLECET_SCENE, GET_RENDER_EXT_PARAMS, GET_RENDER_POSITION, }; enum RenderInputType { INPUT_INT = 0, INPUT_FLOAT, INPUT_UINT32, }; typedef int32_t (*AudioRenderOperation)(struct IAudioRender **); struct ProcessRenderMenuSwitchList { enum RenderMenuId cmd; AudioRenderOperation operation; }; static int32_t CheckInputName(int type, void *val) { if (val == NULL) { return HDF_FAILURE; } int ret; int inputInt = 0; float inputFloat = 0.0; uint32_t inputUint = 0; printf("\n"); switch (type) { case INPUT_INT: ret = scanf_s("%d", &inputInt); if (inputInt < 0 || inputInt > GET_RENDER_POSITION + 1) { if (g_frame != NULL) { OsalMemFree(g_frame); g_frame = NULL; } AUDIO_FUNC_LOGE("Input failure"); return HDF_FAILURE; } *(int *)val = inputInt; break; case INPUT_FLOAT: ret = scanf_s("%f", &inputFloat); *(float *)val = inputFloat; break; case INPUT_UINT32: ret = scanf_s("%u", &inputUint); if (inputUint > 0xFFFFFFFF) { return HDF_FAILURE; } *(uint32_t *)val = inputUint; break; default: ret = EOF; break; } if (ret == 0) { CleanStdin(); } else if (ret == EOF) { AUDIO_FUNC_LOGE("Input failure occurs!"); return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t InitAttrs(struct AudioSampleAttributes *attrs) { if (attrs == NULL) { return HDF_FAILURE; } /* Initialization of audio parameters for playback */ attrs->format = AUDIO_FORMAT_TYPE_PCM_16_BIT; attrs->channelCount = AUDIO_CHANNELCOUNT; attrs->sampleRate = AUDIO_SAMPLE_RATE_48K; attrs->interleaved = 0; attrs->type = AUDIO_IN_MEDIA; attrs->period = DEEP_BUFFER_RENDER_PERIOD_SIZE; attrs->frameSize = PCM_16_BIT * attrs->channelCount / PCM_8_BIT; attrs->isBigEndian = false; attrs->isSignedData = true; attrs->startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs->frameSize); attrs->stopThreshold = INT_32_MAX; attrs->silenceThreshold = 0; return HDF_SUCCESS; } static int32_t InitDevDesc(struct AudioDeviceDescriptor *devDesc, uint32_t portId) { if (devDesc == NULL) { return HDF_FAILURE; } /* Initialization of audio parameters for playback */ devDesc->portId = portId; devDesc->pins = PIN_OUT_SPEAKER; devDesc->desc = strdup("cardname"); return HDF_SUCCESS; } static void StreamClose(int32_t sig) { /* allow the stream to be closed gracefully */ (void)signal(sig, SIG_IGN); g_closeEnd = 1; } static uint32_t PcmFramesToBytes(const struct AudioSampleAttributes attrs) { return DEEP_BUFFER_RENDER_PERIOD_SIZE * attrs.channelCount * (PcmFormatToBits(attrs.format) >> BITS_TO_FROMAT); } static int32_t StopAudioFiles(struct IAudioRender **renderS) { if (renderS == NULL) { return HDF_FAILURE; } if (g_waitSleep) { pthread_mutex_lock(&g_mutex); g_waitSleep = false; pthread_cond_signal(&g_functionCond); pthread_mutex_unlock(&g_mutex); } if (!g_closeEnd) { g_closeEnd = true; usleep(100000); // sleep 100000us } struct IAudioRender *render = *renderS; if (render == NULL) { AUDIO_FUNC_LOGE("render is null"); return HDF_FAILURE; } int32_t ret = render->Stop((void *)render); if (ret < 0) { AUDIO_FUNC_LOGE("Stop Render!"); } if (g_adapter == NULL || g_adapter->DestroyRender == NULL) { return HDF_FAILURE; } ret = g_adapter->DestroyRender(g_adapter, g_renderId); if (ret < 0) { AUDIO_FUNC_LOGE("Destroy Render!"); } IAudioRenderRelease(render, g_isDirect); *renderS = NULL; g_render = NULL; if (g_frame != NULL) { OsalMemFree(g_frame); g_frame = NULL; } if (g_file != NULL) { fclose(g_file); g_file = NULL; } printf("Stop Successful\n"); return ret; } static int32_t FrameStartMmap(const struct StrPara *param) { if (param == NULL) { return HDF_FAILURE; } const struct StrPara *strParam = param; struct IAudioRender *render = strParam->render; struct AudioMmapBufferDescriptor mmapDesc; (void)signal(SIGINT, StreamClose); // get file length char pathBuf[PATH_MAX] = {'\0'}; if (realpath(g_path, pathBuf) == NULL) { return HDF_FAILURE; } // get fileSize FILE *fp = fopen(pathBuf, "rb+"); if (fp == NULL) { printf("Open file failed!\n"); return HDF_FAILURE; } int32_t ret = fseek(fp, 0, SEEK_END); if (ret != 0) { fclose(fp); return HDF_FAILURE; } int32_t reqSize = (int32_t)ftell(fp); if (reqSize < 0) { fclose(fp); return HDF_FAILURE; } (void)fclose(fp); // Init param mmapDesc.memoryFd = 0; // default 0 mmapDesc.filePath = strdup(pathBuf); mmapDesc.isShareable = 1; // 1:Shareable ,0:Don't share mmapDesc.transferFrameSize = DEEP_BUFFER_RENDER_PERIOD_SIZE / 4; // One frame size 4 bit mmapDesc.offset = sizeof(g_wavHeadInfo); // start if (render == NULL || render->ReqMmapBuffer == NULL) { free(mmapDesc.filePath); return HDF_FAILURE; } ret = render->ReqMmapBuffer(render, reqSize, &mmapDesc); if (ret < 0 || reqSize <= 0) { free(mmapDesc.filePath); printf("Request map fail,please check.\n"); return HDF_FAILURE; } if (g_render != NULL) { ret = StopAudioFiles(&render); if (ret < 0) { free(mmapDesc.filePath); AUDIO_FUNC_LOGE("StopAudioFiles File!"); } } free(mmapDesc.filePath); return HDF_SUCCESS; } static int32_t FrameStart(const struct StrPara *param) { if (param == NULL) { return HDF_FAILURE; } size_t numRead; char *frame = param->frame; int32_t bufferSize = param->bufferSize; struct IAudioRender *render = param->render; size_t remainingDataSize = g_wavHeadInfo.riffSize; (void)signal(SIGINT, StreamClose); if (g_file == NULL) { return HDF_FAILURE; } if (render == NULL || render->RenderFrame == NULL || frame == NULL) { return HDF_FAILURE; } do { uint64_t replyBytes = 0; size_t readSize = (remainingDataSize > bufferSize) ? (size_t)bufferSize : remainingDataSize; numRead = fread(frame, 1, readSize, g_file); if (numRead > 0) { int32_t ret = render->RenderFrame(render, (int8_t *)frame, numRead, &replyBytes); if (ret == HDF_ERR_INVALID_OBJECT) { AUDIO_FUNC_LOGE("Render already stop!"); break; } remainingDataSize -= numRead; } while (g_waitSleep) { printf("music pause now.\n"); pthread_cond_wait(&g_functionCond, &g_mutex); printf("music resume now.\n"); } } while (!g_closeEnd && numRead > 0 && remainingDataSize > 0); if (!g_closeEnd) { printf("\nPlay complete, please select input again\n"); (void)StopAudioFiles(&render); } return HDF_SUCCESS; } static int32_t InitPlayingAudioParam(struct IAudioRender *render) { if (render == NULL) { return HDF_FAILURE; } uint64_t frameSize = 0; uint64_t frameCount = 0; uint64_t bufferSize = 0; if (render->GetFrameSize(render, &frameSize) != HDF_SUCCESS) { AUDIO_FUNC_LOGE("get frame size failed"); } if (render->GetFrameCount(render, &frameCount) != HDF_SUCCESS) { AUDIO_FUNC_LOGE("get frame count failed"); } bufferSize = frameCount * frameSize; if (bufferSize == 0) { bufferSize = PcmFramesToBytes(g_attrs); AUDIO_FUNC_LOGE("buffer size by calc is %" PRIu64 "", bufferSize); } g_frame = (char *)OsalMemCalloc(bufferSize); if (g_frame == NULL) { return HDF_FAILURE; } (void)memset_s(&g_str, sizeof(struct StrPara), 0, sizeof(struct StrPara)); g_str.render = render; g_str.bufferSize = (int32_t)bufferSize; g_str.frame = g_frame; return HDF_SUCCESS; } static void PrintPlayMode(void) { printf(" ============= Play Render Mode ==========\n"); printf("| 1. Render non-mmap |\n"); printf("| 2. Render mmap |\n"); printf(" ======================================== \n"); } static int32_t SelectPlayMode(int32_t *palyModeFlag) { if (palyModeFlag == NULL) { AUDIO_FUNC_LOGE("palyModeFlag is null"); return HDF_FAILURE; } int choice = 0; system("clear"); PrintPlayMode(); printf("Please enter your choice:"); int32_t ret = CheckInputName(INPUT_INT, (void *)&choice); if (ret < 0) { AUDIO_FUNC_LOGE("CheckInputName Fail"); return HDF_FAILURE; } else { *palyModeFlag = choice; } return HDF_SUCCESS; } static int32_t StartPlayThread(int32_t palyModeFlag) { pthread_attr_t tidsAttr; pthread_attr_init(&tidsAttr); pthread_attr_setdetachstate(&tidsAttr, PTHREAD_CREATE_DETACHED); switch (palyModeFlag) { case 1: // 1. Stander Loading if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) { AUDIO_FUNC_LOGE("Create Thread Fail"); return HDF_FAILURE; } break; case 2: // 2. Low latency Loading if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStartMmap), &g_str) != 0) { AUDIO_FUNC_LOGE("Create Thread Fail"); return HDF_FAILURE; } break; default: printf("Input error,Switched to non-mmap Mode for you.\n"); SystemInputFail(); if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) { AUDIO_FUNC_LOGE("Create Thread Fail"); return HDF_FAILURE; } break; } return HDF_SUCCESS; } static int32_t PlayingAudioInitFile(void) { if (g_file != NULL) { AUDIO_FUNC_LOGE("the music is playing,please stop first"); return HDF_FAILURE; } g_closeEnd = false; char pathBuf[PATH_MAX] = {'\0'}; if (realpath(g_path, pathBuf) == NULL) { return HDF_FAILURE; } g_file = fopen(pathBuf, "rb"); if (g_file == NULL) { printf("failed to open '%s'\n", g_path); return HDF_FAILURE; } if (CheckWavFileHeader(g_file, &g_wavHeadInfo, &g_attrs) < 0) { FileClose(&g_file); return HDF_FAILURE; } (void)chmod(g_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); return HDF_SUCCESS; } static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp) { if (renderTemp == NULL) { AUDIO_FUNC_LOGE("render is null"); return HDF_FAILURE; } struct IAudioRender *render = NULL; if (g_adapter == NULL || g_adapter->CreateRender == NULL) { return HDF_FAILURE; } int32_t ret = g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &render, &g_renderId); if (render == NULL || ret < 0 || render->RenderFrame == NULL) { AUDIO_FUNC_LOGE("AudioDeviceCreateRender failed or RenderFrame is null"); return HDF_FAILURE; } // Playing audio files if (render->Start((void *)render)) { AUDIO_FUNC_LOGE("Start Bind Fail!"); g_adapter->DestroyRender(g_adapter, g_renderId); IAudioRenderRelease(render, g_isDirect); return HDF_FAILURE; } if (InitPlayingAudioParam(render) < 0) { g_adapter->DestroyRender(g_adapter, g_renderId); IAudioRenderRelease(render, g_isDirect); return HDF_FAILURE; } *renderTemp = render; return HDF_SUCCESS; } static int32_t PlayingAudioFiles(struct IAudioRender **renderS) { if (renderS == NULL || g_adapter == NULL) { return HDF_FAILURE; } if (PlayingAudioInitFile() < 0) { AUDIO_FUNC_LOGE("PlayingAudioInitFile Fail"); return HDF_FAILURE; } int32_t palyModeFlag = 0; if (SelectPlayMode(&palyModeFlag) < 0) { AUDIO_FUNC_LOGE("SelectPlayMode Fail"); FileClose(&g_file); return HDF_FAILURE; } struct IAudioRender *render = NULL; if (PlayingAudioInitRender(&render) < 0) { AUDIO_FUNC_LOGE("PlayingAudioInitRender fail"); FileClose(&g_file); return HDF_FAILURE; } if (StartPlayThread(palyModeFlag) < 0) { FileClose(&g_file); if (g_adapter != NULL && g_adapter->DestroyRender != NULL) { g_adapter->DestroyRender(g_adapter, g_renderId); } IAudioRenderRelease(render, g_isDirect); return HDF_FAILURE; } *renderS = render; printf("Start Successful,Music is playing\n"); return HDF_SUCCESS; } static int32_t SelectLoadingMode(void) { int choice = 0; system("clear"); PrintLoadModeMenu(); printf("Please enter your choice:"); int32_t ret = CheckInputName(INPUT_INT, (void *)&choice); if (ret < 0) { return HDF_FAILURE; } switch (choice) { case 1: // 1 is Passthrough Loading g_isDirect = true; break; case 2: // 2 is IPC Loading g_isDirect = false; break; default: printf("Input error,Switched to direct loading in for you.\n"); SystemInputFail(); g_isDirect = true; break; } return HDF_SUCCESS; } void AudioAdapterDescriptorFree(struct AudioAdapterDescriptor *dataBlock, bool freeSelf) { if (dataBlock == NULL) { return; } if (dataBlock->adapterName != NULL) { OsalMemFree(dataBlock->adapterName); dataBlock->adapterName = NULL; } if (dataBlock->ports != NULL) { OsalMemFree(dataBlock->ports); } if (freeSelf) { OsalMemFree(dataBlock); } } static void ReleaseAdapterDescs(struct AudioAdapterDescriptor **descs, uint32_t descsLen) { if (descsLen > 0 && descs != NULL && (*descs) != NULL) { for (uint32_t i = 0; i < descsLen; i++) { AudioAdapterDescriptorFree(&(*descs)[i], false); } OsalMemFree(*descs); *descs = NULL; } } static int32_t GetManagerAndLoadAdapter(struct AudioPort *renderPort) { int32_t adapterIndex = 0; if (renderPort == NULL) { AUDIO_FUNC_LOGE("The Parameter is NULL"); return HDF_FAILURE; } struct IAudioManager *audioManagerIns = IAudioManagerGet(g_isDirect); if (audioManagerIns == NULL) { AUDIO_FUNC_LOGE("Get audio Manager Fail"); return HDF_FAILURE; } g_audioManager = audioManagerIns; struct AudioAdapterDescriptor *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc( sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC)); if (descs == NULL) { AUDIO_FUNC_LOGE("OsalMemCalloc for descs failed"); return HDF_FAILURE; } uint32_t adapterNum = MAX_AUDIO_ADAPTER_DESC; int32_t ret = audioManagerIns->GetAllAdapters(audioManagerIns, descs, &adapterNum); if (ret < 0 || adapterNum == 0) { AUDIO_FUNC_LOGE("Get All Adapters Fail"); ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC); return HDF_ERR_NOT_SUPPORT; } if (SelectAudioCard(descs, adapterNum, &adapterIndex) != HDF_SUCCESS) { ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC); return HDF_ERR_NOT_SUPPORT; } if (strcpy_s(g_adapterName, PATH_LEN, descs[adapterIndex - 1].adapterName) < 0) { ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC); return HDF_ERR_NOT_SUPPORT; } if (SwitchAudioPort(&descs[adapterIndex - 1], PORT_OUT, renderPort) != HDF_SUCCESS) { ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC); return HDF_ERR_NOT_SUPPORT; } if (audioManagerIns->LoadAdapter(audioManagerIns, &descs[adapterIndex - 1], &g_adapter)) { AUDIO_FUNC_LOGE("Load Adapter Fail"); ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC); return HDF_ERR_NOT_SUPPORT; } ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC); return HDF_SUCCESS; } static int32_t InitRenderParam(uint32_t portId) { if (g_adapter == NULL || g_adapter->InitAllPorts == NULL) { return HDF_FAILURE; } // Initialization port information, can fill through mode and other parameters (void)g_adapter->InitAllPorts(g_adapter); // User needs to set if (InitAttrs(&g_attrs) < 0) { AUDIO_FUNC_LOGE("InitAttrs failed"); return HDF_FAILURE; } // Specify a hardware device if (InitDevDesc(&g_devDesc, portId) < 0) { AUDIO_FUNC_LOGE("InitDevDesc failed"); return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t RenderGetAdapterAndInitEnvParams(void) { struct AudioPort renderPort; int32_t ret = GetManagerAndLoadAdapter(&renderPort); if (ret < 0) { return ret; } if (InitRenderParam(renderPort.portId) < 0) { g_audioManager->UnloadAdapter(g_audioManager, g_adapterName); IAudioAdapterRelease(g_adapter, g_isDirect); g_adapter = NULL; return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t InitParam(void) { if (SelectLoadingMode() < 0) { return HDF_FAILURE; } /* Select loading mode,end */ g_audioPort.dir = PORT_OUT; g_audioPort.portId = 0; g_audioPort.portName = "AOP"; if (RenderGetAdapterAndInitEnvParams() < 0) { AUDIO_FUNC_LOGE("GetProxyManagerFunc Fail"); if (g_audioManager != NULL) { IAudioManagerRelease(g_audioManager, g_isDirect); g_audioManager = NULL; } return HDF_FAILURE; } return HDF_SUCCESS; } static int32_t SetRenderMute(struct IAudioRender **render) { (void)render; if (g_render == NULL || g_render->GetMute == NULL) { return HDF_FAILURE; } int32_t val; bool isMute = false; int32_t ret = g_render->GetMute((void *)g_render, &isMute); if (ret < 0) { AUDIO_FUNC_LOGE("The current mute state was not obtained!"); } printf("Now %s ,Do you need to set mute status(1/0):", isMute ? "mute" : "not mute"); ret = CheckInputName(INPUT_INT, (void *)&val); if (ret < 0) { return HDF_FAILURE; } if (g_render == NULL || g_render->SetMute == NULL) { AUDIO_FUNC_LOGE("Music already stop!"); SystemInputFail(); return HDF_FAILURE; } if (val == 1) { ret = g_render->SetMute((void *)g_render, !isMute); } return ret; } static int32_t SetRenderVolume(struct IAudioRender **render) { (void)render; if (g_render == NULL || g_render->GetVolume == NULL) { return HDF_FAILURE; } int32_t ret; float val = 0.0; ret = g_render->GetVolume((void *)g_render, &val); if (ret < 0) { AUDIO_FUNC_LOGE("Get current volume failed!"); SystemInputFail(); return ret; } printf("Now the volume is %f ,Please enter the volume value you want to set (0.0-1.0):", val); ret = CheckInputName(INPUT_FLOAT, (void *)&val); if (ret < 0) { return HDF_FAILURE; } if (val < 0.0 || val > 1.0) { AUDIO_FUNC_LOGE("Invalid volume value!"); SystemInputFail(); return HDF_FAILURE; } if (g_render == NULL || g_render->SetVolume == NULL) { AUDIO_FUNC_LOGE("Music already stop!"); SystemInputFail(); return HDF_FAILURE; } ret = g_render->SetVolume((void *)g_render, val); if (ret < 0) { AUDIO_FUNC_LOGE("set volume fail!"); SystemInputFail(); } return ret; } static int32_t GetRenderGain(struct IAudioRender **render) { (void)render; if (g_render == NULL || g_render->GetGain == NULL) { return HDF_FAILURE; } float val = 1.0; int32_t ret = g_render->GetGain((void *)g_render, &val); if (ret < 0) { AUDIO_FUNC_LOGE("Get current gain failed!"); SystemInputFail(); return HDF_FAILURE; } printf("Now the gain is %f,", val); SystemInputFail(); return HDF_SUCCESS; } static int32_t SetRenderPause(struct IAudioRender **render) { (void)render; if (g_waitSleep) { AUDIO_FUNC_LOGE("Already pause,not need pause again!"); SystemInputFail(); return HDF_FAILURE; } if (g_render == NULL || g_render->Pause == NULL) { return HDF_FAILURE; } int32_t ret = g_render->Pause((void *)g_render); if (ret != 0) { return HDF_FAILURE; } printf("Pause success!\n"); g_waitSleep = true; return HDF_SUCCESS; } static int32_t SetRenderResume(struct IAudioRender **render) { (void)render; if (!g_waitSleep) { AUDIO_FUNC_LOGE("Now is Playing,not need resume!"); SystemInputFail(); return HDF_FAILURE; } if (g_render == NULL || g_render->Resume == NULL) { return HDF_FAILURE; } int32_t ret = g_render->Resume((void *)g_render); if (ret != 0) { return HDF_FAILURE; } printf("resume success!\n"); pthread_mutex_lock(&g_mutex); g_waitSleep = false; pthread_cond_signal(&g_functionCond); pthread_mutex_unlock(&g_mutex); return HDF_SUCCESS; } static void PrintAttributesFromat(void) { printf(" ============= Render Sample Attributes Fromat =============== \n"); printf("| 1. Render AUDIO_FORMAT_TYPE_PCM_8_BIT |\n"); printf("| 2. Render AUDIO_FORMAT_TYPE_PCM_16_BIT |\n"); printf("| 3. Render AUDIO_FORMAT_TYPE_PCM_24_BIT |\n"); printf("| 4. Render AUDIO_FORMAT_TYPE_PCM_32_BIT |\n"); printf(" ============================================================= \n"); } static int32_t SelectAttributesFomat(uint32_t *pcmFomat) { if (pcmFomat == NULL) { AUDIO_FUNC_LOGE("fomat is null!"); return HDF_FAILURE; } int val = 0; PrintAttributesFromat(); printf("Please select audio format,If not selected, the default is 16bit:"); int32_t ret = CheckInputName(INPUT_INT, (void *)&val); if (ret < 0) { AUDIO_FUNC_LOGE("CheckInputName failed."); return HDF_FAILURE; } switch (val) { case AUDIO_FORMAT_TYPE_PCM_8_BIT: *pcmFomat = AUDIO_FORMAT_TYPE_PCM_8_BIT; break; case AUDIO_FORMAT_TYPE_PCM_16_BIT: *pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT; break; case AUDIO_FORMAT_TYPE_PCM_24_BIT: *pcmFomat = AUDIO_FORMAT_TYPE_PCM_24_BIT; break; case AUDIO_FORMAT_TYPE_PCM_32_BIT: *pcmFomat = AUDIO_FORMAT_TYPE_PCM_32_BIT; break; default: *pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT; break; } return HDF_SUCCESS; } static int32_t SetRenderAttributes(struct IAudioRender **render) { (void)render; struct AudioSampleAttributes attrs; if (g_render == NULL || g_render->GetSampleAttributes == NULL) { AUDIO_FUNC_LOGE("The pointer is null!"); return HDF_FAILURE; } int32_t ret = g_render->GetSampleAttributes((void *)g_render, &attrs); if (ret < 0) { AUDIO_FUNC_LOGE("GetRenderAttributes failed!"); } else { printf("Current sample attributes:\n"); printf("audioType is %u\nfomat is %u\nsampleRate is %u\nchannalCount is" "%u\nperiod is %u\nframesize is %u\nbigEndian is %u\nSignedData is %u\n", attrs.type, attrs.format, attrs.sampleRate, attrs.channelCount, attrs.period, attrs.frameSize, attrs.isBigEndian, attrs.isSignedData); } printf("Set Sample Attributes,"); SystemInputFail(); system("clear"); printf("The sample attributes you want to set,Step by step, please.\n"); ret = SelectAttributesFomat((uint32_t *)(&attrs.format)); if (ret < 0) { AUDIO_FUNC_LOGE("SetRenderAttributes format failed!"); return HDF_FAILURE; } printf("\nPlease input sample rate(48000,44100,32000...):"); ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.sampleRate)); if (ret < 0) { return HDF_FAILURE; } printf("\nPlease input bigEndian(false=0/true=1):"); ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.isBigEndian)); if (ret < 0) { return HDF_FAILURE; } if (g_render == NULL || g_render->SetSampleAttributes == NULL) { AUDIO_FUNC_LOGE("Music already complete,Please replay and set the attrbutes!"); SystemInputFail(); return HDF_FAILURE; } ret = g_render->SetSampleAttributes((void *)g_render, &attrs); if (ret < 0) { AUDIO_FUNC_LOGE("Set render attributes failed!"); SystemInputFail(); } return ret; } static int32_t PrintRenderSelectPinFirst(struct AudioSceneDescriptor *scene) { system("clear"); printf(" ==================== Select Pin ===================== \n"); printf("| 0. Speaker |\n"); printf("| 1. HeadPhones |\n"); printf(" ===================================================== \n"); printf("Please input your choice:\n"); int32_t val = 0; int32_t ret = CheckInputName(INPUT_INT, (void *)&val); if (ret < 0) { AUDIO_FUNC_LOGE("Invalid value!"); SystemInputFail(); return HDF_FAILURE; } if (val == 1) { scene->desc.pins = PIN_OUT_HEADSET; } else { scene->desc.pins = PIN_OUT_SPEAKER; } return HDF_SUCCESS; } static int32_t PrintRenderSelectPinSecond(struct AudioSceneDescriptor *scene) { system("clear"); printf(" ==================== Select Pin ===================== \n"); printf("| 0. Speaker |\n"); printf("| 1. HeadPhones |\n"); printf("| 2. Speaker and HeadPhones |\n"); printf(" ===================================================== \n"); printf("Please input your choice:\n"); int32_t val = 0; int32_t ret = CheckInputName(INPUT_INT, (void *)&val); if (ret < 0) { AUDIO_FUNC_LOGE("Invalid value!"); SystemInputFail(); return HDF_FAILURE; } if (val == 1) { scene->desc.pins = PIN_OUT_HEADSET; } else if (val == 0) { scene->desc.pins = PIN_OUT_SPEAKER; } else { scene->desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET; } return HDF_SUCCESS; } static int32_t PrintRenderSelectPinThird(struct AudioSceneDescriptor *scene) { system("clear"); printf(" ==================== Select Pin ===================== \n"); printf("| 0. Speaker |\n"); printf("| 1. HeadPhones |\n"); printf(" ===================================================== \n"); printf("Please input your choice:\n"); int32_t val = 0; int32_t ret = CheckInputName(INPUT_INT, (void *)&val); if (ret < 0) { AUDIO_FUNC_LOGE("Invalid value!"); SystemInputFail(); return HDF_FAILURE; } if (val == 1) { scene->desc.pins = PIN_OUT_HEADSET; } else { scene->desc.pins = PIN_OUT_SPEAKER; } return HDF_SUCCESS; } static void SelectSceneMenu(void) { printf(" =================== Select Scene ======================== \n"); printf("0 is Midea. |\n"); printf("1 is Communication. |\n"); printf("2 is Ring-Tone. |\n"); printf("3 is Voice-Call. |\n"); printf("4 is Mmap. |\n"); printf(" ========================================================= \n"); } static int32_t SelectRenderScene(struct IAudioRender **render) { (void)render; int32_t val = 0; struct AudioSceneDescriptor scene; system("clear"); SelectSceneMenu(); printf("Please input your choice:\n"); int32_t ret = CheckInputName(INPUT_INT, (void *)&val); if (ret < 0) { AUDIO_FUNC_LOGE("Invalid value!"); SystemInputFail(); return HDF_FAILURE; } switch (val) { case AUDIO_IN_MEDIA: scene.scene.id = AUDIO_IN_MEDIA; PrintRenderSelectPinFirst(&scene); break; case AUDIO_IN_COMMUNICATION: scene.scene.id = AUDIO_IN_COMMUNICATION; PrintRenderSelectPinSecond(&scene); break; case AUDIO_IN_RINGTONE: scene.scene.id = AUDIO_IN_RINGTONE; scene.desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET; break; case AUDIO_IN_CALL: scene.scene.id = AUDIO_IN_CALL; PrintRenderSelectPinThird(&scene); break; case AUDIO_MMAP_NOIRQ: scene.scene.id = AUDIO_MMAP_NOIRQ; PrintRenderSelectPinFirst(&scene); break; default: break; } scene.desc.desc = "mic"; if (g_render == NULL || g_render->SelectScene == NULL) { AUDIO_FUNC_LOGE("Music already stop,"); SystemInputFail(); return HDF_FAILURE; } ret = g_render->SelectScene((void *)g_render, &scene); if (ret < 0) { AUDIO_FUNC_LOGE("Select scene fail\n"); } return ret; } static int32_t GetExtParams(struct IAudioRender **render) { (void)render; if (g_render == NULL || g_render->GetExtraParams == NULL) { return HDF_FAILURE; } char keyValueList[BUFFER_LEN] = {0}; int32_t ret = g_render->GetExtraParams((void *)g_render, keyValueList, EXT_PARAMS_MAXLEN); if (ret < 0) { AUDIO_FUNC_LOGE("Get EXT params failed!"); SystemInputFail(); return HDF_FAILURE; } printf("keyValueList = %s\n", keyValueList); return HDF_SUCCESS; } static int32_t GetRenderMmapPosition(struct IAudioRender **render) { (void)render; if (g_render == NULL || g_render->GetMmapPosition == NULL) { return HDF_FAILURE; } uint64_t frames = 0; struct AudioTimeStamp time; time.tvNSec = 0; time.tvSec = 0; int32_t ret = g_render->GetMmapPosition((void *)g_render, &frames, &time); if (ret < 0) { AUDIO_FUNC_LOGE("Get current Mmap frames Position failed!"); SystemInputFail(); return HDF_FAILURE; } printf("Now the Position is %" PRIu64 "\n", frames); return HDF_SUCCESS; } static void PrintMenu2(void) { printf(" ================== Play Render Menu ================== \n"); printf("| 1. Render Start |\n"); printf("| 2. Render Stop |\n"); printf("| 3. Render Resume |\n"); printf("| 4. Render Pause |\n"); printf("| 5. Render SetVolume |\n"); printf("| 6. Render GetGain |\n"); printf("| 7. Render SetMute |\n"); printf("| 8. Render SetAttributes |\n"); printf("| 9. Render SelectScene |\n"); printf("| 10. Render getEXtParams |\n"); printf("| 11. Render getMmapPosition |\n"); printf("| 12.Exit |\n"); printf(" ====================================================== \n"); } static struct ProcessRenderMenuSwitchList g_processRenderMenuSwitchList[] = { {RENDER_START, PlayingAudioFiles }, {RENDER_STOP, StopAudioFiles }, {RENDER_RESUME, SetRenderResume }, {RENDER_PAUSE, SetRenderPause }, {SET_RENDER_VOLUME, SetRenderVolume }, {SET_RENDER_GAIN, GetRenderGain }, {SET_RENDER_MUTE, SetRenderMute }, {SET_RENDER_ATTRIBUTES, SetRenderAttributes }, {SET_RENDER_SLECET_SCENE, SelectRenderScene }, {GET_RENDER_EXT_PARAMS, GetExtParams }, {GET_RENDER_POSITION, GetRenderMmapPosition}, }; static void ProcessMenu(int32_t choice) { if (choice == GET_RENDER_POSITION + 1) { return; } if (g_render == NULL && choice != 1) { AUDIO_FUNC_LOGE("This render already release!"); SystemInputFail(); return; } for (int32_t i = RENDER_START; i <= GET_RENDER_POSITION; ++i) { if ((choice == (int32_t)g_processRenderMenuSwitchList[i - 1].cmd) && (g_processRenderMenuSwitchList[i - 1].operation != NULL)) { g_processRenderMenuSwitchList[i - 1].operation(&g_render); } } } static void Choice(void) { int32_t choice = 0; while (choice < GET_RENDER_POSITION + 1 && choice >= 0) { system("clear"); PrintMenu2(); printf("your choice is:\n"); int32_t ret = CheckInputName(INPUT_INT, (void *)&choice); if (ret < 0) { continue; } if (choice < RENDER_START || choice > GET_RENDER_POSITION + 1) { AUDIO_FUNC_LOGE("You input is wrong!"); choice = 0; SystemInputFail(); continue; } ProcessMenu(choice); } } int32_t main(int32_t argc, char const *argv[]) { if (argc < 2 || argv == NULL || argv[0] == NULL) { // The parameter number is not greater than 2 printf("usage:[1]sample [2]/data/test.wav\n"); return 0; } if (argv[1] == NULL || strlen(argv[1]) == 0) { return HDF_FAILURE; } int32_t ret = strncpy_s(g_path, PATH_LEN - 1, argv[1], strlen(argv[1]) + 1); if (ret != 0) { AUDIO_FUNC_LOGE("strncpy_s Fail!"); return HDF_FAILURE; } char pathBuf[PATH_MAX] = {'\0'}; if (realpath(g_path, pathBuf) == NULL) { AUDIO_FUNC_LOGE("realpath Fail!"); return HDF_FAILURE; } if (InitParam() != HDF_SUCCESS) { // init AUDIO_FUNC_LOGE("InitParam Fail!"); return HDF_FAILURE; } Choice(); if (g_render != NULL && g_adapter != NULL) { StopAudioFiles(&g_render); } if (g_audioManager != NULL && g_audioManager->UnloadAdapter != NULL) { g_audioManager->UnloadAdapter(g_audioManager, g_adapterName); IAudioAdapterRelease(g_adapter, g_isDirect); g_adapter = NULL; IAudioManagerRelease(g_audioManager, g_isDirect); g_audioManager = NULL; } return 0; }