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 /* FUNCTION: */
25 /* LVM_Mix_GetTimeConstant */
26 /* */
27 /* DESCRIPTION: */
28 /* This function calculates the filter coefficient using the following */
29 /* equation: */
30 /* Alpha = exp(ln(0.1)/ (tc * Update + 1.0)) */
31 /* */
32 /* This is to be used with the follow first order filter, called at a */
33 /* rate of Update times a second. tc is the required time constant in */
34 /* units of 100us. */
35 /* */
36 /* Output(n) = Alpha * Output(n-1) + (1 - Alpha) * Target(n) */
37 /* */
38 /* The function assumes the block size is large, i.e. the update rate */
39 /* is approximately a fixed, and correct factor of the value of Fs */
40 /* given in the call. This is especially not true when the block size */
41 /* is very small, see the mixer documentation for further details. */
42 /* */
43 /* The function does not support all possible combinations of input */
44 /* values: */
45 /* */
46 /* 1. NumChannels is limited to the values 1 (Mono) and 2 (Stereo) */
47 /* 2. The product tc * Fs is limited approximately to the range */
48 /* 8 < (tc * Fs) < 2^35 */
49 /* */
50 /* PARAMETERS: */
51 /* tc - the time constant in 100us steps, i.e. 10 = 1ms */
52 /* Fs - the filter update rate in Hz */
53 /* NumChannels - Number of channels 1=Mono, 2=Stereo */
54 /* */
55 /* RETURNS: */
56 /* Alpha - the filter coefficient Q31 format */
57 /* */
58 /************************************************************************/
LVM_Mixer_TimeConstant(LVM_UINT32 tc,LVM_UINT32 Fs,LVM_UINT16 NumChannels)59 LVM_FLOAT LVM_Mixer_TimeConstant(LVM_UINT32 tc, LVM_UINT32 Fs, LVM_UINT16 NumChannels) {
60 LVM_UINT32 Product;
61 LVM_FLOAT ProductFloat;
62 LVM_INT16 InterpolateShort;
63 LVM_FLOAT Interpolate;
64 LVM_UINT16 Shift;
65 LVM_FLOAT Diff;
66 LVM_FLOAT Table[] = {
67 ALPHA_Float_0, /* Log spaced look-up table */
68 ALPHA_Float_1, ALPHA_Float_2, ALPHA_Float_3, ALPHA_Float_4, ALPHA_Float_5,
69 ALPHA_Float_6, ALPHA_Float_7, ALPHA_Float_8, ALPHA_Float_9, ALPHA_Float_10,
70 ALPHA_Float_11, ALPHA_Float_12, ALPHA_Float_13, ALPHA_Float_14, ALPHA_Float_15,
71 ALPHA_Float_16, ALPHA_Float_17, ALPHA_Float_18, ALPHA_Float_19, ALPHA_Float_20,
72 ALPHA_Float_21, ALPHA_Float_22, ALPHA_Float_23, ALPHA_Float_24, ALPHA_Float_25,
73 ALPHA_Float_26, ALPHA_Float_27, ALPHA_Float_28, ALPHA_Float_29, ALPHA_Float_30,
74 ALPHA_Float_31, ALPHA_Float_32, ALPHA_Float_33, ALPHA_Float_34, ALPHA_Float_35,
75 ALPHA_Float_36, ALPHA_Float_37, ALPHA_Float_38, ALPHA_Float_39, ALPHA_Float_40,
76 ALPHA_Float_41, ALPHA_Float_42, ALPHA_Float_43, ALPHA_Float_44, ALPHA_Float_45,
77 ALPHA_Float_46, ALPHA_Float_47, ALPHA_Float_48, ALPHA_Float_49, ALPHA_Float_50};
78
79 /* Calculate the product of the time constant and the sample rate */
80 Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13; /* Stereo value */
81 Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3);
82
83 if (NumChannels == 1) {
84 Product = Product >> 1; /* Mono value */
85 }
86
87 /* Normalize to get the table index and interpolation factor */
88 for (Shift = 0; Shift < ((Alpha_TableSize - 1) / 2); Shift++) {
89 if ((Product & 0x80000000) != 0) {
90 break;
91 }
92
93 Product = Product << 1;
94 }
95 Shift = (LVM_UINT16)((Shift << 1));
96
97 if ((Product & 0x40000000) == 0) {
98 Shift++;
99 }
100
101 InterpolateShort = (LVM_INT16)((Product >> 15) & 0x00007FFF);
102 Interpolate = (LVM_FLOAT)InterpolateShort / 32768.0f;
103
104 Diff = (Table[Shift] - Table[Shift + 1]);
105 Diff = Diff * Interpolate;
106 ProductFloat = Table[Shift + 1] + Diff;
107
108 return ProductFloat;
109 }
110