diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj
index bdb0d64d84db38673c91f6f4c3926a309ba1806f..04b61751f69cd4a23646ee380127a863447f39a2 100644
--- a/Workspace_msvc/lib_dec.vcxproj
+++ b/Workspace_msvc/lib_dec.vcxproj
@@ -337,6 +337,7 @@
+
diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters
index 5c6f6a8d66471244e38acd9361547ec47854f267..c3704d1c3e4ac6e7234552216d5e4d3a99d3d421 100644
--- a/Workspace_msvc/lib_dec.vcxproj.filters
+++ b/Workspace_msvc/lib_dec.vcxproj.filters
@@ -832,6 +832,8 @@
decoder_ivas_c
+
+ decoder_ivas_c
diff --git a/lib_com/igf_base.c b/lib_com/igf_base.c
index 3c97125e264236dcd219dcd077b59130c7fe8b78..383e1421d564ca0b5332effc0e3738892cad69fd 100644
--- a/lib_com/igf_base.c
+++ b/lib_com/igf_base.c
@@ -357,348 +357,6 @@ int16_t IGF_MapBitRateToIndex_flt(
return bitRateIndex;
}
-#ifdef IVAS_FLOAT_FIXED
-Word16 IGF_MapBitRateToIndex(
- const Word32 brate, /* i : bitrate */
- const Word16 bwidth, /* i : audio bandwidth */
- const Word16 element_mode, /* i : element mode */
- const Word16 rf_mode /* i : flag to signal the RF mode */
-)
-{
- Word16 bitRateIndex = IGF_BITRATE_UNKNOWN;
- move16();
-
- /* Stereo/CPE modes */
- IF ( GT_16( element_mode, IVAS_SCE ) )
- {
- SWITCH ( bwidth )
- {
- case IGF_MODE_WB:
- IF ( LE_32( brate, IVAS_13k2 ) && EQ_16( rf_mode, 1 ) )
- {
- bitRateIndex = IGF_BITRATE_RF_WB_13200;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_9k60 ) )
- {
- bitRateIndex = IGF_BITRATE_WB_13200_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_13k2 ) )
- {
- bitRateIndex = IGF_BITRATE_WB_16400_CPE;
- move16();
- }
- BREAK;
- case IGF_MODE_SWB:
- /* DFT and TD Stereo bitrates */
- IF ( LE_32( brate, ACELP_9k60 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_13200_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_13k2 ) )
- {
- IF ( EQ_16( rf_mode, 1 ) )
- {
- bitRateIndex = IGF_BITRATE_RF_SWB_13200;
- move16();
- }
- ELSE
- {
- bitRateIndex = IGF_BITRATE_SWB_16400_CPE;
- move16();
- }
- }
- ELSE IF ( LE_32( brate, IVAS_16k4 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_24400_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_24k4 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_32000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_32k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_32000;
- move16();
- }
- /* MDCT Stereo bitrates */
- ELSE IF ( LE_32( brate, IVAS_48k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_48000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_64k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_64000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_80k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_80000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_96k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_96000_CPE;
- move16();
- }
- BREAK;
- case IGF_MODE_FB:
- /* DFT and TD Stereo bitrates */
- IF ( LE_32( brate, IVAS_16k4 ) )
- {
- bitRateIndex = IGF_BITRATE_FB_24400_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_24k4 ) )
- {
- bitRateIndex = IGF_BITRATE_FB_32000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_32k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_32000;
- move16();
- }
- /* MDCT Stereo bitrates */
- ELSE IF ( LE_32( brate, IVAS_48k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_48000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_64k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_64000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_80k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_80000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_96k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_96000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_128k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_128000_CPE;
- move16();
- }
- BREAK;
- }
- }
- /* SCE modes: use tunings done for DFT stereo bitrates also for according SCE bitrates, otherwise same config as mono modes */
- ELSE IF ( EQ_16( element_mode, IVAS_SCE ) )
- {
- SWITCH ( bwidth )
- {
- case IGF_MODE_WB:
- IF ( LE_32( brate, IVAS_13k2 ) && EQ_16( rf_mode, 1 ) )
- {
- bitRateIndex = IGF_BITRATE_RF_WB_13200;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_9k60 ) ) /* bitrates 8000 and 9600 */
- {
- bitRateIndex = IGF_BITRATE_WB_9600;
- move16();
- }
- BREAK;
- case IGF_MODE_SWB:
- IF ( LE_32( brate, ACELP_9k60 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_13200_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_13k2 ) )
- {
- IF ( EQ_16( rf_mode, 1 ) )
- {
- bitRateIndex = IGF_BITRATE_RF_SWB_13200;
- move16();
- }
- ELSE
- {
- bitRateIndex = IGF_BITRATE_SWB_16400_CPE;
- move16();
- }
- }
- ELSE IF ( LE_32( brate, IVAS_16k4 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_24400_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_24k4 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_32000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_32k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_32000;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_48k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_48000;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_64k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_64000;
- move16();
- }
- BREAK;
- case IGF_MODE_FB:
- IF ( LE_32( brate, IVAS_16k4 ) )
- {
- bitRateIndex = IGF_BITRATE_FB_24400_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_24k4 ) )
- {
- bitRateIndex = IGF_BITRATE_FB_32000_CPE;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_32k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_32000;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_48k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_48000;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_64k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_64000;
- }
- ELSE IF ( LE_32( brate, IVAS_96k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_96000;
- move16();
- }
- ELSE IF ( LE_32( brate, IVAS_128k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_128000;
- move16();
- }
- BREAK;
- }
- }
- /* EVS mono */
- ELSE
- {
- SWITCH ( bwidth )
- {
- case IGF_MODE_WB:
- IF ( LE_32( brate, ACELP_13k20 ) && EQ_16( rf_mode, 1 ) )
- {
- bitRateIndex = IGF_BITRATE_RF_WB_13200;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_9k60 ) ) /* bitrates 8000 and 9600 */
- {
- bitRateIndex = IGF_BITRATE_WB_9600;
- move16();
- }
- BREAK;
- case IGF_MODE_SWB:
- IF ( LE_32( brate, ACELP_9k60 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_9600;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_13k20 ) )
- {
- IF ( EQ_16( rf_mode, 1 ) )
- {
- bitRateIndex = IGF_BITRATE_RF_SWB_13200;
- move16();
- }
- ELSE
- {
- bitRateIndex = IGF_BITRATE_SWB_13200;
- move16();
- }
- }
- ELSE IF ( LE_32( brate, ACELP_16k40 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_16400;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_24k40 ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_24400;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_32k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_32000;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_48k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_48000;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_64k ) )
- {
- bitRateIndex = IGF_BITRATE_SWB_64000;
- move16();
- }
- BREAK;
- case IGF_MODE_FB:
- IF ( LE_32( brate, ACELP_16k40 ) )
- {
- bitRateIndex = IGF_BITRATE_FB_16400;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_24k40 ) )
- {
- bitRateIndex = IGF_BITRATE_FB_24400;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_32k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_32000;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_48k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_48000;
- move16();
- }
- ELSE IF ( LE_32( brate, ACELP_64k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_64000;
- move16();
- }
- ELSE IF ( LE_32( brate, HQ_96k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_96000;
- move16();
- }
- ELSE IF ( LE_32( brate, HQ_128k ) )
- {
- bitRateIndex = IGF_BITRATE_FB_128000;
- move16();
- }
- BREAK;
- }
- }
-
- return bitRateIndex;
-}
-#endif
-
/*---------------------------------------------------------------------*
* IGF_gridSetUp_flt()
*
diff --git a/lib_com/igf_base_fx.c b/lib_com/igf_base_fx.c
index 89ddd1899590e07d19b99a92c2c756de16cb3e44..3bcc9dc9ba2ba97df2e19a6bef537ba7a8932cf6 100644
--- a/lib_com/igf_base_fx.c
+++ b/lib_com/igf_base_fx.c
@@ -16,7 +16,7 @@
/**********************************************************************/ /*
returns an int val, multiplied with transFac
**************************************************************************/
-static Word16 IGF_ApplyTransFac( /**< out: Q0 | multiplication factor */
+Word16 IGF_ApplyTransFac( /**< out: Q0 | multiplication factor */
const Word16 val, /**< in: Q15 | input value for multiplication, Q15 */
const Word16 transFac /**< in: Q14 | multiplicator for variable val, Q14: 1.25f=0x5000, 1.0f=0x4000, 0.5f=0x2000 */
)
@@ -39,7 +39,7 @@ static Word16 IGF_ApplyTransFac(
/**********************************************************************/ /*
maps a given bitrate to the IGF_BITRATE index
**************************************************************************/
-static Word16 IGF_MapBitRateToIndex(
+Word16 IGF_MapBitRateToIndex(
const Word32 brate, /* i : bitrate */
const Word16 bwidth, /* i : audio bandwidth */
const Word16 element_mode, /* i : element mode */
diff --git a/lib_com/ivas_stereo_mdct_bands_com.c b/lib_com/ivas_stereo_mdct_bands_com.c
index 80994dda9f721f5cad6b07dce22d3e8d1cc1df2f..d1d0d9bb2c5c9597f3e83969457e5c9d57afb58b 100644
--- a/lib_com/ivas_stereo_mdct_bands_com.c
+++ b/lib_com/ivas_stereo_mdct_bands_com.c
@@ -39,7 +39,11 @@
#include "rom_com.h"
#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
/*-------------------------------------------------------------------*
* Local union
@@ -62,6 +66,157 @@ typedef union
* initialize stereo band tables for MDCT stereo
*-------------------------------------------------------------------*/
+#ifdef IVAS_FLOAT_FIXED
+void stereo_mdct_init_bands_fx(
+ const Word16 L_frame, /* i : frame length */
+ const Word16 tmp_tcx_mode, /* i : tcx mode (TCX10, TCX 20), -1 if transition frame */
+ const Word32 element_brate, /* i : element bitrate */
+ const Word16 igf, /* i : flag indicating if IGF is used */
+ const H_IGF_GRID hIgfGrid, /* i : IGF grid setup */
+ Word16 *sfbOffset, /* o : sfb offset table */
+ Word16 *sfbCnt /* o : number of sfbs */
+)
+{
+ SBPARAMS sfbParam;
+ Word16 i, cnt, specStartOffset, L_frameTCX, tcx_mode;
+ const UWord8 *sfbWidths;
+
+ IF( tmp_tcx_mode > 0 )
+ {
+ tcx_mode = tmp_tcx_mode;
+ L_frameTCX = ( tcx_mode == TCX_20_CORE ) ? L_frame : ( L_frame / 2 );
+ }
+ ELSE
+ {
+ /*transition frame*/
+ L_frameTCX = L_frame + L_frame / 4;
+ tcx_mode = TCX_20_CORE;
+ }
+
+ /* select table */
+ IF( L_frame == L_FRAME48k )
+ {
+ sfbParam.steBands = mdctStereoBands_32000_640;
+
+ cnt = ( tcx_mode == TCX_20_CORE ? sfbParam.steBands->bdnCnt_TCX20[0] : sfbParam.steBands->bndCnt_TCX10[0] );
+
+ sfbWidths = ( tcx_mode == TCX_20_CORE ? sfbParam.steBands->bandLengthsTCX20 : sfbParam.steBands->bandLengthsTCX10 );
+ }
+ ELSE
+ {
+ IF( element_brate < IVAS_96k )
+ {
+ sfbParam.steBands = mdctStereoBands_32000_640;
+
+ SWITCH( L_frame )
+ {
+ case L_FRAME32k:
+ cnt = ( tcx_mode == TCX_20_CORE ? sfbParam.steBands->bdnCnt_TCX20[1] : sfbParam.steBands->bndCnt_TCX10[1] );
+ BREAK;
+ case L_FRAME25_6k:
+ cnt = ( tcx_mode == TCX_20_CORE ? sfbParam.steBands->bdnCnt_TCX20[2] : sfbParam.steBands->bndCnt_TCX10[2] );
+ BREAK;
+ case L_FRAME16k:
+ cnt = ( tcx_mode == TCX_20_CORE ? sfbParam.steBands->bdnCnt_TCX20[3] : sfbParam.steBands->bndCnt_TCX10[3] );
+ BREAK;
+ default:
+ assert( !"Subband division not defined for this frame size" );
+ return;
+ }
+
+ sfbWidths = ( tcx_mode == TCX_20_CORE ? sfbParam.steBands->bandLengthsTCX20 : sfbParam.steBands->bandLengthsTCX10 );
+ }
+ ELSE
+ {
+ SWITCH( L_frame )
+ {
+ case L_FRAME48k:
+ case L_FRAME32k:
+ sfbParam.lpcBndsParam = sw32000Hz;
+ BREAK;
+ case L_FRAME25_6k:
+ sfbParam.lpcBndsParam = sw25600Hz;
+ BREAK;
+ case L_FRAME16k:
+ sfbParam.lpcBndsParam = sw16000Hz;
+ BREAK;
+ default:
+ assert( !"Subband division not defined for this frame size" );
+ return;
+ }
+
+ sfbWidths = ( tcx_mode == TCX_20_CORE ? sfbParam.lpcBndsParam->bandLengthsTCX20 : sfbParam.lpcBndsParam->bandLengthsTCX10 );
+ cnt = 64;
+ }
+ }
+
+ /* calc sfb offsets */
+ specStartOffset = 0;
+
+ FOR( i = 0; i < cnt; i++ )
+ {
+ sfbOffset[i] = min( specStartOffset, L_frameTCX );
+ specStartOffset += sfbWidths[i];
+
+ IF( sfbOffset[i] >= L_frameTCX )
+ {
+ BREAK;
+ }
+ }
+
+ *sfbCnt = i;
+ sfbOffset[*sfbCnt] = min( specStartOffset, L_frameTCX );
+
+ IF( igf )
+ {
+ Word16 sfbOldCnt = *sfbCnt;
+ Word16 igfSfbStep = hIgfGrid->infoIsRefined ? 2 : 1;
+ Word16 k;
+
+ /* modify sfb bands according to igf grid */
+ assert( hIgfGrid != NULL );
+
+ /* find sfb where IGF starts */
+ FOR( i = 0; i <= *sfbCnt; i++ )
+ {
+ IF( sfbOffset[i] >= hIgfGrid->startLine )
+ {
+ /* set band border to igf start line */
+ sfbOffset[i] = hIgfGrid->startLine;
+ *sfbCnt = i;
+ BREAK;
+ }
+ }
+ /* change bands above the igf start line to match igf bands */
+ for( i = 1, k = igfSfbStep; i < hIgfGrid->swb_offset_len; i++, k += igfSfbStep )
+ {
+ sfbOffset[*sfbCnt + i] = hIgfGrid->swb_offset[k];
+ }
+
+ *sfbCnt += ( hIgfGrid->swb_offset_len - 1 );
+
+ /* better save than sorry, overwrite anything that is left above */
+ FOR( i = *sfbCnt + 1; i < sfbOldCnt + 1; i++ )
+ {
+ sfbOffset[i] = 0;
+ }
+ }
+ ELSE
+ {
+ IF( sfbOffset[*sfbCnt] < L_frameTCX )
+ {
+ Word16 nMissingBins = L_frameTCX - sfbOffset[*sfbCnt];
+ IF( sfbWidths[i] / 2 < nMissingBins )
+ {
+ ( *sfbCnt )++;
+ }
+ sfbOffset[*sfbCnt] = L_frameTCX;
+ }
+ }
+ return;
+}
+#endif
+
void stereo_mdct_init_bands(
const int16_t L_frame, /* i : frame length */
const int16_t tmp_tcx_mode, /* i : tcx mode (TCX10, TCX 20), -1 if transition frame */
@@ -217,6 +372,37 @@ void stereo_mdct_init_bands(
* initialize start band of the IGF in MDCT stereo
*-------------------------------------------------------------------*/
+#ifdef IVAS_FLOAT_FIXED
+void stereo_mdct_init_igf_start_band_fx(
+ STEREO_MDCT_BAND_PARAMETERS *stbParams, /* i/o: stereo frequency band parameters */
+ const Word16 transFac, /* i : transform factor */
+ const Word16 bwidth, /* i : audio bandwidth */
+ const Word32 element_brate /* i : element bitrate */
+)
+{
+ Word16 i, bitRateIndex, igfStartLine;
+ const Word16 *swb_offset;
+
+ bitRateIndex = IGF_MapBitRateToIndex( element_brate, bwidth, IVAS_CPE_MDCT, 0 );
+ swb_offset = &swb_offset_LB_new[bitRateIndex][1];
+ igfStartLine = IGF_ApplyTransFac( swb_offset[0], transFac );
+
+ FOR( i = 0; i < stbParams->sfbCnt; i++ )
+ {
+ IF( igfStartLine == stbParams->sfbOffset[i] )
+ {
+ stbParams->sfbIgfStart = i;
+ BREAK;
+ }
+ }
+
+ stbParams->nBandsStereoCore = stbParams->sfbIgfStart;
+
+
+ return;
+}
+#endif
+
void stereo_mdct_init_igf_start_band(
STEREO_MDCT_BAND_PARAMETERS *stbParams, /* i/o: stereo frequency band parameters */
const float transFac, /* i : transform factor */
diff --git a/lib_com/ivas_stereo_mdct_stereo_com.c b/lib_com/ivas_stereo_mdct_stereo_com.c
index c9151b72df87f1e9d08b63734f7177c668f85579..e7c5f2b7d61e66218e8c4c9d97b44c4840533195 100644
--- a/lib_com/ivas_stereo_mdct_stereo_com.c
+++ b/lib_com/ivas_stereo_mdct_stereo_com.c
@@ -36,6 +36,42 @@
#include "ivas_prot.h"
#include "wmc_auto.h"
#include
+#ifdef IVAS_FLOAT_FIXED
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "ivas_prot_fx.h"
+#endif
+
+#ifdef IVAS_FLOAT_FIXED
+#define POINT_2_Q15 6554
+/*-------------------------------------------------------------------*
+ * splitAvailableBits()
+ *
+ * split available bits between channels based on the split ratio
+ *-------------------------------------------------------------------*/
+
+void splitAvailableBits_fx(
+ const Word16 total_bits, /* i : total available bits for TCX coding */
+ const Word16 split_ratio, /* i : split ratio */
+ const Word16 isSBAStereoMode, /* i : signal core coding for SBA */
+ Word16 *bits_ch0, /* o : bits for channel 0 */
+ Word16 *bits_ch1 /* o : bits for channel 1 */
+)
+{
+ assert( split_ratio >= 1 && split_ratio < SMDCT_BITRATE_RATIO_RANGE );
+
+ *bits_ch0 = split_ratio * total_bits / SMDCT_BITRATE_RATIO_RANGE;
+ /* for SBA mode bias the distribution towards the W channel */
+ if ( split_ratio < 7 && isSBAStereoMode )
+ {
+ //*bits_ch0 += (int16_t) ( 0.2 * *bits_ch0 );
+ *bits_ch0 += (Word16) ( Mpy_32_16_1( 6554, *bits_ch0 ) ); // 0.2 in Q15
+ }
+ *bits_ch1 = total_bits - *bits_ch0;
+
+ return;
+}
+#endif
/*-------------------------------------------------------------------*
* splitAvailableBits()
diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h
index 667d29dc0c7b24f243f1288bbf033de39d08e0c8..e960f09751c8e0e6706988fcbed0902b7dcd3009 100644
--- a/lib_com/prot_fx2.h
+++ b/lib_com/prot_fx2.h
@@ -4923,6 +4923,18 @@ void Inac_swtch_ematch_fx(
const short last_codec_mode /* i : Last codec mode */
);
//igf_base_fx.c
+Word16 IGF_ApplyTransFac( /**< out: Q0 | multiplication factor */
+ const Word16 val, /**< in: Q15 | input value for multiplication, Q15 */
+ const Word16 transFac /**< in: Q14 | multiplicator for variable val, Q14: 1.25f=0x5000, 1.0f=0x4000, 0.5f=0x2000 */
+);
+
+Word16 IGF_MapBitRateToIndex(
+ const Word32 brate, /* i : bitrate */
+ const Word16 bwidth, /* i : audio bandwidth */
+ const Word16 element_mode, /* i : element mode */
+ const Word16 rf_mode /* i : flag to signal the RF mode */
+);
+
void IGFCommonFuncsCalcSfbEnergyPowerSpec(const Word16 startSfb, /**< in: Q0 | start sfb index */
const Word16 stopSfb, /**< in: Q0 | stop sfb index */
const Word16 *swb_offset, /**< in: Q0 | IGF swb offset table */
diff --git a/lib_dec/igf_dec_fx.c b/lib_dec/igf_dec_fx.c
index 79e578f775669c08cf97d3cf8402cf2cddd8ee9d..90c044cee21f947b3ddc52ff6869c8dcbd090bfe 100644
--- a/lib_dec/igf_dec_fx.c
+++ b/lib_dec/igf_dec_fx.c
@@ -18,6 +18,9 @@
#include "basop_util.h"
//Temporarily added
#define MID 57/* (.89*1<<6)*/
+#ifdef IVAS_FLOAT_FIXED
+#include "ivas_prot_fx.h"
+#endif
/**********************************************************************/ /*
get scalefactor of an Word32 array with condition
@@ -1395,6 +1398,90 @@ static void IGF_RefineGrid_ivas_fx( H_IGF_GRID hGrid /**< in/out: | IGF grid han
/**********************************************************************/ /*
reads whitening information from the bitstream
**************************************************************************/
+#ifdef IVAS_FLOAT_FIXED
+void IGFDecReadData_ivas_fx( const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */
+ Decoder_State *st, /**< in: | decoder state */
+ const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */
+ const Word16 isIndepFrame /**< in: Q0 | if 1: arith dec force reset, if 0: no reset */
+)
+{
+ IGF_DEC_PRIVATE_DATA_HANDLE hPrivateData;
+ H_IGF_GRID hGrid;
+ Word16 p;
+ Word16 nT;
+ Word16 tmp;
+
+
+ IF( hInstance != NULL )
+ {
+ hPrivateData = &hInstance->igfData;
+ hGrid = &hPrivateData->igfInfo.grid[igfGridIdx];
+ nT = hGrid->nTiles;
+ move16();
+ tmp = 0;
+ move16();
+
+ /* set/reset all values to default = IGF_WHITENING_OFF */
+ FOR( p = 0; p < IGF_MAX_TILES; p++ )
+ {
+ hPrivateData->currWhiteningLevel[p] = IGF_WHITENING_OFF;
+ move16();
+ }
+
+ IF( isIndepFrame == 0 )
+ {
+ tmp = get_next_indice( st, 1 );
+ }
+
+ IF( tmp == 1 )
+ {
+ FOR( p = 0; p < nT; p++ )
+ {
+ hPrivateData->currWhiteningLevel[p] = hPrivateData->prevWhiteningLevel[p];
+ move16();
+ }
+ }
+ ELSE
+ {
+ IGF_decode_whitening_level( st, hPrivateData, 0 );
+ IF( hPrivateData->igfInfo.bitRateIndex == IGF_BITRATE_SWB_48000_CPE || hPrivateData->igfInfo.bitRateIndex == IGF_BITRATE_FB_48000_CPE )
+ {
+ tmp = 0;
+ }
+ ELSE
+ {
+ tmp = get_next_indice( st, 1 );
+ }
+
+ IF( tmp == 1 )
+ {
+ FOR( p = 1; p < nT; p++ )
+ {
+ IGF_decode_whitening_level( st, hPrivateData, p );
+ }
+ }
+ ELSE
+ {
+ FOR( p = 1; p < nT; p++ )
+ {
+ hPrivateData->currWhiteningLevel[p] = hPrivateData->currWhiteningLevel[0];
+ move16();
+ }
+ }
+ }
+
+ /* save current level for concealment */
+ FOR( p = 0; p < IGF_MAX_TILES; p++ )
+ {
+ hPrivateData->prevWhiteningLevel[p] = hPrivateData->currWhiteningLevel[p];
+ move16();
+ }
+
+ /* read flattening trigger from bitstream */
+ IGF_decode_temp_flattening_trigger( st, hInstance );
+ }
+}
+#endif
void IGFDecReadData(const IGF_DEC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Deccoder */
Decoder_State *st, /**< in: | decoder state */
const Word16 igfGridIdx, /**< in: Q0 | in case of CELP->TCX switching, use 1.25 framelength */
diff --git a/lib_dec/ivas_core_dec.c b/lib_dec/ivas_core_dec.c
index 4665cc5176b7f40c046f5c7f4a949a5d47372fc8..b009eb38e3db64e44dd388256876feaba9ee8fd3 100644
--- a/lib_dec/ivas_core_dec.c
+++ b/lib_dec/ivas_core_dec.c
@@ -471,7 +471,11 @@ ivas_error ivas_core_dec(
}
else
{
+#ifdef IVAS_FLOAT_FIXED
+ stereo_mdct_core_dec_fx( st_ivas, hCPE, output, synth );
+#else
stereo_mdct_core_dec( st_ivas, hCPE, output, synth );
+#endif
}
}
/* for inactive frames with mono output, copy and (if necessary) downmix buffers */
@@ -1087,7 +1091,7 @@ ivas_error ivas_core_dec(
{
hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[ind] = (Word32) ( hCPE->hCoreCoder[0]->hHQ_core->old_outLB[ind] * ( 1 << q ) );
}
- IF( (hCPE->hCoreCoder[0] != NULL) && (hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL) )
+ IF( ( hCPE->hCoreCoder[0] != NULL ) && ( hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL ) )
FOR( int ind = 0; ind < L_FRAME16k; ind++ )
{
hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[ind] = (Word32) ( hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[ind] * ( 1 << q ) );
@@ -1133,7 +1137,8 @@ ivas_error ivas_core_dec(
}
// Function call goes here
stereo_dft_dec_core_switching_fx( hCPE, output_fx, synth_fx, hb_synth_fx, DFT_fx, output_frame, use_cldfb_for_dft, 0, &q, q_DFT );
- IF(DFT != NULL) {
+ IF( DFT != NULL )
+ {
FOR( i = 0; i < CPE_CHANNELS; i++ )
{
FOR( Word16 j = 0; j < STEREO_DFT_BUF_MAX; j++ )
@@ -1152,12 +1157,12 @@ ivas_error ivas_core_dec(
hCPE->input_mem[1][i] = (float) hCPE->input_mem_fx[1][i] / (float) ( 1 << q );
FOR( i = 0; i < STEREO_DFT32MS_OVL_16k; i++ )
hCPE->input_mem_LB[1][i] = (float) hCPE->input_mem_LB_fx[1][i] / (float) ( 1 << q );
- IF( hCPE->hStereoDft !=NULL )
+ IF( hCPE->hStereoDft != NULL )
FOR( i = 0; i < NS2SA( 16000, DELAY_BWE_TOTAL_NS ); i++ )
{
hCPE->hStereoDft->ap_delay_mem[i] = (float) hCPE->hStereoDft->ap_delay_mem_fx[i] / (float) ( 1 << q );
}
- IF( (hCPE->hCoreCoder[0] !=NULL) && (hCPE->hCoreCoder[0]->p_bpf_noise_buf_32!=NULL) )
+ IF( ( hCPE->hCoreCoder[0] != NULL ) && ( hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL ) )
FOR( i = 0; i < L_FRAME16k; i++ )
{
hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[i] = (float) hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[i] / (float) ( 1 << q );
diff --git a/lib_dec/ivas_mdct_core_dec.c b/lib_dec/ivas_mdct_core_dec.c
index bee437aec399a1f08a19e5a19d75f9df9b0ff0ba..1fdefee69a8d4adbea9771b44730aeaef5ae33f7 100644
--- a/lib_dec/ivas_mdct_core_dec.c
+++ b/lib_dec/ivas_mdct_core_dec.c
@@ -58,6 +58,42 @@
* read IGF side bits
*-----------------------------------------------------------------*/
+#ifdef IVAS_FLOAT_FIXED
+void mdct_read_IGF_bits_fx(
+ Decoder_State *st, /* i/o: Decoder state handle */
+ Decoder_State *st0 /* i : pointer to handle where bitstream is read */
+)
+{
+ int16_t k, start;
+
+ start = st0->next_bit_pos;
+
+ IF( st->core == TCX_20_CORE )
+ {
+ /* read IGF payload */
+ IGFDecReadLevel( st->hIGFDec, st0, ( st->last_core == ACELP_CORE ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM, 1 );
+
+ IGFDecReadData_ivas_fx( st->hIGFDec, st0, ( st->last_core == ACELP_CORE ) ? IGF_GRID_LB_TRAN : IGF_GRID_LB_NORM, 1 );
+ }
+
+ IF( st->core == TCX_10_CORE )
+ {
+ FOR( k = 0; k < 2; k++ )
+ {
+ IGFDecReadLevel( st->hIGFDec, st0, IGF_GRID_LB_SHORT, k == 0 ? 1 : 0 );
+
+ IGFDecReadData_ivas_fx( st->hIGFDec, st0, IGF_GRID_LB_SHORT, k == 0 ? 1 : 0 );
+
+ IGFDecStoreTCX10SubFrameData( st->hIGFDec, k );
+ }
+ }
+
+ st->side_bits_frame_channel += ( st0->next_bit_pos - start );
+
+ return;
+}
+#endif
+
void mdct_read_IGF_bits(
Decoder_State *st, /* i/o: Decoder state handle */
Decoder_State *st0 /* i : pointer to handle where bitstream is read */
@@ -99,6 +135,107 @@ void mdct_read_IGF_bits(
* decode TCX side parameters
*-----------------------------------------------------------------*/
+#ifdef IVAS_FLOAT_FIXED
+static void dec_prm_tcx_sidebits_fx(
+ Word16 param[], /* o : decoded parameters */
+ Decoder_State *st, /* i/o: decoder memory state */
+ const Word16 tnsSize[NB_DIV], /* i : TNS activity/subframe (in channel 0 in case of 2) */
+ Word16 p_param[NB_DIV], /* o : pointer to parameters for next round of bs reading*/
+ Word16 nTnsBitsTCX10[NB_DIV], /* o : number of TNS bits per TCX10 subframe */
+ Decoder_State *st0, /* i/o: core decoder state handle - for bitstream */
+ const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0) */
+ const Word16 ch /* i : channel */
+)
+{
+ CONTEXT_HM_CONFIG hm_cfg;
+ Word16 start_bit_pos;
+
+ /*--------------------------------------------------------------------------------*
+ * Initialization
+ *--------------------------------------------------------------------------------*/
+
+ hm_cfg.indexBuffer = NULL;
+
+ start_bit_pos = st0->next_bit_pos;
+
+ /* Init LTP data */
+ st->hTcxDec->tcx_hm_LtpPitchLag = -1;
+ st->hTcxLtpDec->tcxltp_gain_float = 0.0f;
+
+ /*--------------------------------------------------------------------------------*
+ * Header
+ *--------------------------------------------------------------------------------*/
+
+ /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */
+ getTCXMode_ivas( st, st0, MCT_flag );
+
+ st->flagGuidedAcelp = 0;
+
+ IF( st->dec_glr )
+ {
+ st->dec_glr_idx = -1;
+ }
+
+ /* last_core for core switching and error concealment */
+ IF( ( st->last_core == ACELP_CORE && st->last_total_brate == FRAME_NO_DATA ) || st->prev_bfi )
+ {
+ /* needed for cases where first TCX frame after a certain transition (e.g. inactive SID/zero frame -> active or stereo switching) is lost */
+ st->last_core_from_bs = get_next_indice( st0, 1 );
+
+ /* ACELP -> TCX_10 transitions are forbidden */
+ IF( st->core == TCX_10_CORE && st->last_core == ACELP_CORE )
+ {
+ st->last_core = TCX_20_CORE;
+ }
+ }
+ ELSE
+ {
+ st->last_core = get_next_indice( st0, 1 );
+ st->last_core_from_bs = st->last_core;
+ }
+
+ getTCXWindowing_ivas( st->core, st->last_core, st->element_mode, st->hTcxCfg, st0 );
+
+ st->hTcxDec->kernel_type[0] = st->hTcxDec->kernel_type[1] = MDCT_IV;
+ st->hTcxDec->kernel_type[0] = get_next_indice( st0, st->last_core_from_bs != ACELP_CORE ? 2 : 1 );
+ IF( st->core == TCX_10_CORE )
+ {
+ st->hTcxDec->kernel_type[1] = 2 * ( st->hTcxDec->kernel_type[0] & 1 ) + get_next_indice( st0, 1 );
+ }
+ IF( st->core == TCX_20_CORE )
+ {
+ st->transform_type[0] = st->transform_type[1] = TCX_20;
+ }
+ ELSE
+ {
+ IF( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP )
+ {
+ st->transform_type[0] = TCX_5;
+ st->transform_type[1] = TCX_10;
+ }
+ ELSE IF( st->hTcxCfg->tcx_last_overlap_mode == FULL_OVERLAP )
+ {
+ st->transform_type[0] = TCX_10;
+ st->transform_type[1] = TCX_5;
+ }
+ ELSE
+ {
+ st->transform_type[0] = st->transform_type[1] = TCX_5;
+ }
+ }
+
+ /*--------------------------------------------------------------------------------*
+ * TCX20/TCX10 parameters
+ *--------------------------------------------------------------------------------*/
+
+ getTCXparam_ivas( st, st0, hm_cfg, param, 0, 0, ( ( ch > 0 ) && ( tnsSize ) && ( tnsSize[0] + tnsSize[1] > 0 ) ? tnsSize : NULL ), p_param, nTnsBitsTCX10, 0 );
+
+ st->side_bits_frame_channel = st0->next_bit_pos - start_bit_pos;
+
+ return;
+}
+#endif
+
static void dec_prm_tcx_sidebits(
int16_t param[], /* o : decoded parameters */
Decoder_State *st, /* i/o: decoder memory state */
@@ -272,6 +409,199 @@ static void dec_prm_tcx_spec(
* Initialize TCX and read TCX side parameters
*-----------------------------------------------------------------*/
+#ifdef IVAS_FLOAT_FIXED
+void ivas_mdct_dec_side_bits_frame_channel_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word16 param_lpc[CPE_CHANNELS][NPRM_LPC_NEW], /* o : lpc_parameters */
+ Word16 p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to param buffer */
+ Decoder_State *st0, /* i : pointer to bitstream handle */
+ Word16 nTnsBitsTCX10[CPE_CHANNELS][NB_DIV], /* o : number of bits for TNS */
+ Word16 param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV], /* i/o: parameters buffer */
+ const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/
+ const Word16 odd_channel_cpe /* i : flag cpe with odd nb of tc channels */
+)
+{
+ Word16 ch, bfi;
+ Decoder_State **sts, *st;
+ Word16 total_nbbits[MCT_MAX_CHANNELS];
+ Word16 bitsRead[MCT_MAX_CHANNELS];
+ Word16 tmp;
+ Word16 sns_low_br_mode;
+ Word16 start_bit_pos_sns;
+ Word8 skipped_first_channel;
+
+ sts = hCPE->hCoreCoder;
+ bfi = sts[0]->bfi;
+
+ set_s( total_nbbits, 0, MCT_MAX_CHANNELS );
+ set_s( bitsRead, 0, MCT_MAX_CHANNELS );
+
+ FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ IF( MCT_flag )
+ {
+ /* Initialization or re-configuration of Stereo TCX */
+ stereo_tcx_init_dec_fx( sts[ch], 1, hCPE->last_element_mode );
+ }
+ sts[ch]->enablePlcWaveadjust = 0;
+ }
+
+ IF( !bfi )
+ {
+ FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ /* disguard reading second channel of odd transport channels, mct_chan_mode is set by default*/
+ IF( odd_channel_cpe && ch == 1 )
+ {
+ continue;
+ }
+
+ st = sts[ch];
+ IF( MCT_flag )
+ {
+ tmp = get_next_indice( st0, 1 );
+ IF( tmp )
+ {
+ st->mct_chan_mode = MCT_CHAN_MODE_IGNORE;
+ }
+ ELSE
+ {
+ st->mct_chan_mode = MCT_CHAN_MODE_REGULAR;
+ }
+ }
+ }
+
+ /*read channel bitrate ratios from bitstream*/
+ FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ st = sts[ch];
+ IF( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE )
+ {
+ sts[ch]->coder_type = INACTIVE;
+ sts[ch]->side_bits_frame_channel = 0;
+ continue;
+ }
+
+ tmp = ch;
+ IF( ch == 1 && param_lpc[0][0] == 2 )
+ {
+ tmp = 3;
+ }
+
+ dec_prm_tcx_sidebits_fx( param[ch], st, ( ( st->element_mode == IVAS_CPE_MDCT && !MCT_flag ) ? sts[0]->hTcxDec->tnsActive : NULL ), p_param[ch], nTnsBitsTCX10[ch], st0, MCT_flag, tmp );
+
+ assert( st->BER_detect != 1 );
+ }
+
+ /*--------------------------------------------------------------------------------*
+ * SNS parameters
+ *--------------------------------------------------------------------------------*/
+
+ sns_low_br_mode = 0;
+ skipped_first_channel = 0;
+ IF( !MCT_flag && sts[0]->sr_core == 25600 && ( ( hCPE->element_brate == IVAS_48k || hCPE->element_brate == IVAS_64k ) ) )
+ {
+ param_lpc[0][0] = SNS_STEREO_MODE_LR;
+ param_lpc[0][1] = SNS_STEREO_MODE_LR;
+ param_lpc[0][2] = 0;
+ param_lpc[0][3] = 0;
+ IF( sts[0]->core == sts[1]->core )
+ {
+ Word16 nSubframes;
+ nSubframes = ( sts[0]->core == TCX_20_CORE ) ? 1 : NB_DIV;
+
+ for ( Word16 n = 0; n < nSubframes; ++n )
+ {
+ param_lpc[0][n] = get_next_indice( st0, 1 );
+ }
+
+ /* zero side flags only get transmitted if needed */
+ for ( Word16 n = 0; n < nSubframes; ++n )
+ {
+ if ( param_lpc[0][n] == SNS_STEREO_MODE_MS )
+ {
+ param_lpc[0][n + SNS_STEREO_MODE_OFFSET_INDICES / 2] = get_next_indice( st0, 1 );
+ }
+ }
+ }
+ for ( ch = 0; ch < CPE_CHANNELS; ++ch )
+ {
+ Word16 nSubframes;
+ Word16 idxIndices;
+
+ st = sts[ch];
+ nSubframes = ( st->core == TCX_20_CORE ) ? 1 : NB_DIV;
+ idxIndices = 0;
+
+ for ( Word16 n = 0; n < nSubframes; ++n )
+ {
+ const Word16 is_side = ch == 1 && param_lpc[0][n] == SNS_STEREO_MODE_MS;
+ const Word16 *bits = ( nSubframes == 1 ) ? ivas_sns_cdbks_tcx20_bits : ivas_sns_cdbks_tcx10_bits;
+ Word16 nStages = ( ( nSubframes == 1 ) ? SNS_MSVQ_NSTAGES_TCX20 : SNS_MSVQ_NSTAGES_TCX10 );
+
+ if ( is_side )
+ {
+ /* check for zero-side flag */
+ if ( param_lpc[0][n + SNS_STEREO_MODE_OFFSET_INDICES / 2] )
+ {
+ continue;
+ }
+ nStages = SNS_MSVQ_NSTAGES_SIDE;
+ bits = ( nSubframes == 1 ) ? ivas_sns_cdbks_side_tcx20_bits : ivas_sns_cdbks_side_tcx10_bits;
+ }
+
+ for ( Word16 j = 0; j < nStages; ++j )
+ {
+ /* plus one in index for stereo mode storage! */
+ param_lpc[ch][j + idxIndices + SNS_STEREO_MODE_OFFSET_INDICES] = get_next_indice_fx( st0, bits[j] );
+ }
+ idxIndices += nStages;
+ }
+ }
+ }
+ else
+ {
+ for ( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ st = sts[ch];
+
+ if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE )
+ {
+ skipped_first_channel = 1;
+ continue;
+ }
+
+ start_bit_pos_sns = st0->next_bit_pos;
+
+ if ( ch == 0 || skipped_first_channel )
+ {
+ /* read SNS stereo mode */
+ param_lpc[0][0] = get_next_indice( st0, 1 ) << 1;
+
+ /* read low br mode flag (if it is possible to be non-zero) */
+ if ( sts[0]->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) )
+ {
+ sns_low_br_mode = get_next_indice( st0, 1 );
+ }
+ }
+
+ tmp = ch;
+ if ( ch == 1 && param_lpc[0][0] == 2 )
+ {
+ tmp = 3;
+ }
+
+ getLPCparam( st, ¶m_lpc[ch][0], st0, tmp, sns_low_br_mode && !( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) );
+
+ st->side_bits_frame_channel += st0->next_bit_pos - start_bit_pos_sns;
+ }
+ }
+ }
+
+ return;
+}
+#endif
+
void ivas_mdct_dec_side_bits_frame_channel(
CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW], /* o : lpc_parameters */
diff --git a/lib_dec/ivas_stereo_mdct_core_dec_fx.c b/lib_dec/ivas_stereo_mdct_core_dec_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..5a10d89566dee8679f1e4e870e5fe0c91f156f8f
--- /dev/null
+++ b/lib_dec/ivas_stereo_mdct_core_dec_fx.c
@@ -0,0 +1,925 @@
+/******************************************************************************************************
+
+ (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
+#include "options.h"
+#ifdef IVAS_FLOAT_FIXED
+#include
+#include "prot.h"
+#include "cnst.h"
+#include "stat_com.h"
+#include "ivas_prot.h"
+#include "ivas_stat_dec.h"
+#include "wmc_auto.h"
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "ivas_prot_fx.h"
+
+/*-------------------------------------------------------------------------
+ * Local function prototypes
+ *-------------------------------------------------------------------------*/
+
+static void apply_dmx_weights_fx( CPE_DEC_HANDLE hCPE, Word32 *x[CPE_CHANNELS][NB_DIV], int16_t transform_type_left[NB_DIV], int16_t transform_type_right[NB_DIV] );
+static void apply_dmx_weights( CPE_DEC_HANDLE hCPE, float *x[CPE_CHANNELS][NB_DIV], int16_t transform_type_left[NB_DIV], int16_t transform_type_right[NB_DIV] );
+
+static void run_min_stats_fx( Decoder_State **sts, float *x[CPE_CHANNELS][NB_DIV] );
+
+/*-------------------------------------------------------------------*
+ * stereo_mdct_dec_stereo()
+ *
+ * decode core and MDCT stereo information
+ *-------------------------------------------------------------------*/
+
+static void stereo_mdct_dec_stereo_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ int16_t ms_mask[2][MAX_SFB] /* o : bandwise MS mask */
+)
+{
+ int16_t availableBits;
+ Decoder_State **sts;
+
+ sts = hCPE->hCoreCoder;
+
+ parse_stereo_from_bitstream( hCPE->hStereoMdct, hCPE->hCoreCoder, 0, hCPE->hStereoMdct->isSBAStereoMode, hCPE->hCoreCoder[0], ms_mask );
+
+ /*Split available bits between channels */
+ availableBits = sts[0]->bits_frame_channel + sts[1]->bits_frame_channel - sts[0]->next_bit_pos - sts[0]->core * ( NF_GAIN_BITS + SMDCT_MINIMUM_ARITH_BITS ) - sts[1]->core * ( NF_GAIN_BITS + SMDCT_MINIMUM_ARITH_BITS );
+
+ splitAvailableBits_fx( availableBits, hCPE->hStereoMdct->split_ratio, hCPE->hStereoMdct->isSBAStereoMode, &sts[0]->bits_frame_channel, &sts[1]->bits_frame_channel );
+
+ sts[0]->bits_frame_channel += sts[0]->core * SMDCT_MINIMUM_ARITH_BITS;
+ sts[1]->bits_frame_channel += sts[1]->core * SMDCT_MINIMUM_ARITH_BITS;
+
+ sts[1]->bit_stream = &sts[0]->bit_stream[sts[0]->next_bit_pos + sts[0]->bits_frame_channel + sts[0]->core * NF_GAIN_BITS];
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * stereo_mdct_core_dec()
+ *
+ * MDCT stereo core/stereo decoder
+ *--------------------------------------------------------------------*/
+
+void stereo_mdct_core_dec_fx(
+ Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ float *signal_out[CPE_CHANNELS], /* o : synthesis @internal_FS */
+ float signal_outFB[CPE_CHANNELS][L_FRAME48k] /* o : synthesis @output_FS */
+)
+{
+ int16_t k, ch, nChannels;
+ Decoder_State *st, **sts;
+
+ /* bitstream */
+ int16_t param[CPE_CHANNELS][DEC_NPRM_DIV * NB_DIV];
+ int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW];
+
+ float Aq[CPE_CHANNELS][( NB_SUBFR16k + 1 ) * ( M + 1 )];
+#ifdef IVAS_FLOAT_FIXED
+ /* NOTE: temporary fix to avoid garbage values while calculating its
+ q-factor when not initialised. */
+ set_zero((float *)Aq, CPE_CHANNELS * (NB_SUBFR16k + 1) * (M + 1));
+#endif
+ float *x[CPE_CHANNELS][NB_DIV];
+
+ /*needed to allocate N_MAX to prevent stereo switching crash */
+ float x_0_buf[CPE_CHANNELS][N_MAX];
+ float *x_0[CPE_CHANNELS][NB_DIV];
+
+ /* Concealment */
+ int16_t bfi;
+
+ /* Framing */
+ int16_t L_frame[CPE_CHANNELS], L_frameTCX[CPE_CHANNELS], nSubframes[CPE_CHANNELS];
+
+ /* TCX */
+ int16_t fUseTns[CPE_CHANNELS][NB_DIV];
+ STnsData tnsData[CPE_CHANNELS][NB_DIV];
+ int16_t tcx_offset[CPE_CHANNELS];
+ int16_t tcx_offsetFB[CPE_CHANNELS];
+ int16_t left_rect[CPE_CHANNELS];
+ int16_t L_spec[CPE_CHANNELS];
+
+ /* stereo */
+ int16_t ms_mask[NB_DIV][MAX_SFB];
+
+ int16_t p_param[CPE_CHANNELS][NB_DIV];
+ int16_t nTnsBitsTCX10[CPE_CHANNELS][NB_DIV];
+ float signal_outFB_tmp[CPE_CHANNELS][L_FRAME_PLUS];
+ float signal_out_tmp[CPE_CHANNELS][L_FRAME_PLUS];
+ push_wmops( "stereo_mdct_core_dec" );
+
+ /*--------------------------------------------------------------------------------*
+ * Initializations
+ *--------------------------------------------------------------------------------*/
+
+ sts = hCPE->hCoreCoder;
+ st = NULL;
+
+ nChannels = CPE_CHANNELS;
+ bfi = sts[0]->bfi;
+
+ for ( ch = 0; ch < nChannels; ch++ )
+ {
+ /* Initialization or re-configuration of Stereo TCX */
+ stereo_tcx_init_dec_fx( sts[ch], 0, hCPE->last_element_mode );
+ sts[ch]->hTcxDec->tnsActive[0] = sts[ch]->hTcxDec->tnsActive[1] = 0;
+ sts[ch]->enablePlcWaveadjust = 0;
+ set_zero( signal_out_tmp[ch], L_FRAME_PLUS );
+ x[ch][0] = &signal_out_tmp[ch][0];
+ x[ch][1] = &signal_out_tmp[ch][0] + L_FRAME_PLUS / 2;
+
+ set_zero( x_0_buf[ch], N_MAX );
+ x_0[ch][0] = &x_0_buf[ch][0];
+ x_0[ch][1] = &x_0_buf[ch][0] + L_FRAME48k / 2;
+ nTnsBitsTCX10[ch][0] = 0;
+ nTnsBitsTCX10[ch][1] = 0;
+
+ set_s( param_lpc[ch], 0, NPRM_LPC_NEW );
+ }
+ set_s( ms_mask[0], 0, MAX_SFB );
+ set_s( ms_mask[1], 0, MAX_SFB );
+
+ initMdctStereoDecData_fx( hCPE->hStereoMdct, sts[0]->igf, sts[0]->hIGFDec->igfData.igfInfo.grid, hCPE->element_brate, sts[0]->bwidth );
+ hCPE->hStereoMdct->isSBAStereoMode = ( ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == SBA_ISM_FORMAT ) && ( st_ivas->nchan_transport == 2 ) );
+ if ( !bfi )
+ {
+ ivas_mdct_dec_side_bits_frame_channel_fx( hCPE, param_lpc, p_param, hCPE->hCoreCoder[0], nTnsBitsTCX10, param, 0, 0 );
+
+ if ( sts[0]->igf )
+ {
+ for ( ch = 0; ch < nChannels; ch++ )
+ {
+ st = sts[ch];
+ mdct_read_IGF_bits_fx( st, sts[0] );
+ }
+ }
+
+ stereo_mdct_dec_stereo_fx( hCPE, ms_mask );
+ }
+ else
+ {
+ mvs2s( hCPE->hStereoMdct->prev_ms_mask[0], ms_mask[0], MAX_SFB );
+ mvs2s( hCPE->hStereoMdct->prev_ms_mask[1], ms_mask[1], MAX_SFB );
+
+ if ( sts[0]->core != TCX_10_CORE && sts[1]->core != TCX_10_CORE )
+ {
+ hCPE->hStereoMdct->mdct_stereo_mode[1] = SMDCT_DUAL_MONO;
+ hCPE->hStereoMdct->IGFStereoMode[1] = SMDCT_DUAL_MONO;
+ }
+ else if ( sts[0]->core == TCX_10_CORE && sts[1]->core == TCX_10_CORE )
+ {
+ hCPE->hStereoMdct->global_ild[0] = hCPE->hStereoMdct->global_ild[1];
+ hCPE->hStereoMdct->mdct_stereo_mode[0] = hCPE->hStereoMdct->mdct_stereo_mode[1];
+ hCPE->hStereoMdct->IGFStereoMode[0] = hCPE->hStereoMdct->IGFStereoMode[1];
+ }
+ }
+
+ ivas_mdct_core_invQ( hCPE, nTnsBitsTCX10, p_param, param_lpc, param, fUseTns, tnsData, x_0, x, Aq, ms_mask, 0 );
+
+ for ( ch = 0; ch < nChannels; ch++ )
+ {
+ nSubframes[ch] = ( sts[ch]->core == TCX_10_CORE ) ? NB_DIV : 1;
+ for ( k = 0; k < nSubframes[ch]; k++ )
+ {
+ L_spec[ch] = sts[ch]->hTcxCfg->tcx_coded_lines / nSubframes[ch];
+
+ init_tcx_info( sts[ch], sts[ch]->L_frame / nSubframes[ch], sts[ch]->hTcxDec->L_frameTCX / nSubframes[ch], k, bfi, &tcx_offset[ch], &tcx_offsetFB[ch], &L_frame[ch], &L_frameTCX[ch], &left_rect[ch], &L_spec[ch] );
+ }
+ }
+
+ /* IGF decoding */
+ if ( sts[0]->igf || sts[1]->igf )
+ {
+ if ( sts[0]->core != sts[1]->core )
+ {
+ for ( ch = 0; ch < nChannels; ch++ )
+ {
+ st = sts[ch];
+ if ( !bfi || ( bfi && st->core != ACELP_CORE ) )
+ {
+ for ( k = 0; k < nSubframes[ch]; k++ )
+ {
+ /* mono or dual mono IGF decoding */
+ decoder_tcx_IGF_mono( st, x[ch][k], L_frame[ch], left_rect[ch], bfi, k );
+ }
+ }
+ }
+ }
+ else if ( sts[0]->core != ACELP_CORE )
+ {
+ assert( nSubframes[0] == nSubframes[1] );
+
+ for ( k = 0; k < nSubframes[0]; k++ )
+ {
+ if ( ( hCPE->hStereoMdct->IGFStereoMode[k] != SMDCT_DUAL_MONO || hCPE->hStereoMdct->mdct_stereo_mode[k] != SMDCT_DUAL_MONO ) && !hCPE->hStereoMdct->isSBAStereoMode )
+ {
+ assert( ( sts[0]->core == sts[1]->core ) || ( hCPE->hStereoMdct->mdct_stereo_mode[0] == SMDCT_DUAL_MONO ) );
+
+ /* stereo IGF decoding */
+ decoder_tcx_IGF_stereo( sts, hCPE->hStereoMdct, ms_mask, x, L_frame[0], left_rect[0], k, bfi, 0 /* MCT_flag */ );
+ }
+ else
+ {
+ for ( ch = 0; ch < nChannels; ch++ )
+ {
+ st = sts[ch];
+ /* mono or dual mono IGF decoding */
+ decoder_tcx_IGF_mono( st, x[ch][k], L_frame[ch], left_rect[ch], bfi, k );
+ }
+ }
+ }
+ }
+ }
+
+ /*--------------------------------------------------------------------------------*
+ * Stereo processing
+ *--------------------------------------------------------------------------------*/
+
+ if ( !bfi )
+ {
+ for ( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ st = sts[ch];
+ for ( k = 0; k < nSubframes[ch]; k++ )
+ {
+ float sns_int_scf[FDNS_NPTS];
+
+#ifdef IVAS_FLOAT_FIXED
+ Word32 sns_int_scf_fx[FDNS_NPTS], Aq_fx[SNS_NPTS];
+ FOR( int c = 0; c < SNS_NPTS; c++ )
+ {
+ Aq_fx[c] = (Word32) ( Aq[ch][k * M + c] * ONE_IN_Q16 );
+ }
+
+ sns_interpolate_scalefactors_fx( sns_int_scf_fx, Aq_fx, DEC );
+
+ FOR( int c = 0; c < FDNS_NPTS; c++ )
+ {
+ sns_int_scf[c] = ( (float) sns_int_scf_fx[c] / ONE_IN_Q16 );
+ }
+#else
+ sns_interpolate_scalefactors( &sns_int_scf[0], &Aq[ch][k * M], DEC );
+#endif // IVAS_FLOAT_FIXED
+
+ if ( st->hTonalMDCTConc != NULL && ( ( k + 1 ) == nSubframes[ch] ) )
+ {
+#ifdef IVAS_FLOAT_FIXED
+ Word32 x_fx[N_MAX];
+ Word16 x_e, scf_fx[FDNS_NPTS], scf_e[FDNS_NPTS];
+ f2me_buf( x[ch][k], x_fx, &x_e, L_frameTCX[ch] );
+ for ( int j = 0; j < st->hTonalMDCTConc->nScaleFactors; j++ )
+ {
+ f2me_16( sns_int_scf[j], &scf_fx[j], &scf_e[j] );
+ }
+ TonalMDCTConceal_SaveFreqSignal_ivas_fx( st->hTonalMDCTConc, x_fx, x_e, L_frameTCX[ch], L_frame[ch], &scf_fx[0], scf_e, 0, get_igf_startline( st, L_frame[ch], L_frameTCX[ch] ) );
+ st->hTonalMDCTConc->last_block_nrg_flt = me2f( st->hTonalMDCTConc->last_block_nrg, st->hTonalMDCTConc->last_block_nrg_exp );
+#else
+ TonalMDCTConceal_SaveFreqSignal_ivas( st->hTonalMDCTConc, x[ch][k], L_frameTCX[ch], L_frame[ch], &sns_int_scf[0], get_igf_startline_flt( st, L_frame[ch], L_frameTCX[ch] ) );
+#endif
+ }
+ }
+
+ TonalMDCTConceal_UpdateState_ivas( st->hTonalMDCTConc, L_frameTCX[ch], ( st->hTcxDec->tcxltp_last_gain_unmodified_float > 0 ) ? st->old_fpitch_float : 0, bfi, bfi && st->tonal_mdct_plc_active );
+ }
+
+ mvs2s( ms_mask[0], hCPE->hStereoMdct->prev_ms_mask[0], MAX_SFB );
+ mvs2s( ms_mask[1], hCPE->hStereoMdct->prev_ms_mask[1], MAX_SFB );
+ }
+
+ if ( ( !bfi || !( sts[0]->core == ACELP_CORE && sts[1]->core == ACELP_CORE ) ) && !hCPE->hStereoMdct->isSBAStereoMode )
+ {
+ stereo_decoder_tcx( hCPE->hStereoMdct, ms_mask, x_0[1], x[0], x[1], &hCPE->hStereoMdct->mdct_stereo_mode[0], sts[0]->core, sts[1]->core, sts[0]->igf, L_frameTCX[0], L_frameTCX[1], 0, sts[0]->last_core, sts[1]->last_core, 0 );
+ }
+
+ ivas_mdct_core_tns_ns( hCPE, fUseTns, tnsData, x, Aq, 0 );
+
+ if ( st_ivas->renderer_type == RENDERER_MC_PARAMMC && ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_STEREO ) )
+ {
+ ivas_ls_setup_conversion_process_mdct_param_mc( st_ivas, x );
+ }
+
+ run_min_stats_fx( sts, x );
+
+ if ( hCPE->nchan_out == 1 && ( !bfi || ( bfi && sts[0]->core != ACELP_CORE && sts[1]->core != ACELP_CORE ) ) )
+ {
+#ifdef IVAS_FLOAT_FIXED
+ Word32 *x_fx[CPE_CHANNELS][NB_DIV];
+ FOR ( ch = 0; ch < nChannels; ch++ )
+ {
+ x_fx[ch][0] = malloc( L_FRAME_PLUS * sizeof( Word32 ) );
+ x_fx[ch][1] = x_fx[ch][0] + L_FRAME_PLUS / 2;
+ FOR ( Word16 j = 0; j < L_FRAME_PLUS / 2; ++j )
+ {
+ x_fx[ch][0][j] = (Word32) ( x[ch][0][j] * ONE_IN_Q11 );
+ x_fx[ch][1][j] = (Word32) ( x[ch][1][j] * ONE_IN_Q11 );
+ }
+ }
+ apply_dmx_weights_fx( hCPE, x_fx, sts[0]->transform_type, sts[1]->transform_type );
+ FOR ( ch = 0; ch < nChannels; ch++ )
+ {
+ FOR ( Word16 j = 0; j < L_FRAME_PLUS / 2; ++j )
+ {
+ x[ch][0][j] = (float) x_fx[ch][0][j] / ONE_IN_Q11;
+ x[ch][1][j] = (float) x_fx[ch][1][j] / ONE_IN_Q11;
+ }
+ free( x_fx[ch][0] );
+ }
+#else
+ apply_dmx_weights( hCPE, x, sts[0]->transform_type, sts[1]->transform_type );
+#endif
+ }
+
+ ivas_mdct_core_reconstruct( hCPE, x, signal_outFB_tmp, fUseTns, 0 );
+
+ mvr2r( signal_out_tmp[0], signal_out[0], L_FRAME48k );
+ mvr2r( signal_out_tmp[1], signal_out[1], L_FRAME48k );
+
+ mvr2r( signal_outFB_tmp[0], signal_outFB[0], hCPE->hCoreCoder[0]->hTcxDec->L_frameTCX );
+ mvr2r( signal_outFB_tmp[1], signal_outFB[1], hCPE->hCoreCoder[1]->hTcxDec->L_frameTCX );
+
+ pop_wmops();
+ return;
+}
+
+static void apply_dmx_weights(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ float *x[CPE_CHANNELS][NB_DIV], /* i/o: MDCT Spectrum */
+ int16_t transform_type_left[NB_DIV], /* i : indicate TCX5 for left ch */
+ int16_t transform_type_right[NB_DIV] /* i : indicate TCX5 for right ch */
+)
+{
+ int16_t b, k, l, i, ch;
+ int16_t nsub, nsub2[2], nChannels;
+ int16_t transform_type[2][2];
+ int16_t numCoeffs[2], frameSize;
+ int16_t tcx_10_only, w_idx;
+ int16_t start, stop, start_tcx5, stop_tcx5;
+ STEREO_MDCT_BAND_PARAMETERS *sfbConf = NULL;
+ float mdst[CPE_CHANNELS][NB_DIV][L_FRAME48k];
+ float convertRes[CPE_CHANNELS][L_FRAME48k];
+ float *sig[CPE_CHANNELS][NB_DIV], *pTmp[CPE_CHANNELS][NB_DIV];
+
+ nChannels = CPE_CHANNELS;
+ frameSize = hCPE->hStereoMdct->stbParamsTCX20.sfbOffset[hCPE->hStereoMdct->stbParamsTCX20.sfbCnt];
+
+ transform_type[0][0] = transform_type_left[0];
+ transform_type[0][1] = transform_type_left[1];
+ transform_type[1][0] = transform_type_right[0];
+ transform_type[1][1] = transform_type_right[1];
+
+ /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
+ if ( transform_type[0][0] == TCX_20 || transform_type[1][0] == TCX_20 )
+ {
+ /* use TCX20 band config for TCX20 in both channels and mixed frames */
+ sfbConf = &hCPE->hStereoMdct->stbParamsTCX20;
+ nsub = nsub2[0] = nsub2[1] = 1; /* overall TCX 20 */
+ tcx_10_only = 0;
+ }
+ else
+ {
+ /* use TCX10 band config only if none of the channels is TCX20 */
+ sfbConf = &hCPE->hStereoMdct->stbParamsTCX10;
+ nsub = 2;
+ /* set resolution per subframe, subdivide again if subframe is TCX5 in both channels */
+ nsub2[0] = ( transform_type[0][0] == TCX_5 && transform_type[1][0] == TCX_5 ) ? 2 : 1;
+ nsub2[1] = ( transform_type[0][1] == TCX_5 && transform_type[1][1] == TCX_5 ) ? 2 : 1;
+ tcx_10_only = 1;
+ }
+
+ /* for subframes with only TCX5 in both channels number of coefficients is only half (in 2 quarterframes) */
+ numCoeffs[0] = ( nsub2[0] == 1 ) ? sfbConf->sfbOffset[sfbConf->sfbCnt] : sfbConf->sfbOffset[sfbConf->sfbCnt] / 2;
+ numCoeffs[1] = ( nsub2[1] == 1 ) ? sfbConf->sfbOffset[sfbConf->sfbCnt] : sfbConf->sfbOffset[sfbConf->sfbCnt] / 2;
+
+ /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
+ sig[0][0] = pTmp[0][0] = x[0][0];
+ sig[0][1] = pTmp[0][1] = x[0][1];
+ sig[1][0] = pTmp[1][0] = x[1][0];
+ sig[1][1] = pTmp[1][1] = x[1][1];
+
+ /* convert (sub)frames to higher frequency resolution */
+ for ( ch = 0; ch < nChannels; ch++ )
+ {
+ for ( k = 0; k < NB_DIV; k++ )
+ {
+ if ( transform_type[ch][k] == TCX_5 && nsub2[k] == 1 )
+ {
+ /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
+ pTmp[ch][k] = sig[ch][k] = convertRes[ch] + k * frameSize / 2;
+ convert_coeffs_to_higher_res( x[ch][k], x[ch][k] + frameSize / 4, pTmp[ch][k], frameSize / 4 );
+ }
+ }
+
+ if ( transform_type[ch][0] != TCX_20 && nsub == 1 )
+ {
+ /* TCX20 and TCX10 in same frame -> convert channel with TCX10 to TCX20 resolution */
+ sig[ch][0] = convertRes[ch];
+ convert_coeffs_to_higher_res( pTmp[ch][0], pTmp[ch][1], sig[ch][0], frameSize / 2 );
+ }
+ }
+
+ /* MDST estimate */
+ for ( ch = 0; ch < nChannels; ch++ )
+ {
+ for ( k = 0; k < nsub; k++ )
+ {
+ for ( l = 0; l < nsub2[k]; l++ )
+ {
+ mdst[ch][k][l * numCoeffs[k]] = mdst[ch][k][( l + 1 ) * numCoeffs[k] - 1] = 0.f;
+ for ( i = l * numCoeffs[k] + 1; i < ( l + 1 ) * numCoeffs[k] - 1; i++ )
+ {
+ mdst[ch][k][i] = sig[ch][k][i + 1] - sig[ch][k][i - 1];
+ }
+ }
+ }
+ }
+
+ /* compute and apply bandwise weigths for active downmix (similar to DFT Stereo) */
+ stop_tcx5 = 0;
+ for ( b = 0; b < sfbConf->sfbCnt; b++ )
+ {
+ float w[CPE_CHANNELS][4];
+
+ for ( k = 0; k < nsub; k++ )
+ {
+ for ( l = 0; l < nsub2[k]; l++ )
+ {
+ float sum_nrg_L = EPSILON, sum_nrg_R = EPSILON;
+ float dot_prod_real = EPSILON, dot_prod_imag = EPSILON;
+ float sum_nrg_Mid, sum_abs, dot_prod_abs;
+
+ start = l * numCoeffs[k] + sfbConf->sfbOffset[b] / nsub2[k];
+ stop = l * numCoeffs[k] + sfbConf->sfbOffset[b + 1] / nsub2[k];
+
+ /* compute band energies and cross correlation */
+ for ( i = start; i < stop; i++ )
+ {
+ sum_nrg_L += sig[0][k][i] * sig[0][k][i] + mdst[0][k][i] * mdst[0][k][i];
+ sum_nrg_R += sig[1][k][i] * sig[1][k][i] + mdst[1][k][i] * mdst[1][k][i];
+ dot_prod_real += sig[0][k][i] * sig[1][k][i] + mdst[0][k][i] * mdst[1][k][i];
+ dot_prod_imag += mdst[0][k][i] * sig[1][k][i] - sig[0][k][i] * mdst[1][k][i];
+ }
+ sum_nrg_Mid = max( 0.f, sum_nrg_L + sum_nrg_R + 2.f * dot_prod_real );
+ sum_abs = sqrtf( sum_nrg_L ) + sqrtf( sum_nrg_R ) + EPSILON;
+ dot_prod_abs = sqrtf( dot_prod_real * dot_prod_real + dot_prod_imag * dot_prod_imag );
+
+ /* calculate weights */
+ if ( hCPE->hStereoMdct->reverse_dmx == 0 )
+ {
+ w[1][2 * k + l] = sqrtf( 0.5f * ( sum_nrg_L + sum_nrg_R ) + dot_prod_abs ) / sum_abs;
+ w[0][2 * k + l] = w[1][2 * k + l] + sqrtf( 2.f ) * ( 1.f - sqrtf( sum_nrg_Mid ) / sum_abs );
+ }
+ else
+ {
+ w[0][2 * k + l] = sqrtf( 0.5f * ( sum_nrg_L + sum_nrg_R ) + dot_prod_abs ) / sum_abs;
+ w[1][2 * k + l] = w[0][2 * k + l] + sqrtf( 2.f ) * ( 1.f - sqrtf( sum_nrg_Mid ) / sum_abs );
+ }
+ }
+ }
+
+ /* apply weights to channels with their original frequency resolutions */
+ for ( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ if ( transform_type[ch][0] == TCX_20 )
+ {
+ for ( i = sfbConf->sfbOffset[b]; i < sfbConf->sfbOffset[b + 1]; i++ )
+ {
+ x[ch][0][i] *= w[ch][0];
+ }
+ }
+ else
+ {
+ start = sfbConf->sfbOffset[b];
+ stop = sfbConf->sfbOffset[b + 1];
+ if ( !tcx_10_only ) /* TCX20 band config is used */
+ {
+ start /= 2;
+ stop /= 2;
+ }
+
+ for ( k = 0; k < NB_DIV; k++ )
+ {
+ w_idx = ( nsub == 1 ) ? 0 : 2 * k;
+ if ( transform_type[ch][k] == TCX_10 )
+ {
+ for ( i = start; i < stop; i++ )
+ {
+ x[ch][k][i] *= w[ch][w_idx];
+ }
+ }
+ else /* TCX_5 */
+ {
+ start_tcx5 = stop_tcx5;
+ stop_tcx5 = ( stop + 1 ) / 2;
+
+ for ( i = start_tcx5; i < stop_tcx5; i++ )
+ {
+ x[ch][k][i] *= w[ch][w_idx];
+ }
+
+ if ( nsub2[k] == 2 )
+ {
+ w_idx++;
+ }
+
+ for ( i = start_tcx5; i < stop_tcx5; i++ )
+ {
+ x[ch][k][i + ( frameSize >> 2 )] *= w[ch][w_idx];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * apply_dmx_weights()
+ *
+ * apply bandwise weighting for later dmx in case of mono output
+ *--------------------------------------------------------------------*/
+
+static void apply_dmx_weights_fx(
+ CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */
+ Word32 *x[CPE_CHANNELS][NB_DIV], /* i/o: MDCT Spectrum */
+ Word16 transform_type_left[NB_DIV], /* i : indicate TCX5 for left ch */
+ Word16 transform_type_right[NB_DIV] /* i : indicate TCX5 for right ch */
+)
+{
+ Word16 b, k, l, i, ch;
+ Word16 nsub, nsub2[2], nChannels;
+ Word16 transform_type[2][2];
+ Word16 numCoeffs[2], frameSize;
+ Word16 tcx_10_only, w_idx;
+ Word16 start, stop, start_tcx5, stop_tcx5;
+ STEREO_MDCT_BAND_PARAMETERS *sfbConf = NULL;
+ Word32 mdst[CPE_CHANNELS][NB_DIV][L_FRAME48k];
+ Word32 convertRes[CPE_CHANNELS][L_FRAME48k];
+ Word32 *sig[CPE_CHANNELS][NB_DIV], *pTmp[CPE_CHANNELS][NB_DIV];
+
+ nChannels = CPE_CHANNELS;
+ frameSize = hCPE->hStereoMdct->stbParamsTCX20.sfbOffset[hCPE->hStereoMdct->stbParamsTCX20.sfbCnt];
+
+ transform_type[0][0] = transform_type_left[0];
+ transform_type[0][1] = transform_type_left[1];
+ transform_type[1][0] = transform_type_right[0];
+ transform_type[1][1] = transform_type_right[1];
+
+ /* set overall frequency resolution of (sub)frame to maximum of (sub)frame, requires conversion if both channels are not the same */
+ IF( transform_type[0][0] == TCX_20 || transform_type[1][0] == TCX_20 )
+ {
+ /* use TCX20 band config for TCX20 in both channels and mixed frames */
+ sfbConf = &hCPE->hStereoMdct->stbParamsTCX20;
+ nsub = nsub2[0] = nsub2[1] = 1; /* overall TCX 20 */
+ tcx_10_only = 0;
+ }
+ ELSE
+ {
+ /* use TCX10 band config only if none of the channels is TCX20 */
+ sfbConf = &hCPE->hStereoMdct->stbParamsTCX10;
+ nsub = 2;
+ /* set resolution per subframe, subdivide again if subframe is TCX5 in both channels */
+ nsub2[0] = ( transform_type[0][0] == TCX_5 && transform_type[1][0] == TCX_5 ) ? 2 : 1;
+ nsub2[1] = ( transform_type[0][1] == TCX_5 && transform_type[1][1] == TCX_5 ) ? 2 : 1;
+ tcx_10_only = 1;
+ }
+
+ /* for subframes with only TCX5 in both channels number of coefficients is only half (in 2 quarterframes) */
+ numCoeffs[0] = ( nsub2[0] == 1 ) ? sfbConf->sfbOffset[sfbConf->sfbCnt] : sfbConf->sfbOffset[sfbConf->sfbCnt] / 2;
+ numCoeffs[1] = ( nsub2[1] == 1 ) ? sfbConf->sfbOffset[sfbConf->sfbCnt] : sfbConf->sfbOffset[sfbConf->sfbCnt] / 2;
+
+ /* initially, set pointers to input; if conversion occurs in (sub)frame, set to convertRes */
+ sig[0][0] = pTmp[0][0] = x[0][0];
+ sig[0][1] = pTmp[0][1] = x[0][1];
+ sig[1][0] = pTmp[1][0] = x[1][0];
+ sig[1][1] = pTmp[1][1] = x[1][1];
+
+ /* convert (sub)frames to higher frequency resolution */
+ FOR( ch = 0; ch < nChannels; ch++ )
+ {
+ FOR( k = 0; k < NB_DIV; k++ )
+ {
+ IF( transform_type[ch][k] == TCX_5 && nsub2[k] == 1 )
+ {
+ /* subframe is TCX5, but TCX10 or TCX20 in other channel -> convert channel with TCX5 to TCX10 resolution */
+ pTmp[ch][k] = sig[ch][k] = convertRes[ch] + k * frameSize / 2;
+ convert_coeffs_to_higher_res_fx( x[ch][k], x[ch][k] + frameSize / 4, pTmp[ch][k], frameSize / 4 );
+ }
+ }
+
+ IF( transform_type[ch][0] != TCX_20 && nsub == 1 )
+ {
+ /* TCX20 and TCX10 in same frame -> convert channel with TCX10 to TCX20 resolution */
+ sig[ch][0] = convertRes[ch];
+ convert_coeffs_to_higher_res_fx( pTmp[ch][0], pTmp[ch][1], sig[ch][0], frameSize / 2 );
+ }
+ }
+
+ /* MDST estimate */
+ FOR( ch = 0; ch < nChannels; ch++ )
+ {
+ FOR( k = 0; k < nsub; k++ )
+ {
+ FOR( l = 0; l < nsub2[k]; l++ )
+ {
+ // mdst[ch][k][l * numCoeffs[k]] = mdst[ch][k][( l + 1 ) * numCoeffs[k] - 1] = 0.f;
+ mdst[ch][k][l * numCoeffs[k]] = mdst[ch][k][( l + 1 ) * numCoeffs[k] - 1] = 0;
+ FOR( i = l * numCoeffs[k] + 1; i < ( l + 1 ) * numCoeffs[k] - 1; i++ )
+ {
+ mdst[ch][k][i] = sig[ch][k][i + 1] - sig[ch][k][i - 1];
+ }
+ }
+ }
+ }
+
+ /* compute and apply bandwise weigths for active downmix (similar to DFT Stereo) */
+ stop_tcx5 = 0;
+ FOR( b = 0; b < sfbConf->sfbCnt; b++ )
+ {
+ Word16 w[CPE_CHANNELS][4];
+
+ FOR( k = 0; k < nsub; k++ )
+ {
+ FOR( l = 0; l < nsub2[k]; l++ )
+ {
+ Word64 sum_nrg_L = 0, sum_nrg_R = 0;
+ Word64 dot_prod_real = 0, dot_prod_imag = 0;
+ Word32 sum_nrg_Mid, sum_abs, dot_prod_abs;
+
+ start = l * numCoeffs[k] + sfbConf->sfbOffset[b] / nsub2[k];
+ stop = l * numCoeffs[k] + sfbConf->sfbOffset[b + 1] / nsub2[k];
+
+ /* compute band energies and cross correlation */
+ FOR( i = start; i < stop; i++ )
+ {
+ sum_nrg_L = W_add( sum_nrg_L, W_add( W_mult_32_32( sig[0][k][i], sig[0][k][i] ), W_mult_32_32( mdst[0][k][i], mdst[0][k][i] ) ) );
+ sum_nrg_R = W_add( sum_nrg_R, W_add( W_mult_32_32( sig[1][k][i], sig[1][k][i] ), W_mult_32_32( mdst[1][k][i], mdst[1][k][i] ) ) );
+ dot_prod_real = W_add( dot_prod_real, W_add( W_mult_32_32( sig[0][k][i], sig[1][k][i] ), W_mult_32_32( mdst[0][k][i], mdst[1][k][i] ) ) );
+ dot_prod_imag = W_add( dot_prod_imag, W_sub( W_mult_32_32( mdst[0][k][i], sig[1][k][i] ), W_mult_32_32( sig[0][k][i], mdst[1][k][i] ) ) );
+ }
+
+ Word16 norm_sum_nrg_L = W_norm( sum_nrg_L );
+ Word16 norm_sum_nrg_R = W_norm( sum_nrg_R );
+ Word16 norm_dot_prod_real = W_norm( dot_prod_real );
+ Word16 norm_dot_prod_imag = W_norm( dot_prod_imag );
+
+ Word16 guard_bit = find_guarded_bits_fx( 4 );
+ Word16 min_norm = min( min( min( norm_sum_nrg_L, norm_sum_nrg_R ), norm_dot_prod_real ), norm_dot_prod_imag ) - guard_bit;
+ Word32 sum_nrg_L_32 = W_extract_h( W_shl( sum_nrg_L, min_norm ) );
+ Word32 sum_nrg_R_32 = W_extract_h( W_shl( sum_nrg_R, min_norm ) );
+ Word32 dot_prod_real_32 = W_extract_h( W_shl( dot_prod_real, min_norm ) );
+ Word32 dot_prod_imag_32 = W_extract_h( W_shl( dot_prod_imag, min_norm ) );
+
+ Word16 q_sum_nrg_L = 23 + min_norm - 32;
+ Word16 q_sum_nrg_R = 23 + min_norm - 32;
+ Word16 q_dot_prod_real = 23 + min_norm - 32;
+ Word16 q_dot_prod_imag = 23 + min_norm - 32;
+
+ Word16 E_sum_nrg_l = 31 - q_sum_nrg_L;
+ Word16 E_sum_nrg_R = 31 - q_sum_nrg_R;
+ Word16 E_dot_prod_abs = 31 - ( q_dot_prod_real * 2 - 31 );
+ Word16 E_sum_nrg_Mid = 31 - q_sum_nrg_L;
+ sum_nrg_Mid = max( 0, L_add( L_add( sum_nrg_L_32, sum_nrg_R_32 ), L_shl( dot_prod_real_32, 1 ) ) );
+ Word32 tmp_nrg_L = Sqrt32( sum_nrg_L_32, &E_sum_nrg_l );
+ Word32 tmp_nrg_R = Sqrt32( sum_nrg_R_32, &E_sum_nrg_R );
+ Word16 max_e_sum_abs = E_sum_nrg_l;
+ IF( E_sum_nrg_R > E_sum_nrg_l )
+ {
+ max_e_sum_abs = E_sum_nrg_R;
+ }
+ max_e_sum_abs = max_e_sum_abs + 1;
+ sum_abs = L_add( L_shr( tmp_nrg_L, max_e_sum_abs - E_sum_nrg_l ), L_shr( tmp_nrg_R, max_e_sum_abs - E_sum_nrg_R ) );
+ dot_prod_abs = Sqrt32( L_add( Mpy_32_32( dot_prod_real_32, dot_prod_real_32 ), Mpy_32_32( dot_prod_imag_32, dot_prod_imag_32 ) ), &E_dot_prod_abs );
+ Word32 num = L_add( L_shr( L_add( sum_nrg_L_32, sum_nrg_R_32 ), 1 ), L_shr( dot_prod_abs, ( 31 - E_dot_prod_abs ) - q_sum_nrg_L ) );
+ Word16 E_num = 31 - q_sum_nrg_L;
+ Word32 num_sqrt = Sqrt32( num, &E_num );
+
+ Word16 e_full_w = max_e_sum_abs;
+ IF( max_e_sum_abs < E_num )
+ {
+ e_full_w = E_num;
+ }
+ Word32 full_w_up;
+ IF( num_sqrt == 0 && sum_abs == 0 )
+ {
+ full_w_up = 6364; // 0.776887059 in Q13
+ }
+ ELSE IF( num_sqrt == 0 && sum_abs != 0 )
+ {
+ full_w_up = 5793; // 0.707106769 in Q13
+ }
+ ELSE
+ {
+ full_w_up = shr( divide3232( L_shr( num_sqrt, e_full_w - E_num ), L_shr( sum_abs, e_full_w - max_e_sum_abs ) ), 2 );
+ }
+
+ Word32 sum_nrg_Mid_sqrt = Sqrt32( sum_nrg_Mid, &E_sum_nrg_Mid );
+
+ Word16 e_full_down = max_e_sum_abs;
+ IF( max_e_sum_abs < E_sum_nrg_Mid )
+ {
+ e_full_down = E_sum_nrg_Mid;
+ }
+ Word32 full_w_down;
+ IF( sum_nrg_Mid_sqrt == 0 && sum_abs == 0 )
+ {
+ full_w_down = 6364;
+ }
+ ELSE IF( sum_nrg_Mid_sqrt == 0 && sum_abs != 0 )
+ {
+ full_w_down = 5793;
+ }
+ ELSE
+ {
+ full_w_down = L_shr( divide3232( L_shr( sum_nrg_Mid_sqrt, e_full_down - E_sum_nrg_Mid ), L_shr( sum_abs, e_full_down - max_e_sum_abs ) ), 1 );
+ }
+
+ IF( hCPE->hStereoMdct->reverse_dmx == 0 )
+ {
+ w[1][2 * k + l] = full_w_up;
+ w[0][2 * k + l] = add( w[1][2 * k + l], mult( 23170 /*sqrt(2.0f in Q14)*/, sub( 16384 /* 1.0f in Q14 */, full_w_down ) ) );
+ }
+ ELSE
+ {
+ w[0][2 * k + l] = full_w_up;
+ w[1][2 * k + l] = add( w[0][2 * k + l], mult( 23170 /*sqrt(2.0f in Q14)*/, sub( 16384 /* 1.0f in Q14 */, full_w_down ) ) );
+ }
+ }
+ }
+
+ /* apply weights to channels with their original frequency resolutions */
+ FOR( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ IF( transform_type[ch][0] == TCX_20 )
+ {
+ FOR( i = sfbConf->sfbOffset[b]; i < sfbConf->sfbOffset[b + 1]; i++ )
+ {
+ x[ch][0][i] = L_shl( Mpy_32_16_1( x[ch][0][i], w[ch][0] ), 2 );
+ }
+ }
+ ELSE
+ {
+ start = sfbConf->sfbOffset[b];
+ stop = sfbConf->sfbOffset[b + 1];
+ IF( !tcx_10_only ) /* TCX20 band config is used */
+ {
+ start /= 2;
+ stop /= 2;
+ }
+
+ FOR( k = 0; k < NB_DIV; k++ )
+ {
+ w_idx = ( nsub == 1 ) ? 0 : 2 * k;
+ IF( transform_type[ch][k] == TCX_10 )
+ {
+ FOR( i = start; i < stop; i++ )
+ {
+ x[ch][k][i] = L_shl( Mpy_32_16_1( x[ch][k][i], w[ch][w_idx] ), 2 );
+ }
+ }
+ ELSE /* TCX_5 */
+ {
+ start_tcx5 = stop_tcx5;
+ stop_tcx5 = ( stop + 1 ) / 2;
+
+ FOR( i = start_tcx5; i < stop_tcx5; i++ )
+ {
+ x[ch][k][i] = L_shl( Mpy_32_16_1( x[ch][k][i], w[ch][w_idx] ), 2 );
+ }
+
+ IF( nsub2[k] == 2 )
+ {
+ w_idx++;
+ }
+
+ FOR( i = start_tcx5; i < stop_tcx5; i++ )
+ {
+ x[ch][k][i + ( frameSize >> 2 )] = L_shl( Mpy_32_16_1( x[ch][k][i + ( frameSize >> 2 )], w[ch][w_idx] ), 2 );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * run_min_stats()
+ *
+ * run the minimum statistics noise estimation algorithm
+ * directly on the MDCT spectrum
+ *--------------------------------------------------------------------*/
+
+static void run_min_stats_fx(
+ Decoder_State **sts,
+ float *x[CPE_CHANNELS][NB_DIV] /* i/o: MDCT Spectrum */
+)
+{
+ int16_t ch, will_estimate_noise_on_channel[CPE_CHANNELS], save_VAD[CPE_CHANNELS];
+ float power_spec[L_FRAME16k];
+ float *spec_in;
+
+ /* Check if the minimum statistics would run on the respective channels. They are run on inactive TCX20 channels */
+ will_estimate_noise_on_channel[0] = sts[0]->core == TCX_20_CORE && !sts[0]->VAD;
+ will_estimate_noise_on_channel[1] = sts[1]->core == TCX_20_CORE && !sts[1]->VAD;
+
+ save_VAD[0] = sts[0]->VAD;
+ save_VAD[1] = sts[1]->VAD;
+
+ /* The first loop calculates the power spectra needed in the minimum statistics (MS) noise estimation. This is only needed if the MS
+ would run at all on at least one of the channels. If they run on both channels, we need to calculate two distinct power spectra
+ for the two different channels. If they would only run on one of the channels, the VAD of the other one is patched so that the MS will
+ still run. This other channel then uses the power spectrum of the other channel to run the MS. This is done to keep continuity and synchronicity
+ between the two noise levels and silently assumes that the background noise is somehow diffuse and at leas partly shared between the channels */
+ for ( ch = 0; ch < CPE_CHANNELS; ch++ )
+ {
+ Decoder_State *st;
+ st = sts[ch];
+
+ if ( !sts[0]->bfi && ( will_estimate_noise_on_channel[0] || will_estimate_noise_on_channel[1] ) )
+ {
+ /* if noise estimation is expected to run on this channel, compute power spectrum from it,
+ otherwise, use other channel's signal */
+ if ( will_estimate_noise_on_channel[ch] )
+ {
+ spec_in = &x[ch][0][0];
+ }
+ else
+ {
+ spec_in = &x[( ch + 1 ) % 2][0][0];
+ /* patch VAD to zero so that estimation runs, will later be restored */
+ st->VAD = 0;
+ }
+
+ /* Compute power spectrum twice if estimation will run on both channels. If only on one channel, it is
+ computed only once (for ch == 0) and not again in the second run sive the outcome will be the same anyway */
+ if ( ( will_estimate_noise_on_channel[0] == will_estimate_noise_on_channel[1] ) || ch == 0 )
+ {
+ /* calculate power spectrum from MDCT coefficients and estimated MDST coeffs */
+ power_spec[0] = spec_in[0] * spec_in[0];
+ power_spec[L_FRAME16k - 1] = spec_in[L_FRAME16k - 1] * spec_in[L_FRAME16k - 1];
+ for ( int16_t i = 1; i < L_FRAME16k - 1; i++ )
+ {
+ float mdst;
+ mdst = spec_in[i + 1] - spec_in[i - 1];
+ power_spec[i] = spec_in[i] * spec_in[i] + mdst * mdst;
+ }
+ }
+
+ noisy_speech_detection_flt( st->hFdCngDec, st->VAD && st->m_frame_type == ACTIVE_FRAME, power_spec );
+
+ st->hFdCngDec->hFdCngCom->likelihood_noisy_speech_flt = 0.99f * st->hFdCngDec->hFdCngCom->likelihood_noisy_speech_flt + 0.01f * (float) st->hFdCngDec->hFdCngCom->flag_noisy_speech;
+
+ st->lp_noise_float = st->hFdCngDec->lp_noise_float;
+ }
+
+ if ( will_estimate_noise_on_channel[0] || will_estimate_noise_on_channel[1] || st->bfi )
+ {
+ ApplyFdCng_flt( NULL, st->bfi ? NULL : power_spec, NULL, NULL, st, st->bfi, 0 );
+ }
+
+ /* restore VAD (see above) */
+ st->VAD = save_VAD[ch];
+ }
+
+ return;
+}
+#endif // IVAS_FLOAT_FIXED
diff --git a/lib_dec/ivas_stereo_mdct_stereo_dec.c b/lib_dec/ivas_stereo_mdct_stereo_dec.c
index 207cf5a2978f41dc0bdb77d5233cf835f91c2f7d..d4f4b23e53cbf20f36f8c33e93ca2ac81044baff 100644
--- a/lib_dec/ivas_stereo_mdct_stereo_dec.c
+++ b/lib_dec/ivas_stereo_mdct_stereo_dec.c
@@ -753,6 +753,49 @@ void inverseMS(
* Initialize MDCT stereo decoder configuration
*-------------------------------------------------------------------*/
+#ifdef IVAS_FLOAT_FIXED
+void initMdctStereoDecData_fx(
+ STEREO_MDCT_DEC_DATA *hStereoMdct, /* i/o: mdct stereo parameters structure */
+ const Word16 igf, /* i : flag indicating IGF activity */
+ const H_IGF_GRID igfGrid, /* i : IGF grid configuration */
+ const Word32 element_brate, /* i : element bitrate */
+ const Word16 bwidth /* i : audio bandwidth */
+)
+{
+ Word16 tcx_coded_lines;
+
+ tcx_coded_lines = getNumTcxCodedLines( bwidth );
+
+ /*Initialize sfb parameteres for TCX20 */
+ stereo_mdct_init_bands_fx( tcx_coded_lines, TCX_20_CORE, element_brate, igf, &igfGrid[IGF_GRID_LB_NORM], &hStereoMdct->stbParamsTCX20.sfbOffset[0], &hStereoMdct->stbParamsTCX20.sfbCnt );
+
+ /*Initialize sfb parameteres for TCX10 */
+ stereo_mdct_init_bands_fx( tcx_coded_lines, TCX_10_CORE, element_brate, igf, &igfGrid[IGF_GRID_LB_SHORT], &hStereoMdct->stbParamsTCX10.sfbOffset[0], &hStereoMdct->stbParamsTCX10.sfbCnt );
+
+ /*Initialize sfb parameteres for transition frames */
+ stereo_mdct_init_bands_fx( tcx_coded_lines, -1, element_brate, igf, &igfGrid[IGF_GRID_LB_TRAN], &hStereoMdct->stbParamsTCX20afterACELP.sfbOffset[0], &hStereoMdct->stbParamsTCX20afterACELP.sfbCnt );
+
+ IF( igf )
+ {
+ /* calculate the igf start band from the igf start line */
+ stereo_mdct_init_igf_start_band_fx( &( hStereoMdct->stbParamsTCX20 ), 16384 /*1 Q14*/, bwidth, element_brate );
+ stereo_mdct_init_igf_start_band_fx( &( hStereoMdct->stbParamsTCX10 ), 8192 /*0.50f Q14*/, bwidth, element_brate );
+ stereo_mdct_init_igf_start_band_fx( &( hStereoMdct->stbParamsTCX20afterACELP ), 20480 /*1.25 Q14*/, bwidth, element_brate );
+ }
+ ELSE
+ {
+ hStereoMdct->stbParamsTCX20.sfbIgfStart = -1;
+ hStereoMdct->stbParamsTCX10.sfbIgfStart = -1;
+ hStereoMdct->stbParamsTCX20afterACELP.sfbIgfStart = -1;
+ hStereoMdct->stbParamsTCX10.nBandsStereoCore = hStereoMdct->stbParamsTCX10.sfbCnt;
+ hStereoMdct->stbParamsTCX20.nBandsStereoCore = hStereoMdct->stbParamsTCX20.sfbCnt;
+ hStereoMdct->stbParamsTCX20afterACELP.nBandsStereoCore = hStereoMdct->stbParamsTCX20afterACELP.sfbCnt;
+ }
+
+ return;
+}
+#endif
+
void initMdctStereoDecData(
STEREO_MDCT_DEC_DATA *hStereoMdct, /* i/o: mdct stereo parameters structure */
const int16_t igf, /* i : flag indicating IGF activity */
diff --git a/lib_dec/ivas_tcx_core_dec.c b/lib_dec/ivas_tcx_core_dec.c
index 3dee78be81ed2ccf70c5d919370a5b9ddeae973f..48ff4486db0e668307d2d47cea739a617e70a468 100644
--- a/lib_dec/ivas_tcx_core_dec.c
+++ b/lib_dec/ivas_tcx_core_dec.c
@@ -61,6 +61,89 @@ static void stereo_tcx_dec_mode_switch_reconf_ivas_fx( Decoder_State *st, const
*
* Initialize stereo TCX decoder
*-------------------------------------------------------------*/
+#ifdef IVAS_FLOAT_FIXED
+void stereo_tcx_init_dec_fx(
+ Decoder_State *st, /* i/o: decoder state structure */
+ const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0)*/
+ const Word16 last_element_mode /* i : element mode of previous frame */
+)
+{
+ TCX_LTP_DEC_HANDLE hTcxLtpDec = st->hTcxLtpDec;
+ TCX_DEC_HANDLE hTcxDec = st->hTcxDec;
+
+ st->rate_switching_init = 0;
+ st->m_frame_type = ACTIVE_FRAME;
+ st->core_brate = st->total_brate;
+
+ /*sampling rate*/
+ st->sr_core = getCoreSamplerateMode2( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->flag_ACELP16k, st->rf_flag, st->is_ism_format );
+ st->fscale = sr2fscale( st->sr_core );
+
+ /*frame size*/
+ st->L_frame = (Word16) ( st->sr_core / FRAMES_PER_SEC );
+ hTcxDec->L_frameTCX = (Word16) ( st->output_Fs / FRAMES_PER_SEC );
+
+ IF( ( st->L_frame == L_FRAME16k && ( st->bits_frame_nominal * FRAMES_PER_SEC ) <= MAX_ACELP_BRATE ) || ( st->tcxonly && ( st->sr_core == 32000 || st->sr_core == INT_FS_16k ) ) )
+ {
+ st->nb_subfr = NB_SUBFR16k;
+ }
+ ELSE
+ {
+ st->nb_subfr = NB_SUBFR;
+ }
+
+ /*TCX tools*/
+ st->hTcxCfg->ctx_hm = getCtxHm( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->rf_flag );
+ st->hTcxCfg->resq = getResq( st->bits_frame_nominal * FRAMES_PER_SEC );
+ hTcxDec->tcx_lpc_shaped_ari = getTcxLpcShapedAri( st->bits_frame_nominal * FRAMES_PER_SEC, st->rf_flag, st->element_mode );
+ st->igf = getIgfPresent_fx( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->bwidth, st->rf_flag );
+
+ IF( st->element_mode != EVS_MONO )
+ {
+ st->hTcxCfg->fIsTNSAllowed = getTnsAllowed( st->bits_frame_nominal * FRAMES_PER_SEC, st->igf, st->element_mode );
+ }
+ IF( hTcxLtpDec != NULL )
+ {
+ hTcxLtpDec->tcxltp = getTcxLtp( st->sr_core );
+ }
+
+ IF( st->element_mode == IVAS_SCE )
+ {
+ st->tcxonly = getTcxonly_fx( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, MCT_flag, st->is_ism_format );
+
+ /* LPC quantization */
+ IF( st->sr_core <= INT_FS_16k && st->tcxonly == 0 )
+ {
+ st->lpcQuantization = 1;
+ }
+ ELSE
+ {
+ st->lpcQuantization = 0;
+ }
+
+ IF( st->tcxonly == 0 )
+ {
+ st->numlpc = 1;
+ }
+ ELSE
+ {
+ st->numlpc = 2;
+ }
+ }
+
+ IF( ( st->bits_frame_nominal != st->last_bits_frame_nominal ) ||
+ ( st->bwidth != st->last_bwidth ) ||
+ ( st->last_core != TCX_20_CORE && st->last_core != TCX_10_CORE && !( st->prev_bfi == 1 && st->last_core == ACELP_CORE && st->last_con_tcx == 1 ) ) ||
+ ( st->idchan == 1 && st->element_mode == IVAS_CPE_MDCT && last_element_mode != IVAS_CPE_MDCT ) )
+ {
+ /*re-initialization*/
+ // Need to replace this with fix call
+ stereo_tcx_dec_mode_switch_reconf( st, MCT_flag, last_element_mode );
+ }
+
+ return;
+}
+#endif
void stereo_tcx_init_dec(
Decoder_State *st, /* i/o: decoder state structure */