1*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
2*f81fb7c4SAndroid Build Coastguard Worker *
3*f81fb7c4SAndroid Build Coastguard Worker * File:
4*f81fb7c4SAndroid Build Coastguard Worker * eas_math.c
5*f81fb7c4SAndroid Build Coastguard Worker *
6*f81fb7c4SAndroid Build Coastguard Worker * Contents and purpose:
7*f81fb7c4SAndroid Build Coastguard Worker * Contains common math routines for the various audio engines.
8*f81fb7c4SAndroid Build Coastguard Worker *
9*f81fb7c4SAndroid Build Coastguard Worker *
10*f81fb7c4SAndroid Build Coastguard Worker * Copyright Sonic Network Inc. 2005
11*f81fb7c4SAndroid Build Coastguard Worker
12*f81fb7c4SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
13*f81fb7c4SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
14*f81fb7c4SAndroid Build Coastguard Worker * You may obtain a copy of the License at
15*f81fb7c4SAndroid Build Coastguard Worker *
16*f81fb7c4SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
17*f81fb7c4SAndroid Build Coastguard Worker *
18*f81fb7c4SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
19*f81fb7c4SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
20*f81fb7c4SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21*f81fb7c4SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
22*f81fb7c4SAndroid Build Coastguard Worker * limitations under the License.
23*f81fb7c4SAndroid Build Coastguard Worker *
24*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
25*f81fb7c4SAndroid Build Coastguard Worker * Revision Control:
26*f81fb7c4SAndroid Build Coastguard Worker * $Revision: 586 $
27*f81fb7c4SAndroid Build Coastguard Worker * $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $
28*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
29*f81fb7c4SAndroid Build Coastguard Worker */
30*f81fb7c4SAndroid Build Coastguard Worker
31*f81fb7c4SAndroid Build Coastguard Worker #include "eas.h"
32*f81fb7c4SAndroid Build Coastguard Worker #include "eas_math.h"
33*f81fb7c4SAndroid Build Coastguard Worker
34*f81fb7c4SAndroid Build Coastguard Worker /* anything less than this converts to a fraction too small to represent in 32-bits */
35*f81fb7c4SAndroid Build Coastguard Worker #define MIN_CENTS -18000
36*f81fb7c4SAndroid Build Coastguard Worker /* anything greater than this converts to a fraction too large to represent in 32-bits */
37*f81fb7c4SAndroid Build Coastguard Worker #define MAX_CENTS 19200
38*f81fb7c4SAndroid Build Coastguard Worker
39*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
40*f81fb7c4SAndroid Build Coastguard Worker * EAS_Calculate2toX()
41*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
42*f81fb7c4SAndroid Build Coastguard Worker * Purpose:
43*f81fb7c4SAndroid Build Coastguard Worker * Calculate 2^x
44*f81fb7c4SAndroid Build Coastguard Worker *
45*f81fb7c4SAndroid Build Coastguard Worker * Inputs:
46*f81fb7c4SAndroid Build Coastguard Worker * nCents - measured in cents
47*f81fb7c4SAndroid Build Coastguard Worker * psEASData - pointer to overall EAS data structure
48*f81fb7c4SAndroid Build Coastguard Worker *
49*f81fb7c4SAndroid Build Coastguard Worker * Outputs:
50*f81fb7c4SAndroid Build Coastguard Worker * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS)
51*f81fb7c4SAndroid Build Coastguard Worker *
52*f81fb7c4SAndroid Build Coastguard Worker * Side Effects:
53*f81fb7c4SAndroid Build Coastguard Worker *
54*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
55*f81fb7c4SAndroid Build Coastguard Worker */
56*f81fb7c4SAndroid Build Coastguard Worker
EAS_Calculate2toX(EAS_I32 nCents)57*f81fb7c4SAndroid Build Coastguard Worker EAS_I32 EAS_Calculate2toX (EAS_I32 nCents)
58*f81fb7c4SAndroid Build Coastguard Worker {
59*f81fb7c4SAndroid Build Coastguard Worker EAS_I32 nDents;
60*f81fb7c4SAndroid Build Coastguard Worker EAS_I32 nExponentInt, nExponentFrac;
61*f81fb7c4SAndroid Build Coastguard Worker EAS_I32 nTemp1, nTemp2;
62*f81fb7c4SAndroid Build Coastguard Worker EAS_I32 nResult;
63*f81fb7c4SAndroid Build Coastguard Worker
64*f81fb7c4SAndroid Build Coastguard Worker /* check for minimum value */
65*f81fb7c4SAndroid Build Coastguard Worker if (nCents < MIN_CENTS)
66*f81fb7c4SAndroid Build Coastguard Worker return 0;
67*f81fb7c4SAndroid Build Coastguard Worker
68*f81fb7c4SAndroid Build Coastguard Worker if (nCents > MAX_CENTS) {
69*f81fb7c4SAndroid Build Coastguard Worker nCents = MAX_CENTS;
70*f81fb7c4SAndroid Build Coastguard Worker }
71*f81fb7c4SAndroid Build Coastguard Worker
72*f81fb7c4SAndroid Build Coastguard Worker /* for the time being, convert cents to dents */
73*f81fb7c4SAndroid Build Coastguard Worker nDents = FMUL_15x15(nCents, CENTS_TO_DENTS);
74*f81fb7c4SAndroid Build Coastguard Worker
75*f81fb7c4SAndroid Build Coastguard Worker nExponentInt = GET_DENTS_INT_PART(nDents);
76*f81fb7c4SAndroid Build Coastguard Worker nExponentFrac = GET_DENTS_FRAC_PART(nDents);
77*f81fb7c4SAndroid Build Coastguard Worker
78*f81fb7c4SAndroid Build Coastguard Worker /*
79*f81fb7c4SAndroid Build Coastguard Worker implement 2^(fracPart) as a power series
80*f81fb7c4SAndroid Build Coastguard Worker */
81*f81fb7c4SAndroid Build Coastguard Worker nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3);
82*f81fb7c4SAndroid Build Coastguard Worker nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1);
83*f81fb7c4SAndroid Build Coastguard Worker nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2);
84*f81fb7c4SAndroid Build Coastguard Worker
85*f81fb7c4SAndroid Build Coastguard Worker /*
86*f81fb7c4SAndroid Build Coastguard Worker implement 2^(intPart) as
87*f81fb7c4SAndroid Build Coastguard Worker a left shift for intPart >= 0 or
88*f81fb7c4SAndroid Build Coastguard Worker a left shift for intPart < 0
89*f81fb7c4SAndroid Build Coastguard Worker */
90*f81fb7c4SAndroid Build Coastguard Worker if (nExponentInt >= 0)
91*f81fb7c4SAndroid Build Coastguard Worker {
92*f81fb7c4SAndroid Build Coastguard Worker /* left shift for positive exponents */
93*f81fb7c4SAndroid Build Coastguard Worker /*lint -e{703} <avoid multiply for performance>*/
94*f81fb7c4SAndroid Build Coastguard Worker nResult = nTemp1 << nExponentInt;
95*f81fb7c4SAndroid Build Coastguard Worker }
96*f81fb7c4SAndroid Build Coastguard Worker else
97*f81fb7c4SAndroid Build Coastguard Worker {
98*f81fb7c4SAndroid Build Coastguard Worker /* right shift for negative exponents */
99*f81fb7c4SAndroid Build Coastguard Worker nExponentInt = -nExponentInt;
100*f81fb7c4SAndroid Build Coastguard Worker nResult = nTemp1 >> nExponentInt;
101*f81fb7c4SAndroid Build Coastguard Worker }
102*f81fb7c4SAndroid Build Coastguard Worker
103*f81fb7c4SAndroid Build Coastguard Worker return nResult;
104*f81fb7c4SAndroid Build Coastguard Worker }
105*f81fb7c4SAndroid Build Coastguard Worker
106*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
107*f81fb7c4SAndroid Build Coastguard Worker * EAS_LogToLinear16()
108*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
109*f81fb7c4SAndroid Build Coastguard Worker * Purpose:
110*f81fb7c4SAndroid Build Coastguard Worker * Transform log value to linear gain multiplier using piece-wise linear
111*f81fb7c4SAndroid Build Coastguard Worker * approximation
112*f81fb7c4SAndroid Build Coastguard Worker *
113*f81fb7c4SAndroid Build Coastguard Worker * Inputs:
114*f81fb7c4SAndroid Build Coastguard Worker * nGain - log scale value in 20.10 format. Even though gain is normally
115*f81fb7c4SAndroid Build Coastguard Worker * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate
116*f81fb7c4SAndroid Build Coastguard Worker * the need for saturation checking when combining gain values.
117*f81fb7c4SAndroid Build Coastguard Worker *
118*f81fb7c4SAndroid Build Coastguard Worker * Outputs:
119*f81fb7c4SAndroid Build Coastguard Worker * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
120*f81fb7c4SAndroid Build Coastguard Worker *
121*f81fb7c4SAndroid Build Coastguard Worker * Side Effects:
122*f81fb7c4SAndroid Build Coastguard Worker *
123*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
124*f81fb7c4SAndroid Build Coastguard Worker */
EAS_LogToLinear16(EAS_I32 nGain)125*f81fb7c4SAndroid Build Coastguard Worker EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain)
126*f81fb7c4SAndroid Build Coastguard Worker {
127*f81fb7c4SAndroid Build Coastguard Worker EAS_INT nExp;
128*f81fb7c4SAndroid Build Coastguard Worker EAS_U16 nTemp;
129*f81fb7c4SAndroid Build Coastguard Worker
130*f81fb7c4SAndroid Build Coastguard Worker /* bias to positive */
131*f81fb7c4SAndroid Build Coastguard Worker nGain += 32767;
132*f81fb7c4SAndroid Build Coastguard Worker
133*f81fb7c4SAndroid Build Coastguard Worker /* check for infinite attenuation */
134*f81fb7c4SAndroid Build Coastguard Worker if (nGain < 0)
135*f81fb7c4SAndroid Build Coastguard Worker return 0;
136*f81fb7c4SAndroid Build Coastguard Worker
137*f81fb7c4SAndroid Build Coastguard Worker /* extract the exponent */
138*f81fb7c4SAndroid Build Coastguard Worker nExp = 31 - (nGain >> 10);
139*f81fb7c4SAndroid Build Coastguard Worker
140*f81fb7c4SAndroid Build Coastguard Worker /* check for maximum output */
141*f81fb7c4SAndroid Build Coastguard Worker if (nExp < 0)
142*f81fb7c4SAndroid Build Coastguard Worker return 0x7fff;
143*f81fb7c4SAndroid Build Coastguard Worker
144*f81fb7c4SAndroid Build Coastguard Worker /* extract mantissa and restore implied 1 bit */
145*f81fb7c4SAndroid Build Coastguard Worker nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp);
146*f81fb7c4SAndroid Build Coastguard Worker
147*f81fb7c4SAndroid Build Coastguard Worker /* use shift to approximate power-of-2 operation */
148*f81fb7c4SAndroid Build Coastguard Worker return nTemp;
149*f81fb7c4SAndroid Build Coastguard Worker }
150*f81fb7c4SAndroid Build Coastguard Worker
151*f81fb7c4SAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
152*f81fb7c4SAndroid Build Coastguard Worker * EAS_VolumeToGain()
153*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
154*f81fb7c4SAndroid Build Coastguard Worker * Purpose:
155*f81fb7c4SAndroid Build Coastguard Worker * Transform volume control in 1dB increments to gain multiplier
156*f81fb7c4SAndroid Build Coastguard Worker *
157*f81fb7c4SAndroid Build Coastguard Worker * Inputs:
158*f81fb7c4SAndroid Build Coastguard Worker * volume - 100 = 0dB, 99 = -1dB, 0 = -inf
159*f81fb7c4SAndroid Build Coastguard Worker *
160*f81fb7c4SAndroid Build Coastguard Worker * Outputs:
161*f81fb7c4SAndroid Build Coastguard Worker * Returns a 16-bit linear value
162*f81fb7c4SAndroid Build Coastguard Worker *----------------------------------------------------------------------------
163*f81fb7c4SAndroid Build Coastguard Worker */
EAS_VolumeToGain(EAS_INT volume)164*f81fb7c4SAndroid Build Coastguard Worker EAS_I16 EAS_VolumeToGain (EAS_INT volume)
165*f81fb7c4SAndroid Build Coastguard Worker {
166*f81fb7c4SAndroid Build Coastguard Worker /* check for limits */
167*f81fb7c4SAndroid Build Coastguard Worker if (volume <= 0)
168*f81fb7c4SAndroid Build Coastguard Worker return 0;
169*f81fb7c4SAndroid Build Coastguard Worker if (volume >= 100)
170*f81fb7c4SAndroid Build Coastguard Worker return 0x7fff;
171*f81fb7c4SAndroid Build Coastguard Worker
172*f81fb7c4SAndroid Build Coastguard Worker /*lint -e{702} use shift instead of division */
173*f81fb7c4SAndroid Build Coastguard Worker return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1);
174*f81fb7c4SAndroid Build Coastguard Worker }
175*f81fb7c4SAndroid Build Coastguard Worker
176