Coverage Report

Created: 2026-07-10 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/speex/libspeex/lsp.c
Line
Count
Source
1
/*---------------------------------------------------------------------------*\
2
Original copyright
3
  FILE........: lsp.c
4
  AUTHOR......: David Rowe
5
  DATE CREATED: 24/2/93
6
7
Heavily modified by Jean-Marc Valin (c) 2002-2006 (fixed-point,
8
                       optimizations, additional functions, ...)
9
10
   This file contains functions for converting Linear Prediction
11
   Coefficients (LPC) to Line Spectral Pair (LSP) and back. Note that the
12
   LSP coefficients are not in radians format but in the x domain of the
13
   unit circle.
14
15
   Speex License:
16
17
   Redistribution and use in source and binary forms, with or without
18
   modification, are permitted provided that the following conditions
19
   are met:
20
21
   - Redistributions of source code must retain the above copyright
22
   notice, this list of conditions and the following disclaimer.
23
24
   - Redistributions in binary form must reproduce the above copyright
25
   notice, this list of conditions and the following disclaimer in the
26
   documentation and/or other materials provided with the distribution.
27
28
   - Neither the name of the Xiph.org Foundation nor the names of its
29
   contributors may be used to endorse or promote products derived from
30
   this software without specific prior written permission.
31
32
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35
   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
36
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
38
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
*/
44
45
/*---------------------------------------------------------------------------*\
46
47
  Introduction to Line Spectrum Pairs (LSPs)
48
  ------------------------------------------
49
50
  LSPs are used to encode the LPC filter coefficients {ak} for
51
  transmission over the channel.  LSPs have several properties (like
52
  less sensitivity to quantisation noise) that make them superior to
53
  direct quantisation of {ak}.
54
55
  A(z) is a polynomial of order lpcrdr with {ak} as the coefficients.
56
57
  A(z) is transformed to P(z) and Q(z) (using a substitution and some
58
  algebra), to obtain something like:
59
60
    A(z) = 0.5[P(z)(z+z^-1) + Q(z)(z-z^-1)]  (1)
61
62
  As you can imagine A(z) has complex zeros all over the z-plane. P(z)
63
  and Q(z) have the very neat property of only having zeros _on_ the
64
  unit circle.  So to find them we take a test point z=exp(jw) and
65
  evaluate P (exp(jw)) and Q(exp(jw)) using a grid of points between 0
66
  and pi.
67
68
  The zeros (roots) of P(z) also happen to alternate, which is why we
69
  swap coefficients as we find roots.  So the process of finding the
70
  LSP frequencies is basically finding the roots of 5th order
71
  polynomials.
72
73
  The root so P(z) and Q(z) occur in symmetrical pairs at +/-w, hence
74
  the name Line Spectrum Pairs (LSPs).
75
76
  To convert back to ak we just evaluate (1), "clocking" an impulse
77
  thru it lpcrdr times gives us the impulse response of A(z) which is
78
  {ak}.
79
80
\*---------------------------------------------------------------------------*/
81
82
#ifdef HAVE_CONFIG_H
83
#include "config.h"
84
#endif
85
86
#include <math.h>
87
#include "lsp.h"
88
#include "stack_alloc.h"
89
#include "math_approx.h"
90
91
#ifndef M_PI
92
#define M_PI           3.14159265358979323846  /* pi */
93
#endif
94
95
#ifndef NULL
96
152k
#define NULL 0
97
#endif
98
99
#ifdef FIXED_POINT
100
101
620k
#define FREQ_SCALE 16384
102
103
/*#define ANGLE2X(a) (32768*cos(((a)/8192.)))*/
104
2.78M
#define ANGLE2X(a) (SHL16(spx_cos(a),2))
105
106
/*#define X2ANGLE(x) (acos(.00006103515625*(x))*LSP_SCALING)*/
107
254k
#define X2ANGLE(x) (spx_acos(x))
108
109
#ifdef BFIN_ASM
110
#include "lsp_bfin.h"
111
#endif
112
113
#else
114
115
/*#define C1 0.99940307
116
#define C2 -0.49558072
117
#define C3 0.03679168*/
118
119
285k
#define FREQ_SCALE 1.
120
1.45M
#define ANGLE2X(a) (spx_cos(a))
121
116k
#define X2ANGLE(x) (acos(x))
122
123
#endif
124
125
#ifndef DISABLE_ENCODER
126
127
/*---------------------------------------------------------------------------*\
128
129
   FUNCTION....: cheb_poly_eva()
130
131
   AUTHOR......: David Rowe
132
   DATE CREATED: 24/2/93
133
134
   This function evaluates a series of Chebyshev polynomials
135
136
\*---------------------------------------------------------------------------*/
137
138
#ifdef FIXED_POINT
139
140
#ifndef OVERRIDE_CHEB_POLY_EVA
141
static inline spx_word32_t cheb_poly_eva(
142
  spx_word16_t *coef, /* P or Q coefs in Q13 format               */
143
  spx_word16_t     x, /* cos of freq (-1.0 to 1.0) in Q14 format  */
144
  int              m, /* LPC order/2                              */
145
  char         *stack
146
)
147
3.64M
{
148
3.64M
    int i;
149
3.64M
    spx_word16_t b0, b1;
150
3.64M
    spx_word32_t sum;
151
152
    /*Prevents overflows*/
153
3.64M
    if (x>16383)
154
27.0k
       x = 16383;
155
3.64M
    if (x<-16383)
156
2.02k
       x = -16383;
157
158
    /* Initialise values */
159
3.64M
    b1=16384;
160
3.64M
    b0=x;
161
162
    /* Evaluate Chebyshev series formulation using an iterative approach  */
163
3.64M
    sum = ADD32(EXTEND32(coef[m]), EXTEND32(MULT16_16_P14(coef[m-1],x)));
164
17.4M
    for(i=2;i<=m;i++)
165
13.7M
    {
166
13.7M
       spx_word16_t tmp=b0;
167
13.7M
       b0 = SUB16(MULT16_16_Q13(x,b0), b1);
168
13.7M
       b1 = tmp;
169
13.7M
       sum = ADD32(sum, EXTEND32(MULT16_16_P14(coef[m-i],b0)));
170
13.7M
    }
171
172
3.64M
    return sum;
173
3.64M
}
174
#endif
175
176
#else
177
178
static float cheb_poly_eva(spx_word32_t *coef, spx_word16_t x, int m, char *stack)
179
1.66M
{
180
1.66M
   int k;
181
1.66M
   float b0, b1, tmp;
182
183
   /* Initial conditions */
184
1.66M
   b0=0; /* b_(m+1) */
185
1.66M
   b1=0; /* b_(m+2) */
186
187
1.66M
   x*=2;
188
189
   /* Calculate the b_(k) */
190
9.56M
   for(k=m;k>0;k--)
191
7.89M
   {
192
7.89M
      tmp=b0;                           /* tmp holds the previous value of b0 */
193
7.89M
      b0=x*b0-b1+coef[m-k];    /* b0 holds its new value based on b0 and b1 */
194
7.89M
      b1=tmp;                           /* b1 holds the previous value of b0 */
195
7.89M
   }
196
197
1.66M
   return(-b1+.5*x*b0+coef[m]);
198
1.66M
}
199
#endif
200
201
/*---------------------------------------------------------------------------*\
202
203
    FUNCTION....: lpc_to_lsp()
204
205
    AUTHOR......: David Rowe
206
    DATE CREATED: 24/2/93
207
208
    This function converts LPC coefficients to LSP
209
    coefficients.
210
211
\*---------------------------------------------------------------------------*/
212
213
#ifdef FIXED_POINT
214
3.38M
#define SIGN_CHANGE(a,b) ((((a)^(b))&0x80000000)||(b==0))
215
#else
216
1.55M
#define SIGN_CHANGE(a,b) (((a)*(b))<0.0)
217
#endif
218
219
220
int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack)
221
/*  float *a          lpc coefficients      */
222
/*  int lpcrdr      order of LPC coefficients (10)    */
223
/*  float *freq           LSP frequencies in the x domain         */
224
/*  int nb      number of sub-intervals (4)     */
225
/*  float delta     grid spacing interval (0.02)    */
226
227
228
39.3k
{
229
39.3k
    spx_word16_t temp_xr,xl,xr,xm=0;
230
39.3k
    spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/;
231
39.3k
    int i,j,m,k;
232
39.3k
    VARDECL(spx_word32_t *Q);                   /* ptrs for memory allocation     */
233
39.3k
    VARDECL(spx_word32_t *P);
234
39.3k
    VARDECL(spx_word16_t *Q16);         /* ptrs for memory allocation     */
235
39.3k
    VARDECL(spx_word16_t *P16);
236
39.3k
    spx_word32_t *px;                 /* ptrs of respective P'(z) & Q'(z) */
237
39.3k
    spx_word32_t *qx;
238
39.3k
    spx_word32_t *p;
239
39.3k
    spx_word32_t *q;
240
39.3k
    spx_word16_t *pt;                 /* ptr used for cheb_poly_eval()
241
        whether P' or Q'      */
242
39.3k
    int roots=0;                /* DR 8/2/94: number of roots found   */
243
39.3k
    m = lpcrdr/2;             /* order of P'(z) & Q'(z) polynomials   */
244
245
    /* Allocate memory space for polynomials */
246
39.3k
    ALLOC(Q, (m+1), spx_word32_t);
247
39.3k
    ALLOC(P, (m+1), spx_word32_t);
248
249
    /* determine P'(z)'s and Q'(z)'s coefficients where
250
      P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */
251
252
39.3k
    px = P;                      /* initialise ptrs       */
253
39.3k
    qx = Q;
254
39.3k
    p = px;
255
39.3k
    q = qx;
256
257
#ifdef FIXED_POINT
258
26.9k
    *px++ = LPC_SCALING;
259
26.9k
    *qx++ = LPC_SCALING;
260
154k
    for(i=0;i<m;i++){
261
127k
       *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++);
262
127k
       *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++);
