/****************************************************************************** * * * 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_common_rom.h" #include "ixheaacd_basic_funcs.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_dsp_fft32x32s.h" #include "ixheaacd_function_selector.h" static VOID ixheaacd_filt_2_ch(const WORD32 *ptr_qmf, WORD32 *ptr_hybrid, ia_sbr_tables_struct *ptr_sbr_tables) { WORD32 cum0, cum1, cum00, cum11; WORD16 *p2_6 = ptr_sbr_tables->ps_tables_ptr->p2_6; cum0 = ptr_qmf[HYBRID_FILTER_DELAY] >> 1; cum00 = ptr_qmf[HYBRID_FILTER_DELAY + 16] >> 1; cum1 = 0L; cum11 = 0L; { cum1 = ixheaacd_add32_sat(cum1, ixheaacd_mult32x16in32(ptr_qmf[1], *p2_6)); cum11 = ixheaacd_add32_sat(cum11, ixheaacd_mult32x16in32(ptr_qmf[17], *p2_6++)); cum1 = ixheaacd_add32_sat(cum1, ixheaacd_mult32x16in32(ptr_qmf[3], *p2_6)); cum11 = ixheaacd_add32_sat(cum11, ixheaacd_mult32x16in32(ptr_qmf[19], *p2_6++)); cum1 = ixheaacd_add32_sat(cum1, ixheaacd_mult32x16in32(ptr_qmf[5], *p2_6)); cum11 = ixheaacd_add32_sat(cum11, ixheaacd_mult32x16in32(ptr_qmf[21], *p2_6++)); cum1 = ixheaacd_add32_sat(cum1, ixheaacd_mult32x16in32(ptr_qmf[7], *p2_6)); cum11 = ixheaacd_add32_sat(cum11, ixheaacd_mult32x16in32(ptr_qmf[23], *p2_6++)); cum1 = ixheaacd_add32_sat(cum1, ixheaacd_mult32x16in32(ptr_qmf[9], *p2_6)); cum11 = ixheaacd_add32_sat(cum11, ixheaacd_mult32x16in32(ptr_qmf[25], *p2_6++)); cum1 = ixheaacd_add32_sat(cum1, ixheaacd_mult32x16in32(ptr_qmf[11], *p2_6)); cum11 = ixheaacd_add32_sat(cum11, ixheaacd_mult32x16in32(ptr_qmf[27], *p2_6++)); } cum1 = ixheaacd_shl32(cum1, 1); cum11 = ixheaacd_shl32(cum11, 1); ptr_hybrid[0] = ixheaacd_add32_sat(cum0, cum1); ptr_hybrid[1] = ixheaacd_sub32_sat(cum0, cum1); ptr_hybrid[16] = ixheaacd_add32_sat(cum00, cum11); ptr_hybrid[17] = ixheaacd_sub32_sat(cum00, cum11); } static VOID ixheaacd_filt_8_ch(const WORD32 *ptr_qmf_real, const WORD32 *ptr_qmf_imag, WORD32 *ptr_hyb_real, WORD32 *ptr_hyb_imag, ia_sbr_tables_struct *ptr_sbr_tables) { const WORD16 tcos = 0x7642; const WORD16 tsin = 0x30fc; const WORD16 tcom = 0x5a82; WORD32 real, imag; WORD32 cum[16]; const WORD16 *p8_13 = ptr_sbr_tables->ps_tables_ptr->p8_13; const WORD16 *p8_13_8 = ptr_sbr_tables->ps_tables_ptr->p8_13 + 8; real = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_real[0], *p8_13), ixheaacd_mult32x16in32(ptr_qmf_real[8], *p8_13_8)), 1); imag = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_imag[0], *p8_13++), ixheaacd_mult32x16in32(ptr_qmf_imag[8], *p8_13_8++)), 1); cum[12] = ixheaacd_shl32( ixheaacd_mult32x16in32(ixheaacd_add32_sat(imag, real), tcom), 1); cum[13] = ixheaacd_shl32( ixheaacd_mult32x16in32(ixheaacd_sub32_sat(imag, real), tcom), 1); real = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_real[1], *p8_13), ixheaacd_mult32x16in32(ptr_qmf_real[9], *p8_13_8)), 1); imag = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_imag[1], *p8_13++), ixheaacd_mult32x16in32(ptr_qmf_imag[9], *p8_13_8++)), 1); cum[10] = ixheaacd_shl32(ixheaacd_add32_sat(ixheaacd_mult32x16in32(imag, tcos), ixheaacd_mult32x16in32(real, tsin)), 1); cum[11] = ixheaacd_shl32(ixheaacd_sub32_sat(ixheaacd_mult32x16in32(imag, tsin), ixheaacd_mult32x16in32(real, tcos)), 1); cum[9] = ixheaacd_shl32( ixheaacd_mult32x16in32( ixheaacd_sub32_sat(ptr_qmf_real[2], ptr_qmf_real[10]), *p8_13_8++), 1); cum[8] = ixheaacd_shl32( ixheaacd_mult32x16in32( ixheaacd_sub32_sat(ptr_qmf_imag[2], ptr_qmf_imag[10]), *p8_13++), 1); real = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_real[3], *p8_13), ixheaacd_mult32x16in32(ptr_qmf_real[11], *p8_13_8)), 1); imag = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_imag[3], *p8_13++), ixheaacd_mult32x16in32(ptr_qmf_imag[11], *p8_13_8++)), 1); cum[6] = ixheaacd_shl32(ixheaacd_sub32_sat(ixheaacd_mult32x16in32(imag, tcos), ixheaacd_mult32x16in32(real, tsin)), 1); cum[7] = ixheaacd_shl32(ixheaacd_negate32_sat(ixheaacd_add32_sat( ixheaacd_mult32x16in32(imag, tsin), ixheaacd_mult32x16in32(real, tcos))), 1); real = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_real[4], *p8_13), ixheaacd_mult32x16in32(ptr_qmf_real[12], *p8_13_8)), 1); imag = ixheaacd_shl32( ixheaacd_add32_sat(ixheaacd_mult32x16in32(ptr_qmf_imag[4], *p8_13++), ixheaacd_mult32x16in32(ptr_qmf_imag[12], *p8_13_8++)), 1); cum[4] = ixheaacd_shl32( ixheaacd_mult32x16in32(ixheaacd_sub32_sat(imag, real), tcom), 1); cum[5] = ixheaacd_shl32( ixheaacd_mult32x16in32( ixheaacd_negate32_sat(ixheaacd_add32_sat(imag, real)), tcom), 1); real = ixheaacd_shl32(ixheaacd_mult32x16in32(ptr_qmf_real[5], *p8_13), 1); imag = ixheaacd_shl32(ixheaacd_mult32x16in32(ptr_qmf_imag[5], *p8_13++), 1); cum[2] = ixheaacd_shl32(ixheaacd_sub32_sat(ixheaacd_mult32x16in32(real, tcos), ixheaacd_mult32x16in32(imag, tsin)), 1); cum[3] = ixheaacd_shl32(ixheaacd_add32_sat(ixheaacd_mult32x16in32(real, tsin), ixheaacd_mult32x16in32(imag, tcos)), 1); cum[0] = ixheaacd_shl32( ixheaacd_mult32x16in32(ptr_qmf_real[HYBRID_FILTER_DELAY], *p8_13), 1); cum[1] = ixheaacd_shl32( ixheaacd_mult32x16in32(ptr_qmf_imag[HYBRID_FILTER_DELAY], *p8_13++), 1); real = ixheaacd_shl32(ixheaacd_mult32x16in32(ptr_qmf_real[7], *p8_13), 1); imag = ixheaacd_shl32(ixheaacd_mult32x16in32(ptr_qmf_imag[7], *p8_13++), 1); cum[14] = ixheaacd_shl32(ixheaacd_add32_sat(ixheaacd_mult32x16in32(imag, tsin), ixheaacd_mult32x16in32(real, tcos)), 1); cum[15] = ixheaacd_shl32(ixheaacd_sub32_sat(ixheaacd_mult32x16in32(imag, tcos), ixheaacd_mult32x16in32(real, tsin)), 1); (*ixheaacd_inv_dit_fft_8pt)(cum, ptr_hyb_real, ptr_hyb_imag); } VOID ixheaacd_hybrid_analysis(const WORD32 *ptr_qmf_real, WORD32 *ptr_hyb_real, WORD32 *ptr_hyb_imag, ia_hybrid_struct *ptr_hybrid, WORD16 scale, ia_sbr_tables_struct *ptr_sbr_tables) { WORD band, j; WORD chn_offset = 0; WORD32 *ptr_re, *ptr_im; WORD32 *ptr_temp_real, *ptr_temp_imag; for (band = 0; band < NO_QMF_CHANNELS_IN_HYBRID; band++) { ptr_re = ptr_hybrid->ptr_qmf_buf_re[band]; ptr_im = ptr_hybrid->ptr_qmf_buf_im[band]; ptr_temp_real = &ptr_hybrid->ptr_work_re[0]; ptr_temp_imag = &ptr_hybrid->ptr_work_im[0]; *ptr_temp_real = *ptr_re; *ptr_temp_imag = *ptr_im; ptr_temp_real++; ptr_re++; ptr_temp_imag++; ptr_im++; for (j = ptr_hybrid->ptr_qmf_buf - 2; j >= 0; j--) { *ptr_temp_real++ = *ptr_re; *(ptr_re - 1) = *ptr_re; ptr_re++; *ptr_temp_imag++ = *ptr_im; *(ptr_im - 1) = *ptr_im; ptr_im++; } { WORD32 temp_re = ptr_qmf_real[band]; WORD32 temp_im = ptr_qmf_real[band + 0x40]; if (scale < 0) { temp_re = ixheaacd_shl32(temp_re, -scale); temp_im = ixheaacd_shl32(temp_im, -scale); } else { temp_re = ixheaacd_shr32(temp_re, scale); temp_im = ixheaacd_shr32(temp_im, scale); } *ptr_temp_real = temp_re; *--ptr_re = temp_re; *ptr_temp_imag = temp_im; *--ptr_im = temp_im; } switch (ptr_hybrid->ptr_resol[band]) { case NO_HYBRID_CHANNELS_LOW: ixheaacd_filt_2_ch(ptr_hybrid->ptr_work_re, &ptr_hyb_real[chn_offset], ptr_sbr_tables); chn_offset += 2; break; case NO_HYBRID_CHANNELS_HIGH: ixheaacd_filt_8_ch(ptr_hybrid->ptr_work_re, ptr_hybrid->ptr_work_im, &ptr_hyb_real[chn_offset], &ptr_hyb_imag[chn_offset], ptr_sbr_tables); chn_offset += 6; } } }