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 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 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 106 void LVDBE_SetFilters(LVDBE_Instance_t *pInstance, 107 LVDBE_Params_t *pParams) 108 { 109 110 /* 111 * Calculate the table offsets 112 */ 113 LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000))); 114 115 116 /* 117 * Setup the high pass filter 118 */ 119 LoadConst_16(0, /* Clear the history, value 0 */ 120 (void *)&pInstance->pData->HPFTaps, /* Destination Cast to void: \ 121 no dereferencing in function*/ 122 sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16)); /* Number of words */ 123 BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */ 124 &pInstance->pData->HPFTaps, 125 (BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]); 126 127 128 /* 129 * Setup the band pass filter 130 */ 131 LoadConst_16(0, /* Clear the history, value 0 */ 132 (void *)&pInstance->pData->BPFTaps, /* Destination Cast to void:\ 133 no dereferencing in function*/ 134 sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16)); /* Number of words */ 135 BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */ 136 &pInstance->pData->BPFTaps, 137 (BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]); 138 139 } 140 141 142 143 /************************************************************************************/ 144 /* */ 145 /* FUNCTION: LVDBE_SetAGC */ 146 /* */ 147 /* DESCRIPTION: */ 148 /* Sets the AGC gain level and attack and decay times constants. */ 149 /* */ 150 /* PARAMETERS: */ 151 /* pInstance Pointer to the instance */ 152 /* pParams Initialisation parameters */ 153 /* */ 154 /************************************************************************************/ 155 156 void LVDBE_SetAGC(LVDBE_Instance_t *pInstance, 157 LVDBE_Params_t *pParams) 158 { 159 160 /* 161 * Get the attack and decay time constants 162 */ 163 pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate]; /* Attack multiplier */ 164 pInstance->pData->AGCInstance.AGC_Decay = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate]; /* Decay multipler */ 165 166 167 /* 168 * Get the boost gain 169 */ 170 if (pParams->HPFSelect == LVDBE_HPF_ON) 171 { 172 pInstance->pData->AGCInstance.AGC_MaxGain = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter on */ 173 } 174 else 175 { 176 pInstance->pData->AGCInstance.AGC_MaxGain = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter off */ 177 } 178 pInstance->pData->AGCInstance.AGC_GainShift = AGC_GAIN_SHIFT; 179 pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL; 180 181 } 182 183 184 /************************************************************************************/ 185 /* */ 186 /* FUNCTION: LVDBE_SetVolume */ 187 /* */ 188 /* DESCRIPTION: */ 189 /* Converts the input volume demand from dBs to linear. */ 190 /* */ 191 /* PARAMETERS: */ 192 /* pInstance Pointer to the instance */ 193 /* pParams Initialisation parameters */ 194 /* */ 195 /* NOTES: */ 196 /* 1. The volume should have the following settings: */ 197 /* */ 198 /* DBE Vol Control Volume setting */ 199 /* === =========== =================== */ 200 /* Off Off HeadroomdB */ 201 /* Off On VolumedB+HeadroomdB */ 202 /* On Off HeadroomdB */ 203 /* On On VolumedB+HeadroomdB */ 204 /* */ 205 /************************************************************************************/ 206 207 void LVDBE_SetVolume(LVDBE_Instance_t *pInstance, 208 LVDBE_Params_t *pParams) 209 { 210 211 LVM_UINT16 dBShifts; /* 6dB shifts */ 212 LVM_UINT16 dBOffset; /* Table offset */ 213 LVM_INT16 Volume = 0; /* Required volume in dBs */ 214 215 /* 216 * Apply the volume if enabled 217 */ 218 if (pParams->VolumeControl == LVDBE_VOLUME_ON) 219 { 220 /* 221 * Limit the gain to the maximum allowed 222 */ 223 if (pParams->VolumedB > VOLUME_MAX) 224 { 225 Volume = VOLUME_MAX; 226 } 227 else 228 { 229 Volume = pParams->VolumedB; 230 } 231 } 232 233 234 /* 235 * Calculate the required gain and shifts 236 */ 237 dBOffset = (LVM_UINT16)(6 + Volume % 6); /* Get the dBs 0-5 */ 238 dBShifts = (LVM_UINT16)(Volume / -6); /* Get the 6dB shifts */ 239 240 241 /* 242 * When DBE is enabled use AGC volume 243 */ 244 pInstance->pData->AGCInstance.Target = ((LVM_INT32)LVDBE_VolumeTable[dBOffset] << 16); 245 pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target >> dBShifts; 246 247 pInstance->pData->AGCInstance.VolumeTC = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate]; /* Volume update time constant */ 248 pInstance->pData->AGCInstance.VolumeShift = VOLUME_SHIFT+1; 249 250 /* 251 * When DBE is disabled use the bypass volume control 252 */ 253 if(dBShifts > 0) 254 { 255 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(((LVM_INT32)LVDBE_VolumeTable[dBOffset]) >> dBShifts)); 256 } 257 else 258 { 259 LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(LVM_INT32)LVDBE_VolumeTable[dBOffset]); 260 } 261 262 pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1; 263 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0], 264 LVDBE_MIXER_TC, 265 (LVM_Fs_en)pInstance->Params.SampleRate, 266 2); 267 } 268 269 270 /****************************************************************************************/ 271 /* */ 272 /* FUNCTION: LVDBE_Control */ 273 /* */ 274 /* DESCRIPTION: */ 275 /* Sets or changes the Bass Enhancement parameters. Changing the parameters while the */ 276 /* module is processing signals may have the following side effects: */ 277 /* */ 278 /* General parameters: */ 279 /* =================== */ 280 /* OperatingMode: Changing the mode of operation may cause a change in volume */ 281 /* level or cause pops and clicks. */ 282 /* */ 283 /* SampleRate: Changing the sample rate may cause pops and clicks. */ 284 /* */ 285 /* EffectLevel: Changing the effect level may cause pops and clicks */ 286 /* */ 287 /* CentreFrequency: Changing the centre frequency may cause pops and clicks */ 288 /* */ 289 /* HPFSelect: Selecting/de-selecting the high pass filter may cause pops and */ 290 /* clicks */ 291 /* */ 292 /* VolumedB Changing the volume setting will have no side effects */ 293 /* */ 294 /* */ 295 /* PARAMETERS: */ 296 /* hInstance Instance handle */ 297 /* pParams Pointer to a parameter structure */ 298 /* */ 299 /* RETURNS: */ 300 /* LVDBE_SUCCESS Always succeeds */ 301 /* */ 302 /* NOTES: */ 303 /* 1. This function must not be interrupted by the LVDBE_Process function */ 304 /* */ 305 /****************************************************************************************/ 306 307 LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance, 308 LVDBE_Params_t *pParams) 309 { 310 311 LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance; 312 LVMixer3_2St_st *pBypassMixer_Instance = &pInstance->pData->BypassMixer; 313 314 315 /* 316 * Update the filters 317 */ 318 if ((pInstance->Params.SampleRate != pParams->SampleRate) || 319 (pInstance->Params.CentreFrequency != pParams->CentreFrequency)) 320 { 321 LVDBE_SetFilters(pInstance, /* Instance pointer */ 322 pParams); /* New parameters */ 323 } 324 325 326 /* 327 * Update the AGC is the effect level has changed 328 */ 329 if ((pInstance->Params.SampleRate != pParams->SampleRate) || 330 (pInstance->Params.EffectLevel != pParams->EffectLevel) || 331 (pInstance->Params.HPFSelect != pParams->HPFSelect)) 332 { 333 LVDBE_SetAGC(pInstance, /* Instance pointer */ 334 pParams); /* New parameters */ 335 336 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0], 337 LVDBE_BYPASS_MIXER_TC,pParams->SampleRate,2); 338 339 LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1], 340 LVDBE_BYPASS_MIXER_TC,pParams->SampleRate,2); 341 342 343 } 344 345 346 /* 347 * Update the Volume if the volume demand has changed 348 */ 349 if ((pInstance->Params.VolumedB != pParams->VolumedB) || 350 (pInstance->Params.SampleRate != pParams->SampleRate) || 351 (pInstance->Params.HeadroomdB != pParams->HeadroomdB) || 352 (pInstance->Params.VolumeControl != pParams->VolumeControl)) 353 { 354 LVDBE_SetVolume(pInstance, /* Instance pointer */ 355 pParams); /* New parameters */ 356 } 357 358 if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF) 359 { 360 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0); 361 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0x00007FFF); 362 } 363 if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON) 364 { 365 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0x00007FFF); 366 LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0); 367 } 368 369 /* 370 * Update the instance parameters 371 */ 372 pInstance->Params = *pParams; 373 374 375 return(LVDBE_SUCCESS); 376 } 377