1*15dc779aSAndroid Build Coastguard Worker /******************************************************************************
2*15dc779aSAndroid Build Coastguard Worker * *
3*15dc779aSAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
4*15dc779aSAndroid Build Coastguard Worker *
5*15dc779aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*15dc779aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*15dc779aSAndroid Build Coastguard Worker * You may obtain a copy of the License at:
8*15dc779aSAndroid Build Coastguard Worker *
9*15dc779aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*15dc779aSAndroid Build Coastguard Worker *
11*15dc779aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*15dc779aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*15dc779aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*15dc779aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*15dc779aSAndroid Build Coastguard Worker * limitations under the License.
16*15dc779aSAndroid Build Coastguard Worker *
17*15dc779aSAndroid Build Coastguard Worker *****************************************************************************
18*15dc779aSAndroid Build Coastguard Worker * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*15dc779aSAndroid Build Coastguard Worker */
20*15dc779aSAndroid Build Coastguard Worker
21*15dc779aSAndroid Build Coastguard Worker #include <math.h>
22*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_type_def.h"
23*15dc779aSAndroid Build Coastguard Worker #include "iusace_bitbuffer.h"
24*15dc779aSAndroid Build Coastguard Worker #include "iusace_cnst.h"
25*15dc779aSAndroid Build Coastguard Worker #include "iusace_tns_usac.h"
26*15dc779aSAndroid Build Coastguard Worker #include "iusace_psy_mod.h"
27*15dc779aSAndroid Build Coastguard Worker #include "iusace_block_switch_const.h"
28*15dc779aSAndroid Build Coastguard Worker #include "iusace_rom.h"
29*15dc779aSAndroid Build Coastguard Worker
iusace_lpc_eval_chebyshev_polyn(FLOAT32 x,FLOAT32 * coefs,WORD32 order)30*15dc779aSAndroid Build Coastguard Worker static FLOAT32 iusace_lpc_eval_chebyshev_polyn(FLOAT32 x, FLOAT32 *coefs, WORD32 order) {
31*15dc779aSAndroid Build Coastguard Worker WORD32 i;
32*15dc779aSAndroid Build Coastguard Worker FLOAT32 b0, b1, b2, x2;
33*15dc779aSAndroid Build Coastguard Worker x2 = 2.0f * x;
34*15dc779aSAndroid Build Coastguard Worker b2 = 1.0f;
35*15dc779aSAndroid Build Coastguard Worker b1 = x2 + coefs[1];
36*15dc779aSAndroid Build Coastguard Worker for (i = 2; i < order; i++) {
37*15dc779aSAndroid Build Coastguard Worker b0 = x2 * b1 - b2 + coefs[i];
38*15dc779aSAndroid Build Coastguard Worker b2 = b1;
39*15dc779aSAndroid Build Coastguard Worker b1 = b0;
40*15dc779aSAndroid Build Coastguard Worker }
41*15dc779aSAndroid Build Coastguard Worker return (x * b1 - b2 + 0.5f * coefs[order]);
42*15dc779aSAndroid Build Coastguard Worker }
43*15dc779aSAndroid Build Coastguard Worker
iusace_lpc_2_lsp_conversion(FLOAT32 * lpc,FLOAT32 * lsp,FLOAT32 * prev_lsp)44*15dc779aSAndroid Build Coastguard Worker VOID iusace_lpc_2_lsp_conversion(FLOAT32 *lpc, FLOAT32 *lsp, FLOAT32 *prev_lsp) {
45*15dc779aSAndroid Build Coastguard Worker FLOAT32 sum_polyn[(ORDER_BY_2) + 1], diff_polyn[(ORDER_BY_2) + 1];
46*15dc779aSAndroid Build Coastguard Worker FLOAT32 *p1_lpc, *p2_lpc, *p_sum_polyn, *p_diff_polyn;
47*15dc779aSAndroid Build Coastguard Worker WORD32 i, j = 0, num_found_freeq = 0, is_first_polyn = 0;
48*15dc779aSAndroid Build Coastguard Worker FLOAT32 x_low, y_low, x_high, y_high, x_mid, y_mid, x_lin_interp;
49*15dc779aSAndroid Build Coastguard Worker
50*15dc779aSAndroid Build Coastguard Worker p_sum_polyn = sum_polyn;
51*15dc779aSAndroid Build Coastguard Worker p_diff_polyn = diff_polyn;
52*15dc779aSAndroid Build Coastguard Worker *p_sum_polyn++ = 1.0f;
53*15dc779aSAndroid Build Coastguard Worker *p_diff_polyn++ = 1.0f;
54*15dc779aSAndroid Build Coastguard Worker sum_polyn[0] = 1.0f;
55*15dc779aSAndroid Build Coastguard Worker diff_polyn[0] = 1.0f;
56*15dc779aSAndroid Build Coastguard Worker p1_lpc = lpc + 1;
57*15dc779aSAndroid Build Coastguard Worker p2_lpc = lpc + ORDER;
58*15dc779aSAndroid Build Coastguard Worker for (i = 0; i <= ORDER_BY_2 - 1; i++) {
59*15dc779aSAndroid Build Coastguard Worker *p_sum_polyn = *p1_lpc + *p2_lpc - *(p_sum_polyn - 1);
60*15dc779aSAndroid Build Coastguard Worker p_sum_polyn++;
61*15dc779aSAndroid Build Coastguard Worker *p_diff_polyn = *p1_lpc++ - *p2_lpc-- + *(p_diff_polyn - 1);
62*15dc779aSAndroid Build Coastguard Worker p_diff_polyn++;
63*15dc779aSAndroid Build Coastguard Worker }
64*15dc779aSAndroid Build Coastguard Worker p_sum_polyn = sum_polyn;
65*15dc779aSAndroid Build Coastguard Worker x_low = iusace_chebyshev_polyn_grid[0];
66*15dc779aSAndroid Build Coastguard Worker y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
67*15dc779aSAndroid Build Coastguard Worker
68*15dc779aSAndroid Build Coastguard Worker while ((num_found_freeq < ORDER) && (j < CHEBYSHEV_NUM_POINTS)) {
69*15dc779aSAndroid Build Coastguard Worker j++;
70*15dc779aSAndroid Build Coastguard Worker x_high = x_low;
71*15dc779aSAndroid Build Coastguard Worker y_high = y_low;
72*15dc779aSAndroid Build Coastguard Worker x_low = iusace_chebyshev_polyn_grid[j];
73*15dc779aSAndroid Build Coastguard Worker y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
74*15dc779aSAndroid Build Coastguard Worker
75*15dc779aSAndroid Build Coastguard Worker if (y_low * y_high <= 0.0) /* if sign change new root exists */
76*15dc779aSAndroid Build Coastguard Worker {
77*15dc779aSAndroid Build Coastguard Worker j--;
78*15dc779aSAndroid Build Coastguard Worker for (i = 0; i < CHEBYSHEV_NUM_ITER; i++) {
79*15dc779aSAndroid Build Coastguard Worker x_mid = 0.5f * (x_low + x_high);
80*15dc779aSAndroid Build Coastguard Worker y_mid = iusace_lpc_eval_chebyshev_polyn(x_mid, p_sum_polyn, ORDER_BY_2);
81*15dc779aSAndroid Build Coastguard Worker if (y_low * y_mid <= 0.0) {
82*15dc779aSAndroid Build Coastguard Worker y_high = y_mid;
83*15dc779aSAndroid Build Coastguard Worker x_high = x_mid;
84*15dc779aSAndroid Build Coastguard Worker } else {
85*15dc779aSAndroid Build Coastguard Worker y_low = y_mid;
86*15dc779aSAndroid Build Coastguard Worker x_low = x_mid;
87*15dc779aSAndroid Build Coastguard Worker }
88*15dc779aSAndroid Build Coastguard Worker }
89*15dc779aSAndroid Build Coastguard Worker
90*15dc779aSAndroid Build Coastguard Worker /* linear interpolation for evaluating the root */
91*15dc779aSAndroid Build Coastguard Worker x_lin_interp = x_low - y_low * (x_high - x_low) / (y_high - y_low);
92*15dc779aSAndroid Build Coastguard Worker
93*15dc779aSAndroid Build Coastguard Worker lsp[num_found_freeq] = x_lin_interp;
94*15dc779aSAndroid Build Coastguard Worker num_found_freeq++;
95*15dc779aSAndroid Build Coastguard Worker
96*15dc779aSAndroid Build Coastguard Worker is_first_polyn = 1 - is_first_polyn;
97*15dc779aSAndroid Build Coastguard Worker p_sum_polyn = is_first_polyn ? diff_polyn : sum_polyn;
98*15dc779aSAndroid Build Coastguard Worker
99*15dc779aSAndroid Build Coastguard Worker x_low = x_lin_interp;
100*15dc779aSAndroid Build Coastguard Worker y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
101*15dc779aSAndroid Build Coastguard Worker }
102*15dc779aSAndroid Build Coastguard Worker }
103*15dc779aSAndroid Build Coastguard Worker
104*15dc779aSAndroid Build Coastguard Worker /* Check if ORDER roots found */
105*15dc779aSAndroid Build Coastguard Worker /* if not use the LSPs from previous frame */
106*15dc779aSAndroid Build Coastguard Worker if (num_found_freeq < ORDER) {
107*15dc779aSAndroid Build Coastguard Worker for (i = 0; i < ORDER; i++) lsp[i] = prev_lsp[i];
108*15dc779aSAndroid Build Coastguard Worker }
109*15dc779aSAndroid Build Coastguard Worker }
110*15dc779aSAndroid Build Coastguard Worker
iusace_compute_coeff_poly_f(FLOAT32 * lsp,FLOAT32 * poly1,FLOAT32 * poly2)111*15dc779aSAndroid Build Coastguard Worker static VOID iusace_compute_coeff_poly_f(FLOAT32 *lsp, FLOAT32 *poly1, FLOAT32 *poly2) {
112*15dc779aSAndroid Build Coastguard Worker FLOAT32 b1, b2;
113*15dc779aSAndroid Build Coastguard Worker FLOAT32 *ptr_lsp;
114*15dc779aSAndroid Build Coastguard Worker WORD32 i, j;
115*15dc779aSAndroid Build Coastguard Worker
116*15dc779aSAndroid Build Coastguard Worker ptr_lsp = lsp;
117*15dc779aSAndroid Build Coastguard Worker poly1[0] = poly2[0] = 1.0f;
118*15dc779aSAndroid Build Coastguard Worker
119*15dc779aSAndroid Build Coastguard Worker for (i = 1; i <= ORDER_BY_2; i++) {
120*15dc779aSAndroid Build Coastguard Worker b1 = -2.0f * (*ptr_lsp++);
121*15dc779aSAndroid Build Coastguard Worker b2 = -2.0f * (*ptr_lsp++);
122*15dc779aSAndroid Build Coastguard Worker poly1[i] = (b1 * poly1[i - 1]) + (2.0f * poly1[i - 2]);
123*15dc779aSAndroid Build Coastguard Worker poly2[i] = (b2 * poly2[i - 1]) + (2.0f * poly2[i - 2]);
124*15dc779aSAndroid Build Coastguard Worker for (j = i - 1; j > 0; j--) {
125*15dc779aSAndroid Build Coastguard Worker poly1[j] += (b1 * poly1[j - 1]) + poly1[j - 2];
126*15dc779aSAndroid Build Coastguard Worker poly2[j] += (b2 * poly2[j - 1]) + poly2[j - 2];
127*15dc779aSAndroid Build Coastguard Worker }
128*15dc779aSAndroid Build Coastguard Worker }
129*15dc779aSAndroid Build Coastguard Worker }
130*15dc779aSAndroid Build Coastguard Worker
iusace_lsp_to_lp_conversion(FLOAT32 * lsp,FLOAT32 * lp_flt_coff_a)131*15dc779aSAndroid Build Coastguard Worker VOID iusace_lsp_to_lp_conversion(FLOAT32 *lsp, FLOAT32 *lp_flt_coff_a) {
132*15dc779aSAndroid Build Coastguard Worker WORD32 i;
133*15dc779aSAndroid Build Coastguard Worker FLOAT32 *ppoly_f1, *ppoly_f2;
134*15dc779aSAndroid Build Coastguard Worker FLOAT32 *plp_flt_coff_a_bott, *plp_flt_coff_a_top;
135*15dc779aSAndroid Build Coastguard Worker FLOAT32 poly1[ORDER_BY_2 + 2], poly2[ORDER_BY_2 + 2];
136*15dc779aSAndroid Build Coastguard Worker
137*15dc779aSAndroid Build Coastguard Worker poly1[0] = 0.0f;
138*15dc779aSAndroid Build Coastguard Worker poly2[0] = 0.0f;
139*15dc779aSAndroid Build Coastguard Worker
140*15dc779aSAndroid Build Coastguard Worker iusace_compute_coeff_poly_f(lsp, &poly1[1], &poly2[1]);
141*15dc779aSAndroid Build Coastguard Worker
142*15dc779aSAndroid Build Coastguard Worker ppoly_f1 = poly1 + ORDER_BY_2 + 1;
143*15dc779aSAndroid Build Coastguard Worker ppoly_f2 = poly2 + ORDER_BY_2 + 1;
144*15dc779aSAndroid Build Coastguard Worker
145*15dc779aSAndroid Build Coastguard Worker for (i = 0; i < ORDER_BY_2; i++) {
146*15dc779aSAndroid Build Coastguard Worker ppoly_f1[0] += ppoly_f1[-1];
147*15dc779aSAndroid Build Coastguard Worker ppoly_f2[0] -= ppoly_f2[-1];
148*15dc779aSAndroid Build Coastguard Worker ppoly_f1--;
149*15dc779aSAndroid Build Coastguard Worker ppoly_f2--;
150*15dc779aSAndroid Build Coastguard Worker }
151*15dc779aSAndroid Build Coastguard Worker
152*15dc779aSAndroid Build Coastguard Worker plp_flt_coff_a_bott = lp_flt_coff_a;
153*15dc779aSAndroid Build Coastguard Worker *plp_flt_coff_a_bott++ = 1.0f;
154*15dc779aSAndroid Build Coastguard Worker plp_flt_coff_a_top = lp_flt_coff_a + ORDER;
155*15dc779aSAndroid Build Coastguard Worker ppoly_f1 = poly1 + 2;
156*15dc779aSAndroid Build Coastguard Worker ppoly_f2 = poly2 + 2;
157*15dc779aSAndroid Build Coastguard Worker for (i = 0; i < ORDER_BY_2; i++) {
158*15dc779aSAndroid Build Coastguard Worker *plp_flt_coff_a_bott++ = 0.5f * (*ppoly_f1 + *ppoly_f2);
159*15dc779aSAndroid Build Coastguard Worker *plp_flt_coff_a_top-- = 0.5f * (*ppoly_f1++ - *ppoly_f2++);
160*15dc779aSAndroid Build Coastguard Worker }
161*15dc779aSAndroid Build Coastguard Worker }
162*15dc779aSAndroid Build Coastguard Worker
iusace_levinson_durbin_algo(FLOAT32 * auto_corr_input,FLOAT32 * lpc)163*15dc779aSAndroid Build Coastguard Worker VOID iusace_levinson_durbin_algo(FLOAT32 *auto_corr_input, FLOAT32 *lpc) {
164*15dc779aSAndroid Build Coastguard Worker WORD32 i, j;
165*15dc779aSAndroid Build Coastguard Worker FLOAT32 lpc_val, sum, sigma;
166*15dc779aSAndroid Build Coastguard Worker FLOAT32 reflection_coeffs[LEV_DUR_MAX_ORDER];
167*15dc779aSAndroid Build Coastguard Worker
168*15dc779aSAndroid Build Coastguard Worker lpc[0] = 1.0f;
169*15dc779aSAndroid Build Coastguard Worker
170*15dc779aSAndroid Build Coastguard Worker reflection_coeffs[0] = -auto_corr_input[1] / auto_corr_input[0];
171*15dc779aSAndroid Build Coastguard Worker lpc[1] = reflection_coeffs[0];
172*15dc779aSAndroid Build Coastguard Worker sigma = auto_corr_input[0] + auto_corr_input[1] * reflection_coeffs[0];
173*15dc779aSAndroid Build Coastguard Worker
174*15dc779aSAndroid Build Coastguard Worker for (i = 2; i <= ORDER; i++) {
175*15dc779aSAndroid Build Coastguard Worker sum = 0.0f;
176*15dc779aSAndroid Build Coastguard Worker for (j = 0; j < i; j++) sum += auto_corr_input[i - j] * lpc[j];
177*15dc779aSAndroid Build Coastguard Worker reflection_coeffs[i - 1] = -sum / sigma;
178*15dc779aSAndroid Build Coastguard Worker
179*15dc779aSAndroid Build Coastguard Worker sigma = sigma * (1.0f - reflection_coeffs[i - 1] * reflection_coeffs[i - 1]);
180*15dc779aSAndroid Build Coastguard Worker
181*15dc779aSAndroid Build Coastguard Worker if (sigma <= 1.0E-09f) {
182*15dc779aSAndroid Build Coastguard Worker for (j = i; j <= ORDER; j++) {
183*15dc779aSAndroid Build Coastguard Worker reflection_coeffs[j - 1] = 0.0f;
184*15dc779aSAndroid Build Coastguard Worker lpc[j] = 0.0f;
185*15dc779aSAndroid Build Coastguard Worker }
186*15dc779aSAndroid Build Coastguard Worker break;
187*15dc779aSAndroid Build Coastguard Worker }
188*15dc779aSAndroid Build Coastguard Worker
189*15dc779aSAndroid Build Coastguard Worker for (j = 1; j <= (i / 2); j++) {
190*15dc779aSAndroid Build Coastguard Worker lpc_val = lpc[j] + reflection_coeffs[i - 1] * lpc[i - j];
191*15dc779aSAndroid Build Coastguard Worker lpc[i - j] += reflection_coeffs[i - 1] * lpc[j];
192*15dc779aSAndroid Build Coastguard Worker lpc[j] = lpc_val;
193*15dc779aSAndroid Build Coastguard Worker }
194*15dc779aSAndroid Build Coastguard Worker
195*15dc779aSAndroid Build Coastguard Worker lpc[i] = reflection_coeffs[i - 1];
196*15dc779aSAndroid Build Coastguard Worker }
197*15dc779aSAndroid Build Coastguard Worker }
198*15dc779aSAndroid Build Coastguard Worker
iusace_get_weighted_lpc(FLOAT32 * lpc,FLOAT32 * weighted_lpc)199*15dc779aSAndroid Build Coastguard Worker VOID iusace_get_weighted_lpc(FLOAT32 *lpc, FLOAT32 *weighted_lpc) {
200*15dc779aSAndroid Build Coastguard Worker WORD32 i;
201*15dc779aSAndroid Build Coastguard Worker for (i = 0; i <= ORDER; i++) {
202*15dc779aSAndroid Build Coastguard Worker weighted_lpc[i] = iusace_gamma_table[i] * lpc[i];
203*15dc779aSAndroid Build Coastguard Worker }
204*15dc779aSAndroid Build Coastguard Worker }
205*15dc779aSAndroid Build Coastguard Worker
iusace_lsp_2_lsf_conversion(FLOAT32 * lsp,FLOAT32 * lsf)206*15dc779aSAndroid Build Coastguard Worker VOID iusace_lsp_2_lsf_conversion(FLOAT32 *lsp, FLOAT32 *lsf) {
207*15dc779aSAndroid Build Coastguard Worker WORD32 i;
208*15dc779aSAndroid Build Coastguard Worker for (i = 0; i < ORDER; i++) {
209*15dc779aSAndroid Build Coastguard Worker lsf[i] = (FLOAT32)(acos(lsp[i]) * LSP_2_LSF_SCALE);
210*15dc779aSAndroid Build Coastguard Worker }
211*15dc779aSAndroid Build Coastguard Worker }
212*15dc779aSAndroid Build Coastguard Worker
iusace_lsf_2_lsp_conversion(FLOAT32 * lsf,FLOAT32 * lsp)213*15dc779aSAndroid Build Coastguard Worker VOID iusace_lsf_2_lsp_conversion(FLOAT32 *lsf, FLOAT32 *lsp) {
214*15dc779aSAndroid Build Coastguard Worker WORD32 i;
215*15dc779aSAndroid Build Coastguard Worker for (i = 0; i < ORDER; i++) lsp[i] = (FLOAT32)cos((FLOAT64)lsf[i] * (FLOAT64)PI_BY_6400);
216*15dc779aSAndroid Build Coastguard Worker }
217