You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
13 KiB
406 lines
13 KiB
/******************************************************************************
|
|
* *
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*****************************************************************************
|
|
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
|
*/
|
|
#include <string.h>
|
|
|
|
#include "ixheaacd_type_def.h"
|
|
#include "ixheaacd_sbr_common.h"
|
|
|
|
#include "ixheaacd_constants.h"
|
|
#include "ixheaacd_basic_ops32.h"
|
|
#include "ixheaacd_basic_ops16.h"
|
|
#include "ixheaacd_basic_ops40.h"
|
|
#include "ixheaacd_basic_ops.h"
|
|
|
|
#include "ixheaacd_bitbuffer.h"
|
|
|
|
#include "ixheaacd_audioobjtypes.h"
|
|
#include "ixheaacd_sbrdecsettings.h"
|
|
#include "ixheaacd_memory_standards.h"
|
|
#include "ixheaacd_error_codes.h"
|
|
|
|
#include "ixheaacd_defines.h"
|
|
#include "ixheaacd_aac_rom.h"
|
|
#include "ixheaacd_pns.h"
|
|
|
|
#include "ixheaacd_pulsedata.h"
|
|
#include "ixheaacd_drc_data_struct.h"
|
|
|
|
#include "ixheaacd_lt_predict.h"
|
|
#include "ixheaacd_channelinfo.h"
|
|
#include "ixheaacd_drc_dec.h"
|
|
|
|
#include "ixheaacd_sbrdecoder.h"
|
|
#include "ixheaacd_sbr_scale.h"
|
|
#include "ixheaacd_lpp_tran.h"
|
|
#include "ixheaacd_env_extr_part.h"
|
|
#include "ixheaacd_sbr_rom.h"
|
|
|
|
#include "ixheaacd_hybrid.h"
|
|
#include "ixheaacd_ps_dec.h"
|
|
#include "ixheaacd_ps_bitdec.h"
|
|
|
|
#include "ixheaacd_pulsedata.h"
|
|
|
|
#include "ixheaacd_pns.h"
|
|
|
|
#include "ixheaacd_env_extr.h"
|
|
#include "ixheaacd_common_rom.h"
|
|
#include "ixheaacd_block.h"
|
|
#include "ixheaacd_channel.h"
|
|
#include "ixheaacd_audioobjtypes.h"
|
|
#include "ixheaacd_latmdemux.h"
|
|
#include "ixheaacd_aacdec.h"
|
|
#include "ixheaacd_config.h"
|
|
#include "ixheaacd_mps_polyphase.h"
|
|
#include "ixheaacd_mps_dec.h"
|
|
#include "ixheaacd_struct_def.h"
|
|
#include "ixheaacd_headerdecode.h"
|
|
|
|
#include "ixheaacd_multichannel.h"
|
|
#include "ixheaacd_basic_op.h"
|
|
|
|
WORD cblock_decode_huff_symbol(UWORD8 *ptr_read_next, WORD32 bit_pos,
|
|
const UWORD16 *huff_ori, WORD16 *input,
|
|
WORD32 *readword)
|
|
|
|
{
|
|
const UWORD16 *h;
|
|
WORD tot_bits;
|
|
{
|
|
UWORD16 first_offset;
|
|
WORD16 sign_ret_val;
|
|
UWORD32 read_word1;
|
|
|
|
read_word1 = *readword << bit_pos;
|
|
|
|
h = (UWORD16 *)(huff_ori);
|
|
first_offset = 7;
|
|
|
|
h += (read_word1) >> (32 - first_offset);
|
|
sign_ret_val = *h;
|
|
tot_bits = 0;
|
|
|
|
while (sign_ret_val > 0) {
|
|
tot_bits += first_offset;
|
|
bit_pos += first_offset;
|
|
|
|
if ((bit_pos -= 8) >= 0) {
|
|
*readword = (*readword << 8) | *ptr_read_next;
|
|
ptr_read_next++;
|
|
} else {
|
|
bit_pos += 8;
|
|
}
|
|
|
|
read_word1 = (read_word1) << (first_offset);
|
|
|
|
first_offset = (sign_ret_val >> 11);
|
|
h += sign_ret_val & (0x07FF);
|
|
|
|
h += (read_word1) >> (32 - first_offset);
|
|
sign_ret_val = *h;
|
|
}
|
|
|
|
tot_bits += ((sign_ret_val & 0x7fff) >> 11);
|
|
bit_pos += ((sign_ret_val & 0x7fff) >> 11);
|
|
if ((bit_pos - 8) >= 0) {
|
|
*readword = (*readword << 8) | *ptr_read_next;
|
|
}
|
|
|
|
*input = (sign_ret_val & (0x07FF)) - 60;
|
|
}
|
|
|
|
return tot_bits;
|
|
}
|
|
|
|
IA_ERRORCODE ixheaacd_dec_coupling_channel_element(
|
|
ia_handle_bit_buf_struct bs, ia_aac_decoder_struct *aac_handle,
|
|
WORD32 samp_rate_idx, ia_aac_dec_tables_struct *ptr_aac_tables,
|
|
ixheaacd_misc_tables *common_tables_ptr, WORD *element_index_order,
|
|
ia_enhaacplus_dec_ind_cc *ind_channel_info, WORD32 total_channels,
|
|
WORD32 frame_size, WORD32 audio_object_type,
|
|
ia_eld_specific_config_struct eld_specific_config, WORD32 ele_type) {
|
|
WORD32 element_instance_tag;
|
|
LOOPIDX c;
|
|
|
|
WORD ind_sw_cce_flag, num_coupled_elements;
|
|
|
|
WORD num_gain_element_lists = 0;
|
|
WORD cc_domain;
|
|
WORD gain_element_sign;
|
|
WORD gain_element_scale;
|
|
|
|
const UWORD16 *hcod_sf =
|
|
ptr_aac_tables->pstr_huffmann_tables->huffman_code_book_scl;
|
|
const UWORD32 *table_idx =
|
|
ptr_aac_tables->pstr_huffmann_tables->huffman_code_book_scl_index;
|
|
WORD16 index, length;
|
|
|
|
IA_ERRORCODE error_status = IA_NO_ERROR;
|
|
|
|
element_instance_tag = ixheaacd_read_bits_buf(bs, 4);
|
|
element_index_order[0] = element_instance_tag;
|
|
|
|
ind_sw_cce_flag = ixheaacd_read_bits_buf(bs, 1);
|
|
num_coupled_elements = ixheaacd_read_bits_buf(bs, 3);
|
|
|
|
for (c = 0; c < MAX_BS_ELEMENT; c++)
|
|
ind_channel_info->elements_coupled[c] = -1;
|
|
|
|
ind_channel_info->num_coupled_elements = num_coupled_elements;
|
|
|
|
for (c = 0; c < (num_coupled_elements + 1); c++) {
|
|
num_gain_element_lists++;
|
|
|
|
ind_channel_info->cc_target_is_cpe[c] = ixheaacd_read_bits_buf(bs, 1);
|
|
ind_channel_info->cc_target_tag_select[c] = ixheaacd_read_bits_buf(bs, 4);
|
|
if (ind_channel_info->cc_target_is_cpe[c]) {
|
|
ind_channel_info->cc_l[c] = ixheaacd_read_bits_buf(bs, 1);
|
|
ind_channel_info->cc_r[c] = ixheaacd_read_bits_buf(bs, 1);
|
|
if (ind_channel_info->cc_l[c] && ind_channel_info->cc_r[c])
|
|
num_gain_element_lists++;
|
|
ind_channel_info->elements_coupled[c] = 1;
|
|
} else
|
|
ind_channel_info->elements_coupled[c] = 0;
|
|
}
|
|
if ((ind_sw_cce_flag == 0) && (num_gain_element_lists > MAX_BS_ELEMENT)) {
|
|
return IA_FATAL_ERROR;
|
|
}
|
|
cc_domain = ixheaacd_read_bits_buf(bs, 1);
|
|
gain_element_sign = ixheaacd_read_bits_buf(bs, 1);
|
|
gain_element_scale = ixheaacd_read_bits_buf(bs, 2);
|
|
|
|
aac_handle->pstr_aac_dec_ch_info[0]->str_ics_info.num_swb_window = 0;
|
|
aac_handle->pstr_aac_dec_ch_info[0]->str_ics_info.sampling_rate_index =
|
|
samp_rate_idx;
|
|
|
|
aac_handle->pstr_aac_dec_ch_info[0]->common_window = 0;
|
|
|
|
error_status = ixheaacd_individual_ch_stream(
|
|
bs, aac_handle, 1, frame_size, total_channels, audio_object_type,
|
|
eld_specific_config, ele_type);
|
|
|
|
if (error_status) return error_status;
|
|
|
|
ind_channel_info->cc_gain[0] = 1 << 29;
|
|
for (c = 1; c < num_gain_element_lists; c++) {
|
|
WORD cge;
|
|
WORD common_gain_element_present[MAX_BS_ELEMENT];
|
|
WORD16 norm_value;
|
|
|
|
if (ind_sw_cce_flag)
|
|
cge = 1;
|
|
else {
|
|
common_gain_element_present[c] = ixheaacd_read_bits_buf(bs, 1);
|
|
cge = common_gain_element_present[c];
|
|
return IA_ENHAACPLUS_DEC_EXE_FATAL_UNIMPLEMENTED_CCE;
|
|
}
|
|
if (cge) {
|
|
UWORD8 *ptr_read_next = bs->ptr_read_next;
|
|
WORD32 bit_pos = 7 - bs->bit_pos;
|
|
WORD32 read_word =
|
|
ixheaacd_aac_showbits_32(bs->ptr_read_next, bs->cnt_bits, NULL);
|
|
UWORD32 read_word1;
|
|
|
|
read_word1 = read_word << bit_pos;
|
|
ixheaacd_huffman_decode(read_word1, &index, &length, hcod_sf, table_idx);
|
|
|
|
bit_pos += length;
|
|
|
|
ixheaacd_aac_read_byte(&ptr_read_next, &bit_pos, &read_word);
|
|
while (bit_pos > 8)
|
|
ixheaacd_aac_read_byte(&ptr_read_next, &bit_pos, &read_word);
|
|
|
|
bs->ptr_read_next = ptr_read_next;
|
|
bs->bit_pos = 7 - bit_pos;
|
|
bs->cnt_bits -= length;
|
|
|
|
norm_value = index - 60;
|
|
if (norm_value == -1)
|
|
ind_channel_info->cc_gain[c] =
|
|
common_tables_ptr->cc_gain_scale[gain_element_scale];
|
|
else {
|
|
int i;
|
|
ind_channel_info->cc_gain[c] =
|
|
common_tables_ptr->cc_gain_scale[gain_element_scale];
|
|
for (i = 0; i < (-norm_value) - 1; i++) {
|
|
ind_channel_info->cc_gain[c] = ixheaacd_mul32_sh(
|
|
ind_channel_info->cc_gain[c],
|
|
common_tables_ptr->cc_gain_scale[gain_element_scale], 29);
|
|
}
|
|
}
|
|
} else {
|
|
return IA_ENHAACPLUS_DEC_EXE_FATAL_UNIMPLEMENTED_CCE;
|
|
}
|
|
}
|
|
if (bs->cnt_bits < 0) {
|
|
return IA_ENHAACPLUS_DEC_EXE_NONFATAL_INSUFFICIENT_INPUT_BYTES;
|
|
}
|
|
return error_status;
|
|
}
|
|
|
|
void ixheaacd_dec_couple_channel(WORD16 *p_time_data, WORD16 *out_samp_cc,
|
|
WORD16 frame_size, WORD total_channels,
|
|
WORD32 gain_cc)
|
|
|
|
{
|
|
WORD i;
|
|
WORD16 out_cc;
|
|
WORD16 *ptr_out_samp = &out_samp_cc[0];
|
|
for (i = frame_size - 1; i >= 0; i--) {
|
|
out_cc = ixheaacd_round16(ixheaacd_shl32_sat(
|
|
ixheaacd_mult32x16in32(gain_cc, *ptr_out_samp++), 3));
|
|
*p_time_data = ixheaacd_add16_sat(out_cc, *p_time_data);
|
|
p_time_data += total_channels;
|
|
}
|
|
}
|
|
|
|
void ixheaacd_dec_ind_coupling(
|
|
ia_exhaacplus_dec_api_struct *p_obj_exhaacplus_dec, WORD16 *coup_ch_output,
|
|
WORD16 frame_size, WORD total_channels, WORD16 *ptr_time_data)
|
|
|
|
{
|
|
WORD c, j, k;
|
|
WORD l;
|
|
WORD coupling_channel;
|
|
|
|
WORD16 *out_samp_cc;
|
|
|
|
ia_enhaacplus_dec_ind_cc *ind_channel_info;
|
|
|
|
{
|
|
coupling_channel = p_obj_exhaacplus_dec->aac_config.ui_coupling_channel;
|
|
|
|
ind_channel_info = &p_obj_exhaacplus_dec->p_state_aac->ind_cc_info;
|
|
|
|
out_samp_cc = coup_ch_output;
|
|
|
|
j = 0;
|
|
for (c = 0; c < ind_channel_info->num_coupled_elements + 1; c++) {
|
|
for (l = 0; l < MAX_BS_ELEMENT; l++) {
|
|
if (p_obj_exhaacplus_dec->aac_config.element_type[l] ==
|
|
ind_channel_info->elements_coupled[c] &&
|
|
p_obj_exhaacplus_dec->aac_config.element_instance_order[l] ==
|
|
ind_channel_info->cc_target_tag_select[c]) {
|
|
break;
|
|
}
|
|
}
|
|
if (l == MAX_BS_ELEMENT) {
|
|
continue;
|
|
}
|
|
|
|
k = p_obj_exhaacplus_dec->aac_config.slot_element[l];
|
|
|
|
if (ind_channel_info->cc_target_is_cpe[c] == 0) {
|
|
WORD16 *p_time_data = &ptr_time_data[k];
|
|
|
|
WORD32 gain_cc = ind_channel_info->cc_gain[j];
|
|
|
|
ixheaacd_dec_couple_channel(p_time_data, out_samp_cc, frame_size,
|
|
total_channels, gain_cc);
|
|
}
|
|
if (ind_channel_info->cc_target_is_cpe[c] == 1) {
|
|
if (ind_channel_info->cc_l[c] == 1) {
|
|
WORD16 *p_time_data = &ptr_time_data[k];
|
|
|
|
WORD32 gain_cc = ind_channel_info->cc_gain[j];
|
|
|
|
ixheaacd_dec_couple_channel(p_time_data, out_samp_cc, frame_size,
|
|
total_channels, gain_cc);
|
|
}
|
|
|
|
k = p_obj_exhaacplus_dec->aac_config.slot_element[l];
|
|
|
|
if (ind_channel_info->cc_r[c] == 1) {
|
|
WORD16 *p_time_data = &ptr_time_data[k + 1];
|
|
WORD32 gain_cc = ind_channel_info->cc_gain[j + 1];
|
|
|
|
ixheaacd_dec_couple_channel(p_time_data, out_samp_cc, frame_size,
|
|
total_channels, gain_cc);
|
|
}
|
|
}
|
|
if (ind_channel_info->cc_target_is_cpe[c] == 1) {
|
|
j += 2;
|
|
} else {
|
|
j += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ixheaacd_dec_downmix_to_stereo(
|
|
ia_exhaacplus_dec_api_struct *p_obj_exhaacplus_dec, WORD16 frame_size,
|
|
WORD total_elements, WORD16 *ptr_time_data, WORD total_channels) {
|
|
LOOPIDX i, j;
|
|
WORD k = 0;
|
|
if (5 == total_channels) k = 0;
|
|
if (6 == total_channels) k = 1;
|
|
if (7 == total_channels) k = 2;
|
|
if (8 == total_channels) k = 3;
|
|
|
|
for (j = 0; j < frame_size; j++) {
|
|
WORD16 temp_l = 0, temp_r = 0;
|
|
for (i = 0; i < total_elements; i++) {
|
|
if (0 == p_obj_exhaacplus_dec->aac_config.element_type[i] ||
|
|
3 == p_obj_exhaacplus_dec->aac_config.element_type[i]) {
|
|
temp_l += (WORD16)(
|
|
ixheaacd_mult32x16in32(
|
|
p_obj_exhaacplus_dec->common_tables->down_mix_martix
|
|
[k][0][p_obj_exhaacplus_dec->aac_config.slot_element[i]],
|
|
ptr_time_data[j * total_channels +
|
|
p_obj_exhaacplus_dec->aac_config
|
|
.slot_element[i]]) >>
|
|
14);
|
|
|
|
temp_r += (WORD16)(
|
|
ixheaacd_mult32x16in32(
|
|
p_obj_exhaacplus_dec->common_tables->down_mix_martix
|
|
[k][1][p_obj_exhaacplus_dec->aac_config.slot_element[i]],
|
|
ptr_time_data[j * total_channels +
|
|
p_obj_exhaacplus_dec->aac_config
|
|
.slot_element[i]]) >>
|
|
14);
|
|
}
|
|
if (1 == p_obj_exhaacplus_dec->aac_config.element_type[i]) {
|
|
temp_l += (WORD16)(
|
|
ixheaacd_mult32x16in32(
|
|
p_obj_exhaacplus_dec->common_tables->down_mix_martix
|
|
[k][0][p_obj_exhaacplus_dec->aac_config.slot_element[i]],
|
|
ptr_time_data[j * total_channels +
|
|
p_obj_exhaacplus_dec->aac_config
|
|
.slot_element[i]]) >>
|
|
14);
|
|
|
|
temp_r += (WORD16)(
|
|
ixheaacd_mult32x16in32(
|
|
p_obj_exhaacplus_dec->common_tables->down_mix_martix
|
|
[k][1]
|
|
[p_obj_exhaacplus_dec->aac_config.slot_element[i] + 1],
|
|
ptr_time_data[j * total_channels +
|
|
p_obj_exhaacplus_dec->aac_config.slot_element[i] +
|
|
1]) >>
|
|
14);
|
|
}
|
|
}
|
|
|
|
ptr_time_data[2 * j] = temp_l;
|
|
ptr_time_data[2 * j + 1] = temp_r;
|
|
}
|
|
}
|