| File: | libs/broadvoice/src/floating/common/a2lsp.c |
| Location: | line 191, column 21 |
| Description: | Value stored to 'xhigh' is never read |
| 1 | /* |
| 2 | * broadvoice - a library for the BroadVoice 16 and 32 codecs |
| 3 | * |
| 4 | * a2lsp.c - |
| 5 | * |
| 6 | * Adapted by Steve Underwood <steveu@coppice.org> from code which is |
| 7 | * Copyright 2000-2009 Broadcom Corporation |
| 8 | * |
| 9 | * All rights reserved. |
| 10 | * |
| 11 | * This program is free software; you can redistribute it and/or modify |
| 12 | * it under the terms of the GNU Lesser General Public License version 2.1, |
| 13 | * as published by the Free Software Foundation. |
| 14 | * |
| 15 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU Lesser General Public License for more details. |
| 19 | * |
| 20 | * You should have received a copy of the GNU Lesser General Public |
| 21 | * License along with this program; if not, write to the Free Software |
| 22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 23 | * |
| 24 | * $Id: a2lsp.c,v 1.1.1.1 2009/11/19 12:10:48 steveu Exp $ |
| 25 | */ |
| 26 | |
| 27 | /*! \file */ |
| 28 | |
| 29 | #if defined(HAVE_CONFIG_H1) |
| 30 | #include "config.h" |
| 31 | #endif |
| 32 | |
| 33 | #include <stdio.h> |
| 34 | #include <math.h> |
| 35 | #include "typedef.h" |
| 36 | #include "bvcommon.h" |
| 37 | |
| 38 | #define PI3.14159265358979 3.14159265358979 |
| 39 | |
| 40 | #define NAB((8 >> 1) + 1) ((LPCO8 >> 1) + 1) |
| 41 | |
| 42 | static Float FNevChebP(Float x, Float *c, int nd2); |
| 43 | |
| 44 | #define NBIS4 4 /* number of bisections */ |
| 45 | |
| 46 | /*---------------------------------------------------------------------------- |
| 47 | * a2lsp - Convert predictor coefficients to line spectral pairs |
| 48 | * |
| 49 | * Description: |
| 50 | * The transfer function of the prediction error filter is formed from the |
| 51 | * predictor coefficients. This polynomial is transformed into two reciprocal |
| 52 | * polynomials having roots on the unit circle. The roots of these polynomials |
| 53 | * interlace. It is these roots that determine the line spectral pairs. |
| 54 | * The two reciprocal polynomials are expressed as series expansions in |
| 55 | * Chebyshev polynomials with roots in the range -1 to +1. The inverse cosine |
| 56 | * of the roots of the Chebyshev polynomial expansion gives the line spectral |
| 57 | * pairs. If np line spectral pairs are not found, this routine |
| 58 | * stops with an error message. This error occurs if the input coefficients |
| 59 | * do not give a prediction error filter with minimum phase. |
| 60 | * |
| 61 | * Line spectral pairs and predictor coefficients are usually expressed |
| 62 | * algebraically as vectors. |
| 63 | * lsp[0] first (lowest frequency) line spectral pair |
| 64 | * lsp[i] 1 <= i < np |
| 65 | * pc[0]=1.0 predictor coefficient corresponding to lag 0 |
| 66 | * pc[i] 1 <= 1 <= np |
| 67 | * |
| 68 | * Parameters: |
| 69 | * -> Float pc[] |
| 70 | * Vector of predictor coefficients (Np+1 values). These are the |
| 71 | * coefficients of the predictor filter, with pc[0] being the predictor |
| 72 | * coefficient corresponding to lag 0, and pc[Np] corresponding to lag Np. |
| 73 | * The predictor coeffs. must correspond to a minimum phase prediction |
| 74 | * error filter. |
| 75 | * <- Float lsp[] |
| 76 | * Array of Np line spectral pairss (in ascending order). Each line |
| 77 | * spectral pair lies in the range 0 to pi. |
| 78 | * -> int Np |
| 79 | * Number of coefficients (at most LPCO = 50) |
| 80 | *---------------------------------------------------------------------------- |
| 81 | */ |
| 82 | |
| 83 | void a2lsp(Float pc[], /* (i) input the np+1 predictor coeff. */ |
| 84 | Float lsp[], /* (o) line spectral pairs */ |
| 85 | Float old_lsp[]) /* (i/o) old lsp[] (in case not found 10 roots) */ |
| 86 | { |
| 87 | Float fa[NAB((8 >> 1) + 1)], fb[NAB((8 >> 1) + 1)]; |
| 88 | Float ta[NAB((8 >> 1) + 1)], tb[NAB((8 >> 1) + 1)]; |
| 89 | Float *t; |
| 90 | Float xlow, xmid, xhigh; |
| 91 | Float ylow, ymid, yhigh; |
| 92 | Float xroot; |
| 93 | Float dx; |
| 94 | int i, j, nf, nd2, nab = ((LPCO8>>1) + 1), ngrd; |
| 95 | |
| 96 | fb[0] = fa[0] = 1.0; |
| 97 | for (i = 1, j = LPCO8; i <= (LPCO8/2); i++, j--) |
| 98 | { |
| 99 | fa[i] = pc[i] + pc[j] - fa[i-1]; |
| 100 | fb[i] = pc[i] - pc[j] + fb[i-1]; |
| 101 | } |
| 102 | |
| 103 | nd2 = LPCO8/2; |
| 104 | |
| 105 | /* |
| 106 | * To look for roots on the unit circle, Ga(D) and Gb(D) are evaluated for |
| 107 | * D=exp(jw). Since Gz(D) and Gb(D) are symmetric, they can be expressed in |
| 108 | * terms of a series in cos(nw) for D on the unit circle. Since M is odd and |
| 109 | * D=exp(jw) |
| 110 | * |
| 111 | * M-1 n |
| 112 | * Ga(D) = SUM fa(n) D (symmetric, fa(n) = fa(M-1-n)) |
| 113 | * n=0 |
| 114 | * Mh-1 |
| 115 | * = exp(j Mh w) [ f1(Mh) + 2 SUM fa(n) cos((Mh-n)w) ] |
| 116 | * n=0 |
| 117 | * Mh |
| 118 | * = exp(j Mh w) SUM ta(n) cos(nw), |
| 119 | * n=0 |
| 120 | * |
| 121 | * where Mh=(M-1)/2=Nc-1. The Nc=Mh+1 coefficients ta(n) are defined as |
| 122 | * |
| 123 | * ta(n) = fa(Nc-1), n=0, |
| 124 | * = 2 fa(Nc-1-n), n=1,...,Nc-1. |
| 125 | * The next step is to identify cos(nw) with the Chebyshev polynomial T(n,x). |
| 126 | * The Chebyshev polynomials satisfy the relationship T(n,cos(w)) = cos(nw). |
| 127 | * Omitting the exponential delay term, the series expansion in terms of |
| 128 | * Chebyshev polynomials is |
| 129 | * |
| 130 | * Nc-1 |
| 131 | * Ta(x) = SUM ta(n) T(n,x) |
| 132 | * n=0 |
| 133 | * |
| 134 | * The domain of Ta(x) is -1 < x < +1. For a given root of Ta(x), say x0, |
| 135 | * the corresponding position of the root of Fa(D) on the unit circle is |
| 136 | * exp(j arccos(x0)). |
| 137 | */ |
| 138 | ta[0] = fa[nab-1]; |
| 139 | tb[0] = fb[nab-1]; |
| 140 | for (i = 1, j = nab - 2; i < nab; ++i, --j) |
| 141 | { |
| 142 | ta[i] = 2.0 * fa[j]; |
| 143 | tb[i] = 2.0 * fb[j]; |
| 144 | } |
| 145 | |
| 146 | /* |
| 147 | * To find the roots, we sample the polynomials Ta(x) and Tb(x) looking for |
| 148 | * sign changes. An interval containing a root is successively bisected to |
| 149 | * narrow the interval and then linear interpolation is used to estimate the |
| 150 | * root. For a given root at x0, the line spectral pair is w0=acos(x0). |
| 151 | * |
| 152 | * Since the roots of the two polynomials interlace, the search for roots |
| 153 | * alternates between the polynomials Ta(x) and Tb(x). The sampling interval |
| 154 | * must be small enough to avoid having two cancelling sign changes in the |
| 155 | * same interval. The sampling (grid) points were trained from a large amount |
| 156 | * of LSP vectors derived with high accuracy and stored in a table. |
| 157 | */ |
| 158 | |
| 159 | nf = 0; |
| 160 | t = ta; |
| 161 | xroot = 2.0; |
| 162 | ngrd = 0; |
| 163 | xlow = grid[0]; |
| 164 | ylow = FNevChebP(xlow, t, nd2); |
| 165 | |
| 166 | |
| 167 | /* Root search loop */ |
| 168 | while (ngrd<(Ngrd60-1) && nf < LPCO8) |
| 169 | { |
| 170 | |
| 171 | /* New trial point */ |
| 172 | ngrd++; |
| 173 | xhigh = xlow; |
| 174 | yhigh = ylow; |
| 175 | xlow = grid[ngrd]; |
| 176 | ylow = FNevChebP(xlow, t, nd2); |
| 177 | |
| 178 | if (ylow * yhigh <= 0.0) |
| 179 | { |
| 180 | |
| 181 | /* Bisections of the interval containing a sign change */ |
| 182 | dx = xhigh - xlow; |
| 183 | for (i = 1; i <= NBIS4; ++i) |
| 184 | { |
| 185 | dx = 0.5 * dx; |
| 186 | xmid = xlow + dx; |
| 187 | ymid = FNevChebP(xmid, t, nd2); |
| 188 | if (ylow * ymid <= 0.0) |
| 189 | { |
| 190 | yhigh = ymid; |
| 191 | xhigh = xmid; |
Value stored to 'xhigh' is never read | |
| 192 | } |
| 193 | else |
| 194 | { |
| 195 | ylow = ymid; |
| 196 | xlow = xmid; |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | /* |
| 201 | * Linear interpolation in the subinterval with a sign change |
| 202 | * (take care if yhigh=ylow=0) |
| 203 | */ |
| 204 | if (yhigh != ylow) |
| 205 | xmid = xlow + dx * ylow / (ylow - yhigh); |
| 206 | else |
| 207 | xmid = xlow + dx; |
| 208 | |
| 209 | /* New root position */ |
| 210 | lsp[nf] = acos(xmid)/PI3.14159265358979; |
| 211 | ++nf; |
| 212 | |
| 213 | /* Start the search for the roots of the next polynomial at the estimated |
| 214 | * location of the root just found. We have to catch the case that the |
| 215 | * two polynomials have roots at the same place to avoid getting stuck at |
| 216 | * that root. |
| 217 | */ |
| 218 | if (xmid >= xroot) |
| 219 | { |
| 220 | xmid = xlow - dx; |
| 221 | } |
| 222 | xroot = xmid; |
| 223 | if (t == ta) |
| 224 | t = tb; |
| 225 | else |
| 226 | t = ta; |
| 227 | xlow = xmid; |
| 228 | ylow = FNevChebP(xlow, t, nd2); |
| 229 | } |
| 230 | } |
| 231 | |
| 232 | if (nf != LPCO8) |
| 233 | { |
| 234 | /* LPCO roots have not been found */ |
| 235 | printf("\nWARNING: a2lsp failed to find all lsp nf=%d LPCO=%d\n", nf, LPCO8); |
| 236 | for (i = 0; i < LPCO8; i++) |
| 237 | lsp[i] = old_lsp[i]; |
| 238 | } |
| 239 | else |
| 240 | { |
| 241 | /* Update LSP of previous frame with the new LSP */ |
| 242 | for (i = 0; i < LPCO8; i++) |
| 243 | old_lsp[i] = lsp[i]; |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | static Float FNevChebP(Float x, /* (i) value */ |
| 248 | Float *c, /* (i) coefficient array */ |
| 249 | int nd2) |
| 250 | { |
| 251 | Float t; |
| 252 | Float b[NAB((8 >> 1) + 1)]; |
| 253 | int i; |
| 254 | |
| 255 | t = x*2; |
| 256 | b[0] = c[nd2]; |
| 257 | b[1] = c[nd2 - 1] + t*b[0]; |
| 258 | for (i = 2; i < nd2; i++) |
| 259 | b[i] = c[nd2 - i] - b[i - 2] + t * b[i - 1]; |
| 260 | return (c[0] - b[nd2 - 2] + x * b[nd2 - 1]); |
| 261 | } |