263
127k
    }
264
    px = P;
265
    qx = Q;
266
154k
    for(i=0;i<m;i++)
267
127k
    {
268
       /*if (fabs(*px)>=32768)
269
          speex_warning_int("px", *px);
270
       if (fabs(*qx)>=32768)
271
       speex_warning_int("qx", *qx);*/
272
127k
       *px = PSHR32(*px,2);
273
127k
       *qx = PSHR32(*qx,2);
274
127k
       px++;
275
127k
       qx++;
276
127k
    }
277
    /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */
278
26.9k
    P[m] = PSHR32(P[m],3);
279
26.9k
    Q[m] = PSHR32(Q[m],3);
280
#else
281
12.3k
    *px++ = LPC_SCALING;
282
12.3k
    *qx++ = LPC_SCALING;
283
70.5k
    for(i=0;i<m;i++){
284
58.1k
       *px++ = (a[i]+a[lpcrdr-1-i]) - *p++;
285
58.1k
       *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++;
286
58.1k
    }
287
    px = P;
288
    qx = Q;
289
70.5k
    for(i=0;i<m;i++){
290
58.1k
       *px = 2**px;
291
58.1k
       *qx = 2**qx;
292
58.1k
       px++;
293
58.1k
       qx++;
294
58.1k
    }
