/*---------------------------------------------------------------------------- | |
* | |
* File: | |
* eas_math.c | |
* | |
* Contents and purpose: | |
* Contains common math routines for the various audio engines. | |
* | |
* | |
* Copyright Sonic Network Inc. 2005 | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* | |
*---------------------------------------------------------------------------- | |
* Revision Control: | |
* $Revision: 586 $ | |
* $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $ | |
*---------------------------------------------------------------------------- | |
*/ | |
#include "eas.h" | |
#include "eas_math.h" | |
/* anything less than this converts to a fraction too small to represent in 32-bits */ | |
#define MIN_CENTS -18000 | |
/*---------------------------------------------------------------------------- | |
* EAS_Calculate2toX() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Calculate 2^x | |
* | |
* Inputs: | |
* nCents - measured in cents | |
* psEASData - pointer to overall EAS data structure | |
* | |
* Outputs: | |
* nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_I32 EAS_Calculate2toX (EAS_I32 nCents) | |
{ | |
EAS_I32 nDents; | |
EAS_I32 nExponentInt, nExponentFrac; | |
EAS_I32 nTemp1, nTemp2; | |
EAS_I32 nResult; | |
/* check for minimum value */ | |
if (nCents < MIN_CENTS) | |
return 0; | |
/* for the time being, convert cents to dents */ | |
nDents = FMUL_15x15(nCents, CENTS_TO_DENTS); | |
nExponentInt = GET_DENTS_INT_PART(nDents); | |
nExponentFrac = GET_DENTS_FRAC_PART(nDents); | |
/* | |
implement 2^(fracPart) as a power series | |
*/ | |
nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3); | |
nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1); | |
nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2); | |
/* | |
implement 2^(intPart) as | |
a left shift for intPart >= 0 or | |
a left shift for intPart < 0 | |
*/ | |
if (nExponentInt >= 0) | |
{ | |
/* left shift for positive exponents */ | |
/*lint -e{703} <avoid multiply for performance>*/ | |
nResult = nTemp1 << nExponentInt; | |
} | |
else | |
{ | |
/* right shift for negative exponents */ | |
nExponentInt = -nExponentInt; | |
nResult = nTemp1 >> nExponentInt; | |
} | |
return nResult; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_LogToLinear16() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Transform log value to linear gain multiplier using piece-wise linear | |
* approximation | |
* | |
* Inputs: | |
* nGain - log scale value in 20.10 format. Even though gain is normally | |
* stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate | |
* the need for saturation checking when combining gain values. | |
* | |
* Outputs: | |
* Returns a 16-bit linear value approximately equal to 2^(nGain/1024) | |
* | |
* Side Effects: | |
* | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain) | |
{ | |
EAS_INT nExp; | |
EAS_U16 nTemp; | |
/* bias to positive */ | |
nGain += 32767; | |
/* check for infinite attenuation */ | |
if (nGain < 0) | |
return 0; | |
/* extract the exponent */ | |
nExp = 31 - (nGain >> 10); | |
/* check for maximum output */ | |
if (nExp < 0) | |
return 0x7fff; | |
/* extract mantissa and restore implied 1 bit */ | |
nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp); | |
/* use shift to approximate power-of-2 operation */ | |
return nTemp; | |
} | |
/*---------------------------------------------------------------------------- | |
* EAS_VolumeToGain() | |
*---------------------------------------------------------------------------- | |
* Purpose: | |
* Transform volume control in 1dB increments to gain multiplier | |
* | |
* Inputs: | |
* volume - 100 = 0dB, 99 = -1dB, 0 = -inf | |
* | |
* Outputs: | |
* Returns a 16-bit linear value | |
*---------------------------------------------------------------------------- | |
*/ | |
EAS_I16 EAS_VolumeToGain (EAS_INT volume) | |
{ | |
/* check for limits */ | |
if (volume <= 0) | |
return 0; | |
if (volume >= 100) | |
return 0x7fff; | |
/*lint -e{702} use shift instead of division */ | |
return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1); | |
} | |