/****************************************************************************** * * * 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 #include "ixheaacd_sbr_common.h" #include #include "ixheaacd_constants.h" #include #include #include #include "ixheaacd_basic_ops.h" #include #include "ixheaacd_intrinsics.h" #include "ixheaacd_common_rom.h" #include "ixheaacd_basic_funcs.h" #include "ixheaacd_bitbuffer.h" #include "ixheaacd_sbr_common.h" #include "ixheaacd_drc_data_struct.h" #include "ixheaacd_drc_dec.h" #include "ixheaacd_sbrdecoder.h" #include "ixheaacd_sbrdecsettings.h" #include "ixheaacd_sbr_scale.h" #include "ixheaacd_lpp_tran.h" #include "ixheaacd_env_extr_part.h" #include #include "ixheaacd_hybrid.h" #include "ixheaacd_ps_dec.h" #include "ixheaacd_env_extr.h" #include #include "ixheaacd_sbr_const.h" #include "ixheaacd_intrinsics.h" #include "ixheaacd_pvc_dec.h" #include "ixheaacd_ps_bitdec.h" #include "ixheaacd_audioobjtypes.h" WORD32 ixheaacd_cnt_leading_ones(WORD32 a) { WORD32 count = 0; while (a) { if (a & 0x80000000) count++; else break; a = a << 1; } return count; } VOID ixheaacd_huffman_decode(WORD32 it_bit_buff, WORD16 *h_index, WORD16 *len, const UWORD16 *input_table, const UWORD32 *idx_table) { UWORD32 temp = 0; UWORD32 temp1 = 0; WORD32 found = 0; UWORD32 mask = 0x80000000; WORD32 clo; WORD32 MAX_LEN; WORD32 ixheaacd_drc_offset = 0; WORD32 length; UWORD32 cwrd; WORD32 len_end; MAX_LEN = input_table[0]; mask = mask - (1 << (31 - MAX_LEN)); mask = mask << 1; temp = (UWORD32)(it_bit_buff & mask); len_end = input_table[0]; clo = ixheaacd_cnt_leading_ones(temp); do { ixheaacd_drc_offset = (idx_table[clo] >> 20) & 0xff; length = input_table[ixheaacd_drc_offset + 1] & 0x1f; cwrd = idx_table[clo] & 0xfffff; temp1 = temp >> (32 - length); if (temp1 <= cwrd) { ixheaacd_drc_offset = ixheaacd_drc_offset - (cwrd - temp1); found = 1; } else { len_end = len_end + ((idx_table[clo] >> 28) & 0xf); clo = len_end; } } while (!found); *h_index = input_table[ixheaacd_drc_offset + 1] >> 5; *len = length; } static WORD32 ixheaacd_read_esbr_pvc_envelope(ia_pvc_data_struct *ptr_pvc_data, ia_bit_buf_struct *it_bit_buff, WORD32 indepFlag) { WORD32 i, j, k; WORD32 fixed_length = 0, num_grid_info = 0, grid_info; UWORD8 div_mode, ns_mode; UWORD16 pvc_id[PVC_NUM_TIME_SLOTS + 1]; UWORD8 num_length; UWORD8 length; UWORD8 reuse_pvc_id; WORD32 sum_length = 0; WORD32 length_bits = 4; UWORD8 pvc_id_bits = PVC_ID_BITS; div_mode = (UWORD8)ixheaacd_read_bits_buf(it_bit_buff, PVC_DIV_MODE_BITS); ns_mode = (UWORD8)ixheaacd_read_bits_buf(it_bit_buff, PVC_NS_MODE_BITS); if (ptr_pvc_data->pvc_mode == 3) { pvc_id_bits = 0; } if (div_mode <= 3) { num_length = div_mode; if (indepFlag) { reuse_pvc_id = 0; } else { reuse_pvc_id = (UWORD8)ixheaacd_read_bits_buf(it_bit_buff, PVC_REUSE_PVC_ID_BITS); } if (reuse_pvc_id == 1) { pvc_id[0] = ptr_pvc_data->prev_pvc_id; } else { pvc_id[0] = (UWORD16)ixheaacd_read_bits_buf(it_bit_buff, pvc_id_bits); } k = 1; if (num_length) { sum_length = 0; for (i = 0; i < num_length; i++) { if (sum_length >= 13) { length_bits = 1; } else if (sum_length >= 11) { length_bits = 2; } else if (sum_length >= 7) { length_bits = 3; } else { length_bits = 4; } length = (UWORD8)ixheaacd_read_bits_buf(it_bit_buff, length_bits); length += 1; sum_length += length; if ((k + length - 1) > PVC_NUM_TIME_SLOTS) { return -1; } for (j = 1; j < length; j++, k++) { pvc_id[k] = pvc_id[k - 1]; } pvc_id[k++] = (UWORD16)ixheaacd_read_bits_buf(it_bit_buff, pvc_id_bits); } } for (; k < 16; k++) { pvc_id[k] = pvc_id[k - 1]; } } else { switch (div_mode) { case 4: num_grid_info = 2; fixed_length = 8; break; case 5: num_grid_info = 4; fixed_length = 4; break; case 6: num_grid_info = 8; fixed_length = 2; break; case 7: num_grid_info = 16; fixed_length = 1; break; default:; } if (indepFlag) { grid_info = 1; } else { grid_info = ixheaacd_read_bits_buf(it_bit_buff, PVC_GRID_INFO_BITS); } if (grid_info) { pvc_id[0] = (UWORD16)ixheaacd_read_bits_buf(it_bit_buff, pvc_id_bits); } else { pvc_id[0] = ptr_pvc_data->prev_pvc_id; } for (j = 1, k = 1; j < fixed_length; j++, k++) { pvc_id[k] = pvc_id[k - 1]; } for (i = 1; i < num_grid_info; i++) { grid_info = ixheaacd_read_bits_buf(it_bit_buff, PVC_GRID_INFO_BITS); if (grid_info == 1) { pvc_id[k++] = (UWORD16)ixheaacd_read_bits_buf(it_bit_buff, pvc_id_bits); } else { pvc_id[k] = pvc_id[k - 1]; k++; } for (j = 1; j < fixed_length; j++, k++) { pvc_id[k] = pvc_id[k - 1]; } } } ptr_pvc_data->div_mode = div_mode; ptr_pvc_data->ns_mode = ns_mode; for (i = 0; i < PVC_NUM_TIME_SLOTS; i++) { ptr_pvc_data->pvc_id[i] = pvc_id[i]; } return 0; } static VOID ixheaacd_pvc_env_dtdf_data( ia_sbr_frame_info_data_struct *ptr_frame_data, ia_bit_buf_struct *it_bit_buff) { WORD32 i; WORD32 usac_independency_flag = ptr_frame_data->usac_independency_flag; WORD32 bs_num_noise = ptr_frame_data->str_frame_info_details.num_noise_env; if (usac_independency_flag) { ptr_frame_data->del_cod_dir_noise_arr[0] = 0; } else { ptr_frame_data->del_cod_dir_noise_arr[0] = ixheaacd_read_bits_buf(it_bit_buff, ESBR_DOMAIN_BITS); } for (i = 1; i < bs_num_noise; i++) { ptr_frame_data->del_cod_dir_noise_arr[i] = ixheaacd_read_bits_buf(it_bit_buff, ESBR_DOMAIN_BITS); } } static VOID ixheaacd_read_sbr_addi_data( ia_sbr_frame_info_data_struct *ptr_frame_data, ia_sbr_header_data_struct *ptr_header_data, ia_bit_buf_struct *it_bit_buff) { WORD32 i; WORD32 flag = ixheaacd_read_bits_buf(it_bit_buff, 1); ptr_frame_data->sin_start_for_cur_top = ptr_frame_data->sin_start_for_next_top; ptr_frame_data->sin_len_for_cur_top = ptr_frame_data->sin_len_for_next_top; ptr_frame_data->sin_start_for_next_top = 0; ptr_frame_data->sin_len_for_next_top = 0; if (flag) { for (i = 0; i < ptr_header_data->pstr_freq_band_data->num_sf_bands[HIGH]; i++) { ptr_frame_data->add_harmonics[i] = ixheaacd_read_bits_buf(it_bit_buff, 1); } if (ptr_frame_data->pvc_mode != 0) { ptr_frame_data->sine_position = ESC_SIN_POS; ptr_frame_data->bs_sin_pos_present = ixheaacd_read_bits_buf(it_bit_buff, 1); if (ptr_frame_data->bs_sin_pos_present == 1) { ptr_frame_data->sine_position = ixheaacd_read_bits_buf(it_bit_buff, 5); } if (ptr_frame_data->var_len > 0) { if (ptr_frame_data->sine_position > 16) { if (ptr_frame_data->sine_position == 31) { ptr_frame_data->sin_start_for_next_top = 0; ptr_frame_data->sin_len_for_next_top = ptr_frame_data->var_len; } else { if ((ptr_frame_data->var_len + 16) == ptr_frame_data->sine_position) { ptr_frame_data->sin_start_for_next_top = 0; ptr_frame_data->sin_len_for_next_top = ptr_frame_data->var_len; } else { ptr_frame_data->sin_start_for_next_top = ptr_frame_data->sine_position - 16; ptr_frame_data->sin_len_for_next_top = ptr_frame_data->var_len; } } } else { ptr_frame_data->sin_start_for_next_top = 0; ptr_frame_data->sin_len_for_next_top = ptr_frame_data->var_len; } } else { ptr_frame_data->sin_start_for_next_top = 0; ptr_frame_data->sin_len_for_next_top = 0; } } } return; } WORD32 ixheaacd_ssc_huff_dec(ia_huffman_data_type t_huff, ia_handle_bit_buf_struct it_bit_buff) { WORD32 index; WORD32 value, bit; WORD16 cw; index = 0; while (index >= 0) { cw = t_huff[index]; bit = ixheaacd_read_bits_buf(it_bit_buff, 1); if (bit) { WORD sign = (cw & 0x0080); if (sign) { index = (cw | 0xffffff80); } else { index = (cw & 0x007f); } } else { index = (cw >> 8); } } value = (index + 64); return (value); } WORD32 ixheaacd_sbr_read_header_data( ia_sbr_header_data_struct *pstr_sbr_header, ia_bit_buf_struct *it_bit_buff, FLAG stereo_flag, ia_sbr_header_data_struct *pstr_sbr_dflt_header) { ia_sbr_header_data_struct prev_header_info; FLAG header_extra_1 = 0, header_extra_2 = 0; WORD32 tmp; WORD32 usac_independency_flag = pstr_sbr_header->usac_independency_flag; WORD32 use_dflt_hdr = 0; WORD32 header_present = 1; WORD32 usac_flag = pstr_sbr_header->usac_flag; if (!usac_flag) { memcpy(&prev_header_info, pstr_sbr_header, sizeof(ia_sbr_header_data_struct)); tmp = ixheaacd_read_bits_buf( it_bit_buff, SBR_AMPLITUDE_RESOLUTION_BITS + SBR_BEGIN_SAMP_FREQ_BITS + SBR_END_SAMP_FREQ_BITS + SBR_CROSS_OVER_BND_BITS); pstr_sbr_header->amp_res = (WORD16)( (tmp & 0x0800) >> (SBR_BEGIN_SAMP_FREQ_BITS + SBR_END_SAMP_FREQ_BITS + SBR_CROSS_OVER_BND_BITS)); pstr_sbr_header->start_freq = (WORD16)( (tmp & 0x0780) >> (SBR_END_SAMP_FREQ_BITS + SBR_CROSS_OVER_BND_BITS)); pstr_sbr_header->stop_freq = (WORD16)((tmp & 0x078) >> (SBR_CROSS_OVER_BND_BITS)); pstr_sbr_header->xover_band = (WORD16)((tmp & 0x07)); tmp = ixheaacd_read_bits_buf( it_bit_buff, SBR_HDR_RESERV_BITS + SBR_HDR_EXTR_1_BITS + SBR_HDR_EXTR_2_BITS); header_extra_1 = (FLAG)((tmp & 0x02) >> (SBR_HDR_EXTR_2_BITS)); header_extra_2 = (FLAG)((tmp & 0x01)); if (stereo_flag) { pstr_sbr_header->channel_mode = SBR_STEREO; } else { pstr_sbr_header->channel_mode = SBR_MONO; } } else { WORD32 info_present = 0; if (pstr_sbr_header->sync_state == SBR_ACTIVE) { memcpy(&prev_header_info, pstr_sbr_header, sizeof(ia_sbr_header_data_struct)); } if (usac_independency_flag) { header_present = 1; info_present = 1; } else { info_present = ixheaacd_read_bits_buf(it_bit_buff, 1); if (info_present) { header_present = ixheaacd_read_bits_buf(it_bit_buff, 1); } else { header_present = 0; } } if (info_present) { tmp = ixheaacd_read_bits_buf(it_bit_buff, SBR_AMPLITUDE_RESOLUTION_BITS + ESBR_CROSS_OVER_BND_BITS + ESBR_PRE_FLAT_BITS); pstr_sbr_header->amp_res = (WORD16)( (tmp & 0x0020) >> (ESBR_CROSS_OVER_BND_BITS + ESBR_PRE_FLAT_BITS)); pstr_sbr_header->xover_band = (WORD16)((tmp & 0x001E) >> (ESBR_PRE_FLAT_BITS)); pstr_sbr_header->pre_proc_flag = (WORD16)((tmp & 0x001)); if (pstr_sbr_header->pvc_flag) { pstr_sbr_header->pvc_mode = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PVC_MODE_BITS); } else { pstr_sbr_header->pvc_mode = 0; } } if (header_present) { use_dflt_hdr = ixheaacd_read_bits_buf(it_bit_buff, 1); if (use_dflt_hdr) { pstr_sbr_header->start_freq = pstr_sbr_dflt_header->start_freq; pstr_sbr_header->stop_freq = pstr_sbr_dflt_header->stop_freq; pstr_sbr_header->header_extra_1 = pstr_sbr_dflt_header->header_extra_1; pstr_sbr_header->header_extra_2 = pstr_sbr_dflt_header->header_extra_2; pstr_sbr_header->freq_scale = pstr_sbr_dflt_header->freq_scale; pstr_sbr_header->alter_scale = pstr_sbr_dflt_header->alter_scale; pstr_sbr_header->noise_bands = pstr_sbr_dflt_header->noise_bands; pstr_sbr_header->limiter_bands = pstr_sbr_dflt_header->limiter_bands; pstr_sbr_header->limiter_gains = pstr_sbr_dflt_header->limiter_gains; pstr_sbr_header->interpol_freq = pstr_sbr_dflt_header->interpol_freq; pstr_sbr_header->smoothing_mode = pstr_sbr_dflt_header->smoothing_mode; } else { tmp = ixheaacd_read_bits_buf( it_bit_buff, SBR_BEGIN_SAMP_FREQ_BITS + SBR_END_SAMP_FREQ_BITS + SBR_HDR_EXTR_1_BITS + SBR_HDR_EXTR_2_BITS); pstr_sbr_header->start_freq = (tmp & 0x03C0) >> (SBR_END_SAMP_FREQ_BITS + SBR_HDR_EXTR_1_BITS + SBR_HDR_EXTR_2_BITS); pstr_sbr_header->stop_freq = (tmp & 0x003C) >> (SBR_HDR_EXTR_1_BITS + SBR_HDR_EXTR_2_BITS); pstr_sbr_header->header_extra_1 = (tmp & 0x0002) >> (SBR_HDR_EXTR_2_BITS); pstr_sbr_header->header_extra_2 = (tmp & 0x0001); header_extra_1 = pstr_sbr_header->header_extra_1; header_extra_2 = pstr_sbr_header->header_extra_2; } } } if (!use_dflt_hdr && header_present) { if (header_extra_1) { tmp = ixheaacd_read_bits_buf( it_bit_buff, SBR_SAMP_FREQ_LVL_BITS + SBR_CHANGE_LVL_BITS + SBR_NOISE_BND_BITS); pstr_sbr_header->freq_scale = (WORD16)((tmp & 0x018) >> (SBR_CHANGE_LVL_BITS + SBR_NOISE_BND_BITS)); pstr_sbr_header->alter_scale = (WORD16)((tmp & 0x04) >> (SBR_NOISE_BND_BITS)); pstr_sbr_header->noise_bands = (WORD16)((tmp & 0x03)); } else { pstr_sbr_header->freq_scale = SBR_SAMP_FEQ_LVL_DEF; pstr_sbr_header->alter_scale = SBR_CHANGE_LVL_DEF; pstr_sbr_header->noise_bands = SBR_NOISE_BND_DEF; } if (header_extra_2) { tmp = ixheaacd_read_bits_buf( it_bit_buff, SBR_BND_LIMIT_BITS + SBR_GAIN_LIMIT_BITS + SBR_INTERPOL_SAMP_FREQ_BITS + SBR_SMOOTH_LEN_BITS); pstr_sbr_header->limiter_bands = (WORD16)( (tmp & 0x030) >> (SBR_GAIN_LIMIT_BITS + SBR_INTERPOL_SAMP_FREQ_BITS + SBR_SMOOTH_LEN_BITS)); pstr_sbr_header->limiter_gains = (WORD16)( (tmp & 0x0c) >> (SBR_INTERPOL_SAMP_FREQ_BITS + SBR_SMOOTH_LEN_BITS)); pstr_sbr_header->interpol_freq = (WORD16)((tmp & 0x02) >> (SBR_SMOOTH_LEN_BITS)); pstr_sbr_header->smoothing_mode = (WORD16)((tmp & 0x01)); } else { pstr_sbr_header->limiter_bands = SBR_BND_LIMIT_DEF; pstr_sbr_header->limiter_gains = SBR_GAIN_LIMIT_DEF; pstr_sbr_header->interpol_freq = SBR_INTERPOL_SAMP_FEQ_DEF; pstr_sbr_header->smoothing_mode = SBR_SMOOTH_LEN_DEF; } } if ((pstr_sbr_header->sync_state != SBR_ACTIVE) || (prev_header_info.start_freq != pstr_sbr_header->start_freq) || (prev_header_info.stop_freq != pstr_sbr_header->stop_freq) || (prev_header_info.xover_band != pstr_sbr_header->xover_band) || (prev_header_info.freq_scale != pstr_sbr_header->freq_scale) || (prev_header_info.alter_scale != pstr_sbr_header->alter_scale) || (prev_header_info.noise_bands != pstr_sbr_header->noise_bands)) { return SBR_RESET; } return 0; } static VOID ixheaacd_sbr_sin_coding_data( ia_sbr_header_data_struct *ptr_header_data, ia_sbr_frame_info_data_struct *ptr_frame_data, ia_bit_buf_struct *it_bit_buff) { FLAG *p_add_harmonic = ptr_frame_data->add_harmonics; WORD32 i; i = ptr_header_data->pstr_freq_band_data->num_sf_bands[HIGH]; do { *p_add_harmonic++ = (FLAG)ixheaacd_read_bits_buf(it_bit_buff, SBR_ADD_SINE_FLAG_BITS); i--; } while (i != 0); return; } static WORD16 ixheaacd_validate_frame_info( ia_frame_info_struct *pstr_frame_info, WORD16 num_time_slots, WORD audio_object_type) { WORD32 i, j; WORD32 start_pos, end_pos, transient_env, start_pos_noise, end_pos_noise, num_env_sf, num_noise_env; num_env_sf = pstr_frame_info->num_env; num_noise_env = pstr_frame_info->num_noise_env; if ((num_env_sf < 1) || (num_env_sf > MAX_ENVELOPES)) return 0; if (num_noise_env > MAX_NOISE_ENVELOPES) return 0; start_pos = pstr_frame_info->border_vec[0]; end_pos = pstr_frame_info->border_vec[num_env_sf]; transient_env = pstr_frame_info->transient_env; if (transient_env > num_env_sf) return 0; start_pos_noise = pstr_frame_info->noise_border_vec[0]; end_pos_noise = pstr_frame_info->noise_border_vec[num_noise_env]; if ((start_pos < 0) || (start_pos >= end_pos)) return 0; if (start_pos > SBR_OV_SLOTS) return 0; if (audio_object_type != AOT_ER_AAC_ELD && audio_object_type != AOT_ER_AAC_LD) { if (end_pos < SBR_TIME_SLOTS) return 0; } else { if (end_pos < num_time_slots) return 0; } if (end_pos > add_d(SBR_TIME_SLOTS, SBR_OV_SLOTS)) return 0; for (i = 0; i < num_env_sf; i++) { if (pstr_frame_info->border_vec[i] > pstr_frame_info->border_vec[i + 1]) return 0; } if ((num_env_sf == 1) && (num_noise_env > 1)) return 0; if ((start_pos != start_pos_noise) || (end_pos != end_pos_noise)) return 0; for (i = 0; i < num_noise_env; i++) { start_pos_noise = pstr_frame_info->noise_border_vec[i]; for (j = 0; j < num_env_sf; j++) { if (pstr_frame_info->border_vec[j] == start_pos_noise) break; } if (j == num_env_sf) return 0; } return 1; } static WORD16 ixheaacd_read_extn_data( ia_sbr_header_data_struct *ptr_header_data, ia_ps_dec_struct *ptr_ps_dec, ia_bit_buf_struct *it_bit_buff, ia_ps_tables_struct *ps_tables_ptr) { WORD i; WORD extended_data; WORD no_bits_left; extended_data = ixheaacd_read_bits_buf(it_bit_buff, SBR_ENLARGED_DATA_BITS); if (extended_data) { WORD cnt; FLAG ps_read; ps_read = 0; cnt = ixheaacd_read_bits_buf(it_bit_buff, SBR_CONT_SIZE_BITS); if (cnt == ((1 << SBR_CONT_SIZE_BITS) - 1)) { cnt = (cnt + ixheaacd_read_bits_buf(it_bit_buff, SBR_CONT_ESC_CNT_BITS)); } no_bits_left = (cnt << 3); while (no_bits_left > 7) { WORD extension_id = ixheaacd_read_bits_buf(it_bit_buff, SBR_CONT_ID_BITS); no_bits_left = (no_bits_left - SBR_CONT_ID_BITS); switch (extension_id) { case EXTENSION_ID_PS_CODING: if (ptr_ps_dec == NULL) { return 0; } if (!(ptr_ps_dec->force_mono || ps_read)) { no_bits_left = (no_bits_left - ixheaacd_read_ps_data(ptr_ps_dec, it_bit_buff, (WORD16)no_bits_left, ps_tables_ptr)); if (no_bits_left < 0) return 0; ptr_header_data->channel_mode = PS_STEREO; ps_read = 1; break; } default: cnt = (no_bits_left >> 3); for (i = cnt - 1; i >= 0; i--) ixheaacd_read_bits_buf(it_bit_buff, 8); no_bits_left = (no_bits_left - (cnt << 3)); break; } } if (no_bits_left < 0) return 0; ixheaacd_read_bits_buf(it_bit_buff, no_bits_left); } return 1; } WORD32 ixheaacd_sbr_read_pvc_sce(ia_sbr_frame_info_data_struct *ptr_frame_data, ia_bit_buf_struct *it_bit_buff, WORD32 hbe_flag, ia_pvc_data_struct *ptr_pvc_data, ia_sbr_tables_struct *ptr_sbr_tables, ia_sbr_header_data_struct *ptr_header_data) { WORD32 i; WORD32 err_code = 0; ia_env_extr_tables_struct *env_extr_tables_ptr = ptr_sbr_tables->env_extr_tables_ptr; WORD32 usac_independency_flag = ptr_frame_data->usac_independency_flag; if (hbe_flag) { ptr_frame_data->sbr_patching_mode = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PATCHING_MODE_BITS); if (ptr_frame_data->sbr_patching_mode == 0) { ptr_frame_data->over_sampling_flag = ixheaacd_read_bits_buf(it_bit_buff, ESBR_OVERSAMPLING_FLAG_BITS); if (ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_FLAG_BITS)) ptr_frame_data->pitch_in_bins = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_BINS_BITS); else ptr_frame_data->pitch_in_bins = 0; } else { ptr_frame_data->over_sampling_flag = ptr_frame_data->pitch_in_bins = 0; } } err_code = ixheaacd_pvc_time_freq_grid_info(it_bit_buff, ptr_frame_data); if (err_code) return err_code; ptr_pvc_data->prev_sbr_mode = PVC_SBR; ixheaacd_pvc_env_dtdf_data(ptr_frame_data, it_bit_buff); for (i = 0; i < ptr_header_data->pstr_freq_band_data->num_nf_bands; i++) { ptr_frame_data->sbr_invf_mode_prev[i] = ptr_frame_data->sbr_invf_mode[i]; ptr_frame_data->sbr_invf_mode[i] = (WORD32)ixheaacd_read_bits_buf(it_bit_buff, ESBR_INVF_MODE_BITS); } ptr_pvc_data->pvc_mode = ptr_header_data->pvc_mode; ixheaacd_read_esbr_pvc_envelope(ptr_pvc_data, it_bit_buff, usac_independency_flag); ixheaacd_read_sbr_noise_floor_data(ptr_header_data, ptr_frame_data, it_bit_buff, env_extr_tables_ptr); memset(ptr_frame_data->add_harmonics, 0, ptr_header_data->pstr_freq_band_data->num_sf_bands[HIGH] * sizeof(WORD32)); ptr_frame_data->pvc_mode = ptr_header_data->pvc_mode; ixheaacd_read_sbr_addi_data(ptr_frame_data, ptr_header_data, it_bit_buff); ptr_frame_data->coupling_mode = COUPLING_OFF; return 0; } WORD8 ixheaacd_sbr_read_sce(ia_sbr_header_data_struct *ptr_header_data, ia_sbr_frame_info_data_struct *ptr_frame_data, ia_ps_dec_struct *ptr_ps_dec, ia_bit_buf_struct *it_bit_buff, ia_sbr_tables_struct *ptr_sbr_tables, WORD audio_object_type) { WORD32 bit; WORD32 i; WORD32 hbe_flag = ptr_header_data->hbe_flag; WORD32 num_if_bands = ptr_header_data->pstr_freq_band_data->num_if_bands; WORD32 usac_flag = ptr_header_data->usac_flag; ia_env_extr_tables_struct *env_extr_tables_ptr = ptr_sbr_tables->env_extr_tables_ptr; ptr_frame_data->coupling_mode = COUPLING_OFF; if (!usac_flag) { bit = ixheaacd_read_bits_buf(it_bit_buff, 1); if (bit) ixheaacd_read_bits_buf(it_bit_buff, SBR_SCE_RESERV_BITS); if (audio_object_type == AOT_ER_AAC_ELD || audio_object_type == AOT_ER_AAC_LD) { if (ptr_frame_data->eld_sbr_flag == 1) { if (!ixheaacd_extract_frame_info_ld(it_bit_buff, ptr_frame_data)) return 0; } } else { if (!ixheaacd_sbr_time_freq_grid_info(it_bit_buff, ptr_frame_data, env_extr_tables_ptr)) return 0; } if (!ixheaacd_validate_frame_info(&ptr_frame_data->str_frame_info_details, ptr_header_data->num_time_slots, audio_object_type)) return 0; } else { if (hbe_flag) { ptr_frame_data->sbr_patching_mode = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PATCHING_MODE_BITS); if (ptr_frame_data->sbr_patching_mode == 0) { ptr_frame_data->over_sampling_flag = ixheaacd_read_bits_buf(it_bit_buff, ESBR_OVERSAMPLING_FLAG_BITS); if (ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_FLAG_BITS)) ptr_frame_data->pitch_in_bins = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_BINS_BITS); else ptr_frame_data->pitch_in_bins = 0; } else { ptr_frame_data->over_sampling_flag = ptr_frame_data->pitch_in_bins = 0; } } ptr_frame_data->num_time_slots = ptr_header_data->num_time_slots; if (!ixheaacd_sbr_time_freq_grid_info(it_bit_buff, ptr_frame_data, env_extr_tables_ptr)) return 0; if (!ixheaacd_validate_frame_info(&ptr_frame_data->str_frame_info_details, ptr_header_data->num_time_slots, audio_object_type)) return 0; ptr_frame_data->prev_sbr_mode = ORIG_SBR; } ixheaacd_sbr_env_dtdf_data(ptr_frame_data, it_bit_buff, ptr_header_data->usac_flag); if (ptr_frame_data->del_cod_dir_arr[0] == DTDF_DIR_FREQ) { ptr_header_data->err_flag = 0; } for (i = 0; i < num_if_bands; i++) { ptr_frame_data->sbr_invf_mode_prev[i] = ptr_frame_data->sbr_invf_mode[i]; ptr_frame_data->sbr_invf_mode[i] = (WORD32)ixheaacd_read_bits_buf(it_bit_buff, SBR_INVERSE_FILT_MODE_BITS); } if (!ixheaacd_read_sbr_env_data(ptr_header_data, ptr_frame_data, it_bit_buff, env_extr_tables_ptr, audio_object_type)) return 0; ixheaacd_read_sbr_noise_floor_data(ptr_header_data, ptr_frame_data, it_bit_buff, env_extr_tables_ptr); if (usac_flag) { memset( ptr_frame_data->add_harmonics, 0, ptr_header_data->pstr_freq_band_data->num_sf_bands[1] * sizeof(WORD32)); ptr_frame_data->coupling_mode = COUPLING_OFF; } bit = (FLAG)ixheaacd_read_bits_buf(it_bit_buff, 1); if (bit) { ixheaacd_sbr_sin_coding_data(ptr_header_data, ptr_frame_data, it_bit_buff); } else { memset(ptr_frame_data->add_harmonics, 0, sizeof(FLAG) * MAX_FREQ_COEFFS); } if (!usac_flag) { ixheaacd_read_extn_data(ptr_header_data, ptr_ps_dec, it_bit_buff, ptr_sbr_tables->ps_tables_ptr); } return 1; } WORD8 ixheaacd_sbr_read_cpe(ia_sbr_header_data_struct *ptr_header_data, ia_sbr_frame_info_data_struct **ptr_frame_data, ia_bit_buf_struct *it_bit_buff, ia_sbr_tables_struct *ptr_sbr_tables, WORD audio_object_type) { WORD32 i, k, bit, num_ch = 2; WORD32 num_if_bands = ptr_header_data->pstr_freq_band_data->num_if_bands; WORD32 hbe_flag = ptr_header_data->hbe_flag; WORD32 usac_flag = ptr_header_data->usac_flag; ia_env_extr_tables_struct *env_extr_tables_ptr = ptr_sbr_tables->env_extr_tables_ptr; bit = ixheaacd_read_bits_buf(it_bit_buff, 1); if (usac_flag) { if (bit) { if (hbe_flag) { ptr_frame_data[0]->sbr_patching_mode = ptr_frame_data[1]->sbr_patching_mode = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PATCHING_MODE_BITS); if (ptr_frame_data[0]->sbr_patching_mode == 0) { ptr_frame_data[0]->over_sampling_flag = ptr_frame_data[1]->over_sampling_flag = ixheaacd_read_bits_buf( it_bit_buff, ESBR_OVERSAMPLING_FLAG_BITS); if (ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_FLAG_BITS)) ptr_frame_data[0]->pitch_in_bins = ptr_frame_data[1]->pitch_in_bins = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_BINS_BITS); else ptr_frame_data[0]->pitch_in_bins = ptr_frame_data[1]->pitch_in_bins = 0; } else { ptr_frame_data[0]->over_sampling_flag = 0; ptr_frame_data[1]->over_sampling_flag = 0; ptr_frame_data[0]->pitch_in_bins = 0; ptr_frame_data[1]->pitch_in_bins = 0; } } ptr_frame_data[0]->coupling_mode = COUPLING_LEVEL; ptr_frame_data[1]->coupling_mode = COUPLING_BAL; } else { if (hbe_flag) { ptr_frame_data[0]->sbr_patching_mode = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PATCHING_MODE_BITS); if (ptr_frame_data[0]->sbr_patching_mode == 0) { ptr_frame_data[0]->over_sampling_flag = ixheaacd_read_bits_buf(it_bit_buff, ESBR_OVERSAMPLING_FLAG_BITS); if (ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_FLAG_BITS)) ptr_frame_data[0]->pitch_in_bins = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_BINS_BITS); else ptr_frame_data[0]->pitch_in_bins = 0; } else { ptr_frame_data[0]->over_sampling_flag = 0; ptr_frame_data[0]->pitch_in_bins = 0; } ptr_frame_data[1]->sbr_patching_mode = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PATCHING_MODE_BITS); if (ptr_frame_data[1]->sbr_patching_mode == 0) { ptr_frame_data[1]->over_sampling_flag = ixheaacd_read_bits_buf(it_bit_buff, ESBR_OVERSAMPLING_FLAG_BITS); if (ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_FLAG_BITS)) ptr_frame_data[1]->pitch_in_bins = ixheaacd_read_bits_buf(it_bit_buff, ESBR_PITCHIN_BINS_BITS); else ptr_frame_data[1]->pitch_in_bins = 0; } else { ptr_frame_data[1]->over_sampling_flag = ptr_frame_data[1]->pitch_in_bins = 0; } } ptr_frame_data[0]->coupling_mode = COUPLING_OFF; ptr_frame_data[1]->coupling_mode = COUPLING_OFF; } } else { if (bit) { ixheaacd_read_bits_buf(it_bit_buff, SBR_SCE_RESERV_BITS + SBR_SCE_RESERV_BITS); } if ((audio_object_type != AOT_ER_AAC_ELD) && (ptr_header_data->channel_mode != SBR_STEREO)) { ptr_header_data->sync_state = UPSAMPLING; return 0; } bit = ixheaacd_read_bits_buf(it_bit_buff, SBR_COUPLNG_MODE_BITS); if (bit) { ptr_frame_data[0]->coupling_mode = COUPLING_LEVEL; ptr_frame_data[1]->coupling_mode = COUPLING_BAL; } else { ptr_frame_data[0]->coupling_mode = COUPLING_OFF; ptr_frame_data[1]->coupling_mode = COUPLING_OFF; } } for (i = 0; i < num_ch; i++) { ptr_frame_data[i]->num_time_slots = ptr_header_data->num_time_slots; if (audio_object_type == AOT_ER_AAC_ELD || audio_object_type == AOT_ER_AAC_LD) { if (ptr_frame_data[i]->eld_sbr_flag == 1) { if (!ixheaacd_extract_frame_info_ld(it_bit_buff, ptr_frame_data[i])) return 0; } } else { if (!ixheaacd_sbr_time_freq_grid_info(it_bit_buff, ptr_frame_data[i], env_extr_tables_ptr)) return 0; } if (!ixheaacd_validate_frame_info( &ptr_frame_data[i]->str_frame_info_details, ptr_header_data->num_time_slots, audio_object_type)) return 0; if (ptr_frame_data[0]->coupling_mode) { memcpy(&ptr_frame_data[1]->str_frame_info_details, &ptr_frame_data[0]->str_frame_info_details, sizeof(ia_frame_info_struct)); if (audio_object_type == AOT_ER_AAC_ELD || audio_object_type == AOT_ER_AAC_LD) { ptr_frame_data[1]->amp_res = ptr_frame_data[0]->amp_res; } num_ch = 1; } } if (ptr_frame_data[0]->coupling_mode && usac_flag) { ixheaacd_sbr_env_dtdf_data(ptr_frame_data[0], it_bit_buff, ptr_header_data->usac_flag); ixheaacd_sbr_env_dtdf_data(ptr_frame_data[1], it_bit_buff, ptr_header_data->usac_flag); for (i = 0; i < ptr_header_data->pstr_freq_band_data->num_if_bands; i++) { ptr_frame_data[0]->sbr_invf_mode_prev[i] = ptr_frame_data[0]->sbr_invf_mode[i]; ptr_frame_data[1]->sbr_invf_mode_prev[i] = ptr_frame_data[1]->sbr_invf_mode[i]; ptr_frame_data[0]->sbr_invf_mode[i] = (WORD32)ixheaacd_read_bits_buf(it_bit_buff, ESBR_INVF_MODE_BITS); ptr_frame_data[1]->sbr_invf_mode[i] = ptr_frame_data[0]->sbr_invf_mode[i]; } ixheaacd_read_sbr_env_data(ptr_header_data, ptr_frame_data[0], it_bit_buff, env_extr_tables_ptr, audio_object_type); ixheaacd_read_sbr_noise_floor_data(ptr_header_data, ptr_frame_data[0], it_bit_buff, env_extr_tables_ptr); ixheaacd_read_sbr_env_data(ptr_header_data, ptr_frame_data[1], it_bit_buff, env_extr_tables_ptr, audio_object_type); ixheaacd_read_sbr_noise_floor_data(ptr_header_data, ptr_frame_data[1], it_bit_buff, env_extr_tables_ptr); memset( ptr_frame_data[0]->add_harmonics, 0, ptr_header_data->pstr_freq_band_data->num_sf_bands[1] * sizeof(WORD32)); memset( ptr_frame_data[1]->add_harmonics, 0, ptr_header_data->pstr_freq_band_data->num_sf_bands[1] * sizeof(WORD32)); } else { ixheaacd_sbr_env_dtdf_data(ptr_frame_data[0], it_bit_buff, ptr_header_data->usac_flag); ixheaacd_sbr_env_dtdf_data(ptr_frame_data[1], it_bit_buff, ptr_header_data->usac_flag); if ((ptr_frame_data[0]->del_cod_dir_arr[0] == DTDF_DIR_FREQ) && (ptr_frame_data[1]->del_cod_dir_arr[0] == DTDF_DIR_FREQ)) { ptr_header_data->err_flag = 0; } for (k = 0; k < num_ch; k++) { for (i = 0; i < num_if_bands; i++) { ptr_frame_data[k]->sbr_invf_mode_prev[i] = ptr_frame_data[k]->sbr_invf_mode[i]; ptr_frame_data[k]->sbr_invf_mode[i] = (WORD32)ixheaacd_read_bits_buf( it_bit_buff, SBR_INVERSE_FILT_MODE_BITS); } } if (ptr_frame_data[0]->coupling_mode) { memcpy(ptr_frame_data[1]->sbr_invf_mode, ptr_frame_data[0]->sbr_invf_mode, sizeof(WORD32) * num_if_bands); if (!ixheaacd_read_sbr_env_data(ptr_header_data, ptr_frame_data[0], it_bit_buff, env_extr_tables_ptr, audio_object_type)) { return 0; } ixheaacd_read_sbr_noise_floor_data(ptr_header_data, ptr_frame_data[0], it_bit_buff, env_extr_tables_ptr); if (!ixheaacd_read_sbr_env_data(ptr_header_data, ptr_frame_data[1], it_bit_buff, env_extr_tables_ptr, audio_object_type)) { return 0; } } else { if (!ixheaacd_read_sbr_env_data(ptr_header_data, ptr_frame_data[0], it_bit_buff, env_extr_tables_ptr, audio_object_type)) return 0; if (!ixheaacd_read_sbr_env_data(ptr_header_data, ptr_frame_data[1], it_bit_buff, env_extr_tables_ptr, audio_object_type)) return 0; ixheaacd_read_sbr_noise_floor_data(ptr_header_data, ptr_frame_data[0], it_bit_buff, env_extr_tables_ptr); } ixheaacd_read_sbr_noise_floor_data(ptr_header_data, ptr_frame_data[1], it_bit_buff, env_extr_tables_ptr); } bit = (FLAG)ixheaacd_read_bits_buf(it_bit_buff, 1); if (bit) { ixheaacd_sbr_sin_coding_data(ptr_header_data, ptr_frame_data[0], it_bit_buff); } else { memset(ptr_frame_data[0]->add_harmonics, 0, sizeof(FLAG) * MAX_FREQ_COEFFS); } bit = (FLAG)ixheaacd_read_bits_buf(it_bit_buff, 1); if (bit) { ixheaacd_sbr_sin_coding_data(ptr_header_data, ptr_frame_data[1], it_bit_buff); } else { memset(ptr_frame_data[1]->add_harmonics, 0, sizeof(FLAG) * MAX_FREQ_COEFFS); } if (!usac_flag) { ixheaacd_read_extn_data(ptr_header_data, NULL, it_bit_buff, ptr_sbr_tables->ps_tables_ptr); } return 1; } VOID ixheaacd_sbr_env_dtdf_data(ia_sbr_frame_info_data_struct *ptr_frame_data, ia_bit_buf_struct *it_bit_buff, WORD32 usac_flag) { WORD32 i; WORD32 num_env = ptr_frame_data->str_frame_info_details.num_env; WORD32 num_noise_env = ptr_frame_data->str_frame_info_details.num_noise_env; WORD16 *p_coding_dir_vec = ptr_frame_data->del_cod_dir_arr; WORD16 *p_coding_dir_noise_vec = ptr_frame_data->del_cod_dir_noise_arr; WORD32 usac_independency_flag = ptr_frame_data->usac_independency_flag; if (usac_flag) { if (usac_independency_flag) { *p_coding_dir_vec = 0; p_coding_dir_vec++; } else { *p_coding_dir_vec = (WORD16)ixheaacd_read_bits_buf(it_bit_buff, SBR_DEL_COD_DIR_BITS); p_coding_dir_vec++; } for (i = num_env - 1; i >= 1; i--) { *p_coding_dir_vec++ = (WORD16)ixheaacd_read_bits_buf(it_bit_buff, SBR_DEL_COD_DIR_BITS); } if (usac_independency_flag) { *p_coding_dir_noise_vec = 0; p_coding_dir_noise_vec++; } else { *p_coding_dir_noise_vec = (WORD16)ixheaacd_read_bits_buf(it_bit_buff, SBR_DEL_COD_DIR_BITS); p_coding_dir_noise_vec++; } for (i = num_noise_env - 1; i >= 1; i--) { *p_coding_dir_noise_vec++ = (WORD16)ixheaacd_read_bits_buf(it_bit_buff, SBR_DEL_COD_DIR_BITS); } } else { for (i = num_env - 1; i >= 0; i--) { *p_coding_dir_vec++ = (WORD16)ixheaacd_read_bits_buf(it_bit_buff, SBR_DEL_COD_DIR_BITS); } for (i = num_noise_env - 1; i >= 0; i--) { *p_coding_dir_noise_vec++ = (WORD16)ixheaacd_read_bits_buf(it_bit_buff, SBR_DEL_COD_DIR_BITS); } } } VOID ixheaacd_read_env_data(ia_sbr_frame_info_data_struct *ptr_frame_data, ia_bit_buf_struct *it_bit_buff, ia_huffman_data_type hcb_t, ia_huffman_data_type hcb_f, WORD32 *idx_t, WORD32 *idx_f, WORD16 *no_band, WORD32 num_env, WORD32 env_data_tbl_comp_factor, WORD32 start_bits, WORD32 start_bits_balance, WORD32 num_noise_env, WORD32 lav, WORD32 usac_flag) { WORD32 j, i, ixheaacd_drc_offset = 0, coupling_mode = ptr_frame_data->coupling_mode, delta, bits, shift; WORD16 *p_coding_dir_vec, *p_sbr_sf; WORD16 index, length; WORD32 readword; FLOAT32 *p_sbr_sf_float; if (num_noise_env) { p_coding_dir_vec = ptr_frame_data->del_cod_dir_noise_arr; p_sbr_sf = ptr_frame_data->int_noise_floor; p_sbr_sf_float = ptr_frame_data->flt_noise_floor; } else { p_coding_dir_vec = ptr_frame_data->del_cod_dir_arr; p_sbr_sf = ptr_frame_data->int_env_sf_arr; p_sbr_sf_float = ptr_frame_data->flt_env_sf_arr; } if (coupling_mode == COUPLING_BAL) { bits = start_bits_balance; shift = env_data_tbl_comp_factor; } else { bits = start_bits; shift = 0; } for (j = 0; j < num_env; j++) { ia_huffman_data_type h; const WORD32 *idx_tab; WORD32 dtdf_dir_flag = p_coding_dir_vec[j]; if (dtdf_dir_flag == DTDF_DIR_FREQ) { p_sbr_sf[ixheaacd_drc_offset] = (WORD16)(ixheaacd_read_bits_buf(it_bit_buff, bits) << shift); p_sbr_sf_float[ixheaacd_drc_offset] = p_sbr_sf[ixheaacd_drc_offset]; h = hcb_f; idx_tab = idx_f; } else { h = hcb_t; idx_tab = idx_t; } for (i = (1 - dtdf_dir_flag); i < no_band[j]; i++) { readword = ixheaacd_show_bits_buf(it_bit_buff, 20); ixheaacd_huffman_decode(readword << 12, &index, &length, (const UWORD16 *)h, (const UWORD32 *)idx_tab); delta = index - lav; ixheaacd_read_bits_buf(it_bit_buff, length); p_sbr_sf[ixheaacd_drc_offset + i] = (WORD16)(delta << env_data_tbl_comp_factor); p_sbr_sf_float[ixheaacd_drc_offset + i] = p_sbr_sf[ixheaacd_drc_offset + i]; } if (usac_flag && (num_noise_env == 0)) { ptr_frame_data->inter_temp_shape_mode[j] = 0; if (ptr_frame_data->inter_tes_flag) { WORD32 flag = (WORD32)ixheaacd_read_bits_buf(it_bit_buff, 1); if (flag) { ptr_frame_data->inter_temp_shape_mode[j] = (WORD32)ixheaacd_read_bits_buf(it_bit_buff, 2); } } } ixheaacd_drc_offset += (no_band[j]); } } VOID ixheaacd_read_sbr_noise_floor_data( ia_sbr_header_data_struct *ptr_header_data, ia_sbr_frame_info_data_struct *ptr_frame_data, ia_bit_buf_struct *it_bit_buff, ia_env_extr_tables_struct *env_extr_tables_ptr) { WORD32 i; WORD32 coupling_mode; WORD16 num_noise_bands[MAX_NOISE_ENVELOPES]; ia_huffman_data_type hcb_noise_env; ia_huffman_data_type hcb_noise; WORD32 *idx_noise_env; WORD32 *idx_noise; WORD32 lav; WORD32 env_data_tbl_comp_factor; WORD32 start_bits; WORD32 start_bits_balance; WORD32 num_noise_env = ptr_frame_data->str_frame_info_details.num_noise_env; for (i = 0; i < num_noise_env; i++) num_noise_bands[i] = ptr_header_data->pstr_freq_band_data->num_nf_bands; start_bits = SBR_BEGIN_NOISE_BITS_AMPLITUDE_RESOLUTION_3_0; start_bits_balance = SBR_BEGIN_NOISE_BITS_BALNCE_AMPLITUDE_RESOLUTION_3_0; coupling_mode = ptr_frame_data->coupling_mode; if (coupling_mode == COUPLING_BAL) { lav = 12; hcb_noise = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_t_huffman_noise_bal_3_0db_inp_table; idx_noise = env_extr_tables_ptr->ixheaacd_t_huffman_noise_bal_3_0db_idx_table; hcb_noise_env = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_f_huffman_env_bal_3_0db_inp_table; idx_noise_env = env_extr_tables_ptr->ixheaacd_f_huffman_env_bal_3_0db_idx_table; env_data_tbl_comp_factor = 1; } else { lav = 31; hcb_noise = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_t_huffman_noise_3_0db_inp_table; idx_noise = env_extr_tables_ptr->ixheaacd_t_huffman_noise_3_0db_idx_table; hcb_noise_env = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_f_huffman_env_3_0db_inp_table; idx_noise_env = env_extr_tables_ptr->ixheaacd_f_huffman_env_3_0db_idx_table; env_data_tbl_comp_factor = 0; } ixheaacd_read_env_data(ptr_frame_data, it_bit_buff, hcb_noise, hcb_noise_env, idx_noise, idx_noise_env, &num_noise_bands[0], num_noise_env, env_data_tbl_comp_factor, start_bits, start_bits_balance, 1, lav, ptr_header_data->usac_flag); } WORD16 ixheaacd_read_sbr_env_data( ia_sbr_header_data_struct *ptr_header_data, ia_sbr_frame_info_data_struct *ptr_frame_data, ia_bit_buf_struct *it_bit_buff, ia_env_extr_tables_struct *env_extr_tables_ptr, WORD audio_object_type) { WORD32 coupling_mode = ptr_frame_data->coupling_mode; WORD32 *idx_t, *idx_f; WORD32 lav; WORD32 i; WORD16 no_band[MAX_ENVELOPES]; WORD32 delta; WORD32 amp_res, num_env, env_data_tbl_comp_factor, start_bits, start_bits_balance; WORD16 *p_freq_res = ptr_frame_data->str_frame_info_details.freq_res; WORD16 *p_num_sf_bands = ptr_header_data->pstr_freq_band_data->num_sf_bands; ia_huffman_data_type hcb_t, hcb_f; delta = 0; amp_res = ptr_header_data->amp_res; num_env = ptr_frame_data->str_frame_info_details.num_env; ptr_frame_data->num_env_sfac = 0; if ((ptr_frame_data->str_frame_info_details.frame_class == FIXFIX) && (num_env == 1)) { if (audio_object_type != AOT_ER_AAC_ELD && audio_object_type != AOT_ER_AAC_LD) { amp_res = SBR_AMPLITUDE_RESOLUTION_1_5; } else { amp_res = ptr_frame_data->amp_res; } } ptr_frame_data->amp_res = amp_res; if (amp_res == SBR_AMPLITUDE_RESOLUTION_3_0) { start_bits = SBR_BEGIN_ENVN_BITS_AMPLITUDE_RESOLUTION_3_0; start_bits_balance = SBR_BEGIN_ENVN_BITS_BALNCE_AMPLITUDE_RESOLUTION_3_0; } else { start_bits = SBR_BEGIN_ENVN_BITS_AMPLITUDE_RESOLUTION_1_5; start_bits_balance = SBR_BEGIN_ENVN_BITS_BALNCE_AMPLITUDE_RESOLUTION_1_5; } for (i = 0; i < num_env; i++) { no_band[i] = p_num_sf_bands[*p_freq_res++]; ptr_frame_data->num_env_sfac = ixheaacd_add16(ptr_frame_data->num_env_sfac, no_band[i]); } if (ptr_frame_data->num_env_sfac > MAX_NUM_ENVELOPE_VALUES) return 0; if (coupling_mode == COUPLING_BAL) { env_data_tbl_comp_factor = 1; if (amp_res == SBR_AMPLITUDE_RESOLUTION_1_5) { lav = 24; hcb_t = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_t_huffman_env_bal_1_5db_inp_table; idx_t = env_extr_tables_ptr->ixheaacd_t_huffman_env_bal_1_5db_idx_table; hcb_f = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_f_huffman_env_bal_1_5db_inp_table; idx_f = env_extr_tables_ptr->ixheaacd_f_huffman_env_bal_1_5db_idx_table; } else { lav = 12; hcb_t = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_t_huffman_env_bal_3_0db_inp_table; idx_t = env_extr_tables_ptr->ixheaacd_t_huffman_env_bal_3_0db_idx_table; hcb_f = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_f_huffman_env_bal_3_0db_inp_table; idx_f = env_extr_tables_ptr->ixheaacd_f_huffman_env_bal_3_0db_idx_table; } } else { env_data_tbl_comp_factor = 0; if (amp_res == SBR_AMPLITUDE_RESOLUTION_1_5) { lav = 60; hcb_t = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_t_huffman_env_1_5db_inp_table; idx_t = env_extr_tables_ptr->ixheaacd_t_huffman_env_1_5db_idx_table; hcb_f = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_f_huffman_env_1_5db_inp_table; idx_f = env_extr_tables_ptr->ixheaacd_f_huffman_env_1_5db_idx_table; } else { lav = 31; hcb_t = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_t_huffman_env_3_0db_inp_table; idx_t = env_extr_tables_ptr->ixheaacd_t_huffman_env_3_0db_idx_table; hcb_f = (ia_huffman_data_type)&env_extr_tables_ptr ->ixheaacd_f_huffman_env_3_0db_inp_table; idx_f = env_extr_tables_ptr->ixheaacd_f_huffman_env_3_0db_idx_table; } } ixheaacd_read_env_data(ptr_frame_data, it_bit_buff, hcb_t, hcb_f, idx_t, idx_f, &no_band[0], num_env, env_data_tbl_comp_factor, start_bits, start_bits_balance, 0, lav, ptr_header_data->usac_flag); return 1; } int ixheaacd_extract_frame_info_ld( ia_bit_buf_struct *it_bit_buff, ia_sbr_frame_info_data_struct *h_frame_data) { int abs_bord_lead = 0, num_rel_lead = 0, num_rel_trail = 0, bs_num_env = 0, frame_class, temp, env, k, abs_bord_trail = 0, middle_bord = 0, bs_num_noise, transient_env_temp = 0, bs_transient_position = 0; WORD16 time_border[MAX_ENVELOPES + 1]; WORD16 time_border_noise[2 + 1]; WORD16 f[MAX_ENVELOPES + 1]; int rel_bord_lead[7] ={0}; ia_frame_info_struct *v_frame_info = &h_frame_data->str_frame_info_details; int numTimeSlots = h_frame_data->num_time_slots; v_frame_info->frame_class = frame_class = ixheaacd_read_bits_buf(it_bit_buff, SBRLD_CLA_BITS); switch (frame_class) { case FIXFIX: temp = ixheaacd_read_bits_buf(it_bit_buff, SBR_ENV_BITS); bs_num_env = 1 << temp; if (bs_num_env == 1) h_frame_data->amp_res = ixheaacd_read_bits_buf(it_bit_buff, SBR_AMPLITUDE_RESOLUTION_BITS); f[0] = ixheaacd_read_bits_buf(it_bit_buff, SBR_RES_BITS); for (env = 1; env < bs_num_env; env++) f[env] = f[0]; break; case LD_TRAN: bs_transient_position = ixheaacd_read_bits_buf(it_bit_buff, SBR_TRAN_BITS); v_frame_info->frame_class = 0; bs_num_env = (numTimeSlots == 16) ? ixheaacd_ld_env_table_512[bs_transient_position] [SBR_ENVT_NUMENV] : ixheaacd_ld_env_table_480[bs_transient_position] [SBR_ENVT_NUMENV]; for (env = 0; env < bs_num_env; env++) f[env] = ixheaacd_read_bits_buf(it_bit_buff, SBR_RES_BITS); break; } switch (frame_class) { case FIXFIX: abs_bord_lead = 0; abs_bord_trail = numTimeSlots; num_rel_lead = bs_num_env - 1; num_rel_trail = 0; for (k = 0; k < num_rel_lead; k++) { rel_bord_lead[k] = ixheaacd_ld_env_table_time_slot[num_rel_lead - 1]; } time_border[0] = abs_bord_lead; time_border[bs_num_env] = abs_bord_trail; for (env = 1; env <= num_rel_lead; env++) { time_border[env] = abs_bord_lead; for (k = 0; k <= env - 1; k++) time_border[env] += rel_bord_lead[k]; } break; case LD_TRAN: time_border[0] = 0; time_border[bs_num_env] = numTimeSlots; for (k = 1; k < bs_num_env; k++) time_border[k] = (numTimeSlots == 16) ? ixheaacd_ld_env_table_512[bs_transient_position][k] : ixheaacd_ld_env_table_480[bs_transient_position][k]; break; default: time_border[0] = 0; break; }; switch (frame_class) { case FIXFIX: middle_bord = bs_num_env / 2; break; case LD_TRAN: middle_bord = 1; break; }; time_border_noise[0] = time_border[0]; if (bs_num_env > 1) { time_border_noise[1] = time_border[middle_bord]; time_border_noise[2] = time_border[bs_num_env]; bs_num_noise = 2; } else { time_border_noise[1] = time_border[bs_num_env]; bs_num_noise = 1; } switch (frame_class) { case FIXFIX: transient_env_temp = -1; break; case LD_TRAN: transient_env_temp = (numTimeSlots == 16) ? ixheaacd_ld_env_table_512[bs_transient_position] [SBR_ENVT_TRANIDX] : ixheaacd_ld_env_table_480[bs_transient_position] [SBR_ENVT_TRANIDX]; break; }; v_frame_info->num_env = bs_num_env; memcpy(v_frame_info->border_vec, time_border, (bs_num_env + 1) * sizeof(WORD16)); memcpy(v_frame_info->freq_res, f, bs_num_env * sizeof(WORD16)); v_frame_info->transient_env = transient_env_temp; v_frame_info->num_noise_env = bs_num_noise; memcpy(v_frame_info->noise_border_vec, time_border_noise, (bs_num_noise + 1) * sizeof(WORD16)); return 1; } WORD32 ixheaacd_pvc_time_freq_grid_info( ia_bit_buf_struct *it_bit_buff, ia_sbr_frame_info_data_struct *ptr_frame_data) { WORD32 bs_num_env = 0, bs_num_noise = 0; WORD32 time_border[MAX_ENVELOPES + 1]; WORD32 time_border_noise[2 + 1]; WORD32 pvc_time_border[MAX_ENVELOPES + 1]; WORD32 pvc_time_border_noise[2 + 1]; WORD32 bs_freq_res[MAX_ENVELOPES + 1]; WORD32 var_len; ia_frame_info_struct *p_frame_info = &ptr_frame_data->str_frame_info_details; ia_frame_info_struct *pvc_frame_info = &ptr_frame_data->str_pvc_frame_info; WORD32 i; WORD32 prev_sbr_mode = ptr_frame_data->prev_sbr_mode; WORD32 tmp; WORD32 bs_noise_pos; bs_noise_pos = ixheaacd_read_bits_buf(it_bit_buff, 4); tmp = ixheaacd_read_bits_buf(it_bit_buff, 1); if (tmp == 0) { ptr_frame_data->var_len = 0; } else { tmp = ixheaacd_read_bits_buf(it_bit_buff, 2); ptr_frame_data->var_len = tmp + 1; } var_len = ptr_frame_data->var_len; if (p_frame_info->num_env > 0) { time_border[0] = p_frame_info->border_vec[p_frame_info->num_env] - 16; } else { time_border[0] = 0; } if (time_border[0] < 0) return -1; pvc_time_border[0] = 0; bs_freq_res[0] = 0; if (bs_noise_pos == 0) { time_border[1] = 16 + var_len; pvc_time_border[1] = 16; bs_num_noise = 1; bs_num_env = 1; } else { time_border[1] = bs_noise_pos; pvc_time_border[1] = bs_noise_pos; time_border[2] = 16 + var_len; pvc_time_border[2] = 16; bs_freq_res[1] = 0; bs_num_noise = 2; bs_num_env = 2; } for (i = 0; i < 3; i++) { time_border_noise[i] = time_border[i]; pvc_time_border_noise[i] = pvc_time_border[i]; } if (prev_sbr_mode == ORIG_SBR) { pvc_time_border[0] = time_border[0]; pvc_time_border_noise[0] = time_border[0]; } pvc_frame_info->num_env = bs_num_env; for (i = 0; i < (bs_num_env + 1); i++) { pvc_frame_info->border_vec[i] = pvc_time_border[i]; } for (i = 0; i < (bs_num_env); i++) { pvc_frame_info->freq_res[i] = bs_freq_res[i]; } pvc_frame_info->transient_env = -1; pvc_frame_info->num_noise_env = bs_num_noise; for (i = 0; i < (bs_num_noise + 1); i++) { pvc_frame_info->noise_border_vec[i] = pvc_time_border_noise[i]; } p_frame_info->num_env = bs_num_env; for (i = 0; i < (bs_num_env + 1); i++) { p_frame_info->border_vec[i] = time_border[i]; } for (i = 0; i < (bs_num_env); i++) { p_frame_info->freq_res[i] = bs_freq_res[i]; } p_frame_info->transient_env = -1; p_frame_info->num_noise_env = bs_num_noise; for (i = 0; i < (bs_num_noise + 1); i++) { p_frame_info->noise_border_vec[i] = time_border_noise[i]; } return 0; } WORD16 ixheaacd_sbr_time_freq_grid_info( ia_bit_buf_struct *it_bit_buff, ia_sbr_frame_info_data_struct *ptr_frame_data, ia_env_extr_tables_struct *env_extr_tables_ptr) { WORD32 i, k, bs_num_rel = 0; WORD32 bs_pointer_bits = 0, bs_num_env = 0, border, bs_pointer, bs_var_bord = 0, temp = 0; WORD32 freq_res_0 = 0, frame_class; WORD32 abs_bord_lead, abs_bord_trail, num_rel_trail, num_rel_lead; WORD32 pointer_bits_array[7] = {1, 2, 2, 3, 3, 3, 3}; ia_frame_info_struct *p_fixfix_tab; ia_frame_info_struct *p_frame_info = &ptr_frame_data->str_frame_info_details; frame_class = ixheaacd_read_bits_buf(it_bit_buff, SBR_FRAME_CLASS_BITS); p_frame_info->frame_class = frame_class; switch (frame_class) { case FIXFIX: temp = ixheaacd_read_bits_buf(it_bit_buff, SBR_ENV_BITS + SBR_FRQ_RES_BITS); bs_num_env = (temp & 0x6) >> SBR_FRQ_RES_BITS; p_fixfix_tab = &env_extr_tables_ptr->sbr_frame_info1_2_4_16[bs_num_env]; memcpy(p_frame_info, p_fixfix_tab, sizeof(ia_frame_info_struct)); bs_num_env = (1 << bs_num_env); freq_res_0 = temp & 0x1; if (!freq_res_0) { memset(&p_frame_info->freq_res[0], 0, sizeof(WORD16) * bs_num_env); } break; case FIXVAR: bs_var_bord = ixheaacd_read_bits_buf(it_bit_buff, SBR_VAR_BORD_BITS + SBR_NUM_BITS); bs_num_rel = bs_var_bord & 3; bs_var_bord = bs_var_bord >> SBR_NUM_BITS; bs_num_env = bs_num_rel + 1; p_frame_info->border_vec[0] = 0; border = bs_var_bord + SBR_TIME_SLOTS; p_frame_info->border_vec[bs_num_env] = border; for (k = bs_num_rel; k > 0; k--) { temp = ixheaacd_read_bits_buf(it_bit_buff, SBR_REL_BITS); border = border - ((temp << 1) + 2); if (border < 0) border = 0; p_frame_info->border_vec[k] = border; } bs_pointer_bits = pointer_bits_array[bs_num_rel]; bs_pointer = ixheaacd_read_bits_buf(it_bit_buff, bs_pointer_bits); if ((bs_pointer - (bs_num_rel + 1)) > 0) return 0; for (k = bs_num_rel; k >= 0; k--) { p_frame_info->freq_res[k] = ixheaacd_read_bits_buf(it_bit_buff, SBR_FRQ_RES_BITS); } if (bs_pointer) { p_frame_info->transient_env = bs_num_env + 1 - bs_pointer; } else { p_frame_info->transient_env = -1; } if ((bs_pointer == 0) || (bs_pointer == 1)) p_frame_info->noise_border_vec[1] = p_frame_info->border_vec[bs_num_rel]; else p_frame_info->noise_border_vec[1] = p_frame_info->border_vec[p_frame_info->transient_env]; break; case VARFIX: bs_var_bord = ixheaacd_read_bits_buf(it_bit_buff, SBR_VAR_BORD_BITS + SBR_NUM_BITS); bs_num_rel = bs_var_bord & 3; bs_var_bord = bs_var_bord >> SBR_NUM_BITS; bs_num_env = bs_num_rel + 1; border = bs_var_bord; p_frame_info->border_vec[0] = border; for (k = 1; k <= bs_num_rel; k++) { temp = ixheaacd_read_bits_buf(it_bit_buff, SBR_REL_BITS); border = border + ((temp << 1) + 2); if (border > SBR_TIME_SLOTS) border = SBR_TIME_SLOTS; p_frame_info->border_vec[k] = border; } p_frame_info->border_vec[k] = SBR_TIME_SLOTS; bs_pointer_bits = pointer_bits_array[bs_num_rel]; bs_pointer = ixheaacd_read_bits_buf(it_bit_buff, bs_pointer_bits); if ((bs_pointer - (bs_num_rel + 1)) > 0) return 0; if (bs_pointer == 0 || (bs_pointer - 1) == 0) { p_frame_info->transient_env = -1; } else { p_frame_info->transient_env = bs_pointer - 1; } for (k = 0; k <= bs_num_rel; k++) { p_frame_info->freq_res[k] = ixheaacd_read_bits_buf(it_bit_buff, SBR_FRQ_RES_BITS); } switch (bs_pointer) { case 0: p_frame_info->noise_border_vec[1] = p_frame_info->border_vec[1]; break; case 1: p_frame_info->noise_border_vec[1] = p_frame_info->border_vec[bs_num_rel]; break; default: p_frame_info->noise_border_vec[1] = p_frame_info->border_vec[(WORD32)p_frame_info->transient_env]; break; } break; case VARVAR: abs_bord_lead = ixheaacd_read_bits_buf( it_bit_buff, 2 * SBR_VAR_BORD_BITS + 2 * SBR_NUM_BITS); abs_bord_trail = (((abs_bord_lead & 0x30) >> (2 * SBR_NUM_BITS)) + SBR_TIME_SLOTS); num_rel_trail = ((abs_bord_lead & 0xc) >> SBR_NUM_BITS); num_rel_lead = (abs_bord_lead & 0x3); abs_bord_lead = abs_bord_lead >> (SBR_VAR_BORD_BITS + 2 * SBR_NUM_BITS); bs_num_env = ((num_rel_trail + num_rel_lead) + 1); border = abs_bord_lead; p_frame_info->border_vec[0] = border; for (k = 1; k <= num_rel_trail; k++) { temp = ixheaacd_read_bits_buf(it_bit_buff, SBR_REL_BITS); border = border + ((temp << 1) + 2); p_frame_info->border_vec[k] = border; } border = abs_bord_trail; i = bs_num_env; p_frame_info->border_vec[i] = border; for (k = 0; k < num_rel_lead; k++) { temp = ixheaacd_read_bits_buf(it_bit_buff, SBR_REL_BITS); border = border - ((temp << 1) + 2); i--; p_frame_info->border_vec[i] = border; } bs_pointer_bits = pointer_bits_array[num_rel_trail + num_rel_lead]; bs_pointer = ixheaacd_read_bits_buf(it_bit_buff, bs_pointer_bits); if ((bs_pointer - ((num_rel_trail + num_rel_lead) + 1)) > 0) return 0; if (bs_pointer) { p_frame_info->transient_env = bs_num_env + 1 - bs_pointer; } else { p_frame_info->transient_env = -1; } for (k = 0; k < bs_num_env; k++) { p_frame_info->freq_res[k] = ixheaacd_read_bits_buf(it_bit_buff, SBR_FRQ_RES_BITS); } p_frame_info->noise_border_vec[0] = abs_bord_lead; if (bs_num_env == 1) { p_frame_info->noise_border_vec[1] = abs_bord_trail; } else { if (bs_pointer == 0 || (bs_pointer - 1) == 0) p_frame_info->noise_border_vec[1] = p_frame_info->border_vec[bs_num_env - 1]; else p_frame_info->noise_border_vec[1] = p_frame_info->border_vec[(WORD32)p_frame_info->transient_env]; p_frame_info->noise_border_vec[2] = abs_bord_trail; } break; } p_frame_info->num_env = bs_num_env; if (bs_num_env == 1) p_frame_info->num_noise_env = 1; else p_frame_info->num_noise_env = 2; if (frame_class == VARFIX || frame_class == FIXVAR) { p_frame_info->noise_border_vec[0] = p_frame_info->border_vec[0]; p_frame_info->noise_border_vec[p_frame_info->num_noise_env] = p_frame_info->border_vec[bs_num_env]; } return 1; }