295
#endif
296
297
39.3k
    px = P;               /* re-initialise ptrs       */
298
39.3k
    qx = Q;
299
300
    /* now that we have computed P and Q convert to 16 bits to
301
       speed up cheb_poly_eval */
302
303
39.3k
    ALLOC(P16, m+1, spx_word16_t);
304
39.3k
    ALLOC(Q16, m+1, spx_word16_t);
305
306
264k
    for (i=0;i<m+1;i++)
307
225k
    {
308
225k
       P16[i] = P[i];
309
225k
       Q16[i] = Q[i];
310
225k
    }
311
312
    /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z).
313
    Keep alternating between the two polynomials as each zero is found  */
314
315
39.3k
    xr = 0;               /* initialise xr to zero    */
316
39.3k
    xl = FREQ_SCALE;                 /* start at point xl = 1    */
317
318
411k
    for(j=0;j<lpcrdr;j++){
319
372k
  if(j&1)              /* determines whether P' or Q' is eval. */
320
186k
      pt = Q16;
321
186k
  else
322
186k
      pt = P16;
323
324
372k
  psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl  */
325
326
866k
  while(xr >= -FREQ_SCALE){
327
864k
           spx_word16_t dd;
328
           /* Modified by JMV to provide smaller steps around x=+-1 */
329
#ifdef FIXED_POINT
330
592k
           dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000)));
331
592k
           if (psuml<512 && psuml>-512)
332
111k
              dd = PSHR16(dd,1);
333
#else
334
           dd=delta*(1-.9*xl*xl);
335
272k
           if (fabs(psuml)<.2)
336
22.1k
              dd *= .5;
337
#endif
338
864k
           xr = SUB16(xl, dd);                         /* interval spacing   */
339
864k
      psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x)  */
340
864k
      temp_psumr = psumr;
341
864k
      temp_xr = xr;
342
343
    /* if no sign change increment xr and re-evaluate poly(xr). Repeat til
344
    sign change.
345
    if a sign change has occurred the interval is bisected and then
346
    checked again for a sign change which determines in which
347
    interval the zero lies in.
348
    If there is no sign change between poly(xm) and poly(xl) set interval
349
    between xm and xr else set interval between xl and xr and repeat till
350
    root is located within the specified limits       */
351
352
864k
      if(SIGN_CHANGE(psumr,psuml))
353
370k
            {
354
370k
    roots++;
355
356
370k
    psumm=psuml;
357
4.44M
    for(k=0;k<=nb;k++){
358
#ifdef FIXED_POINT
359
2.79M
        xm = ADD16(PSHR16(xl,1),PSHR16(xr,1));          /* bisect the interval  */
360
#else
361
                    xm = .5*(xl+xr);          /* bisect the interval  */
362
#endif
363
4.07M
        psumm=cheb_poly_eva(pt,xm,m,stack);
364
        /*if(psumm*psuml>0.)*/
365
4.07M
        if(!SIGN_CHANGE(psumm,psuml))
366
2.13M
                    {
367
2.13M
      psuml=psumm;
368
2.13M
      xl=xm;
369
2.13M
        } else {
370
1.93M
      psumr=psumm;
371
1.93M
      xr=xm;
372
1.93M
        }
373
4.07M
    }
374
375
         /* once zero is found, reset initial interval to xr  */
376
370k
         freq[j] = X2ANGLE(xm);
377
370k
         xl = xm;
378
370k
         break;
379
370k
      }
