Coverage Report

Created: 2026-06-15 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pjsip/third_party/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
#define NULL 0
97
#endif
98
99
#ifdef FIXED_POINT
100
101
#define FREQ_SCALE 16384
102
103
/*#define ANGLE2X(a) (32768*cos(((a)/8192.)))*/
104
#define ANGLE2X(a) (SHL16(spx_cos(a),2))
105
106
/*#define X2ANGLE(x) (acos(.00006103515625*(x))*LSP_SCALING)*/
107
#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
29.6k
#define FREQ_SCALE 1.
120
106k
#define ANGLE2X(a) (spx_cos(a))
121
12.4k
#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
{
148
    int i;
149
    spx_word16_t b0, b1;
150
    spx_word32_t sum;
151
152
    /*Prevents overflows*/
153
    if (x>16383)
154
       x = 16383;
155
    if (x<-16383)
156
       x = -16383;
157
158
    /* Initialise values */
159
    b1=16384;
160
    b0=x;
161
162
    /* Evaluate Chebyshev series formulation using an iterative approach  */
163
    sum = ADD32(EXTEND32(coef[m]), EXTEND32(MULT16_16_P14(coef[m-1],x)));
164
    for(i=2;i<=m;i++)
165
    {
166
       spx_word16_t tmp=b0;
167
       b0 = SUB16(MULT16_16_Q13(x,b0), b1);
168
       b1 = tmp;
169
       sum = ADD32(sum, EXTEND32(MULT16_16_P14(coef[m-i],b0)));
170
    }
171
172
    return sum;
173
}
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
177k
{
180
177k
   int k;
181
177k
   float b0, b1, tmp;
182
183
   /* Initial conditions */
184
177k
   b0=0; /* b_(m+1) */
185
177k
   b1=0; /* b_(m+2) */
186
187
177k
   x*=2;
188
189
   /* Calculate the b_(k) */
190
1.06M
   for(k=m;k>0;k--)
191
888k
   {
192
888k
      tmp=b0;                           /* tmp holds the previous value of b0 */
193
888k
      b0=x*b0-b1+coef[m-k];    /* b0 holds its new value based on b0 and b1 */
194
888k
      b1=tmp;                           /* b1 holds the previous value of b0 */
195
888k
   }
196
197
177k
   return(-b1+.5*x*b0+coef[m]);
198
177k
}
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
#define SIGN_CHANGE(a,b) ((((a)^(b))&0x80000000)||(b==0))
215
#else
216
165k
#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
1.24k
{
229
1.24k
    spx_word16_t temp_xr,xl,xr,xm=0;
230
1.24k
    spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/;
231
1.24k
    int i,j,m,k;
232
1.24k
    VARDECL(spx_word32_t *Q);                  /* ptrs for memory allocation     */
233
1.24k
    VARDECL(spx_word32_t *P);
234
1.24k
    VARDECL(spx_word16_t *Q16);         /* ptrs for memory allocation    */
235
1.24k
    VARDECL(spx_word16_t *P16);
236
1.24k
    spx_word32_t *px;                 /* ptrs of respective P'(z) & Q'(z) */
237
1.24k
    spx_word32_t *qx;
238
1.24k
    spx_word32_t *p;
239
1.24k
    spx_word32_t *q;
240
1.24k
    spx_word16_t *pt;                 /* ptr used for cheb_poly_eval()
241
        whether P' or Q'      */
242
1.24k
    int roots=0;                /* DR 8/2/94: number of roots found   */
243
1.24k
    m = lpcrdr/2;             /* order of P'(z) & Q'(z) polynomials   */
244
245
    /* Allocate memory space for polynomials */
246
1.24k
    ALLOC(Q, (m+1), spx_word32_t);
247
1.24k
    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
1.24k
    px = P;                      /* initialise ptrs       */
253
1.24k
    qx = Q;
254
1.24k
    p = px;
255
1.24k
    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
1.24k
    *px++ = LPC_SCALING;
282
1.24k
    *qx++ = LPC_SCALING;
283
7.47k
    for(i=0;i<m;i++){
284
6.22k
       *px++ = (a[i]+a[lpcrdr-1-i]) - *p++;
285
6.22k
       *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++;
286
6.22k
    }
287
1.24k
    px = P;
288
1.24k
    qx = Q;
289
7.47k
    for(i=0;i<m;i++){
290
6.22k
       *px = 2**px;
291
6.22k
       *qx = 2**qx;
292
6.22k
       px++;
293
6.22k
       qx++;
294
6.22k
    }
295
1.24k
#endif
296
297
1.24k
    px = P;               /* re-initialise ptrs       */
298
1.24k
    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
1.24k
    ALLOC(P16, m+1, spx_word16_t);
304
1.24k
    ALLOC(Q16, m+1, spx_word16_t);
305
306
8.71k
    for (i=0;i<m+1;i++)
307
7.47k
    {
308
7.47k
       P16[i] = P[i];
309
7.47k
       Q16[i] = Q[i];
310
7.47k
    }
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
1.24k
    xr = 0;               /* initialise xr to zero    */
316
1.24k
    xl = FREQ_SCALE;                 /* start at point xl = 1    */
317
318
13.6k
    for(j=0;j<lpcrdr;j++){
319
12.4k
  if(j&1)              /* determines whether P' or Q' is eval. */
320
6.22k
      pt = Q16;
321
6.22k
  else
322
6.22k
      pt = P16;
323
324
12.4k
  psuml = cheb_poly_eva(pt,xl,m,stack); /* evals poly. at xl  */
325
326
28.3k
  while(xr >= -FREQ_SCALE){
327
28.3k
           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
28.3k
           dd=delta*(1-.9*xl*xl);
335
28.3k
           if (fabs(psuml)<.2)
336
3.21k
              dd *= .5;
337
28.3k
#endif
338
28.3k
           xr = SUB16(xl, dd);                         /* interval spacing   */
339
28.3k
      psumr = cheb_poly_eva(pt,xr,m,stack);/* poly(xl-delta_x)  */
340
28.3k
      temp_psumr = psumr;
341
28.3k
      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
28.3k
      if(SIGN_CHANGE(psumr,psuml))
353
12.4k
            {
354
12.4k
    roots++;
355
356
12.4k
    psumm=psuml;
357
149k
    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
136k
                    xm = .5*(xl+xr);          /* bisect the interval  */
362
136k
#endif
363
136k
        psumm=cheb_poly_eva(pt,xm,m,stack);
364
        /*if(psumm*psuml>0.)*/
365
136k
        if(!SIGN_CHANGE(psumm,psuml))
366
69.5k
                    {
367
69.5k
      psuml=psumm;
368
69.5k
      xl=xm;
369
69.5k
        } else {
370
67.4k
      psumr=psumm;
371
67.4k
      xr=xm;
372
67.4k
        }
373
136k
    }
374
375
         /* once zero is found, reset initial interval to xr  */
376
12.4k
         freq[j] = X2ANGLE(xm);
377
12.4k
         xl = xm;
378
12.4k
         break;
379
12.4k
      }
380
15.9k
      else{
381
15.9k
    psuml=temp_psumr;
382
15.9k
    xl=temp_xr;
383
15.9k
      }
384
28.3k
  }
385
12.4k
    }
