blob: 5c5f6467141883a0ecdf833921abf2bb0ef7a6cd [file] [log] [blame]
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +05301/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <assert.h>
17#include <inttypes.h>
Saketh Sathuvallicb398ab2019-02-16 13:12:59 +053018#include <iterator>
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +053019#include <math.h>
20#include <stdlib.h>
21#include <string.h>
22#include <vector>
23
24#include <audio_utils/channels.h>
25#include <audio_utils/primitives.h>
26#include <log/log.h>
Saketh Sathuvalli7b66e3b2019-02-08 15:18:54 +053027#include <system/audio.h>
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +053028
29#include "EffectBundle.h"
30#include "LVM_Private.h"
31
32#ifdef VERY_VERY_VERBOSE_LOGGING
33#define ALOGVV ALOGV
34#else
35#define ALOGVV(a...) \
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +053036 do { \
37 } while (false)
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +053038#endif
39
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +053040#define CHECK_ARG(cond) \
41 { \
42 if (!(cond)) { \
43 ALOGE("\tLVM_ERROR : Invalid argument: " #cond); \
44 return -EINVAL; \
45 } \
46 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +053047
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +053048#define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc) \
49 { \
50 if ((LvmStatus) == LVM_NULLADDRESS) { \
51 ALOGE("\tLVM_ERROR : Parameter error - " \
52 "null pointer returned by %s in %s\n\n\n\n", \
53 callingFunc, calledFunc); \
54 } \
55 if ((LvmStatus) == LVM_ALIGNMENTERROR) { \
56 ALOGE("\tLVM_ERROR : Parameter error - " \
57 "bad alignment returned by %s in %s\n\n\n\n", \
58 callingFunc, calledFunc); \
59 } \
60 if ((LvmStatus) == LVM_INVALIDNUMSAMPLES) { \
61 ALOGE("\tLVM_ERROR : Parameter error - " \
62 "bad number of samples returned by %s in %s\n\n\n\n", \
63 callingFunc, calledFunc); \
64 } \
65 if ((LvmStatus) == LVM_OUTOFRANGE) { \
66 ALOGE("\tLVM_ERROR : Parameter error - " \
67 "out of range returned by %s in %s\n", \
68 callingFunc, calledFunc); \
69 } \
70 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +053071
72struct lvmConfigParams_t {
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +053073 int samplingFreq = 44100;
74 int nrChannels = 2;
75 int chMask = AUDIO_CHANNEL_OUT_STEREO;
76 int vcBal = 0;
77 int fChannels = 2;
78 bool monoMode = false;
79 int bassEffectLevel = 0;
80 int eqPresetLevel = 0;
81 int frameLength = 256;
82 LVM_BE_Mode_en bassEnable = LVM_BE_OFF;
83 LVM_TE_Mode_en trebleEnable = LVM_TE_OFF;
84 LVM_EQNB_Mode_en eqEnable = LVM_EQNB_OFF;
85 LVM_Mode_en csEnable = LVM_MODE_OFF;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +053086};
87
Saketh Sathuvalli7b66e3b2019-02-08 15:18:54 +053088constexpr audio_channel_mask_t lvmConfigChMask[] = {
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +053089 AUDIO_CHANNEL_OUT_MONO,
90 AUDIO_CHANNEL_OUT_STEREO,
91 AUDIO_CHANNEL_OUT_2POINT1,
92 AUDIO_CHANNEL_OUT_2POINT0POINT2,
93 AUDIO_CHANNEL_OUT_QUAD,
94 AUDIO_CHANNEL_OUT_QUAD_BACK,
95 AUDIO_CHANNEL_OUT_QUAD_SIDE,
96 AUDIO_CHANNEL_OUT_SURROUND,
Mikhail Naganov48e23452020-10-07 20:57:51 +000097 AUDIO_CHANNEL_INDEX_MASK_4,
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +053098 AUDIO_CHANNEL_OUT_2POINT1POINT2,
99 AUDIO_CHANNEL_OUT_3POINT0POINT2,
100 AUDIO_CHANNEL_OUT_PENTA,
Mikhail Naganov48e23452020-10-07 20:57:51 +0000101 AUDIO_CHANNEL_INDEX_MASK_5,
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530102 AUDIO_CHANNEL_OUT_3POINT1POINT2,
103 AUDIO_CHANNEL_OUT_5POINT1,
104 AUDIO_CHANNEL_OUT_5POINT1_BACK,
105 AUDIO_CHANNEL_OUT_5POINT1_SIDE,
Mikhail Naganov48e23452020-10-07 20:57:51 +0000106 AUDIO_CHANNEL_INDEX_MASK_6,
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530107 AUDIO_CHANNEL_OUT_6POINT1,
Mikhail Naganov48e23452020-10-07 20:57:51 +0000108 AUDIO_CHANNEL_INDEX_MASK_7,
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530109 AUDIO_CHANNEL_OUT_5POINT1POINT2,
110 AUDIO_CHANNEL_OUT_7POINT1,
Mikhail Naganov48e23452020-10-07 20:57:51 +0000111 AUDIO_CHANNEL_INDEX_MASK_8,
Saketh Sathuvalli7b66e3b2019-02-08 15:18:54 +0530112};
113
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530114void printUsage() {
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530115 printf("\nUsage: ");
116 printf("\n <executable> -i:<input_file> -o:<out_file> [options]\n");
117 printf("\nwhere, \n <inputfile> is the input file name");
118 printf("\n on which LVM effects are applied");
119 printf("\n <outputfile> processed output file");
120 printf("\n and options are mentioned below");
121 printf("\n");
122 printf("\n -help (or) -h");
123 printf("\n Prints this usage information");
124 printf("\n");
125 printf("\n -chMask:<channel_mask>\n");
126 printf("\n 0 - AUDIO_CHANNEL_OUT_MONO");
127 printf("\n 1 - AUDIO_CHANNEL_OUT_STEREO");
128 printf("\n 2 - AUDIO_CHANNEL_OUT_2POINT1");
129 printf("\n 3 - AUDIO_CHANNEL_OUT_2POINT0POINT2");
130 printf("\n 4 - AUDIO_CHANNEL_OUT_QUAD");
131 printf("\n 5 - AUDIO_CHANNEL_OUT_QUAD_BACK");
132 printf("\n 6 - AUDIO_CHANNEL_OUT_QUAD_SIDE");
133 printf("\n 7 - AUDIO_CHANNEL_OUT_SURROUND");
134 printf("\n 8 - canonical channel index mask for 4 ch: (1 << 4) - 1");
135 printf("\n 9 - AUDIO_CHANNEL_OUT_2POINT1POINT2");
136 printf("\n 10 - AUDIO_CHANNEL_OUT_3POINT0POINT2");
137 printf("\n 11 - AUDIO_CHANNEL_OUT_PENTA");
138 printf("\n 12 - canonical channel index mask for 5 ch: (1 << 5) - 1");
139 printf("\n 13 - AUDIO_CHANNEL_OUT_3POINT1POINT2");
140 printf("\n 14 - AUDIO_CHANNEL_OUT_5POINT1");
141 printf("\n 15 - AUDIO_CHANNEL_OUT_5POINT1_BACK");
142 printf("\n 16 - AUDIO_CHANNEL_OUT_5POINT1_SIDE");
143 printf("\n 17 - canonical channel index mask for 6 ch: (1 << 6) - 1");
144 printf("\n 18 - AUDIO_CHANNEL_OUT_6POINT1");
145 printf("\n 19 - canonical channel index mask for 7 ch: (1 << 7) - 1");
146 printf("\n 20 - AUDIO_CHANNEL_OUT_5POINT1POINT2");
147 printf("\n 21 - AUDIO_CHANNEL_OUT_7POINT1");
148 printf("\n 22 - canonical channel index mask for 8 ch: (1 << 8) - 1");
149 printf("\n default 0");
150 printf("\n -vcBal:<Left Right Balance control in dB [-96 to 96 dB]>");
151 printf("\n -ve values reduce Right channel while +ve value reduces Left channel");
152 printf("\n default 0");
153 printf("\n -fch:<file_channels> (1 through 8)\n\n");
154 printf("\n -M");
155 printf("\n Mono mode (force all input audio channels to be identical)");
156 printf("\n -basslvl:<effect_level>");
157 printf("\n A value that ranges between %d - %d default 0", LVM_BE_MIN_EFFECTLEVEL,
158 LVM_BE_MAX_EFFECTLEVEL);
159 printf("\n");
160 printf("\n -eqPreset:<preset Value>");
161 const size_t numPresetLvls = std::size(gEqualizerPresets);
162 for (size_t i = 0; i < numPresetLvls; ++i) {
163 printf("\n %zu - %s", i, gEqualizerPresets[i].name);
164 }
165 printf("\n default - 0");
166 printf("\n -bE ");
167 printf("\n Enable Dynamic Bass Enhancement");
168 printf("\n");
169 printf("\n -tE ");
170 printf("\n Enable Treble Boost");
171 printf("\n");
172 printf("\n -csE ");
173 printf("\n Enable Concert Surround");
174 printf("\n");
175 printf("\n -eqE ");
176 printf("\n Enable Equalizer");
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530177}
178
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530179//----------------------------------------------------------------------------
180// LvmBundle_init()
181//----------------------------------------------------------------------------
182// Purpose: Initialize engine with default configuration, creates instance
183// with all effects disabled.
184//
185// Inputs:
186// pContext: effect engine context
187//
188// Outputs:
189//
190//----------------------------------------------------------------------------
191
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530192int LvmBundle_init(struct EffectContext* pContext, LVM_ControlParams_t* params) {
193 ALOGV("\tLvmBundle_init start");
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530194
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530195 pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
196 pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
197 pContext->config.inputCfg.format = EFFECT_BUFFER_FORMAT;
198 pContext->config.inputCfg.samplingRate = 44100;
199 pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
200 pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
201 pContext->config.inputCfg.bufferProvider.cookie = NULL;
202 pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
203 pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
204 pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
205 pContext->config.outputCfg.format = EFFECT_BUFFER_FORMAT;
206 pContext->config.outputCfg.samplingRate = 44100;
207 pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
208 pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
209 pContext->config.outputCfg.bufferProvider.cookie = NULL;
210 pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530211
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530212 if (pContext->pBundledContext->hInstance != NULL) {
213 ALOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
214 "-> Calling pContext->pBassBoost->free()");
215 LVM_DelInstanceHandle(&pContext->pBundledContext->hInstance);
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530216
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530217 ALOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
218 "-> Called pContext->pBassBoost->free()");
219 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530220
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530221 LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
222 LVM_InstParams_t InstParams; /* Instance parameters */
223 LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */
224 LVM_HeadroomParams_t HeadroomParams; /* Headroom parameters */
225 LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS];
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530226
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530227 /* Set the capabilities */
228 InstParams.BufferMode = LVM_UNMANAGED_BUFFERS;
229 InstParams.MaxBlockSize = MAX_CALL_SIZE;
230 InstParams.EQNB_NumBands = MAX_NUM_BANDS;
231 InstParams.PSA_Included = LVM_PSA_ON;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530232
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530233 LvmStatus = LVM_GetInstanceHandle(&pContext->pBundledContext->hInstance, &InstParams);
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530234
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530235 LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "LvmBundle_init");
236 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530237
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530238 ALOGV("\tLvmBundle_init CreateInstance Successfully called "
239 "LVM_GetInstanceHandle\n");
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530240
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530241 /* Set the initial process parameters */
242 /* General parameters */
243 params->OperatingMode = LVM_MODE_ON;
244 params->SampleRate = LVM_FS_44100;
245 params->SourceFormat = LVM_STEREO;
246 params->ChMask = AUDIO_CHANNEL_OUT_STEREO;
247 params->SpeakerType = LVM_HEADPHONES;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530248
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530249 pContext->pBundledContext->SampleRate = LVM_FS_44100;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530250
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530251 /* Concert Sound parameters */
252 params->VirtualizerOperatingMode = LVM_MODE_OFF;
253 params->VirtualizerType = LVM_CONCERTSOUND;
254 params->VirtualizerReverbLevel = 100;
255 params->CS_EffectLevel = LVM_CS_EFFECT_NONE;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530256
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530257 /* N-Band Equaliser parameters */
258 params->EQNB_OperatingMode = LVM_EQNB_ON;
259 params->EQNB_NBands = FIVEBAND_NUMBANDS;
260 params->pEQNB_BandDefinition = &BandDefs[0];
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530261
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530262 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
263 BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
264 BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
265 BandDefs[i].Gain = EQNB_5BandSoftPresets[i];
266 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530267
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530268 /* Volume Control parameters */
269 params->VC_EffectLevel = 0;
270 params->VC_Balance = 0;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530271
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530272 /* Treble Enhancement parameters */
273 params->TE_OperatingMode = LVM_TE_OFF;
274 params->TE_EffectLevel = 0;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530275
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530276 /* PSA Control parameters */
277 params->PSA_Enable = LVM_PSA_OFF;
278 params->PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530279
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530280 /* Bass Enhancement parameters */
281 params->BE_OperatingMode = LVM_BE_ON;
282 params->BE_EffectLevel = 0;
283 params->BE_CentreFreq = LVM_BE_CENTRE_90Hz;
284 params->BE_HPF = LVM_BE_HPF_ON;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530285
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530286 /* PSA Control parameters */
287 params->PSA_Enable = LVM_PSA_OFF;
288 params->PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530289
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530290 /* TE Control parameters */
291 params->TE_OperatingMode = LVM_TE_OFF;
292 params->TE_EffectLevel = 0;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530293
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530294 /* Activate the initial settings */
295 LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, params);
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530296
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530297 LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init");
298 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530299
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530300 ALOGV("\tLvmBundle_init CreateInstance Successfully called "
301 "LVM_SetControlParameters\n");
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530302
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530303 /* Set the headroom parameters */
304 HeadroomBandDef[0].Limit_Low = 20;
305 HeadroomBandDef[0].Limit_High = 4999;
306 HeadroomBandDef[0].Headroom_Offset = 0;
307 HeadroomBandDef[1].Limit_Low = 5000;
308 HeadroomBandDef[1].Limit_High = 24000;
309 HeadroomBandDef[1].Headroom_Offset = 0;
310 HeadroomParams.pHeadroomDefinition = &HeadroomBandDef[0];
311 HeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
312 HeadroomParams.NHeadroomBands = 2;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530313
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530314 LvmStatus = LVM_SetHeadroomParams(pContext->pBundledContext->hInstance, &HeadroomParams);
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530315
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530316 LVM_ERROR_CHECK(LvmStatus, "LVM_SetHeadroomParams", "LvmBundle_init");
317 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530318
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530319 ALOGV("\tLvmBundle_init CreateInstance Successfully called "
320 "LVM_SetHeadroomParams\n");
321 ALOGV("\tLvmBundle_init End");
322 return 0;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530323} /* end LvmBundle_init */
324
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530325int lvmCreate(struct EffectContext* pContext, lvmConfigParams_t* plvmConfigParams,
326 LVM_ControlParams_t* params) {
327 int ret = 0;
328 pContext->pBundledContext = NULL;
329 pContext->pBundledContext = (BundledEffectContext*)malloc(sizeof(struct BundledEffectContext));
330 if (NULL == pContext->pBundledContext) {
331 return -EINVAL;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530332 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530333
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530334 pContext->pBundledContext->SessionNo = 0;
335 pContext->pBundledContext->SessionId = 0;
336 pContext->pBundledContext->hInstance = NULL;
337 pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
338 pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
339 pContext->pBundledContext->bBassEnabled = LVM_FALSE;
340 pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
341 pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
342 pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
343 pContext->pBundledContext->nOutputDevice = AUDIO_DEVICE_NONE;
344 pContext->pBundledContext->nVirtualizerForcedDevice = AUDIO_DEVICE_NONE;
345 pContext->pBundledContext->NumberEffectsEnabled = 0;
346 pContext->pBundledContext->NumberEffectsCalled = 0;
347 pContext->pBundledContext->firstVolume = LVM_TRUE;
348 pContext->pBundledContext->volume = 0;
349
350 /* Saved strength is used to return the exact strength that was used in the
351 * set to the get
352 * because we map the original strength range of 0:1000 to 1:15, and this will
353 * avoid
354 * quantisation like effect when returning
355 */
356 pContext->pBundledContext->BassStrengthSaved = 0;
357 pContext->pBundledContext->VirtStrengthSaved = 0;
358 pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
359 pContext->pBundledContext->levelSaved = 0;
360 pContext->pBundledContext->bMuteEnabled = LVM_FALSE;
361 pContext->pBundledContext->bStereoPositionEnabled = LVM_FALSE;
362 pContext->pBundledContext->positionSaved = 0;
363 pContext->pBundledContext->workBuffer = NULL;
364 pContext->pBundledContext->frameCount = -1;
365 pContext->pBundledContext->SamplesToExitCountVirt = 0;
366 pContext->pBundledContext->SamplesToExitCountBb = 0;
367 pContext->pBundledContext->SamplesToExitCountEq = 0;
368 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
369 pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i];
370 }
371 pContext->config.inputCfg.channels = plvmConfigParams->nrChannels;
372 ALOGV("\tEffectCreate - Calling LvmBundle_init");
373 ret = LvmBundle_init(pContext, params);
374
375 if (ret < 0) {
376 ALOGE("\tLVM_ERROR : lvmCreate() Bundle init failed");
377 return ret;
378 }
379 return 0;
380}
381
382int lvmControl(struct EffectContext* pContext, lvmConfigParams_t* plvmConfigParams,
383 LVM_ControlParams_t* params) {
384 LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
385
386 /* Set the initial process parameters */
387 /* General parameters */
388 params->OperatingMode = LVM_MODE_ON;
389 params->SpeakerType = LVM_HEADPHONES;
390
391 params->ChMask = plvmConfigParams->chMask;
392 params->NrChannels = plvmConfigParams->nrChannels;
393 if (params->NrChannels == 1) {
394 params->SourceFormat = LVM_MONO;
395 } else if (params->NrChannels == 2) {
396 params->SourceFormat = LVM_STEREO;
397 } else if (params->NrChannels > 2 && params->NrChannels <= 8) { // FCC_2 FCC_8
398 params->SourceFormat = LVM_MULTICHANNEL;
399 } else {
400 return -EINVAL;
401 }
402
403 LVM_Fs_en sampleRate;
404 switch (plvmConfigParams->samplingFreq) {
405 case 8000:
406 sampleRate = LVM_FS_8000;
407 break;
408 case 11025:
409 sampleRate = LVM_FS_11025;
410 break;
411 case 12000:
412 sampleRate = LVM_FS_12000;
413 break;
414 case 16000:
415 sampleRate = LVM_FS_16000;
416 break;
417 case 22050:
418 sampleRate = LVM_FS_22050;
419 break;
420 case 24000:
421 sampleRate = LVM_FS_24000;
422 break;
423 case 32000:
424 sampleRate = LVM_FS_32000;
425 break;
426 case 44100:
427 sampleRate = LVM_FS_44100;
428 break;
429 case 48000:
430 sampleRate = LVM_FS_48000;
431 break;
432 case 88200:
433 sampleRate = LVM_FS_88200;
434 break;
435 case 96000:
436 sampleRate = LVM_FS_96000;
437 break;
438 case 176400:
439 sampleRate = LVM_FS_176400;
440 break;
441 case 192000:
442 sampleRate = LVM_FS_192000;
443 break;
444 default:
445 return -EINVAL;
446 }
447 params->SampleRate = sampleRate;
448
449 /* Concert Sound parameters */
450 params->VirtualizerOperatingMode = plvmConfigParams->csEnable;
451 params->VirtualizerType = LVM_CONCERTSOUND;
452 params->VirtualizerReverbLevel = 100;
453 params->CS_EffectLevel = LVM_CS_EFFECT_NONE;
454
455 /* N-Band Equaliser parameters */
456 const int eqPresetLevel = plvmConfigParams->eqPresetLevel;
457 LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */
458 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
459 BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
460 BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
461 BandDefs[i].Gain = EQNB_5BandSoftPresets[(FIVEBAND_NUMBANDS * eqPresetLevel) + i];
462 }
463 params->EQNB_OperatingMode = plvmConfigParams->eqEnable;
464 // Caution: raw pointer to stack data, stored in instance by LVM_SetControlParameters.
465 params->pEQNB_BandDefinition = &BandDefs[0];
466
467 /* Volume Control parameters */
468 params->VC_EffectLevel = 0;
469 params->VC_Balance = plvmConfigParams->vcBal;
470
471 /* Treble Enhancement parameters */
472 params->TE_OperatingMode = plvmConfigParams->trebleEnable;
473
474 /* PSA Control parameters */
475 params->PSA_Enable = LVM_PSA_ON;
476
477 /* Bass Enhancement parameters */
478 params->BE_OperatingMode = plvmConfigParams->bassEnable;
479
480 /* Activate the initial settings */
481 LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, params);
482
483 LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init");
484 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
485
486 LvmStatus = LVM_ApplyNewSettings(pContext->pBundledContext->hInstance);
487
488 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
489
490 return 0;
491}
492
493int lvmExecute(float* floatIn, float* floatOut, struct EffectContext* pContext,
494 lvmConfigParams_t* plvmConfigParams) {
495 const int frameLength = plvmConfigParams->frameLength;
496 return LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
497 floatIn, /* Input buffer */
498 floatOut, /* Output buffer */
499 (LVM_UINT16)frameLength, /* Number of samples to read */
500 0); /* Audio Time */
501}
502
503int lvmMainProcess(EffectContext* pContext, LVM_ControlParams_t* pParams,
504 lvmConfigParams_t* plvmConfigParams, FILE* finp, FILE* fout) {
505 int errCode = lvmControl(pContext, plvmConfigParams, pParams);
506 if (errCode) {
507 ALOGE("Error: lvmControl returned with %d\n", errCode);
508 return errCode;
509 }
510
511 const int channelCount = plvmConfigParams->nrChannels;
512 const int frameLength = plvmConfigParams->frameLength;
513 const int frameSize = channelCount * sizeof(float); // processing size
514 const int ioChannelCount = plvmConfigParams->fChannels;
515 const int ioFrameSize = ioChannelCount * sizeof(short); // file load size
516 const int maxChannelCount = std::max(channelCount, ioChannelCount);
517 /*
518 * Mono input will be converted to 2 channels internally in the process call
519 * by copying the same data into the second channel.
520 * Hence when channelCount is 1, output buffer should be allocated for
521 * 2 channels. The memAllocChCount takes care of allocation of sufficient
522 * memory for the output buffer.
523 */
524 const int memAllocChCount = (channelCount == 1 ? 2 : channelCount);
525
526 std::vector<short> in(frameLength * maxChannelCount);
527 std::vector<short> out(frameLength * maxChannelCount);
528 std::vector<float> floatIn(frameLength * channelCount);
529 std::vector<float> floatOut(frameLength * memAllocChCount);
530
531 int frameCounter = 0;
532 while (fread(in.data(), ioFrameSize, frameLength, finp) == (size_t)frameLength) {
533 if (ioChannelCount != channelCount) {
534 adjust_channels(in.data(), ioChannelCount, in.data(), channelCount, sizeof(short),
535 frameLength * ioFrameSize);
536 }
537 memcpy_to_float_from_i16(floatIn.data(), in.data(), frameLength * channelCount);
538
539 // Mono mode will replicate the first channel to all other channels.
540 // This ensures all audio channels are identical. This is useful for testing
541 // Bass Boost, which extracts a mono signal for processing.
542 if (plvmConfigParams->monoMode && channelCount > 1) {
543 for (int i = 0; i < frameLength; ++i) {
544 auto* fp = &floatIn[i * channelCount];
545 std::fill(fp + 1, fp + channelCount, *fp); // replicate ch 0
546 }
547 }
548#ifndef BYPASS_EXEC
549 errCode = lvmExecute(floatIn.data(), floatOut.data(), pContext, plvmConfigParams);
550 if (errCode) {
551 printf("\nError: lvmExecute returned with %d\n", errCode);
552 return errCode;
553 }
554
555 (void)frameSize; // eliminate warning
556#else
557 memcpy(floatOut.data(), floatIn.data(), frameLength * frameSize);
558#endif
559 memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * channelCount);
560 if (ioChannelCount != channelCount) {
561 adjust_channels(out.data(), channelCount, out.data(), ioChannelCount, sizeof(short),
562 frameLength * channelCount * sizeof(short));
563 }
564 (void)fwrite(out.data(), ioFrameSize, frameLength, fout);
565 frameCounter += frameLength;
566 }
567 printf("frameCounter: [%d]\n", frameCounter);
568 return 0;
569}
570
571int main(int argc, const char* argv[]) {
572 if (argc == 1) {
573 printUsage();
574 return -1;
575 }
576
577 lvmConfigParams_t lvmConfigParams{}; // default initialize
578 const char* infile = nullptr;
579 const char* outfile = nullptr;
580
581 for (int i = 1; i < argc; i++) {
582 printf("%s ", argv[i]);
583 if (!strncmp(argv[i], "-i:", 3)) {
584 infile = argv[i] + 3;
585 } else if (!strncmp(argv[i], "-o:", 3)) {
586 outfile = argv[i] + 3;
587 } else if (!strncmp(argv[i], "-fs:", 4)) {
588 const int samplingFreq = atoi(argv[i] + 4);
589 if (samplingFreq != 8000 && samplingFreq != 11025 && samplingFreq != 12000 &&
590 samplingFreq != 16000 && samplingFreq != 22050 && samplingFreq != 24000 &&
591 samplingFreq != 32000 && samplingFreq != 44100 && samplingFreq != 48000 &&
592 samplingFreq != 88200 && samplingFreq != 96000 && samplingFreq != 176400 &&
593 samplingFreq != 192000) {
594 printf("Error: Unsupported Sampling Frequency : %d\n", samplingFreq);
595 return -1;
596 }
597 lvmConfigParams.samplingFreq = samplingFreq;
598 } else if (!strncmp(argv[i], "-chMask:", 8)) {
599 const int chMaskConfigIdx = atoi(argv[i] + 8);
600 if (chMaskConfigIdx < 0 || (size_t)chMaskConfigIdx >= std::size(lvmConfigChMask)) {
601 ALOGE("\nError: Unsupported Channel Mask : %d\n", chMaskConfigIdx);
602 return -1;
603 }
604 const audio_channel_mask_t chMask = lvmConfigChMask[chMaskConfigIdx];
605 lvmConfigParams.chMask = chMask;
606 lvmConfigParams.nrChannels = audio_channel_count_from_out_mask(chMask);
607 } else if (!strncmp(argv[i], "-vcBal:", 7)) {
608 const int vcBalance = atoi(argv[i] + 7);
609 if (vcBalance > 96 || vcBalance < -96) {
610 ALOGE("\nError: Unsupported volume balance value: %d\n", vcBalance);
611 }
612 lvmConfigParams.vcBal = vcBalance;
613 } else if (!strncmp(argv[i], "-fch:", 5)) {
614 const int fChannels = atoi(argv[i] + 5);
615 if (fChannels > 8 || fChannels < 1) {
616 printf("Error: Unsupported number of file channels : %d\n", fChannels);
617 return -1;
618 }
619 lvmConfigParams.fChannels = fChannels;
620 } else if (!strcmp(argv[i], "-M")) {
621 lvmConfigParams.monoMode = true;
622 } else if (!strncmp(argv[i], "-basslvl:", 9)) {
623 const int bassEffectLevel = atoi(argv[i] + 9);
624 if (bassEffectLevel > LVM_BE_MAX_EFFECTLEVEL ||
625 bassEffectLevel < LVM_BE_MIN_EFFECTLEVEL) {
626 printf("Error: Unsupported Bass Effect Level : %d\n", bassEffectLevel);
627 printUsage();
628 return -1;
629 }
630 lvmConfigParams.bassEffectLevel = bassEffectLevel;
631 } else if (!strncmp(argv[i], "-eqPreset:", 10)) {
632 const int eqPresetLevel = atoi(argv[i] + 10);
633 const int numPresetLvls = std::size(gEqualizerPresets);
634 if (eqPresetLevel >= numPresetLvls || eqPresetLevel < 0) {
635 printf("Error: Unsupported Equalizer Preset : %d\n", eqPresetLevel);
636 printUsage();
637 return -1;
638 }
639 lvmConfigParams.eqPresetLevel = eqPresetLevel;
640 } else if (!strcmp(argv[i], "-bE")) {
641 lvmConfigParams.bassEnable = LVM_BE_ON;
642 } else if (!strcmp(argv[i], "-eqE")) {
643 lvmConfigParams.eqEnable = LVM_EQNB_ON;
644 } else if (!strcmp(argv[i], "-tE")) {
645 lvmConfigParams.trebleEnable = LVM_TE_ON;
646 } else if (!strcmp(argv[i], "-csE")) {
647 lvmConfigParams.csEnable = LVM_MODE_ON;
648 } else if (!strcmp(argv[i], "-h")) {
649 printUsage();
650 return 0;
Andy Hungb144b4b2018-12-20 14:15:49 -0800651 }
652 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530653
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530654 if (infile == nullptr || outfile == nullptr) {
655 printf("Error: missing input/output files\n");
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530656 printUsage();
657 return -1;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530658 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530659
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530660 FILE* finp = fopen(infile, "rb");
661 if (finp == nullptr) {
662 printf("Cannot open input file %s", infile);
663 return -1;
664 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530665
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530666 FILE* fout = fopen(outfile, "wb");
667 if (fout == nullptr) {
668 printf("Cannot open output file %s", outfile);
669 fclose(finp);
670 return -1;
671 }
Saketh Sathuvalliab18bac2019-01-24 17:15:10 +0530672
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530673 EffectContext context;
674 LVM_ControlParams_t params;
675 int errCode = lvmCreate(&context, &lvmConfigParams, &params);
676 if (errCode == 0) {
677 errCode = lvmMainProcess(&context, &params, &lvmConfigParams, finp, fout);
678 if (errCode != 0) {
679 printf("Error: lvmMainProcess returned with the error: %d", errCode);
680 }
681 } else {
682 printf("Error: lvmCreate returned with the error: %d", errCode);
683 }
Saketh Sathuvalliab18bac2019-01-24 17:15:10 +0530684 fclose(finp);
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530685 fclose(fout);
686 /* Free the allocated buffers */
687 if (context.pBundledContext != nullptr) {
688 if (context.pBundledContext->hInstance != nullptr) {
689 LVM_DelInstanceHandle(&context.pBundledContext->hInstance);
690 }
691 free(context.pBundledContext);
Saketh Sathuvalliab18bac2019-01-24 17:15:10 +0530692 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530693
Harish Mahendrakar0bbbe072020-10-01 23:28:48 +0530694 if (errCode) {
695 return -1;
696 }
697 return 0;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530698}