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