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
)));