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