xref: /btstack/3rd-party/lc3-google/src/tns.c (revision 6897da5c53aac5b1f90f41b5b15d0bd43d61dfff)
19a19cd78SMatthias Ringwald /******************************************************************************
29a19cd78SMatthias Ringwald  *
34930cef6SMatthias Ringwald  *  Copyright 2022 Google LLC
49a19cd78SMatthias Ringwald  *
59a19cd78SMatthias Ringwald  *  Licensed under the Apache License, Version 2.0 (the "License");
69a19cd78SMatthias Ringwald  *  you may not use this file except in compliance with the License.
79a19cd78SMatthias Ringwald  *  You may obtain a copy of the License at:
89a19cd78SMatthias Ringwald  *
99a19cd78SMatthias Ringwald  *  http://www.apache.org/licenses/LICENSE-2.0
109a19cd78SMatthias Ringwald  *
119a19cd78SMatthias Ringwald  *  Unless required by applicable law or agreed to in writing, software
129a19cd78SMatthias Ringwald  *  distributed under the License is distributed on an "AS IS" BASIS,
139a19cd78SMatthias Ringwald  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149a19cd78SMatthias Ringwald  *  See the License for the specific language governing permissions and
159a19cd78SMatthias Ringwald  *  limitations under the License.
169a19cd78SMatthias Ringwald  *
179a19cd78SMatthias Ringwald  ******************************************************************************/
189a19cd78SMatthias Ringwald 
199a19cd78SMatthias Ringwald #include "tns.h"
209a19cd78SMatthias Ringwald #include "tables.h"
219a19cd78SMatthias Ringwald 
229a19cd78SMatthias Ringwald 
239a19cd78SMatthias Ringwald /* ----------------------------------------------------------------------------
249a19cd78SMatthias Ringwald  *  Filter Coefficients
259a19cd78SMatthias Ringwald  * -------------------------------------------------------------------------- */
269a19cd78SMatthias Ringwald 
279a19cd78SMatthias Ringwald /**
289a19cd78SMatthias Ringwald  * Resolve LPC Weighting indication according bitrate
299a19cd78SMatthias Ringwald  * dt, nbytes      Duration and size of the frame
309a19cd78SMatthias Ringwald  * return          True when LPC Weighting enabled
319a19cd78SMatthias Ringwald  */
resolve_lpc_weighting(enum lc3_dt dt,int nbytes)329a19cd78SMatthias Ringwald static bool resolve_lpc_weighting(enum lc3_dt dt, int nbytes)
339a19cd78SMatthias Ringwald {
34*6897da5cSDirk Helbig     return nbytes * 8 < 120 * (int)(1 + dt);
359a19cd78SMatthias Ringwald }
369a19cd78SMatthias Ringwald 
379a19cd78SMatthias Ringwald /**
389a19cd78SMatthias Ringwald  * Return dot product of 2 vectors
399a19cd78SMatthias Ringwald  * a, b, n         The 2 vectors of size `n`
409a19cd78SMatthias Ringwald  * return          sum( a[i] * b[i] ), i = [0..n-1]
419a19cd78SMatthias Ringwald  */
dot(const float * a,const float * b,int n)424930cef6SMatthias Ringwald LC3_HOT static inline float dot(const float *a, const float *b, int n)
439a19cd78SMatthias Ringwald {
449a19cd78SMatthias Ringwald     float v = 0;
459a19cd78SMatthias Ringwald 
469a19cd78SMatthias Ringwald     while (n--)
479a19cd78SMatthias Ringwald         v += *(a++) * *(b++);
489a19cd78SMatthias Ringwald 
499a19cd78SMatthias Ringwald     return v;
509a19cd78SMatthias Ringwald }
519a19cd78SMatthias Ringwald 
529a19cd78SMatthias Ringwald /**
539a19cd78SMatthias Ringwald  * LPC Coefficients
549a19cd78SMatthias Ringwald  * dt, bw          Duration and bandwidth of the frame
55*6897da5cSDirk Helbig  * maxorder        Maximum order of filter
569a19cd78SMatthias Ringwald  * x               Spectral coefficients
579a19cd78SMatthias Ringwald  * gain, a         Output the prediction gains and LPC coefficients
589a19cd78SMatthias Ringwald  */
compute_lpc_coeffs(enum lc3_dt dt,enum lc3_bandwidth bw,int maxorder,const float * x,float * gain,float (* a)[9])594930cef6SMatthias Ringwald LC3_HOT static void compute_lpc_coeffs(
60*6897da5cSDirk Helbig     enum lc3_dt dt, enum lc3_bandwidth bw, int maxorder,
619a19cd78SMatthias Ringwald     const float *x, float *gain, float (*a)[9])
629a19cd78SMatthias Ringwald {
63*6897da5cSDirk Helbig 
64*6897da5cSDirk Helbig #if LC3_PLUS
65*6897da5cSDirk Helbig 
66*6897da5cSDirk Helbig     static const int sub_2m5_nb[]   = {  3,  10,  20 };
67*6897da5cSDirk Helbig     static const int sub_2m5_wb[]   = {  3,  20,  40 };
68*6897da5cSDirk Helbig     static const int sub_2m5_sswb[] = {  3,  30,  60 };
69*6897da5cSDirk Helbig     static const int sub_2m5_swb[]  = {  3,  40,  80 };
70*6897da5cSDirk Helbig     static const int sub_2m5_fb[]   = {  3,  51, 100 };
71*6897da5cSDirk Helbig 
72*6897da5cSDirk Helbig     static const int sub_5m_nb[]    = {  6,  23,  40 };
73*6897da5cSDirk Helbig     static const int sub_5m_wb[]    = {  6,  43,  80 };
74*6897da5cSDirk Helbig     static const int sub_5m_sswb[]  = {  6,  63, 120 };
75*6897da5cSDirk Helbig     static const int sub_5m_swb[]   = {  6,  43,  80, 120, 160 };
76*6897da5cSDirk Helbig     static const int sub_5m_fb[]    = {  6,  53, 100, 150, 200 };
77*6897da5cSDirk Helbig 
78*6897da5cSDirk Helbig #endif /* LC3_PLUS */
79*6897da5cSDirk Helbig 
809a19cd78SMatthias Ringwald     static const int sub_7m5_nb[]   = {  9,  26,  43,  60 };
819a19cd78SMatthias Ringwald     static const int sub_7m5_wb[]   = {  9,  46,  83, 120 };
829a19cd78SMatthias Ringwald     static const int sub_7m5_sswb[] = {  9,  66, 123, 180 };
839a19cd78SMatthias Ringwald     static const int sub_7m5_swb[]  = {  9,  46,  82, 120, 159, 200, 240 };
849a19cd78SMatthias Ringwald     static const int sub_7m5_fb[]   = {  9,  56, 103, 150, 200, 250, 300 };
859a19cd78SMatthias Ringwald 
869a19cd78SMatthias Ringwald     static const int sub_10m_nb[]   = { 12,  34,  57,  80 };
879a19cd78SMatthias Ringwald     static const int sub_10m_wb[]   = { 12,  61, 110, 160 };
889a19cd78SMatthias Ringwald     static const int sub_10m_sswb[] = { 12,  88, 164, 240 };
899a19cd78SMatthias Ringwald     static const int sub_10m_swb[]  = { 12,  61, 110, 160, 213, 266, 320 };
909a19cd78SMatthias Ringwald     static const int sub_10m_fb[]   = { 12,  74, 137, 200, 266, 333, 400 };
919a19cd78SMatthias Ringwald 
929a19cd78SMatthias Ringwald     static const float lag_window[] = {
939a19cd78SMatthias Ringwald         1.00000000e+00, 9.98028026e-01, 9.92135406e-01, 9.82391584e-01,
949a19cd78SMatthias Ringwald         9.68910791e-01, 9.51849807e-01, 9.31404933e-01, 9.07808230e-01,
959a19cd78SMatthias Ringwald         8.81323137e-01
969a19cd78SMatthias Ringwald     };
979a19cd78SMatthias Ringwald 
98*6897da5cSDirk Helbig     const int *sub = (const int * const [LC3_NUM_DT][LC3_NUM_BANDWIDTH]){
99*6897da5cSDirk Helbig 
100*6897da5cSDirk Helbig #if LC3_PLUS
101*6897da5cSDirk Helbig 
102*6897da5cSDirk Helbig         [LC3_DT_2M5] = {
103*6897da5cSDirk Helbig           sub_2m5_nb, sub_2m5_wb, sub_2m5_sswb, sub_2m5_swb,
104*6897da5cSDirk Helbig           sub_2m5_fb, sub_2m5_fb, sub_2m5_fb                },
105*6897da5cSDirk Helbig 
106*6897da5cSDirk Helbig         [LC3_DT_5M] = {
107*6897da5cSDirk Helbig             sub_5m_nb , sub_5m_wb , sub_5m_sswb , sub_5m_swb ,
108*6897da5cSDirk Helbig             sub_5m_fb , sub_5m_fb , sub_5m_fb                 },
109*6897da5cSDirk Helbig 
110*6897da5cSDirk Helbig #endif /* LC3_PLUS */
111*6897da5cSDirk Helbig 
112*6897da5cSDirk Helbig         [LC3_DT_7M5] = {
113*6897da5cSDirk Helbig             sub_7m5_nb, sub_7m5_wb, sub_7m5_sswb, sub_7m5_swb,
114*6897da5cSDirk Helbig             sub_7m5_fb                                        },
115*6897da5cSDirk Helbig 
116*6897da5cSDirk Helbig         [LC3_DT_10M] = {
117*6897da5cSDirk Helbig             sub_10m_nb, sub_10m_wb, sub_10m_sswb, sub_10m_swb,
118*6897da5cSDirk Helbig             sub_10m_fb, sub_10m_fb, sub_10m_fb                },
119*6897da5cSDirk Helbig 
1209a19cd78SMatthias Ringwald     }[dt][bw];
1219a19cd78SMatthias Ringwald 
122*6897da5cSDirk Helbig     /* --- Normalized autocorrelation --- */
123*6897da5cSDirk Helbig 
124*6897da5cSDirk Helbig     int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
125*6897da5cSDirk Helbig     int nsubdivisions = 2 + (dt >= LC3_DT_7M5);
1269a19cd78SMatthias Ringwald 
1279a19cd78SMatthias Ringwald     const float *xs, *xe = x + *sub;
1289a19cd78SMatthias Ringwald     float r[2][9];
1299a19cd78SMatthias Ringwald 
1309a19cd78SMatthias Ringwald     for (int f = 0; f < nfilters; f++) {
131*6897da5cSDirk Helbig         float c[9][3] = { 0 };
1329a19cd78SMatthias Ringwald 
133*6897da5cSDirk Helbig         for (int s = 0; s < nsubdivisions; s++) {
1349a19cd78SMatthias Ringwald             xs = xe, xe = x + *(++sub);
1359a19cd78SMatthias Ringwald 
136*6897da5cSDirk Helbig             for (int k = 0; k <= maxorder; k++)
1379a19cd78SMatthias Ringwald                 c[k][s] = dot(xs, xs + k, (xe - xs) - k);
1389a19cd78SMatthias Ringwald         }
1399a19cd78SMatthias Ringwald 
140*6897da5cSDirk Helbig         r[f][0] = nsubdivisions;
141*6897da5cSDirk Helbig         if (nsubdivisions == 2) {
142*6897da5cSDirk Helbig             float e0 = c[0][0], e1 = c[0][1];
143*6897da5cSDirk Helbig             for (int k = 1; k <= maxorder; k++)
144*6897da5cSDirk Helbig                 r[f][k] = e0 == 0 || e1 == 0 ? 0 :
145*6897da5cSDirk Helbig                   (c[k][0]/e0 + c[k][1]/e1) * lag_window[k];
1469a19cd78SMatthias Ringwald 
147*6897da5cSDirk Helbig         } else {
148*6897da5cSDirk Helbig             float e0 = c[0][0], e1 = c[0][1], e2 = c[0][2];
149*6897da5cSDirk Helbig             for (int k = 1; k <= maxorder; k++)
1509a19cd78SMatthias Ringwald                 r[f][k] = e0 == 0 || e1 == 0 || e2 == 0 ? 0 :
1519a19cd78SMatthias Ringwald                   (c[k][0]/e0 + c[k][1]/e1 + c[k][2]/e2) * lag_window[k];
1529a19cd78SMatthias Ringwald         }
153*6897da5cSDirk Helbig     }
1549a19cd78SMatthias Ringwald 
1559a19cd78SMatthias Ringwald     /* --- Levinson-Durbin recursion --- */
1569a19cd78SMatthias Ringwald 
1579a19cd78SMatthias Ringwald     for (int f = 0; f < nfilters; f++) {
1589a19cd78SMatthias Ringwald         float *a0 = a[f], a1[9];
1599a19cd78SMatthias Ringwald         float err = r[f][0], rc;
1609a19cd78SMatthias Ringwald 
1619a19cd78SMatthias Ringwald         gain[f] = err;
1629a19cd78SMatthias Ringwald 
1639a19cd78SMatthias Ringwald         a0[0] = 1;
164*6897da5cSDirk Helbig         for (int k = 1; k <= maxorder; ) {
1659a19cd78SMatthias Ringwald 
1669a19cd78SMatthias Ringwald             rc = -r[f][k];
1679a19cd78SMatthias Ringwald             for (int i = 1; i < k; i++)
1689a19cd78SMatthias Ringwald                 rc -= a0[i] * r[f][k-i];
1699a19cd78SMatthias Ringwald 
1709a19cd78SMatthias Ringwald             rc /= err;
1719a19cd78SMatthias Ringwald             err *= 1 - rc * rc;
1729a19cd78SMatthias Ringwald 
1739a19cd78SMatthias Ringwald             for (int i = 1; i < k; i++)
1749a19cd78SMatthias Ringwald                 a1[i] = a0[i] + rc * a0[k-i];
1759a19cd78SMatthias Ringwald             a1[k++] = rc;
1769a19cd78SMatthias Ringwald 
1779a19cd78SMatthias Ringwald             rc = -r[f][k];
1789a19cd78SMatthias Ringwald             for (int i = 1; i < k; i++)
1799a19cd78SMatthias Ringwald                 rc -= a1[i] * r[f][k-i];
1809a19cd78SMatthias Ringwald 
1819a19cd78SMatthias Ringwald             rc /= err;
1829a19cd78SMatthias Ringwald             err *= 1 - rc * rc;
1839a19cd78SMatthias Ringwald 
1849a19cd78SMatthias Ringwald             for (int i = 1; i < k; i++)
1859a19cd78SMatthias Ringwald                 a0[i] = a1[i] + rc * a1[k-i];
1869a19cd78SMatthias Ringwald             a0[k++] = rc;
1879a19cd78SMatthias Ringwald         }
1889a19cd78SMatthias Ringwald 
1899a19cd78SMatthias Ringwald         gain[f] /= err;
1909a19cd78SMatthias Ringwald     }
1919a19cd78SMatthias Ringwald }
1929a19cd78SMatthias Ringwald 
1939a19cd78SMatthias Ringwald /**
1949a19cd78SMatthias Ringwald  * LPC Weighting
1959a19cd78SMatthias Ringwald  * gain, a         Prediction gain and LPC coefficients, weighted as output
1969a19cd78SMatthias Ringwald  */
lpc_weighting(float pred_gain,float * a)1974930cef6SMatthias Ringwald LC3_HOT static void lpc_weighting(float pred_gain, float *a)
1989a19cd78SMatthias Ringwald {
1994930cef6SMatthias Ringwald     float gamma = 1.f - (1.f - 0.85f) * (2.f - pred_gain) / (2.f - 1.5f);
2004930cef6SMatthias Ringwald     float g = 1.f;
2014930cef6SMatthias Ringwald 
2029a19cd78SMatthias Ringwald     for (int i = 1; i < 9; i++)
2039a19cd78SMatthias Ringwald         a[i] *= (g *= gamma);
2049a19cd78SMatthias Ringwald }
2059a19cd78SMatthias Ringwald 
2069a19cd78SMatthias Ringwald /**
2079a19cd78SMatthias Ringwald  * LPC reflection
208*6897da5cSDirk Helbig  * a, maxorder     LPC coefficients, and maximum order (4 or 8)
2099a19cd78SMatthias Ringwald  * rc              Output refelection coefficients
2109a19cd78SMatthias Ringwald  */
lpc_reflection(const float * a,int maxorder,float * rc)211*6897da5cSDirk Helbig LC3_HOT static void lpc_reflection(
212*6897da5cSDirk Helbig     const float *a, int maxorder, float *rc)
2139a19cd78SMatthias Ringwald {
2149a19cd78SMatthias Ringwald     float e, b[2][7], *b0, *b1;
2159a19cd78SMatthias Ringwald 
216*6897da5cSDirk Helbig     rc[maxorder-1] = a[maxorder];
217*6897da5cSDirk Helbig     e = 1 - rc[maxorder-1] * rc[maxorder-1];
2189a19cd78SMatthias Ringwald 
2199a19cd78SMatthias Ringwald     b1 = b[1];
220*6897da5cSDirk Helbig     for (int i = 0; i < maxorder-1; i++)
221*6897da5cSDirk Helbig         b1[i] = (a[1+i] - rc[maxorder-1] * a[(maxorder-1)-i]) / e;
2229a19cd78SMatthias Ringwald 
223*6897da5cSDirk Helbig     for (int k = maxorder-2; k > 0; k--) {
2249a19cd78SMatthias Ringwald         b0 = b1, b1 = b[k & 1];
2259a19cd78SMatthias Ringwald 
2269a19cd78SMatthias Ringwald         rc[k] = b0[k];
2279a19cd78SMatthias Ringwald         e = 1 - rc[k] * rc[k];
2289a19cd78SMatthias Ringwald 
2299a19cd78SMatthias Ringwald         for (int i = 0; i < k; i++)
2309a19cd78SMatthias Ringwald             b1[i] = (b0[i] - rc[k] * b0[k-1-i]) / e;
2319a19cd78SMatthias Ringwald     }
2329a19cd78SMatthias Ringwald 
2339a19cd78SMatthias Ringwald     rc[0] = b1[0];
2349a19cd78SMatthias Ringwald }
2359a19cd78SMatthias Ringwald 
2369a19cd78SMatthias Ringwald /**
2379a19cd78SMatthias Ringwald  * Quantization of RC coefficients
238*6897da5cSDirk Helbig  * rc, maxorder    Refelection coefficients, and maximum order (4 or 8)
239*6897da5cSDirk Helbig  * order           Return order of coefficients
2409a19cd78SMatthias Ringwald  * rc_i            Return quantized coefficients
2419a19cd78SMatthias Ringwald  */
quantize_rc(const float * rc,int maxorder,int * order,int * rc_q)242*6897da5cSDirk Helbig static void quantize_rc(const float *rc, int maxorder, int *order, int *rc_q)
2439a19cd78SMatthias Ringwald {
244*6897da5cSDirk Helbig     /* Quantization table, sin(delta * (i + 0.5)), delta = Pi / 17,
245*6897da5cSDirk Helbig      * rounded to fixed point Q15 value (LC3-Plus HR requirements). */
2469a19cd78SMatthias Ringwald 
2479a19cd78SMatthias Ringwald     static float q_thr[] = {
248*6897da5cSDirk Helbig         0x0bcfp-15, 0x2307p-15, 0x390ep-15, 0x4d23p-15,
249*6897da5cSDirk Helbig         0x5e98p-15, 0x6cd4p-15, 0x775bp-15, 0x7dd2p-15,
2509a19cd78SMatthias Ringwald     };
2519a19cd78SMatthias Ringwald 
252*6897da5cSDirk Helbig     *order = maxorder;
2539a19cd78SMatthias Ringwald 
254*6897da5cSDirk Helbig     for (int i = 0; i < maxorder; i++) {
2559a19cd78SMatthias Ringwald         float rc_m = fabsf(rc[i]);
2569a19cd78SMatthias Ringwald 
2579a19cd78SMatthias Ringwald         rc_q[i] = 4 * (rc_m >= q_thr[4]);
2589a19cd78SMatthias Ringwald         for (int j = 0; j < 4 && rc_m >= q_thr[rc_q[i]]; j++, rc_q[i]++);
2599a19cd78SMatthias Ringwald 
2609a19cd78SMatthias Ringwald         if (rc[i] < 0)
2619a19cd78SMatthias Ringwald             rc_q[i] = -rc_q[i];
2629a19cd78SMatthias Ringwald 
263*6897da5cSDirk Helbig         *order = rc_q[i] != 0 ? maxorder : *order - 1;
2649a19cd78SMatthias Ringwald     }
2659a19cd78SMatthias Ringwald }
2669a19cd78SMatthias Ringwald 
2679a19cd78SMatthias Ringwald /**
2689a19cd78SMatthias Ringwald  * Unquantization of RC coefficients
269*6897da5cSDirk Helbig  * rc_q, order     Quantized coefficients, and order
2709a19cd78SMatthias Ringwald  * rc              Return refelection coefficients
2719a19cd78SMatthias Ringwald  */
unquantize_rc(const int * rc_q,int order,float rc[8])272*6897da5cSDirk Helbig static void unquantize_rc(const int *rc_q, int order, float rc[8])
2739a19cd78SMatthias Ringwald {
274*6897da5cSDirk Helbig     /* Quantization table, sin(delta * i), delta = Pi / 17,
275*6897da5cSDirk Helbig      * rounded to fixed point Q15 value (LC3-Plus HR requirements). */
2769a19cd78SMatthias Ringwald 
2779a19cd78SMatthias Ringwald     static float q_inv[] = {
278*6897da5cSDirk Helbig         0x0000p-15, 0x1785p-15, 0x2e3dp-15, 0x4362p-15,
279*6897da5cSDirk Helbig         0x563cp-15, 0x6625p-15, 0x7295p-15, 0x7b1dp-15, 0x7f74p-15,
2809a19cd78SMatthias Ringwald     };
2819a19cd78SMatthias Ringwald 
2829a19cd78SMatthias Ringwald     int i;
2839a19cd78SMatthias Ringwald 
284*6897da5cSDirk Helbig     for (i = 0; i < order; i++) {
2859a19cd78SMatthias Ringwald         float rc_m = q_inv[LC3_ABS(rc_q[i])];
2869a19cd78SMatthias Ringwald         rc[i] = rc_q[i] < 0 ? -rc_m : rc_m;
2879a19cd78SMatthias Ringwald     }
2889a19cd78SMatthias Ringwald }
2899a19cd78SMatthias Ringwald 
2909a19cd78SMatthias Ringwald 
2919a19cd78SMatthias Ringwald /* ----------------------------------------------------------------------------
2929a19cd78SMatthias Ringwald  *  Filtering
2939a19cd78SMatthias Ringwald  * -------------------------------------------------------------------------- */
2949a19cd78SMatthias Ringwald 
2959a19cd78SMatthias Ringwald /**
2969a19cd78SMatthias Ringwald  * Forward filtering
2979a19cd78SMatthias Ringwald  * dt, bw          Duration and bandwidth of the frame
2989a19cd78SMatthias Ringwald  * rc_order, rc    Order of coefficients, and coefficients
2999a19cd78SMatthias Ringwald  * x               Spectral coefficients, filtered as output
3009a19cd78SMatthias Ringwald  */
forward_filtering(enum lc3_dt dt,enum lc3_bandwidth bw,const int rc_order[2],float (* const rc)[8],float * x)3014930cef6SMatthias Ringwald LC3_HOT static void forward_filtering(
3029a19cd78SMatthias Ringwald     enum lc3_dt dt, enum lc3_bandwidth bw,
303*6897da5cSDirk Helbig     const int rc_order[2], float (* const rc)[8], float *x)
3049a19cd78SMatthias Ringwald {
305*6897da5cSDirk Helbig     int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
306*6897da5cSDirk Helbig     int nf = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB))
307*6897da5cSDirk Helbig                 >> (nfilters - 1);
308*6897da5cSDirk Helbig     int i0, ie = 3*(1 + dt);
3099a19cd78SMatthias Ringwald 
3109a19cd78SMatthias Ringwald     float s[8] = { 0 };
3119a19cd78SMatthias Ringwald 
3129a19cd78SMatthias Ringwald     for (int f = 0; f < nfilters; f++) {
3139a19cd78SMatthias Ringwald 
3149a19cd78SMatthias Ringwald         i0 = ie;
3159a19cd78SMatthias Ringwald         ie = nf * (1 + f);
3169a19cd78SMatthias Ringwald 
3179a19cd78SMatthias Ringwald         if (!rc_order[f])
3189a19cd78SMatthias Ringwald             continue;
3199a19cd78SMatthias Ringwald 
3209a19cd78SMatthias Ringwald         for (int i = i0; i < ie; i++) {
3219a19cd78SMatthias Ringwald             float xi = x[i];
3229a19cd78SMatthias Ringwald             float s0, s1 = xi;
3239a19cd78SMatthias Ringwald 
3249a19cd78SMatthias Ringwald             for (int k = 0; k < rc_order[f]; k++) {
3259a19cd78SMatthias Ringwald                 s0 = s[k];
3269a19cd78SMatthias Ringwald                 s[k] = s1;
3279a19cd78SMatthias Ringwald 
3289a19cd78SMatthias Ringwald                 s1  = rc[f][k] * xi + s0;
3299a19cd78SMatthias Ringwald                 xi += rc[f][k] * s0;
3309a19cd78SMatthias Ringwald             }
3319a19cd78SMatthias Ringwald 
3329a19cd78SMatthias Ringwald             x[i] = xi;
3339a19cd78SMatthias Ringwald         }
3349a19cd78SMatthias Ringwald     }
3359a19cd78SMatthias Ringwald }
3369a19cd78SMatthias Ringwald 
3379a19cd78SMatthias Ringwald /**
3389a19cd78SMatthias Ringwald  * Inverse filtering
3399a19cd78SMatthias Ringwald  * dt, bw          Duration and bandwidth of the frame
3409a19cd78SMatthias Ringwald  * rc_order, rc    Order of coefficients, and unquantized coefficients
3419a19cd78SMatthias Ringwald  * x               Spectral coefficients, filtered as output
3429a19cd78SMatthias Ringwald  */
inverse_filtering(enum lc3_dt dt,enum lc3_bandwidth bw,const int rc_order[2],float (* const rc)[8],float * x)3434930cef6SMatthias Ringwald LC3_HOT static void inverse_filtering(
3449a19cd78SMatthias Ringwald     enum lc3_dt dt, enum lc3_bandwidth bw,
345*6897da5cSDirk Helbig     const int rc_order[2], float (* const rc)[8], float *x)
3469a19cd78SMatthias Ringwald {
347*6897da5cSDirk Helbig     int nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
348*6897da5cSDirk Helbig     int nf = lc3_ne(dt, (enum lc3_srate)LC3_MIN(bw, LC3_BANDWIDTH_FB))
349*6897da5cSDirk Helbig                 >> (nfilters - 1);
350*6897da5cSDirk Helbig     int i0, ie = 3*(1 + dt);
3519a19cd78SMatthias Ringwald 
3529a19cd78SMatthias Ringwald     float s[8] = { 0 };
3539a19cd78SMatthias Ringwald 
3549a19cd78SMatthias Ringwald     for (int f = 0; f < nfilters; f++) {
3559a19cd78SMatthias Ringwald 
3569a19cd78SMatthias Ringwald         i0 = ie;
3579a19cd78SMatthias Ringwald         ie = nf * (1 + f);
3589a19cd78SMatthias Ringwald 
3599a19cd78SMatthias Ringwald         if (!rc_order[f])
3609a19cd78SMatthias Ringwald             continue;
3619a19cd78SMatthias Ringwald 
3629a19cd78SMatthias Ringwald         for (int i = i0; i < ie; i++) {
3639a19cd78SMatthias Ringwald             float xi = x[i];
3649a19cd78SMatthias Ringwald 
3659a19cd78SMatthias Ringwald             xi -= s[7] * rc[f][7];
3669a19cd78SMatthias Ringwald             for (int k = 6; k >= 0; k--) {
3679a19cd78SMatthias Ringwald                 xi -= s[k] * rc[f][k];
3689a19cd78SMatthias Ringwald                 s[k+1] = s[k] + rc[f][k] * xi;
3699a19cd78SMatthias Ringwald             }
3709a19cd78SMatthias Ringwald             s[0] = xi;
3719a19cd78SMatthias Ringwald             x[i] = xi;
3729a19cd78SMatthias Ringwald         }
3739a19cd78SMatthias Ringwald 
3749a19cd78SMatthias Ringwald         for (int k = 7; k >= rc_order[f]; k--)
3759a19cd78SMatthias Ringwald             s[k] = 0;
3769a19cd78SMatthias Ringwald     }
3779a19cd78SMatthias Ringwald }
3789a19cd78SMatthias Ringwald 
3799a19cd78SMatthias Ringwald 
3809a19cd78SMatthias Ringwald /* ----------------------------------------------------------------------------
3819a19cd78SMatthias Ringwald  *  Interface
3829a19cd78SMatthias Ringwald  * -------------------------------------------------------------------------- */
3839a19cd78SMatthias Ringwald 
3849a19cd78SMatthias Ringwald /**
3859a19cd78SMatthias Ringwald  * TNS analysis
3869a19cd78SMatthias Ringwald  */
lc3_tns_analyze(enum lc3_dt dt,enum lc3_bandwidth bw,bool nn_flag,int nbytes,struct lc3_tns_data * data,float * x)3879a19cd78SMatthias Ringwald void lc3_tns_analyze(enum lc3_dt dt, enum lc3_bandwidth bw,
3889a19cd78SMatthias Ringwald     bool nn_flag, int nbytes, struct lc3_tns_data *data, float *x)
3899a19cd78SMatthias Ringwald {
3909a19cd78SMatthias Ringwald     /* Processing steps :
3919a19cd78SMatthias Ringwald      * - Determine the LPC (Linear Predictive Coding) Coefficients
3929a19cd78SMatthias Ringwald      * - Check is the filtering is disabled
3939a19cd78SMatthias Ringwald      * - The coefficients are weighted on low bitrates and predicition gain
3949a19cd78SMatthias Ringwald      * - Convert to reflection coefficients and quantize
3959a19cd78SMatthias Ringwald      * - Finally filter the spectral coefficients */
3969a19cd78SMatthias Ringwald 
3979a19cd78SMatthias Ringwald     float pred_gain[2], a[2][9];
3989a19cd78SMatthias Ringwald     float rc[2][8];
3999a19cd78SMatthias Ringwald 
4009a19cd78SMatthias Ringwald     data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
401*6897da5cSDirk Helbig     data->nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
402*6897da5cSDirk Helbig     int maxorder = dt <= LC3_DT_5M ? 4 : 8;
4039a19cd78SMatthias Ringwald 
404*6897da5cSDirk Helbig     compute_lpc_coeffs(dt, bw, maxorder, x, pred_gain, a);
4059a19cd78SMatthias Ringwald 
4069a19cd78SMatthias Ringwald     for (int f = 0; f < data->nfilters; f++) {
4079a19cd78SMatthias Ringwald 
4089a19cd78SMatthias Ringwald         data->rc_order[f] = 0;
4094930cef6SMatthias Ringwald         if (nn_flag || pred_gain[f] <= 1.5f)
4109a19cd78SMatthias Ringwald             continue;
4119a19cd78SMatthias Ringwald 
4124930cef6SMatthias Ringwald         if (data->lpc_weighting && pred_gain[f] < 2.f)
4139a19cd78SMatthias Ringwald             lpc_weighting(pred_gain[f], a[f]);
4149a19cd78SMatthias Ringwald 
415*6897da5cSDirk Helbig         lpc_reflection(a[f], maxorder, rc[f]);
4169a19cd78SMatthias Ringwald 
417*6897da5cSDirk Helbig         quantize_rc(rc[f], maxorder, &data->rc_order[f], data->rc[f]);
4189a19cd78SMatthias Ringwald         unquantize_rc(data->rc[f], data->rc_order[f], rc[f]);
4199a19cd78SMatthias Ringwald     }
4209a19cd78SMatthias Ringwald 
4219a19cd78SMatthias Ringwald     forward_filtering(dt, bw, data->rc_order, rc, x);
4229a19cd78SMatthias Ringwald }
4239a19cd78SMatthias Ringwald 
4249a19cd78SMatthias Ringwald /**
4259a19cd78SMatthias Ringwald  * TNS synthesis
4269a19cd78SMatthias Ringwald  */
lc3_tns_synthesize(enum lc3_dt dt,enum lc3_bandwidth bw,const struct lc3_tns_data * data,float * x)4279a19cd78SMatthias Ringwald void lc3_tns_synthesize(enum lc3_dt dt, enum lc3_bandwidth bw,
4289a19cd78SMatthias Ringwald     const struct lc3_tns_data *data, float *x)
4299a19cd78SMatthias Ringwald {
430*6897da5cSDirk Helbig     float rc[2][8] = { 0 };
4319a19cd78SMatthias Ringwald 
4329a19cd78SMatthias Ringwald     for (int f = 0; f < data->nfilters; f++)
4339a19cd78SMatthias Ringwald         if (data->rc_order[f])
4349a19cd78SMatthias Ringwald             unquantize_rc(data->rc[f], data->rc_order[f], rc[f]);
4359a19cd78SMatthias Ringwald 
4369a19cd78SMatthias Ringwald     inverse_filtering(dt, bw, data->rc_order, rc, x);
4379a19cd78SMatthias Ringwald }
4389a19cd78SMatthias Ringwald 
4399a19cd78SMatthias Ringwald /**
4409a19cd78SMatthias Ringwald  * Bit consumption of bitstream data
4419a19cd78SMatthias Ringwald  */
lc3_tns_get_nbits(const struct lc3_tns_data * data)4429a19cd78SMatthias Ringwald int lc3_tns_get_nbits(const struct lc3_tns_data *data)
4439a19cd78SMatthias Ringwald {
4449a19cd78SMatthias Ringwald     int nbits = 0;
4459a19cd78SMatthias Ringwald 
4469a19cd78SMatthias Ringwald     for (int f = 0; f < data->nfilters; f++) {
4479a19cd78SMatthias Ringwald 
4489a19cd78SMatthias Ringwald         int nbits_2048 = 2048;
4499a19cd78SMatthias Ringwald         int rc_order = data->rc_order[f];
4509a19cd78SMatthias Ringwald 
4519a19cd78SMatthias Ringwald         nbits_2048 += rc_order > 0 ? lc3_tns_order_bits
4529a19cd78SMatthias Ringwald             [data->lpc_weighting][rc_order-1] : 0;
4539a19cd78SMatthias Ringwald 
4549a19cd78SMatthias Ringwald         for (int i = 0; i < rc_order; i++)
4559a19cd78SMatthias Ringwald             nbits_2048 += lc3_tns_coeffs_bits[i][8 + data->rc[f][i]];
4569a19cd78SMatthias Ringwald 
4579a19cd78SMatthias Ringwald         nbits += (nbits_2048 + (1 << 11) - 1) >> 11;
4589a19cd78SMatthias Ringwald     }
4599a19cd78SMatthias Ringwald 
4609a19cd78SMatthias Ringwald     return nbits;
4619a19cd78SMatthias Ringwald }
4629a19cd78SMatthias Ringwald 
4639a19cd78SMatthias Ringwald /**
4649a19cd78SMatthias Ringwald  * Put bitstream data
4659a19cd78SMatthias Ringwald  */
lc3_tns_put_data(lc3_bits_t * bits,const struct lc3_tns_data * data)4669a19cd78SMatthias Ringwald void lc3_tns_put_data(lc3_bits_t *bits, const struct lc3_tns_data *data)
4679a19cd78SMatthias Ringwald {
4689a19cd78SMatthias Ringwald     for (int f = 0; f < data->nfilters; f++) {
4699a19cd78SMatthias Ringwald         int rc_order = data->rc_order[f];
4709a19cd78SMatthias Ringwald 
4719a19cd78SMatthias Ringwald         lc3_put_bits(bits, rc_order > 0, 1);
4729a19cd78SMatthias Ringwald         if (rc_order <= 0)
4739a19cd78SMatthias Ringwald             continue;
4749a19cd78SMatthias Ringwald 
4759a19cd78SMatthias Ringwald         lc3_put_symbol(bits,
4769a19cd78SMatthias Ringwald             lc3_tns_order_models + data->lpc_weighting, rc_order-1);
4779a19cd78SMatthias Ringwald 
4789a19cd78SMatthias Ringwald         for (int i = 0; i < rc_order; i++)
4799a19cd78SMatthias Ringwald             lc3_put_symbol(bits,
4809a19cd78SMatthias Ringwald                 lc3_tns_coeffs_models + i, 8 + data->rc[f][i]);
4819a19cd78SMatthias Ringwald     }
4829a19cd78SMatthias Ringwald }
4839a19cd78SMatthias Ringwald 
4849a19cd78SMatthias Ringwald /**
4859a19cd78SMatthias Ringwald  * Get bitstream data
4869a19cd78SMatthias Ringwald  */
lc3_tns_get_data(lc3_bits_t * bits,enum lc3_dt dt,enum lc3_bandwidth bw,int nbytes,lc3_tns_data_t * data)487*6897da5cSDirk Helbig int lc3_tns_get_data(lc3_bits_t *bits,
4889a19cd78SMatthias Ringwald     enum lc3_dt dt, enum lc3_bandwidth bw, int nbytes, lc3_tns_data_t *data)
4899a19cd78SMatthias Ringwald {
490*6897da5cSDirk Helbig     data->nfilters = 1 + (dt >= LC3_DT_5M && bw >= LC3_BANDWIDTH_SWB);
4919a19cd78SMatthias Ringwald     data->lpc_weighting = resolve_lpc_weighting(dt, nbytes);
4929a19cd78SMatthias Ringwald 
4939a19cd78SMatthias Ringwald     for (int f = 0; f < data->nfilters; f++) {
4949a19cd78SMatthias Ringwald 
4959a19cd78SMatthias Ringwald         data->rc_order[f] = lc3_get_bit(bits);
4969a19cd78SMatthias Ringwald         if (!data->rc_order[f])
4979a19cd78SMatthias Ringwald             continue;
4989a19cd78SMatthias Ringwald 
4999a19cd78SMatthias Ringwald         data->rc_order[f] += lc3_get_symbol(bits,
5009a19cd78SMatthias Ringwald             lc3_tns_order_models + data->lpc_weighting);
501*6897da5cSDirk Helbig         if (dt <= LC3_DT_5M && data->rc_order[f] > 4)
502*6897da5cSDirk Helbig             return -1;
5039a19cd78SMatthias Ringwald 
5049a19cd78SMatthias Ringwald         for (int i = 0; i < data->rc_order[f]; i++)
5059a19cd78SMatthias Ringwald             data->rc[f][i] = (int)lc3_get_symbol(bits,
5069a19cd78SMatthias Ringwald                 lc3_tns_coeffs_models + i) - 8;
5079a19cd78SMatthias Ringwald     }
508*6897da5cSDirk Helbig 
509*6897da5cSDirk Helbig     return 0;
5109a19cd78SMatthias Ringwald }
511