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