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 */