380
494k
      else{
381
494k
    psuml=temp_psumr;
382
494k
    xl=temp_xr;
383
494k
      }
384
864k
  }
385
372k
    }
386
39.3k
    return(roots);
387
39.3k
}
lpc_to_lsp
Line
Count
Source
228
12.3k
{
229
12.3k
    spx_word16_t temp_xr,xl,xr,xm=0;
230
12.3k
    spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/;
231
12.3k
    int i,j,m,k;
232
12.3k
    VARDECL(spx_word32_t *Q);                   /* ptrs for memory allocation     */
233
12.3k
    VARDECL(spx_word32_t *P);
234
12.3k
    VARDECL(spx_word16_t *Q16);         /* ptrs for memory allocation     */
235
12.3k
    VARDECL(spx_word16_t *P16);
236
12.3k
    spx_word32_t *px;                 /* ptrs of respective P'(z) & Q'(z) */
237
12.3k
    spx_word32_t *qx;
238
12.3k
    spx_word32_t *p;
239
12.3k
    spx_word32_t *q;
240
12.3k
    spx_word16_t *pt;                 /* ptr used for cheb_poly_eval()
241
        whether P' or Q'      */
242
12.3k
    int roots=0;                /* DR 8/2/94: number of roots found   */
243
12.3k
    m = lpcrdr/2;             /* order of P'(z) & Q'(z) polynomials   */
244
245
    /* Allocate memory space for polynomials */
246
12.3k
    ALLOC(Q, (m+1), spx_word32_t);
247
12.3k
    ALLOC(P, (m+1), spx_word32_t);
248
249
    /* determine P'(z)'s and Q'(z)'s coefficients where
250
      P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */
251
252
12.3k
    px = P;                      /* initialise ptrs       */
253
12.3k
    qx = Q;
254
12.3k
    p = px;
255
12.3k
    q = qx;
256
257
#ifdef FIXED_POINT
258
    *px++ = LPC_SCALING;
259
    *qx++ = LPC_SCALING;
260
    for(i=0;i<m;i++){
261
       *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++);
262
       *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++);
263
    }
264
    px = P;
265
    qx = Q;
266
    for(i=0;i<m;i++)
267
    {
268
       /*if (fabs(*px)>=32768)
269
          speex_warning_int("px", *px);
270
       if (fabs(*qx)>=32768)
271
       speex_warning_int("qx", *qx);*/
272
       *px = PSHR32(*px,2);
273
       *qx = PSHR32(*qx,2);
274
       px++;
275
       qx++;
276
    }
277
    /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */
278
    P[m] = PSHR32(P[m],3);
279
    Q[m] = PSHR32(Q[m],3);
280
#else
281
12.3k
    *px++ = LPC_SCALING;
282
12.3k
    *qx++ = LPC_SCALING;
283
70.5k
    for(i=0;i<m;i++){
284
58.1k
       *px++ = (a[i]+a[lpcrdr-1-i]) - *p++;
285
58.1k
       *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++;
286
58.1k
    }
287
12.3k
    px = P;
288
12.3k
    qx = Q;
289
70.5k
    for(i=0;i<m;i++){
290
58.1k
       *px = 2**px;
291
58.1k
       *qx = 2**qx;
292
58.1k
       px++;
293
58.1k
       qx++;
294
58.1k
    }
295
12.3k
#endif
296
297
12.3k
    px = P;               /* re-initialise ptrs       */
298
12.3k
    qx = Q;
299
300
    /* now that we have computed P and Q convert to 16 bits to
301
       speed up cheb_poly_eval */
302
303
12.3k
    ALLOC(P16, m+1, spx_word16_t);
304
12.3k
    ALLOC(Q16, m+1, spx_word16_t);
305
306
82.9k
    for (i=0;i<m+1;i++)
307
70.5k
    {
308
70.5k
       P16[i] = P[i];
309
70.5k
       Q16[i] = Q[i];
310
70.5k
    }
311
312
    /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z).
313
    Keep alternating between the two polynomials as each zero is found  */
314
315
12.3k
    xr = 0;               /* initialise xr to zero    */
316
12.3k
    xl = FREQ_SCALE;                 /* start at point xl = 1    */
317
318
128k
    for(j=0;j<lpcrdr;j++){
319
116k
  if(j&1)              /* determines whether P' or Q' is eval. */
320
58.1k
      pt = Q16;
321
58.1k
  else
322
58.1k
      pt = P16;
323
324
116k
  psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl  */
325
326
272k
  while(xr >= -FREQ_SCALE){
327
272k
           spx_word16_t dd;
328
           /* Modified by JMV to provide smaller steps around x=+-1 */
329
#ifdef FIXED_POINT
330
           dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000)));
331
           if (psuml<512 && psuml>-512)
332
              dd = PSHR16(dd,1);
333
#else
334
272k
           dd=delta*(1-.9*xl*xl);