386
1.24k
    return(roots);
387
1.24k
}
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
{
408
    int i,j;
409
    spx_word32_t xout1,xout2,xin;
410
    spx_word32_t mult, a;
411
    VARDECL(spx_word16_t *freqn);
412
    VARDECL(spx_word32_t **xp);
413
    VARDECL(spx_word32_t *xpmem);
414
    VARDECL(spx_word32_t **xq);
415
    VARDECL(spx_word32_t *xqmem);
416
    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
    ALLOC(xp, (m+1), spx_word32_t*);
443
    ALLOC(xpmem, (m+1)*(lpcrdr+1+2), spx_word32_t);
444
445
    ALLOC(xq, (m+1), spx_word32_t*);
446
    ALLOC(xqmem, (m+1)*(lpcrdr+1+2), spx_word32_t);
447
448
    for(i=0; i<=m; i++) {
449
      xp[i] = xpmem + i*(lpcrdr+1+2);
450
      xq[i] = xqmem + i*(lpcrdr+1+2);
451
    }
452
453
    /* work out 2cos terms in Q14 */
454
455
    ALLOC(freqn, lpcrdr, spx_word16_t);
456
    for (i=0;i<lpcrdr;i++)
457
       freqn[i] = ANGLE2X(freq[i]);
458
459
    #define QIMP  21   /* scaling for impulse */
460
461
    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
    for(i=0;i<=m;i++) {
466
     xp[i][1] = 0;
467
     xp[i][2] = xin;
468
     xp[i][2+2*i] = xin;
469
     xq[i][1] = 0;
470
     xq[i][2] = xin;
471
     xq[i][2+2*i] = xin;
472
    }
473
474
    /* 2nd row (first output row) is trivial */
475
476
    xp[1][3] = -MULT16_32_Q14(freqn[0],xp[0][2]);
477
    xq[1][3] = -MULT16_32_Q14(freqn[1],xq[0][2]);
478
479
    xout1 = xout2 = 0;
480
481
    /* now generate remaining rows */
482
483
    for(i=1;i<m;i++) {
484
485
      for(j=1;j<2*(i+1)-1;j++) {
486
  mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
487
  xp[i+1][j+2] = ADD32(SUB32(xp[i][j+2], mult), xp[i][j]);
488
  mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
489
  xq[i+1][j+2] = ADD32(SUB32(xq[i][j+2], mult), xq[i][j]);
490
      }
491
492
      /* for last col xp[i][j+2] = xq[i][j+2] = 0 */
493
494
      mult = MULT16_32_Q14(freqn[2*i],xp[i][j+1]);
495
      xp[i+1][j+2] = SUB32(xp[i][j], mult);
496
      mult = MULT16_32_Q14(freqn[2*i+1],xq[i][j+1]);
497
      xq[i+1][j+2] = SUB32(xq[i][j], mult);
498
    }
499
500
    /* process last row to extra a{k} */
501
502
    for(j=1;j<=lpcrdr;j++) {
503
      int shift = QIMP-13;
504
505
      /* final filter sections */
506
      a = PSHR32(xp[m][j+2] + xout1 + xq[m][j+2] - xout2, shift);
507
      xout1 = xp[m][j+2];
508
      xout2 = xq[m][j+2];
509
510
      /* hard limit ak's to +/- 32767 */
511
512
      if (a < -32767) a = -32767;
513
      if (a > 32767) a = 32767;
514
      ak[j-1] = (short)a;
515
516
    }
517
518
}
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
10.6k
{
529
10.6k
    int i,j;
530
10.6k
    float xout1,xout2,xin1,xin2;
531
10.6k
    VARDECL(float *Wp);
532
10.6k
    float *pw,*n1,*n2,*n3,*n4=NULL;
533
10.6k
    VARDECL(float *x_freq);
534
10.6k
    int m = lpcrdr>>1;
535
536
10.6k
    ALLOC(Wp, 4*m+2, float);
537
10.6k
    pw = Wp;
538
539
    /* initialise contents of array */
540
541
244k
    for(i=0;i<=4*m+1;i++){         /* set contents of buffer to 0 */
542
233k
  *pw++ = 0.0;
543
233k
    }
544
545
    /* Set pointers up */
546
547
10.6k
    pw = Wp;
548
10.6k
    xin1 = 1.0;
549
10.6k
    xin2 = 1.0;
550
551
10.6k
    ALLOC(x_freq, lpcrdr, float);
552
116k
    for (i=0;i<lpcrdr;i++)
553
106k
       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
127k
    for(j=0;j<=lpcrdr;j++){
560
116k
       int i2=0;
561
700k
  for(i=0;i<m;i++,i2+=2){
562
583k
      n1 = pw+(i*4);
563
583k
      n2 = n1 + 1;
564
583k
      n3 = n2 + 1;
565
583k
      n4 = n3 + 1;
566
583k
      xout1 = xin1 - 2.f*x_freq[i2] * *n1 + *n2;
567
583k
      xout2 = xin2 - 2.f*x_freq[i2+1] * *n3 + *n4;
568
583k
      *n2 = *n1;
569
583k
      *n4 = *n3;
570
583k
      *n1 = xin1;
571
583k
      *n3 = xin2;
572
583k
      xin1 = xout1;
573
583k
      xin2 = xout2;
574
583k
  }
575
116k
  xout1 = xin1 + *(n4+1);
576
116k
  xout2 = xin2 - *(n4+2);
577
116k
  if (j>0)
578
106k
     ak[j-1] = (xout1 + xout2)*0.5f;
579
116k
  *(n4+1) = xin1;
580
116k
  *(n4+2) = xin2;
581
582
116k
  xin1 = 0.0;
583
116k
  xin2 = 0.0;
584
116k
    }
585
586
10.6k
}
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
{
595
   int i;
596
   spx_word16_t m = margin;
597
   spx_word16_t m2 = 25736-margin;
598
   spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes);
