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 #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 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 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 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