blob: 43271d22124de48cb41c46323e20caca8b17f4e5 [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>
18#include <math.h>
19#include <stdlib.h>
20#include <string.h>
21#include <vector>
22
23#include <audio_utils/channels.h>
24#include <audio_utils/primitives.h>
25#include <log/log.h>
26
27#include "EffectBundle.h"
28#include "LVM_Private.h"
29
30#ifdef VERY_VERY_VERBOSE_LOGGING
31#define ALOGVV ALOGV
32#else
33#define ALOGVV(a...) \
34 do { \
35 } while (false)
36#endif
37
38#define CHECK_ARG(cond) \
39 { \
40 if (!(cond)) { \
41 ALOGE("\tLVM_ERROR : Invalid argument: " #cond); \
42 return -EINVAL; \
43 } \
44 \
45}
46
47#define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc) \
48 { \
49 if ((LvmStatus) == LVM_NULLADDRESS) { \
50 ALOGE( \
51 "\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( \
57 "\tLVM_ERROR : Parameter error - " \
58 "bad alignment returned by %s in %s\n\n\n\n", \
59 callingFunc, calledFunc); \
60 } \
61 if ((LvmStatus) == LVM_INVALIDNUMSAMPLES) { \
62 ALOGE( \
63 "\tLVM_ERROR : Parameter error - " \
64 "bad number of samples returned by %s in %s\n\n\n\n", \
65 callingFunc, calledFunc); \
66 } \
67 if ((LvmStatus) == LVM_OUTOFRANGE) { \
68 ALOGE( \
69 "\tLVM_ERROR : Parameter error - " \
70 "out of range returned by %s in %s\n", \
71 callingFunc, calledFunc); \
72 } \
73 }
74
75struct lvmConfigParams_t {
76 int samplingFreq = 44100;
77 int nrChannels = 2;
78 int fChannels = 2;
Andy Hungb144b4b2018-12-20 14:15:49 -080079 bool monoMode = false;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +053080 int bassEffectLevel = 0;
81 int eqPresetLevel = 0;
82 int frameLength = 256;
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
89void printUsage() {
90 printf("\nUsage: ");
91 printf("\n <exceutable> -i:<input_file> -o:<out_file> [options]\n");
92 printf("\nwhere, \n <inputfile> is the input file name");
93 printf("\n on which LVM effects are applied");
94 printf("\n <outputfile> processed output file");
95 printf("\n and options are mentioned below");
96 printf("\n");
97 printf("\n -help (or) -h");
98 printf("\n Prints this usage information");
99 printf("\n");
100 printf("\n -ch:<process_channels> (1 through 8)\n\n");
101 printf("\n -fch:<file_channels> (1 through 8)\n\n");
Andy Hungb144b4b2018-12-20 14:15:49 -0800102 printf("\n -M");
103 printf("\n Mono mode (force all input audio channels to be identical)");
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530104 printf("\n -basslvl:<effect_level>");
105 printf("\n A value that ranges between 0 - 15 default 0");
106 printf("\n");
107 printf("\n -eqPreset:<preset Value>");
108 printf("\n 0 - Normal");
109 printf("\n 1 - Classical");
110 printf("\n 2 - Dance");
111 printf("\n 3 - Flat");
112 printf("\n 4 - Folk");
113 printf("\n 5 - Heavy Metal");
114 printf("\n 6 - Hip Hop");
115 printf("\n 7 - Jazz");
116 printf("\n 8 - Pop");
117 printf("\n 9 - Rock");
118 printf("\n default 0");
119 printf("\n -bE ");
120 printf("\n Enable Dynamic Bass Enhancement");
121 printf("\n");
122 printf("\n -tE ");
123 printf("\n Enable Treble Boost");
124 printf("\n");
125 printf("\n -csE ");
126 printf("\n Enable Concert Surround");
127 printf("\n");
128 printf("\n -eqE ");
129 printf("\n Enable Equalizer");
130}
131
132//----------------------------------------------------------------------------
133// LvmEffect_free()
134//----------------------------------------------------------------------------
135// Purpose: Free all memory associated with the Bundle.
136//
137// Inputs:
138// pContext: effect engine context
139//
140// Outputs:
141//
142//----------------------------------------------------------------------------
143
144void LvmEffect_free(struct EffectContext *pContext) {
145 LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
146 LVM_MemTab_t MemTab;
147
148 /* Free the algorithm memory */
149 LvmStatus = LVM_GetMemoryTable(pContext->pBundledContext->hInstance, &MemTab,
150 LVM_NULL);
151
152 LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "LvmEffect_free")
153
154 for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) {
155 if (MemTab.Region[i].Size != 0) {
156 if (MemTab.Region[i].pBaseAddress != NULL) {
157 ALOGV("\tLvmEffect_free - START freeing %" PRIu32
158 " bytes for region %u at %p\n",
159 MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
160
161 free(MemTab.Region[i].pBaseAddress);
162
163 ALOGV("\tLvmEffect_free - END freeing %" PRIu32
164 " bytes for region %u at %p\n",
165 MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
166 } else {
167 ALOGE(
168 "\tLVM_ERROR : LvmEffect_free - trying to free with NULL pointer "
169 "%" PRIu32 " bytes for region %u at %p ERROR\n",
170 MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
171 }
172 }
173 }
174} /* end LvmEffect_free */
175
176//----------------------------------------------------------------------------
177// LvmBundle_init()
178//----------------------------------------------------------------------------
179// Purpose: Initialize engine with default configuration, creates instance
180// with all effects disabled.
181//
182// Inputs:
183// pContext: effect engine context
184//
185// Outputs:
186//
187//----------------------------------------------------------------------------
188
189int LvmBundle_init(struct EffectContext *pContext, LVM_ControlParams_t *params) {
190 ALOGV("\tLvmBundle_init start");
191
192 pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
193 pContext->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
194 pContext->config.inputCfg.format = EFFECT_BUFFER_FORMAT;
195 pContext->config.inputCfg.samplingRate = 44100;
196 pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
197 pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
198 pContext->config.inputCfg.bufferProvider.cookie = NULL;
199 pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
200 pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
201 pContext->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
202 pContext->config.outputCfg.format = EFFECT_BUFFER_FORMAT;
203 pContext->config.outputCfg.samplingRate = 44100;
204 pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
205 pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
206 pContext->config.outputCfg.bufferProvider.cookie = NULL;
207 pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
208
209 if (pContext->pBundledContext->hInstance != NULL) {
210 ALOGV(
211 "\tLvmBundle_init pContext->pBassBoost != NULL "
212 "-> Calling pContext->pBassBoost->free()");
213
214 LvmEffect_free(pContext);
215
216 ALOGV(
217 "\tLvmBundle_init pContext->pBassBoost != NULL "
218 "-> Called pContext->pBassBoost->free()");
219 }
220
221 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];
226 LVM_MemTab_t MemTab; /* Memory allocation table */
227 bool bMallocFailure = LVM_FALSE;
228
229 /* Set the capabilities */
230 InstParams.BufferMode = LVM_UNMANAGED_BUFFERS;
231 InstParams.MaxBlockSize = MAX_CALL_SIZE;
232 InstParams.EQNB_NumBands = MAX_NUM_BANDS;
233 InstParams.PSA_Included = LVM_PSA_ON;
234
235 /* Allocate memory, forcing alignment */
236 LvmStatus = LVM_GetMemoryTable(LVM_NULL, &MemTab, &InstParams);
237
238 LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "LvmBundle_init");
239 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
240
241 ALOGV("\tCreateInstance Succesfully called LVM_GetMemoryTable\n");
242
243 /* Allocate memory */
244 for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) {
245 if (MemTab.Region[i].Size != 0) {
246 MemTab.Region[i].pBaseAddress = malloc(MemTab.Region[i].Size);
247
248 if (MemTab.Region[i].pBaseAddress == LVM_NULL) {
249 ALOGE(
250 "\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate "
251 "%" PRIu32 " bytes for region %u\n",
252 MemTab.Region[i].Size, i);
253 bMallocFailure = LVM_TRUE;
254 break;
255 } else {
256 ALOGV("\tLvmBundle_init CreateInstance allocated %" PRIu32
257 " bytes for region %u at %p\n",
258 MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
259 }
260 }
261 }
262
263 /* If one or more of the memory regions failed to allocate, free the regions
264 * that were
265 * succesfully allocated and return with an error
266 */
267 if (bMallocFailure == LVM_TRUE) {
268 for (int i = 0; i < LVM_NR_MEMORY_REGIONS; i++) {
269 if (MemTab.Region[i].pBaseAddress == LVM_NULL) {
270 ALOGE(
271 "\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate "
272 "%" PRIu32 " bytes for region %u Not freeing\n",
273 MemTab.Region[i].Size, i);
274 } else {
275 ALOGE(
276 "\tLVM_ERROR :LvmBundle_init CreateInstance Failed: but allocated "
277 "%" PRIu32 " bytes for region %u at %p- free\n",
278 MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
279 free(MemTab.Region[i].pBaseAddress);
280 }
281 }
282 return -EINVAL;
283 }
284 ALOGV("\tLvmBundle_init CreateInstance Succesfully malloc'd memory\n");
285
286 /* Initialise */
287 pContext->pBundledContext->hInstance = LVM_NULL;
288
289 /* Init sets the instance handle */
290 LvmStatus = LVM_GetInstanceHandle(&pContext->pBundledContext->hInstance,
291 &MemTab, &InstParams);
292
293 LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "LvmBundle_init");
294 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
295
296 ALOGV(
297 "\tLvmBundle_init CreateInstance Succesfully called "
298 "LVM_GetInstanceHandle\n");
299
300 /* Set the initial process parameters */
301 /* General parameters */
302 params->OperatingMode = LVM_MODE_ON;
303 params->SampleRate = LVM_FS_44100;
304 params->SourceFormat = LVM_STEREO;
305 params->SpeakerType = LVM_HEADPHONES;
306
307 pContext->pBundledContext->SampleRate = LVM_FS_44100;
308
309 /* Concert Sound parameters */
310 params->VirtualizerOperatingMode = LVM_MODE_OFF;
311 params->VirtualizerType = LVM_CONCERTSOUND;
312 params->VirtualizerReverbLevel = 100;
313 params->CS_EffectLevel = LVM_CS_EFFECT_NONE;
314
315 /* N-Band Equaliser parameters */
316 params->EQNB_OperatingMode = LVM_EQNB_ON;
317 params->EQNB_NBands = FIVEBAND_NUMBANDS;
318 params->pEQNB_BandDefinition = &BandDefs[0];
319
320 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
321 BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
322 BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
323 BandDefs[i].Gain = EQNB_5BandSoftPresets[i];
324 }
325
326 /* Volume Control parameters */
327 params->VC_EffectLevel = 0;
328 params->VC_Balance = 0;
329
330 /* Treble Enhancement parameters */
331 params->TE_OperatingMode = LVM_TE_OFF;
332 params->TE_EffectLevel = 0;
333
334 /* PSA Control parameters */
335 params->PSA_Enable = LVM_PSA_OFF;
336 params->PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
337
338 /* Bass Enhancement parameters */
339 params->BE_OperatingMode = LVM_BE_ON;
340 params->BE_EffectLevel = 0;
341 params->BE_CentreFreq = LVM_BE_CENTRE_90Hz;
342 params->BE_HPF = LVM_BE_HPF_ON;
343
344 /* PSA Control parameters */
345 params->PSA_Enable = LVM_PSA_OFF;
346 params->PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
347
348 /* TE Control parameters */
349 params->TE_OperatingMode = LVM_TE_OFF;
350 params->TE_EffectLevel = 0;
351
352 /* Activate the initial settings */
353 LvmStatus =
354 LVM_SetControlParameters(pContext->pBundledContext->hInstance, params);
355
356 LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init");
357 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
358
359 ALOGV(
360 "\tLvmBundle_init CreateInstance Succesfully called "
361 "LVM_SetControlParameters\n");
362
363 /* Set the headroom parameters */
364 HeadroomBandDef[0].Limit_Low = 20;
365 HeadroomBandDef[0].Limit_High = 4999;
366 HeadroomBandDef[0].Headroom_Offset = 0;
367 HeadroomBandDef[1].Limit_Low = 5000;
368 HeadroomBandDef[1].Limit_High = 24000;
369 HeadroomBandDef[1].Headroom_Offset = 0;
370 HeadroomParams.pHeadroomDefinition = &HeadroomBandDef[0];
371 HeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
372 HeadroomParams.NHeadroomBands = 2;
373
374 LvmStatus = LVM_SetHeadroomParams(pContext->pBundledContext->hInstance,
375 &HeadroomParams);
376
377 LVM_ERROR_CHECK(LvmStatus, "LVM_SetHeadroomParams", "LvmBundle_init");
378 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
379
380 ALOGV(
381 "\tLvmBundle_init CreateInstance Succesfully called "
382 "LVM_SetHeadroomParams\n");
383 ALOGV("\tLvmBundle_init End");
384 return 0;
385} /* end LvmBundle_init */
386
387int lvmCreate(struct EffectContext *pContext,
388 lvmConfigParams_t *plvmConfigParams,
389 LVM_ControlParams_t *params) {
390 int ret = 0;
391 pContext->pBundledContext = NULL;
392 pContext->pBundledContext = (BundledEffectContext *)malloc(sizeof(struct BundledEffectContext));
393 if (NULL == pContext->pBundledContext) {
394 return -EINVAL;
395 }
396
397 pContext->pBundledContext->SessionNo = 0;
398 pContext->pBundledContext->SessionId = 0;
399 pContext->pBundledContext->hInstance = NULL;
400 pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
401 pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
402 pContext->pBundledContext->bBassEnabled = LVM_FALSE;
403 pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
404 pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
405 pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
406 pContext->pBundledContext->nOutputDevice = AUDIO_DEVICE_NONE;
407 pContext->pBundledContext->nVirtualizerForcedDevice = AUDIO_DEVICE_NONE;
408 pContext->pBundledContext->NumberEffectsEnabled = 0;
409 pContext->pBundledContext->NumberEffectsCalled = 0;
410 pContext->pBundledContext->firstVolume = LVM_TRUE;
411 pContext->pBundledContext->volume = 0;
412
413 /* Saved strength is used to return the exact strength that was used in the
414 * set to the get
415 * because we map the original strength range of 0:1000 to 1:15, and this will
416 * avoid
417 * quantisation like effect when returning
418 */
419 pContext->pBundledContext->BassStrengthSaved = 0;
420 pContext->pBundledContext->VirtStrengthSaved = 0;
421 pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
422 pContext->pBundledContext->levelSaved = 0;
423 pContext->pBundledContext->bMuteEnabled = LVM_FALSE;
424 pContext->pBundledContext->bStereoPositionEnabled = LVM_FALSE;
425 pContext->pBundledContext->positionSaved = 0;
426 pContext->pBundledContext->workBuffer = NULL;
427 pContext->pBundledContext->frameCount = -1;
428 pContext->pBundledContext->SamplesToExitCountVirt = 0;
429 pContext->pBundledContext->SamplesToExitCountBb = 0;
430 pContext->pBundledContext->SamplesToExitCountEq = 0;
431#if defined(BUILD_FLOAT) && !defined(NATIVE_FLOAT_BUFFER)
432 pContext->pBundledContext->pInputBuffer = NULL;
433 pContext->pBundledContext->pOutputBuffer = NULL;
434#endif
435 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
436 pContext->pBundledContext->bandGaindB[i] = EQNB_5BandSoftPresets[i];
437 }
438 pContext->config.inputCfg.channels = plvmConfigParams->nrChannels;
439 ALOGV("\tEffectCreate - Calling LvmBundle_init");
440 ret = LvmBundle_init(pContext, params);
441
442 if (ret < 0) {
443 ALOGE("\tLVM_ERROR : lvmCreate() Bundle init failed");
444 return ret;
445 }
446 return 0;
447}
448
449int lvmControl(struct EffectContext *pContext,
450 lvmConfigParams_t *plvmConfigParams,
451 LVM_ControlParams_t *params) {
452 LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530453
454 /* Set the initial process parameters */
455 /* General parameters */
456 params->OperatingMode = LVM_MODE_ON;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530457 params->SpeakerType = LVM_HEADPHONES;
458
Saketh Sathuvalli0c5015f2018-11-28 18:37:06 +0530459 const int nrChannels = plvmConfigParams->nrChannels;
460 params->NrChannels = nrChannels;
461 if (nrChannels == 1) {
462 params->SourceFormat = LVM_MONO;
463 } else if (nrChannels == 2) {
464 params->SourceFormat = LVM_STEREO;
465 } else if (nrChannels > 2 && nrChannels <= 8) { // FCC_2 FCC_8
466 params->SourceFormat = LVM_MULTICHANNEL;
467 } else {
468 return -EINVAL;
469 }
470
471 LVM_Fs_en sampleRate;
472 switch (plvmConfigParams->samplingFreq) {
473 case 8000:
474 sampleRate = LVM_FS_8000;
475 break;
476 case 11025:
477 sampleRate = LVM_FS_11025;
478 break;
479 case 12000:
480 sampleRate = LVM_FS_12000;
481 break;
482 case 16000:
483 sampleRate = LVM_FS_16000;
484 break;
485 case 22050:
486 sampleRate = LVM_FS_22050;
487 break;
488 case 24000:
489 sampleRate = LVM_FS_24000;
490 break;
491 case 32000:
492 sampleRate = LVM_FS_32000;
493 break;
494 case 44100:
495 sampleRate = LVM_FS_44100;
496 break;
497 case 48000:
498 sampleRate = LVM_FS_48000;
499 break;
500 case 88200:
501 sampleRate = LVM_FS_88200;
502 break;
503 case 96000:
504 sampleRate = LVM_FS_96000;
505 break;
506 case 176400:
507 sampleRate = LVM_FS_176400;
508 break;
509 case 192000:
510 sampleRate = LVM_FS_192000;
511 break;
512 default:
513 return -EINVAL;
514 }
515 params->SampleRate = sampleRate;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530516
517 /* Concert Sound parameters */
518 params->VirtualizerOperatingMode = plvmConfigParams->csEnable;
519 params->VirtualizerType = LVM_CONCERTSOUND;
520 params->VirtualizerReverbLevel = 100;
521 params->CS_EffectLevel = LVM_CS_EFFECT_NONE;
522
523 /* N-Band Equaliser parameters */
Saketh Sathuvalli0c5015f2018-11-28 18:37:06 +0530524 const int eqPresetLevel = plvmConfigParams->eqPresetLevel;
525 LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530526 for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
527 BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
528 BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
529 BandDefs[i].Gain =
530 EQNB_5BandSoftPresets[(FIVEBAND_NUMBANDS * eqPresetLevel) + i];
531 }
Saketh Sathuvalli0c5015f2018-11-28 18:37:06 +0530532 params->EQNB_OperatingMode = plvmConfigParams->eqEnable;
533 // Caution: raw pointer to stack data, stored in instance by LVM_SetControlParameters.
534 params->pEQNB_BandDefinition = &BandDefs[0];
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530535
536 /* Volume Control parameters */
537 params->VC_EffectLevel = 0;
538 params->VC_Balance = 0;
539
540 /* Treble Enhancement parameters */
541 params->TE_OperatingMode = plvmConfigParams->trebleEnable;
542
543 /* PSA Control parameters */
544 params->PSA_Enable = LVM_PSA_ON;
545
546 /* Bass Enhancement parameters */
547 params->BE_OperatingMode = plvmConfigParams->bassEnable;
548
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530549 /* Activate the initial settings */
550 LvmStatus =
551 LVM_SetControlParameters(pContext->pBundledContext->hInstance, params);
552
553 LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init");
554 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
555
556 LvmStatus = LVM_ApplyNewSettings(pContext->pBundledContext->hInstance);
557
558 if (LvmStatus != LVM_SUCCESS) return -EINVAL;
559
560 return 0;
561}
562
563int lvmExecute(float *floatIn, float *floatOut, struct EffectContext *pContext,
564 lvmConfigParams_t *plvmConfigParams) {
565 const int frameLength = plvmConfigParams->frameLength;
566 return
567 LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
568 floatIn, /* Input buffer */
569 floatOut, /* Output buffer */
570 (LVM_UINT16)frameLength, /* Number of samples to read */
571 0); /* Audio Time */
572}
573
574int lvmMainProcess(lvmConfigParams_t *plvmConfigParams, FILE *finp, FILE *fout) {
575 struct EffectContext context;
576 LVM_ControlParams_t params;
577
578 int errCode = lvmCreate(&context, plvmConfigParams, &params);
579 if (errCode) {
580 ALOGE("Error: lvmCreate returned with %d\n", errCode);
581 return errCode;
582 }
583
584 errCode = lvmControl(&context, plvmConfigParams, &params);
585 if (errCode) {
586 ALOGE("Error: lvmControl returned with %d\n", errCode);
587 return errCode;
588 }
589
590 const int channelCount = plvmConfigParams->nrChannels;
591 const int frameLength = plvmConfigParams->frameLength;
592 const int frameSize = channelCount * sizeof(float); // processing size
593 const int ioChannelCount = plvmConfigParams->fChannels;
594 const int ioFrameSize = ioChannelCount * sizeof(short); // file load size
595 const int maxChannelCount = std::max(channelCount, ioChannelCount);
596 /*
597 * Mono input will be converted to 2 channels internally in the process call
598 * by copying the same data into the second channel.
599 * Hence when channelCount is 1, output buffer should be allocated for
600 * 2 channels. The memAllocChCount takes care of allocation of sufficient
601 * memory for the output buffer.
602 */
603 const int memAllocChCount = (channelCount == 1 ? 2 : channelCount);
604
605 std::vector<short> in(frameLength * maxChannelCount);
606 std::vector<short> out(frameLength * maxChannelCount);
607 std::vector<float> floatIn(frameLength * channelCount);
608 std::vector<float> floatOut(frameLength * memAllocChCount);
609
610 int frameCounter = 0;
611 while (fread(in.data(), ioFrameSize, frameLength, finp) == (size_t)frameLength) {
612 if (ioChannelCount != channelCount) {
613 adjust_channels(in.data(), ioChannelCount, in.data(), channelCount,
614 sizeof(short), frameLength * ioFrameSize);
615 }
616 memcpy_to_float_from_i16(floatIn.data(), in.data(), frameLength * channelCount);
617
Andy Hungb144b4b2018-12-20 14:15:49 -0800618 // Mono mode will replicate the first channel to all other channels.
619 // This ensures all audio channels are identical. This is useful for testing
620 // Bass Boost, which extracts a mono signal for processing.
621 if (plvmConfigParams->monoMode && channelCount > 1) {
622 for (int i = 0; i < frameLength; ++i) {
623 auto *fp = &floatIn[i * channelCount];
624 std::fill(fp + 1, fp + channelCount, *fp); // replicate ch 0
625 }
626 }
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530627#if 1
628 errCode = lvmExecute(floatIn.data(), floatOut.data(), &context, plvmConfigParams);
629 if (errCode) {
630 printf("\nError: lvmExecute returned with %d\n", errCode);
631 return errCode;
632 }
633
634 (void)frameSize; // eliminate warning
635#else
636 memcpy(floatOut.data(), floatIn.data(), frameLength * frameSize);
637#endif
638 memcpy_to_i16_from_float(out.data(), floatOut.data(), frameLength * channelCount);
639 if (ioChannelCount != channelCount) {
640 adjust_channels(out.data(), channelCount, out.data(), ioChannelCount,
641 sizeof(short), frameLength * channelCount * sizeof(short));
642 }
643 (void) fwrite(out.data(), ioFrameSize, frameLength, fout);
644 frameCounter += frameLength;
645 }
646 printf("frameCounter: [%d]\n", frameCounter);
647 return 0;
648}
649
650int main(int argc, const char *argv[]) {
651 if (argc == 1) {
652 printUsage();
653 return -1;
654 }
655
656 lvmConfigParams_t lvmConfigParams{}; // default initialize
657 FILE *finp = nullptr, *fout = nullptr;
658
659 for (int i = 1; i < argc; i++) {
660 printf("%s ", argv[i]);
661 if (!strncmp(argv[i], "-i:", 3)) {
662 finp = fopen(argv[i] + 3, "rb");
663 } else if (!strncmp(argv[i], "-o:", 3)) {
664 fout = fopen(argv[i] + 3, "wb");
665 } else if (!strncmp(argv[i], "-fs:", 4)) {
666 const int samplingFreq = atoi(argv[i] + 4);
667 if (samplingFreq != 8000 && samplingFreq != 11025 &&
668 samplingFreq != 12000 && samplingFreq != 16000 &&
669 samplingFreq != 22050 && samplingFreq != 24000 &&
670 samplingFreq != 32000 && samplingFreq != 44100 &&
Saketh Sathuvalli0c5015f2018-11-28 18:37:06 +0530671 samplingFreq != 48000 && samplingFreq != 88200 &&
672 samplingFreq != 96000 && samplingFreq != 176400 &&
673 samplingFreq != 192000) {
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530674 ALOGE("\nError: Unsupported Sampling Frequency : %d\n", samplingFreq);
675 return -1;
676 }
677 lvmConfigParams.samplingFreq = samplingFreq;
678 } else if (!strncmp(argv[i], "-ch:", 4)) {
679 const int nrChannels = atoi(argv[i] + 4);
680 if (nrChannels > 8 || nrChannels < 1) {
681 ALOGE("\nError: Unsupported number of channels : %d\n", nrChannels);
682 return -1;
683 }
684 lvmConfigParams.nrChannels = nrChannels;
685 } else if (!strncmp(argv[i], "-fch:", 5)) {
686 const int fChannels = atoi(argv[i] + 5);
687 if (fChannels > 8 || fChannels < 1) {
688 ALOGE("\nError: Unsupported number of file channels : %d\n", fChannels);
689 return -1;
690 }
691 lvmConfigParams.fChannels = fChannels;
Andy Hungb144b4b2018-12-20 14:15:49 -0800692 } else if (!strcmp(argv[i],"-M")) {
693 lvmConfigParams.monoMode = true;
Saketh Sathuvallib99e1bc2018-02-21 17:10:34 +0530694 } else if (!strncmp(argv[i], "-basslvl:", 9)) {
695 const int bassEffectLevel = atoi(argv[i] + 9);
696 if (bassEffectLevel > 15 || bassEffectLevel < 0) {
697 ALOGE("\nError: Unsupported Bass Effect Level : %d\n",
698 bassEffectLevel);
699 printUsage();
700 return -1;
701 }
702 lvmConfigParams.bassEffectLevel = bassEffectLevel;
703 } else if (!strncmp(argv[i], "-eqPreset:", 10)) {
704 const int eqPresetLevel = atoi(argv[i] + 10);
705 if (eqPresetLevel > 9 || eqPresetLevel < 0) {
706 ALOGE("\nError: Unsupported Equalizer Preset : %d\n", eqPresetLevel);
707 printUsage();
708 return -1;
709 }
710 lvmConfigParams.eqPresetLevel = eqPresetLevel;
711 } else if (!strcmp(argv[i], "-bE")) {
712 lvmConfigParams.bassEnable = LVM_BE_ON;
713 } else if (!strcmp(argv[i], "-eqE")) {
714 lvmConfigParams.eqEnable = LVM_EQNB_ON;
715 } else if (!strcmp(argv[i], "-tE")) {
716 lvmConfigParams.trebleEnable = LVM_TE_ON;
717 } else if (!strcmp(argv[i], "-csE")) {
718 lvmConfigParams.csEnable = LVM_MODE_ON;
719 } else if (!strcmp(argv[i], "-h")) {
720 printUsage();
721 return 0;
722 }
723 }
724
725 if (finp == nullptr || fout == nullptr) {
726 ALOGE("\nError: missing input/output files\n");
727 printUsage();
728 // ok not to close.
729 return -1;
730 }
731
732 const int errCode = lvmMainProcess(&lvmConfigParams, finp, fout);
733 fclose(finp);
734 fclose(fout);
735
736 if (errCode) {
737 ALOGE("Error: lvmMainProcess returns with the error: %d \n", errCode);
738 return -1;
739 }
740 return 0;
741}