1 /*
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>
18 #include <iterator>
19 #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>
27 #include <system/audio.h>
28
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...) \
36 do { \
37 } while (false)
38 #endif
39
40 #define CHECK_ARG(cond) \
41 { \
42 if (!(cond)) { \
43 ALOGE("\tLVM_ERROR : Invalid argument: " #cond); \
44 return -EINVAL; \
45 } \
46 }
47
48 #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 }
71
72 struct lvmConfigParams_t {
73 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 int trebleEffectLevel = 0;
83 LVM_BE_Mode_en bassEnable = LVM_BE_OFF;
84 LVM_TE_Mode_en trebleEnable = LVM_TE_OFF;
85 LVM_EQNB_Mode_en eqEnable = LVM_EQNB_OFF;
86 LVM_Mode_en csEnable = LVM_MODE_OFF;
87 };
88
89 constexpr audio_channel_mask_t lvmConfigChMask[] = {
90 AUDIO_CHANNEL_OUT_MONO,
91 AUDIO_CHANNEL_OUT_STEREO,
92 AUDIO_CHANNEL_OUT_2POINT1,
93 AUDIO_CHANNEL_OUT_2POINT0POINT2,
94 AUDIO_CHANNEL_OUT_QUAD,
95 AUDIO_CHANNEL_OUT_QUAD_BACK,
96 AUDIO_CHANNEL_OUT_QUAD_SIDE,
97 AUDIO_CHANNEL_OUT_SURROUND,
98 AUDIO_CHANNEL_INDEX_MASK_4,
99 AUDIO_CHANNEL_OUT_2POINT1POINT2,
100 AUDIO_CHANNEL_OUT_3POINT0POINT2,
101 AUDIO_CHANNEL_OUT_PENTA,
102 AUDIO_CHANNEL_INDEX_MASK_5,
103 AUDIO_CHANNEL_OUT_3POINT1POINT2,
104 AUDIO_CHANNEL_OUT_5POINT1,
105 AUDIO_CHANNEL_OUT_5POINT1_BACK,
106 AUDIO_CHANNEL_OUT_5POINT1_SIDE,
107 AUDIO_CHANNEL_INDEX_MASK_6,
108 AUDIO_CHANNEL_OUT_6POINT1,
109 AUDIO_CHANNEL_INDEX_MASK_7,
110 AUDIO_CHANNEL_OUT_5POINT1POINT2,
111 AUDIO_CHANNEL_OUT_7POINT1,
112 AUDIO_CHANNEL_INDEX_MASK_8,
113 AUDIO_CHANNEL_INDEX_MASK_9,
114 AUDIO_CHANNEL_INDEX_MASK_10,
115 AUDIO_CHANNEL_INDEX_MASK_11,
116 AUDIO_CHANNEL_INDEX_MASK_12,
117 AUDIO_CHANNEL_INDEX_MASK_13,
118 AUDIO_CHANNEL_INDEX_MASK_14,
119 AUDIO_CHANNEL_INDEX_MASK_15,
120 AUDIO_CHANNEL_INDEX_MASK_16,
121 AUDIO_CHANNEL_INDEX_MASK_17,
122 AUDIO_CHANNEL_INDEX_MASK_18,
123 AUDIO_CHANNEL_INDEX_MASK_19,
124 AUDIO_CHANNEL_INDEX_MASK_20,
125 AUDIO_CHANNEL_INDEX_MASK_21,
126 AUDIO_CHANNEL_INDEX_MASK_22,
127 AUDIO_CHANNEL_INDEX_MASK_23,
128 AUDIO_CHANNEL_INDEX_MASK_24,
129 };
130
printUsage()131 void printUsage() {
132 printf("\nUsage: ");
133 printf("\n <executable> -i:<input_file> -o:<out_file> [options]\n");
134 printf("\nwhere, \n <inputfile> is the input file name");
135 printf("\n on which LVM effects are applied");
136 printf("\n <outputfile> processed output file");
137 printf("\n and options are mentioned below");
138 printf("\n");
139 printf("\n -help (or) -h");
140 printf("\n Prints this usage information");
141 printf("\n");
142 printf("\n -chMask:<channel_mask>\n");
143 printf("\n 0 - AUDIO_CHANNEL_OUT_MONO");
144 printf("\n 1 - AUDIO_CHANNEL_OUT_STEREO");
145 printf("\n 2 - AUDIO_CHANNEL_OUT_2POINT1");
146 printf("\n 3 - AUDIO_CHANNEL_OUT_2POINT0POINT2");
147 printf("\n 4 - AUDIO_CHANNEL_OUT_QUAD");
148 printf("\n 5 - AUDIO_CHANNEL_OUT_QUAD_BACK");
149 printf("\n 6 - AUDIO_CHANNEL_OUT_QUAD_SIDE");
150 printf("\n 7 - AUDIO_CHANNEL_OUT_SURROUND");
151 printf("\n 8 - canonical channel index mask for 4 ch: (1 << 4) - 1");
152 printf("\n 9 - AUDIO_CHANNEL_OUT_2POINT1POINT2");
153 printf("\n 10 - AUDIO_CHANNEL_OUT_3POINT0POINT2");
154 printf("\n 11 - AUDIO_CHANNEL_OUT_PENTA");
155 printf("\n 12 - canonical channel index mask for 5 ch: (1 << 5) - 1");
156 printf("\n 13 - AUDIO_CHANNEL_OUT_3POINT1POINT2");
157 printf("\n 14 - AUDIO_CHANNEL_OUT_5POINT1");
158 printf("\n 15 - AUDIO_CHANNEL_OUT_5POINT1_BACK");
159 printf("\n 16 - AUDIO_CHANNEL_OUT_5POINT1_SIDE");
160 printf("\n 17 - canonical channel index mask for 6 ch: (1 << 6) - 1");
161 printf("\n 18 - AUDIO_CHANNEL_OUT_6POINT1");
162 printf("\n 19 - canonical channel index mask for 7 ch: (1 << 7) - 1");
163 printf("\n 20 - AUDIO_CHANNEL_OUT_5POINT1POINT2");
164 printf("\n 21 - AUDIO_CHANNEL_OUT_7POINT1");
165 printf("\n 22 - canonical channel index mask for 8 ch: (1 << 8) - 1");
166 printf("\n default 0");
167 printf("\n -vcBal:<Left Right Balance control in dB [-96 to 96 dB]>");
168 printf("\n -ve values reduce Right channel while +ve value reduces Left channel");
169 printf("\n default 0");
170 printf("\n -fch:<file_channels> (1 through 8)\n\n");
171 printf("\n -M");
172 printf("\n Mono mode (force all input audio channels to be identical)");
173 printf("\n -basslvl:<effect_level>");
174 printf("\n A value that ranges between %d - %d default 0", LVM_BE_MIN_EFFECTLEVEL,
175 LVM_BE_MAX_EFFECTLEVEL);
176 printf("\n");
177 printf("\n -eqPreset:<preset Value>");
178 const size_t numPresetLvls = std::size(gEqualizerPresets);
179 for (size_t i = 0; i < numPresetLvls; ++i) {
180 printf("\n %zu - %s", i, gEqualizerPresets[i].name);
181 }
182 printf("\n default - 0");
183 printf("\n -bE ");
184 printf("\n Enable Dynamic Bass Enhancement");
185 printf("\n");
186 printf("\n -tE ");
187 printf("\n Enable Treble Boost");
188 printf("\n");
189 printf("\n -csE ");
190 printf("\n Enable Concert Surround");
191 printf("\n");
192 printf("\n -eqE ");
193 printf("\n Enable Equalizer");
194 }
195
196 //----------------------------------------------------------------------------
197 // LvmBundle_init()
198 //----------------------------------------------------------------------------
199 // Purpose: Initialize engine with default configuration, creates instance
200 // with all effects disabled.
201 //
202 // Inputs:
203 // pContext: effect engine context
204 //
205 // Outputs:
206 //
207 //----------------------------------------------------------------------------
208
LvmBundle_init(struct EffectContext * pContext,LVM_ControlParams_t * params)209 int LvmBundle_init(struct EffectContext* pContext, LVM_ControlParams_t* params) {
210 ALOGV("\tLvmBundle_init start");
211
212 pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
213 pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
214 pContext->config.inputCfg.format = EFFECT_BUFFER_FORMAT;
215 pContext->config.inputCfg.samplingRate = 44100;
216 pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
217 pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
218 pContext->config.inputCfg.bufferProvider.cookie = NULL;
219 pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
220 pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
221 pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
222 pContext->config.outputCfg.format = EFFECT_BUFFER_FORMAT;
223 pContext->config.outputCfg.samplingRate = 44100;
224 pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
225 pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
226 pContext->config.outputCfg.bufferProvider.cookie = NULL;
227 pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
228
229 if (pContext->pBundledContext->hInstance != NULL) {
230 ALOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
231 "-> Calling pContext->pBassBoost->free()");
232 LVM_DelInstanceHandle(&pContext->pBundledContext->hInstance);
233
234 ALOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
235 "-> Called pContext->pBassBoost->free()");
236 }
237
238 LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
239 LVM_InstParams_t InstParams; /* Instance parameters */
240 LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */
241 LVM_HeadroomParams_t HeadroomParams; /* Headroom parameters */
242 LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS];
243
244 /* Set the capabilities */
245 InstParams.BufferMode = LVM_UNMANAGED_BUFFERS;
246 InstParams.MaxBlockSize = MAX_CALL_SIZE;
247 InstParams.EQNB_NumBands = MAX_NUM_BANDS;
248 InstParams.PSA_Included = LVM_PSA_ON;
249
250 LvmStatus = LVM_GetInstanceHandle(&pContext->pBundledContext->hInstance, &InstParams);
251
252 LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "LvmBundle_init");
253 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
254
255 ALOGV("\tLvmBundle_init CreateInstance Successfully called "
256 "LVM_GetInstanceHandle\n");
257
258 /* Set the initial process parameters */
259 /* General parameters */
260 params->OperatingMode = LVM_MODE_ON;
261 params->SampleRate = LVM_FS_44100;
262 params->SourceFormat = LVM_STEREO;
263 params->ChMask = AUDIO_CHANNEL_OUT_STEREO;
264 params->SpeakerType = LVM_HEADPHONES;
265
266 pContext->pBundledContext->SampleRate = LVM_FS_44100;
267
268 /* Concert Sound parameters */
269 params->VirtualizerOperatingMode = LVM_MODE_OFF;
270 params->VirtualizerType = LVM_CONCERTSOUND;
271 params->VirtualizerReverbLevel = 100;
272 params->CS_EffectLevel = LVM_CS_EFFECT_NONE;
273
274 /* N-Band Equaliser parameters */
275 params->EQNB_OperatingMode = LVM_EQNB_ON;
276 params->EQNB_NBands = FIVEBAND_NUMBANDS;
277 params->pEQNB_BandDefinition = &BandDefs[0];
278
279 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
280 BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
281 BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
282 BandDefs[i].Gain = EQNB_5BandSoftPresets[i];
283 }
284
285 /* Volume Control parameters */
286 params->VC_EffectLevel = 0;
287 params->VC_Balance = 0;
288
289 /* Treble Enhancement parameters */
290 params->TE_OperatingMode = LVM_TE_OFF;
291 params->TE_EffectLevel = 0;
292
293 /* PSA Control parameters */
294 params->PSA_Enable = LVM_PSA_OFF;
295 params->PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
296
297 /* Bass Enhancement parameters */
298 params->BE_OperatingMode = LVM_BE_ON;
299 params->BE_EffectLevel = 0;
300 params->BE_CentreFreq = LVM_BE_CENTRE_90Hz;
301 params->BE_HPF = LVM_BE_HPF_ON;
302
303 /* PSA Control parameters */
304 params->PSA_Enable = LVM_PSA_OFF;
305 params->PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
306
307 /* Activate the initial settings */
308 LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, params);
309
310 LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init");
311 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
312
313 ALOGV("\tLvmBundle_init CreateInstance Successfully called "
314 "LVM_SetControlParameters\n");
315
316 /* Set the headroom parameters */
317 HeadroomBandDef[0].Limit_Low = 20;
318 HeadroomBandDef[0].Limit_High = 4999;
319 HeadroomBandDef[0].Headroom_Offset = 0;
320 HeadroomBandDef[1].Limit_Low = 5000;
321 HeadroomBandDef[1].Limit_High = 24000;
322 HeadroomBandDef[1].Headroom_Offset = 0;
323 HeadroomParams.pHeadroomDefinition = &HeadroomBandDef[0];
324 HeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
325 HeadroomParams.NHeadroomBands = 2;
326
327 LvmStatus = LVM_SetHeadroomParams(pContext->pBundledContext->hInstance, &HeadroomParams);
328
329 LVM_ERROR_CHECK(LvmStatus, "LVM_SetHeadroomParams", "LvmBundle_init");
330 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
331
332 ALOGV("\tLvmBundle_init CreateInstance Successfully called "
333 "LVM_SetHeadroomParams\n");
334 ALOGV("\tLvmBundle_init End");
335 return 0;
336 } /* end LvmBundle_init */
337
lvmCreate(struct EffectContext * pContext,lvmConfigParams_t * plvmConfigParams,LVM_ControlParams_t * params)338 int lvmCreate(struct EffectContext* pContext, lvmConfigParams_t* plvmConfigParams,
339 LVM_ControlParams_t* params) {
340 int ret = 0;
341 pContext->pBundledContext = NULL;
342 pContext->pBundledContext = (BundledEffectContext*)malloc(sizeof(struct BundledEffectContext));
343 if (NULL == pContext->pBundledContext) {
344 return -EINVAL;
345 }
346
347 pContext->pBundledContext->SessionNo = 0;
348 pContext->pBundledContext->SessionId = 0;
349 pContext->pBundledContext->hInstance = NULL;
350 pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
351 pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
352 pContext->pBundledContext->bBassEnabled = LVM_FALSE;
353 pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
354 pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
355 pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
356 pContext->pBundledContext->nOutputDevice = AUDIO_DEVICE_NONE;
357 pContext->pBundledContext->nVirtualizerForcedDevice = AUDIO_DEVICE_NONE;
358 pContext->pBundledContext->NumberEffectsEnabled = 0;
359 pContext->pBundledContext->NumberEffectsCalled = 0;
360 pContext->pBundledContext->firstVolume = LVM_TRUE;
361 pContext->pBundledContext->volume = 0;
362
363 /* Saved strength is used to return the exact strength that was used in the
364 * set to the get
365 * because we map the original strength range of 0:1000 to 1:15, and this will
366 * avoid
367 * quantisation like effect when returning
368 */
369 pContext->pBundledContext->BassStrengthSaved = 0;
370 pContext->pBundledContext->VirtStrengthSaved = 0;
371 pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
372 pContext->pBundledContext->levelSaved = 0;
373 pContext->pBundledContext->bMuteEnabled = LVM_FALSE;
374 pContext->pBundledContext->bStereoPositionEnabled = LVM_FALSE;
375 pContext->pBundledContext->positionSaved = 0;
376 pContext->pBundledContext->workBuffer = NULL;
377 pContext->pBundledContext->frameCount = -1;
378 pContext->pBundledContext->SamplesToExitCountVirt = 0;
379 pContext->pBundledContext->SamplesToExitCountBb = 0;
380 pContext->pBundledContext->SamplesToExitCountEq = 0;
381 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
382 pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i];
383 }
384 pContext->config.inputCfg.channels = plvmConfigParams->nrChannels;
385 ALOGV("\tEffectCreate - Calling LvmBundle_init");
386 ret = LvmBundle_init(pContext, params);
387
388 if (ret < 0) {
389 ALOGE("\tLVM_ERROR : lvmCreate() Bundle init failed");
390 return ret;
391 }
392 return 0;
393 }
394
lvmControl(struct EffectContext * pContext,lvmConfigParams_t * plvmConfigParams,LVM_ControlParams_t * params)395 int lvmControl(struct EffectContext* pContext, lvmConfigParams_t* plvmConfigParams,
396 LVM_ControlParams_t* params) {
397 LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
398
399 /* Set the initial process parameters */
400 /* General parameters */
401 params->OperatingMode = LVM_MODE_ON;
402 params->SpeakerType = LVM_HEADPHONES;
403
404 params->ChMask = plvmConfigParams->chMask;
405 params->NrChannels = plvmConfigParams->nrChannels;
406 if (params->NrChannels == 1) {
407 params->SourceFormat = LVM_MONO;
408 } else if (params->NrChannels == 2) {
409 params->SourceFormat = LVM_STEREO;
410 } else if (params->NrChannels > FCC_2 && params->NrChannels <= FCC_24) {
411 params->SourceFormat = LVM_MULTICHANNEL;
412 } else {
413 return -EINVAL;
414 }
415 params->SampleRate = lvmFsForSampleRate(plvmConfigParams->samplingFreq);
416 if (params->SampleRate == LVM_FS_INVALID) {
417 ALOGE("lvmControl invalid sampling rate %d", plvmConfigParams->samplingFreq);
418 return -EINVAL;
419 }
420
421 /* Concert Sound parameters */
422 params->VirtualizerOperatingMode = plvmConfigParams->csEnable;
423 params->VirtualizerType = LVM_CONCERTSOUND;
424 params->VirtualizerReverbLevel = 100;
425 params->CS_EffectLevel = LVM_CS_EFFECT_NONE;
426
427 /* N-Band Equaliser parameters */
428 const int eqPresetLevel = plvmConfigParams->eqPresetLevel;
429 LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */
430 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
431 BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
432 BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
433 BandDefs[i].Gain = EQNB_5BandSoftPresets[(FIVEBAND_NUMBANDS * eqPresetLevel) + i];
434 }
435 params->EQNB_OperatingMode = plvmConfigParams->eqEnable;
436 // Caution: raw pointer to stack data, stored in instance by LVM_SetControlParameters.
437 params->pEQNB_BandDefinition = &BandDefs[0];
438
439 /* Volume Control parameters */
440 params->VC_EffectLevel = 0;
441 params->VC_Balance = plvmConfigParams->vcBal;
442
443 /* Treble Enhancement parameters */
444 params->TE_OperatingMode = plvmConfigParams->trebleEnable;
445 params->TE_EffectLevel = plvmConfigParams->trebleEffectLevel;
446
447 /* PSA Control parameters */
448 params->PSA_Enable = LVM_PSA_ON;
449
450 /* Bass Enhancement parameters */
451 params->BE_OperatingMode = plvmConfigParams->bassEnable;
452
453 /* Activate the initial settings */
454 LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, params);
455
456 LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init");
457 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
458
459 LvmStatus = LVM_ApplyNewSettings(pContext->pBundledContext->hInstance);
460
461 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
462
463 return 0;
464 }
465
lvmExecute(float * floatIn,float * floatOut,struct EffectContext * pContext,lvmConfigParams_t * plvmConfigParams)466 int lvmExecute(float* floatIn, float* floatOut, struct EffectContext* pContext,
467 lvmConfigParams_t* plvmConfigParams) {
468 const int frameLength = plvmConfigParams->frameLength;
469 return LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
470 floatIn, /* Input buffer */
471 floatOut, /* Output buffer */
472 (LVM_UINT16)frameLength, /* Number of samples to read */
473 0); /* Audio Time */
474 }
475
lvmMainProcess(EffectContext * pContext,LVM_ControlParams_t * pParams,lvmConfigParams_t * plvmConfigParams,FILE * finp,FILE * fout)476 int lvmMainProcess(EffectContext* pContext, LVM_ControlParams_t* pParams,
477 lvmConfigParams_t* plvmConfigParams, FILE* finp, FILE* fout) {
478 int errCode = lvmControl(pContext, plvmConfigParams, pParams);
479 if (errCode) {
480 ALOGE("Error: lvmControl returned with %d\n", errCode);
481 return errCode;
482 }
483
484 const int channelCount = plvmConfigParams->nrChannels;
485 const int frameLength = plvmConfigParams->frameLength;
486 const int frameSize = channelCount * sizeof(float); // processing size
487 const int ioChannelCount = plvmConfigParams->fChannels;
488 const int ioFrameSize = ioChannelCount * sizeof(short); // file load size
489 const int maxChannelCount = std::max(channelCount, ioChannelCount);
490
491 std::vector<short> in(frameLength * maxChannelCount);
492 std::vector<short> out(frameLength * maxChannelCount);
493 std::vector<float> floatIn(frameLength * channelCount);
494 std::vector<float> floatOut(frameLength * channelCount);
495
496 int frameCounter = 0;
497 while (fread(in.data(), ioFrameSize, frameLength, finp) == (size_t)frameLength) {
498 if (ioChannelCount != channelCount) {
499 adjust_channels(in.data(), ioChannelCount, in.data(), channelCount, sizeof(short),
500 frameLength * ioFrameSize);
501 }
502 memcpy_to_float_from_i16(floatIn.data(), in.data(), frameLength * channelCount);
503
504 // Mono mode will replicate the first channel to all other channels.
505 // This ensures all audio channels are identical. This is useful for testing
506 // Bass Boost, which extracts a mono signal for processing.
507 if (plvmConfigParams->monoMode && channelCount > 1) {
508 for (int i = 0; i < frameLength; ++i) {
509 auto* fp = &floatIn[i * channelCount];
510 std::fill(fp + 1, fp + channelCount, *fp); // replicate ch 0
511 }
512 }
513 #ifndef BYPASS_EXEC
514 errCode = lvmExecute(floatIn.data(), floatOut.data(), pContext, plvmConfigParams);
515 if (errCode) {
516 printf("\nError: lvmExecute returned with %d\n", errCode);
517 return errCode;
518 }
519
520 (void)frameSize; // eliminate warning
521 #else
522 memcpy(floatOut.data(), floatIn.data(), frameLength * frameSize);
523 #endif
524 memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * channelCount);
525 if (ioChannelCount != channelCount) {
526 adjust_channels(out.data(), channelCount, out.data(), ioChannelCount, sizeof(short),
527 frameLength * channelCount * sizeof(short));
528 }
529 (void)fwrite(out.data(), ioFrameSize, frameLength, fout);
530 frameCounter += frameLength;
531 }
532 printf("frameCounter: [%d]\n", frameCounter);
533 return 0;
534 }
535
main(int argc,const char * argv[])536 int main(int argc, const char* argv[]) {
537 if (argc == 1) {
538 printUsage();
539 return -1;
540 }
541
542 lvmConfigParams_t lvmConfigParams{}; // default initialize
543 const char* infile = nullptr;
544 const char* outfile = nullptr;
545
546 for (int i = 1; i < argc; i++) {
547 printf("%s ", argv[i]);
548 if (!strncmp(argv[i], "-i:", 3)) {
549 infile = argv[i] + 3;
550 } else if (!strncmp(argv[i], "-o:", 3)) {
551 outfile = argv[i] + 3;
552 } else if (!strncmp(argv[i], "-fs:", 4)) {
553 const int samplingFreq = atoi(argv[i] + 4);
554 if (samplingFreq != 8000 && samplingFreq != 11025 && samplingFreq != 12000 &&
555 samplingFreq != 16000 && samplingFreq != 22050 && samplingFreq != 24000 &&
556 samplingFreq != 32000 && samplingFreq != 44100 && samplingFreq != 48000 &&
557 samplingFreq != 88200 && samplingFreq != 96000 && samplingFreq != 176400 &&
558 samplingFreq != 192000) {
559 printf("Error: Unsupported Sampling Frequency : %d\n", samplingFreq);
560 return -1;
561 }
562 lvmConfigParams.samplingFreq = samplingFreq;
563 } else if (!strncmp(argv[i], "-chMask:", 8)) {
564 const int chMaskConfigIdx = atoi(argv[i] + 8);
565 if (chMaskConfigIdx < 0 || (size_t)chMaskConfigIdx >= std::size(lvmConfigChMask)) {
566 ALOGE("\nError: Unsupported Channel Mask : %d\n", chMaskConfigIdx);
567 return -1;
568 }
569 const audio_channel_mask_t chMask = lvmConfigChMask[chMaskConfigIdx];
570 lvmConfigParams.chMask = chMask;
571 lvmConfigParams.nrChannels = audio_channel_count_from_out_mask(chMask);
572 } else if (!strncmp(argv[i], "-vcBal:", 7)) {
573 const int vcBalance = atoi(argv[i] + 7);
574 if (vcBalance > 96 || vcBalance < -96) {
575 ALOGE("\nError: Unsupported volume balance value: %d\n", vcBalance);
576 }
577 lvmConfigParams.vcBal = vcBalance;
578 } else if (!strncmp(argv[i], "-fch:", 5)) {
579 const int fChannels = atoi(argv[i] + 5);
580 if (fChannels > 8 || fChannels < 1) {
581 printf("Error: Unsupported number of file channels : %d\n", fChannels);
582 return -1;
583 }
584 lvmConfigParams.fChannels = fChannels;
585 } else if (!strcmp(argv[i], "-M")) {
586 lvmConfigParams.monoMode = true;
587 } else if (!strncmp(argv[i], "-basslvl:", 9)) {
588 const int bassEffectLevel = atoi(argv[i] + 9);
589 if (bassEffectLevel > LVM_BE_MAX_EFFECTLEVEL ||
590 bassEffectLevel < LVM_BE_MIN_EFFECTLEVEL) {
591 printf("Error: Unsupported Bass Effect Level : %d\n", bassEffectLevel);
592 printUsage();
593 return -1;
594 }
595 lvmConfigParams.bassEffectLevel = bassEffectLevel;
596 } else if (!strncmp(argv[i], "-eqPreset:", 10)) {
597 const int eqPresetLevel = atoi(argv[i] + 10);
598 const int numPresetLvls = std::size(gEqualizerPresets);
599 if (eqPresetLevel >= numPresetLvls || eqPresetLevel < 0) {
600 printf("Error: Unsupported Equalizer Preset : %d\n", eqPresetLevel);
601 printUsage();
602 return -1;
603 }
604 lvmConfigParams.eqPresetLevel = eqPresetLevel;
605 } else if (!strncmp(argv[i], "-trebleLvl:", 11)) {
606 const int trebleEffectLevel = atoi(argv[i] + 11);
607 if (trebleEffectLevel > LVM_TE_MAX_EFFECTLEVEL ||
608 trebleEffectLevel < LVM_TE_MIN_EFFECTLEVEL) {
609 printf("Error: Unsupported Treble Effect Level : %d\n", trebleEffectLevel);
610 printUsage();
611 return -1;
612 }
613 lvmConfigParams.trebleEffectLevel = trebleEffectLevel;
614 } else if (!strcmp(argv[i], "-bE")) {
615 lvmConfigParams.bassEnable = LVM_BE_ON;
616 } else if (!strcmp(argv[i], "-eqE")) {
617 lvmConfigParams.eqEnable = LVM_EQNB_ON;
618 } else if (!strcmp(argv[i], "-tE")) {
619 lvmConfigParams.trebleEnable = LVM_TE_ON;
620 } else if (!strcmp(argv[i], "-csE")) {
621 lvmConfigParams.csEnable = LVM_MODE_ON;
622 } else if (!strcmp(argv[i], "-h")) {
623 printUsage();
624 return 0;
625 }
626 }
627
628 if (infile == nullptr || outfile == nullptr) {
629 printf("Error: missing input/output files\n");
630 printUsage();
631 return -1;
632 }
633
634 FILE* finp = fopen(infile, "rb");
635 if (finp == nullptr) {
636 printf("Cannot open input file %s", infile);
637 return -1;
638 }
639
640 FILE* fout = fopen(outfile, "wb");
641 if (fout == nullptr) {
642 printf("Cannot open output file %s", outfile);
643 fclose(finp);
644 return -1;
645 }
646
647 EffectContext context;
648 LVM_ControlParams_t params;
649 int errCode = lvmCreate(&context, &lvmConfigParams, ¶ms);
650 if (errCode == 0) {
651 errCode = lvmMainProcess(&context, ¶ms, &lvmConfigParams, finp, fout);
652 if (errCode != 0) {
653 printf("Error: lvmMainProcess returned with the error: %d", errCode);
654 }
655 } else {
656 printf("Error: lvmCreate returned with the error: %d", errCode);
657 }
658 fclose(finp);
659 fclose(fout);
660 /* Free the allocated buffers */
661 if (context.pBundledContext != nullptr) {
662 if (context.pBundledContext->hInstance != nullptr) {
663 LVM_DelInstanceHandle(&context.pBundledContext->hInstance);
664 }
665 free(context.pBundledContext);
666 }
667
668 if (errCode) {
669 return -1;
670 }
671 return 0;
672 }
673