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 #include "LVM_Types.h"
19 #include "LVM_Macros.h"
20 #include "ScalarArithmetic.h"
21 #include "BIQUAD.h"
22 #include "Filter.h"
23
24
25 /*-------------------------------------------------------------------------*/
26 /* FUNCTION: */
27 /* void LVM_FO_LPF( LVM_INT32 w , */
28 /* FO_C32_Coefs_t *pCoeffs); */
29 /* */
30 /* */
31 /* DESCRIPTION: */
32 /* This function calculates the coefficient of first order low pass */
33 /* filter. It uses the equations: */
34 /* */
35 /* B1 = (tan(w/2) - 1 ) / (tan(w/2) + 1 ) */
36 /* A0 = (1 + B1) / 2 */
37 /* A1 = A0 */
38 /* */
39 /* The value of B1 is then calculated directly from the value w by a */
40 /* polynomial expansion using a 9th order polynomial. It uses the */
41 /* following table of 32-bit integer polynomial coefficients: */
42 /* */
43 /* Coefficient Value */
44 /* A0 -8388571 */
45 /* A1 33547744 */
46 /* A2 -66816791 */
47 /* A3 173375308 */
48 /* A4 -388437573 */
49 /* A5 752975383 */
50 /* A6 -1103016663 */
51 /* A7 1121848567 */
52 /* A8 -688078159 */
53 /* A9 194669577 */
54 /* A10 8 */
55 /* */
56 /* Y = (A0 + A1*X + A2*X2 + A3*X3 + �.. + AN*xN) << AN+1 */
57 /* */
58 /* */
59 /* PARAMETERS: */
60 /* */
61 /* w Sample rate in radians, where: */
62 /* w = 2 * Pi * Fc / Fs */
63 /* Fc is the corner frequency in Hz */
64 /* Fs is the sample rate in Hz */
65 /* w is in Q2.29 format and data range is [0 Pi] */
66 /* pCoeffs Points to the filter coefficients calculated here */
67 /* in Q1.30 format */
68 /* RETURNS: */
69 /* */
70 /*-------------------------------------------------------------------------*/
71 #ifdef BUILD_FLOAT
LVM_FO_LPF(LVM_FLOAT w,FO_FLOAT_Coefs_t * pCoeffs)72 LVM_FLOAT LVM_FO_LPF( LVM_FLOAT w,
73 FO_FLOAT_Coefs_t *pCoeffs)
74 {
75 LVM_FLOAT Y,Coefficients[13] = {-0.999996f,
76 0.999801f,
77 -0.497824f,
78 0.322937f,
79 -0.180880f,
80 0.087658f,
81 -0.032102f,
82 0.008163f,
83 -0.001252f,
84 0.000089f,
85 0};
86 Y=LVM_Polynomial((LVM_UINT16)9, Coefficients, w);
87 pCoeffs->B1 = -Y; // Store -B1 in filter structure instead of B1!
88 // A0=(1+B1)/2= B1/2 + 0.5
89 Y = Y / 2.0f; // A0=Y=B1/2
90 Y = Y + 0.5f; // A0=Y=(B1/2 + 0.5)
91
92 pCoeffs->A0 = Y * FILTER_LOSS_FLOAT;
93 pCoeffs->A1 = pCoeffs->A0;
94
95 return 1;
96 }
97 #else
LVM_FO_LPF(LVM_INT32 w,FO_C32_Coefs_t * pCoeffs)98 LVM_INT32 LVM_FO_LPF( LVM_INT32 w,
99 FO_C32_Coefs_t *pCoeffs)
100 {
101 LVM_INT32 Y,Coefficients[13]={ -8388571,
102 33547744,
103 -66816791,
104 173375308,
105 -388437573,
106 752975383,
107 -1103016663,
108 1121848567,
109 -688078159,
110 194669577,
111 8};
112 Y=LVM_Polynomial( (LVM_UINT16)9,
113 Coefficients,
114 w);
115 pCoeffs->B1=-Y; // Store -B1 in filter structure instead of B1!
116 // A0=(1+B1)/2= B1/2 + 0.5
117 Y=Y>>1; // A0=Y=B1/2
118 Y=Y+0x40000000; // A0=Y=(B1/2 + 0.5)
119 MUL32x16INTO32(Y, FILTER_LOSS ,pCoeffs->A0 ,15) // Apply loss to avoid overflow
120 pCoeffs->A1=pCoeffs->A0;
121 return 1;
122 }
123 #endif
124