blob: 96c1aed942f4ed705a8aa1ec5b43f83039745a4c [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
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
pbos@webrtc.org0946a562013-04-09 00:28:06 +000029int16_t WebRtcIlbcfix_Chebyshev(
niklase@google.com470e71d2011-07-07 08:21:25 +000030 /* (o) Result of C(x) */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000031 int16_t x, /* (i) Value to the Chevyshev polynomial */
32 int16_t *f /* (i) The coefficients in the polynomial */
niklase@google.com470e71d2011-07-07 08:21:25 +000033 ) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +000034 int16_t b1_high, b1_low; /* Use the high, low format to increase the accuracy */
35 int32_t b2;
36 int32_t tmp1W32;
37 int32_t tmp2W32;
niklase@google.com470e71d2011-07-07 08:21:25 +000038 int i;
39
pbos@webrtc.org0946a562013-04-09 00:28:06 +000040 b2 = (int32_t)0x1000000; /* b2 = 1.0 (Q23) */
niklase@google.com470e71d2011-07-07 08:21:25 +000041 /* Calculate b1 = 2*x + f[1] */
pbos@webrtc.org0946a562013-04-09 00:28:06 +000042 tmp1W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)x, 10);
43 tmp1W32 += WEBRTC_SPL_LSHIFT_W32((int32_t)f[1], 14);
niklase@google.com470e71d2011-07-07 08:21:25 +000044
45 for (i = 2; i < 5; i++) {
46 tmp2W32 = tmp1W32;
47
48 /* Split b1 (in tmp1W32) into a high and low part */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +000049 b1_high = (int16_t)(tmp1W32 >> 16);
50 b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1);
niklase@google.com470e71d2011-07-07 08:21:25 +000051
52 /* Calculate 2*x*b1-b2+f[i] */
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +000053 tmp1W32 = WEBRTC_SPL_LSHIFT_W32(b1_high * x + ((b1_low * x) >> 15), 2);
niklase@google.com470e71d2011-07-07 08:21:25 +000054
55 tmp1W32 -= b2;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000056 tmp1W32 += WEBRTC_SPL_LSHIFT_W32((int32_t)f[i], 14);
niklase@google.com470e71d2011-07-07 08:21:25 +000057
58 /* Update b2 for next round */
59 b2 = tmp2W32;
60 }
61
62 /* Split b1 (in tmp1W32) into a high and low part */
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +000063 b1_high = (int16_t)(tmp1W32 >> 16);
64 b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1);
niklase@google.com470e71d2011-07-07 08:21:25 +000065
66 /* tmp1W32 = x*b1 - b2 + f[i]/2 */
bjornv@webrtc.orgba97ea62015-02-13 09:51:40 +000067 tmp1W32 = WEBRTC_SPL_LSHIFT_W32(b1_high * x, 1) +
bjornv@webrtc.org2f6ae0d2015-03-01 19:50:41 +000068 WEBRTC_SPL_LSHIFT_W32((b1_low * x) >> 15, 1);
niklase@google.com470e71d2011-07-07 08:21:25 +000069
70 tmp1W32 -= b2;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000071 tmp1W32 += WEBRTC_SPL_LSHIFT_W32((int32_t)f[i], 13);
niklase@google.com470e71d2011-07-07 08:21:25 +000072
pbos@webrtc.org0946a562013-04-09 00:28:06 +000073 /* Handle overflows and set to maximum or minimum int16_t instead */
74 if (tmp1W32>((int32_t)33553408)) {
niklase@google.com470e71d2011-07-07 08:21:25 +000075 return(WEBRTC_SPL_WORD16_MAX);
pbos@webrtc.org0946a562013-04-09 00:28:06 +000076 } else if (tmp1W32<((int32_t)-33554432)) {
niklase@google.com470e71d2011-07-07 08:21:25 +000077 return(WEBRTC_SPL_WORD16_MIN);
78 } else {
bjornv@webrtc.org78ea06d2014-10-21 07:17:24 +000079 return (int16_t)(tmp1W32 >> 10);
niklase@google.com470e71d2011-07-07 08:21:25 +000080 }
81}