From 6f4544030b156793a3643c065708ace9cf8aae14 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 31 Jan 2024 10:37:27 +0530 Subject: [PATCH 1/2] Few functions in ivas_mct_dec_mct converted to fixed point. Added changes for the following functions: [x] indexToChannelPair() [x] ivas_mct_dec_mct() [x] applyGlobalILD() [x] apply_MCT_dec() [x] stereo_decoder_tcx() --- Workspace_msvc/lib_dec.vcxproj | 1 + Workspace_msvc/lib_dec.vcxproj.filters | 2 + lib_com/ivas_prot.h | 2 + lib_com/ivas_prot_fx.h | 49 +++ lib_dec/ivas_corecoder_dec_reconfig.c | 3 + lib_dec/ivas_cpe_dec.c | 3 + lib_dec/ivas_mct_core_dec.c | 73 ++++ lib_dec/ivas_mct_dec.c | 3 + lib_dec/ivas_mct_dec_mct.c | 3 + lib_dec/ivas_mct_dec_mct_fx.c | 469 +++++++++++++++++++++++++ lib_dec/ivas_stat_dec.h | 6 + lib_dec/ivas_stereo_mdct_stereo_dec.c | 418 +++++++++++++++++++--- lib_dec/ivas_stereo_switching_dec.c | 4 + 13 files changed, 996 insertions(+), 40 deletions(-) create mode 100644 lib_dec/ivas_mct_dec_mct_fx.c diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index 1c79d4b21..bdb0d64d8 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -302,6 +302,7 @@ + diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters index eb880863d..5c6f6a8d6 100644 --- a/Workspace_msvc/lib_dec.vcxproj.filters +++ b/Workspace_msvc/lib_dec.vcxproj.filters @@ -817,6 +817,8 @@ decoder_all_c + + decoder_ivas_c decoder_ivas_c diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 7db57ae2a..33074e3a3 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -2628,6 +2628,7 @@ int16_t write_stereo_to_bitstream BSTR_ENC_HANDLE hBstr /* i/o: bitstream handle */ ); +#ifndef IVAS_FLOAT_FIXED void parse_stereo_from_bitstream( STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo decoder structure */ Decoder_State **sts, /* i/o: decoder state structure */ @@ -2636,6 +2637,7 @@ void parse_stereo_from_bitstream( Decoder_State *st0, /* i/o: decoder state structure for Bstr */ int16_t ms_mask[NB_DIV][MAX_SFB] /* o : bandwise MS mask */ ); +#endif void FindSplitRatio( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 480d3dd14..46bf52166 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -721,4 +721,53 @@ ivas_error ivas_ls_custom_output_init_fx( ivas_error ivas_ls_custom_open_fx( LSSETUP_CUSTOM_HANDLE *hLsSetupCustom /* o : Custom loudspeaker setup handle */ ); + +// ivas_mct_dec_mct_fx.c +void ivas_mct_dec_mct_fx( + MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ + Decoder_State **sts, /* i/o: decoder state structure */ + const Word16 nchan /* i : number of channels */ +); + +void apply_MCT_dec_fx( + MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ + Decoder_State **sts, /* i/o: decoder state structure */ + Word32 *x[MCT_MAX_CHANNELS][NB_DIV], /* i/o: decoded and dequan. spect. input to MCT */ + Word16 q_x[MCT_MAX_CHANNELS] ); + +void mctStereoIGF_dec_fx( + MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ + Decoder_State **stm, /* i/o: decoder state structure */ + Word32 *x[MCT_MAX_CHANNELS][NB_DIV], /* i/o: decoded and dequantized spectrum*/ + const Word16 bfi /* i : bad frame flag */ +); + +// ivas_stereo_mdct_stereo_dec.c +void parse_stereo_from_bitstream( + STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo decoder structure */ + Decoder_State **sts, /* i/o: decoder state structure */ + const Word16 mct_on, /* i : flag mct block (1) or stereo (0)*/ + const Word16 isSBAStereoMode, /* i : flag core coding for SBA */ + Decoder_State *st0, /* i/o: decoder state structure for Bstr*/ + Word16 ms_mask[NB_DIV][MAX_SFB] /* o : bandwise MS mask */ +); + +void stereo_decoder_tcx_fx( + STEREO_MDCT_DEC_DATA *hStereoMdct, /* i/o: MDCT stereo decoder structure */ + Word16 ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ + Word32 *spec_r_0[NB_DIV], /* i/o: spectrum right channel */ + Word32 *spec_l[], /* i/o: spectrum left channel [NB_DIV][N] */ + Word32 *spec_r[], /* i/o: spectrum right channel [NB_DIV][N] */ + const Word16 mdct_stereo_mode[], /* i : stereo mode (FB/band wise MS, dual mono */ + const Word16 core_l, /* i : core for left channel (TCX20/TCX10) */ + const Word16 core_r, /* i : core for right channel (TCX20/TCX10) */ + const Word16 igf, /* i : flag for IGF activity */ + const Word16 L_frameTCX_l, /* i : TCX frame length of left channel */ + const Word16 L_frameTCX_r, /* i : TCX frame length of right channel */ + const Word16 mct_on, /* i : flag mct block (1) or stereo (0) */ + const Word16 last_core_l, /* i : last core for left channel */ + const Word16 last_core_r, /* i : last core for right channel */ + const Word16 tmp_plc_upmix, /* i : indicates temp upmix for PLC decision */ + Word16 *q_x_ch2, + Word16 *q_x_ch1 ); #endif diff --git a/lib_dec/ivas_corecoder_dec_reconfig.c b/lib_dec/ivas_corecoder_dec_reconfig.c index 37cb165c4..b8bd80bad 100644 --- a/lib_dec/ivas_corecoder_dec_reconfig.c +++ b/lib_dec/ivas_corecoder_dec_reconfig.c @@ -287,6 +287,9 @@ ivas_error ivas_corecoder_dec_reconfig( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->use_itd = 0; st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->reverse_dmx = 0; st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->smooth_ratio = 1.f; +#ifdef IVAS_FLOAT_FIXED + st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->smooth_ratio_fx = ONE_IN_Q26; +#endif set_s( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->prev_ms_mask[0], 0, MAX_SFB ); set_s( st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->prev_ms_mask[1], 0, MAX_SFB ); st_ivas->hCPE[st_ivas->nCPE - 1]->hStereoMdct->lastCoh = 1.f; diff --git a/lib_dec/ivas_cpe_dec.c b/lib_dec/ivas_cpe_dec.c index 5218f7f03..ed0c01e3f 100644 --- a/lib_dec/ivas_cpe_dec.c +++ b/lib_dec/ivas_cpe_dec.c @@ -882,6 +882,9 @@ ivas_error create_cpe_dec( hCPE->hStereoMdct->reverse_dmx = 0; hCPE->hStereoMdct->smooth_ratio = 1.f; +#ifdef IVAS_FLOAT_FIXED + hCPE->hStereoMdct->smooth_ratio_fx = ONE_IN_Q26; +#endif set_s( hCPE->hStereoMdct->prev_ms_mask[0], 0, MAX_SFB ); set_s( hCPE->hStereoMdct->prev_ms_mask[1], 0, MAX_SFB ); hCPE->hStereoMdct->lastCoh = 1.f; diff --git a/lib_dec/ivas_mct_core_dec.c b/lib_dec/ivas_mct_core_dec.c index 7364813ff..80005135e 100644 --- a/lib_dec/ivas_mct_core_dec.c +++ b/lib_dec/ivas_mct_core_dec.c @@ -42,6 +42,9 @@ #include "ivas_prot.h" #include "ivas_stat_dec.h" #include "ivas_stat_com.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif /*-----------------------------------------------------------------* @@ -104,7 +107,11 @@ void ivas_mct_side_bits( { availableBits = 0; +#ifdef IVAS_FLOAT_FIXED + ivas_mct_dec_mct_fx( hMCT, sts, nChannels ); +#else ivas_mct_dec_mct( hMCT, sts, nChannels ); +#endif /*read channel bitrate ratios from bitstream*/ for ( ch = 0; ch < nChannels; ch++ ) @@ -251,7 +258,39 @@ void ivas_mct_core_dec( } else { +#ifdef IVAS_FLOAT_FIXED + Word32 *x_fx[MCT_MAX_CHANNELS][NB_DIV]; + Word16 q_x[MCT_MAX_CHANNELS]; + + FOR( ch = 0; ch < nChannels; ch++ ) + { + x_fx[ch][0] = malloc( ( L_FRAME48k ) * sizeof( Word32 ) ); + x_fx[ch][1] = x_fx[ch][0] + L_FRAME48k / 2; + + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x_fx[ch][0][j] = (Word32) ( x[ch][0][j] * ONE_IN_Q16 ); + x_fx[ch][1][j] = (Word32) ( x[ch][1][j] * ONE_IN_Q16 ); + } + q_x[ch] = Q16; + } + mctStereoIGF_dec_fx( hMCT, sts, x_fx, bfi ); + FOR( ch = 0; ch < nChannels; ch++ ) + { + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x[ch][0][j] = (float) x_fx[ch][0][j] / ( 1 << q_x[ch] ); + x[ch][1][j] = (float) x_fx[ch][1][j] / ( 1 << q_x[ch] ); + } + } + + FOR( ch = 0; ch < nChannels; ch++ ) + { + free( x_fx[ch][0] ); + } +#else mctStereoIGF_dec( hMCT, sts, x, bfi ); +#endif } } @@ -261,7 +300,41 @@ void ivas_mct_core_dec( * MCT processing *--------------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + Word32 *x_fx[MCT_MAX_CHANNELS][NB_DIV]; + Word16 q_x[MCT_MAX_CHANNELS]; + + FOR( ch = 0; ch < nChannels; ch++ ) + { + x_fx[ch][0] = malloc( ( L_FRAME48k ) * sizeof( Word32 ) ); + x_fx[ch][1] = x_fx[ch][0] + L_FRAME48k / 2; + + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x_fx[ch][0][j] = (Word32) ( x[ch][0][j] * ONE_IN_Q16 ); + x_fx[ch][1][j] = (Word32) ( x[ch][1][j] * ONE_IN_Q16 ); + } + q_x[ch] = Q16; + } + + apply_MCT_dec_fx( hMCT, sts, x_fx, q_x ); + + FOR( ch = 0; ch < nChannels; ch++ ) + { + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x[ch][0][j] = (float) x_fx[ch][0][j] / ( 1 << q_x[ch] ); + x[ch][1][j] = (float) x_fx[ch][1][j] / ( 1 << q_x[ch] ); + } + } + + FOR( ch = 0; ch < nChannels; ch++ ) + { + free( x_fx[ch][0] ); + } +#else apply_MCT_dec( hMCT, sts, x ); +#endif } pop_wmops(); diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index dae6a663c..eb35eff97 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -517,6 +517,9 @@ ivas_error create_mct_dec( hMCT->hBlockData[n]->hStereoMdct->use_itd = 0; hMCT->hBlockData[n]->hStereoMdct->reverse_dmx = 0; hMCT->hBlockData[n]->hStereoMdct->smooth_ratio = 1.f; +#ifdef IVAS_FLOAT_FIXED + hMCT->hBlockData[n]->hStereoMdct->smooth_ratio_fx = ONE_IN_Q26; +#endif } for ( ; n < MCT_MAX_BLOCKS; n++ ) { diff --git a/lib_dec/ivas_mct_dec_mct.c b/lib_dec/ivas_mct_dec_mct.c index 881c35119..abf147525 100644 --- a/lib_dec/ivas_mct_dec_mct.c +++ b/lib_dec/ivas_mct_dec_mct.c @@ -38,6 +38,9 @@ #include "wmc_auto.h" #include #include "stat_enc.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif /*----------------------------------------------------------* diff --git a/lib_dec/ivas_mct_dec_mct_fx.c b/lib_dec/ivas_mct_dec_mct_fx.c new file mode 100644 index 000000000..cf48b5abf --- /dev/null +++ b/lib_dec/ivas_mct_dec_mct_fx.c @@ -0,0 +1,469 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "ivas_cnst.h" +#include "ivas_prot.h" +#include "prot.h" +#include "wmc_auto.h" +#include +#include "stat_enc.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" +#include "ivas_prot_fx.h" + +/*----------------------------------------------------------* + * indexToChannelPair() + * + * get the index of each channel pair + *----------------------------------------------------------*/ + +static void indexToChannelPair_fx( + MCT_DEC_BLOCK_DATA_HANDLE hBlock, + const Word16 nChannels, + const Word16 pairIdx ) +{ + Word16 ch1, ch2; + Word16 tmpIdx = 0; + + FOR( ch2 = 1; ch2 < nChannels; ch2++ ) + { + FOR( ch1 = 0; ch1 < ch2; ch1++ ) + { + IF( EQ_16( tmpIdx, pairIdx ) ) + { + hBlock->ch1 = ch1; + move16(); + hBlock->ch2 = ch2; + move16(); + + return; + } + ELSE + { + tmpIdx++; + } + } + } + + return; +} + + +/*-------------------------------------------------------------------* + * ivas_mct_dec_mct() + * + * decode core and mct information + *-------------------------------------------------------------------*/ + +void ivas_mct_dec_mct_fx( + MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ + Decoder_State **sts, /* i/o: decoder state structure */ + const Word16 nchan /* i : number of channels */ +) +{ + Word16 pair, ch, channelPairIndex; + MCT_DEC_BLOCK_DATA_HANDLE hBlock; + Decoder_State *p_st[CPE_CHANNELS]; + Word16 nchan_active = 0; + + hMCT->currBlockDataCnt = get_next_indice_fx( sts[0], MCT_NUM_BLOCK_DATA_BITS ); + move16(); + + /*first get core and overlap info for all channels*/ + FOR( ch = 0; ch < nchan; ch++ ) + { + test(); + IF( hMCT->currBlockDataCnt && NE_16( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + hMCT->mc_global_ild[ch] = get_next_indice_fx( sts[0], SMDCT_GLOBAL_ILD_BITS ); + move16(); + } + ELSE + { + hMCT->mc_global_ild[ch] = 0; + move16(); + } + } + + IF( hMCT->currBlockDataCnt ) + { + FOR( ch = 0; ch < nchan; ch++ ) + { + IF( + NE_16( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + hMCT->lowE_ch[ch] = get_next_indice_fx( sts[0], 1 ); + move16(); + } + } + } + + FOR( ch = 0; ch < nchan; ch++ ) + { + IF( NE_16( sts[ch]->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + nchan_active++; + } + } + + FOR( pair = hMCT->currBlockDataCnt - 1; pair >= 0; pair-- ) + { + assert( GE_16( nchan_active, 2 ) ); + hBlock = hMCT->hBlockData[pair]; + + /*get channel pair index from BS*/ + channelPairIndex = get_next_indice_fx( sts[0], hMCT->bitsChannelPairIndex ); + indexToChannelPair_fx( hBlock, nchan, channelPairIndex ); + + /*point to decoder states of actual channels to read block pair bits*/ + p_st[0] = sts[hBlock->ch1]; + p_st[1] = sts[hBlock->ch2]; + + parse_stereo_from_bitstream( hBlock->hStereoMdct, p_st, 1, 0, sts[0], hBlock->mask ); + } + + return; +} + + +/*----------------------------------------------------------* + * applyGlobalILD() + * + * revert to initial channel energy levels using the ratios + * sent from the encoder + *----------------------------------------------------------*/ + +static void applyGlobalILD_fx( + Decoder_State **sts, + MCT_DEC_HANDLE hMCT, + Word32 *x[MCT_MAX_CHANNELS][NB_DIV], + Word16 q_x[MCT_MAX_CHANNELS] ) +{ + Word16 ch, k; + Word16 nSubframes, L_subframeTCX; + Word32 qratio; + Word16 q_qratio; + Word16 tmp, tmp_e; + + FOR( ch = 0; ch < ( hMCT->nchan_out_woLFE ); + ch++ ) + { + nSubframes = ( EQ_16( sts[ch]->core, TCX_20_CORE ) ) ? 1 : NB_DIV; + move16(); + tmp = BASOP_Util_Divide1616_Scale( sts[ch]->hTcxDec->L_frameTCX, nSubframes, &tmp_e ); + L_subframeTCX = shr( tmp, add( 15, negate( tmp_e ) ) ); + + IF( hMCT->mc_global_ild[ch] ) + { + IF( hMCT->lowE_ch[ch] ) + { + tmp = BASOP_Util_Divide3216_Scale( (Word32) hMCT->mc_global_ild[ch] << Q26, SMDCT_ILD_RANGE, &tmp_e ); // Q26 + qratio = L_shr( (Word32) tmp, negate( add( 1, tmp_e ) ) ); + } + ELSE + { + tmp = BASOP_Util_Divide3216_Scale( ( SMDCT_ILD_RANGE << Q26 ), hMCT->mc_global_ild[ch], &tmp_e ); + qratio = L_shr( (Word32) tmp, negate( add( 1, tmp_e ) ) ); // Q26 + } + + q_qratio = norm_l( qratio ); + qratio = L_shl( qratio, q_qratio ); + FOR( k = 0; k < nSubframes; k++ ) + { + v_multc_fixed( x[ch][k], qratio, x[ch][k], L_subframeTCX ); + } + q_x[ch] = q_x[ch] - 5 + q_qratio; + move16(); + } + ELSE + { + CONTINUE; + } + } + + return; +} + + +/*----------------------------------------------------------* + * apply_MCT_dec() + * + * main MCT decoding function + *----------------------------------------------------------*/ + +void apply_MCT_dec_fx( + MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ + Decoder_State **sts, /* i/o: decoder state structure */ + Word32 *x[MCT_MAX_CHANNELS][NB_DIV], /* i/o: decoded and dequan. spect. input to MCT */ + Word16 q_x[MCT_MAX_CHANNELS] ) +{ + Word16 pair; + MCT_DEC_BLOCK_DATA_HANDLE hBlock; + + FOR( pair = hMCT->currBlockDataCnt - 1; pair >= 0; pair-- ) + { + hBlock = hMCT->hBlockData[pair]; + + stereo_decoder_tcx_fx( hBlock->hStereoMdct, hBlock->mask, &x[hBlock->ch2][0], &x[hBlock->ch1][0], &x[hBlock->ch2][0], hBlock->hStereoMdct->mdct_stereo_mode, sts[hBlock->ch1]->core, sts[hBlock->ch2]->core, sts[0]->igf, sts[0]->hTcxDec->L_frameTCX, sts[1]->hTcxDec->L_frameTCX, 1, TCX_20_CORE, TCX_20_CORE, 0, &q_x[hBlock->ch2], &q_x[hBlock->ch1] ); + } + + applyGlobalILD_fx( sts, hMCT, x, q_x ); + + return; +} + +/*----------------------------------------------------------* + * mctStereoIGF_dec() + * + * apply IGF to MCT stereo block pairs + *----------------------------------------------------------*/ + +void mctStereoIGF_dec_fx( + MCT_DEC_HANDLE hMCT, /* i/o: MCT decoder structure */ + Decoder_State **stm, /* i/o: decoder state structure */ + Word32 *x[MCT_MAX_CHANNELS][NB_DIV], /* i/o: decoded and dequantized spectrum*/ + const Word16 bfi /* i : bad frame flag */ +) +{ + Word16 b, core, nSubframes, k, ch, p_ch[CPE_CHANNELS], ch1, ch2; + Decoder_State *sts[CPE_CHANNELS], *st = NULL; + Word16 tcx_offset[CPE_CHANNELS]; + Word16 tcx_offsetFB[CPE_CHANNELS]; + Word16 left_rect[CPE_CHANNELS]; + Word16 L_spec[CPE_CHANNELS]; + Word16 L_frame[CPE_CHANNELS]; + Word16 L_frameTCX[CPE_CHANNELS]; + Word32 *p_x[CPE_CHANNELS][NB_DIV]; + Word16 singleChEle[MCT_MAX_CHANNELS]; + Word16 tmp_e; + Word16 L_frame_nSubframe, L_frameTCX_nSubframe, tmp; + + set16_fx( singleChEle, 1, ( hMCT->nchan_out_woLFE ) ); + + FOR( b = 0; b < hMCT->currBlockDataCnt; b++ ) + { + ch1 = hMCT->hBlockData[b]->ch1; + move16(); + ch2 = hMCT->hBlockData[b]->ch2; + move16(); + + sts[0] = stm[ch1]; + sts[1] = stm[ch2]; + core = sts[0]->core; + move16(); + nSubframes = core; + move16(); + p_ch[0] = ch1; + move16(); + p_ch[1] = ch2; + move16(); + singleChEle[hMCT->hBlockData[b]->ch1] = 0; + move16(); + singleChEle[hMCT->hBlockData[b]->ch2] = 0; + move16(); + +#ifndef IVAS_FLOAT_FIX_TBD + Float32 *p_x_flt[CPE_CHANNELS][NB_DIV]; + + FOR( k = 0; k < CPE_CHANNELS; k++ ) + { + p_x_flt[k][0] = malloc( L_FRAME48k * sizeof( Float32 ) ); + p_x_flt[k][1] = p_x_flt[k][0] + L_FRAME48k / 2; + } + FOR( k = 0; k < CPE_CHANNELS; k++ ) + { + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + p_x_flt[0][k][j] = (Float32) x[ch1][k][j] / ONE_IN_Q16; + p_x_flt[1][k][j] = (Float32) x[ch2][k][j] / ONE_IN_Q16; + } + } +#endif + + FOR( k = 0; k < nSubframes; k++ ) + { + p_x[0][k] = x[ch1][k]; + p_x[1][k] = x[ch2][k]; + + test(); + IF( NE_16( hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[k], SMDCT_DUAL_MONO ) || NE_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[k], SMDCT_DUAL_MONO ) ) + { + tmp = BASOP_Util_Divide1616_Scale( sts[0]->hTcxCfg->tcx_coded_lines, nSubframes, &tmp_e ); + L_spec[0] = shr( tmp, add( 15, negate( tmp_e ) ) ); + + tmp = BASOP_Util_Divide1616_Scale( sts[0]->L_frame, nSubframes, &tmp_e ); + L_frame_nSubframe = shr( tmp, add( 15, negate( tmp_e ) ) ); + + tmp = BASOP_Util_Divide1616_Scale( sts[0]->hTcxDec->L_frameTCX, nSubframes, &tmp_e ); + L_frameTCX_nSubframe = shr( tmp, add( 15, negate( tmp_e ) ) ); + + init_tcx_info_fx( sts[0], L_frame_nSubframe, L_frameTCX_nSubframe, k, bfi, &tcx_offset[0], &tcx_offsetFB[0], &L_frame[0], &L_frameTCX[0], &left_rect[0], &L_spec[0] ); + + /* stereo IGF decoding */ + assert( ( EQ_16( sts[0]->core, sts[1]->core ) ) || ( EQ_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[0], SMDCT_DUAL_MONO ) ) ); + +#ifdef IVAS_FLOAT_FIX_TBD + decoder_tcx_IGF_stereo( sts, hMCT->hBlockData[b]->hStereoMdct, hMCT->hBlockData[b]->mask, p_x, L_frame[0], left_rect[0], k, bfi, 1 /* MCT_flag */ ); +#else + decoder_tcx_IGF_stereo( sts, hMCT->hBlockData[b]->hStereoMdct, hMCT->hBlockData[b]->mask, p_x_flt, L_frame[0], left_rect[0], k, bfi, 1 /* MCT_flag */ ); +#endif + } + ELSE + { + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + test(); + IF( bfi && EQ_16( st->core, ACELP_CORE ) ) /*no igf processing needed*/ + { + CONTINUE; + } + tmp = BASOP_Util_Divide1616_Scale( st->hTcxCfg->tcx_coded_lines, nSubframes, &tmp_e ); + L_spec[ch] = shr( tmp, add( 15, negate( tmp_e ) ) ); + + tmp = BASOP_Util_Divide1616_Scale( st->L_frame, nSubframes, &tmp_e ); + L_frame_nSubframe = shr( tmp, add( 15, negate( tmp_e ) ) ); + + tmp = BASOP_Util_Divide1616_Scale( st->hTcxDec->L_frameTCX, nSubframes, &tmp_e ); + L_frameTCX_nSubframe = shr( tmp, add( 15, negate( tmp_e ) ) ); + + init_tcx_info_fx( st, L_frame_nSubframe, L_frameTCX_nSubframe, k, bfi, &tcx_offset[ch], &tcx_offsetFB[ch], &L_frame[ch], &L_frameTCX[ch], &left_rect[ch], &L_spec[ch] ); + + /* mono or dual mono IGF decoding */ +#ifdef IVAS_FLOAT_FIX_TBD + decoder_tcx_IGF_mono( st, x[p_ch[ch]][k], L_frame[ch], left_rect[ch], bfi, k ); +#else + Float32 *x_flt = malloc( ( L_FRAME48k / 2 ) * sizeof( Float32 ) ); + + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x_flt[j] = (Float32) x[p_ch[ch]][k][j] / ONE_IN_Q16; + } + decoder_tcx_IGF_mono( st, x_flt, L_frame[ch], left_rect[ch], bfi, k ); + + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x[p_ch[ch]][k][j] = (Word32) ( x_flt[j] * ONE_IN_Q16 ); + } + + free( x_flt ); +#endif + } + } + } +#ifndef IVAS_FLOAT_FIX_TBD + FOR( k = 0; k < CPE_CHANNELS; k++ ) + { + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x[ch1][k][j] = (Word32) ( p_x_flt[0][k][j] * ONE_IN_Q16 ); + x[ch2][k][j] = (Word32) ( p_x_flt[1][k][j] * ONE_IN_Q16 ); + } + } + + FOR( k = 0; k < CPE_CHANNELS; k++ ) + { + free( p_x_flt[k][0] ); + } +#endif + } + + IF( NE_16( sum16_fx( singleChEle, ( hMCT->nchan_out_woLFE ) ), 0 ) ) + { + FOR( ch = 0; ch < ( hMCT->nchan_out_woLFE ); ch++ ) + { + IF( singleChEle[ch] ) + { + st = stm[ch]; + test(); + IF( bfi && EQ_16( st->core, ACELP_CORE ) ) /*no igf processing needed*/ + { + CONTINUE; + } + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + CONTINUE; + } + nSubframes = ( EQ_16( st->core, TCX_10_CORE ) ) ? NB_DIV : 1; + move16(); + +#ifndef IVAS_FLOAT_FIX_TBD + Float32 *x_flt[NB_DIV]; + x_flt[0] = malloc( ( L_FRAME48k ) * sizeof( Float32 ) ); + x_flt[1] = x_flt[0] + L_FRAME48k / 2; + + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x_flt[0][j] = (Float32) x[ch][0][j] / ONE_IN_Q16; + x_flt[1][j] = (Float32) x[ch][1][j] / ONE_IN_Q16; + } + +#endif + FOR( k = 0; k < nSubframes; k++ ) + { + tmp = BASOP_Util_Divide1616_Scale( st->hTcxCfg->tcx_coded_lines, nSubframes, &tmp_e ); + L_spec[0] = shr( tmp, add( 15, negate( tmp_e ) ) ); + + tmp = BASOP_Util_Divide1616_Scale( st->L_frame, nSubframes, &tmp_e ); + L_frame_nSubframe = shr( tmp, add( 15, negate( tmp_e ) ) ); + + tmp = BASOP_Util_Divide1616_Scale( st->hTcxDec->L_frameTCX, nSubframes, &tmp_e ); + L_frameTCX_nSubframe = shr( tmp, add( 15, negate( tmp_e ) ) ); + + init_tcx_info_fx( st, L_frame_nSubframe, L_frameTCX_nSubframe, k, bfi, &tcx_offset[0], &tcx_offsetFB[0], &L_frame[0], &L_frameTCX[0], &left_rect[0], &L_spec[0] ); + + /* mono or dual mono IGF decoding */ +#ifdef IVAS_FLOAT_FIX_TBD + decoder_tcx_IGF_mono( st, x[ch][k], L_frame[0], left_rect[0], bfi, k ); +#else + decoder_tcx_IGF_mono( st, x_flt[k], L_frame[0], left_rect[0], bfi, k ); +#endif + } +#ifndef IVAS_FLOAT_FIX_TBD + FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) + { + x[ch][0][j] = (Word32) ( x_flt[0][j] * ONE_IN_Q16 ); + x[ch][1][j] = (Word32) ( x_flt[1][j] * ONE_IN_Q16 ); + } + + free( x_flt[0] ); +#endif + } + } + } + + return; +} +#endif diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 692603a1a..2eb543cbf 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -343,9 +343,15 @@ typedef struct stereo_mdct_dec_data_structure int16_t use_itd; int16_t itd_mode; /*0/1*/ float itd; +#ifdef IVAS_FLOAT_FIXED + Word32 itd_fx; +#endif int16_t reverse_dmx; float smooth_ratio; +#ifdef IVAS_FLOAT_FIXED + Word32 smooth_ratio_fx; +#endif int16_t prev_ms_mask[NB_DIV][MAX_SFB]; float lastCoh; diff --git a/lib_dec/ivas_stereo_mdct_stereo_dec.c b/lib_dec/ivas_stereo_mdct_stereo_dec.c index 712ca1e87..207cf5a29 100644 --- a/lib_dec/ivas_stereo_mdct_stereo_dec.c +++ b/lib_dec/ivas_stereo_mdct_stereo_dec.c @@ -39,6 +39,8 @@ #include "prot.h" #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" #include "ivas_prot_fx.h" #endif // IVAS_FLOAT_FIXED #include "prot_fx1.h" @@ -52,6 +54,7 @@ static void inverseBwMS( const int16_t startLine, const int16_t stopLine, float x0[], float x1[], const float norm_fac ); +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * parse_stereo_from_bitstream * @@ -190,6 +193,7 @@ void parse_stereo_from_bitstream( return; } +#endif /*-------------------------------------------------------------------* @@ -204,18 +208,18 @@ void stereo_decoder_tcx( STEREO_MDCT_DEC_DATA *hStereoMdct, /* i/o: MDCT stereo decoder structure */ int16_t ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ float *spec_r_0[NB_DIV], /* i/o: spectrum right channel */ - float *spec_l[], /* i/o: spectrum left channel [NB_DIV][N] */ - float *spec_r[], /* i/o: spectrum right channel [NB_DIV][N] */ - const int16_t mdct_stereo_mode[], /* i : stereo mode (FB/band wise MS, dual mono */ - const int16_t core_l, /* i : core for left channel (TCX20/TCX10) */ - const int16_t core_r, /* i : core for right channel (TCX20/TCX10) */ - const int16_t igf, /* i : flag for IGF activity */ - const int16_t L_frameTCX_l, /* i : TCX frame length of left channel */ - const int16_t L_frameTCX_r, /* i : TCX frame length of right channel */ - const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ - const int16_t last_core_l, /* i : last core for left channel */ - const int16_t last_core_r, /* i : last core for right channel */ - const int16_t tmp_plc_upmix /* i : indicates temp upmix for PLC decision */ + float *spec_l[], /* i/o: spectrum left channel [NB_DIV][N] */ + float *spec_r[], /* i/o: spectrum right channel [NB_DIV][N] */ + const int16_t mdct_stereo_mode[], /* i : stereo mode (FB/band wise MS, dual mono */ + const int16_t core_l, /* i : core for left channel (TCX20/TCX10) */ + const int16_t core_r, /* i : core for right channel (TCX20/TCX10) */ + const int16_t igf, /* i : flag for IGF activity */ + const int16_t L_frameTCX_l, /* i : TCX frame length of left channel */ + const int16_t L_frameTCX_r, /* i : TCX frame length of right channel */ + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t last_core_l, /* i : last core for left channel */ + const int16_t last_core_r, /* i : last core for right channel */ + const int16_t tmp_plc_upmix /* i : indicates temp upmix for PLC decision */ ) { int16_t i, k, sfb, nSubframes; @@ -326,35 +330,172 @@ void stereo_decoder_tcx( return; } +#ifdef IVAS_FLOAT_FIXED +#define NF_RED_FAC_FIXED 1610612736 // Q31 +#define SQRT2_OVER_2_FIXED 1518500250 // Q31 +#define POINT_8_FIXED 1717986918 // Q31 +#define POINT_2_FIXED 429496730 // Q31 +#define ONE_POINT_3_FIXED 87241523 // Q26 +#define POINT_9_FIXED 60397978 // Q26 /*-------------------------------------------------------------------* - * inverseBwMS() + * parse_stereo_from_bitstream + * * - * Band-wise M/S stereo processing *-------------------------------------------------------------------*/ -static void inverseBwMS( - const int16_t startLine, /* i : start line of sfb */ - const int16_t stopLine, /* i : stop line of sfb */ - float x0[], /* i/o: mid/left channel coefficients */ - float x1[], /* i/o: side/right channel coefficients */ - const float norm_fac /* i : normalization factor */ +void parse_stereo_from_bitstream( + STEREO_MDCT_DEC_DATA_HANDLE hStereoMdct, /* i/o: MDCT stereo decoder structure */ + Decoder_State **sts, /* i/o: decoder state structure */ + const Word16 mct_on, /* i : flag mct block (1) or stereo (0)*/ + const Word16 isSBAStereoMode, /* i : flag core coding for SBA */ + Decoder_State *st0, /* i/o: decoder state structure for Bstr*/ + Word16 ms_mask[NB_DIV][MAX_SFB] /* o : bandwise MS mask */ ) { - int16_t j; - float tmpValue; + Word16 i, k, nSubframes, mdct_stereo_mode; + STEREO_MDCT_BAND_PARAMETERS *sfbConf; - for ( j = startLine; j < stopLine; j++ ) + IF( !isSBAStereoMode ) { - tmpValue = x0[j]; - x0[j] = ( x0[j] + x1[j] ) * norm_fac; - x1[j] = ( tmpValue - x1[j] ) * norm_fac; + nSubframes = ( EQ_16( sts[0]->core, TCX_10_CORE ) || ( NE_16( sts[0]->core, sts[1]->core ) ) ) ? NB_DIV : 1; + move16(); + sfbConf = ( EQ_16( sts[0]->core, TCX_20_CORE ) ) ? &hStereoMdct->stbParamsTCX20 : &hStereoMdct->stbParamsTCX10; + IF( EQ_16( sts[0]->last_core_from_bs, ACELP_CORE ) ) + { + sfbConf = &hStereoMdct->stbParamsTCX20afterACELP; + } + + IF( hStereoMdct->use_itd ) + { + Word16 I; + + hStereoMdct->itd_mode = (Word16) get_next_indice_fx( st0, STEREO_DFT_ITD_MODE_NBITS ); + /*(*nb_bits) += STEREO_DFT_ITD_MODE_NBITS;*/ /*ITD mode flag: 1bit*/ + + hStereoMdct->itd = 0.f; +#ifdef IVAS_FLOAT_FIXED + hStereoMdct->itd_fx = 0; + move32(); +#endif + IF( hStereoMdct->itd_mode ) + { + /*(*nb_bits) += */ read_itd( st0, &I ); + stereo_dft_dequantize_itd( &I, &hStereoMdct->itd, st0->output_Fs ); + } + } + + FOR( k = 0; k < nSubframes; k++ ) + { + mdct_stereo_mode = (Word16) get_next_indice_fx( st0, 1 ); + IF( mdct_stereo_mode ) + { + mdct_stereo_mode = add( 1, (Word16) get_next_indice_fx( st0, 1 ) ); + } + SWITCH( mdct_stereo_mode ) + { + case 0: + hStereoMdct->mdct_stereo_mode[k] = SMDCT_DUAL_MONO; + move16(); + BREAK; + case 1: + hStereoMdct->mdct_stereo_mode[k] = SMDCT_MS_FULL; + move16(); + BREAK; + case 2: + hStereoMdct->mdct_stereo_mode[k] = SMDCT_BW_MS; + move16(); + BREAK; + default: + assert( !"Not supported stereo mode\n" ); + } + + IF( !mct_on ) + { + test(); + IF( EQ_16( sts[0]->core, sts[1]->core ) || EQ_16( k, 0 ) ) + { + hStereoMdct->global_ild[k] = (Word16) get_next_indice_fx( st0, SMDCT_GLOBAL_ILD_BITS ); + move16(); + assert( ( GT_16( hStereoMdct->global_ild[k], 0 ) ) && ( LT_16( hStereoMdct->global_ild[k], SMDCT_ILD_RANGE ) ) ); + } + ELSE + { + hStereoMdct->global_ild[1] = hStereoMdct->global_ild[0]; + move16(); + } + } + + set16_fx( ms_mask[k], ( EQ_16( hStereoMdct->mdct_stereo_mode[k], SMDCT_MS_FULL ) ) ? 1 : 0, sfbConf->nBandsStereoCore ); + + IF( EQ_16( hStereoMdct->mdct_stereo_mode[k], SMDCT_BW_MS ) ) + { + FOR( i = 0; i < sfbConf->nBandsStereoCore; i++ ) + { + ms_mask[k][i] = (Word16) get_next_indice_fx( st0, 1 ); + move16(); + } + } + + IF( st0->igf ) + { + mdct_stereo_mode = (Word16) get_next_indice_fx( st0, 1 ); + IF( mdct_stereo_mode ) + { + mdct_stereo_mode = add( 1, (Word16) get_next_indice_fx( st0, 1 ) ); + } + + SWITCH( mdct_stereo_mode ) + { + case 0: + hStereoMdct->IGFStereoMode[k] = SMDCT_DUAL_MONO; + move16(); + BREAK; + case 1: + hStereoMdct->IGFStereoMode[k] = SMDCT_MS_FULL; + move16(); + BREAK; + case 2: + hStereoMdct->IGFStereoMode[k] = SMDCT_BW_MS; + move16(); + BREAK; + default: + assert( !"Not supported stereo mode\n" ); + } + + set16_fx( &ms_mask[k][sfbConf->nBandsStereoCore], ( EQ_16( hStereoMdct->IGFStereoMode[k], SMDCT_MS_FULL ) ) ? 1 : 0, sub( sfbConf->sfbCnt, sfbConf->nBandsStereoCore ) ); + + IF( EQ_16( hStereoMdct->IGFStereoMode[k], SMDCT_BW_MS ) ) + { + FOR( i = sfbConf->nBandsStereoCore; i < sfbConf->sfbCnt; i++ ) + { + ms_mask[k][i] = (Word16) get_next_indice_fx( st0, 1 ); + move16(); + } + } + } + ELSE + { + hStereoMdct->IGFStereoMode[k] = SMDCT_DUAL_MONO; + move16(); + } + } } + IF( !mct_on ) + { + hStereoMdct->split_ratio = SMDCT_EQUAL_RATIO_RANGE; /* Equal bits to both channels */ + move16(); + hStereoMdct->split_ratio = (Word16) get_next_indice_fx( st0, SMDCT_NBBITS_SPLIT_RATIO ); + + assert( GT_16( hStereoMdct->split_ratio, 0 ) ); + } + + return; } -#ifdef IVAS_FLOAT_FIXED + static void inverseBwMS_fx( const Word16 startLine, /* i : start line of sfb */ const Word16 stopLine, /* i : stop line of sfb */ @@ -366,18 +507,227 @@ static void inverseBwMS_fx( Word16 j; Word32 tmpValue; - for ( j = startLine; j < stopLine; j++ ) + FOR( j = startLine; j < stopLine; j++ ) { tmpValue = x0[j]; + move32(); x0[j] = Mpy_32_32( L_add( x0[j], x1[j] ), norm_fac ); + move32(); x1[j] = Mpy_32_32( L_sub_sat( tmpValue, x1[j] ), norm_fac ); + move32(); } return; } + +void inverseMS_fx( + const Word16 L_frame, /* i : frame length */ + Word32 x0[], /* i/o: mid/left channel coefficients */ + Word32 x1[], /* i/o: side/right channel coefficients */ + const Word32 norm_fac /* i : normalization factor */ +) +{ + inverseBwMS_fx( 0, L_frame, x0, x1, norm_fac ); + + return; +} + + +void stereo_decoder_tcx_fx( + STEREO_MDCT_DEC_DATA *hStereoMdct, /* i/o: MDCT stereo decoder structure */ + Word16 ms_mask[NB_DIV][MAX_SFB], /* i : bandwise MS mask */ + Word32 *spec_r_0[NB_DIV], /* i/o: spectrum right channel */ + Word32 *spec_l[], /* i/o: spectrum left channel [NB_DIV][N] */ + Word32 *spec_r[], /* i/o: spectrum right channel [NB_DIV][N] */ + const Word16 mdct_stereo_mode[], /* i : stereo mode (FB/band wise MS, dual mono */ + const Word16 core_l, /* i : core for left channel (TCX20/TCX10) */ + const Word16 core_r, /* i : core for right channel (TCX20/TCX10) */ + const Word16 igf, /* i : flag for IGF activity */ + const Word16 L_frameTCX_l, /* i : TCX frame length of left channel */ + const Word16 L_frameTCX_r, /* i : TCX frame length of right channel */ + const Word16 mct_on, /* i : flag mct block (1) or stereo (0) */ + const Word16 last_core_l, /* i : last core for left channel */ + const Word16 last_core_r, /* i : last core for right channel */ + const Word16 tmp_plc_upmix, /* i : indicates temp upmix for PLC decision */ + Word16 *q_x_ch2, + Word16 *q_x_ch1 ) +{ + Word16 i, k, sfb, nSubframes; + STEREO_MDCT_BAND_PARAMETERS *sfbConf = NULL; + Word32 nrgRatio; + Word16 tmp, tmp_e; + + nSubframes = 2; + move16(); + test(); + test(); + IF( ( LE_16( core_l, TCX_20_CORE ) && LE_16( core_r, TCX_20_CORE ) ) || tmp_plc_upmix ) + { + nSubframes = 1; + move16(); + } + + FOR( k = 0; k < nSubframes; k++ ) + { + sfbConf = ( EQ_16( core_l, TCX_20_CORE ) ) ? &hStereoMdct->stbParamsTCX20 : &hStereoMdct->stbParamsTCX10; + + test(); + IF( EQ_16( last_core_l, ACELP_CORE ) || EQ_16( last_core_r, ACELP_CORE ) ) + { + sfbConf = &hStereoMdct->stbParamsTCX20afterACELP; + } + + IF( EQ_16( mdct_stereo_mode[k], SMDCT_MS_FULL ) ) + { + FOR( i = 0; i < sfbConf->sfbOffset[sfbConf->nBandsStereoCore]; i++ ) + { + IF( EQ_32( spec_r_0[k][i], 0 ) ) + { + spec_r[k][i] = Mpy_32_32( spec_r[k][i], NF_RED_FAC_FIXED ); + move32(); + } + } + inverseMS_fx( sfbConf->sfbOffset[sfbConf->nBandsStereoCore], spec_l[k], spec_r[k], SQRT2_OVER_2_FIXED ); + *q_x_ch2 = *q_x_ch2; + move16(); + *q_x_ch1 = *q_x_ch1; + move16(); + } + ELSE IF( EQ_16( mdct_stereo_mode[k], SMDCT_BW_MS ) ) + { + FOR( sfb = 0; sfb < sfbConf->nBandsStereoCore; sfb++ ) + { + IF( ms_mask[k][sfb] ) + { + FOR( i = sfbConf->sfbOffset[sfb]; i < sfbConf->sfbOffset[sfb + 1]; i++ ) + { + IF( EQ_32( spec_r_0[k][i], 0 ) ) + { + spec_r[k][i] = Mpy_32_32( spec_r[k][i], NF_RED_FAC_FIXED ); + move32(); + } + } + inverseBwMS_fx( sfbConf->sfbOffset[sfb], sfbConf->sfbOffset[sfb + 1], spec_l[k], spec_r[k], SQRT2_OVER_2_FIXED ); + *q_x_ch2 = *q_x_ch2; + move16(); + *q_x_ch1 = *q_x_ch1; + move16(); + } + } + } + + IF( igf ) + { + IF( EQ_16( hStereoMdct->IGFStereoMode[k], SMDCT_MS_FULL ) ) + { + FOR( i = sfbConf->sfbOffset[sfbConf->nBandsStereoCore]; i < sfbConf->sfbOffset[sfbConf->sfbCnt]; i++ ) + { + IF( EQ_32( spec_r_0[k][i], 0 ) ) + { + spec_r[k][i] = Mpy_32_32( spec_r[k][i], NF_RED_FAC_FIXED ); + move32(); + } + } + inverseMS_fx( sfbConf->sfbOffset[sfbConf->sfbCnt] - sfbConf->sfbOffset[sfbConf->nBandsStereoCore], &spec_l[k][sfbConf->sfbOffset[sfbConf->nBandsStereoCore]], &spec_r[k][sfbConf->sfbOffset[sfbConf->nBandsStereoCore]], SQRT2_OVER_2_FIXED ); + *q_x_ch2 = *q_x_ch2; + move16(); + *q_x_ch1 = *q_x_ch1; + move16(); + } + ELSE IF( EQ_16( hStereoMdct->IGFStereoMode[k], SMDCT_BW_MS ) ) + { + FOR( sfb = sfbConf->nBandsStereoCore; sfb < sfbConf->sfbCnt; sfb++ ) + { + IF( ms_mask[k][sfb] ) + { + FOR( i = sfbConf->sfbOffset[sfb]; i < sfbConf->sfbOffset[sfb + 1]; i++ ) + { + IF( EQ_32( spec_r_0[k][i], 0 ) ) + { + spec_r[k][i] = Mpy_32_32( spec_r[k][i], NF_RED_FAC_FIXED ); + move32(); + } + } + inverseBwMS_fx( sfbConf->sfbOffset[sfb], sfbConf->sfbOffset[sfb + 1], spec_l[k], spec_r[k], SQRT2_OVER_2_FIXED ); + *q_x_ch2 = *q_x_ch2; + move16(); + *q_x_ch1 = *q_x_ch1; + move16(); + } + } + } + } + + IF( !mct_on ) + { + tmp = BASOP_Util_Divide3216_Scale( ( SMDCT_ILD_RANGE << Q26 ), sub( hStereoMdct->global_ild[k], 1 ), &tmp_e ); + nrgRatio = L_shr( (Word32) tmp, negate( add( 1, tmp_e ) ) ); /* nrgRatio = nrg[1]/nrg[0] */ // Q26 + + hStereoMdct->smooth_ratio_fx = L_add( Mpy_32_32( POINT_8_FIXED, hStereoMdct->smooth_ratio_fx ), Mpy_32_32( POINT_2_FIXED, nrgRatio ) ); // Q26 + /* set flag to reverse dmx computation in case of right-side panning, only relevant for mono output */ + IF( GT_32( hStereoMdct->smooth_ratio_fx, ONE_POINT_3_FIXED ) ) + { + hStereoMdct->reverse_dmx = 1; + move16(); + } + ELSE IF( LT_32( hStereoMdct->smooth_ratio_fx, POINT_9_FIXED ) ) + { + hStereoMdct->reverse_dmx = 0; + move16(); + } + + test(); + test(); + IF( ( GT_32( nrgRatio, ONE_IN_Q26 ) ) && ( LT_16( k, ( ( EQ_16( core_r, TCX_10_CORE ) ) ? NB_DIV : 1 ) ) ) ) + { + v_multc_fixed( spec_r[k], nrgRatio, spec_r[k], L_frameTCX_r ); + *q_x_ch2 = *q_x_ch2 - 5; + move16(); + } + ELSE IF( ( LT_32( nrgRatio, ONE_IN_Q26 ) ) && ( LT_16( k, ( ( EQ_16( core_l, TCX_10_CORE ) ) ? NB_DIV : 1 ) ) ) ) + { + v_multc_fixed( spec_l[k], L_shl( (Word32) divide3232( ONE_IN_Q26, nrgRatio ), Q11 ), spec_l[k], L_frameTCX_l ); + *q_x_ch1 = *q_x_ch1 - 5; + move16(); + } + } + } /* for k */ + + return; +} + #endif + +/*-------------------------------------------------------------------* + * inverseBwMS() + * + * Band-wise M/S stereo processing + *-------------------------------------------------------------------*/ + +static void inverseBwMS( + const int16_t startLine, /* i : start line of sfb */ + const int16_t stopLine, /* i : stop line of sfb */ + float x0[], /* i/o: mid/left channel coefficients */ + float x1[], /* i/o: side/right channel coefficients */ + const float norm_fac /* i : normalization factor */ +) +{ + int16_t j; + float tmpValue; + + for ( j = startLine; j < stopLine; j++ ) + { + tmpValue = x0[j]; + x0[j] = ( x0[j] + x1[j] ) * norm_fac; + x1[j] = ( tmpValue - x1[j] ) * norm_fac; + } + + return; +} + + /*-------------------------------------------------------------------* * inverseMS() * @@ -396,19 +746,7 @@ void inverseMS( return; } -#ifdef IVAS_FLOAT_FIXED -void inverseMS_fx( - const Word16 L_frame, /* i : frame length */ - Word32 x0[], /* i/o: mid/left channel coefficients */ - Word32 x1[], /* i/o: side/right channel coefficients */ - const Word32 norm_fac /* i : normalization factor */ -) -{ - inverseBwMS_fx( 0, L_frame, x0, x1, norm_fac ); - return; -} -#endif /*-------------------------------------------------------------------* * initMdctStereoDecData() * diff --git a/lib_dec/ivas_stereo_switching_dec.c b/lib_dec/ivas_stereo_switching_dec.c index 036e8d300..250e65daa 100644 --- a/lib_dec/ivas_stereo_switching_dec.c +++ b/lib_dec/ivas_stereo_switching_dec.c @@ -758,6 +758,10 @@ ivas_error stereo_memory_dec( } hCPE->hStereoMdct->reverse_dmx = 0; hCPE->hStereoMdct->smooth_ratio = 1.f; +#ifdef IVAS_FLOAT_FIXED + hCPE->hStereoMdct->smooth_ratio_fx = ONE_IN_Q26; +#endif + } } -- GitLab From b6acad51ff7247abc633a98f6d96a63ffbb2c7ba Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 31 Jan 2024 14:52:46 +0530 Subject: [PATCH 2/2] Update to Q for fixing crash with +10dB inputs. --- lib_dec/ivas_mct_core_dec.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib_dec/ivas_mct_core_dec.c b/lib_dec/ivas_mct_core_dec.c index 80005135e..7c074ebc1 100644 --- a/lib_dec/ivas_mct_core_dec.c +++ b/lib_dec/ivas_mct_core_dec.c @@ -311,10 +311,10 @@ void ivas_mct_core_dec( FOR( Word16 j = 0; j < L_FRAME48k / 2; j++ ) { - x_fx[ch][0][j] = (Word32) ( x[ch][0][j] * ONE_IN_Q16 ); - x_fx[ch][1][j] = (Word32) ( x[ch][1][j] * ONE_IN_Q16 ); + x_fx[ch][0][j] = (Word32) ( x[ch][0][j] * ONE_IN_Q15 ); + x_fx[ch][1][j] = (Word32) ( x[ch][1][j] * ONE_IN_Q15 ); } - q_x[ch] = Q16; + q_x[ch] = Q15; } apply_MCT_dec_fx( hMCT, sts, x_fx, q_x ); -- GitLab