1464 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1464 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
| /******************************************************************************
 | |
|  *                                                                            *
 | |
|  * 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 <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <math.h>
 | |
| 
 | |
| #include <assert.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include "ixheaacd_type_def.h"
 | |
| 
 | |
| #include "ixheaacd_bitbuffer.h"
 | |
| 
 | |
| #include "ixheaacd_defines.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_drc_dec.h"
 | |
| 
 | |
| #include "ixheaacd_lt_predict.h"
 | |
| #include "ixheaacd_channelinfo.h"
 | |
| #include "ixheaacd_channel.h"
 | |
| #include "ixheaacd_channelinfo.h"
 | |
| #include "ixheaacd_sbrdecoder.h"
 | |
| #include "ixheaacd_audioobjtypes.h"
 | |
| #include "ixheaacd_latmdemux.h"
 | |
| #include "ixheaacd_aacdec.h"
 | |
| #include "ixheaacd_sbr_common.h"
 | |
| 
 | |
| #include "ixheaacd_mps_polyphase.h"
 | |
| #include "ixheaacd_config.h"
 | |
| #include "ixheaacd_mps_dec.h"
 | |
| #include "ixheaacd_mps_interface.h"
 | |
| #include "ixheaacd_struct_def.h"
 | |
| 
 | |
| #include "ixheaacd_config.h"
 | |
| #include "ixheaacd_mps_interface.h"
 | |
| 
 | |
| #include "ixheaacd_mps_polyphase.h"
 | |
| 
 | |
| #include "ixheaacd_mps_dec.h"
 | |
| #include "ixheaacd_mps_process.h"
 | |
| #include "ixheaacd_mps_decor.h"
 | |
| #include "ixheaacd_mps_hybfilter.h"
 | |
| #include "ixheaacd_mps_nlc_dec.h"
 | |
| #include "ixheaacd_mps_huff_tab.h"
 | |
| #include "ixheaacd_error_standards.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_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 != 0) return err_code;
 | |
| 
 | |
|   if ((self->residual_coding) && (self->res_bands > 0)) self->res_ch_count++;
 | |
| 
 | |
|   ixheaacd_mps_env_init(self);
 | |
| 
 | |
|   ixheaacd_mps_synt_create(&self->poly_phase_filt_kernel, 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,
 | |
|                                      self->config->bs_decorr_config);
 | |
|   if (err_code != IA_NO_ERROR) 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));
 | |
| 
 | |
|   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) {
 | |
|   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->qmf_band_count,
 | |
|                                      self->time_slots, self->hyb_res);
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_mps_qmf_hyb_synthesis(ia_mps_dec_state_struct* self) {
 | |
|   WORD32 ch;
 | |
| 
 | |
|   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);
 | |
| 
 | |
|     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; 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[ts][qs].re;
 | |
|           self->w_dir[row][ts][qs].im = self->hyb_res[ts][qs].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_create_w(ia_mps_dec_state_struct* self) {
 | |
|   ixheaacd_mps_decor(self);
 | |
|   ixheaacd_mps_mix_res_decor(self);
 | |
| }
 | |
| 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->output_buffer = output_buffer;
 | |
| 
 | |
|   assert(self->present_time_slot + time_slots <= self->time_slots);
 | |
| 
 | |
|   for (ts = 0; ts < time_slots; ts++) {
 | |
|     for (ch = 0; ch < in_ch_count; ch++) {
 | |
|       for (qs = 0; qs < self->qmf_band_count; qs++) {
 | |
|         self->qmf_in[ch][self->present_time_slot + ts][qs].re =
 | |
|             self->input_gain * input_buffer[2 * ch][ts][qs];
 | |
|         self->qmf_in[ch][self->present_time_slot + ts][qs].im =
 | |
|             self->input_gain * input_buffer[2 * ch + 1][ts][qs];
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   self->present_time_slot += time_slots;
 | |
| 
 | |
|   if (self->present_time_slot < self->time_slots) return 0;
 | |
| 
 | |
|   self->present_time_slot = 0;
 | |
| 
 | |
|   err = ixheaacd_mps_frame_decode(self);
 | |
| 
 | |
|   if (err != 0) return err;
 | |
|   ixheaacd_mps_qmf_hyb_analysis(self);
 | |
| 
 | |
|   ixheaacd_pre_and_mix_matrix_calculation(self);
 | |
| 
 | |
|   ixheaacd_mps_pre_matrix_mix_matrix_smoothing(self);
 | |
| 
 | |
|   err = ixheaacd_mps_apply_pre_matrix(self);
 | |
|   if (err < 0) return err;
 | |
| 
 | |
|   ixheaacd_mps_create_w(self);
 | |
| 
 | |
|   err = ixheaacd_mps_apply_mix_matrix(self);
 | |
|   if (err < 0) return err;
 | |
| 
 | |
|   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;
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| #define min(a, b) (((a) < (b)) ? (a) : (b))
 | |
| 
 | |
| static VOID ixheaacd_mps_pcm_decode(ia_handle_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:
 | |
|       assert(0);
 | |
|   }
 | |
| 
 | |
|   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_handle_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_handle_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_handle_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_handle_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_handle_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_handle_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_handle_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_handle_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 ixheaacd_mps_huff_dec_cld_2d(
 | |
|     ia_handle_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_handle_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_handle_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 WORD32 ixheaacd_huff_decode(ia_handle_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 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;
 | |
| 
 | |
|       default:
 | |
|         if (out_data_1 != NULL) {
 | |
|           return 0;
 | |
|         }
 | |
|         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)) {
 | |
|       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;
 | |
| 
 | |
|         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;
 | |
| 
 | |
|             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;
 | |
| 
 | |
|             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 1;
 | |
| }
 | |
| 
 | |
| 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_handle_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_handle_bit_buf_struct it_bit_buff,
 | |
|                                   WORD32 outdata[][MAXBANDS],
 | |
|                                   WORD32 history[MAXBANDS], WORD32 data_type,
 | |
|                                   WORD32 set_idx, WORD32 data_bands,
 | |
|                                   WORD32 pair_flag, WORD32 coarse_flag,
 | |
|                                   WORD32 independency_flag)
 | |
| 
 | |
| {
 | |
|   WORD32 diff_time_back_flag = !independency_flag || (set_idx > 0);
 | |
|   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;
 | |
| 
 | |
|   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;
 | |
| 
 | |
|     default:
 | |
|       fprintf(stderr, "Unknown type of data!\n");
 | |
|       return -1;
 | |
|   }
 | |
| 
 | |
|   data = ixheaacd_read_bits_buf(it_bit_buff, 1);
 | |
|   pcm_coding_flag = data;
 | |
| 
 | |
|   pilot_coding_flag = 0;
 | |
| 
 | |
|   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) return -1;
 | |
| 
 | |
|     if (!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)) {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     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_handle_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;
 | |
| }
 |