/src/libxaac/encoder/ixheaace_cplx_pred.c
Line | Count | Source |
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 <string.h> |
23 | | #include <float.h> |
24 | | #include "iusace_type_def.h" |
25 | | #include "ixheaac_error_standards.h" |
26 | | #include "ixheaace_error_codes.h" |
27 | | #include "ixheaace_mps_common_define.h" |
28 | | #include "iusace_cnst.h" |
29 | | #include "iusace_fd_quant.h" |
30 | | #include "iusace_bitbuffer.h" |
31 | | #include "impd_drc_common_enc.h" |
32 | | #include "impd_drc_uni_drc.h" |
33 | | #include "impd_drc_api.h" |
34 | | #include "impd_drc_uni_drc_eq.h" |
35 | | #include "impd_drc_uni_drc_filter_bank.h" |
36 | | #include "impd_drc_gain_enc.h" |
37 | | #include "impd_drc_struct_def.h" |
38 | | |
39 | | #include "ixheaace_memory_standards.h" |
40 | | #include "iusace_tns_usac.h" |
41 | | #include "iusace_psy_mod.h" |
42 | | #include "iusace_config.h" |
43 | | #include "iusace_block_switch_const.h" |
44 | | #include "iusace_block_switch_struct_def.h" |
45 | | #include "iusace_signal_classifier.h" |
46 | | #include "iusace_ms.h" |
47 | | #include "ixheaace_adjust_threshold_data.h" |
48 | | #include "iusace_fd_qc_util.h" |
49 | | #include "ixheaace_sbr_header.h" |
50 | | #include "ixheaace_config.h" |
51 | | #include "ixheaace_asc_write.h" |
52 | | #include "iusace_main.h" |
53 | | #include "iusace_rom.h" |
54 | | #include "ixheaace_common_utils.h" |
55 | | |
56 | | static VOID iusace_compute_pred_coef(WORD32 num_lines, WORD32 complex_coef, |
57 | | FLOAT64 *ptr_spec_mdct_dmx, FLOAT64 *ptr_spec_mdst_dmx, |
58 | | FLOAT64 *ptr_spec_mdct_mid_side, FLOAT32 *pred_coef_re, |
59 | | FLOAT32 *pred_coef_im, FLOAT32 *pred_coef_q_re, |
60 | | FLOAT32 *pred_coef_q_im, WORD32 *pred_coef_q_int_re, |
61 | 816k | WORD32 *pred_coef_q_int_im) { |
62 | 816k | LOOPIDX bin_idx; |
63 | 816k | FLOAT32 iprod_re = 0.0f, iprod_im = 0.0f; |
64 | 816k | FLOAT32 eps = 1.0e-6f; |
65 | 816k | const FLOAT32 k_delta = 0.1f; |
66 | 816k | const FLOAT32 k_max = 3.0f; |
67 | 816k | WORD32 pred_coef_sign_re, pred_coef_sign_im; |
68 | 816k | FLOAT32 pred_coef_abs_re, pred_coef_abs_im; |
69 | 816k | FLOAT32 abs_dmx = 0.0f; |
70 | | |
71 | 29.8M | for (bin_idx = 0; bin_idx < num_lines; bin_idx++) { |
72 | | /* D = Dr + jDi */ |
73 | | /* D*S = (Dr + jDi)*S = Dr*S + j(Di*S) */ |
74 | | /* alpha = alpha_r - jalpha_i */ |
75 | 29.0M | if (complex_coef == 1) { |
76 | 2.52M | iprod_re += (FLOAT32)(ptr_spec_mdct_dmx[bin_idx] * ptr_spec_mdct_mid_side[bin_idx]); |
77 | 2.52M | iprod_im += (FLOAT32)(ptr_spec_mdst_dmx[bin_idx] * ptr_spec_mdct_mid_side[bin_idx]); |
78 | 2.52M | abs_dmx += (FLOAT32)(ptr_spec_mdct_dmx[bin_idx] * ptr_spec_mdct_dmx[bin_idx] + |
79 | 2.52M | ptr_spec_mdst_dmx[bin_idx] * ptr_spec_mdst_dmx[bin_idx]); |
80 | 26.5M | } else { |
81 | 26.5M | iprod_re += (FLOAT32)(ptr_spec_mdct_dmx[bin_idx] * ptr_spec_mdct_mid_side[bin_idx]); |
82 | 26.5M | abs_dmx += (FLOAT32)(ptr_spec_mdct_dmx[bin_idx] * ptr_spec_mdct_dmx[bin_idx]); |
83 | 26.5M | } |
84 | 29.0M | } |
85 | | |
86 | | /* Compute real and imaginary parts of prediction coefficient */ |
87 | 816k | *pred_coef_re = iprod_re / (abs_dmx + eps); |
88 | 816k | pred_coef_sign_re = *pred_coef_re > 0 ? 1 : -1; |
89 | 816k | pred_coef_abs_re = (FLOAT32)MIN(fabs(*pred_coef_re), k_max); |
90 | 816k | *pred_coef_q_int_re = pred_coef_sign_re * (WORD32)(pred_coef_abs_re / k_delta + 0.5f); |
91 | 816k | *pred_coef_q_re = *pred_coef_q_int_re * k_delta; |
92 | | |
93 | 816k | if (complex_coef == 1) { |
94 | 75.3k | *pred_coef_im = iprod_im / (abs_dmx + eps); |
95 | 75.3k | pred_coef_sign_im = *pred_coef_im > 0 ? 1 : -1; |
96 | 75.3k | pred_coef_abs_im = (FLOAT32)MIN(fabs(*pred_coef_im), k_max); |
97 | 75.3k | *pred_coef_q_int_im = pred_coef_sign_im * (WORD32)(pred_coef_abs_im / k_delta + 0.5f); |
98 | 75.3k | *pred_coef_q_im = *pred_coef_q_int_im * k_delta; |
99 | 75.3k | } |
100 | 816k | } |
101 | | |
102 | | static VOID iusace_compute_res(WORD32 num_lines, WORD32 complex_coef, FLOAT32 pred_coef_q_re, |
103 | | FLOAT32 pred_coef_q_im, FLOAT64 *ptr_spec_mdct_dmx, |
104 | | FLOAT64 *ptr_spec_mdst_dmx, FLOAT64 *ptr_spec_mdct_mid_side, |
105 | 816k | FLOAT64 *ptr_spec_mdct_res) { |
106 | 816k | LOOPIDX i; |
107 | | |
108 | 29.8M | for (i = 0; i < num_lines; i++) { |
109 | | /* DMX = M; E = S - alpha*DMX if pred_dir = 0 */ |
110 | | /* DMX = S; E = M - alpha*DMX if pred_dir = 1 */ |
111 | 29.0M | if (complex_coef == 1) { |
112 | 2.52M | ptr_spec_mdct_res[i] = |
113 | 2.52M | (FLOAT32)(ptr_spec_mdct_mid_side[i] - pred_coef_q_re * ptr_spec_mdct_dmx[i] - |
114 | 2.52M | pred_coef_q_im * ptr_spec_mdst_dmx[i]); |
115 | 26.5M | } else { |
116 | 26.5M | ptr_spec_mdct_res[i] = |
117 | 26.5M | (FLOAT32)(ptr_spec_mdct_mid_side[i] - pred_coef_q_re * ptr_spec_mdct_dmx[i]); |
118 | 26.5M | } |
119 | 29.0M | } |
120 | 816k | } |
121 | | |
122 | | static VOID iusace_filter_and_add(const FLOAT64 *ptr_in, const WORD32 length, |
123 | | const FLOAT64 *ptr_filter, FLOAT64 *ptr_out, |
124 | 37.8k | const WORD32 factor_even) { |
125 | 37.8k | LOOPIDX i; |
126 | 37.8k | FLOAT64 s; |
127 | | |
128 | 37.8k | i = 0; |
129 | 37.8k | s = ptr_filter[6] * ptr_in[2] + ptr_filter[5] * ptr_in[1] + ptr_filter[4] * ptr_in[0] + |
130 | 37.8k | ptr_filter[3] * ptr_in[0] + ptr_filter[2] * ptr_in[1] + ptr_filter[1] * ptr_in[2] + |
131 | 37.8k | ptr_filter[0] * ptr_in[3]; |
132 | 37.8k | ptr_out[i] += s * factor_even; |
133 | 37.8k | i = 1; |
134 | 37.8k | s = ptr_filter[6] * ptr_in[1] + ptr_filter[5] * ptr_in[0] + ptr_filter[4] * ptr_in[0] + |
135 | 37.8k | ptr_filter[3] * ptr_in[1] + ptr_filter[2] * ptr_in[2] + ptr_filter[1] * ptr_in[3] + |
136 | 37.8k | ptr_filter[0] * ptr_in[4]; |
137 | 37.8k | ptr_out[i] += s; |
138 | 37.8k | i = 2; |
139 | 37.8k | s = ptr_filter[6] * ptr_in[0] + ptr_filter[5] * ptr_in[0] + ptr_filter[4] * ptr_in[1] + |
140 | 37.8k | ptr_filter[3] * ptr_in[2] + ptr_filter[2] * ptr_in[3] + ptr_filter[1] * ptr_in[4] + |
141 | 37.8k | ptr_filter[0] * ptr_in[5]; |
142 | 37.8k | ptr_out[i] += s * factor_even; |
143 | | |
144 | 2.42M | for (i = 3; i < length - 4; i += 2) { |
145 | 2.38M | s = ptr_filter[6] * ptr_in[i - 3] + ptr_filter[5] * ptr_in[i - 2] + |
146 | 2.38M | ptr_filter[4] * ptr_in[i - 1] + ptr_filter[3] * ptr_in[i] + |
147 | 2.38M | ptr_filter[2] * ptr_in[i + 1] + ptr_filter[1] * ptr_in[i + 2] + |
148 | 2.38M | ptr_filter[0] * ptr_in[i + 3]; |
149 | 2.38M | ptr_out[i] += s; |
150 | 2.38M | s = ptr_filter[6] * ptr_in[i - 2] + ptr_filter[5] * ptr_in[i - 1] + |
151 | 2.38M | ptr_filter[4] * ptr_in[i] + ptr_filter[3] * ptr_in[i + 1] + |
152 | 2.38M | ptr_filter[2] * ptr_in[i + 2] + ptr_filter[1] * ptr_in[i + 3] + |
153 | 2.38M | ptr_filter[0] * ptr_in[i + 4]; |
154 | 2.38M | ptr_out[i + 1] += s * factor_even; |
155 | 2.38M | } |
156 | | |
157 | 37.8k | i = length - 3; |
158 | 37.8k | s = ptr_filter[6] * ptr_in[i - 3] + ptr_filter[5] * ptr_in[i - 2] + |
159 | 37.8k | ptr_filter[4] * ptr_in[i - 1] + ptr_filter[3] * ptr_in[i] + ptr_filter[2] * ptr_in[i + 1] + |
160 | 37.8k | ptr_filter[1] * ptr_in[i + 2] + ptr_filter[0] * ptr_in[i + 2]; |
161 | 37.8k | ptr_out[i] += s; |
162 | 37.8k | i = length - 2; |
163 | 37.8k | s = ptr_filter[6] * ptr_in[i - 3] + ptr_filter[5] * ptr_in[i - 2] + |
164 | 37.8k | ptr_filter[4] * ptr_in[i - 1] + ptr_filter[3] * ptr_in[i] + ptr_filter[2] * ptr_in[i + 1] + |
165 | 37.8k | ptr_filter[1] * ptr_in[i + 1] + ptr_filter[0] * ptr_in[i]; |
166 | 37.8k | ptr_out[i] += s * factor_even; |
167 | 37.8k | i = length - 1; |
168 | 37.8k | s = ptr_filter[6] * ptr_in[i - 3] + ptr_filter[5] * ptr_in[i - 2] + |
169 | 37.8k | ptr_filter[4] * ptr_in[i - 1] + ptr_filter[3] * ptr_in[i] + ptr_filter[2] * ptr_in[i] + |
170 | 37.8k | ptr_filter[1] * ptr_in[i - 1] + ptr_filter[0] * ptr_in[i - 2]; |
171 | 37.8k | ptr_out[i] += s; |
172 | 37.8k | } |
173 | | |
174 | | static VOID iusace_estimate_dmx_im(const FLOAT64 *ptr_dmx_re, const FLOAT64 *ptr_dmx_re_prev, |
175 | | FLOAT64 *ptr_dmx_im, WORD32 window, const WORD32 w_shape, |
176 | | const WORD32 prev_w_shape, WORD32 num_sbk, |
177 | 2.96k | WORD32 bins_per_sbk) { |
178 | 2.96k | LOOPIDX i; |
179 | 2.96k | const FLOAT64 *ptr_mdst_fcoeff_curr, *ptr_mdst_fcoeff_prev; |
180 | | |
181 | 2.96k | switch (window) { |
182 | 363 | case ONLY_LONG_SEQUENCE: |
183 | 2.66k | case EIGHT_SHORT_SEQUENCE: |
184 | 2.66k | ptr_mdst_fcoeff_curr = iusace_mdst_fcoeff_longshort_curr[prev_w_shape][w_shape]; |
185 | 2.66k | ptr_mdst_fcoeff_prev = iusace_mdst_fcoeff_l_s_start_left_prev[prev_w_shape]; |
186 | 2.66k | break; |
187 | 99 | case LONG_START_SEQUENCE: |
188 | 99 | ptr_mdst_fcoeff_curr = iusace_mdst_fcoeff_start_curr[prev_w_shape][w_shape]; |
189 | 99 | ptr_mdst_fcoeff_prev = iusace_mdst_fcoeff_l_s_start_left_prev[prev_w_shape]; |
190 | 99 | break; |
191 | 205 | case LONG_STOP_SEQUENCE: |
192 | 205 | ptr_mdst_fcoeff_curr = iusace_mdst_fcoeff_stop_cur[prev_w_shape][w_shape]; |
193 | 205 | ptr_mdst_fcoeff_prev = iusace_mdst_fcoeff_stop_stopstart_left_prev[prev_w_shape]; |
194 | 205 | break; |
195 | 0 | case STOP_START_SEQUENCE: |
196 | 0 | ptr_mdst_fcoeff_curr = iusace_mdst_fcoeff_stopstart_cur[prev_w_shape][w_shape]; |
197 | 0 | ptr_mdst_fcoeff_prev = iusace_mdst_fcoeff_stop_stopstart_left_prev[prev_w_shape]; |
198 | 0 | break; |
199 | 0 | default: |
200 | 0 | ptr_mdst_fcoeff_curr = iusace_mdst_fcoeff_stopstart_cur[prev_w_shape][w_shape]; |
201 | 0 | ptr_mdst_fcoeff_prev = iusace_mdst_fcoeff_stop_stopstart_left_prev[prev_w_shape]; |
202 | 0 | break; |
203 | 2.96k | } |
204 | | |
205 | 22.0k | for (i = 0; i < num_sbk; i++) { |
206 | 19.0k | iusace_filter_and_add(ptr_dmx_re, bins_per_sbk, ptr_mdst_fcoeff_curr, ptr_dmx_im, 1); |
207 | | |
208 | 19.0k | if (ptr_dmx_re_prev) { |
209 | 18.8k | iusace_filter_and_add(ptr_dmx_re_prev, bins_per_sbk, ptr_mdst_fcoeff_prev, ptr_dmx_im, -1); |
210 | 18.8k | } |
211 | | |
212 | 19.0k | ptr_dmx_re_prev = ptr_dmx_re; |
213 | 19.0k | ptr_dmx_re += bins_per_sbk; |
214 | 19.0k | ptr_dmx_im += bins_per_sbk; |
215 | 19.0k | } |
216 | 2.96k | return; |
217 | 2.96k | } |
218 | | |
219 | | static VOID iusace_usac_cplx_save_prev(FLOAT64 *ptr_mdct_spec, FLOAT64 *ptr_mdct_spec_prev, |
220 | | WORD32 save_zeros, WORD32 condition_2, WORD32 samp_per_bk, |
221 | 2.96k | WORD32 bins_per_sbk) { |
222 | 2.96k | WORD32 offset; |
223 | | |
224 | 2.96k | offset = samp_per_bk - bins_per_sbk; |
225 | | |
226 | 2.96k | if (save_zeros || condition_2) { |
227 | 203 | memset(ptr_mdct_spec_prev + offset, 0, sizeof(FLOAT64) * bins_per_sbk); |
228 | 2.76k | } else { |
229 | 2.76k | memcpy(ptr_mdct_spec_prev + offset, ptr_mdct_spec + offset, sizeof(FLOAT64) * bins_per_sbk); |
230 | 2.76k | } |
231 | 2.96k | return; |
232 | 2.96k | } |
233 | | |
234 | | static FLOAT64 iusace_compute_ipd(FLOAT64 *ptr_spec_real1, FLOAT64 *ptr_spec_imag1, |
235 | | FLOAT64 *ptr_spec_real2, FLOAT64 *ptr_spec_imag2, |
236 | 34.9k | WORD32 num_lines) { |
237 | 34.9k | LOOPIDX i; |
238 | | |
239 | 34.9k | FLOAT64 ipd = 0.0f; |
240 | 34.9k | FLOAT64 cross_corr_real = 0.0f, cross_corr_imag = 0.0f; |
241 | | |
242 | 29.8M | for (i = 0; i < num_lines; i++) { |
243 | 29.7M | cross_corr_real += |
244 | 29.7M | ptr_spec_real1[i] * ptr_spec_real2[i] + ptr_spec_imag1[i] * ptr_spec_imag2[i]; |
245 | 29.7M | cross_corr_imag += |
246 | 29.7M | -ptr_spec_imag2[i] * ptr_spec_real1[i] + ptr_spec_imag1[i] * ptr_spec_real2[i]; |
247 | 29.7M | } |
248 | | |
249 | 34.9k | ipd = (FLOAT64)atan2(cross_corr_imag, cross_corr_real); |
250 | 34.9k | ipd = ipd > 0 ? ipd : 2. * PI + ipd; |
251 | | |
252 | 34.9k | return ipd; |
253 | 34.9k | } |
254 | | |
255 | | static IA_ERRORCODE iusace_cplx_pred_main( |
256 | | WORD32 num_sfb, WORD32 num_window_groups, FLOAT64 *ptr_spec_mdct_mid, |
257 | | FLOAT64 *ptr_spec_mdct_side, WORD32 pred_coef_q_int_re[MAX_SHORT_WINDOWS][MAX_SFB_LONG], |
258 | | WORD32 pred_coef_q_int_im[MAX_SHORT_WINDOWS][MAX_SFB_LONG], WORD32 *pred_dir, |
259 | | ia_usac_data_struct *pstr_usac_data, ia_sfb_params_struct *pstr_sfb_prms, |
260 | | WORD32 usac_independancy_flag, ia_usac_encoder_config_struct *pstr_usac_config, |
261 | | FLOAT64 *ptr_scratch_cmpx_mdct_buf, WORD32 cplx_pred_used[MAX_SHORT_WINDOWS][MAX_SFB_LONG], |
262 | | WORD32 chn, const WORD32 *ptr_sfb_offsets, FLOAT32 nrg_mid, FLOAT32 nrg_side, |
263 | 34.9k | WORD32 *ms_mask_flag) { |
264 | 34.9k | LOOPIDX group, sfb, i; |
265 | 34.9k | FLOAT32 pred_coef_re, pred_coef_im, pred_coef_q_re, pred_coef_q_im = 0.0f; |
266 | 34.9k | const WORD32 sfb_per_pred_band = 2; |
267 | 34.9k | WORD32 left = 0, right = 0, save_zeros = 0, condition_2 = 0, samp_per_bk = 0, bins_per_sbk = 0, |
268 | 34.9k | num_sbk = 0; |
269 | 34.9k | FLOAT64 *ptr_dmx_re_prev; |
270 | 34.9k | FLOAT64 *ptr_spec_mdct_res = &ptr_scratch_cmpx_mdct_buf[0]; |
271 | 34.9k | const WORD32 sfb_count = num_window_groups * num_sfb; |
272 | 34.9k | const WORD32 sfb_per_group = num_sfb; |
273 | 34.9k | WORD32 sfb_offsets = 0, zero_flag, spec_start, spec_end; |
274 | | |
275 | 34.9k | left = chn, right = chn + 1; |
276 | | |
277 | | /* Number of sub-blocks */ |
278 | 34.9k | if (pstr_usac_config->window_sequence[left] == EIGHT_SHORT_SEQUENCE) { |
279 | 17.9k | num_sbk = MAX_SHORT_WINDOWS; |
280 | 17.9k | } |
281 | 34.9k | if (pstr_usac_config->window_sequence[left] == ONLY_LONG_SEQUENCE || |
282 | 25.5k | pstr_usac_config->window_sequence[left] == LONG_START_SEQUENCE || |
283 | 22.5k | pstr_usac_config->window_sequence[left] == LONG_STOP_SEQUENCE || |
284 | 17.9k | pstr_usac_config->window_sequence[left] == STOP_START_SEQUENCE) { |
285 | 17.0k | num_sbk = 1; |
286 | 17.0k | } |
287 | | |
288 | 34.9k | if (num_sbk == 0) { |
289 | 0 | return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_NUM_SBK; |
290 | 0 | } |
291 | | |
292 | 34.9k | samp_per_bk = pstr_usac_config->ccfl; |
293 | 34.9k | bins_per_sbk = samp_per_bk / num_sbk; |
294 | | |
295 | | /* Compute prediction direction */ |
296 | 34.9k | if (nrg_mid >= nrg_side) { |
297 | 15.6k | *pred_dir = 0; |
298 | 19.3k | } else { |
299 | 19.3k | *pred_dir = 1; |
300 | 19.3k | } |
301 | | |
302 | 34.9k | if (pstr_usac_data->complex_coef[chn] == 1) { |
303 | 2.96k | save_zeros = ((pstr_usac_config->window_sequence[left] == EIGHT_SHORT_SEQUENCE && |
304 | 2.29k | pstr_usac_config->window_sequence[right] != EIGHT_SHORT_SEQUENCE) || |
305 | 2.96k | (pstr_usac_config->window_sequence[left] != EIGHT_SHORT_SEQUENCE && |
306 | 667 | pstr_usac_config->window_sequence[right] == EIGHT_SHORT_SEQUENCE)); |
307 | | |
308 | 2.96k | condition_2 = (usac_independancy_flag || pstr_usac_data->core_mode_prev[left] || |
309 | 2.76k | pstr_usac_data->core_mode_prev[right]); |
310 | | |
311 | | /* Compute current frame's MDST down-mix*/ |
312 | 2.96k | ptr_dmx_re_prev = !(usac_independancy_flag) ? pstr_usac_data->ptr_dmx_re_save[chn] : NULL; |
313 | | |
314 | 2.96k | memset(pstr_usac_data->ptr_dmx_im[chn], 0, sizeof(FLOAT64) * FRAME_LEN_LONG); |
315 | | |
316 | 2.96k | iusace_estimate_dmx_im(*pred_dir == 0 ? ptr_spec_mdct_mid : ptr_spec_mdct_side, |
317 | 2.96k | ptr_dmx_re_prev, pstr_usac_data->ptr_dmx_im[chn], |
318 | 2.96k | pstr_usac_config->window_sequence[left], |
319 | 2.96k | pstr_sfb_prms->window_shape[left], |
320 | 2.96k | pstr_usac_config->window_shape_prev[left], num_sbk, bins_per_sbk); |
321 | | |
322 | | /* MCLT of downmix = dmx_re + j*dmx_im */ |
323 | | /* Save MDCT down-mix for use as previous frame MDCT down-mix in the next frame */ |
324 | 2.96k | iusace_usac_cplx_save_prev(*pred_dir == 0 ? &ptr_spec_mdct_mid[0] : &ptr_spec_mdct_side[0], |
325 | 2.96k | pstr_usac_data->ptr_dmx_re_save[chn], save_zeros, condition_2, |
326 | 2.96k | samp_per_bk, bins_per_sbk); |
327 | 2.96k | } |
328 | | |
329 | | /* Reset buffer to zero */ |
330 | 314k | for (group = 0; group < MAX_SHORT_WINDOWS; group++) { |
331 | 279k | memset(pred_coef_q_int_re, 0, MAX_SFB_LONG * sizeof(WORD32)); |
332 | 279k | memset(pred_coef_q_int_im, 0, MAX_SFB_LONG * sizeof(WORD32)); |
333 | 279k | } |
334 | | |
335 | 34.9k | group = 0; |
336 | 121k | for (sfb = 0; sfb < sfb_count; sfb += sfb_per_group, group++) { |
337 | 903k | for (sfb_offsets = 0; sfb_offsets < sfb_per_group; sfb_offsets += sfb_per_pred_band) { |
338 | 816k | if (cplx_pred_used[group][sfb_offsets] == 1) { |
339 | 816k | zero_flag = (ptr_sfb_offsets[sfb + sfb_offsets + 1] != FRAME_LEN_LONG); |
340 | 816k | spec_start = ptr_sfb_offsets[sfb + sfb_offsets]; |
341 | 816k | spec_end = (zero_flag ? ptr_sfb_offsets[sfb + sfb_offsets + 2] |
342 | 816k | : ptr_sfb_offsets[sfb + sfb_offsets + 1]); |
343 | | |
344 | | /* Calculate prediction coefficients */ |
345 | 816k | iusace_compute_pred_coef( |
346 | 816k | spec_end - spec_start, pstr_usac_data->complex_coef[chn], |
347 | 816k | *pred_dir == 0 ? &ptr_spec_mdct_mid[spec_start] : &ptr_spec_mdct_side[spec_start], |
348 | 816k | pstr_usac_data->complex_coef[chn] == 1 ? &pstr_usac_data->ptr_dmx_im[chn][spec_start] |
349 | 816k | : NULL, |
350 | 816k | *pred_dir == 0 ? &ptr_spec_mdct_side[spec_start] : &ptr_spec_mdct_mid[spec_start], |
351 | 816k | &pred_coef_re, pstr_usac_data->complex_coef[chn] == 1 ? &pred_coef_im : NULL, |
352 | 816k | &pred_coef_q_re, pstr_usac_data->complex_coef[chn] == 1 ? &pred_coef_q_im : NULL, |
353 | 816k | &pred_coef_q_int_re[group][sfb_offsets], |
354 | 816k | pstr_usac_data->complex_coef[chn] == 1 ? &pred_coef_q_int_im[group][sfb_offsets] |
355 | 816k | : NULL); |
356 | | |
357 | | /* Calculate residual */ |
358 | 816k | iusace_compute_res( |
359 | 816k | spec_end - spec_start, pstr_usac_data->complex_coef[chn], pred_coef_q_re, |
360 | 816k | pstr_usac_data->complex_coef[chn] == 1 ? pred_coef_q_im : 0, |
361 | 816k | *pred_dir == 0 ? &ptr_spec_mdct_mid[spec_start] : &ptr_spec_mdct_side[spec_start], |
362 | 816k | pstr_usac_data->complex_coef[chn] == 1 ? &pstr_usac_data->ptr_dmx_im[chn][spec_start] |
363 | 816k | : NULL, |
364 | 816k | *pred_dir == 0 ? &ptr_spec_mdct_side[spec_start] : &ptr_spec_mdct_mid[spec_start], |
365 | 816k | &ptr_spec_mdct_res[spec_start]); |
366 | 816k | } |
367 | 816k | } |
368 | 86.3k | } |
369 | | |
370 | | /* Compute the prediction gain */ |
371 | 34.9k | FLOAT32 pred_gain = 0.f, nrg_res = 0.f; |
372 | 29.8M | for (i = 0; i < pstr_usac_config->ccfl; i++) { |
373 | 29.7M | nrg_res += (FLOAT32)(ptr_spec_mdct_res[i] * ptr_spec_mdct_res[i]); |
374 | 29.7M | } |
375 | 34.9k | pred_gain = 10.f * log10f(ixheaace_div32((*pred_dir == 0 ? nrg_side : nrg_mid), nrg_res)); |
376 | | /* Prediction gain in dB */ |
377 | | |
378 | 34.9k | if (pred_gain > 20.f) /* Retain complex prediction */ |
379 | 15.6k | { |
380 | 15.6k | if (*pred_dir == 1) { |
381 | 11.2M | for (i = 0; i < pstr_usac_config->ccfl; i++) { |
382 | 11.2M | ptr_spec_mdct_mid[i] = ptr_spec_mdct_side[i]; |
383 | 11.2M | ptr_spec_mdct_side[i] = ptr_spec_mdct_res[i]; |
384 | 11.2M | } |
385 | 13.8k | } else { |
386 | 1.73M | for (i = 0; i < pstr_usac_config->ccfl; i++) { |
387 | 1.73M | ptr_spec_mdct_side[i] = ptr_spec_mdct_res[i]; |
388 | 1.73M | } |
389 | 1.87k | } |
390 | 15.6k | } else /* Use M/S */ |
391 | 19.3k | { |
392 | 19.3k | *ms_mask_flag = 0; |
393 | | /* Revert spectra to L and R */ |
394 | 16.8M | for (i = 0; i < pstr_usac_config->ccfl; i++) { |
395 | 16.8M | ptr_spec_mdct_mid[i] = pstr_usac_data->left_chan_save[chn][i]; |
396 | 16.8M | ptr_spec_mdct_side[i] = pstr_usac_data->right_chan_save[chn][i]; |
397 | 16.8M | } |
398 | 19.3k | } |
399 | | |
400 | 34.9k | return IA_NO_ERROR; |
401 | 34.9k | } |
402 | | |
403 | | IA_ERRORCODE iusace_cplx_pred_proc( |
404 | | ia_usac_data_struct *pstr_usac_data, ia_usac_encoder_config_struct *pstr_usac_config, |
405 | | WORD32 usac_independancy_flag, ia_sfb_params_struct *pstr_sfb_prms, WORD32 chn, |
406 | | ia_psy_mod_data_struct *pstr_psy_data, const WORD32 *ptr_sfb_offsets, |
407 | 34.9k | FLOAT64 *ptr_scratch_cmpx_mdct_buf, FLOAT64 *ptr_ms_spec, FLOAT32 nrg_mid, FLOAT32 nrg_side) { |
408 | 34.9k | IA_ERRORCODE err_code; |
409 | 34.9k | FLOAT32 *ptr_sfb_enegry_left = pstr_psy_data[chn].ptr_sfb_energy_long; |
410 | 34.9k | FLOAT32 *ptr_sfb_energy_right = pstr_psy_data[chn + 1].ptr_sfb_energy_long; |
411 | 34.9k | const FLOAT32 *ptr_sfb_energy_mid = pstr_psy_data[chn].ptr_sfb_energy_long_ms; |
412 | 34.9k | const FLOAT32 *ptr_sfb_energy_side = pstr_psy_data[chn + 1].ptr_sfb_energy_long_ms; |
413 | 34.9k | FLOAT32 *ptr_sfb_thr_left = pstr_psy_data[chn].ptr_sfb_thr_long; |
414 | 34.9k | FLOAT32 *ptr_sfb_thr_right = pstr_psy_data[chn + 1].ptr_sfb_thr_long; |
415 | 34.9k | FLOAT32 *ptr_sfb_spread_energy_left = pstr_psy_data[chn].ptr_sfb_spreaded_energy_long; |
416 | 34.9k | FLOAT32 *ptr_sfb_spread_energy_right = pstr_psy_data[chn + 1].ptr_sfb_spreaded_energy_long; |
417 | 34.9k | WORD32 sfb, sfb_offsets; |
418 | 34.9k | WORD32 *ptr_num_sfb = pstr_sfb_prms->num_sfb; |
419 | 34.9k | WORD32 *ptr_num_window_groups = pstr_sfb_prms->num_window_groups; |
420 | 34.9k | const WORD32 sfb_count = ptr_num_window_groups[chn] * ptr_num_sfb[chn]; |
421 | 34.9k | const WORD32 sfb_per_group = ptr_num_sfb[chn]; |
422 | 34.9k | WORD32 grp = 0, i, zero_flag; |
423 | 34.9k | const WORD32 sfb_per_pred_band = 2; |
424 | 34.9k | FLOAT32 min_thr_1, min_thr_2 = 0.0f; |
425 | 34.9k | FLOAT32 temp_1 = 0, temp_2 = 0; |
426 | 34.9k | ia_ms_info_struct *pstr_ms_info = &pstr_usac_data->str_ms_info[chn]; |
427 | | |
428 | 34.9k | FLOAT64 ipd; |
429 | | /* Compute IPD between L and R channels */ |
430 | 34.9k | ipd = iusace_compute_ipd(&pstr_usac_data->spectral_line_vector[chn][0], |
431 | 34.9k | &pstr_usac_data->mdst_spectrum[chn][0], |
432 | 34.9k | &pstr_usac_data->spectral_line_vector[chn + 1][0], |
433 | 34.9k | &pstr_usac_data->mdst_spectrum[chn + 1][0], pstr_usac_config->ccfl); |
434 | | |
435 | | /* Decide value of complex_coef based on IPD */ |
436 | 34.9k | if ((ipd > (PI / 2 - 5 * PI / 180) && ipd < (PI / 2 + 5 * PI / 180)) || |
437 | 33.5k | (ipd > (3 * PI / 2 - 5 * PI / 180) && ipd < (3 * PI / 2 + 5 * PI / 180))) { |
438 | 2.96k | pstr_usac_data->complex_coef[chn] = 1; |
439 | 32.0k | } else { |
440 | 32.0k | pstr_usac_data->complex_coef[chn] = 0; |
441 | 32.0k | } |
442 | | |
443 | | /* Compute M and S spectra */ |
444 | 29.8M | for (i = 0; i < pstr_usac_config->ccfl; i++) { |
445 | 29.7M | pstr_usac_data->spectral_line_vector[chn][i] = ptr_ms_spec[i]; |
446 | 29.7M | pstr_usac_data->spectral_line_vector[chn + 1][i] = ptr_ms_spec[pstr_usac_config->ccfl + i]; |
447 | 29.7M | } |
448 | | |
449 | 34.9k | err_code = iusace_cplx_pred_main( |
450 | 34.9k | pstr_sfb_prms->num_sfb[chn], pstr_sfb_prms->num_window_groups[chn], |
451 | 34.9k | pstr_usac_data->spectral_line_vector[chn], pstr_usac_data->spectral_line_vector[chn + 1], |
452 | 34.9k | pstr_usac_data->pred_coef_re[chn], pstr_usac_data->pred_coef_im[chn], |
453 | 34.9k | &pstr_usac_data->pred_dir_idx[chn], pstr_usac_data, pstr_sfb_prms, usac_independancy_flag, |
454 | 34.9k | pstr_usac_config, ptr_scratch_cmpx_mdct_buf, pstr_usac_data->cplx_pred_used[chn], chn, |
455 | 34.9k | ptr_sfb_offsets, nrg_mid, nrg_side, &pstr_ms_info->ms_mask); |
456 | 34.9k | if (err_code != IA_NO_ERROR) { |
457 | 0 | return err_code; |
458 | 0 | } |
459 | | |
460 | 34.9k | if (pstr_ms_info->ms_mask == 3) { |
461 | | /* Compute thresholds required for quantization (similar to that in MS coding) */ |
462 | 54.1k | for (sfb = 0; sfb < sfb_count; sfb += sfb_per_group, grp++) { |
463 | 398k | for (sfb_offsets = 0; sfb_offsets < sfb_per_group; sfb_offsets += sfb_per_pred_band) { |
464 | 359k | if (pstr_usac_data->cplx_pred_used[chn][grp][sfb_offsets] == 1) { |
465 | 359k | zero_flag = (ptr_sfb_offsets[sfb + sfb_offsets + 1] != pstr_usac_config->ccfl); |
466 | 359k | min_thr_1 = |
467 | 359k | MIN(ptr_sfb_thr_left[sfb + sfb_offsets], ptr_sfb_thr_right[sfb + sfb_offsets]); |
468 | 359k | if (zero_flag) { |
469 | 351k | min_thr_2 = MIN(ptr_sfb_thr_left[sfb + sfb_offsets + 1], |
470 | 351k | ptr_sfb_thr_right[sfb + sfb_offsets + 1]); |
471 | 351k | } |
472 | | |
473 | 359k | ptr_sfb_thr_left[sfb + sfb_offsets] = ptr_sfb_thr_right[sfb + sfb_offsets] = min_thr_1; |
474 | 359k | ptr_sfb_enegry_left[sfb + sfb_offsets] = ptr_sfb_energy_mid[sfb + sfb_offsets]; |
475 | 359k | ptr_sfb_energy_right[sfb + sfb_offsets] = ptr_sfb_energy_side[sfb + sfb_offsets]; |
476 | 359k | if (zero_flag) { |
477 | 351k | ptr_sfb_thr_left[sfb + sfb_offsets + 1] = ptr_sfb_thr_right[sfb + sfb_offsets + 1] = |
478 | 351k | min_thr_2; |
479 | 351k | ptr_sfb_enegry_left[sfb + sfb_offsets + 1] = |
480 | 351k | ptr_sfb_energy_mid[sfb + sfb_offsets + 1]; |
481 | 351k | ptr_sfb_energy_right[sfb + sfb_offsets + 1] = |
482 | 351k | ptr_sfb_energy_side[sfb + sfb_offsets + 1]; |
483 | 351k | } |
484 | 359k | ptr_sfb_spread_energy_left[sfb + sfb_offsets] = |
485 | 359k | ptr_sfb_spread_energy_right[sfb + sfb_offsets] = |
486 | 359k | MIN(ptr_sfb_spread_energy_left[sfb + sfb_offsets], |
487 | 359k | ptr_sfb_spread_energy_right[sfb + sfb_offsets]) * |
488 | 359k | 0.5f; |
489 | 359k | if (zero_flag) { |
490 | 351k | ptr_sfb_spread_energy_left[sfb + sfb_offsets + 1] = |
491 | 351k | ptr_sfb_spread_energy_right[sfb + sfb_offsets + 1] = |
492 | 351k | MIN(ptr_sfb_spread_energy_left[sfb + sfb_offsets + 1], |
493 | 351k | ptr_sfb_spread_energy_right[sfb + sfb_offsets + 1]) * |
494 | 351k | 0.5f; |
495 | 351k | } |
496 | 359k | } |
497 | 359k | } |
498 | 38.4k | } |
499 | | |
500 | 15.6k | if (pstr_usac_data->pred_dir_idx[chn] == 1) { |
501 | 13.8k | grp = 0; |
502 | | |
503 | 46.8k | for (sfb = 0; sfb < sfb_count; sfb += sfb_per_group, grp++) { |
504 | 344k | for (sfb_offsets = 0; sfb_offsets < sfb_per_group; sfb_offsets += sfb_per_pred_band) { |
505 | 311k | zero_flag = (ptr_sfb_offsets[sfb + sfb_offsets + 1] != pstr_usac_config->ccfl); |
506 | | |
507 | 311k | if (pstr_usac_data->cplx_pred_used[chn][grp][sfb_offsets] == 1) { |
508 | 311k | temp_1 = ptr_sfb_enegry_left[sfb + sfb_offsets]; |
509 | 311k | ptr_sfb_enegry_left[sfb + sfb_offsets] = ptr_sfb_energy_right[sfb + sfb_offsets]; |
510 | 311k | ptr_sfb_energy_right[sfb + sfb_offsets] = temp_1; |
511 | 311k | if (zero_flag) { |
512 | 304k | temp_2 = ptr_sfb_enegry_left[sfb + sfb_offsets + 1]; |
513 | 304k | ptr_sfb_enegry_left[sfb + sfb_offsets + 1] = |
514 | 304k | ptr_sfb_energy_right[sfb + sfb_offsets + 1]; |
515 | 304k | ptr_sfb_energy_right[sfb + sfb_offsets + 1] = temp_2; |
516 | 304k | } |
517 | 311k | } |
518 | 311k | } |
519 | 33.0k | } |
520 | 13.8k | } |
521 | 15.6k | } |
522 | 34.9k | return IA_NO_ERROR; |
523 | 34.9k | } |