diff options
Diffstat (limited to 'media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c')
-rwxr-xr-x | media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c new file mode 100755 index 0000000..4881049 --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2004-2010 NXP Software + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/********************************************************************************** + + $Author: beq07716 $ + $Revision: 1005 $ + $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $ + +***********************************************************************************/ + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVEQNB_Private.h" + + +/****************************************************************************************/ +/* */ +/* Defines */ +/* */ +/****************************************************************************************/ + +#define PI 3.14159265358979 + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_DoublePrecCoefs */ +/* */ +/* DESCRIPTION: */ +/* Calculate double precision coefficients for a peaking filter */ +/* */ +/* PARAMETERS: */ +/* Fs Sampling frequency index */ +/* pFilterDefinition Pointer to the filter definition */ +/* pCoefficients Pointer to the coefficients */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Always succeeds */ +/* */ +/* NOTES: */ +/* 1. The equations used are as follows: */ +/* */ +/* G = 10^(GaindB/20) - 1 */ +/* t0 = 2 * Pi * Fc / Fs */ +/* D = 1 if GaindB >= 0 */ +/* D = 1 / (1 + G) if GaindB < 0 */ +/* */ +/* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */ +/* b1 = (0.5 - b2) * (1 - coserr(t0)) */ +/* a0 = (0.5 + b2) / 2 */ +/* */ +/* Where: */ +/* GaindB is the gain in dBs, range -15dB to +15dB */ +/* Fc is the centre frequency, DC to Fs/50 */ +/* Fs is the sample frequency, 8000 to 48000 in descrete steps */ +/* Q is the Q factor, 0.25 to 12 (represented by 25 to 1200) */ +/* */ +/* 2. The double precision coefficients are only used when fc is less than fs/85, so */ +/* the cosine of t0 is always close to 1.0. Instead of calculating the cosine */ +/* itself the difference from the value 1.0 is calculated, this can be done with */ +/* lower precision maths. */ +/* */ +/* 3. The value of the B2 coefficient is only calculated as a single precision value, */ +/* small errors in this value have a combined effect on the Q and Gain but not the */ +/* the frequency of the filter. */ +/* */ +/****************************************************************************************/ + + +LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16 Fs, + LVEQNB_BandDef_t *pFilterDefinition, + PK_C32_Coefs_t *pCoefficients) +{ + + extern LVM_INT16 LVEQNB_GainTable[]; + extern LVM_INT16 LVEQNB_TwoPiOnFsTable[]; + extern LVM_INT16 LVEQNB_DTable[]; + extern LVM_INT16 LVEQNB_DPCosCoef[]; + + /* + * Get the filter definition + */ + LVM_INT16 Gain = pFilterDefinition->Gain; + LVM_UINT16 Frequency = pFilterDefinition->Frequency; + LVM_UINT16 QFactor = pFilterDefinition->QFactor; + + /* + * Intermediate variables and temporary values + */ + LVM_INT32 T0; + LVM_INT16 D; + LVM_INT32 A0; + LVM_INT32 B1; + LVM_INT32 B2; + LVM_INT32 Dt0; + LVM_INT32 B2_Den; + LVM_INT32 B2_Num; + LVM_INT32 CosErr; + LVM_INT16 coef; + LVM_INT32 factor; + LVM_INT16 t0; + LVM_INT16 i; + + /* + * Calculating the intermediate values + */ + T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */ + if (Gain >= 0) + { + D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */ + } + else + { + D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */ + } + + /* + * Calculate the B2 coefficient + */ + Dt0 = D * (T0 >> 10); + B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2); + B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18); + B2 = (B2_Num / (B2_Den >> 16)) << 15; + + /* + * Calculate the cosine error by a polynomial expansion using the equation: + * + * CosErr += coef(n) * t0^n For n = 0 to 4 + */ + T0 = (T0 >> 6) * 0x7f53; /* Scale to 1.0 in 16-bit for range 0 to fs/50 */ + t0 = (LVM_INT16)(T0 >> 16); + factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */ + CosErr = 0; /* Initialise the error to zero */ + for (i=1; i<5; i++) + { + coef = LVEQNB_DPCosCoef[i]; /* Get the nth coefficient */ + CosErr += (factor * coef) >> 5; /* The nth partial sum */ + factor = (factor * t0) >> 15; /* Calculate t0^n */ + } + CosErr = CosErr << (LVEQNB_DPCosCoef[0]); /* Correct the scaling */ + + /* + * Calculate the B1 and A0 coefficients + */ + B1 = (0x40000000 - B2); /* B1 = (0.5 - b2/2) */ + A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6; /* Temporary storage for (0.5 - b2/2) * coserr(t0) */ + B1 -= A0; /* B1 = (0.5 - b2/2) * (1 - coserr(t0)) */ + A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) */ + + /* + * Write coeff into the data structure + */ + pCoefficients->A0 = A0; + pCoefficients->B1 = B1; + pCoefficients->B2 = B2; + pCoefficients->G = LVEQNB_GainTable[Gain+15]; + + return(LVEQNB_SUCCESS); + +} + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_SinglePrecCoefs */ +/* */ +/* DESCRIPTION: */ +/* Calculate single precision coefficients for a peaking filter */ +/* */ +/* PARAMETERS: */ +/* Fs Sampling frequency index */ +/* pFilterDefinition Pointer to the filter definition */ +/* pCoefficients Pointer to the coefficients */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Always succeeds */ +/* */ +/* NOTES: */ +/* 1. The equations used are as follows: */ +/* */ +/* G = 10^(GaindB/20) - 1 */ +/* t0 = 2 * Pi * Fc / Fs */ +/* D = 1 if GaindB >= 0 */ +/* D = 1 / (1 + G) if GaindB < 0 */ +/* */ +/* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */ +/* b1 = (0.5 - b2) * cos(t0) */ +/* a0 = (0.5 + b2) / 2 */ +/* */ +/* Where: */ +/* GaindB is the gain in dBs, range -15dB to +15dB */ +/* Fc is the centre frequency, DC to Nyquist */ +/* Fs is the sample frequency, 8000 to 48000 in descrete steps */ +/* Q is the Q factor, 0.25 to 12 */ +/* */ +/****************************************************************************************/ + + +LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16 Fs, + LVEQNB_BandDef_t *pFilterDefinition, + PK_C16_Coefs_t *pCoefficients) +{ + + extern LVM_INT16 LVEQNB_GainTable[]; + extern LVM_INT16 LVEQNB_TwoPiOnFsTable[]; + extern LVM_INT16 LVEQNB_DTable[]; + extern LVM_INT16 LVEQNB_CosCoef[]; + + + /* + * Get the filter definition + */ + LVM_INT16 Gain = pFilterDefinition->Gain; + LVM_UINT16 Frequency = pFilterDefinition->Frequency; + LVM_UINT16 QFactor = pFilterDefinition->QFactor; + + + /* + * Intermediate variables and temporary values + */ + LVM_INT32 T0; + LVM_INT16 D; + LVM_INT32 A0; + LVM_INT32 B1; + LVM_INT32 B2; + LVM_INT32 Dt0; + LVM_INT32 B2_Den; + LVM_INT32 B2_Num; + LVM_INT32 COS_T0; + LVM_INT16 coef; + LVM_INT32 factor; + LVM_INT16 t0; + LVM_INT16 i; + + /* + * Calculating the intermediate values + */ + T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */ + if (Gain >= 0) + { + D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */ + } + else + { + D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */ + } + + /* + * Calculate the B2 coefficient + */ + Dt0 = D * (T0 >> 10); + B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2); + B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18); + B2 = (B2_Num / (B2_Den >> 16)) << 15; + + /* + * Calculate the cosine by a polynomial expansion using the equation: + * + * Cos += coef(n) * t0^n For n = 0 to 6 + */ + T0 = (T0 >> 10) * 20859; /* Scale to 1.0 in 16-bit for range 0 to fs/2 */ + t0 = (LVM_INT16)(T0 >> 16); + factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */ + COS_T0 = 0; /* Initialise the error to zero */ + for (i=1; i<7; i++) + { + coef = LVEQNB_CosCoef[i]; /* Get the nth coefficient */ + COS_T0 += (factor * coef) >> 5; /* The nth partial sum */ + factor = (factor * t0) >> 15; /* Calculate t0^n */ + } + COS_T0 = COS_T0 << (LVEQNB_CosCoef[0]+6); /* Correct the scaling */ + + + B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16); /* B1 = (0.5 - b2/2) * cos(t0) */ + A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2/2) */ + + /* + * Write coeff into the data structure + */ + pCoefficients->A0 = (LVM_INT16)(A0>>16); + pCoefficients->B1 = (LVM_INT16)(B1>>15); + pCoefficients->B2 = (LVM_INT16)(B2>>16); + pCoefficients->G = LVEQNB_GainTable[Gain+15]; + + + return(LVEQNB_SUCCESS); + +} |