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 /* anything greater than this converts to a fraction too large to represent in 32-bits */
37 #define MAX_CENTS    19200
38 
39 /*----------------------------------------------------------------------------
40  * EAS_Calculate2toX()
41  *----------------------------------------------------------------------------
42  * Purpose:
43  * Calculate 2^x
44  *
45  * Inputs:
46  * nCents -     measured in cents
47  * psEASData - pointer to overall EAS data structure
48  *
49  * Outputs:
50  * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS)
51  *
52  * Side Effects:
53  *
54  *----------------------------------------------------------------------------
55 */
56 
EAS_Calculate2toX(EAS_I32 nCents)57 EAS_I32 EAS_Calculate2toX (EAS_I32 nCents)
58 {
59     EAS_I32 nDents;
60     EAS_I32 nExponentInt, nExponentFrac;
61     EAS_I32 nTemp1, nTemp2;
62     EAS_I32 nResult;
63 
64     /* check for minimum value */
65     if (nCents < MIN_CENTS)
66         return 0;
67 
68     if (nCents > MAX_CENTS) {
69         nCents = MAX_CENTS;
70     }
71 
72     /* for the time being, convert cents to dents */
73     nDents = FMUL_15x15(nCents, CENTS_TO_DENTS);
74 
75     nExponentInt = GET_DENTS_INT_PART(nDents);
76     nExponentFrac = GET_DENTS_FRAC_PART(nDents);
77 
78     /*
79     implement 2^(fracPart) as a power series
80     */
81     nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3);
82     nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1);
83     nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2);
84 
85     /*
86     implement 2^(intPart) as
87     a left shift for intPart >= 0 or
88     a left shift for intPart <  0
89     */
90     if (nExponentInt >= 0)
91     {
92         /* left shift for positive exponents */
93         /*lint -e{703} <avoid multiply for performance>*/
94         nResult = nTemp1 << nExponentInt;
95     }
96     else
97     {
98         /* right shift for negative exponents */
99         nExponentInt = -nExponentInt;
100         nResult = nTemp1 >> nExponentInt;
101     }
102 
103     return nResult;
104 }
105 
106 /*----------------------------------------------------------------------------
107  * EAS_LogToLinear16()
108  *----------------------------------------------------------------------------
109  * Purpose:
110  * Transform log value to linear gain multiplier using piece-wise linear
111  * approximation
112  *
113  * Inputs:
114  * nGain - log scale value in 20.10 format. Even though gain is normally
115  * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate
116  * the need for saturation checking when combining gain values.
117  *
118  * Outputs:
119  * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
120  *
121  * Side Effects:
122  *
123  *----------------------------------------------------------------------------
124 */
EAS_LogToLinear16(EAS_I32 nGain)125 EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain)
126 {
127     EAS_INT nExp;
128     EAS_U16 nTemp;
129 
130     /* bias to positive */
131     nGain += 32767;
132 
133     /* check for infinite attenuation */
134     if (nGain < 0)
135         return 0;
136 
137     /* extract the exponent */
138     nExp = 31 - (nGain >> 10);
139 
140     /* check for maximum output */
141     if (nExp < 0)
142         return 0x7fff;
143 
144     /* extract mantissa and restore implied 1 bit */
145     nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp);
146 
147     /* use shift to approximate power-of-2 operation */
148     return nTemp;
149 }
150 
151 /*----------------------------------------------------------------------------
152  * EAS_VolumeToGain()
153  *----------------------------------------------------------------------------
154  * Purpose:
155  * Transform volume control in 1dB increments to gain multiplier
156  *
157  * Inputs:
158  * volume - 100 = 0dB, 99 = -1dB, 0 = -inf
159  *
160  * Outputs:
161  * Returns a 16-bit linear value
162  *----------------------------------------------------------------------------
163 */
EAS_VolumeToGain(EAS_INT volume)164 EAS_I16 EAS_VolumeToGain (EAS_INT volume)
165 {
166     /* check for limits */
167     if (volume <= 0)
168         return 0;
169     if (volume >= 100)
170         return 0x7fff;
171 
172     /*lint -e{702} use shift instead of division */
173     return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1);
174 }
175 
176