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 */ 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 */ 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 */ 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