xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_fd_qc_adjthr.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1*15dc779aSAndroid Build Coastguard Worker /******************************************************************************
2*15dc779aSAndroid Build Coastguard Worker  *                                                                            *
3*15dc779aSAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
4*15dc779aSAndroid Build Coastguard Worker  *
5*15dc779aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*15dc779aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*15dc779aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at:
8*15dc779aSAndroid Build Coastguard Worker  *
9*15dc779aSAndroid Build Coastguard Worker  * http://www.apache.org/licenses/LICENSE-2.0
10*15dc779aSAndroid Build Coastguard Worker  *
11*15dc779aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*15dc779aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*15dc779aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*15dc779aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*15dc779aSAndroid Build Coastguard Worker  * limitations under the License.
16*15dc779aSAndroid Build Coastguard Worker  *
17*15dc779aSAndroid Build Coastguard Worker  *****************************************************************************
18*15dc779aSAndroid Build Coastguard Worker  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*15dc779aSAndroid Build Coastguard Worker  */
20*15dc779aSAndroid Build Coastguard Worker 
21*15dc779aSAndroid Build Coastguard Worker #include <string.h>
22*15dc779aSAndroid Build Coastguard Worker #include <math.h>
23*15dc779aSAndroid Build Coastguard Worker #include <stdlib.h>
24*15dc779aSAndroid Build Coastguard Worker #include <limits.h>
25*15dc779aSAndroid Build Coastguard Worker #include <float.h>
26*15dc779aSAndroid Build Coastguard Worker #include "iusace_type_def.h"
27*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_error_standards.h"
28*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_error_codes.h"
29*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_psy_const.h"
30*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_tns.h"
31*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_tns_params.h"
32*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_rom.h"
33*15dc779aSAndroid Build Coastguard Worker #include "iusace_block_switch_const.h"
34*15dc779aSAndroid Build Coastguard Worker #include "iusace_cnst.h"
35*15dc779aSAndroid Build Coastguard Worker #include "iusace_rom.h"
36*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_mps_common_define.h"
37*15dc779aSAndroid Build Coastguard Worker #include "iusace_bitbuffer.h"
38*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_common_enc.h"
39*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc.h"
40*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_api.h"
41*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc_eq.h"
42*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_uni_drc_filter_bank.h"
43*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_gain_enc.h"
44*15dc779aSAndroid Build Coastguard Worker #include "impd_drc_struct_def.h"
45*15dc779aSAndroid Build Coastguard Worker 
46*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_memory_standards.h"
47*15dc779aSAndroid Build Coastguard Worker #include "iusace_tns_usac.h"
48*15dc779aSAndroid Build Coastguard Worker #include "iusace_psy_mod.h"
49*15dc779aSAndroid Build Coastguard Worker #include "iusace_config.h"
50*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_adjust_threshold_data.h"
51*15dc779aSAndroid Build Coastguard Worker #include "iusace_fd_qc_util.h"
52*15dc779aSAndroid Build Coastguard Worker #include "iusace_fd_qc_adjthr.h"
53*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_aac_constants.h"
54*15dc779aSAndroid Build Coastguard Worker #include "ixheaace_sbr_def.h"
55*15dc779aSAndroid Build Coastguard Worker 
iusace_bits_to_pe(const FLOAT32 bits)56*15dc779aSAndroid Build Coastguard Worker FLOAT32 iusace_bits_to_pe(const FLOAT32 bits) { return (bits * 1.18f); }
57*15dc779aSAndroid Build Coastguard Worker 
iusace_adj_thr_init(ia_adj_thr_elem_struct * pstr_adj_thr_ele,const FLOAT32 mean_pe,WORD32 ch_bitrate)58*15dc779aSAndroid Build Coastguard Worker VOID iusace_adj_thr_init(ia_adj_thr_elem_struct *pstr_adj_thr_ele, const FLOAT32 mean_pe,
59*15dc779aSAndroid Build Coastguard Worker                          WORD32 ch_bitrate) {
60*15dc779aSAndroid Build Coastguard Worker   ia_min_snr_adapt_param_struct *pstr_min_snr_params =
61*15dc779aSAndroid Build Coastguard Worker       &pstr_adj_thr_ele->str_min_snr_adapt_params;
62*15dc779aSAndroid Build Coastguard Worker 
63*15dc779aSAndroid Build Coastguard Worker   pstr_adj_thr_ele->pe_min = (FLOAT32)0.8f * mean_pe;
64*15dc779aSAndroid Build Coastguard Worker   pstr_adj_thr_ele->pe_max = (FLOAT32)1.2f * mean_pe;
65*15dc779aSAndroid Build Coastguard Worker   pstr_adj_thr_ele->pe_offset = 0.0f;
66*15dc779aSAndroid Build Coastguard Worker 
67*15dc779aSAndroid Build Coastguard Worker   if (ch_bitrate < 32000) {
68*15dc779aSAndroid Build Coastguard Worker     pstr_adj_thr_ele->pe_offset =
69*15dc779aSAndroid Build Coastguard Worker         MAX((FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate);
70*15dc779aSAndroid Build Coastguard Worker   }
71*15dc779aSAndroid Build Coastguard Worker 
72*15dc779aSAndroid Build Coastguard Worker   if (ch_bitrate > 20000) {
73*15dc779aSAndroid Build Coastguard Worker     pstr_adj_thr_ele->str_ah_param.modify_min_snr = TRUE;
74*15dc779aSAndroid Build Coastguard Worker     pstr_adj_thr_ele->str_ah_param.start_sfb_long = 15;
75*15dc779aSAndroid Build Coastguard Worker     pstr_adj_thr_ele->str_ah_param.start_sfb_short = 3;
76*15dc779aSAndroid Build Coastguard Worker   } else {
77*15dc779aSAndroid Build Coastguard Worker     pstr_adj_thr_ele->str_ah_param.modify_min_snr = FALSE;
78*15dc779aSAndroid Build Coastguard Worker     pstr_adj_thr_ele->str_ah_param.start_sfb_long = 0;
79*15dc779aSAndroid Build Coastguard Worker     pstr_adj_thr_ele->str_ah_param.start_sfb_short = 0;
80*15dc779aSAndroid Build Coastguard Worker   }
81*15dc779aSAndroid Build Coastguard Worker 
82*15dc779aSAndroid Build Coastguard Worker   pstr_min_snr_params->max_red = (FLOAT32)0.25f;
83*15dc779aSAndroid Build Coastguard Worker 
84*15dc779aSAndroid Build Coastguard Worker   pstr_min_snr_params->start_ratio = (FLOAT32)10.0f;
85*15dc779aSAndroid Build Coastguard Worker 
86*15dc779aSAndroid Build Coastguard Worker   pstr_min_snr_params->max_ratio = (FLOAT32)1000.0f;
87*15dc779aSAndroid Build Coastguard Worker 
88*15dc779aSAndroid Build Coastguard Worker   pstr_min_snr_params->red_ratio_fac =
89*15dc779aSAndroid Build Coastguard Worker       (1.0f - pstr_min_snr_params->max_red) /
90*15dc779aSAndroid Build Coastguard Worker       (10.0f * (FLOAT32)log10(pstr_min_snr_params->start_ratio / pstr_min_snr_params->max_ratio));
91*15dc779aSAndroid Build Coastguard Worker 
92*15dc779aSAndroid Build Coastguard Worker   pstr_min_snr_params->red_offs = 1.0f - pstr_min_snr_params->red_ratio_fac * 10.0f *
93*15dc779aSAndroid Build Coastguard Worker                                              (FLOAT32)log10(pstr_min_snr_params->start_ratio);
94*15dc779aSAndroid Build Coastguard Worker 
95*15dc779aSAndroid Build Coastguard Worker   pstr_adj_thr_ele->pe_last = (FLOAT32)0.0f;
96*15dc779aSAndroid Build Coastguard Worker   pstr_adj_thr_ele->dyn_bits_last = 0;
97*15dc779aSAndroid Build Coastguard Worker   pstr_adj_thr_ele->pe_correction_fac = (FLOAT32)1.0f;
98*15dc779aSAndroid Build Coastguard Worker }
99*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_sfb_pe_data(ia_qc_pe_data_struct * pstr_qc_pe_data,ia_psy_mod_out_data_struct * pstr_psy_out,WORD32 num_channels,WORD32 chn)100*15dc779aSAndroid Build Coastguard Worker static VOID iusace_calc_sfb_pe_data(ia_qc_pe_data_struct *pstr_qc_pe_data,
101*15dc779aSAndroid Build Coastguard Worker                                     ia_psy_mod_out_data_struct *pstr_psy_out, WORD32 num_channels,
102*15dc779aSAndroid Build Coastguard Worker                                     WORD32 chn) {
103*15dc779aSAndroid Build Coastguard Worker   WORD32 ch, idx = 0;
104*15dc779aSAndroid Build Coastguard Worker   WORD32 scf_band_grp;
105*15dc779aSAndroid Build Coastguard Worker   FLOAT32 num_lines;
106*15dc779aSAndroid Build Coastguard Worker   FLOAT32 ld_thr, ld_ratio;
107*15dc779aSAndroid Build Coastguard Worker   WORD32 i = 0, scf;
108*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb_count;
109*15dc779aSAndroid Build Coastguard Worker   WORD32 scf_band_per_grp;
110*15dc779aSAndroid Build Coastguard Worker   WORD32 max_sfb_per_grp;
111*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_sfb_energy;
112*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_sfb_thr;
113*15dc779aSAndroid Build Coastguard Worker   ia_qc_pe_chan_data_struct *str_qc_pe_chan_data;
114*15dc779aSAndroid Build Coastguard Worker 
115*15dc779aSAndroid Build Coastguard Worker   pstr_qc_pe_data->pe = pstr_qc_pe_data->offset;
116*15dc779aSAndroid Build Coastguard Worker   pstr_qc_pe_data->const_part = 0.0f;
117*15dc779aSAndroid Build Coastguard Worker   pstr_qc_pe_data->num_active_lines = 0.0f;
118*15dc779aSAndroid Build Coastguard Worker 
119*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_channels; ch++) {
120*15dc779aSAndroid Build Coastguard Worker     sfb_count = pstr_psy_out[ch].sfb_count;
121*15dc779aSAndroid Build Coastguard Worker     scf_band_per_grp = pstr_psy_out[ch].sfb_per_group;
122*15dc779aSAndroid Build Coastguard Worker     max_sfb_per_grp = pstr_psy_out[ch].max_sfb_per_grp;
123*15dc779aSAndroid Build Coastguard Worker     ptr_sfb_energy = pstr_psy_out[ch].ptr_sfb_energy;
124*15dc779aSAndroid Build Coastguard Worker     ptr_sfb_thr = pstr_psy_out[ch].ptr_sfb_thr;
125*15dc779aSAndroid Build Coastguard Worker     str_qc_pe_chan_data = &pstr_qc_pe_data->pe_ch_data[idx];
126*15dc779aSAndroid Build Coastguard Worker     str_qc_pe_chan_data->pe = 0;
127*15dc779aSAndroid Build Coastguard Worker     str_qc_pe_chan_data->num_active_lines = 0;
128*15dc779aSAndroid Build Coastguard Worker     str_qc_pe_chan_data->const_part = 0;
129*15dc779aSAndroid Build Coastguard Worker 
130*15dc779aSAndroid Build Coastguard Worker     for (scf_band_grp = 0; scf_band_grp < sfb_count; scf_band_grp += scf_band_per_grp) {
131*15dc779aSAndroid Build Coastguard Worker       i = scf_band_grp;
132*15dc779aSAndroid Build Coastguard Worker       for (scf = max_sfb_per_grp - 1; scf >= 0; scf--, i++) {
133*15dc779aSAndroid Build Coastguard Worker         if (ptr_sfb_energy[i] > ptr_sfb_thr[i]) {
134*15dc779aSAndroid Build Coastguard Worker           ld_thr = (FLOAT32)log(ptr_sfb_thr[i]) * LOG2_1;
135*15dc779aSAndroid Build Coastguard Worker           ld_ratio = str_qc_pe_chan_data->sfb_ld_energy[i] - ld_thr;
136*15dc779aSAndroid Build Coastguard Worker           num_lines = str_qc_pe_chan_data->sfb_lines[i];
137*15dc779aSAndroid Build Coastguard Worker           if (ld_ratio >= PE_C1) {
138*15dc779aSAndroid Build Coastguard Worker             str_qc_pe_chan_data->sfb_pe[i] = num_lines * ld_ratio;
139*15dc779aSAndroid Build Coastguard Worker             str_qc_pe_chan_data->sfb_const_part[i] =
140*15dc779aSAndroid Build Coastguard Worker                 num_lines * str_qc_pe_chan_data->sfb_ld_energy[i];
141*15dc779aSAndroid Build Coastguard Worker           } else {
142*15dc779aSAndroid Build Coastguard Worker             str_qc_pe_chan_data->sfb_pe[i] = num_lines * (PE_C2 + PE_C3 * ld_ratio);
143*15dc779aSAndroid Build Coastguard Worker             str_qc_pe_chan_data->sfb_const_part[i] =
144*15dc779aSAndroid Build Coastguard Worker                 num_lines * (PE_C2 + PE_C3 * str_qc_pe_chan_data->sfb_ld_energy[i]);
145*15dc779aSAndroid Build Coastguard Worker             num_lines = num_lines * PE_C3;
146*15dc779aSAndroid Build Coastguard Worker           }
147*15dc779aSAndroid Build Coastguard Worker           str_qc_pe_chan_data->num_sfb_active_lines[i] = num_lines;
148*15dc779aSAndroid Build Coastguard Worker         } else {
149*15dc779aSAndroid Build Coastguard Worker           str_qc_pe_chan_data->sfb_pe[i] = 0.0f;
150*15dc779aSAndroid Build Coastguard Worker           str_qc_pe_chan_data->sfb_const_part[i] = 0.0f;
151*15dc779aSAndroid Build Coastguard Worker           str_qc_pe_chan_data->num_sfb_active_lines[i] = 0.0;
152*15dc779aSAndroid Build Coastguard Worker         }
153*15dc779aSAndroid Build Coastguard Worker 
154*15dc779aSAndroid Build Coastguard Worker         str_qc_pe_chan_data->pe += str_qc_pe_chan_data->sfb_pe[i];
155*15dc779aSAndroid Build Coastguard Worker         str_qc_pe_chan_data->const_part += str_qc_pe_chan_data->sfb_const_part[i];
156*15dc779aSAndroid Build Coastguard Worker         str_qc_pe_chan_data->num_active_lines += str_qc_pe_chan_data->num_sfb_active_lines[i];
157*15dc779aSAndroid Build Coastguard Worker       }
158*15dc779aSAndroid Build Coastguard Worker     }
159*15dc779aSAndroid Build Coastguard Worker     pstr_qc_pe_data->pe += str_qc_pe_chan_data->pe;
160*15dc779aSAndroid Build Coastguard Worker     pstr_qc_pe_data->const_part += str_qc_pe_chan_data->const_part;
161*15dc779aSAndroid Build Coastguard Worker     pstr_qc_pe_data->num_active_lines += str_qc_pe_chan_data->num_active_lines;
162*15dc779aSAndroid Build Coastguard Worker     pstr_psy_out[ch].pe = pstr_qc_pe_data->pe;
163*15dc779aSAndroid Build Coastguard Worker     idx++;
164*15dc779aSAndroid Build Coastguard Worker   }
165*15dc779aSAndroid Build Coastguard Worker   return;
166*15dc779aSAndroid Build Coastguard Worker }
167*15dc779aSAndroid Build Coastguard Worker 
iusace_adj_pe_minmax(const FLOAT32 curr_pe,FLOAT32 * pe_min,FLOAT32 * pe_max)168*15dc779aSAndroid Build Coastguard Worker static VOID iusace_adj_pe_minmax(const FLOAT32 curr_pe, FLOAT32 *pe_min, FLOAT32 *pe_max) {
169*15dc779aSAndroid Build Coastguard Worker   FLOAT32 min_hi_fac = 0.3f, max_hi_fac = 1.0f, min_low_fac = 0.14f, max_low_fac = 0.07f;
170*15dc779aSAndroid Build Coastguard Worker   FLOAT32 diff;
171*15dc779aSAndroid Build Coastguard Worker   FLOAT32 min_diff = curr_pe * (FLOAT32)0.1666666667f;
172*15dc779aSAndroid Build Coastguard Worker 
173*15dc779aSAndroid Build Coastguard Worker   if (curr_pe > *pe_max) {
174*15dc779aSAndroid Build Coastguard Worker     diff = (curr_pe - *pe_max);
175*15dc779aSAndroid Build Coastguard Worker     *pe_min += diff * min_hi_fac;
176*15dc779aSAndroid Build Coastguard Worker     *pe_max += diff * max_hi_fac;
177*15dc779aSAndroid Build Coastguard Worker   } else {
178*15dc779aSAndroid Build Coastguard Worker     if (curr_pe < *pe_min) {
179*15dc779aSAndroid Build Coastguard Worker       diff = (*pe_min - curr_pe);
180*15dc779aSAndroid Build Coastguard Worker       *pe_min -= diff * min_low_fac;
181*15dc779aSAndroid Build Coastguard Worker       *pe_max -= diff * max_low_fac;
182*15dc779aSAndroid Build Coastguard Worker     } else {
183*15dc779aSAndroid Build Coastguard Worker       *pe_min += (curr_pe - *pe_min) * min_hi_fac;
184*15dc779aSAndroid Build Coastguard Worker       *pe_max -= (*pe_max - curr_pe) * max_low_fac;
185*15dc779aSAndroid Build Coastguard Worker     }
186*15dc779aSAndroid Build Coastguard Worker   }
187*15dc779aSAndroid Build Coastguard Worker 
188*15dc779aSAndroid Build Coastguard Worker   if ((*pe_max - *pe_min) < min_diff) {
189*15dc779aSAndroid Build Coastguard Worker     FLOAT32 low_part, high_part;
190*15dc779aSAndroid Build Coastguard Worker     low_part = MAX((FLOAT32)0.0f, curr_pe - *pe_min);
191*15dc779aSAndroid Build Coastguard Worker     high_part = MAX((FLOAT32)0.0f, *pe_max - curr_pe);
192*15dc779aSAndroid Build Coastguard Worker     *pe_max = curr_pe + high_part / (low_part + high_part) * min_diff;
193*15dc779aSAndroid Build Coastguard Worker     *pe_min = curr_pe - low_part / (low_part + high_part) * min_diff;
194*15dc779aSAndroid Build Coastguard Worker     *pe_min = MAX((FLOAT32)0.0f, *pe_min);
195*15dc779aSAndroid Build Coastguard Worker   }
196*15dc779aSAndroid Build Coastguard Worker 
197*15dc779aSAndroid Build Coastguard Worker   return;
198*15dc779aSAndroid Build Coastguard Worker }
199*15dc779aSAndroid Build Coastguard Worker 
iusace_bitres_calc_bitfac(const WORD32 bitres_bits,const WORD32 max_bitres_bits,const FLOAT32 pe,const WORD32 win_seq,const WORD32 avg_bits,const FLOAT32 max_bit_fac,ia_adj_thr_elem_struct * pstr_adj_thr_elem)200*15dc779aSAndroid Build Coastguard Worker static FLOAT32 iusace_bitres_calc_bitfac(const WORD32 bitres_bits, const WORD32 max_bitres_bits,
201*15dc779aSAndroid Build Coastguard Worker                                          const FLOAT32 pe, const WORD32 win_seq,
202*15dc779aSAndroid Build Coastguard Worker                                          const WORD32 avg_bits, const FLOAT32 max_bit_fac,
203*15dc779aSAndroid Build Coastguard Worker                                          ia_adj_thr_elem_struct *pstr_adj_thr_elem) {
204*15dc779aSAndroid Build Coastguard Worker   FLOAT32 pex;
205*15dc779aSAndroid Build Coastguard Worker   FLOAT32 fill_lvl = 0.0f;
206*15dc779aSAndroid Build Coastguard Worker   FLOAT32 bit_save, bit_spend, bitres_factor;
207*15dc779aSAndroid Build Coastguard Worker 
208*15dc779aSAndroid Build Coastguard Worker   if (max_bitres_bits) {
209*15dc779aSAndroid Build Coastguard Worker     fill_lvl = (FLOAT32)bitres_bits / max_bitres_bits;
210*15dc779aSAndroid Build Coastguard Worker   }
211*15dc779aSAndroid Build Coastguard Worker 
212*15dc779aSAndroid Build Coastguard Worker   if (win_seq != EIGHT_SHORT_SEQUENCE) {
213*15dc779aSAndroid Build Coastguard Worker     fill_lvl = MAX(fill_lvl, CLIP_SAVE_LO_LONG);
214*15dc779aSAndroid Build Coastguard Worker     fill_lvl = MIN(fill_lvl, CLIP_SAVE_HI_LONG);
215*15dc779aSAndroid Build Coastguard Worker     bit_save = MAX_BITS_SAVE_LONG - (BITS_SAVE_RATIO_LONG * (fill_lvl - CLIP_SAVE_LO_LONG));
216*15dc779aSAndroid Build Coastguard Worker     bit_spend = MIN_BITS_SPEND_LONG + (BITS_SPEND_RATIO_LONG * (fill_lvl - CLIP_SPEND_LO_LONG));
217*15dc779aSAndroid Build Coastguard Worker   } else {
218*15dc779aSAndroid Build Coastguard Worker     fill_lvl = MAX(fill_lvl, CLIP_SPEND_LO_SHORT);
219*15dc779aSAndroid Build Coastguard Worker     fill_lvl = MIN(fill_lvl, CLIP_SPEND_HI_SHORT);
220*15dc779aSAndroid Build Coastguard Worker     bit_save = MAX_BITS_SAVE_SHORT - (BITS_SAVE_RATIO_SHORT * (fill_lvl - CLIP_SAVE_LO_SHORT));
221*15dc779aSAndroid Build Coastguard Worker     bit_spend =
222*15dc779aSAndroid Build Coastguard Worker         MIN_BITS_SPEND_SHORT + (BITS_SPEND_RATIO_SHORT * (fill_lvl - CLIP_SPEND_LO_SHORT));
223*15dc779aSAndroid Build Coastguard Worker   }
224*15dc779aSAndroid Build Coastguard Worker 
225*15dc779aSAndroid Build Coastguard Worker   pex = MAX(pe, pstr_adj_thr_elem->pe_min);
226*15dc779aSAndroid Build Coastguard Worker   pex = MIN(pex, pstr_adj_thr_elem->pe_max);
227*15dc779aSAndroid Build Coastguard Worker 
228*15dc779aSAndroid Build Coastguard Worker   bitres_factor =
229*15dc779aSAndroid Build Coastguard Worker       (FLOAT32)1.0f - bit_save +
230*15dc779aSAndroid Build Coastguard Worker       ((bit_spend + bit_save) / (pstr_adj_thr_elem->pe_max - pstr_adj_thr_elem->pe_min)) *
231*15dc779aSAndroid Build Coastguard Worker           (pex - pstr_adj_thr_elem->pe_min);
232*15dc779aSAndroid Build Coastguard Worker   bitres_factor = MIN(bitres_factor,
233*15dc779aSAndroid Build Coastguard Worker                       (FLOAT32)1.0f - (FLOAT32)0.3f + (FLOAT32)bitres_bits / (FLOAT32)avg_bits);
234*15dc779aSAndroid Build Coastguard Worker 
235*15dc779aSAndroid Build Coastguard Worker   bitres_factor = MIN(bitres_factor, max_bit_fac);
236*15dc779aSAndroid Build Coastguard Worker   iusace_adj_pe_minmax(pe, &pstr_adj_thr_elem->pe_min, &pstr_adj_thr_elem->pe_max);
237*15dc779aSAndroid Build Coastguard Worker 
238*15dc779aSAndroid Build Coastguard Worker   return bitres_factor;
239*15dc779aSAndroid Build Coastguard Worker }
240*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_pe_correction(FLOAT32 * correction_fac,const FLOAT32 pe_act,const FLOAT32 pe_last,const WORD32 bits_prev)241*15dc779aSAndroid Build Coastguard Worker static VOID iusace_calc_pe_correction(FLOAT32 *correction_fac, const FLOAT32 pe_act,
242*15dc779aSAndroid Build Coastguard Worker                                       const FLOAT32 pe_last, const WORD32 bits_prev) {
243*15dc779aSAndroid Build Coastguard Worker   if ((bits_prev > 0) && (pe_act < (FLOAT32)1.5f * pe_last) &&
244*15dc779aSAndroid Build Coastguard Worker       (pe_act > (FLOAT32)0.7f * pe_last) &&
245*15dc779aSAndroid Build Coastguard Worker       ((FLOAT32)1.2f * iusace_bits_to_pe((FLOAT32)bits_prev) > pe_last) &&
246*15dc779aSAndroid Build Coastguard Worker       ((FLOAT32)0.65f * iusace_bits_to_pe((FLOAT32)bits_prev) < pe_last)) {
247*15dc779aSAndroid Build Coastguard Worker     FLOAT32 new_fac = pe_last / iusace_bits_to_pe((FLOAT32)bits_prev);
248*15dc779aSAndroid Build Coastguard Worker 
249*15dc779aSAndroid Build Coastguard Worker     if (new_fac < (FLOAT32)1.0f) {
250*15dc779aSAndroid Build Coastguard Worker       new_fac = MIN((FLOAT32)1.1f * new_fac, (FLOAT32)1.0f);
251*15dc779aSAndroid Build Coastguard Worker       new_fac = MAX(new_fac, (FLOAT32)0.85f);
252*15dc779aSAndroid Build Coastguard Worker     } else {
253*15dc779aSAndroid Build Coastguard Worker       new_fac = MAX((FLOAT32)0.9f * new_fac, (FLOAT32)1.0f);
254*15dc779aSAndroid Build Coastguard Worker       new_fac = MIN(new_fac, (FLOAT32)1.15f);
255*15dc779aSAndroid Build Coastguard Worker     }
256*15dc779aSAndroid Build Coastguard Worker     if (((new_fac > (FLOAT32)1.0f) && (*correction_fac < (FLOAT32)1.0f)) ||
257*15dc779aSAndroid Build Coastguard Worker         ((new_fac < (FLOAT32)1.0f) && (*correction_fac > (FLOAT32)1.0f))) {
258*15dc779aSAndroid Build Coastguard Worker       *correction_fac = (FLOAT32)1.0f;
259*15dc779aSAndroid Build Coastguard Worker     }
260*15dc779aSAndroid Build Coastguard Worker 
261*15dc779aSAndroid Build Coastguard Worker     if ((*correction_fac < (FLOAT32)1.0f && new_fac < *correction_fac) ||
262*15dc779aSAndroid Build Coastguard Worker         (*correction_fac > (FLOAT32)1.0f && new_fac > *correction_fac))
263*15dc779aSAndroid Build Coastguard Worker       *correction_fac = (FLOAT32)0.85f * (*correction_fac) + (FLOAT32)0.15f * new_fac;
264*15dc779aSAndroid Build Coastguard Worker     else
265*15dc779aSAndroid Build Coastguard Worker       *correction_fac = (FLOAT32)0.7f * (*correction_fac) + (FLOAT32)0.3f * new_fac;
266*15dc779aSAndroid Build Coastguard Worker 
267*15dc779aSAndroid Build Coastguard Worker     *correction_fac = MIN(*correction_fac, (FLOAT32)1.15f);
268*15dc779aSAndroid Build Coastguard Worker     *correction_fac = MAX(*correction_fac, (FLOAT32)0.85f);
269*15dc779aSAndroid Build Coastguard Worker   } else {
270*15dc779aSAndroid Build Coastguard Worker     *correction_fac = (FLOAT32)1.0f;
271*15dc779aSAndroid Build Coastguard Worker   }
272*15dc779aSAndroid Build Coastguard Worker 
273*15dc779aSAndroid Build Coastguard Worker   return;
274*15dc779aSAndroid Build Coastguard Worker }
275*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_thr_exp(FLOAT32 ** thr_exp,ia_psy_mod_out_data_struct * pstr_psy_out,WORD32 num_chans,WORD32 chn)276*15dc779aSAndroid Build Coastguard Worker static VOID iusace_calc_thr_exp(FLOAT32 **thr_exp, ia_psy_mod_out_data_struct *pstr_psy_out,
277*15dc779aSAndroid Build Coastguard Worker                                 WORD32 num_chans, WORD32 chn) {
278*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb, ch, scf_band_grp, idx = 0;
279*15dc779aSAndroid Build Coastguard Worker   ia_psy_mod_out_data_struct *pstr_psy_chan_out;
280*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *scf_band_thr;
281*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_thr_exp;
282*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_chans; ch++) {
283*15dc779aSAndroid Build Coastguard Worker     pstr_psy_chan_out = &pstr_psy_out[ch];
284*15dc779aSAndroid Build Coastguard Worker     ptr_thr_exp = thr_exp[idx];
285*15dc779aSAndroid Build Coastguard Worker     for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
286*15dc779aSAndroid Build Coastguard Worker          scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
287*15dc779aSAndroid Build Coastguard Worker       FLOAT32 *thr_exp1 = &ptr_thr_exp[scf_band_grp];
288*15dc779aSAndroid Build Coastguard Worker       scf_band_thr = &pstr_psy_chan_out->ptr_sfb_thr[scf_band_grp];
289*15dc779aSAndroid Build Coastguard Worker       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
290*15dc779aSAndroid Build Coastguard Worker         thr_exp1[sfb] = (FLOAT32)pow(*scf_band_thr++, RED_EXP_VAL);
291*15dc779aSAndroid Build Coastguard Worker       }
292*15dc779aSAndroid Build Coastguard Worker     }
293*15dc779aSAndroid Build Coastguard Worker     idx++;
294*15dc779aSAndroid Build Coastguard Worker   }
295*15dc779aSAndroid Build Coastguard Worker 
296*15dc779aSAndroid Build Coastguard Worker   return;
297*15dc779aSAndroid Build Coastguard Worker }
298*15dc779aSAndroid Build Coastguard Worker 
iusace_adapt_min_snr(ia_psy_mod_out_data_struct * pstr_psy_out,ia_min_snr_adapt_param_struct * pstr_min_snr_params,WORD32 num_chans,WORD32 chn)299*15dc779aSAndroid Build Coastguard Worker static VOID iusace_adapt_min_snr(ia_psy_mod_out_data_struct *pstr_psy_out,
300*15dc779aSAndroid Build Coastguard Worker                                  ia_min_snr_adapt_param_struct *pstr_min_snr_params,
301*15dc779aSAndroid Build Coastguard Worker                                  WORD32 num_chans, WORD32 chn) {
302*15dc779aSAndroid Build Coastguard Worker   WORD32 num_sfb = 0, ch, scf_band_cnt, sfb_off, sfb;
303*15dc779aSAndroid Build Coastguard Worker   FLOAT32 avg_energy = 0.0f, db_ratio, min_snr_red;
304*15dc779aSAndroid Build Coastguard Worker   WORD32 i;
305*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_chans; ch++) {
306*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
307*15dc779aSAndroid Build Coastguard Worker 
308*15dc779aSAndroid Build Coastguard Worker     num_sfb = 0;
309*15dc779aSAndroid Build Coastguard Worker     avg_energy = 0;
310*15dc779aSAndroid Build Coastguard Worker     scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp;
311*15dc779aSAndroid Build Coastguard Worker 
312*15dc779aSAndroid Build Coastguard Worker     for (sfb_off = 0; sfb_off < pstr_psy_chan_out->sfb_count;
313*15dc779aSAndroid Build Coastguard Worker          sfb_off += pstr_psy_chan_out->sfb_per_group) {
314*15dc779aSAndroid Build Coastguard Worker       FLOAT32 *sfb_energy = &pstr_psy_chan_out->ptr_sfb_energy[sfb_off];
315*15dc779aSAndroid Build Coastguard Worker       for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--) {
316*15dc779aSAndroid Build Coastguard Worker         avg_energy += sfb_energy[sfb];
317*15dc779aSAndroid Build Coastguard Worker       }
318*15dc779aSAndroid Build Coastguard Worker       num_sfb += scf_band_cnt;
319*15dc779aSAndroid Build Coastguard Worker     }
320*15dc779aSAndroid Build Coastguard Worker 
321*15dc779aSAndroid Build Coastguard Worker     if (num_sfb > 0) {
322*15dc779aSAndroid Build Coastguard Worker       avg_energy /= num_sfb;
323*15dc779aSAndroid Build Coastguard Worker     }
324*15dc779aSAndroid Build Coastguard Worker 
325*15dc779aSAndroid Build Coastguard Worker     for (sfb_off = 0; sfb_off < pstr_psy_chan_out->sfb_count;
326*15dc779aSAndroid Build Coastguard Worker          sfb_off += pstr_psy_chan_out->sfb_per_group) {
327*15dc779aSAndroid Build Coastguard Worker       i = sfb_off;
328*15dc779aSAndroid Build Coastguard Worker       for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--, i++) {
329*15dc779aSAndroid Build Coastguard Worker         if (pstr_min_snr_params->start_ratio * pstr_psy_chan_out->ptr_sfb_energy[i] <
330*15dc779aSAndroid Build Coastguard Worker             avg_energy) {
331*15dc779aSAndroid Build Coastguard Worker           db_ratio =
332*15dc779aSAndroid Build Coastguard Worker               (FLOAT32)(10.0 * log10((MIN_FLT_VAL + avg_energy) /
333*15dc779aSAndroid Build Coastguard Worker                                      (MIN_FLT_VAL + pstr_psy_chan_out->ptr_sfb_energy[i])));
334*15dc779aSAndroid Build Coastguard Worker           min_snr_red =
335*15dc779aSAndroid Build Coastguard Worker               pstr_min_snr_params->red_offs + pstr_min_snr_params->red_ratio_fac * db_ratio;
336*15dc779aSAndroid Build Coastguard Worker           min_snr_red = MAX(min_snr_red, pstr_min_snr_params->max_red);
337*15dc779aSAndroid Build Coastguard Worker           pstr_psy_chan_out->sfb_min_snr[i] =
338*15dc779aSAndroid Build Coastguard Worker               (FLOAT32)pow(pstr_psy_out[ch].sfb_min_snr[i], min_snr_red);
339*15dc779aSAndroid Build Coastguard Worker           pstr_psy_chan_out->sfb_min_snr[i] = MIN(MIN_SNR_LIMIT, pstr_psy_out[ch].sfb_min_snr[i]);
340*15dc779aSAndroid Build Coastguard Worker         }
341*15dc779aSAndroid Build Coastguard Worker       }
342*15dc779aSAndroid Build Coastguard Worker     }
343*15dc779aSAndroid Build Coastguard Worker   }
344*15dc779aSAndroid Build Coastguard Worker 
345*15dc779aSAndroid Build Coastguard Worker   return;
346*15dc779aSAndroid Build Coastguard Worker }
347*15dc779aSAndroid Build Coastguard Worker 
iusace_init_avoid_hole_flag(WORD32 ** ah_flag,ia_psy_mod_out_data_struct * pstr_psy_out,ia_ah_param_struct * pstr_ah_param,WORD32 num_chans,WORD32 chn)348*15dc779aSAndroid Build Coastguard Worker static VOID iusace_init_avoid_hole_flag(WORD32 **ah_flag,
349*15dc779aSAndroid Build Coastguard Worker                                         ia_psy_mod_out_data_struct *pstr_psy_out,
350*15dc779aSAndroid Build Coastguard Worker                                         ia_ah_param_struct *pstr_ah_param, WORD32 num_chans,
351*15dc779aSAndroid Build Coastguard Worker                                         WORD32 chn) {
352*15dc779aSAndroid Build Coastguard Worker   WORD32 ch, idx;
353*15dc779aSAndroid Build Coastguard Worker   FLOAT32 sfb_energy;
354*15dc779aSAndroid Build Coastguard Worker   FLOAT32 scale_spread_energy;
355*15dc779aSAndroid Build Coastguard Worker   WORD32 scf_band_grp, sfb, scf_band;
356*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_scf_band_spread_energy, *ptr_scf_band_energy, *ptr_scf_band_min_snr;
357*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_chans; ch++) {
358*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
359*15dc779aSAndroid Build Coastguard Worker 
360*15dc779aSAndroid Build Coastguard Worker     if (pstr_psy_chan_out->window_sequence != EIGHT_SHORT_SEQUENCE) {
361*15dc779aSAndroid Build Coastguard Worker       scale_spread_energy = 0.5f;
362*15dc779aSAndroid Build Coastguard Worker     } else {
363*15dc779aSAndroid Build Coastguard Worker       scale_spread_energy = 0.63f;
364*15dc779aSAndroid Build Coastguard Worker     }
365*15dc779aSAndroid Build Coastguard Worker 
366*15dc779aSAndroid Build Coastguard Worker     for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
367*15dc779aSAndroid Build Coastguard Worker          scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
368*15dc779aSAndroid Build Coastguard Worker       ptr_scf_band_spread_energy = &pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp];
369*15dc779aSAndroid Build Coastguard Worker       sfb = pstr_psy_chan_out->max_sfb_per_grp;
370*15dc779aSAndroid Build Coastguard Worker       for (scf_band = sfb - 1; scf_band >= 0; scf_band--) {
371*15dc779aSAndroid Build Coastguard Worker         *ptr_scf_band_spread_energy = *ptr_scf_band_spread_energy * scale_spread_energy;
372*15dc779aSAndroid Build Coastguard Worker         ptr_scf_band_spread_energy++;
373*15dc779aSAndroid Build Coastguard Worker       }
374*15dc779aSAndroid Build Coastguard Worker     }
375*15dc779aSAndroid Build Coastguard Worker   }
376*15dc779aSAndroid Build Coastguard Worker 
377*15dc779aSAndroid Build Coastguard Worker   if (pstr_ah_param->modify_min_snr) {
378*15dc779aSAndroid Build Coastguard Worker     for (ch = chn; ch < chn + num_chans; ch++) {
379*15dc779aSAndroid Build Coastguard Worker       ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
380*15dc779aSAndroid Build Coastguard Worker       ptr_scf_band_energy = pstr_psy_chan_out->ptr_sfb_energy;
381*15dc779aSAndroid Build Coastguard Worker 
382*15dc779aSAndroid Build Coastguard Worker       ptr_scf_band_min_snr = pstr_psy_chan_out->sfb_min_snr;
383*15dc779aSAndroid Build Coastguard Worker 
384*15dc779aSAndroid Build Coastguard Worker       for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
385*15dc779aSAndroid Build Coastguard Worker            scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
386*15dc779aSAndroid Build Coastguard Worker         for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
387*15dc779aSAndroid Build Coastguard Worker           FLOAT32 sfb_en_m1, sfb_en_p1, avg_energy;
388*15dc779aSAndroid Build Coastguard Worker           if (scf_band > 0) {
389*15dc779aSAndroid Build Coastguard Worker             sfb_en_m1 = ptr_scf_band_energy[scf_band_grp + scf_band - 1];
390*15dc779aSAndroid Build Coastguard Worker           } else {
391*15dc779aSAndroid Build Coastguard Worker             sfb_en_m1 = ptr_scf_band_energy[scf_band_grp];
392*15dc779aSAndroid Build Coastguard Worker           }
393*15dc779aSAndroid Build Coastguard Worker           if (scf_band < pstr_psy_chan_out->max_sfb_per_grp - 1)
394*15dc779aSAndroid Build Coastguard Worker             sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band + 1];
395*15dc779aSAndroid Build Coastguard Worker           else
396*15dc779aSAndroid Build Coastguard Worker             sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band];
397*15dc779aSAndroid Build Coastguard Worker 
398*15dc779aSAndroid Build Coastguard Worker           avg_energy = (sfb_en_m1 + sfb_en_p1) / (FLOAT32)2.0f;
399*15dc779aSAndroid Build Coastguard Worker           sfb_energy = ptr_scf_band_energy[scf_band_grp + scf_band];
400*15dc779aSAndroid Build Coastguard Worker 
401*15dc779aSAndroid Build Coastguard Worker           if (sfb_energy > avg_energy) {
402*15dc779aSAndroid Build Coastguard Worker             FLOAT32 temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.316f);
403*15dc779aSAndroid Build Coastguard Worker             if (pstr_psy_chan_out->window_sequence != EIGHT_SHORT_SEQUENCE)
404*15dc779aSAndroid Build Coastguard Worker               temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.316f);
405*15dc779aSAndroid Build Coastguard Worker             else
406*15dc779aSAndroid Build Coastguard Worker               temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.5f);
407*15dc779aSAndroid Build Coastguard Worker             ptr_scf_band_min_snr[scf_band_grp + scf_band] =
408*15dc779aSAndroid Build Coastguard Worker                 MIN(ptr_scf_band_min_snr[scf_band_grp + scf_band], temp_min_snr);
409*15dc779aSAndroid Build Coastguard Worker           }
410*15dc779aSAndroid Build Coastguard Worker 
411*15dc779aSAndroid Build Coastguard Worker           if (((FLOAT32)2.0f * sfb_energy < avg_energy) && (sfb_energy > (FLOAT32)0.0f)) {
412*15dc779aSAndroid Build Coastguard Worker             FLOAT32 temp_min_snr = avg_energy / ((FLOAT32)2.0f * sfb_energy) *
413*15dc779aSAndroid Build Coastguard Worker                                    ptr_scf_band_min_snr[scf_band_grp + scf_band];
414*15dc779aSAndroid Build Coastguard Worker             temp_min_snr = MIN((FLOAT32)0.8f, temp_min_snr);
415*15dc779aSAndroid Build Coastguard Worker             ptr_scf_band_min_snr[scf_band_grp + scf_band] =
416*15dc779aSAndroid Build Coastguard Worker                 MIN(temp_min_snr, ptr_scf_band_min_snr[scf_band_grp + scf_band] * (FLOAT32)3.16f);
417*15dc779aSAndroid Build Coastguard Worker           }
418*15dc779aSAndroid Build Coastguard Worker         }
419*15dc779aSAndroid Build Coastguard Worker       }
420*15dc779aSAndroid Build Coastguard Worker     }
421*15dc779aSAndroid Build Coastguard Worker   }
422*15dc779aSAndroid Build Coastguard Worker 
423*15dc779aSAndroid Build Coastguard Worker   if (num_chans == 2) {
424*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *psy_out_mid = &pstr_psy_out[chn];
425*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *psy_out_side = &pstr_psy_out[chn + 1];
426*15dc779aSAndroid Build Coastguard Worker 
427*15dc779aSAndroid Build Coastguard Worker     for (sfb = 0; sfb < psy_out_mid->sfb_count; sfb++) {
428*15dc779aSAndroid Build Coastguard Worker       if (pstr_psy_out[chn].ms_used[sfb]) {
429*15dc779aSAndroid Build Coastguard Worker         FLOAT32 sfb_en_mid = psy_out_mid->ptr_sfb_energy[sfb];
430*15dc779aSAndroid Build Coastguard Worker         FLOAT32 sfb_en_side = psy_out_side->ptr_sfb_energy[sfb];
431*15dc779aSAndroid Build Coastguard Worker         FLOAT32 max_sfb_en = MAX(sfb_en_mid, sfb_en_side);
432*15dc779aSAndroid Build Coastguard Worker         FLOAT32 max_thr = 0.25f * psy_out_mid->sfb_min_snr[sfb] * max_sfb_en;
433*15dc779aSAndroid Build Coastguard Worker 
434*15dc779aSAndroid Build Coastguard Worker         psy_out_mid->sfb_min_snr[sfb] = (FLOAT32)MAX(
435*15dc779aSAndroid Build Coastguard Worker             psy_out_mid->sfb_min_snr[sfb],
436*15dc779aSAndroid Build Coastguard Worker             MIN(MAX_FLT_VAL, ((double)max_thr / (MIN_FLT_VAL + (double)sfb_en_mid))));
437*15dc779aSAndroid Build Coastguard Worker 
438*15dc779aSAndroid Build Coastguard Worker         if (psy_out_mid->ptr_sfb_energy[sfb] <= 1.0f) {
439*15dc779aSAndroid Build Coastguard Worker           psy_out_mid->ptr_sfb_energy[sfb] = MIN(psy_out_mid->ptr_sfb_energy[sfb], 0.8f);
440*15dc779aSAndroid Build Coastguard Worker         }
441*15dc779aSAndroid Build Coastguard Worker 
442*15dc779aSAndroid Build Coastguard Worker         psy_out_side->sfb_min_snr[sfb] = (FLOAT32)MAX(
443*15dc779aSAndroid Build Coastguard Worker             psy_out_side->sfb_min_snr[sfb],
444*15dc779aSAndroid Build Coastguard Worker             MIN(MAX_FLT_VAL, ((double)max_thr / (MIN_FLT_VAL + (double)sfb_en_side))));
445*15dc779aSAndroid Build Coastguard Worker 
446*15dc779aSAndroid Build Coastguard Worker         if (psy_out_side->sfb_min_snr[sfb] <= 1.0f) {
447*15dc779aSAndroid Build Coastguard Worker           psy_out_side->sfb_min_snr[sfb] = MIN(psy_out_side->sfb_min_snr[sfb], 0.8f);
448*15dc779aSAndroid Build Coastguard Worker         }
449*15dc779aSAndroid Build Coastguard Worker 
450*15dc779aSAndroid Build Coastguard Worker         if (sfb_en_mid > psy_out_mid->ptr_sfb_spread_energy[sfb]) {
451*15dc779aSAndroid Build Coastguard Worker           psy_out_side->ptr_sfb_spread_energy[sfb] = 0.9f * sfb_en_side;
452*15dc779aSAndroid Build Coastguard Worker         }
453*15dc779aSAndroid Build Coastguard Worker 
454*15dc779aSAndroid Build Coastguard Worker         if (sfb_en_side > psy_out_side->ptr_sfb_spread_energy[sfb]) {
455*15dc779aSAndroid Build Coastguard Worker           psy_out_mid->ptr_sfb_spread_energy[sfb] = 0.9f * sfb_en_mid;
456*15dc779aSAndroid Build Coastguard Worker         }
457*15dc779aSAndroid Build Coastguard Worker       }
458*15dc779aSAndroid Build Coastguard Worker     }
459*15dc779aSAndroid Build Coastguard Worker   }
460*15dc779aSAndroid Build Coastguard Worker   idx = 0;
461*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_chans; ch++) {
462*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
463*15dc779aSAndroid Build Coastguard Worker     for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
464*15dc779aSAndroid Build Coastguard Worker          scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
465*15dc779aSAndroid Build Coastguard Worker       for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
466*15dc779aSAndroid Build Coastguard Worker         if (pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp + scf_band] >
467*15dc779aSAndroid Build Coastguard Worker                 pstr_psy_chan_out->ptr_sfb_energy[scf_band_grp + scf_band] ||
468*15dc779aSAndroid Build Coastguard Worker             pstr_psy_chan_out->sfb_min_snr[scf_band_grp + scf_band] > (float)1.0) {
469*15dc779aSAndroid Build Coastguard Worker           ah_flag[idx][scf_band_grp + scf_band] = NO_AH;
470*15dc779aSAndroid Build Coastguard Worker         } else {
471*15dc779aSAndroid Build Coastguard Worker           ah_flag[idx][scf_band_grp + scf_band] = AH_INACTIVE;
472*15dc779aSAndroid Build Coastguard Worker         }
473*15dc779aSAndroid Build Coastguard Worker       }
474*15dc779aSAndroid Build Coastguard Worker 
475*15dc779aSAndroid Build Coastguard Worker       for (scf_band = pstr_psy_chan_out->max_sfb_per_grp;
476*15dc779aSAndroid Build Coastguard Worker            scf_band < pstr_psy_chan_out->sfb_per_group; scf_band++) {
477*15dc779aSAndroid Build Coastguard Worker         ah_flag[idx][scf_band_grp + scf_band] = NO_AH;
478*15dc779aSAndroid Build Coastguard Worker       }
479*15dc779aSAndroid Build Coastguard Worker     }
480*15dc779aSAndroid Build Coastguard Worker     idx++;
481*15dc779aSAndroid Build Coastguard Worker   }
482*15dc779aSAndroid Build Coastguard Worker 
483*15dc779aSAndroid Build Coastguard Worker   return;
484*15dc779aSAndroid Build Coastguard Worker }
485*15dc779aSAndroid Build Coastguard Worker 
iusace_reduce_thr(ia_psy_mod_out_data_struct * pstr_psy_out,WORD32 ** ah_flag,FLOAT32 ** thr_exp,const FLOAT32 red_value,WORD32 num_channels,WORD32 chn)486*15dc779aSAndroid Build Coastguard Worker static VOID iusace_reduce_thr(ia_psy_mod_out_data_struct *pstr_psy_out, WORD32 **ah_flag,
487*15dc779aSAndroid Build Coastguard Worker                               FLOAT32 **thr_exp, const FLOAT32 red_value, WORD32 num_channels,
488*15dc779aSAndroid Build Coastguard Worker                               WORD32 chn) {
489*15dc779aSAndroid Build Coastguard Worker   WORD32 ch, sfb_group, sfb, idx = 0;
490*15dc779aSAndroid Build Coastguard Worker   FLOAT32 sfb_energy, sfb_threshold, sfb_thr_reduced;
491*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *sfb_energy_fix, *sfb_threshold_fix, *sfb_min_snr_fix, *thr_exp_fix;
492*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_channels; ch++) {
493*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
494*15dc779aSAndroid Build Coastguard Worker     sfb_energy_fix = pstr_psy_chan_out->ptr_sfb_energy;
495*15dc779aSAndroid Build Coastguard Worker     sfb_threshold_fix = pstr_psy_chan_out->ptr_sfb_thr;
496*15dc779aSAndroid Build Coastguard Worker     sfb_min_snr_fix = pstr_psy_chan_out->sfb_min_snr;
497*15dc779aSAndroid Build Coastguard Worker     thr_exp_fix = &thr_exp[idx][0];
498*15dc779aSAndroid Build Coastguard Worker     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
499*15dc779aSAndroid Build Coastguard Worker          sfb_group += pstr_psy_chan_out->sfb_per_group) {
500*15dc779aSAndroid Build Coastguard Worker       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
501*15dc779aSAndroid Build Coastguard Worker         sfb_energy = sfb_energy_fix[sfb_group + sfb];
502*15dc779aSAndroid Build Coastguard Worker         sfb_threshold = sfb_threshold_fix[sfb_group + sfb];
503*15dc779aSAndroid Build Coastguard Worker         if (sfb_energy > sfb_threshold) {
504*15dc779aSAndroid Build Coastguard Worker           sfb_thr_reduced =
505*15dc779aSAndroid Build Coastguard Worker               (FLOAT32)pow((thr_exp_fix[sfb_group + sfb] + red_value), INV_RED_EXP_VAL);
506*15dc779aSAndroid Build Coastguard Worker 
507*15dc779aSAndroid Build Coastguard Worker           if ((sfb_thr_reduced > sfb_min_snr_fix[sfb_group + sfb] * sfb_energy) &&
508*15dc779aSAndroid Build Coastguard Worker               (ah_flag[idx][sfb_group + sfb] != NO_AH)) {
509*15dc779aSAndroid Build Coastguard Worker             sfb_thr_reduced = MAX(sfb_min_snr_fix[sfb_group + sfb] * sfb_energy, sfb_threshold);
510*15dc779aSAndroid Build Coastguard Worker             ah_flag[idx][sfb_group + sfb] = AH_ACTIVE;
511*15dc779aSAndroid Build Coastguard Worker           }
512*15dc779aSAndroid Build Coastguard Worker           sfb_threshold_fix[sfb_group + sfb] = sfb_thr_reduced;
513*15dc779aSAndroid Build Coastguard Worker         }
514*15dc779aSAndroid Build Coastguard Worker       }
515*15dc779aSAndroid Build Coastguard Worker     }
516*15dc779aSAndroid Build Coastguard Worker     idx++;
517*15dc779aSAndroid Build Coastguard Worker   }
518*15dc779aSAndroid Build Coastguard Worker 
519*15dc779aSAndroid Build Coastguard Worker   return;
520*15dc779aSAndroid Build Coastguard Worker }
521*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_pe_no_active_holes(FLOAT32 * pe,FLOAT32 * const_part,FLOAT32 * nactive_lines,ia_qc_pe_data_struct * pstr_qs_pe_data,WORD32 ** ah_flag,ia_psy_mod_out_data_struct * pstr_psy_out,WORD32 num_channels,WORD32 chn)522*15dc779aSAndroid Build Coastguard Worker static VOID iusace_calc_pe_no_active_holes(FLOAT32 *pe, FLOAT32 *const_part,
523*15dc779aSAndroid Build Coastguard Worker                                            FLOAT32 *nactive_lines,
524*15dc779aSAndroid Build Coastguard Worker                                            ia_qc_pe_data_struct *pstr_qs_pe_data,
525*15dc779aSAndroid Build Coastguard Worker                                            WORD32 **ah_flag,
526*15dc779aSAndroid Build Coastguard Worker                                            ia_psy_mod_out_data_struct *pstr_psy_out,
527*15dc779aSAndroid Build Coastguard Worker                                            WORD32 num_channels, WORD32 chn) {
528*15dc779aSAndroid Build Coastguard Worker   WORD32 ch, sfb_group, sfb, idx = 0;
529*15dc779aSAndroid Build Coastguard Worker   *pe = 0.0f;
530*15dc779aSAndroid Build Coastguard Worker   *const_part = 0.0f;
531*15dc779aSAndroid Build Coastguard Worker   *nactive_lines = 0;
532*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_channels; ch++) {
533*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
534*15dc779aSAndroid Build Coastguard Worker     ia_qc_pe_chan_data_struct *pe_channel_data = &pstr_qs_pe_data->pe_ch_data[idx];
535*15dc779aSAndroid Build Coastguard Worker 
536*15dc779aSAndroid Build Coastguard Worker     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
537*15dc779aSAndroid Build Coastguard Worker          sfb_group += pstr_psy_chan_out->sfb_per_group) {
538*15dc779aSAndroid Build Coastguard Worker       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
539*15dc779aSAndroid Build Coastguard Worker         if (ah_flag[idx][sfb_group + sfb] < AH_ACTIVE) {
540*15dc779aSAndroid Build Coastguard Worker           *pe += pe_channel_data->sfb_pe[sfb_group + sfb];
541*15dc779aSAndroid Build Coastguard Worker           *const_part += pe_channel_data->sfb_const_part[sfb_group + sfb];
542*15dc779aSAndroid Build Coastguard Worker           *nactive_lines += pe_channel_data->num_sfb_active_lines[sfb_group + sfb];
543*15dc779aSAndroid Build Coastguard Worker         }
544*15dc779aSAndroid Build Coastguard Worker       }
545*15dc779aSAndroid Build Coastguard Worker     }
546*15dc779aSAndroid Build Coastguard Worker     idx++;
547*15dc779aSAndroid Build Coastguard Worker   }
548*15dc779aSAndroid Build Coastguard Worker 
549*15dc779aSAndroid Build Coastguard Worker   return;
550*15dc779aSAndroid Build Coastguard Worker }
551*15dc779aSAndroid Build Coastguard Worker 
iusace_correct_thr(ia_psy_mod_out_data_struct * pstr_psy_out,WORD32 ** ah_flag,ia_qc_pe_data_struct * pstr_qs_pe_data,FLOAT32 ** thr_exp,const FLOAT32 red_value,const FLOAT32 delta_pe,WORD32 num_channels,WORD32 chn,UWORD8 * ptr_scratch)552*15dc779aSAndroid Build Coastguard Worker static IA_ERRORCODE iusace_correct_thr(ia_psy_mod_out_data_struct *pstr_psy_out, WORD32 **ah_flag,
553*15dc779aSAndroid Build Coastguard Worker                                        ia_qc_pe_data_struct *pstr_qs_pe_data, FLOAT32 **thr_exp,
554*15dc779aSAndroid Build Coastguard Worker                                        const FLOAT32 red_value, const FLOAT32 delta_pe,
555*15dc779aSAndroid Build Coastguard Worker                                        WORD32 num_channels, WORD32 chn, UWORD8 *ptr_scratch) {
556*15dc779aSAndroid Build Coastguard Worker   WORD32 i, ch, sfb_group, sfb, idx = 0;
557*15dc779aSAndroid Build Coastguard Worker   FLOAT32 delta_sfb_pe;
558*15dc779aSAndroid Build Coastguard Worker   FLOAT32 thr_factor;
559*15dc779aSAndroid Build Coastguard Worker   FLOAT32 norm_factor[2] = {0};
560*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *sfb_pe_factors[2];
561*15dc779aSAndroid Build Coastguard Worker   for (i = 0; i < 2; i++) {
562*15dc779aSAndroid Build Coastguard Worker     sfb_pe_factors[i] = (FLOAT32 *)ptr_scratch;
563*15dc779aSAndroid Build Coastguard Worker     ptr_scratch += (MAX_NUM_GROUPED_SFB) * sizeof(sfb_pe_factors[0][0]);
564*15dc779aSAndroid Build Coastguard Worker   }
565*15dc779aSAndroid Build Coastguard Worker   FLOAT32 sfb_en, sfb_thr, sfb_thr_reduced;
566*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *p_thr_exp;
567*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *p_sfb_energy, *p_sfb_thr, *p_sfb_min_snr;
568*15dc779aSAndroid Build Coastguard Worker   ia_psy_mod_out_data_struct *pstr_psy_chan_out = NULL;
569*15dc779aSAndroid Build Coastguard Worker   ia_qc_pe_chan_data_struct *pe_channel_data = NULL;
570*15dc779aSAndroid Build Coastguard Worker 
571*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_channels; ch++) {
572*15dc779aSAndroid Build Coastguard Worker     if (idx >= IXHEAACE_MAX_CH_IN_BS_ELE) {
573*15dc779aSAndroid Build Coastguard Worker       return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_NUM_CHANNEL;
574*15dc779aSAndroid Build Coastguard Worker     }
575*15dc779aSAndroid Build Coastguard Worker     pstr_psy_chan_out = &pstr_psy_out[ch];
576*15dc779aSAndroid Build Coastguard Worker     pe_channel_data = &pstr_qs_pe_data->pe_ch_data[idx];
577*15dc779aSAndroid Build Coastguard Worker     norm_factor[idx] = MIN_FLT_VAL;
578*15dc779aSAndroid Build Coastguard Worker     p_thr_exp = thr_exp[idx];
579*15dc779aSAndroid Build Coastguard Worker 
580*15dc779aSAndroid Build Coastguard Worker     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
581*15dc779aSAndroid Build Coastguard Worker          sfb_group += pstr_psy_chan_out->sfb_per_group) {
582*15dc779aSAndroid Build Coastguard Worker       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
583*15dc779aSAndroid Build Coastguard Worker         if ((ah_flag[idx][sfb_group + sfb] < AH_ACTIVE) || (delta_pe > 0)) {
584*15dc779aSAndroid Build Coastguard Worker           sfb_pe_factors[idx][sfb_group + sfb] =
585*15dc779aSAndroid Build Coastguard Worker               pe_channel_data->num_sfb_active_lines[sfb_group + sfb] /
586*15dc779aSAndroid Build Coastguard Worker               (p_thr_exp[sfb_group + sfb] + red_value);
587*15dc779aSAndroid Build Coastguard Worker           norm_factor[idx] += sfb_pe_factors[idx][sfb_group + sfb];
588*15dc779aSAndroid Build Coastguard Worker         } else {
589*15dc779aSAndroid Build Coastguard Worker           sfb_pe_factors[idx][sfb_group + sfb] = 0.0f;
590*15dc779aSAndroid Build Coastguard Worker         }
591*15dc779aSAndroid Build Coastguard Worker       }
592*15dc779aSAndroid Build Coastguard Worker     }
593*15dc779aSAndroid Build Coastguard Worker     idx++;
594*15dc779aSAndroid Build Coastguard Worker   }
595*15dc779aSAndroid Build Coastguard Worker   if (num_channels > 1) {
596*15dc779aSAndroid Build Coastguard Worker     norm_factor[0] = norm_factor[0] + norm_factor[1];
597*15dc779aSAndroid Build Coastguard Worker   }
598*15dc779aSAndroid Build Coastguard Worker   norm_factor[0] = 1.0f / norm_factor[0];
599*15dc779aSAndroid Build Coastguard Worker   idx = 0;
600*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_channels; ch++) {
601*15dc779aSAndroid Build Coastguard Worker     if (idx >= IXHEAACE_MAX_CH_IN_BS_ELE) {
602*15dc779aSAndroid Build Coastguard Worker       return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_NUM_CHANNEL;
603*15dc779aSAndroid Build Coastguard Worker     }
604*15dc779aSAndroid Build Coastguard Worker     pstr_psy_chan_out = &pstr_psy_out[ch];
605*15dc779aSAndroid Build Coastguard Worker     pe_channel_data = &pstr_qs_pe_data->pe_ch_data[idx];
606*15dc779aSAndroid Build Coastguard Worker     p_sfb_energy = pstr_psy_chan_out->ptr_sfb_energy;
607*15dc779aSAndroid Build Coastguard Worker     p_sfb_thr = pstr_psy_chan_out->ptr_sfb_thr;
608*15dc779aSAndroid Build Coastguard Worker     p_sfb_min_snr = pstr_psy_chan_out->sfb_min_snr;
609*15dc779aSAndroid Build Coastguard Worker 
610*15dc779aSAndroid Build Coastguard Worker     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
611*15dc779aSAndroid Build Coastguard Worker          sfb_group += pstr_psy_chan_out->sfb_per_group) {
612*15dc779aSAndroid Build Coastguard Worker       i = sfb_group;
613*15dc779aSAndroid Build Coastguard Worker       for (sfb = pstr_psy_chan_out->max_sfb_per_grp - 1; sfb >= 0; sfb--, i++) {
614*15dc779aSAndroid Build Coastguard Worker         delta_sfb_pe = sfb_pe_factors[idx][i] * norm_factor[0] * delta_pe;
615*15dc779aSAndroid Build Coastguard Worker         if (pe_channel_data->num_sfb_active_lines[i] > (FLOAT32)0.5f) {
616*15dc779aSAndroid Build Coastguard Worker           sfb_en = p_sfb_energy[i];
617*15dc779aSAndroid Build Coastguard Worker           sfb_thr = p_sfb_thr[i];
618*15dc779aSAndroid Build Coastguard Worker           thr_factor = MIN(-delta_sfb_pe / pe_channel_data->num_sfb_active_lines[i], 20.f);
619*15dc779aSAndroid Build Coastguard Worker           thr_factor = (FLOAT32)pow(2.0f, thr_factor);
620*15dc779aSAndroid Build Coastguard Worker           sfb_thr_reduced = sfb_thr * thr_factor;
621*15dc779aSAndroid Build Coastguard Worker 
622*15dc779aSAndroid Build Coastguard Worker           if ((sfb_thr_reduced > p_sfb_min_snr[i] * sfb_en) && (ah_flag[idx][i] == AH_INACTIVE)) {
623*15dc779aSAndroid Build Coastguard Worker             sfb_thr_reduced = MAX(p_sfb_min_snr[i] * sfb_en, sfb_thr);
624*15dc779aSAndroid Build Coastguard Worker             ah_flag[idx][i] = AH_ACTIVE;
625*15dc779aSAndroid Build Coastguard Worker           }
626*15dc779aSAndroid Build Coastguard Worker           p_sfb_thr[i] = sfb_thr_reduced;
627*15dc779aSAndroid Build Coastguard Worker         }
628*15dc779aSAndroid Build Coastguard Worker       }
629*15dc779aSAndroid Build Coastguard Worker     }
630*15dc779aSAndroid Build Coastguard Worker     idx++;
631*15dc779aSAndroid Build Coastguard Worker   }
632*15dc779aSAndroid Build Coastguard Worker 
633*15dc779aSAndroid Build Coastguard Worker   return IA_NO_ERROR;
634*15dc779aSAndroid Build Coastguard Worker }
635*15dc779aSAndroid Build Coastguard Worker 
iusace_reduce_min_snr(ia_psy_mod_out_data_struct * pstr_psy_out,ia_qc_pe_data_struct * pstr_qs_pe_data,WORD32 ** ah_flag,const FLOAT32 desired_pe,WORD32 num_channels,WORD32 chn)636*15dc779aSAndroid Build Coastguard Worker static VOID iusace_reduce_min_snr(ia_psy_mod_out_data_struct *pstr_psy_out,
637*15dc779aSAndroid Build Coastguard Worker                                   ia_qc_pe_data_struct *pstr_qs_pe_data, WORD32 **ah_flag,
638*15dc779aSAndroid Build Coastguard Worker                                   const FLOAT32 desired_pe, WORD32 num_channels, WORD32 chn) {
639*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb, sfb_sub_win, ch, idx;
640*15dc779aSAndroid Build Coastguard Worker   FLOAT32 delta_pe;
641*15dc779aSAndroid Build Coastguard Worker 
642*15dc779aSAndroid Build Coastguard Worker   sfb_sub_win = pstr_psy_out[chn].max_sfb_per_grp;
643*15dc779aSAndroid Build Coastguard Worker 
644*15dc779aSAndroid Build Coastguard Worker   while (pstr_qs_pe_data->pe > desired_pe && sfb_sub_win > 0) {
645*15dc779aSAndroid Build Coastguard Worker     sfb_sub_win--;
646*15dc779aSAndroid Build Coastguard Worker     for (sfb = sfb_sub_win; sfb < pstr_psy_out[chn].sfb_count;
647*15dc779aSAndroid Build Coastguard Worker          sfb += pstr_psy_out[chn].sfb_per_group) {
648*15dc779aSAndroid Build Coastguard Worker       idx = 0;
649*15dc779aSAndroid Build Coastguard Worker       for (ch = chn; ch < chn + num_channels; ch++) {
650*15dc779aSAndroid Build Coastguard Worker         if (ah_flag[idx][sfb] != NO_AH && pstr_psy_out[ch].sfb_min_snr[sfb] < MIN_SNR_LIMIT) {
651*15dc779aSAndroid Build Coastguard Worker           pstr_psy_out[ch].sfb_min_snr[sfb] = MIN_SNR_LIMIT;
652*15dc779aSAndroid Build Coastguard Worker           pstr_psy_out[ch].ptr_sfb_thr[sfb] =
653*15dc779aSAndroid Build Coastguard Worker               pstr_psy_out[ch].ptr_sfb_energy[sfb] * pstr_psy_out[ch].sfb_min_snr[sfb];
654*15dc779aSAndroid Build Coastguard Worker           delta_pe = pstr_qs_pe_data->pe_ch_data[idx].sfb_lines[sfb] * 1.5f -
655*15dc779aSAndroid Build Coastguard Worker                      pstr_qs_pe_data->pe_ch_data[idx].sfb_pe[sfb];
656*15dc779aSAndroid Build Coastguard Worker           pstr_qs_pe_data->pe += delta_pe;
657*15dc779aSAndroid Build Coastguard Worker           pstr_qs_pe_data->pe_ch_data[idx].pe += delta_pe;
658*15dc779aSAndroid Build Coastguard Worker         }
659*15dc779aSAndroid Build Coastguard Worker         idx++;
660*15dc779aSAndroid Build Coastguard Worker       }
661*15dc779aSAndroid Build Coastguard Worker       if (pstr_qs_pe_data->pe <= desired_pe) break;
662*15dc779aSAndroid Build Coastguard Worker     }
663*15dc779aSAndroid Build Coastguard Worker   }
664*15dc779aSAndroid Build Coastguard Worker 
665*15dc779aSAndroid Build Coastguard Worker   return;
666*15dc779aSAndroid Build Coastguard Worker }
667*15dc779aSAndroid Build Coastguard Worker 
iusace_allow_more_holes(ia_psy_mod_out_data_struct * pstr_psy_out,ia_qc_pe_data_struct * pstr_qs_pe_data,WORD32 ** ah_flag,const ia_ah_param_struct * str_ah_param,const FLOAT32 desired_pe,WORD32 num_channels,WORD32 chn,UWORD8 * ptr_scratch)668*15dc779aSAndroid Build Coastguard Worker static VOID iusace_allow_more_holes(ia_psy_mod_out_data_struct *pstr_psy_out,
669*15dc779aSAndroid Build Coastguard Worker                                     ia_qc_pe_data_struct *pstr_qs_pe_data, WORD32 **ah_flag,
670*15dc779aSAndroid Build Coastguard Worker                                     const ia_ah_param_struct *str_ah_param,
671*15dc779aSAndroid Build Coastguard Worker                                     const FLOAT32 desired_pe, WORD32 num_channels, WORD32 chn,
672*15dc779aSAndroid Build Coastguard Worker                                     UWORD8 *ptr_scratch) {
673*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb, ch, idx;
674*15dc779aSAndroid Build Coastguard Worker   FLOAT32 act_pe = pstr_qs_pe_data->pe;
675*15dc779aSAndroid Build Coastguard Worker 
676*15dc779aSAndroid Build Coastguard Worker   if (num_channels == 2 &&
677*15dc779aSAndroid Build Coastguard Worker       pstr_psy_out[chn].window_sequence == pstr_psy_out[chn + 1].window_sequence) {
678*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *psy_out_left = &pstr_psy_out[chn];
679*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *psy_out_right = &pstr_psy_out[chn + 1];
680*15dc779aSAndroid Build Coastguard Worker 
681*15dc779aSAndroid Build Coastguard Worker     for (sfb = 0; sfb < psy_out_left->sfb_count; sfb++) {
682*15dc779aSAndroid Build Coastguard Worker       if (pstr_psy_out[chn].ms_used[sfb]) {
683*15dc779aSAndroid Build Coastguard Worker         if (ah_flag[1][sfb] != NO_AH &&
684*15dc779aSAndroid Build Coastguard Worker             0.4f * psy_out_left->sfb_min_snr[sfb] * psy_out_left->ptr_sfb_energy[sfb] >
685*15dc779aSAndroid Build Coastguard Worker                 psy_out_right->ptr_sfb_energy[sfb]) {
686*15dc779aSAndroid Build Coastguard Worker           ah_flag[1][sfb] = NO_AH;
687*15dc779aSAndroid Build Coastguard Worker 
688*15dc779aSAndroid Build Coastguard Worker           psy_out_right->ptr_sfb_thr[sfb] = 2.0f * psy_out_right->ptr_sfb_energy[sfb];
689*15dc779aSAndroid Build Coastguard Worker 
690*15dc779aSAndroid Build Coastguard Worker           act_pe -= pstr_qs_pe_data->pe_ch_data[1].sfb_pe[sfb];
691*15dc779aSAndroid Build Coastguard Worker         } else {
692*15dc779aSAndroid Build Coastguard Worker           if (ah_flag[0][sfb] != NO_AH &&
693*15dc779aSAndroid Build Coastguard Worker               0.4f * psy_out_right->sfb_min_snr[sfb] * psy_out_right->ptr_sfb_energy[sfb] >
694*15dc779aSAndroid Build Coastguard Worker                   psy_out_left->ptr_sfb_energy[sfb]) {
695*15dc779aSAndroid Build Coastguard Worker             ah_flag[0][sfb] = NO_AH;
696*15dc779aSAndroid Build Coastguard Worker 
697*15dc779aSAndroid Build Coastguard Worker             psy_out_left->ptr_sfb_thr[sfb] = 2.0f * psy_out_left->ptr_sfb_energy[sfb];
698*15dc779aSAndroid Build Coastguard Worker 
699*15dc779aSAndroid Build Coastguard Worker             act_pe -= pstr_qs_pe_data->pe_ch_data[0].sfb_pe[sfb];
700*15dc779aSAndroid Build Coastguard Worker           }
701*15dc779aSAndroid Build Coastguard Worker         }
702*15dc779aSAndroid Build Coastguard Worker         if (act_pe < desired_pe) break;
703*15dc779aSAndroid Build Coastguard Worker       }
704*15dc779aSAndroid Build Coastguard Worker     }
705*15dc779aSAndroid Build Coastguard Worker   }
706*15dc779aSAndroid Build Coastguard Worker   if (act_pe > desired_pe) {
707*15dc779aSAndroid Build Coastguard Worker     WORD32 *start_sfb = (WORD32 *)ptr_scratch;
708*15dc779aSAndroid Build Coastguard Worker     memset(start_sfb, 0, MAX_TIME_CHANNELS * sizeof(start_sfb[0]));
709*15dc779aSAndroid Build Coastguard Worker     FLOAT32 average_energy, min_energy;
710*15dc779aSAndroid Build Coastguard Worker     WORD32 ah_cnt;
711*15dc779aSAndroid Build Coastguard Worker     WORD32 en_idx;
712*15dc779aSAndroid Build Coastguard Worker     FLOAT32 energy[4];
713*15dc779aSAndroid Build Coastguard Worker     WORD32 min_sfb, max_sfb;
714*15dc779aSAndroid Build Coastguard Worker     WORD32 done;
715*15dc779aSAndroid Build Coastguard Worker     for (ch = chn; ch < chn + num_channels; ch++) {
716*15dc779aSAndroid Build Coastguard Worker       if (pstr_psy_out[ch].window_sequence != EIGHT_SHORT_SEQUENCE)
717*15dc779aSAndroid Build Coastguard Worker         start_sfb[ch] = str_ah_param->start_sfb_long;
718*15dc779aSAndroid Build Coastguard Worker       else
719*15dc779aSAndroid Build Coastguard Worker         start_sfb[ch] = str_ah_param->start_sfb_short;
720*15dc779aSAndroid Build Coastguard Worker     }
721*15dc779aSAndroid Build Coastguard Worker 
722*15dc779aSAndroid Build Coastguard Worker     average_energy = 0.0f;
723*15dc779aSAndroid Build Coastguard Worker     min_energy = MAX_FLT_VAL;
724*15dc779aSAndroid Build Coastguard Worker     ah_cnt = 0;
725*15dc779aSAndroid Build Coastguard Worker     idx = 0;
726*15dc779aSAndroid Build Coastguard Worker     for (ch = chn; ch < chn + num_channels; ch++) {
727*15dc779aSAndroid Build Coastguard Worker       ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
728*15dc779aSAndroid Build Coastguard Worker       for (sfb = start_sfb[ch]; sfb < pstr_psy_chan_out->sfb_count; sfb++) {
729*15dc779aSAndroid Build Coastguard Worker         if ((ah_flag[idx][sfb] != NO_AH) &&
730*15dc779aSAndroid Build Coastguard Worker             (pstr_psy_chan_out->ptr_sfb_energy[sfb] > pstr_psy_chan_out->ptr_sfb_thr[sfb])) {
731*15dc779aSAndroid Build Coastguard Worker           min_energy = MIN(min_energy, pstr_psy_chan_out->ptr_sfb_energy[sfb]);
732*15dc779aSAndroid Build Coastguard Worker           average_energy += pstr_psy_chan_out->ptr_sfb_energy[sfb];
733*15dc779aSAndroid Build Coastguard Worker           ah_cnt++;
734*15dc779aSAndroid Build Coastguard Worker         }
735*15dc779aSAndroid Build Coastguard Worker       }
736*15dc779aSAndroid Build Coastguard Worker       idx++;
737*15dc779aSAndroid Build Coastguard Worker     }
738*15dc779aSAndroid Build Coastguard Worker 
739*15dc779aSAndroid Build Coastguard Worker     average_energy = MIN(MAX_FLT_VAL, average_energy / (ah_cnt + MIN_FLT_VAL));
740*15dc779aSAndroid Build Coastguard Worker 
741*15dc779aSAndroid Build Coastguard Worker     for (en_idx = 0; en_idx < 4; en_idx++) {
742*15dc779aSAndroid Build Coastguard Worker       energy[en_idx] = min_energy * (FLOAT32)pow(average_energy / (min_energy + MIN_FLT_VAL),
743*15dc779aSAndroid Build Coastguard Worker                                                  (2 * en_idx + 1) / 7.0f);
744*15dc779aSAndroid Build Coastguard Worker     }
745*15dc779aSAndroid Build Coastguard Worker     max_sfb = pstr_psy_out[chn].sfb_count - 1;
746*15dc779aSAndroid Build Coastguard Worker     min_sfb = start_sfb[chn];
747*15dc779aSAndroid Build Coastguard Worker 
748*15dc779aSAndroid Build Coastguard Worker     if (num_channels == 2) {
749*15dc779aSAndroid Build Coastguard Worker       max_sfb = MAX(max_sfb, pstr_psy_out[chn + 1].sfb_count - 1);
750*15dc779aSAndroid Build Coastguard Worker 
751*15dc779aSAndroid Build Coastguard Worker       min_sfb = MIN(min_sfb, start_sfb[chn + 1]);
752*15dc779aSAndroid Build Coastguard Worker     }
753*15dc779aSAndroid Build Coastguard Worker 
754*15dc779aSAndroid Build Coastguard Worker     sfb = max_sfb;
755*15dc779aSAndroid Build Coastguard Worker     en_idx = 0;
756*15dc779aSAndroid Build Coastguard Worker     done = 0;
757*15dc779aSAndroid Build Coastguard Worker     while (!done) {
758*15dc779aSAndroid Build Coastguard Worker       idx = 0;
759*15dc779aSAndroid Build Coastguard Worker       for (ch = chn; ch < chn + num_channels; ch++) {
760*15dc779aSAndroid Build Coastguard Worker         ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
761*15dc779aSAndroid Build Coastguard Worker         if (sfb >= start_sfb[ch] && sfb < pstr_psy_chan_out->sfb_count) {
762*15dc779aSAndroid Build Coastguard Worker           if (ah_flag[idx][sfb] != NO_AH &&
763*15dc779aSAndroid Build Coastguard Worker               pstr_psy_chan_out->ptr_sfb_energy[sfb] < energy[en_idx]) {
764*15dc779aSAndroid Build Coastguard Worker             ah_flag[idx][sfb] = NO_AH;
765*15dc779aSAndroid Build Coastguard Worker             pstr_psy_chan_out->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_chan_out->ptr_sfb_energy[sfb];
766*15dc779aSAndroid Build Coastguard Worker             act_pe -= pstr_qs_pe_data->pe_ch_data[idx].sfb_pe[sfb];
767*15dc779aSAndroid Build Coastguard Worker           }
768*15dc779aSAndroid Build Coastguard Worker 
769*15dc779aSAndroid Build Coastguard Worker           if (act_pe < desired_pe) {
770*15dc779aSAndroid Build Coastguard Worker             done = 1;
771*15dc779aSAndroid Build Coastguard Worker             break;
772*15dc779aSAndroid Build Coastguard Worker           }
773*15dc779aSAndroid Build Coastguard Worker         }
774*15dc779aSAndroid Build Coastguard Worker         idx++;
775*15dc779aSAndroid Build Coastguard Worker       }
776*15dc779aSAndroid Build Coastguard Worker       sfb--;
777*15dc779aSAndroid Build Coastguard Worker       if (sfb < min_sfb) {
778*15dc779aSAndroid Build Coastguard Worker         sfb = max_sfb;
779*15dc779aSAndroid Build Coastguard Worker         en_idx++;
780*15dc779aSAndroid Build Coastguard Worker         if (en_idx >= 4) {
781*15dc779aSAndroid Build Coastguard Worker           done = 1;
782*15dc779aSAndroid Build Coastguard Worker         }
783*15dc779aSAndroid Build Coastguard Worker       }
784*15dc779aSAndroid Build Coastguard Worker     }
785*15dc779aSAndroid Build Coastguard Worker   }
786*15dc779aSAndroid Build Coastguard Worker 
787*15dc779aSAndroid Build Coastguard Worker   return;
788*15dc779aSAndroid Build Coastguard Worker }
789*15dc779aSAndroid Build Coastguard Worker 
iusace_adapt_thr_to_pe(ia_psy_mod_out_data_struct * pstr_psy_out,ia_qc_pe_data_struct * pstr_qs_pe_data,const FLOAT32 desired_pe,ia_ah_param_struct * str_ah_param,ia_min_snr_adapt_param_struct * msa_param,WORD32 num_channels,WORD32 chn,UWORD8 * ptr_scratch)790*15dc779aSAndroid Build Coastguard Worker static IA_ERRORCODE iusace_adapt_thr_to_pe(ia_psy_mod_out_data_struct *pstr_psy_out,
791*15dc779aSAndroid Build Coastguard Worker                                            ia_qc_pe_data_struct *pstr_qs_pe_data,
792*15dc779aSAndroid Build Coastguard Worker                                            const FLOAT32 desired_pe,
793*15dc779aSAndroid Build Coastguard Worker                                            ia_ah_param_struct *str_ah_param,
794*15dc779aSAndroid Build Coastguard Worker                                            ia_min_snr_adapt_param_struct *msa_param,
795*15dc779aSAndroid Build Coastguard Worker                                            WORD32 num_channels, WORD32 chn, UWORD8 *ptr_scratch) {
796*15dc779aSAndroid Build Coastguard Worker   IA_ERRORCODE err_code;
797*15dc779aSAndroid Build Coastguard Worker   FLOAT32 no_red_pe, red_pe, red_pe_no_ah;
798*15dc779aSAndroid Build Coastguard Worker   FLOAT32 const_part, const_part_no_ah;
799*15dc779aSAndroid Build Coastguard Worker   FLOAT32 nactive_lines, nactive_lines_no_ah;
800*15dc779aSAndroid Build Coastguard Worker   FLOAT32 desired_pe_no_ah;
801*15dc779aSAndroid Build Coastguard Worker   FLOAT32 redval = 0.0f;
802*15dc779aSAndroid Build Coastguard Worker   WORD32 *ah_flag[2];
803*15dc779aSAndroid Build Coastguard Worker   WORD32 iteration;
804*15dc779aSAndroid Build Coastguard Worker   for (WORD32 i = 0; i < 2; i++) {
805*15dc779aSAndroid Build Coastguard Worker     ah_flag[i] = (WORD32 *)ptr_scratch;
806*15dc779aSAndroid Build Coastguard Worker     ptr_scratch += (MAX_NUM_GROUPED_SFB) * sizeof(ah_flag[0][0]);
807*15dc779aSAndroid Build Coastguard Worker   }
808*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *thr_exp[2];
809*15dc779aSAndroid Build Coastguard Worker   for (WORD32 i = 0; i < 2; i++) {
810*15dc779aSAndroid Build Coastguard Worker     thr_exp[i] = (FLOAT32 *)ptr_scratch;
811*15dc779aSAndroid Build Coastguard Worker     ptr_scratch += (MAX_NUM_GROUPED_SFB) * sizeof(thr_exp[0][0]);
812*15dc779aSAndroid Build Coastguard Worker   }
813*15dc779aSAndroid Build Coastguard Worker 
814*15dc779aSAndroid Build Coastguard Worker   iusace_calc_thr_exp(thr_exp, pstr_psy_out, num_channels, chn);
815*15dc779aSAndroid Build Coastguard Worker   iusace_adapt_min_snr(pstr_psy_out, msa_param, num_channels, chn);
816*15dc779aSAndroid Build Coastguard Worker   iusace_init_avoid_hole_flag(ah_flag, pstr_psy_out, str_ah_param, num_channels, chn);
817*15dc779aSAndroid Build Coastguard Worker 
818*15dc779aSAndroid Build Coastguard Worker   no_red_pe = pstr_qs_pe_data->pe;
819*15dc779aSAndroid Build Coastguard Worker   const_part = pstr_qs_pe_data->const_part;
820*15dc779aSAndroid Build Coastguard Worker   nactive_lines = pstr_qs_pe_data->num_active_lines;
821*15dc779aSAndroid Build Coastguard Worker   if (nactive_lines > FLT_EPSILON) {
822*15dc779aSAndroid Build Coastguard Worker     FLOAT32 avg_thr_exp = (FLOAT32)pow(2.0f, (const_part - no_red_pe) /
823*15dc779aSAndroid Build Coastguard Worker                   (INV_RED_EXP_VAL * nactive_lines));
824*15dc779aSAndroid Build Coastguard Worker     redval = (FLOAT32)pow(2.0f, (const_part - desired_pe) / (INV_RED_EXP_VAL * nactive_lines)) -
825*15dc779aSAndroid Build Coastguard Worker              avg_thr_exp;
826*15dc779aSAndroid Build Coastguard Worker     redval = MAX(0.0f, redval);
827*15dc779aSAndroid Build Coastguard Worker     iusace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
828*15dc779aSAndroid Build Coastguard Worker   }
829*15dc779aSAndroid Build Coastguard Worker 
830*15dc779aSAndroid Build Coastguard Worker   iusace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
831*15dc779aSAndroid Build Coastguard Worker   red_pe = pstr_qs_pe_data->pe;
832*15dc779aSAndroid Build Coastguard Worker 
833*15dc779aSAndroid Build Coastguard Worker   iteration = 0;
834*15dc779aSAndroid Build Coastguard Worker   do {
835*15dc779aSAndroid Build Coastguard Worker     iusace_calc_pe_no_active_holes(&red_pe_no_ah, &const_part_no_ah, &nactive_lines_no_ah,
836*15dc779aSAndroid Build Coastguard Worker                                    pstr_qs_pe_data, ah_flag, pstr_psy_out, num_channels, chn);
837*15dc779aSAndroid Build Coastguard Worker 
838*15dc779aSAndroid Build Coastguard Worker     desired_pe_no_ah = MAX(desired_pe - (red_pe - red_pe_no_ah), 0);
839*15dc779aSAndroid Build Coastguard Worker     if (nactive_lines_no_ah > FLT_EPSILON) {
840*15dc779aSAndroid Build Coastguard Worker       FLOAT32 avg_thr_exp = (FLOAT32)pow(
841*15dc779aSAndroid Build Coastguard Worker           2.0f, (const_part_no_ah - red_pe_no_ah) / (INV_RED_EXP_VAL * nactive_lines_no_ah));
842*15dc779aSAndroid Build Coastguard Worker       redval += (FLOAT32)pow(2.0f, (const_part_no_ah - desired_pe_no_ah) /
843*15dc779aSAndroid Build Coastguard Worker                                        (INV_RED_EXP_VAL * nactive_lines_no_ah)) -
844*15dc779aSAndroid Build Coastguard Worker                 avg_thr_exp;
845*15dc779aSAndroid Build Coastguard Worker       redval = MAX(0.0f, redval);
846*15dc779aSAndroid Build Coastguard Worker       iusace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
847*15dc779aSAndroid Build Coastguard Worker     }
848*15dc779aSAndroid Build Coastguard Worker 
849*15dc779aSAndroid Build Coastguard Worker     iusace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
850*15dc779aSAndroid Build Coastguard Worker     red_pe = pstr_qs_pe_data->pe;
851*15dc779aSAndroid Build Coastguard Worker     iteration++;
852*15dc779aSAndroid Build Coastguard Worker   } while ((fabs(red_pe - desired_pe) > (0.05f) * desired_pe) && (iteration < 2));
853*15dc779aSAndroid Build Coastguard Worker   if (red_pe < 1.15f * desired_pe) {
854*15dc779aSAndroid Build Coastguard Worker     err_code = iusace_correct_thr(pstr_psy_out, ah_flag, pstr_qs_pe_data, thr_exp, redval,
855*15dc779aSAndroid Build Coastguard Worker                                   desired_pe - red_pe, num_channels, chn, ptr_scratch);
856*15dc779aSAndroid Build Coastguard Worker     if (err_code != IA_NO_ERROR) {
857*15dc779aSAndroid Build Coastguard Worker       return err_code;
858*15dc779aSAndroid Build Coastguard Worker     }
859*15dc779aSAndroid Build Coastguard Worker   } else {
860*15dc779aSAndroid Build Coastguard Worker     iusace_reduce_min_snr(pstr_psy_out, pstr_qs_pe_data, ah_flag, 1.05f * desired_pe,
861*15dc779aSAndroid Build Coastguard Worker                           num_channels, chn);
862*15dc779aSAndroid Build Coastguard Worker     iusace_allow_more_holes(pstr_psy_out, pstr_qs_pe_data, ah_flag, str_ah_param,
863*15dc779aSAndroid Build Coastguard Worker                             1.05f * desired_pe, num_channels, chn, ptr_scratch);
864*15dc779aSAndroid Build Coastguard Worker   }
865*15dc779aSAndroid Build Coastguard Worker 
866*15dc779aSAndroid Build Coastguard Worker   return IA_NO_ERROR;
867*15dc779aSAndroid Build Coastguard Worker }
868*15dc779aSAndroid Build Coastguard Worker 
iusace_adj_thr(ia_adj_thr_elem_struct * pstr_adj_thr_elem,ia_psy_mod_out_data_struct * pstr_psy_out,FLOAT32 * ch_bit_dist,ia_qc_out_data_struct * pstr_qc_out,const WORD32 avg_bits,const WORD32 bitres_bits,const WORD32 max_bitres_bits,const WORD32 side_info_bits,FLOAT32 * max_bit_fac,WORD32 num_channels,WORD32 chn,iusace_scratch_mem * pstr_scratch)869*15dc779aSAndroid Build Coastguard Worker IA_ERRORCODE iusace_adj_thr(ia_adj_thr_elem_struct *pstr_adj_thr_elem,
870*15dc779aSAndroid Build Coastguard Worker                             ia_psy_mod_out_data_struct *pstr_psy_out, FLOAT32 *ch_bit_dist,
871*15dc779aSAndroid Build Coastguard Worker                             ia_qc_out_data_struct *pstr_qc_out, const WORD32 avg_bits,
872*15dc779aSAndroid Build Coastguard Worker                             const WORD32 bitres_bits, const WORD32 max_bitres_bits,
873*15dc779aSAndroid Build Coastguard Worker                             const WORD32 side_info_bits, FLOAT32 *max_bit_fac,
874*15dc779aSAndroid Build Coastguard Worker                             WORD32 num_channels, WORD32 chn, iusace_scratch_mem *pstr_scratch) {
875*15dc779aSAndroid Build Coastguard Worker   IA_ERRORCODE err_code;
876*15dc779aSAndroid Build Coastguard Worker   FLOAT32 no_red_pe, granted_pe, granted_pe_corr;
877*15dc779aSAndroid Build Coastguard Worker   WORD32 curr_win_sequence;
878*15dc779aSAndroid Build Coastguard Worker   ia_qc_pe_data_struct *pstr_qc_pe_data = (ia_qc_pe_data_struct *)pstr_scratch->ptr_fd_scratch;
879*15dc779aSAndroid Build Coastguard Worker   pUWORD8 ptr_scratch = pstr_scratch->ptr_fd_scratch + sizeof(ia_qc_pe_data_struct);
880*15dc779aSAndroid Build Coastguard Worker   FLOAT32 bit_factor;
881*15dc779aSAndroid Build Coastguard Worker   WORD32 ch;
882*15dc779aSAndroid Build Coastguard Worker 
883*15dc779aSAndroid Build Coastguard Worker   pstr_qc_pe_data->pe_ch_data[0].sfb_lines = pstr_scratch->ptr_sfb_num_relevant_lines[0];
884*15dc779aSAndroid Build Coastguard Worker   pstr_qc_pe_data->pe_ch_data[0].sfb_ld_energy = pstr_scratch->ptr_sfb_ld_energy[0];
885*15dc779aSAndroid Build Coastguard Worker   if (num_channels == 2) {
886*15dc779aSAndroid Build Coastguard Worker     pstr_qc_pe_data->pe_ch_data[1].sfb_lines = pstr_scratch->ptr_sfb_num_relevant_lines[1];
887*15dc779aSAndroid Build Coastguard Worker     pstr_qc_pe_data->pe_ch_data[1].sfb_ld_energy = pstr_scratch->ptr_sfb_ld_energy[1];
888*15dc779aSAndroid Build Coastguard Worker   }
889*15dc779aSAndroid Build Coastguard Worker   pstr_qc_pe_data->offset = pstr_adj_thr_elem->pe_offset;
890*15dc779aSAndroid Build Coastguard Worker 
891*15dc779aSAndroid Build Coastguard Worker   iusace_calc_sfb_pe_data(pstr_qc_pe_data, pstr_psy_out, num_channels, chn);
892*15dc779aSAndroid Build Coastguard Worker   no_red_pe = pstr_qc_pe_data->pe;
893*15dc779aSAndroid Build Coastguard Worker 
894*15dc779aSAndroid Build Coastguard Worker   curr_win_sequence = ONLY_LONG_SEQUENCE;
895*15dc779aSAndroid Build Coastguard Worker   if (num_channels == 2) {
896*15dc779aSAndroid Build Coastguard Worker     if ((pstr_psy_out[chn].window_sequence == EIGHT_SHORT_SEQUENCE) ||
897*15dc779aSAndroid Build Coastguard Worker         (pstr_psy_out[chn + 1].window_sequence == EIGHT_SHORT_SEQUENCE)) {
898*15dc779aSAndroid Build Coastguard Worker       curr_win_sequence = EIGHT_SHORT_SEQUENCE;
899*15dc779aSAndroid Build Coastguard Worker     }
900*15dc779aSAndroid Build Coastguard Worker   } else {
901*15dc779aSAndroid Build Coastguard Worker     curr_win_sequence = pstr_psy_out[chn].window_sequence;
902*15dc779aSAndroid Build Coastguard Worker   }
903*15dc779aSAndroid Build Coastguard Worker 
904*15dc779aSAndroid Build Coastguard Worker   bit_factor =
905*15dc779aSAndroid Build Coastguard Worker       iusace_bitres_calc_bitfac(bitres_bits, max_bitres_bits, no_red_pe + 5.0f * side_info_bits,
906*15dc779aSAndroid Build Coastguard Worker                                 curr_win_sequence, avg_bits, *max_bit_fac, pstr_adj_thr_elem);
907*15dc779aSAndroid Build Coastguard Worker   granted_pe = bit_factor * iusace_bits_to_pe((FLOAT32)avg_bits);
908*15dc779aSAndroid Build Coastguard Worker   iusace_calc_pe_correction(&(pstr_adj_thr_elem->pe_correction_fac), MIN(granted_pe, no_red_pe),
909*15dc779aSAndroid Build Coastguard Worker                             pstr_adj_thr_elem->pe_last, pstr_adj_thr_elem->dyn_bits_last);
910*15dc779aSAndroid Build Coastguard Worker   granted_pe_corr = granted_pe * pstr_adj_thr_elem->pe_correction_fac;
911*15dc779aSAndroid Build Coastguard Worker 
912*15dc779aSAndroid Build Coastguard Worker   if (granted_pe_corr < no_red_pe) {
913*15dc779aSAndroid Build Coastguard Worker     err_code = iusace_adapt_thr_to_pe(
914*15dc779aSAndroid Build Coastguard Worker         pstr_psy_out, pstr_qc_pe_data, granted_pe_corr, &pstr_adj_thr_elem->str_ah_param,
915*15dc779aSAndroid Build Coastguard Worker         &pstr_adj_thr_elem->str_min_snr_adapt_params, num_channels, chn, ptr_scratch);
916*15dc779aSAndroid Build Coastguard Worker     if (err_code != IA_NO_ERROR) {
917*15dc779aSAndroid Build Coastguard Worker       return err_code;
918*15dc779aSAndroid Build Coastguard Worker     }
919*15dc779aSAndroid Build Coastguard Worker   }
920*15dc779aSAndroid Build Coastguard Worker 
921*15dc779aSAndroid Build Coastguard Worker   for (ch = 0; ch < num_channels; ch++) {
922*15dc779aSAndroid Build Coastguard Worker     FLOAT32 tmp_var, temp1;
923*15dc779aSAndroid Build Coastguard Worker     if (pstr_qc_pe_data->pe) {
924*15dc779aSAndroid Build Coastguard Worker       tmp_var = 1.0f - num_channels * 0.2f;
925*15dc779aSAndroid Build Coastguard Worker       temp1 = pstr_qc_pe_data->pe_ch_data[ch].pe / pstr_qc_pe_data->pe;
926*15dc779aSAndroid Build Coastguard Worker       temp1 = temp1 * tmp_var;
927*15dc779aSAndroid Build Coastguard Worker       ch_bit_dist[ch] = temp1 + 0.2f;
928*15dc779aSAndroid Build Coastguard Worker       if (ch_bit_dist[ch] < 0.2f) ch_bit_dist[ch] = 0.2f;
929*15dc779aSAndroid Build Coastguard Worker     } else {
930*15dc779aSAndroid Build Coastguard Worker       ch_bit_dist[ch] = 0.2f;
931*15dc779aSAndroid Build Coastguard Worker     }
932*15dc779aSAndroid Build Coastguard Worker   }
933*15dc779aSAndroid Build Coastguard Worker 
934*15dc779aSAndroid Build Coastguard Worker   pstr_qc_out->pe = no_red_pe;
935*15dc779aSAndroid Build Coastguard Worker   pstr_adj_thr_elem->pe_last = granted_pe;
936*15dc779aSAndroid Build Coastguard Worker 
937*15dc779aSAndroid Build Coastguard Worker   return IA_NO_ERROR;
938*15dc779aSAndroid Build Coastguard Worker }
939*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_form_fac_per_chan(ia_psy_mod_out_data_struct * pstr_psy_out_chan,iusace_scratch_mem * pstr_scratch,WORD32 i_ch)940*15dc779aSAndroid Build Coastguard Worker VOID iusace_calc_form_fac_per_chan(ia_psy_mod_out_data_struct *pstr_psy_out_chan,
941*15dc779aSAndroid Build Coastguard Worker                                    iusace_scratch_mem *pstr_scratch, WORD32 i_ch) {
942*15dc779aSAndroid Build Coastguard Worker   WORD32 i, j, sfb_offs;
943*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb, sfb_width;
944*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_sfb_form_factor = pstr_scratch->ptr_sfb_form_fac[i_ch];
945*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_sfb_num_relevant_lines = pstr_scratch->ptr_sfb_num_relevant_lines[i_ch];
946*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_sfb_ld_energy = pstr_scratch->ptr_sfb_ld_energy[i_ch];
947*15dc779aSAndroid Build Coastguard Worker   FLOAT64 spec_coef = 0;
948*15dc779aSAndroid Build Coastguard Worker 
949*15dc779aSAndroid Build Coastguard Worker   memset(ptr_sfb_num_relevant_lines, 0, sizeof(FLOAT32) * pstr_psy_out_chan->sfb_count);
950*15dc779aSAndroid Build Coastguard Worker 
951*15dc779aSAndroid Build Coastguard Worker   for (sfb_offs = 0; sfb_offs < pstr_psy_out_chan->sfb_count;
952*15dc779aSAndroid Build Coastguard Worker        sfb_offs += pstr_psy_out_chan->sfb_per_group) {
953*15dc779aSAndroid Build Coastguard Worker     i = sfb_offs;
954*15dc779aSAndroid Build Coastguard Worker     for (sfb = 0; sfb < pstr_psy_out_chan->max_sfb_per_grp; sfb++, i++) {
955*15dc779aSAndroid Build Coastguard Worker       ptr_sfb_form_factor[i] = MIN_FLT_VAL;
956*15dc779aSAndroid Build Coastguard Worker       if (pstr_psy_out_chan->ptr_sfb_energy[i] > pstr_psy_out_chan->ptr_sfb_thr[i]) {
957*15dc779aSAndroid Build Coastguard Worker         FLOAT32 avg_form_factor;
958*15dc779aSAndroid Build Coastguard Worker 
959*15dc779aSAndroid Build Coastguard Worker         for (j = pstr_psy_out_chan->sfb_offsets[i]; j < pstr_psy_out_chan->sfb_offsets[i + 1];
960*15dc779aSAndroid Build Coastguard Worker              j++) {
961*15dc779aSAndroid Build Coastguard Worker           spec_coef = fabs(pstr_psy_out_chan->ptr_spec_coeffs[j]);
962*15dc779aSAndroid Build Coastguard Worker           if (spec_coef < EPS && spec_coef != 0) spec_coef = EPS;
963*15dc779aSAndroid Build Coastguard Worker           ptr_sfb_form_factor[i] += (FLOAT32)sqrt(spec_coef);
964*15dc779aSAndroid Build Coastguard Worker         }
965*15dc779aSAndroid Build Coastguard Worker 
966*15dc779aSAndroid Build Coastguard Worker         sfb_width = pstr_psy_out_chan->sfb_offsets[i + 1] - pstr_psy_out_chan->sfb_offsets[i];
967*15dc779aSAndroid Build Coastguard Worker         avg_form_factor =
968*15dc779aSAndroid Build Coastguard Worker             (FLOAT32)pow(pstr_psy_out_chan->ptr_sfb_energy[i] / (FLOAT32)sfb_width, 0.25);
969*15dc779aSAndroid Build Coastguard Worker         ptr_sfb_num_relevant_lines[i] = ptr_sfb_form_factor[i] / avg_form_factor;
970*15dc779aSAndroid Build Coastguard Worker         ptr_sfb_ld_energy[i] = (FLOAT32)(log(pstr_psy_out_chan->ptr_sfb_energy[i]) * LOG2_1);
971*15dc779aSAndroid Build Coastguard Worker       }
972*15dc779aSAndroid Build Coastguard Worker     }
973*15dc779aSAndroid Build Coastguard Worker   }
974*15dc779aSAndroid Build Coastguard Worker 
975*15dc779aSAndroid Build Coastguard Worker   return;
976*15dc779aSAndroid Build Coastguard Worker }
977*15dc779aSAndroid Build Coastguard Worker 
iusace_quantize_lines(const WORD32 gain,const WORD32 num_lines,FLOAT32 * ptr_exp_spectrum,WORD16 * ptr_quant_spectrum,FLOAT32 * ptr_mdct_spec)978*15dc779aSAndroid Build Coastguard Worker VOID iusace_quantize_lines(const WORD32 gain, const WORD32 num_lines, FLOAT32 *ptr_exp_spectrum,
979*15dc779aSAndroid Build Coastguard Worker                            WORD16 *ptr_quant_spectrum, FLOAT32 *ptr_mdct_spec) {
980*15dc779aSAndroid Build Coastguard Worker   FLOAT32 quantizer;
981*15dc779aSAndroid Build Coastguard Worker   FLOAT32 k = 0.4054f;
982*15dc779aSAndroid Build Coastguard Worker   WORD32 line;
983*15dc779aSAndroid Build Coastguard Worker 
984*15dc779aSAndroid Build Coastguard Worker   quantizer = ixheaace_fd_quant_table[gain + 128];
985*15dc779aSAndroid Build Coastguard Worker   for (line = 0; line < num_lines; line++) {
986*15dc779aSAndroid Build Coastguard Worker     FLOAT32 tmp = ptr_mdct_spec[line];
987*15dc779aSAndroid Build Coastguard Worker     if (tmp < 0.0f) {
988*15dc779aSAndroid Build Coastguard Worker       ptr_exp_spectrum[line] = (FLOAT32)sqrt(-tmp);
989*15dc779aSAndroid Build Coastguard Worker       ptr_exp_spectrum[line] *= (FLOAT32)sqrt(ptr_exp_spectrum[line]);
990*15dc779aSAndroid Build Coastguard Worker       ptr_quant_spectrum[line] = -(WORD16)(k + quantizer * ptr_exp_spectrum[line]);
991*15dc779aSAndroid Build Coastguard Worker     } else {
992*15dc779aSAndroid Build Coastguard Worker       ptr_exp_spectrum[line] = (FLOAT32)sqrt(tmp);
993*15dc779aSAndroid Build Coastguard Worker       ptr_exp_spectrum[line] *= (FLOAT32)sqrt(ptr_exp_spectrum[line]);
994*15dc779aSAndroid Build Coastguard Worker       ptr_quant_spectrum[line] = (WORD16)(k + quantizer * ptr_exp_spectrum[line]);
995*15dc779aSAndroid Build Coastguard Worker     }
996*15dc779aSAndroid Build Coastguard Worker   }
997*15dc779aSAndroid Build Coastguard Worker   return;
998*15dc779aSAndroid Build Coastguard Worker }
999*15dc779aSAndroid Build Coastguard Worker 
iusace_calculate_exp_spec(const WORD32 num_lines,FLOAT32 * ptr_exp_spectrum,FLOAT32 * ptr_mdct_spec)1000*15dc779aSAndroid Build Coastguard Worker VOID iusace_calculate_exp_spec(const WORD32 num_lines, FLOAT32 *ptr_exp_spectrum,
1001*15dc779aSAndroid Build Coastguard Worker                                FLOAT32 *ptr_mdct_spec) {
1002*15dc779aSAndroid Build Coastguard Worker   WORD32 line;
1003*15dc779aSAndroid Build Coastguard Worker 
1004*15dc779aSAndroid Build Coastguard Worker   for (line = 0; line < num_lines; line++) {
1005*15dc779aSAndroid Build Coastguard Worker     ptr_exp_spectrum[line] = (FLOAT32)sqrt(fabs(ptr_mdct_spec[line]));
1006*15dc779aSAndroid Build Coastguard Worker     ptr_exp_spectrum[line] *= (FLOAT32)sqrt(ptr_exp_spectrum[line]);
1007*15dc779aSAndroid Build Coastguard Worker   }
1008*15dc779aSAndroid Build Coastguard Worker   return;
1009*15dc779aSAndroid Build Coastguard Worker }
1010*15dc779aSAndroid Build Coastguard Worker 
iusace_scf_delta_bit_count(WORD32 delta)1011*15dc779aSAndroid Build Coastguard Worker static WORD32 iusace_scf_delta_bit_count(WORD32 delta) {
1012*15dc779aSAndroid Build Coastguard Worker   if (delta > 60) {
1013*15dc779aSAndroid Build Coastguard Worker     return (iusace_huffman_code_table[120][0]);
1014*15dc779aSAndroid Build Coastguard Worker   }
1015*15dc779aSAndroid Build Coastguard Worker   if (delta < -60) {
1016*15dc779aSAndroid Build Coastguard Worker     return (iusace_huffman_code_table[0][0]);
1017*15dc779aSAndroid Build Coastguard Worker   }
1018*15dc779aSAndroid Build Coastguard Worker   return (iusace_huffman_code_table[delta + 60][0]);
1019*15dc779aSAndroid Build Coastguard Worker }
1020*15dc779aSAndroid Build Coastguard Worker 
iusace_count_single_scf_bits(WORD32 scf,WORD32 left_scf,WORD32 right_scf)1021*15dc779aSAndroid Build Coastguard Worker static WORD32 iusace_count_single_scf_bits(WORD32 scf, WORD32 left_scf, WORD32 right_scf) {
1022*15dc779aSAndroid Build Coastguard Worker   WORD32 scf_bits;
1023*15dc779aSAndroid Build Coastguard Worker 
1024*15dc779aSAndroid Build Coastguard Worker   scf_bits =
1025*15dc779aSAndroid Build Coastguard Worker       iusace_scf_delta_bit_count(left_scf - scf) + iusace_scf_delta_bit_count(scf - right_scf);
1026*15dc779aSAndroid Build Coastguard Worker 
1027*15dc779aSAndroid Build Coastguard Worker   return scf_bits;
1028*15dc779aSAndroid Build Coastguard Worker }
1029*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_single_spec_pe(WORD32 scf,FLOAT32 sfb_const_pe_part,FLOAT32 num_lines)1030*15dc779aSAndroid Build Coastguard Worker static FLOAT32 iusace_calc_single_spec_pe(WORD32 scf, FLOAT32 sfb_const_pe_part,
1031*15dc779aSAndroid Build Coastguard Worker                                           FLOAT32 num_lines) {
1032*15dc779aSAndroid Build Coastguard Worker   FLOAT32 spec_pe;
1033*15dc779aSAndroid Build Coastguard Worker   FLOAT32 ld_ratio;
1034*15dc779aSAndroid Build Coastguard Worker 
1035*15dc779aSAndroid Build Coastguard Worker   ld_ratio = sfb_const_pe_part - (FLOAT32)0.375f * (FLOAT32)scf;
1036*15dc779aSAndroid Build Coastguard Worker 
1037*15dc779aSAndroid Build Coastguard Worker   if (ld_ratio >= PE_C1) {
1038*15dc779aSAndroid Build Coastguard Worker     spec_pe = (FLOAT32)0.7f * num_lines * ld_ratio;
1039*15dc779aSAndroid Build Coastguard Worker   } else {
1040*15dc779aSAndroid Build Coastguard Worker     spec_pe = (FLOAT32)0.7f * num_lines * (PE_C2 + PE_C3 * ld_ratio);
1041*15dc779aSAndroid Build Coastguard Worker   }
1042*15dc779aSAndroid Build Coastguard Worker 
1043*15dc779aSAndroid Build Coastguard Worker   return spec_pe;
1044*15dc779aSAndroid Build Coastguard Worker }
1045*15dc779aSAndroid Build Coastguard Worker 
iusace_count_scf_bits_diff(WORD16 * ptr_sfb_prev,WORD16 * ptr_sfb_new,WORD32 sfb_count,WORD32 start_sfb,WORD32 stop_sfb)1046*15dc779aSAndroid Build Coastguard Worker static WORD32 iusace_count_scf_bits_diff(WORD16 *ptr_sfb_prev, WORD16 *ptr_sfb_new,
1047*15dc779aSAndroid Build Coastguard Worker                                          WORD32 sfb_count, WORD32 start_sfb, WORD32 stop_sfb) {
1048*15dc779aSAndroid Build Coastguard Worker   WORD32 scf_bits_diff = 0;
1049*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb = 0, sfb_last;
1050*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb_prev, sfb_next;
1051*15dc779aSAndroid Build Coastguard Worker 
1052*15dc779aSAndroid Build Coastguard Worker   sfb_last = start_sfb;
1053*15dc779aSAndroid Build Coastguard Worker 
1054*15dc779aSAndroid Build Coastguard Worker   while ((sfb_last < stop_sfb) && (ptr_sfb_prev[sfb_last] == SHRT_MIN)) {
1055*15dc779aSAndroid Build Coastguard Worker     sfb_last++;
1056*15dc779aSAndroid Build Coastguard Worker   }
1057*15dc779aSAndroid Build Coastguard Worker 
1058*15dc779aSAndroid Build Coastguard Worker   sfb_prev = start_sfb - 1;
1059*15dc779aSAndroid Build Coastguard Worker 
1060*15dc779aSAndroid Build Coastguard Worker   while ((sfb_prev >= 0) && (ptr_sfb_prev[sfb_prev] == SHRT_MIN)) {
1061*15dc779aSAndroid Build Coastguard Worker     sfb_prev--;
1062*15dc779aSAndroid Build Coastguard Worker   }
1063*15dc779aSAndroid Build Coastguard Worker 
1064*15dc779aSAndroid Build Coastguard Worker   if (sfb_prev >= 0) {
1065*15dc779aSAndroid Build Coastguard Worker     scf_bits_diff += iusace_scf_delta_bit_count(ptr_sfb_new[sfb_prev] - ptr_sfb_new[sfb_last]) -
1066*15dc779aSAndroid Build Coastguard Worker                      iusace_scf_delta_bit_count(ptr_sfb_prev[sfb_prev] - ptr_sfb_prev[sfb_last]);
1067*15dc779aSAndroid Build Coastguard Worker   }
1068*15dc779aSAndroid Build Coastguard Worker 
1069*15dc779aSAndroid Build Coastguard Worker   for (sfb = sfb_last + 1; sfb < stop_sfb; sfb++) {
1070*15dc779aSAndroid Build Coastguard Worker     if (ptr_sfb_prev[sfb] != SHRT_MIN) {
1071*15dc779aSAndroid Build Coastguard Worker       scf_bits_diff += iusace_scf_delta_bit_count(ptr_sfb_new[sfb_last] - ptr_sfb_new[sfb]) -
1072*15dc779aSAndroid Build Coastguard Worker                        iusace_scf_delta_bit_count(ptr_sfb_prev[sfb_last] - ptr_sfb_prev[sfb]);
1073*15dc779aSAndroid Build Coastguard Worker 
1074*15dc779aSAndroid Build Coastguard Worker       sfb_last = sfb;
1075*15dc779aSAndroid Build Coastguard Worker     }
1076*15dc779aSAndroid Build Coastguard Worker   }
1077*15dc779aSAndroid Build Coastguard Worker 
1078*15dc779aSAndroid Build Coastguard Worker   sfb_next = stop_sfb;
1079*15dc779aSAndroid Build Coastguard Worker 
1080*15dc779aSAndroid Build Coastguard Worker   while ((sfb_next < sfb_count) && (ptr_sfb_prev[sfb_next] == SHRT_MIN)) {
1081*15dc779aSAndroid Build Coastguard Worker     sfb_next++;
1082*15dc779aSAndroid Build Coastguard Worker   }
1083*15dc779aSAndroid Build Coastguard Worker 
1084*15dc779aSAndroid Build Coastguard Worker   if (sfb_next < sfb_count) {
1085*15dc779aSAndroid Build Coastguard Worker     scf_bits_diff += iusace_scf_delta_bit_count(ptr_sfb_new[sfb_last] - ptr_sfb_new[sfb_next]) -
1086*15dc779aSAndroid Build Coastguard Worker                      iusace_scf_delta_bit_count(ptr_sfb_prev[sfb_last] - ptr_sfb_prev[sfb_next]);
1087*15dc779aSAndroid Build Coastguard Worker   }
1088*15dc779aSAndroid Build Coastguard Worker 
1089*15dc779aSAndroid Build Coastguard Worker   return scf_bits_diff;
1090*15dc779aSAndroid Build Coastguard Worker }
1091*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_spec_pe_diff(ia_psy_mod_out_data_struct * pstr_psy_out,WORD16 * scf_prev,WORD16 * scf_new,FLOAT32 * ptr_sfb_const_pe_part,FLOAT32 * ptr_sfb_form_fac,FLOAT32 * ptr_sfb_num_rel_lines,WORD32 start_sfb,WORD32 stop_sfb)1092*15dc779aSAndroid Build Coastguard Worker static FLOAT32 iusace_calc_spec_pe_diff(ia_psy_mod_out_data_struct *pstr_psy_out,
1093*15dc779aSAndroid Build Coastguard Worker                                         WORD16 *scf_prev, WORD16 *scf_new,
1094*15dc779aSAndroid Build Coastguard Worker                                         FLOAT32 *ptr_sfb_const_pe_part, FLOAT32 *ptr_sfb_form_fac,
1095*15dc779aSAndroid Build Coastguard Worker                                         FLOAT32 *ptr_sfb_num_rel_lines, WORD32 start_sfb,
1096*15dc779aSAndroid Build Coastguard Worker                                         WORD32 stop_sfb) {
1097*15dc779aSAndroid Build Coastguard Worker   FLOAT32 spec_pe_diff = 0.0f;
1098*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb;
1099*15dc779aSAndroid Build Coastguard Worker 
1100*15dc779aSAndroid Build Coastguard Worker   for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1101*15dc779aSAndroid Build Coastguard Worker     if (scf_prev[sfb] != SHRT_MIN) {
1102*15dc779aSAndroid Build Coastguard Worker       FLOAT32 ld_ratio_prev, ld_ratio_new, pe_prev, pe_new;
1103*15dc779aSAndroid Build Coastguard Worker 
1104*15dc779aSAndroid Build Coastguard Worker       if (ptr_sfb_const_pe_part[sfb] == MIN_FLT_VAL) {
1105*15dc779aSAndroid Build Coastguard Worker         ptr_sfb_const_pe_part[sfb] = (FLOAT32)log(pstr_psy_out->ptr_sfb_energy[sfb] *
1106*15dc779aSAndroid Build Coastguard Worker                                                   (FLOAT32)6.75f / ptr_sfb_form_fac[sfb]) *
1107*15dc779aSAndroid Build Coastguard Worker                                      LOG2_1;
1108*15dc779aSAndroid Build Coastguard Worker       }
1109*15dc779aSAndroid Build Coastguard Worker 
1110*15dc779aSAndroid Build Coastguard Worker       ld_ratio_prev = ptr_sfb_const_pe_part[sfb] - 0.375f * scf_prev[sfb];
1111*15dc779aSAndroid Build Coastguard Worker       ld_ratio_new = ptr_sfb_const_pe_part[sfb] - 0.375f * scf_new[sfb];
1112*15dc779aSAndroid Build Coastguard Worker 
1113*15dc779aSAndroid Build Coastguard Worker       if (ld_ratio_prev >= PE_C1) {
1114*15dc779aSAndroid Build Coastguard Worker         pe_prev = ld_ratio_prev;
1115*15dc779aSAndroid Build Coastguard Worker       } else {
1116*15dc779aSAndroid Build Coastguard Worker         pe_prev = PE_C2 + PE_C3 * ld_ratio_prev;
1117*15dc779aSAndroid Build Coastguard Worker       }
1118*15dc779aSAndroid Build Coastguard Worker 
1119*15dc779aSAndroid Build Coastguard Worker       if (ld_ratio_new >= PE_C1) {
1120*15dc779aSAndroid Build Coastguard Worker         pe_new = ld_ratio_new;
1121*15dc779aSAndroid Build Coastguard Worker       } else {
1122*15dc779aSAndroid Build Coastguard Worker         pe_new = PE_C2 + PE_C3 * ld_ratio_new;
1123*15dc779aSAndroid Build Coastguard Worker       }
1124*15dc779aSAndroid Build Coastguard Worker 
1125*15dc779aSAndroid Build Coastguard Worker       spec_pe_diff += (FLOAT32)0.7f * ptr_sfb_num_rel_lines[sfb] * (pe_new - pe_prev);
1126*15dc779aSAndroid Build Coastguard Worker     }
1127*15dc779aSAndroid Build Coastguard Worker   }
1128*15dc779aSAndroid Build Coastguard Worker 
1129*15dc779aSAndroid Build Coastguard Worker   return spec_pe_diff;
1130*15dc779aSAndroid Build Coastguard Worker }
1131*15dc779aSAndroid Build Coastguard Worker 
iusace_calc_sfb_dist(const FLOAT32 * ptr_spec,const FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD32 sfb_width,WORD32 gain)1132*15dc779aSAndroid Build Coastguard Worker FLOAT32 iusace_calc_sfb_dist(const FLOAT32 *ptr_spec, const FLOAT32 *ptr_exp_spec,
1133*15dc779aSAndroid Build Coastguard Worker                              WORD16 *ptr_quant_spec, WORD32 sfb_width, WORD32 gain) {
1134*15dc779aSAndroid Build Coastguard Worker   WORD32 i;
1135*15dc779aSAndroid Build Coastguard Worker   FLOAT32 dist = 0;
1136*15dc779aSAndroid Build Coastguard Worker   FLOAT32 k = 0.4054f;
1137*15dc779aSAndroid Build Coastguard Worker   FLOAT32 quantizer = ixheaace_fd_quant_table[gain + 128];
1138*15dc779aSAndroid Build Coastguard Worker   FLOAT32 inv_quantizer = ixheaace_fd_inv_quant_table[gain + 128];
1139*15dc779aSAndroid Build Coastguard Worker 
1140*15dc779aSAndroid Build Coastguard Worker   for (i = 0; i < sfb_width; i++) {
1141*15dc779aSAndroid Build Coastguard Worker     FLOAT32 iq_val;
1142*15dc779aSAndroid Build Coastguard Worker     FLOAT32 diff;
1143*15dc779aSAndroid Build Coastguard Worker 
1144*15dc779aSAndroid Build Coastguard Worker     ptr_quant_spec[i] = (WORD16)(k + quantizer * ptr_exp_spec[i]);
1145*15dc779aSAndroid Build Coastguard Worker 
1146*15dc779aSAndroid Build Coastguard Worker     if (ptr_quant_spec[i] < 64) {
1147*15dc779aSAndroid Build Coastguard Worker       iq_val = ixheaace_pow_4_3_table[ptr_quant_spec[i]] * inv_quantizer;
1148*15dc779aSAndroid Build Coastguard Worker     } else {
1149*15dc779aSAndroid Build Coastguard Worker       iq_val = (FLOAT32)((pow((FLOAT32)abs(ptr_quant_spec[i]), 4.0f / 3.0f)) * inv_quantizer);
1150*15dc779aSAndroid Build Coastguard Worker     }
1151*15dc779aSAndroid Build Coastguard Worker 
1152*15dc779aSAndroid Build Coastguard Worker     diff = (FLOAT32)fabs(ptr_spec[i]) - iq_val;
1153*15dc779aSAndroid Build Coastguard Worker 
1154*15dc779aSAndroid Build Coastguard Worker     dist += diff * diff;
1155*15dc779aSAndroid Build Coastguard Worker   }
1156*15dc779aSAndroid Build Coastguard Worker 
1157*15dc779aSAndroid Build Coastguard Worker   return dist;
1158*15dc779aSAndroid Build Coastguard Worker }
1159*15dc779aSAndroid Build Coastguard Worker 
iusace_improve_scf(FLOAT32 * ptr_spec,FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD16 * ptr_quant_spec_temp,WORD32 sfb_width,FLOAT32 threshold,WORD16 scf,WORD16 min_scf,FLOAT32 * dist,WORD16 * ptr_min_calc_scf)1160*15dc779aSAndroid Build Coastguard Worker static WORD16 iusace_improve_scf(FLOAT32 *ptr_spec, FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
1161*15dc779aSAndroid Build Coastguard Worker                                  WORD16 *ptr_quant_spec_temp, WORD32 sfb_width, FLOAT32 threshold,
1162*15dc779aSAndroid Build Coastguard Worker                                  WORD16 scf, WORD16 min_scf, FLOAT32 *dist,
1163*15dc779aSAndroid Build Coastguard Worker                                  WORD16 *ptr_min_calc_scf) {
1164*15dc779aSAndroid Build Coastguard Worker   FLOAT32 sfb_dist;
1165*15dc779aSAndroid Build Coastguard Worker   WORD16 best_scf = scf;
1166*15dc779aSAndroid Build Coastguard Worker   WORD32 j;
1167*15dc779aSAndroid Build Coastguard Worker 
1168*15dc779aSAndroid Build Coastguard Worker   sfb_dist = iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec, sfb_width, scf);
1169*15dc779aSAndroid Build Coastguard Worker 
1170*15dc779aSAndroid Build Coastguard Worker   *ptr_min_calc_scf = scf;
1171*15dc779aSAndroid Build Coastguard Worker 
1172*15dc779aSAndroid Build Coastguard Worker   if (sfb_dist > (1.25 * threshold)) {
1173*15dc779aSAndroid Build Coastguard Worker     WORD16 estimated_scf = scf;
1174*15dc779aSAndroid Build Coastguard Worker     FLOAT32 best_sfb_dist = sfb_dist;
1175*15dc779aSAndroid Build Coastguard Worker     WORD32 count;
1176*15dc779aSAndroid Build Coastguard Worker 
1177*15dc779aSAndroid Build Coastguard Worker     count = 0;
1178*15dc779aSAndroid Build Coastguard Worker 
1179*15dc779aSAndroid Build Coastguard Worker     while ((sfb_dist > (1.25 * threshold)) && (count++ < SCF_COUNT_LIMIT_THREE)) {
1180*15dc779aSAndroid Build Coastguard Worker       scf++;
1181*15dc779aSAndroid Build Coastguard Worker 
1182*15dc779aSAndroid Build Coastguard Worker       sfb_dist =
1183*15dc779aSAndroid Build Coastguard Worker           iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
1184*15dc779aSAndroid Build Coastguard Worker 
1185*15dc779aSAndroid Build Coastguard Worker       if (sfb_dist < best_sfb_dist) {
1186*15dc779aSAndroid Build Coastguard Worker         best_scf = scf;
1187*15dc779aSAndroid Build Coastguard Worker         best_sfb_dist = sfb_dist;
1188*15dc779aSAndroid Build Coastguard Worker 
1189*15dc779aSAndroid Build Coastguard Worker         memcpy(ptr_quant_spec, ptr_quant_spec_temp, sfb_width * sizeof(WORD16));
1190*15dc779aSAndroid Build Coastguard Worker       }
1191*15dc779aSAndroid Build Coastguard Worker     }
1192*15dc779aSAndroid Build Coastguard Worker 
1193*15dc779aSAndroid Build Coastguard Worker     count = 0;
1194*15dc779aSAndroid Build Coastguard Worker     scf = estimated_scf;
1195*15dc779aSAndroid Build Coastguard Worker     sfb_dist = best_sfb_dist;
1196*15dc779aSAndroid Build Coastguard Worker 
1197*15dc779aSAndroid Build Coastguard Worker     while ((sfb_dist > (1.25 * threshold)) && (count++ < SCF_COUNT_LIMIT_ONE) &&
1198*15dc779aSAndroid Build Coastguard Worker       (scf > min_scf)) {
1199*15dc779aSAndroid Build Coastguard Worker       scf--;
1200*15dc779aSAndroid Build Coastguard Worker 
1201*15dc779aSAndroid Build Coastguard Worker       sfb_dist =
1202*15dc779aSAndroid Build Coastguard Worker           iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
1203*15dc779aSAndroid Build Coastguard Worker 
1204*15dc779aSAndroid Build Coastguard Worker       if (sfb_dist < best_sfb_dist) {
1205*15dc779aSAndroid Build Coastguard Worker         best_scf = scf;
1206*15dc779aSAndroid Build Coastguard Worker         best_sfb_dist = sfb_dist;
1207*15dc779aSAndroid Build Coastguard Worker 
1208*15dc779aSAndroid Build Coastguard Worker         memcpy(ptr_quant_spec, ptr_quant_spec_temp, sfb_width * sizeof(WORD16));
1209*15dc779aSAndroid Build Coastguard Worker       }
1210*15dc779aSAndroid Build Coastguard Worker       *ptr_min_calc_scf = scf;
1211*15dc779aSAndroid Build Coastguard Worker     }
1212*15dc779aSAndroid Build Coastguard Worker     *dist = best_sfb_dist;
1213*15dc779aSAndroid Build Coastguard Worker   } else {
1214*15dc779aSAndroid Build Coastguard Worker     FLOAT32 best_sfb_dist = sfb_dist;
1215*15dc779aSAndroid Build Coastguard Worker     FLOAT32 allowed_sfb_dist = MIN(sfb_dist * 1.25f, threshold);
1216*15dc779aSAndroid Build Coastguard Worker     WORD32 count;
1217*15dc779aSAndroid Build Coastguard Worker 
1218*15dc779aSAndroid Build Coastguard Worker     for (count = 0; count < SCF_COUNT_LIMIT_THREE; count++) {
1219*15dc779aSAndroid Build Coastguard Worker       scf++;
1220*15dc779aSAndroid Build Coastguard Worker 
1221*15dc779aSAndroid Build Coastguard Worker       sfb_dist =
1222*15dc779aSAndroid Build Coastguard Worker           iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
1223*15dc779aSAndroid Build Coastguard Worker 
1224*15dc779aSAndroid Build Coastguard Worker       if (sfb_dist < allowed_sfb_dist) {
1225*15dc779aSAndroid Build Coastguard Worker         *ptr_min_calc_scf = best_scf + 1;
1226*15dc779aSAndroid Build Coastguard Worker 
1227*15dc779aSAndroid Build Coastguard Worker         best_scf = scf;
1228*15dc779aSAndroid Build Coastguard Worker         best_sfb_dist = sfb_dist;
1229*15dc779aSAndroid Build Coastguard Worker         memcpy(ptr_quant_spec, ptr_quant_spec_temp, sfb_width * sizeof(WORD16));
1230*15dc779aSAndroid Build Coastguard Worker       }
1231*15dc779aSAndroid Build Coastguard Worker     }
1232*15dc779aSAndroid Build Coastguard Worker     *dist = best_sfb_dist;
1233*15dc779aSAndroid Build Coastguard Worker   }
1234*15dc779aSAndroid Build Coastguard Worker 
1235*15dc779aSAndroid Build Coastguard Worker   for (j = 0; j < sfb_width; j++) {
1236*15dc779aSAndroid Build Coastguard Worker     if (ptr_spec[j] < 0) {
1237*15dc779aSAndroid Build Coastguard Worker       ptr_quant_spec[j] = -ptr_quant_spec[j];
1238*15dc779aSAndroid Build Coastguard Worker     }
1239*15dc779aSAndroid Build Coastguard Worker   }
1240*15dc779aSAndroid Build Coastguard Worker 
1241*15dc779aSAndroid Build Coastguard Worker   return best_scf;
1242*15dc779aSAndroid Build Coastguard Worker }
1243*15dc779aSAndroid Build Coastguard Worker 
iusace_assimilate_single_scf(ia_psy_mod_out_data_struct * pstr_psy_out,FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD16 * ptr_quant_spec_temp,WORD16 * scf,WORD16 * ptr_min_scf,FLOAT32 * ptr_sfb_dist,FLOAT32 * ptr_sfb_const_pe_part,FLOAT32 * ptr_sfb_form_fac,FLOAT32 * ptr_sfb_num_lines,WORD16 * ptr_min_calc_scf,FLOAT32 * ptr_mdct_spec_float)1244*15dc779aSAndroid Build Coastguard Worker static VOID iusace_assimilate_single_scf(ia_psy_mod_out_data_struct *pstr_psy_out,
1245*15dc779aSAndroid Build Coastguard Worker                                          FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
1246*15dc779aSAndroid Build Coastguard Worker                                          WORD16 *ptr_quant_spec_temp, WORD16 *scf,
1247*15dc779aSAndroid Build Coastguard Worker                                          WORD16 *ptr_min_scf, FLOAT32 *ptr_sfb_dist,
1248*15dc779aSAndroid Build Coastguard Worker                                          FLOAT32 *ptr_sfb_const_pe_part,
1249*15dc779aSAndroid Build Coastguard Worker                                          FLOAT32 *ptr_sfb_form_fac, FLOAT32 *ptr_sfb_num_lines,
1250*15dc779aSAndroid Build Coastguard Worker                                          WORD16 *ptr_min_calc_scf, FLOAT32 *ptr_mdct_spec_float) {
1251*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb_prev, sfb_act, sfb_next;
1252*15dc779aSAndroid Build Coastguard Worker   WORD16 scf_act = 0, *scf_prev, *scf_next, min_scf, max_scf;
1253*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb_width, sfb_offs;
1254*15dc779aSAndroid Build Coastguard Worker   FLOAT32 energy;
1255*15dc779aSAndroid Build Coastguard Worker   FLOAT32 sfb_pe_prev, sfb_pe_new;
1256*15dc779aSAndroid Build Coastguard Worker   FLOAT32 sfb_dist_new;
1257*15dc779aSAndroid Build Coastguard Worker   WORD32 j;
1258*15dc779aSAndroid Build Coastguard Worker   WORD32 success = 0;
1259*15dc779aSAndroid Build Coastguard Worker   FLOAT32 delta_pe = 0.0f, delta_pe_new, delta_pe_temp;
1260*15dc779aSAndroid Build Coastguard Worker   WORD16 prev_scf_last[MAX_NUM_GROUPED_SFB], prev_scf_next[MAX_NUM_GROUPED_SFB];
1261*15dc779aSAndroid Build Coastguard Worker   FLOAT32 delta_pe_last[MAX_NUM_GROUPED_SFB];
1262*15dc779aSAndroid Build Coastguard Worker   WORD32 update_min_scf;
1263*15dc779aSAndroid Build Coastguard Worker 
1264*15dc779aSAndroid Build Coastguard Worker   for (j = 0; j < pstr_psy_out->sfb_count; j++) {
1265*15dc779aSAndroid Build Coastguard Worker     prev_scf_last[j] = SHRT_MAX;
1266*15dc779aSAndroid Build Coastguard Worker     prev_scf_next[j] = SHRT_MAX;
1267*15dc779aSAndroid Build Coastguard Worker     delta_pe_last[j] = MAX_FLT_VAL;
1268*15dc779aSAndroid Build Coastguard Worker   }
1269*15dc779aSAndroid Build Coastguard Worker 
1270*15dc779aSAndroid Build Coastguard Worker   sfb_prev = -1;
1271*15dc779aSAndroid Build Coastguard Worker   sfb_act = -1;
1272*15dc779aSAndroid Build Coastguard Worker   sfb_next = -1;
1273*15dc779aSAndroid Build Coastguard Worker   scf_prev = 0;
1274*15dc779aSAndroid Build Coastguard Worker   scf_next = 0;
1275*15dc779aSAndroid Build Coastguard Worker   min_scf = SHRT_MAX;
1276*15dc779aSAndroid Build Coastguard Worker   max_scf = SHRT_MAX;
1277*15dc779aSAndroid Build Coastguard Worker 
1278*15dc779aSAndroid Build Coastguard Worker   do {
1279*15dc779aSAndroid Build Coastguard Worker     sfb_next++;
1280*15dc779aSAndroid Build Coastguard Worker 
1281*15dc779aSAndroid Build Coastguard Worker     while ((sfb_next < pstr_psy_out->sfb_count) && (scf[sfb_next] == SHRT_MIN)) {
1282*15dc779aSAndroid Build Coastguard Worker       sfb_next++;
1283*15dc779aSAndroid Build Coastguard Worker     }
1284*15dc779aSAndroid Build Coastguard Worker 
1285*15dc779aSAndroid Build Coastguard Worker     if ((sfb_prev >= 0) && (sfb_act >= 0) && (sfb_next < pstr_psy_out->sfb_count)) {
1286*15dc779aSAndroid Build Coastguard Worker       scf_act = scf[sfb_act];
1287*15dc779aSAndroid Build Coastguard Worker 
1288*15dc779aSAndroid Build Coastguard Worker       scf_prev = scf + sfb_prev;
1289*15dc779aSAndroid Build Coastguard Worker       scf_next = scf + sfb_next;
1290*15dc779aSAndroid Build Coastguard Worker 
1291*15dc779aSAndroid Build Coastguard Worker       min_scf = MIN(*scf_prev, *scf_next);
1292*15dc779aSAndroid Build Coastguard Worker 
1293*15dc779aSAndroid Build Coastguard Worker       max_scf = MAX(*scf_prev, *scf_next);
1294*15dc779aSAndroid Build Coastguard Worker     } else {
1295*15dc779aSAndroid Build Coastguard Worker       if ((sfb_prev == -1) && (sfb_act >= 0) && (sfb_next < pstr_psy_out->sfb_count)) {
1296*15dc779aSAndroid Build Coastguard Worker         scf_act = scf[sfb_act];
1297*15dc779aSAndroid Build Coastguard Worker 
1298*15dc779aSAndroid Build Coastguard Worker         scf_prev = &scf_act;
1299*15dc779aSAndroid Build Coastguard Worker 
1300*15dc779aSAndroid Build Coastguard Worker         scf_next = scf + sfb_next;
1301*15dc779aSAndroid Build Coastguard Worker 
1302*15dc779aSAndroid Build Coastguard Worker         min_scf = *scf_next;
1303*15dc779aSAndroid Build Coastguard Worker 
1304*15dc779aSAndroid Build Coastguard Worker         max_scf = *scf_next;
1305*15dc779aSAndroid Build Coastguard Worker       } else {
1306*15dc779aSAndroid Build Coastguard Worker         if ((sfb_prev >= 0) && (sfb_act >= 0) && (sfb_next == pstr_psy_out->sfb_count)) {
1307*15dc779aSAndroid Build Coastguard Worker           scf_act = scf[sfb_act];
1308*15dc779aSAndroid Build Coastguard Worker 
1309*15dc779aSAndroid Build Coastguard Worker           scf_prev = scf + sfb_prev;
1310*15dc779aSAndroid Build Coastguard Worker 
1311*15dc779aSAndroid Build Coastguard Worker           scf_next = &scf_act;
1312*15dc779aSAndroid Build Coastguard Worker 
1313*15dc779aSAndroid Build Coastguard Worker           min_scf = *scf_prev;
1314*15dc779aSAndroid Build Coastguard Worker 
1315*15dc779aSAndroid Build Coastguard Worker           max_scf = *scf_prev;
1316*15dc779aSAndroid Build Coastguard Worker         }
1317*15dc779aSAndroid Build Coastguard Worker       }
1318*15dc779aSAndroid Build Coastguard Worker     }
1319*15dc779aSAndroid Build Coastguard Worker 
1320*15dc779aSAndroid Build Coastguard Worker     if (sfb_act >= 0) {
1321*15dc779aSAndroid Build Coastguard Worker       min_scf = MAX(min_scf, ptr_min_scf[sfb_act]);
1322*15dc779aSAndroid Build Coastguard Worker     }
1323*15dc779aSAndroid Build Coastguard Worker 
1324*15dc779aSAndroid Build Coastguard Worker     if ((sfb_act >= 0) && (sfb_prev >= 0 || sfb_next < pstr_psy_out->sfb_count) &&
1325*15dc779aSAndroid Build Coastguard Worker         (scf_act > min_scf) && (scf_act <= min_scf + MAX_SCF_DELTA) &&
1326*15dc779aSAndroid Build Coastguard Worker         (scf_act >= max_scf - MAX_SCF_DELTA) &&
1327*15dc779aSAndroid Build Coastguard Worker         (*scf_prev != prev_scf_last[sfb_act] || *scf_next != prev_scf_next[sfb_act] ||
1328*15dc779aSAndroid Build Coastguard Worker          delta_pe < delta_pe_last[sfb_act])) {
1329*15dc779aSAndroid Build Coastguard Worker       success = 0;
1330*15dc779aSAndroid Build Coastguard Worker 
1331*15dc779aSAndroid Build Coastguard Worker       sfb_width = pstr_psy_out->sfb_offsets[sfb_act + 1] - pstr_psy_out->sfb_offsets[sfb_act];
1332*15dc779aSAndroid Build Coastguard Worker 
1333*15dc779aSAndroid Build Coastguard Worker       sfb_offs = pstr_psy_out->sfb_offsets[sfb_act];
1334*15dc779aSAndroid Build Coastguard Worker 
1335*15dc779aSAndroid Build Coastguard Worker       energy = pstr_psy_out->ptr_sfb_energy[sfb_act];
1336*15dc779aSAndroid Build Coastguard Worker 
1337*15dc779aSAndroid Build Coastguard Worker       if (ptr_sfb_const_pe_part[sfb_act] == MIN_FLT_VAL) {
1338*15dc779aSAndroid Build Coastguard Worker         ptr_sfb_const_pe_part[sfb_act] =
1339*15dc779aSAndroid Build Coastguard Worker             (FLOAT32)log(energy * (FLOAT32)6.75f / ptr_sfb_form_fac[sfb_act]) * LOG2_1;
1340*15dc779aSAndroid Build Coastguard Worker       }
1341*15dc779aSAndroid Build Coastguard Worker 
1342*15dc779aSAndroid Build Coastguard Worker       sfb_pe_prev = iusace_calc_single_spec_pe(scf_act, ptr_sfb_const_pe_part[sfb_act],
1343*15dc779aSAndroid Build Coastguard Worker                                                ptr_sfb_num_lines[sfb_act]) +
1344*15dc779aSAndroid Build Coastguard Worker                     iusace_count_single_scf_bits(scf_act, *scf_prev, *scf_next);
1345*15dc779aSAndroid Build Coastguard Worker 
1346*15dc779aSAndroid Build Coastguard Worker       delta_pe_new = delta_pe;
1347*15dc779aSAndroid Build Coastguard Worker       update_min_scf = 1;
1348*15dc779aSAndroid Build Coastguard Worker 
1349*15dc779aSAndroid Build Coastguard Worker       do {
1350*15dc779aSAndroid Build Coastguard Worker         scf_act--;
1351*15dc779aSAndroid Build Coastguard Worker 
1352*15dc779aSAndroid Build Coastguard Worker         if (scf_act < ptr_min_calc_scf[sfb_act] && scf_act >= max_scf - MAX_SCF_DELTA) {
1353*15dc779aSAndroid Build Coastguard Worker           sfb_pe_new = iusace_calc_single_spec_pe(scf_act, ptr_sfb_const_pe_part[sfb_act],
1354*15dc779aSAndroid Build Coastguard Worker                                                   ptr_sfb_num_lines[sfb_act]) +
1355*15dc779aSAndroid Build Coastguard Worker                        (FLOAT32)iusace_count_single_scf_bits(scf_act, *scf_prev, *scf_next);
1356*15dc779aSAndroid Build Coastguard Worker 
1357*15dc779aSAndroid Build Coastguard Worker           delta_pe_temp = delta_pe + sfb_pe_new - sfb_pe_prev;
1358*15dc779aSAndroid Build Coastguard Worker 
1359*15dc779aSAndroid Build Coastguard Worker           if (delta_pe_temp < (FLOAT32)10.0f) {
1360*15dc779aSAndroid Build Coastguard Worker             sfb_dist_new =
1361*15dc779aSAndroid Build Coastguard Worker                 iusace_calc_sfb_dist(ptr_mdct_spec_float + sfb_offs, ptr_exp_spec + sfb_offs,
1362*15dc779aSAndroid Build Coastguard Worker                                      ptr_quant_spec_temp + sfb_offs, sfb_width, scf_act);
1363*15dc779aSAndroid Build Coastguard Worker 
1364*15dc779aSAndroid Build Coastguard Worker             if (sfb_dist_new < ptr_sfb_dist[sfb_act]) {
1365*15dc779aSAndroid Build Coastguard Worker               scf[sfb_act] = scf_act;
1366*15dc779aSAndroid Build Coastguard Worker               ptr_sfb_dist[sfb_act] = sfb_dist_new;
1367*15dc779aSAndroid Build Coastguard Worker 
1368*15dc779aSAndroid Build Coastguard Worker               for (j = sfb_offs; j < sfb_offs + sfb_width; j++) {
1369*15dc779aSAndroid Build Coastguard Worker                 ptr_quant_spec[j] = ptr_quant_spec_temp[j];
1370*15dc779aSAndroid Build Coastguard Worker 
1371*15dc779aSAndroid Build Coastguard Worker                 if (ptr_mdct_spec_float[j] < 0.0f) {
1372*15dc779aSAndroid Build Coastguard Worker                   ptr_quant_spec[j] = -ptr_quant_spec[j];
1373*15dc779aSAndroid Build Coastguard Worker                 }
1374*15dc779aSAndroid Build Coastguard Worker               }
1375*15dc779aSAndroid Build Coastguard Worker               delta_pe_new = delta_pe_temp;
1376*15dc779aSAndroid Build Coastguard Worker               success = 1;
1377*15dc779aSAndroid Build Coastguard Worker             }
1378*15dc779aSAndroid Build Coastguard Worker 
1379*15dc779aSAndroid Build Coastguard Worker             if (update_min_scf) {
1380*15dc779aSAndroid Build Coastguard Worker               ptr_min_calc_scf[sfb_act] = scf_act;
1381*15dc779aSAndroid Build Coastguard Worker             }
1382*15dc779aSAndroid Build Coastguard Worker           } else {
1383*15dc779aSAndroid Build Coastguard Worker             update_min_scf = 0;
1384*15dc779aSAndroid Build Coastguard Worker           }
1385*15dc779aSAndroid Build Coastguard Worker         }
1386*15dc779aSAndroid Build Coastguard Worker       } while (scf_act > min_scf);
1387*15dc779aSAndroid Build Coastguard Worker 
1388*15dc779aSAndroid Build Coastguard Worker       delta_pe = delta_pe_new;
1389*15dc779aSAndroid Build Coastguard Worker 
1390*15dc779aSAndroid Build Coastguard Worker       prev_scf_last[sfb_act] = *scf_prev;
1391*15dc779aSAndroid Build Coastguard Worker       prev_scf_next[sfb_act] = *scf_next;
1392*15dc779aSAndroid Build Coastguard Worker       delta_pe_last[sfb_act] = delta_pe;
1393*15dc779aSAndroid Build Coastguard Worker     }
1394*15dc779aSAndroid Build Coastguard Worker 
1395*15dc779aSAndroid Build Coastguard Worker     if (success) {
1396*15dc779aSAndroid Build Coastguard Worker       sfb_prev = -1;
1397*15dc779aSAndroid Build Coastguard Worker       sfb_act = -1;
1398*15dc779aSAndroid Build Coastguard Worker       sfb_next = -1;
1399*15dc779aSAndroid Build Coastguard Worker       scf_prev = 0;
1400*15dc779aSAndroid Build Coastguard Worker       scf_next = 0;
1401*15dc779aSAndroid Build Coastguard Worker       min_scf = SHRT_MAX;
1402*15dc779aSAndroid Build Coastguard Worker       max_scf = SHRT_MAX;
1403*15dc779aSAndroid Build Coastguard Worker       success = 0;
1404*15dc779aSAndroid Build Coastguard Worker     } else {
1405*15dc779aSAndroid Build Coastguard Worker       sfb_prev = sfb_act;
1406*15dc779aSAndroid Build Coastguard Worker       sfb_act = sfb_next;
1407*15dc779aSAndroid Build Coastguard Worker     }
1408*15dc779aSAndroid Build Coastguard Worker   } while (sfb_next < pstr_psy_out->sfb_count);
1409*15dc779aSAndroid Build Coastguard Worker   return;
1410*15dc779aSAndroid Build Coastguard Worker }
1411*15dc779aSAndroid Build Coastguard Worker 
iusace_assimilate_multiple_scf(ia_psy_mod_out_data_struct * pstr_psy_out,FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD16 * ptr_quant_spec_temp,WORD16 * ptr_scf,WORD16 * ptr_min_scf,FLOAT32 * ptr_sfb_dist,FLOAT32 * ptr_sfb_const_pe_part,FLOAT32 * ptr_sfb_form_fac,FLOAT32 * ptr_sfb_num_lines,FLOAT32 * ptr_mdct_spec_float,pUWORD8 pstr_scratch)1412*15dc779aSAndroid Build Coastguard Worker static VOID iusace_assimilate_multiple_scf(ia_psy_mod_out_data_struct *pstr_psy_out,
1413*15dc779aSAndroid Build Coastguard Worker                                            FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
1414*15dc779aSAndroid Build Coastguard Worker                                            WORD16 *ptr_quant_spec_temp, WORD16 *ptr_scf,
1415*15dc779aSAndroid Build Coastguard Worker                                            WORD16 *ptr_min_scf, FLOAT32 *ptr_sfb_dist,
1416*15dc779aSAndroid Build Coastguard Worker                                            FLOAT32 *ptr_sfb_const_pe_part,
1417*15dc779aSAndroid Build Coastguard Worker                                            FLOAT32 *ptr_sfb_form_fac, FLOAT32 *ptr_sfb_num_lines,
1418*15dc779aSAndroid Build Coastguard Worker                                            FLOAT32 *ptr_mdct_spec_float, pUWORD8 pstr_scratch) {
1419*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb, start_sfb, stop_sfb;
1420*15dc779aSAndroid Build Coastguard Worker   WORD16 scf_temp[MAX_NUM_GROUPED_SFB], min_scf, max_scf, scf_act;
1421*15dc779aSAndroid Build Coastguard Worker   WORD32 possible_region_found;
1422*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb_width, sfb_offs, j;
1423*15dc779aSAndroid Build Coastguard Worker   FLOAT32 prev_dist_sum, new_dist_sum;
1424*15dc779aSAndroid Build Coastguard Worker   WORD32 delta_scf_bits;
1425*15dc779aSAndroid Build Coastguard Worker   FLOAT32 delta_spec_pe;
1426*15dc779aSAndroid Build Coastguard Worker   FLOAT32 delta_pe = 0.0f, delta_pe_new;
1427*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb_count = pstr_psy_out->sfb_count;
1428*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *sfb_dist_new = (FLOAT32 *)pstr_scratch;
1429*15dc779aSAndroid Build Coastguard Worker   min_scf = SHRT_MAX;
1430*15dc779aSAndroid Build Coastguard Worker   max_scf = SHRT_MIN;
1431*15dc779aSAndroid Build Coastguard Worker 
1432*15dc779aSAndroid Build Coastguard Worker   for (sfb = 0; sfb < sfb_count; sfb++) {
1433*15dc779aSAndroid Build Coastguard Worker     if (ptr_scf[sfb] != SHRT_MIN) {
1434*15dc779aSAndroid Build Coastguard Worker       min_scf = MIN(min_scf, ptr_scf[sfb]);
1435*15dc779aSAndroid Build Coastguard Worker 
1436*15dc779aSAndroid Build Coastguard Worker       max_scf = MAX(max_scf, ptr_scf[sfb]);
1437*15dc779aSAndroid Build Coastguard Worker     }
1438*15dc779aSAndroid Build Coastguard Worker   }
1439*15dc779aSAndroid Build Coastguard Worker 
1440*15dc779aSAndroid Build Coastguard Worker   if (max_scf != SHRT_MIN && max_scf <= min_scf + MAX_SCF_DELTA) {
1441*15dc779aSAndroid Build Coastguard Worker     scf_act = max_scf;
1442*15dc779aSAndroid Build Coastguard Worker 
1443*15dc779aSAndroid Build Coastguard Worker     do {
1444*15dc779aSAndroid Build Coastguard Worker       scf_act--;
1445*15dc779aSAndroid Build Coastguard Worker 
1446*15dc779aSAndroid Build Coastguard Worker       memcpy(scf_temp, ptr_scf, MAX_NUM_GROUPED_SFB * sizeof(WORD16));
1447*15dc779aSAndroid Build Coastguard Worker 
1448*15dc779aSAndroid Build Coastguard Worker       stop_sfb = 0;
1449*15dc779aSAndroid Build Coastguard Worker 
1450*15dc779aSAndroid Build Coastguard Worker       do {
1451*15dc779aSAndroid Build Coastguard Worker         sfb = stop_sfb;
1452*15dc779aSAndroid Build Coastguard Worker 
1453*15dc779aSAndroid Build Coastguard Worker         while (sfb < sfb_count && (ptr_scf[sfb] == SHRT_MIN || ptr_scf[sfb] <= scf_act)) {
1454*15dc779aSAndroid Build Coastguard Worker           sfb++;
1455*15dc779aSAndroid Build Coastguard Worker         }
1456*15dc779aSAndroid Build Coastguard Worker 
1457*15dc779aSAndroid Build Coastguard Worker         start_sfb = sfb;
1458*15dc779aSAndroid Build Coastguard Worker 
1459*15dc779aSAndroid Build Coastguard Worker         sfb++;
1460*15dc779aSAndroid Build Coastguard Worker 
1461*15dc779aSAndroid Build Coastguard Worker         while (sfb < sfb_count && (ptr_scf[sfb] == SHRT_MIN || ptr_scf[sfb] > scf_act)) {
1462*15dc779aSAndroid Build Coastguard Worker           sfb++;
1463*15dc779aSAndroid Build Coastguard Worker         }
1464*15dc779aSAndroid Build Coastguard Worker 
1465*15dc779aSAndroid Build Coastguard Worker         stop_sfb = sfb;
1466*15dc779aSAndroid Build Coastguard Worker 
1467*15dc779aSAndroid Build Coastguard Worker         possible_region_found = 0;
1468*15dc779aSAndroid Build Coastguard Worker 
1469*15dc779aSAndroid Build Coastguard Worker         if (start_sfb < sfb_count) {
1470*15dc779aSAndroid Build Coastguard Worker           possible_region_found = 1;
1471*15dc779aSAndroid Build Coastguard Worker 
1472*15dc779aSAndroid Build Coastguard Worker           for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1473*15dc779aSAndroid Build Coastguard Worker             if (ptr_scf[sfb] != SHRT_MIN) {
1474*15dc779aSAndroid Build Coastguard Worker               if (scf_act < ptr_min_scf[sfb]) {
1475*15dc779aSAndroid Build Coastguard Worker                 possible_region_found = 0;
1476*15dc779aSAndroid Build Coastguard Worker                 break;
1477*15dc779aSAndroid Build Coastguard Worker               }
1478*15dc779aSAndroid Build Coastguard Worker             }
1479*15dc779aSAndroid Build Coastguard Worker           }
1480*15dc779aSAndroid Build Coastguard Worker         }
1481*15dc779aSAndroid Build Coastguard Worker 
1482*15dc779aSAndroid Build Coastguard Worker         if (possible_region_found) {
1483*15dc779aSAndroid Build Coastguard Worker           for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1484*15dc779aSAndroid Build Coastguard Worker             if (scf_temp[sfb] != SHRT_MIN) {
1485*15dc779aSAndroid Build Coastguard Worker               scf_temp[sfb] = scf_act;
1486*15dc779aSAndroid Build Coastguard Worker             }
1487*15dc779aSAndroid Build Coastguard Worker           }
1488*15dc779aSAndroid Build Coastguard Worker 
1489*15dc779aSAndroid Build Coastguard Worker           delta_scf_bits =
1490*15dc779aSAndroid Build Coastguard Worker               iusace_count_scf_bits_diff(ptr_scf, scf_temp, sfb_count, start_sfb, stop_sfb);
1491*15dc779aSAndroid Build Coastguard Worker 
1492*15dc779aSAndroid Build Coastguard Worker           delta_spec_pe =
1493*15dc779aSAndroid Build Coastguard Worker               iusace_calc_spec_pe_diff(pstr_psy_out, ptr_scf, scf_temp, ptr_sfb_const_pe_part,
1494*15dc779aSAndroid Build Coastguard Worker                                        ptr_sfb_form_fac, ptr_sfb_num_lines, start_sfb, stop_sfb);
1495*15dc779aSAndroid Build Coastguard Worker 
1496*15dc779aSAndroid Build Coastguard Worker           delta_pe_new = delta_pe + (FLOAT32)delta_scf_bits + delta_spec_pe;
1497*15dc779aSAndroid Build Coastguard Worker 
1498*15dc779aSAndroid Build Coastguard Worker           if (delta_pe_new < (FLOAT32)10.0f) {
1499*15dc779aSAndroid Build Coastguard Worker             prev_dist_sum = new_dist_sum = 0.0f;
1500*15dc779aSAndroid Build Coastguard Worker 
1501*15dc779aSAndroid Build Coastguard Worker             for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1502*15dc779aSAndroid Build Coastguard Worker               if (scf_temp[sfb] != SHRT_MIN) {
1503*15dc779aSAndroid Build Coastguard Worker                 prev_dist_sum += ptr_sfb_dist[sfb];
1504*15dc779aSAndroid Build Coastguard Worker 
1505*15dc779aSAndroid Build Coastguard Worker                 sfb_width = pstr_psy_out->sfb_offsets[sfb + 1] - pstr_psy_out->sfb_offsets[sfb];
1506*15dc779aSAndroid Build Coastguard Worker 
1507*15dc779aSAndroid Build Coastguard Worker                 sfb_offs = pstr_psy_out->sfb_offsets[sfb];
1508*15dc779aSAndroid Build Coastguard Worker 
1509*15dc779aSAndroid Build Coastguard Worker                 sfb_dist_new[sfb] =
1510*15dc779aSAndroid Build Coastguard Worker                     iusace_calc_sfb_dist(ptr_mdct_spec_float + sfb_offs, ptr_exp_spec + sfb_offs,
1511*15dc779aSAndroid Build Coastguard Worker                                          ptr_quant_spec_temp + sfb_offs, sfb_width, scf_act);
1512*15dc779aSAndroid Build Coastguard Worker 
1513*15dc779aSAndroid Build Coastguard Worker                 if (sfb_dist_new[sfb] > pstr_psy_out->ptr_sfb_thr[sfb]) {
1514*15dc779aSAndroid Build Coastguard Worker                   new_dist_sum = (FLOAT32)2.0f * prev_dist_sum;
1515*15dc779aSAndroid Build Coastguard Worker                   break;
1516*15dc779aSAndroid Build Coastguard Worker                 }
1517*15dc779aSAndroid Build Coastguard Worker 
1518*15dc779aSAndroid Build Coastguard Worker                 new_dist_sum += sfb_dist_new[sfb];
1519*15dc779aSAndroid Build Coastguard Worker               }
1520*15dc779aSAndroid Build Coastguard Worker             }
1521*15dc779aSAndroid Build Coastguard Worker 
1522*15dc779aSAndroid Build Coastguard Worker             if (new_dist_sum < prev_dist_sum) {
1523*15dc779aSAndroid Build Coastguard Worker               delta_pe = delta_pe_new;
1524*15dc779aSAndroid Build Coastguard Worker 
1525*15dc779aSAndroid Build Coastguard Worker               for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1526*15dc779aSAndroid Build Coastguard Worker                 if (ptr_scf[sfb] != SHRT_MIN) {
1527*15dc779aSAndroid Build Coastguard Worker                   sfb_width = pstr_psy_out->sfb_offsets[sfb + 1] - pstr_psy_out->sfb_offsets[sfb];
1528*15dc779aSAndroid Build Coastguard Worker 
1529*15dc779aSAndroid Build Coastguard Worker                   sfb_offs = pstr_psy_out->sfb_offsets[sfb];
1530*15dc779aSAndroid Build Coastguard Worker                   ptr_scf[sfb] = scf_act;
1531*15dc779aSAndroid Build Coastguard Worker                   ptr_sfb_dist[sfb] = sfb_dist_new[sfb];
1532*15dc779aSAndroid Build Coastguard Worker 
1533*15dc779aSAndroid Build Coastguard Worker                   for (j = sfb_offs; j < sfb_offs + sfb_width; j++) {
1534*15dc779aSAndroid Build Coastguard Worker                     ptr_quant_spec[j] = ptr_quant_spec_temp[j];
1535*15dc779aSAndroid Build Coastguard Worker 
1536*15dc779aSAndroid Build Coastguard Worker                     if (ptr_mdct_spec_float[j] < 0.0f) {
1537*15dc779aSAndroid Build Coastguard Worker                       ptr_quant_spec[j] = -ptr_quant_spec[j];
1538*15dc779aSAndroid Build Coastguard Worker                     }
1539*15dc779aSAndroid Build Coastguard Worker                   }
1540*15dc779aSAndroid Build Coastguard Worker                 }
1541*15dc779aSAndroid Build Coastguard Worker               }
1542*15dc779aSAndroid Build Coastguard Worker             }
1543*15dc779aSAndroid Build Coastguard Worker           }
1544*15dc779aSAndroid Build Coastguard Worker         }
1545*15dc779aSAndroid Build Coastguard Worker 
1546*15dc779aSAndroid Build Coastguard Worker       } while (stop_sfb <= sfb_count);
1547*15dc779aSAndroid Build Coastguard Worker 
1548*15dc779aSAndroid Build Coastguard Worker     } while (scf_act > min_scf);
1549*15dc779aSAndroid Build Coastguard Worker   }
1550*15dc779aSAndroid Build Coastguard Worker   return;
1551*15dc779aSAndroid Build Coastguard Worker }
1552*15dc779aSAndroid Build Coastguard Worker 
iusace_estimate_scfs_chan(ia_psy_mod_out_data_struct * pstr_psy_out,ia_qc_out_chan_struct * str_qc_out_chan,WORD32 num_channels,WORD32 chn,iusace_scratch_mem * pstr_scratch)1553*15dc779aSAndroid Build Coastguard Worker VOID iusace_estimate_scfs_chan(ia_psy_mod_out_data_struct *pstr_psy_out,
1554*15dc779aSAndroid Build Coastguard Worker                                ia_qc_out_chan_struct *str_qc_out_chan, WORD32 num_channels,
1555*15dc779aSAndroid Build Coastguard Worker                                WORD32 chn, iusace_scratch_mem *pstr_scratch) {
1556*15dc779aSAndroid Build Coastguard Worker   WORD16 *ptr_scalefactor;
1557*15dc779aSAndroid Build Coastguard Worker   WORD32 *global_gain;
1558*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *p_sfb_form_factor;
1559*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *p_sfb_num_relevant_lines;
1560*15dc779aSAndroid Build Coastguard Worker   WORD16 *ptr_quant_spec;
1561*15dc779aSAndroid Build Coastguard Worker   WORD32 i, ch, j, idx = 0;
1562*15dc779aSAndroid Build Coastguard Worker   FLOAT32 thresh, energy, energy_part, thr_part;
1563*15dc779aSAndroid Build Coastguard Worker   FLOAT32 scf_float;
1564*15dc779aSAndroid Build Coastguard Worker   WORD16 scf_int = 0, min_scf = 0, max_scf = 0;
1565*15dc779aSAndroid Build Coastguard Worker   FLOAT64 max_spec = 0.0f;
1566*15dc779aSAndroid Build Coastguard Worker   WORD16 min_sf_max_quant[MAX_NUM_GROUPED_SFB] = {0};
1567*15dc779aSAndroid Build Coastguard Worker   pUWORD8 ptr_scratch = pstr_scratch->ptr_fd_scratch;
1568*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_sfb_dist = (FLOAT32 *)ptr_scratch;
1569*15dc779aSAndroid Build Coastguard Worker   ptr_scratch += MAX_NUM_GROUPED_SFB * sizeof(ptr_sfb_dist[0]);
1570*15dc779aSAndroid Build Coastguard Worker   WORD16 min_calc_scf[MAX_NUM_GROUPED_SFB] = {0};
1571*15dc779aSAndroid Build Coastguard Worker 
1572*15dc779aSAndroid Build Coastguard Worker   WORD16 *ptr_quant_spec_temp = pstr_scratch->p_adjthr_quant_spec_temp;
1573*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_exp_spec = pstr_scratch->p_adjthr_ptr_exp_spec;
1574*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *ptr_mdct_spec_float = pstr_scratch->p_adjthr_mdct_spec_float;
1575*15dc779aSAndroid Build Coastguard Worker   FLOAT32 *sfb_const_pe_part = (FLOAT32 *)ptr_scratch;
1576*15dc779aSAndroid Build Coastguard Worker 
1577*15dc779aSAndroid Build Coastguard Worker   FLOAT32 **ptr_sfb_form_factor = &pstr_scratch->ptr_sfb_form_fac[0];
1578*15dc779aSAndroid Build Coastguard Worker   FLOAT32 **ptr_sfb_num_relevant_lines = &pstr_scratch->ptr_sfb_num_relevant_lines[0];
1579*15dc779aSAndroid Build Coastguard Worker 
1580*15dc779aSAndroid Build Coastguard Worker   ptr_scratch += MAX_NUM_GROUPED_SFB * sizeof(sfb_const_pe_part[0]);
1581*15dc779aSAndroid Build Coastguard Worker 
1582*15dc779aSAndroid Build Coastguard Worker   memset(ptr_quant_spec_temp, 0, FRAME_LEN_LONG * sizeof(WORD16));
1583*15dc779aSAndroid Build Coastguard Worker   memset(ptr_mdct_spec_float, 0, FRAME_LEN_LONG * sizeof(FLOAT32));
1584*15dc779aSAndroid Build Coastguard Worker   memset(ptr_exp_spec, 0, FRAME_LEN_LONG * sizeof(FLOAT32));
1585*15dc779aSAndroid Build Coastguard Worker   memset(ptr_sfb_dist, 0, MAX_NUM_GROUPED_SFB * sizeof(FLOAT32));
1586*15dc779aSAndroid Build Coastguard Worker   for (ch = chn; ch < chn + num_channels; ch++) {
1587*15dc779aSAndroid Build Coastguard Worker     ia_psy_mod_out_data_struct *ptr_psy_out = &pstr_psy_out[ch];
1588*15dc779aSAndroid Build Coastguard Worker     str_qc_out_chan[idx].global_gain = 0;
1589*15dc779aSAndroid Build Coastguard Worker 
1590*15dc779aSAndroid Build Coastguard Worker     memset(str_qc_out_chan[idx].scalefactor, 0,
1591*15dc779aSAndroid Build Coastguard Worker            sizeof(str_qc_out_chan[idx].scalefactor[0]) * pstr_psy_out[ch].sfb_count);
1592*15dc779aSAndroid Build Coastguard Worker     memset(str_qc_out_chan[idx].quant_spec, 0,
1593*15dc779aSAndroid Build Coastguard Worker            sizeof(str_qc_out_chan[idx].quant_spec[0]) * FRAME_LEN_LONG);
1594*15dc779aSAndroid Build Coastguard Worker 
1595*15dc779aSAndroid Build Coastguard Worker     ptr_scalefactor = str_qc_out_chan[idx].scalefactor;
1596*15dc779aSAndroid Build Coastguard Worker     global_gain = &str_qc_out_chan[idx].global_gain;
1597*15dc779aSAndroid Build Coastguard Worker     p_sfb_form_factor = &ptr_sfb_form_factor[idx][0];
1598*15dc779aSAndroid Build Coastguard Worker     p_sfb_num_relevant_lines = &ptr_sfb_num_relevant_lines[idx][0];
1599*15dc779aSAndroid Build Coastguard Worker     ptr_quant_spec = str_qc_out_chan[idx].quant_spec;
1600*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1601*15dc779aSAndroid Build Coastguard Worker       thresh = ptr_psy_out->ptr_sfb_thr[i];
1602*15dc779aSAndroid Build Coastguard Worker       energy = ptr_psy_out->ptr_sfb_energy[i];
1603*15dc779aSAndroid Build Coastguard Worker       max_spec = 0.0;
1604*15dc779aSAndroid Build Coastguard Worker 
1605*15dc779aSAndroid Build Coastguard Worker       for (j = ptr_psy_out->sfb_offsets[i]; j < ptr_psy_out->sfb_offsets[i + 1]; j++) {
1606*15dc779aSAndroid Build Coastguard Worker         max_spec = MAX(max_spec, fabs(ptr_psy_out->ptr_spec_coeffs[j]));
1607*15dc779aSAndroid Build Coastguard Worker       }
1608*15dc779aSAndroid Build Coastguard Worker 
1609*15dc779aSAndroid Build Coastguard Worker       ptr_scalefactor[i] = MIN_SHRT_VAL;
1610*15dc779aSAndroid Build Coastguard Worker       min_sf_max_quant[i] = MIN_SHRT_VAL;
1611*15dc779aSAndroid Build Coastguard Worker 
1612*15dc779aSAndroid Build Coastguard Worker       if ((max_spec > 0.0) && (energy > thresh) && (p_sfb_form_factor[i] != MIN_FLT_VAL)) {
1613*15dc779aSAndroid Build Coastguard Worker         energy_part = (FLOAT32)log10(p_sfb_form_factor[i] + FLT_EPSILON);
1614*15dc779aSAndroid Build Coastguard Worker 
1615*15dc779aSAndroid Build Coastguard Worker         thr_part = (FLOAT32)log10(6.75 * thresh + MIN_FLT_VAL);
1616*15dc779aSAndroid Build Coastguard Worker         scf_float = 8.8585f * (thr_part - energy_part);
1617*15dc779aSAndroid Build Coastguard Worker         scf_int = (WORD16)floor(scf_float);
1618*15dc779aSAndroid Build Coastguard Worker         min_sf_max_quant[i] = (WORD16)ceil(C1_SF + C2_SF * log(max_spec));
1619*15dc779aSAndroid Build Coastguard Worker         scf_int = MAX(scf_int, min_sf_max_quant[i]);
1620*15dc779aSAndroid Build Coastguard Worker         scf_int = MAX(scf_int, MIN_GAIN_INDEX);
1621*15dc779aSAndroid Build Coastguard Worker         scf_int = MIN(scf_int, (MAX_GAIN_INDEX - SCF_COUNT_LIMIT_THREE));
1622*15dc779aSAndroid Build Coastguard Worker         for (j = 0; j < ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i]; j++) {
1623*15dc779aSAndroid Build Coastguard Worker           ptr_exp_spec[ptr_psy_out->sfb_offsets[i] + j] =
1624*15dc779aSAndroid Build Coastguard Worker               (FLOAT32)(ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i] + j]);
1625*15dc779aSAndroid Build Coastguard Worker           ptr_mdct_spec_float[ptr_psy_out->sfb_offsets[i] + j] =
1626*15dc779aSAndroid Build Coastguard Worker               (FLOAT32)(ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i] + j]);
1627*15dc779aSAndroid Build Coastguard Worker         }
1628*15dc779aSAndroid Build Coastguard Worker 
1629*15dc779aSAndroid Build Coastguard Worker         iusace_calculate_exp_spec(ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i],
1630*15dc779aSAndroid Build Coastguard Worker                                   ptr_exp_spec + ptr_psy_out->sfb_offsets[i],
1631*15dc779aSAndroid Build Coastguard Worker                                   ptr_mdct_spec_float + ptr_psy_out->sfb_offsets[i]);
1632*15dc779aSAndroid Build Coastguard Worker 
1633*15dc779aSAndroid Build Coastguard Worker         scf_int = iusace_improve_scf(
1634*15dc779aSAndroid Build Coastguard Worker             ptr_mdct_spec_float + ptr_psy_out->sfb_offsets[i],
1635*15dc779aSAndroid Build Coastguard Worker             ptr_exp_spec + ptr_psy_out->sfb_offsets[i],
1636*15dc779aSAndroid Build Coastguard Worker             ptr_quant_spec + ptr_psy_out->sfb_offsets[i],
1637*15dc779aSAndroid Build Coastguard Worker             ptr_quant_spec_temp + ptr_psy_out->sfb_offsets[i],
1638*15dc779aSAndroid Build Coastguard Worker             ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i], thresh, scf_int,
1639*15dc779aSAndroid Build Coastguard Worker             min_sf_max_quant[i], &ptr_sfb_dist[i], &min_calc_scf[i]);
1640*15dc779aSAndroid Build Coastguard Worker 
1641*15dc779aSAndroid Build Coastguard Worker         ptr_scalefactor[i] = scf_int;
1642*15dc779aSAndroid Build Coastguard Worker       }
1643*15dc779aSAndroid Build Coastguard Worker     }
1644*15dc779aSAndroid Build Coastguard Worker 
1645*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1646*15dc779aSAndroid Build Coastguard Worker       sfb_const_pe_part[i] = MIN_FLT_VAL;
1647*15dc779aSAndroid Build Coastguard Worker     }
1648*15dc779aSAndroid Build Coastguard Worker 
1649*15dc779aSAndroid Build Coastguard Worker     iusace_assimilate_single_scf(ptr_psy_out, ptr_exp_spec, ptr_quant_spec, ptr_quant_spec_temp,
1650*15dc779aSAndroid Build Coastguard Worker                                  ptr_scalefactor, min_sf_max_quant, ptr_sfb_dist,
1651*15dc779aSAndroid Build Coastguard Worker                                  sfb_const_pe_part, p_sfb_form_factor, p_sfb_num_relevant_lines,
1652*15dc779aSAndroid Build Coastguard Worker                                  min_calc_scf, ptr_mdct_spec_float);
1653*15dc779aSAndroid Build Coastguard Worker 
1654*15dc779aSAndroid Build Coastguard Worker     iusace_assimilate_multiple_scf(ptr_psy_out, ptr_exp_spec, ptr_quant_spec, ptr_quant_spec_temp,
1655*15dc779aSAndroid Build Coastguard Worker                                    ptr_scalefactor, min_sf_max_quant, ptr_sfb_dist,
1656*15dc779aSAndroid Build Coastguard Worker                                    sfb_const_pe_part, p_sfb_form_factor, p_sfb_num_relevant_lines,
1657*15dc779aSAndroid Build Coastguard Worker                                    ptr_mdct_spec_float, ptr_scratch);
1658*15dc779aSAndroid Build Coastguard Worker 
1659*15dc779aSAndroid Build Coastguard Worker     max_scf = MIN_SHRT_VAL;
1660*15dc779aSAndroid Build Coastguard Worker     min_scf = MAX_SHRT_VAL;
1661*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1662*15dc779aSAndroid Build Coastguard Worker       if (max_scf < ptr_scalefactor[i]) {
1663*15dc779aSAndroid Build Coastguard Worker         max_scf = ptr_scalefactor[i];
1664*15dc779aSAndroid Build Coastguard Worker       }
1665*15dc779aSAndroid Build Coastguard Worker       if ((ptr_scalefactor[i] != MIN_SHRT_VAL) && (min_scf > ptr_scalefactor[i])) {
1666*15dc779aSAndroid Build Coastguard Worker         min_scf = ptr_scalefactor[i];
1667*15dc779aSAndroid Build Coastguard Worker       }
1668*15dc779aSAndroid Build Coastguard Worker     }
1669*15dc779aSAndroid Build Coastguard Worker 
1670*15dc779aSAndroid Build Coastguard Worker     for (i = 0; i < pstr_psy_out[ch].sfb_count; i++) {
1671*15dc779aSAndroid Build Coastguard Worker       if ((ptr_scalefactor[i] != MIN_SHRT_VAL) &&
1672*15dc779aSAndroid Build Coastguard Worker           (min_scf + MAX_SCF_DELTA) < ptr_scalefactor[i]) {
1673*15dc779aSAndroid Build Coastguard Worker         ptr_scalefactor[i] = min_scf + MAX_SCF_DELTA;
1674*15dc779aSAndroid Build Coastguard Worker 
1675*15dc779aSAndroid Build Coastguard Worker         iusace_calc_sfb_dist(ptr_mdct_spec_float + ptr_psy_out->sfb_offsets[i],
1676*15dc779aSAndroid Build Coastguard Worker                              ptr_exp_spec + ptr_psy_out->sfb_offsets[i],
1677*15dc779aSAndroid Build Coastguard Worker                              ptr_quant_spec + ptr_psy_out->sfb_offsets[i],
1678*15dc779aSAndroid Build Coastguard Worker                              ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i],
1679*15dc779aSAndroid Build Coastguard Worker                              ptr_scalefactor[i]);
1680*15dc779aSAndroid Build Coastguard Worker       }
1681*15dc779aSAndroid Build Coastguard Worker     }
1682*15dc779aSAndroid Build Coastguard Worker 
1683*15dc779aSAndroid Build Coastguard Worker     max_scf = MIN((min_scf + MAX_SCF_DELTA), max_scf);
1684*15dc779aSAndroid Build Coastguard Worker 
1685*15dc779aSAndroid Build Coastguard Worker     if (max_scf > MIN_SHRT_VAL) {
1686*15dc779aSAndroid Build Coastguard Worker       *global_gain = max_scf;
1687*15dc779aSAndroid Build Coastguard Worker       for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1688*15dc779aSAndroid Build Coastguard Worker         if (ptr_scalefactor[i] == MIN_SHRT_VAL) {
1689*15dc779aSAndroid Build Coastguard Worker           ptr_scalefactor[i] = 0;
1690*15dc779aSAndroid Build Coastguard Worker           memset(
1691*15dc779aSAndroid Build Coastguard Worker               &ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i]], 0,
1692*15dc779aSAndroid Build Coastguard Worker               (ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i]) * sizeof(FLOAT64));
1693*15dc779aSAndroid Build Coastguard Worker         } else {
1694*15dc779aSAndroid Build Coastguard Worker           ptr_scalefactor[i] = max_scf - ptr_scalefactor[i];
1695*15dc779aSAndroid Build Coastguard Worker         }
1696*15dc779aSAndroid Build Coastguard Worker       }
1697*15dc779aSAndroid Build Coastguard Worker     } else {
1698*15dc779aSAndroid Build Coastguard Worker       *global_gain = 0;
1699*15dc779aSAndroid Build Coastguard Worker       for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1700*15dc779aSAndroid Build Coastguard Worker         ptr_scalefactor[i] = 0;
1701*15dc779aSAndroid Build Coastguard Worker         memset(&ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i]], 0,
1702*15dc779aSAndroid Build Coastguard Worker                (ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i]) * sizeof(FLOAT64));
1703*15dc779aSAndroid Build Coastguard Worker       }
1704*15dc779aSAndroid Build Coastguard Worker     }
1705*15dc779aSAndroid Build Coastguard Worker     idx++;
1706*15dc779aSAndroid Build Coastguard Worker   }
1707*15dc779aSAndroid Build Coastguard Worker 
1708*15dc779aSAndroid Build Coastguard Worker   return;
1709*15dc779aSAndroid Build Coastguard Worker }
1710