You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
4.9 KiB
176 lines
4.9 KiB
/*----------------------------------------------------------------------------
|
|
*
|
|
* 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
|
|
/* anything greater than this converts to a fraction too large to represent in 32-bits */
|
|
#define MAX_CENTS 19200
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* 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;
|
|
|
|
if (nCents > MAX_CENTS) {
|
|
nCents = MAX_CENTS;
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
|