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