lsp.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:16k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*---------------------------------------------------------------------------*
  2. Original copyright
  3. FILE........: AKSLSPD.C
  4. TYPE........: Turbo C
  5. COMPANY.....: Voicetronix
  6. AUTHOR......: David Rowe
  7. DATE CREATED: 24/2/93
  8. Heavily modified by Jean-Marc Valin (fixed-point, optimizations, 
  9.                                      additional functions, ...)
  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.    Speex License:
  15.    Redistribution and use in source and binary forms, with or without
  16.    modification, are permitted provided that the following conditions
  17.    are met:
  18.    
  19.    - Redistributions of source code must retain the above copyright
  20.    notice, this list of conditions and the following disclaimer.
  21.    
  22.    - Redistributions in binary form must reproduce the above copyright
  23.    notice, this list of conditions and the following disclaimer in the
  24.    documentation and/or other materials provided with the distribution.
  25.    
  26.    - Neither the name of the Xiph.org Foundation nor the names of its
  27.    contributors may be used to endorse or promote products derived from
  28.    this software without specific prior written permission.
  29.    
  30.    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31.    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32.    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  33.    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
  34.    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  35.    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  36.    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  37.    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  38.    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  39.    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  40.    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41. */
  42. #ifdef HAVE_CONFIG_H
  43. #include "config.h"
  44. #endif
  45. #include <math.h>
  46. #include "lsp.h"
  47. #include "stack_alloc.h"
  48. #include "math_approx.h"
  49. #ifndef M_PI
  50. #define M_PI           3.14159265358979323846  /* pi */
  51. #endif
  52. #ifndef NULL
  53. #define NULL 0
  54. #endif
  55. #ifdef FIXED_POINT
  56. #define C1 8192
  57. #define C2 -4096
  58. #define C3 340
  59. #define C4 -10
  60. static spx_word16_t spx_cos(spx_word16_t x)
  61. {
  62.    spx_word16_t x2;
  63.    if (x<12868)
  64.    {
  65.       x2 = MULT16_16_P13(x,x);
  66.       return ADD32(C1, MULT16_16_P13(x2, ADD32(C2, MULT16_16_P13(x2, ADD32(C3, MULT16_16_P13(C4, x2))))));
  67.    } else {
  68.       x = SUB16(25736,x);
  69.       x2 = MULT16_16_P13(x,x);
  70.       return SUB32(-C1, MULT16_16_P13(x2, ADD32(C2, MULT16_16_P13(x2, ADD32(C3, MULT16_16_P13(C4, x2))))));
  71.       /*return SUB32(-C1, MULT16_16_Q13(x2, ADD32(C2, MULT16_16_Q13(C3, x2))));*/
  72.    }
  73. }
  74. #define FREQ_SCALE 16384
  75. /*#define ANGLE2X(a) (32768*cos(((a)/8192.)))*/
  76. #define ANGLE2X(a) (SHL16(spx_cos(a),2))
  77. /*#define X2ANGLE(x) (acos(.00006103515625*(x))*LSP_SCALING)*/
  78. #define X2ANGLE(x) (spx_acos(x))
  79. #else
  80. /*#define C1 0.99940307
  81. #define C2 -0.49558072
  82. #define C3 0.03679168*/
  83. #define C1 0.9999932946f
  84. #define C2 -0.4999124376f
  85. #define C3 0.0414877472f
  86. #define C4 -0.0012712095f
  87. #define SPX_PI_2 1.5707963268
  88. static inline spx_word16_t spx_cos(spx_word16_t x)
  89. {
  90.    if (x<SPX_PI_2)
  91.    {
  92.       x *= x;
  93.       return C1 + x*(C2+x*(C3+C4*x));
  94.    } else {
  95.       x = M_PI-x;
  96.       x *= x;
  97.       return NEG16(C1 + x*(C2+x*(C3+C4*x)));
  98.    }
  99. }
  100. #define FREQ_SCALE 1.
  101. #define ANGLE2X(a) (spx_cos(a))
  102. #define X2ANGLE(x) (acos(x))
  103. #endif
  104. /*---------------------------------------------------------------------------*
  105. FUNCTION....: cheb_poly_eva()
  106. AUTHOR......: David Rowe
  107. DATE CREATED: 24/2/93
  108.     This function evaluates a series of Chebyshev polynomials
  109. *---------------------------------------------------------------------------*/
  110. #ifdef FIXED_POINT
  111. static inline spx_word32_t cheb_poly_eva(spx_word32_t *coef,spx_word16_t x,int m,char *stack)
  112. /*  float coef[]   coefficients of the polynomial to be evaluated  */
  113. /*  float x    the point where polynomial is to be evaluated  */
  114. /*  int m  order of the polynomial  */
  115. {
  116.     int i;
  117.     VARDECL(spx_word16_t *T);
  118.     spx_word32_t sum;
  119.     int m2=m>>1;
  120.     VARDECL(spx_word16_t *coefn);
  121.     /*Prevents overflows*/
  122.     if (x>16383)
  123.        x = 16383;
  124.     if (x<-16383)
  125.        x = -16383;
  126.     /* Allocate memory for Chebyshev series formulation */
  127.     ALLOC(T, m2+1, spx_word16_t);
  128.     ALLOC(coefn, m2+1, spx_word16_t);
  129.     for (i=0;i<m2+1;i++)
  130.     {
  131.        coefn[i] = coef[i];
  132.        /*printf ("%f ", coef[i]);*/
  133.     }
  134.     /*printf ("n");*/
  135.     /* Initialise values */
  136.     T[0]=16384;
  137.     T[1]=x;
  138.     /* Evaluate Chebyshev series formulation using iterative approach  */
  139.     /* Evaluate polynomial and return value also free memory space */
  140.     sum = ADD32(EXTEND32(coefn[m2]), EXTEND32(MULT16_16_P14(coefn[m2-1],x)));
  141.     /*x *= 2;*/
  142.     for(i=2;i<=m2;i++)
  143.     {
  144.        T[i] = SUB16(MULT16_16_Q13(x,T[i-1]), T[i-2]);
  145.        sum = ADD32(sum, EXTEND32(MULT16_16_P14(coefn[m2-i],T[i])));
  146.        /*printf ("%f ", sum);*/
  147.     }
  148.     
  149.     /*printf ("n");*/
  150.     return sum;
  151. }
  152. #else
  153. static float cheb_poly_eva(spx_word32_t *coef,float x,int m,char *stack)
  154. /*  float coef[]   coefficients of the polynomial to be evaluated  */
  155. /*  float x    the point where polynomial is to be evaluated  */
  156. /*  int m  order of the polynomial  */
  157. {
  158.     int i;
  159.     VARDECL(float *T);
  160.     float sum;
  161.     int m2=m>>1;
  162.     /* Allocate memory for Chebyshev series formulation */
  163.     ALLOC(T, m2+1, float);
  164.     /* Initialise values */
  165.     T[0]=1;
  166.     T[1]=x;
  167.     /* Evaluate Chebyshev series formulation using iterative approach  */
  168.     /* Evaluate polynomial and return value also free memory space */
  169.     sum = coef[m2] + coef[m2-1]*x;
  170.     x *= 2;
  171.     for(i=2;i<=m2;i++)
  172.     {
  173.        T[i] = x*T[i-1] - T[i-2];
  174.        sum += coef[m2-i] * T[i];
  175.     }
  176.     
  177.     return sum;
  178. }
  179. #endif
  180. /*---------------------------------------------------------------------------*
  181. FUNCTION....: lpc_to_lsp()
  182. AUTHOR......: David Rowe
  183. DATE CREATED: 24/2/93
  184.     This function converts LPC coefficients to LSP
  185.     coefficients.
  186. *---------------------------------------------------------------------------*/
  187. #ifdef FIXED_POINT
  188. #define SIGN_CHANGE(a,b) (((a)&0x70000000)^((b)&0x70000000)||(b==0))
  189. #else
  190. #define SIGN_CHANGE(a,b) (((a)*(b))<0.0)
  191. #endif
  192. int lpc_to_lsp (spx_coef_t *a,int lpcrdr,spx_lsp_t *freq,int nb,spx_word16_t delta, char *stack)
  193. /*  float *a        lpc coefficients */
  194. /*  int lpcrdr order of LPC coefficients (10)  */
  195. /*  float *freq         LSP frequencies in the x domain        */
  196. /*  int nb number of sub-intervals (4)  */
  197. /*  float delta grid spacing interval (0.02)  */
  198. {
  199.     spx_word16_t temp_xr,xl,xr,xm=0;
  200.     spx_word32_t psuml,psumr,psumm,temp_psumr/*,temp_qsumr*/;
  201.     int i,j,m,flag,k;
  202.     VARDECL(spx_word32_t *Q);                  /* ptrs for memory allocation  */
  203.     VARDECL(spx_word32_t *P);
  204.     spx_word32_t *px;                 /* ptrs of respective P'(z) & Q'(z) */
  205.     spx_word32_t *qx;
  206.     spx_word32_t *p;
  207.     spx_word32_t *q;
  208.     spx_word32_t *pt;                 /* ptr used for cheb_poly_eval()
  209. whether P' or Q'  */
  210.     int roots=0;               /* DR 8/2/94: number of roots found  */
  211.     flag = 1;                 /*  program is searching for a root when,
  212. 1 else has found one  */
  213.     m = lpcrdr/2;             /* order of P'(z) & Q'(z) polynomials  */
  214.     /* Allocate memory space for polynomials */
  215.     ALLOC(Q, (m+1), spx_word32_t);
  216.     ALLOC(P, (m+1), spx_word32_t);
  217.     /* determine P'(z)'s and Q'(z)'s coefficients where
  218.       P'(z) = P(z)/(1 + z^(-1)) and Q'(z) = Q(z)/(1-z^(-1)) */
  219.     px = P;                      /* initialise ptrs  */
  220.     qx = Q;
  221.     p = px;
  222.     q = qx;
  223. #ifdef FIXED_POINT
  224.     *px++ = LPC_SCALING;
  225.     *qx++ = LPC_SCALING;
  226.     for(i=0;i<m;i++){
  227.        *px++ = SUB32(ADD32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *p++);
  228.        *qx++ = ADD32(SUB32(EXTEND32(a[i]),EXTEND32(a[lpcrdr-i-1])), *q++);
  229.     }
  230.     px = P;
  231.     qx = Q;
  232.     for(i=0;i<m;i++)
  233.     {
  234.        /*if (fabs(*px)>=32768)
  235.           speex_warning_int("px", *px);
  236.        if (fabs(*qx)>=32768)
  237.        speex_warning_int("qx", *qx);*/
  238.        *px = PSHR32(*px,2);
  239.        *qx = PSHR32(*qx,2);
  240.        px++;
  241.        qx++;
  242.     }
  243.     /* The reason for this lies in the way cheb_poly_eva() is implemented for fixed-point */
  244.     P[m] = PSHR32(P[m],3);
  245.     Q[m] = PSHR32(Q[m],3);
  246. #else
  247.     *px++ = LPC_SCALING;
  248.     *qx++ = LPC_SCALING;
  249.     for(i=0;i<m;i++){
  250.        *px++ = (a[i]+a[lpcrdr-1-i]) - *p++;
  251.        *qx++ = (a[i]-a[lpcrdr-1-i]) + *q++;
  252.     }
  253.     px = P;
  254.     qx = Q;
  255.     for(i=0;i<m;i++){
  256.        *px = 2**px;
  257.        *qx = 2**qx;
  258.        px++;
  259.        qx++;
  260.     }
  261. #endif
  262.     px = P;              /* re-initialise ptrs  */
  263.     qx = Q;
  264.     /* Search for a zero in P'(z) polynomial first and then alternate to Q'(z).
  265.     Keep alternating between the two polynomials as each zero is found  */
  266.     xr = 0;              /* initialise xr to zero  */
  267.     xl = FREQ_SCALE;                /* start at point xl = 1  */
  268.     for(j=0;j<lpcrdr;j++){
  269. if(j&1)             /* determines whether P' or Q' is eval. */
  270.     pt = qx;
  271. else
  272.     pt = px;
  273. psuml = cheb_poly_eva(pt,xl,lpcrdr,stack); /* evals poly. at xl  */
  274. flag = 1;
  275. while(flag && (xr >= -FREQ_SCALE)){
  276.            spx_word16_t dd;
  277.            /* Modified by JMV to provide smaller steps around x=+-1 */
  278. #ifdef FIXED_POINT
  279.            dd = MULT16_16_Q15(delta,SUB16(FREQ_SCALE, MULT16_16_Q14(MULT16_16_Q14(xl,xl),14000)));
  280.            if (psuml<512 && psuml>-512)
  281.               dd = PSHR16(dd,1);
  282. #else
  283.            dd=delta*(1-.9*xl*xl);
  284.            if (fabs(psuml)<.2)
  285.               dd *= .5;
  286. #endif
  287.            xr = SUB16(xl, dd);                         /* interval spacing  */
  288.     psumr = cheb_poly_eva(pt,xr,lpcrdr,stack);/* poly(xl-delta_x)  */
  289.     temp_psumr = psumr;
  290.     temp_xr = xr;
  291.     /* if no sign change increment xr and re-evaluate poly(xr). Repeat til
  292.     sign change.
  293.     if a sign change has occurred the interval is bisected and then
  294.     checked again for a sign change which determines in which
  295.     interval the zero lies in.
  296.     If there is no sign change between poly(xm) and poly(xl) set interval
  297.     between xm and xr else set interval between xl and xr and repeat till
  298.     root is located within the specified limits  */
  299.     if(SIGN_CHANGE(psumr,psuml))
  300.             {
  301. roots++;
  302. psumm=psuml;
  303. for(k=0;k<=nb;k++){
  304. #ifdef FIXED_POINT
  305.     xm = ADD16(PSHR16(xl,1),PSHR16(xr,1));         /* bisect the interval  */
  306. #else
  307.                     xm = .5*(xl+xr);         /* bisect the interval  */
  308. #endif
  309.     psumm=cheb_poly_eva(pt,xm,lpcrdr,stack);
  310.     /*if(psumm*psuml>0.)*/
  311.     if(!SIGN_CHANGE(psumm,psuml))
  312.                     {
  313. psuml=psumm;
  314. xl=xm;
  315.     } else {
  316. psumr=psumm;
  317. xr=xm;
  318.     }
  319. }
  320.        /* once zero is found, reset initial interval to xr  */
  321.        freq[j] = X2ANGLE(xm);
  322.        xl = xm;
  323.        flag = 0;        /* reset flag for next search  */
  324.     }
  325.     else{
  326. psuml=temp_psumr;
  327. xl=temp_xr;
  328.     }
  329. }
  330.     }
  331.     return(roots);
  332. }
  333. /*---------------------------------------------------------------------------*
  334. FUNCTION....: lsp_to_lpc()
  335. AUTHOR......: David Rowe
  336. DATE CREATED: 24/2/93
  337.     lsp_to_lpc: This function converts LSP coefficients to LPC
  338.     coefficients.
  339. *---------------------------------------------------------------------------*/
  340. #ifdef FIXED_POINT
  341. void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
  342. /*  float *freq  array of LSP frequencies in the x domain */
  343. /*  float *ak  array of LPC coefficients  */
  344. /*  int lpcrdr   order of LPC coefficients  */
  345. {
  346.     int i,j;
  347.     spx_word32_t xout1,xout2,xin1,xin2;
  348.     VARDECL(spx_word32_t *Wp);
  349.     spx_word32_t *pw,*n1,*n2,*n3,*n4=NULL;
  350.     VARDECL(spx_word16_t *freqn);
  351.     int m = lpcrdr>>1;
  352.     
  353.     ALLOC(freqn, lpcrdr, spx_word16_t);
  354.     for (i=0;i<lpcrdr;i++)
  355.        freqn[i] = ANGLE2X(freq[i]);
  356.     ALLOC(Wp, 4*m+2, spx_word32_t);
  357.     pw = Wp;
  358.     /* initialise contents of array */
  359.     for(i=0;i<=4*m+1;i++){        /* set contents of buffer to 0 */
  360. *pw++ = 0;
  361.     }
  362.     /* Set pointers up */
  363.     pw = Wp;
  364.     xin1 = 1048576;
  365.     xin2 = 1048576;
  366.     /* reconstruct P(z) and Q(z) by  cascading second order
  367.       polynomials in form 1 - 2xz(-1) +z(-2), where x is the
  368.       LSP coefficient */
  369.     for(j=0;j<=lpcrdr;j++){
  370.        spx_word16_t *fr=freqn;
  371. for(i=0;i<m;i++){
  372.     n1 = pw+(i<<2);
  373.     n2 = n1 + 1;
  374.     n3 = n2 + 1;
  375.     n4 = n3 + 1;
  376.     xout1 = ADD32(SUB32(xin1, MULT16_32_Q14(*fr,*n1)), *n2);
  377.             fr++;
  378.             xout2 = ADD32(SUB32(xin2, MULT16_32_Q14(*fr,*n3)), *n4);
  379.             fr++;
  380.     *n2 = *n1;
  381.     *n4 = *n3;
  382.     *n1 = xin1;
  383.     *n3 = xin2;
  384.     xin1 = xout1;
  385.     xin2 = xout2;
  386. }
  387. xout1 = xin1 + *(n4+1);
  388. xout2 = xin2 - *(n4+2);
  389.         /* FIXME: perhaps apply bandwidth expansion in case of overflow? */
  390. if (j>0)
  391. {
  392.         if (xout1 + xout2>SHL32(EXTEND32(32766),8))
  393.            ak[j-1] = 32767;
  394.         else if (xout1 + xout2 < -SHL32(EXTEND32(32766),8))
  395.            ak[j-1] = -32767;
  396.         else
  397.            ak[j-1] = EXTRACT16(PSHR32(ADD32(xout1,xout2),8));
  398. } else {/*speex_warning_int("ak[0] = ", EXTRACT16(PSHR32(ADD32(xout1,xout2),8)));*/}
  399. *(n4+1) = xin1;
  400. *(n4+2) = xin2;
  401. xin1 = 0;
  402. xin2 = 0;
  403.     }
  404. }
  405. #else
  406. void lsp_to_lpc(spx_lsp_t *freq,spx_coef_t *ak,int lpcrdr, char *stack)
  407. /*  float *freq  array of LSP frequencies in the x domain */
  408. /*  float *ak  array of LPC coefficients  */
  409. /*  int lpcrdr   order of LPC coefficients  */
  410. {
  411.     int i,j;
  412.     float xout1,xout2,xin1,xin2;
  413.     VARDECL(float *Wp);
  414.     float *pw,*n1,*n2,*n3,*n4=NULL;
  415.     VARDECL(float *x_freq);
  416.     int m = lpcrdr>>1;
  417.     ALLOC(Wp, 4*m+2, float);
  418.     pw = Wp;
  419.     /* initialise contents of array */
  420.     for(i=0;i<=4*m+1;i++){        /* set contents of buffer to 0 */
  421. *pw++ = 0.0;
  422.     }
  423.     /* Set pointers up */
  424.     pw = Wp;
  425.     xin1 = 1.0;
  426.     xin2 = 1.0;
  427.     ALLOC(x_freq, lpcrdr, float);
  428.     for (i=0;i<lpcrdr;i++)
  429.        x_freq[i] = ANGLE2X(freq[i]);
  430.     /* reconstruct P(z) and Q(z) by  cascading second order
  431.       polynomials in form 1 - 2xz(-1) +z(-2), where x is the
  432.       LSP coefficient */
  433.     for(j=0;j<=lpcrdr;j++){
  434.        int i2=0;
  435. for(i=0;i<m;i++,i2+=2){
  436.     n1 = pw+(i*4);
  437.     n2 = n1 + 1;
  438.     n3 = n2 + 1;
  439.     n4 = n3 + 1;
  440.     xout1 = xin1 - 2.f*x_freq[i2] * *n1 + *n2;
  441.     xout2 = xin2 - 2.f*x_freq[i2+1] * *n3 + *n4;
  442.     *n2 = *n1;
  443.     *n4 = *n3;
  444.     *n1 = xin1;
  445.     *n3 = xin2;
  446.     xin1 = xout1;
  447.     xin2 = xout2;
  448. }
  449. xout1 = xin1 + *(n4+1);
  450. xout2 = xin2 - *(n4+2);
  451. if (j>0)
  452.    ak[j-1] = (xout1 + xout2)*0.5f;
  453. *(n4+1) = xin1;
  454. *(n4+2) = xin2;
  455. xin1 = 0.0;
  456. xin2 = 0.0;
  457.     }
  458. }
  459. #endif
  460. #ifdef FIXED_POINT
  461. /*Makes sure the LSPs are stable*/
  462. void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin)
  463. {
  464.    int i;
  465.    spx_word16_t m = margin;
  466.    spx_word16_t m2 = 25736-margin;
  467.   
  468.    if (lsp[0]<m)
  469.       lsp[0]=m;
  470.    if (lsp[len-1]>m2)
  471.       lsp[len-1]=m2;
  472.    for (i=1;i<len-1;i++)
  473.    {
  474.       if (lsp[i]<lsp[i-1]+m)
  475.          lsp[i]=lsp[i-1]+m;
  476.       if (lsp[i]>lsp[i+1]-m)
  477.          lsp[i]= SHR16(lsp[i],1) + SHR16(lsp[i+1]-m,1);
  478.    }
  479. }
  480. void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes)
  481. {
  482.    int i;
  483.    spx_word16_t tmp = DIV32_16(SHL32(EXTEND32(1 + subframe),14),nb_subframes);
  484.    spx_word16_t tmp2 = 16384-tmp;
  485.    for (i=0;i<len;i++)
  486.    {
  487.       interp_lsp[i] = MULT16_16_P14(tmp2,old_lsp[i]) + MULT16_16_P14(tmp,new_lsp[i]);
  488.    }
  489. }
  490. #else
  491. /*Makes sure the LSPs are stable*/
  492. void lsp_enforce_margin(spx_lsp_t *lsp, int len, spx_word16_t margin)
  493. {
  494.    int i;
  495.    if (lsp[0]<LSP_SCALING*margin)
  496.       lsp[0]=LSP_SCALING*margin;
  497.    if (lsp[len-1]>LSP_SCALING*(M_PI-margin))
  498.       lsp[len-1]=LSP_SCALING*(M_PI-margin);
  499.    for (i=1;i<len-1;i++)
  500.    {
  501.       if (lsp[i]<lsp[i-1]+LSP_SCALING*margin)
  502.          lsp[i]=lsp[i-1]+LSP_SCALING*margin;
  503.       if (lsp[i]>lsp[i+1]-LSP_SCALING*margin)
  504.          lsp[i]= .5f* (lsp[i] + lsp[i+1]-LSP_SCALING*margin);
  505.    }
  506. }
  507. void lsp_interpolate(spx_lsp_t *old_lsp, spx_lsp_t *new_lsp, spx_lsp_t *interp_lsp, int len, int subframe, int nb_subframes)
  508. {
  509.    int i;
  510.    float tmp = (1.0f + subframe)/nb_subframes;
  511.    for (i=0;i<len;i++)
  512.    {
  513.       interp_lsp[i] = (1-tmp)*old_lsp[i] + tmp*new_lsp[i];
  514.    }
  515. }
  516. #endif