1134 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1134 lines
		
	
	
		
			36 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 <stdio.h>
 | |
| #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_sbr_scale.h"
 | |
| #include "ixheaacd_sbrdecsettings.h"
 | |
| #include "ixheaacd_lpp_tran.h"
 | |
| #include "ixheaacd_bitbuffer.h"
 | |
| #include "ixheaacd_defines.h"
 | |
| 
 | |
| #include "ixheaacd_pns.h"
 | |
| 
 | |
| #include "ixheaacd_aac_rom.h"
 | |
| #include "ixheaacd_pulsedata.h"
 | |
| 
 | |
| #include "ixheaacd_drc_data_struct.h"
 | |
| 
 | |
| #include "ixheaacd_lt_predict.h"
 | |
| 
 | |
| #include "ixheaacd_channelinfo.h"
 | |
| #include "ixheaacd_drc_dec.h"
 | |
| 
 | |
| #include "ixheaacd_sbrdecoder.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_intrinsics.h"
 | |
| #include "ixheaacd_basic_funcs.h"
 | |
| 
 | |
| #include "ixheaacd_qmf_dec.h"
 | |
| #include "ixheaacd_env_calc.h"
 | |
| #include "ixheaacd_sbr_const.h"
 | |
| 
 | |
| #include "ixheaacd_pvc_dec.h"
 | |
| #include "ixheaacd_sbr_dec.h"
 | |
| #include "ixheaacd_function_selector.h"
 | |
| 
 | |
| #include "ixheaacd_audioobjtypes.h"
 | |
| 
 | |
| #define LPC_SCALE_FACTOR 2
 | |
| 
 | |
