1
/* Copyright (C) 2002 Jean-Marc Valin */
4
@brief Various math approximation functions for Speex
7
Redistribution and use in source and binary forms, with or without
8
modification, are permitted provided that the following conditions
11
- Redistributions of source code must retain the above copyright
12
notice, this list of conditions and the following disclaimer.
14
- Redistributions in binary form must reproduce the above copyright
15
notice, this list of conditions and the following disclaimer in the
16
documentation and/or other materials provided with the distribution.
18
- Neither the name of the Xiph.org Foundation nor the names of its
19
contributors may be used to endorse or promote products derived from
20
this software without specific prior written permission.
22
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
26
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45
#define spx_cos_norm(x) (cos((.5f*M_PI)*(x)))
48
/** Generate a pseudo-random number */
49
static inline spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed)
51
const unsigned int jflone = 0x3f800000;
52
const unsigned int jflmsk = 0x007fffff;
53
union {int i; float f;} ran;
54
*seed = 1664525 * *seed + 1013904223;
55
ran.i = jflone | (jflmsk & *seed);
57
return 3.4642*std*ran.f;
64
static inline spx_int16_t spx_ilog2(spx_uint32_t x)
67
if (x>=(spx_int32_t)65536)
94
static inline spx_int16_t spx_ilog4(spx_uint32_t x)
97
if (x>=(spx_int32_t)65536)
121
/** Generate a pseudo-random number */
122
static inline spx_word16_t speex_rand(spx_word16_t std, spx_int32_t *seed)
125
*seed = 1664525 * *seed + 1013904223;
126
res = MULT16_16(EXTRACT16(SHR32(*seed,16)),std);
127
return EXTRACT16(PSHR32(SUB32(res, SHR32(res, 3)),14));
130
/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25723*x^3 (for .25 < x < 1) */
136
/* sqrt(x) ~= 0.22178 + 1.29227*x - 0.77070*x^2 + 0.25659*x^3 (for .25 < x < 1) */
142
static inline spx_word16_t spx_sqrt(spx_word32_t x)
147
x = VSHR32(x, (k<<1));
148
rt = ADD16(C0, MULT16_16_Q14(x, ADD16(C1, MULT16_16_Q14(x, ADD16(C2, MULT16_16_Q14(x, (C3)))))));
153
/* log(x) ~= -2.18151 + 4.20592*x - 2.88938*x^2 + 0.86535*x^3 (for .5 < x < 1) */
160
static inline spx_word16_t spx_acos(spx_word16_t x)
173
sq = MULT16_16_Q13(x, ADD16(A1, MULT16_16_Q13(x, ADD16(A2, MULT16_16_Q13(x, (A3))))));
174
ret = spx_sqrt(SHL32(EXTEND32(sq),13));
176
/*ret = spx_sqrt(67108864*(-1.6129e-04 + 2.0104e+00*f + 2.7373e-01*f*f + 1.8136e-01*f*f*f));*/
178
ret = SUB16(25736,ret);
188
static inline spx_word16_t spx_cos(spx_word16_t x)
194
x2 = MULT16_16_P13(x,x);
195
return ADD32(K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
198
x2 = MULT16_16_P13(x,x);
199
return SUB32(-K1, MULT16_16_P13(x2, ADD32(K2, MULT16_16_P13(x2, ADD32(K3, MULT16_16_P13(K4, x2))))));
208
static inline spx_word16_t _spx_cos_pi_2(spx_word16_t x)
212
x2 = MULT16_16_P15(x,x);
213
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))))))));
216
static inline spx_word16_t spx_cos_norm(spx_word32_t x)
219
if (x>SHL32(EXTEND32(1), 16))
220
x = SUB32(SHL32(EXTEND32(1), 17),x);
223
if (x<SHL32(EXTEND32(1), 15))
225
return _spx_cos_pi_2(EXTRACT16(x));
227
return NEG32(_spx_cos_pi_2(EXTRACT16(65536-x)));
232
else if (x&0x0001ffff)
249
/* Input in Q11 format, output in Q16 */
250
static inline spx_word32_t spx_exp2(spx_word16_t x)
254
integer = SHR16(x,11);
257
else if (integer < -15)
259
frac = SHL16(x-SHL16(integer,11),3);
260
frac = ADD16(D0, MULT16_16_Q14(frac, ADD16(D1, MULT16_16_Q14(frac, ADD16(D2 , MULT16_16_Q14(D3,frac))))));
261
return VSHR32(EXTEND32(frac), -integer-2);
264
/* Input in Q11 format, output in Q16 */
265
static inline spx_word32_t spx_exp(spx_word16_t x)
272
return spx_exp2(MULT16_16_P14(23637,x));
279
static inline spx_word16_t spx_atan01(spx_word16_t x)
281
return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
289
/* Input in Q15, output in Q14 */
290
static inline spx_word16_t spx_atan(spx_word32_t x)
294
return SHR16(spx_atan01(x),1);
296
int e = spx_ilog2(x);
299
x = DIV32_16(SHL32(EXTEND32(32767),29-e), EXTRACT16(SHR32(x, e-14)));
300
return SUB16(25736, SHR16(spx_atan01(x),1));
306
#define M_PI 3.14159265358979323846 /* pi */
309
#define C1 0.9999932946f
310
#define C2 -0.4999124376f
311
#define C3 0.0414877472f
312
#define C4 -0.0012712095f
315
#define SPX_PI_2 1.5707963268
316
static inline spx_word16_t spx_cos(spx_word16_t x)
321
return C1 + x*(C2+x*(C3+C4*x));
325
return NEG16(C1 + x*(C2+x*(C3+C4*x)));