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 <audio_utils/BiquadFilter.h>
25 #include <system/audio.h>
26 #include "LVDBE.h"
27 #include "LVDBE_Private.h"
28 #include "VectorArithmetic.h"
29 #include "LVDBE_Coeffs.h"
30 #include "LVDBE_Tables.h"
31
32 /****************************************************************************************/
33 /* */
34 /* FUNCTION: LVDBE_GetParameters */
35 /* */
36 /* DESCRIPTION: */
37 /* Request the Dynamic Bass Enhancement parameters. The current parameter set is */
38 /* returned via the parameter pointer. */
39 /* */
40 /* PARAMETERS: */
41 /* hInstance Instance handle */
42 /* pParams Pointer to an empty parameter structure */
43 /* */
44 /* RETURNS: */
45 /* LVDBE_SUCCESS Always succeeds */
46 /* */
47 /* NOTES: */
48 /* 1. This function may be interrupted by the LVDBE_Process function */
49 /* */
50 /****************************************************************************************/
51
LVDBE_GetParameters(LVDBE_Handle_t hInstance,LVDBE_Params_t * pParams)52 LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t hInstance, LVDBE_Params_t* pParams) {
53 LVDBE_Instance_t* pInstance = (LVDBE_Instance_t*)hInstance;
54
55 *pParams = pInstance->Params;
56
57 return (LVDBE_SUCCESS);
58 }
59
60 /************************************************************************************/
61 /* */
62 /* FUNCTION: LVDBE_GetCapabilities */
63 /* */
64 /* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
65 /* returned via the pointer. */
66 /* */
67 /* PARAMETERS: */
68 /* hInstance Instance handle */
69 /* pCapabilities Pointer to an empty capability structure */
70 /* */
71 /* RETURNS: */
72 /* LVDBE_Success Always succeeds */
73 /* */
74 /* NOTES: */
75 /* 1. This function may be interrupted by the LVDBE_Process function */
76 /* */
77 /************************************************************************************/
78
LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,LVDBE_Capabilities_t * pCapabilities)79 LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,
80 LVDBE_Capabilities_t* pCapabilities) {
81 LVDBE_Instance_t* pInstance = (LVDBE_Instance_t*)hInstance;
82
83 *pCapabilities = pInstance->Capabilities;
84
85 return (LVDBE_SUCCESS);
86 }
87
88 /************************************************************************************/
89 /* */
90 /* FUNCTION: LVDBE_SetFilters */
91 /* */
92 /* DESCRIPTION: */
93 /* Sets the filter coefficients and clears the data history */
94 /* */
95 /* PARAMETERS: */
96 /* pInstance Pointer to the instance */
97 /* pParams Initialisation parameters */
98 /* */
99 /************************************************************************************/
100
LVDBE_SetFilters(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)101 void LVDBE_SetFilters(LVDBE_Instance_t* pInstance, LVDBE_Params_t* pParams) {
102 /*
103 * Calculate the table offsets
104 */
105 LVM_UINT16 Offset =
106 (LVM_UINT16)((LVM_UINT16)pParams->SampleRate +
107 (LVM_UINT16)(pParams->CentreFrequency * (1 + LVDBE_FS_192000)));
108
109 /*
110 * Setup the high pass filter
111 */
112 std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
113 LVDBE_HPF_Table[Offset].A0, LVDBE_HPF_Table[Offset].A1, LVDBE_HPF_Table[Offset].A2,
114 -(LVDBE_HPF_Table[Offset].B1), -(LVDBE_HPF_Table[Offset].B2)};
115 pInstance->pHPFBiquad
116 ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
117
118 /*
119 * Setup the band pass filter
120 */
121 coefs = {LVDBE_BPF_Table[Offset].A0, 0.0, -(LVDBE_BPF_Table[Offset].A0),
122 -(LVDBE_BPF_Table[Offset].B1), -(LVDBE_BPF_Table[Offset].B2)};
123 pInstance->pBPFBiquad
124 ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
125 }
126
127 /************************************************************************************/
128 /* */
129 /* FUNCTION: LVDBE_SetAGC */
130 /* */
131 /* DESCRIPTION: */
132 /* Sets the AGC gain level and attack and decay times constants. */
133 /* */
134 /* PARAMETERS: */
135 /* pInstance Pointer to the instance */
136 /* pParams Initialisation parameters */
137 /* */
138 /************************************************************************************/
139
LVDBE_SetAGC(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)140 void LVDBE_SetAGC(LVDBE_Instance_t* pInstance, LVDBE_Params_t* pParams) {
141 /*
142 * Get the attack and decay time constants
143 */
144 pInstance->pData->AGCInstance.AGC_Attack =
145 LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate]; /* Attack multiplier */
146 pInstance->pData->AGCInstance.AGC_Decay =
147 LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate]; /* Decay multipler */
148
149 /*
150 * Get the boost gain
151 */
152 if (pParams->HPFSelect == LVDBE_HPF_ON) {
153 pInstance->pData->AGCInstance.AGC_MaxGain =
154 LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter on */
155 } else {
156 pInstance->pData->AGCInstance.AGC_MaxGain =
157 LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter off */
158 }
159 pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
160 }
161
162 /************************************************************************************/
163 /* */
164 /* FUNCTION: LVDBE_SetVolume */
165 /* */
166 /* DESCRIPTION: */
167 /* Converts the input volume demand from dBs to linear. */
168 /* */
169 /* PARAMETERS: */
170 /* pInstance Pointer to the instance */
171 /* pParams Initialisation parameters */
172 /* */
173 /* NOTES: */
174 /* 1. The volume should have the following settings: */
175 /* */
176 /* DBE Vol Control Volume setting */
177 /* === =========== =================== */
178 /* Off Off HeadroomdB */
179 /* Off On VolumedB+HeadroomdB */
180 /* On Off HeadroomdB */
181 /* On On VolumedB+HeadroomdB */
182 /* */
183 /************************************************************************************/
184
LVDBE_SetVolume(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)185 void LVDBE_SetVolume(LVDBE_Instance_t* pInstance, LVDBE_Params_t* pParams) {
186 LVM_UINT16 dBShifts; /* 6dB shifts */
187 LVM_UINT16 dBOffset; /* Table offset */
188 LVM_INT16 Volume = 0; /* Required volume in dBs */
189
190 LVM_FLOAT dBShifts_fac;
191 /*
192 * Apply the volume if enabled
193 */
194 if (pParams->VolumeControl == LVDBE_VOLUME_ON) {
195 /*
196 * Limit the gain to the maximum allowed
197 */
198 if (pParams->VolumedB > VOLUME_MAX) {
199 Volume = VOLUME_MAX;
200 } else {
201 Volume = pParams->VolumedB;
202 }
203 }
204
205 /*
206 * Calculate the required gain and shifts
207 */
208 dBOffset = (LVM_UINT16)(6 + Volume % 6); /* Get the dBs 0-5 */
209 dBShifts = (LVM_UINT16)(Volume / -6); /* Get the 6dB shifts */
210
211 dBShifts_fac = (LVM_FLOAT)(1 << dBShifts);
212 /*
213 * When DBE is enabled use AGC volume
214 */
215 pInstance->pData->AGCInstance.Target = (LVDBE_VolumeTable[dBOffset]);
216 pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target / dBShifts_fac;
217 pInstance->pData->AGCInstance.VolumeTC =
218 LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate]; /* Volume update time constant */
219
220 /*
221 * When DBE is disabled use the bypass volume control
222 */
223 if (dBShifts > 0) {
224 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
225 LVDBE_VolumeTable[dBOffset] / dBShifts_fac);
226 } else {
227 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
228 LVDBE_VolumeTable[dBOffset]);
229 }
230
231 pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
232 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
233 LVDBE_MIXER_TC, (LVM_Fs_en)pInstance->Params.SampleRate, 2);
234 }
235
236 /****************************************************************************************/
237 /* */
238 /* FUNCTION: LVDBE_Control */
239 /* */
240 /* DESCRIPTION: */
241 /* Sets or changes the Bass Enhancement parameters. Changing the parameters while the */
242 /* module is processing signals may have the following side effects: */
243 /* */
244 /* General parameters: */
245 /* =================== */
246 /* OperatingMode: Changing the mode of operation may cause a change in volume */
247 /* level or cause pops and clicks. */
248 /* */
249 /* SampleRate: Changing the sample rate may cause pops and clicks. */
250 /* */
251 /* EffectLevel: Changing the effect level may cause pops and clicks */
252 /* */
253 /* CentreFrequency: Changing the centre frequency may cause pops and clicks */
254 /* */
255 /* HPFSelect: Selecting/de-selecting the high pass filter may cause pops and */
256 /* clicks */
257 /* */
258 /* VolumedB Changing the volume setting will have no side effects */
259 /* */
260 /* */
261 /* PARAMETERS: */
262 /* hInstance Instance handle */
263 /* pParams Pointer to a parameter structure */
264 /* */
265 /* RETURNS: */
266 /* LVDBE_SUCCESS Always succeeds */
267 /* */
268 /* NOTES: */
269 /* 1. This function must not be interrupted by the LVDBE_Process function */
270 /* */
271 /****************************************************************************************/
272
LVDBE_Control(LVDBE_Handle_t hInstance,LVDBE_Params_t * pParams)273 LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance, LVDBE_Params_t* pParams) {
274 LVDBE_Instance_t* pInstance = (LVDBE_Instance_t*)hInstance;
275 LVMixer3_2St_FLOAT_st* pBypassMixer_Instance = &pInstance->pData->BypassMixer;
276
277 /*
278 * Create biquad instance
279 */
280 if (pInstance->Params.NrChannels != pParams->NrChannels) {
281 pInstance->pHPFBiquad.reset(
282 new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels));
283 }
284 /*
285 * Update the filters
286 */
287 if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
288 (pInstance->Params.NrChannels != pParams->NrChannels) ||
289 (pInstance->Params.CentreFrequency != pParams->CentreFrequency)) {
290 LVDBE_SetFilters(pInstance, /* Instance pointer */
291 pParams); /* New parameters */
292 }
293
294 /*
295 * Update the AGC is the effect level has changed
296 */
297 if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
298 (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
299 (pInstance->Params.HPFSelect != pParams->HPFSelect)) {
300 LVDBE_SetAGC(pInstance, /* Instance pointer */
301 pParams); /* New parameters */
302 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0], LVDBE_BYPASS_MIXER_TC,
303 (LVM_Fs_en)pParams->SampleRate, 2);
304
305 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1], LVDBE_BYPASS_MIXER_TC,
306 (LVM_Fs_en)pParams->SampleRate, 2);
307 }
308
309 /*
310 * Update the Volume if the volume demand has changed
311 */
312 if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
313 (pInstance->Params.SampleRate != pParams->SampleRate) ||
314 (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
315 (pInstance->Params.VolumeControl != pParams->VolumeControl)) {
316 LVDBE_SetVolume(pInstance, /* Instance pointer */
317 pParams); /* New parameters */
318 }
319
320 if (pInstance->Params.OperatingMode == LVDBE_ON && pParams->OperatingMode == LVDBE_OFF) {
321 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 0);
322 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 1.0f);
323 }
324 if (pInstance->Params.OperatingMode == LVDBE_OFF && pParams->OperatingMode == LVDBE_ON) {
325 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 1.0f);
326 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 0);
327 }
328
329 /*
330 * Update the instance parameters
331 */
332 pInstance->Params = *pParams;
333
334 return (LVDBE_SUCCESS);
335 }
336