From 6f248478bc08aa91caafd118705253b8bdcfc05e Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Sun, 28 Jan 2024 14:54:54 +0530 Subject: [PATCH] Fixed the crash happening in L_lerp_fx function due to overflow in L_sub basop [x] Added a separate implementation for L_lerp_fx function to take variable q factor and use guard bits to right shift the array by appropriate value before passing it to L_lerp_proc_fx function. --- lib_com/cldfb.c | 2 +- lib_com/ivas_prot_fx.h | 2 +- lib_com/lerp.c | 53 ++++++++++++++++++++++++++++++++++- lib_com/prot_fx2.h | 4 ++- lib_dec/ivas_core_dec.c | 2 +- lib_dec/ivas_post_proc.c | 10 +++---- lib_dec/ivas_stereo_cng_dec.c | 14 ++++----- 7 files changed, 70 insertions(+), 17 deletions(-) diff --git a/lib_com/cldfb.c b/lib_com/cldfb.c index 9f89fd1db..e35a5cbfe 100644 --- a/lib_com/cldfb.c +++ b/lib_com/cldfb.c @@ -1504,7 +1504,7 @@ void resampleCldfb_ivas( /*low complexity-resampling only stored previous samples that are needed for next frame modulation */ lerp_flt( hs->cldfb_state, hs->cldfb_state, timeOffset, timeOffsetold ); #ifdef IVAS_FLOAT_FIXED - L_lerp_fx( hs->cldfb_state_fx, hs->cldfb_state_fx, timeOffset, timeOffsetold ); + L_lerp_fx_q11( hs->cldfb_state_fx, hs->cldfb_state_fx, timeOffset, timeOffsetold ); #endif return; diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index a21a55f5f..e8d67304e 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -612,7 +612,7 @@ void updateBuffersForDmxMdctStereo_fx( void stereo_cng_compute_PScorr_fx( Word32 output_fx0[], /* i : Output signal */ Word32 output_fx1[], /* i : Output signal */ - Word16 output_Q, + Word16 *output_Q, Word32 *c_PS_LT_fx, /* i/o: Correlation */ Word16 Q_c_PS_LT_fx, const Word16 L_frame_0, /* i : L_frame channel 0 */ diff --git a/lib_com/lerp.c b/lib_com/lerp.c index fcb42345c..0031b0796 100644 --- a/lib_com/lerp.c +++ b/lib_com/lerp.c @@ -392,7 +392,58 @@ static void L_lerp_proc_fx( const Word32 *f_fx, Word32 *f_out_fx, const Word16 b * * * * *-------------------------------------------------------------*/ -void L_lerp_fx( Word32 *f, Word32 *f_out, Word16 bufferNewSize, Word16 bufferOldSize ) + +void L_lerp_fx( Word32 *f, Word32 *f_out, Word16 bufferNewSize, Word16 bufferOldSize, Word16 *q ) +{ + Word16 tmpNewSize; + Word16 guard_bits = s_max(find_guarded_bits_fx(bufferNewSize / bufferOldSize), find_guarded_bits_fx(bufferOldSize / bufferNewSize)) + 1; + q -= guard_bits; + + FOR(Word16 ind = 0; ind < bufferNewSize; ind++) f[ind] = L_shr(f[ind], guard_bits); + FOR(Word16 ind = 0; ind < bufferNewSize; ind++) f_out[ind] = L_shr(f_out[ind], guard_bits); + + IF ( 128 * bufferNewSize > bufferOldSize * 507 ) + { + tmpNewSize = bufferOldSize * 2; + WHILE ( bufferNewSize > bufferOldSize ) + { + IF ( 128 * bufferNewSize <= 507 * bufferOldSize ) + { + tmpNewSize = bufferNewSize; + } + + L_lerp_proc_fx( f, f_out, tmpNewSize, bufferOldSize ); + + f = f_out; + bufferOldSize = tmpNewSize; + tmpNewSize *= 2; + } + } + ELSE IF ( 128 * bufferOldSize > bufferNewSize * 507 ) + { + tmpNewSize = bufferOldSize / 2; + WHILE ( bufferNewSize < bufferOldSize ) + { + IF ( 128 * bufferOldSize <= 507 * bufferNewSize ) + { + tmpNewSize = bufferNewSize; + } + + L_lerp_proc_fx( f, f_out, tmpNewSize, bufferOldSize ); + + f = f_out; + bufferOldSize = tmpNewSize; + tmpNewSize /= 2; + } + } + ELSE + { + L_lerp_proc_fx( f, f_out, bufferNewSize, bufferOldSize ); + } + + return; +} +void L_lerp_fx_q11( Word32 *f, Word32 *f_out, Word16 bufferNewSize, Word16 bufferOldSize ) { Word16 tmpNewSize; diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 1734df734..a35c6b26e 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -2100,7 +2100,9 @@ void synth_mem_updt2( //lerp.c void lerp(Word16 *f, Word16 *f_out, Word16 bufferNewSize, Word16 bufferOldSize); -void L_lerp_fx( Word32 *f, Word32 *f_out, Word16 bufferNewSize, Word16 bufferOldSize ); +void L_lerp_fx_q11( Word32 *f, Word32 *f_out, Word16 bufferNewSize, Word16 bufferOldSize ); + +void L_lerp_fx( Word32 *f, Word32 *f_out, Word16 bufferNewSize, Word16 bufferOldSize, Word16 *q ); //index_pvq_opt.c diff --git a/lib_dec/ivas_core_dec.c b/lib_dec/ivas_core_dec.c index db2525a21..79dcafd25 100644 --- a/lib_dec/ivas_core_dec.c +++ b/lib_dec/ivas_core_dec.c @@ -601,7 +601,7 @@ ivas_error ivas_core_dec( } Word32 c_PS_LT_fx = float_to_fix(hCPE->hStereoCng->c_PS_LT, Q_c_PS_LT); - stereo_cng_compute_PScorr_fx(output_fx[0], output_fx[1], Q_output, &c_PS_LT_fx, Q_c_PS_LT, sts[0]->L_frame, sts[1]->L_frame); + stereo_cng_compute_PScorr_fx(output_fx[0], output_fx[1], &Q_output, &c_PS_LT_fx, Q_c_PS_LT, sts[0]->L_frame, sts[1]->L_frame); hCPE->hStereoCng->c_PS_LT = fix_to_float( c_PS_LT_fx, Q_c_PS_LT ); #ifdef DUMPS_ENABLED diff --git a/lib_dec/ivas_post_proc.c b/lib_dec/ivas_post_proc.c index 148f1c4e6..f78373d2f 100644 --- a/lib_dec/ivas_post_proc.c +++ b/lib_dec/ivas_post_proc.c @@ -208,8 +208,8 @@ void stereo_dft_dec_core_switching_fx( IF( st->last_L_frame != st->L_frame && st->last_L_frame <= L_FRAME16k && st->L_frame <= L_FRAME16k ) { - L_lerp_fx( hCPE->input_mem_LB_fx[0], hCPE->input_mem_LB_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( st->last_L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); - L_lerp_fx( hCPE->input_mem_BPF_fx[0], hCPE->input_mem_BPF_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( st->last_L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); + L_lerp_fx_q11( hCPE->input_mem_LB_fx[0], hCPE->input_mem_LB_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( st->last_L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); + L_lerp_fx_q11( hCPE->input_mem_BPF_fx[0], hCPE->input_mem_BPF_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( st->last_L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); } IF( st->prev_bfi && !( st->last_core_bfi == ACELP_CORE && st->last_con_tcx == 1 ) ) @@ -338,7 +338,7 @@ void stereo_dft_dec_core_switching_fx( IF( ( st->last_L_frame <= L_FRAME16k && st->L_frame <= L_FRAME16k ) || ( sba_dirac_stereo_dtx_flag && st->core_brate == SID_2k40 && st->cng_type == FD_CNG ) ) { /* In case of a TCX to ACELP switch, retrieve the LB-TCX memories FOR the first STEREO_DFT32MS_OVL_NS NS of OLA */ - L_lerp_fx( hCPE->hStereoDft->buff_LBTCX_mem_fx, hCPE->input_mem_LB_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( st->last_L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); + L_lerp_fx_q11( hCPE->hStereoDft->buff_LBTCX_mem_fx, hCPE->input_mem_LB_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( st->last_L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); } IF( sba_dirac_stereo_dtx_flag && st->core_brate == SID_2k40 && st->cng_type == FD_CNG ) @@ -448,7 +448,7 @@ void stereo_dft_dec_core_switching_fx( /* this needs an indication FOR sba2stereo in general */ ELSE IF( hCPE->element_mode == IVAS_SCE && st->last_core_brate <= SID_2k40 && st->cng_type == FD_CNG ) { - L_lerp_fx( hCPE->input_mem_fx[0], hCPE->input_mem_LB_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( output_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); + L_lerp_fx_q11( hCPE->input_mem_fx[0], hCPE->input_mem_LB_fx[0], NS2SA( st->L_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ), NS2SA( output_frame * FRAMES_PER_SEC, STEREO_DFT32MS_OVL_NS ) ); } /* ACELP synthesis @ internal sampling rate */ @@ -582,7 +582,7 @@ void stereo_dft_dec_core_switching_fx( { IF( !use_cldfb_for_dft ) /* Skip this FOR DFT Stereo mono output at non-residual bitrates */ { - L_lerp_fx( output_fx, synth_fx, output_frame, hCPE->hCoreCoder[0]->L_frame ); /* Dirty resampling, but should be good enough FOR ECU analysis */ + L_lerp_fx_q11( output_fx, synth_fx, output_frame, hCPE->hCoreCoder[0]->L_frame ); /* Dirty resampling, but should be good enough FOR ECU analysis */ } IF( !use_cldfb_for_dft || ( ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) && st->cng_type == LP_CNG && st->extl == SWB_CNG && hCPE->nchan_out == 1 ) ) { diff --git a/lib_dec/ivas_stereo_cng_dec.c b/lib_dec/ivas_stereo_cng_dec.c index 20e10d4f4..b74860a9d 100644 --- a/lib_dec/ivas_stereo_cng_dec.c +++ b/lib_dec/ivas_stereo_cng_dec.c @@ -748,7 +748,7 @@ void stereo_cng_dec_update( void stereo_cng_compute_PScorr_fx( Word32 output_fx0[], /* i : Output signal Qx = 1/*temp*/ Word32 output_fx1[], /* i : Output signal Qx*/ - Word16 output_Q, + Word16 *output_Q, Word32 *c_PS_LT_fx, Word16 Q_c_PS_LT_fx, const Word16 L_frame_0, /* i : L_frame channel 0 */ @@ -765,16 +765,16 @@ void stereo_cng_compute_PScorr_fx( IF( GT_16( L_frame_0, L_frame_1 ) ) { outputPptr_fx = output_fx0; - outputPptr_Q = output_Q; - L_lerp_fx( output_fx1, outputResamp_fx, L_frame_0, L_frame_1 ); + L_lerp_fx( output_fx1, outputResamp_fx, L_frame_0, L_frame_1, output_Q ); + outputPptr_Q = *output_Q; outputSptr_fx = outputResamp_fx; outputSptr_Q = 1; } ELSE IF( GT_16( L_frame_1, L_frame_0 ) ) { outputSptr_fx = output_fx1; - outputSptr_Q = output_Q; - L_lerp_fx( output_fx0, outputResamp_fx, L_frame_1, L_frame_0 ); + L_lerp_fx( output_fx0, outputResamp_fx, L_frame_1, L_frame_0, output_Q ); + outputSptr_Q = *output_Q; outputPptr_fx = outputResamp_fx; outputPptr_Q = 1; } @@ -782,8 +782,8 @@ void stereo_cng_compute_PScorr_fx( { outputPptr_fx = output_fx0; outputSptr_fx = output_fx1; - outputPptr_Q = output_Q; - outputSptr_Q = output_Q; + outputPptr_Q = *output_Q; + outputSptr_Q = *output_Q; } Word16 guard_bits = (Word16) find_guarded_bits_fx( L_frame_0 ); -- GitLab