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 "Mixer.h" 21 #include "LVM_Mixer_FilterCoeffs.h" 22 23 24 /************************************************************************/ 25 /* FUNCTION: */ 26 /* LVM_Mix_GetTimeConstant */ 27 /* */ 28 /* DESCRIPTION: */ 29 /* This function calculates the filter coefficient using the following */ 30 /* equation: */ 31 /* Alpha = exp(ln(0.1)/ (tc * Update + 1.0)) */ 32 /* */ 33 /* This is to be used with the follow first order filter, called at a */ 34 /* rate of Update times a second. tc is the required time constant in */ 35 /* units of 100us. */ 36 /* */ 37 /* Output(n) = Alpha * Output(n-1) + (1 - Alpha) * Target(n) */ 38 /* */ 39 /* The function assumes the block size is large, i.e. the update rate */ 40 /* is approximately a fixed, and correct factor of the value of Fs */ 41 /* given in the call. This is especially not true when the block size */ 42 /* is very small, see the mixer documentation for further details. */ 43 /* */ 44 /* The function does not support all possible combinations of input */ 45 /* values: */ 46 /* */ 47 /* 1. NumChannels is limited to the values 1 (Mono) and 2 (Stereo) */ 48 /* 2. The product tc * Fs is limited approximately to the range */ 49 /* 8 < (tc * Fs) < 2^35 */ 50 /* */ 51 /* PARAMETERS: */ 52 /* tc - the time constant in 100us steps, i.e. 10 = 1ms */ 53 /* Fs - the filter update rate in Hz */ 54 /* NumChannels - Number of channels 1=Mono, 2=Stereo */ 55 /* */ 56 /* RETURNS: */ 57 /* Alpha - the filter coefficient Q31 format */ 58 /* */ 59 /************************************************************************/ 60 #ifdef BUILD_FLOAT 61 LVM_FLOAT LVM_Mixer_TimeConstant(LVM_UINT32 tc, 62 #ifdef HIGHER_FS 63 LVM_UINT32 Fs, 64 #else 65 LVM_UINT16 Fs, 66 #endif 67 LVM_UINT16 NumChannels) 68 { 69 70 LVM_UINT32 Product; 71 LVM_FLOAT ProductFloat; 72 LVM_INT16 InterpolateShort; 73 LVM_FLOAT Interpolate; 74 LVM_UINT16 Shift; 75 LVM_FLOAT Diff; 76 LVM_FLOAT Table[] = {ALPHA_Float_0, /* Log spaced look-up table */ 77 ALPHA_Float_1, 78 ALPHA_Float_2, 79 ALPHA_Float_3, 80 ALPHA_Float_4, 81 ALPHA_Float_5, 82 ALPHA_Float_6, 83 ALPHA_Float_7, 84 ALPHA_Float_8, 85 ALPHA_Float_9, 86 ALPHA_Float_10, 87 ALPHA_Float_11, 88 ALPHA_Float_12, 89 ALPHA_Float_13, 90 ALPHA_Float_14, 91 ALPHA_Float_15, 92 ALPHA_Float_16, 93 ALPHA_Float_17, 94 ALPHA_Float_18, 95 ALPHA_Float_19, 96 ALPHA_Float_20, 97 ALPHA_Float_21, 98 ALPHA_Float_22, 99 ALPHA_Float_23, 100 ALPHA_Float_24, 101 ALPHA_Float_25, 102 ALPHA_Float_26, 103 ALPHA_Float_27, 104 ALPHA_Float_28, 105 ALPHA_Float_29, 106 ALPHA_Float_30, 107 ALPHA_Float_31, 108 ALPHA_Float_32, 109 ALPHA_Float_33, 110 ALPHA_Float_34, 111 ALPHA_Float_35, 112 ALPHA_Float_36, 113 ALPHA_Float_37, 114 ALPHA_Float_38, 115 ALPHA_Float_39, 116 ALPHA_Float_40, 117 ALPHA_Float_41, 118 ALPHA_Float_42, 119 ALPHA_Float_43, 120 ALPHA_Float_44, 121 ALPHA_Float_45, 122 ALPHA_Float_46, 123 ALPHA_Float_47, 124 ALPHA_Float_48, 125 ALPHA_Float_49, 126 ALPHA_Float_50}; 127 128 /* Calculate the product of the time constant and the sample rate */ 129 Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13; /* Stereo value */ 130 Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3); 131 132 if (NumChannels == 1) 133 { 134 Product = Product >> 1; /* Mono value */ 135 } 136 137 /* Normalize to get the table index and interpolation factor */ 138 for (Shift = 0; Shift < ((Alpha_TableSize - 1) / 2); Shift++) 139 { 140 if ((Product & 0x80000000) != 0) 141 { 142 break; 143 } 144 145 Product = Product << 1; 146 } 147 Shift = (LVM_UINT16)((Shift << 1)); 148 149 if ((Product & 0x40000000)==0) 150 { 151 Shift++; 152 } 153 154 InterpolateShort = (LVM_INT16)((Product >> 15) & 0x00007FFF); 155 Interpolate = (LVM_FLOAT)InterpolateShort / 32768.0f; 156 157 Diff = (Table[Shift] - Table[Shift + 1]); 158 Diff = Diff * Interpolate; 159 ProductFloat = Table[Shift + 1] + Diff; 160 161 return ProductFloat; 162 } 163 #else 164 LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32 tc, 165 LVM_UINT16 Fs, 166 LVM_UINT16 NumChannels) 167 { 168 169 LVM_UINT32 Product; 170 LVM_INT16 Interpolate; 171 LVM_UINT16 Shift; 172 LVM_INT32 Diff; 173 LVM_UINT32 Table[] = {ALPHA_0, /* Log spaced look-up table */ 174 ALPHA_1, 175 ALPHA_2, 176 ALPHA_3, 177 ALPHA_4, 178 ALPHA_5, 179 ALPHA_6, 180 ALPHA_7, 181 ALPHA_8, 182 ALPHA_9, 183 ALPHA_10, 184 ALPHA_11, 185 ALPHA_12, 186 ALPHA_13, 187 ALPHA_14, 188 ALPHA_15, 189 ALPHA_16, 190 ALPHA_17, 191 ALPHA_18, 192 ALPHA_19, 193 ALPHA_20, 194 ALPHA_21, 195 ALPHA_22, 196 ALPHA_23, 197 ALPHA_24, 198 ALPHA_25, 199 ALPHA_26, 200 ALPHA_27, 201 ALPHA_28, 202 ALPHA_29, 203 ALPHA_30, 204 ALPHA_31, 205 ALPHA_32, 206 ALPHA_33, 207 ALPHA_34, 208 ALPHA_35, 209 ALPHA_36, 210 ALPHA_37, 211 ALPHA_38, 212 ALPHA_39, 213 ALPHA_40, 214 ALPHA_41, 215 ALPHA_42, 216 ALPHA_43, 217 ALPHA_44, 218 ALPHA_45, 219 ALPHA_46, 220 ALPHA_47, 221 ALPHA_48, 222 ALPHA_49, 223 ALPHA_50}; 224 225 226 /* Calculate the product of the time constant and the sample rate */ 227 Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13; /* Stereo value */ 228 Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3); 229 230 if (NumChannels == 1) 231 { 232 Product = Product >> 1; /* Mono value */ 233 } 234 235 /* Normalize to get the table index and interpolation factor */ 236 for (Shift=0; Shift<((Alpha_TableSize-1)/2); Shift++) 237 { 238 if ((Product & 0x80000000)!=0) 239 { 240 break; 241 } 242 243 Product = Product << 1; 244 } 245 Shift = (LVM_UINT16)((Shift << 1)); 246 247 if ((Product & 0x40000000)==0) 248 { 249 Shift++; 250 } 251 252 Interpolate = (LVM_INT16)((Product >> 15) & 0x00007FFF); 253 254 Diff = (LVM_INT32)(Table[Shift] - Table[Shift+1]); 255 MUL32x16INTO32(Diff,Interpolate,Diff,15) 256 Product = Table[Shift+1] + (LVM_UINT32)Diff; 257 258 return Product; 259 } 260 #endif 261