312 lines
11 KiB
C
312 lines
11 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 "ixheaacd_type_def.h"
|
|
#include "ixheaacd_constants.h"
|
|
#include "ixheaacd_error_standards.h"
|
|
|
|
#include "ixheaacd_bitbuffer.h"
|
|
#include "ixheaacd_config.h"
|
|
|
|
#include <assert.h>
|
|
|
|
#ifndef sign
|
|
#define sign(a) (((a) > 0) ? 1 : ((a) < 0) ? -1 : 0)
|
|
#endif
|
|
|
|
typedef struct {
|
|
WORD32 num_input_chan;
|
|
WORD32 num_output_chan;
|
|
WORD32 num_ott_boxes;
|
|
WORD32 num_ttt_boxes;
|
|
WORD32 ott_mode_lfe[MAX_NUM_OTT];
|
|
} ia_ld_mps_dec_tree_properties_struct;
|
|
|
|
static WORD32 ixheaacd_freq_res_table[] = {0, 23, 15, 12, 9, 7, 5, 4};
|
|
|
|
static WORD32 ixheaacd_hrtf_freq_res_table[][8] = {{0, 28, 20, 14, 10, 7, 5, 4},
|
|
{0, 13, 13, 8, 7, 4, 3, 3}};
|
|
|
|
static ia_ld_mps_dec_tree_properties_struct ixheaacd_tree_property_table[] = {
|
|
{1, 6, 5, 0, {0, 0, 0, 0, 1}}, {1, 6, 5, 0, {0, 0, 1, 0, 0}}, {2, 6, 3, 1, {1, 0, 0, 0, 0}},
|
|
{2, 8, 5, 1, {1, 0, 0, 0, 0}}, {2, 8, 5, 1, {1, 0, 0, 0, 0}}, {6, 8, 2, 0, {0, 0, 0, 0, 0}},
|
|
{6, 8, 2, 0, {0, 0, 0, 0, 0}}, {1, 2, 1, 0, {0, 0, 0, 0, 0}}};
|
|
|
|
static IA_ERRORCODE ixheaacd_ld_spatial_extension_config(
|
|
ia_bit_buf_struct *it_bit_buff, ia_usac_dec_mps_config_struct *config,
|
|
WORD32 bits_available) {
|
|
WORD32 j, ch, idx, tmp, tmp_open, sac_ext_len, bits_read, n_fill_bits;
|
|
UWORD32 i;
|
|
WORD32 ba = bits_available;
|
|
|
|
config->sac_ext_cnt = 0;
|
|
|
|
tmp = it_bit_buff->cnt_bits;
|
|
|
|
while (ba >= 8) {
|
|
if (config->sac_ext_cnt >= MAX_NUM_EXT_TYPES) return IA_FATAL_ERROR;
|
|
|
|
config->bs_sac_ext_type[config->sac_ext_cnt] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 4);
|
|
ba -= 4;
|
|
|
|
sac_ext_len = ixheaacd_read_bits_buf(it_bit_buff, 4);
|
|
ba -= 4;
|
|
|
|
if ((ba >= 6) && (sac_ext_len > 0)) {
|
|
if (sac_ext_len == 15) {
|
|
sac_ext_len += ixheaacd_read_bits_buf(it_bit_buff, 8);
|
|
ba -= 8;
|
|
if (sac_ext_len == 15 + 255) {
|
|
sac_ext_len += ixheaacd_read_bits_buf(it_bit_buff, 16);
|
|
ba -= 16;
|
|
}
|
|
}
|
|
|
|
switch (config->bs_sac_ext_type[config->sac_ext_cnt]) {
|
|
case 0:
|
|
config->bs_residual_coding = 1;
|
|
|
|
config->bs_residual_sampling_freq_index =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 4);
|
|
config->bs_residual_frames_per_spatial_frame =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 2);
|
|
|
|
if ((config->num_ott_boxes + config->num_ttt_boxes) >
|
|
MAX_RESIDUAL_CHANNELS)
|
|
return IA_FATAL_ERROR;
|
|
for (j = 0; j < config->num_ott_boxes + config->num_ttt_boxes; j++) {
|
|
config->bs_residual_present[j] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
if (config->bs_residual_present[j]) {
|
|
config->bs_residual_bands_ld_mps[j] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 5);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
config->bs_arbitrary_downmix = 2;
|
|
|
|
config->bs_arbitrary_downmix_residual_sampling_freq_index =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 4);
|
|
config->bs_arbitrary_downmix_residual_frames_per_spatial_frame =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 2);
|
|
config->bs_arbitrary_downmix_residual_bands =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 5);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
config->num_out_chan_AT = 0;
|
|
config->num_ott_boxes_AT = 0;
|
|
if (config->num_output_channels > MAX_OUTPUT_CHANNELS)
|
|
return IA_FATAL_ERROR;
|
|
for (ch = 0; ch < config->num_output_channels; ch++) {
|
|
tmp_open = 1;
|
|
idx = 0;
|
|
while ((tmp_open > 0) && (idx < MAX_ARBITRARY_TREE_INDEX)) {
|
|
config->bs_ott_box_present_AT[ch][idx] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
if (config->bs_ott_box_present_AT[ch][idx]) {
|
|
config->num_ott_boxes_AT++;
|
|
tmp_open++;
|
|
} else {
|
|
config->num_out_chan_AT++;
|
|
tmp_open--;
|
|
}
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < config->num_ott_boxes_AT; i++) {
|
|
config->bs_ott_default_cld_AT[i] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
config->bs_ott_mode_lfe_AT[i] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
if (config->bs_ott_mode_lfe_AT[i]) {
|
|
config->bs_ott_bands_AT[i] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 5);
|
|
} else {
|
|
config->bs_ott_bands_AT[i] = ixheaacd_freq_res_table[config->bs_freq_res];
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < config->num_out_chan_AT; i++) {
|
|
config->bs_output_channel_pos_AT[i] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 5);
|
|
}
|
|
|
|
break;
|
|
|
|
default:;
|
|
}
|
|
}
|
|
|
|
bits_read = tmp - it_bit_buff->cnt_bits;
|
|
n_fill_bits = 8 * sac_ext_len - bits_read;
|
|
|
|
while (n_fill_bits > 7) {
|
|
ixheaacd_read_bits_buf(it_bit_buff, 8);
|
|
n_fill_bits -= 8;
|
|
}
|
|
if (n_fill_bits > 0) {
|
|
ixheaacd_read_bits_buf(it_bit_buff, n_fill_bits);
|
|
}
|
|
|
|
ba -= 8 * sac_ext_len;
|
|
config->sac_ext_cnt++;
|
|
}
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
IA_ERRORCODE ixheaacd_ld_spatial_specific_config(
|
|
ia_usac_dec_mps_config_struct *config, ia_bit_buf_struct *it_bit_buff) {
|
|
WORD32 i, num_header_bits;
|
|
UWORD32 hc, hb;
|
|
WORD32 sac_header_len;
|
|
WORD32 bits_available;
|
|
WORD32 tmp = it_bit_buff->cnt_bits;
|
|
WORD32 err = 0;
|
|
|
|
sac_header_len = tmp;
|
|
|
|
bits_available = sac_header_len;
|
|
config->bs_sampling_freq_index = ixheaacd_read_bits_buf(it_bit_buff, 4);
|
|
if (config->bs_sampling_freq_index == 15) {
|
|
config->bs_fampling_frequency = ixheaacd_read_bits_buf(it_bit_buff, 24);
|
|
}
|
|
|
|
config->bs_frame_length = ixheaacd_read_bits_buf(it_bit_buff, 5);
|
|
config->bs_freq_res = ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
config->bs_tree_config = ixheaacd_read_bits_buf(it_bit_buff, 4);
|
|
|
|
if (config->bs_tree_config > 7) return IA_FATAL_ERROR;
|
|
|
|
if (config->bs_tree_config != 15) {
|
|
config->num_ott_boxes =
|
|
ixheaacd_tree_property_table[config->bs_tree_config].num_ott_boxes;
|
|
config->num_ttt_boxes =
|
|
ixheaacd_tree_property_table[config->bs_tree_config].num_ttt_boxes;
|
|
config->num_input_channels =
|
|
ixheaacd_tree_property_table[config->bs_tree_config].num_input_chan;
|
|
config->num_output_channels =
|
|
ixheaacd_tree_property_table[config->bs_tree_config].num_output_chan;
|
|
for (i = 0; i < MAX_NUM_OTT; i++) {
|
|
config->ott_mode_lfe[i] =
|
|
ixheaacd_tree_property_table[config->bs_tree_config].ott_mode_lfe[i];
|
|
}
|
|
}
|
|
config->bs_quant_mode = ixheaacd_read_bits_buf(it_bit_buff, 2);
|
|
if (config->bs_tree_config != 7) {
|
|
config->bs_one_icc = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
}
|
|
config->bs_arbitrary_downmix = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
if (config->bs_tree_config != 7) {
|
|
config->bs_fixed_gain_sur = ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
config->bs_fixed_gain_LFE = ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
}
|
|
config->bs_fixed_gain_dmx = ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
if (config->bs_tree_config != 7) {
|
|
config->bs_matrix_mode = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
}
|
|
config->bs_temp_shape_config = ixheaacd_read_bits_buf(it_bit_buff, 2);
|
|
config->bs_decorr_config = ixheaacd_read_bits_buf(it_bit_buff, 2);
|
|
if (config->bs_tree_config != 7) {
|
|
config->bs_3D_audio_mode = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
} else {
|
|
config->bs_3D_audio_mode = 0;
|
|
}
|
|
|
|
// ott_config
|
|
for (i = 0; i < config->num_ott_boxes; i++) {
|
|
if (config->ott_mode_lfe[i]) {
|
|
config->bs_ott_bands[i] = ixheaacd_read_bits_buf(it_bit_buff, 5);
|
|
} else {
|
|
config->bs_ott_bands[i] = ixheaacd_freq_res_table[config->bs_freq_res];
|
|
}
|
|
}
|
|
|
|
// ttt_config
|
|
for (i = 0; i < config->num_ttt_boxes; i++) {
|
|
config->bs_ttt_dual_mode[i] = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
config->bs_ttt_mode_low[i] = ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
if (config->bs_ttt_dual_mode[i]) {
|
|
config->bs_ttt_mode_high[i] = ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
config->bs_ttt_bands_low[i] = ixheaacd_read_bits_buf(it_bit_buff, 5);
|
|
config->bs_ttt_bands_high[i] = ixheaacd_freq_res_table[config->bs_freq_res];
|
|
} else {
|
|
config->bs_ttt_bands_low[i] = ixheaacd_freq_res_table[config->bs_freq_res];
|
|
}
|
|
}
|
|
|
|
if (config->bs_temp_shape_config == 2) {
|
|
config->bs_env_quant_mode = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
}
|
|
|
|
if (config->bs_3D_audio_mode) {
|
|
config->bs_3D_audio_HRTF_set = ixheaacd_read_bits_buf(it_bit_buff, 2);
|
|
// param_HRTF_set
|
|
if (config->bs_3D_audio_HRTF_set == 0) {
|
|
config->bs_HRTF_freq_res = ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
config->bs_HRTF_num_chan = 5;
|
|
config->bs_HRTF_asymmetric = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
|
|
config->HRTF_num_band = ixheaacd_hrtf_freq_res_table[0][config->bs_HRTF_freq_res];
|
|
config->HRTF_num_phase = ixheaacd_hrtf_freq_res_table[1][config->bs_HRTF_freq_res];
|
|
|
|
for (hc = 0; hc < config->bs_HRTF_num_chan; hc++) {
|
|
for (hb = 0; hb < config->HRTF_num_band; hb++) {
|
|
config->bs_HRTF_level_left[hc][hb] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 6);
|
|
}
|
|
for (hb = 0; hb < config->HRTF_num_band; hb++) {
|
|
config->bs_HRTF_level_right[hc][hb] =
|
|
config->bs_HRTF_asymmetric
|
|
? ixheaacd_read_bits_buf(it_bit_buff, 6)
|
|
: config->bs_HRTF_level_left[hc][hb];
|
|
}
|
|
config->bs_HRTF_phase[hc] = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
for (hb = 0; hb < config->HRTF_num_phase; hb++) {
|
|
config->bs_HRTF_phase_LR[hc][hb] =
|
|
config->bs_HRTF_phase[hc] ? ixheaacd_read_bits_buf(it_bit_buff, 6)
|
|
: 0;
|
|
}
|
|
config->bs_HRTF_icc[hc] = ixheaacd_read_bits_buf(it_bit_buff, 1);
|
|
if (config->bs_HRTF_icc[hc]) {
|
|
for (hb = 0; hb < config->HRTF_num_band; hb++)
|
|
config->bs_HRTF_icc_LR[hc][hb] =
|
|
ixheaacd_read_bits_buf(it_bit_buff, 3);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// byte_align
|
|
i = (it_bit_buff->cnt_bits & 0x7);
|
|
ixheaacd_read_bits_buf(it_bit_buff, i);
|
|
|
|
num_header_bits = tmp - (it_bit_buff->cnt_bits);
|
|
bits_available -= num_header_bits;
|
|
|
|
err =
|
|
ixheaacd_ld_spatial_extension_config(it_bit_buff, config, bits_available);
|
|
return err;
|
|
}
|