niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 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 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 29 | int16_t WebRtcIlbcfix_Chebyshev( |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 30 | /* (o) Result of C(x) */ |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 31 | int16_t x, /* (i) Value to the Chevyshev polynomial */ |
| 32 | int16_t *f /* (i) The coefficients in the polynomial */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 33 | ) { |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 34 | 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.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 38 | int i; |
| 39 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 40 | b2 = (int32_t)0x1000000; /* b2 = 1.0 (Q23) */ |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 41 | /* Calculate b1 = 2*x + f[1] */ |
bjornv@webrtc.org | 4ab23d0 | 2015-03-20 06:01:06 +0000 | [diff] [blame] | 42 | tmp1W32 = (x << 10) + (f[1] << 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 43 | |
| 44 | for (i = 2; i < 5; i++) { |
| 45 | tmp2W32 = tmp1W32; |
| 46 | |
| 47 | /* Split b1 (in tmp1W32) into a high and low part */ |
bjornv@webrtc.org | 78ea06d | 2014-10-21 07:17:24 +0000 | [diff] [blame] | 48 | b1_high = (int16_t)(tmp1W32 >> 16); |
| 49 | b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 50 | |
| 51 | /* Calculate 2*x*b1-b2+f[i] */ |
bjornv@webrtc.org | 4ab23d0 | 2015-03-20 06:01:06 +0000 | [diff] [blame] | 52 | tmp1W32 = ((b1_high * x + ((b1_low * x) >> 15)) << 2) - b2 + (f[i] << 14); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 53 | |
| 54 | /* Update b2 for next round */ |
| 55 | b2 = tmp2W32; |
| 56 | } |
| 57 | |
| 58 | /* Split b1 (in tmp1W32) into a high and low part */ |
bjornv@webrtc.org | 78ea06d | 2014-10-21 07:17:24 +0000 | [diff] [blame] | 59 | b1_high = (int16_t)(tmp1W32 >> 16); |
| 60 | b1_low = (int16_t)((tmp1W32 - ((int32_t)b1_high << 16)) >> 1); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 61 | |
| 62 | /* tmp1W32 = x*b1 - b2 + f[i]/2 */ |
bjornv@webrtc.org | 4ab23d0 | 2015-03-20 06:01:06 +0000 | [diff] [blame] | 63 | tmp1W32 = ((b1_high * x) << 1) + (((b1_low * x) >> 15) << 1) - |
| 64 | b2 + (f[i] << 13); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 65 | |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 66 | /* Handle overflows and set to maximum or minimum int16_t instead */ |
| 67 | if (tmp1W32>((int32_t)33553408)) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 68 | return(WEBRTC_SPL_WORD16_MAX); |
pbos@webrtc.org | 0946a56 | 2013-04-09 00:28:06 +0000 | [diff] [blame] | 69 | } else if (tmp1W32<((int32_t)-33554432)) { |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 70 | return(WEBRTC_SPL_WORD16_MIN); |
| 71 | } else { |
bjornv@webrtc.org | 78ea06d | 2014-10-21 07:17:24 +0000 | [diff] [blame] | 72 | return (int16_t)(tmp1W32 >> 10); |
niklase@google.com | 470e71d | 2011-07-07 08:21:25 +0000 | [diff] [blame] | 73 | } |
| 74 | } |