/src/libxaac/encoder/iusace_lpd_utils.c
Line | Count | Source (jump to first uncovered line) |
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 <string.h> |
22 | | #include <math.h> |
23 | | #include "ixheaac_type_def.h" |
24 | | #include "ixheaace_adjust_threshold_data.h" |
25 | | #include "iusace_bitbuffer.h" |
26 | | |
27 | | /* DRC */ |
28 | | #include "impd_drc_common_enc.h" |
29 | | #include "impd_drc_uni_drc.h" |
30 | | #include "impd_drc_tables.h" |
31 | | #include "impd_drc_api.h" |
32 | | #include "impd_drc_uni_drc_eq.h" |
33 | | #include "impd_drc_uni_drc_filter_bank.h" |
34 | | #include "impd_drc_gain_enc.h" |
35 | | #include "impd_drc_struct_def.h" |
36 | | |
37 | | #include "iusace_cnst.h" |
38 | | #include "iusace_tns_usac.h" |
39 | | #include "iusace_psy_mod.h" |
40 | | #include "iusace_fd_qc_util.h" |
41 | | #include "iusace_tns_usac.h" |
42 | | #include "iusace_config.h" |
43 | | #include "iusace_arith_enc.h" |
44 | | #include "iusace_fd_quant.h" |
45 | | #include "iusace_block_switch_const.h" |
46 | | #include "iusace_block_switch_struct_def.h" |
47 | | #include "iusace_ms.h" |
48 | | #include "iusace_signal_classifier.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_func_prototypes.h" |
54 | | #include "iusace_lpd_rom.h" |
55 | | #include "ixheaace_common_utils.h" |
56 | | |
57 | 188k | WORD32 ia_get_sample_rate(WORD32 sample_rate) { |
58 | 188k | if (92017 <= sample_rate) { |
59 | 0 | return 11; |
60 | 0 | } |
61 | 188k | if (75132 <= sample_rate) { |
62 | 0 | return 10; |
63 | 0 | } |
64 | 188k | if (55426 <= sample_rate) { |
65 | 0 | return 9; |
66 | 0 | } |
67 | 188k | if (46009 <= sample_rate) { |
68 | 0 | return 8; |
69 | 0 | } |
70 | 188k | if (37566 <= sample_rate) { |
71 | 0 | return 7; |
72 | 0 | } |
73 | 188k | if (27713 <= sample_rate) { |
74 | 19.6k | return 6; |
75 | 19.6k | } |
76 | 169k | if (23004 <= sample_rate) { |
77 | 40.4k | return 5; |
78 | 40.4k | } |
79 | 128k | if (18783 <= sample_rate) { |
80 | 7.74k | return 4; |
81 | 7.74k | } |
82 | 120k | if (13856 <= sample_rate) { |
83 | 41.4k | return 3; |
84 | 41.4k | } |
85 | 79.4k | if (11502 <= sample_rate) { |
86 | 29.3k | return 2; |
87 | 29.3k | } |
88 | 50.0k | if (9391 <= sample_rate) { |
89 | 5.30k | return 1; |
90 | 5.30k | } |
91 | 44.7k | return 0; |
92 | 50.0k | } |
93 | | |
94 | 9.58M | VOID iusace_write_bits2buf(WORD32 value, WORD32 no_of_bits, WORD16 *bitstream) { |
95 | 9.58M | WORD16 *pt_bitstream; |
96 | 9.58M | WORD32 i; |
97 | 9.58M | pt_bitstream = bitstream + no_of_bits; |
98 | 52.0M | for (i = 0; i < no_of_bits; i++) { |
99 | 42.4M | *--pt_bitstream = (WORD16)(value & MASK); |
100 | 42.4M | value >>= 1; |
101 | 42.4M | } |
102 | 9.58M | return; |
103 | 9.58M | } |
104 | | |
105 | 1.13M | WORD32 iusace_get_num_params(WORD32 *qn) { |
106 | 1.13M | return 2 + ((qn[0] > 0) ? 9 : 0) + ((qn[1] > 0) ? 9 : 0); |
107 | 1.13M | } |
108 | | |
109 | 1.59M | FLOAT32 iusace_cal_segsnr(FLOAT32 *sig1, FLOAT32 *sig2, WORD16 len, WORD16 nseg) { |
110 | 1.59M | FLOAT32 snr = 0.0f; |
111 | 1.59M | FLOAT32 signal, noise, error, fac; |
112 | 1.59M | WORD16 i, j; |
113 | 10.8M | for (i = 0; i < len; i += nseg) { |
114 | 9.25M | signal = 1e-6f; |
115 | 9.25M | noise = 1e-6f; |
116 | 601M | for (j = 0; j < nseg; j++) { |
117 | 592M | signal += (*sig1) * (*sig1); |
118 | 592M | error = *sig1++ - *sig2++; |
119 | 592M | noise += error * error; |
120 | 592M | } |
121 | 9.25M | snr += (FLOAT32)log10((FLOAT64)(signal / noise)); |
122 | 9.25M | } |
123 | 1.59M | fac = ((FLOAT32)(10 * nseg)) / (FLOAT32)len; |
124 | 1.59M | snr = fac * snr; |
125 | 1.59M | if (snr < -99.0f) { |
126 | 14.9k | snr = -99.0f; |
127 | 14.9k | } |
128 | 1.59M | return (snr); |
129 | 1.59M | } |
130 | | |
131 | 188k | VOID iusace_highpass_50hz_12k8(FLOAT32 *signal, WORD32 lg, FLOAT32 *mem, WORD32 fscale) { |
132 | 188k | WORD32 i; |
133 | 188k | WORD32 sr_idx = 0; |
134 | 188k | FLOAT32 x0, x1, x2, y0, y1, y2; |
135 | 188k | const FLOAT32 *a = NULL, *b = NULL; |
136 | | |
137 | 188k | y1 = mem[0]; |
138 | 188k | y2 = mem[1]; |
139 | 188k | x0 = mem[2]; |
140 | 188k | x1 = mem[3]; |
141 | 188k | sr_idx = ia_get_sample_rate(fscale); |
142 | 188k | a = &iusace_hp20_filter_coeffs[sr_idx][0]; |
143 | 188k | b = &iusace_hp20_filter_coeffs[sr_idx][2]; |
144 | | |
145 | 176M | for (i = 0; i < lg; i++) { |
146 | 176M | x2 = x1; |
147 | 176M | x1 = x0; |
148 | 176M | x0 = signal[i]; |
149 | 176M | y0 = (y1 * a[0]) + (y2 * a[1]) + (x0 * b[1]) + (x1 * b[0]) + (x2 * b[1]); |
150 | 176M | signal[i] = y0; |
151 | 176M | y2 = y1; |
152 | 176M | y1 = y0; |
153 | 176M | } |
154 | | |
155 | 188k | mem[0] = ((y1 > 1e-10) | (y1 < -1e-10)) ? y1 : 0; |
156 | 188k | mem[1] = ((y2 > 1e-10) | (y2 < -1e-10)) ? y2 : 0; |
157 | 188k | mem[2] = ((x0 > 1e-10) | (x0 < -1e-10)) ? x0 : 0; |
158 | 188k | mem[3] = ((x1 > 1e-10) | (x1 < -1e-10)) ? x1 : 0; |
159 | 188k | } |
160 | | |
161 | 9.78M | VOID iusace_apply_preemph(FLOAT32 *signal, FLOAT32 factor, WORD32 length, FLOAT32 *mem) { |
162 | 9.78M | WORD32 i; |
163 | 9.78M | FLOAT32 temp; |
164 | 9.78M | temp = signal[length - 1]; |
165 | 1.08G | for (i = length - 1; i > 0; i--) { |
166 | 1.07G | signal[i] = signal[i] - factor * signal[i - 1]; |
167 | 1.07G | } |
168 | 9.78M | signal[0] -= factor * (*mem); |
169 | 9.78M | *mem = temp; |
170 | 9.78M | } |
171 | | |
172 | 18.1M | VOID iusace_apply_deemph(FLOAT32 *signal, FLOAT32 factor, WORD32 length, FLOAT32 *mem) { |
173 | 18.1M | WORD32 i; |
174 | 18.1M | signal[0] = signal[0] + factor * (*mem); |
175 | 2.59G | for (i = 1; i < length; i++) { |
176 | 2.57G | signal[i] = signal[i] + factor * signal[i - 1]; |
177 | 2.57G | } |
178 | 18.1M | *mem = signal[length - 1]; |
179 | 18.1M | if ((*mem < 1e-10) & (*mem > -1e-10)) { |
180 | 257k | *mem = 0; |
181 | 257k | } |
182 | 18.1M | } |
183 | | |
184 | | VOID iusace_synthesis_tool_float(FLOAT32 *a, FLOAT32 *x, FLOAT32 *y, WORD32 l, FLOAT32 *mem, |
185 | 14.1M | FLOAT32 *scratch_synth_tool) { |
186 | 14.1M | FLOAT32 s; |
187 | 14.1M | FLOAT32 *yy; |
188 | 14.1M | WORD32 i, j; |
189 | 14.1M | memcpy(scratch_synth_tool, mem, ORDER * sizeof(FLOAT32)); |
190 | 14.1M | yy = &scratch_synth_tool[ORDER]; |
191 | 1.06G | for (i = 0; i < l; i++) { |
192 | 1.05G | s = x[i]; |
193 | 5.27G | for (j = 1; j <= ORDER; j += 4) { |
194 | 4.22G | s -= a[j] * yy[i - j]; |
195 | 4.22G | s -= a[j + 1] * yy[i - (j + 1)]; |
196 | 4.22G | s -= a[j + 2] * yy[i - (j + 2)]; |
197 | 4.22G | s -= a[j + 3] * yy[i - (j + 3)]; |
198 | 4.22G | } |
199 | 1.05G | yy[i] = s; |
200 | 1.05G | y[i] = s; |
201 | 1.05G | } |
202 | 14.1M | } |
203 | | |
204 | 40.4M | VOID iusace_compute_lp_residual(FLOAT32 *a, FLOAT32 *x, FLOAT32 *y, WORD32 l) { |
205 | 40.4M | FLOAT32 s; |
206 | 40.4M | WORD32 i; |
207 | 2.65G | for (i = 0; i < l; i++) { |
208 | 2.60G | s = x[i]; |
209 | 2.60G | s += a[1] * x[i - 1]; |
210 | 2.60G | s += a[2] * x[i - 2]; |
211 | 2.60G | s += a[3] * x[i - 3]; |
212 | 2.60G | s += a[4] * x[i - 4]; |
213 | 2.60G | s += a[5] * x[i - 5]; |
214 | 2.60G | s += a[6] * x[i - 6]; |
215 | 2.60G | s += a[7] * x[i - 7]; |
216 | 2.60G | s += a[8] * x[i - 8]; |
217 | 2.60G | s += a[9] * x[i - 9]; |
218 | 2.60G | s += a[10] * x[i - 10]; |
219 | 2.60G | s += a[11] * x[i - 11]; |
220 | 2.60G | s += a[12] * x[i - 12]; |
221 | 2.60G | s += a[13] * x[i - 13]; |
222 | 2.60G | s += a[14] * x[i - 14]; |
223 | 2.60G | s += a[15] * x[i - 15]; |
224 | 2.60G | s += a[16] * x[i - 16]; |
225 | 2.60G | y[i] = s; |
226 | 2.60G | } |
227 | 40.4M | } |
228 | | |
229 | 8.04M | VOID iusace_convolve(FLOAT32 *signal, FLOAT32 *wsynth_filter_ir, FLOAT32 *conv_out) { |
230 | 8.04M | FLOAT32 temp; |
231 | 8.04M | WORD32 i, n; |
232 | 265M | for (n = 0; n < LEN_SUBFR; n += 2) { |
233 | 257M | temp = 0.0f; |
234 | 8.49G | for (i = 0; i <= n; i++) { |
235 | 8.23G | temp += signal[i] * wsynth_filter_ir[n - i]; |
236 | 8.23G | } |
237 | 257M | conv_out[n] = temp; |
238 | 257M | temp = 0.0f; |
239 | 4.50G | for (i = 0; i <= (n + 1); i += 2) { |
240 | 4.24G | temp += signal[i] * wsynth_filter_ir[(n + 1) - i]; |
241 | 4.24G | temp += signal[i + 1] * wsynth_filter_ir[n - i]; |
242 | 4.24G | } |
243 | 257M | conv_out[n + 1] = temp; |
244 | 257M | } |
245 | 8.04M | } |
246 | | |
247 | | VOID iusace_autocorr_plus(FLOAT32 *speech, FLOAT32 *auto_corr_vector, WORD32 window_len, |
248 | 722k | const FLOAT32 *lp_analysis_win, FLOAT32 *temp_aut_corr) { |
249 | 722k | FLOAT32 val; |
250 | 722k | WORD16 i, j; |
251 | 328M | for (i = 0; i < window_len; i++) { |
252 | 327M | temp_aut_corr[i] = speech[i] * lp_analysis_win[i]; |
253 | 327M | } |
254 | 13.0M | for (i = 0; i <= ORDER; i++) { |
255 | 12.2M | val = 0.0f; |
256 | 5.48G | for (j = 0; j < window_len - i; j++) { |
257 | 5.47G | val += temp_aut_corr[j] * temp_aut_corr[j + i]; |
258 | 5.47G | } |
259 | 12.2M | auto_corr_vector[i] = val; |
260 | 12.2M | } |
261 | 722k | if (auto_corr_vector[0] < 1.0) { |
262 | 22.0k | auto_corr_vector[0] = 1.0; |
263 | 22.0k | } |
264 | 722k | } |
265 | | |
266 | | static VOID iusace_get_norm_correlation(FLOAT32 *exc, FLOAT32 *xn, FLOAT32 *wsyn_filt_ir, |
267 | | WORD32 min_interval, WORD32 max_interval, |
268 | 2.68M | FLOAT32 *norm_corr) { |
269 | 2.68M | WORD32 i, j, k; |
270 | 2.68M | FLOAT32 filt_prev_exc[LEN_SUBFR]; |
271 | 2.68M | FLOAT32 energy_filt_exc, corr, norm; |
272 | 2.68M | k = -min_interval; |
273 | | |
274 | 2.68M | iusace_convolve(&exc[k], wsyn_filt_ir, filt_prev_exc); |
275 | | |
276 | 62.2M | for (i = min_interval; i <= max_interval; i++) { |
277 | 59.5M | corr = 0.0F; |
278 | 59.5M | energy_filt_exc = 0.01F; |
279 | 3.87G | for (j = 0; j < LEN_SUBFR; j++) { |
280 | 3.81G | corr += xn[j] * filt_prev_exc[j]; |
281 | 3.81G | energy_filt_exc += filt_prev_exc[j] * filt_prev_exc[j]; |
282 | 3.81G | } |
283 | | |
284 | 59.5M | norm = (FLOAT32)(1.0f / sqrt(energy_filt_exc)); |
285 | 59.5M | norm_corr[i - min_interval] = corr * norm; |
286 | | |
287 | 59.5M | if (i != max_interval) { |
288 | 56.8M | k--; |
289 | 3.64G | for (j = LEN_SUBFR - 1; j > 0; j--) { |
290 | 3.58G | filt_prev_exc[j] = filt_prev_exc[j - 1] + exc[k] * wsyn_filt_ir[j]; |
291 | 3.58G | } |
292 | 56.8M | filt_prev_exc[0] = exc[k]; |
293 | 56.8M | } |
294 | 59.5M | } |
295 | 2.68M | } |
296 | | |
297 | 14.5M | static FLOAT32 iusace_corr_interpolate(FLOAT32 *x, WORD32 fraction) { |
298 | 14.5M | FLOAT32 interpol_value, *x1, *x2; |
299 | 14.5M | const FLOAT32 *p1_interp4_1_table, *p2_interp4_1_table; |
300 | 14.5M | if (fraction < 0) { |
301 | 5.48M | fraction += 4; |
302 | 5.48M | x--; |
303 | 5.48M | } |
304 | 14.5M | x1 = &x[0]; |
305 | 14.5M | x2 = &x[1]; |
306 | 14.5M | p1_interp4_1_table = &iusace_interp4_1[fraction]; |
307 | 14.5M | p2_interp4_1_table = &iusace_interp4_1[4 - fraction]; |
308 | 14.5M | interpol_value = x1[0] * p1_interp4_1_table[0] + x2[0] * p2_interp4_1_table[0]; |
309 | 14.5M | interpol_value += x1[-1] * p1_interp4_1_table[4] + x2[1] * p2_interp4_1_table[4]; |
310 | 14.5M | interpol_value += x1[-2] * p1_interp4_1_table[8] + x2[2] * p2_interp4_1_table[8]; |
311 | 14.5M | interpol_value += x1[-3] * p1_interp4_1_table[12] + x2[3] * p2_interp4_1_table[12]; |
312 | | |
313 | 14.5M | return interpol_value; |
314 | 14.5M | } |
315 | | |
316 | | VOID iusace_open_loop_search(FLOAT32 *wsp, WORD32 min_pitch_lag, WORD32 max_pitch_lag, |
317 | | WORD32 num_frame, WORD32 *ol_pitch_lag, |
318 | 1.24M | ia_usac_td_encoder_struct *st) { |
319 | 1.24M | WORD32 i, j, k; |
320 | 1.24M | FLOAT32 r, corr, energy1, energy2, corr_max = -1.0e23f; |
321 | 1.24M | const FLOAT32 *p1_ol_cw_table, *p2_ol_cw_table; |
322 | 1.24M | FLOAT32 *data_a, *data_b, *hp_wsp, *p, *p1; |
323 | | |
324 | 1.24M | p1_ol_cw_table = &iusace_ol_corr_weight[453]; |
325 | 1.24M | p2_ol_cw_table = &iusace_ol_corr_weight[259 + max_pitch_lag - st->prev_pitch_med]; |
326 | 1.24M | *ol_pitch_lag = 0; |
327 | 167M | for (i = max_pitch_lag; i > min_pitch_lag; i--) { |
328 | 166M | p = &wsp[0]; |
329 | 166M | p1 = &wsp[-i]; |
330 | 166M | corr = 0.0; |
331 | 5.91G | for (j = 0; j < num_frame; j += 2) { |
332 | 5.74G | corr += p[j] * p1[j]; |
333 | 5.74G | corr += p[j + 1] * p1[j + 1]; |
334 | 5.74G | } |
335 | 166M | corr *= *p1_ol_cw_table--; |
336 | 166M | if ((st->prev_pitch_med > 0) && (st->ol_wght_flg == 1)) { |
337 | 37.5M | corr *= *p2_ol_cw_table--; |
338 | 37.5M | } |
339 | 166M | if (corr >= corr_max) { |
340 | 64.5M | corr_max = corr; |
341 | 64.5M | *ol_pitch_lag = i; |
342 | 64.5M | } |
343 | 166M | } |
344 | 1.24M | data_a = st->hp_ol_ltp_mem; |
345 | 1.24M | data_b = st->hp_ol_ltp_mem + HP_ORDER; |
346 | 1.24M | hp_wsp = st->prev_hp_wsp + max_pitch_lag; |
347 | 87.0M | for (k = 0; k < num_frame; k++) { |
348 | 85.7M | data_b[0] = data_b[1]; |
349 | 85.7M | data_b[1] = data_b[2]; |
350 | 85.7M | data_b[2] = data_b[3]; |
351 | 85.7M | data_b[HP_ORDER] = wsp[k]; |
352 | 85.7M | r = data_b[0] * 0.83787057505665F; |
353 | 85.7M | r += data_b[1] * -2.50975570071058F; |
354 | 85.7M | r += data_b[2] * 2.50975570071058F; |
355 | 85.7M | r += data_b[3] * -0.83787057505665F; |
356 | 85.7M | r -= data_a[0] * -2.64436711600664F; |
357 | 85.7M | r -= data_a[1] * 2.35087386625360F; |
358 | 85.7M | r -= data_a[2] * -0.70001156927424F; |
359 | 85.7M | data_a[2] = data_a[1]; |
360 | 85.7M | data_a[1] = data_a[0]; |
361 | 85.7M | data_a[0] = r; |
362 | 85.7M | hp_wsp[k] = r; |
363 | 85.7M | } |
364 | 1.24M | p = &hp_wsp[0]; |
365 | 1.24M | p1 = &hp_wsp[-(*ol_pitch_lag)]; |
366 | 1.24M | corr = 0.0F; |
367 | 1.24M | energy1 = 0.0F; |
368 | 1.24M | energy2 = 0.0F; |
369 | 87.0M | for (j = 0; j < num_frame; j++) { |
370 | 85.7M | energy1 += p1[j] * p1[j]; |
371 | 85.7M | energy2 += p[j] * p[j]; |
372 | 85.7M | corr += p[j] * p1[j]; |
373 | 85.7M | } |
374 | 1.24M | st->ol_gain = (FLOAT32)(corr / (sqrt(energy1 * energy2) + 1e-5)); |
375 | 1.24M | memmove(st->prev_hp_wsp, &st->prev_hp_wsp[num_frame], max_pitch_lag * sizeof(FLOAT32)); |
376 | 1.24M | } |
377 | | |
378 | 133k | WORD32 iusace_get_ol_lag_median(WORD32 prev_ol_lag, WORD32 *prev_ol_lags) { |
379 | 133k | WORD32 sorted_ol_lags_out[NUM_OPEN_LOOP_LAGS + 1] = {0}; |
380 | 133k | WORD32 i, j, idx, val; |
381 | 133k | WORD32 num_lags = NUM_OPEN_LOOP_LAGS; |
382 | 667k | for (i = NUM_OPEN_LOOP_LAGS - 1; i > 0; i--) { |
383 | 533k | prev_ol_lags[i] = prev_ol_lags[i - 1]; |
384 | 533k | } |
385 | 133k | prev_ol_lags[0] = prev_ol_lag; |
386 | 800k | for (i = 0; i < NUM_OPEN_LOOP_LAGS; i++) { |
387 | 667k | sorted_ol_lags_out[i + 1] = prev_ol_lags[i]; |
388 | 667k | } |
389 | | |
390 | 133k | idx = (NUM_OPEN_LOOP_LAGS >> 1) + 1; |
391 | 800k | for (;;) { |
392 | 800k | if (idx > 1) { |
393 | 266k | val = sorted_ol_lags_out[--idx]; |
394 | 533k | } else { |
395 | 533k | val = sorted_ol_lags_out[num_lags]; |
396 | 533k | sorted_ol_lags_out[num_lags] = sorted_ol_lags_out[1]; |
397 | 533k | if (--num_lags == 1) { |
398 | 133k | sorted_ol_lags_out[1] = val; |
399 | 133k | break; |
400 | 133k | } |
401 | 533k | } |
402 | 667k | i = idx; |
403 | 667k | j = idx << 1; |
404 | 1.43M | while (j <= num_lags) { |
405 | 766k | if (j < num_lags && sorted_ol_lags_out[j] < sorted_ol_lags_out[j + 1]) { |
406 | 84.9k | ++j; |
407 | 84.9k | } |
408 | 766k | if (val < sorted_ol_lags_out[j]) { |
409 | 264k | sorted_ol_lags_out[i] = sorted_ol_lags_out[j]; |
410 | 264k | i = j; |
411 | 264k | j *= 2; |
412 | 502k | } else { |
413 | 502k | j = num_lags + 1; |
414 | 502k | } |
415 | 766k | } |
416 | 667k | sorted_ol_lags_out[i] = val; |
417 | 667k | } |
418 | | |
419 | 133k | return sorted_ol_lags_out[OPEN_LOOP_LAG_MEDIAN]; |
420 | 133k | } |
421 | | |
422 | | VOID iusace_closed_loop_search(FLOAT32 *exc, FLOAT32 *xn, FLOAT32 *wsyn_filt_ir, |
423 | | WORD32 search_range_min, WORD32 search_range_max, WORD32 *pit_frac, |
424 | | WORD32 is_first_subfrm, WORD32 min_pitch_lag_res1_2, |
425 | 2.68M | WORD32 min_pitch_lag_res_1, WORD32 *pitch_lag_out) { |
426 | 2.68M | WORD32 i, fraction, step; |
427 | 2.68M | FLOAT32 corr_vector[15 + 2 * LEN_INTERPOL1 + 1] = {0}; |
428 | 2.68M | FLOAT32 corr_max, temp; |
429 | 2.68M | FLOAT32 *p_norm_corr_vector; |
430 | 2.68M | WORD32 min_interval, max_interval; |
431 | 2.68M | min_interval = search_range_min - LEN_INTERPOL1; |
432 | 2.68M | max_interval = search_range_max + LEN_INTERPOL1; |
433 | 2.68M | p_norm_corr_vector = &corr_vector[0]; |
434 | 2.68M | iusace_get_norm_correlation(exc, xn, wsyn_filt_ir, min_interval, max_interval, |
435 | 2.68M | p_norm_corr_vector); |
436 | | |
437 | 2.68M | corr_max = p_norm_corr_vector[LEN_INTERPOL1]; |
438 | 2.68M | *pitch_lag_out = search_range_min; |
439 | 38.1M | for (i = search_range_min + 1; i <= search_range_max; i++) { |
440 | 35.4M | if (p_norm_corr_vector[i - search_range_min + LEN_INTERPOL1] > corr_max) { |
441 | 9.37M | corr_max = p_norm_corr_vector[i - search_range_min + LEN_INTERPOL1]; |
442 | 9.37M | *pitch_lag_out = i; |
443 | 9.37M | } |
444 | 35.4M | } |
445 | 2.68M | if ((is_first_subfrm == 0) && (*pitch_lag_out >= min_pitch_lag_res_1)) { |
446 | 343k | *pit_frac = 0; |
447 | 2.33M | } else { |
448 | 2.33M | step = 1; |
449 | 2.33M | fraction = -3; |
450 | 2.33M | if (((is_first_subfrm == 0) && (*pitch_lag_out >= min_pitch_lag_res1_2)) || |
451 | 2.33M | (min_pitch_lag_res1_2 == TMIN)) { |
452 | 136k | step = 2; |
453 | 136k | fraction = -2; |
454 | 136k | } |
455 | 2.33M | if (*pitch_lag_out == search_range_min) { |
456 | 426k | fraction = 0; |
457 | 426k | } |
458 | 2.33M | corr_max = iusace_corr_interpolate( |
459 | 2.33M | &p_norm_corr_vector[(*pitch_lag_out) - search_range_min + LEN_INTERPOL1], fraction); |
460 | 14.5M | for (i = (fraction + step); i <= 3; i += step) { |
461 | 12.2M | temp = iusace_corr_interpolate( |
462 | 12.2M | &p_norm_corr_vector[(*pitch_lag_out) - search_range_min + LEN_INTERPOL1], i); |
463 | 12.2M | if (temp > corr_max) { |
464 | 5.95M | corr_max = temp; |
465 | 5.95M | fraction = i; |
466 | 5.95M | } |
467 | 12.2M | } |
468 | 2.33M | if (fraction < 0) { |
469 | 571k | fraction += 4; |
470 | 571k | (*pitch_lag_out) -= 1; |
471 | 571k | } |
472 | 2.33M | *pit_frac = fraction; |
473 | 2.33M | } |
474 | 2.68M | } |
475 | | |
476 | | VOID iusace_decim2_fir_filter(FLOAT32 *signal, WORD32 length, FLOAT32 *mem, |
477 | 727k | FLOAT32 *scratch_fir_sig_buf) { |
478 | 727k | FLOAT32 *sig_buf = scratch_fir_sig_buf; |
479 | 727k | FLOAT32 temp; |
480 | 727k | WORD32 i, j; |
481 | 727k | memcpy(sig_buf, mem, DECIM2_FIR_FILT_MEM_SIZE * sizeof(FLOAT32)); |
482 | 727k | memcpy(sig_buf + DECIM2_FIR_FILT_MEM_SIZE, signal, length * sizeof(FLOAT32)); |
483 | 2.90M | for (i = 0; i < DECIM2_FIR_FILT_MEM_SIZE; i++) { |
484 | 2.18M | mem[i] = ((signal[length - DECIM2_FIR_FILT_MEM_SIZE + i] > 1e-10) || |
485 | 2.18M | (signal[length - DECIM2_FIR_FILT_MEM_SIZE + i] < -1e-10)) |
486 | 2.18M | ? signal[length - DECIM2_FIR_FILT_MEM_SIZE + i] |
487 | 2.18M | : 0; |
488 | 2.18M | } |
489 | 87.6M | for (i = 0, j = 0; i < length; i += 2, j++) { |
490 | 86.8M | temp = sig_buf[i] * 0.13F; |
491 | 86.8M | temp += sig_buf[i + 1] * 0.23F; |
492 | 86.8M | temp += sig_buf[i + 2] * 0.28F; |
493 | | #ifdef _WIN32 |
494 | | #pragma warning(suppress : 6385) |
495 | | #endif |
496 | 86.8M | temp += sig_buf[i + 3] * 0.23F; |
497 | 86.8M | temp += sig_buf[i + 4] * 0.13F; |
498 | 86.8M | signal[j] = temp; |
499 | 86.8M | } |
500 | 727k | } |
501 | | |
502 | | FLOAT32 iusace_calc_sq_gain(FLOAT32 *x, WORD32 num_bits, WORD32 length, |
503 | 1.01M | FLOAT32 *scratch_sq_gain_en) { |
504 | 1.01M | WORD32 i, j, k; |
505 | 1.01M | FLOAT32 gain, ener, temp, target, factor, offset; |
506 | 1.01M | FLOAT32 *en = scratch_sq_gain_en; |
507 | | |
508 | 104M | for (i = 0; i < length; i += 4) { |
509 | 103M | ener = 0.01f; |
510 | 518M | for (j = i; j < i + 4; j++) { |
511 | 414M | ener += x[j] * x[j]; |
512 | 414M | } |
513 | | |
514 | 103M | temp = (FLOAT32)log10(ener); |
515 | 103M | en[i / 4] = 9.0f + 10.0f * temp; |
516 | 103M | } |
517 | | |
518 | 1.01M | target = (6.0f / 4.0f) * (FLOAT32)(num_bits - (length / 16)); |
519 | | |
520 | 1.01M | factor = 128.0f; |
521 | 1.01M | offset = factor; |
522 | | |
523 | 11.2M | for (k = 0; k < 10; k++) { |
524 | 10.1M | factor *= 0.5f; |
525 | 10.1M | offset -= factor; |
526 | 10.1M | ener = 0.0f; |
527 | 1.04G | for (i = 0; i < length / 4; i++) { |
528 | 1.03G | temp = en[i] - offset; |
529 | | |
530 | 1.03G | if (temp > 3.0f) { |
531 | 555M | ener += temp; |
532 | 555M | } |
533 | 1.03G | } |
534 | 10.1M | if (ener > target) { |
535 | 4.81M | offset += factor; |
536 | 4.81M | } |
537 | 10.1M | } |
538 | | |
539 | 1.01M | gain = (FLOAT32)pow(10.0f, offset / 20.0f); |
540 | | |
541 | 1.01M | return (gain); |
542 | 1.01M | } |
543 | | |
544 | | VOID iusace_lpc_coef_gen(FLOAT32 *lsf_old, FLOAT32 *lsf_new, FLOAT32 *a, WORD32 nb_subfr, |
545 | 1.01M | WORD32 m) { |
546 | 1.01M | FLOAT32 lsf[ORDER] = {0}, *ptr_a; |
547 | 1.01M | FLOAT32 inc, fnew, fold; |
548 | 1.01M | WORD32 i = 0; |
549 | | |
550 | 1.01M | ptr_a = a; |
551 | | |
552 | 1.01M | inc = 1.0f / (FLOAT32)nb_subfr; |
553 | 1.01M | fnew = 0.5f - (0.5f * inc); |
554 | 1.01M | fold = 1.0f - fnew; |
555 | 17.2M | for (i = 0; i < m; i++) { |
556 | 16.1M | lsf[i] = (lsf_old[i] * fold) + (lsf_new[i] * fnew); |
557 | 16.1M | } |
558 | 1.01M | iusace_lsp_to_lp_conversion(lsf, ptr_a); |
559 | 1.01M | ptr_a += (m + 1); |
560 | 1.01M | iusace_lsp_to_lp_conversion(lsf_old, ptr_a); |
561 | 1.01M | ptr_a += (m + 1); |
562 | 1.01M | iusace_lsp_to_lp_conversion(lsf_new, ptr_a); |
563 | | |
564 | 1.01M | return; |
565 | 1.01M | } |
566 | | |
567 | | VOID iusace_interpolation_lsp_params(FLOAT32 *lsp_old, FLOAT32 *lsp_new, FLOAT32 *lp_flt_coff_a, |
568 | 1.43M | WORD32 nb_subfr) { |
569 | 1.43M | FLOAT32 lsp[ORDER]; |
570 | 1.43M | FLOAT32 factor; |
571 | 1.43M | WORD32 i, k; |
572 | 1.43M | FLOAT32 x_plus_y, x_minus_y; |
573 | | |
574 | 1.43M | factor = 1.0f / (FLOAT32)nb_subfr; |
575 | | |
576 | 1.43M | x_plus_y = 0.5f * factor; |
577 | | |
578 | 6.79M | for (k = 0; k < nb_subfr; k++) { |
579 | 5.36M | x_minus_y = 1.0f - x_plus_y; |
580 | 91.1M | for (i = 0; i < ORDER; i++) { |
581 | 85.7M | lsp[i] = (lsp_old[i] * x_minus_y) + (lsp_new[i] * x_plus_y); |
582 | 85.7M | } |
583 | 5.36M | x_plus_y += factor; |
584 | | |
585 | 5.36M | iusace_lsp_to_lp_conversion(lsp, lp_flt_coff_a); |
586 | | |
587 | 5.36M | lp_flt_coff_a += (ORDER + 1); |
588 | 5.36M | } |
589 | | |
590 | 1.43M | iusace_lsp_to_lp_conversion(lsp_new, lp_flt_coff_a); |
591 | | |
592 | 1.43M | return; |
593 | 1.43M | } |