| #define SHIFT 5
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mult32x16hin32(WORD32 a, WORD32 b) {
 | |
|   WORD32 result;
 | |
|   WORD64 temp_result;
 | |
| 
 | |
|   temp_result = (WORD64)(a) * (WORD64)(b >> 16);
 | |
|   result = (WORD32)(temp_result >> 16);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_mac32x16hin32(WORD32 a, WORD32 b,
 | |
|                                                      WORD32 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a + ixheaacd_mult32x16hin32(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE WORD32 ixheaacd_macn32x16hin32(WORD32 a, WORD32 b,
 | |
|                                                       WORD32 c) {
 | |
|   WORD32 result;
 | |
| 
 | |
|   result = a - ixheaacd_mult32x16hin32(b, c);
 | |
| 
 | |
|   return (result);
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_filterstep3(WORD16 a0r, WORD16 a0i, WORD16 a1r, WORD16 a1i,
 | |
|                           WORD32 start_indx, WORD32 stop_idx, WORD32 low_band,
 | |
|                           WORD32 high_band, WORD32 *qmf_buffer) {
 | |
|   WORD32 i;
 | |
|   WORD32 prev1r, prev1i;
 | |
|   WORD32 prev2r, prev2i;
 | |
|   WORD16 coef1r = (a0r);
 | |
|   WORD16 coef1i = (a0i);
 | |
|   WORD16 coef2r = (a1r);
 | |
|   WORD16 coef2i = (a1i);
 | |
|   WORD32 *p_src, *p_dst;
 | |
|   WORD32 qmf_real, qmf_imag;
 | |
| 
 | |
|   WORD32 curr, curi;
 | |
|   p_src = qmf_buffer + low_band + ((start_indx) << 7);
 | |
|   prev2r = *p_src;
 | |
|   p_src += 64;
 | |
| 
 | |
|   prev2i = *p_src;
 | |
|   p_src += 64;
 | |
| 
 | |
|   prev1r = *p_src;
 | |
|   p_src += 64;
 | |
| 
 | |
|   prev1i = *p_src;
 | |
|   p_src += 64;
 | |
| 
 | |
|   p_dst = qmf_buffer + high_band + ((start_indx + 2) << 7);
 | |
| 
 | |
|   for (i = stop_idx - start_indx; i != 0; i--) {
 | |
|     WORD32 accu;
 | |
| 
 | |
|     curr = *p_src;
 | |
|     p_src += 64;
 | |
| 
 | |
|     curi = *p_src;
 | |
|     p_src += 64;
 | |
| 
 | |
|     qmf_real = (curr >> LPC_SCALE_FACTOR);
 | |
|     qmf_imag = (curi >> LPC_SCALE_FACTOR);
 | |
| 
 | |
|     accu = ixheaacd_sub32(
 | |
|         ixheaacd_add32(ixheaacd_sub32(ixheaacd_mult32x16in32(prev1r, coef1r),
 | |
|                                       ixheaacd_mult32x16in32(prev1i, coef1i)),
 | |
|                        ixheaacd_mult32x16in32(prev2r, coef2r)),
 | |
|         ixheaacd_mult32x16in32(prev2i, coef2i));
 | |
| 
 | |
|     *p_dst = ixheaacd_add32(qmf_real, (accu << 1));
 | |
|     p_dst += 64;
 | |
| 
 | |
|     accu = ixheaacd_add32(
 | |
|         ixheaacd_add32_sat(
 | |
|             ixheaacd_add32_sat(ixheaacd_mult32x16in32(prev1r, coef1i),
 | |
|                                ixheaacd_mult32x16in32(prev1i, coef1r)),
 | |
|             ixheaacd_mult32x16in32(prev2r, coef2i)),
 | |
|         ixheaacd_mult32x16in32(prev2i, coef2r));
 | |
| 
 | |
|     *p_dst = ixheaacd_add32(qmf_imag, (accu << 1));
 | |
|     p_dst += 64;
 | |
| 
 | |
|     prev2r = prev1r;
 | |
|     prev1r = curr;
 | |
|     prev2i = prev1i;
 | |
|     prev1i = curi;
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_covariance_matrix_calc_dec(
 | |
|     WORD32 *sub_sign_xlow, ixheaacd_lpp_trans_cov_matrix *cov_matrix,
 | |
|     WORD32 count) {
 | |
|   WORD32 j, k;
 | |
|   WORD32 ixheaacd_drc_offset = 2;
 | |
|   WORD32 len = 38;
 | |
|   WORD32 factor;
 | |
|   WORD32 max_val, q_factor;
 | |
|   WORD32 temp1, temp2, temp3, temp4;
 | |
|   WORD32 *temp_buf_ptr = sub_sign_xlow;
 | |
| 
 | |
|   for (k = count; k > 0; k--) {
 | |
|     WORD32 t_phi_01 = 0, t_phi_02 = 0, t_phi_11 = 0;
 | |
|     WORD32 t_phi_12 = 0, t_phi_22 = 0;
 | |
| 
 | |
|     factor = -3;
 | |
|     j = ixheaacd_drc_offset;
 | |
|     sub_sign_xlow = temp_buf_ptr;
 | |
| 
 | |
|     temp1 = ixheaacd_shl32_dir(*sub_sign_xlow, factor);
 | |
|     sub_sign_xlow += 64;
 | |
| 
 | |
|     temp2 = ixheaacd_shl32_dir(*sub_sign_xlow, factor);
 | |
|     sub_sign_xlow += 64;
 | |
| 
 | |
|     for (; (j = j + 3) < ixheaacd_drc_offset + len;) {
 | |
|       temp3 = ixheaacd_shl32_dir(*sub_sign_xlow, factor);
 | |
|       sub_sign_xlow += 64;
 | |
| 
 | |
|       t_phi_01 += ixheaacd_mult32x16hin32(temp3, temp2);
 | |
|       t_phi_02 += ixheaacd_mult32x16hin32(temp3, temp1);
 | |
|       t_phi_11 += ixheaacd_mult32x16hin32(temp2, temp2);
 | |
| 
 | |
|       temp1 = ixheaacd_shl32_dir(*sub_sign_xlow, factor);
 | |
|       sub_sign_xlow += 64;
 | |
| 
 | |
|       t_phi_01 += ixheaacd_mult32x16hin32(temp1, temp3);
 | |
|       t_phi_02 += ixheaacd_mult32x16hin32(temp1, temp2);
 | |
|       t_phi_11 += ixheaacd_mult32x16hin32(temp3, temp3);
 | |
| 
 | |
|       temp2 = ixheaacd_shl32_dir(*sub_sign_xlow, factor);
 | |
|       sub_sign_xlow += 64;
 | |
| 
 | |
|       t_phi_01 += ixheaacd_mult32x16hin32(temp2, temp1);
 | |
|       t_phi_02 += ixheaacd_mult32x16hin32(temp2, temp3);
 | |
|       t_phi_11 += ixheaacd_mult32x16hin32(temp1, temp1);
 | |
|     }
 | |
| 
 | |
|     temp3 = ixheaacd_shl32_dir(*sub_sign_xlow, factor);
 | |
|     sub_sign_xlow += 64;
 | |
| 
 | |
|     t_phi_01 += ixheaacd_mult32x16hin32(temp3, temp2);
 | |
|     t_phi_02 += ixheaacd_mult32x16hin32(temp3, temp1);
 | |
|     t_phi_11 += ixheaacd_mult32x16hin32(temp2, temp2);
 | |
| 
 | |
|     temp1 = ixheaacd_shl32_dir(*sub_sign_xlow, factor);
 | |
|     sub_sign_xlow += 64;
 | |
| 
 | |
|     t_phi_01 += ixheaacd_mult32x16hin32(temp1, temp3);
 | |
|     t_phi_02 += ixheaacd_mult32x16hin32(temp1, temp2);
 | |
|     t_phi_11 += ixheaacd_mult32x16hin32(temp3, temp3);
 | |
| 
 | |
|     temp2 = ixheaacd_shl32_dir(*temp_buf_ptr, factor);
 | |
|     temp4 = ixheaacd_shl32_dir(*(temp_buf_ptr + 64), factor);
 | |
| 
 | |
|     t_phi_12 = (t_phi_01 - ixheaacd_mult32x16hin32(temp1, temp3) +
 | |
|                 ixheaacd_mult32x16hin32(temp4, temp2));
 | |
| 
 | |
|     t_phi_22 = (t_phi_11 - ixheaacd_mult32x16hin32(temp3, temp3) +
 | |
|                 ixheaacd_mult32x16hin32(temp2, temp2));
 | |
| 
 | |
|     max_val = ixheaacd_abs32_nrm(t_phi_01);
 | |
|     max_val = max_val | ixheaacd_abs32_nrm(t_phi_02);
 | |
|     max_val = max_val | ixheaacd_abs32_nrm(t_phi_12);
 | |
|     max_val = max_val | (t_phi_11);
 | |
|     max_val = max_val | (t_phi_22);
 | |
| 
 | |
|     q_factor = ixheaacd_pnorm32(max_val);
 | |
| 
 | |
|     cov_matrix->phi_11 = (t_phi_11 << q_factor);
 | |
|     cov_matrix->phi_22 = (t_phi_22 << q_factor);
 | |
|     cov_matrix->phi_01 = (t_phi_01 << q_factor);
 | |
|     cov_matrix->phi_02 = (t_phi_02 << q_factor);
 | |
|     cov_matrix->phi_12 = (t_phi_12 << q_factor);
 | |
| 
 | |
|     cov_matrix->d = ixheaacd_sub32_sat(
 | |
|         ixheaacd_mult32(cov_matrix->phi_22, cov_matrix->phi_11),
 | |
|         ixheaacd_mult32(cov_matrix->phi_12, cov_matrix->phi_12));
 | |
| 
 | |
|     cov_matrix++;
 | |
|     temp_buf_ptr++;
 | |
|   }
 | |
| 
 | |
|   return;
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_covariance_matrix_calc_2_dec(
 | |
|     ixheaacd_lpp_trans_cov_matrix *cov_matrix,
 | |
| 
 | |
|     WORD32 *real_buffer, WORD32 num_bands, WORD16 slots) {
 | |
|   WORD32 k;
 | |
|   WORD32 *img_buffer;
 | |
|   WORD32 *ptr_real = real_buffer;
 | |
|   ixheaacd_lpp_trans_cov_matrix *pac_arr = cov_matrix;
 | |
| 
 | |
|   for (k = 0; k < num_bands; k++) {
 | |
|     WORD32 t_phi_11 = 0, t_phi_01 = 0, t_phi_01_i = 0;
 | |
|     WORD32 prev_real, prev_imag, curr_real, curr_imag;
 | |
| 
 | |
|     real_buffer = ptr_real;
 | |
|     img_buffer = real_buffer + 64;
 | |
|     cov_matrix = pac_arr;
 | |
| 
 | |
|     prev_real = real_buffer[-128];
 | |
|     prev_imag = img_buffer[-128];
 | |
| 
 | |
|     curr_real = real_buffer[0];
 | |
|     curr_imag = img_buffer[0];
 | |
| 
 | |
|     curr_real = ixheaacd_shr32(curr_real, 3);
 | |
|     curr_imag = ixheaacd_shr32(curr_imag, 3);
 | |
|     prev_real = ixheaacd_shr32(prev_real, 3);
 | |
|     prev_imag = ixheaacd_shr32(prev_imag, 3);
 | |
| 
 | |
|     t_phi_01 = ixheaacd_mult32x16hin32(curr_real, prev_real);
 | |
|     t_phi_01 = ixheaacd_mac32x16hin32(t_phi_01, curr_imag, prev_imag);
 | |
| 
 | |
|     t_phi_01_i = ixheaacd_mult32x16hin32(curr_imag, prev_real);
 | |
|     t_phi_01_i = ixheaacd_macn32x16hin32(t_phi_01_i, curr_real, prev_imag);
 | |
| 
 | |
|     t_phi_11 = ixheaacd_mult32x16hin32(prev_real, prev_real);
 | |
|     t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, prev_imag, prev_imag);
 | |
| 
 | |
|     {
 | |
|       WORD n;
 | |
|       WORD32 *real1 = &real_buffer[128];
 | |
|       WORD32 *imag1 = &img_buffer[128];
 | |
| 
 | |
|       prev_real = curr_real;
 | |
|       prev_imag = curr_imag;
 | |
| 
 | |
|       for (n = ((slots - 2) >> 1); n; n--) {
 | |
|         curr_real = *real1;
 | |
|         real1 += 128;
 | |
|         curr_imag = *imag1;
 | |
|         imag1 += 128;
 | |
| 
 | |
|         curr_real = ixheaacd_shr32(curr_real, 3);
 | |
|         curr_imag = ixheaacd_shr32(curr_imag, 3);
 | |
| 
 | |
|         t_phi_01 = ixheaacd_mac32x16hin32(t_phi_01, curr_real, prev_real);
 | |
|         t_phi_01 = ixheaacd_mac32x16hin32(t_phi_01, curr_imag, prev_imag);
 | |
| 
 | |
|         t_phi_01_i = ixheaacd_mac32x16hin32(t_phi_01_i, curr_imag, prev_real);
 | |
|         t_phi_01_i = ixheaacd_macn32x16hin32(t_phi_01_i, curr_real, prev_imag);
 | |
| 
 | |
|         t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, prev_real, prev_real);
 | |
|         t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, prev_imag, prev_imag);
 | |
| 
 | |
|         prev_real = *real1;
 | |
|         real1 += 128;
 | |
|         prev_imag = *imag1;
 | |
|         imag1 += 128;
 | |
| 
 | |
|         prev_real = ixheaacd_shr32(prev_real, 3);
 | |
|         prev_imag = ixheaacd_shr32(prev_imag, 3);
 | |
| 
 | |
|         t_phi_01 = ixheaacd_mac32x16hin32(t_phi_01, prev_real, curr_real);
 | |
|         t_phi_01 = ixheaacd_mac32x16hin32(t_phi_01, prev_imag, curr_imag);
 | |
| 
 | |
|         t_phi_01_i = ixheaacd_mac32x16hin32(t_phi_01_i, prev_imag, curr_real);
 | |
|         t_phi_01_i = ixheaacd_macn32x16hin32(t_phi_01_i, prev_real, curr_imag);
 | |
| 
 | |
|         t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, curr_real, curr_real);
 | |
|         t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, curr_imag, curr_imag);
 | |
|       }
 | |
| 
 | |
|       if (slots & 0x01) {
 | |
|         curr_real = *real1;
 | |
|         curr_imag = *imag1;
 | |
| 
 | |
|         curr_real = ixheaacd_shr32(curr_real, 3);
 | |
|         curr_imag = ixheaacd_shr32(curr_imag, 3);
 | |
| 
 | |
|         t_phi_01 = ixheaacd_mac32x16hin32(t_phi_01, curr_real, prev_real);
 | |
|         t_phi_01 = ixheaacd_mac32x16hin32(t_phi_01, curr_imag, prev_imag);
 | |
| 
 | |
|         t_phi_01_i = ixheaacd_mac32x16hin32(t_phi_01_i, curr_imag, prev_real);
 | |
|         t_phi_01_i = ixheaacd_macn32x16hin32(t_phi_01_i, curr_real, prev_imag);
 | |
| 
 | |
|         t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, prev_real, prev_real);
 | |
|         t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, prev_imag, prev_imag);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     {
 | |
|       WORD32 t_phi_22 = t_phi_11;
 | |
|       WORD32 curr_real = real_buffer[-2 * 128];
 | |
|       WORD32 curr_imag = img_buffer[-2 * 128];
 | |
| 
 | |
|       curr_real = ixheaacd_shr32(curr_real, 3);
 | |
|       curr_imag = ixheaacd_shr32(curr_imag, 3);
 | |
| 
 | |
|       t_phi_22 = ixheaacd_mac32x16hin32(t_phi_22, curr_real, curr_real);
 | |
|       t_phi_22 = ixheaacd_mac32x16hin32(t_phi_22, curr_imag, curr_imag);
 | |
| 
 | |
|       curr_real = real_buffer[(slots - 2) * 128];
 | |
|       curr_imag = img_buffer[(slots - 2) * 128];
 | |
| 
 | |
|       curr_real = ixheaacd_shr32(curr_real, 3);
 | |
|       curr_imag = ixheaacd_shr32(curr_imag, 3);
 | |
| 
 | |
|       t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, curr_real, curr_real);
 | |
|       t_phi_11 = ixheaacd_mac32x16hin32(t_phi_11, curr_imag, curr_imag);
 | |
| 
 | |
|       cov_matrix->phi_11 = t_phi_11;
 | |
|       cov_matrix->phi_22 = t_phi_22;
 | |
|     }
 | |
| 
 | |
|     {
 | |
|       WORD32 t_phi_12 = t_phi_01;
 | |
| 
 | |
|       t_phi_12 = ixheaacd_mac32x16hin32(t_phi_12, real_buffer[-128] >> 3,
 | |
|                                         real_buffer[-2 * 128] >> 3);
 | |
|       t_phi_12 = ixheaacd_mac32x16hin32(t_phi_12, img_buffer[-128] >> 3,
 | |
|                                         img_buffer[-2 * 128] >> 3);
 | |
|       t_phi_01 =
 | |
|           ixheaacd_mac32x16hin32(t_phi_01, real_buffer[(slots - 1) * 128] >> 3,
 | |
|                                  real_buffer[(slots - 2) * 128] >> 3);
 | |
|       t_phi_01 =
 | |
|           ixheaacd_mac32x16hin32(t_phi_01, img_buffer[(slots - 1) * 128] >> 3,
 | |
|                                  img_buffer[(slots - 2) * 128] >> 3);
 | |
| 
 | |
|       cov_matrix->phi_01 = t_phi_01;
 | |
|       cov_matrix->phi_12 = t_phi_12;
 | |
|     }
 | |
| 
 | |
|     {
 | |
|       WORD32 t_phi_12_i = t_phi_01_i;
 | |
| 
 | |
|       t_phi_12_i = ixheaacd_mac32x16hin32(t_phi_12_i, img_buffer[-128] >> 3,
 | |
|                                           real_buffer[-2 * 128] >> 3);
 | |
|       t_phi_12_i = ixheaacd_macn32x16hin32(t_phi_12_i, real_buffer[-128] >> 3,
 | |
|                                            img_buffer[-2 * 128] >> 3);
 | |
|       t_phi_01_i =
 | |
|           ixheaacd_mac32x16hin32(t_phi_01_i, img_buffer[(slots - 1) * 128] >> 3,
 | |
|                                  real_buffer[(slots - 2) * 128] >> 3);
 | |
|       t_phi_01_i = ixheaacd_macn32x16hin32(t_phi_01_i,
 | |
|                                            real_buffer[(slots - 1) * 128] >> 3,
 | |
|                                            img_buffer[(slots - 2) * 128] >> 3);
 | |
| 
 | |
|       cov_matrix->phi_01_im = t_phi_01_i;
 | |
|       cov_matrix->phi_12_im = t_phi_12_i;
 | |
|     }
 | |
| 
 | |
|     {
 | |
|       WORD16 n, len_by_4, p;
 | |
|       WORD32 t_phi_02 = 0x00, t_phi_02_i = 0x00;
 | |
| 
 | |
|       len_by_4 = (slots >> 2);
 | |
|       p = 0;
 | |
|       for (n = 0; n < len_by_4; n++) {
 | |
|         WORD32 real1, real2, imag1, imag2;
 | |
|         real1 = real_buffer[p * 128];
 | |
|         real2 = real_buffer[(p - 2) * 128];
 | |
|         imag1 = img_buffer[p * 128];
 | |
|         imag2 = img_buffer[(p - 2) * 128];
 | |
| 
 | |
|         real1 = ixheaacd_shr32(real1, 3);
 | |
|         real2 = ixheaacd_shr32(real2, 3);
 | |
|         imag1 = ixheaacd_shr32(imag1, 3);
 | |
|         imag2 = ixheaacd_shr32(imag2, 3);
 | |
| 
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, real1, real2);
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, imag1, imag2);
 | |
|         t_phi_02_i = ixheaacd_mac32x16hin32(t_phi_02_i, imag1, real2);
 | |
|         t_phi_02_i = ixheaacd_macn32x16hin32(t_phi_02_i, real1, imag2);
 | |
| 
 | |
|         real1 = real_buffer[(p + 1) * 128];
 | |
|         real2 = real_buffer[(p - 1) * 128];
 | |
|         imag1 = img_buffer[(p + 1) * 128];
 | |
|         imag2 = img_buffer[(p - 1) * 128];
 | |
| 
 | |
|         real1 = ixheaacd_shr32(real1, 3);
 | |
|         real2 = ixheaacd_shr32(real2, 3);
 | |
|         imag1 = ixheaacd_shr32(imag1, 3);
 | |
|         imag2 = ixheaacd_shr32(imag2, 3);
 | |
| 
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, real1, real2);
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, imag1, imag2);
 | |
|         t_phi_02_i = ixheaacd_mac32x16hin32(t_phi_02_i, imag1, real2);
 | |
|         t_phi_02_i = ixheaacd_macn32x16hin32(t_phi_02_i, real1, imag2);
 | |
| 
 | |
|         real1 = real_buffer[(p + 2) * 128];
 | |
|         real2 = real_buffer[p * 128];
 | |
|         imag1 = img_buffer[(p + 2) * 128];
 | |
|         imag2 = img_buffer[p * 128];
 | |
| 
 | |
|         real1 = ixheaacd_shr32(real1, 3);
 | |
|         real2 = ixheaacd_shr32(real2, 3);
 | |
|         imag1 = ixheaacd_shr32(imag1, 3);
 | |
|         imag2 = ixheaacd_shr32(imag2, 3);
 | |
| 
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, real1, real2);
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, imag1, imag2);
 | |
