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