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 "LVEQNB.h" 25#include "LVEQNB_Private.h" 26#include "VectorArithmetic.h" 27#include "BIQUAD.h" 28 29 30/****************************************************************************************/ 31/* */ 32/* Defines */ 33/* */ 34/****************************************************************************************/ 35 36#define LOW_FREQ 298 /* 32768/110 for low test frequency */ 37#define HIGH_FREQ 386 /* 32768/85 for high test frequency */ 38 39/****************************************************************************************/ 40/* */ 41/* FUNCTION: LVEQNB_GetParameters */ 42/* */ 43/* DESCRIPTION: */ 44/* Request the N-Band equaliser parameters. The current parameter set is returned via */ 45/* the parameter pointer. */ 46/* */ 47/* PARAMETERS: */ 48/* hInstance Instance handle */ 49/* pParams Pointer to an empty parameter structure */ 50/* */ 51/* RETURNS: */ 52/* LVEQNB_SUCCESS Succeeds */ 53/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */ 54/* */ 55/* NOTES: */ 56/* 1. This function may be interrupted by the LVEQNB_Process function */ 57/* */ 58/****************************************************************************************/ 59 60LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t hInstance, 61 LVEQNB_Params_t *pParams) 62{ 63 64 LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; 65 66 /* 67 * Check for error conditions 68 */ 69 if((hInstance == LVM_NULL) || (pParams == LVM_NULL)) 70 { 71 return LVEQNB_NULLADDRESS; 72 } 73 74 *pParams = pInstance->Params; 75 76 return(LVEQNB_SUCCESS); 77} 78 79 80/************************************************************************************/ 81/* */ 82/* FUNCTION: LVEQNB_GetCapabilities */ 83/* */ 84/* DESCRIPTION: */ 85/* Get the N-Band equaliser capabilities. The current capabilities are returned */ 86/* via the pointer. */ 87/* */ 88/* PARAMETERS: */ 89/* hInstance Instance handle */ 90/* pCapabilities Pointer to an empty capability structure */ 91/* */ 92/* RETURNS: */ 93/* LVEQNB_Success Succeeds */ 94/* LVEQNB_NULLADDRESS hInstance or pCapabilities is NULL */ 95/* */ 96/* NOTES: */ 97/* 1. This function may be interrupted by the LVEQNB_Process function */ 98/* */ 99/************************************************************************************/ 100 101LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance, 102 LVEQNB_Capabilities_t *pCapabilities) 103{ 104 105 LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; 106 107 if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL)) 108 { 109 return LVEQNB_NULLADDRESS; 110 } 111 112 *pCapabilities = pInstance->Capabilities; 113 114 return(LVEQNB_SUCCESS); 115} 116 117 118/************************************************************************************/ 119/* */ 120/* FUNCTION: LVEQNB_SetFilters */ 121/* */ 122/* DESCRIPTION: */ 123/* Sets the filter type based on the definition. */ 124/* */ 125/* PARAMETERS: */ 126/* pInstance Pointer to the instance */ 127/* pParams Initialisation parameters */ 128/* */ 129/* RETURNS: */ 130/* void Nothing */ 131/* */ 132/* NOTES: */ 133/* 1. To select the biquad type the follow rules are applied: */ 134/* Double precision if (fc <= fs/110) */ 135/* Double precision if (fs/110 < fc < fs/85) & (Q>3) */ 136/* Single precision otherwise */ 137/* */ 138/************************************************************************************/ 139 140void LVEQNB_SetFilters(LVEQNB_Instance_t *pInstance, 141 LVEQNB_Params_t *pParams) 142{ 143 144 extern const LVM_UINT16 LVEQNB_SampleRateTab[]; /* Sample rate table */ 145 LVM_UINT16 i; /* Filter band index */ 146 LVM_UINT32 fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate]; /* Sample rate */ 147 LVM_UINT32 fc; /* Filter centre frequency */ 148 LVM_INT16 QFactor; /* Filter Q factor */ 149 150 151 pInstance->NBands = pParams->NBands; 152 153 for (i=0; i<pParams->NBands; i++) 154 { 155 /* 156 * Get the filter settings 157 */ 158 fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency; /* Get the band centre frequency */ 159 QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor; /* Get the band Q factor */ 160 161 162 /* 163 * For each filter set the type of biquad required 164 */ 165 pInstance->pBiquadType[i] = LVEQNB_SinglePrecision; /* Default to single precision */ 166 if ((fc << 15) <= (LOW_FREQ * fs)) 167 { 168 /* 169 * fc <= fs/110 170 */ 171 pInstance->pBiquadType[i] = LVEQNB_DoublePrecision; 172 } 173 else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300)) 174 { 175 /* 176 * (fs/110 < fc < fs/85) & (Q>3) 177 */ 178 pInstance->pBiquadType[i] = LVEQNB_DoublePrecision; 179 } 180 181 182 /* 183 * Check for out of range frequencies 184 */ 185 if (fc > (fs >> 1)) 186 { 187 pInstance->pBiquadType[i] = LVEQNB_OutOfRange; 188 } 189 190 191 /* 192 * Copy the filter definition to persistant memory 193 */ 194 pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i]; 195 196 } 197} 198 199 200/************************************************************************************/ 201/* */ 202/* FUNCTION: LVEQNB_SetCoefficients */ 203/* */ 204/* DESCRIPTION: */ 205/* Sets the filter coefficients. This uses the type to select single or double */ 206/* precision coefficients. */ 207/* */ 208/* PARAMETERS: */ 209/* pInstance Pointer to the instance */ 210/* pParams Initialisation parameters */ 211/* */ 212/************************************************************************************/ 213 214void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance) 215{ 216 217 LVM_UINT16 i; /* Filter band index */ 218 LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */ 219 220 221 /* 222 * Set the coefficients for each band by the init function 223 */ 224 for (i=0; i<pInstance->Params.NBands; i++) 225 { 226 227 /* 228 * Check band type for correct initialisation method and recalculate the coefficients 229 */ 230 BiquadType = pInstance->pBiquadType[i]; 231 switch (BiquadType) 232 { 233 case LVEQNB_DoublePrecision: 234 { 235 PK_C32_Coefs_t Coefficients; 236 237 /* 238 * Calculate the double precision coefficients 239 */ 240 LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate, 241 &pInstance->pBandDefinitions[i], 242 &Coefficients); 243 244 /* 245 * Set the coefficients 246 */ 247 PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i], 248 &pInstance->pEQNB_Taps[i], 249 &Coefficients); 250 break; 251 } 252 253 case LVEQNB_SinglePrecision: 254 { 255 PK_C16_Coefs_t Coefficients; 256 257 /* 258 * Calculate the single precision coefficients 259 */ 260 LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate, 261 &pInstance->pBandDefinitions[i], 262 &Coefficients); 263 264 /* 265 * Set the coefficients 266 */ 267 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i], 268 &pInstance->pEQNB_Taps[i], 269 &Coefficients); 270 break; 271 } 272 default: 273 break; 274 } 275 } 276 277} 278 279 280/************************************************************************************/ 281/* */ 282/* FUNCTION: LVEQNB_ClearFilterHistory */ 283/* */ 284/* DESCRIPTION: */ 285/* Clears the filter data history */ 286/* */ 287/* PARAMETERS: */ 288/* pInstance Pointer to the instance */ 289/* */ 290/************************************************************************************/ 291 292void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance) 293{ 294 LVM_INT16 *pTapAddress; 295 LVM_INT16 NumTaps; 296 297 298 pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps; 299 NumTaps = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16)); 300 301 if (NumTaps != 0) 302 { 303 LoadConst_16(0, /* Clear the history, value 0 */ 304 pTapAddress, /* Destination */ 305 NumTaps); /* Number of words */ 306 } 307} 308 309 310/****************************************************************************************/ 311/* */ 312/* FUNCTION: LVEQNB_Control */ 313/* */ 314/* DESCRIPTION: */ 315/* Sets or changes the LifeVibes module parameters. */ 316/* */ 317/* PARAMETERS: */ 318/* hInstance Instance handle */ 319/* pParams Pointer to a parameter structure */ 320/* */ 321/* RETURNS: */ 322/* LVEQNB_Success Always succeeds */ 323/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */ 324/* LVEQNB_NULLADDRESS NULL address for the equaliser filter definitions and the */ 325/* number of bands is non-zero */ 326/* */ 327/* NOTES: */ 328/* 1. This function may be interrupted by the LVEQNB_Process function */ 329/* */ 330/****************************************************************************************/ 331 332LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t hInstance, 333 LVEQNB_Params_t *pParams) 334{ 335 336 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; 337 LVM_INT16 bChange = LVM_FALSE; 338 LVM_INT16 i = 0; 339 LVEQNB_Mode_en OperatingModeSave ; 340 341 /* 342 * Check for error conditions 343 */ 344 if((hInstance == LVM_NULL) || (pParams == LVM_NULL)) 345 { 346 return LVEQNB_NULLADDRESS; 347 } 348 349 if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL)) 350 { 351 return LVEQNB_NULLADDRESS; 352 } 353 354 OperatingModeSave = pInstance->Params.OperatingMode; 355 356 /* Set the alpha factor of the mixer */ 357 if (pParams->SampleRate != pInstance->Params.SampleRate) 358 { 359 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); 360 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); 361 } 362 363 364 if( (pInstance->Params.NBands != pParams->NBands ) || 365 (pInstance->Params.OperatingMode != pParams->OperatingMode ) || 366 (pInstance->Params.pBandDefinition != pParams->pBandDefinition ) || 367 (pInstance->Params.SampleRate != pParams->SampleRate ) || 368 (pInstance->Params.SourceFormat != pParams->SourceFormat )) 369 { 370 371 bChange = LVM_TRUE; 372 } 373 else 374 { 375 for(i = 0; i < pParams->NBands; i++) 376 { 377 378 if((pInstance->pBandDefinitions[i].Frequency != pParams->pBandDefinition[i].Frequency )|| 379 (pInstance->pBandDefinitions[i].Gain != pParams->pBandDefinition[i].Gain )|| 380 (pInstance->pBandDefinitions[i].QFactor != pParams->pBandDefinition[i].QFactor )) 381 { 382 383 bChange = LVM_TRUE; 384 } 385 } 386 } 387 388 389 if(bChange){ 390 391 /* 392 * If the sample rate has changed clear the history 393 */ 394 if (pInstance->Params.SampleRate != pParams->SampleRate) 395 { 396 LVEQNB_ClearFilterHistory(pInstance); /* Clear the history */ 397 } 398 399 /* 400 * Update the instance parameters 401 */ 402 pInstance->Params = *pParams; 403 404 405 /* 406 * Reset the filters except if the algo is switched off 407 */ 408 if(pParams->OperatingMode != LVEQNB_BYPASS){ 409 /* 410 * Reset the filters as all parameters could have changed 411 */ 412 LVEQNB_SetFilters(pInstance, /* Instance pointer */ 413 pParams); /* New parameters */ 414 415 /* 416 * Update the filters 417 */ 418 LVEQNB_SetCoefficients(pInstance); /* Instance pointer */ 419 } 420 421 if(pParams->OperatingMode != OperatingModeSave) 422 { 423 if(pParams->OperatingMode == LVEQNB_ON) 424 { 425 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16); 426 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0); 427 428 pInstance->BypassMixer.MixerStream[0].CallbackSet = 1; 429 pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; 430 } 431 else 432 { 433 /* Stay on the ON operating mode until the transition is done */ 434 pInstance->Params.OperatingMode = LVEQNB_ON; 435 436 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0); 437 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16); 438 pInstance->BypassMixer.MixerStream[0].CallbackSet = 1; 439 pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; 440 } 441 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); 442 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); 443 444 pInstance->bInOperatingModeTransition = LVM_TRUE; 445 } 446 447 } 448 return(LVEQNB_SUCCESS); 449} 450 451 452/****************************************************************************************/ 453/* */ 454/* FUNCTION: LVEQNB_BypassMixerCallBack */ 455/* */ 456/* DESCRIPTION: */ 457/* CallBack function of the mixer */ 458/* transition */ 459/* */ 460/****************************************************************************************/ 461LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, 462 void *pGeneralPurpose, 463 LVM_INT16 CallbackParam) 464{ 465 LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; 466 LVM_Callback CallBack = pInstance->Capabilities.CallBack; 467 468 (void) pGeneralPurpose; 469 470 /* 471 * Send an ALGOFF event if the ON->OFF switch transition is finished 472 */ 473 if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) && 474 (CallbackParam == 0)){ 475 pInstance->Params.OperatingMode = LVEQNB_BYPASS; 476 if (CallBack != LVM_NULL){ 477 CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF); 478 } 479 } 480 481 /* 482 * Exit transition state 483 */ 484 pInstance->bInOperatingModeTransition = LVM_FALSE; 485 486 return 1; 487} 488 489 490 491 492 493 494