335
272k
           if (fabs(psuml)<.2)
336
22.1k
              dd *= .5;
337
272k
#endif
338
272k
           xr = SUB16(xl, dd);                         /* interval spacing   */
339
272k
      psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x)  */
340
272k
      temp_psumr = psumr;
341
272k
      temp_xr = xr;
342
343
    /* if no sign change increment xr and re-evaluate poly(xr). Repeat til
344
    sign change.
345
    if a sign change has occurred the interval is bisected and then
346
    checked again for a sign change which determines in which
347
    interval the zero lies in.
348
    If there is no sign change between poly(xm) and poly(xl) set interval
349
    between xm and xr else set interval between xl and xr and repeat till
350
    root is located within the specified limits       */
351
352
272k
      if(SIGN_CHANGE(psumr,psuml))
353
116k
            {
354
116k
    roots++;
355
356
116k
    psumm=psuml;
357
1.39M
    for(k=0;k<=nb;k++){
358
#ifdef FIXED_POINT
359
        xm = ADD16(PSHR16(xl,1),PSHR16(xr,1));          /* bisect the interval  */
360
#else
361
1.27M
                    xm = .5*(xl+xr);          /* bisect the interval  */
362
1.27M
#endif
363
1.27M
        psumm=cheb_poly_eva(pt,xm,m,stack);
364
        /*if(psumm*psuml>0.)*/
365
1.27M
        if(!SIGN_CHANGE(psumm,psuml))
366
638k
                    {
367
638k
      psuml=psumm;
368
638k
      xl=xm;
369
640k
        } else {
370
640k
      psumr=psumm;
371
640k
      xr=xm;
372
640k
        }
373
1.27M
    }
374
375
         /* once zero is found, reset initial interval to xr  */
376
116k
         freq[j] = X2ANGLE(xm);
377
116k
         xl = xm;
378
116k
         break;
379
116k
      }
380
156k
      else{
381
156k
    psuml=temp_psumr;
382
156k
    xl=temp_xr;
383
156k
      }
384
272k
  }
385
116k
    }
386
12.3k
    return(roots);
387
12.3k
}
lpc_to_lsp
Line
Count
Source
228
26.9k
{
229
26.9k
    spx_word16_t temp_xr,xl,xr,xm=0;
230
26.9k
    spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/;
231
26.9k
    int i,j,m,k;
232
26.9k
    VARDECL(spx_word32_t *Q);                   /* ptrs for memory allocation     */
233
26.9k
    VARDECL(spx_word32_t *P);
234
26.9k
    VARDECL(spx_word16_t *Q16);         /* ptrs for memory allocation     */
235
26.9k
    VARDECL(spx_word16_t *P16);
236
26.9k
    spx_word32_t *px;                 /* ptrs of respective P'(z) & Q'(z) */
237
26.9k
    spx_word32_t *qx;
238
26.9k
    spx_word32_t *p;
239
26.9k
    spx_word32_t *q;
240
26.9k
    spx_word16_t *pt;                 /* ptr used for cheb_poly_eval()
241
        whether P' or Q'      */
242
26.9k
    int roots=0;                /* DR 8/2/94: number of roots found   */
243
26.9k
    m = lpcrdr/2;             /* order of P'(z) & Q'(z) polynomials   */
244
245
    /* Allocate memory space for polynomials */
246
26.9k
    ALLOC(Q, (m+1), spx_word32_t);
247
26.9k
    ALLOC(P, (m+1), spx_word32_t);
248
249
    /* determine P'(z)'s and Q'(z)'s coefficients where
250
      P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */
251
252
26.9k
    px = P;                      /* initialise ptrs       */
253
26.9k
    qx = Q;
254
26.9k
    p = px;
255
26.9k
    q = qx;
256
257
26.9k
#ifdef FIXED_POINT
258
26.9k
    *px++ = LPC_SCALING;
259
26.9k
    *qx++ = LPC_SCALING;
260
154k
    for(i=0;i<m;i++){
261
127k
       *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++);
262
127k
       *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++);
263
127k
    }
264
26.9k
    px = P;
265
26.9k
    qx = Q;
266
154k
    for(i=0;i<m;i++)
267
127k
    {
268
       /*if (fabs(*px)>=32768)
269
          speex_warning_int("px", *px);
270
       if (fabs(*qx)>=32768)
271
       speex_warning_int("qx", *qx);*/
272
127k
       *px = PSHR32(*px,2);
273
127k
       *qx = PSHR32(*qx,2);
274
127k
       px++;
275
127k
       qx++;
276
127k
    }
277
    /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */
278
26.9k
    P[m] = PSHR32(P[m],3);
279
26.9k
    Q[m] = PSHR32(Q[m],3);
280
#else
281
    *px++ = LPC_SCALING;
282
    *qx++ = LPC_SCALING;
283
    for(i=0;i<m;i++){
284
       *px++ = (a[i]+a[lpcrdr-1-i]) - *p++;
285
       *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++;
286
    }
