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