Home | History | Annotate | Download | only in lib_src
      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