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 72LVM_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 98LVM_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