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
LVM_Mixer_TimeConstant(LVM_UINT32 tc,LVM_UINT32 Fs,LVM_UINT16 NumChannels)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
LVM_Mixer_TimeConstant(LVM_UINT32 tc,LVM_UINT16 Fs,LVM_UINT16 NumChannels)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