287
    px = P;
288
    qx = Q;
289
    for(i=0;i<m;i++){
290
       *px = 2**px;
291
       *qx = 2**qx;
292
       px++;
293
       qx++;
294
    }
295
#endif
296
297
26.9k
    px = P;               /* re-initialise ptrs       */
298
26.9k
    qx = Q;
299
300
    /* now that we have computed P and Q convert to 16 bits to
301
       speed up cheb_poly_eval */
302
303
26.9k
    ALLOC(P16, m+1, spx_word16_t);
304
26.9k
    ALLOC(Q16, m+1, spx_word16_t);
305
306
181k
    for (i=0;i<m+1;i++)
307
154k
    {
308
154k
       P16[i] = P[i];
309
154k
       Q16[i] = Q[i];
310
154k
    }
311
312
    /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z).
313
    Keep alternating between the two polynomials as each zero is found  */
314
315
26.9k
    xr = 0;               /* initialise xr to zero    */
316
26.9k
    xl = FREQ_SCALE;                 /* start at point xl = 1    */
317
318
282k
    for(j=0;j<lpcrdr;j++){
319
255k
  if(j&1)              /* determines whether P' or Q' is eval. */
320
127k
      pt = Q16;
321
127k
  else
322
127k
      pt = P16;
323
324
255k
  psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl  */
325
326
593k
  while(xr >= -FREQ_SCALE){
327
592k
           spx_word16_t dd;
328
           /* Modified by JMV to provide smaller steps around x=+-1 */
329
592k
#ifdef FIXED_POINT
330
592k
           dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000)));
331
592k
           if (psuml<512 && psuml>-512)
332
111k
              dd = PSHR16(dd,1);
333
#else
334
           dd=delta*(1-.9*xl*xl);
335
           if (fabs(psuml)<.2)
336
              dd *= .5;
337
#endif
338
592k
           xr = SUB16(xl, dd);                         /* interval spacing   */
339
592k
      psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x)  */
340
592k
      temp_psumr = psumr;
341
592k
      temp_xr = xr;
342
343
    /* if no sign change increment xr and re-evaluate poly(xr). Repeat til
344
    sign change.
345
    if a sign change has occurred the interval is bisected and then
346
    checked again for a sign change which determines in which
347
    interval the zero lies in.
348
    If there is no sign change between poly(xm) and poly(xl) set interval
349
    between xm and xr else set interval between xl and xr and repeat till
350
    root is located within the specified limits       */
351
352
592k
      if(SIGN_CHANGE(psumr,psuml))
353
254k
            {
354
254k
    roots++;
355
356
254k
    psumm=psuml;
357
3.05M
    for(k=0;k<=nb;k++){
358
2.79M
#ifdef FIXED_POINT
359
2.79M
        xm = ADD16(PSHR16(xl,1),PSHR16(xr,1));          /* bisect the interval  */
360
#else
361
                    xm = .5*(xl+xr);          /* bisect the interval  */
362
#endif
363
2.79M
        psumm=cheb_poly_eva(pt,xm,m,stack);
364
        /*if(psumm*psuml>0.)*/
365
2.79M
        if(!SIGN_CHANGE(psumm,psuml))
366
1.50M
                    {
367
1.50M
      psuml=psumm;
368
1.50M
      xl=xm;
369
1.50M
        } else {
370
1.29M
      psumr=psumm;
371
1.29M
      xr=xm;
372
1.29M
        }
373
2.79M
    }
374
375
         /* once zero is found, reset initial interval to xr  */
376
254k
         freq[j] = X2ANGLE(xm);
377
254k
         xl = xm;
378
254k
         break;
379
254k
      }
380
337k
      else{
381
337k
    psuml=temp_psumr;
382
337k
    xl=temp_xr;
383
337k
      }
384
592k
  }
385
255k
    }
386
26.9k
    return(roots);
