1 /*
2 * Copyright (C) 2004-2010 NXP Software
3 * Copyright (C) 2010 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /****************************************************************************************/
19 /* */
20 /* Includes */
21 /* */
22 /****************************************************************************************/
23
24 #include "LVDBE.h"
25 #include "LVDBE_Private.h"
26 #include "VectorArithmetic.h"
27 #include "LVDBE_Coeffs.h"
28 #include "LVDBE_Tables.h"
29
30 /****************************************************************************************/
31 /* */
32 /* FUNCTION: LVDBE_GetParameters */
33 /* */
34 /* DESCRIPTION: */
35 /* Request the Dynamic Bass Enhancement parameters. The current parameter set is */
36 /* returned via the parameter pointer. */
37 /* */
38 /* PARAMETERS: */
39 /* hInstance Instance handle */
40 /* pParams Pointer to an empty parameter structure */
41 /* */
42 /* RETURNS: */
43 /* LVDBE_SUCCESS Always succeeds */
44 /* */
45 /* NOTES: */
46 /* 1. This function may be interrupted by the LVDBE_Process function */
47 /* */
48 /****************************************************************************************/
49
LVDBE_GetParameters(LVDBE_Handle_t hInstance,LVDBE_Params_t * pParams)50 LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t hInstance,
51 LVDBE_Params_t *pParams)
52 {
53
54 LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
55
56 *pParams = pInstance->Params;
57
58 return(LVDBE_SUCCESS);
59 }
60
61
62 /************************************************************************************/
63 /* */
64 /* FUNCTION: LVDBE_GetCapabilities */
65 /* */
66 /* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
67 /* returned via the pointer. */
68 /* */
69 /* PARAMETERS: */
70 /* hInstance Instance handle */
71 /* pCapabilities Pointer to an empty capability structure */
72 /* */
73 /* RETURNS: */
74 /* LVDBE_Success Always succeeds */
75 /* */
76 /* NOTES: */
77 /* 1. This function may be interrupted by the LVDBE_Process function */
78 /* */
79 /************************************************************************************/
80
LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,LVDBE_Capabilities_t * pCapabilities)81 LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,
82 LVDBE_Capabilities_t *pCapabilities)
83 {
84
85 LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
86
87 *pCapabilities = pInstance->Capabilities;
88
89 return(LVDBE_SUCCESS);
90 }
91
92
93 /************************************************************************************/
94 /* */
95 /* FUNCTION: LVDBE_SetFilters */
96 /* */
97 /* DESCRIPTION: */
98 /* Sets the filter coefficients and clears the data history */
99 /* */
100 /* PARAMETERS: */
101 /* pInstance Pointer to the instance */
102 /* pParams Initialisation parameters */
103 /* */
104 /************************************************************************************/
105
LVDBE_SetFilters(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)106 void LVDBE_SetFilters(LVDBE_Instance_t *pInstance,
107 LVDBE_Params_t *pParams)
108 {
109
110 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
111 /*
112 * Calculate the table offsets
113 */
114 LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
115 (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_192000)));
116 #else
117 /*
118 * Calculate the table offsets
119 */
120 LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
121 (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
122 #endif
123
124 /*
125 * Setup the high pass filter
126 */
127 #ifndef BUILD_FLOAT
128 LoadConst_16(0, /* Clear the history, value 0 */
129 (void *)&pInstance->pData->HPFTaps, /* Destination Cast to void: \
130 no dereferencing in function*/
131 sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16)); /* Number of words */
132 #else
133 LoadConst_Float(0, /* Clear the history, value 0 */
134 (void *)&pInstance->pData->HPFTaps, /* Destination Cast to void: \
135 no dereferencing in function*/
136 sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
137 #endif
138 #ifndef BUILD_FLOAT
139 BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
140 &pInstance->pData->HPFTaps,
141 (BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]);
142 #else
143 BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
144 &pInstance->pData->HPFTaps,
145 (BQ_FLOAT_Coefs_t *)&LVDBE_HPF_Table[Offset]);
146 #endif
147
148
149 /*
150 * Setup the band pass filter
151 */
152 #ifndef BUILD_FLOAT
153 LoadConst_16(0, /* Clear the history, value 0 */
154 (void *)&pInstance->pData->BPFTaps, /* Destination Cast to void: \
155 no dereferencing in function*/
156 sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16)); /* Number of words */
157 #else
158 LoadConst_Float(0, /* Clear the history, value 0 */
159 (void *)&pInstance->pData->BPFTaps, /* Destination Cast to void: \
160 no dereferencing in function*/
161 sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
162 #endif
163 #ifndef BUILD_FLOAT
164 BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
165 &pInstance->pData->BPFTaps,
166 (BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]);
167 #else
168 BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
169 &pInstance->pData->BPFTaps,
170 (BP_FLOAT_Coefs_t *)&LVDBE_BPF_Table[Offset]);
171 #endif
172 }
173
174
175
176 /************************************************************************************/
177 /* */
178 /* FUNCTION: LVDBE_SetAGC */
179 /* */
180 /* DESCRIPTION: */
181 /* Sets the AGC gain level and attack and decay times constants. */
182 /* */
183 /* PARAMETERS: */
184 /* pInstance Pointer to the instance */
185 /* pParams Initialisation parameters */
186 /* */
187 /************************************************************************************/
188
LVDBE_SetAGC(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)189 void LVDBE_SetAGC(LVDBE_Instance_t *pInstance,
190 LVDBE_Params_t *pParams)
191 {
192
193 /*
194 * Get the attack and decay time constants
195 */
196 pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate]; /* Attack multiplier */
197 pInstance->pData->AGCInstance.AGC_Decay = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate]; /* Decay multipler */
198
199
200 /*
201 * Get the boost gain
202 */
203 if (pParams->HPFSelect == LVDBE_HPF_ON)
204 {
205 pInstance->pData->AGCInstance.AGC_MaxGain = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter on */
206 }
207 else
208 {
209 pInstance->pData->AGCInstance.AGC_MaxGain = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter off */
210 }
211 #ifndef BUILD_FLOAT
212 pInstance->pData->AGCInstance.AGC_GainShift = AGC_GAIN_SHIFT;
213 #endif
214 pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
215
216 }
217
218
219 /************************************************************************************/
220 /* */
221 /* FUNCTION: LVDBE_SetVolume */
222 /* */
223 /* DESCRIPTION: */
224 /* Converts the input volume demand from dBs to linear. */
225 /* */
226 /* PARAMETERS: */
227 /* pInstance Pointer to the instance */
228 /* pParams Initialisation parameters */
229 /* */
230 /* NOTES: */
231 /* 1. The volume should have the following settings: */
232 /* */
233 /* DBE Vol Control Volume setting */
234 /* === =========== =================== */
235 /* Off Off HeadroomdB */
236 /* Off On VolumedB+HeadroomdB */
237 /* On Off HeadroomdB */
238 /* On On VolumedB+HeadroomdB */
239 /* */
240 /************************************************************************************/
241
LVDBE_SetVolume(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)242 void LVDBE_SetVolume(LVDBE_Instance_t *pInstance,
243 LVDBE_Params_t *pParams)
244 {
245
246 LVM_UINT16 dBShifts; /* 6dB shifts */
247 LVM_UINT16 dBOffset; /* Table offset */
248 LVM_INT16 Volume = 0; /* Required volume in dBs */
249
250 #ifdef BUILD_FLOAT
251 LVM_FLOAT dBShifts_fac;
252 #endif
253 /*
254 * Apply the volume if enabled
255 */
256 if (pParams->VolumeControl == LVDBE_VOLUME_ON)
257 {
258 /*
259 * Limit the gain to the maximum allowed
260 */
261 if (pParams->VolumedB > VOLUME_MAX)
262 {
263 Volume = VOLUME_MAX;
264 }
265 else
266 {
267 Volume = pParams->VolumedB;
268 }
269 }
270
271
272 /*
273 * Calculate the required gain and shifts
274 */
275 dBOffset = (LVM_UINT16)(6 + Volume % 6); /* Get the dBs 0-5 */
276 dBShifts = (LVM_UINT16)(Volume / -6); /* Get the 6dB shifts */
277
278 #ifdef BUILD_FLOAT
279 dBShifts_fac = (LVM_FLOAT)(1 << dBShifts);
280 #endif
281 /*
282 * When DBE is enabled use AGC volume
283 */
284 #ifndef BUILD_FLOAT
285 pInstance->pData->AGCInstance.Target = ((LVM_INT32)LVDBE_VolumeTable[dBOffset] << 16);
286 pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target >> dBShifts;
287 #else
288 pInstance->pData->AGCInstance.Target = (LVDBE_VolumeTable[dBOffset]);
289 pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target / dBShifts_fac;
290 #endif
291 pInstance->pData->AGCInstance.VolumeTC = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate]; /* Volume update time constant */
292 #ifndef BUILD_FLOAT
293 pInstance->pData->AGCInstance.VolumeShift = VOLUME_SHIFT+1;
294 #endif
295
296 /*
297 * When DBE is disabled use the bypass volume control
298 */
299 if(dBShifts > 0)
300 {
301 #ifndef BUILD_FLOAT
302 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(((LVM_INT32)LVDBE_VolumeTable[dBOffset]) >> dBShifts));
303 #else
304 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
305 LVDBE_VolumeTable[dBOffset] / dBShifts_fac);
306 #endif
307 }
308 else
309 {
310 #ifndef BUILD_FLOAT
311 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(LVM_INT32)LVDBE_VolumeTable[dBOffset]);
312 #else
313 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
314 LVDBE_VolumeTable[dBOffset]);
315 #endif
316 }
317
318 pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
319 #ifndef BUILD_FLOAT
320 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
321 LVDBE_MIXER_TC,
322 (LVM_Fs_en)pInstance->Params.SampleRate,
323 2);
324 #else
325 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
326 LVDBE_MIXER_TC,
327 (LVM_Fs_en)pInstance->Params.SampleRate,
328 2);
329 #endif
330 }
331
332
333 /****************************************************************************************/
334 /* */
335 /* FUNCTION: LVDBE_Control */
336 /* */
337 /* DESCRIPTION: */
338 /* Sets or changes the Bass Enhancement parameters. Changing the parameters while the */
339 /* module is processing signals may have the following side effects: */
340 /* */
341 /* General parameters: */
342 /* =================== */
343 /* OperatingMode: Changing the mode of operation may cause a change in volume */
344 /* level or cause pops and clicks. */
345 /* */
346 /* SampleRate: Changing the sample rate may cause pops and clicks. */
347 /* */
348 /* EffectLevel: Changing the effect level may cause pops and clicks */
349 /* */
350 /* CentreFrequency: Changing the centre frequency may cause pops and clicks */
351 /* */
352 /* HPFSelect: Selecting/de-selecting the high pass filter may cause pops and */
353 /* clicks */
354 /* */
355 /* VolumedB Changing the volume setting will have no side effects */
356 /* */
357 /* */
358 /* PARAMETERS: */
359 /* hInstance Instance handle */
360 /* pParams Pointer to a parameter structure */
361 /* */
362 /* RETURNS: */
363 /* LVDBE_SUCCESS Always succeeds */
364 /* */
365 /* NOTES: */
366 /* 1. This function must not be interrupted by the LVDBE_Process function */
367 /* */
368 /****************************************************************************************/
369
LVDBE_Control(LVDBE_Handle_t hInstance,LVDBE_Params_t * pParams)370 LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance,
371 LVDBE_Params_t *pParams)
372 {
373
374 LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
375 #ifndef BUILD_FLOAT
376 LVMixer3_2St_st *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
377 #else
378 LVMixer3_2St_FLOAT_st *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
379 #endif
380
381
382 /*
383 * Update the filters
384 */
385 if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
386 (pInstance->Params.CentreFrequency != pParams->CentreFrequency))
387 {
388 LVDBE_SetFilters(pInstance, /* Instance pointer */
389 pParams); /* New parameters */
390 }
391
392
393 /*
394 * Update the AGC is the effect level has changed
395 */
396 if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
397 (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
398 (pInstance->Params.HPFSelect != pParams->HPFSelect))
399 {
400 LVDBE_SetAGC(pInstance, /* Instance pointer */
401 pParams); /* New parameters */
402 #ifndef BUILD_FLOAT
403 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
404 LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
405
406 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
407 LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
408 #else
409 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
410 LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
411
412 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
413 LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
414 #endif
415
416
417 }
418
419
420 /*
421 * Update the Volume if the volume demand has changed
422 */
423 if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
424 (pInstance->Params.SampleRate != pParams->SampleRate) ||
425 (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
426 (pInstance->Params.VolumeControl != pParams->VolumeControl))
427 {
428 LVDBE_SetVolume(pInstance, /* Instance pointer */
429 pParams); /* New parameters */
430 }
431
432 if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
433 {
434 #ifndef BUILD_FLOAT
435 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0);
436 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0x00007FFF);
437 #else
438 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 0);
439 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 1.0f);
440 #endif
441 }
442 if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
443 {
444 #ifndef BUILD_FLOAT
445 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0x00007FFF);
446 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0);
447 #else
448 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 1.0f);
449 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 0);
450 #endif
451 }
452
453 /*
454 * Update the instance parameters
455 */
456 pInstance->Params = *pParams;
457
458
459 return(LVDBE_SUCCESS);
460 }
461