|         t_phi_02_i = ixheaacd_mac32x16hin32(t_phi_02_i, imag1, real2);
 | |
|         t_phi_02_i = ixheaacd_macn32x16hin32(t_phi_02_i, real1, imag2);
 | |
| 
 | |
|         real1 = real_buffer[(p + 3) * 128];
 | |
|         real2 = real_buffer[(p + 1) * 128];
 | |
|         imag1 = img_buffer[(p + 3) * 128];
 | |
|         imag2 = img_buffer[(p + 1) * 128];
 | |
| 
 | |
|         real1 = ixheaacd_shr32(real1, 3);
 | |
|         real2 = ixheaacd_shr32(real2, 3);
 | |
|         imag1 = ixheaacd_shr32(imag1, 3);
 | |
|         imag2 = ixheaacd_shr32(imag2, 3);
 | |
| 
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, real1, real2);
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, imag1, imag2);
 | |
|         t_phi_02_i = ixheaacd_mac32x16hin32(t_phi_02_i, imag1, real2);
 | |
|         t_phi_02_i = ixheaacd_macn32x16hin32(t_phi_02_i, real1, imag2);
 | |
|         p += 4;
 | |
|       }
 | |
|       n = ixheaacd_shl16(len_by_4, 2);
 | |
|       for (; n < slots; n++) {
 | |
|         WORD32 real1, real2, imag1, imag2;
 | |
|         real1 = real_buffer[(n * 128)];
 | |
|         real2 = real_buffer[(n - 2) * 128];
 | |
|         imag1 = img_buffer[n * 128];
 | |
|         imag2 = img_buffer[(n - 2) * 128];
 | |
| 
 | |
|         real1 = ixheaacd_shr32(real1, 3);
 | |
|         real2 = ixheaacd_shr32(real2, 3);
 | |
|         imag1 = ixheaacd_shr32(imag1, 3);
 | |
|         imag2 = ixheaacd_shr32(imag2, 3);
 | |
| 
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, real1, real2);
 | |
