xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_tns_hp.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1 /******************************************************************************
2  *                                                                            *
3  * Copyright (C) 2023 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *****************************************************************************
18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19  */
20 
21 #include <math.h>
22 #include <stddef.h>
23 #include "ixheaac_type_def.h"
24 #include "ixheaac_constants.h"
25 #include "impd_drc_common_enc.h"
26 #include "impd_drc_uni_drc.h"
27 #include "impd_drc_tables.h"
28 #include "impd_drc_api.h"
29 #include "ixheaace_api.h"
30 #include "ixheaace_aac_constants.h"
31 #include "ixheaace_common_rom.h"
32 #include "ixheaace_psy_const.h"
33 #include "ixheaace_tns.h"
34 #include "ixheaace_tns_params.h"
35 #include "ixheaace_rom.h"
36 #include "ixheaace_bitbuffer.h"
37 #include "ixheaace_psy_configuration.h"
38 #include "ixheaace_tns_func.h"
39 #include "ixheaac_basic_ops32.h"
40 #include "ixheaac_basic_ops16.h"
41 #include "ixheaac_basic_ops40.h"
42 #include "ixheaac_basic_ops.h"
43 
ia_enhaacplus_enc_calc_weighted_spectrum(FLOAT32 * ptr_spectrum,FLOAT32 * ptr_weighted_spec,FLOAT32 * ptr_sfb_energy,const WORD32 * ptr_sfb_offset,WORD32 lpc_start_line,WORD32 lpc_stop_line,WORD32 lpc_start_band,WORD32 lpc_stop_band,FLOAT32 * ptr_shared_buffer1,WORD32 aot)44 VOID ia_enhaacplus_enc_calc_weighted_spectrum(FLOAT32 *ptr_spectrum, FLOAT32 *ptr_weighted_spec,
45                                               FLOAT32 *ptr_sfb_energy,
46                                               const WORD32 *ptr_sfb_offset, WORD32 lpc_start_line,
47                                               WORD32 lpc_stop_line, WORD32 lpc_start_band,
48                                               WORD32 lpc_stop_band, FLOAT32 *ptr_shared_buffer1,
49                                               WORD32 aot) {
50   WORD32 i, sfb, tempcnt;
51   FLOAT32 tmp;
52   FLOAT32 *ptr_tns_sfb_mean = ptr_shared_buffer1;
53   FLOAT32 temp1, temp2;
54   FLOAT32 *ptr_spec;
55   FLOAT32 *ptr_ws1;
56   WORD sfb_width, j;
57 
58   for (sfb = lpc_start_band; sfb < lpc_stop_band; sfb++) {
59     FLOAT32 sfb_nrg_tmp = ptr_sfb_energy[sfb];
60     ptr_tns_sfb_mean[sfb] = 1 / ((FLOAT32)sqrt(sfb_nrg_tmp) + 1e-30f);
61   }
62 
63   sfb = lpc_start_band;
64 
65   tmp = ptr_tns_sfb_mean[sfb];
66 
67   for (i = lpc_start_line; i < lpc_stop_line; i += sfb_width) {
68     ptr_spec = &ptr_weighted_spec[i];
69     WORD start = i, stop = ptr_sfb_offset[sfb + 1];
70 
71     stop = MIN(stop, lpc_stop_line);
72     sfb_width = stop - start;
73 
74     for (j = (sfb_width >> 1) - 1; j >= 0; j--) {
75       *ptr_spec++ = tmp;
76       *ptr_spec++ = tmp;
77     }
78     sfb++;
79 
80     if ((sfb + 1) < lpc_stop_band) {
81       tmp = ptr_tns_sfb_mean[sfb];
82     }
83   }
84 
85   /* Filter down */
86   if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS || aot == AOT_AAC_ELD) {
87     for (i = lpc_stop_line - 2; i >= lpc_start_line; i--) {
88       ptr_weighted_spec[i] = (ptr_weighted_spec[i] + ptr_weighted_spec[i + 1]) * 0.5f;
89     }
90     for (i = lpc_start_line + 1; i < lpc_stop_line; i++) {
91       ptr_weighted_spec[i] = (ptr_weighted_spec[i] + ptr_weighted_spec[i - 1]) * 0.5f;
92     }
93 
94     /* Weight and normalize */
95     for (i = lpc_start_line; i < lpc_stop_line; i++) {
96       ptr_weighted_spec[i] = ptr_weighted_spec[i] * ptr_spectrum[i];
97     }
98   } else if (aot == AOT_AAC_LD || aot == AOT_AAC_ELD) {
99     WORD32 remaining;
100     FLOAT32 multout_temp;
101 
102     ptr_ws1 = &ptr_weighted_spec[lpc_stop_line - 1];
103     tempcnt = (lpc_stop_line - lpc_start_line) >> 2;
104     remaining = lpc_stop_line - lpc_start_line - (tempcnt << 2);
105 
106     temp1 = *ptr_ws1--;
107     temp2 = (*ptr_ws1 + temp1);
108     for (i = tempcnt - 1; i >= 0; i--) {
109       *ptr_ws1-- = temp2;
110       temp1 = (*ptr_ws1 + temp2 * 0.5f);
111       *ptr_ws1-- = temp1;
112       temp2 = (*ptr_ws1 + temp1 * 0.5f);
113       *ptr_ws1-- = temp2;
114       temp1 = (*ptr_ws1 + temp2 * 0.5f);
115       *ptr_ws1-- = temp1;
116       temp2 = (*ptr_ws1 + temp1 * 0.5f);
117     }
118     ptr_ws1++;
119     if (remaining) {
120       for (i = remaining - 1; i >= 0; i--) {
121         temp1 = *ptr_ws1--;
122         *ptr_ws1 = (*ptr_ws1 + temp1 * 0.5f);
123       }
124     }
125 
126     ptr_weighted_spec[lpc_start_line + 1] = (FLOAT32)(
127         ((ptr_weighted_spec[lpc_start_line + 1]) + (ptr_weighted_spec[lpc_start_line])) * 0.5f);
128     multout_temp = (ptr_weighted_spec[lpc_start_line] * ptr_spectrum[lpc_start_line]);
129     ptr_weighted_spec[lpc_start_line] = multout_temp;
130 
131     /* Weight and normalize */
132     ptr_spec = &ptr_spectrum[lpc_start_line + 1];
133     ptr_ws1 = &ptr_weighted_spec[lpc_start_line + 1];
134 
135     tempcnt = (lpc_stop_line - lpc_start_line - 2) >> 2;
136     remaining = (lpc_stop_line - lpc_start_line - 2) - (tempcnt << 2);
137     temp2 = *ptr_ws1;
138 
139     for (i = tempcnt - 1; i >= 0; i--) {
140       temp1 = *(ptr_ws1 + 1);
141       temp1 = (FLOAT32)((temp1 + temp2) * 0.5f);
142       multout_temp = (temp2 * *ptr_spec++);
143       *ptr_ws1++ = multout_temp;
144 
145       temp2 = *(ptr_ws1 + 1);
146       temp2 = (FLOAT32)((temp2 + temp1) * 0.5f);
147       multout_temp = (temp1 * *ptr_spec++);
148       *ptr_ws1++ = multout_temp;
149 
150       temp1 = *(ptr_ws1 + 1);
151       temp1 = (FLOAT32)((temp2 + temp1) * 0.5f);
152       multout_temp = (temp2 * *ptr_spec++);
153       *ptr_ws1++ = multout_temp;
154 
155       temp2 = *(ptr_ws1 + 1);
156       temp2 = (FLOAT32)((temp2 + temp1) * 0.5f);
157       multout_temp = (temp1 * *ptr_spec++);
158       *ptr_ws1++ = multout_temp;
159     }
160 
161     if (remaining) {
162       for (i = remaining - 1; i >= 0; i--) {
163         temp1 = *(ptr_ws1 + 1);
164 
165         multout_temp = (temp2 * *ptr_spec++);
166         *ptr_ws1++ = multout_temp;
167         temp2 = (FLOAT32)((temp1 + temp2) * 0.5f);
168       }
169     }
170 
171     multout_temp = (temp2 + ptr_spectrum[lpc_stop_line - 1]);
172 
173     ptr_weighted_spec[lpc_stop_line - 1] = multout_temp;
174   }
175 }
176 
ia_enhaacplus_enc_auto_correlation(const FLOAT32 * ptr_input,FLOAT32 * ptr_corr,WORD32 samples,WORD32 corr_coeff)177 VOID ia_enhaacplus_enc_auto_correlation(const FLOAT32 *ptr_input, FLOAT32 *ptr_corr,
178                                         WORD32 samples, WORD32 corr_coeff) {
179   WORD32 i, j;
180   FLOAT32 tmp_var;
181   WORD32 remaining;
182   remaining = corr_coeff - ((corr_coeff >> 1) << 1);
183 
184   for (i = 0; i < samples; i += 2) {
185     const FLOAT32 *ptr_input1 = &ptr_input[i];
186     FLOAT32 temp1 = *ptr_input1;
187     FLOAT32 temp2 = *(ptr_input1 + 1);
188     FLOAT32 inp_tmp1 = *ptr_input1++;
189     for (j = 0; j < (corr_coeff >> 1) << 1; j++) {
190       FLOAT32 inp_tmp2;
191       tmp_var = (temp1 * inp_tmp1);
192       inp_tmp2 = *ptr_input1++;
193       tmp_var += (temp2 * inp_tmp2);
194       ptr_corr[j] += tmp_var;
195       j++;
196       tmp_var = (temp1 * inp_tmp2);
197       inp_tmp1 = *ptr_input1++;
198       tmp_var += (temp2 * inp_tmp1);
199       ptr_corr[j] += (tmp_var);
200     }
201     if (remaining) {
202       tmp_var = (temp1 * inp_tmp1);
203       tmp_var += (temp2 * *ptr_input1);
204       ptr_corr[j] += (tmp_var);
205     }
206   }
207 }
208 
ia_enhaacplus_enc_analysis_filter_lattice(const FLOAT32 * ptr_signal,WORD32 num_lines,const FLOAT32 * ptr_par_coeff,WORD32 order,FLOAT32 * ptr_output)209 VOID ia_enhaacplus_enc_analysis_filter_lattice(const FLOAT32 *ptr_signal, WORD32 num_lines,
210                                                const FLOAT32 *ptr_par_coeff, WORD32 order,
211                                                FLOAT32 *ptr_output) {
212   FLOAT32 state_par[TEMPORAL_NOISE_SHAPING_MAX_ORDER] = {0};
213   WORD32 j;
214 
215   if (order <= 0) {
216     return;
217   }
218 
219   for (j = 0; j < num_lines; j++) {
220     WORD32 i;
221     FLOAT32 x = ptr_signal[j];
222     FLOAT32 accu, tmp, tmp_save;
223 
224     tmp_save = x;
225     accu = x;
226 
227     for (i = 0; i < order - 1; i++) {
228       tmp = (accu * ptr_par_coeff[i]);
229 
230       tmp += state_par[i];
231 
232       accu += (state_par[i] * ptr_par_coeff[i]);
233 
234       state_par[i] = tmp_save;
235       tmp_save = tmp;
236     }
237 
238     /* last stage: only need half operations */
239     accu += (state_par[order - 1] * ptr_par_coeff[order - 1]);
240 
241     state_par[order - 1] = tmp_save;
242 
243     ptr_output[j] = accu;
244   }
245 }
246