summaryrefslogtreecommitdiffstats
path: root/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c')
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c306
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);
+
+}