xref: /aosp_15_r20/external/sonivox/arm-wt-22k/lib_src/eas_math.c (revision f81fb7c475c4b71ff83bdcc517de2a8c174e4e5c)
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