1 /******************************************************************************
2 *
3 * Copyright (C) 2023 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #include "ixheaac_type_def.h"
21 #include "ixheaac_constants.h"
22 #include "ixheaacd_cnst.h"
23 #include "ixheaac_basic_ops32.h"
24 #include "ixheaac_basic_ops16.h"
25 #include "ixheaacd_bitbuffer.h"
26 #include "ixheaacd_mps_aac_struct.h"
27 #include "ixheaacd_mps_res_rom.h"
28 #include "ixheaacd_mps_res_channelinfo.h"
29 #include "ixheaacd_mps_res_tns.h"
30
ixheaacd_res_get_maximum_tns_bands(ia_mps_dec_residual_ics_info_struct * p_ics_info,ia_mps_dec_residual_aac_tables_struct * aac_tables_ptr,WORD32 * win_len)31 static PLATFORM_INLINE WORD16 ixheaacd_res_get_maximum_tns_bands(
32 ia_mps_dec_residual_ics_info_struct *p_ics_info,
33 ia_mps_dec_residual_aac_tables_struct *aac_tables_ptr, WORD32 *win_len) {
34 WORD32 i = 0;
35 *win_len = 1;
36
37 if (p_ics_info->window_sequence == EIGHT_SHORT_SEQUENCE) {
38 *win_len = 8;
39 i = 1;
40 }
41
42 return aac_tables_ptr->res_block_tables_ptr
43 ->tns_max_bands_tbl[p_ics_info->sampling_rate_index][i];
44 }
45
ixheaacd_res_tns_decode_coeffs_32x16(const ia_mps_dec_residual_filter_struct * filter,WORD16 * a,ia_mps_dec_residual_aac_tables_struct * aac_tables_ptr)46 VOID ixheaacd_res_tns_decode_coeffs_32x16(const ia_mps_dec_residual_filter_struct *filter,
47 WORD16 *a,
48 ia_mps_dec_residual_aac_tables_struct *aac_tables_ptr) {
49 WORD tmp;
50 WORD16 *aptr = a;
51 WORD16 *tns_coeff_ptr;
52 WORD8 offset = 4;
53 WORD8 *p_coeff = (WORD8 *)&filter->coeff[0];
54 WORD32 tmp1;
55
56 tmp = filter->resolution;
57 tns_coeff_ptr = aac_tables_ptr->res_block_tables_ptr->tns_coeff3_16;
58 if (tmp) {
59 tns_coeff_ptr = aac_tables_ptr->res_block_tables_ptr->tns_coeff4_16;
60 offset = offset << 1;
61 }
62 tmp1 = filter->order;
63 do {
64 WORD8 temp = *p_coeff++;
65 *aptr++ = tns_coeff_ptr[temp + offset];
66 tmp1--;
67 } while (tmp1 != 0);
68 }
69
ixheaacd_res_ctns_apply(ia_mps_dec_residual_channel_info_struct * p_aac_decoder_channel_info,WORD16 max_sfb,ia_mps_dec_residual_aac_tables_struct * aac_tables_ptr)70 VOID ixheaacd_res_ctns_apply(ia_mps_dec_residual_channel_info_struct *p_aac_decoder_channel_info,
71 WORD16 max_sfb,
72 ia_mps_dec_residual_aac_tables_struct *aac_tables_ptr) {
73 WORD i;
74 WORD16 scale_lpc;
75
76 ia_mps_dec_residual_tns_data *p_tns_data = &p_aac_decoder_channel_info->tns_data;
77 WORD32 *p_spectrum = p_aac_decoder_channel_info->p_spectral_coefficient;
78
79 WORD window, index, start, stop, size, scale_spec;
80 ia_mps_dec_residual_ics_info_struct *p_ics_info = &p_aac_decoder_channel_info->ics_info;
81 WORD win_len, tns_max_bands;
82 WORD16 maximum_bins_short = ixheaac_shr16_dir_sat(p_ics_info->frame_length, 3);
83
84 WORD32 coeff_parc[MAX_ORDER + 1];
85 WORD32 lpc[MAX_ORDER + 1];
86
87 const WORD16 *scale_factor_bands_tbl;
88
89 if (!p_tns_data->tns_data_present) return;
90
91 tns_max_bands = ixheaacd_res_get_maximum_tns_bands(p_ics_info, aac_tables_ptr, &win_len);
92
93 scale_factor_bands_tbl =
94 ixheaacd_res_get_sfb_offsets(&p_aac_decoder_channel_info->ics_info, aac_tables_ptr);
95
96 for (window = 0; window < win_len; window++) {
97 WORD ind_len = p_tns_data->number_of_filters[window];
98
99 for (index = 0; index < ind_len; index++) {
100 ia_mps_dec_residual_filter_struct *filter = &p_tns_data->filter[window][index];
101
102 if (filter->order <= 0 || filter->order > MAX_ORDER_LONG) continue;
103
104 ixheaacd_res_tns_decode_coeffs_32x16(filter, (WORD16 *)coeff_parc, aac_tables_ptr);
105
106 start = ixheaac_min32(ixheaac_min32(filter->start_band, tns_max_bands), max_sfb);
107
108 start = scale_factor_bands_tbl[start];
109
110 stop = ixheaac_min32(ixheaac_min32(filter->stop_band, tns_max_bands), max_sfb);
111
112 stop = scale_factor_bands_tbl[stop];
113
114 size = (stop - start);
115 if (size <= 0) continue;
116
117 ixheaacd_res_tns_parcor_2_lpc_32x16((WORD16 *)coeff_parc, (WORD16 *)lpc, &scale_lpc,
118 filter->order);
119 {
120 WORD32 *p_tmp = p_spectrum + (window * maximum_bins_short) + start;
121 scale_spec = ixheaacd_res_calc_max_spectral_line(p_tmp, size);
122 }
123
124 scale_spec = ((scale_spec - 4) - scale_lpc);
125
126 if (scale_spec > 0) {
127 WORD shift;
128
129 scale_spec = ixheaac_min32(scale_spec, 31);
130
131 if (filter->direction == -1)
132 shift = stop - 1;
133 else
134 shift = start;
135
136 ixheaacd_res_tns_ar_filter_fixed_32x16(&p_spectrum[(window * maximum_bins_short) + shift],
137 size, filter->direction, (WORD16 *)lpc,
138 filter->order, (WORD32)scale_lpc, scale_spec);
139 } else {
140 WORD shift;
141 WORD32 *p_tmp = p_spectrum + (window * maximum_bins_short) + start;
142
143 scale_spec = -scale_spec;
144 scale_spec = ixheaac_min32(scale_spec, 31);
145
146 for (i = size; i != 0; i--) {
147 *p_tmp = (*p_tmp >> scale_spec);
148 p_tmp++;
149 }
150
151 if (filter->direction == -1)
152 shift = stop - 1;
153 else
154 shift = start;
155
156 {
157 WORD32 shift_val = scale_lpc;
158
159 ixheaacd_res_tns_ar_filter_fixed_32x16(
160 &p_spectrum[(window * maximum_bins_short) + shift], size, filter->direction,
161 (WORD16 *)lpc, filter->order, shift_val, 0);
162 }
163 {
164 p_tmp = p_spectrum + (window * maximum_bins_short) + start;
165 i = size;
166 do {
167 *p_tmp = (*p_tmp << scale_spec);
168 p_tmp++;
169 i--;
170 } while (i != 0);
171 }
172 }
173 }
174 }
175 }
176