blob: 646633863e1a344d93301e4bcfcbb85d8917bc8b [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2023 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 "ixheaac_type_def.h"
#include "ixheaacd_memory_standards.h"
#include "ixheaacd_mps_struct_def.h"
#include "ixheaacd_mps_res_rom.h"
#include "ixheaacd_mps_aac_struct.h"
#include "ixheaac_constants.h"
#include "ixheaac_basic_ops32.h"
#include "ixheaac_basic_ops40.h"
#include "ixheaacd_bitbuffer.h"
#include "ixheaacd_common_rom.h"
#include "ixheaacd_sbrdecsettings.h"
#include "ixheaacd_sbr_scale.h"
#include "ixheaacd_env_extr_part.h"
#include "ixheaacd_sbr_rom.h"
#include "ixheaacd_hybrid.h"
#include "ixheaacd_ps_dec.h"
#include "ixheaacd_mps_polyphase.h"
#include "ixheaacd_config.h"
#include "ixheaacd_qmf_dec.h"
#include "ixheaacd_mps_dec.h"
#include "ixheaacd_mps_decor.h"
#include "ixheaacd_mps_hybfilter.h"
#include "ixheaacd_mps_mdct_2_qmf.h"
#include "ixheaacd_mps_get_index.h"
#include "ixheaacd_mps_macro_def.h"
#include "ixheaacd_mps_basic_op.h"
#include "ixheaac_error_standards.h"
VOID ixheaacd_mdct_2_qmf(ia_heaac_mps_state_struct *pstr_mps_state) {
ia_mps_dec_reuse_array_struct *p_array_struct = pstr_mps_state->array_struct;
WORD32 ch, rfpsf, qb;
WORD32 qmf_global_offset;
WORD32 time_slots = pstr_mps_state->time_slots;
WORD32 time_slots_x4 = (time_slots << 2);
WORD32 qmf_bands = pstr_mps_state->qmf_bands;
WORD32 *p_qmf_residual_real_post, *p_qmf_residual_imag_post;
VOID *scratch = pstr_mps_state->mps_scratch_mem_v;
if (pstr_mps_state->up_mix_type != 2) {
WORD32 num_ch = pstr_mps_state->num_ott_boxes + pstr_mps_state->num_ttt_boxes;
WORD32 rfpsf_max = pstr_mps_state->residual_frames_per_spatial_frame;
WORD32 upd_qmf = pstr_mps_state->upd_qmf;
WORD32 *qmf_residual_real_pre = p_array_struct->qmf_residual_real_pre;
WORD32 *qmf_residual_real_post = p_array_struct->qmf_residual_real_post;
WORD32 *qmf_residual_imag_pre = p_array_struct->qmf_residual_imag_pre;
WORD32 *qmf_residual_imag_post = p_array_struct->qmf_residual_imag_post;
WORD32 *p_res_mdct = p_array_struct->res_mdct;
for (ch = 0; ch < num_ch; ch++) {
if (pstr_mps_state->bs_config.bs_residual_present[ch]) {
WORD32 *res_mdct = p_res_mdct;
qmf_global_offset = 0;
p_qmf_residual_real_post = qmf_residual_real_post;
p_qmf_residual_imag_post = qmf_residual_imag_post;
for (qb = 0; qb < qmf_bands; qb++) {
memset(p_qmf_residual_real_post, 0, time_slots_x4);
memset(p_qmf_residual_imag_post, 0, time_slots_x4);
p_qmf_residual_real_post += MAX_TIME_SLOTS;
p_qmf_residual_imag_post += MAX_TIME_SLOTS;
}
for (rfpsf = 0; rfpsf < rfpsf_max; rfpsf++) {
ixheaacd_mdct2qmf_process(upd_qmf, res_mdct, qmf_residual_real_pre,
qmf_residual_real_post, qmf_residual_imag_pre,
qmf_residual_imag_post,
pstr_mps_state->res_block_type[ch][rfpsf], qmf_global_offset,
&(pstr_mps_state->ia_mps_dec_mps_table), scratch, time_slots);
qmf_global_offset += upd_qmf;
res_mdct += MDCTCOEFX2;
}
}
qmf_residual_real_pre += QBXTS;
qmf_residual_imag_pre += QBXTS;
qmf_residual_real_post += QBXTS;
qmf_residual_imag_post += QBXTS;
p_res_mdct += RFX2XMDCTCOEF;
}
}
if (pstr_mps_state->arbitrary_downmix == 2) {
WORD32 arbdmx_upd_qmf = pstr_mps_state->arbdmx_upd_qmf;
WORD32 offset = pstr_mps_state->num_ott_boxes + pstr_mps_state->num_ttt_boxes;
WORD32 in_ch = pstr_mps_state->num_input_channels;
WORD32 rfpsf_max = pstr_mps_state->arbdmx_frames_per_spatial_frame;
WORD32 *qmf_residual_real_pre = p_array_struct->qmf_residual_real_pre + offset * QBXTS;
WORD32 *qmf_residual_imag_pre = p_array_struct->qmf_residual_imag_pre + offset * QBXTS;
WORD32 *qmf_residual_real_post = p_array_struct->qmf_residual_real_post + offset * QBXTS;
WORD32 *qmf_residual_imag_post = p_array_struct->qmf_residual_imag_post + offset * QBXTS;
WORD32 *p_res_mdct = p_array_struct->res_mdct + offset * RFX2XMDCTCOEF;
for (ch = 0; ch < in_ch; ch++) {
WORD32 *res_mdct = p_res_mdct;
qmf_global_offset = 0;
p_qmf_residual_real_post = qmf_residual_real_post;
p_qmf_residual_imag_post = qmf_residual_imag_post;
for (qb = 0; qb < qmf_bands; qb++) {
memset(p_qmf_residual_real_post, 0, time_slots_x4);
memset(p_qmf_residual_imag_post, 0, time_slots_x4);
p_qmf_residual_real_post += MAX_TIME_SLOTS;
p_qmf_residual_imag_post += MAX_TIME_SLOTS;
}
for (rfpsf = 0; rfpsf < rfpsf_max; rfpsf++) {
ixheaacd_mdct2qmf_process(
arbdmx_upd_qmf, res_mdct, qmf_residual_real_pre, qmf_residual_real_post,
qmf_residual_imag_pre, qmf_residual_imag_post,
pstr_mps_state->res_block_type[offset + ch][rfpsf], qmf_global_offset,
&(pstr_mps_state->ia_mps_dec_mps_table), scratch, time_slots);
qmf_global_offset += arbdmx_upd_qmf;
res_mdct += MDCTCOEFX2;
}
qmf_residual_real_pre += QBXTS;
qmf_residual_imag_pre += QBXTS;
qmf_residual_imag_post += QBXTS;
qmf_residual_real_post += QBXTS;
p_res_mdct += RFX2XMDCTCOEF;
}
}
return;
}
VOID ixheaacd_hybrid_qmf_analysis(ia_heaac_mps_state_struct *pstr_mps_state) {
WORD32 ch;
WORD32 in_ch = pstr_mps_state->num_input_channels;
WORD32 num_ott_boxes = pstr_mps_state->num_ott_boxes;
WORD32 num_ttt_boxes = pstr_mps_state->num_ttt_boxes;
WORD32 num_input_channels = in_ch;
WORD32 qmf_bands = pstr_mps_state->qmf_bands;
WORD32 time_slots = pstr_mps_state->time_slots;
WORD32 hybrid_bands = pstr_mps_state->hybrid_bands;
WORD32 num_parameter_bands = pstr_mps_state->num_parameter_bands;
SIZE_T *kernels = pstr_mps_state->kernels;
WORD32 *res_bands = pstr_mps_state->res_bands;
WORD32 *index = pstr_mps_state->index;
ia_mps_dec_thyb_filter_state_struct *hyb_filter_state =
pstr_mps_state->mps_persistent_mem.hyb_filter_state;
ia_mps_dec_reuse_array_struct *p_array_struct = pstr_mps_state->array_struct;
ia_mps_dec_hybrid_tables_struct *hybrid_table_ptr =
pstr_mps_state->ia_mps_dec_mps_table.hybrid_table_ptr;
WORD32 *p_buf_real = p_array_struct->buf_real;
WORD32 *p_buf_imag = p_array_struct->buf_imag;
WORD32 *p_x_real = p_array_struct->x_real;
WORD32 *p_x_imag = p_array_struct->x_imag;
for (ch = 0; ch < in_ch; ch++) {
ixheaacd_apply_ana_hyb_filt_bank_create_x(&hyb_filter_state[ch], p_buf_real, p_buf_imag,
qmf_bands, time_slots, p_x_real, p_x_imag,
hybrid_table_ptr);
pstr_mps_state->index[ch] = hybrid_bands;
p_buf_real += TSXHB;
p_buf_imag += TSXHB;
p_x_real += TSXHB;
p_x_imag += TSXHB;
}
if ((pstr_mps_state->residual_coding) && (pstr_mps_state->up_mix_type != 2)) {
WORD32 *qmf_residual_real = p_array_struct->qmf_residual_real_pre;
WORD32 *qmf_residual_imag = p_array_struct->qmf_residual_imag_pre;
WORD32 *p_dry_real = p_array_struct->w_dry_real;
WORD32 *p_dry_imag = p_array_struct->w_dry_imag;
for (ch = 0; ch < num_ott_boxes; ch++) {
if (res_bands[ch] > 0) {
ixheaacd_apply_ana_hyb_filt_bank_merge_res_decor(
&hyb_filter_state[ch + num_input_channels], qmf_residual_real, qmf_residual_imag,
qmf_bands, time_slots, p_dry_real, p_dry_imag, hybrid_table_ptr);
}
qmf_residual_real += QBXTS;
qmf_residual_imag += QBXTS;
p_dry_real += TSXHB;
p_dry_imag += TSXHB;
}
for (ch = num_ott_boxes; ch < num_ott_boxes + num_ttt_boxes; ch++, in_ch++) {
if (res_bands[ch] > 0) {
ixheaacd_apply_ana_hyb_filt_bank_create_x_res(
&hyb_filter_state[ch + num_input_channels], qmf_residual_real, qmf_residual_imag,
qmf_bands, time_slots, p_x_real, p_x_imag, kernels, res_bands[ch], hybrid_bands,
num_parameter_bands, &index[in_ch], hybrid_table_ptr);
} else
index[in_ch] = 0;
qmf_residual_real += QBXTS;
qmf_residual_imag += QBXTS;
p_x_real += TSXHB;
p_x_imag += TSXHB;
}
}
in_ch = num_input_channels + num_ttt_boxes;
if (pstr_mps_state->arbitrary_downmix == 2) {
WORD32 offset = num_ott_boxes + num_ttt_boxes;
WORD32 *qmf_residual_real = p_array_struct->qmf_residual_real_pre + offset * QBXTS;
WORD32 *qmf_residual_imag = p_array_struct->qmf_residual_imag_pre + offset * QBXTS;
p_x_real = p_array_struct->x_real + in_ch * TSXHB;
p_x_imag = p_array_struct->x_imag + in_ch * TSXHB;
for (ch = 0; ch < num_input_channels; ch++, in_ch++) {
ixheaacd_apply_ana_hyb_filt_bank_create_x_res(
&hyb_filter_state[offset + ch + num_input_channels], qmf_residual_real,
qmf_residual_imag, qmf_bands, time_slots, p_x_real, p_x_imag, kernels,
pstr_mps_state->arbdmx_residual_bands, hybrid_bands, num_parameter_bands, &index[in_ch],
hybrid_table_ptr);
qmf_residual_real += QBXTS;
qmf_residual_imag += QBXTS;
p_x_real += TSXHB;
p_x_imag += TSXHB;
}
}
}
VOID ixheaacd_merge_res_decor(ia_heaac_mps_state_struct *pstr_mps_state) {
WORD32 ts, qs, row, res;
WORD32 temp_1;
SIZE_T *idx;
ia_mps_dec_reuse_array_struct *p_array_struct = pstr_mps_state->array_struct;
ia_mps_dec_auxilary_struct *p_aux_struct = pstr_mps_state->aux_struct;
WORD32 time_slots = pstr_mps_state->time_slots;
WORD32 hybrid_bands = pstr_mps_state->hybrid_bands;
WORD32 num_direct_signals = pstr_mps_state->num_direct_signals;
WORD32 num_w_channels = pstr_mps_state->num_w_channels;
WORD32 num_parameter_bands = pstr_mps_state->num_parameter_bands;
SIZE_T *kernels_ptr = pstr_mps_state->kernels;
WORD32 *p_buf_real, *p_buf_imag, *p_buf_re, *p_buf_im;
WORD32 *buf_real_ch4, *buf_imag_ch4;
WORD32 *buf_real_ch3, *buf_imag_ch3;
p_buf_real = p_array_struct->buffer_real + TSXHBX5;
p_buf_imag = p_array_struct->buffer_imag + TSXHBX5;
for (ts = 0; ts < time_slots; ts++) {
p_buf_re = p_buf_real;
p_buf_im = p_buf_imag;
buf_real_ch4 = p_buf_real - TSXHB;
buf_imag_ch4 = p_buf_imag - TSXHB;
buf_real_ch3 = buf_real_ch4 - TSXHB;
buf_imag_ch3 = buf_imag_ch4 - TSXHB;
for (qs = 0; qs < hybrid_bands; qs++) {
if ((kernels_ptr[qs] < ((UWORD32)(p_aux_struct->ttt_config[0][0].stop_band)) &&
p_aux_struct->ttt_config[0][0].use_ttt_decorr) ||
(kernels_ptr[qs] >= ((UWORD32)p_aux_struct->ttt_config[1][0].start_band) &&
p_aux_struct->ttt_config[1][0].use_ttt_decorr)) {
temp_1 = (WORD32)ONE_BY_SQRT_TWO_Q30;
*p_buf_re = ixheaacd_mps_mult32_shr_30(*p_buf_re, temp_1);
*p_buf_re += (*buf_real_ch3 + *buf_real_ch4);
*p_buf_im = ixheaacd_mps_mult32_shr_30(*p_buf_im, temp_1);
*p_buf_im += (*buf_imag_ch3 + *buf_imag_ch4);
}
p_buf_re++;
p_buf_im++;
buf_real_ch4++;
buf_imag_ch4++;
buf_real_ch3++;
buf_imag_ch3++;
}
p_buf_real += MAX_HYBRID_BANDS;
p_buf_imag += MAX_HYBRID_BANDS;
}
if (pstr_mps_state->residual_coding) {
for (row = num_direct_signals; row < num_w_channels; row++) {
WORD32 resband;
res = ixheaacd_get_res_idx(pstr_mps_state, row);
resband = pstr_mps_state->res_bands[res];
if (resband == 1 && (num_parameter_bands == 20 || num_parameter_bands == 28))
pstr_mps_state->index[res] = 3;
else {
idx = &kernels_ptr[0];
for (qs = 0; qs < hybrid_bands; qs++) {
if (*idx++ >= (SIZE_T)resband) {
pstr_mps_state->index[res] = qs;
qs = hybrid_bands;
}
}
}
}
}
}
VOID ixheaacd_create_w(ia_heaac_mps_state_struct *pstr_mps_state) {
WORD32 k;
ia_mps_dec_reuse_array_struct *p_array_struct = pstr_mps_state->array_struct;
WORD32 num_direct_signals = pstr_mps_state->num_direct_signals;
WORD32 counter = num_direct_signals + pstr_mps_state->num_decor_signals;
WORD32 time_slots = pstr_mps_state->time_slots;
WORD32 offset = num_direct_signals * TSXHB;
WORD32 *p_buffer_real = p_array_struct->buf_real + offset;
WORD32 *p_buffer_imag = p_array_struct->buf_imag + offset;
WORD32 *p_buf_real = p_array_struct->buffer_real + offset;
WORD32 *p_buf_imag = p_array_struct->buffer_imag + offset;
for (k = num_direct_signals; k < counter; k++) {
ixheaacd_decorr_apply(pstr_mps_state, time_slots, p_buffer_real, p_buffer_imag, p_buf_real,
p_buf_imag, k);
p_buffer_real += TSXHB;
p_buffer_imag += TSXHB;
p_buf_real += TSXHB;
p_buf_imag += TSXHB;
}
ixheaacd_merge_res_decor(pstr_mps_state);
}
VOID ixheaacd_update_buffers(ia_heaac_mps_state_struct *pstr_mps_state) {
ia_mps_dec_reuse_array_struct *p_array_struct = pstr_mps_state->array_struct;
WORD32 *temp_addr = p_array_struct->qmf_residual_real_post;
p_array_struct->qmf_residual_real_post = p_array_struct->qmf_residual_real_pre;
p_array_struct->qmf_residual_real_pre = temp_addr;
temp_addr = p_array_struct->qmf_residual_imag_post;
p_array_struct->qmf_residual_imag_post = p_array_struct->qmf_residual_imag_pre;
p_array_struct->qmf_residual_imag_pre = temp_addr;
p_array_struct->buffer_real = p_array_struct->qmf_residual_real_post;
p_array_struct->buffer_imag = p_array_struct->qmf_residual_imag_post;
p_array_struct->m1_param = (ia_mps_dec_m1_param_struct *)p_array_struct->buffer_real;
}