summaryrefslogtreecommitdiffstats
path: root/apps/codecs/libspeex/math_approx.c
diff options
context:
space:
mode:
authorDan Everton <dan@iocaine.org>2007-02-10 11:44:26 +0000
committerDan Everton <dan@iocaine.org>2007-02-10 11:44:26 +0000
commit7bf62e8da66ca8ff0acc2702f92ea4fe06eb94b1 (patch)
treec9db4558a73ae3094839c4655fa0b8ebc2231c56 /apps/codecs/libspeex/math_approx.c
parent51587512635a8b19e6a5f19a20074d0d4d1f17da (diff)
downloadrockbox-7bf62e8da66ca8ff0acc2702f92ea4fe06eb94b1.tar.gz
rockbox-7bf62e8da66ca8ff0acc2702f92ea4fe06eb94b1.zip
* Sync Speex codec with Speex SVN revision 12449 (roughly Speex 1.2beta1).
* Redo the changes required to make Speex compile in Rockbox. Should be a bit easier to keep in sync with Speex SVN now. * Fix name of Speex library in codecs Makefile. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12254 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libspeex/math_approx.c')
-rw-r--r--apps/codecs/libspeex/math_approx.c459
1 files changed, 153 insertions, 306 deletions
diff --git a/apps/codecs/libspeex/math_approx.c b/apps/codecs/libspeex/math_approx.c
index 54a34120bf..21af7667aa 100644
--- a/apps/codecs/libspeex/math_approx.c
+++ b/apps/codecs/libspeex/math_approx.c
@@ -34,181 +34,89 @@
#include "config.h"
#endif
-
-
#include "math_approx.h"
#include "misc.h"
-#ifdef FIXED_POINT
-
-/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */
-#define C0 3634
-#define C1 21173
-#define C2 -12627
-#define C3 4215
-
-spx_word16_t spx_sqrt(spx_word32_t x)
+spx_int16_t spx_ilog2(spx_uint32_t x)
{
- int k=0;
- spx_word32_t rt;
-
- if (x<=0)
- return 0;
-#if 1
- if (x>=16777216)
+ int r=0;
+ if (x>=(spx_int32_t)65536)
{
- x>>=10;
- k+=5;
+ x >>= 16;
+ r += 16;
}
- if (x>=1048576)
+ if (x>=256)
{
- x>>=6;
- k+=3;
+ x >>= 8;
+ r += 8;
}
- if (x>=262144)
+ if (x>=16)
{
- x>>=4;
- k+=2;
+ x >>= 4;
+ r += 4;
}
- if (x>=32768)
+ if (x>=4)
{
- x>>=2;
- k+=1;
+ x >>= 2;
+ r += 2;
}
- if (x>=16384)
+ if (x>=2)
{
- x>>=2;
- k+=1;
+ r += 1;
}
-#else
- while (x>=16384)
+ return r;
+}
+
+spx_int16_t spx_ilog4(spx_uint32_t x)
+{
+ int r=0;
+ if (x>=(spx_int32_t)65536)
{
- x>>=2;
- k++;
- }
-#endif
- while (x<4096)
+ x >>= 16;
+ r += 8;
+ }
+ if (x>=256)
{
- x<<=2;
- k--;
+ x >>= 8;
+ r += 4;
}
- rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3)))))));
- if (rt > 16383)
- rt = 16383;
- if (k>0)
- rt <<= k;
- else
- rt >>= -k;
- rt >>=7;
- return rt;
+ if (x>=16)
+ {
+ x >>= 4;
+ r += 2;
+ }
+ if (x>=4)
+ {
+ r += 1;
+ }
+ return r;
}
- static int intSqrt(int x) {
- int xn;
- static int sqrt_table[256] = {
- 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57,
- 59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83,
- 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102,
- 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118,
- 119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132,
- 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145,
- 146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157,
- 158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
- 169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178,
- 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188,
- 189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197,
- 198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206,
- 207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215,
- 215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223,
- 224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231,
- 231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
- 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246,
- 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253,
- 253, 254, 254, 255
- };
- if (x >= 0x10000) {
- if (x >= 0x1000000) {
- if (x >= 0x10000000) {
- if (x >= 0x40000000) {
- xn = sqrt_table[x >> 24] << 8;
- } else {
- xn = sqrt_table[x >> 22] << 7;
- }
- } else {
- if (x >= 0x4000000) {
- xn = sqrt_table[x >> 20] << 6;
- } else {
- xn = sqrt_table[x >> 18] << 5;
- }
- }
-
- xn = (xn + 1 + (x / xn)) >> 1;
- xn = (xn + 1 + (x / xn)) >> 1;
- return ((xn * xn) > x) ? --xn : xn;
- } else {
- if (x >= 0x100000) {
- if (x >= 0x400000) {
- xn = sqrt_table[x >> 16] << 4;
- } else {
- xn = sqrt_table[x >> 14] << 3;
- }
- } else {
- if (x >= 0x40000) {
- xn = sqrt_table[x >> 12] << 2;
- } else {
- xn = sqrt_table[x >> 10] << 1;
- }
- }
-
- xn = (xn + 1 + (x / xn)) >> 1;
+#ifdef FIXED_POINT
- return ((xn * xn) > x) ? --xn : xn;
- }
- } else {
- if (x >= 0x100) {
- if (x >= 0x1000) {
- if (x >= 0x4000) {
- xn = (sqrt_table[x >> 8]) + 1;
- } else {
- xn = (sqrt_table[x >> 6] >> 1) + 1;
- }
- } else {
- if (x >= 0x400) {
- xn = (sqrt_table[x >> 4] >> 2) + 1;
- } else {
- xn = (sqrt_table[x >> 2] >> 3) + 1;
- }
- }
+/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */
+/*#define C0 3634
+#define C1 21173
+#define C2 -12627
+#define C3 4215*/
- return ((xn * xn) > x) ? --xn : xn;
- } else {
- if (x >= 0) {
- return sqrt_table[x] >> 4;
- }
- }
- }
-
- return -1;
- }
+/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */
+#define C0 3634
+#define C1 21173
+#define C2 -12627
+#define C3 4204
-float spx_sqrtf(float arg)
+spx_word16_t spx_sqrt(spx_word32_t x)
{
- if(arg==0.0)
- return 0.0;
- else if(arg==1.0)
- return 1.0;
- else if(arg==2.0)
- return 1.414;
- else if(arg==3.27)
- return 1.8083;
- //printf("Sqrt:%f:%f:%f\n",arg,(((float)intSqrt((int)(arg*10000)))/100)+0.0055,(float)spx_sqrt((spx_word32_t)arg));
- //return ((float)fastSqrt((int)(arg*2500)))/50;
- //LOGF("Sqrt:%d:%d\n",arg,(intSqrt((int)(arg*2500)))/50);
- return (((float)intSqrt((int)(arg*10000)))/100)+0.0055;//(float)spx_sqrt((spx_word32_t)arg);
- //return 1;
+ int k;
+ spx_word32_t rt;
+ k = spx_ilog4(x)-6;
+ x = VSHR32(x, (k<<1));
+ rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3)))))));
+ rt = VSHR32(rt,7-k);
+ return rt;
}
-
/* log(x) ~= -2.18151 + 4.20592*x - 2.88938*x^2 + 0.86535*x^3 (for .5 < x < 1) */
@@ -259,6 +167,101 @@ spx_word16_t spx_cos(spx_word16_t x)
}
}
+#define L1 32767
+#define L2 -7651
+#define L3 8277
+#define L4 -626
+
+static inline spx_word16_t _spx_cos_pi_2(spx_word16_t x)
+{
+ spx_word16_t x2;
+
+ x2 = MULT16_16_P15(x,x);
+ return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2))))))));
+}
+
+spx_word16_t spx_cos_norm(spx_word32_t x)
+{
+ x = x&0x0001ffff;
+ if (x>SHL32(EXTEND32(1), 16))
+ x = SUB32(SHL32(EXTEND32(1), 17),x);
+ if (x&0x00007fff)
+ {
+ if (x<SHL32(EXTEND32(1), 15))
+ {
+ return _spx_cos_pi_2(EXTRACT16(x));
+ } else {
+ return NEG32(_spx_cos_pi_2(EXTRACT16(65536-x)));
+ }
+ } else {
+ if (x&0x0000ffff)
+ return 0;
+ else if (x&0x0001ffff)
+ return -32767;
+ else
+ return 32767;
+ }
+}
+
+/*
+ K0 = 1
+ K1 = log(2)
+ K2 = 3-4*log(2)
+ K3 = 3*log(2) - 2
+*/
+#define D0 16384
+#define D1 11356
+#define D2 3726
+#define D3 1301
+/* Input in Q11 format, output in Q16 */
+static spx_word32_t spx_exp2(spx_word16_t x)
+{
+ int integer;
+ spx_word16_t frac;
+ integer = SHR16(x,11);
+ if (integer>14)
+ return 0x7fffffff;
+ else if (integer < -15)
+ return 0;
+ frac = SHL16(x-SHL16(integer,11),3);
+ frac = ADD16(D0, MULT16_16_Q14(frac, ADD16(D1, MULT16_16_Q14(frac, ADD16(D2 , MULT16_16_Q14(D3,frac))))));
+ return VSHR32(EXTEND32(frac), -integer-2);
+}
+
+/* Input in Q11 format, output in Q16 */
+spx_word32_t spx_exp(spx_word16_t x)
+{
+ if (x>21290)
+ return 0x7fffffff;
+ else if (x<-21290)
+ return 0;
+ else
+ return spx_exp2(MULT16_16_P14(23637,x));
+}
+#define M1 32767
+#define M2 -21
+#define M3 -11943
+#define M4 4936
+
+static inline spx_word16_t spx_atan01(spx_word16_t x)
+{
+ return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
+}
+
+/* Input in Q15, output in Q14 */
+spx_word16_t spx_atan(spx_word32_t x)
+{
+ if (x <= 32767)
+ {
+ return SHR16(spx_atan01(x),1);
+ } else {
+ int e = spx_ilog2(x);
+ if (e>=29)
+ return 25736;
+ x = DIV32_16(SHL32(EXTEND32(32767),29-e), EXTRACT16(SHR32(x, e-14)));
+ return SUB16(25736, SHR16(spx_atan01(x),1));
+ }
+}
#else
#ifndef M_PI
@@ -284,161 +287,5 @@ spx_word16_t spx_cos(spx_word16_t x)
return NEG16(C1 + x*(C2+x*(C3+C4*x)));
}
}
-#endif
-
-inline float spx_floor(float x){
- return ((float)(((int)x)));
-}
-
-#define FP_BITS (14)
-#define FP_MASK ((1 << FP_BITS) - 1)
-#define FP_ONE (1 << FP_BITS)
-#define FP_TWO (2 << FP_BITS)
-#define FP_HALF (1 << (FP_BITS - 1))
-#define FP_LN2 ( 45426 >> (16 - FP_BITS))
-#define FP_LN2_INV ( 94548 >> (16 - FP_BITS))
-#define FP_EXP_ZERO ( 10922 >> (16 - FP_BITS))
-#define FP_EXP_ONE ( -182 >> (16 - FP_BITS))
-#define FP_EXP_TWO ( 4 >> (16 - FP_BITS))
-// #define FP_INF (0x7fffffff)
-// #define FP_LN10 (150902 >> (16 - FP_BITS))
-
-#define FP_MAX_DIGITS (4)
-#define FP_MAX_DIGITS_INT (10000)
-
-// #define FP_FAST_MUL_DIV
-
-// #ifdef FP_FAST_MUL_DIV
-
-/* These macros can easily overflow, but they are good enough for our uses,
- * and saves some code.
- */
-#define fp_mul(x, y) (((x) * (y)) >> FP_BITS)
-#define fp_div(x, y) (((x) << FP_BITS) / (y))
-
-#ifndef abs
- #define abs(x) (((x)<0)?((x)*-1):(x))
#endif
-
-float spx_sqrt2(float xf) {
- long x=(xf*(2.0*FP_BITS));
- int i=0, s = (x + FP_ONE) >> 1;
- for (; i < 8; i++) {
- s = (s + fp_div(x, s)) >> 1;
- }
- return s/((float)(2*FP_BITS));
-}
-
-static int exp_s16p16(int x)
-{
- int t;
- int y = 0x00010000;
-
- if (x < 0) x += 0xb1721, y >>= 16;
- t = x - 0x58b91; if (t >= 0) x = t, y <<= 8;
- t = x - 0x2c5c8; if (t >= 0) x = t, y <<= 4;
- t = x - 0x162e4; if (t >= 0) x = t, y <<= 2;
- t = x - 0x0b172; if (t >= 0) x = t, y <<= 1;
- t = x - 0x067cd; if (t >= 0) x = t, y += y >> 1;
- t = x - 0x03920; if (t >= 0) x = t, y += y >> 2;
- t = x - 0x01e27; if (t >= 0) x = t, y += y >> 3;
- t = x - 0x00f85; if (t >= 0) x = t, y += y >> 4;
- t = x - 0x007e1; if (t >= 0) x = t, y += y >> 5;
- t = x - 0x003f8; if (t >= 0) x = t, y += y >> 6;
- t = x - 0x001fe; if (t >= 0) x = t, y += y >> 7;
- y += ((y >> 8) * x) >> 8;
-
- return y;
-}
-float spx_expB(float xf) {
- return exp_s16p16(xf*32)/32;
-}
-float spx_expC(float xf){
- long x=xf*(2*FP_BITS);
-/*
-static long fp_exp(long x)
-{*/
- long k;
- long z;
- long R;
- long xp;
-
- if (x == 0)
- {
- return FP_ONE;
- }
-
- k = (fp_mul(abs(x), FP_LN2_INV) + FP_HALF) & ~FP_MASK;
-
- if (x < 0)
- {
- k = -k;
- }
-
- x -= fp_mul(k, FP_LN2);
- z = fp_mul(x, x);
- R = FP_TWO + fp_mul(z, FP_EXP_ZERO + fp_mul(z, FP_EXP_ONE
- + fp_mul(z, FP_EXP_TWO)));
- xp = FP_ONE + fp_div(fp_mul(FP_TWO, x), R - x);
-
- if (k < 0)
- {
- k = FP_ONE >> (-k >> FP_BITS);
- }
- else
- {
- k = FP_ONE << (k >> FP_BITS);
- }
-
- return fp_mul(k, xp)/(2*FP_BITS);
-}
-/*To generate (ruby code): (0...33).each { |idx| puts Math.exp((idx-10) / 8.0).to_s + "," } */
-const float exp_lookup_int[33]={0.28650479686019,0.32465246735835,0.367879441171442,0.416862019678508,0.472366552741015,0.53526142851899,0.606530659712633,0.687289278790972,0.778800783071405,0.882496902584595,1.0,1.13314845306683,1.28402541668774,1.4549914146182,1.64872127070013,1.86824595743222,2.11700001661267,2.3988752939671,2.71828182845905,3.08021684891803,3.49034295746184,3.95507672292058,4.48168907033806,5.07841903718008,5.75460267600573,6.52081912033011,7.38905609893065,8.37289748812726,9.48773583635853,10.7510131860764,12.1824939607035,13.8045741860671,15.6426318841882};
-/*To generate (ruby code): (0...32).each { |idx| puts Math.exp((idx-16.0) / 4.0).to_s+","} */
-static const float exp_table[32]={0.0183156388887342,0.0235177458560091,0.0301973834223185,0.038774207831722,0.0497870683678639,0.0639278612067076,0.0820849986238988,0.105399224561864,0.135335283236613,0.173773943450445,0.22313016014843,0.28650479686019,0.367879441171442,0.472366552741015,0.606530659712633,0.778800783071405,1.0,1.28402541668774,1.64872127070013,2.11700001661267,2.71828182845905,3.49034295746184,4.48168907033806,5.75460267600573,7.38905609893065,9.48773583635853,12.1824939607035,15.6426318841882,20.0855369231877,25.7903399171931,33.1154519586923,42.5210820000628};
-/**Returns exp(x) Range x=-4-+4 {x.0,x.25,x.5,x.75} */
-float spx_exp(float xf){
- float flt=spx_floor(xf);
- if(-4<xf&&4>xf&&(abs(xf-flt)==0.0||abs(xf-flt)==0.25||abs(xf-flt)==0.5||abs(xf-flt)==0.75||abs(xf-flt)==1.0)){
-#ifdef SIMULATOR
-/* printf("NtbSexp:%f,%d,%f:%f,%f,%f:%d,%d:%d\n",
- exp_sqrt_table[(int)((xf+4.0)*4.0)],
- (int)((xf-4.0)*4.0),
- (xf-4.0)*4.0,
- xf,
- flt,
- xf-flt,
- -4<xf,
- 4>xf,
- abs(xf-flt)
- );*/
-#endif
- return exp_table[(int)((xf+4.0)*4.0)];
- } else if (-4<xf&&4>xf){
-#ifdef SIMULATOR
-/* printf("NtbLexp:%f,%f,%f:%d,%d:%d\n",xf,flt,xf-flt,-4<xf,4>xf,abs(xf-flt)); */
-#endif
-
- return exp_table[(int)((xf+4.0)*4.0)];
- }
-
-#ifdef SIMULATOR
-/* printf("NTBLexp:%f,%f,%f:%d,%d:%d\n",xf,flt,xf-flt,-4<xf,4>xf,abs(xf-flt)); */
-#endif
- return spx_expB(xf);
- //return exp(xf);
-}
-//Placeholders (not fixed point, only used when encoding):
-float pow(float a,float b){
- return 0;
-}
-float log(float l){
- return 0;
-}
-float fabs(float a){
- return 0;
-}
-float sin(float a){
- return 0;
-}