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