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 50LVDBE_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 81LVDBE_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 106void 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 189void 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 242void 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 370LVDBE_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