diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj
index 1c79d4b2175ab0a9ffd42632737359fdc0086f86..bdb0d64d84db38673c91f6f4c3926a309ba1806f 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 eb880863d4b559008292d62875182086c2e791af..5c6f6a8d66471244e38acd9361547ec47854f267 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 7db57ae2a045e0f2f62e7e0f68ba14f6c5c4eb52..33074e3a3d0e67af59e0d0fe55ba0660043c1e32 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 480d3dd1444e2ce48ce025d99ba6e815d6a95848..46bf5216653fba8a171630988cc5cf70333a4a3d 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 37cb165c4877dc7f09dbffcf2a64c2f457c71fb5..b8bd80bad4b455b84632f42f7e9d5a33d0bd0080 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 5218f7f03bbab3cf5c2bcecac470d0dc46f7c596..ed0c01e3ffc1354a50bc8de12469c8a476220008 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 7364813ff97081aa3ae925d6db3d348803f4b7db..7c074ebc1a47023fc753752b86537b1616118a9c 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_Q15 );
+ x_fx[ch][1][j] = (Word32) ( x[ch][1][j] * ONE_IN_Q15 );
+ }
+ q_x[ch] = Q15;
+ }
+
+ 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 dae6a663c1f46c10ebb733941c949a4b8337437c..eb35eff975e0cbd7a43fc8e7f1e73f877a578ca4 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 881c35119cdbaef891ac4f8adde4cef504241a95..abf1475253d913257d2fe7541659c99545cc2862 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 0000000000000000000000000000000000000000..cf48b5abf01f3531f851bb4ed78319b7c396f5f1
--- /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 692603a1a6cacab262752f813573b695a1ca9995..2eb543cbff313e8cbcd67375c24f0d9cd4f69e63 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 712ca1e87bbfe59dfedcbd87315945e680b85ab5..207cf5a2978f41dc0bdb77d5233cf835f91c2f7d 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 036e8d300c0c8289e34d508bcff45ac785340a66..250e65daaa29119be55df0c5539fd0c25264cb3c 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
+
}
}