* FS#10411 - Fixed point math code is bloated by Jeffrey Goode
* Set svn:keywords properties git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21701 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
616905f965
commit
8d4d4610b6
3 changed files with 43 additions and 92 deletions
|
@ -5,7 +5,7 @@
|
||||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
* \/ \/ \/ \/ \/
|
* \/ \/ \/ \/ \/
|
||||||
* $Id: fixedpoint.h -1 $
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Jens Arnold
|
* Copyright (C) 2006 Jens Arnold
|
||||||
*
|
*
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
* \/ \/ \/ \/ \/
|
* \/ \/ \/ \/ \/
|
||||||
* $Id: fixedpoint.c -1 $
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Jens Arnold
|
* Copyright (C) 2006 Jens Arnold
|
||||||
*
|
*
|
||||||
|
@ -261,24 +261,18 @@ long fp16_log(int x) {
|
||||||
|
|
||||||
#if (!defined(PLUGIN) && !defined(CODEC))
|
#if (!defined(PLUGIN) && !defined(CODEC))
|
||||||
/** MODIFIED FROM replaygain.c */
|
/** MODIFIED FROM replaygain.c */
|
||||||
/* These math routines have 64-bit internal precision to avoid overflows.
|
|
||||||
* Arguments and return values are 32-bit (long) precision.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define FP_MUL64(x, y) (((x) * (y)) >> (fracbits))
|
#define FP_MUL_FRAC(x, y) fp_mul(x, y, fracbits)
|
||||||
#define FP_DIV64(x, y) (((x) << (fracbits)) / (y))
|
#define FP_DIV_FRAC(x, y) fp_div(x, y, fracbits)
|
||||||
|
|
||||||
static long long fp_exp10(long long x, unsigned int fracbits);
|
|
||||||
/* static long long fp_log10(long long n, unsigned int fracbits); */
|
|
||||||
|
|
||||||
/* constants in fixed point format, 28 fractional bits */
|
/* constants in fixed point format, 28 fractional bits */
|
||||||
#define FP28_LN2 (186065279LL) /* ln(2) */
|
#define FP28_LN2 (186065279L) /* ln(2) */
|
||||||
#define FP28_LN2_INV (387270501LL) /* 1/ln(2) */
|
#define FP28_LN2_INV (387270501L) /* 1/ln(2) */
|
||||||
#define FP28_EXP_ZERO (44739243LL) /* 1/6 */
|
#define FP28_EXP_ZERO (44739243L) /* 1/6 */
|
||||||
#define FP28_EXP_ONE (-745654LL) /* -1/360 */
|
#define FP28_EXP_ONE (-745654L) /* -1/360 */
|
||||||
#define FP28_EXP_TWO (12428LL) /* 1/21600 */
|
#define FP28_EXP_TWO (12428L) /* 1/21600 */
|
||||||
#define FP28_LN10 (618095479LL) /* ln(10) */
|
#define FP28_LN10 (618095479L) /* ln(10) */
|
||||||
#define FP28_LOG10OF2 (80807124LL) /* log10(2) */
|
#define FP28_LOG10OF2 (80807124L) /* log10(2) */
|
||||||
|
|
||||||
#define TOL_BITS 2 /* log calculation tolerance */
|
#define TOL_BITS 2 /* log calculation tolerance */
|
||||||
|
|
||||||
|
@ -290,24 +284,24 @@ static long long fp_exp10(long long x, unsigned int fracbits);
|
||||||
/** FIXED POINT EXP10
|
/** FIXED POINT EXP10
|
||||||
* Return 10^x as FP integer. Argument is FP integer.
|
* Return 10^x as FP integer. Argument is FP integer.
|
||||||
*/
|
*/
|
||||||
static long long fp_exp10(long long x, unsigned int fracbits)
|
static long fp_exp10(long x, unsigned int fracbits)
|
||||||
{
|
{
|
||||||
long long k;
|
long k;
|
||||||
long long z;
|
long z;
|
||||||
long long R;
|
long R;
|
||||||
long long xp;
|
long xp;
|
||||||
|
|
||||||
/* scale constants */
|
/* scale constants */
|
||||||
const long long fp_one = (1 << fracbits);
|
const long fp_one = (1 << fracbits);
|
||||||
const long long fp_half = (1 << (fracbits - 1));
|
const long fp_half = (1 << (fracbits - 1));
|
||||||
const long long fp_two = (2 << fracbits);
|
const long fp_two = (2 << fracbits);
|
||||||
const long long fp_mask = (fp_one - 1);
|
const long fp_mask = (fp_one - 1);
|
||||||
const long long fp_ln2_inv = (FP28_LN2_INV >> (28 - fracbits));
|
const long fp_ln2_inv = (FP28_LN2_INV >> (28 - fracbits));
|
||||||
const long long fp_ln2 = (FP28_LN2 >> (28 - fracbits));
|
const long fp_ln2 = (FP28_LN2 >> (28 - fracbits));
|
||||||
const long long fp_ln10 = (FP28_LN10 >> (28 - fracbits));
|
const long fp_ln10 = (FP28_LN10 >> (28 - fracbits));
|
||||||
const long long fp_exp_zero = (FP28_EXP_ZERO >> (28 - fracbits));
|
const long fp_exp_zero = (FP28_EXP_ZERO >> (28 - fracbits));
|
||||||
const long long fp_exp_one = (FP28_EXP_ONE >> (28 - fracbits));
|
const long fp_exp_one = (FP28_EXP_ONE >> (28 - fracbits));
|
||||||
const long long fp_exp_two = (FP28_EXP_TWO >> (28 - fracbits));
|
const long fp_exp_two = (FP28_EXP_TWO >> (28 - fracbits));
|
||||||
|
|
||||||
/* exp(0) = 1 */
|
/* exp(0) = 1 */
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
|
@ -316,21 +310,21 @@ static long long fp_exp10(long long x, unsigned int fracbits)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert from base 10 to base e */
|
/* convert from base 10 to base e */
|
||||||
x = FP_MUL64(x, fp_ln10);
|
x = FP_MUL_FRAC(x, fp_ln10);
|
||||||
|
|
||||||
/* calculate exp(x) */
|
/* calculate exp(x) */
|
||||||
k = (FP_MUL64(abs(x), fp_ln2_inv) + fp_half) & ~fp_mask;
|
k = (FP_MUL_FRAC(abs(x), fp_ln2_inv) + fp_half) & ~fp_mask;
|
||||||
|
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
{
|
{
|
||||||
k = -k;
|
k = -k;
|
||||||
}
|
}
|
||||||
|
|
||||||
x -= FP_MUL64(k, fp_ln2);
|
x -= FP_MUL_FRAC(k, fp_ln2);
|
||||||
z = FP_MUL64(x, x);
|
z = FP_MUL_FRAC(x, x);
|
||||||
R = fp_two + FP_MUL64(z, fp_exp_zero + FP_MUL64(z, fp_exp_one
|
R = fp_two + FP_MUL_FRAC(z, fp_exp_zero + FP_MUL_FRAC(z, fp_exp_one
|
||||||
+ FP_MUL64(z, fp_exp_two)));
|
+ FP_MUL_FRAC(z, fp_exp_two)));
|
||||||
xp = fp_one + FP_DIV64(FP_MUL64(fp_two, x), R - x);
|
xp = fp_one + FP_DIV_FRAC(FP_MUL_FRAC(fp_two, x), R - x);
|
||||||
|
|
||||||
if (k < 0)
|
if (k < 0)
|
||||||
{
|
{
|
||||||
|
@ -341,7 +335,7 @@ static long long fp_exp10(long long x, unsigned int fracbits)
|
||||||
k = fp_one << (k >> fracbits);
|
k = fp_one << (k >> fracbits);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FP_MUL64(k, xp);
|
return FP_MUL_FRAC(k, xp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -349,13 +343,13 @@ static long long fp_exp10(long long x, unsigned int fracbits)
|
||||||
/** FIXED POINT LOG10
|
/** FIXED POINT LOG10
|
||||||
* Return log10(x) as FP integer. Argument is FP integer.
|
* Return log10(x) as FP integer. Argument is FP integer.
|
||||||
*/
|
*/
|
||||||
static long long fp_log10(long long n, unsigned int fracbits)
|
static long fp_log10(long n, unsigned int fracbits)
|
||||||
{
|
{
|
||||||
/* Calculate log2 of argument */
|
/* Calculate log2 of argument */
|
||||||
|
|
||||||
long long log2, frac;
|
long log2, frac;
|
||||||
const long long fp_one = (1 << fracbits);
|
const long fp_one = (1 << fracbits);
|
||||||
const long long fp_two = (2 << fracbits);
|
const long fp_two = (2 << fracbits);
|
||||||
const long tolerance = (1 << ((fracbits / 2) + 2));
|
const long tolerance = (1 << ((fracbits / 2) + 2));
|
||||||
|
|
||||||
if (n <=0) return FP_NEGINF;
|
if (n <=0) return FP_NEGINF;
|
||||||
|
@ -378,7 +372,7 @@ static long long fp_log10(long long n, unsigned int fracbits)
|
||||||
while (frac > tolerance)
|
while (frac > tolerance)
|
||||||
{
|
{
|
||||||
frac >>= 1;
|
frac >>= 1;
|
||||||
n = FP_MUL64(n, n);
|
n = FP_MUL_FRAC(n, n);
|
||||||
if (n >= fp_two)
|
if (n >= fp_two)
|
||||||
{
|
{
|
||||||
n >>= 1;
|
n >>= 1;
|
||||||
|
@ -387,31 +381,15 @@ static long long fp_log10(long long n, unsigned int fracbits)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* convert log2 to log10 */
|
/* convert log2 to log10 */
|
||||||
return FP_MUL64(log2, (FP28_LOG10OF2 >> (28 - fracbits)));
|
return FP_MUL_FRAC(log2, (FP28_LOG10OF2 >> (28 - fracbits)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** CONVERT FACTOR TO DECIBELS */
|
/** CONVERT FACTOR TO DECIBELS */
|
||||||
long fp_decibels(unsigned long factor, unsigned int fracbits)
|
long fp_decibels(unsigned long factor, unsigned int fracbits)
|
||||||
{
|
{
|
||||||
long long decibels;
|
|
||||||
long long f = (long long)factor;
|
|
||||||
bool neg;
|
|
||||||
|
|
||||||
/* keep factor in signed long range */
|
|
||||||
if (f >= (1LL << 31))
|
|
||||||
f = (1LL << 31) - 1;
|
|
||||||
|
|
||||||
/* decibels = 20 * log10(factor) */
|
/* decibels = 20 * log10(factor) */
|
||||||
decibels = FP_MUL64((20LL << fracbits), fp_log10(f, fracbits));
|
return FP_MUL_FRAC((20L << fracbits), fp_log10(factor, fracbits));
|
||||||
|
|
||||||
/* keep result in signed long range */
|
|
||||||
if ((neg = (decibels < 0)))
|
|
||||||
decibels = -decibels;
|
|
||||||
if (decibels >= (1LL << 31))
|
|
||||||
return neg ? FP_NEGINF : FP_INF;
|
|
||||||
|
|
||||||
return neg ? (long)-decibels : (long)decibels;
|
|
||||||
}
|
}
|
||||||
#endif /* unused code */
|
#endif /* unused code */
|
||||||
|
|
||||||
|
@ -419,34 +397,7 @@ long fp_decibels(unsigned long factor, unsigned int fracbits)
|
||||||
/** CONVERT DECIBELS TO FACTOR */
|
/** CONVERT DECIBELS TO FACTOR */
|
||||||
long fp_factor(long decibels, unsigned int fracbits)
|
long fp_factor(long decibels, unsigned int fracbits)
|
||||||
{
|
{
|
||||||
bool neg;
|
|
||||||
long long factor;
|
|
||||||
long long db = (long long)decibels;
|
|
||||||
|
|
||||||
/* if decibels is 0, factor is 1 */
|
|
||||||
if (db == 0)
|
|
||||||
return (1L << fracbits);
|
|
||||||
|
|
||||||
/* calculate for positive decibels only */
|
|
||||||
if ((neg = (db < 0)))
|
|
||||||
db = -db;
|
|
||||||
|
|
||||||
/* factor = 10 ^ (decibels / 20) */
|
/* factor = 10 ^ (decibels / 20) */
|
||||||
factor = fp_exp10(FP_DIV64(db, (20LL << fracbits)), fracbits);
|
return fp_exp10(FP_DIV_FRAC(decibels, (20L << fracbits)), fracbits);
|
||||||
|
|
||||||
/* keep result in signed long range, return 0 if very small */
|
|
||||||
if (factor >= (1LL << 31))
|
|
||||||
{
|
|
||||||
if (neg)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return FP_INF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if negative argument, factor is 1 / result */
|
|
||||||
if (neg)
|
|
||||||
factor = FP_DIV64((1LL << fracbits), factor);
|
|
||||||
|
|
||||||
return (long)factor;
|
|
||||||
}
|
}
|
||||||
#endif /* !PLUGIN and !CODEC */
|
#endif /* !PLUGIN and !CODEC */
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
* \/ \/ \/ \/ \/
|
* \/ \/ \/ \/ \/
|
||||||
* $Id: fixedpoint.h -1 $
|
* $Id$
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006 Jens Arnold
|
* Copyright (C) 2006 Jens Arnold
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue