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, &params);
650     if (errCode == 0) {
651         errCode = lvmMainProcess(&context, &params, &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