|         t_phi_02 = ixheaacd_mac32x16hin32(t_phi_02, imag1, imag2);
 | |
|         t_phi_02_i = ixheaacd_mac32x16hin32(t_phi_02_i, imag1, real2);
 | |
|         t_phi_02_i = ixheaacd_macn32x16hin32(t_phi_02_i, real1, imag2);
 | |
|       }
 | |
| 
 | |
|       cov_matrix->phi_02 = t_phi_02;
 | |
|       cov_matrix->phi_02_im = t_phi_02_i;
 | |
|     }
 | |
|     ptr_real++;
 | |
|     pac_arr++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| static PLATFORM_INLINE VOID ixheaacd_filt_step3_lp(WORD len, WORD32 coef1,
 | |
|                                                    WORD32 coef2,
 | |
|                                                    WORD32 *pqmf_real_low,
 | |
|                                                    WORD32 *pqmf_real_high) {
 | |
|   WORD32 prev1;
 | |
|   WORD32 prev2;
 | |
|   WORD32 i;
 | |
| 
 | |
|   prev2 = *pqmf_real_low;
 | |
|   pqmf_real_low += 64;
 | |
| 
 | |
|   prev1 = *pqmf_real_low;
 | |
|   pqmf_real_low += 64;
 | |
| 
 | |
|   for (i = len; i >= 0; i -= 2) {
 | |
|     WORD32 curr = *pqmf_real_low;
 | |
|     WORD32 temp = ixheaacd_mult32x16hin32(prev2, coef2);
 | |
|     pqmf_real_low += 64;
 | |
| 
 | |
|     *pqmf_real_high = ixheaacd_add32_sat(
 | |
|         (curr >> LPC_SCALE_FACTOR),
 | |
|         (ixheaacd_shl32_sat(ixheaacd_mac32x16hin32(temp, prev1, coef1), 1)));
 | |
|     pqmf_real_high += 64;
 | |
| 
 | |
|     prev2 = *pqmf_real_low;
 | |
|     temp = ixheaacd_mult32x16hin32(prev1, coef2);
 | |
|     pqmf_real_low += 64;
 | |
| 
 | |
|     *pqmf_real_high = ixheaacd_add32_sat(
 | |
|         (prev2 >> LPC_SCALE_FACTOR),
 | |
|         (ixheaacd_shl32_sat(ixheaacd_mac32x16hin32(temp, curr, coef1), 1)));
 | |
|     pqmf_real_high += 64;
 | |
| 
 | |
|     prev1 = prev2;
 | |
|     prev2 = curr;
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_filter1_lp(ia_sbr_hf_generator_struct *hf_generator,
 | |
|                          ixheaacd_lpp_trans_cov_matrix *cov_matrix_seq,
 | |
|                          WORD32 *bw_array, WORD16 *degree_alias,
 | |
|                          WORD32 start_idx, WORD32 stop_idx,
 | |
|                          WORD32 max_qmf_subband, WORD32 start_patch,
 | |
|                          WORD32 stop_patch, WORD32 *sub_sig_x) {
 | |
|   WORD16 k1, k1_below = 0, k1_below2 = 0;
 | |
|   WORD32 i;
 | |
|   WORD16 alpha_real[LPC_ORDER];
 | |
|   WORD32 low_band, high_band;
 | |
|   WORD32 patch;
 | |
|   WORD16 bw = 0;
 | |
|   WORD32 a0r, a1r;
 | |
| 
 | |
|   WORD num_patches = hf_generator->pstr_settings->num_patches;
 | |
|   ia_patch_param_struct *patch_param =
 | |
|       hf_generator->pstr_settings->str_patch_param;
 | |
|   WORD32 bw_index[MAX_NUM_PATCHES];
 | |
| 
 | |
|   memset(bw_index, 0, sizeof(WORD32) * num_patches);
 | |
| 
 | |
|   for (low_band = start_patch; low_band < stop_patch; low_band++) {
 | |
|     ixheaacd_lpp_trans_cov_matrix *p_cov_matrix = &cov_matrix_seq[low_band];
 | |
| 
 | |
|     alpha_real[1] = 0;
 | |
|     alpha_real[0] = 0;
 | |
| 
 | |
|     if (p_cov_matrix->d != 0) {
 | |
|       WORD32 tmp_r, temp_real, modulus_d;
 | |
|       WORD16 inverse_d;
 | |
|       WORD32 norm_d;
 | |
| 
 | |
|       norm_d = ixheaacd_norm32(p_cov_matrix->d);
 | |
| 
 | |
|       inverse_d =
 | |
|           (WORD16)(*ixheaacd_fix_div)(0x40000000, (p_cov_matrix->d << norm_d));
 | |
|       modulus_d = ixheaacd_abs32(p_cov_matrix->d);
 | |
| 
 | |
|       tmp_r =
 | |
|           (ixheaacd_sub32_sat(
 | |
|                ixheaacd_mult32(p_cov_matrix->phi_01, p_cov_matrix->phi_12),
 | |
|                ixheaacd_mult32(p_cov_matrix->phi_02, p_cov_matrix->phi_11)) >>
 | |
|            LPC_SCALE_FACTOR);
 | |
|       temp_real = ixheaacd_abs32(tmp_r);
 | |
| 
 | |
|       if (temp_real < modulus_d) {
 | |
|         alpha_real[1] = (WORD16)(
 | |
|             (ixheaacd_mult32x16in32_shl_sat(tmp_r, inverse_d) << norm_d) >> 15);
 | |
|       }
 | |
| 
 | |
|       tmp_r =
 | |
|           (ixheaacd_sub32_sat(
 | |
|                ixheaacd_mult32(p_cov_matrix->phi_02, p_cov_matrix->phi_12),
 | |
|                ixheaacd_mult32(p_cov_matrix->phi_01, p_cov_matrix->phi_22)) >>
 | |
|            LPC_SCALE_FACTOR);
 | |
|       temp_real = ixheaacd_abs32(tmp_r);
 | |
| 
 | |
|       if (temp_real < modulus_d) {
 | |
|         alpha_real[0] = (WORD16)(
 | |
|             (ixheaacd_mult32x16in32_shl_sat(tmp_r, inverse_d) << norm_d) >> 15);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (p_cov_matrix->phi_11 == 0) {
 | |
|       k1 = 0;
 | |
|     } else {
 | |
|       if (ixheaacd_abs32_sat(p_cov_matrix->phi_01) >= p_cov_matrix->phi_11) {
 | |
|         if (p_cov_matrix->phi_01 < 0) {
 | |
|           k1 = 0x7fff;
 | |
|         } else {
 | |
|           k1 = (WORD16)-0x8000;
 | |
|         }
 | |
|       } else {
 | |
|         k1 = -((WORD16)(
 | |
|             (*ixheaacd_fix_div)(p_cov_matrix->phi_01, p_cov_matrix->phi_11)));
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (low_band > 1) {
 | |
|       WORD16 deg = ixheaacd_sub16_sat(
 | |
|           0x7fff, ixheaacd_mult16_shl_sat(k1_below, k1_below));
 | |
|       degree_alias[low_band] = 0;
 | |
| 
 | |
|       if (((low_band & 1) == 0) && (k1 < 0)) {
 | |
|         if (k1_below < 0) {
 | |
|           degree_alias[low_band] = 0x7fff;
 | |
| 
 | |
|           if (k1_below2 > 0) {
 | |
|             degree_alias[low_band - 1] = deg;
 | |
|           }
 | |
|         } else {
 | |
|           if (k1_below2 > 0) {
 | |
|             degree_alias[low_band] = deg;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (((low_band & 1) != 0) && (k1 > 0)) {
 | |
|         if (k1_below > 0) {
 | |
|           degree_alias[low_band] = 0x7fff;
 | |
| 
 | |
|           if (k1_below2 < 0) {
 | |
|             degree_alias[low_band - 1] = deg;
 | |
|           }
 | |
|         } else {
 | |
|           if (k1_below2 < 0) {
 | |
|             degree_alias[low_band] = deg;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     k1_below2 = k1_below;
 | |
|     k1_below = k1;
 | |
| 
 | |
|     patch = 0;
 | |
|     while (patch < num_patches) {
 | |
|       ia_patch_param_struct *p_loc_patch_param = &patch_param[patch];
 | |
|       WORD32 bw_vec, bw_idx;
 | |
|       WORD16 alpha1, alpha2;
 | |
| 
 | |
|       high_band = (((low_band + p_loc_patch_param->dst_end_band) << 8) >> 8);
 | |
| 
 | |
|       if ((low_band < p_loc_patch_param->src_start_band) ||
 | |
|           (low_band >= p_loc_patch_param->src_end_band) ||
 | |
|           (high_band < max_qmf_subband)) {
 | |
|         patch++;
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       bw_idx = bw_index[patch];
 | |
|       while (high_band >= hf_generator->pstr_settings->bw_borders[bw_idx]) {
 | |
|         bw_idx++;
 | |
|         bw_index[patch] = bw_idx;
 | |
|       }
 | |
| 
 | |
|       bw_vec = bw_array[bw_idx];
 | |
|       alpha1 = alpha_real[0];
 | |
|       alpha2 = alpha_real[1];
 | |
| 
 | |
|       bw = ixheaacd_extract16h(bw_vec);
 | |
|       a0r = ixheaacd_mult16x16in32_shl(bw, alpha1);
 | |
|       bw = ixheaacd_mult16_shl_sat(bw, bw);
 | |
|       a1r = ixheaacd_mult16x16in32_shl(bw, alpha2);
 | |
| 
 | |
|       {
 | |
|         WORD32 *p_sub_signal_xlow = sub_sig_x + low_band + ((start_idx) << 6);
 | |
|         WORD32 *p_sub_signal_xhigh =
 | |
|             sub_sig_x + high_band + ((start_idx + 2) << 6);
 | |
|         WORD32 len = stop_idx - start_idx - 1;
 | |
| 
 | |
|         if (bw > 0) {
 | |
|           ixheaacd_filt_step3_lp(len, a0r, a1r, p_sub_signal_xlow,
 | |
|                                  p_sub_signal_xhigh);
 | |
| 
 | |
|         } else {
 | |
|           p_sub_signal_xlow += 128;
 | |
|           for (i = len; i >= 0; i--) {
 | |
|             *p_sub_signal_xhigh = *p_sub_signal_xlow >> LPC_SCALE_FACTOR;
 | |
|             p_sub_signal_xlow += 64;
 | |
|             p_sub_signal_xhigh += 64;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       patch++;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_clr_subsamples(WORD32 *ptr_qmf_buf, WORD32 num, WORD32 size) {
 | |
|   WORD32 i;
 | |
|   for (i = num; i >= 0; i--) {
 | |
|     memset(ptr_qmf_buf, 0, sizeof(WORD32) * (size));
 | |
|     ptr_qmf_buf += 64;
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_low_pow_hf_generator(ia_sbr_hf_generator_struct *hf_generator,
 | |
|                                    WORD32 **qmf_real, WORD16 *degree_alias,
 | |
|                                    WORD32 start_idx, WORD32 stop_idx,
 | |
|                                    WORD32 num_if_bands, WORD32 max_qmf_subband,
 | |
|                                    WORD32 *sbr_invf_mode,
 | |
|                                    WORD32 *sbr_invf_mode_prev, WORD32 norm_max,
 | |
|                                    WORD32 *sub_sig_x) {
 | |
|   WORD32 bw_array[MAX_NUM_PATCHES];
 | |
|   WORD32 i;
 | |
|   WORD32 start_patch, stop_patch, low_band, high_band;
 | |
|   ia_patch_param_struct *patch_param =
 | |
|       hf_generator->pstr_settings->str_patch_param;
 | |
|   WORD32 patch;
 | |
|   ixheaacd_lpp_trans_cov_matrix cov_matrix_seq[MAX_COLS];
 | |
| 
 | |
|   WORD32 actual_stop_band;
 | |
|   WORD32 num_patches = hf_generator->pstr_settings->num_patches;
 | |
| 
 | |
|   stop_idx = (hf_generator->pstr_settings->num_columns + stop_idx);
 | |
| 
 | |
|   ixheaacd_invfilt_level_emphasis(hf_generator, num_if_bands, sbr_invf_mode,
 | |
|                                   sbr_invf_mode_prev, bw_array);
 | |
| 
 | |
|   actual_stop_band =
 | |
|       ixheaacd_add16(patch_param[num_patches - 1].dst_start_band,
 | |
|                      patch_param[num_patches - 1].num_bands_in_patch);
 | |
| 
 | |
|   {
 | |
|     WORD32 *p_qmf_real;
 | |
|     WORD32 len = 6, num;
 | |
| 
 | |
|     if (len > stop_idx) len = stop_idx;
 | |
| 
 | |
|     p_qmf_real = &qmf_real[start_idx][actual_stop_band];
 | |
|     num = (len - start_idx - 1);
 | |
|     ixheaacd_clr_subsamples(p_qmf_real, num,
 | |
|                             (NO_SYNTHESIS_CHANNELS - actual_stop_band));
 | |
| 
 | |
|     if (actual_stop_band < 32) {
 | |
|       num = (stop_idx - len - 1);
 | |
|       p_qmf_real = &qmf_real[len][actual_stop_band];
 | |
|       ixheaacd_clr_subsamples(p_qmf_real, num,
 | |
|                               (NO_ANALYSIS_CHANNELS - actual_stop_band));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   start_patch = ixheaacd_max16(
 | |
|       1, ixheaacd_sub16(hf_generator->pstr_settings->start_patch, 2));
 | |
|   stop_patch = patch_param[0].dst_start_band;
 | |
| 
 | |
|   {
 | |
|     WORD32 *ptr = &sub_sig_x[0];
 | |
|     WORD32 *plpc_filt_states_real = &hf_generator->lpc_filt_states_real[0][0];
 | |
|     for (i = LPC_ORDER; i != 0; i--) {
 | |
|       memcpy(ptr, plpc_filt_states_real, sizeof(WORD32) * (stop_patch));
 | |
|       ptr += NO_SYNTHESIS_CHANNELS;
 | |
|       plpc_filt_states_real += 32;
 | |
|     }
 | |
|   }
 | |
|   if (norm_max != 30) {
 | |
|     (*ixheaacd_covariance_matrix_calc)(sub_sig_x + start_patch,
 | |
|                                        &cov_matrix_seq[start_patch],
 | |
|                                        (stop_patch - start_patch));
 | |
| 
 | |
|   } else {
 | |
|     memset(&cov_matrix_seq[0], 0,
 | |
|            sizeof(ixheaacd_lpp_trans_cov_matrix) * stop_patch);
 | |
|   }
 | |
| 
 | |
|   ixheaacd_filter1_lp(hf_generator, cov_matrix_seq, bw_array, degree_alias,
 | |
|                       start_idx, stop_idx, max_qmf_subband, start_patch,
 | |
|                       stop_patch, sub_sig_x);
 | |
| 
 | |
|   start_patch = hf_generator->pstr_settings->start_patch;
 | |
|   stop_patch = hf_generator->pstr_settings->stop_patch;
 | |
| 
 | |
|   for (low_band = start_patch; low_band < stop_patch; low_band++) {
 | |
|     WORD32 src_start_band, src_end_band, dst_start_band, dst_end_band;
 | |
|     patch = 0;
 | |
| 
 | |
|     while (patch < num_patches) {
 | |
|       ia_patch_param_struct *ptr_loc_patch_param = &patch_param[patch];
 | |
| 
 | |
|       src_start_band = ptr_loc_patch_param->src_start_band;
 | |
|       src_end_band = ptr_loc_patch_param->src_end_band;
 | |
|       dst_start_band = ptr_loc_patch_param->dst_start_band;
 | |
|       dst_end_band = ptr_loc_patch_param->dst_end_band;
 | |
| 
 | |
|       high_band = (low_band + ptr_loc_patch_param->dst_end_band);
 | |
| 
 | |
|       if ((low_band < src_start_band) || (low_band >= src_end_band) ||
 | |
|           (high_band >= NO_SYNTHESIS_CHANNELS)) {
 | |
|         patch++;
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if ((high_band != dst_start_band)) {
 | |
|         degree_alias[high_band] = degree_alias[low_band];
 | |
|       }
 | |
| 
 | |
|       patch++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   memcpy(hf_generator->bw_array_prev, bw_array, sizeof(WORD32) * num_if_bands);
 | |
| }
 | |
| 
 | |
| VOID ixheaacd_hf_generator(ia_sbr_hf_generator_struct *hf_generator,
 | |
|                            ia_sbr_scale_fact_struct *scale_factor,
 | |
|                            WORD32 **qmf_real, WORD32 **qmf_imag, WORD32 factor,
 | |
|                            WORD32 start_idx, WORD32 stop_idx,
 | |
|                            WORD32 num_if_bands, WORD32 max_qmf_subband,
 | |
|                            WORD32 *sbr_invf_mode, WORD32 *sbr_invf_mode_prev,
 | |
|                            WORD32 *sub_sig_x, WORD audio_object_type) {
 | |
|   WORD32 bw_index[MAX_NUM_PATCHES];
 | |
|   WORD32 bw_array[MAX_NUM_PATCHES];
 | |
| 
 | |
|   WORD32 i, j;
 | |
|   WORD32 start_patch, stop_patch, low_band, high_band;
 | |
|   ia_patch_param_struct *patch_param =
 | |
|       hf_generator->pstr_settings->str_patch_param;
 | |
|   WORD32 patch;
 | |
| 
 | |
|   WORD16 alpha_real[LPC_ORDER];
 | |
|   WORD16 a0r, a1r;
 | |
|   WORD16 alpha_imag[LPC_ORDER];
 | |
|   WORD16 a0i = 0, a1i = 0;
 | |
| 
 | |
|   WORD16 bw = 0;
 | |
| 
 | |
|   ixheaacd_lpp_trans_cov_matrix cov_matrix;
 | |
|   ixheaacd_lpp_trans_cov_matrix cov_matrix_seq[MAX_COLS];
 | |
| 
 | |
|   WORD32 common_scale;
 | |
|   WORD32 actual_stop_band;
 | |
|   WORD32 num_patches = hf_generator->pstr_settings->num_patches;
 | |
| 
 | |
|   start_idx = (start_idx * factor);
 | |
| 
 | |
|   stop_idx = (hf_generator->pstr_settings->num_columns + (stop_idx * factor));
 | |
| 
 | |
|   ixheaacd_invfilt_level_emphasis(hf_generator, num_if_bands, sbr_invf_mode,
 | |
|                                   sbr_invf_mode_prev, bw_array);
 | |
| 
 | |
|   actual_stop_band =
 | |
|       ixheaacd_add16(patch_param[num_patches - 1].dst_start_band,
 | |
|                      patch_param[num_patches - 1].num_bands_in_patch);
 | |
| 
 | |
|   for (i = start_idx; i < stop_idx; i++) {
 | |
|     WORD32 *p_qmf_real = &qmf_real[i][actual_stop_band];
 | |
|     WORD32 *p_qmf_imag = &qmf_imag[i][actual_stop_band];
 | |
| 
 | |
|     for (j = NO_SYNTHESIS_CHANNELS - actual_stop_band; j != 0; j--) {
 | |
|       *p_qmf_real++ = 0;
 | |
|       *p_qmf_imag++ = 0;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   memset(bw_index, 0, sizeof(WORD32) * num_patches);
 | |
| 
 | |
|   common_scale =
 | |
|       ixheaacd_min32(scale_factor->ov_lb_scale, scale_factor->lb_scale);
 | |
| 
 | |
|   start_patch = hf_generator->pstr_settings->start_patch;
 | |
|   stop_patch = hf_generator->pstr_settings->stop_patch;
 | |
| 
 | |
|   {
 | |
|     WORD32 *ptr;
 | |
|     for (i = 0; i < LPC_ORDER; i++) {
 | |
|       ptr = sub_sig_x + (start_patch) + i * 128;
 | |
|       memcpy(ptr, &hf_generator->lpc_filt_states_real[i][start_patch],
 | |
|              sizeof(WORD32) * (stop_patch - start_patch));
 | |
|       memcpy(ptr + 64, &hf_generator->lpc_filt_states_imag[i][start_patch],
 | |
|              sizeof(WORD32) * (stop_patch - start_patch));
 | |
|     }
 | |
|   }
 | |
|   if (audio_object_type != AOT_ER_AAC_ELD &&
 | |
|       audio_object_type != AOT_ER_AAC_LD) {
 | |
|     (*ixheaacd_covariance_matrix_calc_2)(
 | |
|         &cov_matrix_seq[start_patch],
 | |
|         (sub_sig_x + start_patch + LPC_ORDER * 128), (stop_patch - start_patch),
 | |
|         38);
 | |
|   } else {
 | |
|     (*ixheaacd_covariance_matrix_calc_2)(
 | |
|         &cov_matrix_seq[start_patch],
 | |
|         (sub_sig_x + start_patch + LPC_ORDER * 128), (stop_patch - start_patch),
 | |
|         16);
 | |
|   }
 | |
| 
 | |
|   for (low_band = start_patch; low_band < stop_patch; low_band++) {
 | |
|     FLAG reset_lpc_coeff = 0;
 | |
|     WORD32 max_val;
 | |
|     WORD32 q_shift;
 | |
|     WORD32 v;
 | |
|     max_val = ixheaacd_abs32_nrm(cov_matrix_seq[low_band].phi_01);
 | |
|     max_val = max_val | ixheaacd_abs32_nrm(cov_matrix_seq[low_band].phi_02);
 | |
|     max_val = max_val | ixheaacd_abs32_nrm(cov_matrix_seq[low_band].phi_12);
 | |
| 
 | |
|     max_val = max_val | (cov_matrix_seq[low_band].phi_11);
 | |
|     max_val = max_val | (cov_matrix_seq[low_band].phi_22);
 | |
|     max_val = max_val | ixheaacd_abs32_nrm(cov_matrix_seq[low_band].phi_01_im);
 | |
|     max_val = max_val | ixheaacd_abs32_nrm(cov_matrix_seq[low_band].phi_02_im);
 | |
|     max_val = max_val | ixheaacd_abs32_nrm(cov_matrix_seq[low_band].phi_12_im);
 | |
| 
 | |
|     q_shift = ixheaacd_pnorm32(max_val);
 | |
| 
 | |
|     cov_matrix.phi_11 = (cov_matrix_seq[low_band].phi_11 << q_shift);
 | |
|     cov_matrix.phi_22 = (cov_matrix_seq[low_band].phi_22 << q_shift);
 | |
|     cov_matrix.phi_01 = (cov_matrix_seq[low_band].phi_01 << q_shift);
 | |
|     cov_matrix.phi_02 = (cov_matrix_seq[low_band].phi_02 << q_shift);
 | |
|     cov_matrix.phi_12 = (cov_matrix_seq[low_band].phi_12 << q_shift);
 | |
|     cov_matrix.phi_01_im = (cov_matrix_seq[low_band].phi_01_im << q_shift);
 | |
|     cov_matrix.phi_02_im = (cov_matrix_seq[low_band].phi_02_im << q_shift);
 | |
|     cov_matrix.phi_12_im = (cov_matrix_seq[low_band].phi_12_im << q_shift);
 | |
| 
 | |
|     max_val = ixheaacd_mult32(cov_matrix.phi_12, cov_matrix.phi_12);
 | |
|     max_val = ixheaacd_add32_sat(
 | |
|         max_val, ixheaacd_mult32(cov_matrix.phi_12_im, cov_matrix.phi_12_im));
 | |
| 
 | |
|     v = ixheaacd_sub32_sat(
 | |
|             ixheaacd_mult32(cov_matrix.phi_11, cov_matrix.phi_22), max_val)
 | |
|         << 1;
 | |
|     cov_matrix.d = v;
 | |
| 
 | |
|     alpha_real[1] = 0;
 | |
|     alpha_imag[1] = 0;
 | |
| 
 | |
|     if (cov_matrix.d != 0) {
 | |
|       WORD32 tmp_r, temp_real, modulus_d;
 | |
|       WORD32 tmp_i, temp_imag;
 | |
|       WORD16 inverse_d;
 | |
|       WORD32 norm_d;
 | |
| 
 | |
|       norm_d = ixheaacd_norm32(cov_matrix.d);
 | |
| 
 | |
|       inverse_d =
 | |
|           (WORD16)(*ixheaacd_fix_div)(0x40000000, (cov_matrix.d << norm_d));
 | |
| 
 | |
|       modulus_d = ixheaacd_abs32_sat(cov_matrix.d);
 | |
|       tmp_r =
 | |
|           (ixheaacd_sub32_sat(
 | |
|               ixheaacd_sub32_sat(
 | |
|                   ixheaacd_mult32(cov_matrix.phi_01, cov_matrix.phi_12),
 | |
|                   ixheaacd_mult32(cov_matrix.phi_01_im, cov_matrix.phi_12_im)),
 | |
|               ixheaacd_mult32(cov_matrix.phi_02, cov_matrix.phi_11))) >>
 | |
|           (LPC_SCALE_FACTOR - 1);
 | |
|       tmp_i = (ixheaacd_sub32_sat(
 | |
|                   ixheaacd_add32_sat(
 | |
|                       ixheaacd_mult32(cov_matrix.phi_01_im, cov_matrix.phi_12),
 | |
|                       ixheaacd_mult32(cov_matrix.phi_01, cov_matrix.phi_12_im)),
 | |
|                   ixheaacd_mult32(cov_matrix.phi_02_im, cov_matrix.phi_11))) >>
 | |
|               (LPC_SCALE_FACTOR - 1);
 | |
|       temp_imag = ixheaacd_abs32(tmp_i);
 | |
|       temp_real = ixheaacd_abs32(tmp_r);
 | |
| 
 | |
|       if (temp_real >= modulus_d) {
 | |
|         reset_lpc_coeff = 1;
 | |
|       } else {
 | |
|         alpha_real[1] = (WORD16)(
 | |
|             (ixheaacd_mult32x16in32(tmp_r, inverse_d) << (norm_d + 1)) >> 15);
 | |
|       }
 | |
| 
 | |
|       if (temp_imag >= modulus_d) {
 | |
|         reset_lpc_coeff = 1;
 | |
|       } else {
 | |
|         alpha_imag[1] = (WORD16)(
 | |
|             (ixheaacd_mult32x16in32(tmp_i, inverse_d) << (norm_d + 1)) >> 15);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     alpha_real[0] = 0;
 | |
|     alpha_imag[0] = 0;
 | |
| 
 | |
|     if (cov_matrix.phi_11 != 0) {
 | |
|       WORD32 tmp_r, temp_real;
 | |
|       WORD32 tmp_i = 0, temp_imag = 0;
 | |
|       WORD16 inverse_r11;
 | |
|       WORD32 norm_r11;
 | |
| 
 | |
|       norm_r11 = ixheaacd_norm32(cov_matrix.phi_11);
 | |
| 
 | |
|       inverse_r11 = (WORD16)(*ixheaacd_fix_div)(
 | |
|           0x40000000, (cov_matrix.phi_11 << norm_r11));
 | |
| 
 | |
|       tmp_r = ixheaacd_add32_sat(
 | |
|           ixheaacd_add32(
 | |
|               (cov_matrix.phi_01 >> (LPC_SCALE_FACTOR + 1)),
 | |
|               ixheaacd_mult32x16in32(cov_matrix.phi_12, alpha_real[1])),
 | |
|           ixheaacd_mult32x16in32(cov_matrix.phi_12_im, alpha_imag[1]));
 | |
|       tmp_i = ixheaacd_sub32_sat(
 | |
|           ixheaacd_add32(
 | |
|               (cov_matrix.phi_01_im >> (LPC_SCALE_FACTOR + 1)),
 | |
|               ixheaacd_mult32x16in32(cov_matrix.phi_12, alpha_imag[1])),
 | |
|           ixheaacd_mult32x16in32(cov_matrix.phi_12_im, alpha_real[1]));
 | |
| 
 | |
|       tmp_r = tmp_r << 1;
 | |
|       tmp_i = tmp_i << 1;
 | |
| 
 | |
|       temp_imag = ixheaacd_abs32(tmp_i);
 | |
|       temp_real = ixheaacd_abs32(tmp_r);
 | |
| 
 | |
|       if (temp_real >= cov_matrix.phi_11) {
 | |
|         reset_lpc_coeff = 1;
 | |
|       } else {
 | |
|         alpha_real[0] = (WORD16)(
 | |
|             (ixheaacd_mult32x16in32(ixheaacd_sub32_sat(0, tmp_r), inverse_r11)
 | |
|              << (norm_r11 + 1)) >>
 | |
|             15);
 | |
|       }
 | |
| 
 | |
|       if (temp_imag >= cov_matrix.phi_11) {
 | |
|         reset_lpc_coeff = 1;
 | |
|       } else {
 | |
|         alpha_imag[0] = (WORD16)(
 | |
|             (ixheaacd_mult32x16in32(ixheaacd_sub32_sat(0, tmp_i), inverse_r11)
 | |
|              << (norm_r11 + 1)) >>
 | |
|             15);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (ixheaacd_add32_sat((alpha_real[0] * alpha_real[0]),
 | |
|                            (alpha_imag[0] * alpha_imag[0])) >= 0x40000000L) {
 | |
|       reset_lpc_coeff = 1;
 | |
|     }
 | |
| 
 | |
|     if (ixheaacd_add32_sat((alpha_real[1] * alpha_real[1]),
 | |
|                            (alpha_imag[1] * alpha_imag[1])) >= 0x40000000L) {
 | |
|       reset_lpc_coeff = 1;
 | |
|     }
 | |
| 
 | |
|     if (reset_lpc_coeff) {
 | |
|       alpha_real[0] = 0;
 | |
|       alpha_real[1] = 0;
 | |
|       alpha_imag[0] = 0;
 | |
|       alpha_imag[1] = 0;
 | |
|     }
 | |
| 
 | |
|     patch = 0;
 | |
| 
 | |
|     while (patch < num_patches) {
 | |
|       high_band = (low_band + patch_param[patch].dst_end_band);
 | |
| 
 | |
|       if ((low_band < patch_param[patch].src_start_band) ||
 | |
|           (low_band >= patch_param[patch].src_end_band)) {
 | |
|         patch++;
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if (high_band < max_qmf_subband) {
 | |
|         patch++;
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       while ((bw_index[patch] < MAX_NUM_PATCHES - 1) &&
 | |
|              (bw_index[patch] < MAX_NUM_NOISE_VALUES) &&
 | |
|              (high_band >=
 | |
|               hf_generator->pstr_settings->bw_borders[bw_index[patch]])) {
 | |
|         bw_index[patch]++;
 | |
|       }
 | |
| 
 | |
|       bw = ixheaacd_extract16h(bw_array[bw_index[patch]]);
 | |
|       a0r = ixheaacd_mult16_shl_sat(bw, alpha_real[0]);
 | |
|       a0i = ixheaacd_mult16_shl_sat(bw, alpha_imag[0]);
 | |
|       bw = ixheaacd_mult16_shl_sat(bw, bw);
 | |
|       a1r = ixheaacd_mult16_shl_sat(bw, alpha_real[1]);
 | |
|       a1i = ixheaacd_mult16_shl_sat(bw, alpha_imag[1]);
 | |
| 
 | |
|       if (bw > 0) {
 | |
|         ixheaacd_filterstep3(a0r, a0i, a1r, a1i, start_idx, stop_idx, low_band,
 | |
|                              high_band, sub_sig_x);
 | |
| 
 | |
|       } else {
 | |
|         WORD32 *p_src = sub_sig_x + low_band + ((start_idx + 2) << 7);
 | |
|         WORD32 *p_dst = sub_sig_x + high_band + ((start_idx + 2) << 7);
 | |
| 
 | |
|         for (i = stop_idx - start_idx; i != 0; i--) {
 | |
|           *(p_dst) = *(p_src) >> LPC_SCALE_FACTOR;
 | |
|           p_src += 64;
 | |
|           p_dst += 64;
 | |
|           *(p_dst) = *(p_src) >> LPC_SCALE_FACTOR;
 | |
|           p_src += 64;
 | |
|           p_dst += 64;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       patch++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   memcpy(hf_generator->bw_array_prev, bw_array, sizeof(WORD32) * num_if_bands);
 | |
| 
 | |
|   scale_factor->hb_scale = (WORD16)(common_scale - LPC_SCALE_FACTOR);
 | |
| }
 |