/src/libxaac/decoder/ixheaacd_multichannel.c
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * * |
3 | | * Copyright (C) 2018 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 <string.h> |
21 | | |
22 | | #include "ixheaac_type_def.h" |
23 | | #include "ixheaacd_sbr_common.h" |
24 | | |
25 | | #include "ixheaac_constants.h" |
26 | | #include "ixheaac_basic_ops32.h" |
27 | | #include "ixheaac_basic_ops16.h" |
28 | | #include "ixheaac_basic_ops40.h" |
29 | | #include "ixheaac_basic_ops.h" |
30 | | |
31 | | #include "ixheaacd_bitbuffer.h" |
32 | | |
33 | | #include "ixheaacd_audioobjtypes.h" |
34 | | #include "ixheaacd_sbrdecsettings.h" |
35 | | #include "ixheaacd_memory_standards.h" |
36 | | #include "ixheaacd_error_codes.h" |
37 | | |
38 | | #include "ixheaacd_defines.h" |
39 | | #include "ixheaacd_aac_rom.h" |
40 | | #include "ixheaacd_pns.h" |
41 | | |
42 | | #include "ixheaacd_pulsedata.h" |
43 | | #include "ixheaacd_drc_data_struct.h" |
44 | | |
45 | | #include "ixheaacd_lt_predict.h" |
46 | | #include "ixheaacd_cnst.h" |
47 | | #include "ixheaacd_ec_defines.h" |
48 | | #include "ixheaacd_ec_struct_def.h" |
49 | | #include "ixheaacd_channelinfo.h" |
50 | | #include "ixheaacd_drc_dec.h" |
51 | | |
52 | | #include "ixheaacd_sbrdecoder.h" |
53 | | #include "ixheaacd_sbr_scale.h" |
54 | | #include "ixheaacd_lpp_tran.h" |
55 | | #include "ixheaacd_env_extr_part.h" |
56 | | #include "ixheaacd_sbr_rom.h" |
57 | | |
58 | | #include "ixheaacd_hybrid.h" |
59 | | #include "ixheaacd_ps_dec.h" |
60 | | #include "ixheaacd_ps_bitdec.h" |
61 | | |
62 | | #include "ixheaacd_pulsedata.h" |
63 | | |
64 | | #include "ixheaacd_pns.h" |
65 | | |
66 | | #include "ixheaacd_env_extr.h" |
67 | | #include "ixheaacd_common_rom.h" |
68 | | #include "ixheaacd_block.h" |
69 | | #include "ixheaacd_channel.h" |
70 | | #include "ixheaacd_audioobjtypes.h" |
71 | | #include "ixheaacd_latmdemux.h" |
72 | | #include "ixheaacd_aacdec.h" |
73 | | #include "ixheaacd_config.h" |
74 | | #include "ixheaacd_hybrid.h" |
75 | | #include "ixheaacd_ps_dec.h" |
76 | | #include "ixheaacd_qmf_dec.h" |
77 | | #include "ixheaacd_mps_polyphase.h" |
78 | | #include "ixheaacd_mps_macro_def.h" |
79 | | #include "ixheaacd_mps_struct_def.h" |
80 | | #include "ixheaacd_mps_res_rom.h" |
81 | | #include "ixheaacd_mps_aac_struct.h" |
82 | | #include "ixheaacd_mps_dec.h" |
83 | | #include "ixheaacd_mps_interface.h" |
84 | | #include "ixheaacd_struct_def.h" |
85 | | #include "ixheaacd_headerdecode.h" |
86 | | |
87 | | #include "ixheaacd_multichannel.h" |
88 | | #include "ixheaac_basic_op.h" |
89 | | |
90 | | WORD cblock_decode_huff_symbol(UWORD8 *ptr_read_next, WORD32 bit_pos, |
91 | | const UWORD16 *huff_ori, WORD16 *input, |
92 | | WORD32 *readword) |
93 | | |
94 | 0 | { |
95 | 0 | const UWORD16 *h; |
96 | 0 | WORD tot_bits; |
97 | 0 | { |
98 | 0 | UWORD16 first_offset; |
99 | 0 | WORD16 sign_ret_val; |
100 | 0 | UWORD32 read_word1; |
101 | |
|
102 | 0 | read_word1 = *readword << bit_pos; |
103 | |
|
104 | 0 | h = (UWORD16 *)(huff_ori); |
105 | 0 | first_offset = 7; |
106 | |
|
107 | 0 | h += (read_word1) >> (32 - first_offset); |
108 | 0 | sign_ret_val = *h; |
109 | 0 | tot_bits = 0; |
110 | |
|
111 | 0 | while (sign_ret_val > 0) { |
112 | 0 | tot_bits += first_offset; |
113 | 0 | bit_pos += first_offset; |
114 | |
|
115 | 0 | if ((bit_pos -= 8) >= 0) { |
116 | 0 | *readword = (*readword << 8) | *ptr_read_next; |
117 | 0 | ptr_read_next++; |
118 | 0 | } else { |
119 | 0 | bit_pos += 8; |
120 | 0 | } |
121 | |
|
122 | 0 | read_word1 = (read_word1) << (first_offset); |
123 | |
|
124 | 0 | first_offset = (sign_ret_val >> 11); |
125 | 0 | h += sign_ret_val & (0x07FF); |
126 | |
|
127 | 0 | h += (read_word1) >> (32 - first_offset); |
128 | 0 | sign_ret_val = *h; |
129 | 0 | } |
130 | |
|
131 | 0 | tot_bits += ((sign_ret_val & 0x7fff) >> 11); |
132 | 0 | bit_pos += ((sign_ret_val & 0x7fff) >> 11); |
133 | 0 | if ((bit_pos - 8) >= 0) { |
134 | 0 | *readword = (*readword << 8) | *ptr_read_next; |
135 | 0 | } |
136 | |
|
137 | 0 | *input = (sign_ret_val & (0x07FF)) - 60; |
138 | 0 | } |
139 | |
|
140 | 0 | return tot_bits; |
141 | 0 | } |
142 | | |
143 | | IA_ERRORCODE ixheaacd_dec_coupling_channel_element( |
144 | | ia_bit_buf_struct *it_bit_buf, ia_aac_decoder_struct *aac_handle, |
145 | | WORD32 samp_rate_idx, ia_aac_dec_tables_struct *ptr_aac_tables, |
146 | | ixheaacd_misc_tables *common_tables_ptr, WORD *element_index_order, |
147 | | ia_enhaacplus_dec_ind_cc *ind_channel_info, WORD32 total_channels, |
148 | | WORD32 frame_size, WORD32 audio_object_type, |
149 | 970 | ia_eld_specific_config_struct eld_specific_config, WORD32 ele_type) { |
150 | 970 | WORD32 element_instance_tag; |
151 | 970 | LOOPIDX c; |
152 | | |
153 | 970 | WORD ind_sw_cce_flag, num_coupled_elements; |
154 | | |
155 | 970 | WORD num_gain_element_lists = 0; |
156 | 970 | WORD gain_element_scale; |
157 | | |
158 | 970 | const UWORD16 *hcod_sf = |
159 | 970 | ptr_aac_tables->pstr_huffmann_tables->huffman_code_book_scl; |
160 | 970 | const UWORD32 *table_idx = |
161 | 970 | ptr_aac_tables->pstr_huffmann_tables->huffman_code_book_scl_index; |
162 | 970 | WORD16 index, length; |
163 | | |
164 | 970 | IA_ERRORCODE error_status = IA_NO_ERROR; |
165 | | |
166 | 970 | element_instance_tag = ixheaacd_read_bits_buf(it_bit_buf, 4); |
167 | 970 | element_index_order[0] = element_instance_tag; |
168 | | |
169 | 970 | ind_sw_cce_flag = ixheaacd_read_bits_buf(it_bit_buf, 1); |
170 | 970 | num_coupled_elements = ixheaacd_read_bits_buf(it_bit_buf, 3); |
171 | | |
172 | 10.5k | for (c = 0; c < MAX_BS_ELEMENT; c++) |
173 | 9.58k | ind_channel_info->elements_coupled[c] = -1; |
174 | | |
175 | 970 | ind_channel_info->num_coupled_elements = num_coupled_elements; |
176 | | |
177 | 4.95k | for (c = 0; c < (num_coupled_elements + 1); c++) { |
178 | 3.98k | num_gain_element_lists++; |
179 | | |
180 | 3.98k | ind_channel_info->cc_target_is_cpe[c] = ixheaacd_read_bits_buf(it_bit_buf, 1); |
181 | 3.98k | ind_channel_info->cc_target_tag_select[c] = ixheaacd_read_bits_buf(it_bit_buf, 4); |
182 | 3.98k | if (ind_channel_info->cc_target_is_cpe[c]) { |
183 | 1.53k | ind_channel_info->cc_l[c] = ixheaacd_read_bits_buf(it_bit_buf, 1); |
184 | 1.53k | ind_channel_info->cc_r[c] = ixheaacd_read_bits_buf(it_bit_buf, 1); |
185 | 1.53k | if (ind_channel_info->cc_l[c] && ind_channel_info->cc_r[c]) |
186 | 620 | num_gain_element_lists++; |
187 | 1.53k | ind_channel_info->elements_coupled[c] = 1; |
188 | 1.53k | } else |
189 | 2.44k | ind_channel_info->elements_coupled[c] = 0; |
190 | 3.98k | } |
191 | 970 | if ((ind_sw_cce_flag == 0) && (num_gain_element_lists > MAX_BS_ELEMENT)) { |
192 | 2 | return IA_FATAL_ERROR; |
193 | 2 | } |
194 | 968 | ixheaacd_read_bits_buf(it_bit_buf, 1);/*cc_domain*/ |
195 | 968 | ixheaacd_read_bits_buf(it_bit_buf, 1);/*gain_element_sign*/ |
196 | 968 | gain_element_scale = ixheaacd_read_bits_buf(it_bit_buf, 2); |
197 | | |
198 | 968 | aac_handle->pstr_aac_dec_ch_info[0]->str_ics_info.num_swb_window = 0; |
199 | 968 | aac_handle->pstr_aac_dec_ch_info[0]->str_ics_info.sampling_rate_index = |
200 | 968 | samp_rate_idx; |
201 | | |
202 | 968 | aac_handle->pstr_aac_dec_ch_info[0]->common_window = 0; |
203 | | |
204 | 968 | error_status = ixheaacd_individual_ch_stream( |
205 | 968 | it_bit_buf, aac_handle, 1, frame_size, total_channels, audio_object_type, |
206 | 968 | eld_specific_config, ele_type); |
207 | | |
208 | 968 | if (error_status) return error_status; |
209 | | |
210 | 938 | ind_channel_info->cc_gain[0] = 1 << 29; |
211 | 4.42k | for (c = 1; c < num_gain_element_lists; c++) { |
212 | 3.49k | WORD cge; |
213 | 3.49k | WORD common_gain_element_present[MAX_BS_ELEMENT]; |
214 | 3.49k | WORD16 norm_value; |
215 | | |
216 | 3.49k | if (ind_sw_cce_flag) |
217 | 3.48k | cge = 1; |
218 | 9 | else { |
219 | 9 | common_gain_element_present[c] = ixheaacd_read_bits_buf(it_bit_buf, 1); |
220 | 9 | cge = common_gain_element_present[c]; |
221 | 9 | return IA_XHEAAC_DEC_EXE_FATAL_UNIMPLEMENTED_CCE; |
222 | 9 | } |
223 | 3.48k | if (cge) { |
224 | 3.48k | UWORD8 *ptr_read_next = it_bit_buf->ptr_read_next; |
225 | 3.48k | WORD32 bit_pos = 7 - it_bit_buf->bit_pos; |
226 | 3.48k | WORD32 read_word = |
227 | 3.48k | ixheaacd_aac_showbits_32(it_bit_buf->ptr_read_next, it_bit_buf->cnt_bits, NULL); |
228 | 3.48k | UWORD32 read_word1; |
229 | | |
230 | 3.48k | read_word1 = read_word << bit_pos; |
231 | 3.48k | ixheaacd_huffman_decode(read_word1, &index, &length, hcod_sf, table_idx); |
232 | | |
233 | 3.48k | bit_pos += length; |
234 | | |
235 | 3.48k | ixheaacd_aac_read_byte(&ptr_read_next, &bit_pos, &read_word); |
236 | 3.64k | while (bit_pos > 8) |
237 | 154 | ixheaacd_aac_read_byte(&ptr_read_next, &bit_pos, &read_word); |
238 | | |
239 | 3.48k | it_bit_buf->ptr_read_next = ptr_read_next; |
240 | 3.48k | it_bit_buf->bit_pos = 7 - bit_pos; |
241 | 3.48k | it_bit_buf->cnt_bits -= length; |
242 | | |
243 | 3.48k | norm_value = index - 60; |
244 | 3.48k | if (norm_value == -1) |
245 | 68 | ind_channel_info->cc_gain[c] = |
246 | 68 | common_tables_ptr->cc_gain_scale[gain_element_scale]; |
247 | 3.41k | else { |
248 | 3.41k | int i; |
249 | 3.41k | ind_channel_info->cc_gain[c] = |
250 | 3.41k | common_tables_ptr->cc_gain_scale[gain_element_scale]; |
251 | 8.57k | for (i = 0; i < (-norm_value) - 1; i++) { |
252 | 5.15k | ind_channel_info->cc_gain[c] = ixheaac_mul32_sh( |
253 | 5.15k | ind_channel_info->cc_gain[c], |
254 | 5.15k | common_tables_ptr->cc_gain_scale[gain_element_scale], 29); |
255 | 5.15k | } |
256 | 3.41k | } |
257 | 3.48k | } else { |
258 | 0 | return IA_XHEAAC_DEC_EXE_FATAL_UNIMPLEMENTED_CCE; |
259 | 0 | } |
260 | 3.48k | } |
261 | 929 | if (it_bit_buf->cnt_bits < 0) { |
262 | 18 | return IA_XHEAAC_DEC_EXE_NONFATAL_INSUFFICIENT_INPUT_BYTES; |
263 | 18 | } |
264 | 911 | return error_status; |
265 | 929 | } |
266 | | |
267 | | void ixheaacd_dec_couple_channel(WORD32 *p_time_data, WORD32 *out_samp_cc, |
268 | | WORD16 frame_size, WORD total_channels, |
269 | | WORD16 gain_cc) |
270 | | |
271 | 408 | { |
272 | 408 | WORD i; |
273 | 408 | WORD32 out_cc; |
274 | 408 | WORD32 *ptr_out_samp = &out_samp_cc[0]; |
275 | 360k | for (i = frame_size - 1; i >= 0; i--) { |
276 | 359k | out_cc = (ixheaac_shl32_sat( |
277 | 359k | ixheaac_mult32x16in32(*ptr_out_samp++, gain_cc), 3)); |
278 | 359k | *p_time_data = ixheaac_add32_sat(out_cc, *p_time_data); |
279 | 359k | p_time_data += total_channels; |
280 | 359k | } |
281 | 408 | } |
282 | | |
283 | | IA_ERRORCODE ixheaacd_dec_ind_coupling( |
284 | | ia_exhaacplus_dec_api_struct *p_obj_exhaacplus_dec, WORD32 *coup_ch_output, |
285 | | WORD16 frame_size, WORD total_channels, VOID *ptr_time_data_tmp) |
286 | | |
287 | 295 | { |
288 | 295 | WORD c, j, k; |
289 | 295 | WORD l; |
290 | 295 | WORD32 *out_samp_cc, err = 0; |
291 | | |
292 | 295 | ia_enhaacplus_dec_ind_cc *ind_channel_info; |
293 | | |
294 | 295 | WORD32 *ptr_time_data = (WORD32 *)ptr_time_data_tmp; |
295 | | |
296 | 295 | { |
297 | 295 | ind_channel_info = &p_obj_exhaacplus_dec->p_state_aac->ind_cc_info; |
298 | | |
299 | 295 | out_samp_cc = coup_ch_output; |
300 | | |
301 | 295 | if (ind_channel_info->num_coupled_elements > 0 && coup_ch_output == NULL) { |
302 | 22 | if (p_obj_exhaacplus_dec->p_state_aac->ec_enable) { |
303 | 0 | ind_channel_info->num_coupled_elements = 0; |
304 | 0 | p_obj_exhaacplus_dec->aac_config.frame_status = 0; |
305 | 22 | } else { |
306 | 22 | return IA_FATAL_ERROR; |
307 | 22 | } |
308 | 22 | } |
309 | | |
310 | 273 | j = 0; |
311 | 1.36k | for (c = 0; c < ind_channel_info->num_coupled_elements + 1; c++) { |
312 | 9.12k | for (l = 0; l < MAX_BS_ELEMENT; l++) { |
313 | 8.39k | if (p_obj_exhaacplus_dec->aac_config.element_type[l] == |
314 | 8.39k | ind_channel_info->elements_coupled[c] && |
315 | 1.72k | p_obj_exhaacplus_dec->aac_config.element_instance_order[l] == |
316 | 1.72k | ind_channel_info->cc_target_tag_select[c]) { |
317 | 364 | break; |
318 | 364 | } |
319 | 8.39k | } |
320 | 1.09k | if (l == MAX_BS_ELEMENT) { |
321 | 726 | continue; |
322 | 726 | } |
323 | | |
324 | 364 | k = p_obj_exhaacplus_dec->aac_config.slot_element[l]; |
325 | | |
326 | 364 | if (ind_channel_info->cc_target_is_cpe[c] == 0) { |
327 | 266 | WORD32 *p_time_data = &ptr_time_data[k]; |
328 | | |
329 | 266 | WORD16 gain_cc = ixheaac_round16(ind_channel_info->cc_gain[j]); |
330 | | |
331 | 266 | ixheaacd_dec_couple_channel(p_time_data, out_samp_cc, frame_size, |
332 | 266 | total_channels, gain_cc); |
333 | 266 | } |
334 | 364 | if (ind_channel_info->cc_target_is_cpe[c] == 1) { |
335 | 98 | if (ind_channel_info->cc_l[c] == 1) { |
336 | 91 | WORD32 *p_time_data = &ptr_time_data[k]; |
337 | | |
338 | 91 | WORD16 gain_cc = ixheaac_round16(ind_channel_info->cc_gain[j]); |
339 | | |
340 | 91 | ixheaacd_dec_couple_channel(p_time_data, out_samp_cc, frame_size, |
341 | 91 | total_channels, gain_cc); |
342 | 91 | } |
343 | | |
344 | 98 | k = p_obj_exhaacplus_dec->aac_config.slot_element[l]; |
345 | | |
346 | 98 | if (ind_channel_info->cc_r[c] == 1) { |
347 | 51 | WORD32 *p_time_data = &ptr_time_data[k + 1]; |
348 | 51 | WORD16 gain_cc = ixheaac_round16(ind_channel_info->cc_gain[j + 1]); |
349 | | |
350 | 51 | ixheaacd_dec_couple_channel(p_time_data, out_samp_cc, frame_size, |
351 | 51 | total_channels, gain_cc); |
352 | 51 | } |
353 | 98 | } |
354 | 364 | if (ind_channel_info->cc_target_is_cpe[c] == 1) { |
355 | 98 | j += 2; |
356 | 266 | } else { |
357 | 266 | j += 1; |
358 | 266 | } |
359 | 364 | } |
360 | 273 | } |
361 | 0 | return err; |
362 | 295 | } |
363 | | |
364 | | void ixheaacd_dec_downmix_to_stereo( |
365 | | ia_exhaacplus_dec_api_struct *p_obj_exhaacplus_dec, WORD16 frame_size, |
366 | 0 | WORD total_elements, WORD16 *ptr_time_data, WORD total_channels) { |
367 | 0 | LOOPIDX i, j; |
368 | 0 | WORD k = 0; |
369 | 0 | if (5 == total_channels) k = 0; |
370 | 0 | if (6 == total_channels) k = 1; |
371 | 0 | if (7 == total_channels) k = 2; |
372 | 0 | if (8 == total_channels) k = 3; |
373 | |
|
374 | 0 | for (j = 0; j < frame_size; j++) { |
375 | 0 | WORD16 temp_l = 0, temp_r = 0; |
376 | 0 | for (i = 0; i < total_elements; i++) { |
377 | 0 | if (0 == p_obj_exhaacplus_dec->aac_config.element_type[i] || |
378 | 0 | 3 == p_obj_exhaacplus_dec->aac_config.element_type[i]) { |
379 | 0 | temp_l += (WORD16)( |
380 | 0 | ixheaac_mult32x16in32( |
381 | 0 | p_obj_exhaacplus_dec->common_tables->down_mix_martix |
382 | 0 | [k][0][p_obj_exhaacplus_dec->aac_config.slot_element[i]], |
383 | 0 | ptr_time_data[j * total_channels + |
384 | 0 | p_obj_exhaacplus_dec->aac_config |
385 | 0 | .slot_element[i]]) >> |
386 | 0 | 14); |
387 | |
|
388 | 0 | temp_r += (WORD16)( |
389 | 0 | ixheaac_mult32x16in32( |
390 | 0 | p_obj_exhaacplus_dec->common_tables->down_mix_martix |
391 | 0 | [k][1][p_obj_exhaacplus_dec->aac_config.slot_element[i]], |
392 | 0 | ptr_time_data[j * total_channels + |
393 | 0 | p_obj_exhaacplus_dec->aac_config |
394 | 0 | .slot_element[i]]) >> |
395 | 0 | 14); |
396 | 0 | } |
397 | 0 | if (1 == p_obj_exhaacplus_dec->aac_config.element_type[i]) { |
398 | 0 | temp_l += (WORD16)( |
399 | 0 | ixheaac_mult32x16in32( |
400 | 0 | p_obj_exhaacplus_dec->common_tables->down_mix_martix |
401 | 0 | [k][0][p_obj_exhaacplus_dec->aac_config.slot_element[i]], |
402 | 0 | ptr_time_data[j * total_channels + |
403 | 0 | p_obj_exhaacplus_dec->aac_config |
404 | 0 | .slot_element[i]]) >> |
405 | 0 | 14); |
406 | |
|
407 | 0 | temp_r += (WORD16)( |
408 | 0 | ixheaac_mult32x16in32( |
409 | 0 | p_obj_exhaacplus_dec->common_tables->down_mix_martix |
410 | 0 | [k][1] |
411 | 0 | [p_obj_exhaacplus_dec->aac_config.slot_element[i] + 1], |
412 | 0 | ptr_time_data[j * total_channels + |
413 | 0 | p_obj_exhaacplus_dec->aac_config.slot_element[i] + |
414 | 0 | 1]) >> |
415 | 0 | 14); |
416 | 0 | } |
417 | 0 | } |
418 | |
|
419 | 0 | ptr_time_data[2 * j] = temp_l; |
420 | 0 | ptr_time_data[2 * j + 1] = temp_r; |
421 | 0 | } |
422 | 0 | } |