387
26.9k
}
388
389
#endif /* DISABLE_ENCODER */
390
/*---------------------------------------------------------------------------*\
391
392
  FUNCTION....: lsp_to_lpc()
393
394
  AUTHOR......: David Rowe
395
  DATE CREATED: 24/2/93
396
397
        Converts LSP coefficients to LPC coefficients.
398
399
\*---------------------------------------------------------------------------*/
400
401
#ifdef FIXED_POINT
402
403
void lsp_to_lpc(const spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
404
/*  float *freq   array of LSP frequencies in the x domain  */
405
/*  float *ak     array of LPC coefficients       */
406
/*  int lpcrdr    order of LPC coefficients       */
407
291k
{
408
291k
    int i,j;
409
291k
    spx_word32_t xout1,xout2,xin;
410
291k
    spx_word32_t mult, a;
411
291k
    VARDECL(spx_word16_t *freqn);
412
291k
    VARDECL(spx_word32_t **xp);
413
291k
    VARDECL(spx_word32_t *xpmem);
414
291k
    VARDECL(spx_word32_t **xq);
415
291k
    VARDECL(spx_word32_t *xqmem);
416
291k
    int m = lpcrdr>>1;
417
418
    /*
419
420
       Reconstruct P(z) and Q(z) by cascading second order polynomials
421
       in form 1 - 2cos(w)z(-1) + z(-2), where w is the LSP frequency.
422
       In the time domain this is:
423
424
       y(n) = x(n) - 2cos(w)x(n-1) + x(n-2)
425
426
       This is what the ALLOCS below are trying to do:
427
428
         int xp[m+1][lpcrdr+1+2]; // P matrix in QIMP
429
         int xq[m+1][lpcrdr+1+2]; // Q matrix in QIMP
430
431
       These matrices store the output of each stage on each row.  The
432
       final (m-th) row has the output of the final (m-th) cascaded
433
       2nd order filter.  The first row is the impulse input to the
434
       system (not written as it is known).
435
436
       The version below takes advantage of the fact that a lot of the
437
       outputs are zero or known, for example if we put an inpulse
438
       into the first section the "clock" it 10 times only the first 3
439
       outputs samples are non-zero (it's an FIR filter).
440
    */
441
442
291k
    ALLOC(xp, (m+1), spx_word32_t*);
443
291k
    ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t);
444
445
291k
    ALLOC(xq, (m+1), spx_word32_t*);
446
291k
    ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t);
447
448
1.97M
    for(i=0; i<=m; i++) {
449
1.68M
      xp[i] = xpmem + i*(lpcrdr+1+2);
450
1.68M
      xq[i] = xqmem + i*(lpcrdr+1+2);
451
1.68M
    }
452
453
    /* work out 2cos terms in Q14 */
454
455
291k
    ALLOC(freqn, lpcrdr, spx_word16_t);
456
3.08M
    for (i=0;i<lpcrdr;i++)
457
2.78M
       freqn[i] = ANGLE2X(freq[i]);
458
459
2.78M
    #define QIMP  21   /* scaling for impulse */
460
461
291k
    xin = SHL32(EXTEND32(1), (QIMP-1)); /* 0.5 in QIMP format */
462
463
    /* first col and last non-zero values of each row are trivial */
464
465
1.97M
    for(i=0;i<=m;i++) {
466
1.68M
     xp[i][1] = 0;
467
1.68M
     xp[i][2] = xin;
468
1.68M
     xp[i][2+2*i] = xin;
469
1.68M
     xq[i][1] = 0;
470
1.68M
     xq[i][2] = xin;
471
1.68M
     xq[i][2+2*i] = xin;
472
1.68M
    }
473
474
    /* 2nd row (first output row) is trivial */
475
476
291k
    xp[1][3] = -MULT16_32_Q14(freqn[0],xp[0][2]);
477
291k
    xq[1][3] = -MULT16_32_Q14(freqn[1],xq[0][2]);
478
479
291k
    xout1 = xout2 = 0;
480
481
    /* now generate remaining rows */
482
483
1.39M
    for(i=1;i<m;i++) {
484
485
6.41M
      for(j=1;j<2*(i+1)-1;j++) {
486
5.31M
  mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
487
5.31M
  xp[i+1][j+2] = ADD32(SUB32(xp[i][j+2], mult), xp[i][j]);
488
5.31M
  mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
489
5.31M
  xq[i+1][j+2] = ADD32(SUB32(xq[i][j+2], mult), xq[i][j]);
490
5.31M
      }
491
492
      /* for last col xp[i][j+2] = xq[i][j+2] = 0 */
493
494
1.10M
      mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
495
1.10M
      xp[i+1][j+2] = SUB32(xp[i][j], mult);
496
1.10M
      mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
497
1.10M
      xq[i+1][j+2] = SUB32(xq[i][j], mult);
498
1.10M
    }
499
500
    /* process last row to extra a{k} */
501
502
3.08M
    for(j=1;j<=lpcrdr;j++) {
503
2.78M
      int shift = QIMP-13;
504
505
      /* final filter sections */
506
2.78M
      a = PSHR32(xp[m][j+2] + xout1 + xq[m][j+2] - xout2, shift);
507
2.78M
      xout1 = xp[m][j+2];
508
2.78M
      xout2 = xq[m][j+2];
509
510
      /* hard limit ak's to +/- 32767 */
511
512
2.78M
      if (a < -32767) a = -32767;
513
2.78M
      if (a > 32767) a = 32767;
514
2.78M
      ak[j-1] = (short)a;
515
516
2.78M
    }
