mirror of
https://github.com/ittiam-systems/libxaac.git
synced 2026-07-11 06:39:13 +07:00
Number of envelopes is becoming zero because of erroneous input stream.Inside SBR start band and stop band are calculated based on number of envelope's. In this case end position is becoming zero, which in turn makes start bands as negative. In sbr processing buffer is accessed from start to stop band. This is causing OOB read access Bug:114744962 Test: poc Change-Id: Ib51fc464d0afc2f5a68d860fcde1b8961fd69d40
823 lines
28 KiB
C
823 lines
28 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 <string.h>
|
|
#include "ixheaacd_sbr_common.h"
|
|
#include <ixheaacd_type_def.h>
|
|
|
|
#include "ixheaacd_constants.h"
|
|
#include <ixheaacd_basic_ops32.h>
|
|
#include <ixheaacd_basic_ops16.h>
|
|
#include <ixheaacd_basic_ops40.h>
|
|
#include "ixheaacd_basic_ops.h"
|
|
|
|
#include <ixheaacd_basic_op.h>
|
|
#include "ixheaacd_intrinsics.h"
|
|
#include "ixheaacd_bitbuffer.h"
|
|
#include "ixheaacd_sbrdecsettings.h"
|
|
#include "ixheaacd_sbr_scale.h"
|
|
#include "ixheaacd_lpp_tran.h"
|
|
#include "ixheaacd_env_extr_part.h"
|
|
#include <ixheaacd_sbr_rom.h>
|
|
#include "ixheaacd_hybrid.h"
|
|
#include "ixheaacd_ps_dec.h"
|
|
|
|
#include "ixheaacd_env_extr.h"
|
|
#include "ixheaacd_common_rom.h"
|
|
#include "ixheaacd_env_dec.h"
|
|
#include "ixheaacd_sbr_const.h"
|
|
|
|
#include "ixheaacd_basic_funcs.h"
|
|
|
|
#include "math.h"
|
|
|
|
#define add16_m(a, b) ((a) + (b))
|
|
#define sub16_m(a, b) ((a) - (b))
|
|
|
|
#define mult16x16_16(a, b) ixheaacd_mult16((a), (b))
|
|
|
|
static VOID ixheaacd_dequant_esbr_env_data(FLOAT32 *ptr_env_sf,
|
|
WORD32 num_env_sf,
|
|
WORD32 num_noise_fac, WORD32 amp_res,
|
|
FLOAT32 *ptr_noise_floor) {
|
|
WORD32 i;
|
|
FLOAT32 array[2] = {0.5f, 1.0f};
|
|
FLOAT32 a_flt = array[amp_res];
|
|
|
|
for (i = 0; i < num_env_sf; i++) {
|
|
ptr_env_sf[i] = (FLOAT32)(pow(2, ptr_env_sf[i] * a_flt) * 64);
|
|
}
|
|
|
|
for (i = 0; i < num_noise_fac; i++) {
|
|
FLOAT32 temp = ptr_noise_floor[i];
|
|
|
|
temp = NOISE_FLOOR_OFFSET - temp;
|
|
temp = (FLOAT32)pow(2.0f, temp);
|
|
|
|
ptr_noise_floor[i] = temp;
|
|
}
|
|
}
|
|
|
|
static VOID ixheaacd_dequant_pvc_env_data(WORD32 num_noise_fac,
|
|
FLOAT32 *ptr_noise_floor) {
|
|
WORD32 i;
|
|
|
|
for (i = 0; i < num_noise_fac; i++) {
|
|
FLOAT32 temp = ptr_noise_floor[i];
|
|
|
|
temp = NOISE_FLOOR_OFFSET - temp;
|
|
temp = (FLOAT32)pow(2.0f, temp);
|
|
|
|
ptr_noise_floor[i] = temp;
|
|
}
|
|
}
|
|
|
|
VOID ixheaacd_map_res_energy(WORD16 curr_val, WORD16 *prev_data,
|
|
WORD32 ixheaacd_drc_offset, WORD32 index,
|
|
WORD32 res) {
|
|
if (res == LOW) {
|
|
if (ixheaacd_drc_offset >= 0) {
|
|
if (index < ixheaacd_drc_offset) {
|
|
prev_data[index] = curr_val;
|
|
} else {
|
|
WORD32 index_2;
|
|
index_2 = ((index + index) - ixheaacd_drc_offset);
|
|
prev_data[index_2] = curr_val;
|
|
prev_data[index_2 + 1] = curr_val;
|
|
}
|
|
} else {
|
|
ixheaacd_drc_offset = -(ixheaacd_drc_offset);
|
|
|
|
if (index < ixheaacd_drc_offset) {
|
|
WORD32 index_3;
|
|
index_3 = ((index + index) + index);
|
|
prev_data[index_3] = curr_val;
|
|
prev_data[index_3 + 1] = curr_val;
|
|
prev_data[index_3 + 2] = curr_val;
|
|
} else {
|
|
WORD32 index_2;
|
|
index_2 = ((index + index) + ixheaacd_drc_offset);
|
|
prev_data[index_2] = curr_val;
|
|
prev_data[index_2 + 1] = curr_val;
|
|
}
|
|
}
|
|
} else {
|
|
prev_data[index] = curr_val;
|
|
}
|
|
}
|
|
|
|
VOID ixheaacd_process_del_cod_env_data(
|
|
ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data) {
|
|
WORD32 i, dtdf_dir, num_sf_bands, band, freq_res;
|
|
WORD16 temp_val;
|
|
WORD16 *ptr_prev_env_sf = ptr_prev_data->sfb_nrg_prev;
|
|
WORD16 *ptr_env_sf = ptr_sbr_data->int_env_sf_arr;
|
|
|
|
FLOAT32 *ptr_env_sf_float = ptr_sbr_data->flt_env_sf_arr;
|
|
|
|
WORD32 ixheaacd_drc_offset;
|
|
band = 0;
|
|
|
|
ixheaacd_drc_offset =
|
|
((ptr_header_data->pstr_freq_band_data->num_sf_bands[LOW] << 1) -
|
|
ptr_header_data->pstr_freq_band_data->num_sf_bands[HIGH]);
|
|
|
|
for (i = 0; i < ptr_sbr_data->str_frame_info_details.num_env; i++) {
|
|
dtdf_dir = ptr_sbr_data->del_cod_dir_arr[i];
|
|
freq_res = ptr_sbr_data->str_frame_info_details.freq_res[i];
|
|
|
|
num_sf_bands = ptr_header_data->pstr_freq_band_data->num_sf_bands[freq_res];
|
|
|
|
if (dtdf_dir == DTDF_DIR_FREQ) {
|
|
ixheaacd_map_res_energy(*ptr_env_sf, ptr_prev_env_sf, ixheaacd_drc_offset,
|
|
0, freq_res);
|
|
ptr_env_sf++;
|
|
|
|
ptr_env_sf_float++;
|
|
|
|
for (band = 1; band < num_sf_bands; band++) {
|
|
*ptr_env_sf = *ptr_env_sf + *(ptr_env_sf - 1);
|
|
ixheaacd_map_res_energy(*ptr_env_sf, ptr_prev_env_sf,
|
|
ixheaacd_drc_offset, band, freq_res);
|
|
|
|
*ptr_env_sf_float = (FLOAT32)(*ptr_env_sf);
|
|
ptr_env_sf_float++;
|
|
|
|
ptr_env_sf++;
|
|
}
|
|
|
|
} else {
|
|
if (freq_res == LOW) {
|
|
if (ixheaacd_drc_offset < 0) {
|
|
WORD32 tar, index_3;
|
|
ixheaacd_drc_offset = -ixheaacd_drc_offset;
|
|
tar = ixheaacd_min32(ixheaacd_drc_offset, band);
|
|
|
|
for (band = 0; band < tar; band++) {
|
|
index_3 = ((band + band) + band);
|
|
temp_val = add16_m(*ptr_env_sf, ptr_prev_env_sf[index_3]);
|
|
|
|
ptr_prev_env_sf[index_3] = temp_val;
|
|
ptr_prev_env_sf[index_3 + 1] = temp_val;
|
|
ptr_prev_env_sf[index_3 + 2] = temp_val;
|
|
*ptr_env_sf++ = temp_val;
|
|
|
|
*ptr_env_sf_float = (FLOAT32)temp_val;
|
|
ptr_env_sf_float++;
|
|
}
|
|
|
|
for (; band < num_sf_bands; band++) {
|
|
index_3 = (band << 1) + ixheaacd_drc_offset;
|
|
temp_val = add16_m(*ptr_env_sf, ptr_prev_env_sf[index_3]);
|
|
ptr_prev_env_sf[index_3] = temp_val;
|
|
ptr_prev_env_sf[index_3 + 1] = temp_val;
|
|
*ptr_env_sf++ = temp_val;
|
|
*ptr_env_sf_float = (FLOAT32)temp_val;
|
|
ptr_env_sf_float++;
|
|
}
|
|
} else {
|
|
WORD32 tar, index_2;
|
|
WORD16 *ptr2 = ptr_prev_env_sf;
|
|
tar = ixheaacd_min32(ixheaacd_drc_offset, band);
|
|
for (band = 0; band < tar; band++) {
|
|
*ptr_env_sf = add16_m(*ptr_env_sf, *ptr2);
|
|
*ptr2 = *ptr_env_sf;
|
|
|
|
*ptr_env_sf_float = (FLOAT32)(*ptr_env_sf);
|
|
ptr_env_sf_float++;
|
|
|
|
ptr2++;
|
|
ptr_env_sf++;
|
|
}
|
|
|
|
for (; band < num_sf_bands; band++) {
|
|
index_2 = (band < ixheaacd_drc_offset)
|
|
? band
|
|
: ((band << 1) - ixheaacd_drc_offset);
|
|
temp_val = add16_m(*ptr_env_sf, ptr_prev_env_sf[index_2]);
|
|
ptr_prev_env_sf[index_2] = temp_val;
|
|
ptr_prev_env_sf[index_2 + 1] = temp_val;
|
|
*ptr_env_sf++ = temp_val;
|
|
|
|
*ptr_env_sf_float = (FLOAT32)temp_val;
|
|
ptr_env_sf_float++;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
WORD16 *ptr2 = ptr_prev_env_sf;
|
|
for (band = num_sf_bands - 1; band >= 0; band--) {
|
|
*ptr_env_sf = add16_m(*ptr_env_sf, *ptr2);
|
|
*ptr2 = *ptr_env_sf;
|
|
*ptr_env_sf_float = (FLOAT32)(*ptr_env_sf);
|
|
ptr_env_sf_float++;
|
|
ptr2++;
|
|
ptr_env_sf++;
|
|
}
|
|
band = num_sf_bands;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static PLATFORM_INLINE WORD32
|
|
ixheaacd_wrong_timing_compensate(ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data,
|
|
ixheaacd_misc_tables *pstr_common_tables) {
|
|
WORD32 i, num_env_sf;
|
|
ia_frame_info_struct *p_frame_info = &ptr_sbr_data->str_frame_info_details;
|
|
WORD16 *num_sf_bands = ptr_header_data->pstr_freq_band_data->num_sf_bands;
|
|
WORD32 start_pos_est;
|
|
WORD32 ref_len, new_len, shift;
|
|
WORD16 delta_exp;
|
|
|
|
start_pos_est =
|
|
(ptr_prev_data->end_position - ptr_header_data->num_time_slots);
|
|
|
|
ref_len = (p_frame_info->border_vec[1] - p_frame_info->border_vec[0]);
|
|
|
|
new_len = (p_frame_info->border_vec[1] - start_pos_est);
|
|
|
|
if (new_len <= 0) {
|
|
new_len = ref_len;
|
|
start_pos_est = p_frame_info->border_vec[0];
|
|
}
|
|
|
|
delta_exp = pstr_common_tables->log_dual_is_table[ref_len];
|
|
delta_exp -= pstr_common_tables->log_dual_is_table[new_len];
|
|
|
|
shift = (SHORT_BITS - ENV_EXP_FRACT - 3 - ptr_sbr_data->amp_res);
|
|
delta_exp = ixheaacd_shr16(delta_exp, (WORD16)shift);
|
|
p_frame_info->border_vec[0] = start_pos_est;
|
|
p_frame_info->noise_border_vec[0] = start_pos_est;
|
|
|
|
if (start_pos_est < 0) return -1;
|
|
|
|
if (ptr_sbr_data->coupling_mode != COUPLING_BAL) {
|
|
num_env_sf =
|
|
((p_frame_info->freq_res[0]) ? num_sf_bands[HIGH] : num_sf_bands[LOW]);
|
|
|
|
for (i = 0; i < num_env_sf; i++) {
|
|
ptr_sbr_data->int_env_sf_arr[i] =
|
|
add16_m(ptr_sbr_data->int_env_sf_arr[i], delta_exp);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD16 ixheaacd_check_env_data(ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data) {
|
|
WORD16 *ptr_evn_sf = ptr_sbr_data->int_env_sf_arr;
|
|
WORD16 *ptr_prev_evn_sf = ptr_prev_data->sfb_nrg_prev;
|
|
WORD32 i;
|
|
FLAG error_code = 0;
|
|
WORD16 sbr_max_env_sf;
|
|
WORD32 amp_res = ptr_sbr_data->amp_res;
|
|
|
|
sbr_max_env_sf = (SBR_ENV_SF_MAX_VAL_1_5 >> amp_res);
|
|
|
|
for (i = 0; i < ptr_sbr_data->num_env_sfac; i++) {
|
|
if (ptr_evn_sf[i] > sbr_max_env_sf) {
|
|
error_code = 1;
|
|
}
|
|
if (ptr_evn_sf[i] < 0) {
|
|
ptr_evn_sf[i] = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ptr_header_data->pstr_freq_band_data->num_sf_bands[HIGH];
|
|
i++) {
|
|
if (ptr_prev_evn_sf[i] < 0) {
|
|
ptr_prev_evn_sf[i] = 0;
|
|
} else {
|
|
if (ptr_prev_evn_sf[i] > sbr_max_env_sf)
|
|
ptr_prev_evn_sf[i] = sbr_max_env_sf;
|
|
}
|
|
}
|
|
return (WORD16)(error_code);
|
|
}
|
|
|
|
VOID ixheaacd_dequant_env_data(ia_sbr_frame_info_data_struct *ptr_sbr_data,
|
|
WORD32 amp_res) {
|
|
WORD32 i;
|
|
WORD32 num_env_sf = ptr_sbr_data->num_env_sfac;
|
|
WORD32 mantissa;
|
|
WORD32 amp_res_1;
|
|
WORD32 exponent;
|
|
WORD32 exp_add = (7 + NRG_EXP_OFFSET);
|
|
WORD16 *ptr_env_sf = ptr_sbr_data->int_env_sf_arr;
|
|
WORD32 mant_arr[2] = {0x4000, 0x5a80};
|
|
|
|
amp_res_1 = (1 - amp_res);
|
|
|
|
for (i = num_env_sf - 1; i >= 0; i--) {
|
|
exponent = *ptr_env_sf;
|
|
mantissa = mant_arr[(exponent & amp_res_1)];
|
|
exponent = (exponent >> amp_res_1);
|
|
exponent = (exponent + exp_add);
|
|
*ptr_env_sf++ = (WORD16)(mantissa | (exponent & MASK_FOR_EXP));
|
|
}
|
|
}
|
|
|
|
static PLATFORM_INLINE VOID
|
|
ixheaacd_limit_noise_floor_fac(ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data) {
|
|
WORD32 i, tot_nf_bands;
|
|
WORD32 value;
|
|
WORD32 num_nf_bands;
|
|
WORD16 *ptr_noise_floor;
|
|
|
|
num_nf_bands = ptr_header_data->pstr_freq_band_data->num_nf_bands;
|
|
|
|
tot_nf_bands =
|
|
ptr_sbr_data->str_frame_info_details.num_noise_env * num_nf_bands;
|
|
|
|
ptr_noise_floor = ptr_sbr_data->int_noise_floor;
|
|
|
|
for (i = tot_nf_bands - 1; i >= 0; i--) {
|
|
value = *ptr_noise_floor;
|
|
if (value > MAX_NOISE_FLOOR_FAC_VAL) {
|
|
*ptr_noise_floor = MAX_NOISE_FLOOR_FAC_VAL;
|
|
} else {
|
|
if (value < MIN_NOISE_FLOOR_FAC_VAL) {
|
|
*ptr_noise_floor = MIN_NOISE_FLOOR_FAC_VAL;
|
|
}
|
|
}
|
|
ptr_noise_floor++;
|
|
}
|
|
}
|
|
|
|
VOID ixheaacd_add_arr(WORD16 *ptr1, WORD16 *ptr2, WORD32 num) {
|
|
WORD32 i;
|
|
for (i = num - 1; i >= 0; i--) {
|
|
*ptr2 = (*ptr2 + *ptr1);
|
|
ptr2++;
|
|
ptr1++;
|
|
}
|
|
}
|
|
|
|
VOID ixheaacd_calc_noise_floor(ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data) {
|
|
WORD32 i;
|
|
WORD32 num_nf_bands;
|
|
WORD32 num_noise_env;
|
|
WORD32 ixheaacd_drc_offset;
|
|
WORD16 *ptr_noise_floor = ptr_sbr_data->int_noise_floor;
|
|
|
|
WORD16 *ptr_prev_noise_floor = ptr_prev_data->prev_noise_level;
|
|
WORD16 *ptr1, *ptr2;
|
|
WORD32 num;
|
|
FLOAT32 *ptr_noise_floor_float = ptr_sbr_data->flt_noise_floor;
|
|
|
|
num_nf_bands = ptr_header_data->pstr_freq_band_data->num_nf_bands;
|
|
num_noise_env = ptr_sbr_data->str_frame_info_details.num_noise_env;
|
|
|
|
if (ptr_sbr_data->del_cod_dir_noise_arr[0] == DTDF_DIR_FREQ) {
|
|
ptr1 = ptr_noise_floor++;
|
|
ptr2 = ptr_noise_floor;
|
|
num = num_nf_bands - 1;
|
|
} else {
|
|
ptr1 = ptr_prev_noise_floor;
|
|
ptr2 = ptr_sbr_data->int_noise_floor;
|
|
num = num_nf_bands;
|
|
}
|
|
|
|
ixheaacd_add_arr(ptr1, ptr2, num);
|
|
|
|
if (num_noise_env > 1) {
|
|
if (ptr_sbr_data->del_cod_dir_noise_arr[1] == DTDF_DIR_FREQ) {
|
|
ptr1 = &ptr_sbr_data->int_noise_floor[num_nf_bands];
|
|
ptr2 = &ptr_sbr_data->int_noise_floor[(num_nf_bands + 1)];
|
|
|
|
num = num_nf_bands - 1;
|
|
} else {
|
|
ptr1 = &ptr_sbr_data->int_noise_floor[0];
|
|
ptr2 = &ptr_sbr_data->int_noise_floor[num_nf_bands];
|
|
|
|
num = num_nf_bands;
|
|
}
|
|
ixheaacd_add_arr(ptr1, ptr2, num);
|
|
}
|
|
|
|
ixheaacd_limit_noise_floor_fac(ptr_header_data, ptr_sbr_data);
|
|
|
|
ixheaacd_drc_offset = num_nf_bands * (num_noise_env - 1);
|
|
ptr1 = &ptr_sbr_data->int_noise_floor[ixheaacd_drc_offset];
|
|
ptr2 = ptr_prev_noise_floor;
|
|
|
|
memcpy(ptr2, ptr1, sizeof(WORD16) * (num_nf_bands));
|
|
|
|
if (ptr_sbr_data->coupling_mode != COUPLING_BAL) {
|
|
WORD32 noise_floor_exp, tot_nf_bands;
|
|
|
|
tot_nf_bands = (num_nf_bands * num_noise_env);
|
|
ptr_noise_floor = &ptr_sbr_data->int_noise_floor[0];
|
|
|
|
for (i = 0; i < tot_nf_bands; i++) {
|
|
noise_floor_exp =
|
|
(NOISE_FLOOR_OFFSET_INT + 1 + NOISE_EXP_OFFSET - *ptr_noise_floor);
|
|
|
|
*ptr_noise_floor_float++ = *ptr_noise_floor;
|
|
*ptr_noise_floor++ = (WORD16)(0x4000 + (noise_floor_exp & MASK_FOR_EXP));
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID ixheaacd_dec_sbrdata_for_pvc(
|
|
ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data) {
|
|
ixheaacd_calc_noise_floor(ptr_header_data, ptr_sbr_data, ptr_prev_data);
|
|
|
|
if (!ptr_sbr_data->coupling_mode) {
|
|
ptr_sbr_data->num_noise_sfac =
|
|
ptr_header_data->pstr_freq_band_data->num_nf_bands *
|
|
ptr_sbr_data->str_frame_info_details.num_noise_env;
|
|
ixheaacd_dequant_pvc_env_data(ptr_sbr_data->num_noise_sfac,
|
|
ptr_sbr_data->flt_noise_floor);
|
|
}
|
|
}
|
|
|
|
VOID ixheaacd_sbr_env_dequant_coup_fix(
|
|
ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_data_left,
|
|
ia_sbr_frame_info_data_struct *ptr_data_right,
|
|
ixheaacd_misc_tables *pstr_common_tables) {
|
|
WORD32 i;
|
|
WORD32 num_env_sf = ptr_data_left->num_env_sfac;
|
|
WORD16 temp_left_mant, temp_right_mant, temp_right_plus1_mant, new_left_mant,
|
|
new_right_mant;
|
|
WORD16 temp_left_exp, temp_right_exp, temp_rightplus1_exp, new_left_exp,
|
|
new_right_exp;
|
|
WORD32 i_end;
|
|
WORD16 *r_data = ptr_data_right->int_env_sf_arr;
|
|
WORD16 *l_data = ptr_data_left->int_env_sf_arr;
|
|
|
|
for (i = 0; i < num_env_sf; i++) {
|
|
temp_right_mant = (WORD16)(*r_data & MASK_M);
|
|
temp_right_exp = (WORD16)(*r_data & MASK_FOR_EXP);
|
|
|
|
temp_right_exp = sub16_m(temp_right_exp, add16_m(18, NRG_EXP_OFFSET));
|
|
temp_left_mant = (WORD16)(*l_data & MASK_M);
|
|
temp_left_exp = (WORD16)(*l_data & MASK_FOR_EXP);
|
|
|
|
temp_left_exp = sub16_m(temp_left_exp, NRG_EXP_OFFSET);
|
|
|
|
ixheaacd_fix_mant_exp_add(temp_right_mant, temp_right_exp, 0x4000, 1,
|
|
&temp_right_plus1_mant, &temp_rightplus1_exp);
|
|
|
|
new_right_exp = ixheaacd_fix_mant_div(temp_left_mant, temp_right_plus1_mant,
|
|
&new_right_mant, pstr_common_tables);
|
|
|
|
new_right_exp += temp_left_exp - temp_rightplus1_exp + 2;
|
|
|
|
new_left_mant = ixheaacd_mult16_shl(temp_right_mant, new_right_mant);
|
|
|
|
new_left_exp = add16_m(temp_right_exp, new_right_exp);
|
|
|
|
*r_data++ = (WORD16)(((new_right_mant + ROUNDING) & MASK_M) +
|
|
((new_right_exp + NRG_EXP_OFFSET) & MASK_FOR_EXP));
|
|
*l_data++ = (WORD16)(((new_left_mant + ROUNDING) & MASK_M) +
|
|
((new_left_exp + NRG_EXP_OFFSET) & MASK_FOR_EXP));
|
|
}
|
|
|
|
i_end = ptr_header_data->pstr_freq_band_data->num_nf_bands *
|
|
ptr_data_left->str_frame_info_details.num_noise_env;
|
|
r_data = ptr_data_right->int_noise_floor;
|
|
l_data = ptr_data_left->int_noise_floor;
|
|
|
|
for (i = i_end - 1; i >= 0; i--) {
|
|
temp_left_exp =
|
|
sub16_m((WORD16)(*l_data & (WORD16)MASK_FOR_EXP), NOISE_EXP_OFFSET);
|
|
temp_right_exp = sub16_m(*r_data, 12);
|
|
|
|
ixheaacd_fix_mant_exp_add(0x4000, ixheaacd_add16(1, temp_right_exp), 0x4000,
|
|
1, &temp_right_plus1_mant, &temp_rightplus1_exp);
|
|
|
|
new_right_exp = ixheaacd_fix_mant_div(0x4000, temp_right_plus1_mant,
|
|
&new_right_mant, pstr_common_tables);
|
|
|
|
new_right_exp += temp_left_exp - temp_rightplus1_exp + 2;
|
|
|
|
new_left_mant = new_right_mant;
|
|
new_left_exp = add16_m(new_right_exp, temp_right_exp);
|
|
*r_data++ = (WORD16)(((new_right_mant + ROUNDING) & MASK_M) +
|
|
((new_right_exp + NOISE_EXP_OFFSET) & MASK_FOR_EXP));
|
|
*l_data++ = (WORD16)(((new_left_mant + ROUNDING) & MASK_M) +
|
|
((new_left_exp + NOISE_EXP_OFFSET) & MASK_FOR_EXP));
|
|
}
|
|
}
|
|
|
|
VOID ixheaacd_sbr_env_dequant_coup(
|
|
ia_sbr_frame_info_data_struct *ptr_data_ch_0,
|
|
ia_sbr_frame_info_data_struct *ptr_data_ch_1) {
|
|
FLOAT32 *ptr_env_sf_left = ptr_data_ch_0->flt_env_sf_arr;
|
|
FLOAT32 *ptr_env_sf_right = ptr_data_ch_1->flt_env_sf_arr;
|
|
FLOAT32 *ptr_noise_floor_left = ptr_data_ch_0->flt_noise_floor;
|
|
FLOAT32 *ptr_noise_floor_right = ptr_data_ch_1->flt_noise_floor;
|
|
WORD32 num_env_sf = ptr_data_ch_0->num_env_sfac;
|
|
WORD32 num_noise_fac = ptr_data_ch_0->num_noise_sfac;
|
|
WORD32 amp_res = ptr_data_ch_0->amp_res;
|
|
|
|
WORD32 i;
|
|
FLOAT32 temp_l, temp_r;
|
|
FLOAT32 pan_offset[2] = {24.0f, 12.0f};
|
|
FLOAT32 a_arr[2] = {0.5f, 1.0f};
|
|
|
|
FLOAT32 a = a_arr[amp_res];
|
|
|
|
for (i = 0; i < num_env_sf; i++) {
|
|
temp_l = ptr_env_sf_left[i];
|
|
temp_r = ptr_env_sf_right[i];
|
|
|
|
ptr_env_sf_left[i] =
|
|
(FLOAT32)(64 * (pow(2, temp_l * a + 1) /
|
|
(1 + pow(2, (pan_offset[amp_res] - temp_r) * a))));
|
|
ptr_env_sf_right[i] =
|
|
(FLOAT32)(64 * (pow(2, temp_l * a + 1) /
|
|
(1 + pow(2, (temp_r - pan_offset[amp_res]) * a))));
|
|
}
|
|
|
|
for (i = 0; i < num_noise_fac; i++) {
|
|
temp_l = ptr_noise_floor_left[i];
|
|
temp_r = ptr_noise_floor_right[i];
|
|
|
|
ptr_noise_floor_left[i] =
|
|
(FLOAT32)(pow(2, NOISE_FLOOR_OFFSET - temp_l + 1) /
|
|
(1 + pow(2, pan_offset[1] - temp_r)));
|
|
ptr_noise_floor_right[i] =
|
|
(FLOAT32)(pow(2, NOISE_FLOOR_OFFSET - temp_l + 1) /
|
|
(1 + pow(2, temp_r - pan_offset[1])));
|
|
}
|
|
}
|
|
WORD32 ixheaacd_dec_sbrdata(ia_sbr_header_data_struct *ptr_header_data_ch_0,
|
|
ia_sbr_header_data_struct *ptr_header_data_ch_1,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data_ch_0,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data_ch_0,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data_ch_1,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data_ch_1,
|
|
ixheaacd_misc_tables *ptr_common_tables) {
|
|
FLAG error_code;
|
|
WORD32 err = 0;
|
|
WORD32 usac_flag = ptr_header_data_ch_0->usac_flag;
|
|
|
|
err = ixheaacd_dec_envelope(ptr_header_data_ch_0, ptr_sbr_data_ch_0,
|
|
ptr_prev_data_ch_0, ptr_prev_data_ch_1,
|
|
ptr_common_tables);
|
|
|
|
if (err) return err;
|
|
|
|
ixheaacd_calc_noise_floor(ptr_header_data_ch_0, ptr_sbr_data_ch_0,
|
|
ptr_prev_data_ch_0);
|
|
|
|
if (!ptr_sbr_data_ch_0->coupling_mode && usac_flag) {
|
|
ptr_sbr_data_ch_0->num_noise_sfac =
|
|
ptr_header_data_ch_0->pstr_freq_band_data->num_nf_bands *
|
|
ptr_sbr_data_ch_0->str_frame_info_details.num_noise_env;
|
|
|
|
ixheaacd_dequant_esbr_env_data(
|
|
ptr_sbr_data_ch_0->flt_env_sf_arr, ptr_sbr_data_ch_0->num_env_sfac,
|
|
ptr_sbr_data_ch_0->num_noise_sfac, ptr_sbr_data_ch_0->amp_res,
|
|
ptr_sbr_data_ch_0->flt_noise_floor);
|
|
}
|
|
|
|
if (ptr_sbr_data_ch_1 != NULL) {
|
|
error_code = ptr_header_data_ch_0->err_flag;
|
|
err = ixheaacd_dec_envelope(ptr_header_data_ch_1, ptr_sbr_data_ch_1,
|
|
ptr_prev_data_ch_1, ptr_prev_data_ch_0,
|
|
ptr_common_tables);
|
|
|
|
if (err) return err;
|
|
|
|
ixheaacd_calc_noise_floor(ptr_header_data_ch_1, ptr_sbr_data_ch_1,
|
|
ptr_prev_data_ch_1);
|
|
|
|
if (!ptr_sbr_data_ch_1->coupling_mode && usac_flag) {
|
|
ptr_sbr_data_ch_1->num_noise_sfac =
|
|
ptr_header_data_ch_1->pstr_freq_band_data->num_nf_bands *
|
|
ptr_sbr_data_ch_1->str_frame_info_details.num_noise_env;
|
|
|
|
ixheaacd_dequant_esbr_env_data(
|
|
ptr_sbr_data_ch_1->flt_env_sf_arr, ptr_sbr_data_ch_1->num_env_sfac,
|
|
ptr_sbr_data_ch_1->num_noise_sfac, ptr_sbr_data_ch_1->amp_res,
|
|
ptr_sbr_data_ch_1->flt_noise_floor);
|
|
}
|
|
|
|
if (!usac_flag) {
|
|
if (!error_code && ptr_header_data_ch_0->err_flag) {
|
|
err = ixheaacd_dec_envelope(ptr_header_data_ch_0, ptr_sbr_data_ch_0,
|
|
ptr_prev_data_ch_0, ptr_prev_data_ch_1,
|
|
ptr_common_tables);
|
|
|
|
if (err) return err;
|
|
}
|
|
}
|
|
|
|
if (ptr_sbr_data_ch_0->coupling_mode) {
|
|
ixheaacd_sbr_env_dequant_coup_fix(ptr_header_data_ch_0, ptr_sbr_data_ch_0,
|
|
ptr_sbr_data_ch_1, ptr_common_tables);
|
|
|
|
ixheaacd_sbr_env_dequant_coup(ptr_sbr_data_ch_0, ptr_sbr_data_ch_1);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
WORD32 ixheaacd_dec_envelope(ia_sbr_header_data_struct *ptr_header_data,
|
|
ia_sbr_frame_info_data_struct *ptr_sbr_data,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data_ch_0,
|
|
ia_sbr_prev_frame_data_struct *ptr_prev_data_ch_1,
|
|
ixheaacd_misc_tables *pstr_common_tables) {
|
|
FLAG error_code;
|
|
WORD32 err;
|
|
WORD16 env_sf_local_arr[MAX_FREQ_COEFFS];
|
|
WORD32 usac_flag = ptr_header_data->usac_flag;
|
|
WORD32 temp_1 =
|
|
ptr_prev_data_ch_0->end_position - ptr_header_data->num_time_slots;
|
|
if (temp_1 < 0) return -1;
|
|
temp_1 = ptr_sbr_data->str_frame_info_details.border_vec[0] - temp_1;
|
|
|
|
if ((!ptr_header_data->err_flag_prev) && (!ptr_header_data->err_flag) &&
|
|
(temp_1 != 0)) {
|
|
if (ptr_sbr_data->del_cod_dir_arr[0] == DTDF_DIR_TIME) {
|
|
ptr_header_data->err_flag = 1;
|
|
} else {
|
|
ptr_header_data->err_flag_prev = 1;
|
|
}
|
|
}
|
|
|
|
if (ptr_header_data->err_flag && !usac_flag) {
|
|
ixheaacd_lean_sbrconcealment(ptr_header_data, ptr_sbr_data,
|
|
ptr_prev_data_ch_0);
|
|
|
|
ixheaacd_process_del_cod_env_data(ptr_header_data, ptr_sbr_data,
|
|
ptr_prev_data_ch_0);
|
|
} else {
|
|
WORD32 num = ptr_header_data->pstr_freq_band_data->num_sf_bands[HIGH];
|
|
if (ptr_header_data->err_flag_prev && !usac_flag) {
|
|
WORD16 *ptr1, *ptr2;
|
|
WORD32 i;
|
|
|
|
err = ixheaacd_wrong_timing_compensate(ptr_header_data, ptr_sbr_data,
|
|
ptr_prev_data_ch_0,
|
|
pstr_common_tables);
|
|
|
|
if (err) return err;
|
|
|
|
if (ptr_sbr_data->coupling_mode !=
|
|
(WORD16)ptr_prev_data_ch_0->coupling_mode) {
|
|
if (ptr_prev_data_ch_0->coupling_mode == COUPLING_BAL) {
|
|
memcpy(ptr_prev_data_ch_0->sfb_nrg_prev,
|
|
ptr_prev_data_ch_1->sfb_nrg_prev, sizeof(WORD16) * num);
|
|
} else {
|
|
if (ptr_sbr_data->coupling_mode == COUPLING_LEVEL) {
|
|
ptr1 = ptr_prev_data_ch_0->sfb_nrg_prev;
|
|
ptr2 = ptr_prev_data_ch_1->sfb_nrg_prev;
|
|
|
|
for (i = 0; i < num; i++) {
|
|
*ptr1 = (add16_m(*ptr1, *ptr2) >> 1);
|
|
ptr2++;
|
|
ptr1++;
|
|
}
|
|
} else {
|
|
if (ptr_sbr_data->coupling_mode == COUPLING_BAL) {
|
|
memset(ptr_prev_data_ch_0->sfb_nrg_prev, SBR_ENERGY_PAN_OFFSET,
|
|
sizeof(WORD16) * num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
memcpy(env_sf_local_arr, ptr_prev_data_ch_0->sfb_nrg_prev,
|
|
sizeof(WORD16) * MAX_FREQ_COEFFS);
|
|
|
|
ixheaacd_process_del_cod_env_data(ptr_header_data, ptr_sbr_data,
|
|
ptr_prev_data_ch_0);
|
|
|
|
if (!usac_flag) {
|
|
error_code = ixheaacd_check_env_data(ptr_header_data, ptr_sbr_data,
|
|
ptr_prev_data_ch_0);
|
|
|
|
if (error_code) {
|
|
ptr_header_data->err_flag = 1;
|
|
|
|
memcpy(ptr_prev_data_ch_0->sfb_nrg_prev, env_sf_local_arr,
|
|
sizeof(WORD16) * MAX_FREQ_COEFFS);
|
|
|
|
err = ixheaacd_dec_envelope(ptr_header_data, ptr_sbr_data,
|
|
ptr_prev_data_ch_0, ptr_prev_data_ch_1,
|
|
pstr_common_tables);
|
|
|
|
if (err) return err;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
if (!usac_flag)
|
|
ixheaacd_dequant_env_data(ptr_sbr_data, ptr_sbr_data->amp_res);
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID ixheaacd_adj_timeslot(WORD32 *ptr_buf_real, WORD32 *ptr_buf_imag,
|
|
WORD16 *ptr_filt_buf, WORD16 *ptr_filt_buf_noise,
|
|
WORD16 *ptr_gain_buf, WORD16 *ptr_noise_floor,
|
|
WORD16 *ptr_sine_lvl_buf, WORD16 noise_floor_exp,
|
|
WORD16 *ptr_harm_index, WORD16 sub_band_start,
|
|
WORD16 num_sub_bands, WORD16 scale_change,
|
|
WORD16 smooth_ratio, FLAG num_noise_flg,
|
|
WORD16 *ptr_phase_index,
|
|
ia_sbr_tables_struct *ptr_sbr_tables) {
|
|
WORD16 k;
|
|
WORD16 *ptr_smoothed_gain, *ptr_smoothed_noise;
|
|
WORD16 direct_ratio;
|
|
WORD32 index = *ptr_phase_index;
|
|
WORD32 harm_idx = *ptr_harm_index;
|
|
WORD32 freq_inv_flag;
|
|
const WORD32 *ptr_rand_ph_buf;
|
|
WORD32 factor = 0;
|
|
|
|
direct_ratio = ixheaacd_sub16_sat(0x7fff, smooth_ratio);
|
|
freq_inv_flag = (sub_band_start & 1);
|
|
|
|
scale_change = scale_change - 1;
|
|
|
|
ptr_rand_ph_buf = &ptr_sbr_tables->sbr_rand_ph[index];
|
|
*ptr_phase_index =
|
|
(WORD16)((index + num_sub_bands) & (SBR_NF_NO_RANDOM_VAL - 1));
|
|
|
|
if (smooth_ratio) {
|
|
WORD16 *ptr_filt_buf_local = &ptr_filt_buf[0];
|
|
WORD16 *ptr_gain_buf_local = &ptr_gain_buf[0];
|
|
WORD16 *ptr_filt_noise_local = &ptr_filt_buf_noise[0];
|
|
WORD16 *ptr_noise_floor_local = &ptr_noise_floor[0];
|
|
|
|
WORD16 tmp, tmp1;
|
|
|
|
for (k = 0; k < num_sub_bands; k++) {
|
|
tmp = add16_m(mult16x16_16(smooth_ratio, *ptr_filt_buf_local),
|
|
mult16x16_16(direct_ratio, *ptr_gain_buf_local++));
|
|
|
|
ptr_gain_buf_local++;
|
|
|
|
tmp1 = add16_m(mult16x16_16(smooth_ratio, *ptr_filt_noise_local),
|
|
mult16x16_16(direct_ratio, *ptr_noise_floor_local++));
|
|
|
|
ptr_noise_floor_local++;
|
|
|
|
*ptr_filt_buf_local++ = tmp << 1;
|
|
ptr_filt_buf_local++;
|
|
*ptr_filt_noise_local++ = tmp1 << 1;
|
|
}
|
|
ptr_smoothed_gain = ptr_filt_buf;
|
|
ptr_smoothed_noise = ptr_filt_buf_noise;
|
|
factor = 1;
|
|
} else {
|
|
ptr_smoothed_gain = ptr_gain_buf;
|
|
ptr_smoothed_noise = ptr_noise_floor;
|
|
factor = 2;
|
|
}
|
|
|
|
switch (harm_idx) {
|
|
case 0:
|
|
case 2:
|
|
ixheaacd_harm_idx_zerotwo(num_noise_flg, num_sub_bands, ptr_buf_real,
|
|
ptr_buf_imag, ptr_smoothed_gain,
|
|
ptr_smoothed_noise, factor, ptr_gain_buf,
|
|
scale_change, ptr_rand_ph_buf, ptr_sine_lvl_buf,
|
|
noise_floor_exp, harm_idx);
|
|
break;
|
|
case 1:
|
|
case 3:
|
|
ixheaacd_harm_idx_onethree(
|
|
num_noise_flg, num_sub_bands, ptr_buf_real, ptr_buf_imag,
|
|
ptr_smoothed_gain, ptr_smoothed_noise, factor, ptr_gain_buf,
|
|
scale_change, ptr_rand_ph_buf, ptr_sine_lvl_buf, noise_floor_exp,
|
|
freq_inv_flag, harm_idx);
|
|
break;
|
|
}
|
|
*ptr_harm_index = (WORD16)((harm_idx + 1) & 3);
|
|
}
|