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_Poly2Lsp.c
16
17 ******************************************************************/
18
19 #include "modules/audio_coding/codecs/ilbc/poly_to_lsp.h"
20
21 #include "modules/audio_coding/codecs/ilbc/chebyshev.h"
22 #include "modules/audio_coding/codecs/ilbc/constants.h"
23
24 /*----------------------------------------------------------------*
25 * conversion from lpc coefficients to lsp coefficients
26 * function is only for 10:th order LPC
27 *---------------------------------------------------------------*/
28
WebRtcIlbcfix_Poly2Lsp(int16_t * a,int16_t * lsp,int16_t * old_lsp)29 void WebRtcIlbcfix_Poly2Lsp(
30 int16_t *a, /* (o) A coefficients in Q12 */
31 int16_t *lsp, /* (i) LSP coefficients in Q15 */
32 int16_t *old_lsp /* (i) old LSP coefficients that are used if the new
33 coefficients turn out to be unstable */
34 ) {
35 int16_t f[2][6]; /* f[0][] represents f1 and f[1][] represents f2 */
36 int16_t *a_i_ptr, *a_10mi_ptr;
37 int16_t *f1ptr, *f2ptr;
38 int32_t tmpW32;
39 int16_t x, y, xlow, ylow, xmid, ymid, xhigh, yhigh, xint;
40 int16_t shifts, sign;
41 int i, j;
42 int foundFreqs;
43 int fi_select;
44
45 /*
46 Calculate the two polynomials f1(z) and f2(z)
47 (the sum and the diff polynomial)
48 f1[0] = f2[0] = 1.0;
49 f1[i+1] = a[i+1] + a[10-i] - f1[i];
50 f2[i+1] = a[i+1] - a[10-i] - f1[i];
51 */
52
53 a_i_ptr = a + 1;
54 a_10mi_ptr = a + 10;
55 f1ptr = f[0];
56 f2ptr = f[1];
57 (*f1ptr) = 1024; /* 1.0 in Q10 */
58 (*f2ptr) = 1024; /* 1.0 in Q10 */
59 for (i = 0; i < 5; i++) {
60 *(f1ptr + 1) =
61 (int16_t)((((int32_t)(*a_i_ptr) + *a_10mi_ptr) >> 2) - *f1ptr);
62 *(f2ptr + 1) =
63 (int16_t)((((int32_t)(*a_i_ptr) - *a_10mi_ptr) >> 2) + *f2ptr);
64 a_i_ptr++;
65 a_10mi_ptr--;
66 f1ptr++;
67 f2ptr++;
68 }
69
70 /*
71 find the LSPs using the Chebychev pol. evaluation
72 */
73
74 fi_select = 0; /* selector between f1 and f2, start with f1 */
75
76 foundFreqs = 0;
77
78 xlow = WebRtcIlbcfix_kCosGrid[0];
79 ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);
80
81 /*
82 Iterate until all the 10 LSP's have been found or
83 all the grid points have been tried. If the 10 LSP's can
84 not be found, set the LSP vector to previous LSP
85 */
86
87 for (j = 1; j < COS_GRID_POINTS && foundFreqs < 10; j++) {
88 xhigh = xlow;
89 yhigh = ylow;
90 xlow = WebRtcIlbcfix_kCosGrid[j];
91 ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);
92
93 if (ylow * yhigh <= 0) {
94 /* Run 4 times to reduce the interval */
95 for (i = 0; i < 4; i++) {
96 /* xmid =(xlow + xhigh)/2 */
97 xmid = (xlow >> 1) + (xhigh >> 1);
98 ymid = WebRtcIlbcfix_Chebyshev(xmid, f[fi_select]);
99
100 if (ylow * ymid <= 0) {
101 yhigh = ymid;
102 xhigh = xmid;
103 } else {
104 ylow = ymid;
105 xlow = xmid;
106 }
107 }
108
109 /*
110 Calculater xint by linear interpolation:
111 xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);
112 */
113
114 x = xhigh - xlow;
115 y = yhigh - ylow;
116
117 if (y == 0) {
118 xint = xlow;
119 } else {
120 sign = y;
121 y = WEBRTC_SPL_ABS_W16(y);
122 shifts = (int16_t)WebRtcSpl_NormW32(y)-16;
123 y <<= shifts;
124 y = (int16_t)WebRtcSpl_DivW32W16(536838144, y); /* 1/(yhigh-ylow) */
125
126 tmpW32 = (x * y) >> (19 - shifts);
127
128 /* y=(xhigh-xlow)/(yhigh-ylow) */
129 y = (int16_t)(tmpW32&0xFFFF);
130
131 if (sign < 0) {
132 y = -y;
133 }
134 /* tmpW32 = ylow*(xhigh-xlow)/(yhigh-ylow) */
135 tmpW32 = (ylow * y) >> 10;
136 xint = xlow-(int16_t)(tmpW32&0xFFFF);
137 }
138
139 /* Store the calculated lsp */
140 lsp[foundFreqs] = (int16_t)xint;
141 foundFreqs++;
142
143 /* if needed, set xlow and ylow for next recursion */
144 if (foundFreqs<10) {
145 xlow = xint;
146 /* Swap between f1 and f2 (f[0][] and f[1][]) */
147 fi_select = ((fi_select+1)&0x1);
148
149 ylow = WebRtcIlbcfix_Chebyshev(xlow, f[fi_select]);
150 }
151 }
152 }
153
154 /* Check if M roots found, if not then use the old LSP */
155 if (foundFreqs < 10) {
156 WEBRTC_SPL_MEMCPY_W16(lsp, old_lsp, 10);
157 }
158 return;
159 }
160