/* * Copyright (C) 2011 The Android Open Source Project * * 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 "EffectBundle.h" #include "LVM_Private.h" #ifdef VERY_VERY_VERBOSE_LOGGING #define ALOGVV ALOGV #else #define ALOGVV(a...) \ do { \ } while (false) #endif #define CHECK_ARG(cond) \ { \ if (!(cond)) { \ ALOGE("\tLVM_ERROR : Invalid argument: " #cond); \ return -EINVAL; \ } \ } #define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc) \ { \ if ((LvmStatus) == LVM_NULLADDRESS) { \ ALOGE("\tLVM_ERROR : Parameter error - " \ "null pointer returned by %s in %s\n\n\n\n", \ callingFunc, calledFunc); \ } \ if ((LvmStatus) == LVM_ALIGNMENTERROR) { \ ALOGE("\tLVM_ERROR : Parameter error - " \ "bad alignment returned by %s in %s\n\n\n\n", \ callingFunc, calledFunc); \ } \ if ((LvmStatus) == LVM_INVALIDNUMSAMPLES) { \ ALOGE("\tLVM_ERROR : Parameter error - " \ "bad number of samples returned by %s in %s\n\n\n\n", \ callingFunc, calledFunc); \ } \ if ((LvmStatus) == LVM_OUTOFRANGE) { \ ALOGE("\tLVM_ERROR : Parameter error - " \ "out of range returned by %s in %s\n", \ callingFunc, calledFunc); \ } \ } struct lvmConfigParams_t { int samplingFreq = 44100; int nrChannels = 2; int chMask = AUDIO_CHANNEL_OUT_STEREO; int vcBal = 0; int fChannels = 2; bool monoMode = false; int bassEffectLevel = 0; int eqPresetLevel = 0; int frameLength = 256; int trebleEffectLevel = 0; LVM_BE_Mode_en bassEnable = LVM_BE_OFF; LVM_TE_Mode_en trebleEnable = LVM_TE_OFF; LVM_EQNB_Mode_en eqEnable = LVM_EQNB_OFF; LVM_Mode_en csEnable = LVM_MODE_OFF; }; constexpr audio_channel_mask_t lvmConfigChMask[] = { AUDIO_CHANNEL_OUT_MONO, AUDIO_CHANNEL_OUT_STEREO, AUDIO_CHANNEL_OUT_2POINT1, AUDIO_CHANNEL_OUT_2POINT0POINT2, AUDIO_CHANNEL_OUT_QUAD, AUDIO_CHANNEL_OUT_QUAD_BACK, AUDIO_CHANNEL_OUT_QUAD_SIDE, AUDIO_CHANNEL_OUT_SURROUND, AUDIO_CHANNEL_INDEX_MASK_4, AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2, AUDIO_CHANNEL_OUT_PENTA, AUDIO_CHANNEL_INDEX_MASK_5, AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_5POINT1_BACK, AUDIO_CHANNEL_OUT_5POINT1_SIDE, AUDIO_CHANNEL_INDEX_MASK_6, AUDIO_CHANNEL_OUT_6POINT1, AUDIO_CHANNEL_INDEX_MASK_7, AUDIO_CHANNEL_OUT_5POINT1POINT2, AUDIO_CHANNEL_OUT_7POINT1, AUDIO_CHANNEL_INDEX_MASK_8, AUDIO_CHANNEL_INDEX_MASK_9, AUDIO_CHANNEL_INDEX_MASK_10, AUDIO_CHANNEL_INDEX_MASK_11, AUDIO_CHANNEL_INDEX_MASK_12, AUDIO_CHANNEL_INDEX_MASK_13, AUDIO_CHANNEL_INDEX_MASK_14, AUDIO_CHANNEL_INDEX_MASK_15, AUDIO_CHANNEL_INDEX_MASK_16, AUDIO_CHANNEL_INDEX_MASK_17, AUDIO_CHANNEL_INDEX_MASK_18, AUDIO_CHANNEL_INDEX_MASK_19, AUDIO_CHANNEL_INDEX_MASK_20, AUDIO_CHANNEL_INDEX_MASK_21, AUDIO_CHANNEL_INDEX_MASK_22, AUDIO_CHANNEL_INDEX_MASK_23, AUDIO_CHANNEL_INDEX_MASK_24, }; void printUsage() { printf("\nUsage: "); printf("\n -i: -o: [options]\n"); printf("\nwhere, \n is the input file name"); printf("\n on which LVM effects are applied"); printf("\n processed output file"); printf("\n and options are mentioned below"); printf("\n"); printf("\n -help (or) -h"); printf("\n Prints this usage information"); printf("\n"); printf("\n -chMask:\n"); printf("\n 0 - AUDIO_CHANNEL_OUT_MONO"); printf("\n 1 - AUDIO_CHANNEL_OUT_STEREO"); printf("\n 2 - AUDIO_CHANNEL_OUT_2POINT1"); printf("\n 3 - AUDIO_CHANNEL_OUT_2POINT0POINT2"); printf("\n 4 - AUDIO_CHANNEL_OUT_QUAD"); printf("\n 5 - AUDIO_CHANNEL_OUT_QUAD_BACK"); printf("\n 6 - AUDIO_CHANNEL_OUT_QUAD_SIDE"); printf("\n 7 - AUDIO_CHANNEL_OUT_SURROUND"); printf("\n 8 - canonical channel index mask for 4 ch: (1 << 4) - 1"); printf("\n 9 - AUDIO_CHANNEL_OUT_2POINT1POINT2"); printf("\n 10 - AUDIO_CHANNEL_OUT_3POINT0POINT2"); printf("\n 11 - AUDIO_CHANNEL_OUT_PENTA"); printf("\n 12 - canonical channel index mask for 5 ch: (1 << 5) - 1"); printf("\n 13 - AUDIO_CHANNEL_OUT_3POINT1POINT2"); printf("\n 14 - AUDIO_CHANNEL_OUT_5POINT1"); printf("\n 15 - AUDIO_CHANNEL_OUT_5POINT1_BACK"); printf("\n 16 - AUDIO_CHANNEL_OUT_5POINT1_SIDE"); printf("\n 17 - canonical channel index mask for 6 ch: (1 << 6) - 1"); printf("\n 18 - AUDIO_CHANNEL_OUT_6POINT1"); printf("\n 19 - canonical channel index mask for 7 ch: (1 << 7) - 1"); printf("\n 20 - AUDIO_CHANNEL_OUT_5POINT1POINT2"); printf("\n 21 - AUDIO_CHANNEL_OUT_7POINT1"); printf("\n 22 - canonical channel index mask for 8 ch: (1 << 8) - 1"); printf("\n default 0"); printf("\n -vcBal:"); printf("\n -ve values reduce Right channel while +ve value reduces Left channel"); printf("\n default 0"); printf("\n -fch: (1 through 8)\n\n"); printf("\n -M"); printf("\n Mono mode (force all input audio channels to be identical)"); printf("\n -basslvl:"); printf("\n A value that ranges between %d - %d default 0", LVM_BE_MIN_EFFECTLEVEL, LVM_BE_MAX_EFFECTLEVEL); printf("\n"); printf("\n -eqPreset:"); const size_t numPresetLvls = std::size(gEqualizerPresets); for (size_t i = 0; i < numPresetLvls; ++i) { printf("\n %zu - %s", i, gEqualizerPresets[i].name); } printf("\n default - 0"); printf("\n -bE "); printf("\n Enable Dynamic Bass Enhancement"); printf("\n"); printf("\n -tE "); printf("\n Enable Treble Boost"); printf("\n"); printf("\n -csE "); printf("\n Enable Concert Surround"); printf("\n"); printf("\n -eqE "); printf("\n Enable Equalizer"); } //---------------------------------------------------------------------------- // LvmBundle_init() //---------------------------------------------------------------------------- // Purpose: Initialize engine with default configuration, creates instance // with all effects disabled. // // Inputs: // pContext: effect engine context // // Outputs: // //---------------------------------------------------------------------------- int LvmBundle_init(struct EffectContext* pContext, LVM_ControlParams_t* params) { ALOGV("\tLvmBundle_init start"); pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; pContext->config.inputCfg.format = EFFECT_BUFFER_FORMAT; pContext->config.inputCfg.samplingRate = 44100; pContext->config.inputCfg.bufferProvider.getBuffer = NULL; pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL; pContext->config.inputCfg.bufferProvider.cookie = NULL; pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL; pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; pContext->config.outputCfg.format = EFFECT_BUFFER_FORMAT; pContext->config.outputCfg.samplingRate = 44100; pContext->config.outputCfg.bufferProvider.getBuffer = NULL; pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL; pContext->config.outputCfg.bufferProvider.cookie = NULL; pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL; if (pContext->pBundledContext->hInstance != NULL) { ALOGV("\tLvmBundle_init pContext->pBassBoost != NULL " "-> Calling pContext->pBassBoost->free()"); LVM_DelInstanceHandle(&pContext->pBundledContext->hInstance); ALOGV("\tLvmBundle_init pContext->pBassBoost != NULL " "-> Called pContext->pBassBoost->free()"); } LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */ LVM_InstParams_t InstParams; /* Instance parameters */ LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */ LVM_HeadroomParams_t HeadroomParams; /* Headroom parameters */ LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS]; /* Set the capabilities */ InstParams.BufferMode = LVM_UNMANAGED_BUFFERS; InstParams.MaxBlockSize = MAX_CALL_SIZE; InstParams.EQNB_NumBands = MAX_NUM_BANDS; InstParams.PSA_Included = LVM_PSA_ON; LvmStatus = LVM_GetInstanceHandle(&pContext->pBundledContext->hInstance, &InstParams); LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "LvmBundle_init"); if (LvmStatus != LVM_SUCCESS) return -EINVAL; ALOGV("\tLvmBundle_init CreateInstance Successfully called " "LVM_GetInstanceHandle\n"); /* Set the initial process parameters */ /* General parameters */ params->OperatingMode = LVM_MODE_ON; params->SampleRate = LVM_FS_44100; params->SourceFormat = LVM_STEREO; params->ChMask = AUDIO_CHANNEL_OUT_STEREO; params->SpeakerType = LVM_HEADPHONES; pContext->pBundledContext->SampleRate = LVM_FS_44100; /* Concert Sound parameters */ params->VirtualizerOperatingMode = LVM_MODE_OFF; params->VirtualizerType = LVM_CONCERTSOUND; params->VirtualizerReverbLevel = 100; params->CS_EffectLevel = LVM_CS_EFFECT_NONE; /* N-Band Equaliser parameters */ params->EQNB_OperatingMode = LVM_EQNB_ON; params->EQNB_NBands = FIVEBAND_NUMBANDS; params->pEQNB_BandDefinition = &BandDefs[0]; for (int i = 0; i < FIVEBAND_NUMBANDS; i++) { BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i]; BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i]; BandDefs[i].Gain = EQNB_5BandSoftPresets[i]; } /* Volume Control parameters */ params->VC_EffectLevel = 0; params->VC_Balance = 0; /* Treble Enhancement parameters */ params->TE_OperatingMode = LVM_TE_OFF; params->TE_EffectLevel = 0; /* PSA Control parameters */ params->PSA_Enable = LVM_PSA_OFF; params->PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0; /* Bass Enhancement parameters */ params->BE_OperatingMode = LVM_BE_ON; params->BE_EffectLevel = 0; params->BE_CentreFreq = LVM_BE_CENTRE_90Hz; params->BE_HPF = LVM_BE_HPF_ON; /* PSA Control parameters */ params->PSA_Enable = LVM_PSA_OFF; params->PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM; /* Activate the initial settings */ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, params); LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init"); if (LvmStatus != LVM_SUCCESS) return -EINVAL; ALOGV("\tLvmBundle_init CreateInstance Successfully called " "LVM_SetControlParameters\n"); /* Set the headroom parameters */ HeadroomBandDef[0].Limit_Low = 20; HeadroomBandDef[0].Limit_High = 4999; HeadroomBandDef[0].Headroom_Offset = 0; HeadroomBandDef[1].Limit_Low = 5000; HeadroomBandDef[1].Limit_High = 24000; HeadroomBandDef[1].Headroom_Offset = 0; HeadroomParams.pHeadroomDefinition = &HeadroomBandDef[0]; HeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON; HeadroomParams.NHeadroomBands = 2; LvmStatus = LVM_SetHeadroomParams(pContext->pBundledContext->hInstance, &HeadroomParams); LVM_ERROR_CHECK(LvmStatus, "LVM_SetHeadroomParams", "LvmBundle_init"); if (LvmStatus != LVM_SUCCESS) return -EINVAL; ALOGV("\tLvmBundle_init CreateInstance Successfully called " "LVM_SetHeadroomParams\n"); ALOGV("\tLvmBundle_init End"); return 0; } /* end LvmBundle_init */ int lvmCreate(struct EffectContext* pContext, lvmConfigParams_t* plvmConfigParams, LVM_ControlParams_t* params) { int ret = 0; pContext->pBundledContext = NULL; pContext->pBundledContext = (BundledEffectContext*)malloc(sizeof(struct BundledEffectContext)); if (NULL == pContext->pBundledContext) { return -EINVAL; } pContext->pBundledContext->SessionNo = 0; pContext->pBundledContext->SessionId = 0; pContext->pBundledContext->hInstance = NULL; pContext->pBundledContext->bVolumeEnabled = LVM_FALSE; pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE; pContext->pBundledContext->bBassEnabled = LVM_FALSE; pContext->pBundledContext->bBassTempDisabled = LVM_FALSE; pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE; pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE; pContext->pBundledContext->nOutputDevice = AUDIO_DEVICE_NONE; pContext->pBundledContext->nVirtualizerForcedDevice = AUDIO_DEVICE_NONE; pContext->pBundledContext->NumberEffectsEnabled = 0; pContext->pBundledContext->NumberEffectsCalled = 0; pContext->pBundledContext->firstVolume = LVM_TRUE; pContext->pBundledContext->volume = 0; /* Saved strength is used to return the exact strength that was used in the * set to the get * because we map the original strength range of 0:1000 to 1:15, and this will * avoid * quantisation like effect when returning */ pContext->pBundledContext->BassStrengthSaved = 0; pContext->pBundledContext->VirtStrengthSaved = 0; pContext->pBundledContext->CurPreset = PRESET_CUSTOM; pContext->pBundledContext->levelSaved = 0; pContext->pBundledContext->bMuteEnabled = LVM_FALSE; pContext->pBundledContext->bStereoPositionEnabled = LVM_FALSE; pContext->pBundledContext->positionSaved = 0; pContext->pBundledContext->workBuffer = NULL; pContext->pBundledContext->frameCount = -1; pContext->pBundledContext->SamplesToExitCountVirt = 0; pContext->pBundledContext->SamplesToExitCountBb = 0; pContext->pBundledContext->SamplesToExitCountEq = 0; for (int i = 0; i < FIVEBAND_NUMBANDS; i++) { pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i]; } pContext->config.inputCfg.channels = plvmConfigParams->nrChannels; ALOGV("\tEffectCreate - Calling LvmBundle_init"); ret = LvmBundle_init(pContext, params); if (ret < 0) { ALOGE("\tLVM_ERROR : lvmCreate() Bundle init failed"); return ret; } return 0; } int lvmControl(struct EffectContext* pContext, lvmConfigParams_t* plvmConfigParams, LVM_ControlParams_t* params) { LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */ /* Set the initial process parameters */ /* General parameters */ params->OperatingMode = LVM_MODE_ON; params->SpeakerType = LVM_HEADPHONES; params->ChMask = plvmConfigParams->chMask; params->NrChannels = plvmConfigParams->nrChannels; if (params->NrChannels == 1) { params->SourceFormat = LVM_MONO; } else if (params->NrChannels == 2) { params->SourceFormat = LVM_STEREO; } else if (params->NrChannels > FCC_2 && params->NrChannels <= FCC_24) { params->SourceFormat = LVM_MULTICHANNEL; } else { return -EINVAL; } params->SampleRate = lvmFsForSampleRate(plvmConfigParams->samplingFreq); if (params->SampleRate == LVM_FS_INVALID) { ALOGE("lvmControl invalid sampling rate %d", plvmConfigParams->samplingFreq); return -EINVAL; } /* Concert Sound parameters */ params->VirtualizerOperatingMode = plvmConfigParams->csEnable; params->VirtualizerType = LVM_CONCERTSOUND; params->VirtualizerReverbLevel = 100; params->CS_EffectLevel = LVM_CS_EFFECT_NONE; /* N-Band Equaliser parameters */ const int eqPresetLevel = plvmConfigParams->eqPresetLevel; LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */ for (int i = 0; i < FIVEBAND_NUMBANDS; i++) { BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i]; BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i]; BandDefs[i].Gain = EQNB_5BandSoftPresets[(FIVEBAND_NUMBANDS * eqPresetLevel) + i]; } params->EQNB_OperatingMode = plvmConfigParams->eqEnable; // Caution: raw pointer to stack data, stored in instance by LVM_SetControlParameters. params->pEQNB_BandDefinition = &BandDefs[0]; /* Volume Control parameters */ params->VC_EffectLevel = 0; params->VC_Balance = plvmConfigParams->vcBal; /* Treble Enhancement parameters */ params->TE_OperatingMode = plvmConfigParams->trebleEnable; params->TE_EffectLevel = plvmConfigParams->trebleEffectLevel; /* PSA Control parameters */ params->PSA_Enable = LVM_PSA_ON; /* Bass Enhancement parameters */ params->BE_OperatingMode = plvmConfigParams->bassEnable; /* Activate the initial settings */ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, params); LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init"); if (LvmStatus != LVM_SUCCESS) return -EINVAL; LvmStatus = LVM_ApplyNewSettings(pContext->pBundledContext->hInstance); if (LvmStatus != LVM_SUCCESS) return -EINVAL; return 0; } int lvmExecute(float* floatIn, float* floatOut, struct EffectContext* pContext, lvmConfigParams_t* plvmConfigParams) { const int frameLength = plvmConfigParams->frameLength; return LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */ floatIn, /* Input buffer */ floatOut, /* Output buffer */ (LVM_UINT16)frameLength, /* Number of samples to read */ 0); /* Audio Time */ } int lvmMainProcess(EffectContext* pContext, LVM_ControlParams_t* pParams, lvmConfigParams_t* plvmConfigParams, FILE* finp, FILE* fout) { int errCode = lvmControl(pContext, plvmConfigParams, pParams); if (errCode) { ALOGE("Error: lvmControl returned with %d\n", errCode); return errCode; } const int channelCount = plvmConfigParams->nrChannels; const int frameLength = plvmConfigParams->frameLength; const int frameSize = channelCount * sizeof(float); // processing size const int ioChannelCount = plvmConfigParams->fChannels; const int ioFrameSize = ioChannelCount * sizeof(short); // file load size const int maxChannelCount = std::max(channelCount, ioChannelCount); std::vector in(frameLength * maxChannelCount); std::vector out(frameLength * maxChannelCount); std::vector floatIn(frameLength * channelCount); std::vector floatOut(frameLength * channelCount); int frameCounter = 0; while (fread(in.data(), ioFrameSize, frameLength, finp) == (size_t)frameLength) { if (ioChannelCount != channelCount) { adjust_channels(in.data(), ioChannelCount, in.data(), channelCount, sizeof(short), frameLength * ioFrameSize); } memcpy_to_float_from_i16(floatIn.data(), in.data(), frameLength * channelCount); // Mono mode will replicate the first channel to all other channels. // This ensures all audio channels are identical. This is useful for testing // Bass Boost, which extracts a mono signal for processing. if (plvmConfigParams->monoMode && channelCount > 1) { for (int i = 0; i < frameLength; ++i) { auto* fp = &floatIn[i * channelCount]; std::fill(fp + 1, fp + channelCount, *fp); // replicate ch 0 } } #ifndef BYPASS_EXEC errCode = lvmExecute(floatIn.data(), floatOut.data(), pContext, plvmConfigParams); if (errCode) { printf("\nError: lvmExecute returned with %d\n", errCode); return errCode; } (void)frameSize; // eliminate warning #else memcpy(floatOut.data(), floatIn.data(), frameLength * frameSize); #endif memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * channelCount); if (ioChannelCount != channelCount) { adjust_channels(out.data(), channelCount, out.data(), ioChannelCount, sizeof(short), frameLength * channelCount * sizeof(short)); } (void)fwrite(out.data(), ioFrameSize, frameLength, fout); frameCounter += frameLength; } printf("frameCounter: [%d]\n", frameCounter); return 0; } int main(int argc, const char* argv[]) { if (argc == 1) { printUsage(); return -1; } lvmConfigParams_t lvmConfigParams{}; // default initialize const char* infile = nullptr; const char* outfile = nullptr; for (int i = 1; i < argc; i++) { printf("%s ", argv[i]); if (!strncmp(argv[i], "-i:", 3)) { infile = argv[i] + 3; } else if (!strncmp(argv[i], "-o:", 3)) { outfile = argv[i] + 3; } else if (!strncmp(argv[i], "-fs:", 4)) { const int samplingFreq = atoi(argv[i] + 4); if (samplingFreq != 8000 && samplingFreq != 11025 && samplingFreq != 12000 && samplingFreq != 16000 && samplingFreq != 22050 && samplingFreq != 24000 && samplingFreq != 32000 && samplingFreq != 44100 && samplingFreq != 48000 && samplingFreq != 88200 && samplingFreq != 96000 && samplingFreq != 176400 && samplingFreq != 192000) { printf("Error: Unsupported Sampling Frequency : %d\n", samplingFreq); return -1; } lvmConfigParams.samplingFreq = samplingFreq; } else if (!strncmp(argv[i], "-chMask:", 8)) { const int chMaskConfigIdx = atoi(argv[i] + 8); if (chMaskConfigIdx < 0 || (size_t)chMaskConfigIdx >= std::size(lvmConfigChMask)) { ALOGE("\nError: Unsupported Channel Mask : %d\n", chMaskConfigIdx); return -1; } const audio_channel_mask_t chMask = lvmConfigChMask[chMaskConfigIdx]; lvmConfigParams.chMask = chMask; lvmConfigParams.nrChannels = audio_channel_count_from_out_mask(chMask); } else if (!strncmp(argv[i], "-vcBal:", 7)) { const int vcBalance = atoi(argv[i] + 7); if (vcBalance > 96 || vcBalance < -96) { ALOGE("\nError: Unsupported volume balance value: %d\n", vcBalance); } lvmConfigParams.vcBal = vcBalance; } else if (!strncmp(argv[i], "-fch:", 5)) { const int fChannels = atoi(argv[i] + 5); if (fChannels > 8 || fChannels < 1) { printf("Error: Unsupported number of file channels : %d\n", fChannels); return -1; } lvmConfigParams.fChannels = fChannels; } else if (!strcmp(argv[i], "-M")) { lvmConfigParams.monoMode = true; } else if (!strncmp(argv[i], "-basslvl:", 9)) { const int bassEffectLevel = atoi(argv[i] + 9); if (bassEffectLevel > LVM_BE_MAX_EFFECTLEVEL || bassEffectLevel < LVM_BE_MIN_EFFECTLEVEL) { printf("Error: Unsupported Bass Effect Level : %d\n", bassEffectLevel); printUsage(); return -1; } lvmConfigParams.bassEffectLevel = bassEffectLevel; } else if (!strncmp(argv[i], "-eqPreset:", 10)) { const int eqPresetLevel = atoi(argv[i] + 10); const int numPresetLvls = std::size(gEqualizerPresets); if (eqPresetLevel >= numPresetLvls || eqPresetLevel < 0) { printf("Error: Unsupported Equalizer Preset : %d\n", eqPresetLevel); printUsage(); return -1; } lvmConfigParams.eqPresetLevel = eqPresetLevel; } else if (!strncmp(argv[i], "-trebleLvl:", 11)) { const int trebleEffectLevel = atoi(argv[i] + 11); if (trebleEffectLevel > LVM_TE_MAX_EFFECTLEVEL || trebleEffectLevel < LVM_TE_MIN_EFFECTLEVEL) { printf("Error: Unsupported Treble Effect Level : %d\n", trebleEffectLevel); printUsage(); return -1; } lvmConfigParams.trebleEffectLevel = trebleEffectLevel; } else if (!strcmp(argv[i], "-bE")) { lvmConfigParams.bassEnable = LVM_BE_ON; } else if (!strcmp(argv[i], "-eqE")) { lvmConfigParams.eqEnable = LVM_EQNB_ON; } else if (!strcmp(argv[i], "-tE")) { lvmConfigParams.trebleEnable = LVM_TE_ON; } else if (!strcmp(argv[i], "-csE")) { lvmConfigParams.csEnable = LVM_MODE_ON; } else if (!strcmp(argv[i], "-h")) { printUsage(); return 0; } } if (infile == nullptr || outfile == nullptr) { printf("Error: missing input/output files\n"); printUsage(); return -1; } FILE* finp = fopen(infile, "rb"); if (finp == nullptr) { printf("Cannot open input file %s", infile); return -1; } FILE* fout = fopen(outfile, "wb"); if (fout == nullptr) { printf("Cannot open output file %s", outfile); fclose(finp); return -1; } EffectContext context; LVM_ControlParams_t params; int errCode = lvmCreate(&context, &lvmConfigParams, ¶ms); if (errCode == 0) { errCode = lvmMainProcess(&context, ¶ms, &lvmConfigParams, finp, fout); if (errCode != 0) { printf("Error: lvmMainProcess returned with the error: %d", errCode); } } else { printf("Error: lvmCreate returned with the error: %d", errCode); } fclose(finp); fclose(fout); /* Free the allocated buffers */ if (context.pBundledContext != nullptr) { if (context.pBundledContext->hInstance != nullptr) { LVM_DelInstanceHandle(&context.pBundledContext->hInstance); } free(context.pBundledContext); } if (errCode) { return -1; } return 0; }