599
   spx_word16_t tmp2 = 16384-tmp;
600
   for (i=0;i<len;i++)
601
      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
   if (lsp[0]<m)
604
      lsp[0]=m;
605
   if (lsp[len-1]>m2)
606
      lsp[len-1]=m2;
607
   for (i=1;i<len-1;i++)
608
   {
609
      if (lsp[i]<lsp[i-1]+m)
610
         lsp[i]=lsp[i-1]+m;
611
612
      if (lsp[i]>lsp[i+1]-m)
613
         lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1);
614
   }
615
}
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
10.3k
{
622
10.3k
   int i;
623
10.3k
   float tmp = (1.0f + subframe)/nb_subframes;
624
114k
   for (i=0;i<len;i++)
625
103k
      lsp[i] = (1-tmp)*old_lsp[i] + tmp*new_lsp[i];
626
   /* Enforce margin to sure the LSPs are stable*/
627
10.3k
   if (lsp[0]<LSP_SCALING*margin)
628
8
      lsp[0]=LSP_SCALING*margin;
629
10.3k
   if (lsp[len-1]>LSP_SCALING*(M_PI-margin))
630
0
      lsp[len-1]=LSP_SCALING*(M_PI-margin);
631
93.5k
   for (i=1;i<len-1;i++)
632
83.1k
   {
633
83.1k
      if (lsp[i]<lsp[i-1]+LSP_SCALING*margin)
634
113
         lsp[i]=lsp[i-1]+LSP_SCALING*margin;
635
636
83.1k
      if (lsp[i]>lsp[i+1]-LSP_SCALING*margin)
637
113
         lsp[i]= .5f* (lsp[i] + lsp[i+1]-LSP_SCALING*margin);
638
83.1k
   }
639
10.3k
}
640
641
#endif