xref: /aosp_15_r20/external/libxaac/decoder/ixheaacd_pns_js_thumb.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
1*15dc779aSAndroid Build Coastguard Worker /******************************************************************************
2*15dc779aSAndroid Build Coastguard Worker  *                                                                            *
3*15dc779aSAndroid Build Coastguard Worker  * Copyright (C) 2018 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 #include <string.h>
21*15dc779aSAndroid Build Coastguard Worker #include <stdio.h>
22*15dc779aSAndroid Build Coastguard Worker #include <stdlib.h>
23*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_sbr_common.h"
24*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_type_def.h"
25*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_constants.h"
26*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_ops32.h"
27*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_ops16.h"
28*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_ops40.h"
29*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_ops.h"
30*15dc779aSAndroid Build Coastguard Worker 
31*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_bitbuffer.h"
32*15dc779aSAndroid Build Coastguard Worker 
33*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_error_codes.h"
34*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_defines.h"
35*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_aac_rom.h"
36*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_common_rom.h"
37*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_basic_funcs.h"
38*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_aac_imdct.h"
39*15dc779aSAndroid Build Coastguard Worker #include "ixheaac_basic_op.h"
40*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_intrinsics.h"
41*15dc779aSAndroid Build Coastguard Worker 
42*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_pulsedata.h"
43*15dc779aSAndroid Build Coastguard Worker 
44*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_pns.h"
45*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_drc_data_struct.h"
46*15dc779aSAndroid Build Coastguard Worker 
47*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_lt_predict.h"
48*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_cnst.h"
49*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_ec_defines.h"
50*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_ec_struct_def.h"
51*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_channelinfo.h"
52*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_drc_dec.h"
53*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_sbrdecoder.h"
54*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_block.h"
55*15dc779aSAndroid Build Coastguard Worker 
56*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_channel.h"
57*15dc779aSAndroid Build Coastguard Worker 
58*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_audioobjtypes.h"
59*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_latmdemux.h"
60*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_aacdec.h"
61*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_tns.h"
62*15dc779aSAndroid Build Coastguard Worker #include "ixheaacd_function_selector.h"
63*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_is_correlation(ia_aac_dec_channel_info_struct * ptr_aac_dec_channel_info,WORD16 pns_band)64*15dc779aSAndroid Build Coastguard Worker static PLATFORM_INLINE WORD16 ixheaacd_is_correlation(
65*15dc779aSAndroid Build Coastguard Worker     ia_aac_dec_channel_info_struct *ptr_aac_dec_channel_info, WORD16 pns_band) {
66*15dc779aSAndroid Build Coastguard Worker   ia_pns_correlation_info_struct *ptr_corr_info =
67*15dc779aSAndroid Build Coastguard Worker       ptr_aac_dec_channel_info->pstr_pns_corr_info;
68*15dc779aSAndroid Build Coastguard Worker 
69*15dc779aSAndroid Build Coastguard Worker   return ((ptr_corr_info->correlated[(pns_band >> PNS_BAND_FLAGS_SHIFT)] >>
70*15dc779aSAndroid Build Coastguard Worker            (pns_band & PNS_BAND_FLAGS_MASK)) &
71*15dc779aSAndroid Build Coastguard Worker           1);
72*15dc779aSAndroid Build Coastguard Worker }
73*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_gen_rand_vec(WORD32 scale,WORD shift,WORD32 * ptr_spec_coef,WORD32 sfb_width,WORD32 * seed)74*15dc779aSAndroid Build Coastguard Worker VOID ixheaacd_gen_rand_vec(WORD32 scale, WORD shift, WORD32 *ptr_spec_coef,
75*15dc779aSAndroid Build Coastguard Worker                            WORD32 sfb_width, WORD32 *seed) {
76*15dc779aSAndroid Build Coastguard Worker   WORD nrg_scale;
77*15dc779aSAndroid Build Coastguard Worker   WORD32 nrg = 0;
78*15dc779aSAndroid Build Coastguard Worker   WORD32 *spec = ptr_spec_coef;
79*15dc779aSAndroid Build Coastguard Worker   WORD32 sfb;
80*15dc779aSAndroid Build Coastguard Worker 
81*15dc779aSAndroid Build Coastguard Worker   for (sfb = 0; sfb <= sfb_width; sfb++) {
82*15dc779aSAndroid Build Coastguard Worker     *seed = (WORD32)(((WORD64)1664525 * (WORD64)(*seed)) + (WORD64)1013904223);
83*15dc779aSAndroid Build Coastguard Worker 
84*15dc779aSAndroid Build Coastguard Worker     *spec = (*seed >> 3);
85*15dc779aSAndroid Build Coastguard Worker 
86*15dc779aSAndroid Build Coastguard Worker     nrg = ixheaac_add32_sat(nrg, ixheaac_mult32_shl_sat(*spec, *spec));
87*15dc779aSAndroid Build Coastguard Worker 
88*15dc779aSAndroid Build Coastguard Worker     spec++;
89*15dc779aSAndroid Build Coastguard Worker   }
90*15dc779aSAndroid Build Coastguard Worker 
91*15dc779aSAndroid Build Coastguard Worker   nrg_scale = ixheaac_norm32(nrg);
92*15dc779aSAndroid Build Coastguard Worker 
93*15dc779aSAndroid Build Coastguard Worker   if (nrg_scale > 0) {
94*15dc779aSAndroid Build Coastguard Worker     nrg_scale &= ~1;
95*15dc779aSAndroid Build Coastguard Worker     nrg = ixheaac_shl32_sat(nrg, nrg_scale);
96*15dc779aSAndroid Build Coastguard Worker     shift = shift - (nrg_scale >> 1);
97*15dc779aSAndroid Build Coastguard Worker   }
98*15dc779aSAndroid Build Coastguard Worker 
99*15dc779aSAndroid Build Coastguard Worker   nrg = ixheaacd_sqrt(nrg);
100*15dc779aSAndroid Build Coastguard Worker   scale = ixheaac_div32_pos_normb(scale, nrg);
101*15dc779aSAndroid Build Coastguard Worker 
102*15dc779aSAndroid Build Coastguard Worker   spec = ptr_spec_coef;
103*15dc779aSAndroid Build Coastguard Worker 
104*15dc779aSAndroid Build Coastguard Worker   if (shift < -31) {
105*15dc779aSAndroid Build Coastguard Worker     shift = -31;
106*15dc779aSAndroid Build Coastguard Worker   }
107*15dc779aSAndroid Build Coastguard Worker   for (sfb = 0; sfb <= sfb_width; sfb++) {
108*15dc779aSAndroid Build Coastguard Worker     *spec = ixheaac_shr32_dir_sat_limit(ixheaac_mult32_shl_sat(*spec, scale),
109*15dc779aSAndroid Build Coastguard Worker                                          shift);
110*15dc779aSAndroid Build Coastguard Worker     spec++;
111*15dc779aSAndroid Build Coastguard Worker   }
112*15dc779aSAndroid Build Coastguard Worker }
113*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_pns_process(ia_aac_dec_channel_info_struct * ptr_aac_dec_channel_info[],WORD32 channel,ia_aac_dec_tables_struct * ptr_aac_tables)114*15dc779aSAndroid Build Coastguard Worker VOID ixheaacd_pns_process(
115*15dc779aSAndroid Build Coastguard Worker     ia_aac_dec_channel_info_struct *ptr_aac_dec_channel_info[], WORD32 channel,
116*15dc779aSAndroid Build Coastguard Worker     ia_aac_dec_tables_struct *ptr_aac_tables) {
117*15dc779aSAndroid Build Coastguard Worker   ia_pns_info_struct *ptr_pns_info =
118*15dc779aSAndroid Build Coastguard Worker       &ptr_aac_dec_channel_info[channel]->str_pns_info;
119*15dc779aSAndroid Build Coastguard Worker   ia_ics_info_struct *ptr_ics_info =
120*15dc779aSAndroid Build Coastguard Worker       &ptr_aac_dec_channel_info[channel]->str_ics_info;
121*15dc779aSAndroid Build Coastguard Worker   WORD16 maximum_bins_short = ptr_ics_info->frame_length >> 3;
122*15dc779aSAndroid Build Coastguard Worker   WORD32 *ptr_scale_mant_tab =
123*15dc779aSAndroid Build Coastguard Worker       ptr_aac_tables->pstr_block_tables->scale_mant_tab;
124*15dc779aSAndroid Build Coastguard Worker 
125*15dc779aSAndroid Build Coastguard Worker   if (ptr_pns_info->pns_active) {
126*15dc779aSAndroid Build Coastguard Worker     const WORD16 *swb_offset =
127*15dc779aSAndroid Build Coastguard Worker         ptr_aac_tables->str_aac_sfb_info[ptr_ics_info->window_sequence]
128*15dc779aSAndroid Build Coastguard Worker             .sfb_index;
129*15dc779aSAndroid Build Coastguard Worker 
130*15dc779aSAndroid Build Coastguard Worker     WORD num_win_group, grp_len, sfb;
131*15dc779aSAndroid Build Coastguard Worker     WORD32 *spec = &ptr_aac_dec_channel_info[channel]->ptr_spec_coeff[0];
132*15dc779aSAndroid Build Coastguard Worker 
133*15dc779aSAndroid Build Coastguard Worker     for (num_win_group = 0; num_win_group < ptr_ics_info->num_window_groups;
134*15dc779aSAndroid Build Coastguard Worker          num_win_group++) {
135*15dc779aSAndroid Build Coastguard Worker       grp_len = ptr_ics_info->window_group_length[num_win_group];
136*15dc779aSAndroid Build Coastguard Worker 
137*15dc779aSAndroid Build Coastguard Worker       for (grp_len = 0;
138*15dc779aSAndroid Build Coastguard Worker            grp_len < ptr_ics_info->window_group_length[num_win_group];
139*15dc779aSAndroid Build Coastguard Worker            grp_len++) {
140*15dc779aSAndroid Build Coastguard Worker         for (sfb = 0; sfb < ptr_ics_info->max_sfb; sfb++) {
141*15dc779aSAndroid Build Coastguard Worker           WORD16 pns_band = ((num_win_group << 4) + sfb);
142*15dc779aSAndroid Build Coastguard Worker 
143*15dc779aSAndroid Build Coastguard Worker           if (ptr_aac_dec_channel_info[channel]
144*15dc779aSAndroid Build Coastguard Worker                   ->str_pns_info.pns_used[pns_band]) {
145*15dc779aSAndroid Build Coastguard Worker             WORD32 scale_mant;
146*15dc779aSAndroid Build Coastguard Worker             WORD32 scale_exp;
147*15dc779aSAndroid Build Coastguard Worker             WORD32 sfb_width = swb_offset[sfb + 1] - swb_offset[sfb] - 1;
148*15dc779aSAndroid Build Coastguard Worker             WORD32 *ptr_spec = &spec[swb_offset[sfb]];
149*15dc779aSAndroid Build Coastguard Worker 
150*15dc779aSAndroid Build Coastguard Worker             scale_mant = ptr_scale_mant_tab[ptr_aac_dec_channel_info[channel]
151*15dc779aSAndroid Build Coastguard Worker                                                 ->ptr_scale_factor[pns_band] &
152*15dc779aSAndroid Build Coastguard Worker                                             PNS_SCALE_MANT_TAB_MASK];
153*15dc779aSAndroid Build Coastguard Worker             scale_exp = add_d(sub_d(31, (ptr_aac_dec_channel_info[channel]
154*15dc779aSAndroid Build Coastguard Worker                                              ->ptr_scale_factor[pns_band] >>
155*15dc779aSAndroid Build Coastguard Worker                                          PNS_SCALEFACTOR_SCALING)),
156*15dc779aSAndroid Build Coastguard Worker                               PNS_SCALE_MANT_TAB_SCALING);
157*15dc779aSAndroid Build Coastguard Worker 
158*15dc779aSAndroid Build Coastguard Worker             if (ixheaacd_is_correlation(ptr_aac_dec_channel_info[LEFT],
159*15dc779aSAndroid Build Coastguard Worker                                         pns_band)) {
160*15dc779aSAndroid Build Coastguard Worker               if (channel == 0) {
161*15dc779aSAndroid Build Coastguard Worker                 ptr_aac_dec_channel_info[LEFT]
162*15dc779aSAndroid Build Coastguard Worker                     ->pstr_pns_corr_info->random_vector[pns_band] =
163*15dc779aSAndroid Build Coastguard Worker                     ptr_aac_dec_channel_info[LEFT]
164*15dc779aSAndroid Build Coastguard Worker                         ->pstr_pns_rand_vec_data->current_seed;
165*15dc779aSAndroid Build Coastguard Worker 
166*15dc779aSAndroid Build Coastguard Worker                 ixheaacd_gen_rand_vec(
167*15dc779aSAndroid Build Coastguard Worker                     scale_mant, scale_exp, ptr_spec, sfb_width,
168*15dc779aSAndroid Build Coastguard Worker                     &(ptr_aac_dec_channel_info[LEFT]
169*15dc779aSAndroid Build Coastguard Worker                           ->pstr_pns_rand_vec_data->current_seed));
170*15dc779aSAndroid Build Coastguard Worker               }
171*15dc779aSAndroid Build Coastguard Worker 
172*15dc779aSAndroid Build Coastguard Worker               else {
173*15dc779aSAndroid Build Coastguard Worker                 ixheaacd_gen_rand_vec(
174*15dc779aSAndroid Build Coastguard Worker                     scale_mant, scale_exp, ptr_spec, sfb_width,
175*15dc779aSAndroid Build Coastguard Worker                     &(ptr_aac_dec_channel_info[LEFT]
176*15dc779aSAndroid Build Coastguard Worker                           ->pstr_pns_corr_info->random_vector[pns_band]));
177*15dc779aSAndroid Build Coastguard Worker               }
178*15dc779aSAndroid Build Coastguard Worker 
179*15dc779aSAndroid Build Coastguard Worker             }
180*15dc779aSAndroid Build Coastguard Worker 
181*15dc779aSAndroid Build Coastguard Worker             else {
182*15dc779aSAndroid Build Coastguard Worker               ixheaacd_gen_rand_vec(
183*15dc779aSAndroid Build Coastguard Worker                   scale_mant, scale_exp, ptr_spec, sfb_width,
184*15dc779aSAndroid Build Coastguard Worker                   &(ptr_aac_dec_channel_info[LEFT]
185*15dc779aSAndroid Build Coastguard Worker                         ->pstr_pns_rand_vec_data->current_seed));
186*15dc779aSAndroid Build Coastguard Worker             }
187*15dc779aSAndroid Build Coastguard Worker           }
188*15dc779aSAndroid Build Coastguard Worker         }
189*15dc779aSAndroid Build Coastguard Worker 
190*15dc779aSAndroid Build Coastguard Worker         if (maximum_bins_short == 120)
191*15dc779aSAndroid Build Coastguard Worker           spec += maximum_bins_short;
192*15dc779aSAndroid Build Coastguard Worker         else
193*15dc779aSAndroid Build Coastguard Worker           spec += 128;
194*15dc779aSAndroid Build Coastguard Worker       }
195*15dc779aSAndroid Build Coastguard Worker     }
196*15dc779aSAndroid Build Coastguard Worker   }
197*15dc779aSAndroid Build Coastguard Worker 
198*15dc779aSAndroid Build Coastguard Worker   if (channel == 0) {
199*15dc779aSAndroid Build Coastguard Worker     ptr_aac_dec_channel_info[0]->pstr_pns_rand_vec_data->pns_frame_number++;
200*15dc779aSAndroid Build Coastguard Worker   }
201*15dc779aSAndroid Build Coastguard Worker }
202*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_tns_decode_coef(const ia_filter_info_struct * filter,WORD16 * parcor_coef,ia_aac_dec_tables_struct * ptr_aac_tables)203*15dc779aSAndroid Build Coastguard Worker VOID ixheaacd_tns_decode_coef(const ia_filter_info_struct *filter,
204*15dc779aSAndroid Build Coastguard Worker                               WORD16 *parcor_coef,
205*15dc779aSAndroid Build Coastguard Worker                               ia_aac_dec_tables_struct *ptr_aac_tables) {
206*15dc779aSAndroid Build Coastguard Worker   WORD order, resolution;
207*15dc779aSAndroid Build Coastguard Worker   WORD16 *ptr_par_coef = parcor_coef;
208*15dc779aSAndroid Build Coastguard Worker   WORD16 *tns_coeff_ptr;
209*15dc779aSAndroid Build Coastguard Worker   WORD8 ixheaacd_drc_offset = 4;
210*15dc779aSAndroid Build Coastguard Worker   WORD8 *ptr_coef = (WORD8 *)filter->coef;
211*15dc779aSAndroid Build Coastguard Worker 
212*15dc779aSAndroid Build Coastguard Worker   resolution = filter->resolution;
213*15dc779aSAndroid Build Coastguard Worker   tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff3_16;
214*15dc779aSAndroid Build Coastguard Worker 
215*15dc779aSAndroid Build Coastguard Worker   if (resolution) {
216*15dc779aSAndroid Build Coastguard Worker     tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff4_16;
217*15dc779aSAndroid Build Coastguard Worker     ixheaacd_drc_offset = ixheaacd_drc_offset << 1;
218*15dc779aSAndroid Build Coastguard Worker   }
219*15dc779aSAndroid Build Coastguard Worker 
220*15dc779aSAndroid Build Coastguard Worker   for (order = 0; order < filter->order; order++) {
221*15dc779aSAndroid Build Coastguard Worker     WORD8 temp = *ptr_coef++;
222*15dc779aSAndroid Build Coastguard Worker     *ptr_par_coef++ = tns_coeff_ptr[temp + ixheaacd_drc_offset];
223*15dc779aSAndroid Build Coastguard Worker   }
224*15dc779aSAndroid Build Coastguard Worker }
225*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_tns_decode_coef_ld(const ia_filter_info_struct * filter,WORD32 * parcor_coef,ia_aac_dec_tables_struct * ptr_aac_tables)226*15dc779aSAndroid Build Coastguard Worker VOID ixheaacd_tns_decode_coef_ld(const ia_filter_info_struct *filter,
227*15dc779aSAndroid Build Coastguard Worker                                  WORD32 *parcor_coef,
228*15dc779aSAndroid Build Coastguard Worker                                  ia_aac_dec_tables_struct *ptr_aac_tables) {
229*15dc779aSAndroid Build Coastguard Worker   WORD order, resolution;
230*15dc779aSAndroid Build Coastguard Worker   WORD32 *ptr_par_coef = parcor_coef;
231*15dc779aSAndroid Build Coastguard Worker   WORD32 *tns_coeff_ptr;
232*15dc779aSAndroid Build Coastguard Worker   WORD8 offset = 4;
233*15dc779aSAndroid Build Coastguard Worker   WORD8 *ptr_coef = (WORD8 *)filter->coef;
234*15dc779aSAndroid Build Coastguard Worker 
235*15dc779aSAndroid Build Coastguard Worker   resolution = filter->resolution;
236*15dc779aSAndroid Build Coastguard Worker   tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff3;
237*15dc779aSAndroid Build Coastguard Worker 
238*15dc779aSAndroid Build Coastguard Worker   if (resolution) {
239*15dc779aSAndroid Build Coastguard Worker     tns_coeff_ptr = ptr_aac_tables->pstr_block_tables->tns_coeff4;
240*15dc779aSAndroid Build Coastguard Worker     offset = offset << 1;
241*15dc779aSAndroid Build Coastguard Worker   }
242*15dc779aSAndroid Build Coastguard Worker 
243*15dc779aSAndroid Build Coastguard Worker   for (order = 0; order < filter->order; order++) {
244*15dc779aSAndroid Build Coastguard Worker     WORD8 temp = *ptr_coef++;
245*15dc779aSAndroid Build Coastguard Worker     *ptr_par_coef++ = tns_coeff_ptr[temp + offset];
246*15dc779aSAndroid Build Coastguard Worker   }
247*15dc779aSAndroid Build Coastguard Worker }
248*15dc779aSAndroid Build Coastguard Worker 
ixheaacd_aac_tns_process(ia_aac_dec_channel_info_struct * ptr_aac_dec_channel_info,WORD32 num_ch,ia_aac_dec_tables_struct * ptr_aac_tables,WORD32 object_type,WORD32 ar_flag,WORD32 * predicted_spectrum)249*15dc779aSAndroid Build Coastguard Worker VOID ixheaacd_aac_tns_process(
250*15dc779aSAndroid Build Coastguard Worker     ia_aac_dec_channel_info_struct *ptr_aac_dec_channel_info, WORD32 num_ch,
251*15dc779aSAndroid Build Coastguard Worker     ia_aac_dec_tables_struct *ptr_aac_tables, WORD32 object_type,
252*15dc779aSAndroid Build Coastguard Worker     WORD32 ar_flag, WORD32 *predicted_spectrum) {
253*15dc779aSAndroid Build Coastguard Worker   WORD i;
254*15dc779aSAndroid Build Coastguard Worker   WORD16 scale_lpc;
255*15dc779aSAndroid Build Coastguard Worker 
256*15dc779aSAndroid Build Coastguard Worker   ia_tns_info_aac_struct *ptr_tns_info =
257*15dc779aSAndroid Build Coastguard Worker       &ptr_aac_dec_channel_info->str_tns_info;
258*15dc779aSAndroid Build Coastguard Worker   WORD32 *spec = ptr_aac_dec_channel_info->ptr_spec_coeff;
259*15dc779aSAndroid Build Coastguard Worker   WORD32 *scratch_buf = ptr_aac_dec_channel_info->scratch_buf_ptr;
260*15dc779aSAndroid Build Coastguard Worker 
261*15dc779aSAndroid Build Coastguard Worker   WORD win, filt, start, stop, size, scale_spec;
262*15dc779aSAndroid Build Coastguard Worker   ia_ics_info_struct *ptr_ics_info = &ptr_aac_dec_channel_info->str_ics_info;
263*15dc779aSAndroid Build Coastguard Worker   WORD num_window, tns_max_bands, win_seq;
264*15dc779aSAndroid Build Coastguard Worker   WORD16 maximum_bins_short = ptr_ics_info->frame_length >> 3;
265*15dc779aSAndroid Build Coastguard Worker   WORD position;
266*15dc779aSAndroid Build Coastguard Worker 
267*15dc779aSAndroid Build Coastguard Worker   WORD32 parcor_coef[MAX_ORDER + 1];
268*15dc779aSAndroid Build Coastguard Worker   WORD16 parcor_coef_16[MAX_ORDER + 1];
269*15dc779aSAndroid Build Coastguard Worker 
270*15dc779aSAndroid Build Coastguard Worker   WORD32 lpc_coef[MAX_ORDER + 1];
271*15dc779aSAndroid Build Coastguard Worker   WORD16 lpc_coef_16[MAX_ORDER + 1];
272*15dc779aSAndroid Build Coastguard Worker 
273*15dc779aSAndroid Build Coastguard Worker   const WORD16 *ptr_sfb_table;
274*15dc779aSAndroid Build Coastguard Worker 
275*15dc779aSAndroid Build Coastguard Worker   WORD16 max_bin_long = ptr_ics_info->frame_length;
276*15dc779aSAndroid Build Coastguard Worker 
277*15dc779aSAndroid Build Coastguard Worker   win_seq = ptr_ics_info->window_sequence == 0
278*15dc779aSAndroid Build Coastguard Worker                 ? 0
279*15dc779aSAndroid Build Coastguard Worker                 : (ptr_ics_info->window_sequence % 2 == 0);
280*15dc779aSAndroid Build Coastguard Worker 
281*15dc779aSAndroid Build Coastguard Worker   if (ar_flag)
282*15dc779aSAndroid Build Coastguard Worker     spec = ptr_aac_dec_channel_info->ptr_spec_coeff;
283*15dc779aSAndroid Build Coastguard Worker   else {
284*15dc779aSAndroid Build Coastguard Worker     spec = predicted_spectrum;
285*15dc779aSAndroid Build Coastguard Worker   }
286*15dc779aSAndroid Build Coastguard Worker 
287*15dc779aSAndroid Build Coastguard Worker   if (object_type == AOT_ER_AAC_ELD || object_type == AOT_ER_AAC_LD ||
288*15dc779aSAndroid Build Coastguard Worker       object_type == AOT_AAC_LTP) {
289*15dc779aSAndroid Build Coastguard Worker     if (512 == ptr_ics_info->frame_length) {
290*15dc779aSAndroid Build Coastguard Worker       tns_max_bands =
291*15dc779aSAndroid Build Coastguard Worker           ptr_aac_tables->pstr_block_tables
292*15dc779aSAndroid Build Coastguard Worker               ->tns_max_bands_tbl_ld[ptr_ics_info->sampling_rate_index];
293*15dc779aSAndroid Build Coastguard Worker       win_seq = 1;
294*15dc779aSAndroid Build Coastguard Worker       num_window = win_seq;
295*15dc779aSAndroid Build Coastguard Worker     } else if (480 == ptr_ics_info->frame_length) {
296*15dc779aSAndroid Build Coastguard Worker       tns_max_bands =
297*15dc779aSAndroid Build Coastguard Worker           ptr_aac_tables->pstr_block_tables
298*15dc779aSAndroid Build Coastguard Worker               ->tns_max_bands_tbl_480[ptr_ics_info->sampling_rate_index];
299*15dc779aSAndroid Build Coastguard Worker       win_seq = 1;
300*15dc779aSAndroid Build Coastguard Worker       num_window = win_seq;
301*15dc779aSAndroid Build Coastguard Worker     } else {
302*15dc779aSAndroid Build Coastguard Worker       tns_max_bands =
303*15dc779aSAndroid Build Coastguard Worker           ptr_aac_tables->pstr_block_tables
304*15dc779aSAndroid Build Coastguard Worker               ->tns_max_bands_tbl[ptr_ics_info->sampling_rate_index][win_seq];
305*15dc779aSAndroid Build Coastguard Worker 
306*15dc779aSAndroid Build Coastguard Worker       num_window = win_seq ? 8 : 1;
307*15dc779aSAndroid Build Coastguard Worker     }
308*15dc779aSAndroid Build Coastguard Worker   } else {
309*15dc779aSAndroid Build Coastguard Worker     tns_max_bands =
310*15dc779aSAndroid Build Coastguard Worker         ptr_aac_tables->pstr_block_tables
311*15dc779aSAndroid Build Coastguard Worker             ->tns_max_bands_tbl[ptr_ics_info->sampling_rate_index][win_seq];
312*15dc779aSAndroid Build Coastguard Worker 
313*15dc779aSAndroid Build Coastguard Worker     num_window = win_seq ? 8 : 1;
314*15dc779aSAndroid Build Coastguard Worker   }
315*15dc779aSAndroid Build Coastguard Worker 
316*15dc779aSAndroid Build Coastguard Worker   ptr_sfb_table =
317*15dc779aSAndroid Build Coastguard Worker       ptr_aac_tables->str_aac_sfb_info[ptr_ics_info->window_sequence].sfb_index;
318*15dc779aSAndroid Build Coastguard Worker 
319*15dc779aSAndroid Build Coastguard Worker   for (win = 0; win < num_window; win++) {
320*15dc779aSAndroid Build Coastguard Worker     WORD n_filt = ptr_tns_info->n_filt[win];
321*15dc779aSAndroid Build Coastguard Worker 
322*15dc779aSAndroid Build Coastguard Worker     for (filt = 0; filt < n_filt; filt++) {
323*15dc779aSAndroid Build Coastguard Worker       ia_filter_info_struct *filter = &ptr_tns_info->str_filter[win][filt];
324*15dc779aSAndroid Build Coastguard Worker 
325*15dc779aSAndroid Build Coastguard Worker       if (filter->order <= 0) {
326*15dc779aSAndroid Build Coastguard Worker         continue;
327*15dc779aSAndroid Build Coastguard Worker       }
328*15dc779aSAndroid Build Coastguard Worker 
329*15dc779aSAndroid Build Coastguard Worker       if ((object_type == AOT_ER_AAC_LD) || (object_type == AOT_AAC_LTP) ||
330*15dc779aSAndroid Build Coastguard Worker           (num_ch > 2)) {
331*15dc779aSAndroid Build Coastguard Worker         ixheaacd_tns_decode_coefficients(filter, parcor_coef, ptr_aac_tables);
332*15dc779aSAndroid Build Coastguard Worker 
333*15dc779aSAndroid Build Coastguard Worker       } else {
334*15dc779aSAndroid Build Coastguard Worker         ixheaacd_tns_decode_coef(filter, parcor_coef_16, ptr_aac_tables);
335*15dc779aSAndroid Build Coastguard Worker       }
336*15dc779aSAndroid Build Coastguard Worker 
337*15dc779aSAndroid Build Coastguard Worker       start = ixheaac_min32(ixheaac_min32(filter->start_band, tns_max_bands),
338*15dc779aSAndroid Build Coastguard Worker                              ptr_ics_info->max_sfb);
339*15dc779aSAndroid Build Coastguard Worker 
340*15dc779aSAndroid Build Coastguard Worker       start = ptr_sfb_table[start];
341*15dc779aSAndroid Build Coastguard Worker 
342*15dc779aSAndroid Build Coastguard Worker       stop = ixheaac_min32(ixheaac_min32(filter->stop_band, tns_max_bands),
343*15dc779aSAndroid Build Coastguard Worker                             ptr_ics_info->max_sfb);
344*15dc779aSAndroid Build Coastguard Worker 
345*15dc779aSAndroid Build Coastguard Worker       stop = ptr_sfb_table[stop];
346*15dc779aSAndroid Build Coastguard Worker 
347*15dc779aSAndroid Build Coastguard Worker       size = (stop - start);
348*15dc779aSAndroid Build Coastguard Worker 
349*15dc779aSAndroid Build Coastguard Worker       if (size <= 0) {
350*15dc779aSAndroid Build Coastguard Worker         continue;
351*15dc779aSAndroid Build Coastguard Worker       }
352*15dc779aSAndroid Build Coastguard Worker       if ((object_type == AOT_ER_AAC_LD) || (object_type == AOT_AAC_LTP) ||
353*15dc779aSAndroid Build Coastguard Worker           (num_ch > 2)) {
354*15dc779aSAndroid Build Coastguard Worker         ixheaacd_tns_parcor_to_lpc(parcor_coef, lpc_coef, &scale_lpc,
355*15dc779aSAndroid Build Coastguard Worker                                    filter->order);
356*15dc779aSAndroid Build Coastguard Worker 
357*15dc779aSAndroid Build Coastguard Worker       } else {
358*15dc779aSAndroid Build Coastguard Worker         (*ixheaacd_tns_parcor_lpc_convert)(parcor_coef_16, lpc_coef_16,
359*15dc779aSAndroid Build Coastguard Worker                                            &scale_lpc, filter->order);
360*15dc779aSAndroid Build Coastguard Worker       }
361*15dc779aSAndroid Build Coastguard Worker 
362*15dc779aSAndroid Build Coastguard Worker       {
363*15dc779aSAndroid Build Coastguard Worker         WORD32 *ptr_tmp;
364*15dc779aSAndroid Build Coastguard Worker 
365*15dc779aSAndroid Build Coastguard Worker         if (maximum_bins_short == 120)
366*15dc779aSAndroid Build Coastguard Worker           ptr_tmp = spec + (win * maximum_bins_short) + start;
367*15dc779aSAndroid Build Coastguard Worker         else
368*15dc779aSAndroid Build Coastguard Worker           ptr_tmp = spec + (win << 7) + start;
369*15dc779aSAndroid Build Coastguard Worker 
370*15dc779aSAndroid Build Coastguard Worker         scale_spec = (*ixheaacd_calc_max_spectral_line)(ptr_tmp, size);
371*15dc779aSAndroid Build Coastguard Worker       }
372*15dc779aSAndroid Build Coastguard Worker 
373*15dc779aSAndroid Build Coastguard Worker       if (filter->direction == -1) {
374*15dc779aSAndroid Build Coastguard Worker         position = stop - 1;
375*15dc779aSAndroid Build Coastguard Worker 
376*15dc779aSAndroid Build Coastguard Worker         if (maximum_bins_short == 120) {
377*15dc779aSAndroid Build Coastguard Worker           if (((win * maximum_bins_short) + position) < filter->order) continue;
378*15dc779aSAndroid Build Coastguard Worker         } else {
379*15dc779aSAndroid Build Coastguard Worker           if (((win << 7) + position) < filter->order) continue;
380*15dc779aSAndroid Build Coastguard Worker         }
381*15dc779aSAndroid Build Coastguard Worker 
382*15dc779aSAndroid Build Coastguard Worker       } else {
383*15dc779aSAndroid Build Coastguard Worker         position = start;
384*15dc779aSAndroid Build Coastguard Worker         if (maximum_bins_short == 120) {
385*15dc779aSAndroid Build Coastguard Worker           if ((((win * maximum_bins_short) + position) + filter->order) > max_bin_long)
386*15dc779aSAndroid Build Coastguard Worker             continue;
387*15dc779aSAndroid Build Coastguard Worker         } else {
388*15dc779aSAndroid Build Coastguard Worker           if ((((win << 7) + position) + filter->order) > MAX_BINS_LONG) continue;
389*15dc779aSAndroid Build Coastguard Worker         }
390*15dc779aSAndroid Build Coastguard Worker       }
391*15dc779aSAndroid Build Coastguard Worker 
392*15dc779aSAndroid Build Coastguard Worker       if ((num_ch <= 2) &&
393*15dc779aSAndroid Build Coastguard Worker           ((object_type != AOT_ER_AAC_LD) && (object_type != AOT_AAC_LTP)))
394*15dc779aSAndroid Build Coastguard Worker         scale_spec = ((scale_spec - 4) - scale_lpc);
395*15dc779aSAndroid Build Coastguard Worker       else {
396*15dc779aSAndroid Build Coastguard Worker         if (scale_spec > 17)
397*15dc779aSAndroid Build Coastguard Worker           scale_spec = ((scale_spec - 6) - scale_lpc);
398*15dc779aSAndroid Build Coastguard Worker         else if (scale_spec > 11)
399*15dc779aSAndroid Build Coastguard Worker           scale_spec = ((scale_spec - 5) - scale_lpc);
400*15dc779aSAndroid Build Coastguard Worker         else
401*15dc779aSAndroid Build Coastguard Worker           scale_spec = ((scale_spec - 4) - scale_lpc);
402*15dc779aSAndroid Build Coastguard Worker       }
403*15dc779aSAndroid Build Coastguard Worker 
404*15dc779aSAndroid Build Coastguard Worker       if (scale_spec > 0) {
405*15dc779aSAndroid Build Coastguard Worker         scale_spec = ixheaac_min32(scale_spec, 31);
406*15dc779aSAndroid Build Coastguard Worker 
407*15dc779aSAndroid Build Coastguard Worker         if ((object_type == AOT_ER_AAC_LD) || (object_type == AOT_AAC_LTP) ||
408*15dc779aSAndroid Build Coastguard Worker             (num_ch > 2)) {
409*15dc779aSAndroid Build Coastguard Worker           if (ar_flag)
410*15dc779aSAndroid Build Coastguard Worker           {
411*15dc779aSAndroid Build Coastguard Worker             if (maximum_bins_short == 120) {
412*15dc779aSAndroid Build Coastguard Worker               (*ixheaacd_tns_ar_filter_fixed)(&spec[(win * maximum_bins_short) + position],
413*15dc779aSAndroid Build Coastguard Worker                                               size, filter->direction,
414*15dc779aSAndroid Build Coastguard Worker                                               (WORD32 *)lpc_coef, filter->order,
415*15dc779aSAndroid Build Coastguard Worker                                               (WORD32)scale_lpc, scale_spec);
416*15dc779aSAndroid Build Coastguard Worker             } else {
417*15dc779aSAndroid Build Coastguard Worker               (*ixheaacd_tns_ar_filter_fixed)(&spec[(win << 7) + position], size,
418*15dc779aSAndroid Build Coastguard Worker                                               filter->direction,
419*15dc779aSAndroid Build Coastguard Worker                                               (WORD32 *)lpc_coef, filter->order,
420*15dc779aSAndroid Build Coastguard Worker                                               (WORD32)scale_lpc, scale_spec);
421*15dc779aSAndroid Build Coastguard Worker             }
422*15dc779aSAndroid Build Coastguard Worker           } else {
423*15dc779aSAndroid Build Coastguard Worker             if (maximum_bins_short == 120) {
424*15dc779aSAndroid Build Coastguard Worker               ixheaacd_tns_ma_filter_fixed_ld(&spec[(win * maximum_bins_short) + position],
425*15dc779aSAndroid Build Coastguard Worker                                               size, filter->direction, lpc_coef,
426*15dc779aSAndroid Build Coastguard Worker                                               filter->order, scale_lpc);
427*15dc779aSAndroid Build Coastguard Worker             } else {
428*15dc779aSAndroid Build Coastguard Worker               ixheaacd_tns_ma_filter_fixed_ld(&spec[(win << 7) + position], size,
429*15dc779aSAndroid Build Coastguard Worker                                               filter->direction, lpc_coef,
430*15dc779aSAndroid Build Coastguard Worker                                               filter->order, scale_lpc);
431*15dc779aSAndroid Build Coastguard Worker             }
432*15dc779aSAndroid Build Coastguard Worker           }
433*15dc779aSAndroid Build Coastguard Worker         } else {
434*15dc779aSAndroid Build Coastguard Worker           if (object_type == AOT_ER_AAC_ELD) scale_spec = scale_spec - 1;
435*15dc779aSAndroid Build Coastguard Worker           if (maximum_bins_short == 120) {
436*15dc779aSAndroid Build Coastguard Worker             (*ixheaacd_tns_ar_filter)(&spec[(win * maximum_bins_short) + position], size,
437*15dc779aSAndroid Build Coastguard Worker                                       filter->direction, lpc_coef_16,
438*15dc779aSAndroid Build Coastguard Worker                                       filter->order, (WORD32)scale_lpc,
439*15dc779aSAndroid Build Coastguard Worker                                       scale_spec, scratch_buf);
440*15dc779aSAndroid Build Coastguard Worker           } else {
441*15dc779aSAndroid Build Coastguard Worker             (*ixheaacd_tns_ar_filter)(&spec[(win << 7) + position], size,
442*15dc779aSAndroid Build Coastguard Worker                                       filter->direction, lpc_coef_16,
443*15dc779aSAndroid Build Coastguard Worker                                       filter->order, (WORD32)scale_lpc,
444*15dc779aSAndroid Build Coastguard Worker                                       scale_spec, scratch_buf);
445*15dc779aSAndroid Build Coastguard Worker           }
446*15dc779aSAndroid Build Coastguard Worker         }
447*15dc779aSAndroid Build Coastguard Worker       }
448*15dc779aSAndroid Build Coastguard Worker 
449*15dc779aSAndroid Build Coastguard Worker       else {
450*15dc779aSAndroid Build Coastguard Worker         WORD32 *ptr_tmp;
451*15dc779aSAndroid Build Coastguard Worker 
452*15dc779aSAndroid Build Coastguard Worker         if (maximum_bins_short == 120)
453*15dc779aSAndroid Build Coastguard Worker           ptr_tmp = spec + (win * maximum_bins_short) + start;
454*15dc779aSAndroid Build Coastguard Worker         else
455*15dc779aSAndroid Build Coastguard Worker           ptr_tmp = spec + (win >> 7) + start;
456*15dc779aSAndroid Build Coastguard Worker 
457*15dc779aSAndroid Build Coastguard Worker         scale_spec = -scale_spec;
458*15dc779aSAndroid Build Coastguard Worker         scale_spec = ixheaac_min32(scale_spec, 31);
459*15dc779aSAndroid Build Coastguard Worker 
460*15dc779aSAndroid Build Coastguard Worker         for (i = size; i != 0; i--) {
461*15dc779aSAndroid Build Coastguard Worker           *ptr_tmp = (*ptr_tmp >> scale_spec);
462*15dc779aSAndroid Build Coastguard Worker           ptr_tmp++;
463*15dc779aSAndroid Build Coastguard Worker         }
464*15dc779aSAndroid Build Coastguard Worker 
465*15dc779aSAndroid Build Coastguard Worker         if ((object_type == AOT_ER_AAC_LD) || (object_type == AOT_AAC_LTP) ||
466*15dc779aSAndroid Build Coastguard Worker             num_ch > 2) {
467*15dc779aSAndroid Build Coastguard Worker           if (ar_flag) {
468*15dc779aSAndroid Build Coastguard Worker             if (maximum_bins_short == 120) {
469*15dc779aSAndroid Build Coastguard Worker               (*ixheaacd_tns_ar_filter_fixed)(
470*15dc779aSAndroid Build Coastguard Worker                   &spec[(win * maximum_bins_short) + position], size, filter->direction,
471*15dc779aSAndroid Build Coastguard Worker                   (WORD32 *)lpc_coef, filter->order, scale_lpc, 0);
472*15dc779aSAndroid Build Coastguard Worker             } else {
473*15dc779aSAndroid Build Coastguard Worker               (*ixheaacd_tns_ar_filter_fixed)(
474*15dc779aSAndroid Build Coastguard Worker                   &spec[(win << 7) + position], size, filter->direction,
475*15dc779aSAndroid Build Coastguard Worker                   (WORD32 *)lpc_coef, filter->order, scale_lpc, 0);
476*15dc779aSAndroid Build Coastguard Worker             }
477*15dc779aSAndroid Build Coastguard Worker           } else {
478*15dc779aSAndroid Build Coastguard Worker             if (maximum_bins_short == 120) {
479*15dc779aSAndroid Build Coastguard Worker               ixheaacd_tns_ma_filter_fixed_ld(&spec[(win * maximum_bins_short) + position],
480*15dc779aSAndroid Build Coastguard Worker                                               size, filter->direction, lpc_coef,
481*15dc779aSAndroid Build Coastguard Worker                                               filter->order, scale_lpc);
482*15dc779aSAndroid Build Coastguard Worker             } else {
483*15dc779aSAndroid Build Coastguard Worker               ixheaacd_tns_ma_filter_fixed_ld(&spec[(win << 7) + position], size,
484*15dc779aSAndroid Build Coastguard Worker                                               filter->direction, lpc_coef,
485*15dc779aSAndroid Build Coastguard Worker                                               filter->order, scale_lpc);
486*15dc779aSAndroid Build Coastguard Worker             }
487*15dc779aSAndroid Build Coastguard Worker           }
488*15dc779aSAndroid Build Coastguard Worker         } else {
489*15dc779aSAndroid Build Coastguard Worker           if (object_type == AOT_ER_AAC_ELD) {
490*15dc779aSAndroid Build Coastguard Worker             scale_lpc = scale_lpc - 1;
491*15dc779aSAndroid Build Coastguard Worker           }
492*15dc779aSAndroid Build Coastguard Worker 
493*15dc779aSAndroid Build Coastguard Worker           if (maximum_bins_short == 120) {
494*15dc779aSAndroid Build Coastguard Worker             (*ixheaacd_tns_ar_filter)(&spec[(win * maximum_bins_short) + position], size,
495*15dc779aSAndroid Build Coastguard Worker                                       filter->direction, lpc_coef_16,
496*15dc779aSAndroid Build Coastguard Worker                                       filter->order, scale_lpc, 0, scratch_buf);
497*15dc779aSAndroid Build Coastguard Worker           } else {
498*15dc779aSAndroid Build Coastguard Worker             (*ixheaacd_tns_ar_filter)(&spec[(win << 7) + position], size,
499*15dc779aSAndroid Build Coastguard Worker                                       filter->direction, lpc_coef_16,
500*15dc779aSAndroid Build Coastguard Worker                                       filter->order, scale_lpc, 0, scratch_buf);
501*15dc779aSAndroid Build Coastguard Worker           }
502*15dc779aSAndroid Build Coastguard Worker         }
503*15dc779aSAndroid Build Coastguard Worker 
504*15dc779aSAndroid Build Coastguard Worker         if (maximum_bins_short == 120)
505*15dc779aSAndroid Build Coastguard Worker           ptr_tmp = spec + (win * maximum_bins_short) + start;
506*15dc779aSAndroid Build Coastguard Worker         else
507*15dc779aSAndroid Build Coastguard Worker           ptr_tmp = spec + (win << 7) + start;
508*15dc779aSAndroid Build Coastguard Worker 
509*15dc779aSAndroid Build Coastguard Worker         for (i = size; i != 0; i--) {
510*15dc779aSAndroid Build Coastguard Worker           *ptr_tmp = (*ptr_tmp << scale_spec);
511*15dc779aSAndroid Build Coastguard Worker           ptr_tmp++;
512*15dc779aSAndroid Build Coastguard Worker         }
513*15dc779aSAndroid Build Coastguard Worker       }
514*15dc779aSAndroid Build Coastguard Worker     }
515*15dc779aSAndroid Build Coastguard Worker   }
516*15dc779aSAndroid Build Coastguard Worker }