517
518
291k
}
519
520
#else
521
522
void lsp_to_lpc(const spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
523
/*  float *freq   array of LSP frequencies in the x domain  */
524
/*  float *ak     array of LPC coefficients       */
525
/*  int lpcrdr    order of LPC coefficients       */
526
527
528
152k
{
529
152k
    int i,j;
530
152k
    float xout1,xout2,xin1,xin2;
531
152k
    VARDECL(float *Wp);
532
152k
    float *pw,*n1,*n2,*n3,*n4=NULL;
533
152k
    VARDECL(float *x_freq);
534
152k
    int m = lpcrdr>>1;
535
536
152k
    ALLOC(Wp, 4*m+2, float);
537
152k
    pw = Wp;
538
539
    /* initialise contents of array */
540
541
3.35M
    for(i=0;i<=4*m+1;i++){         /* set contents of buffer to 0 */
542
3.20M
  *pw++ = 0.0;
543
3.20M
    }
544
545
    /* Set pointers up */
546
547
152k
    pw = Wp;
548
152k
    xin1 = 1.0;
549
152k
    xin2 = 1.0;
550
551
152k
    ALLOC(x_freq, lpcrdr, float);
552
1.60M
    for (i=0;i<lpcrdr;i++)
553
1.45M
       x_freq[i] = ANGLE2X(freq[i]);
554
555
    /* reconstruct P(z) and Q(z) by  cascading second order
556
      polynomials in form 1 - 2xz(-1) +z(-2), where x is the
557
      LSP coefficient */
558
559
1.75M
    for(j=0;j<=lpcrdr;j++){
560
1.60M
       int i2=0;
561
9.28M
  for(i=0;i<m;i++,i2+=2){
562
7.67M
      n1 = pw+(i*4);
563
7.67M
      n2 = n1 + 1;
564
7.67M
      n3 = n2 + 1;
565
7.67M
      n4 = n3 + 1;
566
7.67M
      xout1 = xin1 - 2.f*x_freq[i2] * *n1 + *n2;
567
7.67M
      xout2 = xin2 - 2.f*x_freq[i2+1] * *n3 + *n4;
568
7.67M
      *n2 = *n1;
569
7.67M
      *n4 = *n3;
570
7.67M
      *n1 = xin1;
571
7.67M
      *n3 = xin2;
572
7.67M
      xin1 = xout1;
573
7.67M
      xin2 = xout2;
574
7.67M
  }
575
1.60M
  xout1 = xin1 + *(n4+1);
576
1.60M
  xout2 = xin2 - *(n4+2);
577
1.60M
  if (j>0)
578
1.45M
     ak[j-1] = (xout1 + xout2)*0.5f;
579
1.60M
  *(n4+1) = xin1;
580
1.60M
  *(n4+2) = xin2;
581
582
1.60M
  xin1 = 0.0;
583
1.60M
  xin2 = 0.0;
584
1.60M
    }
585
586
152k
}
587
#endif
588
589
590
#ifdef FIXED_POINT
591
592
593
void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *lsp, int len, int subframe, int nb_subframes, spx_word16_t margin)
594
438k
{
595
438k
   int i;
596
438k
   spx_word16_t m = margin;
597
438k
   spx_word16_t m2 = 25736-margin;
598
438k
   spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes);
599
438k
   spx_word16_t tmp2 = 16384-tmp;
600
4.61M
   for (i=0;i<len;i++)
601
4.18M
      lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]);
602
   /* Enforce margin to sure the LSPs are stable*/
603
438k
   if (lsp[0]<m)
604
679
      lsp[0]=m;
605
438k
   if (lsp[len-1]>m2)
606
646
      lsp[len-1]=m2;
607
3.74M
   for (i=1;i<len-1;i++)
608
3.30M
   {
609
3.30M
      if (lsp[i]<lsp[i-1]+m)
610
7.98k
         lsp[i]=lsp[i-1]+m;
611
612
3.30M
      if (lsp[i]>lsp[i+1]-m)
613
8.42k
         lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1);
614
3.30M
   }
615
438k
}
616
617
#else
618
619
620
void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *lsp, int len, int subframe, int nb_subframes, spx_word16_t margin)
621
438k
{
622
438k
   int i;
623
438k
   float tmp = (1.0f + subframe)/nb_subframes;
624
4.61M
   for (i=0;i<len;i++)
625
4.18M
      lsp[i] = (1-tmp)*old_lsp[i] + tmp*new_lsp[i];
626
   /* Enforce margin to sure the LSPs are stable*/
627
438k
   if (lsp[0]<LSP_SCALING*margin)
628
679
      lsp[0]=LSP_SCALING*margin;
629
438k
   if (lsp[len-1]>LSP_SCALING*(M_PI-margin))
630
646
      lsp[len-1]=LSP_SCALING*(M_PI-margin);
631
3.74M
   for (i=1;i<len-1;i++)
632
3.30M
   {
633
3.30M
      if (lsp[i]<lsp[i-1]+LSP_SCALING*margin)
634
7.98k
         lsp[i]=lsp[i-1]+LSP_SCALING*margin;
635
636
3.30M
      if (lsp[i]>lsp[i+1]-LSP_SCALING*margin)
637
8.42k
         lsp[i]= .5f* (lsp[i] + lsp[i+1]-LSP_SCALING*margin);
638
3.30M
   }
639
438k
}
640
641
#endif