/src/libxaac/encoder/iusace_tns_usac.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 "ixheaace_mps_common_define.h" |
24 | | #include "ixheaac_constants.h" |
25 | | #include "iusace_cnst.h" |
26 | | #include "ixheaac_type_def.h" |
27 | | #include "iusace_bitbuffer.h" |
28 | | #include "iusace_tns_usac.h" |
29 | | #include "iusace_psy_mod.h" |
30 | | #include "ixheaac_basic_ops32.h" |
31 | | #include "ixheaac_basic_ops40.h" |
32 | | #include "ixheaac_basic_ops.h" |
33 | | #include "ixheaac_error_standards.h" |
34 | | #include "ixheaace_error_codes.h" |
35 | | |
36 | | static const WORD32 iusace_tns_supported_sampling_rates[13] = { |
37 | | 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0}; |
38 | | |
39 | | static const UWORD16 iusace_tns_min_band_number_long[12] = {11, 12, 15, 16, 17, 20, |
40 | | 25, 26, 24, 28, 30, 31}; |
41 | | |
42 | | static const UWORD16 iusace_tns_min_band_number_short[12] = {2, 2, 2, 3, 3, 4, |
43 | | 6, 6, 8, 10, 10, 12}; |
44 | | |
45 | | static const WORD32 iusace_tns_max_bands_table[16][2] = {{31, 9}, /**< 96000 */ |
46 | | {31, 9}, /**< 88200 */ |
47 | | {34, 10}, /**< 64000 */ |
48 | | {40, 14}, /**< 48000 */ |
49 | | {42, 14}, /**< 44100 */ |
50 | | {51, 14}, /**< 32000 */ |
51 | | {47, 15}, /**< 24000 */ |
52 | | {47, 15}, /**< 22050 */ |
53 | | {43, 15}, /**< 16000 */ |
54 | | {43, 15}, /**< 12000 */ |
55 | | {43, 15}, /**< 11025 */ |
56 | | {40, 15}, /**< 8000 */ |
57 | | {40, 15}, /**< 7350 */ |
58 | | {0, 0}, {0, 0}, {0, 0}}; |
59 | | |
60 | | static WORD32 iusace_freq_to_band_mapping(WORD32 freq, WORD32 sample_rate, WORD32 num_bands, |
61 | 10.7k | const WORD32 *ptr_band_start_offset) { |
62 | 10.7k | WORD32 line_num, band; |
63 | | |
64 | 10.7k | line_num = (freq * ptr_band_start_offset[num_bands] * 4 / sample_rate + 1) / 2; |
65 | | |
66 | 10.7k | if (line_num >= ptr_band_start_offset[num_bands]) { |
67 | 4.38k | return num_bands; |
68 | 4.38k | } |
69 | | |
70 | 117k | for (band = 0; band < num_bands; band++) { |
71 | 117k | if (ptr_band_start_offset[band + 1] > line_num) break; |
72 | 117k | } |
73 | | |
74 | 6.40k | if (line_num - ptr_band_start_offset[band] > ptr_band_start_offset[band + 1] - line_num) { |
75 | 1.87k | band++; |
76 | 1.87k | } |
77 | | |
78 | 6.40k | return band; |
79 | 10.7k | }; |
80 | | |
81 | | static VOID iusace_calc_gauss_win(FLOAT64 *ptr_win, const WORD32 length, const WORD32 sample_rate, |
82 | 5.39k | const WORD32 win_seq, const FLOAT32 time_resolution) { |
83 | 5.39k | WORD32 i; |
84 | 5.39k | FLOAT32 gauss_exp = 3.14159265358979323f * sample_rate * 0.001f * (FLOAT32)time_resolution / |
85 | 5.39k | (win_seq != EIGHT_SHORT_SEQUENCE ? 1024.0f : 128.0f); |
86 | | |
87 | 5.39k | gauss_exp = -0.5f * gauss_exp * gauss_exp; |
88 | | |
89 | 70.1k | for (i = 0; i < length; i++) { |
90 | 64.7k | ptr_win[i] = (FLOAT32)exp(gauss_exp * (i + 0.5) * (i + 0.5)); |
91 | 64.7k | } |
92 | 5.39k | return; |
93 | 5.39k | } |
94 | | |
95 | | IA_ERRORCODE iusace_tns_init(WORD32 sampling_rate, WORD32 bit_rate, ia_tns_info *tns_info, |
96 | 2.72k | WORD32 num_channels) { |
97 | 2.72k | IA_ERRORCODE err_code = IA_NO_ERROR; |
98 | 2.72k | WORD32 fs_index = 0; |
99 | 2.72k | WORD32 lpc_stop_freq = 16000; |
100 | 2.72k | WORD32 lpc_start_freq_long = 2500, lpc_start_freq_short = 3750; |
101 | 2.72k | tns_info->threshold = 1.41f; |
102 | 2.72k | tns_info->tns_time_res_short = 0.6f; |
103 | 2.72k | tns_info->tns_time_res_long = 0.6f; |
104 | | |
105 | 2.72k | if (sampling_rate == 14700) { |
106 | 0 | sampling_rate = 16000; |
107 | 0 | } |
108 | 2.72k | if (sampling_rate == 29400) { |
109 | 0 | sampling_rate = 32000; |
110 | 0 | } |
111 | | |
112 | 2.72k | if (bit_rate < 32000) { |
113 | 7 | if (num_channels == 1) { |
114 | 4 | tns_info->threshold = 1.2f; |
115 | 4 | lpc_start_freq_long = 2000; |
116 | 4 | } |
117 | 2.71k | } else if (bit_rate < 36000) { |
118 | 180 | if (num_channels == 1) { |
119 | 1 | tns_info->tns_time_res_long = 0.8f; |
120 | 179 | } else { |
121 | 179 | tns_info->tns_time_res_long = 0.5f; |
122 | 179 | } |
123 | 180 | tns_info->tns_time_res_short = 0.3f; |
124 | 2.53k | } else { |
125 | 2.53k | tns_info->tns_time_res_long = 0.5f; |
126 | 2.53k | tns_info->tns_time_res_short = 0.3f; |
127 | 2.53k | } |
128 | | |
129 | | /** Determine if sampling rate is supported |
130 | | */ |
131 | 19.4k | while (sampling_rate != iusace_tns_supported_sampling_rates[fs_index]) { |
132 | 16.7k | if (!iusace_tns_supported_sampling_rates[fs_index]) { |
133 | 21 | return IA_EXHEAACE_INIT_FATAL_USAC_INVALID_CORE_SAMPLE_RATE; |
134 | 21 | } |
135 | 16.7k | fs_index++; |
136 | 16.7k | } |
137 | | |
138 | 2.69k | tns_info->tns_max_bands_long = iusace_tns_max_bands_table[fs_index][0]; |
139 | 2.69k | tns_info->tns_max_bands_short = iusace_tns_max_bands_table[fs_index][1]; |
140 | 2.69k | tns_info->tns_max_order_long = 15; |
141 | 2.69k | tns_info->tns_max_order_short = 7; |
142 | | |
143 | 2.69k | tns_info->tns_min_band_number_long = iusace_tns_min_band_number_long[fs_index]; |
144 | 2.69k | tns_info->tns_min_band_number_short = iusace_tns_min_band_number_short[fs_index]; |
145 | | |
146 | 2.69k | tns_info->lpc_start_band_long = |
147 | 2.69k | iusace_freq_to_band_mapping(lpc_start_freq_long, sampling_rate, tns_info->max_sfb_long, |
148 | 2.69k | tns_info->sfb_offset_table_long); |
149 | | |
150 | 2.69k | tns_info->lpc_start_band_short = |
151 | 2.69k | iusace_freq_to_band_mapping(lpc_start_freq_short, sampling_rate, tns_info->max_sfb_short, |
152 | 2.69k | tns_info->sfb_offset_table_short); |
153 | | |
154 | 2.69k | tns_info->lpc_stop_band_long = iusace_freq_to_band_mapping( |
155 | 2.69k | lpc_stop_freq, sampling_rate, tns_info->max_sfb_long, tns_info->sfb_offset_table_long); |
156 | | |
157 | 2.69k | tns_info->lpc_stop_band_short = iusace_freq_to_band_mapping( |
158 | 2.69k | lpc_stop_freq, sampling_rate, tns_info->max_sfb_short, tns_info->sfb_offset_table_short); |
159 | | |
160 | 2.69k | iusace_calc_gauss_win(tns_info->win_long, tns_info->tns_max_order_long + 1, sampling_rate, |
161 | 2.69k | ONLY_LONG_SEQUENCE, tns_info->tns_time_res_long); |
162 | | |
163 | 2.69k | iusace_calc_gauss_win(tns_info->win_short, tns_info->tns_max_order_short + 1, sampling_rate, |
164 | 2.69k | EIGHT_SHORT_SEQUENCE, tns_info->tns_time_res_short); |
165 | 2.69k | return err_code; |
166 | 2.72k | } |
167 | | |
168 | | VOID iusace_tns_filter(WORD32 length, FLOAT64 *spec, ia_tns_filter_data *filter, |
169 | 245k | FLOAT64 *scratch_tns_filter) { |
170 | 245k | WORD32 i, j, k = 0; |
171 | 245k | WORD32 order = filter->order; |
172 | 245k | FLOAT64 *a = filter->a_coeffs; |
173 | 245k | FLOAT64 *temp = scratch_tns_filter; |
174 | | |
175 | | /** Determine loop parameters for given direction |
176 | | */ |
177 | 245k | if (filter->direction) { |
178 | | /** Startup, initial state is zero |
179 | | */ |
180 | 0 | temp[length - 1] = spec[length - 1]; |
181 | 0 | for (i = length - 2; i > (length - 1 - order); i--) { |
182 | 0 | temp[i] = spec[i]; |
183 | 0 | k++; |
184 | 0 | for (j = 1; j <= k; j++) { |
185 | 0 | spec[i] += temp[i + j] * a[j]; |
186 | 0 | } |
187 | 0 | } |
188 | | |
189 | | /** Now filter the rest |
190 | | */ |
191 | 0 | for (i = length - 1 - order; i >= 0; i--) { |
192 | 0 | temp[i] = spec[i]; |
193 | 0 | for (j = 1; j <= order; j++) { |
194 | 0 | spec[i] += temp[i + j] * a[j]; |
195 | 0 | } |
196 | 0 | } |
197 | 245k | } else { |
198 | | /** Startup, initial state is zero |
199 | | */ |
200 | 245k | temp[0] = spec[0]; |
201 | 1.19M | for (i = 1; i < order; i++) { |
202 | 948k | temp[i] = spec[i]; |
203 | 5.08M | for (j = 1; j <= i; j++) { |
204 | 4.13M | spec[i] += temp[i - j] * a[j]; |
205 | 4.13M | } |
206 | 948k | } |
207 | | |
208 | | /** Now filter the rest |
209 | | */ |
210 | 74.4M | for (i = order; i < length; i++) { |
211 | 74.2M | temp[i] = spec[i]; |
212 | 681M | for (j = 1; j <= order; j++) { |
213 | 607M | spec[i] += temp[i - j] * a[j]; |
214 | 607M | } |
215 | 74.2M | } |
216 | 245k | } |
217 | | |
218 | 245k | return; |
219 | 245k | } |
220 | | |
221 | 245k | static WORD32 iusace_truncate_coeffs(WORD32 f_order, FLOAT64 threshold, FLOAT64 *k_array) { |
222 | 245k | WORD32 i; |
223 | 1.44M | for (i = f_order; i >= 0; i--) { |
224 | 1.44M | k_array[i] = (fabs(k_array[i]) > threshold) ? k_array[i] : 0.0; |
225 | 1.44M | if (k_array[i] != 0.0) { |
226 | 245k | return i; |
227 | 245k | } |
228 | 1.44M | } |
229 | 0 | return 0; |
230 | 245k | } |
231 | | |
232 | | VOID iusace_quantize_reflection_coeffs(WORD32 f_order, WORD32 coeff_res, FLOAT64 *k_array, |
233 | 245k | WORD32 *index_array) { |
234 | 245k | FLOAT64 iqfac, iqfac_m; |
235 | 245k | WORD32 i; |
236 | | |
237 | 245k | iqfac = (((SIZE_T)1 << (coeff_res - 1)) - 0.5) / (PI / 2); |
238 | 245k | iqfac_m = (((SIZE_T)1 << (coeff_res - 1)) + 0.5) / (PI / 2); |
239 | | |
240 | | /* Quantize and inverse quantize */ |
241 | 2.64M | for (i = 1; i <= f_order; i++) { |
242 | 2.39M | index_array[i] = (WORD32)(0.5 + (asin(k_array[i]) * ((k_array[i] >= 0) ? iqfac : iqfac_m))); |
243 | 2.39M | k_array[i] = sin((FLOAT64)index_array[i] / ((index_array[i] >= 0) ? iqfac : iqfac_m)); |
244 | 2.39M | } |
245 | 245k | return; |
246 | 245k | } |
247 | | |
248 | 613k | VOID iusace_tns_auto_corr(WORD32 max_order, WORD32 data_size, FLOAT64 *data, FLOAT64 *r_array) { |
249 | 613k | WORD32 i, j; |
250 | 613k | FLOAT64 tmp_var; |
251 | 59.5M | for (i = 0; i < data_size; i += 2) { |
252 | 58.8M | const FLOAT64 *input1 = &data[i]; |
253 | 58.8M | FLOAT64 temp1 = *input1; |
254 | 58.8M | FLOAT64 temp2 = *(input1 + 1); |
255 | 58.8M | FLOAT64 inp_tmp1 = *input1++; |
256 | 462M | for (j = 0; j <= max_order; j++) { |
257 | 403M | FLOAT64 inp_tmp2; |
258 | 403M | tmp_var = temp1 * inp_tmp1; |
259 | 403M | inp_tmp2 = *input1++; |
260 | 403M | tmp_var += temp2 * inp_tmp2; |
261 | 403M | r_array[j] += tmp_var; |
262 | 403M | j++; |
263 | 403M | tmp_var = temp1 * inp_tmp2; |
264 | 403M | inp_tmp1 = *input1++; |
265 | 403M | tmp_var += temp2 * inp_tmp1; |
266 | 403M | r_array[j] += tmp_var; |
267 | 403M | } |
268 | 58.8M | } |
269 | 613k | return; |
270 | 613k | } |
271 | | |
272 | | static FLOAT64 iusace_levinson_durbin(WORD32 order, WORD32 data_size, FLOAT64 *ptr_data, |
273 | 613k | FLOAT64 *ptr_k, FLOAT64 *ptr_win, FLOAT64 *ptr_scratch) { |
274 | 613k | WORD32 i, j; |
275 | 613k | FLOAT64 *ptr_work_buffer_temp; |
276 | 613k | FLOAT64 *ptr_work_buffer = ptr_scratch; |
277 | 613k | FLOAT64 *ptr_input = ptr_scratch + TNS_MAX_ORDER + 1; |
278 | 613k | memset(ptr_input, 0, (TNS_MAX_ORDER + 1) * sizeof(ptr_input[0])); |
279 | 613k | iusace_tns_auto_corr(order, data_size, ptr_data, ptr_input); |
280 | | |
281 | 613k | WORD32 num_of_coeff = order; |
282 | 613k | FLOAT64 *ptr_refl_coeff = ptr_k; |
283 | 613k | ptr_k[0] = 1.0; |
284 | | |
285 | 613k | if (ptr_input[0] == 0) { |
286 | 111k | return 0; |
287 | 111k | } |
288 | | |
289 | 5.44M | for (i = 0; i < num_of_coeff + 1; i++) { |
290 | 4.94M | ptr_input[i] = ptr_input[i] * ptr_win[i]; |
291 | 4.94M | } |
292 | | |
293 | 501k | FLOAT64 tmp_var; |
294 | 501k | ptr_work_buffer[0] = ptr_input[0]; |
295 | | |
296 | 4.44M | for (i = 1; i < num_of_coeff; i++) { |
297 | 3.94M | tmp_var = ptr_input[i]; |
298 | 3.94M | ptr_work_buffer[i] = tmp_var; |
299 | 3.94M | ptr_work_buffer[i + num_of_coeff - 1] = tmp_var; |
300 | 3.94M | } |
301 | 501k | ptr_work_buffer[i + num_of_coeff - 1] = ptr_input[i]; |
302 | | |
303 | 4.94M | for (i = 0; i < num_of_coeff; i++) { |
304 | 4.44M | FLOAT64 refc, tmp; |
305 | 4.44M | tmp = ptr_work_buffer[num_of_coeff + i]; |
306 | 4.44M | if (tmp < 0) { |
307 | 2.43M | tmp = -tmp; |
308 | 2.43M | } else { |
309 | 2.01M | if (ptr_work_buffer[0] < tmp) { |
310 | 0 | break; |
311 | 0 | } |
312 | 2.01M | } |
313 | 4.44M | if (ptr_work_buffer[0] == 0) { |
314 | 0 | refc = 0; |
315 | 4.44M | } else { |
316 | 4.44M | refc = tmp / ptr_work_buffer[0]; |
317 | 4.44M | } |
318 | | |
319 | 4.44M | if (ptr_work_buffer[num_of_coeff + i] > 0) { |
320 | 1.80M | refc = -refc; |
321 | 1.80M | } |
322 | 4.44M | ptr_refl_coeff[i + 1] = refc; |
323 | 4.44M | ptr_work_buffer_temp = &(ptr_work_buffer[num_of_coeff]); |
324 | | |
325 | 29.2M | for (j = i; j < num_of_coeff; j++) { |
326 | 24.8M | FLOAT64 accu1, accu2; |
327 | 24.8M | accu1 = refc * ptr_work_buffer[j - i]; |
328 | 24.8M | accu1 += ptr_work_buffer_temp[j]; |
329 | 24.8M | accu2 = refc * ptr_work_buffer_temp[j]; |
330 | 24.8M | accu2 += ptr_work_buffer[j - i]; |
331 | 24.8M | ptr_work_buffer_temp[j] = accu1; |
332 | 24.8M | ptr_work_buffer[j - i] = accu2; |
333 | 24.8M | } |
334 | 4.44M | } |
335 | 501k | return (ptr_input[0] / ptr_work_buffer[0]); |
336 | 613k | } |
337 | | |
338 | 245k | static VOID iusace_step_up(WORD32 f_order, FLOAT64 *ptr_k, FLOAT64 *ptr_a, FLOAT64 *ptr_scratch) { |
339 | 245k | FLOAT64 *ptr_a_temp = ptr_scratch; |
340 | 245k | WORD32 i, order; |
341 | | |
342 | 245k | ptr_a[0] = 1.0; |
343 | 245k | ptr_a_temp[0] = 1.0; |
344 | 1.43M | for (order = 1; order <= f_order; order++) { |
345 | 1.19M | ptr_a[order] = 0.0; |
346 | 6.51M | for (i = 1; i <= order; i++) { |
347 | 5.32M | ptr_a_temp[i] = ptr_a[i] + ptr_k[order] * ptr_a[order - i]; |
348 | 5.32M | } |
349 | 6.51M | for (i = 1; i <= order; i++) { |
350 | 5.32M | ptr_a[i] = ptr_a_temp[i]; |
351 | 5.32M | } |
352 | 1.19M | } |
353 | 245k | return; |
354 | 245k | } |
355 | | |
356 | | static VOID iusace_calc_weighted_spec(FLOAT64 *ptr_spec, FLOAT64 *ptr_wgt_spec, |
357 | | FLOAT32 *ptr_sfb_en, WORD32 *ptr_sfb_offset, |
358 | | WORD32 lpc_start_band, WORD32 lpc_stop_band, |
359 | 613k | FLOAT64 *ptr_scratch) { |
360 | 613k | WORD32 i, sfb; |
361 | 613k | FLOAT32 temp; |
362 | 613k | FLOAT32 *ptr_tns_sfb_mean = (FLOAT32 *)ptr_scratch; |
363 | 613k | memset(ptr_scratch, 0, MAX_NUM_GROUPED_SFB * sizeof(ptr_tns_sfb_mean[0])); |
364 | 613k | WORD32 lpc_stop_line = ptr_sfb_offset[lpc_stop_band]; |
365 | 613k | WORD32 lpc_start_line = ptr_sfb_offset[lpc_start_band]; |
366 | | |
367 | 5.79M | for (sfb = lpc_start_band; sfb < lpc_stop_band; sfb++) { |
368 | 5.18M | ptr_tns_sfb_mean[sfb] = (FLOAT32)(1.0 / sqrt(ptr_sfb_en[sfb] + 1e-30f)); |
369 | 5.18M | } |
370 | | |
371 | 613k | sfb = lpc_start_band; |
372 | 613k | temp = ptr_tns_sfb_mean[sfb]; |
373 | | |
374 | 118M | for (i = lpc_start_line; i < lpc_stop_line; i++) { |
375 | 117M | if (ptr_sfb_offset[sfb + 1] == i) { |
376 | 4.57M | sfb++; |
377 | | |
378 | 4.57M | if (sfb + 1 < lpc_stop_band) { |
379 | 3.97M | temp = ptr_tns_sfb_mean[sfb]; |
380 | 3.97M | } |
381 | 4.57M | } |
382 | 117M | ptr_wgt_spec[i] = temp; |
383 | 117M | } |
384 | | |
385 | 117M | for (i = lpc_stop_line - 2; i >= lpc_start_line; i--) { |
386 | 117M | ptr_wgt_spec[i] = (ptr_wgt_spec[i] + ptr_wgt_spec[i + 1]) * 0.5f; |
387 | 117M | } |
388 | | |
389 | 117M | for (i = lpc_start_line + 1; i < lpc_stop_line; i++) { |
390 | 117M | ptr_wgt_spec[i] = (ptr_wgt_spec[i] + ptr_wgt_spec[i - 1]) * 0.5f; |
391 | 117M | } |
392 | | |
393 | 118M | for (i = lpc_start_line; i < lpc_stop_line; i++) { |
394 | 117M | ptr_wgt_spec[i] = ptr_wgt_spec[i] * ptr_spec[i]; |
395 | 117M | } |
396 | 613k | return; |
397 | 613k | } |
398 | | |
399 | | VOID iusace_tns_data_sync(ia_tns_info *ptr_tns_dest, ia_tns_info *ptr_tns_src, const WORD32 w, |
400 | 289k | WORD32 order) { |
401 | 289k | ia_tns_window_data *win_data_src = &ptr_tns_src->window_data[w]; |
402 | 289k | ia_tns_window_data *win_data_dest = &ptr_tns_dest->window_data[w]; |
403 | 289k | WORD32 i; |
404 | 289k | if (fabs(win_data_dest->tns_pred_gain - win_data_src->tns_pred_gain) < |
405 | 289k | ((FLOAT32)0.03f * win_data_dest->tns_pred_gain)) { |
406 | 133k | win_data_dest->tns_active = win_data_src->tns_active; |
407 | | |
408 | 1.28M | for (i = 0; i < order; i++) { |
409 | 1.14M | win_data_dest->tns_filter->k_coeffs[i] = win_data_src->tns_filter->k_coeffs[i]; |
410 | 1.14M | } |
411 | 133k | } |
412 | 289k | return; |
413 | 289k | } |
414 | | |
415 | | VOID iusace_tns_encode(ia_tns_info *pstr_tns_info_ch2, ia_tns_info *pstr_tns_info, |
416 | | FLOAT32 *ptr_sfb_energy, WORD32 w, WORD32 i_ch, WORD32 low_pass_line, |
417 | | FLOAT64 *ptr_scratch_tns_filter, WORD32 core_mode, |
418 | 613k | FLOAT64 *ptr_tns_scratch) { |
419 | 613k | WORD32 number_of_bands = pstr_tns_info->number_of_bands; |
420 | 613k | WORD32 block_type = pstr_tns_info->block_type; |
421 | 613k | FLOAT64 *ptr_spec = pstr_tns_info->spec; |
422 | 613k | WORD32 start_band, stop_band, order; /**< bands over which to apply TNS */ |
423 | 613k | WORD32 length_in_bands; /**< Length to filter, in bands */ |
424 | 613k | WORD32 start_index, length; |
425 | 613k | WORD32 nbands; |
426 | 613k | WORD32 coeff_res; |
427 | 613k | FLOAT64 *ptr_weighted_spec = ptr_tns_scratch; |
428 | 613k | memset(ptr_weighted_spec, 0, 4096 * sizeof(ptr_weighted_spec[0])); |
429 | 613k | FLOAT64 *ptr_scratch = ptr_tns_scratch + 4096; |
430 | 613k | FLOAT64 *ptr_window = NULL; |
431 | 613k | WORD32 lpc_start_band, lpc_stop_band; |
432 | 613k | WORD32 *ptr_sfb_offset_table; |
433 | | |
434 | 613k | switch (block_type) { |
435 | 484k | case EIGHT_SHORT_SEQUENCE: |
436 | 484k | start_band = pstr_tns_info->tns_min_band_number_short; |
437 | 484k | stop_band = number_of_bands; |
438 | 484k | length_in_bands = stop_band - start_band; |
439 | 484k | order = pstr_tns_info->tns_max_order_short; |
440 | 484k | start_band = MIN(start_band, pstr_tns_info->tns_max_bands_short); |
441 | 484k | stop_band = MIN(stop_band, pstr_tns_info->tns_max_bands_short); |
442 | 484k | coeff_res = 3; |
443 | 484k | ptr_window = pstr_tns_info->win_short; |
444 | 484k | nbands = pstr_tns_info->max_sfb_short; |
445 | 484k | lpc_start_band = pstr_tns_info->lpc_start_band_short; |
446 | 484k | lpc_stop_band = pstr_tns_info->lpc_stop_band_short; |
447 | 484k | if (core_mode == CORE_MODE_FD) { |
448 | 484k | ptr_sfb_offset_table = pstr_tns_info->sfb_offset_table_short; |
449 | 484k | } else { |
450 | 0 | ptr_sfb_offset_table = pstr_tns_info->sfb_offset_table_short_tcx; |
451 | 0 | } |
452 | 484k | break; |
453 | | |
454 | 128k | default: |
455 | 128k | start_band = pstr_tns_info->tns_min_band_number_long; |
456 | 128k | stop_band = number_of_bands; |
457 | 128k | length_in_bands = stop_band - start_band; |
458 | 128k | order = pstr_tns_info->tns_max_order_long; |
459 | 128k | start_band = MIN(start_band, pstr_tns_info->tns_max_bands_long); |
460 | 128k | stop_band = MIN(stop_band, pstr_tns_info->tns_max_bands_long); |
461 | 128k | coeff_res = 4; |
462 | 128k | ptr_window = pstr_tns_info->win_long; |
463 | 128k | nbands = pstr_tns_info->max_sfb_long; |
464 | 128k | lpc_start_band = pstr_tns_info->lpc_start_band_long; |
465 | 128k | lpc_stop_band = pstr_tns_info->lpc_stop_band_long; |
466 | 128k | ptr_sfb_offset_table = pstr_tns_info->sfb_offset_table_long; |
467 | 128k | break; |
468 | 613k | } |
469 | | |
470 | | /** Make sure that start and stop bands < max_sfb |
471 | | * Make sure that start and stop bands >= 0 |
472 | | */ |
473 | 613k | start_band = MIN(start_band, nbands); |
474 | 613k | stop_band = MIN(stop_band, nbands); |
475 | 613k | start_band = MAX(start_band, 0); |
476 | 613k | stop_band = MAX(stop_band, 0); |
477 | | |
478 | 613k | pstr_tns_info->tns_data_present = 0; /**< default TNS not used */ |
479 | | |
480 | | /** Perform analysis and filtering for each window |
481 | | */ |
482 | 613k | { |
483 | 613k | ia_tns_window_data *window_data = &pstr_tns_info->window_data[w]; |
484 | 613k | ia_tns_filter_data *tns_filter = window_data->tns_filter; |
485 | 613k | FLOAT64 *k = tns_filter->k_coeffs; /**< reflection coeffs */ |
486 | 613k | FLOAT64 *a = tns_filter->a_coeffs; /**< prediction coeffs */ |
487 | | |
488 | 613k | iusace_calc_weighted_spec(ptr_spec, ptr_weighted_spec, ptr_sfb_energy, ptr_sfb_offset_table, |
489 | 613k | lpc_start_band, lpc_stop_band, ptr_scratch); |
490 | | |
491 | 613k | window_data->n_filt = 0; |
492 | 613k | window_data->coef_res = coeff_res; |
493 | | |
494 | 613k | start_index = ptr_sfb_offset_table[lpc_start_band]; |
495 | 613k | length = |
496 | 613k | ptr_sfb_offset_table[lpc_stop_band] - |
497 | 613k | ptr_sfb_offset_table[lpc_start_band]; /**< The length of the spectral data to be |
498 | | processed |
499 | | */ |
500 | | |
501 | 613k | window_data->tns_pred_gain = iusace_levinson_durbin( |
502 | 613k | order, length, &ptr_weighted_spec[start_index], k, ptr_window, ptr_scratch); |
503 | | |
504 | 613k | window_data->tns_active = 0; |
505 | 613k | if (window_data->tns_pred_gain > DEF_TNS_GAIN_THRESH) { |
506 | 245k | window_data->tns_active = 1; |
507 | 245k | } |
508 | | |
509 | 613k | if (i_ch == 1) { |
510 | 289k | iusace_tns_data_sync(pstr_tns_info, pstr_tns_info_ch2, w, order); |
511 | 289k | } |
512 | | |
513 | 613k | if (window_data->tns_pred_gain > DEF_TNS_GAIN_THRESH) { |
514 | | /** Use TNS |
515 | | */ |
516 | 245k | WORD32 truncated_order; |
517 | 245k | window_data->n_filt++; |
518 | 245k | pstr_tns_info->tns_data_present = 1; |
519 | 245k | tns_filter->direction = 0; |
520 | 245k | tns_filter->coef_compress = 0; |
521 | 245k | tns_filter->length = length_in_bands; |
522 | 245k | iusace_quantize_reflection_coeffs(order, coeff_res, k, tns_filter->index); |
523 | 245k | truncated_order = iusace_truncate_coeffs(order, DEF_TNS_COEFF_THRESH, k); |
524 | 245k | tns_filter->order = truncated_order; |
525 | 245k | iusace_step_up(truncated_order, k, a, ptr_scratch); /**< Compute prediction coefficients */ |
526 | 245k | start_index = ptr_sfb_offset_table[start_band]; |
527 | 245k | length = MIN(ptr_sfb_offset_table[stop_band], low_pass_line) - start_index; |
528 | 245k | if (block_type == EIGHT_SHORT_SEQUENCE) { |
529 | 160k | length = ptr_sfb_offset_table[stop_band] - start_index; |
530 | 160k | } |
531 | 245k | iusace_tns_filter(length, &ptr_spec[start_index], tns_filter, |
532 | 245k | ptr_scratch_tns_filter); /**< filter */ |
533 | 245k | } |
534 | 613k | } |
535 | 613k | return; |
536 | 613k | } |