1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 /******************************************************************
12 
13  iLBC Speech Coder ANSI-C Source Code
14 
15  WebRtcIlbcfix_Chebyshev.c
16 
17 ******************************************************************/
18 
19 #include "defines.h"
20 #include "constants.h"
21 
22 /*------------------------------------------------------------------*
23  *  Calculate the Chevyshev polynomial series
24  *  F(w) = 2*exp(-j5w)*C(x)
25  *   C(x) = (T_0(x) + f(1)T_1(x) + ... + f(4)T_1(x) + f(5)/2)
26  *   T_i(x) is the i:th order Chebyshev polynomial
27  *------------------------------------------------------------------*/
28 
WebRtcIlbcfix_Chebyshev(WebRtc_Word16 x,WebRtc_Word16 * f)29 WebRtc_Word16 WebRtcIlbcfix_Chebyshev(
30     /* (o) Result of C(x) */
31     WebRtc_Word16 x,  /* (i) Value to the Chevyshev polynomial */
32     WebRtc_Word16 *f  /* (i) The coefficients in the polynomial */
33                                       ) {
34   WebRtc_Word16 b1_high, b1_low; /* Use the high, low format to increase the accuracy */
35   WebRtc_Word32 b2;
36   WebRtc_Word32 tmp1W32;
37   WebRtc_Word32 tmp2W32;
38   int i;
39 
40   b2 = (WebRtc_Word32)0x1000000; /* b2 = 1.0 (Q23) */
41   /* Calculate b1 = 2*x + f[1] */
42   tmp1W32 = WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)x, 10);
43   tmp1W32 += WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)f[1], 14);
44 
45   for (i = 2; i < 5; i++) {
46     tmp2W32 = tmp1W32;
47 
48     /* Split b1 (in tmp1W32) into a high and low part */
49     b1_high = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32, 16);
50     b1_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32-WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)b1_high),16), 1);
51 
52     /* Calculate 2*x*b1-b2+f[i] */
53     tmp1W32 = WEBRTC_SPL_LSHIFT_W32( (WEBRTC_SPL_MUL_16_16(b1_high, x) +
54                                       WEBRTC_SPL_MUL_16_16_RSFT(b1_low, x, 15)), 2);
55 
56     tmp1W32 -= b2;
57     tmp1W32 += WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)f[i], 14);
58 
59     /* Update b2 for next round */
60     b2 = tmp2W32;
61   }
62 
63   /* Split b1 (in tmp1W32) into a high and low part */
64   b1_high = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32, 16);
65   b1_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32-WEBRTC_SPL_LSHIFT_W32(((WebRtc_Word32)b1_high),16), 1);
66 
67   /* tmp1W32 = x*b1 - b2 + f[i]/2 */
68   tmp1W32 = WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16(b1_high, x), 1) +
69       WEBRTC_SPL_LSHIFT_W32(WEBRTC_SPL_MUL_16_16_RSFT(b1_low, x, 15), 1);
70 
71   tmp1W32 -= b2;
72   tmp1W32 += WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)f[i], 13);
73 
74   /* Handle overflows and set to maximum or minimum WebRtc_Word16 instead */
75   if (tmp1W32>((WebRtc_Word32)33553408)) {
76     return(WEBRTC_SPL_WORD16_MAX);
77   } else if (tmp1W32<((WebRtc_Word32)-33554432)) {
78     return(WEBRTC_SPL_WORD16_MIN);
79   } else {
80     return((WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmp1W32, 10));
81   }
82 }
83