xref: /aosp_15_r20/external/libxaac/encoder/iusace_psy_utils.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 <string.h>
23 
24 #include "ixheaac_type_def.h"
25 #include "ixheaace_adjust_threshold_data.h"
26 #include "iusace_block_switch_const.h"
27 #include "iusace_cnst.h"
28 #include "iusace_bitbuffer.h"
29 #include "ixheaace_mps_common_define.h"
30 
31 /* DRC */
32 #include "impd_drc_common_enc.h"
33 #include "impd_drc_uni_drc.h"
34 #include "impd_drc_tables.h"
35 #include "impd_drc_api.h"
36 #include "impd_drc_uni_drc_eq.h"
37 #include "impd_drc_uni_drc_filter_bank.h"
38 #include "impd_drc_gain_enc.h"
39 #include "impd_drc_struct_def.h"
40 
41 #include "iusace_tns_usac.h"
42 #include "iusace_psy_mod.h"
43 #include "iusace_tns_usac.h"
44 #include "iusace_config.h"
45 #include "iusace_psy_utils.h"
46 #include "iusace_fd_qc_util.h"
47 #include "iusace_fd_qc_adjthr.h"
48 #include "ixheaac_error_standards.h"
49 #include "ixheaace_error_codes.h"
50 
51 extern ia_sfb_info_struct iusace_sfb_info_1024[12];
52 extern ia_sfb_info_struct iusace_sfb_info_768[12];
53 
54 static const FLOAT32 iusace_bark_quiet_thr_val[] = {
55     15.0f, 10.0f, 7.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.0f,  0.0f, 0.0f,
56     0.0f,  0.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 3.0f, 5.0f, 10.0f, 20.0f, 30.0f};
57 
iusace_calc_band_energy(const FLOAT64 * ptr_spec_coeffs,const WORD32 * band_offset,const WORD32 num_bands,FLOAT32 * ptr_band_energy,WORD32 sfb_count)58 VOID iusace_calc_band_energy(const FLOAT64 *ptr_spec_coeffs, const WORD32 *band_offset,
59                              const WORD32 num_bands, FLOAT32 *ptr_band_energy, WORD32 sfb_count) {
60   WORD32 i, j;
61 
62   j = 0;
63   memset(ptr_band_energy, 0, sfb_count * sizeof(FLOAT32));
64   for (i = 0; i < num_bands; i++) {
65     while (j < band_offset[i + 1]) {
66       ptr_band_energy[i] += (FLOAT32)(ptr_spec_coeffs[j] * ptr_spec_coeffs[j]);
67       j++;
68     }
69   }
70   return;
71 }
72 
iusace_find_max_spreading(const WORD32 sfb_count,const FLOAT32 * ptr_mask_low_fac,const FLOAT32 * ptr_mask_high_fac,FLOAT32 * ptr_spreaded_enegry)73 VOID iusace_find_max_spreading(const WORD32 sfb_count, const FLOAT32 *ptr_mask_low_fac,
74                                const FLOAT32 *ptr_mask_high_fac, FLOAT32 *ptr_spreaded_enegry) {
75   WORD32 i;
76 
77   for (i = 1; i < sfb_count; i++) {
78     ptr_spreaded_enegry[i] =
79         MAX(ptr_spreaded_enegry[i], ptr_mask_high_fac[i] * ptr_spreaded_enegry[i - 1]);
80   }
81 
82   for (i = sfb_count - 2; i >= 0; i--) {
83     ptr_spreaded_enegry[i] =
84         MAX(ptr_spreaded_enegry[i], ptr_mask_low_fac[i] * ptr_spreaded_enegry[i + 1]);
85   }
86   return;
87 }
88 
iusace_pre_echo_control(FLOAT32 * ptr_thr_nm1,WORD32 sfb_count,FLOAT32 max_allowed_inc_fac,FLOAT32 min_remaining_thr_fac,FLOAT32 * ptr_threshold)89 VOID iusace_pre_echo_control(FLOAT32 *ptr_thr_nm1, WORD32 sfb_count, FLOAT32 max_allowed_inc_fac,
90                              FLOAT32 min_remaining_thr_fac, FLOAT32 *ptr_threshold) {
91   WORD32 i;
92   FLOAT32 thr1, thr2;
93 
94   for (i = 0; i < sfb_count; i++) {
95     thr1 = max_allowed_inc_fac * (ptr_thr_nm1[i]);
96     thr2 = min_remaining_thr_fac * ptr_threshold[i];
97 
98     ptr_thr_nm1[i] = ptr_threshold[i];
99 
100     if (ptr_threshold[i] > thr1) {
101       ptr_threshold[i] = thr1;
102     }
103     if (thr2 > ptr_threshold[i]) {
104       ptr_threshold[i] = thr2;
105     }
106   }
107   return;
108 }
109 
iusace_sfb_init(WORD32 sample_rate,WORD32 block_type,WORD32 * ptr_sfb_offset,WORD32 * ptr_sfb_count,WORD32 ccfl)110 static VOID iusace_sfb_init(WORD32 sample_rate, WORD32 block_type, WORD32 *ptr_sfb_offset,
111                             WORD32 *ptr_sfb_count, WORD32 ccfl) {
112   const WORD16 *ptr_sfb_params = 0;
113   WORD32 start_offset, block_len = 0;
114   const ia_sfb_info_struct *pstr_sfb_info_tbls = &iusace_sfb_info_1024[0];
115   WORD32 sampling_rate_mapped = iusace_map_sample_rate(sample_rate);
116   WORD16 prev_val = 0;
117   if (ccfl == LEN_SUPERFRAME_768) {
118     pstr_sfb_info_tbls = &iusace_sfb_info_768[0];
119   }
120 
121 
122   if (block_type == ONLY_LONG_SEQUENCE) {
123     block_len = ccfl;
124     switch (sampling_rate_mapped) {
125       case 96000:
126         ptr_sfb_params = pstr_sfb_info_tbls[11].cb_offset_long;
127         break;
128       case 88200:
129         ptr_sfb_params = pstr_sfb_info_tbls[10].cb_offset_long;
130         break;
131       case 64000:
132         ptr_sfb_params = pstr_sfb_info_tbls[9].cb_offset_long;
133         break;
134       case 48000:
135         ptr_sfb_params = pstr_sfb_info_tbls[8].cb_offset_long;
136         break;
137       case 44100:
138         ptr_sfb_params = pstr_sfb_info_tbls[7].cb_offset_long;
139         break;
140       case 32000:
141       case 29400:
142         ptr_sfb_params = pstr_sfb_info_tbls[6].cb_offset_long;
143         break;
144       case 24000:
145         ptr_sfb_params = pstr_sfb_info_tbls[5].cb_offset_long;
146         break;
147       case 22050:
148         ptr_sfb_params = pstr_sfb_info_tbls[4].cb_offset_long;
149         break;
150       case 16000:
151       case 14700:
152         ptr_sfb_params = pstr_sfb_info_tbls[3].cb_offset_long;
153         break;
154       case 12000:
155         ptr_sfb_params = pstr_sfb_info_tbls[2].cb_offset_long;
156         break;
157       case 11025:
158         ptr_sfb_params = pstr_sfb_info_tbls[1].cb_offset_long;
159         break;
160       case 8000:
161         ptr_sfb_params = pstr_sfb_info_tbls[0].cb_offset_long;
162         break;
163       default:
164         ptr_sfb_params = pstr_sfb_info_tbls[8].cb_offset_long;
165         break;
166     }
167   } else {
168     block_len = ccfl >> 3;
169     switch (sampling_rate_mapped) {
170       case 96000:
171         ptr_sfb_params = pstr_sfb_info_tbls[11].cb_offset_short;
172         break;
173       case 88200:
174         ptr_sfb_params = pstr_sfb_info_tbls[10].cb_offset_short;
175         break;
176       case 64000:
177         ptr_sfb_params = pstr_sfb_info_tbls[9].cb_offset_short;
178         break;
179       case 48000:
180         ptr_sfb_params = pstr_sfb_info_tbls[8].cb_offset_short;
181         break;
182       case 44100:
183         ptr_sfb_params = pstr_sfb_info_tbls[7].cb_offset_short;
184         break;
185       case 32000:
186       case 29400:
187         ptr_sfb_params = pstr_sfb_info_tbls[6].cb_offset_short;
188         break;
189       case 24000:
190         ptr_sfb_params = pstr_sfb_info_tbls[5].cb_offset_short;
191         break;
192       case 22050:
193         ptr_sfb_params = pstr_sfb_info_tbls[4].cb_offset_short;
194         break;
195       case 16000:
196       case 14700:
197         ptr_sfb_params = pstr_sfb_info_tbls[3].cb_offset_short;
198         break;
199       case 12000:
200         ptr_sfb_params = pstr_sfb_info_tbls[2].cb_offset_short;
201         break;
202       case 11025:
203         ptr_sfb_params = pstr_sfb_info_tbls[1].cb_offset_short;
204         break;
205       case 8000:
206         ptr_sfb_params = pstr_sfb_info_tbls[0].cb_offset_short;
207         break;
208       default:
209         ptr_sfb_params = pstr_sfb_info_tbls[8].cb_offset_short;
210         break;
211     }
212   }
213 
214   *ptr_sfb_count = 0;
215   start_offset = 0;
216 
217   do {
218     ptr_sfb_offset[*ptr_sfb_count] = start_offset;
219     if (*ptr_sfb_count == 0)
220       prev_val = 0;
221     else
222       prev_val = ptr_sfb_params[*ptr_sfb_count - 1];
223     start_offset += ptr_sfb_params[*ptr_sfb_count] - prev_val;
224     (*ptr_sfb_count)++;
225   } while (start_offset < block_len);
226 
227   ptr_sfb_offset[*ptr_sfb_count] = start_offset;
228 
229   return;
230 }
231 
iusace_atan_approx(FLOAT32 val)232 static FLOAT32 iusace_atan_approx(FLOAT32 val) {
233   if (val < (FLOAT32)1.0) {
234     return (val / ((FLOAT32)1.0f + (FLOAT32)0.280872f * val * val));
235   } else {
236     return ((FLOAT32)1.57079633f - val / ((FLOAT32)0.280872f + val * val));
237   }
238 }
239 
iusace_calc_bark_line_value(WORD32 num_lines,WORD32 fft_line,WORD32 sample_rate)240 static FLOAT32 iusace_calc_bark_line_value(WORD32 num_lines, WORD32 fft_line,
241                                            WORD32 sample_rate) {
242   FLOAT32 center_freq, temp, b_value;
243 
244   center_freq = (FLOAT32)fft_line * ((FLOAT32)sample_rate * (FLOAT32)0.5f) / (FLOAT32)num_lines;
245   temp = (FLOAT32)iusace_atan_approx((FLOAT32)1.3333333e-4f * center_freq);
246   b_value = (FLOAT32)13.3f * iusace_atan_approx((FLOAT32)0.00076f * center_freq) +
247             (FLOAT32)3.5f * temp * temp;
248 
249   return (b_value);
250 }
251 
iusace_bark_values_init(WORD32 sfb_count,WORD32 * ptr_sfb_offset,WORD32 num_lines,WORD32 sample_rate,FLOAT32 * ptr_b_value)252 static VOID iusace_bark_values_init(WORD32 sfb_count, WORD32 *ptr_sfb_offset, WORD32 num_lines,
253                                     WORD32 sample_rate, FLOAT32 *ptr_b_value) {
254   WORD32 i;
255   FLOAT32 b_val0, b_val1;
256   b_val0 = 0.0f;
257 
258   for (i = 0; i < sfb_count; i++) {
259     b_val1 = iusace_calc_bark_line_value(num_lines, ptr_sfb_offset[i + 1], sample_rate);
260     ptr_b_value[i] = (b_val0 + b_val1) * (FLOAT32)0.5f;
261     b_val0 = b_val1;
262   }
263   return;
264 }
265 
iusace_thr_quiet_init(WORD32 sfb_count,WORD32 * ptr_sfb_offset,FLOAT32 * ptr_bark_val,FLOAT32 * ptr_thr_quiet)266 static VOID iusace_thr_quiet_init(WORD32 sfb_count, WORD32 *ptr_sfb_offset, FLOAT32 *ptr_bark_val,
267                                   FLOAT32 *ptr_thr_quiet) {
268   WORD32 i;
269   FLOAT32 bark_thr_quiet;
270 
271   for (i = 0; i < sfb_count; i++) {
272     WORD32 b_val1, b_val2;
273 
274     if (i > 0) {
275       b_val1 = (WORD32)(ptr_bark_val[i] + ptr_bark_val[i - 1]) >> 1;
276     } else {
277       b_val1 = (WORD32)(ptr_bark_val[i]) >> 1;
278     }
279 
280     if (i < sfb_count - 1) {
281       b_val2 = (WORD32)(ptr_bark_val[i] + ptr_bark_val[i + 1]) >> 1;
282     } else {
283       b_val2 = (WORD32)(ptr_bark_val[i]);
284     }
285     b_val1 = MIN(b_val1, (WORD32)MAX_BARK_VALUE);
286     b_val2 = MIN(b_val2, (WORD32)MAX_BARK_VALUE);
287     bark_thr_quiet = MIN(iusace_bark_quiet_thr_val[b_val1], iusace_bark_quiet_thr_val[b_val2]);
288 
289     ptr_thr_quiet[i] = (FLOAT32)pow(10.0f, (bark_thr_quiet - 20.0f) * (FLOAT32)0.1f) * 16887.8f *
290                        (FLOAT32)(ptr_sfb_offset[i + 1] - ptr_sfb_offset[i]);
291   }
292   return;
293 }
294 
iusace_spreading_init(WORD32 sfb_count,FLOAT32 * ptr_bark_val,FLOAT32 * ptr_mask_low_fac,FLOAT32 * ptr_mask_high_fac,FLOAT32 * ptr_mask_low_fac_spr_energy,FLOAT32 * ptr_mask_high_fac_spr_energy,const WORD32 bit_rate,WORD32 block_type)295 static VOID iusace_spreading_init(WORD32 sfb_count, FLOAT32 *ptr_bark_val,
296                                   FLOAT32 *ptr_mask_low_fac, FLOAT32 *ptr_mask_high_fac,
297                                   FLOAT32 *ptr_mask_low_fac_spr_energy,
298                                   FLOAT32 *ptr_mask_high_fac_spr_energy, const WORD32 bit_rate,
299                                   WORD32 block_type) {
300   WORD32 i;
301   FLOAT32 mask_low_spr_energy, mask_high_spr_energy;
302 
303   if (block_type != EIGHT_SHORT_SEQUENCE) {
304     mask_low_spr_energy = MASK_LOW_SP_ENERGY_L;
305     mask_high_spr_energy = (bit_rate > 22000) ? MASK_HIGH_SP_ENERGY_L : MASK_HIGH_SP_ENERGY_L_LBR;
306   } else {
307     mask_low_spr_energy = MASK_LOW_SP_ENERGY_S;
308     mask_high_spr_energy = MASK_HIGH_SP_ENERGY_S;
309   }
310 
311   for (i = 0; i < sfb_count; i++) {
312     if (i > 0) {
313       FLOAT32 db_val;
314       FLOAT32 diff_val = (ptr_bark_val[i] - ptr_bark_val[i - 1]);
315 
316       db_val = MASK_HIGH_FAC * diff_val;
317       ptr_mask_high_fac[i] = (FLOAT32)pow(10.0f, -db_val);
318       db_val = MASK_LOW_FAC * diff_val;
319       ptr_mask_low_fac[i - 1] = (FLOAT32)pow(10.0f, -db_val);
320       db_val = mask_high_spr_energy * diff_val;
321       ptr_mask_high_fac_spr_energy[i] = (FLOAT32)pow(10.0f, -db_val);
322       db_val = mask_low_spr_energy * diff_val;
323       ptr_mask_low_fac_spr_energy[i - 1] = (FLOAT32)pow(10.0f, -db_val);
324     } else {
325       ptr_mask_high_fac[i] = 0.0f;
326       ptr_mask_low_fac[sfb_count - 1] = 0.0f;
327       ptr_mask_high_fac_spr_energy[i] = 0.0f;
328       ptr_mask_low_fac_spr_energy[sfb_count - 1] = 0.0f;
329     }
330   }
331   return;
332 }
333 
iusace_min_snr_init(const WORD32 bit_rate,const WORD32 sample_rate,const WORD32 num_lines,const WORD32 * ptr_sfb_offset,const FLOAT32 * ptr_bark_value,const WORD32 sfb_active,FLOAT32 * ptr_sfb_min_snr)334 static VOID iusace_min_snr_init(const WORD32 bit_rate, const WORD32 sample_rate,
335                                 const WORD32 num_lines, const WORD32 *ptr_sfb_offset,
336                                 const FLOAT32 *ptr_bark_value, const WORD32 sfb_active,
337                                 FLOAT32 *ptr_sfb_min_snr) {
338   WORD32 sfb;
339   FLOAT32 bark_fac;
340   FLOAT32 bark_width;
341   FLOAT32 pe_per_window, pe_part;
342   FLOAT32 snr;
343   FLOAT32 b_val0, b_val1;
344 
345   if (sfb_active == 0) {
346     bark_fac = 1.0f;
347   } else {
348     bark_fac = (FLOAT32)1.0 / MIN(ptr_bark_value[sfb_active - 1] / MAX_BARK_VALUE, (FLOAT32)1.0);
349   }
350 
351   pe_per_window =
352       iusace_bits_to_pe((FLOAT32)bit_rate / (FLOAT32)sample_rate * (FLOAT32)num_lines);
353 
354   b_val0 = (FLOAT32)0.0f;
355 
356   for (sfb = 0; sfb < sfb_active; sfb++) {
357     b_val1 = (FLOAT32)2.0 * ptr_bark_value[sfb] - b_val0;
358     bark_width = b_val1 - b_val0;
359     b_val0 = b_val1;
360 
361     pe_part = pe_per_window * (FLOAT32)0.024f * bark_fac;
362     pe_part *= bark_width;
363     pe_part /= (FLOAT32)(ptr_sfb_offset[sfb + 1] - ptr_sfb_offset[sfb]);
364     snr = (FLOAT32)pow(2.0f, pe_part) - 1.5f;
365     snr = 1.0f / MAX(snr, 1.0f);
366     snr = MIN(snr, 0.8f);
367     snr = MAX(snr, 0.003f);
368     ptr_sfb_min_snr[sfb] = snr;
369   }
370   return;
371 }
372 
iusace_psy_long_config_init(WORD32 bit_rate,WORD32 sample_rate,WORD32 band_width,ia_psy_mod_long_config_struct * pstr_psy_config,WORD32 ccfl)373 VOID iusace_psy_long_config_init(WORD32 bit_rate, WORD32 sample_rate, WORD32 band_width,
374                                  ia_psy_mod_long_config_struct *pstr_psy_config, WORD32 ccfl) {
375   WORD32 sfb;
376   FLOAT32 sfb_bark_val[MAX_NUM_GROUPED_SFB];
377 
378   iusace_sfb_init(sample_rate, ONLY_LONG_SEQUENCE, pstr_psy_config->sfb_offset,
379                   &(pstr_psy_config->sfb_count), ccfl);
380 
381   iusace_bark_values_init(pstr_psy_config->sfb_count, pstr_psy_config->sfb_offset,
382                           pstr_psy_config->sfb_offset[pstr_psy_config->sfb_count], sample_rate,
383                           sfb_bark_val);
384 
385   iusace_thr_quiet_init(pstr_psy_config->sfb_count, pstr_psy_config->sfb_offset, sfb_bark_val,
386                         pstr_psy_config->sfb_thr_quiet);
387 
388   iusace_spreading_init(
389       pstr_psy_config->sfb_count, sfb_bark_val, pstr_psy_config->sfb_mask_low_fac,
390       pstr_psy_config->sfb_mask_high_fac, pstr_psy_config->sfb_mask_low_fac_spr_ener,
391       pstr_psy_config->sfb_mask_high_fac_spr_ener, bit_rate, ONLY_LONG_SEQUENCE);
392 
393   pstr_psy_config->ratio = C_RATIO;
394   pstr_psy_config->max_allowed_inc_fac = 2.0f;
395   pstr_psy_config->min_remaining_thr_fac = 0.01f;
396 
397   pstr_psy_config->clip_energy = (CLIP_ENERGY_VALUE_LONG * ccfl) / FRAME_LEN_LONG;
398   pstr_psy_config->low_pass_line = (WORD32)((2 * band_width * ccfl) / sample_rate);
399 
400   for (sfb = 0; sfb < pstr_psy_config->sfb_count; sfb++) {
401     if (pstr_psy_config->sfb_offset[sfb] >= pstr_psy_config->low_pass_line) break;
402   }
403   pstr_psy_config->sfb_active = sfb;
404 
405   iusace_min_snr_init(bit_rate, sample_rate,
406                       pstr_psy_config->sfb_offset[pstr_psy_config->sfb_count],
407                       pstr_psy_config->sfb_offset, sfb_bark_val, pstr_psy_config->sfb_active,
408                       pstr_psy_config->sfb_min_snr);
409 
410   return;
411 }
412 
iusace_psy_short_config_init(WORD32 bit_rate,WORD32 sample_rate,WORD32 band_width,ia_psy_mod_short_config_struct * pstr_psy_config,WORD32 ccfl)413 VOID iusace_psy_short_config_init(WORD32 bit_rate, WORD32 sample_rate, WORD32 band_width,
414                                   ia_psy_mod_short_config_struct *pstr_psy_config, WORD32 ccfl) {
415   WORD32 sfb;
416   WORD32 frame_len_short = (ccfl * FRAME_LEN_SHORT_128) / FRAME_LEN_LONG;
417   FLOAT32 sfb_bark_val[MAX_NUM_GROUPED_SFB];
418 
419   iusace_sfb_init(sample_rate, EIGHT_SHORT_SEQUENCE, pstr_psy_config->sfb_offset,
420                   &(pstr_psy_config->sfb_count), ccfl);
421 
422   iusace_bark_values_init(pstr_psy_config->sfb_count, pstr_psy_config->sfb_offset,
423                           pstr_psy_config->sfb_offset[pstr_psy_config->sfb_count], sample_rate,
424                           sfb_bark_val);
425 
426   iusace_thr_quiet_init(pstr_psy_config->sfb_count, pstr_psy_config->sfb_offset, sfb_bark_val,
427                         pstr_psy_config->sfb_thr_quiet);
428 
429   iusace_spreading_init(
430       pstr_psy_config->sfb_count, sfb_bark_val, pstr_psy_config->sfb_mask_low_fac,
431       pstr_psy_config->sfb_mask_high_fac, pstr_psy_config->sfb_mask_low_fac_spr_ener,
432       pstr_psy_config->sfb_mask_high_fac_spr_ener, bit_rate, EIGHT_SHORT_SEQUENCE);
433 
434   pstr_psy_config->ratio = C_RATIO;
435   pstr_psy_config->max_allowed_inc_fac = 2.0f;
436   pstr_psy_config->min_remaining_thr_fac = 0.01f;
437 
438   pstr_psy_config->clip_energy =
439       (CLIP_ENERGY_VALUE_SHORT * frame_len_short) / FRAME_LEN_SHORT_128;
440   pstr_psy_config->low_pass_line = (WORD32)((2 * band_width * frame_len_short) / sample_rate);
441 
442   for (sfb = 0; sfb < pstr_psy_config->sfb_count; sfb++) {
443     if (pstr_psy_config->sfb_offset[sfb] >= pstr_psy_config->low_pass_line) break;
444   }
445   pstr_psy_config->sfb_active = sfb;
446 
447   iusace_min_snr_init(bit_rate, sample_rate,
448                       pstr_psy_config->sfb_offset[pstr_psy_config->sfb_count],
449                       pstr_psy_config->sfb_offset, sfb_bark_val, pstr_psy_config->sfb_active,
450                       pstr_psy_config->sfb_min_snr);
451 
452   return;
453 }
454 
iusace_sfb_params_init(WORD32 sample_rate,WORD32 frame_len,WORD32 * ptr_sfb_width,WORD32 * num_sfb,WORD32 win_seq)455 IA_ERRORCODE iusace_sfb_params_init(WORD32 sample_rate, WORD32 frame_len, WORD32 *ptr_sfb_width,
456                                     WORD32 *num_sfb, WORD32 win_seq) {
457   WORD32 i, j, k;
458   ia_sfb_info_struct *ptr_sr_info = NULL;
459   WORD32 sampling_rate_mapped = 0;
460 
461   if (frame_len == 1024) {
462     ptr_sr_info = &iusace_sfb_info_1024[0];
463   } else {
464     ptr_sr_info = &iusace_sfb_info_768[0];
465   }
466 
467   if (sample_rate < 0)
468   {
469     return IA_EXHEAACE_INIT_FATAL_USAC_INVALID_CORE_SAMPLE_RATE;
470   }
471 
472   sampling_rate_mapped = iusace_map_sample_rate(sample_rate);
473 
474   while (ptr_sr_info->sample_rate != sampling_rate_mapped) {
475     if (ptr_sr_info->sample_rate == -1) {
476       return IA_EXHEAACE_INIT_FATAL_USAC_INVALID_CORE_SAMPLE_RATE;
477     }
478     ptr_sr_info++;
479   }
480 
481   j = 0;
482   for (i = 0; i < ptr_sr_info->num_sfb_long; i++) {
483     k = ptr_sr_info->cb_offset_long[i];
484     ptr_sr_info->sfb_width_long[i] = k - j;
485     j = k;
486   }
487   j = 0;
488   for (i = 0; i < ptr_sr_info->num_sfb_short; i++) {
489     k = ptr_sr_info->cb_offset_short[i];
490     ptr_sr_info->sfb_width_short[i] = k - j;
491     j = k;
492   }
493 
494   switch (win_seq) {
495     case EIGHT_SHORT_SEQUENCE:
496       memcpy(ptr_sfb_width, ptr_sr_info->sfb_width_short, (MAX_SFB_SHORT) * sizeof(WORD32));
497       *num_sfb = ptr_sr_info->num_sfb_short;
498       break;
499     case ONLY_LONG_SEQUENCE:
500     case LONG_START_SEQUENCE:
501     case STOP_START_SEQUENCE:
502     case LONG_STOP_SEQUENCE:
503     default:
504       memcpy(ptr_sfb_width, ptr_sr_info->sfb_width_long, MAX_SFB_LONG * sizeof(WORD32));
505       *num_sfb = ptr_sr_info->num_sfb_long;
506       break;
507   }
508 
509   return IA_NO_ERROR;
510 }
511