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_Private.h" 25 26 27 /****************************************************************************************/ 28 /* */ 29 /* Defines */ 30 /* */ 31 /****************************************************************************************/ 32 33 #define PI 3.14159265358979 34 35 /****************************************************************************************/ 36 /* */ 37 /* FUNCTION: LVEQNB_DoublePrecCoefs */ 38 /* */ 39 /* DESCRIPTION: */ 40 /* Calculate double precision coefficients for a peaking filter */ 41 /* */ 42 /* PARAMETERS: */ 43 /* Fs Sampling frequency index */ 44 /* pFilterDefinition Pointer to the filter definition */ 45 /* pCoefficients Pointer to the coefficients */ 46 /* */ 47 /* RETURNS: */ 48 /* LVEQNB_SUCCESS Always succeeds */ 49 /* */ 50 /* NOTES: */ 51 /* 1. The equations used are as follows: */ 52 /* */ 53 /* G = 10^(GaindB/20) - 1 */ 54 /* t0 = 2 * Pi * Fc / Fs */ 55 /* D = 1 if GaindB >= 0 */ 56 /* D = 1 / (1 + G) if GaindB < 0 */ 57 /* */ 58 /* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */ 59 /* b1 = (0.5 - b2) * (1 - coserr(t0)) */ 60 /* a0 = (0.5 + b2) / 2 */ 61 /* */ 62 /* Where: */ 63 /* GaindB is the gain in dBs, range -15dB to +15dB */ 64 /* Fc is the centre frequency, DC to Fs/50 */ 65 /* Fs is the sample frequency, 8000 to 48000 in descrete steps */ 66 /* Q is the Q factor, 0.25 to 12 (represented by 25 to 1200) */ 67 /* */ 68 /* 2. The double precision coefficients are only used when fc is less than fs/85, so */ 69 /* the cosine of t0 is always close to 1.0. Instead of calculating the cosine */ 70 /* itself the difference from the value 1.0 is calculated, this can be done with */ 71 /* lower precision maths. */ 72 /* */ 73 /* 3. The value of the B2 coefficient is only calculated as a single precision value, */ 74 /* small errors in this value have a combined effect on the Q and Gain but not the */ 75 /* the frequency of the filter. */ 76 /* */ 77 /****************************************************************************************/ 78 79 80 LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16 Fs, 81 LVEQNB_BandDef_t *pFilterDefinition, 82 PK_C32_Coefs_t *pCoefficients) 83 { 84 85 extern LVM_INT16 LVEQNB_GainTable[]; 86 extern LVM_INT16 LVEQNB_TwoPiOnFsTable[]; 87 extern LVM_INT16 LVEQNB_DTable[]; 88 extern LVM_INT16 LVEQNB_DPCosCoef[]; 89 90 /* 91 * Get the filter definition 92 */ 93 LVM_INT16 Gain = pFilterDefinition->Gain; 94 LVM_UINT16 Frequency = pFilterDefinition->Frequency; 95 LVM_UINT16 QFactor = pFilterDefinition->QFactor; 96 97 /* 98 * Intermediate variables and temporary values 99 */ 100 LVM_INT32 T0; 101 LVM_INT16 D; 102 LVM_INT32 A0; 103 LVM_INT32 B1; 104 LVM_INT32 B2; 105 LVM_INT32 Dt0; 106 LVM_INT32 B2_Den; 107 LVM_INT32 B2_Num; 108 LVM_INT32 CosErr; 109 LVM_INT16 coef; 110 LVM_INT32 factor; 111 LVM_INT16 t0; 112 LVM_INT16 i; 113 114 /* 115 * Calculating the intermediate values 116 */ 117 T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */ 118 if (Gain >= 0) 119 { 120 D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */ 121 } 122 else 123 { 124 D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */ 125 } 126 127 /* 128 * Calculate the B2 coefficient 129 */ 130 Dt0 = D * (T0 >> 10); 131 B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2); 132 B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18); 133 B2 = (B2_Num / (B2_Den >> 16)) << 15; 134 135 /* 136 * Calculate the cosine error by a polynomial expansion using the equation: 137 * 138 * CosErr += coef(n) * t0^n For n = 0 to 4 139 */ 140 T0 = (T0 >> 6) * 0x7f53; /* Scale to 1.0 in 16-bit for range 0 to fs/50 */ 141 t0 = (LVM_INT16)(T0 >> 16); 142 factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */ 143 CosErr = 0; /* Initialise the error to zero */ 144 for (i=1; i<5; i++) 145 { 146 coef = LVEQNB_DPCosCoef[i]; /* Get the nth coefficient */ 147 CosErr += (factor * coef) >> 5; /* The nth partial sum */ 148 factor = (factor * t0) >> 15; /* Calculate t0^n */ 149 } 150 CosErr = CosErr << (LVEQNB_DPCosCoef[0]); /* Correct the scaling */ 151 152 /* 153 * Calculate the B1 and A0 coefficients 154 */ 155 B1 = (0x40000000 - B2); /* B1 = (0.5 - b2/2) */ 156 A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6; /* Temporary storage for (0.5 - b2/2) * coserr(t0) */ 157 B1 -= A0; /* B1 = (0.5 - b2/2) * (1 - coserr(t0)) */ 158 A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) */ 159 160 /* 161 * Write coeff into the data structure 162 */ 163 pCoefficients->A0 = A0; 164 pCoefficients->B1 = B1; 165 pCoefficients->B2 = B2; 166 pCoefficients->G = LVEQNB_GainTable[Gain+15]; 167 168 return(LVEQNB_SUCCESS); 169 170 } 171 172 173 /****************************************************************************************/ 174 /* */ 175 /* FUNCTION: LVEQNB_SinglePrecCoefs */ 176 /* */ 177 /* DESCRIPTION: */ 178 /* Calculate single precision coefficients for a peaking filter */ 179 /* */ 180 /* PARAMETERS: */ 181 /* Fs Sampling frequency index */ 182 /* pFilterDefinition Pointer to the filter definition */ 183 /* pCoefficients Pointer to the coefficients */ 184 /* */ 185 /* RETURNS: */ 186 /* LVEQNB_SUCCESS Always succeeds */ 187 /* */ 188 /* NOTES: */ 189 /* 1. The equations used are as follows: */ 190 /* */ 191 /* G = 10^(GaindB/20) - 1 */ 192 /* t0 = 2 * Pi * Fc / Fs */ 193 /* D = 1 if GaindB >= 0 */ 194 /* D = 1 / (1 + G) if GaindB < 0 */ 195 /* */ 196 /* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */ 197 /* b1 = (0.5 - b2) * cos(t0) */ 198 /* a0 = (0.5 + b2) / 2 */ 199 /* */ 200 /* Where: */ 201 /* GaindB is the gain in dBs, range -15dB to +15dB */ 202 /* Fc is the centre frequency, DC to Nyquist */ 203 /* Fs is the sample frequency, 8000 to 48000 in descrete steps */ 204 /* Q is the Q factor, 0.25 to 12 */ 205 /* */ 206 /****************************************************************************************/ 207 208 209 LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16 Fs, 210 LVEQNB_BandDef_t *pFilterDefinition, 211 PK_C16_Coefs_t *pCoefficients) 212 { 213 214 extern LVM_INT16 LVEQNB_GainTable[]; 215 extern LVM_INT16 LVEQNB_TwoPiOnFsTable[]; 216 extern LVM_INT16 LVEQNB_DTable[]; 217 extern LVM_INT16 LVEQNB_CosCoef[]; 218 219 220 /* 221 * Get the filter definition 222 */ 223 LVM_INT16 Gain = pFilterDefinition->Gain; 224 LVM_UINT16 Frequency = pFilterDefinition->Frequency; 225 LVM_UINT16 QFactor = pFilterDefinition->QFactor; 226 227 228 /* 229 * Intermediate variables and temporary values 230 */ 231 LVM_INT32 T0; 232 LVM_INT16 D; 233 LVM_INT32 A0; 234 LVM_INT32 B1; 235 LVM_INT32 B2; 236 LVM_INT32 Dt0; 237 LVM_INT32 B2_Den; 238 LVM_INT32 B2_Num; 239 LVM_INT32 COS_T0; 240 LVM_INT16 coef; 241 LVM_INT32 factor; 242 LVM_INT16 t0; 243 LVM_INT16 i; 244 245 /* 246 * Calculating the intermediate values 247 */ 248 T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */ 249 if (Gain >= 0) 250 { 251 D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */ 252 } 253 else 254 { 255 D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */ 256 } 257 258 /* 259 * Calculate the B2 coefficient 260 */ 261 Dt0 = D * (T0 >> 10); 262 B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2); 263 B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18); 264 B2 = (B2_Num / (B2_Den >> 16)) << 15; 265 266 /* 267 * Calculate the cosine by a polynomial expansion using the equation: 268 * 269 * Cos += coef(n) * t0^n For n = 0 to 6 270 */ 271 T0 = (T0 >> 10) * 20859; /* Scale to 1.0 in 16-bit for range 0 to fs/2 */ 272 t0 = (LVM_INT16)(T0 >> 16); 273 factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */ 274 COS_T0 = 0; /* Initialise the error to zero */ 275 for (i=1; i<7; i++) 276 { 277 coef = LVEQNB_CosCoef[i]; /* Get the nth coefficient */ 278 COS_T0 += (factor * coef) >> 5; /* The nth partial sum */ 279 factor = (factor * t0) >> 15; /* Calculate t0^n */ 280 } 281 COS_T0 = COS_T0 << (LVEQNB_CosCoef[0]+6); /* Correct the scaling */ 282 283 284 B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16); /* B1 = (0.5 - b2/2) * cos(t0) */ 285 A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2/2) */ 286 287 /* 288 * Write coeff into the data structure 289 */ 290 pCoefficients->A0 = (LVM_INT16)(A0>>16); 291 pCoefficients->B1 = (LVM_INT16)(B1>>15); 292 pCoefficients->B2 = (LVM_INT16)(B2>>16); 293 pCoefficients->G = LVEQNB_GainTable[Gain+15]; 294 295 296 return(LVEQNB_SUCCESS); 297 298 } 299