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