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 #include <math.h>
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 /*                                                                                      */
81 /* FUNCTION:                  LVEQNB_SinglePrecCoefs                                    */
82 /*                                                                                      */
83 /* DESCRIPTION:                                                                         */
84 /*    Calculate single precision coefficients    for a peaking filter                   */
85 /*                                                                                      */
86 /* PARAMETERS:                                                                          */
87 /*  Fs                           Sampling frequency index                               */
88 /*  pFilterDefinition          Pointer to the filter definition                         */
89 /*  pCoefficients            Pointer to the coefficients                                */
90 /*                                                                                      */
91 /* RETURNS:                                                                             */
92 /*  LVEQNB_SUCCESS            Always succeeds                                           */
93 /*                                                                                      */
94 /* NOTES:                                                                               */
95 /*  1. The equations used are as follows:                                               */
96 /*                                                                                      */
97 /*      G  = 10^(GaindB/20) - 1                                                         */
98 /*      t0 = 2 * Pi * Fc / Fs                                                           */
99 /*      D  = 1                  if GaindB >= 0                                          */
100 /*      D  = 1 / (1 + G)        if GaindB <  0                                          */
101 /*                                                                                      */
102 /*      b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0)                                       */
103 /*      b1 = (0.5 - b2) * cos(t0)                                                       */
104 /*      a0 = (0.5 + b2) / 2                                                             */
105 /*                                                                                      */
106 /*  Where:                                                                              */
107 /*      GaindB      is the gain in dBs, range -15dB to +15dB                            */
108 /*      Fc          is the centre frequency, DC to Nyquist                              */
109 /*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
110 /*      Q           is the Q factor, 0.25 to 12                                         */
111 /*                                                                                      */
112 /****************************************************************************************/
113 
LVEQNB_SinglePrecCoefs(LVM_UINT16 Fs,LVEQNB_BandDef_t * pFilterDefinition,PK_FLOAT_Coefs_t * pCoefficients)114 LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
115                                               LVEQNB_BandDef_t  *pFilterDefinition,
116                                               PK_FLOAT_Coefs_t  *pCoefficients)
117 {
118 
119     extern LVM_FLOAT    LVEQNB_GainTable[];
120     extern LVM_FLOAT    LVEQNB_TwoPiOnFsTable[];
121     extern LVM_FLOAT    LVEQNB_DTable[];
122 
123     /*
124      * Get the filter definition
125      */
126     LVM_INT16           Gain        = pFilterDefinition->Gain;
127     LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
128     /* As mentioned in effectbundle.h */
129     LVM_FLOAT           QFactor     = (LVM_FLOAT)pFilterDefinition->QFactor / 100.0f;
130 
131     /*
132      * Intermediate variables and temporary values
133      */
134     LVM_FLOAT           T0;
135     LVM_FLOAT           D;
136     LVM_FLOAT           A0;
137     LVM_FLOAT           B1;
138     LVM_FLOAT           B2;
139 
140     /*
141      * Calculating the intermediate values
142      */
143     T0 = Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
144     if (Gain >= 0)
145     {
146         D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
147     }
148     else
149     {
150         D = LVEQNB_DTable[Gain + 15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
151     }
152 
153     /*
154      * Calculate the B2,B1,A0 coefficients
155      */
156     B2 = -0.5 * (2 * QFactor - D * T0) / (2 * QFactor + D * T0);
157     B1 = (0.5 - B2) * cos(T0);
158     A0 = (0.5 + B2) / 2.0;
159 
160     /*
161      * Write coeff into the data structure
162      */
163     /* all the coefficients are multiplied with 2 to make them align with fixed point values*/
164     pCoefficients->A0 = 2 * A0;
165     pCoefficients->B1 = 2 * B1;
166     pCoefficients->B2 = 2 * B2;
167     pCoefficients->G  = LVEQNB_GainTable[Gain + 15];
168 
169     return(LVEQNB_SUCCESS);
170 }
171