| /****************************************************************************** |
| * * |
| * 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 <math.h> |
| #include <string.h> |
| #include "ixheaac_type_def.h" |
| #include "ixheaac_constants.h" |
| #include "ixheaac_basic_ops32.h" |
| #include "ixheaac_basic_ops40.h" |
| #include "ixheaacd_bitbuffer.h" |
| #include "ixheaacd_defines.h" |
| #include "ixheaac_sbr_const.h" |
| #include "ixheaacd_memory_standards.h" |
| #include "ixheaacd_sbrdecsettings.h" |
| #include "ixheaacd_env_extr_part.h" |
| #include "ixheaacd_aac_rom.h" |
| #include "ixheaacd_common_rom.h" |
| #include "ixheaacd_sbr_rom.h" |
| #include "ixheaacd_pulsedata.h" |
| #include "ixheaacd_pns.h" |
| #include "ixheaacd_sbr_common.h" |
| #include "ixheaacd_drc_data_struct.h" |
| #include "ixheaacd_cnst.h" |
| #include "ixheaacd_ec_defines.h" |
| #include "ixheaacd_ec_struct_def.h" |
| #include "ixheaacd_error_codes.h" |
| #include "ixheaacd_channelinfo.h" |
| #include "ixheaacd_sbrdecoder.h" |
| #include "ixheaacd_audioobjtypes.h" |
| #include "ixheaacd_latmdemux.h" |
| #include "ixheaacd_aacdec.h" |
| #include "ixheaacd_hybrid.h" |
| #include "ixheaacd_sbr_scale.h" |
| #include "ixheaacd_ps_dec.h" |
| #include "ixheaacd_lpp_tran.h" |
| #include "ixheaacd_env_extr.h" |
| #include "ixheaacd_qmf_dec.h" |
| #include "ixheaacd_env_calc.h" |
| #include "ixheaacd_pvc_dec.h" |
| #include "ixheaacd_sbr_dec.h" |
| #include "ixheaacd_mps_polyphase.h" |
| #include "ixheaacd_config.h" |
| #include "ixheaacd_mps_macro_def.h" |
| #include "ixheaacd_mps_struct_def.h" |
| #include "ixheaacd_mps_res_rom.h" |
| #include "ixheaacd_mps_aac_struct.h" |
| #include "ixheaacd_mps_dec.h" |
| #include "ixheaacd_mps_interface.h" |
| #include "ixheaacd_struct_def.h" |
| #include "ixheaacd_mps_process.h" |
| #include "ixheaacd_mps_bitdec.h" |
| #include "ixheaacd_mps_smoothing.h" |
| #include "ixheaacd_mps_tp_process.h" |
| #include "ixheaacd_mps_reshape_bb_env.h" |
| #include "ixheaacd_mps_blind.h" |
| #include "ixheaacd_mps_m1m2.h" |
| #include "ixheaacd_mps_basic_op.h" |
| #include "ixheaacd_mps_decor.h" |
| #include "ixheaacd_mps_hybfilter.h" |
| #include "ixheaacd_mps_nlc_dec.h" |
| #include "ixheaacd_mps_huff_tab.h" |
| |
| extern const ia_huff_pt0_nodes_struct ixheaacd_huff_part0_nodes; |
| extern const ia_huff_ipd_nodes_struct ixheaacd_huff_ipd_nodes; |
| extern const ia_huff_lav_nodes_struct ixheaacd_huff_lav_idx_nodes; |
| extern const ia_huff_pt0_nodes_struct ixheaacd_huff_pilot_nodes; |
| extern const ia_huff_cld_nodes_struct ixheaacd_huff_cld_nodes; |
| extern const ia_huff_icc_nodes_struct ixheaacd_huff_icc_nodes; |
| extern const ia_huff_cpc_nodes_struct ixheaacd_huff_cpc_nodes; |
| extern const ia_huff_res_nodes_struct ixheaacd_huff_reshape_nodes; |
| |
| WORD32 ixheaacd_mps_create(ia_mps_dec_state_struct* self, WORD32 bs_frame_len, |
| WORD32 residual_coding, |
| ia_usac_dec_mps_config_struct* mps212_config) { |
| WORD32 num_ch; |
| WORD32 err_code = 0; |
| |
| ia_mps_bs_frame bs_frame; |
| |
| self->num_parameter_sets = 1; |
| self->qmf_band_count = 64; |
| |
| self->res_ch_count = 0; |
| |
| if (mps212_config) { |
| self->config = mps212_config; |
| self->frame_length = bs_frame_len; |
| self->in_ch_count = 1; |
| self->out_ch_count = 2; |
| self->residual_coding = residual_coding; |
| if (self->residual_coding) { |
| self->bs_residual_present = 1; |
| self->bs_residual_bands = mps212_config->bs_residual_bands; |
| if (self->config->bs_phase_coding) { |
| self->config->bs_phase_coding = 2; |
| } |
| } |
| } |
| |
| err_code = ixheaacd_mps_header_decode(self); |
| |
| if (err_code != IA_NO_ERROR) { |
| self->mps_init_done = 0; |
| return err_code; |
| } |
| |
| if ((self->residual_coding) && (self->res_bands > 0)) self->res_ch_count++; |
| |
| ixheaacd_mps_env_init(self); |
| |
| self->resolution = self->qmf_band_count; |
| |
| for (num_ch = 0; num_ch < self->out_ch_count; num_ch++) { |
| ixheaacd_mps_synt_init(self->qmf_filt_state[num_ch]); |
| } |
| |
| ixheaacd_mps_qmf_hybrid_analysis_init(&self->hyb_filt_state[0]); |
| |
| if ((self->residual_coding) && (self->res_bands > 0)) |
| ixheaacd_mps_qmf_hybrid_analysis_init(&self->hyb_filt_state[1]); |
| |
| err_code = ixheaacd_mps_decor_init(&(self->mps_decor), self->hyb_band_count_max, |
| self->config->bs_decorr_config, |
| self->object_type); |
| |
| if (err_code != IA_NO_ERROR) { |
| self->mps_init_done = 0; |
| return err_code; |
| } |
| |
| ixheaacd_mps_init_pre_and_post_matrix(self); |
| |
| self->parse_nxt_frame = 1; |
| |
| bs_frame = self->bs_frame; |
| memset(bs_frame.cld_idx_pre, 0, MAX_PARAMETER_BANDS * sizeof(WORD32)); |
| memset(bs_frame.icc_idx_pre, 0, MAX_PARAMETER_BANDS * sizeof(WORD32)); |
| memset(bs_frame.cmp_cld_idx_prev, 0, MAX_PARAMETER_BANDS * sizeof(WORD32)); |
| memset(bs_frame.cmp_icc_idx_prev, 0, MAX_PARAMETER_BANDS * sizeof(WORD32)); |
| |
| self->subband_var.init_flag = 0; |
| self->subband_var.update_old_ener = 0; |
| self->subband_var.nrg_dir = 0; |
| memset(self->subband_var.nrg_diff, 0, 2 * sizeof(FLOAT32)); |
| |
| memset(self->opd_smooth.smooth_l_phase, 0, |
| MAX_PARAMETER_BANDS * sizeof(WORD32)); |
| memset(self->opd_smooth.smooth_r_phase, 0, |
| MAX_PARAMETER_BANDS * sizeof(WORD32)); |
| self->mps_init_done = 1; |
| |
| return 0; |
| } |
| |
| static const FLOAT32 ixheaacd_tsd_mul_re[] = { |
| 1.0f, 0.707106781186548f, 0.0f, -0.707106781186548f, |
| -1.0f, -0.707106781186548f, 0.0f, 0.707106781186548f}; |
| |
| static const FLOAT32 ixheaacd_tsd_mul_im[] = { |
| 0.0f, 0.707106781186548f, 1.0f, 0.707106781186548f, |
| 0.0f, -0.707106781186548f, -1.0f, -0.707106781186548f}; |
| |
| VOID ixheaacd_mps_qmf_hyb_analysis(ia_mps_dec_state_struct* self) { |
| if (self->object_type == AOT_ER_AAC_ELD || |
| self->object_type == AOT_ER_AAC_LD) { |
| WORD32 k, n; |
| |
| for (n = 0; n < self->time_slots; n++) { |
| for (k = 0; k < self->qmf_band_count; k++) { |
| self->hyb_in[0][k][n].re = self->qmf_in[0][n][k].re; |
| self->hyb_in[0][k][n].im = self->qmf_in[0][n][k].im; |
| } |
| } |
| } else { |
| ixheaacd_mps_qmf_hybrid_analysis(&self->hyb_filt_state[0], self->qmf_in[0], |
| self->qmf_band_count, self->time_slots, |
| self->hyb_in[0]); |
| } |
| |
| if ((self->residual_coding) && (self->res_bands > 0)) { |
| ixheaacd_mps_qmf_hybrid_analysis(&self->hyb_filt_state[self->in_ch_count], |
| self->qmf_in[1], self->band_count[1], |
| self->time_slots, self->hyb_res); |
| } |
| } |
| |
| VOID ixheaacd_mps_qmf_hyb_synthesis(ia_mps_dec_state_struct* self) { |
| WORD32 ch; |
| |
| if (self->object_type == AOT_ER_AAC_ELD || |
| self->object_type == AOT_ER_AAC_LD) { |
| WORD32 k, n; |
| for (ch = 0; ch < self->out_ch_count; ch++) { |
| for (n = 0; n < self->time_slots; n++) { |
| for (k = 0; k < self->qmf_band_count; k++) { |
| self->qmf_out_dir[ch][n][k].re = self->hyb_dir_out[ch][n][k].re; |
| self->qmf_out_dir[ch][n][k].im = self->hyb_dir_out[ch][n][k].im; |
| } |
| } |
| } |
| } else { |
| for (ch = 0; ch < self->out_ch_count; ch++) { |
| ixheaacd_mps_qmf_hybrid_synthesis(self->hyb_dir_out[ch], |
| self->qmf_band_count, self->time_slots, |
| self->qmf_out_dir[ch]); |
| } |
| } |
| } |
| |
| VOID ixheaacd_mps_decor(ia_mps_dec_state_struct* self) { |
| WORD32 k, sb_sample, idx; |
| |
| ia_cmplx_flt_struct(*scratch)[MAX_HYBRID_BANDS_MPS]; |
| |
| ia_cmplx_flt_struct coeff; |
| WORD32 band_start = 7; |
| |
| scratch = self->scratch; |
| |
| for (k = self->dir_sig_count; k < self->dir_sig_count + self->decor_sig_count; |
| k++) { |
| if (self->bs_tsd_enable) { |
| for (sb_sample = 0; sb_sample < self->time_slots; sb_sample++) { |
| if (self->bs_tsd_sep_data[sb_sample]) { |
| for (idx = band_start; idx < self->mps_decor.num_bins; idx++) { |
| scratch[sb_sample][idx].re = self->v[k][sb_sample][idx].re; |
| scratch[sb_sample][idx].im = self->v[k][sb_sample][idx].im; |
| self->v[k][sb_sample][idx].re = 0.0f; |
| self->v[k][sb_sample][idx].im = 0.0f; |
| } |
| } |
| } |
| } |
| |
| ixheaacd_mps_decor_apply(&self->mps_decor, self->v[k], self->w_diff[k], |
| self->time_slots, NO_RES_BANDS, |
| self->ldmps_config.ldmps_present_flag); |
| |
| if (self->bs_tsd_enable) { |
| for (sb_sample = 0; sb_sample < self->time_slots; sb_sample++) { |
| if (self->bs_tsd_sep_data[sb_sample]) { |
| coeff.re = ixheaacd_tsd_mul_re[self->bs_tsd_tr_phase_data[sb_sample]]; |
| coeff.im = ixheaacd_tsd_mul_im[self->bs_tsd_tr_phase_data[sb_sample]]; |
| |
| for (idx = band_start; idx < self->mps_decor.num_bins; idx++) { |
| self->w_diff[k][sb_sample][idx].re += |
| coeff.re * scratch[sb_sample][idx].re - |
| coeff.im * scratch[sb_sample][idx].im; |
| self->w_diff[k][sb_sample][idx].im += |
| coeff.im * scratch[sb_sample][idx].re + |
| coeff.re * scratch[sb_sample][idx].im; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| VOID ixheaacd_mps_mix_res_decor(ia_mps_dec_state_struct* self) { |
| WORD32 ts, qs, row, indx; |
| |
| for (ts = 0; ts < self->time_slots; ts++) { |
| for (qs = 0; qs < self->hyb_band_count_max; qs++) { |
| indx = self->hyb_band_to_processing_band_table[qs]; |
| |
| for (row = 0; row < self->dir_sig_count; row++) { |
| self->w_dir[row][ts][qs].re = self->v[row][ts][qs].re; |
| self->w_dir[row][ts][qs].im = self->v[row][ts][qs].im; |
| } |
| |
| for (row = self->dir_sig_count; |
| row < (self->dir_sig_count + self->decor_sig_count); row++) { |
| if (indx < self->res_bands) { |
| self->w_dir[row][ts][qs].re = self->hyb_res[qs][ts].re; |
| self->w_dir[row][ts][qs].im = self->hyb_res[qs][ts].im; |
| } else { |
| self->w_dir[row][ts][qs].re = 0.0f; |
| self->w_dir[row][ts][qs].im = 0.0f; |
| } |
| } |
| |
| for (row = 0; row < self->dir_sig_count; row++) { |
| self->w_diff[row][ts][qs].re = 0.0f; |
| self->w_diff[row][ts][qs].im = 0.0f; |
| } |
| |
| for (row = self->dir_sig_count; |
| row < (self->dir_sig_count + self->decor_sig_count); row++) { |
| if (indx < self->res_bands) { |
| self->w_diff[row][ts][qs].re = 0.0f; |
| self->w_diff[row][ts][qs].im = 0.0f; |
| } |
| } |
| } |
| } |
| } |
| |
| VOID ixheaacd_mps_mix_res_decor_residual_band(ia_mps_dec_state_struct* self) { |
| WORD32 ts, qs, indx; |
| for (qs = 0; qs < self->hyb_band_count_max; qs++) { |
| indx = self->hyb_band_to_processing_band_table[qs]; |
| if (indx >= self->res_bands) { |
| if (qs < self->hyb_band_count[1]) { |
| for (ts = 0; ts < self->time_slots; ts++) { |
| self->w_dir[1][ts][qs].re = 0.0f; |
| self->w_dir[1][ts][qs].im = 0.0f; |
| } |
| } |
| } else { |
| for (ts = 0; ts < self->time_slots; ts++) { |
| self->w_diff[1][ts][qs].re = 0.0f; |
| self->w_diff[1][ts][qs].im = 0.0f; |
| } |
| } |
| } |
| } |
| |
| VOID ixheaacd_mps_create_w(ia_mps_dec_state_struct* self) { |
| ixheaacd_mps_decor(self); |
| ixheaacd_mps_mix_res_decor(self); |
| } |
| |
| VOID ixheaacd_mps_qmf_hyb_analysis_no_pre_mix(ia_mps_dec_state_struct* self) { |
| ixheaacd_mps_qmf_hybrid_analysis_no_pre_mix( |
| &self->hyb_filt_state[0], self->qmf_in[0], self->band_count[0], |
| self->time_slots, self->w_dir[0]); |
| |
| if (self->res_bands) { |
| ixheaacd_mps_qmf_hybrid_analysis_no_pre_mix( |
| &self->hyb_filt_state[1], self->qmf_in[1], self->band_count[1], |
| self->time_slots, self->w_dir[1]); |
| |
| if (self->res_bands != 28) { |
| ixheaacd_mps_decor_apply(&self->mps_decor, self->w_dir[0], |
| self->w_diff[1], self->time_slots, |
| self->res_bands, |
| self->ldmps_config.ldmps_present_flag); |
| |
| ixheaacd_mps_mix_res_decor_residual_band(self); |
| } |
| } else { |
| ixheaacd_mps_decor_apply(&self->mps_decor, self->w_dir[0], self->w_diff[1], |
| self->time_slots, NO_RES_BANDS, |
| self->ldmps_config.ldmps_present_flag); |
| } |
| } |
| |
| WORD32 ixheaacd_mps_apply(ia_mps_dec_state_struct* self, |
| FLOAT32** input_buffer[4], |
| FLOAT32 (*output_buffer)[4096]) { |
| WORD32 ch, ts, qs; |
| WORD32 time_slots = self->time_slots; |
| WORD32 in_ch_count = self->in_ch_count + self->res_ch_count; |
| WORD32 err = 0; |
| self->hyb_band_count[0] = self->band_count[0] - QMF_BANDS_TO_HYBRID + 10; |
| self->hyb_band_count[1] = self->band_count[1] - QMF_BANDS_TO_HYBRID + 10; |
| self->hyb_band_count_max = |
| max(self->hyb_band_count[0], self->hyb_band_count[1]); |
| self->mps_decor.decor_nrg_smooth.num_bins = self->hyb_band_count_max; |
| self->mps_decor.num_bins = self->hyb_band_count_max; |
| self->output_buffer = output_buffer; |
| |
| err = ixheaacd_mps_frame_decode(self); |
| |
| if (err != IA_NO_ERROR) return err; |
| |
| ixheaacd_pre_and_mix_matrix_calculation(self); |
| |
| ixheaacd_mps_pre_matrix_mix_matrix_smoothing(self); |
| |
| for (ch = 0; ch < in_ch_count; ch++) { |
| for (ts = 0; ts < time_slots; ts++) { |
| for (qs = 0; qs < self->band_count[ch]; qs++) { |
| self->qmf_in[ch][qs][ts].re = |
| self->input_gain * input_buffer[2 * ch][ts][qs]; |
| self->qmf_in[ch][qs][ts].im = |
| self->input_gain * input_buffer[2 * ch + 1][ts][qs]; |
| } |
| } |
| } |
| |
| if (!(self->pre_mix_req | self->bs_tsd_enable)) { |
| ixheaacd_mps_qmf_hyb_analysis_no_pre_mix(self); |
| } else { |
| ixheaacd_mps_qmf_hyb_analysis(self); |
| |
| ixheaacd_mps_apply_pre_matrix(self); |
| |
| ixheaacd_mps_create_w(self); |
| } |
| |
| if ((!(self->res_bands | self->pre_mix_req)) && |
| (self->config->bs_phase_coding == 0)) { |
| ixheaacd_mps_apply_mix_matrix_type1(self); |
| |
| } else if (self->pre_mix_req) { |
| ixheaacd_mps_apply_mix_matrix_type2(self); |
| |
| } else { |
| ixheaacd_mps_apply_mix_matrix_type3(self); |
| } |
| |
| if (self->config->bs_temp_shape_config == 2) { |
| ixheaacd_mps_time_env_shaping(self); |
| } |
| |
| err = ixheaacd_mps_temp_process(self); |
| if (err) return err; |
| |
| self->parse_nxt_frame = 1; |
| self->pre_mix_req = 0; |
| return 0; |
| } |
| |
| static VOID ixheaacd_mps_pcm_decode(ia_bit_buf_struct *it_bit_buff, |
| WORD32* out_data_1, WORD32* out_data_2, |
| WORD32 ixheaacd_drc_offset, WORD32 num_val, |
| WORD32 num_levels) { |
| WORD32 i = 0, j = 0, idx = 0; |
| WORD32 max_grp_len = 0, grp_len = 0, next_val = 0, grp_val = 0; |
| UWORD32 data = 0; |
| |
| FLOAT32 ld_nlev = 0.f; |
| |
| WORD32 pcm_chunk_size[7] = {0}; |
| |
| switch (num_levels) { |
| case 3: |
| max_grp_len = 5; |
| break; |
| case 7: |
| max_grp_len = 6; |
| break; |
| case 11: |
| max_grp_len = 2; |
| break; |
| case 13: |
| max_grp_len = 4; |
| break; |
| case 19: |
| max_grp_len = 4; |
| break; |
| case 25: |
| max_grp_len = 3; |
| break; |
| case 51: |
| max_grp_len = 4; |
| break; |
| case 4: |
| case 8: |
| case 15: |
| case 16: |
| case 26: |
| case 31: |
| max_grp_len = 1; |
| break; |
| default: |
| return; |
| } |
| |
| ld_nlev = (FLOAT32)(log((FLOAT32)num_levels) / log(2.f)); |
| |
| for (i = 1; i <= max_grp_len; i++) { |
| pcm_chunk_size[i] = (WORD32)ceil((FLOAT32)(i)*ld_nlev); |
| } |
| |
| for (i = 0; i < num_val; i += max_grp_len) { |
| grp_len = min(max_grp_len, num_val - i); |
| data = ixheaacd_read_bits_buf(it_bit_buff, pcm_chunk_size[grp_len]); |
| |
| grp_val = data; |
| |
| for (j = 0; j < grp_len; j++) { |
| idx = i + (grp_len - j - 1); |
| next_val = grp_val % num_levels; |
| |
| if (out_data_2 == NULL) { |
| out_data_1[idx] = next_val - ixheaacd_drc_offset; |
| } else if (out_data_1 == NULL) { |
| out_data_2[idx] = next_val - ixheaacd_drc_offset; |
| } else { |
| if (idx % 2) { |
| out_data_2[idx / 2] = next_val - ixheaacd_drc_offset; |
| } else { |
| out_data_1[idx / 2] = next_val - ixheaacd_drc_offset; |
| } |
| } |
| |
| grp_val = (grp_val - next_val) / num_levels; |
| } |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_read(ia_bit_buf_struct *it_bit_buff, |
| const WORD32 (*node_tab)[][2], |
| WORD32* out_data) { |
| WORD32 node = 0; |
| UWORD32 next_bit = 0; |
| |
| do { |
| next_bit = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| node = (*node_tab)[node][next_bit]; |
| } while (node > 0); |
| |
| *out_data = node; |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_read_2d(ia_bit_buf_struct *it_bit_buff, |
| const WORD32 (*node_tab)[][2], |
| WORD32 out_data[2], WORD32* escape) |
| |
| { |
| WORD32 huff_2d_8bit = 0; |
| WORD32 node = 0; |
| |
| ixheaacd_mps_huff_read(it_bit_buff, node_tab, &node); |
| *escape = (node == 0); |
| |
| if (*escape) { |
| out_data[0] = 0; |
| out_data[1] = 1; |
| } else { |
| huff_2d_8bit = -(node + 1); |
| out_data[0] = huff_2d_8bit >> 4; |
| out_data[1] = huff_2d_8bit & 0xf; |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_sym_restore(ia_bit_buf_struct *it_bit_buff, |
| WORD32 lav, WORD32 data[2]) { |
| WORD32 tmp = 0; |
| UWORD32 sym_bit = 0; |
| |
| WORD32 sum_val = data[0] + data[1]; |
| WORD32 diff_val = data[0] - data[1]; |
| |
| if (sum_val > lav) { |
| data[0] = -sum_val + (2 * lav + 1); |
| data[1] = -diff_val; |
| } else { |
| data[0] = sum_val; |
| data[1] = diff_val; |
| } |
| |
| if (data[0] + data[1] != 0) { |
| sym_bit = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| if (sym_bit) { |
| data[0] = -data[0]; |
| data[1] = -data[1]; |
| } |
| } |
| |
| if (data[0] - data[1] != 0) { |
| sym_bit = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| if (sym_bit) { |
| tmp = data[0]; |
| data[0] = data[1]; |
| data[1] = tmp; |
| } |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_sym_restoreipd(ia_bit_buf_struct *it_bit_buff, |
| WORD32 lav, WORD32 data[2]) { |
| WORD32 tmp = 0; |
| UWORD32 sym_bit = 0; |
| |
| WORD32 sum_val = data[0] + data[1]; |
| WORD32 diff_val = data[0] - data[1]; |
| |
| if (sum_val > lav) { |
| data[0] = -sum_val + (2 * lav + 1); |
| data[1] = -diff_val; |
| } else { |
| data[0] = sum_val; |
| data[1] = diff_val; |
| } |
| |
| if (data[0] - data[1] != 0) { |
| sym_bit = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| if (sym_bit) { |
| tmp = data[0]; |
| data[0] = data[1]; |
| data[1] = tmp; |
| } |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_dec_pilot(ia_bit_buf_struct *it_bit_buff, |
| const WORD32 (*node_tab)[][2], |
| WORD32* pilot_data) { |
| WORD32 node = 0; |
| |
| ixheaacd_mps_huff_read(it_bit_buff, node_tab, &node); |
| *pilot_data = -(node + 1); |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_dec_cld_1d( |
| ia_bit_buf_struct *it_bit_buff, |
| const ia_huff_cld_node_1d_struct* huff_nodes, WORD32* out_data, |
| WORD32 num_val, WORD32 p0_flag) { |
| WORD32 i = 0, node = 0, ixheaacd_drc_offset = 0; |
| WORD32 od = 0, od_sign = 0; |
| UWORD32 data = 0; |
| |
| if (p0_flag) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&ixheaacd_huff_part0_nodes.cld, |
| &node); |
| out_data[0] = -(node + 1); |
| ixheaacd_drc_offset = 1; |
| } |
| |
| for (i = ixheaacd_drc_offset; i < num_val; i++) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->node_tab, &node); |
| od = -(node + 1); |
| |
| if (od != 0) { |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| od_sign = data; |
| |
| if (od_sign) od = -od; |
| } |
| |
| out_data[i] = od; |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_dec_ipd_1d( |
| ia_bit_buf_struct *it_bit_buff, |
| const ia_huff_ipd_node_1d_struct* huff_nodes, WORD32* out_data, |
| WORD32 num_val, WORD32 p0_flag) { |
| WORD32 i = 0, node = 0, ixheaacd_drc_offset = 0; |
| WORD32 od = 0; |
| |
| if (p0_flag) { |
| ixheaacd_mps_huff_read( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_ipd_nodes.hp0.node_tab, |
| &node); |
| out_data[0] = -(node + 1); |
| ixheaacd_drc_offset = 1; |
| } |
| |
| for (i = ixheaacd_drc_offset; i < num_val; i++) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->node_tab, &node); |
| od = -(node + 1); |
| out_data[i] = od; |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_dec_icc_1d( |
| ia_bit_buf_struct *it_bit_buff, |
| const ia_huff_icc_node_1d_struct* huff_nodes, WORD32* out_data, |
| WORD32 num_val, WORD32 p0_flag) { |
| WORD32 i = 0, node = 0, ixheaacd_drc_offset = 0; |
| WORD32 od = 0, od_sign = 0; |
| UWORD32 data = 0; |
| |
| if (p0_flag) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&ixheaacd_huff_part0_nodes.icc, |
| &node); |
| out_data[0] = -(node + 1); |
| ixheaacd_drc_offset = 1; |
| } |
| |
| for (i = ixheaacd_drc_offset; i < num_val; i++) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->node_tab, &node); |
| od = -(node + 1); |
| |
| if (od != 0) { |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| od_sign = data; |
| |
| if (od_sign) od = -od; |
| } |
| |
| out_data[i] = od; |
| } |
| |
| return; |
| } |
| |
| static VOID ia_mps_dec_huff_dec_cpc_1d( |
| const ia_huff_cpc_node_1d_struct *huff_nodes, WORD32 *out_data, |
| WORD32 num_val, WORD32 p0_flag, ia_bit_buf_struct *h_bit_buf) { |
| WORD32 i = 0, node = 0, offset = 0; |
| WORD32 od = 0, od_sign = 0; |
| WORD32 data = 0; |
| |
| if (p0_flag) { |
| ixheaacd_mps_huff_read( |
| h_bit_buf, (ia_huff_node_struct) & (ixheaacd_huff_part0_nodes.cpc), |
| &node); |
| out_data[0] = -(node + 1); |
| offset = 1; |
| } |
| |
| for (i = offset; i < num_val; i++) { |
| ixheaacd_mps_huff_read(h_bit_buf, |
| (ia_huff_node_struct)&huff_nodes->node_tab, &node); |
| od = -(node + 1); |
| |
| if (od != 0) { |
| data = ixheaacd_read_bits_buf(h_bit_buf, 1); |
| od_sign = data; |
| |
| if (od_sign) od = -od; |
| } |
| |
| out_data[i] = od; |
| } |
| } |
| |
| static VOID ixheaacd_mps_huff_dec_cld_2d( |
| ia_bit_buf_struct *it_bit_buff, |
| const ia_huff_cld_node_2d_struct* huff_nodes, WORD32 out_data[][2], |
| WORD32 num_val, WORD32 ch_fac, WORD32* p0_data[2]) { |
| WORD32 i = 0, lav = 0, escape = 0, esc_contrl = 0; |
| WORD32 node = 0; |
| UWORD32 data = 0; |
| |
| WORD32 esc_data[MAXBANDS][2] = {{0}}; |
| WORD32 esc_idx[MAXBANDS] = {0}; |
| |
| ixheaacd_mps_huff_read( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_lav_idx_nodes.node_tab, |
| &node); |
| data = -(node + 1); |
| |
| lav = 2 * data + 3; |
| |
| if (p0_data[0] != NULL) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&ixheaacd_huff_part0_nodes.cld, |
| &node); |
| *p0_data[0] = -(node + 1); |
| } |
| if (p0_data[1] != NULL) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&ixheaacd_huff_part0_nodes.cld, |
| &node); |
| *p0_data[1] = -(node + 1); |
| } |
| |
| for (i = 0; i < num_val; i += ch_fac) { |
| switch (lav) { |
| case 3: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav3, |
| out_data[i], &escape); |
| break; |
| case 5: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav5, |
| out_data[i], &escape); |
| break; |
| case 7: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav7, |
| out_data[i], &escape); |
| break; |
| case 9: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav9, |
| out_data[i], &escape); |
| break; |
| default: |
| break; |
| } |
| |
| if (escape) { |
| esc_idx[esc_contrl++] = i; |
| } else { |
| ixheaacd_mps_sym_restore(it_bit_buff, lav, out_data[i]); |
| } |
| } |
| |
| if (esc_contrl > 0) { |
| ixheaacd_mps_pcm_decode(it_bit_buff, esc_data[0], esc_data[1], 0, |
| 2 * esc_contrl, (2 * lav + 1)); |
| |
| for (i = 0; i < esc_contrl; i++) { |
| out_data[esc_idx[i]][0] = esc_data[0][i] - lav; |
| out_data[esc_idx[i]][1] = esc_data[1][i] - lav; |
| } |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_dec_icc_2d( |
| ia_bit_buf_struct *it_bit_buff, |
| const ia_huff_icc_node_2d_struct* huff_nodes, WORD32 out_data[][2], |
| WORD32 num_val, WORD32 ch_fac, WORD32* p0_data[2]) { |
| WORD32 i = 0, lav = 0, escape = 0, esc_contrl = 0; |
| WORD32 node = 0; |
| UWORD32 data = 0; |
| |
| WORD32 esc_data[2][MAXBANDS] = {{0}}; |
| WORD32 esc_idx[MAXBANDS] = {0}; |
| |
| ixheaacd_mps_huff_read( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_lav_idx_nodes.node_tab, |
| &node); |
| data = -(node + 1); |
| |
| lav = 2 * data + 1; |
| |
| if (p0_data[0] != NULL) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&ixheaacd_huff_part0_nodes.icc, |
| &node); |
| *p0_data[0] = -(node + 1); |
| } |
| if (p0_data[1] != NULL) { |
| ixheaacd_mps_huff_read(it_bit_buff, |
| (ia_huff_node_struct)&ixheaacd_huff_part0_nodes.icc, |
| &node); |
| *p0_data[1] = -(node + 1); |
| } |
| |
| for (i = 0; i < num_val; i += ch_fac) { |
| switch (lav) { |
| case 1: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav1, |
| out_data[i], &escape); |
| break; |
| case 3: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav3, |
| out_data[i], &escape); |
| break; |
| case 5: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav5, |
| out_data[i], &escape); |
| break; |
| case 7: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav7, |
| out_data[i], &escape); |
| break; |
| } |
| |
| if (escape) { |
| esc_idx[esc_contrl++] = i; |
| } else { |
| ixheaacd_mps_sym_restore(it_bit_buff, lav, out_data[i]); |
| } |
| } |
| |
| if (esc_contrl > 0) { |
| ixheaacd_mps_pcm_decode(it_bit_buff, esc_data[0], esc_data[1], 0, |
| 2 * esc_contrl, (2 * lav + 1)); |
| |
| for (i = 0; i < esc_contrl; i++) { |
| out_data[esc_idx[i]][0] = esc_data[0][i] - lav; |
| out_data[esc_idx[i]][1] = esc_data[1][i] - lav; |
| } |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_mps_huff_dec_ipd_2d( |
| ia_bit_buf_struct *it_bit_buff, |
| const ia_huff_ipd_node_2d_struct* huff_nodes, WORD32 out_data[][2], |
| WORD32 num_val, WORD32 ch_fac, WORD32* p0_data[2]) { |
| WORD32 i = 0, lav = 0, escape = 0, esc_contrl = 0; |
| WORD32 node = 0; |
| UWORD32 data = 0; |
| |
| WORD32 esc_data[2][MAXBANDS] = {{0}}; |
| WORD32 esc_idx[MAXBANDS] = {0}; |
| |
| ixheaacd_mps_huff_read( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_lav_idx_nodes.node_tab, |
| &node); |
| |
| data = -(node + 1); |
| if (data == 0) |
| data = 3; |
| else |
| data--; |
| |
| lav = 2 * data + 1; |
| |
| if (p0_data[0] != NULL) { |
| ixheaacd_mps_huff_read( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_ipd_nodes.hp0.node_tab, |
| &node); |
| *p0_data[0] = -(node + 1); |
| } |
| if (p0_data[1] != NULL) { |
| ixheaacd_mps_huff_read( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_ipd_nodes.hp0.node_tab, |
| &node); |
| *p0_data[1] = -(node + 1); |
| } |
| |
| for (i = 0; i < num_val; i += ch_fac) { |
| switch (lav) { |
| case 1: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav1, |
| out_data[i], &escape); |
| break; |
| case 3: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav3, |
| out_data[i], &escape); |
| break; |
| case 5: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav5, |
| out_data[i], &escape); |
| break; |
| case 7: |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&huff_nodes->lav7, |
| out_data[i], &escape); |
| break; |
| } |
| |
| if (escape) { |
| esc_idx[esc_contrl++] = i; |
| } else { |
| ixheaacd_mps_sym_restoreipd(it_bit_buff, lav, out_data[i]); |
| } |
| } |
| |
| if (esc_contrl > 0) { |
| ixheaacd_mps_pcm_decode(it_bit_buff, esc_data[0], esc_data[1], 0, |
| 2 * esc_contrl, (2 * lav + 1)); |
| |
| for (i = 0; i < esc_contrl; i++) { |
| out_data[esc_idx[i]][0] = esc_data[0][i] - lav; |
| out_data[esc_idx[i]][1] = esc_data[1][i] - lav; |
| } |
| } |
| |
| return; |
| } |
| |
| static VOID ia_mps_dec_huff_dec_cpc_2d( |
| const ia_mps_dec_huff_cpc_nod_2d *huff_nodes, WORD32 out_data[][2], |
| WORD32 num_val, WORD32 stride, WORD32 *p0_data[2], |
| ia_bit_buf_struct *h_bit_buf) { |
| WORD32 i = 0, lav = 0, escape = 0, esc_cntr = 0; |
| WORD32 node = 0; |
| WORD32 data = 0; |
| |
| WORD32 esc_data[2][MAXBANDS] = {{0}}; |
| WORD32 esc_idx[MAXBANDS] = {0}; |
| |
| ixheaacd_mps_huff_read( |
| h_bit_buf, (ia_huff_node_struct) & (ixheaacd_huff_lav_idx_nodes.node_tab), |
| &node); |
| data = -(node + 1); |
| |
| lav = 3 * data + 3; |
| |
| if (p0_data[0] != NULL) { |
| ixheaacd_mps_huff_read( |
| h_bit_buf, (ia_huff_node_struct) & (ixheaacd_huff_part0_nodes.cpc), |
| &node); |
| *p0_data[0] = -(node + 1); |
| } |
| if (p0_data[1] != NULL) { |
| ixheaacd_mps_huff_read( |
| h_bit_buf, (ia_huff_node_struct) & (ixheaacd_huff_part0_nodes.cpc), |
| &node); |
| *p0_data[1] = -(node + 1); |
| } |
| |
| for (i = 0; i < num_val; i += stride) { |
| switch (lav) { |
| case LAV_3: |
| ixheaacd_mps_huff_read_2d(h_bit_buf, |
| (ia_huff_node_struct)&huff_nodes->lav3, |
| out_data[i], &escape); |
| break; |
| case LAV_6: |
| ixheaacd_mps_huff_read_2d(h_bit_buf, |
| (ia_huff_node_struct)&huff_nodes->lav6, |
| out_data[i], &escape); |
| break; |
| case LAV_9: |
| ixheaacd_mps_huff_read_2d(h_bit_buf, |
| (ia_huff_node_struct)&huff_nodes->lav9, |
| out_data[i], &escape); |
| break; |
| case LAV_12: |
| ixheaacd_mps_huff_read_2d(h_bit_buf, |
| (ia_huff_node_struct)&huff_nodes->lav12, |
| out_data[i], &escape); |
| break; |
| default: |
| break; |
| } |
| |
| if (escape) { |
| esc_idx[esc_cntr++] = i; |
| } else { |
| ixheaacd_mps_sym_restore(h_bit_buf, lav, out_data[i]); |
| } |
| } |
| |
| if (esc_cntr > 0) { |
| ixheaacd_mps_pcm_decode(h_bit_buf, esc_data[0], esc_data[1], 0, |
| (esc_cntr << 1), ((lav << 1) + 1)); |
| |
| for (i = 0; i < esc_cntr; i++) { |
| out_data[esc_idx[i]][0] = esc_data[0][i] - lav; |
| out_data[esc_idx[i]][1] = esc_data[1][i] - lav; |
| } |
| } |
| return; |
| } |
| |
| static VOID ixheaacd_huff_decode(ia_bit_buf_struct *it_bit_buff, WORD32 *out_data_1, |
| WORD32 *out_data_2, WORD32 data_type, WORD32 diff_type_1, |
| WORD32 diff_type_2, WORD32 pilot_coding_flag, WORD32 *pilot_data, |
| WORD32 num_val, WORD32 *cdg_scheme, WORD32 ld_mps_flag) { |
| WORD32 diff_type; |
| |
| WORD32 i = 0; |
| UWORD32 data = 0; |
| |
| WORD32 pair_vec[MAXBANDS][2]; |
| |
| WORD32* p0_data_1[2] = {NULL, NULL}; |
| WORD32* p0_data_2[2] = {NULL, NULL}; |
| |
| WORD32 p0_flag[2]; |
| |
| WORD32 num_val_1_int = num_val; |
| WORD32 num_val_2_int = num_val; |
| |
| WORD32* out_data_1_int = out_data_1; |
| WORD32* out_data_2_int = out_data_2; |
| |
| WORD32 df_rest_flag_1 = 0; |
| WORD32 df_rest_flag_2 = 0; |
| |
| WORD32 huff_yy_1; |
| WORD32 huff_yy_2; |
| WORD32 huff_yy; |
| if (pilot_coding_flag) { |
| switch (data_type) { |
| case CLD: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_pilot( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_pilot_nodes.cld, |
| pilot_data); |
| } |
| break; |
| |
| case ICC: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_pilot( |
| it_bit_buff, (ia_huff_node_struct)&ixheaacd_huff_pilot_nodes.icc, |
| pilot_data); |
| } |
| break; |
| |
| case CPC: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_pilot( |
| it_bit_buff, |
| (ia_huff_node_struct) & (ixheaacd_huff_pilot_nodes.cpc), |
| pilot_data); |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| *cdg_scheme = data << PAIR_SHIFT; |
| |
| if (*cdg_scheme >> PAIR_SHIFT == HUFF_2D) { |
| if ((out_data_1 != NULL) && (out_data_2 != NULL) && (ld_mps_flag != 1)) { |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| *cdg_scheme |= data; |
| } else { |
| *cdg_scheme |= FREQ_PAIR; |
| } |
| } |
| |
| if (pilot_coding_flag) { |
| huff_yy_1 = PCM_PLT; |
| huff_yy_2 = PCM_PLT; |
| } else { |
| huff_yy_1 = diff_type_1; |
| huff_yy_2 = diff_type_2; |
| } |
| |
| switch (*cdg_scheme >> PAIR_SHIFT) { |
| case HUFF_1D: |
| |
| p0_flag[0] = (diff_type_1 == DIFF_FREQ) && !pilot_coding_flag; |
| p0_flag[1] = (diff_type_2 == DIFF_FREQ) && !pilot_coding_flag; |
| |
| switch (data_type) { |
| case CLD: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_cld_1d( |
| it_bit_buff, &ixheaacd_huff_cld_nodes.h_1_dim[huff_yy_1], |
| out_data_1, num_val_1_int, p0_flag[0]); |
| } |
| if (out_data_2 != NULL) { |
| ixheaacd_mps_huff_dec_cld_1d( |
| it_bit_buff, &ixheaacd_huff_cld_nodes.h_1_dim[huff_yy_2], |
| out_data_2, num_val_2_int, p0_flag[1]); |
| } |
| |
| break; |
| |
| case ICC: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_icc_1d( |
| it_bit_buff, &ixheaacd_huff_icc_nodes.h_1_dim[huff_yy_1], |
| out_data_1, num_val_1_int, p0_flag[0]); |
| } |
| if (out_data_2 != NULL) { |
| ixheaacd_mps_huff_dec_icc_1d( |
| it_bit_buff, &ixheaacd_huff_icc_nodes.h_1_dim[huff_yy_2], |
| out_data_2, num_val_2_int, p0_flag[1]); |
| } |
| |
| break; |
| |
| case IPD: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_ipd_1d( |
| it_bit_buff, &ixheaacd_huff_ipd_nodes.h_1_dim[huff_yy_1], |
| out_data_1, num_val_1_int, p0_flag[0]); |
| } |
| if (out_data_2 != NULL) { |
| ixheaacd_mps_huff_dec_ipd_1d( |
| it_bit_buff, &ixheaacd_huff_ipd_nodes.h_1_dim[huff_yy_2], |
| out_data_2, num_val_2_int, p0_flag[1]); |
| } |
| |
| break; |
| case CPC: |
| if (out_data_1 != NULL) { |
| ia_mps_dec_huff_dec_cpc_1d( |
| &(ixheaacd_huff_cpc_nodes.h_1_dim[huff_yy_1]), out_data_1, |
| num_val_1_int, p0_flag[0], it_bit_buff); |
| } |
| if (out_data_2 != NULL) { |
| ia_mps_dec_huff_dec_cpc_1d( |
| &(ixheaacd_huff_cpc_nodes.h_1_dim[huff_yy_2]), out_data_2, |
| num_val_2_int, p0_flag[1], it_bit_buff); |
| } |
| |
| break; |
| default: |
| break; |
| } |
| |
| break; |
| |
| case HUFF_2D: |
| |
| switch (*cdg_scheme & PAIR_MASK) { |
| case FREQ_PAIR: |
| |
| if (out_data_1 != NULL) { |
| if (!pilot_coding_flag && diff_type_1 == DIFF_FREQ) { |
| p0_data_1[0] = &out_data_1[0]; |
| p0_data_1[1] = NULL; |
| |
| num_val_1_int -= 1; |
| out_data_1_int += 1; |
| } |
| df_rest_flag_1 = num_val_1_int % 2; |
| if (df_rest_flag_1) num_val_1_int -= 1; |
| } |
| if (out_data_2 != NULL) { |
| if (!pilot_coding_flag && diff_type_2 == DIFF_FREQ) { |
| p0_data_2[0] = NULL; |
| p0_data_2[1] = &out_data_2[0]; |
| |
| num_val_2_int -= 1; |
| out_data_2_int += 1; |
| } |
| df_rest_flag_2 = num_val_2_int % 2; |
| if (df_rest_flag_2) num_val_2_int -= 1; |
| } |
| |
| switch (data_type) { |
| case CLD: |
| |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_cld_2d( |
| it_bit_buff, |
| &ixheaacd_huff_cld_nodes.h_2_dim[huff_yy_1][FREQ_PAIR], |
| pair_vec, num_val_1_int, 2, p0_data_1); |
| if (df_rest_flag_1) { |
| ixheaacd_mps_huff_dec_cld_1d( |
| it_bit_buff, &ixheaacd_huff_cld_nodes.h_1_dim[huff_yy_1], |
| out_data_1_int + num_val_1_int, 1, 0); |
| } |
| } |
| if (out_data_2 != NULL) { |
| ixheaacd_mps_huff_dec_cld_2d( |
| it_bit_buff, |
| &ixheaacd_huff_cld_nodes.h_2_dim[huff_yy_2][FREQ_PAIR], |
| pair_vec + 1, num_val_2_int, 2, p0_data_2); |
| if (df_rest_flag_2) { |
| ixheaacd_mps_huff_dec_cld_1d( |
| it_bit_buff, &ixheaacd_huff_cld_nodes.h_1_dim[huff_yy_2], |
| out_data_2_int + num_val_2_int, 1, 0); |
| } |
| } |
| break; |
| |
| case ICC: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_icc_2d( |
| it_bit_buff, |
| &ixheaacd_huff_icc_nodes.h_2_dim[huff_yy_1][FREQ_PAIR], |
| pair_vec, num_val_1_int, 2, p0_data_1); |
| if (df_rest_flag_1) { |
| ixheaacd_mps_huff_dec_icc_1d( |
| it_bit_buff, &ixheaacd_huff_icc_nodes.h_1_dim[huff_yy_1], |
| out_data_1_int + num_val_1_int, 1, 0); |
| } |
| } |
| if (out_data_2 != NULL) { |
| ixheaacd_mps_huff_dec_icc_2d( |
| it_bit_buff, |
| &ixheaacd_huff_icc_nodes.h_2_dim[huff_yy_2][FREQ_PAIR], |
| pair_vec + 1, num_val_2_int, 2, p0_data_2); |
| if (df_rest_flag_2) { |
| ixheaacd_mps_huff_dec_icc_1d( |
| it_bit_buff, &ixheaacd_huff_icc_nodes.h_1_dim[huff_yy_2], |
| out_data_2_int + num_val_2_int, 1, 0); |
| } |
| } |
| break; |
| |
| case IPD: |
| if (out_data_1 != NULL) { |
| ixheaacd_mps_huff_dec_ipd_2d( |
| it_bit_buff, |
| &ixheaacd_huff_ipd_nodes.h_2_dim[huff_yy_1][FREQ_PAIR], |
| pair_vec, num_val_1_int, 2, p0_data_1); |
| if (df_rest_flag_1) { |
| ixheaacd_mps_huff_dec_ipd_1d( |
| it_bit_buff, &ixheaacd_huff_ipd_nodes.h_1_dim[huff_yy_1], |
| out_data_1_int + num_val_1_int, 1, 0); |
| } |
| } |
| if (out_data_2 != NULL) { |
| ixheaacd_mps_huff_dec_ipd_2d( |
| it_bit_buff, |
| &ixheaacd_huff_ipd_nodes.h_2_dim[huff_yy_2][FREQ_PAIR], |
| pair_vec + 1, num_val_2_int, 2, p0_data_2); |
| if (df_rest_flag_2) { |
| ixheaacd_mps_huff_dec_ipd_1d( |
| it_bit_buff, &ixheaacd_huff_ipd_nodes.h_1_dim[huff_yy_2], |
| out_data_2_int + num_val_2_int, 1, 0); |
| } |
| } |
| break; |
| case CPC: |
| if (out_data_1 != NULL) { |
| ia_mps_dec_huff_dec_cpc_2d( |
| &(ixheaacd_huff_cpc_nodes.h_2_dim[huff_yy_1][FREQ_PAIR]), pair_vec, |
| num_val_1_int, 2, p0_data_1, it_bit_buff); |
| if (df_rest_flag_1) { |
| ia_mps_dec_huff_dec_cpc_1d(&(ixheaacd_huff_cpc_nodes.h_1_dim[huff_yy_1]), |
| out_data_1_int + num_val_1_int, 1, 0, it_bit_buff); |
| } |
| } |
| if (out_data_2 != NULL) { |
| ia_mps_dec_huff_dec_cpc_2d( |
| &(ixheaacd_huff_cpc_nodes.h_2_dim[huff_yy_2][FREQ_PAIR]), pair_vec + 1, |
| num_val_2_int, 2, p0_data_2, it_bit_buff); |
| |
| if (df_rest_flag_2) { |
| ia_mps_dec_huff_dec_cpc_1d( |
| &(ixheaacd_huff_cpc_nodes.h_1_dim[huff_yy_2]), |
| out_data_2_int + num_val_2_int, 1, 0, it_bit_buff); |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| |
| if (out_data_1 != NULL) { |
| for (i = 0; i < num_val_1_int - 1; i += 2) { |
| out_data_1_int[i] = pair_vec[i][0]; |
| out_data_1_int[i + 1] = pair_vec[i][1]; |
| } |
| } |
| if (out_data_2 != NULL) { |
| for (i = 0; i < num_val_2_int - 1; i += 2) { |
| out_data_2_int[i] = pair_vec[i + 1][0]; |
| out_data_2_int[i + 1] = pair_vec[i + 1][1]; |
| } |
| } |
| |
| break; |
| |
| case TIME_PAIR: |
| |
| if (!pilot_coding_flag && |
| ((diff_type_1 == DIFF_FREQ) || (diff_type_2 == DIFF_FREQ))) { |
| p0_data_1[0] = &out_data_1[0]; |
| p0_data_1[1] = &out_data_2[0]; |
| |
| out_data_1_int += 1; |
| out_data_2_int += 1; |
| |
| num_val_1_int -= 1; |
| } |
| |
| if ((diff_type_1 == DIFF_TIME) || (diff_type_2 == DIFF_TIME)) { |
| diff_type = DIFF_TIME; |
| } else { |
| diff_type = DIFF_FREQ; |
| } |
| if (pilot_coding_flag) { |
| huff_yy = PCM_PLT; |
| } else { |
| huff_yy = diff_type; |
| } |
| |
| switch (data_type) { |
| case CLD: |
| ixheaacd_mps_huff_dec_cld_2d( |
| it_bit_buff, |
| &ixheaacd_huff_cld_nodes.h_2_dim[huff_yy][TIME_PAIR], |
| pair_vec, num_val_1_int, 1, p0_data_1); |
| break; |
| |
| case ICC: |
| ixheaacd_mps_huff_dec_icc_2d( |
| it_bit_buff, |
| &ixheaacd_huff_icc_nodes.h_2_dim[huff_yy][TIME_PAIR], |
| pair_vec, num_val_1_int, 1, p0_data_1); |
| break; |
| |
| case IPD: |
| ixheaacd_mps_huff_dec_ipd_2d( |
| it_bit_buff, |
| &ixheaacd_huff_ipd_nodes.h_2_dim[huff_yy][TIME_PAIR], |
| pair_vec, num_val_1_int, 1, p0_data_1); |
| break; |
| case CPC: |
| ia_mps_dec_huff_dec_cpc_2d(&(ixheaacd_huff_cpc_nodes.h_2_dim[huff_yy][TIME_PAIR]), |
| pair_vec, num_val_1_int, 1, p0_data_1, it_bit_buff); |
| break; |
| default: |
| break; |
| } |
| |
| for (i = 0; i < num_val_1_int; i++) { |
| out_data_1_int[i] = pair_vec[i][0]; |
| out_data_2_int[i] = pair_vec[i][1]; |
| } |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| break; |
| |
| default: |
| break; |
| } |
| |
| return; |
| } |
| |
| static VOID ixheaacd_diff_freq_decode(WORD32* diff_data, WORD32* out_data, |
| WORD32 num_val) { |
| WORD32 i = 0; |
| |
| out_data[0] = diff_data[0]; |
| |
| for (i = 1; i < num_val; i++) { |
| out_data[i] = out_data[i - 1] + diff_data[i]; |
| } |
| } |
| |
| static VOID ixheaacd_mps_diff_time_dec_bwd(WORD32* prev_data, WORD32* diff_data, |
| WORD32* out_data, |
| WORD32 mixed_diff_type, |
| WORD32 num_val) { |
| WORD32 i = 0; |
| |
| if (mixed_diff_type) { |
| out_data[0] = diff_data[0]; |
| for (i = 1; i < num_val; i++) { |
| out_data[i] = prev_data[i] + diff_data[i]; |
| } |
| } else { |
| for (i = 0; i < num_val; i++) { |
| out_data[i] = prev_data[i] + diff_data[i]; |
| } |
| } |
| } |
| |
| static VOID ixheaacd_mps_diff_time_dec_fwd(WORD32* prev_data, WORD32* diff_data, |
| WORD32* out_data, |
| WORD32 mixed_diff_type, |
| WORD32 num_val) { |
| WORD32 i = 0; |
| |
| if (mixed_diff_type) { |
| out_data[0] = diff_data[0]; |
| for (i = 1; i < num_val; i++) { |
| out_data[i] = prev_data[i] - diff_data[i]; |
| } |
| } else { |
| for (i = 0; i < num_val; i++) { |
| out_data[i] = prev_data[i] - diff_data[i]; |
| } |
| } |
| } |
| |
| static VOID ixheaacd_attach_lsb(ia_bit_buf_struct *it_bit_buff, |
| WORD32* in_data_msb, WORD32 ixheaacd_drc_offset, |
| WORD32 num_lsb, WORD32 num_val, |
| WORD32* out_data) { |
| WORD32 i = 0, lsb = 0, msb = 0; |
| UWORD32 data = 0; |
| |
| for (i = 0; i < num_val; i++) { |
| msb = in_data_msb[i]; |
| |
| if (num_lsb > 0) { |
| data = ixheaacd_read_bits_buf(it_bit_buff, num_lsb); |
| lsb = data; |
| |
| out_data[i] = ((msb << num_lsb) | lsb) - ixheaacd_drc_offset; |
| } else |
| out_data[i] = msb - ixheaacd_drc_offset; |
| } |
| |
| return; |
| } |
| |
| WORD32 ixheaacd_mps_ecdatapairdec(ia_bit_buf_struct *it_bit_buff, WORD32 outdata[][MAXBANDS], |
| WORD32 history[MAXBANDS], WORD32 data_type, WORD32 set_idx, |
| WORD32 start_band, WORD32 data_bands, WORD32 pair_flag, |
| WORD32 coarse_flag, WORD32 diff_time_back_flag, |
| WORD32 ld_mps_flag, WORD32 heaac_mps_present, WORD32 ec_flag) { |
| WORD32 attach_lsb_flag = 0; |
| WORD32 pcm_coding_flag = 0; |
| WORD32 pilot_coding_flag = 0; |
| WORD32 pilot_data[2] = {0, 0}; |
| WORD32 mixed_time_pair = 0, pcm_val = 0; |
| WORD32 quant_levels = 0, quant_offset = 0; |
| UWORD32 data = 0; |
| WORD32 band_start = 0; |
| |
| WORD32 data_pair[2][MAXBANDS] = {{0}}; |
| WORD32 data_diff[2][MAXBANDS] = {{0}}; |
| |
| WORD32 msb_state[MAXBANDS] = {0}; |
| |
| WORD32* data_array[2] = {NULL, NULL}; |
| |
| WORD32 diff_type[2] = {DIFF_FREQ, DIFF_FREQ}; |
| WORD32 cdg_scheme = HUFF_1D; |
| WORD32 direction = BACKWARDS; |
| |
| if (heaac_mps_present == 1) { |
| band_start = start_band; |
| } |
| |
| switch (data_type) { |
| case CLD: |
| if (coarse_flag) { |
| attach_lsb_flag = 0; |
| quant_levels = 15; |
| quant_offset = 7; |
| } else { |
| attach_lsb_flag = 0; |
| quant_levels = 31; |
| quant_offset = 15; |
| } |
| |
| break; |
| |
| case ICC: |
| if (coarse_flag) { |
| attach_lsb_flag = 0; |
| quant_levels = 4; |
| quant_offset = 0; |
| } else { |
| attach_lsb_flag = 0; |
| quant_levels = 8; |
| quant_offset = 0; |
| } |
| |
| break; |
| |
| case IPD: |
| if (coarse_flag) { |
| attach_lsb_flag = 0; |
| quant_levels = 8; |
| quant_offset = 0; |
| } else { |
| attach_lsb_flag = 1; |
| quant_levels = 16; |
| quant_offset = 0; |
| } |
| break; |
| |
| case CPC: |
| if (coarse_flag) { |
| attach_lsb_flag = 0; |
| quant_levels = 26; |
| quant_offset = 10; |
| } else { |
| attach_lsb_flag = 1; |
| quant_levels = 51; |
| quant_offset = 20; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| pcm_coding_flag = data; |
| |
| pilot_coding_flag = 0; |
| |
| if (heaac_mps_present == 1) { |
| if (pcm_coding_flag && data_bands > 4) { |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| pilot_coding_flag = data; |
| } |
| } |
| |
| if (pcm_coding_flag && !pilot_coding_flag) { |
| if (pair_flag) { |
| data_array[0] = data_pair[0]; |
| data_array[1] = data_pair[1]; |
| pcm_val = 2 * data_bands; |
| } else { |
| data_array[0] = data_pair[0]; |
| data_array[1] = NULL; |
| pcm_val = data_bands; |
| } |
| |
| ixheaacd_mps_pcm_decode(it_bit_buff, data_array[0], data_array[1], |
| quant_offset, pcm_val, quant_levels); |
| |
| } else { |
| if (pair_flag) { |
| data_array[0] = data_diff[0]; |
| data_array[1] = data_diff[1]; |
| } else { |
| data_array[0] = data_diff[0]; |
| data_array[1] = NULL; |
| } |
| |
| diff_type[0] = DIFF_FREQ; |
| diff_type[1] = DIFF_FREQ; |
| |
| direction = BACKWARDS; |
| |
| if (!pilot_coding_flag) { |
| if (pair_flag || diff_time_back_flag) { |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| diff_type[0] = data; |
| } |
| |
| if (pair_flag && ((diff_type[0] == DIFF_FREQ) || diff_time_back_flag)) { |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| diff_type[1] = data; |
| } |
| } |
| |
| if (data_bands <= 0) { |
| if (!ec_flag) |
| return -1; |
| else |
| longjmp(*(it_bit_buff->xaac_jmp_buf), IA_FATAL_ERROR); |
| } |
| |
| ixheaacd_huff_decode(it_bit_buff, data_array[0], data_array[1], data_type, diff_type[0], |
| diff_type[1], pilot_coding_flag, pilot_data, data_bands, &cdg_scheme, |
| ld_mps_flag); |
| |
| if (pilot_coding_flag && heaac_mps_present == 1) { |
| WORD32 i; |
| for (i = 0; i < data_bands; i++) { |
| data_pair[0][i] = data_diff[0][i] + pilot_data[0]; |
| } |
| |
| if (pair_flag) { |
| for (i = 0; i < data_bands; i++) { |
| data_pair[1][i] = data_diff[1][i] + pilot_data[0]; |
| } |
| } |
| } else { |
| if ((diff_type[0] == DIFF_TIME) || (diff_type[1] == DIFF_TIME)) { |
| if (pair_flag) { |
| if ((diff_type[0] == DIFF_TIME) && !diff_time_back_flag) { |
| direction = FORWARDS; |
| } else if (diff_type[1] == DIFF_TIME) { |
| direction = BACKWARDS; |
| } else { |
| data = ixheaacd_read_bits_buf(it_bit_buff, 1); |
| direction = data; |
| } |
| } else { |
| direction = BACKWARDS; |
| } |
| } |
| |
| mixed_time_pair = (diff_type[0] != diff_type[1]) && |
| ((cdg_scheme & PAIR_MASK) == TIME_PAIR); |
| |
| if (direction == BACKWARDS) { |
| if (diff_type[0] == DIFF_FREQ) { |
| ixheaacd_diff_freq_decode(data_diff[0], data_pair[0], data_bands); |
| } else { |
| WORD32 i; |
| for (i = 0; i < data_bands; i++) { |
| msb_state[i] = history[i + band_start] + quant_offset; |
| if (attach_lsb_flag) { |
| msb_state[i] >>= 1; |
| } |
| } |
| ixheaacd_mps_diff_time_dec_bwd(msb_state, data_diff[0], data_pair[0], |
| mixed_time_pair, data_bands); |
| } |
| if (diff_type[1] == DIFF_FREQ) { |
| ixheaacd_diff_freq_decode(data_diff[1], data_pair[1], data_bands); |
| } else { |
| ixheaacd_mps_diff_time_dec_bwd(data_pair[0], data_diff[1], data_pair[1], |
| mixed_time_pair, data_bands); |
| } |
| } else { |
| ixheaacd_diff_freq_decode(data_diff[1], data_pair[1], data_bands); |
| |
| if (diff_type[0] == DIFF_FREQ) { |
| ixheaacd_diff_freq_decode(data_diff[0], data_pair[0], data_bands); |
| } else { |
| ixheaacd_mps_diff_time_dec_fwd(data_pair[1], data_diff[0], data_pair[0], |
| mixed_time_pair, data_bands); |
| } |
| } |
| } |
| ixheaacd_attach_lsb(it_bit_buff, data_pair[0], quant_offset, |
| attach_lsb_flag ? 1 : 0, data_bands, data_pair[0]); |
| if (pair_flag) { |
| ixheaacd_attach_lsb(it_bit_buff, data_pair[1], quant_offset, |
| attach_lsb_flag ? 1 : 0, data_bands, data_pair[1]); |
| } |
| } |
| |
| memcpy(outdata[set_idx] + band_start, data_pair[0], |
| sizeof(WORD32) * data_bands); |
| if (pair_flag) { |
| memcpy(outdata[set_idx + 1] + band_start, data_pair[1], |
| sizeof(WORD32) * data_bands); |
| } |
| |
| return IA_NO_ERROR; |
| } |
| |
| VOID ixheaacd_mps_huff_decode(ia_bit_buf_struct *it_bit_buff, |
| WORD32* out_data, WORD32 num_val) { |
| WORD32 val_rcvd = 0, dummy = 0, i = 0, val = 0, len = 0; |
| WORD32 rl_data[2] = {0}; |
| |
| while (val_rcvd < num_val) { |
| ixheaacd_mps_huff_read_2d(it_bit_buff, |
| (ia_huff_node_struct)&ixheaacd_huff_reshape_nodes, |
| rl_data, &dummy); |
| val = rl_data[0]; |
| len = rl_data[1] + 1; |
| for (i = val_rcvd; i < val_rcvd + len; i++) { |
| out_data[i] = val; |
| } |
| val_rcvd += len; |
| } |
| |
| return; |
| } |
| |
| VOID ixheaacd_update_out_buffer(ia_heaac_mps_state_struct *pstr_mps_state, |
| WORD16 *out_buf) { |
| WORD32 ch, sam; |
| WORD32 num_output_channels_at = pstr_mps_state->num_output_channels_at; |
| WORD32 frame_length = pstr_mps_state->frame_length; |
| |
| WORD32 *p_time_out = pstr_mps_state->array_struct->time_out; |
| |
| for (ch = 0; ch < num_output_channels_at; ch++) { |
| WORD32 *time_out = p_time_out; |
| for (sam = 0; sam < frame_length; sam++) { |
| out_buf[sam * num_output_channels_at + ch] = (*time_out++) >> 16; |
| } |
| p_time_out += QBXTS; |
| } |
| |
| return; |
| } |
| |
| VOID ixheaacd_update_time_out_buffer(ia_heaac_mps_state_struct *pstr_mps_state) { |
| WORD32 n; |
| WORD32 up_mix_type = pstr_mps_state->up_mix_type; |
| WORD32 tree_config = pstr_mps_state->tree_config; |
| WORD32 lfe_gain = pstr_mps_state->lfe_gain; |
| WORD32 surround_gain = pstr_mps_state->surround_gain; |
| |
| if (!pstr_mps_state->bs_config.arbitrary_tree && up_mix_type != 2 && up_mix_type != 3) { |
| WORD32 frame_length = pstr_mps_state->frame_length; |
| |
| WORD32 *time_out_3 = pstr_mps_state->array_struct->time_out + QBXTSX3; |
| WORD32 *time_out_4 = time_out_3 + QBXTS; |
| WORD32 *time_out_5 = time_out_4 + QBXTS; |
| WORD32 *time_out_6 = time_out_5 + QBXTS; |
| WORD32 *time_out_7 = time_out_6 + QBXTS; |
| |
| for (n = 0; n < frame_length; n++) { |
| *time_out_3 = ixheaacd_mps_mult32_shr_15(*time_out_3, lfe_gain); |
| time_out_3++; |
| *time_out_4 = ixheaacd_mps_mult32_shr_15(*time_out_4, surround_gain); |
| time_out_4++; |
| *time_out_5 = ixheaacd_mps_mult32_shr_15(*time_out_5, surround_gain); |
| time_out_5++; |
| } |
| |
| if (tree_config == 4 || tree_config == 6) { |
| for (n = 0; n < frame_length; n++) { |
| *time_out_6 = ixheaacd_mps_mult32_shr_15(*time_out_6, surround_gain); |
| time_out_6++; |
| *time_out_7 = ixheaacd_mps_mult32_shr_15(*time_out_7, surround_gain); |
| time_out_7++; |
| } |
| } |
| } |
| } |
| |
| static IA_ERRORCODE ixheaacd_apply_frame(ia_heaac_mps_state_struct *pstr_mps_state, |
| WORD32 in_time_slots, |
| WORD32 *m_qmf_real, WORD32 *m_qmf_imag, |
| WORD16 *out_buf) { |
| IA_ERRORCODE err_code = IA_NO_ERROR; |
| WORD32 ch, ts, qs; |
| WORD32 *pbuf_real, *pbuf_imag, *pbuf_re, *pbuf_im; |
| WORD32 *buf_real, *buf_imag; |
| WORD32 *qmf_input_delay_real_2 = |
| pstr_mps_state->mps_persistent_mem.qmf_input_delay_real; |
| WORD32 *qmf_input_delay_imag_2 = |
| pstr_mps_state->mps_persistent_mem.qmf_input_delay_imag; |
| WORD32 num_input_channels = pstr_mps_state->num_input_channels; |
| WORD32 qmf_bands = pstr_mps_state->qmf_bands; |
| WORD32 cur_time_slot = pstr_mps_state->cur_time_slot; |
| WORD32 time_slots = pstr_mps_state->time_slots; |
| WORD32 qmf_input_delay_index = pstr_mps_state->qmf_input_delay_index; |
| WORD32 up_mix_type = pstr_mps_state->up_mix_type; |
| WORD32 residual_coding = pstr_mps_state->residual_coding; |
| WORD32 arbitrary_downmix = pstr_mps_state->arbitrary_downmix; |
| |
| WORD32 *qmf_input_delay_real_1, *qmf_input_delay_imag_1; |
| WORD32 *qmf_input_delay_real, *qmf_input_delay_imag; |
| |
| WORD32 *p_qmf_real = m_qmf_real; |
| WORD32 *p_qmf_imag = m_qmf_imag; |
| WORD32 *p_qmf_re, *p_qmf_im, *qmf_real, *qmf_imag; |
| |
| if (cur_time_slot + in_time_slots > time_slots) { |
| if (pstr_mps_state->ec_flag) |
| cur_time_slot = time_slots - in_time_slots; |
| else |
| return IA_FATAL_ERROR; |
| } |
| if (time_slots % HOP_SLOTS != 0) { |
| if (pstr_mps_state->ec_flag) |
| time_slots = time_slots - (time_slots % HOP_SLOTS); |
| else |
| return IA_XHEAAC_MPS_DEC_EXE_FATAL_INVALID_TIMESLOTS; |
| } |
| |
| pbuf_real = pstr_mps_state->array_struct->buf_real; |
| pbuf_imag = pstr_mps_state->array_struct->buf_imag; |
| |
| if (up_mix_type == 1) { |
| for (ch = 0; ch < num_input_channels; ch++) { |
| pbuf_re = pbuf_real; |
| pbuf_im = pbuf_imag; |
| |
| p_qmf_re = p_qmf_real; |
| p_qmf_im = p_qmf_imag; |
| |
| for (ts = 0; ts < in_time_slots; ts++) { |
| buf_real = pbuf_re + (cur_time_slot + ts); |
| buf_imag = pbuf_im + (cur_time_slot + ts); |
| |
| qmf_real = p_qmf_re; |
| qmf_imag = p_qmf_im; |
| |
| for (qs = 0; qs < qmf_bands; qs++) { |
| *buf_real++ = *qmf_real++; |
| *buf_imag++ = *qmf_imag++; |
| } |
| pbuf_re += MAX_HYBRID_BANDS; |
| pbuf_im += MAX_HYBRID_BANDS; |
| |
| p_qmf_re += MAX_NUM_QMF_BANDS; |
| p_qmf_im += MAX_NUM_QMF_BANDS; |
| } |
| pbuf_real += TSXHB; |
| pbuf_imag += TSXHB; |
| |
| p_qmf_real += QBXTS; |
| p_qmf_imag += QBXTS; |
| } |
| } else { |
| for (ch = 0; ch < num_input_channels; ch++) { |
| WORD32 offset = ch * PCXQB; |
| qmf_input_delay_index = pstr_mps_state->qmf_input_delay_index; |
| qmf_input_delay_real_1 = qmf_input_delay_real_2 + offset; |
| qmf_input_delay_imag_1 = qmf_input_delay_imag_2 + offset; |
| |
| pbuf_re = pbuf_real + cur_time_slot * MAX_HYBRID_BANDS; |
| pbuf_im = pbuf_imag + cur_time_slot * MAX_HYBRID_BANDS; |
| |
| p_qmf_re = p_qmf_real; |
| p_qmf_im = p_qmf_imag; |
| |
| for (ts = 0; ts < in_time_slots; ts++) { |
| WORD32 off_set = qmf_input_delay_index * MAX_NUM_QMF_BANDS; |
| qmf_input_delay_real = qmf_input_delay_real_1 + off_set; |
| qmf_input_delay_imag = qmf_input_delay_imag_1 + off_set; |
| |
| buf_real = pbuf_re; |
| buf_imag = pbuf_im; |
| |
| qmf_real = p_qmf_re; |
| qmf_imag = p_qmf_im; |
| |
| for (qs = 0; qs < qmf_bands; qs++) { |
| { |
| *buf_real++ = *qmf_input_delay_real; |
| *buf_imag++ = *qmf_input_delay_imag; |
| |
| *qmf_input_delay_real++ = *qmf_real++; |
| *qmf_input_delay_imag++ = *qmf_imag++; |
| } |
| } |
| |
| qmf_input_delay_index++; |
| |
| if (qmf_input_delay_index == PC_FILTERDELAY) { |
| qmf_input_delay_index = 0; |
| } |
| pbuf_re += MAX_HYBRID_BANDS; |
| pbuf_im += MAX_HYBRID_BANDS; |
| |
| p_qmf_re += MAX_NUM_QMF_BANDS; |
| p_qmf_im += MAX_NUM_QMF_BANDS; |
| } |
| pbuf_real += TSXHB; |
| pbuf_imag += TSXHB; |
| |
| p_qmf_real += QBXTS; |
| p_qmf_imag += QBXTS; |
| } |
| pstr_mps_state->qmf_input_delay_index = qmf_input_delay_index; |
| } |
| |
| pstr_mps_state->cur_time_slot += in_time_slots; |
| cur_time_slot = pstr_mps_state->cur_time_slot; |
| |
| if (pstr_mps_state->cur_time_slot < time_slots) { |
| if (pstr_mps_state->ec_flag) { |
| pstr_mps_state->cur_time_slot = time_slots; |
| } else |
| return IA_FATAL_ERROR; |
| } |
| |
| pstr_mps_state->cur_time_slot = 0; |
| |
| err_code = ixheaacd_decode_frame(pstr_mps_state); |
| if (err_code != IA_NO_ERROR) return err_code; |
| |
| ixheaacd_mdct_2_qmf(pstr_mps_state); |
| |
| ixheaacd_hybrid_qmf_analysis(pstr_mps_state); |
| |
| if (residual_coding || (arbitrary_downmix == 2)) { |
| ixheaacd_update_buffers(pstr_mps_state); |
| } |
| |
| if (up_mix_type == 1) { |
| ixheaacd_apply_blind(pstr_mps_state); |
| } |
| |
| ixheaacd_calc_m1m2(pstr_mps_state); |
| |
| ixheaacd_smooth_m1m2(pstr_mps_state); |
| |
| ixheaacd_mps_apply_m1(pstr_mps_state); |
| |
| ixheaacd_buffer_m1(pstr_mps_state); |
| |
| if (up_mix_type != 2) { |
| if (pstr_mps_state->temp_shape_config == 2) { |
| ixheaacd_pre_reshape_bb_env(pstr_mps_state); |
| } |
| } |
| |
| ixheaacd_create_w(pstr_mps_state); |
| |
| ixheaacd_apply_m2(pstr_mps_state); |
| |
| ixheaacd_buffer_m2(pstr_mps_state); |
| |
| if (up_mix_type != 2) { |
| if (pstr_mps_state->temp_shape_config == 2) { |
| ixheaacd_reshape_bb_env(pstr_mps_state); |
| } |
| } |
| |
| ixheaacd_tp_process(pstr_mps_state); |
| |
| ixheaacd_update_time_out_buffer(pstr_mps_state); |
| |
| ixheaacd_update_out_buffer(pstr_mps_state, out_buf); |
| |
| pstr_mps_state->parse_next_bitstream_frame = 1; |
| |
| return IA_NO_ERROR; |
| } |
| |
| IA_ERRORCODE ixheaacd_heaac_mps_apply(ia_exhaacplus_dec_api_struct *self, |
| WORD16 *output_buf, UWORD8 *mps_buffer, |
| WORD32 mps_bytes) { |
| ia_heaac_mps_state_struct *pstr_mps_state = |
| &self->p_state_aac->heaac_mps_handle; |
| IA_ERRORCODE error_code = IA_NO_ERROR; |
| WORD32 n_channels, n_time_slots, qmf_bands, channel; |
| ia_heaac_mps_state_struct *curr_state = pstr_mps_state; |
| |
| WORD32 *p_qmf_real = pstr_mps_state->array_struct->m_qmf_real; |
| WORD32 *p_qmf_imag = pstr_mps_state->array_struct->m_qmf_imag; |
| WORD32 buffer_size = mps_bytes; |
| |
| if (self->p_state_aac->heaac_mps_handle.is_first == 1) { |
| self->p_state_aac->heaac_mps_handle.is_first = 1; |
| if (pstr_mps_state->bytes_remaining != 0) { |
| buffer_size = mps_bytes + pstr_mps_state->bytes_remaining; |
| for (WORD32 ii = 0; ii < mps_bytes; ii++) { |
| pstr_mps_state->temp_buf[ii + pstr_mps_state->bytes_remaining] = |
| mps_buffer[ii]; |
| } |
| |
| pstr_mps_state->ptr_mps_bit_buff = ixheaacd_create_bit_buf( |
| &pstr_mps_state->mps_bit_buf, (UWORD8 *)pstr_mps_state->temp_buf, |
| buffer_size); |
| pstr_mps_state->ptr_mps_bit_buff->xaac_jmp_buf = |
| &self->p_state_aac->xaac_jmp_buf; |
| |
| pstr_mps_state->ptr_mps_bit_buff->cnt_bits += (8 * buffer_size); |
| } else { |
| memcpy(pstr_mps_state->temp_buf, mps_buffer, mps_bytes); |
| buffer_size = mps_bytes; |
| pstr_mps_state->ptr_mps_bit_buff = ixheaacd_create_bit_buf( |
| &pstr_mps_state->mps_bit_buf, (UWORD8 *)mps_buffer, buffer_size); |
| pstr_mps_state->ptr_mps_bit_buff->cnt_bits += (8 * buffer_size); |
| |
| pstr_mps_state->ptr_mps_bit_buff->xaac_jmp_buf = |
| &self->p_state_aac->xaac_jmp_buf; |
| } |
| } |
| |
| if (curr_state->num_input_channels > 2 && pstr_mps_state->mps_with_sbr == 1) { |
| if (pstr_mps_state->ec_flag) { |
| curr_state->num_input_channels = 2; |
| pstr_mps_state->frame_ok = 0; |
| } else { |
| return IA_FATAL_ERROR; |
| } |
| } |
| |
| n_channels = curr_state->num_input_channels; |
| n_time_slots = curr_state->time_slots; |
| qmf_bands = curr_state->qmf_bands; |
| |
| if (pstr_mps_state->mps_decode == 1) { |
| if (pstr_mps_state->mps_with_sbr) { |
| for (channel = 0; channel < n_channels; channel++) { |
| WORD32 kk = 0; |
| if (self->aac_config.ui_enh_sbr) |
| { |
| for (WORD32 ii = 0; ii < n_time_slots; ii++) { |
| FLOAT32 *qmf_re = self->p_state_aac->str_sbr_dec_info[0] |
| ->pstr_sbr_channel[channel]->str_sbr_dec.pp_qmf_buf_real[ii]; |
| FLOAT32 *qmf_im = self->p_state_aac->str_sbr_dec_info[0] |
| ->pstr_sbr_channel[channel]->str_sbr_dec.pp_qmf_buf_imag[ii]; |
| |
| for (WORD32 jj = 0; jj < qmf_bands; jj++) { |
| p_qmf_real[kk] = ixheaacd_mps_mult32_shr_15( |
| curr_state->clip_protect_gain, (WORD32)(qmf_re[jj] * 1024)); |
| p_qmf_imag[kk++] = ixheaacd_mps_mult32_shr_15( |
| curr_state->clip_protect_gain, (WORD32)(qmf_im[jj] * 1024)); |
| } |
| } |
| } |
| else |
| { |
| for (WORD32 ii = 0; ii < n_time_slots; ii++) { |
| WORD32 *qmf_re = self->p_state_aac->str_sbr_dec_info[0] |
| ->pstr_sbr_channel[channel]->str_sbr_dec.p_arr_qmf_buf_real[ii]; |
| WORD32 *qmf_im = self->p_state_aac->str_sbr_dec_info[0] |
| ->pstr_sbr_channel[channel]->str_sbr_dec.p_arr_qmf_buf_imag[ii]; |
| |
| for (WORD32 jj = 0; jj < qmf_bands; jj++) { |
| p_qmf_real[kk] = ixheaacd_mps_mult32_shr_15( |
| curr_state->clip_protect_gain, qmf_re[jj] * 256); |
| p_qmf_imag[kk++] = ixheaacd_mps_mult32_shr_15( |
| curr_state->clip_protect_gain, qmf_im[jj] * 256); |
| } |
| } |
| } |
| p_qmf_real += QBXTS; |
| p_qmf_imag += QBXTS; |
| } |
| } else { |
| for (channel = 0; channel < n_channels; channel++) { |
| ixheaacd_calc_ana_filt_bank(pstr_mps_state, output_buf, p_qmf_real, |
| p_qmf_imag, channel); |
| |
| p_qmf_real += QBXTS; |
| p_qmf_imag += QBXTS; |
| } |
| } |
| if (!pstr_mps_state->ec_flag && pstr_mps_state->frame_ok) { |
| error_code = ixheaacd_parse_frame(pstr_mps_state); |
| if (error_code != IA_NO_ERROR) return error_code; |
| } |
| |
| if (!pstr_mps_state->first_frame || !pstr_mps_state->ec_flag) { |
| error_code = ixheaacd_apply_frame(pstr_mps_state, n_time_slots, |
| pstr_mps_state->array_struct->m_qmf_real, |
| pstr_mps_state->array_struct->m_qmf_imag, output_buf); |
| if (error_code != IA_NO_ERROR) return error_code; |
| } |
| if (error_code == 0 && pstr_mps_state->ec_flag && pstr_mps_state->frame_ok) { |
| error_code = ixheaacd_parse_frame(pstr_mps_state); |
| if (error_code != IA_NO_ERROR) { |
| pstr_mps_state->frame_ok = 0; |
| } |
| } |
| |
| pstr_mps_state->i_bytes_consumed_mps = |
| (WORD32)(pstr_mps_state->ptr_mps_bit_buff->ptr_read_next - |
| pstr_mps_state->ptr_mps_bit_buff->ptr_bit_buf_base); |
| |
| pstr_mps_state->bytes_remaining = |
| buffer_size - pstr_mps_state->i_bytes_consumed_mps; |
| if (pstr_mps_state->bytes_remaining < 0) |
| { |
| if (pstr_mps_state->ec_flag) |
| { |
| pstr_mps_state->bytes_remaining = 0; |
| pstr_mps_state->frame_ok = 0; |
| } |
| else |
| { |
| return IA_FATAL_ERROR; |
| } |
| } |
| |
| if (pstr_mps_state->bytes_remaining != 0) { |
| for (WORD32 ii = 0; ii < pstr_mps_state->bytes_remaining; ii++) { |
| pstr_mps_state->temp_buf[ii] = |
| pstr_mps_state->temp_buf[ii + pstr_mps_state->i_bytes_consumed_mps]; |
| } |
| } |
| } |
| self->p_state_aac->heaac_mps_handle.is_first = 1; |
| self->p_state_aac->heaac_mps_handle.first_frame = 0; |
| |
| return error_code; |
| } |