diff --git a/Makefile b/Makefile
index b148e1a5045dcbb386c0da0606f1dc9e7e5c4386..311cb8b9bf516dd249a464a155eed6541b11e834 100644
--- a/Makefile
+++ b/Makefile
@@ -117,7 +117,7 @@ CFLAGS += $(foreach DIR,$(SRC_DIRS),-I$(DIR))
VPATH = $(SRC_DIRS)
# Filter out files that are not part of the build
-EXCLUDED_FILES = SNR_calc_fx.c
+EXCLUDED_FILES =
###############################################################################
diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj
index e1fbbd2ec18fe79d2130fcffaa5065431c6cdd3a..c885d6c395e6238edc6481f8cf4b56faab2c1b21 100644
--- a/Workspace_msvc/lib_com.vcxproj
+++ b/Workspace_msvc/lib_com.vcxproj
@@ -400,6 +400,7 @@
+
diff --git a/Workspace_msvc/lib_com.vcxproj.filters b/Workspace_msvc/lib_com.vcxproj.filters
index d5223e2b3876cc19db79a3f4bc29346deef2ccc4..7f01afc95ba20bbdacada20f0926711d8af5010f 100644
--- a/Workspace_msvc/lib_com.vcxproj.filters
+++ b/Workspace_msvc/lib_com.vcxproj.filters
@@ -281,108 +281,108 @@
common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
-
- common_all_c
+
+ common_all_c
-
- common_all_c
+
+ common_all_c
-
- common_all_c
+
+ common_all_c
- common_all_c
+ common_all_c
- common_all_c
+ common_all_c
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
-
-
+
+
common_all_c
@@ -402,6 +402,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -474,6 +592,9 @@
+
+ common_h
+
diff --git a/Workspace_msvc/lib_enc.vcxproj b/Workspace_msvc/lib_enc.vcxproj
index e033d4a0e14d262bea06a66626c4d5a48d6987a2..384fb8bb1855a74c55dcab5b3087c521a642062f 100644
--- a/Workspace_msvc/lib_enc.vcxproj
+++ b/Workspace_msvc/lib_enc.vcxproj
@@ -140,8 +140,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -275,12 +347,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -322,32 +435,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Workspace_msvc/lib_enc.vcxproj.filters b/Workspace_msvc/lib_enc.vcxproj.filters
index dfe3a1e1151f43963a6938cef9697488a726f2ac..2476cdb6cf5fa921fe54ffb28616676ae9849a81 100644
--- a/Workspace_msvc/lib_enc.vcxproj.filters
+++ b/Workspace_msvc/lib_enc.vcxproj.filters
@@ -611,6 +611,408 @@
enc_all_c
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_all_c
+
+
+ enc_evs_c
+
+
+ enc_evs_c
+
@@ -626,6 +1028,12 @@
enc_h
+
+ enc_h
+
+
+ enc_h
+
diff --git a/apps/encoder.c b/apps/encoder.c
index c255170a78fcdd028e9a76265f475db64190547d..fdecc217a5f90f512c5507f3aacbdb0dcc726ae1 100644
--- a/apps/encoder.c
+++ b/apps/encoder.c
@@ -364,8 +364,7 @@ int main(
break;
case IVAS_ENC_INPUT_SBA:
if ( ( error = IVAS_ENC_ConfigureForAmbisonics( hIvasEnc, arg.inputFs, totalBitrate, arg.max_bwidth_user, bandwidth, arg.dtxConfig, arg.inputFormatConfig.sba.order, arg.inputFormatConfig.sba.isPlanar,
- arg.pca
- ) ) != IVAS_ERR_OK )
+ arg.pca ) ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nIVAS_ENC_ConfigureForAmbisonics failed: %s\n\n", IVAS_ENC_GetErrorMessage( error ) );
goto cleanup;
@@ -414,12 +413,13 @@ int main(
/*------------------------------------------------------------------------------------------*
* Open input audio file
*------------------------------------------------------------------------------------------*/
-
- if ( AudioFileReader_open( &audioReader, arg.inputWavFilename ) != IVAS_ERR_OK )
+ short isInputRawFile;
+ if ( AudioFileReader_open( &audioReader, arg.inputWavFilename, &isInputRawFile ) != IVAS_ERR_OK )
{
fprintf( stderr, "\nCan't open %s\n\n", arg.inputWavFilename );
goto cleanup;
}
+ set_raw_file_flag( hIvasEnc, isInputRawFile );
/* Validate input sampling rate */
int32_t inFileSampleRate = 0;
@@ -1026,7 +1026,6 @@ static bool parseCmdlIVAS_enc(
{
i++;
arg->inputFormat = IVAS_ENC_INPUT_STEREO;
-
}
else if ( strcmp( argv_to_upper, "-BINAURAL" ) == 0 )
{
@@ -1716,5 +1715,4 @@ static bool readBitrate(
}
-
#undef WMC_TOOL_SKIP
diff --git a/apps/renderer.c b/apps/renderer.c
index dabddd8ed5967e4ff4c85bd32c4ccf14be1cd3eb..10e5f249c9ce4c6032b7d792912acaca74f59eb4 100644
--- a/apps/renderer.c
+++ b/apps/renderer.c
@@ -780,8 +780,8 @@ int main(
exit( -1 );
}
}
-
- if ( AudioFileReader_open( &audioReader, audioFilePath ) != IVAS_ERR_OK )
+ short ignore;
+ if ( AudioFileReader_open( &audioReader, audioFilePath, &ignore ) != IVAS_ERR_OK )
{
fprintf( stderr, "Error opening file: %s\n", audioFilePath );
exit( -1 );
diff --git a/lib_com/basop_util.h b/lib_com/basop_util.h
index 3e18edbb1d61dc632de973c4bf59150506a95785..f8a68a50980dbeca604048dc44e673a6b1c3f2eb 100644
--- a/lib_com/basop_util.h
+++ b/lib_com/basop_util.h
@@ -52,6 +52,9 @@
#define modDiv2( x ) sub( x, shl( shr( x, 1 ), 1 ) )
#define modDiv8( x ) L_sub( x, L_shl( L_shr( x, 3 ), 3 ) )
+//basop_mpy.h
+#define MUL_F(A,B) Mpy_32_16_1((A),(B))
+
#ifndef CHEAP_NORM_SIZE
#define CHEAP_NORM_SIZE 161
#endif
diff --git a/lib_com/bitstream_fx.c b/lib_com/bitstream_fx.c
index 8801e4ebdea6cb1ae9058d5993d9662ee97764d2..cf40862d30c78aeba8a6a3c00968fa2d10622384 100644
--- a/lib_com/bitstream_fx.c
+++ b/lib_com/bitstream_fx.c
@@ -36,6 +36,7 @@
#include
#include
+#include
#include "options.h"
#include "ivas_cnst.h" /* Common constants */
#include "prot_fx2.h" /* Function prototypes */
@@ -657,6 +658,110 @@ void write_indices_fx(
return;
}
+/*-------------------------------------------------------------------*
+ * write_indices_buf_fx()
+ *
+ * Write the buffer of indices to a file
+ *-------------------------------------------------------------------*/
+
+void write_indices_buf_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
+ UWord16 *out_buf, /* i : output bitstream buf */
+ UWord8 *pFrame, /* i: byte array with bit packet and byte aligned coded speech data */
+ Word16 pFrame_size, /* i: size of the binary encoded access unit [bits] */
+ UWord16 *num_bits )
+{
+ Word16 i, k;
+ Word16 stream[2 + MAX_BITS_PER_FRAME], *pt_stream;
+ Word32 mask;
+ UWord8 header;
+ Word16 isAmrWb = 0;
+
+ if ( st_fx->bitstreamformat == G192 )
+ {
+ /*-----------------------------------------------------------------*
+ * Encode Sync Header and Frame Length
+ *-----------------------------------------------------------------*/
+ pt_stream = stream;
+ for ( i = 0; i < ( 2 + MAX_BITS_PER_FRAME ); ++i )
+ {
+ stream[i] = 0;
+ }
+ //*pt_stream++ = (Word16) SYNC_GOOD_FRAME;
+ //*pt_stream++ = hBstr->nb_bits_tot_fx;
+ *num_bits = hBstr->nb_bits_tot_fx;
+
+ /*----------------------------------------------------------------*
+ * Bitstream packing (conversion of individual indices into a serial stream)
+ * Writing the serial stream into file
+ *----------------------------------------------------------------*/
+ for ( i = 0; i < MAX_NUM_INDICES; i++ )
+ {
+ if ( hBstr->ind_list_fx[i].nb_bits != -1 )
+ {
+ /* mask from MSB to LSB */
+ mask = 1 << ( hBstr->ind_list_fx[i].nb_bits - 1 );
+
+ /* write bit by bit */
+ for ( k = 0; k < hBstr->ind_list_fx[i].nb_bits; k++ )
+ {
+ if ( hBstr->ind_list_fx[i].value & mask )
+ {
+ //*pt_stream++ = G192_BIN1;
+ *pt_stream++ = 1;
+ }
+ else
+ {
+ //*pt_stream++ = G192_BIN0;
+ *pt_stream++ = 0;
+ }
+
+ mask >>= 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Create and write ToC header */
+ /* qbit always set to 1 on encoder side for AMRWBIO , no qbit in use for EVS, but set to 0(bad) */
+ header = (UWord8) ( st_fx->Opt_AMR_WB_fx << 5 | st_fx->Opt_AMR_WB_fx << 4 | rate2EVSmode( hBstr->nb_bits_tot_fx * 50, &isAmrWb ) );
+ // fwrite(&header, sizeof(UWord8), 1, file);
+ memcpy( out_buf, &header, sizeof( UWord8 ) );
+ *num_bits += sizeof( UWord8 );
+ /* Write speech bits */
+ // fwrite(pFrame, sizeof(UWord8), (pFrame_size + 7) >> 3, file);
+ memcpy( out_buf, pFrame, sizeof( UWord8 ) * ( ( pFrame_size + 7 ) >> 3 ) );
+ *num_bits += sizeof( UWord8 ) * ( ( pFrame_size + 7 ) >> 3 );
+ }
+
+ /* Clearing of indices */
+ FOR( i = 0; i < MAX_NUM_INDICES; i++ )
+ {
+ hBstr->ind_list_fx[i].nb_bits = -1;
+ move16();
+ }
+
+
+ if ( st_fx->bitstreamformat == G192 )
+ {
+ /* write the serial stream into file */
+ // fwrite(stream, sizeof(unsigned short), 2 + stream[1], file);
+ // FILE *ftemp = fopen( "./output/bitstreams/out.COD", "ab" );
+ // fwrite( stream, sizeof( unsigned short ), 2 + stream[1], ftemp );
+ // fclose( ftemp );
+ memcpy( out_buf, stream, sizeof( unsigned short ) * ( *num_bits ) );
+ //*num_bits += sizeof( unsigned short ) * ( 2 + stream[1] );
+ }
+ /* reset index pointers */
+ hBstr->nb_bits_tot_fx = 0;
+ hBstr->next_ind_fx = 0;
+ hBstr->last_ind_fx = -1;
+
+ return;
+}
+
/*-------------------------------------------------------------------*
* indices_to_serial()
*
diff --git a/lib_com/cldfb_evs.c b/lib_com/cldfb_evs.c
index 63b3030fae3d9ed303e39c5602988a81f839ab58..7f17f4f15926bcb3053d6e10575273375a448fc2 100644
--- a/lib_com/cldfb_evs.c
+++ b/lib_com/cldfb_evs.c
@@ -1183,7 +1183,7 @@ AnalysisPostSpectrumScaling_Fx (HANDLE_CLDFB_FILTER_BANK cldfbBank, /*!< Handle
*--------------------------------------------------------------------*/
void analysisCldfbEncoder_fx(
- Encoder_State *st_fx, /* i/o: encoder state structure */
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
const Word16 *timeIn,
Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
@@ -1213,7 +1213,7 @@ void analysisCldfbEncoder_fx(
/* perform analysis */
cldfbAnalysisFiltering (
- st_fx->cldfbAnaEnc,
+ st_fx->cldfbAna_Fx,
ppBuf_Real,
ppBuf_Imag,
scale,
@@ -1228,7 +1228,7 @@ void analysisCldfbEncoder_fx(
/* get 16bit respresentation */
AnalysisPostSpectrumScaling_Fx (
- st_fx->cldfbAnaEnc,
+ st_fx->cldfbAna_Fx,
ppBuf_Real,
ppBuf_Imag,
ppBuf_Real16,
@@ -1243,8 +1243,8 @@ void analysisCldfbEncoder_fx(
ppBuf_Real16,
ppBuf_Imag16,
enerScale.lb_scale16,
- st_fx->cldfbAnaEnc->no_channels,
- st_fx->cldfbAnaEnc->no_col,
+ st_fx->cldfbAna_Fx->no_channels,
+ st_fx->cldfbAna_Fx->no_col,
&st_fx->currEnergyHF_fx,
&st_fx->currEnergyHF_e_fx,
enerBuffSum,
diff --git a/lib_com/cnst.h b/lib_com/cnst.h
index 4e1d2e47a0d735dc0c359c85366faa40e2f1e0de..6296e2fc1bb8d9666f8bf071a657aabcf03ac698 100644
--- a/lib_com/cnst.h
+++ b/lib_com/cnst.h
@@ -483,7 +483,12 @@ enum
IND_STEREO_ICBWE_MSFLAG,
IND_SHB_ENER_SF,
IND_SHB_RES_GS,
- IND_SHB_VF = IND_SHB_RES_GS + 5,
+ IND_SHB_RES_GS1,
+ IND_SHB_RES_GS2,
+ IND_SHB_RES_GS3,
+ IND_SHB_RES_GS4,
+ IND_SHB_RES_GS5,
+ IND_SHB_VF,
IND_SHB_LSF,
IND_SHB_MIRROR = IND_SHB_LSF + 5,
IND_SHB_GRID,
@@ -1457,6 +1462,7 @@ enum
#define L_SHB_TRANSITION_LENGTH ( 2 * NS2SA( 48000, DELAY_BWE_TOTAL_NS ) )
+#define ACELP_LOOK_12k8 NS2SA(INT_FS_FX, ACELP_LOOK_NS) /* SHB Low delay look-ahead at 12.8kHz */
#define NUM_BITS_SHB_SubGain 6
#define NUM_BITS_SHB_FrameGain 6
@@ -2946,6 +2952,7 @@ extern const Word16 Idx2Freq_Tbl[];
#define L_NEXT_MAX_12k8 112 /* maximum encoder lookahead at 12k8Hz */
#define L_PAST_MAX_12k8 144 /* maximum encoder past samples at 12k8Hz */
#define L_DIV 256 /* 20ms frame size (ACELP or short TCX frame) */
+#define L_DIV_MAX 320
//tbs_vase.c
@@ -2954,5 +2961,12 @@ extern const Word16 Idx2Freq_Tbl[];
#define FS_48K_IN_NS_Q31 103079
#define FS_32K_IN_NS_Q31 68719
#define FS_16K_IN_NS_Q31 34360
+
+typedef enum
+{
+ MCT_CHAN_MODE_REGULAR,
+ MCT_CHAN_MODE_LFE,
+ MCT_CHAN_MODE_IGNORE
+} MCT_CHAN_MODE;
/* clang-format on */
#endif /* CNST_H */
diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h
index b47dcb65a27002648ef5ace79feaacf60879b8bd..a2fd290ddf48c175852ed05d86ccb12ebc3755e7 100644
--- a/lib_com/ivas_cnst.h
+++ b/lib_com/ivas_cnst.h
@@ -1320,11 +1320,11 @@ typedef enum
#define MCT_NUM_BLOCK_DATA_BITS 4
-typedef enum
+/*typedef enum
{
MCT_CHAN_MODE_REGULAR,
MCT_CHAN_MODE_IGNORE
-} MCT_CHAN_MODE;
+} MCT_CHAN_MODE;*/
/*----------------------------------------------------------------------------------*
diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h
index a629e1a6ad145622bf93f713d3e3e1dd2a5e23f5..7db57ae2a045e0f2f62e7e0f68ba14f6c5c4eb52 100644
--- a/lib_com/ivas_prot.h
+++ b/lib_com/ivas_prot.h
@@ -92,6 +92,11 @@ ivas_error create_sce_enc(
const int32_t element_brate /* i : element bitrate */
);
+ivas_error create_evs_sce_enc(
+ Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */
+ const int16_t sce_id /* i : SCE # identifier */
+);
+
ivas_error create_cpe_enc(
Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */
const int16_t cpe_id, /* i : CPE # identifier */
diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h
index e8d67304ea58b2066f29525ae6c8adf9d3a5174c..480d3dd1444e2ce48ce025d99ba6e815d6a95848 100644
--- a/lib_com/ivas_prot_fx.h
+++ b/lib_com/ivas_prot_fx.h
@@ -721,4 +721,4 @@ ivas_error ivas_ls_custom_output_init_fx(
ivas_error ivas_ls_custom_open_fx(
LSSETUP_CUSTOM_HANDLE *hLsSetupCustom /* o : Custom loudspeaker setup handle */
);
-#endif
\ No newline at end of file
+#endif
diff --git a/lib_com/lsf_tools_fx.c b/lib_com/lsf_tools_fx.c
index 99171912ddfe3d37424ed6b8c8aab6c7b4a8390e..bbcfab6cf687a33fa5503313631da4097596ce82 100644
--- a/lib_com/lsf_tools_fx.c
+++ b/lib_com/lsf_tools_fx.c
@@ -2648,7 +2648,7 @@ Word16 qlsf_ARSN_tcvq_Dec_16k_fx(
/*=======================================================================*/
void lsf_syn_mem_backup_fx(
- Encoder_State *st_fx, /* i: state structure */
+ Encoder_State_fx *st_fx, /* i: state structure */
Word16 *btilt_code_fx, /* i: tilt code */
Word32 *gc_threshold_fx, /* i: */
Word16 *clip_var_bck_fx, /* o: */
@@ -2785,7 +2785,7 @@ void lsf_update_memory(
/* _ None */
/*=======================================================================*/
void lsf_syn_mem_restore_fx(
- Encoder_State *st_fx, /* o: state structure */
+ Encoder_State_fx *st_fx, /* o: state structure */
Word16 btilt_code_fx, /* i: */
Word32 gc_threshold_fx, /* i: */
Word16 *clip_var_bck_fx, /* i: */
diff --git a/lib_com/math_op.h b/lib_com/math_op.h
index fe5a85a928ec56db4c7bbd8c1e49a023f94092f6..28d72147f6dbeb381cec75263582a6ffbb5fbd1b 100644
--- a/lib_com/math_op.h
+++ b/lib_com/math_op.h
@@ -44,5 +44,12 @@ Word16 Frac_sqrt( /* o : Square root if input */
Word16 i_mult2 (Word16 a, Word16 b);
+Word32 Dot_product12_o( /* (o) Q31: normalized result (1 < val <= -1) */
+ const Word16 x[], /* (i) 12bits: x vector */
+ const Word16 y[], /* (i) 12bits: y vector */
+ const Word16 lg, /* (i) : vector length */
+ Word16* exp, /* (o) : exponent of result (0..+30) */
+ Flag* Overflow_out /* o : propagating the Overflow flag to upper level */
+);
diff --git a/lib_com/options.h b/lib_com/options.h
index 392abbe6a059182e78cbac62bc7814167232eb66..099a285701e233bba166665ae23335b664ea775b 100644
--- a/lib_com/options.h
+++ b/lib_com/options.h
@@ -88,11 +88,11 @@
#define BE_FIX_832_ASAN_ERROR_EFAP_OSBA /* FhG: issue #832: fix ASAN error caused by re-allocating EFAP memories in OSBA*/
#define NONBE_FIX_819_DOUBLE_PREC_COMB_FORMATS /* VA: issue 820: Double precision arithmetic in combined formats */
#define NONBE_FIX_849_OMASA_BFI_CRASH /* VA: issue 849: fix OMASA 2TC and FEC crashes */
-
#define IVAS_FLOAT_FIXED
//#define DEBUGGING
//#define DBG_WAV_WRITER
#define EVS_FLOAT
+#define EVS_FLOAT_ENC
//#define DUMPS_ENABLED
#define FIX_667_DISABLE_INITIAL_PLC_SUPPRESSION
#define IVAS_CNST
diff --git a/lib_com/parameter_bitmaping.c b/lib_com/parameter_bitmaping.c
index 718d0966d7f2a796e220657a1564431bc49d6377..162f3927d80d5264f8a701c102e58ed71e653526 100644
--- a/lib_com/parameter_bitmaping.c
+++ b/lib_com/parameter_bitmaping.c
@@ -39,6 +39,7 @@
#include "options.h"
#include "stat_com.h"
#include "prot.h"
+#include "prot_fx2.h"
#include "wmc_auto.h"
@@ -56,6 +57,25 @@ static int16_t PutIntoBitstream( const int16_t **pStream, TEncodeValue EncodeVal
return value;
}
+/** Put nBits long encoded value from *pStream into bitstream. Using the function EncodeValue for encoding. */
+static Word16 PutIntoBitstream_fx(
+ const Word16 **pStream,
+ TEncodeValue EncodeValue,
+ Word16 index,
+ BSTR_ENC_HANDLE hBstr,
+ const Word16 nBits )
+{
+ Word16 value;
+ Word16 codedValue;
+
+ move16();
+ value = *( *pStream )++;
+ codedValue = EncodeValue( value, index );
+
+ push_next_indice_fx( hBstr, codedValue, nBits );
+
+ return value;
+}
/** Get nBits long value from bitstream into *pStream. */
static int16_t GetFromBitstream(
@@ -272,6 +292,72 @@ void WriteToBitstream(
return;
}
+void WriteToBitstream_fx(
+ ParamsBitMap const *paramsBitMap,
+ const Word16 nArrayLength,
+ const Word16 **pStream,
+ Word16 *pnSize,
+ BSTR_ENC_HANDLE hBstr,
+ Word16 *pnBits )
+{
+ Word16 index;
+ Word16 iParam, nParams;
+
+
+ assert( ( paramsBitMap != NULL ) && ( nArrayLength > 0 ) && ( pStream != NULL ) && ( pnSize != NULL ) && ( hBstr != NULL ) && ( pnBits != NULL ) );
+ nParams = paramsBitMap->nParams;
+
+ FOR( index = 0; index < nArrayLength; index++ )
+ {
+
+ FOR( iParam = 0; iParam < nParams; iParam++ )
+ {
+ ParamBitMap const *param;
+ Word16 nBits;
+ /* If a function for encoding/decoding value is defined than it should take care of 0 */
+ Word16 fShiftValue;
+ TEncodeValue EncodeValue;
+ Word16 value;
+
+ move16();
+ param = ¶msBitMap->params[iParam];
+
+ move16();
+ nBits = param->nBits;
+ IF( param->nBits == 0 )
+ {
+ nBits = param->GetNumberOfBits( **pStream, index );
+ }
+
+ test();
+ test();
+ fShiftValue = s_and( param->fZeroAllowed == 0, param->EncodeValue == NULL );
+ move16();
+ EncodeValue = param->EncodeValue;
+ if ( param->EncodeValue == NULL )
+ {
+ move16();
+ EncodeValue = &FixedWidthEncoding;
+ }
+ value = PutIntoBitstream_fx( pStream, EncodeValue, index, hBstr, nBits );
+ if ( fShiftValue )
+ {
+ value = add( value, 1 );
+ }
+
+ move16();
+ *pnSize = add( *pnSize, 1 );
+ move16();
+ *pnBits = add( *pnBits, nBits );
+
+ IF( ( param->pSubParamBitMap != NULL ) && ( value > 0 ) )
+ {
+ WriteToBitstream_fx( param->pSubParamBitMap, value, pStream, pnSize, hBstr, pnBits );
+ }
+ }
+ }
+}
+
void ReadFromBitstream(
ParamsBitMap const *paramsBitMap,
diff --git a/lib_com/prot.h b/lib_com/prot.h
index 71fbd33767ca0f34dbf6a00fc641cfe2761042c1..12f67086e25f377e7f88d45195596d5a50d1fb65 100644
--- a/lib_com/prot.h
+++ b/lib_com/prot.h
@@ -8868,6 +8868,14 @@ void WriteToBitstream(
BSTR_ENC_HANDLE hBstr,
int16_t *pnBits );
+void WriteToBitstream_fx(
+ ParamsBitMap const *paramsBitMap,
+ const Word16 nArrayLength,
+ const Word16 **pStream,
+ Word16 *pnSize,
+ BSTR_ENC_HANDLE hBstr,
+ Word16 *pnBits );
+
void ReadFromBitstream(
ParamsBitMap const *paramsBitMap,
const int16_t nArrayLength,
diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h
index a35c6b26efcca530e546bb91cb6c1dcede88f221..5e52d1613028a01a124797345191519e9378e99a 100644
--- a/lib_com/prot_fx2.h
+++ b/lib_com/prot_fx2.h
@@ -758,7 +758,7 @@ Word16 tcxlpc_get_cdk(
);
void lsf_syn_mem_restore_fx(
- Encoder_State *st_fx, /* o: state structure */
+ Encoder_State_fx *st_fx, /* o: state structure */
Word16 btilt_code_fx, /* i: */
Word32 gc_threshold_fx, /* i: */
Word16 *clip_var_bck_fx, /* i: */
@@ -790,7 +790,7 @@ void lsf_update_memory(
);
void lsf_syn_mem_backup_fx(
- Encoder_State *st_fx, /* i: state structure */
+ Encoder_State_fx *st_fx, /* i: state structure */
Word16 *btilt_code, /* i: tilt code */
Word32 *bgc_threshold, /* i: */
Word16 *clip_var_bck, /* o: */
@@ -1075,6 +1075,15 @@ void write_indices_fx(
Word16 pFrame_size /* i: size of the binary encoded access unit [bits] */
);
+void write_indices_buf_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
+ UWord16 *out_buf, /* i : output bitstream file */
+ UWord8 *pFrame, /* i: byte array with bit packet and byte aligned coded speech data */
+ Word16 pFrame_size, /* i: size of the binary encoded access unit [bits] */
+ UWord16 *num_bits
+);
+
void indices_to_serial(
const Encoder_State* st_fx, /* i: encoder state structure */
BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
@@ -2175,7 +2184,7 @@ void Residu3_fx(
);
void calc_residu_fx(
- Encoder_State *st, /* i/o: state structure */
+ Encoder_State_fx *st, /* i/o: state structure */
const Word16 *speech, /* i : weighted speech signal */
Word16 *res, /* o : residual signal */
const Word16 *p_Aq /* i : quantized LP filter coefficients */
@@ -3191,7 +3200,7 @@ void quantize_uvg_fx(
);
void nelp_encoder_fx(
- Encoder_State *st_fx, /* i/o: encoder state */
+ Encoder_State_fx *st_fx, /* i/o: encoder state */
Word16 *in_fx, /* i : residual signal */
Word16 *exc_fx, /* o : NELP quantized excitation signal */
Word16 *qIn1
@@ -3203,7 +3212,7 @@ swb_bwe_enc_lr_fx.c
/========================================================================================================*/
void swb_bwe_enc_lr_fx(
- Encoder_State *st_fx, /* i/o: encoder state structure */
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
const Word32 L_m_core[], /* i : lowband synthesis */
Word16 QsL,
const Word32 L_m_orig[], /* i/o: scaled orig signal (MDCT) */
@@ -3232,7 +3241,7 @@ isf_enc_amr_wb_fx.c
/========================================================================================================*/
void isf_enc_amr_wb_fx(
- Encoder_State* st, /* i/o: state structure */
+ Encoder_State_fx* st, /* i/o: state structure */
Word16* isf_new, /* i/o: quantized ISF vector */
Word16* isp_new, /* i/o: ISP vector to quantize/quantized */
Word16* Aq /* o : quantized A(z) for 4 subframes */
@@ -3246,7 +3255,7 @@ Word16 detect_transient_fx(
const Word16 *in_fx, /*Q_new */
const Word16 L,
Word16 Q_new,
- Encoder_State *st_fx
+ Encoder_State_fx *st_fx
);
/*========================================================================================================/
@@ -4007,7 +4016,7 @@ AnalysisPostSpectrumScaling_Fx(HANDLE_CLDFB_FILTER_BANK cldfbBank,
);
void analysisCldfbEncoder_fx(
- Encoder_State *st_fx, /* i/o: encoder state structure */
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
const Word16 *timeIn,
Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
@@ -8171,6 +8180,12 @@ void bpf_pitch_coherence_fx(
const Word32 pitch_buf[] /* i : pitch for each subframe [0,1,2,3] */
);
+/* fft_rel.c */
+
+#define SIZE_256 256
+#define NUM_STAGE_256 7
+#define SIZE2_256 (SIZE_256/2)
+
void cldfbAnalysis_ivas_fx(
const Word32 *timeIn_fx, /* i : time buffer Qx */
Word32 **realBuffer_fx, /* o : real value buffer Qx - 5*/
diff --git a/lib_com/pvq_com_fx.c b/lib_com/pvq_com_fx.c
index 31cf8bb752ac8fe113b9322c7e2ed0f4d4fe4285..05d86c074594e347b110b001934f51d5333a997f 100644
--- a/lib_com/pvq_com_fx.c
+++ b/lib_com/pvq_com_fx.c
@@ -479,7 +479,7 @@ void apply_gain_fx(
}
/*--------------------------------------------------------------------------*
- * fine_gain_quant()
+ * fine_gain_quant_fx()
*
* Fine gain quantization
*--------------------------------------------------------------------------*/
diff --git a/lib_com/residu_fx.c b/lib_com/residu_fx.c
index 2c3624a5d88dea59ce90901cfac4df60c933d96e..ea9c6297caeb4f468e946f6f71a456e0eeed8d8e 100644
--- a/lib_com/residu_fx.c
+++ b/lib_com/residu_fx.c
@@ -194,7 +194,7 @@ void Residu3_fx(
/*==========================================================================*/
void calc_residu_fx(
- Encoder_State *st, /* i/o: state structure */
+ Encoder_State_fx *st, /* i/o: state structure */
const Word16 *speech, /* i : weighted speech signal */
Word16 *res, /* o : residual signal */
const Word16 *p_Aq /* i : quantized LP filter coefficients */
@@ -202,7 +202,7 @@ void calc_residu_fx(
{
Word16 i_subfr;
- FOR( i_subfr = 0; i_subfr < st->L_frame; i_subfr += L_SUBFR )
+ FOR( i_subfr = 0; i_subfr < st->L_frame_fx; i_subfr += L_SUBFR )
{
/* calculate the residual signal */
Residu3_fx( p_Aq, &speech[i_subfr], &res[i_subfr], L_SUBFR, 1 );
diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c
index 1fd50722ddc3159c361dbb25a0853b9c2f227c1d..a2434cd9c26fa70a0cde2dfb335c1b8d8c5496fc 100644
--- a/lib_com/rom_com.c
+++ b/lib_com/rom_com.c
@@ -6025,6 +6025,11 @@ const Word16 tbl_gain_code_tc_fx[N_GAIN_CODE_TC] = /*q13 */
16993,
27280
};
+const Word16 tbl_gain_code_tc_quant_mean[N_GAIN_CODE_TC - 1] =
+{
+ 4448, 6927, 8818, 10639,
+ 12660, 15374, 22136
+}; /* Q13 */
/*-----------------------------------------------------------------*
* Transition coding - gain quantization table for g_trans
*-----------------------------------------------------------------*/
@@ -6711,12 +6716,28 @@ const float filt_lp[1+L_FILT] =
0.018130f, 0.010578f, 0.005221f, 0.001946f, 0.000385f
};
+/* For bass post filter */
+const Word16 filt_lp_fx[1 + L_FILT] =
+{
+ 2892/*0.088250f Q15*/, 2831/*0.086410f Q15*/, 2657/*0.081074f Q15*/, 2384/*0.072768f Q15*/,
+ 2041/*0.062294f Q15*/, 1659/*0.050623f Q15*/, 1271/*0.038774f Q15*/, 907/*0.027692f Q15*/,
+ 594/*0.018130f Q15*/, 347/*0.010578f Q15*/, 171/*0.005221f Q15*/, 64/*0.001946f Q15*/,
+ 13/*0.000385f Q15*/
+};
+
const float filt_lp_16kHz[1+L_FILT16k] =
{
0.071410f, 0.070433f, 0.067568f, 0.062999f, 0.057020f, 0.050005f,
0.042378f, 0.034577f, 0.027022f, 0.020078f, 0.014031f, 0.009070f,
0.005276f, 0.002625f, 0.000999f, 0.000205f
};
+const Word16 filt_lp_16kHz_fx[1 + L_FILT16k] =
+{
+ 2340/*0.071410f Q15*/, 2308/*0.070433f Q15*/, 2214/*0.067568f Q15*/, 2064/*0.062999f Q15*/,
+ 1868/*0.057020f Q15*/, 1639/*0.050005f Q15*/, 1389/*0.042378f Q15*/, 1133/*0.034577f Q15*/,
+ 885/*0.027022f Q15*/, 658/*0.020078f Q15*/, 460/*0.014031f Q15*/, 297/*0.009070f Q15*/,
+ 173/*0.005276f Q15*/, 86/*0.002625f Q15*/, 33/*0.000999f Q15*/, 7/*0.000205f Q15*/
+};
/*-------------------------------------------------------------------*
* Pulse indexing tables for ACELP innovation coding
@@ -6772,6 +6793,7 @@ const int32_t PI_offset[8][8] =
const int16_t PI_factor[7] = {0,0,120,560,1820,4368,8008};
/* ACELP pulse coding */
+const Word16 hi_to_low_tmpl[10] = { 0, 0, 0, 3, 9, 5, 3, 1, 8, 8 };
const uint16_t low_len[10] = { 0, 0, 8, 5, 7,11,13,15,16,16 };
const uint16_t low_mask[10] = { 0, 0, 255,31,127,2047,8191,32767,65535,65535 };
const uint16_t indx_fact[10] = { 0, 0,2,172,345,140,190,223,463,1732 };
@@ -7910,6 +7932,10 @@ const float lsf_init[16] =
3375.0, 3750.0, 4125.0, 4500.0, 4875.0, 5250.0, 5625.0, 6000.0
};
+const Word16 lsf_init_fx[16] = /*14Q1*1.28*/
+{
+ 960, 1920, 2880, 3840, 4800, 5760, 6720, 7680, 8640, 9600, 10560, 11520, 12480, 13440, 14400, 15360
+};
/*----------------------------------------------------------------------------------*
* Gaussian codebook
@@ -19110,28 +19136,28 @@ const float CNG_SN1[256] =
451.9531f, 710.9375f, 1072.2656f, 1369.1406f, 1700.7813f, 1991.0156f, 2317.1875f, 2596.8750f, 2893.7500f, 3138.2813f, 3373.0469f, 3548.0469f, 3897.2656f, 4776.5625f, 5398.0469f, 5901.5625f,
223.4375f, 547.2656f, 982.0313f, 1367.5781f, 1758.9844f, 2134.7656f, 2526.9531f, 2904.2969f, 3287.5000f, 3643.7500f, 4025.7813f, 4417.5781f, 4815.6250f, 5196.4844f, 5588.2813f, 5961.3281f
};
+
/* An 16-by-16 matrix */
-const short CNG_SN1_fx[256] =
-{
- 600, 1640, 3039, 4257, 5512, 6740, 7989, 9169, 10393, 11612, 12880, 14100, 15378, 16554, 17816, 18918,
- 1188, 2487, 3746, 4903, 6103, 7261, 8437, 9587, 10776, 11954, 13172, 14355, 15564, 16712, 17913, 19012,
- 346, 799, 2259, 3555, 4876, 6175, 7516, 8803, 10073, 11323, 12631, 13938, 15282, 16553, 17817, 19039,
- 439, 1616, 3446, 4743, 6073, 7288, 8553, 9726, 10947, 12106, 13312, 14474, 15650, 16773, 17894, 18977,
- 921, 1800, 2976, 4007, 5105, 6137, 7178, 8150, 9057, 9914, 11009, 12545, 13671, 15502, 17428, 18927,
- 896, 1899, 3035, 4128, 5301, 6429, 7604, 8719, 9886, 11059, 12417, 13621, 14962, 16135, 17475, 18460,
- 722, 1507, 2537, 3437, 4328, 5190, 6018, 6841, 7587, 8343, 8925, 9511, 9919, 11075, 13613, 15021,
- 315, 612, 1671, 2910, 3990, 5083, 6120, 7170, 8188, 9173, 10148, 11186, 12250, 13262, 14290, 15284,
- 885, 1928, 3010, 3973, 4952, 5900, 6848, 7769, 8701, 9609, 10581, 11540, 12508, 13450, 14412, 15349,
- 338, 1020, 2657, 3736, 4839, 5791, 6806, 7760, 8738, 9659, 10627, 11567, 12534, 13468, 14416, 15334,
- 1126, 1964, 2999, 3855, 4764, 5608, 6482, 7286, 8109, 8827, 9570, 10649, 11999, 13125, 14223, 15252,
- 385, 815, 2000, 2939, 3906, 4879, 5793, 6734, 7661, 8526, 9309, 10146, 11597, 12955, 14106, 15241,
- 633, 1445, 2400, 3293, 4235, 5171, 6143, 7084, 8057, 8980, 9924, 10924, 11987, 12998, 14016, 15058,
- 584, 1248, 2250, 3131, 4050, 4920, 5811, 6652, 7471, 8244, 8913, 9480, 10188, 12225, 13871, 15123,
- 1157, 1820, 2745, 3505, 4354, 5097, 5932, 6648, 7408, 8034, 8635, 9083, 9977, 12228, 13819, 15108,
- 572, 1401, 2514, 3501, 4503, 5465, 6469, 7435, 8416, 9328, 10306, 11309, 12328, 13303, 14306, 15261,
+const Word16 CNG_SN1_fx[256] =
+{
+ 600, 1640, 3039, 4257, 5512, 6740, 7989, 9169, 10393, 11612, 12880, 14100, 15378, 16554, 17816, 18918,
+ 1188, 2487, 3746, 4903, 6103, 7261, 8437, 9587, 10776, 11954, 13172, 14355, 15564, 16712, 17913, 19012,
+ 346, 799, 2259, 3555, 4876, 6175, 7516, 8803, 10073, 11323, 12631, 13938, 15282, 16553, 17817, 19039,
+ 439, 1616, 3446, 4743, 6073, 7288, 8553, 9726, 10947, 12106, 13312, 14474, 15650, 16773, 17894, 18977,
+ 921, 1800, 2976, 4007, 5105, 6137, 7178, 8150, 9057, 9914, 11009, 12545, 13671, 15502, 17428, 18927,
+ 896, 1899, 3035, 4128, 5301, 6429, 7604, 8719, 9886, 11059, 12417, 13621, 14962, 16135, 17475, 18460,
+ 722, 1507, 2537, 3437, 4328, 5190, 6018, 6841, 7587, 8343, 8925, 9511, 9919, 11075, 13613, 15021,
+ 315, 612, 1671, 2910, 3990, 5083, 6120, 7170, 8188, 9173, 10148, 11186, 12250, 13262, 14290, 15284,
+ 885, 1928, 3010, 3973, 4952, 5900, 6848, 7769, 8701, 9609, 10581, 11540, 12508, 13450, 14412, 15349,
+ 338, 1020, 2657, 3736, 4839, 5791, 6806, 7760, 8738, 9659, 10627, 11567, 12534, 13468, 14416, 15334,
+ 1126, 1964, 2999, 3855, 4764, 5608, 6482, 7286, 8109, 8827, 9570, 10649, 11999, 13125, 14223, 15252,
+ 385, 815, 2000, 2939, 3906, 4879, 5793, 6734, 7661, 8526, 9309, 10146, 11597, 12955, 14106, 15241,
+ 633, 1445, 2400, 3293, 4235, 5171, 6143, 7084, 8057, 8980, 9924, 10924, 11987, 12998, 14016, 15058,
+ 584, 1248, 2250, 3131, 4050, 4920, 5811, 6652, 7471, 8244, 8913, 9480, 10188, 12225, 13871, 15123,
+ 1157, 1820, 2745, 3505, 4354, 5097, 5932, 6648, 7408, 8034, 8635, 9083, 9977, 12228, 13819, 15108,
+ 572, 1401, 2514, 3501, 4503, 5465, 6469, 7435, 8416, 9328, 10306, 11309, 12328, 13303, 14306, 15261,
};
-
/* An 16-by-32 matrix */
const float IAA_MA1[512] =
{
@@ -20340,6 +20366,58 @@ const float pl_HQ[] = /* vectors in first layers */
3.5f, 1.5f, 1.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f
};
+const Word16 pl_HQ_fx[] = /* Q1 vectors in first layers */
+{
+ 2, 2, 0, 0, 0, 0, 0, 0, /* 112, 4, 28 */
+ 1, 1, 1, 1, 1, 1, 1, 1, /* 128, 128, 1 */
+ 2, 2, 2, 2, 0, 0, 0, 0, /* 1120, 16, 70 */
+ 4, 0, 0, 0, 0, 0, 0, 0, /* 16 , 2, 8 */
+ 3, 1, 1, 1, 1, 1, 1, 1, /* 5 */ /* 1024,128, 8 */
+ 2, 2, 2, 2, 2, 2, 0, 0, /* 1792, 64, 28 */
+ 4, 2, 2, 0, 0, 0, 0, 0, /* 1344, 8, 168 */
+ 3, 3, 1, 1, 1, 1, 1, 1, /* 3584, 128, 28*/
+ 2, 2, 2, 2, 2, 2, 2, 2, /*256, 256, 1*/
+ 4, 2, 2, 2, 2, 0, 0, 0, /* 10 */ /* 8960, 32, 280 */
+ 4, 4, 0, 0, 0, 0, 0, 0, /* 112, 4, 28 */
+ 3, 3, 3, 1, 1, 1, 1, 1, /* 7168, 128, 56 */
+ 5, 1, 1, 1, 1, 1, 1, 1, /* 1024, 128, 8*/
+ 4, 2, 2, 2, 2, 2, 2, 0, /* 7168, 128, 56*/
+ 4, 4, 2, 2, 0, 0, 0, 0, /* 15 */ /* 6720, 16, 420 */
+ 6, 2, 0, 0, 0, 0, 0, 0, /* 224, 4, 56 */
+ 3, 3, 3, 3, 1, 1, 1, 1, /* 8960, 128, 70 */
+ 5, 3, 1, 1, 1, 1, 1, 1, /* 7168, 128, 56*/
+ 4, 4, 2, 2, 2, 2, 0, 0, /* 26880, 64, 420 */
+ 4, 4, 4, 0, 0, 0, 0, 0, /*20 */ /* 448, 8, 56 */
+ 6, 2, 2, 2, 0, 0, 0, 0, /* 4480, 16, 280 */
+ 3, 3, 3, 3, 3, 1, 1, 1, /* 7168, 128, 56 */
+ 5, 3, 3, 1, 1, 1, 1, 1, /* 21504, 128, 168 */
+ 4, 4, 2, 2, 2, 2, 2, 2, /* 7168, 256, 28 */
+ 4, 4, 4, 2, 2, 0, 0, 0, /* 25 */ /* 17920, 32, 560 */
+ 6, 2, 2, 2, 2, 2, 0, 0, /* 10752, 64, 168 */
+ 6, 4, 2, 0, 0, 0, 0, 0, /* 2688, 8, 336 */
+ 3, 3, 3, 3, 3, 3, 1, 1, /* 3584, 128, 28 */
+ 5, 3, 3, 3, 1, 1, 1, 1, /* 35840,128,280*/
+ 5, 5, 1, 1, 1, 1, 1, 1, /*30 */ /* 3584, 128, 28*/
+ 7, 1, 1, 1, 1, 1, 1, 1, /* 1024,128, 8 */
+ 4, 4, 4, 2, 2, 2, 2, 0,
+ 4, 4, 4, 4, 0, 0, 0, 0,
+ 6, 2, 2, 2, 2, 2, 2, 2,
+ 6, 4, 2, 2, 2, 0, 0, 0,
+ 8, 0, 0, 0, 0, 0, 0, 0,
+ 3, 3, 3, 3, 3, 3, 3, 1,
+ 5, 3, 3, 3, 3, 1, 1, 1,
+ 5, 5, 3, 1, 1, 1, 1, 1,
+ 7, 3, 1, 1, 1, 1, 1, 1,
+ 4, 4, 4, 4, 2, 2, 0, 0,
+ 6, 4, 2, 2, 2, 2, 2, 0,
+ 6, 4, 4, 2, 0, 0, 0, 0,
+ 6, 6, 0, 0, 0, 0, 0, 0,
+ 8, 2, 2, 0, 0, 0, 0, 0,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 5, 3, 3, 3, 3, 3, 1, 1,
+ 5, 5, 3, 3, 1, 1, 1, 1,
+ 7, 3, 3, 1, 1, 1, 1, 1
+};
/*----------------------------------------------------------------------------------*
* LSF quantization for CNG
*----------------------------------------------------------------------------------*/
@@ -21245,6 +21323,45 @@ const float inv_sigma_MSLVQ[][16] =
{0.0133594f, 0.0102708f, 0.0099854f, 0.0109052f, 0.0110643f, 0.0111547f, 0.0120188f, 0.0118931f, 0.0122050f, 0.0103696f, 0.0090101f, 0.0107903f, 0.0119766f, 0.0121760f, 0.0128401f, 0.0141047f}
};
+/* An 16-by-33 matrix in Scale = 32768.00f */
+const Word16 inv_sigma_MSLVQ_fx[][16] =
+{
+ {32767},
+ {32767},
+ {783, 746, 523, 453, 416, 397, 384, 378, 378, 386, 384, 310, 256, 477, 1273, 1935},
+ {670, 647, 461, 452, 440, 421, 412, 405, 410, 440, 468, 369, 275, 321, 883, 1305},
+ {679, 682, 477, 426, 405, 385, 368, 357, 362, 385, 401, 308, 245, 388, 942, 1231},
+ {383, 395, 329, 309, 307, 307, 322, 329, 335, 338, 337, 278, 256, 213, 989, 2243},
+ {32767},
+ {32767},
+ {740, 628, 382, 332, 322, 305, 306, 292, 276, 259, 261, 258, 240, 240, 223, 253},
+ {530, 469, 346, 338, 341, 323, 326, 314, 302, 306, 304, 290, 271, 272, 269, 274},
+ {576, 576, 378, 327, 322, 302, 289, 278, 264, 268, 259, 238, 213, 206, 202, 210},
+ {386, 370, 292, 277, 266, 271, 284, 276, 276, 275, 264, 257, 236, 262, 275, 300},
+ {32767},
+ {32767},
+ {435, 389, 296, 262, 244, 233, 223, 205, 203, 188, 175, 172, 167, 180, 184, 175},
+ {365, 352, 268, 254, 251, 255, 247, 235, 237, 234, 214, 208, 190, 183, 221, 169},
+ {363, 302, 276, 261, 241, 237, 229, 226, 225, 211, 191, 186, 198, 203, 220, 188},
+ {318, 292, 230, 218, 218, 225, 219, 225, 213, 208, 187, 192, 208, 195, 209, 143},
+ {374, 281, 320, 318, 325, 344, 322, 296, 268, 284, 305, 301, 322, 294, 293, 210},
+ {204, 267, 279, 253, 250, 245, 235, 205, 195, 203, 231, 231, 248, 252, 266, 204},
+ {616, 312, 245, 229, 207, 195, 204, 199, 189, 180, 193, 198, 256, 340, 356, 349},
+ {471, 194, 275, 313, 325, 333, 332, 342, 335, 336, 342, 328, 347, 307, 280, 226},
+ {241, 251, 250, 246, 250, 254, 245, 197, 166, 116, 107, 128, 83, 97, 242, 339},
+ {266, 274, 259, 274, 279, 302, 304, 292, 221, 213, 257, 252, 247, 219, 227, 134},
+ {355, 336, 348, 363, 348, 342, 353, 379, 391, 442, 462, 472, 458, 196, 456,1518},
+ {744, 443, 233, 269, 253, 257, 283, 313, 308, 298, 262, 305, 383, 413, 469, 585},
+ {308, 330, 343, 353, 347, 356, 392, 387, 376, 322, 359, 435, 448, 458, 482, 514},
+ {756, 261, 305, 384, 394, 406, 415, 409, 409, 372, 352, 403, 438, 448, 498, 552},
+ {219, 257, 280, 293, 289, 288, 304, 335, 325, 289, 195, 161, 211, 275, 306, 312},
+ {550, 380, 309, 288, 244, 271, 272, 326, 332, 328, 248, 171, 168, 421, 468, 781},
+ {371, 355, 356, 350, 336, 353, 368, 376, 369, 348, 269, 269, 281, 268, 199, 233},
+ {380, 353, 392, 381, 342, 344, 362, 379, 399, 403, 420, 367, 228, 195, 789,1184},
+ {337, 324, 314, 297, 301, 305, 335, 354, 414, 401, 425, 301, 154, 165, 690, 927},
+ {438, 337, 327, 357, 363, 365, 394, 390, 400, 340, 295, 354, 392, 399, 421, 462},
+};
+
/* An 16-by-19 matrix in Scale = 20.48f */
const float sigma_p[][16] =
{
@@ -21291,6 +21408,30 @@ const float inv_sigma_p[][16] =
{0.0181399f, 0.0142124f, 0.0120329f, 0.0114670f, 0.0110464f, 0.0109343f, 0.0105567f, 0.0106834f, 0.0102451f, 0.0101286f, 0.0095522f, 0.0100343f, 0.0104597f, 0.0109110f, 0.0113024f, 0.0127840f },/* NOT USED ! AU 16k */
{0.0143820f, 0.0124726f, 0.0098699f, 0.0099081f, 0.0093902f, 0.0089943f, 0.0092922f, 0.0088505f, 0.0085690f, 0.0085333f, 0.0082681f, 0.0079938f, 0.0076475f, 0.0077693f, 0.0081045f, 0.0095300f} /* G WB for MA*/
};
+/* An 16-by-19 matrix in Scale = 32768.00f */
+const Word16 inv_sigma_p_fx[][16] =
+{
+ {552, 513, 469, 494, 486, 478, 492, 496, 496, 482, 480, 388, 339, 276, 743, 760},
+ {640, 492, 472, 478, 482, 471, 470, 471, 623, 504, 501, 477, 459, 425, 421, 408},
+ {1001, 939, 696, 589, 545, 480, 456, 451, 444, 462, 472, 424, 342, 441, 1567, 3002},
+ {609, 534, 419, 432, 444, 403, 406, 407, 391, 425, 452, 378, 269, 278, 818, 1939},
+ {32767},
+ {574, 507, 459, 432, 425, 415, 440, 442, 449, 450, 490, 443, 299, 270, 1377, 2451},
+ {591, 499, 456, 457, 449, 441, 448, 446, 443, 436, 420, 397, 364, 342, 496, 475},
+ {482, 512, 498, 426, 280, 225, 422, 1411, 404, 404, 402, 385, 364, 342, 355, 361},
+ {917, 831, 572, 507, 482, 430, 406, 399, 385, 365, 364, 344, 313, 309, 311, 335},
+ {533, 436, 371, 399, 398, 368, 367, 348, 343, 342, 338, 319, 306, 305, 311, 334},
+ {32767},
+ {641, 523, 458, 434, 415, 410, 412, 395, 397, 394, 386, 381, 366, 392, 413, 419},
+ {449, 380, 364, 366, 354, 362, 362, 356, 337, 323, 293, 296, 336, 352, 353, 283},
+ {32767},
+ {601, 485, 348, 262, 267, 266, 276, 285, 255, 233, 227, 235, 216, 237, 233, 212},
+ {338, 279, 247, 244, 233, 239, 231, 232, 228, 215, 194, 194, 207, 210, 222, 180},
+ {32767},
+ {594, 466, 394, 376, 362, 358, 346, 350, 336, 332, 313, 329, 343, 358, 370, 419},
+ {471, 409, 323, 325, 308, 295, 305, 290, 281, 280, 271, 262, 251, 255, 266, 312},
+};
+
const Word16 sigma_p_fx[][16] =
{
{152, 164, 179, 170, 172, 176, 171, 169, 169, 174, 175, 216, 247, 304, 113, 110},
@@ -22189,6 +22330,12 @@ const Word16 scale_ARSN_fx[M] = /* Q14 */
};
const float scale_inv_ARSN[M] = {0.5462f, 0.5434f, 0.5553f, 0.5742f, 0.5800f, 0.5725f, 0.6209f, 0.6062f, 0.6369f, 0.6432f, 0.6351f, 0.6173f, 0.6397f, 0.6562f, 0.6331f, 0.6404f};
+const Word16 scale_inv_ARSN_fx[M] = /* Q15 */
+{
+ 17898, 17806, 18196, 18815, 19005, 18760, 20342, 19864,
+ 20870, 21076, 20811, 20228, 20962, 21502, 20745, 20985
+};
+
/* TCVQ Codebook */
const float AR_TCVQ_CB_SUB1[2][128][2] =
{
@@ -22702,6 +22849,11 @@ const float HO_ATT[5] =
0.5370318f, 0.6165950f, 0.6839116f, 0.7079458f, 0.7079458f
};
+const Word16 HO_ATT_FX[5] = /* Q15 */
+{
+ 17597, 20205, 22410, 23198, 23198
+};
+
const int16_t uniform_model[] = { MAX_AR_FREQ, MAX_AR_FREQ / 2, 0 };
@@ -23316,6 +23468,35 @@ const float win_lpc_shb[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/8]=
0.9969597324f, 0.9975656090f, 0.9981043719f, 0.9985759486f, 0.9989802753f, 0.9993172977f, 0.9995869701f, 0.9997892562f, 0.9999241288f, 0.9999915697f
};
+const Word16 win_lpc_shb_fx[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5 / 8] =
+{
+ /*Q15 */
+ 1, 4, 10, 18, 28, 40, 54, 71, 89, 110, 134, 159, 186, 216, 248,
+ 282, 318, 357, 397, 440, 485, 532, 581, 632, 686, 741, 799, 859, 921,
+ 984, 1050, 1119, 1189, 1261, 1335, 1411, 1490, 1570, 1652, 1736, 1823,
+ 1911, 2001, 2093, 2187, 2283, 2381, 2481, 2582, 2686, 2791, 2898, 3007,
+ 3118, 3230, 3345, 3461, 3579, 3698, 3819, 3942, 4067, 4193, 4321, 4451,
+ 4582, 4715, 4849, 4985, 5123, 5261, 5402, 5544, 5687, 5832, 5978, 6126,
+ 6275, 6426, 6577, 6730, 6885, 7041, 7197, 7356, 7515, 7676, 7837, 8000,
+ 8164, 8329, 8496, 8663, 8831, 9001, 9171, 9342, 9515, 9688, 9862, 10037,
+ 10213, 10390, 10567, 10745, 10924, 11104, 11285, 11466, 11648, 11830, 12013,
+ 12197, 12381, 12566, 12751, 12937, 13123, 13310, 13497, 13684, 13872, 14060,
+ 14249, 14438, 14627, 14816, 15006, 15195, 15385, 15575, 15765, 15955, 16146,
+ 16336, 16526, 16716, 16907, 17097, 17287, 17477, 17667, 17856, 18046, 18235,
+ 18424, 18612, 18801, 18989, 19176, 19364, 19551, 19737, 19923, 20109, 20294,
+ 20478, 20662, 20846, 21028, 21210, 21392, 21573, 21753, 21932, 22111, 22289,
+ 22466, 22642, 22818, 22992, 23166, 23339, 23510, 23681, 23851, 24020, 24188,
+ 24355, 24520, 24685, 24848, 25011, 25172, 25332, 25491, 25648, 25804, 25960,
+ 26113, 26266, 26417, 26567, 26715, 26862, 27007, 27152, 27294, 27435, 27575,
+ 27713, 27850, 27985, 28119, 28251, 28381, 28510, 28637, 28762, 28886, 29008,
+ 29129, 29248, 29364, 29480, 29593, 29705, 29815, 29923, 30029, 30133, 30236,
+ 30337, 30435, 30532, 30627, 30720, 30811, 30901, 30988, 31073, 31156, 31238,
+ 31317, 31394, 31469, 31543, 31614, 31683, 31750, 31815, 31878, 31938, 31997,
+ 32054, 32108, 32161, 32211, 32259, 32305, 32349, 32390, 32430, 32467, 32502,
+ 32535, 32566, 32595, 32621, 32645, 32667, 32687, 32705, 32720, 32734, 32745,
+ 32753, 32760, 32765, 32767
+};
+
const float win_lpc_hb_wb[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/32]=
{
0.000171338f, 0.001541333f, 0.004277569f, 0.008372546f, 0.01381504f, 0.020590133f, 0.028679254f, 0.038060234f,
@@ -23327,6 +23508,19 @@ const float win_lpc_hb_wb[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/32]=
0.912063094f, 0.926320082f, 0.939408556f, 0.951292642f, 0.961939766f, 0.971320746f, 0.979409867f, 0.98618496f,
0.991627454f, 0.995722431f, 0.998458667f, 0.999828662f
};
+const Word16 win_lpc_hb_wb_fx[(L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5 / 32] =
+{
+ 17, 70, 157, 279, 435, 625, 849, 1106,
+ 1396, 1718, 2071, 2454, 2867, 3309, 3779, 4276,
+ 4799, 5346, 5917, 6510, 7125, 7759, 8411, 9081,
+ 9766, 10465, 11177, 11900, 12633, 13373, 14120, 14872,
+ 15627, 16384, 17141, 17896, 18648, 19395, 20135, 20868,
+ 21591, 22303, 23002, 23687, 24357, 25009, 25643, 26258,
+ 26851, 27422, 27969, 28492, 28989, 29459, 29901, 30314,
+ 30697, 31050, 31372, 31662, 31919, 32143, 32333, 32489,
+ 32611, 32698, 32751
+};
+
const float ola_win_shb_switch_fold[L_SUBFR16k] =
{
@@ -23341,6 +23535,19 @@ const float ola_win_shb_switch_fold[L_SUBFR16k] =
0.954044402f, 0.959744037f, 0.965073672f, 0.970031253f, 0.974614869f, 0.978822751f, 0.982653279f, 0.986104976f,
0.989176510f, 0.991866698f, 0.994174502f, 0.996099033f, 0.997639549f, 0.998795456f, 0.999566309f, 0.999951809f
};
+const Word16 ola_win_shb_switch_fold_fx[L_SUBFR16k] =
+{
+ 322, 965, 1608, 2250, 2892, 3532, 4171, 4808,
+ 5444, 6077, 6708, 7336, 7962, 8585, 9204, 9819,
+ 10431, 11039, 11643, 12242, 12836, 13426, 14010, 14589,
+ 15162, 15730, 16291, 16846, 17395, 17937, 18472, 18999,
+ 19520, 20033, 20538, 21035, 21525, 22006, 22478, 22942,
+ 23397, 23843, 24279, 24707, 25125, 25533, 25931, 26320,
+ 26698, 27066, 27423, 27770, 28106, 28431, 28746, 29049,
+ 29341, 29622, 29891, 30149, 30395, 30630, 30853, 31063,
+ 31262, 31449, 31624, 31786, 31936, 32074, 32200, 32313,
+ 32413, 32501, 32577, 32640, 32691, 32729, 32754, 32766
+};
/* Window for calculating whitening filter for SHB excitation */
const float win_flatten[ L_FRAME16k/2]=
@@ -24447,6 +24654,33 @@ const float wac_swb[LPC_SHB_ORDER + 1] =
0.99556853f, 0.99308446f, 0.99005679f, 0.98649053f,
0.98239158f, 0.97776669f, 0.97262346f
};
+const Word16 wac_swb_h[LPC_SHB_ORDER] =
+{
+ 32758,
+ 32731,
+ 32686,
+ 32622,
+ 32541,
+ 32442,
+ 32325,
+ 32191,
+ 32039,
+ 31870
+};
+
+const Word16 wac_swb_l[LPC_SHB_ORDER] =
+{
+ 29673,
+ 20874,
+ 7850,
+ 25873,
+ 12831,
+ 5927,
+ 10541,
+ 239,
+ 15037,
+ 30328
+};
const float lbr_wb_bwe_lsfvq_cbook_2bit[4*4] = {0.11829331f, 0.18065347f, 0.27315149f, 0.36268139f,
0.20006990f, 0.24350365f, 0.33066865f, 0.40078221f,
@@ -24809,6 +25043,13 @@ const float decimate_3_ov_2_lowpass_num[3] =
0.195271809895833f
};
+const Word16 decimate_3_ov_2_lowpass_num_fx[3] = /* Q15 */
+{
+ 6399,
+ 12797,
+ 6399
+};
+
const float decimate_3_ov_2_lowpass_den[3] =
{
1.0f,
@@ -24816,6 +25057,13 @@ const float decimate_3_ov_2_lowpass_den[3] =
0.171630859375f
};
+const Word16 decimate_3_ov_2_lowpass_den_fx[3] = /* Q15 */
+{
+ 32767,
+ 0,
+ 5624
+};
+
/*------------------------------------------------------------------------------*
* WB BWE tables
@@ -24884,12 +25132,14 @@ const int16_t swb_bwe_subband[SWB_FENV+1] = {240, 256, 280, 296, 320, 336, 360,
const Word16 fb_bwe_subband[DIM_FB + 1] = { 640, 680, 720, 800 };
const Word16 fb_bwe_sm_subband[DIM_FB] = { 656, 696, 760 };
const float swb_inv_bwe_subband_width[SWB_FENV] = {0.0625f, 0.04167f, 0.0625f, 0.04167f, 0.0625f, 0.04167f, 0.0625f, 0.04167f, 0.04167f, 0.04167f, 0.04167f, 0.04167f, 0.03125f, 0.03125f};
+const Word16 swb_inv_bwe_subband_width_fx[SWB_FENV] = { 2048,1365,2048,1365,2048,1365,2048,1365,1365,1365,1365,1365,1024,1024 };
const int16_t swb_bwe_sm_subband[SWB_FENV] = {248, 268, 288, 308, 328, 348, 368, 388, 412, 436, 460, 484, 512, 544};
const float smooth_factor[SWB_FENV-1] = {0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.05f, 0.0417f, 0.0417f, 0.0417f, 0.0417f, 0.03125f, 0.03125f};
const Word16 smooth_factor_fx[SWB_FENV - 1] = { 1638, 1638, 1638, 1638, 1638, 1638, 1638, 1366, 1366, 1366, 1366, 1024, 1024 };
const int16_t fb_bwe_subband_float[DIM_FB+1] = {640, 680, 720, 800};
const float fb_inv_bwe_subband_width[DIM_FB] = {0.0250f, 0.0250f, 0.0125f};
+const Word16 fb_inv_bwe_subband_width_fx[DIM_FB] = { 819, 819, 409 };
const int16_t fb_bwe_sm_subband_float[DIM_FB] = {656, 696, 760};
const float fb_smooth_factor[DIM_FB] = {0.03125f, 0.0250f, 0.015625f};
const Word16 fb_smooth_factor_fx[DIM_FB] = { 1024, 819, 512 };
@@ -25648,6 +25898,11 @@ const float Mean_env_fb[DIM_FB] = {13.75f, 6.29f, 3.70f};
const Word16 Mean_env_fb_fx[DIM_FB] = { 1760, 805, 473 }; /*Q8 */
const float w_NOR[SWB_FENV] = {1.f,0.97826087f,0.957446809f,0.9375f,0.918367347f,0.9f,0.882352941f,0.865384615f,0.849056604f,0.833333333f,0.818181818f,0.803571429f,0.789473684f,0.775862069f};
+const Word16 w_NOR_fx[SWB_FENV] = /*Q15 */
+{
+ 32767, 32056, 31374, 30720, 30093, 29491, 28913,
+ 28357, 27822, 27307, 26810, 26331, 25869, 25423,
+};
const float Mean_env[SWB_FENV] = {28.62f, 28.96f, 28.05f, 27.97f, 26.91f, 26.82f, 26.35f, 25.98f, 24.94f, 24.03f, 22.94f, 22.14f, 21.23f, 20.40f};
const Word16 Mean_env_fx[SWB_FENV] = /*Q8 */
{
@@ -27991,6 +28246,7 @@ const float mfreq_loc[] =
const int16_t mfreq_bindiv_loc[] = { 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32 };
const float mean_gp[] = { 0.5853f };
+const Word16 mean_gp_fx[] = { 9590 }; /*Q14*/
const float dic_gp[] =
{
@@ -30640,6 +30896,9 @@ const float FFT_RotVector_960[1860] = {
/* HVQ */
const float hvq_thr_adj[5] = { 0.7071068f, 0.5000000f, 0.2500000f, 0.5000000f, 0.7071068f};
+const Word16 hvq_thr_adj_fx[5] = { 23170, 16384, 8192, 16384, 23170 }; /* Q15 */
+
+const Word16 hvq_index_mapping_fx[4] = { 0, 1, 3, 4 };
const float hvq_class_c[16] =
{
@@ -30648,6 +30907,13 @@ const float hvq_class_c[16] =
-0.1384814f, 0.4312476f, -0.1351437f, 0.1471332f,
0.2109977f, 0.0651793f, -0.4390556f, -0.2324457f
};
+const Word16 hvq_class_c_fx[16] = /* Q15 */
+{
+ -7617, -14387, 2136, 6914,
+ 4821, -4428, 14131, -4538,
+ -4538, 14131, -4428, 4821,
+ 6914, 2136, -14387, -7617
+};
const int16_t hvq_cb_search_overlap24k[17] =
{
@@ -34789,6 +35055,10 @@ const float tnsAcfWindow[TNS_MAX_FILTER_ORDER] =
0.997803f, 0.991211f, 0.980225f, 0.964844f, 0.945068f, 0.920898f, 0.892334f, 0.859375f
};
+const Word16 tnsAcfWindow_fx[TNS_MAX_FILTER_ORDER] =
+{
+ 32696/*0.997803f Q15*/, 32480/*0.991211f Q15*/, 32120/*0.980225f Q15*/, 31616/*0.964844f Q15*/, 30968/*0.945068f Q15*/, 30176/*0.920898f Q15*/, 29240/*0.892334f Q15*/, 28160/*0.859375f Q15*/
+};
/* Definition of the mapping between TNS parameters and a bitstream */
@@ -40040,7 +40310,10 @@ const Word16 Tab_esc_nb[4] = { 0 << (NBITS_CONTEXT + NBITS_RATEQ),
};
const Word16 pow2tab[15] = { 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
-
+const Word32 pow2[] =
+{
+ 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576
+};
//d_gain2p.c
const Word16 Es_pred_qua[8] =
{
@@ -40083,6 +40356,272 @@ const Word16 T_DIV_L_Frame[] = /*0Q15 * 2^-7 */
,6553 /*640*/
};
+/* order 8 LPF for nelp frames when non-native sampling freq inputs used with -max_band NB */
+/* used to suppress frequencies above 4kHz present at the output of filters in pre_proc() */
+
+const Word16 num_nelp_lp_fx[NELP_LP_ORDER + 1] = /*Q13*/
+{
+ 727,
+ 3506,
+ 8988,
+ 15029,
+ 17732,
+ 15022,
+ 8979,
+ 3501,
+ 726
+};
+
+const Word16 den_nelp_lp_fx[NELP_LP_ORDER + 1] =
+{
+ 8192,
+ 8819,
+ 21618,
+ 12167,
+ 15902,
+ 3553,
+ 3998,
+ -120,
+ 353
+};
+
+/*----------------------------------------------------------------------------------*
+ * AMR-WB IO WB BWE - band-pass 6-8kHz FIR filter, values in Q15:
+ *----------------------------------------------------------------------------------*/
+const Word16 fir_6k_8k_fx[31] =
+{
+ 44, -155, 323, -482, 563, -590, 726, -1180, 1986, -2818, 3028,
+ -1991, -423, 3583, -6281, 7342, -6281, 3583, -423, -1991, 3028,
+ -2818, 1986, -1180, 726, -590, 563, -482, 323, -155, 44
+};
+
+const Word16 pwf78_fx[17] = { 25559, 19936, 15550, 12129, 9460, 7379, 5755, 4489,
+ 3501, 2731, 2130, 1661, 1296, 1011, 788, 615,
+ 479
+}; /* 0.78^i (i=1,...,17), Q15 */
+
+/*------------------------------------------------------------------------------*
+ * lag window for windowing the autocorrelations in LP analysis
+ * Used in lib_enc\analy_lp_fx.c
+ *------------------------------------------------------------------------------*/
+const Word16 Hamcos_Window[L_LP_AMR_WB] =
+{
+ 2621, 2622, 2626, 2632, 2640, 2650, 2662, 2677,
+ 2694, 2714, 2735, 2759, 2785, 2814, 2844, 2877,
+ 2912, 2949, 2989, 3031, 3075, 3121, 3169, 3220,
+ 3273, 3328, 3385, 3444, 3506, 3569, 3635, 3703,
+ 3773, 3845, 3919, 3996, 4074, 4155, 4237, 4321,
+ 4408, 4496, 4587, 4680, 4774, 4870, 4969, 5069,
+ 5171, 5275, 5381, 5489, 5599, 5710, 5824, 5939,
+ 6056, 6174, 6295, 6417, 6541, 6666, 6793, 6922,
+ 7052, 7185, 7318, 7453, 7590, 7728, 7868, 8009,
+ 8152, 8296, 8442, 8589, 8737, 8887, 9038, 9191,
+ 9344, 9499, 9655, 9813, 9971, 10131, 10292, 10454,
+ 10617, 10781, 10946, 11113, 11280, 11448, 11617, 11787,
+ 11958, 12130, 12303, 12476, 12650, 12825, 13001, 13178,
+ 13355, 13533, 13711, 13890, 14070, 14250, 14431, 14612,
+ 14793, 14975, 15158, 15341, 15524, 15708, 15891, 16076,
+ 16260, 16445, 16629, 16814, 16999, 17185, 17370, 17555,
+ 17740, 17926, 18111, 18296, 18481, 18666, 18851, 19036,
+ 19221, 19405, 19589, 19773, 19956, 20139, 20322, 20504,
+ 20686, 20867, 21048, 21229, 21408, 21588, 21767, 21945,
+ 22122, 22299, 22475, 22651, 22825, 22999, 23172, 23344,
+ 23516, 23686, 23856, 24025, 24192, 24359, 24525, 24689,
+ 24853, 25016, 25177, 25337, 25496, 25654, 25811, 25967,
+ 26121, 26274, 26426, 26576, 26725, 26873, 27019, 27164,
+ 27308, 27450, 27590, 27729, 27867, 28003, 28137, 28270,
+ 28401, 28531, 28659, 28785, 28910, 29033, 29154, 29274,
+ 29391, 29507, 29622, 29734, 29845, 29953, 30060, 30165,
+ 30268, 30370, 30469, 30566, 30662, 30755, 30847, 30936,
+ 31024, 31109, 31193, 31274, 31354, 31431, 31506, 31579,
+ 31651, 31719, 31786, 31851, 31914, 31974, 32032, 32088,
+ 32142, 32194, 32243, 32291, 32336, 32379, 32419, 32458,
+ 32494, 32528, 32560, 32589, 32617, 32642, 32664, 32685,
+ 32703, 32719, 32733, 32744, 32753, 32760, 32764, 32767,
+ 32767, 32765, 32757, 32745, 32727, 32705, 32678, 32646,
+ 32609, 32567, 32520, 32468, 32411, 32349, 32283, 32211,
+ 32135, 32054, 31968, 31877, 31781, 31681, 31575, 31465,
+ 31351, 31231, 31107, 30978, 30844, 30706, 30563, 30415,
+ 30263, 30106, 29945, 29779, 29609, 29434, 29255, 29071,
+ 28883, 28691, 28494, 28293, 28087, 27878, 27664, 27446,
+ 27224, 26997, 26767, 26533, 26294, 26052, 25806, 25555,
+ 25301, 25043, 24782, 24516, 24247, 23974, 23698, 23418,
+ 23134, 22847, 22557, 22263, 21965, 21665, 21361, 21054,
+ 20743, 20430, 20113, 19794, 19471, 19146, 18817, 18486,
+ 18152, 17815, 17476, 17134, 16789, 16442, 16092, 15740,
+ 15385, 15028, 14669, 14308, 13944, 13579, 13211, 12841,
+ 12470, 12096, 11721, 11344, 10965, 10584, 10202, 9819,
+ 9433, 9047, 8659, 8270, 7879, 7488, 7095, 6701,
+ 6306, 5910, 5514, 5116, 4718, 4319, 3919, 3519,
+ 3118, 2716, 2315, 1913, 1510, 1108, 705, 302
+};
+
+
+const Word16 CNG_burst_att_fx[6][8] =
+{
+ {30076, 27793, 25832, 24129, 22637, 21319, 20146, 19095},
+ {29714, 27181, 25046, 23222, 21646, 20270, 20205, 20205},
+ {29415, 26685, 24418, 22506, 22410, 22410, 22410, 22410},
+ {29310, 26512, 24201, 23198, 23198, 23198, 23198, 23198},
+ {29310, 26512, 24201, 23198, 23198, 23198, 23198, 23198},
+ {29789, 27307, 25206, 23406, 21845, 20480, 19661, 19661}
+};
+
+const Word16 lpc_weights_fx[LPC_SHB_ORDER + 1] =
+{
+ 32767, 31948, 31150, 30371, 29612,
+ 28871, 28149, 27446, 26760, 26091, 25438
+};
+
+const Word16 SHBCB_SubGain5bit_12_fx[128] =
+{
+ /*Q12 */
+ -597, -1952, -1644, -1506, -1767, -1357, -1249, -874,
+ -4181, -3836, -240, -1985, -6573, -1480, -1229, -1094,
+ -381, -1655, -2119, -2406, -2012, -1022, -2235, -761,
+ -908, -1282, -1241, -1845, -68, -4666, -6058, -6355,
+ -2311, -1888, -1396, -513, -523, -1155, -2300, -3657,
+ -1161, -549, -2564, -2424, -609, -2346, -2934, -1142,
+ -3591, -2859, -2063, -205, -4048, -4083, -4261, -56,
+ -1352, -2147, -1894, -574, -6577, -5483, -1881, -628,
+ -815, -1061, -1987, -1654, -455, -1380, -3818, -4941,
+ -926, -934, -1463, -2630, -2520, -1013, -1016, -1250,
+ -977, -2477, -720, -2401, -130, -2789, -3155, -3192,
+ -1135, -1287, -1552, -1115, -1217, -1918, -1059, -1102,
+ -2291, -3353, -744, -979, -3067, -1892, -961, -707,
+ -1795, -1229, -652, -2348, -1569, -717, -1490, -1628,
+ -3240, -258, -2129, -2748, -2062, -1902, -625, -1257,
+ -1453, -1250, -965, -1445, -4227, -1494, -1108, -819,
+
+
+};
+
+
+const Word16 E_ROM_inter4_1_fx[UP_SAMP * L_INTERPOL1 + 1] =
+{
+ /* cut-off frequency at 0.9*fs/2 */
+ 14746/*0.900000F Q14*/,
+ 13418/*0.818959F Q14*/, 9910/*0.604850F Q14*/, 5429/*0.331379F Q14*/, 1376/*0.083958F Q14*/,
+ -1242/*-0.075795F Q14*/, -2142/*-0.130717F Q14*/, -1732/*-0.105685F Q14*/, -766/*-0.046774F Q14*/,
+ 73/*0.004467F Q14*/, 455/*0.027789F Q14*/, 420/*0.025642F Q14*/, 206/*0.012571F Q14*/,
+ 32/*0.001927F Q14*/, -26/*-0.001571F Q14*/, -12/*-0.000753F Q14*/, 0/*0.000000f Q14*/
+};
+const Word16 E_ROM_inter6_1_fx[PIT_UP_SAMP6 * L_INTERPOL1 + 1] =
+{
+ 14759/*0.900848F Q14*/,
+ 14158/*0.864136F Q14*/,
+ 12453/*0.760071F Q14*/,
+ 9919/*0.605408F Q14*/,
+ 6948/*0.424072F Q14*/,
+ 3972/*0.242462F Q14*/,
+ 1377/*0.0840759F Q14*/,
+ -563/*-0.0343933F Q14*/,
+ -1729/*-0.105560F Q14*/,
+ -2152/*-0.131348F Q14*/,
+ -1984/*-0.121124F Q14*/,
+ -1450/*-0.0884705F Q14*/,
+ -780/*-0.0476379F Q14*/,
+ -168/*-0.0102539F Q14*/,
+ 267/*0.0162964F Q14*/,
+ 485/*0.0296021F Q14*/,
+ 512/*0.0312195F Q14*/,
+ 412/*0.0251160F Q14*/,
+ 258/*0.0157471F Q14*/,
+ 110/*0.00671387F Q14*/,
+ 0/*0.000000F Q14*/,
+ -65/*-0.00399780F Q14*/,
+ -97/*-0.00592041F Q14*/,
+ -108/*-0.00656128F Q14*/,
+ 0/*0.000000F Q14*/
+};
+const Word16 kLog2TableFrac_x[256] =
+{
+ 0, 1, 3, 4, 6, 7, 9, 10,
+ 11, 13, 14, 16, 17, 18, 20, 21,
+ 22, 24, 25, 26, 28, 29, 30, 32,
+ 33, 34, 36, 37, 38, 40, 41, 42,
+ 44, 45, 46, 47, 49, 50, 51, 52,
+ 54, 55, 56, 57, 59, 60, 61, 62,
+ 63, 65, 66, 67, 68, 69, 71, 72,
+ 73, 74, 75, 77, 78, 79, 80, 81,
+ 82, 84, 85, 86, 87, 88, 89, 90,
+ 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 102, 103, 104, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 116, 117,
+ 118, 119, 120, 121, 122, 123, 124, 125,
+ 126, 127, 128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139, 140, 141,
+ 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 151, 152, 153, 154, 155, 155, 156,
+ 157, 158, 159, 160, 161, 162, 163, 164,
+ 165, 166, 167, 168, 169, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 178,
+ 179, 180, 181, 182, 183, 184, 185, 185,
+ 186, 187, 188, 189, 190, 191, 192, 192,
+ 193, 194, 195, 196, 197, 198, 198, 199,
+ 200, 201, 202, 203, 203, 204, 205, 206,
+ 207, 208, 208, 209, 210, 211, 212, 212,
+ 213, 214, 215, 216, 216, 217, 218, 219,
+ 220, 220, 221, 222, 223, 224, 224, 225,
+ 226, 227, 228, 228, 229, 230, 231, 231,
+ 232, 233, 234, 234, 235, 236, 237, 238,
+ 238, 239, 240, 241, 241, 242, 243, 244,
+ 244, 245, 246, 247, 247, 248, 249, 249,
+ 250, 251, 252, 252, 253, 254, 255, 255
+};
+
+const Word16 kExp2TableFrac_x[256] = /* Q15 */
+{
+ 32767, 32678, 32590, 32502, 32414, 32326, 32239, 32152,
+ 32065, 31978, 31892, 31805, 31719, 31634, 31548, 31463,
+ 31378, 31293, 31208, 31124, 31040, 30956, 30872, 30789,
+ 30705, 30622, 30540, 30457, 30375, 30293, 30211, 30129,
+ 30047, 29966, 29885, 29804, 29724, 29643, 29563, 29483,
+ 29404, 29324, 29245, 29166, 29087, 29008, 28930, 28852,
+ 28774, 28696, 28618, 28541, 28464, 28387, 28310, 28233,
+ 28157, 28081, 28005, 27929, 27854, 27778, 27703, 27628,
+ 27554, 27479, 27405, 27331, 27257, 27183, 27110, 27036,
+ 26963, 26890, 26818, 26745, 26673, 26601, 26529, 26457,
+ 26385, 26314, 26243, 26172, 26101, 26031, 25960, 25890,
+ 25820, 25750, 25681, 25611, 25542, 25473, 25404, 25335,
+ 25267, 25198, 25130, 25062, 24995, 24927, 24860, 24792,
+ 24725, 24659, 24592, 24525, 24459, 24393, 24327, 24261,
+ 24196, 24130, 24065, 24000, 23935, 23870, 23806, 23741,
+ 23677, 23613, 23549, 23486, 23422, 23359, 23296, 23233,
+ 23170, 23107, 23045, 22982, 22920, 22858, 22796, 22735,
+ 22673, 22612, 22551, 22490, 22429, 22368, 22308, 22248,
+ 22187, 22127, 22068, 22008, 21948, 21889, 21830, 21771,
+ 21712, 21653, 21595, 21536, 21478, 21420, 21362, 21304,
+ 21247, 21189, 21132, 21075, 21018, 20961, 20904, 20848,
+ 20791, 20735, 20679, 20623, 20568, 20512, 20456, 20401,
+ 20346, 20291, 20236, 20181, 20127, 20072, 20018, 19964,
+ 19910, 19856, 19802, 19749, 19696, 19642, 19589, 19536,
+ 19483, 19431, 19378, 19326, 19274, 19221, 19169, 19118,
+ 19066, 19014, 18963, 18912, 18861, 18810, 18759, 18708,
+ 18657, 18607, 18557, 18506, 18456, 18406, 18357, 18307,
+ 18258, 18208, 18159, 18110, 18061, 18012, 17963, 17915,
+ 17866, 17818, 17770, 17722, 17674, 17626, 17578, 17531,
+ 17483, 17436, 17389, 17342, 17295, 17248, 17202, 17155,
+ 17109, 17063, 17016, 16970, 16925, 16879, 16833, 16788,
+ 16742, 16697, 16652, 16607, 16562, 16517, 16472, 16428
+};
+
+/*-------------------------------------------------------------------*
+ * inverse (reciprocal) of integer, used in FEC_fx.c, pitch_extr and in pitchDoubling_det
+ * 1/n = One_div[n-1]
+ *-------------------------------------------------------------------*/
+const Word16 One_div_fx[] = /* in Q15 */
+{
+ 32767, /* 1/1 */
+ 16384, /* 1/2 */
+ 10923, /* 1/3 */
+ 8192, /* 1/4 */
+ 6554, /* 1/5 */
+ 5461, /* 1/6 */
+ 4681, /* 1/7 */
+ 4096 /* 1/8 */
+};
+
const Word32 tbl_two_pow_shift_by_4[35] = {
1073741824, 902905664, 759250112, 638450688, 536870912, 451452832, 379625056, 319225344,
268435456, 225726416, 189812528, 159612672, 134217728, 112863208, 94906264, 79806336,
@@ -40298,4 +40837,4 @@ const Word16 ivas_sin_az_fx[361] = {
SHC( 0x11d0 ), SHC( 0x0f99 ), SHC( 0x0d61 ), SHC( 0x0b27 ), SHC( 0x08ed ), SHC( 0x06b2 ), SHC( 0x0477 ), SHC( 0x023b ),
SHC( 0x0000 )
-};
\ No newline at end of file
+};
diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h
index 2c9ab8eab524489a2a4e5d9d4e4654634a0679e5..7d680e9aa0f2f21cf1ff610b96269dcae29dce5d 100644
--- a/lib_com/rom_com.h
+++ b/lib_com/rom_com.h
@@ -338,6 +338,7 @@ extern const float gain_qua_mless[];
extern const float tbl_gain_code_tc[]; /* TC - code gain quantization table */
extern const Word16 tbl_gain_code_tc_fx[N_GAIN_CODE_TC];
+extern const Word16 tbl_gain_code_tc_quant_mean[N_GAIN_CODE_TC - 1];
extern const float tbl_gain_trans_tc[]; /* TC - gain quantization table for g_trans */
extern const float glottal_cdbk[]; /* TC - table of prototype glottal impulses */
@@ -349,6 +350,7 @@ extern const int32_t PI_offset[8][8]; /* offset table for Pulse indexing
extern const int16_t PI_factor[]; /* EVS_PI factor table for Pulse indexing */
/* ACELP pulse coding */
+extern const Word16 hi_to_low_tmpl[10];
extern const uint16_t low_len[10];
extern const uint16_t low_mask[10];
extern const uint16_t indx_fact[10];
@@ -384,7 +386,9 @@ extern const Word16 mid_H[64];
extern const Word16 mid_H16k[80];
extern const float filt_lp[1 + L_FILT];
+extern const Word16 filt_lp_fx[1 + L_FILT];
extern const float filt_lp_16kHz[1 + L_FILT16k];
+extern const Word16 filt_lp_16kHz_fx[1 + L_FILT16k];
extern const float tab_hup_l[SIZ_TAB_HUP_L]; /* NB post-filter */
extern const float tab_hup_s[SIZ_TAB_HUP_S]; /* NB post-filter */
@@ -448,6 +452,7 @@ extern const float ENR_ATT[5];
extern const Word16 ENR_ATT_fx[5];
extern const float HO_ATT[5];
+extern const Word16 HO_ATT_FX[5];
extern const int16_t hq_swb_bwe_nb_bits[];
@@ -615,7 +620,9 @@ extern const Word16 sigma_MSLVQ_fx[][16];
extern const float sigma_p[][16];
extern const Word16 sigma_p_fx[][16];
extern const float inv_sigma_MSLVQ[][16];
+extern const Word16 inv_sigma_MSLVQ_fx[][16];
extern const float inv_sigma_p[][16];
+extern const Word16 inv_sigma_p_fx[][16];
extern const float scales[][MAX_NO_SCALES * 2];
extern const float scales_p[][MAX_NO_SCALES * 2];
extern const Word16 scales_fx[][MAX_NO_SCALES * 2];
@@ -623,6 +630,7 @@ extern const Word16 scales_p_fx[][MAX_NO_SCALES * 2];
extern const int16_t predmode_tab_float[][6];
extern const Word16 predmode_tab[][6];
extern const float pl_HQ[];
+extern const Word16 pl_HQ_fx[];
extern const int16_t pi0[];
//extern const Word16 pi0_fx[];
@@ -681,6 +689,7 @@ extern const Word16 SN_IntraCoeff_fx[N_STAGE_VQ - 1][2][2];
extern const float scale_ARSN[];
extern const Word16 scale_ARSN_fx[];
extern const float scale_inv_ARSN[];
+extern const Word16 scale_inv_ARSN_fx[];
extern const float AR_TCVQ_CB_SUB1[2][128][2];
extern const float AR_TCVQ_CB_SUB2[2][64][2];
@@ -730,6 +739,7 @@ extern const Word16 tbl_mid_voi_wb_5b_fx[];
*-----------------------------------------------------------------*/
extern const float lsf_init[16];
+extern const Word16 lsf_init_fx[16];
extern const float means_wb_31bits_ma_lsf_float[16];
extern const float means_nb_31bits_ma_lsf_float[16];
extern const float *const lsf_means_float[2];
@@ -841,8 +851,11 @@ extern const Word16 cos_fb_exc_fx[32];
extern const float recip_order[];
extern const float win_lpc_shb[]; /* Window for calculating SHB LPC coeffs */
+extern const Word16 win_lpc_shb_fx[]; /* Window for calculating SHB LPC coeffs */
extern const float win_lpc_hb_wb[];
+extern const Word16 win_lpc_hb_wb_fx[];
extern const float ola_win_shb_switch_fold[];
+extern const Word16 ola_win_shb_switch_fold_fx[];
extern const float win_flatten[]; /* Window for calculating whitening filter for SHB excitation */
extern const Word16 win_flatten_fx[];
extern const float win_flatten_4k[]; /* Window for calculating whitening filter for WB excitation */
@@ -863,6 +876,8 @@ extern const Word16 Hilbert_coeffs_fx[4 * NUM_HILBERTS][HILBERT_ORDER1 + 1];
extern const float wac[];
extern const float wac_swb[];
+extern const Word16 wac_swb_h[];
+extern const Word16 wac_swb_l[];
extern const float wb_bwe_lsfvq_cbook_8bit[];
extern const Word16 wb_bwe_lsfvq_cbook_8bit_fx[];
@@ -913,7 +928,9 @@ extern const Word16 swb_hr_env_code3_fx[]; /* HR SWB BWE - envelope Q table - tw
extern const float allpass_poles_3_ov_2_flt[];
extern const Word16 allpass_poles_3_ov_2[];
extern const float decimate_3_ov_2_lowpass_num[];
+extern const Word16 decimate_3_ov_2_lowpass_num_fx[];
extern const float decimate_3_ov_2_lowpass_den[];
+extern const Word16 decimate_3_ov_2_lowpass_den_fx[];
/*------------------------------------------------------------------------------*
@@ -937,11 +954,13 @@ extern const int16_t swb_bwe_subband[];
extern const Word16 fb_bwe_subband[];
extern const Word16 fb_bwe_sm_subband[];
extern const float swb_inv_bwe_subband_width[];
+extern const Word16 swb_inv_bwe_subband_width_fx[];
extern const int16_t swb_bwe_sm_subband[];
extern const float smooth_factor[];
extern const Word16 smooth_factor_fx[];
extern const int16_t fb_bwe_subband_float[];
extern const float fb_inv_bwe_subband_width[];
+extern const Word16 fb_inv_bwe_subband_width_fx[];
extern const int16_t fb_bwe_sm_subband_float[];
extern const float fb_smooth_factor[];
extern const Word16 fb_smooth_factor_fx[];
@@ -963,6 +982,7 @@ extern const float Env_TR_Cdbk2[];
extern const Word16 Env_TR_Cdbk1_fx[];
extern const Word16 Env_TR_Cdbk2_fx[];
extern const float w_NOR[];
+extern const Word16 w_NOR_fx[];
extern const float Mean_env[];
extern const Word16 Mean_env_fx[];
extern const float Mean_env_fb[];
@@ -1360,9 +1380,12 @@ extern const float sinc[8][12];
extern const Word16 sinc_fx[8][12];
extern const float hvq_thr_adj[5];
+extern const Word16 hvq_thr_adj_fx[5];
+extern const Word16 hvq_index_mapping_fx[4];
extern const float hvq_peak_cb[1024];
extern const Word16 hvq_peak_cb_fx[];
extern const float hvq_class_c[16];
+extern const Word16 hvq_class_c_fx[16];
extern const int16_t hvq_cb_search_overlap24k[17];
extern const int16_t hvq_cb_search_overlap32k[21];
@@ -1394,6 +1417,7 @@ extern const float mfreq_loc[];
extern const int16_t mfreq_bindiv_loc[];
extern const float mean_gp[];
+extern const Word16 mean_gp_fx[];
extern const float dic_gp[];
extern const Word16 dic_gp_fx[];
extern const float Gain_mean[];
@@ -1835,6 +1859,7 @@ extern const struct TnsParameters tnsParameters48kHz_grouped[2];
extern const struct TnsParameters tnsParameters32kHz_Stereo[2];
extern const float tnsAcfWindow[TNS_MAX_FILTER_ORDER];
+extern const Word16 tnsAcfWindow_fx[TNS_MAX_FILTER_ORDER];
extern const ParamsBitMap tnsEnabledSWBTCX20BitMap;
extern const ParamsBitMap tnsEnabledSWBTCX10BitMap;
@@ -2045,6 +2070,7 @@ extern const Word16 Mid_H_phasedisp[L_SUBFR];
//ACcontextMapping_dec_fx.c
extern const Word16 Tab_esc_nb[4];
extern const Word16 pow2tab[15];
+extern const Word32 pow2[];
extern const Word16 Es_pred_qua[8];
extern const Word16 Es_pred_qua_2[16];
extern const Word16 T_DIV_L_Frame[];/*0Q15 * 2^-7 */
@@ -2054,6 +2080,32 @@ extern const Word16 pow_tilt_16k[64]; /* Q7 */
extern const Word16 pow_tilt_25_6k[64]; /* Q7 */
extern const Word16 pow_tilt_32k[64]; /* Q7 */
+/*EVS basop*/
+
+extern const Word16 num_nelp_lp_fx[NELP_LP_ORDER + 1];
+extern const Word16 den_nelp_lp_fx[NELP_LP_ORDER + 1];
+
+extern const Word16 fir_6k_8k_fx[]; /* HF BWE - band-pass filter coefficients */
+extern const Word16 pwf78_fx[17];
+
+enum FUNC_GAIN_ENC
+{
+ FUNC_GAIN_ENC_MLESS = 0, /* Memory-less gain coding */
+ FUNC_GAIN_ENC_2 = 1, /* AMR-WB gains quantizer (6bits/subfr (mode 4) or 7bits/subfr (mode 5)) */ /* !!! to be removed !!! */
+ FUNC_GAIN_ENC_UV, /* UV gains quantizer (5bits/subfr) */
+ FUNC_GAIN_ENC_GACELP_UV /* UV GACELP gain quantizer ((7=5-2bits/subfr) */
+};
+
+extern const Word16 Hamcos_Window[];
+extern const Word16 CNG_burst_att_fx[6][8];
+extern const Word16 lpc_weights_fx[];
+extern const Word16 SHBCB_SubGain5bit_12_fx[]; /* 5 bit Quantizer table for SHB gain shapes */
+extern const Word16 E_ROM_inter4_1_fx[PIT_UP_SAMP * L_INTERPOL1 + 1];
+extern const Word16 E_ROM_inter6_1_fx[PIT_UP_SAMP6 * L_INTERPOL1 + 1];
+extern const Word16 kLog2TableFrac_x[256];
+extern const Word16 kExp2TableFrac_x[256];
+extern const Word16 One_div_fx[];
+
//ivas_lfe_dec_fx.c
extern const Word32 tbl_two_pow_shift_by_4[35]; /* Q30 */
diff --git a/lib_enc/ACcontextMapping_enc_fx.c b/lib_enc/ACcontextMapping_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..e613c9096103bed0a6445d6aa0292d79c8af6993
--- /dev/null
+++ b/lib_enc/ACcontextMapping_enc_fx.c
@@ -0,0 +1,1580 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "basop_util.h"
+#include "cnst.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h"
+#include "rom_com.h"
+//#include "prot_fx.h"
+#include "prot_fx_enc.h"
+
+/*-------------------------------------------------------------------*
+ * ACcontextMapping_encode2_no_mem_s17_LC_fx()
+ *
+ * Arithmetic encoder
+ *-------------------------------------------------------------------*/
+ /**
+ * \brief Arithmetic encoder
+ * \param[i] x
+ * \param[o] ntuples amount of encoded tuple (2 lines per tuple)
+ * \param[i] nt
+ * \param[i] nbbits
+ * \param[i] resQMaxBits
+ * \return none
+ */
+void ACcontextMapping_encode2_no_mem_s17_LC_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */
+ Word16 *x,
+ Word16 nt,
+ Word16 lastnz,
+ Word16 nbbits,
+ Word16 resQMaxBits,
+ CONTEXT_HM_CONFIG *hm_cfg
+)
+{
+ Word16 ptr[BITBUFSIZE];
+ TastatEnc as, as_overflow;
+ Word16 bp, bp_overflow;
+ Word16 a1, b1, a1_i, b1_i, k;
+ Word16 t, pki, lev1;
+ Word16 rateFlag;
+ Word16 value;
+ Word16 nbbits_ntuples, nbbits_lsbs, nbbits_signs, nbbits_signs_overflow, nbbits_lsbs_overflow, flag_overflow;
+ Word16 *lsbs_bits2;
+ Word16 tmp;
+ Word16 nt_half;
+ Word16 c[2], *ctx;
+ Word16 p1, p2;
+ Word16 ii[2], idx1, idx2, idx;
+ Word16 numPeakIndicesOrig, numHoleIndices;
+ get_next_coeff_function get_next_coeff;
+ Word16 signs[N_MAX];
+ Word16 nbbits_m2;
+
+ a1 = 0; /* to avoid compilation warnings */
+ b1 = 0; /* to avoid compilation warnings */
+
+
+ /* Rate flag */
+ rateFlag = 0;
+ move16();
+ if (GT_16(nbbits, 400))
+ {
+ rateFlag = 2 << NBITS_CONTEXT;
+ move16();
+ }
+
+ /* Init */
+ nt_half = shr(nt, 1);
+ c[0] = c[1] = 0;
+ move16();
+ move16();
+
+ /* Bits for encoding the number of encoded tuples */
+ nbbits_ntuples = sub(14, norm_s(negate(nt)));
+
+ t = 0;
+ move16();
+ bp = nbbits_ntuples;
+ move16();
+ nbbits_signs = 0;
+ move16();
+ nbbits_lsbs = 0;
+ move16();
+ nbbits_m2 = sub(nbbits, 2);
+ flag_overflow = 0;
+ move16();
+
+ IF (hm_cfg) /* mapped domain */
+ {
+ numPeakIndicesOrig = hm_cfg->numPeakIndices;
+ move16();
+ hm_cfg->numPeakIndices = s_min(hm_cfg->numPeakIndices, lastnz);
+ move16();
+ numHoleIndices = sub(lastnz, hm_cfg->numPeakIndices);
+
+ /* Mark hole indices beyond lastnz as pruned */
+ FOR (k=numHoleIndices; knumHoleIndices; ++k)
+ {
+ hm_cfg->holeIndices[k] = add(hm_cfg->holeIndices[k], nt);
+ move16();
+ }
+
+ ii[0] = numPeakIndicesOrig;
+ move16();
+ ii[1] = 0;
+ move16();
+
+ get_next_coeff = get_next_coeff_mapped;
+ move16();
+ }
+ ELSE /* unmapped domain */
+ {
+ ii[0] = 0;
+ move16();
+
+ p1 = p2 = 0;
+ move16();
+ move16();
+
+ get_next_coeff = get_next_coeff_unmapped;
+ move16();
+
+ /* Find last non-zero tuple */
+ /* ensure termination of while loop by dummy value */
+ a1 = x[0];
+ move16();
+ x[0] = 1;
+ move16();
+
+ WHILE (s_or(x[lastnz-1], x[lastnz-2]) == 0)
+ {
+ lastnz = sub(lastnz, 2);
+ }
+ x[0] = a1;
+ move16();
+ }
+
+ lsbs_bits2 = ptr+nbbits-1;
+
+ /*Start Encoding*/
+ ari_start_encoding_14bits_fx(&as);
+
+ /*Main Loop through the 2-tuples*/
+ b1_i = -1;
+ move16();
+ FOR (k = 0; k < lastnz; k += 2)
+ {
+ /* First coefficient */
+ a1_i = get_next_coeff(ii, &p1, &idx1, hm_cfg);
+
+ /* Second coefficient */
+ b1_i = get_next_coeff(ii, &p2, &idx2, hm_cfg);
+
+ idx = s_min(idx1, idx2);
+
+ /* Get context */
+ ctx = &c[s_or(p1, p2)];
+ move16();
+ /* _DIFF_FLOAT_FIX_ float is using t as UWord16 */
+ t = add(*ctx, rateFlag);
+ if (GT_16(idx, nt_half))
+ {
+ t = add(t, 1 << NBITS_CONTEXT);
+ }
+
+ /* Init current 2-tuple encoding */
+ if (flag_overflow != 0)
+ {
+ x[a1_i] = 0;
+ move16();
+ }
+ if (flag_overflow != 0)
+ {
+ x[b1_i] = 0;
+ move16();
+ }
+
+ a1 = abs_s(x[a1_i]);
+ b1 = abs_s(x[b1_i]);
+
+ lev1 = -1;
+ move16();
+
+ /*Copy states*/
+ ari_copy_states_fx(&as, &as_overflow);
+ bp_overflow = bp;
+ move16();
+ nbbits_signs_overflow = nbbits_signs;
+ move16();
+ nbbits_lsbs_overflow = nbbits_lsbs;
+ move16();
+
+ /*Signs encoding*/
+ signs[nbbits_signs] = lshr(x[a1_i], 15);
+ move16();
+ if (a1 > 0)
+ {
+ nbbits_signs = add(nbbits_signs, 1);
+ }
+ signs[nbbits_signs] = lshr(x[b1_i], 15);
+ move16();
+ if (b1 > 0)
+ {
+ nbbits_signs = add(nbbits_signs, 1);
+ }
+
+ /* MSBs coding */
+ WHILE (GE_16(s_max(a1, b1), A_THRES))
+ {
+ tmp = add(t, Tab_esc_nb[lev1+1]);
+ assert(tmp >= 0 && tmp < 4096);
+ pki = ari_lookup_s17_LC[tmp];
+ move16();
+ bp = ari_encode_14bits_ext_fx(ptr, bp, &as, VAL_ESC, ari_pk_s17_LC_ext[pki]);
+
+ *lsbs_bits2-- = s_and(a1, 1);
+ move16();
+ *lsbs_bits2-- = s_and(b1, 1);
+ move16();
+
+ /* LSBs bit counting */
+ nbbits_lsbs = add(nbbits_lsbs, 2);
+
+ a1 = shr(a1, 1);
+ b1 = shr(b1, 1);
+
+ lev1 = s_min(add(lev1, 1), 2);
+ }
+
+ tmp = add(t, Tab_esc_nb[lev1+1]);
+ assert(tmp >= 0 && tmp < 4096);
+ pki = ari_lookup_s17_LC[tmp];
+ move16();
+ bp = ari_encode_14bits_ext_fx(ptr, bp, &as, add(a1, shl(b1, A_THRES_SHIFT)), ari_pk_s17_LC_ext[pki]);
+
+ /* Check bit budget */
+ IF (GT_16(add(add(add(bp, extract_l(as.value)), nbbits_signs), nbbits_lsbs), nbbits_m2))
+ {
+ ari_copy_states_fx(&as_overflow, &as);
+ bp = bp_overflow;
+ move16();
+
+ IF (flag_overflow == 0)
+ {
+ nbbits_signs = nbbits_signs_overflow;
+ move16();
+ nbbits_lsbs = nbbits_lsbs_overflow;
+ move16();
+ IF (hm_cfg)
+ {
+ flag_overflow = 1;
+ move16();
+
+ /* Code from now only zeros */
+ x[a1_i] = 0;
+ move16();
+ x[b1_i] = 0;
+ move16();
+ lev1 = -1;
+ move16();
+
+ assert(t >= 0 && t < 4096);
+ pki = ari_lookup_s17_LC[t];
+ move16();
+ bp = ari_encode_14bits_ext_fx(ptr, bp, &as, 0, ari_pk_s17_LC_ext[pki]);
+
+ IF (GT_16(add(add(add(bp, extract_l(as.value)), nbbits_signs), nbbits_lsbs), nbbits_m2))
+ {
+ ari_copy_states_fx(&as_overflow, &as);
+ bp = bp_overflow;
+ move16();
+ BREAK;
+ }
+ }
+ ELSE
+ {
+ BREAK;
+ }
+ }
+ ELSE
+ {
+ BREAK;
+ }
+ }
+
+ /* Update context for next 2-tuple */
+ IF (EQ_16(p1, p2)) /* peak-peak or hole-hole context */
+ {
+ if (lev1 > 0) t = add(12, lev1);
+ if (lev1 <= 0) t = add(a1, b1);
+ if (lev1 == 0) t = add(t, t);
+
+ *ctx = add(shl(s_and(*ctx, 0xf), 4), add(t, 1));
+ move16();
+ }
+ ELSE /* mixed context */
+ {
+ IF (s_and(idx1, 1)) /* update first context */
+ {
+ c[p1] = update_mixed_context(c[p1], abs_s(x[a1_i]));
+ move16();
+ }
+
+ IF (s_and(idx2, 1)) /* update second context */
+ {
+ c[p2] = update_mixed_context(c[p2], abs_s(x[b1_i]));
+ move16();
+ }
+ }
+ } /*end of the 2-tuples loop*/
+
+ /* End arithmetic coder, overflow management */
+ bp = ari_done_encoding_14bits_fx(ptr, bp, &as);
+
+ /* Overflow is detected */
+ IF (NE_16(k, lastnz))
+ {
+ IF (hm_cfg)
+ {
+ /* Fill with zero to be sure that the decoder finishes the MSB decoding at the same position */
+ tmp = sub(nbbits, add(nbbits_signs, nbbits_lsbs));
+ set16_fx(&ptr[bp], 0, sub(tmp, bp));
+ bp = tmp;
+ move16();
+ }
+ if (!hm_cfg)
+ {
+ lastnz = k;
+ move16();
+ }
+ }
+
+ /* Push number of encoded tuples */
+ value = sub(shr(lastnz, 1), 1);
+ push_next_indice_fx(hBstr, value, nbbits_ntuples);
+
+ /* Push arithmetic coded bits */
+ push_next_bits_fx(hBstr, &ptr[nbbits_ntuples], sub(bp, nbbits_ntuples));
+
+ /* Push sign bits */
+ push_next_bits_fx(hBstr, signs, nbbits_signs);
+ bp = add(bp, nbbits_signs);
+
+ /*write residual Quantization bits*/
+ tmp = s_min(sub(sub(nbbits, bp), nbbits_lsbs), resQMaxBits);
+ FOR (k = 0; k < tmp; k++)
+ {
+ ptr[nbbits-1-nbbits_lsbs-k] = x[nt+k];
+ move16();
+ }
+ /* Write filler bits */
+ tmp = sub(nbbits, add(bp, nbbits_lsbs));
+ FOR (; kindexBuffer;
+ move16();
+ }
+
+ lobs[0] = 4;
+ move16();
+ lobs[1] = shr(length, 1); /* length/2 */ move16();
+ lobs[2] = add(lobs[1], shr(length, 2));
+ move16();
+ lobs[3] = add(lobs[2], shr(length, 3));
+ move16();
+
+ last_nz = 0;
+ move16();
+ i = length;
+ move16();
+ FOR (stage=3; stage>=0; --stage)
+ {
+ IF (hm_cfg) /* mapped kernel */
+ {
+ FOR (; i >= lobs[stage]; i-=2)
+ {
+ if (x[tmp[i-2]] != 0)
+ {
+ last_nz = s_max(last_nz, i);
+ }
+ if (x[tmp[i-1]] != 0)
+ {
+ last_nz = s_max(last_nz, i);
+ }
+ }
+ }
+ ELSE /* unmapped kernel */
+ {
+ FOR (; i >= lobs[stage]; i-=2)
+ {
+ if (x[i-2] != 0)
+ {
+ last_nz = s_max(last_nz, i);
+ }
+ if (x[i-1] != 0)
+ {
+ last_nz = s_max(last_nz, i);
+ }
+ }
+ }
+ IF (last_nz > 0)
+ {
+ BREAK;
+ }
+ }
+
+ return s_max(last_nz, 2);
+}
+/*-------------------------------------------------------------------*
+ * ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+Word16 ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx(
+ const Word16 *x,
+ Word16 nt,
+ Word16 *lastnz_out,
+ Word16 *nEncoded,
+ Word16 target,
+ Word16 *stop,
+ CONTEXT_HM_CONFIG *hm_cfg
+)
+{
+ Word16 a1, b1, a1_i, b1_i;
+ Word16 k, t, pki, lev1;
+ Word16 lastnz, lastnz2;
+ Word16 rateFlag;
+ Word16 nbits_old, nbits;
+ Word16 stop2;
+ Word16 cum_freq_norm, cum_freq_norm_e;
+ Word32 proba;
+ Word16 nlz;
+ const UWord16 *cum_freq;
+ Word16 symbol;
+ const Word8 *lookup;
+ Word16 nt_half;
+ Word16 c[2], *ctx;
+ Word16 p1, p2;
+ Word16 ii[2], idx1, idx2, idx;
+ Word16 numPeakIndicesOrig=0, numHoleIndices=0; /* initialize just to avoid compiler warning */
+ get_next_coeff_function get_next_coeff;
+
+
+ /* Rate flag */
+ rateFlag = 0;
+ move16();
+ if (GT_16(target, 400))
+ {
+ rateFlag = 2 << NBITS_CONTEXT;
+ move16();
+ }
+
+ /* proba coded on 14bits -> proba=1 */
+ proba = L_deposit_l(16384);
+
+ /* Init */
+ nt_half = shr(nt, 1);
+ stop2 = 0;
+ move16();
+ c[0] = c[1] = 0;
+ move16();
+ move16();
+
+ /* bits to encode lastnz + 2 bits headroom */
+ nbits = sub(2+14, norm_s(sub(nt, 1)));
+ nbits_old = nbits;
+ move16();
+ nbits = sub(nbits, target);
+
+ /* Find last non-zero tuple in the mapped domain signal */
+ lastnz = find_last_nz_pair(x, nt, hm_cfg);
+
+ /* At least one tuple is coded */
+ lastnz2 = 2;
+ move16();
+
+ IF (hm_cfg) /* mapped domain */
+ {
+ numPeakIndicesOrig = hm_cfg->numPeakIndices;
+ move16();
+ hm_cfg->numPeakIndices = s_min(hm_cfg->numPeakIndices, lastnz);
+ move16();
+ numHoleIndices = sub(lastnz, hm_cfg->numPeakIndices);
+
+ /* Mark hole indices beyond lastnz as pruned */
+ FOR (k=numHoleIndices; knumHoleIndices; ++k)
+ {
+ hm_cfg->holeIndices[k] = add(hm_cfg->holeIndices[k], nt);
+ move16();
+ }
+
+ ii[0] = numPeakIndicesOrig;
+ move16();
+ ii[1] = 0;
+ move16();
+
+ get_next_coeff = get_next_coeff_mapped;
+ move16();
+ }
+ ELSE /* unmapped domain */
+ {
+ ii[0] = 0;
+ move16();
+
+ p1 = p2 = 0;
+ move16();
+ move16();
+
+ get_next_coeff = get_next_coeff_unmapped;
+ move16();
+ }
+
+ /* Main Loop through the 2-tuples */
+ FOR (k=0; k 0)
+ {
+ nbits = add(nbits, 1);
+ }
+
+ if (b1 > 0)
+ {
+ nbits = add(nbits, 1);
+ }
+
+ /* pre-compute address of ari_pk_s17_LC_ext[0][Val_esc] to avoid doing it multiple times inside the loop */
+
+ /* check while condition */
+
+ /* MSBs coding */
+ lookup = &ari_lookup_s17_LC[t] + (1 << (NBITS_CONTEXT+NBITS_RATEQ)); /* address calculation not counted */
+ WHILE (GE_16(s_max(a1, b1), A_THRES))
+ {
+ pki = lookup[lev1];
+ move16();
+ cum_freq = ari_pk_s17_LC_ext[pki] + VAL_ESC; /* address calculation not counted */
+ /*p1*p2=proba on 28 bits: p=0.5->power(2,27)*/
+
+ cum_freq_norm_e = norm_s(cum_freq[0]);
+ cum_freq_norm = shl(cum_freq[0], cum_freq_norm_e);
+ proba = Mpy_32_16_1(proba, cum_freq_norm);
+ proba = L_shl(proba, sub(14, cum_freq_norm_e));
+
+ /*Number of leading zero computed in one cycle=norm_l() in BASOP*/
+ nlz = sub(norm_l(proba), 2);
+ proba = L_shl(proba, sub(nlz, 15));
+
+ nbits = add(nbits, nlz);
+ /*addition added as shift not done in norm_l(): real shift = 14-nlz*/
+ /*proba is rounded down on 14 bits ->automatic over-estimation of bit consumption*/
+
+ a1 = shr(a1, 1);
+ b1 = shr(b1, 1);
+ lev1 = s_min(add(lev1, 1 << (NBITS_CONTEXT+NBITS_RATEQ)), 2 << (NBITS_CONTEXT+NBITS_RATEQ));
+ }
+
+ pki = lookup[lev1];
+ move16();
+ symbol = add(a1, shl(b1, A_THRES_SHIFT));
+ cum_freq = ari_pk_s17_LC_ext[pki] + symbol; /* address calculation not counted */
+ /*p1*p2=proba on 28 bits: p=0.5->power(2,27)*/
+
+ cum_freq_norm = sub(cum_freq[0], cum_freq[1]);
+ cum_freq_norm_e = norm_s(cum_freq_norm);
+ cum_freq_norm = shl(cum_freq_norm, cum_freq_norm_e);
+ proba = Mpy_32_16_1(proba, cum_freq_norm);
+ proba = L_shl(proba, sub(15, cum_freq_norm_e));
+
+ /*Number of leading zero computed in one cycle=norm_l() in BASOP*/
+ nlz = sub(norm_l(proba), 3);
+ proba = L_shl(proba, sub(nlz, 14));
+
+ nbits = add(nbits, nlz);
+ /*addition added as shift not done in norm_l(): real shift = 14-nlz*/
+ /*proba is rounded down on 14 bits ->automatic over-estimation of bit consumption*/
+
+ /* Should we truncate? */
+
+ IF (nbits > 0)
+ {
+ stop2 = 1;
+ move16();
+
+ IF (*stop)
+ {
+ BREAK;
+ }
+ }
+ ELSE
+ {
+ test();
+ test();
+ IF (hm_cfg || k==0 || s_or(x[a1_i], x[b1_i]))
+ {
+ nbits_old = add(nbits, target);
+ lastnz2 = add(b1_i, 1);
+ }
+ }
+
+ /* Update context for next 2-tuple */
+ IF (EQ_16(p1, p2)) /* peak-peak or hole-hole context */
+ {
+ lev1 = shr(lev1, NBITS_CONTEXT+NBITS_RATEQ);
+ if (lev1 > 0) t = add(12, lev1);
+ if (lev1 <= 0) t = add(a1, b1);
+ if (lev1 == 0) t = add(t, t);
+
+ *ctx = add(shl(s_and(*ctx, 0xf), 4), add(t, 1));
+ move16();
+ }
+ ELSE /* mixed context */
+ {
+ IF (s_and(idx1, 1)) /* update first context */
+ {
+ c[p1] = update_mixed_context(c[p1], abs_s(x[a1_i]));
+ move16();
+ }
+
+ IF (s_and(idx2, 1)) /* update second context */
+ {
+ c[p2] = update_mixed_context(c[p2], abs_s(x[b1_i]));
+ move16();
+ }
+ }
+ } /* end of the 2-tuples loop */
+
+ nbits = add(nbits, target);
+
+ /* Output */
+ if (*stop)
+ {
+ nbits = nbits_old;
+ move16();
+ }
+
+ if (stop2)
+ {
+ stop2 = nbits;
+ move16();
+ }
+ *nEncoded = lastnz2;
+ move16();
+ *stop = stop2;
+ move16();
+ if (lastnz_out)
+ {
+ *lastnz_out = lastnz;
+ move16();
+ }
+
+ IF (hm_cfg)
+ {
+ /* Restore hole indices beyond lastnz */
+ FOR (k=numHoleIndices; knumHoleIndices; ++k)
+ {
+ hm_cfg->holeIndices[k] = sub(hm_cfg->holeIndices[k], nt);
+ move16();
+ }
+ hm_cfg->numPeakIndices = numPeakIndicesOrig;
+ move16();
+ }
+
+
+ return nbits_old;
+}
+
+#ifdef IVAS_CODE_RANGE_CODER
+
+/* Range Coder Functions */
+
+/*-------------------------------------------------------------------*
+ * RCcontextMapping_encode2_no_mem_s17_LCS()
+ *
+ * Range encoder
+ *-------------------------------------------------------------------*/
+
+void RCcontextMapping_encode2_no_mem_s17_LCS(
+ BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */
+ int16_t* x,
+ const int16_t nt,
+ int16_t lastnz,
+ const int16_t nbbits,
+ const int16_t resQMaxBits,
+ CONTEXT_HM_CONFIG* hm_cfg)
+{
+ int16_t ptr[BITBUFSIZE];
+ RangeUniEncState rc_st_enc;
+ int16_t bp;
+ int16_t rc_tot_bits; /* No. of bits returned by range coder */
+ int16_t pki, lev1;
+ uint16_t t;
+ int16_t rateFlag;
+ int16_t value;
+ int16_t nbbits_ntuples, nbbits_lsbs, nbbits_signs;
+ int16_t* lsbs_bits;
+ int16_t nt_half;
+ int16_t signs[N_MAX];
+ int16_t a1, b1, k;
+
+ a1 = 0; /* to avoid compilation warnings */
+ b1 = 0; /* to avoid compilation warnings */
+
+ /* Init */
+ nt_half = nt >> 1;
+
+ /* Bits for encoding the number of encoded tuples */
+ nbbits_ntuples = 0;
+ k = 1;
+ while (k < nt / 2)
+ {
+ nbbits_ntuples++;
+ k = k << 1;
+ }
+
+ t = 0;
+ nbbits_signs = 0;
+ nbbits_lsbs = 0;
+
+ if (hm_cfg)
+ {
+ int16_t a1_i, b1_i;
+ int32_t c[2], * ctx;
+ int32_t p1, p2;
+ int16_t ii[2];
+ int16_t idx1, idx2, idx;
+ int16_t numPeakIndicesOrig, numHoleIndices;
+
+ /* Rate flag */
+ if (nbbits > 400)
+ {
+ rateFlag = 2 << NBITS_CONTEXT;
+ }
+ else
+ {
+ rateFlag = 0;
+ }
+
+ c[0] = c[1] = 0;
+
+ /* mapped domain */
+ numPeakIndicesOrig = hm_cfg->numPeakIndices;
+ hm_cfg->numPeakIndices = min(hm_cfg->numPeakIndices, lastnz);
+ numHoleIndices = lastnz - hm_cfg->numPeakIndices;
+
+ /* Mark hole indices beyond lastnz as pruned */
+ for (k = numHoleIndices; k < hm_cfg->numHoleIndices; ++k)
+ {
+ hm_cfg->holeIndices[k] = hm_cfg->holeIndices[k] + nt;
+ }
+
+ ii[0] = numPeakIndicesOrig;
+ ii[1] = 0;
+
+ p1 = p2 = 0; /* to avoid compilation warnings */
+
+ lsbs_bits = ptr + nbbits - 1;
+
+ /*Start Encoding*/
+ /* Initialize range encoder */
+ rc_uni_enc_init(&rc_st_enc);
+
+ /*Main Loop through the 2-tuples*/
+ b1_i = -1;
+
+ for (k = 0; k < lastnz; k += 2)
+ {
+ a1_i = get_next_coeff_mapped(ii, &p1, &idx1, hm_cfg);
+ b1_i = get_next_coeff_mapped(ii, &p2, &idx2, hm_cfg);
+
+ idx = min(idx1, idx2);
+
+ /* Get context */
+ ctx = &c[p1 | p2];
+
+ t = (uint16_t)(*ctx + rateFlag);
+ t += (nt_half >= idx) ? 0 : (1 << NBITS_CONTEXT);
+
+ /* Init current 2-tuple encoding */
+ a1 = (int16_t)abs(x[a1_i]);
+ b1 = (int16_t)abs(x[b1_i]);
+
+ lev1 = -1;
+
+ /*Signs encoding*/
+ if (a1 > 0)
+ {
+ signs[nbbits_signs++] = ((uint16_t)x[a1_i] >> (sizeof(uint16_t) * 8 - 1));
+ }
+
+ if (b1 > 0)
+ {
+ signs[nbbits_signs++] = ((uint16_t)x[b1_i] >> (sizeof(uint16_t) * 8 - 1));
+ }
+
+ /* MSBs coding */
+ while (max(a1, b1) >= A_THRES)
+ {
+ pki = ari_lookup_s17_LC[t + ((lev1 + 1) << (NBITS_CONTEXT + NBITS_RATEQ))];
+ rc_uni_enc_encode_symbol_fastS(&rc_st_enc, VAL_ESC, cum_freq_ari_pk_s17_LC_ext[pki], sym_freq_ari_pk_s17_LC_ext[pki], 14); /* Encode ESC symbol */
+
+ *lsbs_bits-- = a1 & 1;
+ *lsbs_bits-- = b1 & 1;
+
+ /* LSBs bit counting */
+ nbbits_lsbs += 2;
+
+ a1 >>= 1;
+ b1 >>= 1;
+
+ lev1 = min(lev1 + 1, 2);
+ }
+
+ pki = ari_lookup_s17_LC[t + ((lev1 + 1) << (NBITS_CONTEXT + NBITS_RATEQ))];
+ rc_uni_enc_encode_symbol_fastS(&rc_st_enc, a1 + A_THRES * b1, cum_freq_ari_pk_s17_LC_ext[pki], sym_freq_ari_pk_s17_LC_ext[pki], 14); /* Encode MSB symbol */
+
+ /*Confirm that there is no overflow, i.e. bit-budget has not exceeded */
+#ifdef DEBUGGING
+ assert(rc_uni_enc_virtual_finish(&rc_st_enc) <= nbbits - nbbits_signs - nbbits_lsbs - nbbits_ntuples);
+#endif
+
+ /* Update context for next 2-tuple */
+ if (p1 == p2)
+ {
+ /* peak-peak or hole-hole context */
+
+ if (lev1 <= 0)
+ {
+ t = 1 + (a1 + b1) * (lev1 + 2);
+ }
+ else
+ {
+ t = 13 + lev1;
+ }
+
+ *ctx = (*ctx & 0xf) * 16 + t;
+ }
+ else
+ {
+ /* mixed context */
+
+ if (idx1 & 1)
+ {
+ /* update first context */
+ c[p1] = update_mixed_context(c[p1], (int16_t)abs(x[a1_i]));
+ }
+
+ if (idx2 & 1)
+ {
+ /* update second context */
+ c[p2] = update_mixed_context(c[p2], (int16_t)abs(x[b1_i]));
+ }
+ }
+
+ } /*end of the 2-tuples loop*/
+ }
+ else /* if (!hm_cfg) */
+ {
+ int16_t cp;
+ int16_t esc_nb, rateQ;
+ uint16_t s;
+
+ /* Rate flag */
+ if (nbbits > 400)
+ {
+ rateFlag = 2;
+ }
+ else
+ {
+ rateFlag = 0;
+ }
+
+ s = 0;
+
+ /* Find last non-zero tuple */
+ /* ensure termination of while loop by dummy value */
+ a1 = x[0];
+ x[0] = 1; /* ensure first tuple is non-zero */
+
+ while (x[lastnz - 1] == 0 && x[lastnz - 2] == 0)
+ {
+ lastnz -= 2;
+ }
+ x[0] = a1;
+
+ lsbs_bits = ptr + nbbits - 1;
+
+ /*Start Encoding*/
+ /* Initialize range encoder */
+ rc_uni_enc_init(&rc_st_enc);
+
+ /*Main Loop through the 2-tuples*/
+ for (k = 0; k < lastnz; k += 2)
+ {
+
+ /* Init current 2-tuple encoding */
+ a1 = (int16_t)abs(x[k + 0]);
+ b1 = (int16_t)abs(x[k + 1]);
+
+ lev1 = 0;
+ esc_nb = 0;
+
+ /*Signs encoding*/
+ if (a1 > 0)
+ {
+ signs[nbbits_signs++] = ((uint16_t)x[k + 0] >> (sizeof(uint16_t) * 8 - 1));
+ }
+
+ if (b1 > 0)
+ {
+ signs[nbbits_signs++] = ((uint16_t)x[k + 1] >> (sizeof(uint16_t) * 8 - 1));
+ }
+
+ rateQ = rateFlag + (k > (nt >> 1));
+
+ /* MSBs coding */
+ while (max(a1, b1) >= A_THRES)
+ {
+ pki = ari_lookup_s17_LC[t + ((rateQ) << NBITS_CONTEXT) + (esc_nb << (NBITS_CONTEXT + NBITS_RATEQ))];
+ rc_uni_enc_encode_symbol_fastS(&rc_st_enc, VAL_ESC, cum_freq_ari_pk_s17_LC_ext[pki], sym_freq_ari_pk_s17_LC_ext[pki], 14); /* Encode ESC symbol */
+
+ *lsbs_bits-- = a1 & 1;
+ *lsbs_bits-- = b1 & 1;
+
+ /* LSBs bit counting */
+ nbbits_lsbs += 2;
+
+ a1 >>= 1;
+ b1 >>= 1;
+
+ lev1++;
+ esc_nb = min(lev1, 3);
+ }
+
+ pki = ari_lookup_s17_LC[t + ((rateQ) << NBITS_CONTEXT) + (esc_nb << (NBITS_CONTEXT + NBITS_RATEQ))];
+ rc_uni_enc_encode_symbol_fastS(&rc_st_enc, a1 + A_THRES * b1, cum_freq_ari_pk_s17_LC_ext[pki], sym_freq_ari_pk_s17_LC_ext[pki], 14); /* Encode MSB symbol */
+
+ /*Confirm that there is no overflow, i.e. bit-budget has not exceeded */
+#ifdef DEBUGGING
+ assert(rc_uni_enc_virtual_finish(&rc_st_enc) <= nbbits - nbbits_signs - nbbits_lsbs - nbbits_ntuples);
+#endif
+
+ /* Update context for next 2-tuple */
+ if (esc_nb < 2)
+ {
+ cp = 1 + ((a1 + b1) * (esc_nb + 1));
+ }
+ else
+ {
+ cp = 12 + esc_nb;
+ }
+
+ /*Shift old 4 bits, replace last 4 bits*/
+ s = (s << 4) + cp;
+ t = s & 0xFF;
+
+ } /*end of the 2-tuples loop*/
+ }
+
+ /* Finish range encoder */
+ rc_tot_bits = rc_uni_enc_finish(&rc_st_enc); /* No. of bits consumed by range coder */
+ bp = rc_tot_bits + nbbits_ntuples; /* Update bitstream pointer */
+
+ /* Cross-check that there is no overflow */
+#ifdef DEBUGGING
+ assert(k == lastnz);
+#endif
+
+ /* Push number of encoded tuples */
+ value = (lastnz >> 1) - 1;
+ push_next_indice(hBstr, value, nbbits_ntuples);
+
+ /* Push range coded bits from byte_buffer to bitstream */
+ /* 1) Push all complete bytes, one byte at a time */
+ for (k = 0; k < (rc_tot_bits >> 3); k++)
+ {
+ push_next_indice(hBstr, rc_st_enc.byte_buffer[k], 8);
+ }
+ /* 2) Push remaining bits */
+ if ((rc_tot_bits & 7) != 0)
+ {
+ push_next_indice(hBstr, rc_st_enc.byte_buffer[k] >> (8 - (rc_tot_bits & 7)), rc_tot_bits & 7);
+ }
+
+ /* Push sign bits */
+ push_next_bits(hBstr, (uint16_t*)signs, nbbits_signs);
+ bp += nbbits_signs;
+
+ /*write residual Quantization bits*/
+
+ for (k = 0; k < min(nbbits - bp - nbbits_lsbs, resQMaxBits); k++)
+ {
+ ptr[nbbits - 1 - nbbits_lsbs - k] = x[nt + k];
+ }
+ /* Write filler bits */
+ for (; k < nbbits - bp - nbbits_lsbs; ++k)
+ {
+ ptr[nbbits - 1 - nbbits_lsbs - k] = 0;
+ }
+
+ /* Check for debugging */
+ assert(bp + k <= nbbits);
+
+ /* Push the rest of the buffer */
+ push_next_bits(hBstr, (uint16_t*)&ptr[bp], nbbits - bp);
+
+ /* return (bp+nbbits_lsbs);*/ /*return only for debug plot*/
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * RCcontextMapping_encode2_estimate_no_mem_s17_LCS()
+ *
+ * Range coder bit-estimation
+ *-------------------------------------------------------------------*/
+
+int16_t RCcontextMapping_encode2_estimate_no_mem_s17_LCS(
+ int16_t* x, /* Spectral coefficients */
+ const int16_t nt, /* L - size of spectrum (no. of spectral coefficients) */
+ int16_t* lastnz_out,
+ int16_t* nEncoded, /* No. of spectral coefficients that can be coded without an overflow occuring */
+ const int16_t target, /* Target bits */
+ int16_t* stop,
+ int16_t mode,
+ CONTEXT_HM_CONFIG* hm_cfg /* context-based harmonic model configuration */
+)
+{
+ /* Common variables */
+ int16_t a1, b1;
+ int16_t k, pki, lev1;
+ uint16_t t;
+ int16_t lastnz, lastnz2;
+ int16_t rateFlag;
+ float bit_estimate;
+ int16_t symbol;
+ const uint8_t* lookup;
+ float nbits2;
+
+ /* Initialization */
+ bit_estimate = 2.0f;
+ nbits2 = 0.f;
+
+ /* bits to encode lastnz */
+ k = 1;
+
+ while (k < nt / 2)
+ {
+ bit_estimate++;
+ k = k << 1;
+ /* check while condition */
+ }
+
+ nbits2 = bit_estimate;
+
+ if (hm_cfg)
+ {
+ int16_t a1_i, b1_i;
+ int16_t stop2;
+ int16_t total_output_bits;
+ int16_t nt_half;
+ int32_t c[2], * ctx;
+ int32_t p1, p2;
+ int16_t ii[2];
+ int16_t idx1, idx2, idx;
+ int16_t numPeakIndicesOrig = 0, numHoleIndices = 0; /* only to avoid compiler warning */
+
+ /* Rate flag */
+ if (target > 400)
+ {
+ rateFlag = 2 << NBITS_CONTEXT; /* Select context-A for higher bitrates */
+ }
+ else
+ {
+ rateFlag = 0; /* Select context-B for lower bitrates */
+ }
+
+ nt_half = nt >> 1;
+ stop2 = 0;
+ c[0] = c[1] = 0;
+
+ /* Find last non-zero tuple in the mapped domain signal */
+ lastnz = find_last_nz_pair(x, nt, hm_cfg);
+
+ lastnz2 = 2;
+
+ /* mapped domain */
+ numPeakIndicesOrig = hm_cfg->numPeakIndices;
+ hm_cfg->numPeakIndices = min(hm_cfg->numPeakIndices, lastnz);
+ numHoleIndices = lastnz - hm_cfg->numPeakIndices;
+
+ /* Mark hole indices beyond lastnz as pruned */
+ for (k = numHoleIndices; k < hm_cfg->numHoleIndices; ++k)
+ {
+ hm_cfg->holeIndices[k] = hm_cfg->holeIndices[k] + nt;
+ }
+
+ ii[0] = numPeakIndicesOrig;
+ ii[1] = 0;
+
+ p1 = p2 = 0; /* to avoid compilation warnings */
+
+ /* Main Loop through the 2-tuples */
+ for (k = 0; k < lastnz; k += 2)
+ {
+ a1_i = get_next_coeff_mapped(ii, &p1, &idx1, hm_cfg);
+ b1_i = get_next_coeff_mapped(ii, &p2, &idx2, hm_cfg);
+
+ idx = min(idx1, idx2);
+
+ /* Get context */
+ ctx = &c[p1 | p2];
+
+ t = (uint16_t)(*ctx + rateFlag);
+ t += (nt_half >= idx) ? 0 : (1 << NBITS_CONTEXT);
+
+ /* Init current 2-tuple encoding */
+ a1 = (int16_t)abs(x[a1_i]);
+ b1 = (int16_t)abs(x[b1_i]);
+ lev1 = -(1 << (NBITS_CONTEXT + NBITS_RATEQ));
+
+ /* Signs Bits */
+ bit_estimate += min(a1, 1);
+ bit_estimate += min(b1, 1);
+
+ /* pre-compute address of ari_pk_s17_LC_ext[0][Val_esc] to avoid doing it multiple times inside the loop */
+ lookup = &ari_lookup_s17_LC[t] + (1 << (NBITS_CONTEXT + NBITS_RATEQ));
+
+ /* check while condition */
+ /* MSBs coding */
+ while (max(a1, b1) >= A_THRES)
+ {
+ pki = lookup[lev1]; /* ESC symbol */
+
+ bit_estimate = bit_estimate + ari_bit_estimate_s17_LC[pki][VAL_ESC];
+ bit_estimate += 2; /* Add 2 LSB bits corresponding to the bit-plane */
+
+ (a1) >>= 1;
+ (b1) >>= 1;
+
+ lev1 = min(lev1 + (1 << (NBITS_CONTEXT + NBITS_RATEQ)), 2 << (NBITS_CONTEXT + NBITS_RATEQ));
+
+ /* check while condition */
+ }
+
+ pki = lookup[lev1];
+
+ symbol = a1 + A_THRES * b1;
+ bit_estimate = bit_estimate + ari_bit_estimate_s17_LC[pki][symbol];
+
+ /* Should we truncate? */
+ if (bit_estimate > target)
+ {
+ stop2 = 1;
+
+ if (*stop)
+ {
+ break;
+ }
+ }
+ else
+ {
+ lastnz2 = b1_i + 1;
+ nbits2 = bit_estimate;
+ }
+
+ /* Update context for next 2-tuple */
+ if (p1 == p2) /* peak-peak or hole-hole context */
+ {
+ lev1 >>= NBITS_CONTEXT + NBITS_RATEQ;
+
+ if (lev1 <= 0)
+ {
+ t = 1 + (a1 + b1) * (lev1 + 2);
+ }
+ else
+ {
+ t = 13 + lev1;
+ }
+
+ *ctx = (*ctx & 0xf) * 16 + t;
+ }
+ else
+ {
+ /* mixed context */
+
+ if (idx1 & 1)
+ {
+ /* update first context */
+ c[p1] = update_mixed_context(c[p1], (int16_t)abs(x[a1_i]));
+ }
+
+ if (idx2 & 1)
+ {
+ /* update second context */
+ c[p2] = update_mixed_context(c[p2], (int16_t)abs(x[b1_i]));
+ }
+ }
+
+ } /*end of the 2-tuples loop*/
+
+ total_output_bits = (int16_t)(bit_estimate + 0.5f);
+ if (*stop)
+ {
+ total_output_bits = (int16_t)(nbits2 + 0.5f);
+ }
+
+ if (stop2)
+ {
+ stop2 = total_output_bits;
+ }
+ *nEncoded = lastnz2;
+ *stop = stop2; /* If zero, it means no overflow occured during bit-estimation */
+ *lastnz_out = lastnz;
+
+ /* Restore hole indices beyond lastnz */
+ for (k = numHoleIndices; k < hm_cfg->numHoleIndices; ++k)
+ {
+ hm_cfg->holeIndices[k] = hm_cfg->holeIndices[k] - nt;
+ }
+ hm_cfg->numPeakIndices = numPeakIndicesOrig;
+
+ return (int16_t)(nbits2 + 0.5f);
+ }
+ else /* if (!hm_cfg) */
+ {
+ int16_t esc_nb, cp, rateQ;
+ uint16_t s;
+ int16_t tot_bits2;
+ int16_t overflow_flag = 0;
+
+ /* Rate flag */
+ if (target > 400)
+ {
+ rateFlag = 2;
+ }
+ else
+ {
+ rateFlag = 0; /* Select context-B for lower bitrates */
+ }
+
+ t = 0;
+ s = 0;
+ cp = 0;
+ lastnz = 1;
+ lastnz2 = 0;
+ tot_bits2 = 0;
+
+ /* Find last non-zero tuple in the mapped domain signal */
+ for (lastnz = (nt - 2); lastnz >= 0; lastnz -= 2)
+ {
+ if ((x[lastnz] != 0) || (x[lastnz + 1] != 0))
+ {
+ break;
+ }
+ }
+ lastnz += 2;
+ if (lastnz < 2)
+ {
+ lastnz = 2; /* At least one tuple is coded */
+ }
+
+ lastnz2 = 2;
+
+ /* Main Loop through the 2-tuples */
+ for (k = 0; k < lastnz; k += 2)
+ {
+ /* Init current 2-tuple encoding */
+ a1 = (int16_t)abs(x[k]);
+ b1 = (int16_t)abs(x[k + 1]);
+ lev1 = 0;
+ esc_nb = 0;
+ rateQ = rateFlag + (k > (nt >> 1));
+
+ /* Signs Bits */
+ bit_estimate += min(a1, 1);
+ bit_estimate += min(b1, 1);
+
+ /* pre-compute address of ari_pk_s17_LC_ext[0][Val_esc] to avoid doing it multiple times inside the loop */
+ lookup = &ari_lookup_s17_LC[t + (rateQ << NBITS_CONTEXT)];
+
+ /* check while condition */
+ /* MSBs coding */
+ while (max(a1, b1) >= A_THRES)
+ {
+ pki = lookup[(esc_nb << (NBITS_CONTEXT + NBITS_RATEQ))];
+
+ bit_estimate = bit_estimate + ari_bit_estimate_s17_LC[pki][VAL_ESC];
+ bit_estimate += 2; /* Add 2 LSB bits corresponding to the bit-plane */
+
+ (a1) >>= 1;
+ (b1) >>= 1;
+
+ lev1++;
+ esc_nb = min(lev1, 3);
+
+ /* check while condition */
+ }
+
+ pki = lookup[(esc_nb << (NBITS_CONTEXT + NBITS_RATEQ))];
+
+ symbol = a1 + A_THRES * b1;
+ bit_estimate = bit_estimate + ari_bit_estimate_s17_LC[pki][symbol];
+
+ /* Should we truncate? */
+ if (bit_estimate > target) /* Overflow occured */
+ {
+ overflow_flag = 1;
+ }
+ else
+ {
+ if (abs(x[k]) || abs(x[k + 1])) /* No overflow & non-zero tuple */
+ {
+ nbits2 = bit_estimate;
+ lastnz2 = k + 2;
+ }
+ }
+
+ /* Update context for next 2-tuple */
+ if (esc_nb < 2)
+ {
+ cp = 1 + (a1 + b1) * (esc_nb + 1);
+ }
+ else
+ {
+ cp = 12 + esc_nb;
+ }
+ /*shift old bits and replace last 4 bits*/
+ s = (s << 4) + cp;
+ t = s & 0xFF;
+
+ } /*end of the 2-tuples loop*/
+
+ tot_bits2 = (int16_t)(nbits2 + 0.5f);
+ if (lastnz2 < lastnz) /* Overflow occured because unable to code all tuples */
+ {
+ overflow_flag = 1;
+ }
+ if (mode == -1)
+ {
+ tot_bits2 = (int16_t)(bit_estimate + 0.5f);
+ }
+ if (overflow_flag == 0) /* No overflow */
+ {
+ *stop = 0;
+ }
+ else /* Overflow */
+ {
+ if (*stop)
+ {
+ *stop = tot_bits2;
+ }
+ else
+ {
+ *stop = (int16_t)(bit_estimate + 0.5f);
+ }
+ }
+
+ *lastnz_out = lastnz;
+ *nEncoded = lastnz2;
+ /* Safety mechanism to avoid overflow */
+ if (lastnz2 == 2 && overflow_flag == 1)
+ {
+ for (k = 0; k < lastnz2; k++)
+ {
+ x[k] = 0;
+ }
+ }
+
+ return tot_bits2;
+ }
+}
+
+/*-------------------------------------------------------------------*
+ * RCcontextMapping_encode2_estimate_bandWise_start()
+ *
+ * Range coder - start bandwise bit-estimation
+ *-------------------------------------------------------------------*/
+
+int16_t RCcontextMapping_encode2_estimate_bandWise_start(
+ int16_t* x,
+ const int16_t nt,
+ const int16_t target,
+ HANDLE_RC_CONTEXT_MEM hContextMem)
+{
+ int16_t i, k;
+
+ /* Rate flag */
+ if (target > 400)
+ {
+ hContextMem->rateFlag = 2 << NBITS_CONTEXT;
+ }
+ else
+ {
+ hContextMem->rateFlag = 0;
+ }
+
+ hContextMem->bit_estimate = 2.0f;
+
+ /* Init */
+ hContextMem->nt_half = nt >> 1;
+
+ /* bits to encode lastnz */
+ k = 1;
+
+ while (k < hContextMem->nt_half)
+ {
+ hContextMem->bit_estimate++;
+
+ k = k << 1;
+ /* check while condition */
+ }
+
+ /* bits to encode lastnz */
+ hContextMem->nbits_old = (int16_t)hContextMem->bit_estimate;
+
+ hContextMem->ctx = 0;
+ hContextMem->lastnz = 2;
+
+ /* Find last non-zero tuple */
+
+ for (i = nt; i >= 4; i -= 2)
+ {
+
+ if (x[i - 2] != 0 || x[i - 1] != 0)
+ {
+ hContextMem->lastnz = i;
+ break;
+ }
+ }
+
+ return (int16_t)hContextMem->bit_estimate;
+}
+
+/*-------------------------------------------------------------------*
+ * RCcontextMapping_encode2_estimate_bandWise()
+ *
+ * Range coder - bandwise bit-estimation
+ *-------------------------------------------------------------------*/
+
+int16_t RCcontextMapping_encode2_estimate_bandWise(
+ int16_t* x,
+ const int16_t start_line,
+ const int16_t end_line,
+ HANDLE_RC_CONTEXT_MEM hContextMem)
+{
+ int16_t a1, b1, a1_i, b1_i;
+ int16_t k, pki, lev1;
+ uint16_t t;
+ int16_t bandBits = 0;
+ int16_t total_output_bits; /* No. of bits after finalization */
+ int16_t symbol;
+ const uint8_t* lookup;
+ int16_t idx;
+
+ /* Main Loop through the 2-tuples */
+ /*hContextMem->nt_half = end_line >> 1;*/
+ for (k = start_line; k < min(hContextMem->lastnz, end_line); k += 2)
+ {
+ a1_i = k;
+ b1_i = k + 1;
+
+ idx = k;
+
+ /* Get context */
+ t = hContextMem->ctx + hContextMem->rateFlag;
+ t += (hContextMem->nt_half >= idx) ? 0 : (1 << NBITS_CONTEXT);
+
+ /* Init current 2-tuple encoding */
+ a1 = (int16_t)abs(x[a1_i]);
+ b1 = (int16_t)abs(x[b1_i]);
+ lev1 = -(1 << (NBITS_CONTEXT + NBITS_RATEQ));
+
+ /* Signs Bits */
+ hContextMem->bit_estimate += min(a1, 1);
+ hContextMem->bit_estimate += min(b1, 1);
+
+ /* pre-compute address of ari_pk_s17_LC_ext[0][Val_esc] to avoid doing it multiple times inside the loop */
+ lookup = &ari_lookup_s17_LC[t] + (1 << (NBITS_CONTEXT + NBITS_RATEQ));
+
+ /* check while condition */
+ /* MSBs coding */
+ while (max(a1, b1) >= A_THRES)
+ {
+ pki = lookup[lev1];
+ hContextMem->bit_estimate = hContextMem->bit_estimate + ari_bit_estimate_s17_LC[pki][VAL_ESC];
+ hContextMem->bit_estimate += 2; /* Add the 2 LSB bits that were shifted out */
+
+ (a1) >>= 1;
+ (b1) >>= 1;
+
+ lev1 = min(lev1 + (1 << (NBITS_CONTEXT + NBITS_RATEQ)), 2 << (NBITS_CONTEXT + NBITS_RATEQ));
+ /* check while condition */
+ }
+
+ pki = lookup[lev1];
+ symbol = a1 + A_THRES * b1; /* MSB symbol */
+ hContextMem->bit_estimate = hContextMem->bit_estimate + ari_bit_estimate_s17_LC[pki][symbol];
+
+ /* Update context */
+ lev1 >>= NBITS_CONTEXT + NBITS_RATEQ;
+
+ if (lev1 <= 0)
+ {
+ t = 1 + (a1 + b1) * (lev1 + 2);
+ }
+ else
+ {
+ t = 13 + lev1;
+ }
+
+ hContextMem->ctx = (hContextMem->ctx & 0xf) * 16 + t;
+
+ } /*end of the 2-tuples loop*/
+ total_output_bits = (int16_t)(hContextMem->bit_estimate + 0.5f);
+
+ bandBits = total_output_bits - hContextMem->nbits_old;
+ hContextMem->nbits_old = total_output_bits;
+
+ return bandBits;
+}
+
+#endif
diff --git a/lib_enc/FEC_enc_fx.c b/lib_enc/FEC_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e5d88aa23b7ad0d785f5757f55fe4bbeee88cd6
--- /dev/null
+++ b/lib_enc/FEC_enc_fx.c
@@ -0,0 +1,294 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+/*============================================================================*/
+/* FUNCTION : void FEC_encode_fx() */
+/*----------------------------------------------------------------------------*/
+/* PURPOSE : Encoder supplementary information for FEC */
+/*----------------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* Word16 *synth i : pointer to synthesized speech for E computation */
+/* Word16 coder_type i : type of coder */
+/* Word16 clas i : signal clas for current frame */
+/* Word16 *fpit i : close loop fractional pitch buffer */
+/* Word16 *res i : LP residual signal frame */
+/* Word16 L_frame i : Frame length */
+/* Word32 total_brate i : total codec bitrate */
+/*----------------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/*----------------------------------------------------------------------------*/
+/* INPUT/OUTPUT ARGUMENTS : */
+/* Word16 *last_pulse_pos i/o: Position of the last pulse */
+/* Encoder_State_fx *st_fx i/o: state structure */
+/*----------------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*----------------------------------------------------------------------------*/
+/* */
+/*============================================================================*/
+void FEC_encode_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
+ const ACELP_config acelp_cfg, /* i/o: configuration of the ACELP */
+ const Word16 *synth, /* i : pointer to synthesized speech for E computation */
+ const Word16 coder_type, /* i : type of coder */
+ Word16 clas, /* i : signal clas for current frame */
+ const Word16 *fpit, /* i : close loop fractional pitch buffer */
+ const Word16 *res, /* i : LP residual signal frame */
+ Word16 *last_pulse_pos, /* i/o: Position of the last pulse */
+ const Word16 L_frame, /* i : Frame length */
+ const Word32 total_brate, /* i : total codec bitrate */
+ const Word16 Q_new, /* i : input scaling */
+ const Word16 shift /* i : scaling to get 12bits */
+)
+{
+ Word16 tmpS, index;
+ Word16 maxi, sign, tmp_FER_pitch;
+ Word32 enr_q, Ltmp;
+ Word16 enr_lg_ent, enr_lg_frac, exp_enrq;
+
+ tmpS = 0;
+ move16();
+ enr_q = 1;
+ move16();
+ sign = 0;
+ move16();
+ test();
+ test();
+ IF( GT_16(coder_type,UNVOICED) && LT_16(coder_type,AUDIO) && acelp_cfg.FEC_mode>0)
+ {
+ /*-----------------------------------------------------------------*
+ * encode signal class (not needed for VC mode since it is clearly voiced) (2 bits)
+ *-----------------------------------------------------------------*/
+ IF ( NE_16(coder_type,VOICED))
+ {
+ /* encode signal clas with 2 bits */
+ test();
+ IF(EQ_16(clas,UNVOICED_CLAS))
+ {
+ index = 0;
+ move16();
+ }
+ ELSE IF( EQ_16(clas,VOICED_TRANSITION)||EQ_16(clas,UNVOICED_TRANSITION))
+ {
+ index = 1;
+ move16();
+ }
+ ELSE IF( EQ_16(clas,VOICED_CLAS))
+ {
+ index = 2;
+ move16();
+ }
+ ELSE
+ {
+ index = 3;
+ move16();
+ }
+ push_indice_fx(hBstr, IND_FEC_CLAS, index, FEC_BITS_CLS);
+ }
+
+ /*-----------------------------------------------------------------*
+ * encode frame energy (5 bits)
+ *-----------------------------------------------------------------*/
+ test();
+ IF(GT_16(acelp_cfg.FEC_mode, 1)) /* GENERIC and VOICED frames */
+ {
+ /* frame energy (maximum energy per pitch period for voiced frames or mean energy per sample over 2nd halframe for unvoiced frames) */
+ /*frame_ener( L_frame, clas, synth, fpit[(L_frame>>6)-1], &enr_q, 0 );*/
+ exp_enrq = frame_ener_fx( L_frame, clas, synth, shr_r(fpit[sub(shr(L_frame , 6),1)],6), &enr_q, L_frame, Q_new, shift, 1);
+
+ /* linearly quantize the energy in the range 0 : FEC_ENR_STEP : 96 dB */
+ /*tmpS = (short)( 10.0 * log10( enr_q + 0.001f ) / FEC_ENR_STEP )*/ /*To be converted fl_2_fx*/
+
+ enr_lg_frac = Log2_norm_lc(enr_q);
+ enr_lg_ent = sub(30, exp_enrq);
+ Ltmp = Mpy_32_16(enr_lg_ent,enr_lg_frac, LG10_s3_0);
+ tmpS = extract_h(L_shl(Ltmp, 1));
+
+ tmpS = s_min(tmpS, 31);
+ tmpS = s_max(tmpS, 0);
+
+ push_indice_fx(hBstr, IND_FEC_ENR, tmpS, FEC_BITS_ENR );
+ }
+ /*-----------------------------------------------------------------*
+ * Encode last glottal pulse position (8 bits)
+ *-----------------------------------------------------------------*/
+ test();
+ IF(GT_16(acelp_cfg.FEC_mode, 2)) /* GENERIC frames */
+ {
+ /* retrieve the last glottal pulse position of the previous frame */
+ /* use the current pitch information to scale or not the quantization */
+ tmp_FER_pitch = shr(fpit[0],6); /* take the 1st subframe pit, since it is easier to get on decoder side */
+ sign = 0;
+ move16();
+ maxi = *last_pulse_pos;
+ move16();
+ IF ( maxi < 0 )
+ {
+ sign = 1;
+ move16();
+ /*maxi = -maxi; */
+ maxi = negate(maxi);
+ }
+
+ if ( GE_16(tmp_FER_pitch,128))
+ {
+ maxi = shr(maxi , 1);
+ }
+
+ if ( GT_16(maxi,127))
+ {
+ /* better not use the glottal pulse position at all instead of using a wrong pulse */
+ /* can happen only with pitch > 254 and max pit = 289 and should happen very rarely */
+ maxi = 0;
+ move16();
+ }
+
+ if( sign == 1 )
+ {
+ maxi = add(maxi,128);/* use 8 bits (MSB represent the sign of the pulse) */
+ }
+
+ push_indice_fx(hBstr, IND_FEC_POS, maxi, FEC_BITS_POS );
+ }
+ maxi = 0;
+ move16();
+
+ /* If bitrate < 24k4, then the pitch
+ is not represented in the same domain (12.k instead of 16k) */
+ test();
+ IF( GE_16(clas,VOICED_CLAS)&&GE_32(total_brate,ACELP_24k40))
+ {
+ /*maxi = findpulse( L_frame, res, (short)(fpit[(L_frame>>6)-1]), 0, &sign ); */
+ maxi = findpulse_fx( L_frame, res, shr_r(fpit[sub(shr(L_frame , 6) , 1)], 6), 0, &sign );
+ if ( sign == 1 )
+ {
+ /*maxi = -maxi;*/
+ maxi = negate(maxi);
+ }
+ }
+
+ *last_pulse_pos = maxi;
+ move16();
+ }
+ ELSE
+ {
+ *last_pulse_pos = 0;
+ move16();
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+* FEC_lsf_estim_enc_fx()
+*
+* Simulates LSF estimation in case of FEC in the encoder ( only one frame erasure is considered )
+* The estimated LSF vector is then used to check LSF stability and may invoke safety-net usage in the next frame
+*-------------------------------------------------------------------*/
+
+void FEC_lsf_estim_enc_fx(
+ Encoder_State_fx *st_fx, /* i : Encoder static memory */
+ Word16 *lsf /* o : estimated LSF vector */
+)
+{
+ Word16 i;
+ Word16 alpha, lsf_mean[M];
+ Word16 tmp;
+
+ IF( EQ_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ Copy( UVWB_Ave_fx, lsf_mean, M );
+ }
+ ELSE
+ {
+ Copy( GEWB2_Ave_fx, lsf_mean, M );
+ }
+
+ /*----------------------------------------------------------------------*
+ * Initialize the alpha factor
+ *----------------------------------------------------------------------*/
+
+ IF( EQ_16(st_fx->last_coder_type_fx, UNVOICED))
+ {
+ /* clearly unvoiced */
+ alpha = _ALPHA_UU_FX;
+ move16();
+ }
+ ELSE
+ {
+ test();
+ test();
+ IF( EQ_16(st_fx->last_coder_type_fx, AUDIO)||EQ_16(st_fx->clas_fx,INACTIVE_CLAS))
+ {
+ alpha = 32604;
+ move16();
+ }
+ ELSE IF( EQ_16(st_fx->clas_fx, UNVOICED_CLAS))
+ {
+ /* if stable, do not flatten the spectrum in the first erased frame */
+ /* alpha = st->stab_fac * (1.0f - 2.0f*ALPHA_U) + 2.0f*ALPHA_U; */
+ alpha = add(mult(st_fx->stab_fac_fx, 32768 - _ALPHA_U_FX_X_2), _ALPHA_U_FX_X_2);
+ }
+ ELSE IF( EQ_16(st_fx->clas_fx, UNVOICED_TRANSITION))
+ {
+ alpha = _ALPHA_UT_FX;
+ move16();
+ }
+ ELSE IF( EQ_16(st_fx->clas_fx, VOICED_CLAS)||EQ_16(st_fx->clas_fx,ONSET))
+ {
+ /* clearly voiced - mild convergence to the CNG spectrum for the first three erased frames */
+ alpha = _ALPHA_V_FX;
+ move16();
+ }
+ ELSE IF( EQ_16(st_fx->clas_fx, SIN_ONSET))
+ {
+ alpha = _ALPHA_S_FX;
+ move16();
+ }
+ ELSE
+ {
+ /* long erasures and onsets - rapid convergence to the CNG spectrum */
+ alpha = _ALPHA_VT_FX;
+ move16();
+ }
+ }
+ /*----------------------------------------------------------------------*
+ * Extrapolate LSF vector
+ *----------------------------------------------------------------------*/
+ tmp = sub(32767, alpha);
+ /* extrapolate the old LSF vector */
+ FOR (i=0; ilsf_adaptive_mean[i]; */
+ lsf_mean[i] = mac_r(L_mult(BETA_FEC_FX, lsf_mean[i]), 32768-BETA_FEC_FX, st_fx->lsf_adaptive_mean_fx[i]);
+
+ /* move old LSF vector towards the mean LSF vector */
+ /* lsf[i] = alpha * st->lsf_old[i] + (1.0f - alpha) * lsf_mean[i]; */
+ lsf[i] = mac_r(L_mult(alpha, st_fx->lsf_old_fx[i]), tmp, lsf_mean[i]);
+ }
+
+ /* check LSF stability through LSF ordering */
+ IF( EQ_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ reorder_lsf_fx( lsf, MODE1_LSF_GAP_FX, M , INT_FS_FX);
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ reorder_lsf_fx( lsf, MODE1_LSF_GAP_FX, M, INT_FS_16k_FX);
+ }
+
+ return;
+}
diff --git a/lib_enc/SNR_calc_fx.c b/lib_enc/SNR_calc_fx.c
index 360cc589b81359cc43abf9ad669c814ff2220cc7..eea94dea19432876652d74264a7961d223581e5d 100644
--- a/lib_enc/SNR_calc_fx.c
+++ b/lib_enc/SNR_calc_fx.c
@@ -4,20 +4,22 @@
#include
#include "options.h"
-#include "options.h"
#include "basop_util.h"
#include "vad_basop.h"
-#include "prot_fx2.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
#include "rom_enc.h"
+#include "rom_com.h"
/*-------------------------------------------------------------------*
- * calc_lf_snr()
+ * calc_lf_snr_fx()
*
*
*-------------------------------------------------------------------*/
-void calc_lf_snr(
+void calc_lf_snr_fx(
Word32 *lf_snr_smooth, /* o : smoothed lf_snr*/
Word32 *lf_snr, /* o : long time frequency domain
SNR calculated by l_speech_snr and l_silence_snr*/
@@ -59,19 +61,19 @@ void calc_lf_snr(
l_snr = L_sub(l_snr, 12079595/* 0.36 Q25 */);
l_snr = L_max(0, l_snr);
- l_snr = L_min(l_snr, MAX_LF_SNR_TAB[bw_index]);
+ l_snr = L_min(l_snr, MAX_LF_SNR_TAB_FX[bw_index]);
*lf_snr = l_snr;
move32();
return;
}
/*-------------------------------------------------------------------*
- * calc_lt_snr()
+ * calc_lt_snr_fx()
*
*
*-------------------------------------------------------------------*/
-void calc_lt_snr(
- VAD_CLDFB_HANDLE hVAD_CLDFB, /* i/o: CLDFB VAD state */
+void calc_lt_snr_fx(
+ VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */
Word32 *lt_snr_org_fp, /* o : original long time SNR*/
Word32 *lt_snr_fp, /* o : long time SNR calculated by fg_energy and bg_energy*/
Word32 fg_energy, /* i : foreground energy sum */
@@ -165,11 +167,11 @@ void calc_lt_snr(
}
/*-------------------------------------------------------------------*
- * calc_snr_flux()
+ * calc_snr_flux_fx()
*
*
*-------------------------------------------------------------------*/
-void calc_snr_flux(
+void calc_snr_flux_fx(
Word32 tsnr, /* i : time-domain SNR*/
Word32 *pre_snr, /* i/o: time-domain SNR storage*/
Word32 *snr_flux_fp /* o : average tsnr*/
@@ -228,7 +230,7 @@ void calc_snr_flux(
*
*-------------------------------------------------------------------*/
void snr_calc(
- VAD_CLDFB_HANDLE hVAD_CLDFB, /* i/o: CLDFB VAD state */
+ VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */
const Word16 sacle_sbpower, /* i : the Scaling of sbpower*/
Word32 *snr, /* o : frequency domain SNR */
Word32* tsnr, /* o : time domain SNR */
@@ -360,7 +362,7 @@ void snr_calc(
return;
}
-Word32 construct_snr_thresh(
+Word32 construct_snr_thresh_fx(
Word16 sp_center[], /* i : spectral center*/
Word32 snr_flux, /* i : snr flux*/
Word32 lt_snr, /* i : long time time domain snr*/
@@ -377,7 +379,7 @@ Word32 construct_snr_thresh(
- snr_delta = COMVAD_INIT_SNR_DELTA[bw_index];
+ snr_delta = COMVAD_INIT_SNR_DELTA_FX[bw_index];
move32();
bw_snr = lt_snr;
move32();
diff --git a/lib_enc/acelp_core_enc_fx.c b/lib_enc/acelp_core_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..6c6c9a5f4048fce4fe348e158302afe87435c5c8
--- /dev/null
+++ b/lib_enc/acelp_core_enc_fx.c
@@ -0,0 +1,773 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h"
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "stat_enc.h"
+#include "rom_com.h"
+#include "rom_enc.h" /* Encoder static table prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * acelp_core_enc()
+ *
+ * ACELP core encoder
+ *--------------------------------------------------------------------*/
+ivas_error acelp_core_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 inp_fx[], /* i : input signal of the current frame */
+ const Word32 ener_fx, /* i : residual energy from Levinson-Durbin*/
+ Word16 A_fx[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes*/
+ Word16 Aw_fx[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/
+ const Word16 epsP_h_fx[M+1], /* i : LP prediction errors */
+ const Word16 epsP_l_fx[M+1], /* i : LP prediction errors */
+ Word16 lsp_new_fx[M], /* i : LSPs at the end of the frame */
+ Word16 lsp_mid_fx[M], /* i : LSPs in the middle of the frame */
+ Word16 vad_hover_flag_fx, /* i : VAD hangover flag */
+ const Word16 attack_flag, /* i : attack flag (GSC or TC) */
+ Word32 bwe_exc_extended_fx[], /* i/o: bandwidth extended excitation */
+ Word16 *voice_factors_fx, /* o : voicing factors */
+ Word16 old_syn_12k8_16k_fx[], /* o : intermediate ACELP synthesis at 12.8kHz or 16kHz to be used by SWB BWE */
+ Word16 pitch_buf_fx[NB_SUBFR16k], /* o : floating pitch for each subframe */
+ Word16 *unbits_fx, /* o : number of unused bits */
+ const Word16 Q_new,
+ const Word16 shift
+#ifdef ADD_LRTD
+ ,
+ STEREO_TD_ENC_DATA_HANDLE hStereoTD, /* i/o: TD stereo encoder handle */
+ const float tdm_lsfQ_PCh[M] /* i : Q LSFs for primary channel */
+#endif
+)
+{
+ Word16 nBits; /* reserved bits */
+ Word16 i;
+ Word16 old_exc_fx[L_EXC], *exc_fx; /* excitation signal buffer */
+ Word16 lsf_new_fx[M]; /* ISFs at the end of the frame */
+ Word16 Aq_fx[NB_SUBFR16k*(M+1)]; /* A(z) quantized for the 4 subframes */
+ Word16 syn_fx[L_FRAME16k]; /* synthesis vector */
+ Word16 res_fx[L_FRAME16k]; /* Residual signal for FER protection */
+ Word16 exc2_fx[L_FRAME16k]; /* enhanced excitation */
+ Word16 Es_pred_fx; /* predicited scaled innovation energy */
+ Word16 tmp_noise_fx; /* NB post-filter long-term noise energy*/
+ Word16 tc_subfr_fx, position; /* TC sub-frame indication */
+ Word16 old_bwe_exc_fx[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */
+ Word16 *bwe_exc_fx; /* excitation for SWB TBE */
+ Word16 allow_cn_step_fx;
+ Word16 int_fs_fx;
+ Word32 L_epsP[2];
+ /* SC-VBR - back-up memories for LSF quantizer and synthesis filter */
+ Word16 mCb1_fx, pstreaklen_fx;
+ Word16 mem_MA_fx[M], mem_AR_fx[M], lsp_new_bck_fx[M], lsf_new_bck_fx[M], lsp_mid_bck_fx[M], mem_syn_bck_fx[M];
+ Word32 Bin_E_fx[L_FFT], Bin_E_old_fx[L_FFT/2];
+ Word16 clip_var_fx, mem_w0_bck_fx, streaklimit_fx;
+ Word16 nb_bits;
+ Word16 indice;
+ Word16 tmp16;
+ Word16 enr_index;
+ Word16 enr;
+
+ Word16 tilt_code_bck_fx;
+ Word32 gc_threshold_bck_fx;
+ Word16 clip_var_bck_fx[6];
+ Word16 next_force_sf_bck_fx;
+ Word32 q_env[NUM_ENV_CNG];
+ Word16 sid_bw=-1;
+ Word16 coder_type;
+ Word16 exc3_fx[L_FRAME16k];
+ Word16 syn1_fx[L_FRAME16k];
+ Word16 ppp_mode, nelp_mode;
+ Word16 tdm_lp_reuse_flag, tdm_low_rate_mode, tdm_Pitch_reuse_flag;
+ Word16* tdm_Pri_pitch_buf;
+ Word16 uc_two_stage_flag;
+ Word16 att;
+
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+ GSC_ENC_HANDLE hGSCEnc = st_fx->hGSCEnc;
+ TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD;
+ FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+ test();
+ IF (EQ_16(st_fx->element_mode, IVAS_CPE_MDCT) && LE_32(st_fx->core_brate_fx, SID_2k40) )
+ {
+ /* Core was ACELP because of DTX in MDCT-Stereo, but SID encoding for that is done in separate function */
+ return error;
+ }
+ /*------------------------------------------------------------------*
+ * Initialization
+ *------------------------------------------------------------------*/
+
+ Es_pred_fx = 0;
+ move16();
+
+ coder_type = st_fx->coder_type;
+
+ exc_fx = old_exc_fx + L_EXC_MEM; /* pointer to excitation signal in the current frame */
+ Copy(hLPDmem->old_exc, old_exc_fx, L_EXC_MEM );
+
+ IF(hBWE_TD != NULL)
+ {
+ bwe_exc_fx = old_bwe_exc_fx + PIT16k_MAX * 2; /* pointer to BWE excitation signal in the current frame */
+ Copy(hBWE_TD->old_bwe_exc_fx, old_bwe_exc_fx, PIT16k_MAX * 2);
+ }
+ ELSE
+ {
+ bwe_exc_fx = NULL;
+ }
+
+ st_fx->bpf_off_fx = 0;
+ move16();
+ test();test();test();
+ IF( EQ_16(st_fx->last_core_fx,HQ_CORE) || EQ_16(st_fx->last_codec_mode,MODE2) ||
+ EQ_16(st_fx->last_core_fx, TCX_20_CORE) || EQ_16(st_fx->last_core_fx, TCX_10_CORE) )
+ {
+ /* in case of HQ->ACELP switching, do not apply BPF */
+ st_fx->bpf_off_fx = 1;
+ move16();
+ if (hGSCEnc != NULL)
+ {
+ hGSCEnc->Last_frame_ener_fx = MAX_32;
+ move32();
+ }
+ }
+
+ /* force safety-net LSFQ in the first frames after CNG segment */
+ if( LE_32(st_fx->last_core_brate_fx,SID_2k40))
+ {
+ st_fx->Nb_ACELP_frames_fx = 0;
+ move16();
+ }
+ st_fx->Nb_ACELP_frames_fx = add(st_fx->Nb_ACELP_frames_fx,1);
+
+ int_fs_fx = INT_FS_16k_FX;
+ move16();
+ if( EQ_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ int_fs_fx = INT_FS_FX;
+ move16();
+ }
+
+ tmp_noise_fx = 0;
+ move16();
+ tc_subfr_fx = -1;
+ move16();
+ position = -1;
+ move16();
+
+ /* SC-VBR temporary variables */
+ mCb1_fx = 0; //-> to be removed
+ move16();
+ pstreaklen_fx = 0;
+ move16();
+ clip_var_fx = 0;
+ move16();
+ mem_w0_bck_fx = 0;
+ move16();
+ streaklimit_fx = 0;
+ move16();
+
+ /* channel-aware mode */
+ reset_rf_indices_fx(st_fx);
+ /* VBR modes */
+ IF (st_fx->Opt_SC_VBR_fx)
+ {
+ ppp_mode = hSC_VBR->ppp_mode;
+ nelp_mode = hSC_VBR->nelp_mode;
+ move16(); move16();
+
+ }
+ ELSE
+ {
+ ppp_mode = 0;
+ nelp_mode = 0;
+ move16();move16();
+ }
+
+ /* TD stereo */
+ test();
+#ifdef ADD_LRTD
+ IF (EQ_16(st_fx->element_mode, IVAS_CPE_TD) && EQ_16(st_fx->idchan, 1))
+ {
+ tdm_lp_reuse_flag = hStereoTD->tdm_lp_reuse_flag;
+ tdm_low_rate_mode = hStereoTD->tdm_low_rate_mode;
+ tdm_Pitch_reuse_flag = hStereoTD->tdm_Pitch_reuse_flag;
+ tdm_Pri_pitch_buf = hStereoTD->tdm_Pri_pitch_buf;
+ }
+ ELSE
+#endif
+ {
+ tdm_lp_reuse_flag = 0;
+ tdm_low_rate_mode = 0;
+ move16(); move16();
+ if (EQ_16(st_fx->element_mode, IVAS_SCE) && st_fx->low_rate_mode)
+ {
+ tdm_low_rate_mode = 1;
+ move16();
+ }
+ tdm_Pitch_reuse_flag = 0;
+ tdm_Pri_pitch_buf = NULL;
+ move16(); move16();
+ }
+ /*-----------------------------------------------------------------*
+ * ACELP@12k8 / ACELP@16k switching
+ *-----------------------------------------------------------------*/
+ test();
+ IF( NE_16(st_fx->last_L_frame_fx,st_fx->L_frame_fx) && (EQ_16(st_fx->last_core_fx, ACELP_CORE) || EQ_16(st_fx->last_core_fx, AMR_WB_CORE) ) )
+ {
+ /* in case of switching, do not apply BPF */
+ st_fx->bpf_off_fx = 1;
+ move16();
+
+ /* force safety-net LSFQ in the first frames after ACELP@12k8/ACELP@16k switching */
+ st_fx->Nb_ACELP_frames_fx = 1;
+ move16();
+
+ /* convert old quantized LSP vector */
+ IF( EQ_16(st_fx->L_frame_fx,L_FRAME))
+ {
+ st_fx->rate_switching_reset = lsp_convert_poly_fx( st_fx->lsp_old_fx, st_fx->L_frame_fx, 0 );
+ }
+ ELSE
+ {
+ st_fx->rate_switching_reset=st_fx->rate_switching_reset_16kHz;
+ move16();
+ Copy( st_fx->lsp_old16k_fx, st_fx->lsp_old_fx, M );
+ }
+
+ /* convert old quantized LSF vector */
+ lsp2lsf_fx( st_fx->lsp_old_fx, st_fx->lsf_old_fx, M, int_fs_fx );
+
+ /* interpolation of unquantized ISPs */
+ IF( st_fx->rate_switching_reset )
+ {
+ /*extrapolation in case of unstable LSP*/
+ int_lsp4_fx( st_fx->L_frame_fx, lsp_mid_fx, lsp_mid_fx, lsp_new_fx, A_fx, M, 0 );
+ }
+ ELSE
+ {
+ int_lsp4_fx( st_fx->L_frame_fx, st_fx->lsp_old_fx, lsp_mid_fx, lsp_new_fx, A_fx, M, 0 );
+ }
+
+ /* Reset LPC mem */
+ Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M );
+ set16_fx( st_fx->mem_MA_fx,0, M );
+
+ /* update synthesis filter memories */
+ synth_mem_updt2( st_fx->L_frame_fx, st_fx->last_L_frame_fx, hLPDmem->old_exc, hLPDmem->mem_syn_r,hLPDmem->mem_syn2, hLPDmem->mem_syn, ENC );
+ Copy( hLPDmem->old_exc, old_exc_fx, L_EXC_MEM );
+ Copy( hLPDmem->mem_syn2, hLPDmem->mem_syn1_fx, M );
+ Copy( hLPDmem->mem_syn2, hLPDmem->mem_syn3, M );
+
+ /* update Aw[] coefficients */
+ weight_a_subfr_fx( shr(st_fx->L_frame_fx,6), A_fx, Aw_fx, st_fx->gamma, M );
+
+ }
+
+ test();
+ test();
+ if(EQ_16(st_fx->last_bwidth_fx,NB)&&NE_16(st_fx->bwidth_fx,NB)&&st_fx->ini_frame_fx!=0)
+ {
+ st_fx->rate_switching_reset=1;
+ move16();
+ }
+ /*----------------------------------------------------------------*
+ * Encoding of CNG frames
+ *----------------------------------------------------------------*/
+ test();
+ IF ( EQ_32(st_fx->core_brate_fx,SID_2k40)||EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA))
+ {
+ IF( EQ_16(st_fx->cng_type_fx,LP_CNG))
+ {
+ /* Run CNG post parameter update */
+ cng_params_postupd_fx(hTdCngEnc->ho_circ_ptr, &hTdCngEnc->cng_buf_cnt, hTdCngEnc->cng_exc2_buf, hTdCngEnc->cng_Qexc_buf,
+ hTdCngEnc->cng_brate_buf, hTdCngEnc->ho_env_circ_fx);
+ /* encode CNG parameters */
+ CNG_enc_fx( st_fx, Aq_fx, inp_fx, ener_fx, lsp_mid_fx, lsp_new_fx, lsf_new_fx, &allow_cn_step_fx, sub(Q_new,1), q_env, &sid_bw);
+
+ /* comfort noise generation */
+ CNG_exc_fx( st_fx->core_brate_fx, st_fx->L_frame_fx, &hTdCngEnc->Enew_fx, &hTdCngEnc->cng_seed, exc_fx, exc2_fx, &hTdCngEnc->lp_ener_fx, st_fx->last_core_brate_fx,
+ &hDtxEnc->first_CNG, &hTdCngEnc->cng_ener_seed, bwe_exc_fx, allow_cn_step_fx, &hTdCngEnc->last_allow_cn_step, sub(st_fx->prev_Q_new,1), sub(Q_new,1), hTdCngEnc->num_ho,
+ q_env, hTdCngEnc->lp_env_fx, hTdCngEnc->old_env_fx, hTdCngEnc->exc_mem_fx, hTdCngEnc->exc_mem1_fx, &sid_bw, &hTdCngEnc->cng_ener_seed1, exc3_fx, st_fx->Opt_AMR_WB_fx, st_fx->element_mode);
+ }
+ ELSE
+ {
+ test();
+ IF( EQ_32(st_fx->core_brate_fx, SID_2k40) && NE_16(st_fx->element_mode, IVAS_CPE_MDCT) )
+ {
+ FdCng_encodeSID_fx( st_fx->hFdCngEnc_fx, st_fx, st_fx->preemph_fac );
+ hDtxEnc->last_CNG_L_frame = st_fx->L_frame_fx;
+ move16();
+ }
+
+ generate_comfort_noise_enc_fx( st_fx, Q_new, 1 );
+
+ FdCng_exc( st_fx->hFdCngEnc_fx->hFdCngCom, &hDtxEnc->CNG_mode, st_fx->L_frame_fx, st_fx->lsp_old_fx,
+ hDtxEnc->first_CNG, hDtxEnc->lspCNG_fx, Aq_fx, lsp_new_fx, lsf_new_fx, exc_fx, exc2_fx, bwe_exc_fx );
+
+ Copy( exc2_fx, exc3_fx, st_fx->L_frame_fx );
+
+ IF( EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ IF (hTdCngEnc != NULL)
+ {
+ /*IVAS_CODE CNG_att is missing */
+ enr = cng_energy_fx(st_fx->element_mode, st_fx->bwidth_fx, hDtxEnc->CNG_mode, /*st_fx->hTdCngEnc->CNG_att*/0, exc_fx, st_fx->L_frame_fx, Q_new);
+
+ /* calculate the energy quantization index */
+ enr_index = add(enr, 512 /* Q8(2.0) */); /* enr + 2.0 */
+ enr_index = extract_l(L_shr(L_mult0(enr_index, STEP_SID_FX), 12 + 8)); /* Q0 (8+12-(8+12)) */
+
+ /* limit the energy quantization index */
+ enr_index = s_min(enr_index, 127);
+ enr_index = s_max(enr_index, 0);
+
+ hTdCngEnc->old_enr_index = enr_index;
+ move16();
+ }
+ }
+ }
+ /* Reset HO counter in the first SID frame */
+ if (hTdCngEnc != NULL)
+ {
+ hTdCngEnc->burst_ho_cnt = 0;
+ move16();
+ }
+ /* synthesis at 12.8kHz sampling rate */
+ syn_12k8_fx( st_fx->L_frame_fx, Aq_fx, exc3_fx, syn1_fx, hLPDmem->mem_syn3, 1, Q_new, st_fx->Q_syn );
+
+ /* reset the encoder */
+ CNG_reset_enc_fx( st_fx, hLPDmem, pitch_buf_fx, voice_factors_fx, 0 );
+
+ /* update st->mem_syn1 for ACELP core switching */
+ Copy( hLPDmem->mem_syn3, hLPDmem->mem_syn1_fx, M );
+
+ /* update ACELP core synthesis filter memory */
+ Copy( hLPDmem->mem_syn3, hLPDmem->mem_syn, M );
+
+ /* update old synthesis buffer - needed for ACELP internal sampling rate switching */
+ Copy( syn1_fx + st_fx->L_frame_fx - L_SYN_MEM, hLPDmem->mem_syn_r, L_SYN_MEM );
+
+ IF (hBWE_FD != NULL)
+ {
+ /* save and delay synthesis to be used by SWB BWE */
+ save_old_syn_fx( st_fx->L_frame_fx, syn1_fx, old_syn_12k8_16k_fx, hBWE_FD->old_syn_12k8_16k_fx, st_fx->preemph_fac, &hBWE_FD->mem_deemph_old_syn_fx );
+ }
+ /* Update MODE2 core switching memory */
+ tmp16 = hLPDmem->syn[M];
+ move16();
+ E_UTIL_deemph2( sub(Q_new,1), syn1_fx, st_fx->preemph_fac, st_fx->L_frame_fx, &tmp16 );
+ Copy( syn1_fx+st_fx->L_frame_fx-M-1, hLPDmem->syn, M+1 );
+
+ }
+
+ /*----------------------------------------------------------------*
+ * Encoding of all other frames
+ *----------------------------------------------------------------*/
+
+ ELSE
+ {
+ /*-----------------------------------------------------------------*
+ * Configure ACELP bit allocation
+ *-----------------------------------------------------------------*/
+
+ nb_bits = 0;
+ st_fx->acelp_cfg.FEC_mode = 0;
+ uc_two_stage_flag = 0;
+ move16();move16();move16();
+ test();
+ IF (!nelp_mode && !ppp_mode)
+ {
+ config_acelp1(ENC, st_fx->total_brate_fx, st_fx->core_brate_fx, st_fx->core_fx, st_fx->extl_fx, st_fx->extl_brate_fx,
+ st_fx->L_frame_fx, st_fx->GSC_noisy_speech_fx, &(st_fx->acelp_cfg), hBstr->nb_bits_tot_fx, st_fx->coder_type,
+ tc_subfr_fx, 0, &nb_bits, unbits_fx, st_fx->element_mode, &uc_two_stage_flag, tdm_lp_reuse_flag, tdm_low_rate_mode, st_fx->idchan, st_fx->active_fr_cnt_fx,
+ tdm_Pitch_reuse_flag, st_fx->tdm_LRTD_flag, st_fx->GSC_IVAS_mode);
+ }
+
+ /*-----------------------------------------------------------------*
+ * After inactive period, use the most up-to-date ISPs
+ *-----------------------------------------------------------------*/
+
+ test();
+ IF ( EQ_32(st_fx->last_core_brate_fx,FRAME_NO_DATA)||EQ_32(st_fx->last_core_brate_fx,SID_2k40))
+ {
+ Copy(hDtxEnc->lspCNG_fx, st_fx->lsp_old_fx, M );
+
+ lsp2lsf_fx(hDtxEnc->lspCNG_fx, st_fx->lsf_old_fx, M, int_fs_fx );
+ }
+
+ /*-----------------------------------------------------------------*
+ * Reset higher ACELP pre-quantizer in case of switching
+ *-----------------------------------------------------------------*/
+ IF( !st_fx->use_acelp_preq )
+ {
+ st_fx->mem_deemp_preQ_fx = 0;
+ move16();
+ st_fx->mem_preemp_preQ_fx = 0;
+ move16();
+ st_fx->last_nq_preQ_fx = 0;
+ move16();
+ }
+
+ st_fx->use_acelp_preq = 0;
+ move16();
+
+ /*-----------------------------------------------------------------*
+ * LSF Quantization
+ * A[z] calculation
+ *-----------------------------------------------------------------*/
+
+ /* SC-VBR - back-up memories for LSF quantizer and synthesis filter */
+ lsf_syn_mem_backup_fx( st_fx, &tilt_code_bck_fx, &gc_threshold_bck_fx, clip_var_bck_fx, &next_force_sf_bck_fx,
+ lsp_new_fx, lsf_new_fx, lsp_mid_fx, &clip_var_fx, mem_AR_fx, mem_MA_fx, lsp_new_bck_fx, lsf_new_bck_fx,
+ lsp_mid_bck_fx, &mCb1_fx, Bin_E_fx, Bin_E_old_fx, mem_syn_bck_fx, &mem_w0_bck_fx, &streaklimit_fx, &pstreaklen_fx);
+
+
+ if (!tdm_lp_reuse_flag)
+ {
+#ifdef LSF_RE_USE_SECONDARY_CHANNEL
+ lsf_enc_fx(st_fx, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, st_fx->Nb_ACELP_frames_fx, tdm_low_rate_mode, st_fx->GSC_IVAS_mode, tdm_lsfQ_PCh, Q_new);
+#else
+ lsf_enc_fx(st_fx, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, st_fx->Nb_ACELP_frames_fx, tdm_low_rate_mode, st_fx->GSC_IVAS_mode, Q_new);
+#endif
+ }
+#ifdef ADD_LRTD
+ else
+ {
+ const float* pt_interp_2;
+#ifdef LSF_RE_USE_SECONDARY_CHANNEL
+ if (st->active_cnt != 1)
+ {
+ int16_t beta_index;
+ float lsf_wgts[M];
+
+ /* intra_frame prediction for the LSFs */
+ lsp2lsf(lsp_new, lsf_new, M, 12800);
+
+ Unified_weighting(&st->Bin_E[L_FFT / 2], lsf_new, lsf_wgts, st->bwidth == NB, st->coder_type == UNVOICED, st->sr_core, M);
+
+ tdm_SCh_lsf_reuse(ENC, st->element_brate, lsf_new, lsp_new, tdm_lsfQ_PCh, lsf_wgts, &beta_index);
+
+ push_indice(hBstr, IND_IC_LSF_PRED, beta_index, TDM_IC_LSF_PRED_BITS);
+ }
+#endif
+ pt_interp_2 = interpol_frac_12k8;
+ if (tdm_low_rate_mode == 1 && st->coder_type > UNVOICED)
+ {
+ pt_interp_2 = interpol_frac2;
+ }
+#ifndef LSF_RE_USE_SECONDARY_CHANNEL
+ if (st->active_cnt == 1)
+ {
+ mvr2r(lsp_new, st->lsp_old, M);
+ lsp2lsf(lsp_new, st->lsf_old, M, st->sr_core);
+ lsp2lsf(lsp_new, lsf_new, M, st->sr_core);
+ }
+#endif
+ /* LSP interpolation and conversion of LSPs to A(z) */
+ int_lsp(st->L_frame, st->lsp_old, lsp_new, Aq, M, pt_interp_2, 0);
+
+ /* Check LSF stability (distance between old LSFs and current LSFs) */
+ st->stab_fac = lsf_stab(lsf_new, st->lsf_old, 0, st->L_frame);
+ }
+ if (st->last_core == HQ_CORE && st->element_mode > EVS_MONO)
+ {
+ /* Prepare ACB memory from last HQ frame */
+ tmpF = hLPDmem->old_exc[0];
+ preemph(hLPDmem->old_exc, st->preemph_fac, st->L_frame, &tmpF);
+ mvr2r(hLPDmem->old_exc + st->L_frame - M, hLPDmem->mem_syn, M);
+ residu(Aq, M, hLPDmem->old_exc, old_exc, st->L_frame);
+ }
+
+ if (st->last_core != ACELP_CORE && st->element_mode > EVS_MONO)
+ {
+ /* Prepare ACB memory of old_bwe_exc */
+#ifdef CR_FIX_639_HQ_ACELP_TRANSITION
+ if (st->L_frame == L_FRAME)
+ {
+ lerp(old_exc, old_bwe_exc, L_EXC_MEM_DEC * HIBND_ACB_L_FAC, L_EXC_MEM_DEC);
+ }
+ else
+ {
+ lerp(old_exc, old_bwe_exc, L_EXC_MEM_DEC * 2, L_EXC_MEM_DEC);
+ }
+#else
+ lerp(old_exc, old_bwe_exc, L_EXC_MEM_DEC * HIBND_ACB_L_FAC, L_EXC_MEM_DEC);
+#endif
+ }
+#endif
+
+
+ /*---------------------------------------------------------------*
+ * Calculation of LP residual (filtering through A[z] filter)
+ *---------------------------------------------------------------*/
+ calc_residu_fx(st_fx, inp_fx, res_fx, Aq_fx);
+ calculate_hangover_attenuation_gain_fx(st_fx, &att, vad_hover_flag_fx);
+ v_multc_att(res_fx, att, res_fx, st_fx->L_frame_fx);
+
+ /*-----------------------------------------------------------------*
+ * Determine TC subframe classification
+ *-----------------------------------------------------------------*/
+
+ IF (EQ_16(st_fx->coder_type, TRANSITION ) )
+ {
+ tc_classif_enc_fx(Q_new, st_fx->L_frame_fx, &tc_subfr_fx, &position, attack_flag, st_fx->pitch_fx[0], res_fx);
+
+ config_acelp1(ENC, st_fx->total_brate_fx, st_fx->core_brate_fx, st_fx->core_fx, st_fx->extl_fx, st_fx->extl_brate_fx, st_fx->L_frame_fx,
+ -1, &(st_fx->acelp_cfg), hBstr->nb_bits_tot_fx, st_fx->coder_type, tc_subfr_fx, 1, NULL, unbits_fx, st_fx->element_mode, &uc_two_stage_flag,
+ tdm_lp_reuse_flag, tdm_low_rate_mode, st_fx->idchan, st_fx->active_fr_cnt_fx, tdm_Pitch_reuse_flag, st_fx->tdm_LRTD_flag, st_fx->GSC_IVAS_mode);
+ }
+
+ /*---------------------------------------------------------------*
+ * Calculation of prediction for scaled innovation energy
+ * (for memory-less gain quantizer)
+ *---------------------------------------------------------------*/
+ IF(nb_bits > 0)
+ {
+ Es_pred_enc_fx( &Es_pred_fx, &indice, st_fx->L_frame_fx, res_fx, st_fx->voicing_fx, nb_bits, 0, Q_new );
+ push_indice_fx( st_fx->hBstr, IND_ES_PRED, indice, nb_bits );
+ }
+
+
+ /*------------------------------------------------------------*
+ * Encode excitation according to coding type
+ *------------------------------------------------------------*/
+ test();
+ test();
+#ifdef ADD_LRTD
+ if (tdm_low_rate_mode) /* tdm stereo low rate mode */
+ {
+ if (st->coder_type <= UNVOICED)
+ {
+ tdm_low_rate_enc(st, Aq, res, syn, exc, pitch_buf, voice_factors, bwe_exc, 0 /*attack_flag*/, lsf_new, &tmp_noise);
+ }
+ else /* GENERIC */
+ {
+ encod_gen_2sbfr(st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf);
+ }
+ }
+ else
+#endif
+ IF(hSC_VBR->nelp_mode )
+ {
+ /* SC-VBR - NELP frames */
+ encod_nelp_fx( st_fx, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, &tmp_noise_fx, exc_fx, exc2_fx, pitch_buf_fx,
+ voice_factors_fx, bwe_exc_fx, Q_new, shift);
+ }
+ ELSE IF( EQ_16(coder_type,UNVOICED))
+ {
+ /* UNVOICED frames (Gauss. excitation) */
+ encod_unvoiced_fx( st_fx, inp_fx, Aw_fx, Aq_fx, Es_pred_fx, uc_two_stage_flag, res_fx, syn_fx, &tmp_noise_fx, exc_fx,
+ pitch_buf_fx, voice_factors_fx, bwe_exc_fx,Q_new,shift );
+ }
+ ELSE IF( EQ_16(coder_type,TRANSITION))
+ {
+ tc_subfr_fx = encod_tran_fx( st_fx, inp_fx, Aw_fx, Aq_fx, Es_pred_fx, res_fx, syn_fx,
+ exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, tc_subfr_fx, position, unbits_fx, shift, Q_new );
+ move16();
+ }
+ ELSE IF(hSC_VBR->ppp_mode )
+ {
+ IF ((error = encod_ppp_fx( st_fx, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, Q_new, shift)) != IVAS_ERR_OK)
+ {
+ return error;
+ }
+
+ IF(hSC_VBR->bump_up ) /* PPP failed, bump up */
+ {
+ /* restore memories of LSF quantizer and synthesis filter */
+ lsf_syn_mem_restore_fx( st_fx, tilt_code_bck_fx, gc_threshold_bck_fx, clip_var_bck_fx, next_force_sf_bck_fx,
+ lsp_new_fx, lsf_new_fx, lsp_mid_fx, clip_var_fx, mem_AR_fx, mem_MA_fx, lsp_new_bck_fx, lsf_new_bck_fx,
+ lsp_mid_bck_fx, mCb1_fx, Bin_E_fx,Bin_E_old_fx,mem_syn_bck_fx, mem_w0_bck_fx, streaklimit_fx, pstreaklen_fx );
+
+ /* Configure ACELP bit allocation */
+ config_acelp1(ENC, st_fx->total_brate_fx, st_fx->core_brate_fx, st_fx->core_fx, st_fx->extl_fx, st_fx->extl_brate_fx, st_fx->L_frame_fx,
+ -1, &(st_fx->acelp_cfg), hBstr->nb_bits_tot_fx, st_fx->coder_type, tc_subfr_fx, 0, &nb_bits, unbits_fx, 0, &uc_two_stage_flag, 0, 0,
+ st_fx->idchan, st_fx->active_fr_cnt_fx, tdm_Pitch_reuse_flag, st_fx->tdm_LRTD_flag, st_fx->GSC_IVAS_mode);
+
+ /* redo LSF quantization */
+#ifdef LSF_RE_USE_SECONDARY_CHANNEL
+ lsf_enc_fx(st_fx, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, st_fx->Nb_ACELP_frames_fx, tdm_low_rate_mode, st_fx->GSC_IVAS_mode, tdm_lsfQ_PCh, Q_new);
+#else
+ lsf_enc_fx( st_fx, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, st_fx->Nb_ACELP_frames_fx, tdm_low_rate_mode, st_fx->GSC_IVAS_mode, Q_new );
+#endif
+ /* recalculation of LP residual (filtering through A[z] filter) */
+ calc_residu_fx( st_fx, inp_fx, res_fx, Aq_fx);
+
+ hTdCngEnc->burst_ho_cnt = 0;
+ move16();
+ /* VOICED frames in SC-VBR when bumped up*/
+ encod_gen_voic_fx( st_fx, inp_fx, Aw_fx, Aq_fx, Es_pred_fx, res_fx, syn_fx,
+ exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, unbits_fx, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf, shift, Q_new );
+ }
+ }
+ ELSE IF( EQ_16(coder_type,AUDIO)||(EQ_16(coder_type,INACTIVE)&&LE_32(st_fx->core_brate_fx,ACELP_24k40)))
+ {
+ /* AUDIO and INACTIVE frames (coded by GSC technology) */
+ encod_audio_fx( st_fx, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, exc_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx,
+ attack_flag, lsf_new_fx, &tmp_noise_fx, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf, Q_new , shift);
+ }
+ ELSE
+ {
+ /* GENERIC, VOICED and INACTIVE frames (coded by AVQ technology) */
+ encod_gen_voic_fx( st_fx, inp_fx, Aw_fx, Aq_fx, Es_pred_fx, res_fx, syn_fx,
+ exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, unbits_fx, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf, shift, Q_new );
+ }
+
+ /* update st->mem_syn1 for ACELP core switching */
+ Copy( hLPDmem->mem_syn, hLPDmem->mem_syn1_fx, M );
+
+ /* update old synthesis buffer - needed for ACELP internal sampling rate switching */
+ Copy( syn_fx + st_fx->L_frame_fx - L_SYN_MEM, hLPDmem->mem_syn_r, L_SYN_MEM );
+
+ /* save and delay synthesis to be used by SWB BWE */
+ IF (hBWE_FD != NULL)
+ {
+ save_old_syn_fx(st_fx->L_frame_fx, syn_fx, old_syn_12k8_16k_fx, hBWE_FD->old_syn_12k8_16k_fx, st_fx->preemph_fac, &hBWE_FD->mem_deemph_old_syn_fx);
+ }
+ /*Update MODE2 core switching memory*/
+ Copy( syn_fx, syn1_fx, st_fx->L_frame_fx );
+ E_UTIL_deemph2( sub(Q_new,1), syn1_fx, st_fx->preemph_fac, st_fx->L_frame_fx, &hLPDmem->syn[M] );
+ Copy( syn1_fx+st_fx->L_frame_fx-M-1, hLPDmem->syn, M+1 );
+ IF (GT_16(st_fx->element_mode, EVS_MONO) && st_fx->hTcxEnc != NULL)
+ {
+ Copy(syn1_fx + st_fx->L_frame_fx / 2, st_fx->hTcxEnc->Txnq, st_fx->L_frame_fx / 2);
+ }
+
+ /*--------------------------------------------------------------------------------------*
+ * Modify the excitation signal when the noise is stationary
+ *--------------------------------------------------------------------------------------*/
+
+ IF (!(EQ_16(st_fx->idchan, 1) && EQ_16(st_fx->element_mode, IVAS_CPE_TD)) && NE_16(nelp_mode, 1) && !(EQ_16(st_fx->element_mode, IVAS_SCE) && tdm_low_rate_mode))
+ {
+ L_epsP[0] = L_Comp(epsP_h_fx[2],epsP_l_fx[2]);
+ move32();
+ L_epsP[1] = L_Comp(epsP_h_fx[M],epsP_l_fx[M]);
+ move32();
+ Copy(exc_fx, exc2_fx, st_fx->L_frame_fx);
+ stat_noise_uv_enc_fx( st_fx, L_epsP, lsp_new_fx, lsp_mid_fx, Aq_fx, exc2_fx, uc_two_stage_flag, Q_new );
+ }
+
+ /*-----------------------------------------------------------------*
+ * Encode supplementary information for Frame Error Concealment
+ *-----------------------------------------------------------------*/
+
+ FEC_encode_fx(hBstr, st_fx->acelp_cfg, syn_fx, coder_type, st_fx->clas_fx, pitch_buf_fx, res_fx, &st_fx->Last_pulse_pos_fx,
+ st_fx->L_frame_fx, st_fx->total_brate_fx, Q_new, shift );
+
+
+ IF (hBWE_TD != NULL)
+ {
+ IF(EQ_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ Copy(Aq_fx + 2 * (M + 1), hBWE_TD->cur_sub_Aq_fx, (M + 1));
+ }
+ ELSE
+ {
+ Copy(Aq_fx + 3 * (M + 1), hBWE_TD->cur_sub_Aq_fx, (M + 1));
+ }
+ }
+ } /* end of active inp coding */
+
+ /*-----------------------------------------------------------------*
+ * Write ACELP unused bits
+ *-----------------------------------------------------------------*/
+
+ test();
+ test();
+ IF ( NE_32(st_fx->core_brate_fx,SID_2k40)&&NE_32(st_fx->core_brate_fx,FRAME_NO_DATA)&&NE_32(st_fx->core_brate_fx,PPP_NELP_2k80))
+ {
+ /* reserved bits */
+ nBits = st_fx->acelp_cfg.ubits;
+
+ WHILE( nBits > 0 )
+ {
+ i = s_min(nBits, 16);
+ push_indice_fx( st_fx->hBstr, IND_UNUSED, 0, i );
+ nBits = sub(nBits,i);
+ }
+ }
+
+
+ /*-----------------------------------------------------------------*
+ * Apply non linearity in case of SWB TBE
+ *-----------------------------------------------------------------*/
+ IF(hBWE_TD != NULL)
+ {
+
+ test(); test();
+ test(); test();
+ test(); test(); test();
+
+ IF((EQ_16(st_fx->last_Opt_SC_VBR_fx, 1) && st_fx->Opt_SC_VBR_fx == 0) || ((EQ_16(st_fx->extl_fx, SWB_TBE) || EQ_16(st_fx->extl_fx, WB_TBE) || EQ_16(st_fx->extl_fx, FB_TBE)) && NE_16(st_fx->last_extl_fx, SWB_TBE) && NE_16(st_fx->last_extl_fx, WB_TBE) && NE_16(st_fx->last_extl_fx, FB_TBE)))
+ {
+ hBWE_TD->bwe_non_lin_prev_scale_fx = L_deposit_l(0);
+ set16_fx(hBWE_TD->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET);
+ }
+
+ IF(!st_fx->Opt_SC_VBR_fx)
+ {
+ /* Apply a non linearity to the SHB excitation */
+ non_linearity_fx(bwe_exc_fx, bwe_exc_extended_fx, L_FRAME32k, &hBWE_TD->bwe_non_lin_prev_scale_fx, Q_new, coder_type, voice_factors_fx, st_fx->L_frame_fx);
+ }
+ test();
+ if (EQ_32(st_fx->core_brate_fx, SID_2k40) || EQ_32(st_fx->core_brate_fx, FRAME_NO_DATA))
+ {
+ hBWE_TD->bwe_non_lin_prev_scale_fx = L_deposit_l(0);
+ }
+ }
+ /*-----------------------------------------------------------------*
+ * Updates
+ *-----------------------------------------------------------------*/
+ updt_enc_fx( st_fx, old_exc_fx, pitch_buf_fx, Es_pred_fx,Aq_fx, lsf_new_fx, lsp_new_fx, old_bwe_exc_fx );
+
+ test();
+ IF(hTdCngEnc != NULL && (st_fx->Opt_DTX_ON_fx != 0 ) && (GT_32(st_fx->core_brate_fx,SID_2k40)))
+ {
+ /* update CNG parameters in active frames */
+ cng_params_upd_fx( lsp_new_fx, exc_fx, st_fx->L_frame_fx, &hTdCngEnc->ho_circ_ptr, hTdCngEnc->ho_ener_circ_fx,
+ &hTdCngEnc->ho_circ_size, hTdCngEnc->ho_lsp_circ_fx, Q_new, ENC, NULL, &hTdCngEnc->cng_buf_cnt,
+ hTdCngEnc->cng_exc2_buf, hTdCngEnc->cng_Qexc_buf, hTdCngEnc->cng_brate_buf, hDtxEnc->last_active_brate );
+
+ IF( EQ_16(st_fx->L_frame_fx,L_FRAME))
+ {
+ /* store LSPs@16k, potentially to be used in CNG@16k */
+ Copy( st_fx->lsp_old16k_fx, &(hTdCngEnc->ho_lsp_circ2_fx[(hTdCngEnc->ho_circ_ptr)*M]), M );
+ }
+
+ /* Set 16k LSP flag for CNG buffer */
+ hTdCngEnc->ho_16k_lsp[hTdCngEnc->ho_circ_ptr] = 0;
+ move16();
+ if(NE_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ hTdCngEnc->ho_16k_lsp[hTdCngEnc->ho_circ_ptr] = 1;
+ move16();
+ }
+
+ /* efficient DTX hangover control */
+ IF ( GT_16(hTdCngEnc->burst_ho_cnt,1))
+ {
+ dtx_hangover_control_fx( st_fx, lsp_new_fx );
+ }
+ }
+
+ /* SC-VBR update of average data rate */
+ IF ( EQ_16(st_fx->vad_flag,1) && (hSC_VBR != NULL) )
+ {
+ update_average_rate_fx(hSC_VBR, st_fx->core_brate_fx);
+ }
+
+ return error;
+}
diff --git a/lib_enc/acelp_core_switch_enc_fx.c b/lib_enc/acelp_core_switch_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..68b926aa0969df70afe95c5ce3cca08955ac1e7d
--- /dev/null
+++ b/lib_enc/acelp_core_switch_enc_fx.c
@@ -0,0 +1,595 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com_fx.h"
+//#include "prot_fx.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+/*---------------------------------------------------------------------*
+ * Local function prototypes
+ *---------------------------------------------------------------------*/
+
+static void encod_gen_voic_core_switch_fx( Encoder_State_fx *st_fx,
+ const Word16 L_frame_fx, const Word16 inp_fx[], const Word16 Aq_fx[], const Word16 A_fx[], const Word16 T_op[],
+ Word16 *exc_fx, const Word32 core_bitrate_fx, Word16 shift, Word16 Q_new );
+
+static void bwe_switch_enc_fx(Encoder_State_fx *st_fx, const Word16 *new_speech );
+
+static Word16 dotprod_satcont(const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len, Word16 delta);
+
+/*-------------------------------------------------------------------*
+ * acelp_core_switch_enc_fx()
+ *
+ * ACELP core encoder in the ACELP->HQ switching frame
+ *--------------------------------------------------------------------*/
+
+void acelp_core_switch_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 inp12k8[], /* i : input signal @12.8 kHz Q0 */
+ const Word16 inp16k[], /* i : input signal @16 kHz Q0 */
+ const Word16 A[NB_SUBFR16k*(M+1)], /* i : A(z) unquantized for the 4 subframes Q12*/
+ Word16 shift,
+ Word16 Q_new
+)
+{
+ Word16 i, j, T_op[2];
+ Word16 old_exc[L_EXC], *exc; /* excitation signal buffer Qexc */
+ const Word16 *inp;
+ Word32 cbrate;
+ Word16 Aq[2*(M+1)];
+ LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+
+ hLPDmem = st_fx->hLPDmem;
+
+ /* initializations */
+ exc = &old_exc[L_EXC_MEM];
+ move16(); /* pointer to excitation signal in the current frame */
+ Copy( hLPDmem->old_exc, old_exc, L_EXC_MEM ); /*now old_exc has the same scaling as st_fx->old_exc; need to change later? */
+
+ Copy( st_fx->old_Aq_12_8_fx, Aq, M+1 );
+ Copy( st_fx->old_Aq_12_8_fx, Aq + (M+1), M+1 );
+ T_op[0] = st_fx->pitch_fx[0];
+ move16();
+ T_op[1] = st_fx->pitch_fx[1];
+ move16();
+
+ /*----------------------------------------------------------------*
+ * set switching frame bitrate
+ *----------------------------------------------------------------*/
+
+ IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME)) /* ACELP@12k8 core */
+ {
+ inp = inp12k8;
+
+ IF( GT_32(st_fx->core_brate_fx, ACELP_24k40 ))
+ {
+ cbrate = L_add(ACELP_24k40, 0);
+ }
+ ELSE
+ {
+ cbrate = L_add(st_fx->core_brate_fx, 0);
+ }
+ }
+ ELSE /* ACELP@16k core */
+ {
+ inp = inp16k;
+
+ IF( LE_32(st_fx->core_brate_fx, ACELP_8k00))
+ {
+ cbrate = L_add(ACELP_8k00, 0);
+ }
+ ELSE IF (LE_32(st_fx->core_brate_fx, ACELP_14k80))
+ {
+ cbrate = L_add(ACELP_14k80, 0);
+ }
+ ELSE
+ {
+ cbrate = L_min( st_fx->core_brate_fx, ACELP_22k60 );
+ }
+ }
+#ifdef FIX_I4_OL_PITCH
+ PMTE()
+ IF (EQ_16(st_fx->last_codec_mode, MODE1))
+ {
+ /* in MODE1 T_op is at 12.8 kHz */
+ IF (NE_16(st_fx->last_L_frame_fx, L_FRAME)) /* ACELP@16k core -> convert T_op to 16 kHz */
+ {
+ T_op[0] = shr(add(round_fx(L_shl(L_mult(20480, T_op[0]), 2)), 1), 1);
+ move16();
+ T_op[1] = shr(add(round_fx(L_shl(L_mult(20480, T_op[1]), 2)), 1), 1);
+ move16();
+ }
+ }
+ ELSE
+ {
+ /* in MODE2 T_op is at 16 kHz */
+ IF (EQ_16(st_fx->last_L_frame_fx, L_FRAME)) /* ACELP@12.8k core -> convert T_op to 12.8 kHz */
+ {
+ move16();move16();
+ T_op[0] = mult_r(26214, T_op[0]);
+ T_op[1] = mult_r(26214, T_op[1]);
+ }
+ }
+#else
+ IF( NE_16(st_fx->last_L_frame_fx, L_FRAME) )
+ {
+ T_op[0] = shr(add(round_fx(L_shl(L_mult(20480, T_op[0]), 2)), 1), 1);
+ move16();
+ T_op[1] = shr(add(round_fx(L_shl(L_mult(20480, T_op[1]), 2)), 1), 1);
+ move16();
+ }
+#endif
+ /*----------------------------------------------------------------*
+ * Excitation encoding
+ *----------------------------------------------------------------*/
+ config_acelp1(ENC, st_fx->total_brate_fx, cbrate, st_fx->core_fx, -1, -1, st_fx->last_L_frame_fx, -1, &(st_fx->acelp_cfg), hBstr->nb_bits_tot_fx,
+ GENERIC, -1, -1, &j, &i, st_fx->element_mode, &i /*dummy*/, 0 /*tdm_lp_reuse_flag*/, 0 /*tdm_low_rate_mode*/, st_fx->idchan, st_fx->active_fr_cnt_fx, 0 /*tdm_Pitch_reuse_flag*/, 0, 0 /*GSC_IVAS_mode*/);
+
+ encod_gen_voic_core_switch_fx( st_fx, st_fx->last_L_frame_fx, inp, Aq, A, T_op, exc, cbrate, shift, Q_new );
+
+ /*----------------------------------------------------------------*
+ * bit-stream: modify the layer of sub frame CELP
+ *----------------------------------------------------------------*/
+#ifdef IVAS_CODE_BITSTREAM
+ i = find_indice(hBstr, TAG_ACELP_SUBFR_LOOP_START, &value, &nb_bits);
+#ifdef DEBUGGING
+ assert(i >= 0 && "Internal error in ACELP core switching - unable to find ACELP subframe indices!");
+#endif
+ while (hBstr->ind_list[i].id == TAG_ACELP_SUBFR_LOOP_START)
+ {
+ push_indice(hBstr, IND_CORE_SWITCHING_CELP_SUBFRAME, hBstr->ind_list[i].value, hBstr->ind_list[i].nb_bits);
+ i++;
+ }
+ delete_indice(hBstr, TAG_ACELP_SUBFR_LOOP_START);
+#else
+ FOR( i=0; i<20; i++ )
+ {
+ hBstr->ind_list_fx[IND_CORE_SWITCHING_CELP_SUBFRAME+i].value= hBstr->ind_list_fx[TAG_ACELP_SUBFR_LOOP_START+i].value;
+ move16();
+ hBstr->ind_list_fx[IND_CORE_SWITCHING_CELP_SUBFRAME+i].nb_bits= hBstr->ind_list_fx[TAG_ACELP_SUBFR_LOOP_START+i].nb_bits;
+ move16();
+ hBstr->ind_list_fx[TAG_ACELP_SUBFR_LOOP_START+i].nb_bits=-1;
+ move16();
+ }
+#endif
+ /*----------------------------------------------------------------*
+ * BWE encoding
+ *----------------------------------------------------------------*/
+
+ test();
+ test();
+ IF( !( ( EQ_16(st_fx->last_L_frame_fx, L_FRAME16k)&&EQ_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME16k))||EQ_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME8k)))
+ {
+ bwe_switch_enc_fx( st_fx, (const Word16 *)st_fx->old_input_signal_fx );
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * encod_gen_voic_core_switch()
+ *
+ * Encode excitation signal in ACELP->HQ switching frame
+ *-------------------------------------------------------------------*/
+
+static void encod_gen_voic_core_switch_fx(
+ Encoder_State_fx *st_fx, /* i/o: state structure */
+ const Word16 L_frame, /* i : length of the frame */
+ const Word16 inp[], /* i : input signal */
+ const Word16 Aq[], /* i : LP coefficients */
+ const Word16 A[], /* i : unquantized A(z) filter */
+ const Word16 T_op[], /* i : open loop pitch */
+ Word16 *exc, /* i/o: current non-enhanced excitation */
+ const Word32 core_bitrate, /* i : switching frame bitrate */
+ Word16 shift,
+ Word16 Q_new
+)
+{
+ Word16 res[L_SUBFR]; /* residual signal Qexc */
+ Word16 Ap[M+1]; /* A(z) with spectral expansion Q12 */
+ Word16 xn[L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
+ Word16 cn[L_SUBFR]; /* Target vector in residual domain */
+ Word16 h1[L_SUBFR+(M+1)]; /* Impulse response vector */
+
+ Word16 code[L_SUBFR]; /* Fixed codebook excitation Q9 */
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */
+ Word16 gain_pit ; /* Pitch gain Q15 */
+ Word16 voice_fac; /* Voicing factor Q15 */
+ Word32 gain_code; /* Gain of code Q16 */
+ Word16 gain_inov; /* inovation gain */
+ Word16 i,gcode16; /* tmp variables */
+ Word16 T0, T0_frac; /* close loop integer pitch and fractional part */
+ Word16 T0_min, T0_max; /* pitch variables */
+
+ Word16 pitch,tmp16; /* floating pitch value */
+ Word16 g_corr[6]; /* ACELP correl, values + gain pitch */
+ Word16 clip_gain; /* ISF clip gain */
+
+ Word16 unbits; /* number of unused bits for PI */
+ Word32 norm_gain_code;
+ Word16 pitch_limit_flag;
+ Word32 L_tmp, Lgcode;
+ Word16 shift_wsp;
+ Word16 h2[L_SUBFR + (M + 1)];
+ Word16 dummyF[NB_SUBFR16k];
+ Word16 lp_select, lp_flag;
+ LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */
+ BSTR_ENC_HANDLE hBstr;
+
+ hLPDmem = st_fx->hLPDmem;
+ hBstr = st_fx->hBstr;
+
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+
+ /*------------------------------------------------------------------*
+ * Initializations
+ *------------------------------------------------------------------*/
+
+ shift_wsp = add(Q_new,shift);
+
+ unbits = 0;
+ move16();
+
+ IF( EQ_16(L_frame, L_FRAME))
+ {
+ T0_max = PIT_MAX;
+ move16();
+ T0_min = PIT_MIN;
+ move16();
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ T0_max = PIT16k_MAX;
+ move16();
+ T0_min = PIT16k_MIN;
+ move16();
+ }
+
+ /*------------------------------------------------------------------*
+ * Calculation of LP residual (filtering through A[z] filter)
+ *------------------------------------------------------------------*/
+
+ tmp16=st_fx->L_frame_fx;
+ move16();
+ st_fx->L_frame_fx=L_SUBFR;
+ move16();
+ calc_residu_fx(st_fx, inp, res, Aq);
+
+ hTdCngEnc->burst_ho_cnt = 0;
+ move16();
+ st_fx->L_frame_fx=tmp16;
+ move16();
+
+ /*------------------------------------------------------------------*
+ * ACELP subframe loop
+ *------------------------------------------------------------------*/
+
+
+ Copy( res, exc, L_SUBFR );
+
+ IF( EQ_16(L_frame,L_FRAME16k))
+ {
+ weight_a_fx( A, Ap, GAMMA16k, M ); /* Bandwidth expansion of A(z) filter coefficients */
+ find_targets_fx(inp, hLPDmem->mem_syn, 0, &(hLPDmem->mem_w0), Aq, res, L_SUBFR, Ap, PREEMPH_FAC_16k, xn, cn, h1);
+ }
+ ELSE
+ {
+ weight_a_fx( A, Ap, GAMMA1, M ); /* Bandwidth expansion of A(z) filter coefficients */
+ find_targets_fx(inp, hLPDmem->mem_syn,0,&(hLPDmem->mem_w0), Aq, res, L_SUBFR, Ap, TILT_FAC_FX, xn, cn ,h1);
+ }
+
+ /*Scale_sig(h1, L_SUBFR, shift); *//*Q14-shift */
+ Copy_Scale_sig(h1, h2, L_SUBFR, -2);
+ Scale_sig(h1, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(xn, L_SUBFR, shift);
+
+ /*----------------------------------------------------------------*
+ * Close-loop pitch search and quantization
+ * Adaptive exc. construction
+ *----------------------------------------------------------------*/
+ set16_fx(dummyF, -1, NB_SUBFR16k); /* hack to signal ACELP->HQ switching frame */
+ pitch = pit_encode_fx(hBstr,
+ st_fx->acelp_cfg.pitch_bits, core_bitrate, 0, L_frame, GENERIC, &pitch_limit_flag, 0, exc, L_SUBFR, T_op, &T0_min, &T0_max, &T0, &T0_frac, h1, xn
+ , 0 /*hStereoTD->tdm_Pitch_reuse_flag*/, dummyF /*hStereoTD->tdm_Pri_pitch_buf*/);
+
+ /*-----------------------------------------------------------------*
+ * Find adaptive exitation
+ *-----------------------------------------------------------------*/
+
+ pred_lt4( &exc[0], &exc[0], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP );
+
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ * or in case of floating point encoder & fixed p. decoder
+ *-----------------------------------------------------------------*/
+
+ clip_gain = gp_clip_fx(st_fx->element_mode, core_bitrate, st_fx->voicing_fx, 0, GENERIC, xn, st_fx->clip_var_fx, sub(shift_wsp, 1) );
+
+ /*-----------------------------------------------------------------*
+ * LP filtering of the adaptive excitation, codebook target computation
+ *-----------------------------------------------------------------*/
+ lp_flag = st_fx->acelp_cfg.ltf_mode;
+ lp_select = lp_filt_exc_enc_fx( MODE1, GENERIC, 0, exc, h1, xn, y1, xn2, L_SUBFR, L_frame, g_corr, clip_gain, &gain_pit, &lp_flag );
+
+ IF( EQ_16(lp_flag,NORMAL_OPERATION))
+ {
+ push_indice_fx(hBstr, IND_LP_FILT_SELECT, lp_select, 1 );
+ }
+
+ /*-----------------------------------------------------------------*
+ * Innovation encoding
+ *-----------------------------------------------------------------*/
+
+ inov_encode_fx( st_fx, core_bitrate, 0, L_frame,st_fx->last_L_frame_fx, GENERIC, st_fx->bwidth_fx, 0, 0, -1, Aq, gain_pit, cn, exc,
+ h2, hLPDmem->tilt_code, pitch, xn2, code, y2, &unbits, L_SUBFR, shift);
+
+ /*-----------------------------------------------------------------*
+ * Gain encoding
+ *-----------------------------------------------------------------*/
+ IF( EQ_16(L_frame,L_FRAME))
+ {
+ gain_enc_mless_fx(hBstr, st_fx->acelp_cfg.gains_mode, st_fx->element_mode, L_frame, 0, -1, xn, y1, shift_wsp, y2, code, st_fx->old_Es_pred_fx,
+ &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain );
+ }
+ ELSE
+ {
+ gain_enc_mless_fx(hBstr, st_fx->acelp_cfg.gains_mode, st_fx->element_mode, L_frame, 0, -1, xn, y1, shift_wsp, y2, code, st_fx->old_Es_pred_fx,
+ &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain );
+ }
+
+ gp_clip_test_gain_pit_fx(st_fx->element_mode, core_bitrate, gain_pit, st_fx->clip_var_fx );
+
+ Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx(Lgcode);
+
+ hLPDmem->tilt_code = Est_tilt2( exc+0, gain_pit, code, gain_code, &voice_fac,shift );
+
+ /*-----------------------------------------------------------------*
+ * Construct adaptive part of the excitation
+ *-----------------------------------------------------------------*/
+
+ FOR( i = 0; i < L_SUBFR; i++ )
+ {
+ /* code in Q9, gain_pit in Q14 */
+ L_tmp = L_mult(gcode16, code[i]);
+ L_tmp = L_shl(L_tmp, 5);
+ L_tmp = L_mac(L_tmp, exc[i ], gain_pit);
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ exc[i ] = round_fx(L_tmp);
+ }
+
+ /* write reserved bits */
+ IF( unbits )
+ {
+ push_indice_fx(hBstr, IND_UNUSED, 0, unbits );
+ }
+
+ /*-----------------------------------------------------------------*
+ * long term prediction on the 2nd sub frame
+ *-----------------------------------------------------------------*/
+
+ pred_lt4(&exc[L_SUBFR], &exc[L_SUBFR], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP);
+
+ FOR( i = L_SUBFR; i < 2*L_SUBFR; i++ )
+ {
+ exc[i] = round_fx(L_shl(L_mult(exc[i], gain_pit), 1));
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * bwe_switch_enc()
+ *
+ * Encode BWE in ACELP->HQ switching frame
+ *-------------------------------------------------------------------*/
+
+static void bwe_switch_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 *new_speech_fx /* i : original input signal Q0 */
+)
+{
+
+ Word16 k, Loverlapp_fx, d1m_fx, maxd1_fx, ind1_fx, gapsize_fx;
+ Word16 delta_fx, fdelay_fx;
+ const Word16 *hp_filter_fx;
+ const Word16 *fpointers_tab[6] = {hp12800_16000_fx, hp12800_32000_fx, hp12800_48000_fx, hp16000_48000_fx, hp16000_32000_fx, hp16000_48000_fx};
+ Word16 tmp, shift;
+ const Word16 *ptmp;
+ Word16 tmp_mem_fx[2*L_FILT48k], tmp_mem2_fx[2*L_FILT48k], hb_synth_tmp_fx[480];
+ Word16 Fs_kHz;
+ Word16 q_tmp1, q_tmp2, Qmc, Qsq;
+ Word32 L_tmp1, L_tmp2, L_tmp3, min_sq_cross_fx;
+ Word16 accA_fx, accB_fx, min_corr_fx, E1_fx, E2_fx, gain_fx;
+ Word16 synth_subfr_bwe_fx[SWITCH_MAX_GAP]; /* synthesized bwe for core switching */
+ Word16 n, L;
+ BSTR_ENC_HANDLE hBstr;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ hBstr = st_fx->hBstr;
+ L = NS2SA_fx2(st_fx->input_Fs_fx,FRAME_SIZE_NS);
+
+ /* set multiplication factor according to the sampling rate */
+ tmp = extract_l(L_shr(st_fx->input_Fs_fx,14));
+ delta_fx = add(tmp,1);
+ Fs_kHz = shl(delta_fx,4);
+ tmp = add(tmp,i_mult2(3,(sub(st_fx->last_L_frame_fx,L_FRAME)!=0)));
+ ptmp = fpointers_tab[tmp];
+ move16();
+
+ hp_filter_fx = ptmp;
+ fdelay_fx=i_mult2(16,delta_fx);
+ IF(EQ_16(st_fx->last_L_frame_fx,L_FRAME))
+ {
+ fdelay_fx=i_mult2(20,delta_fx);
+ }
+
+ n = i_mult2(N16_CORE_SW,delta_fx);
+
+ set16_fx( tmp_mem_fx, 0, 2*L_FILT48k);
+ set16_fx( tmp_mem2_fx, 0, 2*L_FILT48k);
+
+ Loverlapp_fx = i_mult2(delta_fx,SWITCH_OVERLAP_8k*2);
+ gapsize_fx = i_mult2(delta_fx,NS2SA(16000,SWITCH_GAP_LENGTH_NS));
+
+ shift = sub(add(add(shr(L,1),n),Loverlapp_fx),gapsize_fx) ;
+ Copy( new_speech_fx+shift,synth_subfr_bwe_fx,add(gapsize_fx,fdelay_fx) );
+ Copy( new_speech_fx+sub(shift,fdelay_fx),tmp_mem_fx,fdelay_fx );
+
+ tmp = add(gapsize_fx, fdelay_fx);
+ fir_fx( synth_subfr_bwe_fx, hp_filter_fx, synth_subfr_bwe_fx, tmp_mem_fx, tmp, fdelay_fx, 1, 0 );
+ Copy(synth_subfr_bwe_fx+shr(fdelay_fx,1),synth_subfr_bwe_fx,sub(gapsize_fx,shr(fdelay_fx,1)) );
+
+ tmp = i_mult2(Fs_kHz,10);
+ fir_fx( new_speech_fx, hp_filter_fx, hb_synth_tmp_fx, tmp_mem2_fx, tmp, fdelay_fx, 1, 0 );
+
+ min_sq_cross_fx = L_negate(1);
+ Qsq = 0;
+ move16();
+ min_corr_fx = 0;
+ move16();
+ Qmc = 0;
+ move16();
+ d1m_fx = 0;
+ move16();
+
+ maxd1_fx = sub(tmp,add(gapsize_fx,fdelay_fx));
+
+ IF (EQ_16(delta_fx, 2))
+ {
+ maxd1_fx = shr(maxd1_fx,1);
+ }
+ ELSE IF (EQ_16(delta_fx, 3))
+ {
+ maxd1_fx = extract_h(L_mult(maxd1_fx, 10923));
+ }
+
+ /* find delay */
+ ptmp = &hb_synth_tmp_fx[fdelay_fx];
+ move16();
+ FOR( k = 0; k < maxd1_fx; k++ )
+ {
+ accA_fx = dotprod_satcont(ptmp, ptmp, 0, 0, &q_tmp1, gapsize_fx, delta_fx);
+ accB_fx = dotprod_satcont(ptmp, synth_subfr_bwe_fx, 0, 0, &q_tmp2, gapsize_fx, delta_fx);
+ ptmp += delta_fx;
+ L_tmp1 = L_mult0(accB_fx, accB_fx); /*2*q_tmp2; */
+ L_tmp2 = Mult_32_16(L_tmp1, min_corr_fx); /*2*q_tmp2+Qmc-15 */
+ L_tmp3 = Mult_32_16(min_sq_cross_fx, accA_fx); /*Qsq+q_tmp1-15 */
+ shift = s_min(add(shl(q_tmp2,1),Qmc),add(q_tmp1,Qsq));
+ L_tmp2 = L_shr(L_tmp2, sub(add(shl(q_tmp2,1),Qmc),shift));
+ L_tmp3 = L_shr(L_tmp3, sub(add(q_tmp1,Qsq),shift));
+
+ IF (GE_32(L_tmp2,L_tmp3))
+ {
+ d1m_fx = k;
+ move16();
+ min_corr_fx = accA_fx;
+ move16();
+ Qmc = q_tmp1;
+ move16();
+ min_sq_cross_fx = L_add(L_tmp1, 0);
+ Qsq = shl(q_tmp2,1);
+ move16();
+ }
+ }
+
+ push_indice_fx(hBstr, IND_CORE_SWITCHING_AUDIO_DELAY, d1m_fx, AUDIODELAYBITS );
+
+ tmp = add(i_mult2(d1m_fx,delta_fx),fdelay_fx);
+ ptmp = &hb_synth_tmp_fx[tmp];
+ move16();
+ E1_fx = dotprod_satcont(synth_subfr_bwe_fx, synth_subfr_bwe_fx, 0, 0, &q_tmp1, gapsize_fx, 1);
+ E2_fx = dotprod_satcont(ptmp, ptmp, 0, 0, &q_tmp2, gapsize_fx, 1);
+
+ IF (!E1_fx)
+ {
+ E1_fx = shl(1,14);
+ q_tmp1 = 14;
+ move16();
+ }
+ IF (!E2_fx)
+ {
+ E2_fx = shl(1,14);
+ q_tmp2 = 14;
+ move16();
+ }
+
+ tmp = div_s(shl(1, 14), E1_fx); /*Q(29-q_tmp1) */
+ L_tmp1 = L_mult(tmp, E2_fx); /*30-q_tmp1+q_tmp2 */
+ q_tmp2 = sub(q_tmp1, q_tmp2); /*30-q_tmp2 */
+ L_tmp1 = L_shl(L_tmp1, sub(q_tmp2, 24));
+#ifdef BASOP_NOGLOB
+ gain_fx = round_fx_o(Isqrt(L_tmp1), &Overflow); /*Q12 */
+#else
+ gain_fx = round_fx(Isqrt(L_tmp1)); /*Q12 */
+#endif
+ ind1_fx = usquant_fx( gain_fx, &gain_fx, shr(MINVALUEOFFIRSTGAIN_FX,1), shr(DELTAOFFIRSTGAIN_FX,4), (1 << NOOFGAINBITS1) );
+ push_indice_fx(hBstr,IND_CORE_SWITCHING_AUDIO_GAIN, ind1_fx, NOOFGAINBITS1 );
+
+ return;
+}
+
+static Word16 dotprod_satcont(const Word16 *x, const Word16 *y, Word16 qx, Word16 qy, Word16 *qo, Word16 len, Word16 delta)
+{
+ Word16 tmp_tabx[L_FRAME48k], tmp_taby[L_FRAME48k];
+ Word16 shift, q, ener, i;
+ Word32 L_tmp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ Copy( x, tmp_tabx, len );
+ Copy( y, tmp_taby, len );
+ shift = 0;
+ move16();
+ DO
+ {
+ L_tmp = L_deposit_l(0);
+ Overflow = 0;
+ move16();
+ FOR ( i = 0; i < len; i += delta )
+ {
+#ifdef BASOP_NOGLOB /* Critical Overflow*/
+ L_tmp = L_mac0_o(L_tmp, tmp_tabx[i], tmp_taby[i], &Overflow); /*Q(qx+qy-shift) */
+#else /* BASOP_NOGLOB */
+ L_tmp = L_mac0(L_tmp, tmp_tabx[i], tmp_taby[i]); /*Q(qx+qy-shift) */
+#endif
+ }
+
+ IF(Overflow != 0)
+ {
+ FOR( i = 0; i < len; i += delta )
+ {
+ tmp_tabx[i] = shr(tmp_tabx[i], 2);
+ move16();
+ tmp_taby[i] = shr(tmp_taby[i], 2);
+ move16();
+ }
+ shift = add(shift, 4);
+ }
+ }
+ WHILE(Overflow != 0);
+
+ q = norm_l(L_tmp);
+ L_tmp = L_shl(L_tmp, q); /*Q(qx+qy-shift+q) */
+ ener = extract_h(L_tmp); /*Q(qx+qy-shift+q-16) */
+ q = add(q, add(qx, qy));
+ *qo = sub(q, add(shift, 16));
+
+ return ener;
+}
diff --git a/lib_enc/acelp_enc_util_fx.c b/lib_enc/acelp_enc_util_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..89399a711e4f43d7bc3f5ce29d335326788dbdf3
--- /dev/null
+++ b/lib_enc/acelp_enc_util_fx.c
@@ -0,0 +1,295 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include
+#include "options.h"
+//#include "prot_fx.h"
+#include "basop_util.h"
+#include "cnst.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "stat_enc.h"
+#include "rom_com.h"
+#include "rom_com_fx.h"
+#include "rom_enc.h"
+
+
+#define _1_Q9 0x200
+
+
+/*
+ * E_ACELP_toeplitz_mul_fx
+ *
+ * Parameters:
+ * R I: coefficients of Toeplitz matrix (Q9)
+ * c I: input vector Q_xn
+ * d O: output vector, exponent = j
+ *
+ * Function:
+ * Multiplication of Toeplitz matrix with vector c, such that
+ * d = toeplitz(R)*c
+ * Vector length is L_SUBFR
+*/
+Word16 E_ACELP_toeplitz_mul_fx(
+ const Word16 R[],
+ const Word16 c[],
+ Word16 d[],
+ const Word16 L_subfr,
+ const Word16 highrate
+)
+{
+ static const Word16 step = 4;
+ Word16 k, j, i;
+ Word32 s;
+ Word32 y32[L_SUBFR16k], L_maxloc, L_tot;
+
+
+ assert(L_subfr <= L_SUBFR16k);
+
+
+ /* first keep the result on 32 bits and find absolute maximum */
+ L_tot = L_deposit_l(1);
+
+ FOR (k = 0; k < step; k++)
+ {
+ L_maxloc = L_deposit_l(0);
+ FOR (i = k; i < L_subfr; i += step)
+ {
+ s = L_mult(R[i], c[0]);
+ FOR (j = 1; j < i; j++)
+ {
+ s = L_mac(s, R[i-j], c[j]);
+ }
+ FOR (; j 16 x tot */
+
+ Copy_Scale_sig_32_16(y32, d, L_subfr, j);
+
+ return j;
+}
+
+void E_ACELP_weighted_code(
+ const Word16 code[], /* i: code */
+ const Word16 H[], /* i: impulse response */
+ Word16 Q, /* i: Q format of H */
+ Word16 y[] /* o: weighted code */
+)
+{
+ Word16 i, j, k, one, n, nz[L_SUBFR];
+ Word32 L_tmp;
+
+ /* Collect nonzeros */
+ n = 0;
+ move16();
+ FOR (i=0; i 0);
+
+ one = shl(1, Q);
+ Q = sub(15, Q);
+
+ /* Generate weighted code */
+ j = nz[0];
+ move16();
+ set16_fx(y, 0, j);
+ FOR (k=0; knb_pulse+(k*4) <= 40);
+
+ copyWord8((const Word8*)E_ROM_tipos+(k * 4), (Word8*)ipos, config->nb_pulse);
+
+ /* if all tracks do not have equal number of pulses */
+ restpulses = s_and(config->nb_pulse, 3);
+
+ IF (restpulses)
+ {
+ SWITCH (config->codetrackpos)
+ {
+ case TRACKPOS_FIXED_FIRST: /* fixed track positions, starting from left */
+ /* add tracks from left */
+ FOR (iPulse=0; iPulsenb_pulse-restpulses+iPulse] = (UWord8)iPulse;
+ move16();
+ }
+ /* Put the same track on the next position, because the 1-pulse search
+ * will access it to determine if this could be in any track. */
+ ipos[config->nb_pulse] = ipos[config->nb_pulse-1];
+ move16();
+ BREAK;
+ case TRACKPOS_FIXED_EVEN: /* fixed track positions, odd tracks */
+ /* odd tracks, switch order for every iteration */
+ ipos[config->nb_pulse-restpulses] = (UWord8)s_and(lshl(k,1),2);
+ move16();/* 0 for even k, 2 for odd */
+ ipos[config->nb_pulse-restpulses+1] = (UWord8)s_xor(ipos[config->nb_pulse-restpulses], 2);
+ move16();/* 2 for even k, 0 for odd */
+ BREAK;
+ case TRACKPOS_FIXED_TWO: /* two tracks instead of four */
+ /* Put the next track on the next position, because the 1-pulse search
+ * will access it to determine if this could be in any track. */
+ ipos[config->nb_pulse] = (UWord8)s_and(add(ipos[config->nb_pulse-1],1),3);
+ move16();
+ BREAK;
+ default: /* one or three free track positions */
+ /* copy an extra position from table - 1pulse search will access this */
+ ipos[config->nb_pulse] = E_ROM_tipos[add(shl(k,2),config->nb_pulse)];
+ move16();
+ BREAK;
+ }
+ }
+}
+
diff --git a/lib_enc/amr_wb_enc_fx.c b/lib_enc/amr_wb_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..2f2f3f4d7d3d456398ccd05cf29678fee1dceef2
--- /dev/null
+++ b/lib_enc/amr_wb_enc_fx.c
@@ -0,0 +1,622 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_enc.h" /* Encoder static table prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "basop_util.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+#include "prot_fx_enc.h"
+
+/*-------------------------------------------------------------------*
+ * amr_wb_enc()
+ *
+ * AMR-WB encoder
+ *--------------------------------------------------------------------*/
+
+void amr_wb_enc_fx(
+ Encoder_State_fx *st, /* i/o: encoder state structure */
+ const Word16 input_sp[], /* i : input signal */
+ const Word16 n_samples /* i : number of input samples */
+)
+{
+ Word16 i, delay;
+ Word16 old_inp[L_INP_12k8], *new_inp, *inp; /* buffer of old input signal */
+ Word16 old_inp_16k[L_INP_12k8+L_SUBFR], *inp_16k, *new_inp_16k;/* buffer of old input signal @16kHz*/
+ Word16 old_exc[L_EXC], *exc; /* excitation signal buffer */
+ Word16 old_wsp[L_WSP], *wsp; /* weighted input signal buffer */
+ Word16 input_frame; /* frame length at input sampling freq. */
+ Word32 fr_bands[2*NB_BANDS]; /* energy in frequency bands */
+ Word32 lf_E[2*VOIC_BINS]; /* per bin spectrum energy in lf */
+ Word32 tmpN[NB_BANDS]; /* temporary noise update */
+ Word32 tmpE[NB_BANDS], PS[L_FFT/2]; /* temporary averaged energy of 2 sf. */
+ Word16 corr_shift; /* correlation shift */
+ Word16 relE; /* frame relative energy */
+ Word16 cor_map_sum, sp_div;
+ Word16 Etot; /* total energy */
+ Word32 ener = 0; /* residual energy from Levinson-Durbin */
+ Word16 A[NB_SUBFR*(M+1)]; /* A(z) unquantized for the 4 subframes */
+ Word16 Aw[NB_SUBFR*(M+1)]; /* A(z) unquantized for the 4 subframes */
+ Word16 vad_hover_flag, noisy_speech_HO, clean_speech_HO, NB_speech_HO;
+ Word16 epsP_h[M+1]; /* LP prediction errors */
+ Word16 epsP_l[M+1]; /* LP prediction errors */
+ Word16 isp_new[M]; /* ISPs at the end of the frame */
+ Word16 isf_new[M]; /* ISFs at the end of the frame */
+ Word16 isp_tmp[M];
+ Word16 Aq[NB_SUBFR*(M+1)]; /* A(z) quantized for the 4 subframes */
+ Word16 syn[L_FRAME]; /* synthesis vector */
+ Word16 res[L_FRAME]; /* residual signal for FER protection */
+ Word16 exc2[L_FRAME]; /* enhanced excitation */
+ Word16 pitch_buf[NB_SUBFR]; /* floating pitch for each subframe */
+ Word16 dummy_buf[L_FRAME32k]; /* dummy buffer - no usage */
+ Word16 snr_sum_he;
+ Word16 allow_cn_step;
+ Word16 tmps;
+ Word16 harm_flag; /* Q0 */
+ Word16 high_lpn_flag;
+ Word16 localVAD_HE_SAD;
+ Word16 vad_flag_dtx;
+ Word16 hf_gain_fx[NB_SUBFR];
+ Word16 Q_new, Q_exp,Q_r[2];
+ Word16 excitation_max_test, shift;
+ Word32 Le_min_scaled;
+ Word16 Q_sp_div;
+ Word16 non_staX, Scale_fac[2];
+ Word16 sp_floor;
+ Word16 fft_buff[2*L_FFT];
+ Word32 q_env[NUM_ENV_CNG];
+ Word16 sid_bw = 0;
+ Word16 exc3[L_FRAME];
+ Word32 lp_bckr, hp_bckr, Ltmp;
+ Word16 tmp, e_tmp;
+ Word16 old_pitch1;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc;
+ NOISE_EST_HANDLE hNoiseEst = st->hNoiseEst;
+ VAD_HANDLE hVAD = st->hVAD;
+ DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc;
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+ GSC_ENC_HANDLE hGSCEnc = st->hGSCEnc;
+ AMRWB_IO_ENC_HANDLE hAmrwb_IO = st->hAmrwb_IO;
+ TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD;
+ FD_BWE_ENC_HANDLE hBWE_FD = st->hBWE_FD;
+
+ /*------------------------------------------------------------------*
+ * Initialization
+ *------------------------------------------------------------------*/
+
+ st->L_frame_fx = L_FRAME;
+ move16();
+ st->gamma = GAMMA1;
+ move16();
+ st->core_fx = AMR_WB_CORE;
+ move16();
+ st->core_brate_fx = st->total_brate_fx;
+ move16();
+ st->input_bwidth_fx = st->last_input_bwidth_fx;
+ move16();
+ st->bwidth_fx = st->last_bwidth_fx;
+ move16();
+ st->coder_type = GENERIC;
+ move16();
+ input_frame = st->input_frame_fx;
+ move16(); /* frame length of the input signal */
+ st->extl_fx = -1;
+ st->encoderPastSamples_enc = (L_FRAME*9)/16;
+ st->encoderLookahead_enc = L_LOOK_12k8;
+ st->bpf_off_fx = 0;
+ move16();
+ test();
+ if( EQ_16(st->last_core_fx,HQ_CORE)||EQ_16(st->last_codec_mode,MODE2))
+ {
+ st->bpf_off_fx = 1;
+ move16();
+ }
+ st->igf = 0;
+ move16();
+
+ /* Updates in case of EVS primary mode -> AMR-WB IO mode switching */
+ IF( NE_16(st->last_core_fx,AMR_WB_CORE))
+ {
+ updt_IO_switch_enc_fx( st, input_frame);
+ }
+
+ /* Updates in case of HQ -> AMR-WB IO mode switching */
+ Q_new = 0;
+ move16(); /* prevent compiler warning only*/
+ core_switching_pre_enc_fx( st, NULL, NULL, 0, 0 );
+
+ set16_fx( hf_gain_fx, 0, NB_SUBFR );
+ set16_fx( old_inp, 0, L_INP_12k8 );
+ exc = old_exc + L_EXC_MEM; /* pointer to excitation signal in the current frame */
+
+ Copy( hLPDmem->old_exc, old_exc, L_EXC_MEM );
+
+ new_inp = old_inp + L_INP_MEM; /* pointer to new samples of the input signal */
+ inp = new_inp - L_LOOK_12k8; /* pointer to current frame of input signal */
+ wsp = old_wsp + L_WSP_MEM; /* pointer to current frame of weighted signal */
+
+ Copy( st->old_inp_12k8_fx, old_inp, L_INP_MEM );
+ Copy( st->old_wsp_fx, old_wsp, L_WSP_MEM );
+
+ new_inp_16k = old_inp_16k + L_INP_MEM; /* pointer to new samples of the input signal in 16kHz core */
+ inp_16k = new_inp_16k - L_LOOK_16k; /* pointer to the current frame of input signal in 16kHz core */
+ Copy( st->old_inp_16k_fx, old_inp_16k, L_INP_MEM );
+
+ /* in case of switching, reset AMR-WB BWE memories */
+ test();
+ IF( EQ_32(st->total_brate_fx,ACELP_23k85)&&NE_32(st->last_core_brate_fx,ACELP_23k85))
+ {
+ hf_cod_init_fx(hAmrwb_IO->mem_hp400_enc_fx, hAmrwb_IO->mem_hf_enc_fx, hAmrwb_IO->mem_syn_hf_enc_fx, hAmrwb_IO->mem_hf2_enc_fx, &hAmrwb_IO->gain_alpha_fx );
+ }
+
+ /*----------------------------------------------------------------*
+ * set input samples buffer
+ *----------------------------------------------------------------*/
+
+ /* get delay to synchronize ACELP and MDCT frame */
+ delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS);
+
+ Copy( st->input - delay, st->old_input_signal_fx, input_frame+delay );
+
+ /*----------------------------------------------------------------*
+ * Buffering of input signal
+ * HP filtering
+ *----------------------------------------------------------------*/
+
+ Copy( input_sp, st->input, n_samples );
+ FOR( i = n_samples; i < input_frame; i++ )
+ {
+ st->input[i] = 0;
+ move16();
+ }
+ hp20( st->input, 1, input_frame, st->mem_hp20_in_fx, st->input_Fs_fx );
+
+ /*-----------------------------------------------------------------*
+ * switching from ACELP@16k core to AMR-WB IO mode
+ *-----------------------------------------------------------------*/
+
+ st->rate_switching_reset=0;
+ move16();
+ test();
+ test();
+ IF( NE_16(st->last_core_fx,AMR_WB_CORE)&&EQ_16(st->last_L_frame_fx,L_FRAME16k)&&NE_16(st->last_core_fx,HQ_CORE))
+ {
+ /* in case of switching, do not apply BPF */
+ st->bpf_off_fx = 1;
+ move16();
+ st->rate_switching_reset=lsp_convert_poly_fx(st->lsp_old_fx, L_FRAME, 1);
+
+ /* convert old quantized LSF vector */
+ lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, INT_FS_FX );
+
+ /* Reset LPC mem */
+ Copy( GEWB_Ave_fx, st->mem_AR_fx, M );
+ set16_fx( st->mem_MA_fx,0, M );
+
+ /* update synthesis filter memories */
+ synth_mem_updt2(L_FRAME, st->last_L_frame_fx, hLPDmem->old_exc, hLPDmem->mem_syn_r, hLPDmem->mem_syn1_fx, hLPDmem->mem_syn, ENC);
+ Copy(hLPDmem->mem_syn1_fx, hLPDmem->mem_syn2, M);
+
+ Copy( hLPDmem->old_exc, old_exc, L_EXC_MEM );
+ Copy( hLPDmem->mem_syn2, hLPDmem->mem_syn3, M );
+
+ /* lsp -> isp */
+ Copy( stable_ISP_fx, isp_tmp, M );
+ lsp2isp_fx( st->lsp_old_fx, st->lsp_old_fx, isp_tmp, M );
+
+ }
+
+ /* update buffer of old subframe pitch values */
+ IF( NE_16(st->last_L_frame_fx,L_FRAME))
+ {
+ move16();
+ IF( EQ_16(st->last_L_frame_fx,L_FRAME32k))
+ {
+ /* (float)12800/(float)32000; */
+ tmp = 13107;
+ }
+ ELSE IF( EQ_16(st->last_L_frame_fx,512))
+ {
+ /* (float)12800/(float)25600; */
+ tmp = 16384;
+ }
+ ELSE /* st->last_L_frame == L_FRAME16k */
+ {
+ /* (float)12800/(float)16000; */
+ tmp = 26214;
+ }
+
+ FOR( i=NB_SUBFR16k-NB_SUBFR; iold_pitch_buf_fx[i-1] = mult_r(tmp, st->old_pitch_buf_fx[i]);
+ move16();
+ }
+
+ FOR( i=2*NB_SUBFR16k-NB_SUBFR; i<2*NB_SUBFR16k; i++ )
+ {
+ st->old_pitch_buf_fx[i-2] = mult_r(tmp, st->old_pitch_buf_fx[i]);
+ move16();
+ }
+ }
+
+ test();
+ if( EQ_16(st->last_bwidth_fx,NB)&&st->ini_frame_fx !=0)
+ {
+ st->rate_switching_reset=1;
+ move16();
+ }
+
+ /*----------------------------------------------------------------*
+ * Change the sampling frequency to 12.8 kHz
+ *----------------------------------------------------------------*/
+
+ modify_Fs_fx( st->input, input_frame, st->input_Fs_fx, new_inp, 12800, st->mem_decim_fx, 0 );
+
+ /* update signal buffer */
+ Copy( new_inp, st->buf_speech_enc+L_FRAME, L_FRAME );
+ Scale_sig( st->buf_speech_enc+L_FRAME, L_FRAME, 1 );
+
+ /*------------------------------------------------------------------*
+ * Perform fixed preemphasis through 1 - g*z^-1
+ *-----------------------------------------------------------------*/
+
+ Preemph_scaled( new_inp, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, 1, L_Q_MEM, L_FRAME, st->last_coder_type_fx, 1 );
+
+ Q_exp = sub(Q_new, st->Q_old);
+ move16();
+ st->Q_old = Q_new;
+ move16();
+
+ Le_min_scaled = Scale_mem_pre_proc( st->ini_frame_fx, Q_exp, &Q_new, old_inp, &(st->mem_wsp_fx), hNoiseEst->enrO_fx, hNoiseEst->bckr_fx, hNoiseEst->ave_enr_fx,
+ hNoiseEst->ave_enr2_fx, hNoiseEst->fr_bands1_fx, hNoiseEst->fr_bands2_fx, st->Bin_E_old_fx );
+
+ Q_exp = sub(Q_new, st->prev_Q_new);
+ move16();
+ Scale_mem_enc( Q_exp, old_inp_16k, old_exc, hBWE_TD->old_bwe_exc_fx, &(hLPDmem->mem_w0), hLPDmem->mem_syn, hLPDmem->mem_syn2,
+ &st->mem_deemp_preQ_fx, hGSCEnc->last_exc_dct_in_fx, hBWE_FD->old_input_lp_fx );
+
+ /*----------------------------------------------------------------*
+ * Compute spectrum, find energy per critical frequency band
+ * Track energy and signal dynamics
+ * Detect NB spectrum in a 16kHz-sampled input
+ *----------------------------------------------------------------*/
+
+ analy_sp_fx(st->element_mode,
+#ifdef IVAS_CODE_CPE
+ hCPE,
+#endif
+ st->input_Fs_fx, inp, Q_new, fr_bands, lf_E, & Etot, st->min_band_fx, st->max_band_fx, Le_min_scaled, Scale_fac, st->Bin_E_fx,
+ st->Bin_E_old_fx, PS, st->lgBin_E_fx, st->band_energies, fft_buff );
+
+ noise_est_pre_fx( Etot, st->ini_frame_fx, hNoiseEst, 0, EVS_MONO, EVS_MONO);
+
+ /*----------------------------------------------------------------*
+ * VAD
+ *----------------------------------------------------------------*/
+
+ st->vad_flag = wb_vad_fx( st, fr_bands, &noisy_speech_HO, &clean_speech_HO, &NB_speech_HO,
+ &snr_sum_he, &localVAD_HE_SAD, &(st->flag_noisy_speech_snr), Q_new
+ , hVAD,hNoiseEst, st->lp_speech_fx, st->lp_noise_fx ) ;
+
+ if (st->vad_flag == 0 )
+ {
+ st->coder_type = INACTIVE;
+ move16();
+ }
+
+ /* apply DTX hangover for CNG analysis */
+ vad_flag_dtx = dtx_hangover_addition_fx( st, st->vad_flag, sub(st->lp_speech_fx, st->lp_noise_fx), 0, &vad_hover_flag, NULL, NULL);
+
+ /*-----------------------------------------------------------------*
+ * Select SID or FRAME_NO_DATA frame if DTX enabled
+ *-----------------------------------------------------------------*/
+
+ IF ( NE_16(st->last_core_fx,AMR_WB_CORE))
+ {
+ st->fd_cng_reset_flag = 1;
+ move16();
+ }
+ ELSE IF ( s_and((st->fd_cng_reset_flag > 0),(Word16)(LT_16(st->fd_cng_reset_flag,10))))
+ {
+ st->fd_cng_reset_flag = add(st->fd_cng_reset_flag,1);
+ }
+ ELSE
+ {
+ st->fd_cng_reset_flag = 0;
+ move16();
+ }
+
+ dtx_fx( st, vad_flag_dtx, inp, Q_new );
+
+ /*----------------------------------------------------------------*
+ * Noise energy down-ward update and total noise energy estimation
+ * Long-term energies and relative frame energy updates
+ * Correlation correction as a function of total noise level
+ *----------------------------------------------------------------*/
+
+ noise_est_down_fx( fr_bands, hNoiseEst->bckr_fx, tmpN, tmpE, st->min_band_fx, st->max_band_fx, &hNoiseEst->totalNoise_fx,
+ Etot, &hNoiseEst->Etot_last_fx, &hNoiseEst->Etot_v_h2_fx, Q_new, Le_min_scaled );
+
+ high_lpn_flag = 0;
+ move16(); /* Q0 flag */
+ long_enr_fx( st, Etot, localVAD_HE_SAD, high_lpn_flag
+#ifdef IVAS_CODE
+ , NULL, 1, NULL, NULL
+#endif
+ );
+ relE = sub(Etot, st->lp_speech_fx); /* Q8 */
+
+ IF( NE_16(st->bwidth_fx, NB))
+ {
+ lp_bckr = Mean32(hNoiseEst->bckr_fx, 10 );
+ }
+ ELSE
+ {
+ lp_bckr = Mean32(hNoiseEst->bckr_fx+1, 9 );
+ }
+ hp_bckr = L_shr(L_add(hNoiseEst->bckr_fx[st->max_band_fx -1] , hNoiseEst->bckr_fx[st->max_band_fx]),1);
+ if( hp_bckr == 0 ) /* Avoid division by zero. */
+ {
+ hp_bckr = L_deposit_l(1);
+ }
+ tmp = BASOP_Util_Divide3232_Scale( lp_bckr, hp_bckr, &e_tmp );
+ Ltmp = L_shr_r( L_deposit_h( tmp ), sub( 15, e_tmp ) );
+ st->bckr_tilt_lt = L_add( Mpy_32_16_r( st->bckr_tilt_lt, 29491 ), Mpy_32_16_r( Ltmp, 3277 ) );
+
+ corr_shift = correlation_shift_fx(hNoiseEst->totalNoise_fx );
+
+ /*----------------------------------------------------------------*
+ * WB, SWB and FB bandwidth detector
+ *----------------------------------------------------------------*/
+
+ bw_detect_fx( st, st->input, NULL, NULL, NULL, MONO_FORMAT, 0);
+
+ /* in AMR_WB IO, limit the maximum band-width to WB */
+ if( GT_16(st->bwidth_fx,WB))
+ {
+ st->bwidth_fx = WB;
+ move16();
+ }
+
+ /*----------------------------------------------------------------*
+ * Perform LP analysis
+ * Compute weighted inp
+ * Perform open-loop pitch analysis
+ * Perform 1/4 pitch precision improvement
+ *----------------------------------------------------------------*/
+
+ IF (st->vad_flag == 0 )
+ {
+ /* reset the OL pitch tracker memories during inactive frames */
+ pitch_ol_init_fx( &st->old_thres_fx, &st->old_pitch, &st->delta_pit_fx, &st->old_corr_fx) ;
+ }
+ old_pitch1 = st->pitch_fx[1];
+ move16();
+ analy_lp_AMR_WB_fx( inp, &ener, A, epsP_h, epsP_l, isp_new, st->lsp_old1_fx,
+ isf_new, st->old_pitch_la, st->old_voicing_la, Q_new, Q_r );
+
+ find_wsp_fx( A, inp, wsp, &st->mem_wsp_fx, TILT_FAC_FX, L_FRAME, L_LOOK_12k8, L_SUBFR, Aw, GAMMA1, NB_SUBFR );
+ Scale_wsp( wsp, &(st->old_wsp_max), &shift, &Q_exp, &(st->old_wsp_shift),
+ st->old_wsp2_fx, st->mem_decim2_fx, st->old_wsp_fx, add(L_FRAME, L_LOOK_12k8));
+
+ excitation_max_test = -32768;
+ move16();
+ FOR (i = 0; i < L_EXC_MEM; i++)
+ {
+ excitation_max_test = s_max(abs_s(old_exc[i]),excitation_max_test);
+ }
+
+ test();
+ if( GT_16(excitation_max_test,8192)&&shift==0)
+ {
+ shift = -1;
+ move16();
+ }
+ pitch_ol_fx( st->pitch_fx, st->voicing_fx, &st->old_pitch, &st->old_corr_fx, corr_shift, &st->old_thres_fx, &st->delta_pit_fx, st->old_wsp2_fx, wsp, st->mem_decim2_fx, relE, 0, st->bwidth_fx, st->Opt_SC_VBR_fx );
+ st->old_pitch_la = st->pitch_fx[2];
+ move16();
+ st->old_voicing_la = st->voicing_fx[2];
+ move16();
+
+ /* VAD parameters update */
+ vad_param_updt_fx( st, old_pitch1 , corr_shift, corr_shift, A, NULL, 1 );
+
+ /*------------------------------------------------------------------*
+ * Update estimated noise energy and voicing cut-off frequency
+ *-----------------------------------------------------------------*/
+
+ noise_est_fx( st, old_pitch1, tmpN, epsP_h, epsP_l, Etot, relE, corr_shift, tmpE, fr_bands, &cor_map_sum,
+ NULL, &sp_div, &Q_sp_div, &non_staX, &harm_flag,
+ lf_E, &hNoiseEst->harm_cor_cnt, hNoiseEst->Etot_l_lp_fx, hNoiseEst->Etot_v_h2_fx, &hNoiseEst->bg_cnt, st->lgBin_E_fx, Q_new, Le_min_scaled, &sp_floor, NULL,
+#ifdef IVAS_CODE
+ NULL, NULL,
+#endif
+ st->ini_frame_fx);
+
+ /*----------------------------------------------------------------*
+ * Change the sampling frequency to 16 kHz,
+ * input@16kHz needed for AMR-WB IO BWE @23.85kbps
+ *----------------------------------------------------------------*/
+
+ test();
+ IF( EQ_32(st->input_Fs_fx, 16000))
+ {
+ /* no resampling needed, only delay adjustement to account for the FIR resampling delay */
+ tmps = NS2SA_fx2(16000, DELAY_FIR_RESAMPL_NS);
+ Copy_Scale_sig( &st->mem_decim16k_fx[tmps], new_inp_16k, tmps, -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */
+ Copy_Scale_sig( st->input, new_inp_16k + tmps, sub(input_frame, tmps), -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */
+ Copy( st->input + input_frame - shl(tmps,1), st->mem_decim16k_fx, shl(tmps,1) ); /* memory still in Q0 */
+ }
+ ELSE IF( EQ_32(st->input_Fs_fx, 32000)||EQ_32(st->input_Fs_fx,48000))
+ {
+ modify_Fs_fx( st->input, input_frame, st->input_Fs_fx, new_inp_16k, 16000, st->mem_decim16k_fx, 0 );
+ }
+
+ /*----------------------------------------------------------------*
+ * Encoding of SID frames
+ *----------------------------------------------------------------*/
+
+ test();
+ IF ( EQ_32(st->core_brate_fx,SID_1k75)||EQ_32(st->core_brate_fx,FRAME_NO_DATA))
+ {
+ /* encode CNG parameters */
+ CNG_enc_fx( st, Aq, inp, ener, isp_new, isp_new, isf_new , &allow_cn_step, sub(Q_new,1), q_env, &sid_bw );
+
+ /* comfort noise generation */
+ CNG_exc_fx( st->core_brate_fx, L_FRAME, &hTdCngEnc->Enew_fx, &hTdCngEnc->cng_seed, exc, exc2, &hTdCngEnc->lp_ener_fx,
+ st->last_core_brate_fx, &hDtxEnc->first_CNG, &hTdCngEnc->cng_ener_seed, dummy_buf, allow_cn_step,
+ &hTdCngEnc->last_allow_cn_step, sub(st->prev_Q_new,1), sub(Q_new,1), hTdCngEnc->num_ho, q_env, hTdCngEnc->lp_env_fx,
+ hTdCngEnc->old_env_fx, hTdCngEnc->exc_mem_fx, hTdCngEnc->exc_mem1_fx, &sid_bw, &hTdCngEnc->cng_ener_seed1, exc3, st->Opt_AMR_WB_fx, st->element_mode);
+
+ if (hDtxEnc->first_CNG == 0 )
+ {
+ hDtxEnc->first_CNG = 1;
+ move16();
+ }
+
+ /* synthesis */
+ syn_12k8_fx( L_FRAME, Aq, exc2, dummy_buf, hLPDmem->mem_syn3, 1, Q_new, st->Q_syn );
+
+ /* reset the encoder */
+ CNG_reset_enc_fx( st, hLPDmem, pitch_buf, dummy_buf+L_FRAME, 0 );
+
+ /* update st->mem_syn1 for ACELP core switching */
+ Copy(hLPDmem->mem_syn3, hLPDmem->mem_syn1_fx, M);
+
+ /* update ACELP core synthesis filter memory */
+ Copy( hLPDmem->mem_syn3, hLPDmem->mem_syn, M );
+
+ /* update old synthesis buffer - needed for ACELP internal sampling rate switching */
+ Copy( dummy_buf + L_FRAME - L_SYN_MEM, hLPDmem->mem_syn_r, L_SYN_MEM );
+ /* Update MODE2 core switching memory */
+ E_UTIL_deemph2( sub(Q_new,1), dummy_buf, PREEMPH_FAC, L_FRAME, &(hLPDmem->syn[M]) );
+ Copy( dummy_buf+L_FRAME-M-1, hLPDmem->syn, M+1 );
+
+ }
+
+ /*----------------------------------------------------------------*
+ * Encoding of all other frames
+ *----------------------------------------------------------------*/
+
+ ELSE
+ {
+ /*-----------------------------------------------------------------*
+ * After inactive period, use the most up-to-date ISPs
+ *-----------------------------------------------------------------*/
+ test();
+ IF( EQ_32(st->last_core_brate_fx,FRAME_NO_DATA)||EQ_32(st->last_core_brate_fx,SID_1k75))
+ {
+ Copy(hDtxEnc->lspCNG_fx, st->lsp_old_fx, M );
+ E_LPC_isp_isf_conversion(hDtxEnc->lspCNG_fx, st->lsf_old_fx, M);
+ set16_fx( old_exc, 0, L_EXC_MEM );
+ }
+
+ /*-----------------------------------------------------------------*
+ * ISF Quantization and interpolation
+ *-----------------------------------------------------------------*/
+
+ isf_enc_amr_wb_fx( st, isf_new, isp_new, Aq);
+
+ /*---------------------------------------------------------------*
+ * Calculation of LP residual (filtering through A[z] filter)
+ *---------------------------------------------------------------*/
+
+ calc_residu_fx(st, inp, res, Aq);
+ if (hTdCngEnc != NULL)
+ {
+ hTdCngEnc->burst_ho_cnt = 0;
+ }
+
+ move16();
+
+ /*------------------------------------------------------------*
+ * Encode excitation
+ *------------------------------------------------------------*/
+
+ encod_amr_wb_fx( st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, hf_gain_fx, inp_16k, shift, Q_new );
+
+ /* update st->mem_syn1 for ACELP core switching */
+ Copy( hLPDmem->mem_syn, hLPDmem->mem_syn1_fx, M );
+
+ /* update old synthesis buffer - needed for ACELP internal sampling rate switching */
+ Copy( syn + L_FRAME - L_SYN_MEM, hLPDmem->mem_syn_r, L_SYN_MEM );
+
+ /* Update MODE2 core switching memory */
+ E_UTIL_deemph2( sub(Q_new,1), syn, PREEMPH_FAC, L_FRAME, &(hLPDmem->syn[M]) );
+ Copy( syn+L_FRAME-M-1, hLPDmem->syn, M+1 );
+
+ /*--------------------------------------------------------------------------------------*
+ * Write VAD information into the bitstream in AMR-WB IO mode
+ *--------------------------------------------------------------------------------------*/
+
+ push_indice_fx( st->hBstr, IND_VAD_FLAG, st->vad_flag, 1 );
+ }
+
+ /*-----------------------------------------------------------------*
+ * Updates
+ *-----------------------------------------------------------------*/
+
+ /* update old weighted speech buffer - for OL pitch analysis */
+ Copy( &old_wsp[L_FRAME], st->old_wsp_fx, L_WSP_MEM );
+
+ /* update old input signal buffer */
+ Copy( &old_inp[L_FRAME], st->old_inp_12k8_fx, L_INP_MEM );
+
+ /* update old input signal @16kHz buffer */
+ IF( GT_32(st->input_Fs_fx,8000))
+ {
+ Copy( &old_inp_16k[L_FRAME16k], st->old_inp_16k_fx, L_INP_MEM );
+ }
+
+ /* update of old per-band energy spectrum */
+ Copy32( fr_bands + NB_BANDS, hNoiseEst->enrO_fx, NB_BANDS );
+
+ /* update the last bandwidth */
+ st->last_input_bwidth_fx = st->input_bwidth_fx;
+ st->last_bwidth_fx = st->bwidth_fx;
+
+ /* update signal buffers */
+ Copy( new_inp, st->buf_speech_enc_pe+L_FRAME, L_FRAME );
+ Copy( wsp, st->buf_wspeech_enc+L_FRAME+L_SUBFR, L_FRAME + L_LOOK_12k8 );
+ updt_enc_fx( st, old_exc, pitch_buf, 0, Aq, isf_new, isp_new, dummy_buf );
+
+ /* update main codec parameters */
+ updt_enc_common_fx(st, Etot, Q_new);
+#ifdef MY_DEBUG
+ dbgwrite_indices(st);
+#endif
+ return;
+}
+/*---------------------------------------------------------------------*
+ * amr_wb_enc_init_fx()
+ *
+ * Initialize AMR-WB encoder
+ *---------------------------------------------------------------------*/
+
+void amr_wb_enc_init_fx(
+ AMRWB_IO_ENC_HANDLE hAmrwb_IO /* i/o: AMR-WB IO encoder handle */
+)
+{
+ int16_t i;
+
+ /* HF (6-7kHz) BWE */
+ hAmrwb_IO->seed2_enc = RANDOM_INITSEED;
+ move16();
+
+ FOR (i = 0; i < GAIN_PRED_ORDER; i++)
+ {
+ hAmrwb_IO->past_qua_en_fx[i] = -14336; /* Q10gain quantization memory (used also in AMR-WB IO mode) */
+ move16();
+ }
+
+ hf_cod_init_fx(hAmrwb_IO->mem_hp400_enc_fx, hAmrwb_IO->mem_hf_enc_fx, hAmrwb_IO->mem_syn_hf_enc_fx, hAmrwb_IO->mem_hf2_enc_fx, &hAmrwb_IO->gain_alpha_fx);
+
+ return;
+}
diff --git a/lib_enc/analy_lp_fx.c b/lib_enc/analy_lp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..cd24dbfbf2b674046fb5dfff7e8dece80712e7c6
--- /dev/null
+++ b/lib_enc/analy_lp_fx.c
@@ -0,0 +1,185 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+#include "rom_enc.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * analy_lp()
+ *
+ * Perform LP analysis
+ *
+ * - autocorrelations + lag windowing
+ * - Levinson-Durbin algorithm to find A(z)
+ * - convert A(z) to LSPs
+ * - find interpolated LSPs and convert back to A(z) for all subframes
+ * - update LSPs for the next frame
+ *-------------------------------------------------------------------*/
+
+void analy_lp_fx(
+ const Word16 speech[], /* i : pointer to the speech frame */
+ const Word16 L_frame, /* i : length of the frame */
+ const Word16 L_look, /* i : look-ahead */
+ Word32 *ener, /* o : residual energy from Levinson-Durbin */
+ Word16 A[], /* o : A(z) filter coefficients */
+ Word16 epsP_h[], /* o : LP analysis residual energies for each iteration */
+ Word16 epsP_l[], /* o : LP analysis residual energies for each iteration */
+ Word16 lsp_new[], /* o : current frame LSPs */
+ Word16 lsp_mid[], /* o : current mid-frame LSPs */
+ Word16 lsp_old[], /* i/o: previous frame unquantized LSPs */
+ const Word16 Top[2], /* i : open loop pitch lag */
+ const Word16 Tnc[2], /* i : open loop pitch gain */
+ const Word32 Core_sr, /* i : Internal core sampling rate */
+ const Word16 sec_chan_low_rate, /* i : flag to signal second channel */
+ Word16 Q_new,
+ Word16 *Q_r
+)
+{
+ Word16 r_h[M+1]; /* Autocorrelations of windowed speech MSB */
+ Word16 r_l[M+1]; /* Autocorrelations of windowed speech LSB */
+ Word32 LepsP[M+1];
+ Word16 i, i_subfr, wind_length = 0;
+ Word16 *lsp;
+ const Word16 *wind = NULL;
+ const Word16 *pt;
+ Word16 half_frame;
+
+ IF( EQ_16(L_frame,L_FRAME))
+ {
+ wind_length = L_LP;
+ move16();
+ wind = Assym_window_W16fx;
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ wind_length = L_LP_16k;
+ move16();
+ wind = assym_window_16k_fx;
+ }
+ lsp = lsp_mid;
+ half_frame = shr(L_frame,1);
+
+ FOR( i_subfr = 0; i_subfr <= 1; i_subfr++ )
+ {
+ pt = speech + sub(add(half_frame, L_look), wind_length);
+ half_frame = shl(half_frame,1);
+
+ /* Autocorrelations */
+ autocorr_fx(pt, M, r_h, r_l, &Q_r[1-i_subfr], wind_length, wind, 0, 0 );
+
+ /* Lag windowing */
+ adapt_lag_wind( r_h, r_l, M, Top[i_subfr], Tnc[i_subfr], Core_sr );
+
+ /* Levinson-Durbin */
+ E_LPC_lev_dur(r_h, r_l, A, LepsP, M, NULL);
+ FOR (i = 0; i <= M; i++)
+ {
+ L_Extract(LepsP[i], &epsP_h[i], &epsP_l[i]);
+ }
+ /*Q_r[... might not be needed from external...*/
+ Q_r[1-i_subfr] = add(Q_r[1-i_subfr], shl(Q_new, 1));
+ move16();
+
+ /* Conversion of A(z) to LSPs */
+ E_LPC_a_lsp_conversion( A, lsp, lsp_old, M );
+
+ lsp = lsp_new;
+ }
+ IF (EQ_16(sec_chan_low_rate, 1) )
+ {
+ /* LSP interpolation */
+ int_lsp4_fx(L_frame, lsp_old, lsp_mid, lsp_new, A, M, -2);
+ }
+ ELSE
+ {
+ /* LSP interpolation */
+ int_lsp4_fx(L_frame, lsp_old, lsp_mid, lsp_new, A, M, 0);
+ }
+ Copy (lsp_new, lsp_old, M);
+ *ener = L_Comp(epsP_h[M],epsP_l[M]);
+ move32();
+
+ return;
+
+}
+
+
+/*-------------------------------------------------------------------*
+ * analy_lp_AMR_WB()
+ *
+ * Perform LP analysis for AMR-WB IO mode
+ *
+ * - autocorrelations + lag windowing
+ * - Levinson-Durbin algorithm to find A(z)
+ * - convert A(z) to ISPs
+ * - find interpolated ISPs and convert back to A(z) for all subframes
+ * - update ISPs for the next frame
+ *-------------------------------------------------------------------*/
+
+void analy_lp_AMR_WB_fx(
+ const Word16 speech[], /* i : pointer to the speech frame */
+ Word32 *ener, /* o : residual energy from Levinson-Durbin */
+ Word16 A[], /* o : A(z) filter coefficients */
+ Word16 epsP_h[], /* o : LP analysis residual energies for each iteration */
+ Word16 epsP_l[], /* o : LP analysis residual energies for each iteration */
+ Word16 isp_new[], /* o : current frame ISPs */
+ Word16 isp_old[], /* i/o: previous frame unquantized ISPs */
+ Word16 isf_new[], /* o : current frame ISPs */
+ Word16 Top, /* i : open loop pitch lag */
+ Word16 Tnc, /* i : open loop pitch gain */
+ Word16 Q_new,
+ Word16 *Q_r
+)
+{
+ Word16 r_h[M+1]; /* Autocorrelations of windowed speech MSB */
+ Word16 r_l[M+1]; /* Autocorrelations of windowed speech LSB */
+ Word32 LepsP[M+1];
+ Word16 i, wind_length = 0;
+ const Word16 *wind;
+
+ /* Initialization */
+ wind_length = L_LP_AMR_WB;
+ move16();
+ wind = Hamcos_Window;
+
+ /* Autocorrelations */
+ autocorr_fx( speech - L_SUBFR, M, r_h, r_l, &Q_r[0], wind_length, wind, 0, 0 );
+
+ /* Lag windowing */
+ adapt_lag_wind( r_h, r_l, M, Top, Tnc, INT_FS_FX );
+
+ /* Levinson-Durbin */
+ /*lev_dur( A, r, M, epsP );*/
+ E_LPC_lev_dur(r_h, r_l, A, LepsP, M, NULL);
+ FOR (i = 0; i <= M; i++)
+ {
+ L_Extract(LepsP[i], &epsP_h[i], &epsP_l[i]);
+ }
+ /*Q_r[... might not be needed from external...*/
+ Q_r[0] = add(Q_r[0], shl(Q_new, 1));
+ move16();
+
+ E_LPC_a_lsf_isf_conversion( A, isf_new, stable_ISF_fx, M, 0 );
+ E_LPC_isf_isp_conversion( isf_new, isp_new, M );
+
+ /* ISP interpolation */
+ int_lsp_fx( L_FRAME, isp_old, isp_new, A, M, interpol_isp_amr_wb_fx, 1 );
+
+ /**ener = epsP[M];*/
+ *ener = L_Comp(epsP_h[M],epsP_l[M]);
+ move32();
+
+ /* updates */
+ Copy( isp_new, isp_old, M );
+
+ return;
+}
diff --git a/lib_enc/analy_sp_fx.c b/lib_enc/analy_sp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..0e115ffa5e82aa41a8dfff3ff539b34016cbeb33
--- /dev/null
+++ b/lib_enc/analy_sp_fx.c
@@ -0,0 +1,585 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+#include "cnst.h"
+#include "basop_util.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "rom_enc.h"
+#include "rom_com.h"
+#include
+
+/*-------------------------------------------------------------------*
+ * Local prototypes
+ *-------------------------------------------------------------------*/
+
+static void find_enr( Word16 data[], Word32 band[], Word32 *ptE, Word32 *LEtot, const Word16 min_band, const Word16 max_band,
+ const Word16 Q_new2, const Word32 e_min, Word32 *Bin_E, Word16 BIN_FREQ_FX, Word32 *band_energies );
+
+#ifdef IVAS_CODE_CPE
+static void find_enr_dft(CPE_ENC_HANDLE hCPE, const int32_t input_Fs, float DFT_past_DMX[], float band[], float* ptE, float* Etot, const int16_t min_band, const int16_t max_band, float* Bin_E, float* band_ener);
+#endif
+
+/*-------------------------------------------------------------------*
+ * analy_sp_fx()
+ *
+ * Spectral analysis of 12.8kHz input
+ *-------------------------------------------------------------------*/
+
+void analy_sp_fx(
+ const Word16 element_mode, /* i : element mode */
+#ifdef IVAS_CODE_CPE
+ CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */
+#endif
+ const Word32 input_Fs, /* i : input sampling rate */
+ Word16 *speech, /* i : speech buffer Q_new - preemph_bits */
+ const Word16 Q_new, /* i : current scaling exp Q0 */
+ Word32 *fr_bands, /* o : energy in critical frequency bands Q_new + QSCALE */
+ Word32 *lf_E, /* o : per bin E for first... Q_new + QSCALE - 2*/
+ Word16 *Etot, /* o : total input energy Q8 */
+ const Word16 min_band, /* i : minimum critical band Q0 */
+ const Word16 max_band, /* i : maximum critical band Q0 */
+ const Word32 e_min_scaled, /* i : minimum energy scaled Q_new + QSCALE */
+ Word16 Scale_fac[2], /* o : FFT scales factors (2 values by frame) Q0 */
+ Word32 *Bin_E, /* o : per-bin energy spectrum */
+ Word32 *Bin_E_old, /* o : per-bin energy spectrum of the previous frame */
+ Word32 *PS, /* o : per-bin energy spectrum */
+ Word16 *EspecdB, /* o : per-bin log energy spectrum (with f=0) Q7 */
+ Word32 *band_energies, /* o : energy in critical frequency bands without minimum noise floor MODE2_E_MIN */
+ Word16 *fft_buff /* o : FFT coefficients */
+)
+{
+ Word16 *pt;
+ Word16 i_subfr, i, exp_etot, frac_etot, exp, exp_frac, exp2;
+ Word32 *pt_bands;
+ Word32 Ltmp, LEtot, L_tmp2;
+ Word16 *pt_fft;
+ Word16 Min_val, Max_val;
+ Word16 Scale_fac2;
+ Word16 fft_temp[L_FFT];
+#ifndef IVAS_CODE_CPE
+ (void)input_Fs;
+#endif
+ /*-----------------------------------------------------------------*
+ * Compute spectrum
+ * find energy per critical frequency band and total energy in dB
+ *-----------------------------------------------------------------*/
+
+ pt_bands = fr_bands;
+ pt_fft = fft_buff;
+ LEtot = L_deposit_l(0);
+ IF(NE_16(element_mode, IVAS_CPE_DFT))
+ {
+ FOR(i_subfr = 0; i_subfr <= 1; i_subfr++)
+ {
+ pt = speech + 3 * (L_SUBFR / 2) - L_FFT / 2;
+ if (i_subfr != 0)
+ {
+ pt = speech + 7 * (L_SUBFR / 2) - L_FFT / 2;
+ }
+
+ /* Clear 1st value of 1st part, copy 1st value of 2nd part */
+ fft_temp[0] = 0;
+ move16();
+ fft_temp[L_FFT / 2] = pt[L_FFT / 2];
+ move16();
+ Max_val = s_max(fft_temp[0], fft_temp[L_FFT / 2]);
+ Min_val = s_min(fft_temp[0], fft_temp[L_FFT / 2]);
+
+ FOR(i = 1; i < L_FFT / 2; i++)
+ {
+ /* 1st windowed part */
+ fft_temp[i] = mult_r(pt[i], sqrt_han_window_fx[i]);
+ move16();
+ if (fft_temp[i] > 0)
+ Max_val = s_max(Max_val, fft_temp[i]);
+ if (fft_temp[i] < 0)
+ Min_val = s_min(Min_val, fft_temp[i]);
+
+ /* 2nd windowed part */
+ fft_temp[L_FFT - i] = mult_r(pt[L_FFT - i], sqrt_han_window_fx[i]);
+ move16();
+ if (fft_temp[L_FFT - i] > 0)
+ Max_val = s_max(Max_val, fft_temp[L_FFT - i]);
+ if (fft_temp[L_FFT - i] < 0)
+ Min_val = s_min(Min_val, fft_temp[L_FFT - i]);
+ }
+
+ /* Combine -Min_val and Max_val into one */
+ Max_val = s_max(negate(Min_val), Max_val);
+
+ Scale_fac[i_subfr] = s_min(sub(norm_s(Max_val), 1), 6);
+ move16();
+ Scale_fac2 = shl(Scale_fac[i_subfr], 1);
+ Scale_sig(fft_temp, L_FRAME_12k8, Scale_fac[i_subfr]);
+
+ r_fft_fx_lc(FFT_W128, SIZE_256, SIZE2_256, NUM_STAGE_256, fft_temp, pt_fft, 1);
+
+ /* find energy per critical band */
+ find_enr(pt_fft, pt_bands, lf_E + i_subfr * VOIC_BINS, &LEtot, min_band, max_band,
+ add(Q_new, Scale_fac2), e_min_scaled, &Bin_E[i_subfr * L_FFT / 2], BIN, band_energies + i_subfr * NB_BANDS);
+
+ pt_bands += NB_BANDS;
+ pt_fft += L_FFT;
+ }
+ }
+#ifdef IVAS_CODE_CPE
+ ELSE
+ {
+ /* find energy per critical band */
+ find_enr_dft(hCPE, input_Fs, hCPE->hStereoDft->DFT[0], pt_bands, lf_E, Etot, min_band, max_band, Bin_E, band_ener);
+ mvr2r(lf_E, lf_E + VOIC_BINS, VOIC_BINS);
+ mvr2r(Bin_E, Bin_E + (L_FFT / 2), L_FFT / 2);
+ mvr2r(band_ener, band_ener + NB_BANDS, NB_BANDS);
+ mvr2r(pt_bands, pt_bands + NB_BANDS, NB_BANDS);
+ *Etot *= 2.f;
+ }
+#endif
+
+ /* Average total log energy over both half-frames */
+ frac_etot = 0;
+ move16();
+ exp_etot = norm_l(LEtot);
+ IF (LEtot != 0) /* Log2_norm_lc doesn't Support Input <= 0; deal with it here */
+ {
+ frac_etot = Log2_norm_lc(L_shl(LEtot, exp_etot));
+ exp_etot = sub(30, exp_etot);
+ }
+ exp_etot = sub(exp_etot, add(Q_new, 1+3)); /* remove scaling effect, 4 already removed */
+ Ltmp = Mpy_32(exp_etot, frac_etot, LG10, 0);
+
+ /*Q8 Averaged the total energy over both half-frames in log10 */
+ *Etot = extract_l(L_shr(Ltmp, 14-8));
+
+ Bin_E[L_FFT/2-1] = Bin_E[L_FFT/2-2];
+ move32();
+ Bin_E[L_FFT-1] = Bin_E[L_FFT-2];
+ move32();
+
+ /* Per-bin log-energy spectrum */
+ exp2 = sub(31, add(Q_new, QSCALE-2));
+ L_tmp2 = L_mac(-56783L, exp2, 28391);
+ FOR (i = 0; i < L_FFT/2; i++)
+ {
+ Bin_E_old[i] = Bin_E[i];
+ move32();
+
+ /* tmp = (input[i] + input[i+Len]+0.001f)/2.0f */
+ Ltmp = L_max(1, L_add(L_shr(Bin_E[i],1), L_shr(Bin_E[i+L_FFT/2],1)));
+ if(PS != NULL)
+ {
+ PS[i] = Ltmp;
+ move32();
+ }
+
+ /* 10.0*log((float)tmp) */
+ /* 10.0*Log(2)*Log2(L_tmp/2) */
+ /* 6.93147*Log2(L_tmp/2) */
+ /* 0.86643*(Log2(L_tmp)-1)*8 */
+ /* 0.86643*Log2(L_tmp)*8 - 6.93147 */
+ /* We'll put it in Q8 */
+ exp = norm_l(Ltmp);
+ exp_frac = Log2_norm_lc(L_shl(Ltmp, exp));
+ /* -56783L is to substract 0.86643 in Q16 */
+ /* 28391 is 0.86643 in Q15 */
+ /* 1774 is (0.86643 in Q15) * 8 / 128 (/128 to go in Q7) */
+ EspecdB[i] = mac_r(L_shl(L_msu(L_tmp2, exp, 28391), 3+7), exp_frac, 887);
+ move16();
+ }
+
+
+ return;
+}
+
+/*------------------------------------------------------------------------*
+ * find_enr()
+ *
+ * find input signal energy for each critical band and first 74 LF bins
+ * The energy is normalized by the number of frequency bins in a channel
+ *------------------------------------------------------------------------*/
+
+static void find_enr(
+ Word16 data[], /* i : fft result */
+ Word32 band[], /* o : per band energy Q_new + QSCALE */
+ Word32 *ptE, /* o : per bin energy for low frequencies Q_new + QSCALE-2 */
+ Word32 *LEtot, /* o : total energy Q_new + QSCALE */
+ const Word16 min_band, /* i : minimum critical band Q0 */
+ const Word16 max_band, /* i : maximum critical band Q0 */
+ const Word16 Q_new2, /* i : scaling factor Q0 */
+ const Word32 e_min, /* i : minimum energy scaled Q_new + QSCALE */
+ Word32 *Bin_E, /* o : Per bin energy Q_new + QSCALE-2 */
+ Word16 BIN_FREQ_FX, /* i : Number of frequency bins */
+ Word32 *band_energies /* o : per band energy without MODE2_E_MIN */
+)
+{
+ Word16 i, cnt, shift_to_norm;
+ Word16 freq, wtmp;
+ Word16 *ptR, *ptI, diff_scaleP1, diff_scaleM2;
+ Word16 exp_band;
+ Word32 Ltmp, Ltmp1;
+ Word16 voic_band;
+ Word32 etot;
+ Word16 exp_etot;
+ Word32 *tmpptr;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+ ptR = &data[1]; /* first real */
+ ptI = &data[L_FFT-1]; /* first imaginary */
+
+ /*-----------------------------------------------------------------------------------*
+ * Scaling needed by band and ptE output
+ * Wants all energies scaled by Q_new + QSCALE to maintain maximum
+ * precision on bckr noise in clean speech
+ * First shift left by Q_new + QSCALE than shift right by 2*Q_new-1
+ * shift left (Q_new + QSCALE - (2*Q_new -1))
+ * shift left (QSCALE - Q_new + 1) == shift left by (QSCALE+1) - Q_new
+ *-----------------------------------------------------------------------------------*/
+
+ diff_scaleP1 = sub(QSCALE+1 + 1, Q_new2);
+ diff_scaleM2 = sub(QSCALE+1 - 2, Q_new2);
+
+ voic_band = VOIC_BAND_8k;
+ move16();
+ assert (VOIC_BAND == VOIC_BAND_8k);
+
+ etot = L_deposit_l(0);
+ exp_etot = 0;
+ move16();
+
+ /*-----------------------------------------------------------------*
+ * For low frequency bins, save per bin energy for the use
+ * in NS and find_tilt()
+ *-----------------------------------------------------------------*/
+
+ freq = BIN_FREQ_FX;
+ move16();
+ FOR (i = 0; i < voic_band; i++) /* up to maximum allowed voiced critical band */
+ {
+ tmpptr = Bin_E;
+ move16();
+ Ltmp1 = L_deposit_l(0);
+
+ FOR (; freq <= crit_bands[i]; freq += BIN_FREQ_FX)
+ {
+ /*ptE = *ptR * *ptR + *ptI * *ptI */ /* energy */
+ Ltmp = L_mult(*ptI, *ptI);
+ Ltmp = L_mac(Ltmp, *ptR, *ptR);
+
+ /* *ptE *= 4.0 / (L_FFT*L_FFT) */
+ /* normalization - corresponds to FFT normalization by 2/L_FFT */
+ BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */
+#ifdef BASOP_NOGLOB
+ *ptE = L_shl_o(Ltmp, diff_scaleM2, &Overflow);
+#else /* BASOP_NOGLOB */
+ *ptE = L_shl(Ltmp, diff_scaleM2);
+#endif /* BASOP_NOGLOB */
+ move32(); /* scaled by Q_new + QSCALE - 2 */
+ BASOP_SATURATE_WARNING_ON_EVS;
+ /*band[i] += *ptE++;*/
+ *Bin_E = *ptE;
+ move32();
+ Bin_E++;
+ Ltmp1 = L_add(Ltmp1, Ltmp);
+
+ ptE++;
+ ptR++;
+ ptI--;
+ }
+
+ exp_band = sub(norm_l(Ltmp1), 1);/* divide by 2 to ensure band < cnt */
+ wtmp = round_fx(L_shl(Ltmp1, exp_band));
+
+ /* band[i] /= cnt */ /* normalization per frequency bin */
+ cnt = (Word16)(Bin_E - tmpptr);
+ shift_to_norm = norm_s(cnt);
+ wtmp = div_s(wtmp, shl(cnt, shift_to_norm));
+ Ltmp1 = L_deposit_l(wtmp);
+
+ exp_band = sub(exp_band, shift_to_norm);
+ exp_band = sub(diff_scaleP1, exp_band);
+ BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */
+#ifdef BASOP_NOGLOB
+ band[i] = L_shl_o(Ltmp1, exp_band, &Overflow);
+#else /* BASOP_NOGLOB */
+ band[i] = L_shl(Ltmp1, exp_band);
+#endif /* BASOP_NOGLOB */
+ move32();/* band scaled by Q_new + QSCALE */
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ test();
+ IF (GE_16(i,min_band)&&LE_16(i,max_band))
+ {
+ IF (LT_32(band[i],e_min))
+ {
+ Ltmp1 = L_shl(e_min, 0);
+ exp_band = 0;
+ move16();
+ }
+
+ wtmp = sub(exp_band, exp_etot);
+ if (wtmp > 0)
+ {
+ etot = L_shr(etot, wtmp);
+ }
+ exp_etot = s_max(exp_etot, exp_band);
+ etot = L_add(etot, L_shl(Ltmp1, sub(exp_band, exp_etot)));
+ }
+
+ band_energies[i] = band[i];
+ move32();
+
+ band[i] = L_max(band[i], e_min);
+ move32();
+ }
+
+ IF (EQ_16(BIN_FREQ_FX, 50))
+ {
+ /*-----------------------------------------------------------------*
+ * Continue compute the E per critical band for high frequencies
+ *-----------------------------------------------------------------*/
+
+ FOR (i = voic_band; i < NB_BANDS; i++)
+ {
+ tmpptr = Bin_E;
+ move16();
+ Ltmp1 = L_deposit_l(0);
+
+ FOR (; freq <= crit_bands[i]; freq += BIN_FREQ_FX)
+ {
+ /* *ptE = *ptR * *ptR + *ptI * *ptI */
+ Ltmp = L_mult(*ptI, *ptI);
+ Ltmp = L_mac(Ltmp, *ptR, *ptR);
+
+ /* *ptE *= 4.0 / (L_FFT*L_FFT) */
+ /* normalization - corresponds to FFT normalization by 2/L_FFT */
+ BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */
+#ifdef BASOP_NOGLOB
+ *Bin_E = L_shl_o(Ltmp, diff_scaleM2, &Overflow);
+#else /* BASOP_NOGLOB */
+ *Bin_E = L_shl(Ltmp, diff_scaleM2);
+#endif /* BASOP_NOGLOB */
+ move32(); /* scaled by Q_new + QSCALE - 2 */
+ BASOP_SATURATE_WARNING_ON_EVS;
+ Bin_E++;
+ Ltmp1 = L_add(Ltmp1, Ltmp);
+
+ ptR++;
+ ptI--;
+ }
+
+ exp_band = sub(norm_l(Ltmp1), 1); /* divide by 2 to ensure band < cnt */
+ wtmp = round_fx(L_shl(Ltmp1, exp_band));
+
+ /* band[i] /= cnt */ /* normalization per frequency bin */
+ cnt = (Word16)(Bin_E - tmpptr);
+ shift_to_norm = norm_s(cnt);
+ wtmp = div_s(wtmp, shl(cnt, shift_to_norm));
+ Ltmp1 = L_deposit_l(wtmp);
+
+ exp_band = sub(exp_band, shift_to_norm);
+ exp_band = sub(diff_scaleP1, exp_band);
+ BASOP_SATURATE_WARNING_OFF_EVS; /* saturation seems to have no effect (tested by simulation) */
+#ifdef BASOP_NOGLOB
+ band[i] = L_shl_o(Ltmp1, exp_band, &Overflow);
+#else /* BASOP_NOGLOB */
+ band[i] = L_shl(Ltmp1, exp_band);
+#endif
+ move32();/* band scaled by Q_new + QSCALE */
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ test();
+ IF (GE_16(i,min_band)&&LE_16(i,max_band))
+ {
+ IF (LT_32(band[i],e_min))
+ {
+ Ltmp1 = L_shl(e_min, 0);
+ exp_band = 0;
+ move16();
+ }
+
+ wtmp = sub(exp_band, exp_etot);
+ if (wtmp > 0)
+ {
+ etot = L_shr(etot, wtmp);
+ }
+ exp_etot = s_max(exp_etot, exp_band);
+
+ etot = L_add(etot, L_shl(Ltmp1, sub(exp_band, exp_etot)));
+ }
+
+ band_energies[i] = band[i];
+ move32();
+
+ band[i] = L_max(band[i], e_min);
+ move32();
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Find the total energy over the input bandwidth
+ *-----------------------------------------------------------------*/
+
+ etot = L_add(*LEtot, L_shl(etot, sub(exp_etot, 4)));
+
+ *LEtot = etot;
+ move32();
+
+
+ return;
+}
+#ifdef IVAS_CODE_CPE
+/*------------------------------------------------------------------------*
+ * find_enr_dft()
+ *
+ * find input signal energy for each critical band using the DFT buffers
+ *------------------------------------------------------------------------*/
+
+static void find_enr_dft(
+ CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */
+ const int32_t input_Fs, /* i : input sampling rate */
+ float DFT_past_DMX[],
+ float band[], /* o : per band energy */
+ float* ptE, /* o : per bin energy for low frequencies */
+ float* Etot, /* i/o: total energy */
+ const int16_t min_band, /* i : minimum critical band */
+ const int16_t max_band, /* i : maximum critical band */
+ float* Bin_E, /* o : Per bin energy */
+ float* band_ener /* o : per band energy without E_MIN */
+)
+{
+ int16_t i, cnt;
+ float freq, tmp;
+ const float* ptR, * ptI;
+ float norm_val;
+ int16_t bin_cnt = 0;
+
+ float c, s;
+ /* One window - 40ms*12.8kHz = 512 samples */
+ float c_1 = cosf(PI2 / STEREO_DFT_N_12k8_ENC);
+ float s_1 = sinf(PI2 / STEREO_DFT_N_12k8_ENC);
+ float g_1 = 1.f + 0.68f * 0.68f;
+ float g_2 = 2 * 0.68f;
+ float g;
+ float scaleWin;
+
+ float BinE[STEREO_DFT_N_12k8_ENC / 2]; /* NB_BANDS = 20 (= 6350Hz) = highest band available for SR 12.8 -> bin_cnt = 158 */
+ float bin_freq = input_Fs / (float)hCPE->hStereoDft->NFFT; /* adaptive frequency bin width */
+
+ scaleWin = 1 / (2 * hCPE->hStereoDft->win_ana_energy);
+ scaleWin *= (float)BIN / bin_freq;
+ norm_val = scaleWin * 4.0f / (hCPE->hStereoDft->NFFT * hCPE->hStereoDft->NFFT);
+
+ ptR = &DFT_past_DMX[2]; /* first real */
+ ptI = &DFT_past_DMX[3]; /* first imaginary */
+ c = c_1;
+ s = s_1;
+
+ /* for low frequency bins, save per bin energy for the use in find_tilt() */
+ freq = bin_freq;
+ for (i = 0; i < NB_BANDS - 1; i++) /* up to maximum allowed voiced critical band */
+ {
+ band[i] = 0.0f;
+ cnt = 0;
+
+ /* bins up to crit_band 17 (<= 3700 Hz):
+ * bin_cnt old (bin_width 50 Hz): 74 (74 * FRAMES_PER_SEC = 3700)
+ * bin_cnt new (bin_width 40 Hz): 92 (92 * 40 = 3680)
+ */
+
+ while (freq <= crit_bands[i])
+ {
+ BinE[bin_cnt] = *ptR * *ptR + *ptI * *ptI; /* energy */
+ g = g_1 - g_2 * c;
+ tmp = c * c_1 - s * s_1;
+ s = s * c_1 + c * s_1;
+ c = tmp;
+ BinE[bin_cnt] *= norm_val * g; /* normalization - corresponds to FFT normalization by 2/L_FFT */
+ band[i] += BinE[bin_cnt];
+ ptR += 2;
+ ptI += 2;
+
+ freq += bin_freq;
+ cnt++;
+ bin_cnt++;
+ }
+
+ band[i] *= inv_tbl[cnt]; /* normalization per frequency bin */
+
+ band_ener[i] = band[i]; /* per band energy without E_MIN */
+
+ if (band[i] < E_MIN)
+ {
+ band[i] = E_MIN;
+ }
+ }
+
+ /* continue computing the energy per critical band for higher frequencies */
+
+ /* old version, FFT 256 @ SR12.8 (-> bin_width = 50 Hz):
+ NB_BANDS = 20 (= 6350Hz) = highest band available for SR 12.8 -> bin_cnt = 127 = L_FFT/2-1*/
+
+ /* new version: DFT (1200/800/400) @ input SR (48/32/16) (-> bin_width = 40 Hz):
+ *
+ */
+ /* NB_BANDS = 20 (= 6350Hz) = highest band available for SR 12.8 -> bin_cnt = 158 */
+ /* NB_BANDS = 21 (= 7700Hz) = highest band available for SR 16 -> bin_cnt = 192 */
+ /* NB_BANDS = 24 (= 15500Hz) = highest band available for SR 32 -> bin_cnt = 387 */
+ /* NB_BANDS = 24 (= 15500Hz) = highest band available for SR 48 -> bin_cnt = 387 */
+
+ for (; i < NB_BANDS; i++)
+ {
+ band[i] = 0.0f;
+ cnt = 0;
+ while (freq < 6399.0f)
+ {
+ BinE[bin_cnt] = *ptR * *ptR + *ptI * *ptI;
+ g = g_1 - g_2 * c;
+ BinE[bin_cnt] *= norm_val * g;
+ band[i] += BinE[bin_cnt];
+ ptR += 2;
+ ptI += 2;
+
+ freq += bin_freq;
+ cnt++;
+ bin_cnt++;
+ }
+
+ band[i] *= inv_tbl[cnt]; /* normalization per frequency bin */
+
+ band_ener[i] = band[i]; /* per band energy without E_MIN */
+
+ if (band[i] < E_MIN)
+ {
+ band[i] = E_MIN;
+ }
+ }
+
+ /* put bin energies from BinE into Bin_E[L_FFT/2-1] (interpolate 40 Hz bin values to fit into 50 Hz bins) */
+ /* Last value of Bin_E is handled outside this function*/
+ assert(bin_cnt == (STEREO_DFT_N_12k8_ENC / 2 - 1));
+ BinE[STEREO_DFT_N_12k8_ENC / 2 - 1] = BinE[STEREO_DFT_N_12k8_ENC / 2 - 2];
+ lerp(BinE, Bin_E, L_FFT / 2, STEREO_DFT_N_12k8_ENC / 2);
+ mvr2r(Bin_E, ptE, VOIC_BINS);
+
+
+ /* find the total log energy */
+ tmp = *Etot;
+ for (i = min_band; i <= max_band; i++)
+ {
+ tmp += band[i];
+ }
+
+ *Etot = tmp;
+
+ return;
+}
+
+#endif
\ No newline at end of file
diff --git a/lib_enc/ari_enc_fx.c b/lib_enc/ari_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..08b35f9186b3434223870e8318426a50fe41a0ea
--- /dev/null
+++ b/lib_enc/ari_enc_fx.c
@@ -0,0 +1,337 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "assert.h"
+#include "options.h"
+//#include "basop_mpy.h"
+#include "cnst.h"
+#include "rom_com.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*---------------------------------------------------------------
+ * ari_copy_states_fx()
+ *
+ * \param[i] source
+ * \param[o] dest
+ *
+ * \return none
+ *-------------------------------------------------------------*/
+void ari_copy_states_fx(TastatEnc *source, TastatEnc *dest)
+{
+ dest->low = source->low;
+ move32();
+ dest->high = source->high;
+ move32();
+ dest->value = source->value;
+ move16();
+}
+
+/*---------------------------------------------------------------
+ Ari encoder 14 bits routines
+ -------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------
+ * ari_start_encoding_14bits_fx()
+ *
+ * \param[o] s
+ *
+ * \return none
+ *-------------------------------------------------------------*/
+void ari_start_encoding_14bits_fx(TastatEnc *s)
+{
+ s->low = L_deposit_l(0);
+ s->high = ari_q4new + 1;
+ move32();
+ s->value = 0;
+ move16();
+}
+
+/*---------------------------------------------------------------
+ * Ari encoder 14 bits routines
+ * Returns: new bit-stream position
+ *-------------------------------------------------------------*/
+static Word16 ari_put_bit_plus_follow(
+ Word16 ptr[], /* o: bit-stream */
+ Word16 bp, /* i: bit-stream position */
+ Word16 bits_to_follow, /* i: number of opposite bits to follow 'bit' */
+ Word16 bit /* i: bit to send */
+)
+{
+ assert(bit == 0 || bit == 1);
+ ptr[bp++] = bit; /* send initially a zero or one */ move16();
+ bit = s_xor(bit, 1); /* invert bit to send */
+ FOR ( ; bits_to_follow > 0; bits_to_follow--)
+ {
+ ptr[bp++] = bit; /* send inverted bit */ move16();
+ }
+ return bp;
+}
+
+/*-------------------------------------------------------------- -
+ *ari_done_encoding_14bits_fx()
+ *
+ *
+ * \param[o] ptr
+ * \param[i] bp
+ * \param[i] s
+ *
+ * \return bit consumption
+ * ------------------------------------------------------------ - */
+Word16 ari_done_encoding_14bits_fx(Word16 *ptr, Word16 bp, TastatEnc *s)
+{
+ Word16 bit;
+
+ bit = 0;
+ move16();
+ if ( GE_32(s->low,ari_q1new))
+ {
+ bit = s_xor(bit,1);
+ }
+ return ari_put_bit_plus_follow(ptr, bp, add(s->value, 1), bit);
+}
+
+
+/*---------------------------------------------------------------
+ *ari_encode_14bits_ext_fx()
+ *
+ * encode function for extended proba tables : less branches needed for coding
+ *
+ *
+ * \param[o] ptr
+ * \param[i] bp
+ * \param[i/o] s
+ * \param[i] symbol
+ * \param[i] cum_freq
+ *
+ * \return bit consumption
+ * ------------------------------------------------------------ - */
+Word16 ari_encode_14bits_ext_fx(
+ Word16 *ptr,
+ Word16 bp,
+ TastatEnc *s,
+ Word32 symbol,
+ UWord16 const *cum_freq
+)
+{
+ Word32 low;
+ Word32 high;
+ Word32 range;
+ Word16 bits_to_follow;
+ Word16 i;
+ UWord16 temp;
+ Word32 L_temp1, L_temp2;
+
+ high = L_add(s->high, 0);
+ low = L_add(s->low, 0);
+ range = L_sub(high, low);
+
+ L_temp1 = L_shl(range,15-stat_bitsnew/*both are constants*/);
+ Mpy_32_16_ss(L_temp1, cum_freq[symbol+1], &L_temp2, &temp);
+ if (symbol != 0) /* when symbol is 0, range remains unchanged */
+ {
+ Mpy_32_16_ss(L_temp1, cum_freq[symbol], &range, &temp);
+ }
+ high = L_add(low, range);
+ low = L_add(low, L_temp2);
+
+ bits_to_follow = s->value;
+ move16();
+
+ FOR (i = 0; i < 0x7FFF; i++)
+ {
+ IF (LE_32(high, ari_q2new))
+ {
+ bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 0);
+ bits_to_follow = 0;
+ move16();
+ }
+ ELSE IF (GE_32(low, ari_q2new))
+ {
+ bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 1);
+ bits_to_follow = 0;
+ move16();
+ low = L_sub(low, ari_q2new);
+ high = L_sub(high, ari_q2new); /* Subtract offset to top. */
+ }
+ ELSE
+ {
+ test();
+ IF (GE_32(low, ari_q1new)&&LE_32(high,ari_q3new))
+ {
+ /* Output an opposite bit */
+ /* later if in middle half. */
+ bits_to_follow = add(bits_to_follow, 1);
+ low = L_sub(low, ari_q1new); /* Subtract offset to middle*/
+ high = L_sub(high, ari_q1new);
+ }
+ ELSE {
+ BREAK; /* Otherwise exit loop. */
+ }
+ }
+
+ low = L_add(low, low);
+ high = L_add(high, high); /* Scale up code range. */
+ }
+
+ s->low = low;
+ move32();
+ s->high = high;
+ move32();
+ s->value = bits_to_follow;
+ move16();
+
+ return bp;
+}
+/*------------------------------------------------------------------------
+ * Function: ari_encode_overflow_fx()
+ *
+ *
+ *-------------------------------------------------------------------------*/
+Word16 ari_encode_overflow_fx(TastatEnc *s)
+{
+ return L_sub(L_sub(s->high, 1), s->low) <= 0;
+}
+
+/*------------------------------------------------------------------------
+ * Function: ari_encode_14bits_high_low()
+ *
+ *
+ *-------------------------------------------------------------------------*/
+static Word16 ari_encode_14bits_high_low(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word32 high, Word32 low)
+{
+ Word16 bits_to_follow, tmp;
+
+ bits_to_follow = s->value;
+ move16();
+
+ /* while there are more than 16 bits left */
+ tmp = sub(16, bits);
+ WHILE (add(add(bp, bits_to_follow), tmp) < 0)
+ {
+ IF (LE_32(high, ari_q2new))
+ {
+ bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 0);
+ bits_to_follow = 0;
+ move16();
+ }
+ ELSE IF (GE_32(low, ari_q2new))
+ {
+ bp = ari_put_bit_plus_follow(ptr, bp, bits_to_follow, 1);
+ bits_to_follow = 0;
+ move16();
+ low = L_sub(low, ari_q2new);
+ high = L_sub(high, ari_q2new); /* Subtract offset to top. */
+ }
+ ELSE
+ {
+ test();
+ IF (GE_32(low, ari_q1new)&&LE_32(high,ari_q3new))
+ {
+ /* Output an opposite bit */
+ /* later if in middle half. */
+ bits_to_follow = add(bits_to_follow, 1);
+ low = L_sub(low, ari_q1new); /* Subtract offset to middle*/
+ high = L_sub(high, ari_q1new);
+ }
+ ELSE {
+ BREAK; /* Otherwise exit loop. */
+ }
+ }
+
+ low = L_add(low, low);
+ high = L_add(high, high); /* Scale up code range. */
+ }
+
+ s->low = low;
+ move32();
+ s->high = high;
+ move32();
+ s->value = bits_to_follow;
+ move16();
+
+ return bp;
+}
+
+/*------------------------------------------------------------------------
+ * Function: ari_encode_14bits_range_fx
+ *
+ * Encode an cumulative frequency interval.
+ *-------------------------------------------------------------------------*/
+
+Word16 ari_encode_14bits_range_fx(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word16 cum_freq_low, Word16 cum_freq_high)
+{
+ Word32 low, high, range;
+
+ range = L_sub(s->high, s->low);
+
+ high = L_add(s->low, mul_sbc_14bits(range, cum_freq_high));
+ low = L_add(s->low, mul_sbc_14bits(range, cum_freq_low));
+
+ return ari_encode_14bits_high_low(ptr, bp, bits, s, high, low);
+}
+
+
+/*------------------------------------------------------------------------
+ * Function: ari_encode_14bits_sign_fx
+ *
+ * Encode a sign with equal probabilities.
+ *-------------------------------------------------------------------------*/
+Word16 ari_encode_14bits_sign_fx(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s, Word16 sign)
+{
+ Word32 low, high, range;
+ Word32 L_tmp;
+
+ high = L_add(s->high, 0);
+ low = L_add(s->low, 0);
+ range = L_sub(high, low);
+
+ L_tmp = L_shr(range, 1);
+ if (sign != 0)
+ {
+ high = L_add(low, L_tmp);
+ }
+ if (sign == 0)
+ {
+ low = L_add(low, L_tmp);
+ }
+
+ return ari_encode_14bits_high_low(ptr, bp, bits, s, high, low);
+}
+
+/*------------------------------------------------------------------------
+ * Function: ari_done_cbr_encoding_14bits_fx
+ *
+ * Finish up encoding in CBR mode.
+ *-------------------------------------------------------------------------*/
+Word16 ari_done_cbr_encoding_14bits_fx(Word16 *ptr, Word16 bp, Word16 bits, TastatEnc *s)
+{
+ Word16 high, tmp, k;
+
+ tmp = sub(bits, 16);
+ WHILE (GT_16(sub(tmp, bp), s->value))
+ {
+ bp = ari_encode_14bits_sign_fx(ptr, bp, bits, s, 0);
+ }
+
+ high = extract_l(L_sub(s->high, 1));
+
+ bp = ari_put_bit_plus_follow(ptr, bp, s->value, lshr(high, 15));
+ high = lshl(high, 1);
+
+ tmp = s_min(15, sub(bits, bp));
+ FOR (k=0; k
+#include
+#include "options.h"
+#include "cnst.h"
+#include "basop_util.h"
+#include "rom_com.h"
+#include "rom_enc.h"
+#include "prot.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * EncodeIndex_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+ /*ari_hm_enc.c*/
+ /* Q13 format */
+const Word16 kLowPeriodicityThr_fx[2] = { 4096/*0.5f Q13*/, 1638/*0.2f Q13*/ };
+
+Word16 EncodeIndex_fx(
+ const Word16 Bandwidth,
+ Word16 PeriodicityIndex,
+ BSTR_ENC_HANDLE hBst /* i/o: bitstream handle */
+)
+{
+ Word16 NumRatioBitsBwLtpIndx;
+
+ IF ( s_and(PeriodicityIndex, kLtpHmFlag) != 0 )
+ {
+ Word16 LtpPitchIndex = shr(PeriodicityIndex, 9);
+ assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16);
+
+ PeriodicityIndex = sub(PeriodicityIndex, 1);
+ assert((PeriodicityIndex & 0xff) < (1 << NumRatioBits[Bandwidth][LtpPitchIndex]));
+
+ NumRatioBitsBwLtpIndx = NumRatioBits[Bandwidth][LtpPitchIndex];
+ move16();
+
+ push_next_indice_fx(hBst, s_and(PeriodicityIndex, 0xff), NumRatioBitsBwLtpIndx);
+ return NumRatioBitsBwLtpIndx;
+ }
+ ELSE
+ {
+ push_next_indice_fx(hBst, PeriodicityIndex, 8);
+ return 8;
+ }
+}
+/*-------------------------------------------------------------------*
+ * SearchPeriodicityIndex_Single()
+ *
+ *
+ *-------------------------------------------------------------------*/
+static Word16 SearchPeriodicityIndex_Single(
+ const Word16 AbsMdct3[],
+ const Word16 NumToConsider,
+ const Word32 Lag,
+ const Word16 FractionalResolution
+)
+{
+ Word16 HighestMultiplier;
+ Word32 AbsMeanCurrent3; /* Mean for BucketWidth == 3 */
+ Word32 Limit, OldIndex, i;
+ Word16 Result, tmp1, tmp2;
+
+
+ Limit = L_deposit_l(sub(NumToConsider, 1));
+ Limit = L_shl(Limit, FractionalResolution);
+ AbsMeanCurrent3 = L_deposit_l(0);
+ HighestMultiplier = 0;
+ move16();
+
+ FOR (i=Lag; i 0) && (GT_16(LtpGain, kLtpHmGainThr)))
+ {
+ Bandwidth = 0;
+ move16();
+ if (GE_16(NumToConsider, 256))
+ {
+ Bandwidth = 1;
+ move16();
+ }
+
+ LtpPitchIndex = sub(mult_r(LtpPitchLag, 1 << (15-kLtpHmFractionalResolution)), 2);
+ assert(0 <= LtpPitchIndex && LtpPitchIndex <= 16);
+
+ tmp32 = L_shl(L_deposit_l(sub(NumToConsider, 2)), kLtpHmFractionalResolution);
+ tmp = shl(1, NumRatioBits[Bandwidth][LtpPitchIndex]);
+ FOR (Multiplier = 1; Multiplier <= tmp; ++Multiplier)
+ {
+ Lag = L_shr(L_mult0(LtpPitchLag, Ratios_fx[Bandwidth][LtpPitchIndex][Multiplier-1]), 8);
+
+ test();
+ IF ((GE_32(Lag, 4< 0)
+ {
+ tmp32 = L_mult0(Score, NumToConsider); /* -> 16Q15 */
+ tmp = sub(norm_l(tmp32), 1);
+ tmp2 = norm_l(AbsTotal);
+#ifdef BASOP_NOGLOB
+ tmp3 = div_s(round_fx_o(L_shl_o(tmp32, tmp, &Overflow), &Overflow), round_fx_o(L_shl_o(AbsTotal, tmp2, &Overflow), &Overflow));
+ * RelativeScore = shr_o(tmp3, add(sub(tmp, tmp2), 2), &Overflow); /* -> 2Q13 */ move16();
+#else
+ tmp3 = div_s(round_fx(L_shl(tmp32, tmp)), round_fx(L_shl(AbsTotal, tmp2)));
+ BASOP_SATURATE_WARNING_OFF_EVS
+ *RelativeScore = shr(tmp3, add(sub(tmp, tmp2), 2)); /* -> 2Q13 */ move16();
+ BASOP_SATURATE_WARNING_ON_EVS
+#endif
+ }
+ ELSE
+ {
+ *RelativeScore = 0;
+ move16();
+ }
+
+ return PeriodicityIndex;
+}
+/*-------------------------------------------------------------------*
+ * PeakFilter()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+static void PeakFilter(
+ const Word32 x[], /* i : absolute spectrum */
+ Word32 y[], /* O : filtered absolute spectrum, must not alias x[] */
+ const Word16 L_frame /* i : number of spectral lines */
+)
+{
+ Word16 flen, i;
+/*#define kPeakElevationThreshold 1.0f*/
+ Word16 m;
+ Word32 a;
+
+ flen = shr(L_frame, 4);
+ /* m = kPeakElevationThreshold / (float)(2*flen + 1); */
+ m = shr(div_s(8/*kPeakElevationThreshold Q3*/, add(shl(flen,1), 1)), 3);
+
+ a = L_deposit_l(0);
+ FOR (i=0; i 0 )
+ {
+ prm_hm[0] = 1; /* flag: on */ move16();
+
+ hm_bits = add(hm_bits, CountIndexBits(bw_flag, prm_hm[1]));
+
+ if (EQ_16(coder_type, VOICED))
+ {
+ hm_bits = add(hm_bits, kTcxHmNumGainBits);
+ }
+
+ tcx_hm_modify_envelope(
+ gain,
+ lag,
+ fract_res,
+ p,
+ env,
+ L_frame
+ );
+ }
+ ELSE
+ {
+ prm_hm[0] = 0; /* flag: off */ move16();
+ prm_hm[1] = -1; /* pitch index */ move16();
+ prm_hm[2] = 0; /* gain index */ move16();
+ }
+
+ *hm_bits_out = hm_bits;
+ move16();
+}
+
diff --git a/lib_enc/arith_coder_enc_fx.c b/lib_enc/arith_coder_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..4d162f09793bf59ab02d7095e03c312d717e6440
--- /dev/null
+++ b/lib_enc/arith_coder_enc_fx.c
@@ -0,0 +1,809 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h"
+#include "rom_com.h"
+
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define kMaxNumHeapElems 10
+#define LOG2_E 23637/*1.44269504089f Q14*/
+
+typedef struct HeapElem
+{
+ Word32 mScore; /* Sort key */
+ Word16 mIndex; /* Original index */
+} HeapElem;
+
+typedef struct Heap
+{
+ HeapElem mElem[2 * kMaxNumHeapElems + 1];
+ Word16 mSize;
+} Heap;
+
+/*-------------------------------------------------------------------*
+ * tcx_arith_estimate_scale()
+ *
+ *
+ * Returns: estimated SQ scale Q15-e
+ *-------------------------------------------------------------------*/
+static Word16 tcx_arith_estimate_scale(
+ const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */
+ const Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */
+ const Word16 L_frame, /* i: number of spectral lines Q0 */
+ const Word16 envelope[], /* i: scaled envelope Q15-e */
+ const Word16 envelope_e, /* i: scaled envelope exponent Q0 */
+ Word16 *scale_e /* o: scale exponent Q0 */
+)
+{
+ Word16 scale, tmp, k, s, s1;
+ Word32 L_tmp, accu;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+
+ /* compute normalised standard deviation and determine approximate scale */
+ accu = L_deposit_l(0);
+ s = 30;
+ move16();
+
+ FOR (k = 0; k < L_frame; k++)
+ {
+ /* tmp = abs_spectrum[k] * envelope[k];
+ scale += tmp * tmp; */
+
+ /* normalize, multiply, square */
+ s1 = 30;
+ move16();
+ if (abs_spectrum[k] != 0)
+ {
+ s1 = norm_l(abs_spectrum[k]);
+ }
+
+#ifdef BASOP_NOGLOB
+ tmp = mult_r(round_fx_o(L_shl(abs_spectrum[k], s1), &Overflow), envelope[k]);
+#else /* BASOP_NOGLOB */
+ tmp = mult_r(round_fx(L_shl(abs_spectrum[k], s1)), envelope[k]);
+#endif /* BASOP_NOGLOB */
+ L_tmp = L_mult0(tmp, tmp);
+ tmp = sub(shl(s1, 1), 1);
+
+ /* adjust accu scaling */
+ s1 = s;
+ move16();
+ if (L_and(accu, 0x40000000) != 0) s = sub(s, 1);
+ s = s_min(s, tmp);
+
+ s1 = sub(s1, s);
+ if (s1 != 0) accu = L_shr(accu, s1);
+
+ /* scale and accumulate */
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ accu = L_add(accu, L_shr(L_tmp, sub(tmp, s)));
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+ s = sub(shl(add(abs_spectrum_e, envelope_e), 1), s);
+ if (accu == 0) accu = L_deposit_l(1);
+
+ /* scale = (float)sqrt((L_frame * 65536.0f*65536.0f*4.0f) / scale); */
+ scale = BASOP_Util_Divide3216_Scale(accu, shl(L_frame, 2), &tmp);
+ s = sub(add(s, tmp), 15);
+ scale = ISqrt16(scale, &s);
+ *scale_e = s;
+
+ return scale;
+}
+
+/*-------------------------------------------------------------------*
+ * MinHeapify_i()
+ *
+ *
+ *-------------------------------------------------------------------*/
+static void MinHeapify_i(Heap *H, Word16 i)
+{
+ Word16 left, right, largest;
+ HeapElem T;
+
+ left = add(shl(i, 1), 1);
+ right = add(left, 1);
+ largest = i;
+ move16();
+
+ if (LT_32(H->mElem[left].mScore, H->mElem[largest].mScore))
+ {
+ largest = left;
+ move16();
+ }
+
+ if (LT_32(H->mElem[right].mScore, H->mElem[largest].mScore))
+ {
+ largest = right;
+ move16();
+ }
+
+ WHILE (NE_16(largest, i))
+ {
+ T.mIndex = H->mElem[i].mIndex;
+ move16();
+ T.mScore = L_add(H->mElem[i].mScore, 0);
+
+ H->mElem[i].mIndex = H->mElem[largest].mIndex;
+ move16();
+ H->mElem[i].mScore = H->mElem[largest].mScore;
+ move32();
+
+ H->mElem[largest].mIndex = T.mIndex;
+ move16();
+ H->mElem[largest].mScore = T.mScore;
+ move32();
+
+ i = largest;
+ move16();
+
+ left = add(shl(i, 1), 1);
+ right = add(left, 1);
+
+ if (LT_32(H->mElem[left].mScore, H->mElem[largest].mScore))
+ {
+ largest = left;
+ move16();
+ }
+
+ if (LT_32(H->mElem[right].mScore, H->mElem[largest].mScore))
+ {
+ largest = right;
+ move16();
+ }
+ }
+
+}
+/*-------------------------------------------------------------------*
+ * tcx_arith_find_max_scale()
+ *
+ *
+ *-------------------------------------------------------------------*/
+static Word16 tcx_arith_find_max_scale( /* Q15-e */
+ const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */
+ const Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */
+ const Word16 L_frame, /* i: number of spectral lines Q0 */
+ const Word16 envelope[], /* i: scaled envelope Q15-e */
+ const Word16 envelope_e, /* i: scaled envelope exponent Q0 */
+ const Word16 exps[], /* i: expfp(-(int)envelope[]/2) Q15 */
+ const Word16 deadzone, /* i: deadzone (0.5f = no deadzone) Q15 */
+ Word16 *scale_e /* o: scale exponent Q0 */
+)
+{
+ Word16 i, k, q, scale, tmp, s;
+ Word32 p, L_tmp;
+ Heap heap = {{{0,0}},0}; /* silence a compiler warning */
+ Word16 tmpi1, tmpi2;
+ const Word32 limit = -325614240l/*-9.70406052784f Q25*/; /* = ln(1/16384): log of smallest allowed probability */
+
+ /* Find the top most offending lines according to probability estimates */
+ FOR (i = 0; i < kMaxNumHeapElems; i++)
+ {
+ heap.mElem[i].mIndex = 0;
+ move16();
+ heap.mElem[i].mScore = L_deposit_l(0);
+ }
+
+ tmp = add(shl(kMaxNumHeapElems, 1), 1);
+ FOR (; i < tmp; i++)
+ {
+ heap.mElem[i].mScore = L_deposit_h(0x7FFF);
+ }
+
+ FOR (k = 0; k < L_frame; k++)
+ {
+ p = Mpy_32_16_1(abs_spectrum[k], envelope[k]);
+
+ IF (GT_32(p, heap.mElem[0].mScore))
+ {
+ heap.mElem[0].mScore = p;
+ move32();
+ heap.mElem[0].mIndex = k;
+ move16();
+ MinHeapify_i(&heap, 0);
+ }
+ }
+
+ /* Make sure the scale is limited so that the offending lines don't cause probability underflow. */
+ /* Also limit scale to avoiding saturation of the gain quantizer */
+ /* scale = 1.0f/(float)sqrt(L_frame*0.5f); */
+ tmp = 15-1;
+ scale = ISqrt16(L_frame, &tmp);
+ move16();
+ *scale_e = tmp;
+ move16();
+
+ FOR (i = 0; i < kMaxNumHeapElems; i++)
+ {
+ k = heap.mElem[i].mIndex;
+ move16();
+
+ /* Get approximate maximum allowed magnitude */
+ /* q = (int)ceil(((limit - log(1.0f - (exps[k]/65536.0) * (exps[k]/65536.0))) / (-(int)envelope[k]/2/65536.0) - 1) / 2.0f); */
+ L_tmp = L_sub(0x7FFFFFFF, L_mult(exps[k], exps[k]));
+ L_tmp = Mpy_32_16_1(BASOP_Util_Log2(L_tmp), 22713); /* Q25; 22713 -> 1/log2(e) */
+ L_tmp = L_sub(limit, L_tmp);
+ tmp = negate(BASOP_Util_Divide3216_Scale(L_tmp, envelope[k], &s));
+ s = sub(add(s, 6), sub(envelope_e, 1));
+ L_tmp = L_shl(L_deposit_h(tmp), sub(s, 15+1)); /* Q16 */
+ L_tmp = L_sub(L_tmp, 0x8000);
+ q = extract_h(L_add(L_tmp, 0xFFFF)); /* ceil */
+
+ /* Refinement: get the exact q */
+ powfp_odd2(exps[k], q, &tmpi1, &tmpi2);
+
+ IF (GE_16(sub(tmpi1, tmpi2), 2)) /* q may be too low */
+ {
+ powfp_odd2(exps[k], add(q, 1), &tmpi1, &tmpi2);
+
+ WHILE (GE_16(sub(tmpi1, tmpi2), 2))
+ {
+ q = add(q, 1);
+ powfp_odd2(exps[k], add(q, 1), &tmpi1, &tmpi2);
+ }
+ }
+ ELSE /* q is too high */
+ {
+ q = sub(q, 1);
+ powfp_odd2(exps[k], q, &tmpi1, &tmpi2);
+
+ WHILE (LT_16(sub(tmpi1, tmpi2), 2))
+ {
+ q = sub(q, 1);
+ powfp_odd2(exps[k], q, &tmpi1, &tmpi2);
+ }
+ }
+
+ /* Find the largest scale so that the quantized magnitude is at most q */
+ /* p = (q+0.99f-deadzone)/(abs_spectrum[k] + 0.000001f); */
+ L_tmp = L_add(L_deposit_h(q), L_mult(sub(32440/*0.99f Q15*/, deadzone), 1)); /* Q16 */
+ tmp = BASOP_Util_Divide3232_Scale(L_tmp, L_add(abs_spectrum[k], 1), &s);
+ s = sub(add(s, 15), abs_spectrum_e);
+
+ k = norm_s(tmp);
+ tmp = shl(tmp, k);
+ s = sub(s, k);
+
+ /* assert((int)(abs_spectrum[k] * p + deadzone) <= q); */
+
+ /* scale = min(scale, p); */
+ IF (compMantExp16Unorm(tmp, s, scale, *scale_e) < 0)
+ {
+ scale = tmp;
+ move16();
+ *scale_e = s;
+ move16();
+ }
+ }
+
+
+ return scale;
+}
+/*-------------------------------------------------------------------*
+ * tcx_arith_find_kMax()
+ *
+ *
+ * Returns: index of highest freq. nonzero line (-1 if all zeros)
+ *-------------------------------------------------------------------*/
+static Word16 tcx_arith_find_kMax(
+ const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */
+ const Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */
+ const Word16 L_frame, /* i: number of spectral lines Q0 */
+ const Word16 scale, /* i: scalar quantizer scale Q15-e */
+ const Word16 scale_e, /* i: scale exponent Q0 */
+ const Word16 deadzone, /* i: deadzone (0.5f = no deadzone) Q15 */
+ const Word8 deadzone_flags[] /* i: line-wise deadzone control */
+)
+{
+ Word16 kMax;
+ Word32 tmp[2];
+
+
+ move32();
+ move32();
+ tmp[0] = L_shr(L_mac(0x7FFFFFFF, deadzone, (Word16)0x8000), abs_spectrum_e); /* 1.0f - deadzone scaled to MDCT exponent */
+ tmp[1] = L_shr(0x7FFFFFFF, abs_spectrum_e); /* 1.0f scaled to MDCT exponent */
+
+ FOR (kMax = sub(L_frame, 1); kMax >= 0; kMax--)
+ {
+ IF (GE_32(L_shl(Mpy_32_16_1(abs_spectrum[kMax], scale), scale_e), tmp[deadzone_flags[kMax]]))
+ {
+ BREAK;
+ }
+ }
+
+
+ return kMax;
+}
+
+/*-------------------------------------------------------------------*
+ * tcx_arith_rateloop()
+ *
+ *
+ * Returns: best scale Q15-e
+ *-------------------------------------------------------------------*/
+static Word16 tcx_arith_rateloop(
+ const Word32 abs_spectrum[], /* i: absolute MDCT coefficients Q31-e */
+ const Word16 abs_spectrum_e, /* i: MDCT exponent Q0 */
+ const Word16 L_frame, /* i: number of spectral lines Q0 */
+ const Word16 envelope[], /* i: scaled envelope Q15-e */
+ const Word16 envelope_e, /* i: scaled envelope exponent Q0 */
+ const Word16 exps[], /* i: expfp(-(int)envelope[]/2) Q15 */
+ const Word16 target_bits, /* i: target bit budget Q0 */
+ const Word16 deadzone, /* i: deadzone (0.5f = no deadzone) Q15 */
+ const Word8 deadzone_flags[], /* i: line-wise deadzone control Q0 */
+ Word16 *target_bits_fac, /* i/o: scale estimator compensation Q14 */
+ Word16 *scale_e /* o: scale exponent Q0 */
+)
+{
+ Word16 k, kMax, q;
+ Word16 s, adjust;
+ Word16 fixed_bits[2][N_MAX_ARI];
+ Word32 max_complexity;
+ Word16 iter; /* rate loop iteration counter */
+ Word16 scale; /* SQ scale factor to try next */
+ Word16 scale_best; /* best SQ scale factor */
+ Word16 scale_max; /* maximum allowable scale factor */
+ Word16 lob; /* lower bound of SQ scale factor */
+ Word16 hib; /* upper bound of SQ scale factor */
+ Word16 flag; /* 1:bit surplus, -1:bit deficit, 0:unknown */
+ Word32 complexity; /* cumulative rate loop complexity */
+ Word32 bits; /* number of bits (approximate) Q9 */
+ Word32 L_tmp;
+ Word16 tmp, tmp3;
+ Word32 tmp2;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+
+ scale = tcx_arith_estimate_scale(abs_spectrum, abs_spectrum_e, L_frame, envelope, envelope_e, &tmp);
+ scale = mult_r(scale, *target_bits_fac);
+ tmp = add(tmp, 1);
+
+ scale_max = tcx_arith_find_max_scale(abs_spectrum, abs_spectrum_e, L_frame, envelope, envelope_e, exps, deadzone, scale_e);
+
+#ifdef BASOP_NOGLOB
+ scale = shl_o(scale, sub(tmp, *scale_e), &Overflow);
+#else
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ scale = shl(scale, sub(tmp, *scale_e));
+ BASOP_SATURATE_WARNING_ON_EVS;
+#endif
+ scale = s_min(scale, scale_max);
+
+ scale_best = scale;
+ move16();
+ lob = 0;
+ move16();
+ hib = 0;
+ move16();
+ flag = 0;
+ move16();
+ complexity = L_deposit_l(0);
+ bits = L_deposit_l(0);
+ iter = 0;
+ move16();
+
+ max_complexity = L_mult0(96, L_frame);
+
+ /* Precalculate fixed bit costs */
+ FOR (k = 0; k < L_frame; k++)
+ {
+ /* fixed_bits[0][k] = -log2f(1 - exps[k] / 65536.0f); */
+ L_tmp = L_mac(0x7FFFFFFF, exps[k], (Word16)0x8000); /* Q31 */
+ L_tmp = L_negate(BASOP_Util_Log2(L_tmp)); /* Q25 */
+ fixed_bits[0][k] = round_fx(L_tmp); /* Q9 */
+
+ /* fixed_bits[1][k] = 1 - s*0.5f*LOG2_E - log2f(1 - (exps[k]/65536.0f) * (exps[k]/65536.0f)); */
+ L_tmp = L_msu(0x7FFFFFFF, exps[k], exps[k]); /* Q31 */
+ L_tmp = BASOP_Util_Log2(L_tmp); /* Q25 */
+ L_tmp = L_sub(1<<25, L_tmp);
+ L_tmp = L_sub(L_tmp, L_shl(L_mult0(mult_r(envelope[k], LOG2_E), 1<<10), envelope_e));
+ fixed_bits[1][k] = round_fx(L_tmp); /* Q9 */
+ }
+
+ tmp2 = L_msu0(L_sub(max_complexity, 48), L_frame, 11);
+ WHILE (LT_32(complexity, tmp2))
+ {
+ kMax = tcx_arith_find_kMax(abs_spectrum, abs_spectrum_e, L_frame, scale, *scale_e, deadzone, deadzone_flags);
+
+ complexity = L_mac0(L_mac0(L_add(complexity, 16+2), sub(L_frame, kMax), 5), kMax, 2);
+
+ bits = /*estimator_undershoot * kMax +*/ L_deposit_l(1<<9); /* Q9 */
+
+ L_tmp = L_mult(deadzone, 1); /* Q16 */
+ tmp = add(sub(abs_spectrum_e, 15), *scale_e);
+ tmp3 = add(2+9, envelope_e);
+ FOR (k = 0; k <= kMax; k++)
+ {
+ q = extract_h(L_add(L_shl(Mpy_32_16_1(abs_spectrum[k], scale), tmp), L_tmp));
+ bits = L_mac0(bits, fixed_bits[s_min(1,q)][k], 1); /* Q9 */
+ bits = L_mac0(bits, round_fx(L_shl(L_mult0(mult_r(envelope[k], LOG2_E), q), tmp3)), 1);
+ }
+ complexity = L_mac0(L_add(complexity, 32), 6, kMax);
+
+ IF (iter == 0) /* First rate loop iteration */
+ {
+ IF (LT_16(scale, scale_max)) /* Only update in non-degenerate case */
+ {
+ /* Update estimator temporal compensation factor */
+ tmp = BASOP_Util_Divide3232_Scale(L_mult0(target_bits, 1<<9), bits, &s);
+#ifdef BASOP_NOGLOB
+ tmp = shl_o(mult_r(*target_bits_fac, tmp), s, &Overflow);
+#else
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ tmp = shl(mult_r(*target_bits_fac, tmp), s);
+ BASOP_SATURATE_WARNING_ON_EVS;
+#endif
+ tmp = s_min(tmp, 20480/*1.25f Q14*/);
+ tmp = s_max(tmp, 12288/*0.75f Q14*/);
+ *target_bits_fac = tmp;
+ move16();
+ }
+ }
+
+ IF (LE_32(bits, L_mult0(target_bits, 1<<9))) /* Bits leftover => scale is too small */
+ {
+ test();
+ IF (flag <= 0 || GE_16(scale, scale_best))
+ {
+ scale_best = scale;
+ move16();
+ flag = 1;
+ move16();
+ }
+
+ lob = scale;
+ move16();
+
+ IF (hib > 0) /* Bisection search */
+ {
+ scale = add(shr(lob, 1), shr(hib, 1));
+ }
+ ELSE /* Initial scale adaptation */
+ {
+ /* adjust = 1.25f * target_bits / (float)bits; */
+ tmp = BASOP_Util_Divide3232_Scale(L_mult0(target_bits, 0x280), bits, &s);
+#ifdef BASOP_NOGLOB
+ adjust = shl_o(tmp, sub(s, 1), &Overflow); /* Q14 */
+ scale = shl_o(mult_r(scale, adjust), 1, &Overflow);
+#else
+ BASOP_SATURATE_WARNING_OFF_EVS; /* adjust limited to <= 2.0, scale to <= scale_max */
+ adjust = shl(tmp, sub(s, 1)); /* Q14 */
+ scale = shl(mult_r(scale, adjust), 1);
+ BASOP_SATURATE_WARNING_ON_EVS;
+#endif
+ scale = s_min(scale, scale_max);
+ }
+ }
+ ELSE /* Ran out of bits => scale is too large */
+ {
+ hib = scale;
+ move16();
+
+ IF (lob > 0) /* Bisection search */
+ {
+ scale = add(shr(lob, 1), shr(hib, 1));
+ }
+ ELSE { /* Initial scale adaptation */
+ /* adjust = 0.8f * target_bits / (float)bits; */
+ tmp = BASOP_Util_Divide3232_Scale(L_mult0(target_bits, 0x19A), bits, &s);
+ adjust = shl(tmp, s); /* Q15 */
+ adjust = s_max(adjust, 16384/*0.5f Q15*/);
+ scale = mult_r(scale, adjust);
+ }
+
+ IF (flag <= 0)
+ {
+ scale_best = scale;
+ move16();
+ flag = 0;
+ move16();
+ }
+ }
+ iter = add(iter, 1);
+ }
+
+
+ return scale_best;
+}
+/*-------------------------------------------------------------------*
+ * tcx_arith_encode()
+ *
+ *
+ * Returns: number of bits consumed
+ *-------------------------------------------------------------------*/
+static Word16 tcx_arith_encode(
+ Word16 q_abs_spectrum[], /* i/o: scalar quantized absolute spectrum Q0 */
+ const Word16 signs[], /* i: signs */
+ const Word16 kMax, /* i: number of nonzero spectral lines to code Q0 */
+ Word16 L_frame, /* i: nominal number of spectral lines Q0 */
+ const Word16 exps[], /* i: expfp(-(int)envelope[]/2) Q15 */
+ Word16 target_bits, /* i: target bit budget Q0 */
+ Word16 prm[] /* o: bit-stream Q0 */
+)
+{
+ TastatEnc as, as_lastgood;
+ Word16 bp, bp_lastgood;
+ Word16 k;
+ Word16 kEncoded;
+ Word16 tmpi1, tmpi2;
+
+
+
+ /* Final coding */
+ ari_start_encoding_14bits_fx(&as);
+ ari_copy_states_fx(&as, &as_lastgood);
+ bp = 0;
+ move16();
+ bp_lastgood = 0;
+ move16();
+ kEncoded = kMax;
+ move16();
+
+ FOR (k = 0; k <= kMax; k++)
+ {
+ IF (q_abs_spectrum[k] == 0)
+ {
+ assert(exps[k] >= 2);
+ bp = ari_encode_14bits_range_fx(prm, bp, target_bits, &as, shr(exps[k], 1), 16384);
+ }
+ ELSE /* q_abs_spectrum[k] != 0 */
+ {
+ powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2);
+
+ WHILE (LT_16(tmpi1, add(tmpi2, 2)))
+ {
+ q_abs_spectrum[k] = sub(q_abs_spectrum[k], 1);
+ move16();
+ powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2);
+ }
+
+ bp = ari_encode_14bits_range_fx(prm, bp, target_bits, &as, shr(tmpi2, 1), shr(tmpi1, 1));
+ bp = ari_encode_14bits_sign_fx(prm, bp, target_bits, &as, signs[k]);
+ }
+ /* Check bit budget status */
+ IF (ari_encode_overflow_fx(&as)) /* no bits left */
+ {
+ /* printf("\noverflow at %d\n\n", k); */
+
+ IF (GT_16(q_abs_spectrum[k], 1)) /* Lower magnitude is still > 0 */
+ {
+ /* Restore state */
+ ari_copy_states_fx(&as_lastgood, &as);
+ bp = bp_lastgood;
+ move16();
+
+ /* Quantize to lower magnitude */
+ q_abs_spectrum[k] = sub(q_abs_spectrum[k], 1);
+ move16();
+
+ /* Retry encoding */
+ powfp_odd2(exps[k], q_abs_spectrum[k], &tmpi1, &tmpi2);
+
+ bp = ari_encode_14bits_range_fx(prm, bp, target_bits, &as, shr(tmpi2, 1), shr(tmpi1, 1));
+ bp = ari_encode_14bits_sign_fx(prm, bp, target_bits, &as, signs[k]);
+
+ IF (!ari_encode_overflow_fx(&as)) /* Success */
+ {
+ ari_copy_states_fx(&as, &as_lastgood);
+ bp_lastgood = bp;
+ move16();
+ kEncoded = k;
+ move16();
+
+ set16_fx(q_abs_spectrum+k+1, 0, sub(kMax, k));
+ BREAK;
+ }
+ }
+ ari_copy_states_fx(&as_lastgood, &as);
+ bp = bp_lastgood;
+ move16();
+ kEncoded = sub(k, 1);
+
+ set16_fx(q_abs_spectrum+k, 0, sub(kMax, kEncoded));
+ BREAK;
+ }
+ ELSE
+ {
+ ari_copy_states_fx(&as, &as_lastgood);
+ bp_lastgood = bp;
+ move16();
+ }
+ }
+
+ /* Send zeros until L_frame */
+ tmpi1 = add(kEncoded, 1);
+ kEncoded = sub(L_frame, 1);
+ FOR (k = tmpi1; k < L_frame; k++)
+ {
+ assert(exps[k] >= 1);
+
+ bp = ari_encode_14bits_range_fx(prm, bp, target_bits, &as, shr(exps[k],1), 16384);
+ /* Check bit budget status */
+ IF (ari_encode_overflow_fx(&as)) /* no bits left */
+ {
+ ari_copy_states_fx(&as_lastgood, &as);
+ bp = bp_lastgood;
+ move16();
+ kEncoded = sub(k, 1);
+ BREAK;
+ }
+ ELSE
+ {
+ ari_copy_states_fx(&as, &as_lastgood);
+ bp_lastgood = bp;
+ move16();
+ }
+ }
+
+ IF (EQ_16(kEncoded, sub(L_frame, 1))) /* RESQ bits possibly available */
+ {
+ /* Limit target bits to actually needed bits */
+ target_bits = add(add(bp, 16), extract_l(as.value));
+ }
+ return ari_done_cbr_encoding_14bits_fx(prm, bp, target_bits, &as);
+}
+/*-------------------------------------------------------------------*
+ * tcx_arith_encode_envelope_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+void tcx_arith_encode_envelope_fx(
+ Word32 spectrum[], /* i/o: MDCT coefficients Q31-e */
+ Word16 *spectrum_e, /* i/o: MDCT exponent Q0 */
+ Word16 signs[], /* o: signs (spectrum[.]<0) Q0 */
+ const Word16 L_frame, /* i: frame or MDCT length Q0 */
+ const Word16 L_spec, /* i: frame or MDCT length Q0 */
+ Encoder_State_fx *st, /* i/o: coder state */
+ const Word16 A_ind[], /* i: quantised LPC coefficients Q12 */
+ Word16 target_bits, /* i: number of available bits Q0 */
+ Word16 prm[], /* o: bitstream parameters Q0 */
+ const Word8 use_hm, /* i: use HM in current frame? */
+ Word16 prm_hm[], /* o: HM parameter area Q0 */
+ const Word16 tcxltp_pitch, /* i: TCX LTP pitch in FD, -1 if n/a Q0*/
+ Word16 *arith_bits, /* o: bits used for ari. coding Q0 */
+ Word16 *signaling_bits, /* o: bits used for signaling Q0 */
+ Word16 *nf_seed, /* o: noise filling seed Q0 */
+ const Word16 low_complexity /* i: low-complexity flag Q0 */
+)
+{
+ Word32 env[N_MAX_ARI]; /* unscaled envelope (Q16) */
+ Word16 *envelope; /* scaled envelope (Q15-e) */
+ Word16 envelope_e;
+ Word16 exponents[N_MAX_ARI]; /* Q15 */
+ Word16 L_spec_core;
+ Word16 *q_spectrum;
+ TCX_CONFIG_HANDLE hTcxCfg;
+ Word16 scale, scale_e;
+ Word16 k, kMax;
+ Word16 deadzone;
+ const Word8 *deadzone_flags;
+ Word16 gamma_w, gamma_uw;
+ Word16 hm_bits;
+ Word32 L_tmp, L_tmp2;
+ Word16 tmp;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+ Flag Carry = 0;
+#endif
+
+ assert(L_spec <= N_MAX_ARI);
+
+ hTcxCfg = st->hTcxCfg;
+ deadzone = hTcxCfg->sq_rounding;
+ move16();
+ deadzone_flags = hTcxEnc->memQuantZeros_fx;
+ *signaling_bits = 0;
+ move16();
+
+ assert(st->enableTcxLpc);
+ gamma_w = 32767/*1.0f Q15*/;
+ move16();
+ gamma_uw = st->inv_gamma;
+ move16();
+
+ tcx_arith_render_envelope(A_ind, L_frame, L_spec, hTcxCfg->preemph_fac, gamma_w, gamma_uw, env);
+
+ FOR (k = 0; k < L_spec; k++)
+ {
+ signs[k] = extract_l(L_lshr(spectrum[k], 31));
+ if (spectrum[k] < 0)
+ {
+ spectrum[k] = L_abs(spectrum[k]);
+ move32();
+ }
+ }
+
+ IF (use_hm != 0)
+ {
+ tcx_hm_analyse_fx(spectrum, spectrum_e, L_spec, env, target_bits, hTcxCfg->coder_type, prm_hm, tcxltp_pitch, hTcxEnc->tcxltp_gain, &hm_bits);
+
+ target_bits = sub(target_bits, hm_bits);
+ *signaling_bits = add(*signaling_bits, hm_bits);
+ move16();
+ }
+ ELSE
+ {
+ prm_hm[0] = 0; /* just to be sure */ move16();
+ hm_bits = 0;
+ move16();
+ }
+
+ L_spec_core = L_spec;
+ move16();
+ if (st->igf)
+ {
+ L_spec_core = s_min(L_spec_core, st->hIGFEnc->infoStartLine);
+ }
+ envelope = (Word16*)env;
+
+ tcx_arith_scale_envelope( L_spec, L_spec_core, env, target_bits, low_complexity, envelope, &envelope_e);
+
+ tmp = sub(envelope_e, 1+15);
+ FOR (k = 0; k < L_spec; k++)
+ {
+ exponents[k] = round_fx(expfp(envelope[k], tmp));
+ }
+
+ scale = tcx_arith_rateloop(spectrum, *spectrum_e, L_spec, envelope, envelope_e, exponents, target_bits, deadzone, deadzone_flags, &(hTcxEnc->tcx_target_bits_fac), &scale_e);
+
+ /* Final quantization */
+ kMax = tcx_arith_find_kMax( spectrum, *spectrum_e, L_spec, scale, scale_e, deadzone, deadzone_flags );
+
+ q_spectrum = (Word16*)env; /* Reuse buffer */
+
+ L_tmp = L_mult(deadzone, 1); /* Q16 */
+ tmp = add(sub(*spectrum_e, 15), scale_e);
+ FOR (k = 0; k <= kMax; k++)
+ {
+ /* quantise using dead-zone */
+ q_spectrum[k] = extract_h(L_add(L_shl(Mpy_32_16_1(spectrum[k], scale), tmp), L_tmp));
+ }
+
+ /* Final encoding */
+ *arith_bits = tcx_arith_encode( q_spectrum, signs, kMax, L_spec, exponents, target_bits, prm);
+
+ /* Multiply back the signs */
+ L_tmp2 = L_deposit_l(0);
+ FOR (k = 0; k <= kMax; k++)
+ {
+#ifdef BASOP_NOGLOB
+ L_tmp2 = L_macNs_co(L_tmp2, q_spectrum[k], k, &Carry, &Overflow);
+#else /* BASOP_NOGLOB */
+ L_tmp2 = L_macNs(L_tmp2, q_spectrum[k], k);
+#endif
+
+ if (signs[k] != 0) L_tmp = L_mult(q_spectrum[k], -(1<< (30 - SPEC_EXP_DEC)));
+ if (signs[k] == 0) L_tmp = L_mult(q_spectrum[k], 1 << (30 - SPEC_EXP_DEC));
+ spectrum[k] = L_tmp;
+ move32();
+ }
+ *spectrum_e = SPEC_EXP_DEC;
+ move16();
+ set32_fx(spectrum+k, 0, sub(s_max(L_frame, L_spec), k));
+
+ /* noise filling seed */
+ *nf_seed = extract_l(L_tmp2);
+
+}
+
diff --git a/lib_enc/avq_cod_fx.c b/lib_enc/avq_cod_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..b05b84536be3574a3f6fa95e96731734af3d5406
--- /dev/null
+++ b/lib_enc/avq_cod_fx.c
@@ -0,0 +1,688 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h"
+#include /* Compilation switches */
+#include "prot.h" /* Function prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "rom_com.h" /* Static table prototypes */
+
+/*-------------------------------------------------------------------*
+ * Local prototypes
+ *-------------------------------------------------------------------*/
+static void wrte_cv(BSTR_ENC_HANDLE hBstr, const Word16 nq, const Word16 i_ind, const Word16 kv_ind, UWord16 I, Word16 kv[], Word16 * bits);
+
+/*-------------------------------------------------------------------*
+* Function AVQ_cod() *
+* *
+* Split algevraic vector quantizer (AVQ) base on RE8 latice *
+*-------------------------------------------------------------------*/
+
+void AVQ_cod_fx( /* o: comfort noise gain factor */
+ const Word16 xri[], /* i: vector to quantize */
+ Word16 xriq[], /* o: quantized normalized vector (assuming the bit budget is enough) */
+ const Word16 NB_BITS, /* i: number of allocated bits */
+ const Word16 Nsv, /* i: number of subvectors (lg=Nsv*8) */
+ const Word16 Q_in_ref /* i: Scaling input */
+)
+{
+ Word16 i, l, iter, c[8];
+ Word16 gain_inv, tmp, nbits, nbits_max, fac, offset;
+ Word16 ebits[NSV_MAX], e_ebits, f_ebits, e_tmp,f_tmp, tmp16, l_8;
+ Word32 Lener, Ltmp, Lgain, x1[8];
+ Word16 tot_est_bits, Q_in;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ Q_in = sub(Q_in_ref,1);
+ move16();
+
+ /* find energy of each subvector in log domain (scaled for bits estimation) */
+ /* if the number of allocated bits is high, recompute the energy of sub vectors with a different scaling factor (applicable only in BASOP code) */
+ DO
+ {
+ Q_in = add(Q_in,1);
+ tot_est_bits = 0;
+ move16();
+ FOR (l=0; l= 0 */
+ FOR (i=0; i<8; i++)
+ {
+#ifdef BASOP_NOGLOB
+ Lener = L_mac_o(Lener, xri[l*8+i], xri[l*8+i], &Overflow);
+#else
+ Lener = L_mac(Lener, xri[l*8+i], xri[l*8+i]);
+#endif
+ }
+ /* estimated bit consumption when gain=1 */
+ /* ebits[l] = 5.0 * FAC_LOG2 * (Word16)log10(ener * 0.5) */
+ e_ebits = norm_l(Lener);
+ f_ebits = Log2_norm_lc(L_shl(Lener, e_ebits));
+ e_ebits = sub(30-2, e_ebits); /* -2 = *0.25 */
+ e_ebits = sub(e_ebits, shl(Q_in,1));
+
+ Ltmp = L_deposit_h(e_ebits);
+ Ltmp = L_mac(Ltmp, f_ebits, 1);
+ Ltmp = L_add(L_shl(Ltmp,6), L_shl(Ltmp,4)); /* Mult by 5.0 and then by 16 (To go to Q4). Do it using Mult by 80 (which is 64+16) */
+ ebits[l] = round_fx(Ltmp); /*Q4*/
+ tot_est_bits = add(tot_est_bits, shr(ebits[l],4));
+ }
+ test();
+ test();
+ }
+ WHILE( (LE_16(Q_in, Q_in_ref))&&LE_16(tot_est_bits,mult(26214,NB_BITS))&>_16(tot_est_bits,600)); /* limited to 1 possible iteration */
+
+ /*----------------------------------------------------------------*
+ * subvector energy worst case:
+ * - typically, it's a tone with maximum of amplitude (RMS=23170).
+ * - fft length max = 1024 (N/2 is 512)
+ * log10(energy) = log10(23710*23710*1024*(N/2)) = 14.45
+ * ebits --> 5.0*FAC_LOG2*14.45 = 240 bits
+ *----------------------------------------------------------------*/
+
+ /* estimate gain according to number of bits allowed */
+ /* start at the middle (offset range = 0 to 255.75) Q6 */
+ fac = 2048;
+ move16();
+ offset = 0;
+ move16();
+
+ Ltmp = L_mult(31130, sub(NB_BITS, Nsv)); /* (1810 - 8 - 1152/8)*.95*/
+ nbits_max = round_fx(L_shl(Ltmp, 4));
+
+ /* tree search with 10 iterations : offset with step of 0.25 bits (0.3 dB) */
+ FOR (iter=0; iter<10; iter++)
+ {
+ offset = add(fac, offset);
+ /* calculate the required number of bits */
+ nbits = 0;
+ move16();
+ FOR (l=0; l 0 )
+ {
+ j = pos_max;
+ move16();
+ j = s_max(pos,j);
+
+ /* compute (number of bits -1) to describe Q #nq */
+ IF(GE_16(nq[pos],2))
+ {
+ overflow = sub(i_mult2(nq[pos],5),1);
+ }
+ ELSE
+ {
+ overflow = 0;
+ move16();
+ }
+
+ /* check for overflow and compute number of bits-1 (n) */
+ IF( GT_16(add(bits,add(overflow,j)),*nb_bits))
+ {
+ /* if budget overflow */
+ pos_tmp = add(shl(pos,3),8); /*(pos*8)+8*/
+ FOR( j=pos*8; j 0)
+ {
+ test();test();
+ IF (EQ_16(sub(*nb_bits, bits), 7) || LT_16(bits, BIT_SAVING_LOW_THR) || GE_16(bits, BIT_SAVING_HIGH_THR))
+ {
+ avq_bit_sFlag = 0;
+ move16();
+ }
+ ELSE
+ {
+ BREAK;
+ }
+ }
+
+ if( EQ_16(sub(i_mult2(5,nq[k]),1),bits)) /* check the overflow */
+ {
+ overflow = 1;
+ move16();
+ }
+
+ IF( GT_16(bits,8))
+ {
+ /* write the unary code for nq[i] */
+ j = sub(nq[k], 1);
+ IF ( nq[k] > 0 )
+ {
+ /* write the unary code */
+ FOR( ; j > 16; j -= 16 )
+ {
+ push_indice_fx( hBstr, nq_ind, 65535, 16 );
+ bits = sub(bits,16);
+ }
+
+ IF ( j > 0 )
+ {
+ push_indice_fx( hBstr, nq_ind, extract_l(L_sub(L_shl(1L,j),1L)), j );
+ bits = sub(bits,j);
+ }
+ }
+ IF ( !overflow )
+ {
+ /* write the stop bit */
+ push_indice_fx( hBstr, nq_ind, 0, 1 );
+ bits = sub(bits,1);
+ }
+
+ wrte_cv(hBstr, nq[k], i_ind, kv_ind, I[k], &kv[shl(k, 3 )], &bits);
+ }
+ } /* for */
+ /* Bit Saving Solution */
+ test();
+ IF (avq_bit_sFlag > 0 && bits > 8)
+ {
+//PMT("code not validated yet")
+ bitsMod = s_and(bits, 4/*bits%5*/);
+ i = svOrder[Nsvm1];
+ move16();
+ IF ( NE_16(i, Nsvm1))
+ {
+ nullVec = 0;
+ move16();
+ FOR (j = i; j < Nsv - 1; j++)
+ {
+ if (nq[svOrder[j]] == 0)
+ {
+ nullVec = add(nullVec,1);
+ }
+ }
+ /*nq_est = bits / 5;*/
+ nq_est = mult(bits,6554);
+ assert(nq_est == bits / 5);
+
+ test();test();test();test();test();test();test();test();test();test();test();
+ IF ((bitsMod > 0 || (EQ_16(nullVec, 4) && EQ_16(nq_est, 5))) && NE_16(bitsMod, 4) && GE_16(add(bits, nullVec), add(add(shl(nq_est ,2), nq_est),4))/*5 * nq_est + 4*/ && nq[svOrder[Nsvm2]] == 0) /* detect need for dummy bits */
+ {
+ dummy_bits = sub(5, bitsMod);
+ bits = add(bits, dummy_bits); /* add dummy bits */
+ bitsMod = 0;
+ move16();
+ }
+ ELSE IF (nq_est > 4 && ((bitsMod == 0 && nullVec > 3 && nullVec < 6) || (bitsMod == 4 && nullVec == 5)) && nq[svOrder[Nsvm2]] == 0) /* wasted bits 4, 5 for nq 6,7..*/
+ {
+ overflow = 0;
+ move16();
+ if (s_and(add(bitsMod, nullVec), 4) != 0)
+ {
+ overflow = 1;
+ move16();
+ }
+ dummy_bits = add(nullVec, overflow);
+ bits = add(bits, dummy_bits); /* add dummy bits */
+ bitsMod = 0;
+ move16();
+ }
+ }
+
+ overflow = 1;
+ move16();
+ IF (NE_16(bitsMod, 4))
+ {
+ overflow = 0;
+ move16();
+ bits = sub(bits, bitsMod);
+ }
+ bits = add(bits, overflow); /*add fake bit */
+ unused_bits = sub(bits, add(shl(nq[i],2), nq[i]));
+ if (nq[i] == 0) /*no bit savings*/
+ {
+ unused_bits = sub(unused_bits, 1); /*Stop Bit*/
+ }
+ /*unused_bits_idx = (int16_t)unused_bits / 5;*/
+ unused_bits_idx = mult(unused_bits, 6554);
+ assert(unused_bits_idx == unused_bits / 5);
+ unusedbitsFlag = 0;
+ move16();
+ IF (dummy_bits == 0)
+ {
+ test(); test();
+ IF (EQ_16(unused_bits_idx, 1) && GT_16(bits, BIT_SAVING_LOW_THR))
+ {
+ unused_bits_idx = 0;
+ unusedbitsFlag = 1;
+ move16();move16();
+ }
+ ELSE IF (unused_bits_idx == 0 && GT_16(bits, BIT_SAVING_LOW_THR))
+ {
+ unused_bits_idx = 1;
+ unusedbitsFlag = -1;
+ move16(); move16();
+ }
+ }
+
+ j = unused_bits_idx;
+ move16();
+ /*Encode Unused Bit Unary Codeword */
+ IF (j > 0)
+ {
+ /* write the unary code */
+ push_indice_fx(hBstr, nq_ind, sub(shl(1, j), 1), j);
+ }
+
+ IF (nq[i] != 0)
+ {
+ /* write the stop bit */
+ push_indice_fx(hBstr, nq_ind, 0, 1);
+ }
+
+ /*Compute AVQ code book number from unused Bits */
+ bit_tmp = add(unusedbitsFlag, unused_bits_idx);
+ /*nq_est = (int16_t)ceil(0.2f * (bits - 5 * (unusedbitsFlag + unused_bits_idx)));*/
+ nq_est = mult(6554, sub(bits, add(shl(bit_tmp, 2), bit_tmp)));
+ assert((int16_t)ceil(0.2f * (bits - 5 * (unusedbitsFlag + unused_bits_idx))) == nq_est);
+
+ if (EQ_16(nq_est, 1))
+ {
+ nq_est = 0;
+ move16();
+ }
+ bits = sub(bits, overflow);
+
+ bits = sub(bits, j);
+
+ if (nq_est != 0)
+ {
+ bits = sub(bits, 1);
+ }
+ nq[i] = nq_est;
+ move16();
+
+ /* write codebook indices (rank I and event. Voronoi index kv) */
+ wrte_cv(hBstr, nq[i], i_ind, kv_ind, I[i], &kv[shl(i, 3)], &bits);
+
+ bits = sub (bits, dummy_bits);
+
+ if (NE_16(bitsMod, 4))
+ {
+ bits = add(bits, bitsMod);
+ }
+ }
+ *nb_bits = bits;
+ move16();
+
+ FOR(i = 0; i < Nsv; i++)
+ {
+ nq_out[i] = nq[i];
+ move16();
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+* Function AVQ_cod_lpc_fx() *
+* *
+* Split algebraic vector quantizer (AVQ) for LPC quantization *
+*-------------------------------------------------------------------*/
+
+void AVQ_cod_lpc_fx(
+ Word16 *nvec, /* input: vector to quantize (normalized) (5Q10)*/
+ Word16 *nvecq, /* output: quantized vector (5Q10)*/
+ Word16 *indx, /* output: index[] (4 bits per words) (15Q0)*/
+ Word16 Nsv /* input: number of subvectors (lg=Nsv*8) */
+)
+{
+ Word16 ival, n, nq, nk, c[8], kv[8];
+ Word16 i, l, pos;
+ Word32 I;
+ Word32 x1[8];
+ UWord16 I16;
+
+
+ /* quantize all subvector using estimated gain */
+ pos = Nsv;
+ move16();
+ FOR (l=0; l 16Q15*/ move32();
+ }
+ re8_PPV_fx(x1, c); /*x1:8Q15, c:15Q0*/
+ re8_cod_fx(c, &nq, &I16, kv);
+ I = UL_deposit_l(I16);
+
+ FOR (i=0; i<8; i++)
+ {
+ nvecq[l*8+i] = shl(c[i],10); /*15Q0->5Q10*/ move16();
+ }
+
+ indx[l] = nq; /* index[0..Nsv-1] = quantizer number (0,2,3,4...) */ move16();
+ nk = 0;
+ move16();
+ n = nq;
+ move16();
+
+ IF (GT_16(nq,4))
+ {
+ nk = shr(sub(nq,3),1); /*nk = (nq-3)>>1;*/
+ n = sub(nq,shl(nk,1)); /*n = nq - nk*2; */
+ }
+
+ /* write n groups of 4-bit for base codebook index (I) */
+ FOR ( ; n > 0; n-- )
+ {
+ indx[pos++] = s_and(extract_l(I),0x000F);
+ move16();
+ I = L_shr(I,4);
+ }
+
+ /* write n groups of 4-bit for Voronoi index (k[]) */
+ FOR ( ; nk > 0; nk--)
+ {
+ ival = 0;
+ move16();
+ FOR (i=0; i<8; i++)
+ {
+ ival = shl(ival,1); /*ival <<= 1;*/
+ ival = add(ival,s_and(kv[i],0x0001)); /*ival += (kv[i] & 0x01);*/
+ kv[i] = shr(kv[i],1); /*kv[i] >>= 1;*/ move16();
+ }
+ indx[pos++] = s_and(ival,0x000F);
+ move16();
+ ival = shr(ival,4);
+ indx[pos++] = s_and(ival,0x000F);
+ move16();
+ }
+ }
+
+
+ return;
+}
+/*------------------------------------------------------------------ - *
+ * Function wrte_cv()
+ *
+ * write codebook indices(rank I and event.Voronoi index kv) *
+ *------------------------------------------------------------------ - */
+static void wrte_cv(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
+ const Word16 nq, /* i : AVQ nq index */
+ const Word16 i_ind, /* i : Base Bitstream index */
+ const Word16 kv_ind, /* i : Vornoi Bitstream index */
+ UWord16 I, /* o : rank I code book index */
+ Word16 kv[], /* o : Vornoi index kv */
+ Word16 *nbits /* i/o: bits */
+)
+{
+ int16_t pos, j;
+ int16_t bits, nq4;
+
+ bits = *nbits;
+ move16();
+
+ /* write codebook indices (rank I and event. Voronoi index kv) */
+ IF (nq == 0) /* Q0 */
+ {
+ /* nothing to write */
+ }
+ ELSE IF (LT_16(nq, 5)) /* Q2, Q3, Q4 */
+ {
+ nq4 = shl(nq, 2);
+ push_indice_fx(hBstr, i_ind, I, nq4);
+ bits = sub(bits, nq4);
+ }
+ ELSE IF (EQ_16(s_and(nq, 1), 0)) /* Q4 + Voronoi extensions r=1,2,3,... */
+ {
+ push_indice_fx(hBstr, i_ind, I, 4 * 4);
+ bits = sub(bits, 4 * 4);
+ /*pos = (int16_t)(nq / 2 - 2);*/ /* Voronoi order determination */
+ pos = sub(shr(nq,1), 2);
+ FOR (j = 0; j < 8; j++)
+ {
+ push_indice_fx(hBstr, kv_ind, kv[j], pos);
+ }
+
+ bits = sub(bits, shl(pos, 3));
+ }
+ ELSE /* Q3 + Voronoi extensions r=1,2,3,... */
+ {
+ push_indice_fx(hBstr, i_ind, I, 4 * 3);
+ bits = sub(bits, 4 * 3);
+
+ /*pos = (int16_t)(nq / 2 - 1);*/ /* Voronoi order determination */
+ pos = sub(shr(nq, 1), 1);
+ FOR (j = 0; j < 8; j++)
+ {
+ push_indice_fx(hBstr, kv_ind, kv[j], pos);
+ }
+
+ bits = sub(bits, shl(pos, 3));
+ }
+
+ *nbits = bits;
+ move16();
+ return;
+}
\ No newline at end of file
diff --git a/lib_enc/bass_psfilter_enc_fx.c b/lib_enc/bass_psfilter_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..4173a2ac63ea8e3fe842938b3b68c9137de28991
--- /dev/null
+++ b/lib_enc/bass_psfilter_enc_fx.c
@@ -0,0 +1,436 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h"
+
+/*---------------------------------------------------------------------*
+ * bass_pf_enc_fx()
+ *
+ * Low-frequency postfiltering, decoder parammeter estimation
+ *---------------------------------------------------------------------*/
+Word16 bass_pf_enc_fx(
+ const Word16* orig, /* i : 12.8kHz original signal Q0 */
+ const Word16* syn, /* i : 12.8kHz synthesis to postfilter Q0 */
+ const Word16* T_sf, /* i : Pitch period for all subframes (T_sf[16]) Q0 */
+ const Word16* gainT_sf, /* i : Pitch gain for all subframes (gainT_sf[16]) Q14 */
+ const Word16 l_frame, /* i : frame length (should be multiple of l_subfr) Q0 */
+ const Word16 l_subfr, /* i : sub-frame length (60/64) Q0 */
+ Word16 *gain_factor_param, /* o : quantized gain factor Q0 */
+ const Word16 mode, /* i : coding mode of adapt bpf */
+ struct MEM_BPF *mem_bpf /* i/o: memory state */
+)
+{
+ Word16 i, j, sf, i_subfr, T, lg, l_filt;
+ Word16 gain, d, tmp16, hr, s1, s2, s2_old, s3, s4, st, st2, st3;
+ Word32 nrg, tmp, nrg1, nrg2, n, snr, lp_error, tmp32;
+ Word16 noise_buf[L_FILT16k+2*L_SUBFR], *noise, *noise_in;
+ Word16 error_buf[L_FILT16k+2*L_SUBFR], *error, *error_in;
+ Word32 cross_n_d, nrg_n;
+ const Word16 *pFilt;
+ Word32 ener2;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+ IF (NE_16(l_frame, L_FRAME16k))
+ {
+ pFilt = filt_lp_fx;
+ l_filt = L_FILT;
+ move16();
+ }
+ ELSE
+ {
+ pFilt = filt_lp_16kHz_fx;
+ l_filt = L_FILT16k;
+ move16();
+ }
+
+ noise = noise_buf + l_filt;
+ noise_in = noise_buf + shl(l_filt, 1);
+ error = error_buf;
+ error_in = error_buf + l_filt;
+
+ sf = 0;
+ move16();
+ snr = L_deposit_l(0);
+ nrg_n = L_deposit_l(0);
+ cross_n_d = L_deposit_l(0);
+ lp_error = L_shl(mem_bpf->lp_error, 0);
+ s2_old = mem_bpf->noise_shift_old;
+ move16();
+ s3 = s4 = 0; /* initialization of s3 and s4 to suppress compiler warnings;
+ s3 and s4 get initialized for i_subfr == 0 */
+
+ nrg1 = nrg2 = 0; /* initialization fo nrg1 and nrg2 to suppress compiler warnings;
+ nrg1 and nrg1 get initialized for i_subfr == 0 */
+
+ FOR (i_subfr = 0; i_subfr < l_frame; i_subfr += l_subfr)
+ {
+ T = T_sf[sf];
+ move16();
+
+ lg = sub(sub(l_frame, T), i_subfr);
+ if (lg < 0)
+ {
+ lg = 0;
+ move16();
+ }
+ if (GT_16(lg, l_subfr))
+ {
+ lg = l_subfr;
+ move16();
+ }
+
+ IF (gainT_sf[sf] > 0)
+ {
+ /* get headroom for used part of syn */
+ tmp16 = s_max(add(lg, shl(T, 1)), add(l_subfr, T));
+ hr = getScaleFactor16(syn + sub(i_subfr, T), tmp16);
+ s1 = sub(hr, 3);
+
+ tmp = L_deposit_l(1);
+ nrg = L_deposit_l(1);
+
+ IF (lg > 0)
+ {
+ FOR (i = 0; i < lg; i++)
+ {
+ tmp32 = L_mult(syn[i+i_subfr-T], 0x4000);
+ tmp32 = L_mac(tmp32, syn[i+i_subfr+T], 0x4000);
+ tmp16 = round_fx(L_shl(tmp32, s1)); /* Q0+s1 */
+
+ tmp = L_mac0(tmp, shl(syn[i+i_subfr], s1), tmp16); /* Q0+2*s1 */
+ nrg = L_mac0(nrg, tmp16, tmp16); /* Q0+2*s1 */
+ }
+ }
+
+ IF (LT_16(lg, l_subfr))
+ {
+ FOR (i = lg; i < l_subfr; i++)
+ {
+ tmp16 = shl(syn[i+i_subfr-T], s1); /* Q0+s1 */
+ tmp = L_mac0(tmp, shl(syn[i+i_subfr], s1), tmp16); /* Q0+2*s1 */
+ nrg = L_mac0(nrg, tmp16, tmp16); /* Q0+2*s1 */
+ }
+ }
+
+ /* gain = tmp/nrg; */
+ gain = BASOP_Util_Divide3232_Scale(tmp, nrg, &tmp16);
+ BASOP_SATURATE_WARNING_OFF_EVS;
+#ifdef BASOP_NOGLOB
+ gain = shl_o(gain, tmp16, &Overflow); /* Q15 */
+#else /* BASOP_NOGLOB */
+ gain = shl(gain, tmp16); /* Q15 */
+#endif /* BASOP_NOGLOB */
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ if (gain < 0)
+ {
+ gain = 0;
+ move16();
+ }
+
+ st = sub(norm_l(lp_error), 3);
+ test();
+ if ((LT_16(st, s1))&&(lp_error!=0))
+ {
+ s1 = st;
+ move16();
+ }
+
+ ener2 = L_deposit_l(0);
+
+ IF (lg > 0)
+ {
+ FOR (i = 0; i < lg; i++)
+ {
+ tmp32 = L_msu0(0, gain, syn[i+i_subfr-T]);
+#ifdef BASOP_NOGLOB
+ tmp32 = L_msu0_o(tmp32, gain, syn[i + i_subfr + T], &Overflow);
+ tmp16 = mac_ro(tmp32, gain, syn[i+i_subfr], &Overflow); /* Q0 */
+#else
+ tmp32 = L_msu0(tmp32, gain, syn[i + i_subfr + T]);
+ tmp16 = mac_r(tmp32, gain, syn[i+i_subfr]); /* Q0 */
+#endif
+
+ lp_error = Mpy_32_16_1(lp_error, 29491/*0.9f Q15*/);
+#ifdef BASOP_NOGLOB
+ lp_error = L_mac_o(lp_error, tmp16, 0x1000, &Overflow); /* Q13 */
+
+ tmp16 = round_fx_o(L_shl_o(lp_error, s1, &Overflow), &Overflow); /* Q0+s1-3 */
+ ener2 = L_mac0_o(ener2, tmp16, tmp16, &Overflow); /* Q0+(s1-3)*2 */
+#else
+ lp_error = L_mac(lp_error, tmp16, 0x1000); /* Q13 */
+
+ tmp16 = round_fx(L_shl(lp_error, s1)); /* Q0+s1-3 */
+ ener2 = L_mac0(ener2, tmp16, tmp16); /* Q0+(s1-3)*2 */
+#endif
+
+ }
+ }
+
+ IF (LT_16(lg, l_subfr))
+ {
+ FOR (i = lg; i < l_subfr; i++)
+ {
+ tmp32 = L_mult0(gain, syn[i+i_subfr]);
+#ifdef BASOP_NOGLOB
+ tmp32 = L_msu0_o(tmp32, gain, syn[i+i_subfr-T], &Overflow); /* Q0 */
+ tmp16 = round_fx_o(tmp32, &Overflow);
+#else
+ tmp32 = L_msu0(tmp32, gain, syn[i+i_subfr-T]); /* Q0 */
+ tmp16 = round_fx(tmp32);
+#endif
+ lp_error = Mpy_32_16_1(lp_error, 29491/*0.9f Q15*/);
+#ifdef BASOP_NOGLOB
+ lp_error = L_mac_o(lp_error, tmp16, 0x1000, &Overflow); /* Q13 */
+
+ tmp16 = round_fx_o(L_shl_o(lp_error, s1, &Overflow), &Overflow); /* Q0+s1-3 */
+ ener2 = L_mac0_o(ener2, tmp16, tmp16, &Overflow); /* Q0+(s1-3)*2 */
+#else
+ lp_error = L_mac(lp_error, tmp16, 0x1000); /* Q13 */
+
+ tmp16 = round_fx(L_shl(lp_error, s1)); /* Q0+s1-3 */
+ ener2 = L_mac0(ener2, tmp16, tmp16); /* Q0+(s1-3)*2 */
+#endif
+ }
+ }
+
+ st = shl(sub(s1, 3), 1);
+
+ IF (ener2 > 0)
+ {
+ ener2 = L_shr(BASOP_Util_Log2(ener2), 9); /* 15Q16 */
+ ener2 = L_add(ener2, L_deposit_h(sub(31, st)));
+ }
+ ELSE
+ {
+ ener2 = 0xFFF95B2C; /* log2(0.01) (15Q16) */ move32();
+ }
+
+ mem_bpf->lp_error_ener = L_add(Mpy_32_16_1(L_sub(mem_bpf->lp_error_ener, ener2), 32440/*0.99f Q15*/), ener2); /* 15Q16 */
+
+ st = add(st, 6);
+ ener2 = L_sub(mem_bpf->lp_error_ener, L_deposit_h(sub(31, st)));
+ IF (ener2 >= 0)
+ {
+ tmp16 = add(extract_h(ener2), 1);
+ ener2 = L_sub(ener2, L_deposit_h(tmp16));
+ tmp = L_shr(tmp, tmp16);
+ nrg = L_shr(nrg, tmp16);
+ }
+ ener2 = BASOP_Util_InvLog2(L_shl(ener2, 9)); /* Q0+2*s1 */
+
+ tmp32 = L_add(L_shr(nrg, 1), L_shr(ener2, 1));
+ if (tmp32 == 0) tmp32 = L_deposit_l(1);
+ tmp16 = BASOP_Util_Divide3232_Scale(tmp, tmp32, &st);
+ BASOP_SATURATE_WARNING_OFF_EVS;
+#ifdef BASOP_NOGLOB
+ tmp16 = shl_o(tmp16, sub(st, 2), &Overflow); /* Q15 */
+#else /* BASOP_NOGLOB */
+ tmp16 = shl(tmp16, sub(st, 2)); /* Q15 */
+#endif /* BASOP_NOGLOB */
+
+ if (GT_16(tmp16, 16384/*0.5f Q15*/))
+ {
+ tmp16 = 16384/*0.5f Q15*/;
+ move16();
+ }
+ if (tmp16 < 0)
+ {
+ tmp16 = 0;
+ move16();
+ }
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ s2 = hr;
+ move16();
+
+ IF (lg > 0)
+ {
+ FOR (i = 0; i < lg; i++)
+ {
+ tmp32 = L_msu0(0, tmp16, syn[i+i_subfr-T]);
+ tmp32 = L_msu0(tmp32, tmp16, syn[i+i_subfr+T]);
+ tmp32 = L_mac(tmp32, tmp16, syn[i+i_subfr]);
+ noise_in[i] = round_fx(L_shl(tmp32, s2)); /* Q0+s2 */
+
+#ifdef BASOP_NOGLOB
+ error_in[i] = sub_o(orig[i+i_subfr], syn[i+i_subfr], &Overflow); /*Q0*/ move16();
+#else
+ error_in[i] = sub(orig[i+i_subfr], syn[i+i_subfr]); /*Q0*/ move16();
+#endif
+ }
+ }
+
+ IF (LT_16(lg, l_subfr))
+ {
+ FOR (i = lg; i < l_subfr; i++)
+ {
+ tmp32 = L_mult0(tmp16, syn[i+i_subfr]);
+ tmp32 = L_msu0(tmp32, tmp16, syn[i+i_subfr-T]);
+ noise_in[i] = round_fx(L_shl(tmp32, s2)); /* Q0+s2 */
+
+#ifdef BASOP_NOGLOB
+ error_in[i] = sub_o(orig[i+i_subfr], syn[i+i_subfr], &Overflow); /*Q0*/ move16();
+#else
+ error_in[i] = sub(orig[i+i_subfr], syn[i+i_subfr]); /*Q0*/ move16();
+#endif
+ }
+ }
+ }
+ ELSE
+ {
+ set16_fx(noise_in, 0, l_subfr);
+ set16_fx(error_in, 0, l_subfr);
+ s2 = s2_old;
+ }
+
+ tmp16 = shl(l_filt, 1);
+
+ /* copy history buffers (rescale noise history to new exponent) */
+ st = sub(s2, s2_old);
+ FOR (i = 0; i < tmp16; i++)
+ {
+ noise_buf[i] = shl(mem_bpf->noise_buf[i], st);
+ move16();
+ }
+ Copy(noise_buf+l_subfr, mem_bpf->noise_buf, tmp16);
+ s2_old = s2;
+ move16();
+
+ Copy(mem_bpf->error_buf, error_buf, l_filt);
+ Copy(error_buf+l_subfr, mem_bpf->error_buf, l_filt);
+
+ /* get noise shift */
+ st = getScaleFactor16(noise-l_filt, add(l_subfr, shl(l_filt, 1)));
+ st = add(sub(st, 3), s2);
+ if (i_subfr == 0)
+ {
+ s3 = st;
+ move16();
+ }
+ tmp16 = sub(st, s3);
+ IF (tmp16 < 0)
+ {
+ nrg_n = L_shl(nrg_n, s_max(-15, shl(tmp16, 1)));
+ cross_n_d = L_shl(cross_n_d, tmp16);
+ s3 = st;
+ move16();
+ }
+
+ /* get error shift */
+ st = getScaleFactor16(error, l_subfr);
+ st = sub(st, 3);
+ if (i_subfr == 0)
+ {
+ s4 = st;
+ move16();
+ }
+ tmp16 = sub(st, s4);
+ IF (tmp16 < 0)
+ {
+ cross_n_d = L_shl(cross_n_d, tmp16);
+ nrg1 = L_shl(nrg1, shl(tmp16, 1));
+ nrg2 = L_shl(nrg2, shl(tmp16, 1));
+ s4 = st;
+ move16();
+ }
+
+ nrg1 = L_deposit_l(1);
+ nrg2 = L_deposit_l(1);
+
+ /* substract from voiced speech low-pass filtered noise */
+ st = sub(s_min(s3, s4), 1);
+ st2 = sub(s3, s2);
+ st3 = sub(st,s2);
+ FOR (i = 0; i < l_subfr; i++)
+ {
+ n = L_mult(pFilt[0], noise[i]); /* Q16+s2 */
+
+ FOR (j = 1; j <= l_filt; j++)
+ {
+ n = L_mac(n, pFilt[j], noise[i-j]);
+ n = L_mac(n, pFilt[j], noise[i+j]);
+ }
+
+ /*for optimal g*/
+ tmp16 = round_fx(L_shl(n, st2)); /* Q0+s3 */
+ d = shl(error[i], s4); /* Q0+s4 */
+ nrg_n = L_mac0(nrg_n, tmp16, tmp16); /* Q0+2*s3 */
+ cross_n_d = L_mac0(cross_n_d, tmp16, d); /* Q0+s3+s4 */
+
+ /*for evaluating SNR*/
+ tmp16 = round_fx(L_shl(n, st3)); /* Q0+st */
+ tmp16 = add(tmp16, shl(error[i], st)); /* Q0+st */
+ nrg1 = L_mac0(nrg1, tmp16, tmp16); /* Q0+2*st */
+ nrg2 = L_mac0(nrg2, d, d); /* Q0+2*s4 */
+ }
+
+ /*SegSNR*/
+ snr = L_add(snr, L_shr(L_sub(BASOP_Util_Log2(nrg2), BASOP_Util_Log2(nrg1)), 9)); /* 15Q16 */
+ snr = L_add(snr, L_deposit_h(shl(sub(st, s4), 1)));
+
+ sf = add(sf, 1);
+ }
+
+ if (nrg_n == 0)
+ {
+ nrg_n = L_deposit_l(1);
+ }
+
+ /*Compute and quantize optimal gain*/
+ /* optimal gain = -/ */
+ *gain_factor_param = 2;
+ move16();
+ IF (EQ_16(mode, 2))
+ {
+ /* *gain_factor_param = (int)(-2.f*(cross_n_d/nrg_n)+0.5f); */
+ tmp16 = BASOP_Util_Divide3232_Scale(cross_n_d, nrg_n, &st); /* Q15-st-s3+s4 */
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ tmp16 = shl(negate(tmp16), add(sub(add(st, s3), s4), 1-14)); /* Q1 */
+ tmp16 = shr(add(tmp16, 1), 1); /* Q0 */
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ *gain_factor_param = tmp16;
+ move16();
+ if (GT_16(tmp16, 3))
+ {
+ *gain_factor_param = 3;
+ move16();
+ }
+ if (tmp16 < 0)
+ {
+ *gain_factor_param = 0;
+ move16();
+ }
+
+ /*If optimal gain negatif or zero but snr still positif->gain=0.5f*/
+ test();
+ if (snr > 0 && *gain_factor_param == 0)
+ {
+ *gain_factor_param = 1;
+ move16();
+ }
+ }
+
+ mem_bpf->lp_error = lp_error;
+ move32();
+ mem_bpf->noise_shift_old = s2_old;
+ move16();
+
+
+ return 0;
+}
+
diff --git a/lib_enc/bw_detect_fx.c b/lib_enc/bw_detect_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..87a328c53407ee88ab90482c36832cdc0059a389
--- /dev/null
+++ b/lib_enc/bw_detect_fx.c
@@ -0,0 +1,1129 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_enc.h" /* Encoder static table prototypes */
+#include "rom_com.h"
+#include "basop_util.h"
+#include "ivas_cnst.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+#define BWD_MIN_BRATE_WIDER_BW_MDCT IVAS_48k
+#define BWD_MIN_BRATE_WIDER_BW_ISM IVAS_32k
+#define BWD_MAX_BRATE_WIDER_BW_MDCT IVAS_80k
+#define BWD_MAX_BRATE_WIDER_BW_ISM IVAS_64k
+
+#define ALPHA_BWD_FX 24576 /* 0.75 in Q15*/
+#define BWD_LT_THRESH_FX 19661 /* 0.6 in Q15*/
+
+#define BWD_COUNT_MAX 100
+#define BWD_COUNT_WIDER_BW 10
+#define BWD_COUNT_WIDER_BW_MDCT 0
+
+#define BWD_N_BINS_MAX 13
+
+#define CLDFB_ENER_OFFSET_FX 26214 /* 1.6 in Q14 */
+
+/*-------------------------------------------------------------------*
+ * bw_detect()
+ *
+ * WB, SWB and FB bandwidth detector
+ *--------------------------------------------------------------------*/
+
+void bw_detect_fx(
+ Encoder_State_fx *st, /* i/o: Encoder State */
+ const Word16 signal_in[], /* i : input signal */
+ Word16* spectrum, /* i : MDCT spectrum */
+ const Word32 *enerBuffer, /* i : CLDFB Energy Q31 */
+ const Word16 *cldfbBuf_Ener_Exp,/* i : CLDFB Energy Exponent */
+ const IVAS_FORMAT ivas_format, /* i : IVAS format */
+ const int16_t mct_on /* i : flag MCT mode */
+)
+{
+ Word16 Q_dct;
+ Word16 i, j, k, bw_max, bin_width, n_bins;
+ Word16 max_NB, max_WB, max_SWB, max_FB, mean_NB, mean_WB, mean_SWB, mean_FB; /* Q11*/
+ const Word16 *pt, *pt1;
+ Word16 spect[L_FRAME48k], spect_bin[BWD_N_BINS_MAX];
+ Word32 spect32[L_FRAME48k],in_win32[BWD_TOTAL_WIDTH];
+ Word16 e_tmp, f_tmp;
+ Word32 L_tmp, sum32;
+
+ Word32 L_tmp1, L_tmp2, L_tmp3;
+ Word16 scale;
+ Word16 ScalFac, ScalFacInv;
+ Word32 cldfb_bin[9];
+ Word16 cldfb_bin_Exp[9];
+ Word16 cldfb_bin_width = 4;
+ const Word32 *pt32;
+ Word32 max_NB32, max_WB32, max_SWB32, max_FB32, mean_NB32, mean_WB32, mean_SWB32, mean_FB32; /* Q11*/ /* we need Word32 for the new cldfb energy vectors */
+ Word16 bwd_count_wider_bw;
+#ifdef IVAS_CODE_DFT
+ Word16 l_frame;
+#endif
+#ifndef IVAS_CODE_BWD
+ (void)spectrum;
+#endif
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ bwd_count_wider_bw = BWD_COUNT_WIDER_BW; move16();
+ test();test();test();test();test();
+ if (st->ini_frame_fx > 0 && ((EQ_16(st->element_mode, IVAS_CPE_MDCT) && (GE_32(st->element_brate, BWD_MIN_BRATE_WIDER_BW_MDCT) || mct_on)) ||
+ (EQ_16(ivas_format, ISM_FORMAT) && GE_32(st->element_brate, BWD_MIN_BRATE_WIDER_BW_ISM))))
+ {
+ bwd_count_wider_bw = BWD_COUNT_WIDER_BW_MDCT; move16();
+ }
+ IF( GT_32(st->input_Fs_fx,8000))
+ {
+
+ IF ( enerBuffer != NULL)
+ {
+ n_bins = 9;
+ move16();
+ scale = st->cldfbAna_Fx->scale;
+ move16();/* 7Q8 */
+
+ /*ScalFac = 1/ ( st->cldfbAnaEnc->scale * st->cldfbAnaEnc->scale * 8.f);*/
+ /*hs->CLDFBscalingFactor = div_s(1, shl(i_mult2(CLDFBscale, CLDFBscale), 3));*/
+
+ assert(2048/*1.0/(1<<4) Q15*/ < mult(scale, scale));
+ /* Exponent ScalFacInv: -16 = -(2*7 (CLDFBscale) + 2 (8.0) */
+ ScalFacInv = shl(mult(scale,scale),1); /* Q8*Q8 = Q16 + shl -> Q17 -16 -> Q1; shl -> Q2 */
+ /* Exponent ScalFac: -15 = -(2*7 (CLDFBscale) + 2 (8.0) - 1 (1.0)) */
+ ScalFac = div_s(0x4000,ScalFacInv); /* bin(17214) *2^-15 * 2^-15 = 0.0000160 , use CLDFBscalingFactor_EXP for this*/ /*Q15*/
+
+
+ /*set_f( cldfb_bin, 0.001f, 9 );*/
+ set32_fx( cldfb_bin, 1, n_bins ); /* Q31*/
+ set16_fx( cldfb_bin_Exp, -15, n_bins );
+
+ /* NB: 1.2 - 2.8 kHz, 4 cldfb-bands */
+ FOR(i=0; i< cldfb_bin_width; i++ )
+ {
+ cldfb_bin[0] = BASOP_Util_Add_Mant32Exp( cldfb_bin[0],cldfb_bin_Exp[0], enerBuffer[3+i], cldfbBuf_Ener_Exp[3+i], &(cldfb_bin_Exp[0]) );
+ move32();/* result: Q31 */
+ }
+
+ cldfb_bin[0] = Mpy_32_16_1(cldfb_bin[0], ScalFac );
+ move32(); /* Q31 */
+ cldfb_bin_Exp[0] = add( cldfb_bin_Exp[0], CLDFBscalingFactor_EXP);
+ move16();
+
+ if(cldfb_bin[i] == 0)
+ {
+ cldfb_bin[i] = L_deposit_l(1);
+ }
+ L_tmp = BASOP_Util_Log2(cldfb_bin[0]); /*(log2(660423549*2^(-31))/64)*2^31*/
+#ifdef BASOP_NOGLOB
+ L_tmp = L_add_o(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[0]),31-LD_DATA_SCALE), &Overflow); /* Q25 */
+#else /* BASOP_NOGLOB */
+ L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[0]),31-LD_DATA_SCALE)); /* Q25 */
+#endif /* BASOP_NOGLOB */
+ cldfb_bin[0] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/);
+ move32();/* 1/log2(10) */ /* Q25 */
+
+ /* WB: 4.4 - 7.2 kHz, 8 cldfb-bands, mid band(14) counted twice */
+ IF( GE_32(st->input_Fs_fx,16000))
+ {
+ /*
+ cldfb_bin[1] += Sum( &(enerBuffer[11]), cldfb_bin_width );
+ cldfb_bin[2] += Sum( &(enerBuffer[14]), cldfb_bin_width );*/
+ FOR(i=0; i< cldfb_bin_width; i++ )
+ {
+ cldfb_bin[1] = BASOP_Util_Add_Mant32Exp( cldfb_bin[1],cldfb_bin_Exp[1], enerBuffer[11+i], cldfbBuf_Ener_Exp[11+i], &(cldfb_bin_Exp[1]) );
+ move32();
+ cldfb_bin[2] = BASOP_Util_Add_Mant32Exp( cldfb_bin[2],cldfb_bin_Exp[2], enerBuffer[14+i], cldfbBuf_Ener_Exp[14+i], &(cldfb_bin_Exp[2]) );
+ move32();
+ }
+ FOR(i=1; i<= 2; i++ )
+ {
+ cldfb_bin[i] = Mpy_32_16_1(cldfb_bin[i], ScalFac );
+ move32();
+ cldfb_bin_Exp[i] = add( cldfb_bin_Exp[i], CLDFBscalingFactor_EXP);
+ move16();
+
+ if(cldfb_bin[i] == 0)
+ {
+ cldfb_bin[i] = L_deposit_l(1);
+ }
+ L_tmp = BASOP_Util_Log2(cldfb_bin[i]); /*(log2(660423549*2^(-31))/64)*2^31*/
+ L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[i]),31-LD_DATA_SCALE)); /* Q25 */
+ cldfb_bin[i] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/);
+ move32();/* 1/log2(10) */ /* Q25 */
+ }
+ }
+
+ /* SWB: 9.2 - 15.6 kHz, 16 cldfb-bands */
+ IF( GE_32(st->input_Fs_fx,32000))
+ {
+ /*
+ cldfb_bin[3] += Sum( &(enerBuffer[23]), cldfb_bin_width );
+ cldfb_bin[4] += Sum( &(enerBuffer[27]), cldfb_bin_width );
+ cldfb_bin[5] += Sum( &(enerBuffer[31]), cldfb_bin_width );
+ cldfb_bin[6] += Sum( &(enerBuffer[35]), cldfb_bin_width );
+ */
+ FOR(i=0; i< cldfb_bin_width; i++ )
+ {
+ cldfb_bin[3] = BASOP_Util_Add_Mant32Exp( cldfb_bin[3],cldfb_bin_Exp[3], enerBuffer[23+i], cldfbBuf_Ener_Exp[23+i], &(cldfb_bin_Exp[3]) );
+ move32();
+ cldfb_bin[4] = BASOP_Util_Add_Mant32Exp( cldfb_bin[4],cldfb_bin_Exp[4], enerBuffer[27+i], cldfbBuf_Ener_Exp[27+i], &(cldfb_bin_Exp[4]) );
+ move32();
+ cldfb_bin[5] = BASOP_Util_Add_Mant32Exp( cldfb_bin[5],cldfb_bin_Exp[5], enerBuffer[31+i], cldfbBuf_Ener_Exp[31+i], &(cldfb_bin_Exp[5]) );
+ move32();
+ cldfb_bin[6] = BASOP_Util_Add_Mant32Exp( cldfb_bin[6],cldfb_bin_Exp[6], enerBuffer[35+i], cldfbBuf_Ener_Exp[35+i], &(cldfb_bin_Exp[6]) );
+ move32();
+ }
+ FOR(i=3; i<= 6; i++ )
+ {
+ cldfb_bin[i] = Mpy_32_16_1(cldfb_bin[i], ScalFac );
+ move32();
+ cldfb_bin_Exp[i] = add( cldfb_bin_Exp[i], CLDFBscalingFactor_EXP);
+ move16();
+
+ if(cldfb_bin[i] == 0)
+ {
+ cldfb_bin[i] = L_deposit_l(1);
+ }
+ L_tmp = BASOP_Util_Log2(cldfb_bin[i]); /*(log2(660423549*2^(-31))/64)*2^31*/
+ L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[i]),31-LD_DATA_SCALE)); /* Q25 */
+ cldfb_bin[i] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/);
+ move32();/* 1/log2(10) */ /* Q25 */
+ }
+ }
+
+ /* FB: 16.8 - 20.0 kHz, 8 cldfb-bands */
+ IF( GE_32(st->input_Fs_fx,48000))
+ {
+ /*
+ cldfb_bin[7] += Sum( &(enerBuffer[42]), cldfb_bin_width );
+ cldfb_bin[8] += Sum( &(enerBuffer[46]), cldfb_bin_width );
+ */
+ FOR(i=0; i< cldfb_bin_width; i++ )
+ {
+ cldfb_bin[7] = BASOP_Util_Add_Mant32Exp( cldfb_bin[7],cldfb_bin_Exp[7], enerBuffer[42+i], cldfbBuf_Ener_Exp[42+i], &(cldfb_bin_Exp[7]) );
+ move32();
+ cldfb_bin[8] = BASOP_Util_Add_Mant32Exp( cldfb_bin[8],cldfb_bin_Exp[8], enerBuffer[46+i], cldfbBuf_Ener_Exp[46+i], &(cldfb_bin_Exp[8]) );
+ move32();
+ }
+ FOR(i=7; i<= 8; i++ )
+ {
+ cldfb_bin[i] = Mpy_32_16_1(cldfb_bin[i], ScalFac );
+ move32();
+ cldfb_bin_Exp[i] = add( cldfb_bin_Exp[i], CLDFBscalingFactor_EXP);
+ move16();
+
+ if(cldfb_bin[i] == 0)
+ {
+ cldfb_bin[i] = L_deposit_l(1);
+ }
+ L_tmp = BASOP_Util_Log2(cldfb_bin[i]); /*(log2(660423549*2^(-31))/64)*2^31*/
+ L_tmp = L_add(L_tmp,L_shl(L_deposit_l(cldfb_bin_Exp[i]),31-LD_DATA_SCALE)); /* Q25 */
+ cldfb_bin[i] = Mpy_32_16_1(L_tmp, 9864/*1.0f/3.3219280948873623478703194294894f Q15*/);
+ move32();/* 1/log2(10) */ /* Q25 */
+ }
+ }
+ /* cldfb_bin_Exp[] are applied now in cldfb_bin[i] -> don't use again */
+ set16_fx( cldfb_bin_Exp, 0, n_bins );
+
+ }
+ ELSE
+ {
+
+ /* set width of a speactral bin (corresponds to 1.5kHz) */
+ IF( EQ_32(st->input_Fs_fx,16000))
+ {
+ bw_max = WB;
+ move16();
+ bin_width = 60;
+ move16();
+ n_bins = 5;
+ move16(); /* spectrum to 7.5 kHz */
+ }
+ ELSE IF( EQ_32(st->input_Fs_fx,32000))
+ {
+ bw_max = SWB;
+ move16();
+ bin_width = 30;
+ move16();
+ n_bins = 10;
+ move16(); /* spectrum to 15.0 kHz */
+ }
+ ELSE /* st->input_Fs == 48000 */
+ {
+ bw_max = FB;
+ move16();
+ bin_width = 20;
+ move16();
+ n_bins = BWD_N_BINS_MAX;
+ move16(); /* spectrum to 19.5 kHz */
+ }
+ Q_dct = 0;
+ move16();
+ IF(signal_in != NULL)
+ {
+ /*---------------------------------------------------------------------*
+ * windowing of the input signal
+ *---------------------------------------------------------------------*/
+ pt = signal_in;
+ pt1 = hann_window_320_fx;
+ /* 1st half of the window */
+ FOR(i = 0; i < BWD_TOTAL_WIDTH / 2; i++)
+ {
+ /*in_win[i] = *pt++ * *pt1++;*/
+ in_win32[i] = L_mult(*pt++,*pt1++);
+ move32(); /* Q0*Q15 -> Q16*/
+ }
+ pt1--;
+ /* 2nd half of the window */
+ FOR(; i < BWD_TOTAL_WIDTH; i++)
+ {
+ /*in_win[i] = *pt++ * *pt1--;*/
+ in_win32[i] = L_mult(*pt++,*pt1--);
+ move32();
+ }
+ edct_fx(in_win32, spect32, BWD_TOTAL_WIDTH, &Q_dct /*,st->element_mode*/);
+
+ FOR(i = 0; i < BWD_TOTAL_WIDTH; i++)
+ {
+#ifdef BASOP_NOGLOB
+ spect[i] = round_fx_o(L_shr_o(spect32[i],Q_dct, &Overflow), &Overflow);
+#else /* BASOP_NOGLOB */
+ spect[i] = round_fx(L_shr(spect32[i],Q_dct));
+#endif
+ }
+ Q_dct = -2;
+ move16();
+ }
+ ELSE
+ {
+#ifdef IVAS_CODE_DFT
+ l_frame = (int16_t)(st->input_Fs / FRAMES_PER_SEC);
+ if (st->core == TCX_10_CORE)
+ {
+ l_frame /= 2;
+ }
+
+ bin_width *= (l_frame / BWD_TOTAL_WIDTH);
+ mvr2r(spectrum, spect, l_frame);
+#endif
+ }
+ /*---------------------------------------------------------------------*
+ * compute energy per spectral bins
+ *---------------------------------------------------------------------*/
+
+ set16_fx( spect_bin, 1, n_bins );
+ Q_dct = shl(Q_dct,1);
+
+ FOR( k=0; k<=bw_max; k++ )
+ {
+ FOR( i=bwd_start_bin[k]; i<=bwd_end_bin[k]; i++ )
+ {
+ sum32 = L_deposit_l(1);
+ pt1 = &spect[i_mult2(i,bin_width)];
+ FOR( j=0; j Q25 */
+
+ mean_NB = extract_l(L_shr( L_add(mean_NB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+ max_NB = extract_l(L_shr( L_add(max_NB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+ mean_WB = extract_l(L_shr( L_add(mean_WB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+ max_WB = extract_l(L_shr( L_add(max_WB32 ,cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+
+
+ /*if WB */
+ IF( EQ_32(st->input_Fs_fx,16000))
+ {
+ /* for 16kHz sampled inputs, do not check SWB & FB */
+ mean_SWB = 0;
+ move16();
+ max_SWB = 0;
+ move16();
+ mean_FB = 0;
+ move16();
+ max_FB = 0;
+ move16();
+ }
+ ELSE
+ {
+ /* else if SWB */
+ IF( EQ_32(st->input_Fs_fx,32000))
+ {
+
+ /* for 32kHz sampled inputs, do not check FB */
+ mean_FB = 0;
+ move16();
+ max_FB = 0;
+ move16();
+
+ /* SWB: 8,8 - 15,2 kHz, 16 cldfb-bands (4 bins) */
+
+ maximum_32_fx( pt32, 4, &max_SWB32 );
+
+ L_tmp = L_shr(*pt32++, 2); /* /4 */
+ L_tmp = L_add(L_tmp,L_shr(*pt32++, 2));
+ L_tmp = L_add(L_tmp,L_shr(*pt32++, 2));
+ mean_SWB32 = L_add(L_tmp,L_shr(*pt32++, 2));
+
+ mean_SWB = extract_l(L_shr(L_add(mean_SWB32, cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+ max_SWB = extract_l(L_shr(L_add(max_SWB32 , cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+
+ }
+ ELSE
+ { /* FB */
+ /* SWB: 8,8 - 15,2 kHz, 16 cldfb-bands (4 bins) */
+
+ maximum_32_fx( pt32, 4, &max_SWB32 );
+
+ L_tmp = L_shr(*pt32++, 2); /* /4 */
+ L_tmp = L_add(L_tmp,L_shr(*pt32++, 2));
+ L_tmp = L_add(L_tmp,L_shr(*pt32++, 2));
+ mean_SWB32 = L_add(L_tmp,L_shr(*pt32++, 2));
+
+ mean_SWB = extract_l(L_shr(L_add(mean_SWB32, cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+ max_SWB = extract_l(L_shr(L_add(max_SWB32 , cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+
+
+ /* FB: 16,4 - 19,6 kHz, 8 cldfb-bands (2 bins) */
+
+ maximum_32_fx( pt32, 2, &max_FB32 );
+
+ L_tmp = L_shr(*pt32++, 1);
+ mean_FB32 = L_add(L_tmp,L_shr(*pt32++, 1));
+
+ mean_FB = extract_l(L_shr(L_add(mean_FB32, cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+ max_FB = extract_l(L_shr(L_add(max_FB32 , cldfb_ener_offset_32), 25-11)); /* (Q25 + Q25) -> Q11 */
+
+ }
+ }
+ }
+ ELSE
+ {
+ pt = (const Word16 *)spect_bin;
+ /* NB: 1.5-3.0kHz (1 bin) */
+ pt++;
+ mean_NB = *pt++;
+ move16();
+ max_NB = mean_NB;
+ move16();
+
+ /* WB: 4.5-7.5kHz (2 bins) */
+ pt++;
+ maximum_fx( pt, 2, &max_WB );
+ L_tmp = L_mult(*pt++,16384);
+ L_tmp = L_mac(L_tmp,*pt++,16384);
+ mean_WB = round_fx(L_tmp);
+
+ IF( EQ_32(st->input_Fs_fx,16000))
+ {
+ /* for 16kHz sampled inputs, do not check SWB & FB */
+ mean_SWB = 0;
+ move16();
+ max_SWB = 0;
+ move16();
+ mean_FB = 0;
+ move16();
+ max_FB = 0;
+ move16();
+ }
+ ELSE
+ {
+ /* SWB: 9.0-15.0kHz (4 bins) */
+ pt++;
+ maximum_fx( pt, 4, &max_SWB );
+ L_tmp = L_mult(*pt++,8192);
+ L_tmp = L_mac(L_tmp,*pt++,8192);
+ L_tmp = L_mac(L_tmp,*pt++,8192);
+ L_tmp = L_mac(L_tmp,*pt++,8192);
+ mean_SWB = round_fx(L_tmp);
+
+ IF( EQ_32(st->input_Fs_fx,48000))
+ {
+ /* FB: 16.5-19.5kHz (2 bins) */
+ pt++;
+ maximum_fx( pt, 2, &max_FB );
+ L_tmp = L_mult(*pt++,16384);
+ L_tmp = L_mac(L_tmp,*pt++,16384);
+ mean_FB = round_fx(L_tmp);
+ }
+ ELSE
+ {
+ /* for 32kHz sampled inputs, do not check FB */
+ mean_FB = 0;
+ move16();
+ max_FB = 0;
+ move16();
+ }
+ }
+ }
+ /*---------------------------------------------------------------------*
+ * update LT counters and energies
+ *---------------------------------------------------------------------*/
+
+ /*if( localVAD || st->lp_noise > 30 )*/
+ test();
+ IF( st->localVAD || GT_16(st->lp_noise_fx,7680))
+ {
+ /*st->lt_mean_NB_fx = ALPHA_BWD * st->lt_mean_NB_fx + (1-ALPHA_BWD) * mean_NB;*/
+ L_tmp = L_mult(ALPHA_BWD_FX, st->lt_mean_NB_fx); /* Q15 * Q11 -> Q27 */
+ L_tmp = L_mac(L_tmp, 32768-ALPHA_BWD_FX, mean_NB); /* Q15 * Q11) -> L_mac(Q27, Q27) -> Q27*/
+ st->lt_mean_NB_fx = round_fx(L_tmp); /* Q11 (27-16) */
+
+ /*st->lt_mean_WB_fx = ALPHA_BWD * st->lt_mean_WB_fx + (1-ALPHA_BWD) * mean_WB;*/
+ L_tmp = L_mult(ALPHA_BWD_FX, st->lt_mean_WB_fx);
+ L_tmp = L_mac(L_tmp, 32768-ALPHA_BWD_FX, mean_WB);
+ st->lt_mean_WB_fx = round_fx(L_tmp);
+
+ /*st->lt_mean_SWB_fx = ALPHA_BWD * st->lt_mean_SWB_fx + (1-ALPHA_BWD) * mean_SWB;*/
+ L_tmp = L_mult(ALPHA_BWD_FX, st->lt_mean_SWB_fx);
+ L_tmp = L_mac(L_tmp, 32768-ALPHA_BWD_FX, mean_SWB);
+ st->lt_mean_SWB_fx = round_fx(L_tmp);
+
+
+
+ IF ( enerBuffer != NULL )
+ {
+ /*if( 0.9f * max_WB > BWD_LT_THRESH_FX * st->lt_mean_NB_fx )*/
+
+ /* optim: if( max_WB > (BWD_LT_THRESH_FX / 0.9) * st->lt_mean_NB_fx )*/
+
+ L_tmp = L_mult(3686,max_WB); /* (0.9 in Q12) x Q11 -> Q24*/
+
+ L_tmp1 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_NB_fx); /* Q15 x Q11 -> Q27 */
+ L_tmp1 = L_shl(L_tmp1, 24-27); /* Q27 -> Q24) */
+ L_tmp1 = L_sub(L_tmp, L_tmp1 );
+
+ IF( L_tmp1 > 0 )
+ {
+ /*if( 2.5f * max_WB > max_NB )*/
+ L_tmp = L_mult(10240,max_WB); /* 2.5 in Q12 x Q11 -> Q24 */
+ L_tmp1 = L_mult(max_NB, 4096); /* Q11 x (1 in Q12) -> Q24 */
+ IF( GT_32(L_tmp,L_tmp1)) /* Q24 */
+ {
+ st->count_WB_fx = add(st->count_WB_fx,1);
+ }
+ }
+ ELSE
+ {
+ /*if( 3.5f * mean_WB < mean_NB )*/
+ L_tmp = L_mult(14336,mean_WB); /* 3.5 in Q12 x Q11 -> Q24*/
+ L_tmp1 = L_mult(mean_NB,4096);
+ L_tmp = L_sub(L_tmp, L_tmp1);
+ IF( L_tmp < 0 )
+ {
+ st->count_WB_fx = sub(st->count_WB_fx, 1);
+ }
+ }
+
+ /*if( 0.83f * max_SWB > BWD_LT_THRESH_FX * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH_FX * st->lt_mean_NB_fx )*/
+ /* IF( L_msu( L_tmp,BWD_LT_THRESH_FX,st->lt_mean_WB_fx) > 0 && L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 )
+ {*/
+
+ L_tmp = L_mult(3400,max_SWB); /* (0.83 in Q12) x Q11 -> Q24*/
+ L_tmp1 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_WB_fx); /* Q15 x Q11 -> Q27 */
+ L_tmp1 = L_shl(L_tmp1, 24-27); /* Q27 -> Q24) */
+ L_tmp1 = L_sub(L_tmp, L_tmp1 );
+
+ L_tmp = L_mult( max_WB,4096);
+ L_tmp2 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_NB_fx); /* Q15 x Q11 -> Q27 */
+ L_tmp2 = L_shl(L_tmp2, 24-27); /* Q27 -> Q24) */
+ L_tmp2 = L_sub(L_tmp, L_tmp2 );
+
+ test();
+ IF(L_tmp1 > 0 && L_tmp2 > 0 )
+ {
+ /*if( 2 * max_SWB > max_WB )*/
+ L_tmp = L_mult(max_WB,4096);
+ L_tmp1 = L_mult(8192,max_SWB); /* 2.0 in Q12 x Q11 -> Q24*/
+ L_tmp1 = L_sub(L_tmp1, L_tmp); /* Q24 - (Q11 x (1 in Q12) ) = Q24 */
+ IF(L_tmp1 > 0 )
+ {
+ st->count_SWB_fx = add(st->count_SWB_fx, 1);
+ }
+ }
+ ELSE
+ {
+ /*if( 3 * mean_SWB < mean_WB )*/
+ L_tmp = L_mult(mean_WB,4096);
+ L_tmp1 = L_mult(12288,mean_SWB); /* 3.0 in Q12 x Q11 -> Q24*/
+ L_tmp1 = L_sub(L_tmp1,L_tmp); /* Q24 - (Q11 x (1 in Q12) ) = Q24 */
+ IF(L_tmp1 < 0 )
+ {
+ st->count_SWB_fx = sub(st->count_SWB_fx,1);
+ }
+ }
+ /*if( max_FB > BWD_LT_THRESH_FX * st->lt_mean_SWB_fx && 0.83f * max_SWB > BWD_LT_THRESH_FX * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH_FX * st->lt_mean_NB_fx )*/
+
+ L_tmp = L_mult(max_FB, 4096); /* Q11 x (1 in Q12) = Q24 */
+ L_tmp1 = L_mult(BWD_LT_THRESH_FX, st->lt_mean_SWB_fx); /* Q15 x Q11 -> Q27 */
+ L_tmp1 = L_shl(L_tmp1, 24-27); /* Q27 -> Q24) */
+ L_tmp1 = L_sub( L_tmp, L_tmp1); /* Q24 */
+
+ L_tmp = L_mult(max_SWB, 3400 ); /* (0.83 in Q12) x Q11) = Q24 */
+ L_tmp2 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_WB_fx); /* Q15 x Q11 -> Q27 */
+ L_tmp2 = L_shl(L_tmp2, 24-27); /* Q27 -> Q24) */
+ L_tmp2 = L_sub(L_tmp, L_tmp2 ); /* Q24 */
+
+ L_tmp = L_mult(max_WB,4096); /* Q11 x (1 in Q12) = Q24*/
+
+ L_tmp3 = L_mult(BWD_LT_THRESH_FX,st->lt_mean_NB_fx); /* Q15 x Q11 -> Q27 */
+ L_tmp3 = L_shl(L_tmp3, 24-27); /* Q27 -> Q24) */
+ L_tmp3 = L_sub(L_tmp, L_tmp3 );
+
+ test();
+ test();
+ IF(L_tmp1 > 0 && L_tmp2 > 0 && L_tmp3 > 0 )
+ {
+ /*if( 3 * max_FB > max_SWB )*/
+ L_tmp = L_mult( max_SWB,4096 ); /* Q11 x (1 in Q12) = Q24*/
+ L_tmp1 = L_mult(12288,max_FB); /* 3.0 in Q12 x Q11 -> Q24*/
+ L_tmp1 = L_sub(L_tmp1, L_tmp); /* Q24 */
+ IF(L_tmp1 > 0 )
+ {
+ st->count_FB_fx = add(st->count_FB_fx,1);
+ }
+ }
+ ELSE
+ {
+ /* if( 4.1f * mean_FB < mean_SWB )*/
+ L_tmp = L_mult(mean_SWB,4096); /* Q11 x (1 in Q12) = Q24 */
+ L_tmp1 = L_mult(16794,mean_FB); /* 4.1 in Q12 x Q11 -> Q24*/
+ L_tmp1 = L_sub(L_tmp1,L_tmp); /* Q24 */
+ IF(L_tmp1 < 0 )
+ {
+ st->count_FB_fx = sub(st->count_FB_fx,1);
+ }
+ }
+
+ }
+ ELSE /* DCT based detection */
+ {
+ /*if( max_WB > BWD_LT_THRESH * st->lt_mean_NB_fx )*/
+ IF( L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 )
+ {
+ /*if( 2 * max_WB > max_NB )*/
+ L_tmp = L_mult(8192,max_WB); /* 2.0 in Q12 x Q11 -> Q24*/
+ if( L_msu(L_tmp,max_NB,4096) > 0 )
+ {
+ st->count_WB_fx = add(st->count_WB_fx,1);
+ }
+ }
+ ELSE
+ {
+ /*if( 2.6f * mean_WB < mean_NB )*/
+ L_tmp = L_mult(10650,mean_WB); /* 2.6 in Q12 x Q11 -> Q24*/
+ L_tmp = L_msu(L_tmp,mean_NB,4096);
+ test();
+ test();
+ if( L_tmp < 0 && !(EQ_16(mean_WB,-1)&&EQ_16(mean_NB,-1)))
+ {
+ st->count_WB_fx = sub(st->count_WB_fx, 1);
+ }
+ }
+
+ test();
+ /*if( max_SWB > BWD_LT_THRESH * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH * st->lt_mean_NB_fx )*/
+ test();
+ IF( L_msu( L_deposit_h(max_SWB),BWD_LT_THRESH_FX,st->lt_mean_WB_fx) > 0 && L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 )
+ {
+ /*if( 2 * max_SWB > max_WB )*/
+ L_tmp = L_mult(8192,max_SWB); /* 2.0 in Q12 x Q11 -> Q24*/
+ if( L_msu(L_tmp,max_WB,4096) > 0 )
+ {
+ st->count_SWB_fx = add(st->count_SWB_fx,1);
+ }
+ }
+ ELSE
+ {
+ /*if( 3 * mean_SWB < mean_WB )*/
+ L_tmp = L_mult(12288,mean_SWB); /* 3.0 in Q12 x Q11 -> Q24*/
+ L_tmp = L_msu(L_tmp,mean_WB,4096);
+ test();
+ test();
+ if( L_tmp < 0 && !(EQ_16(mean_SWB,-1)&&EQ_16(mean_WB,-1)))
+ {
+ st->count_SWB_fx = sub(st->count_SWB_fx,1);
+ }
+ }
+
+ test();
+ test();
+ /*if( max_FB > BWD_LT_THRESH * st->lt_mean_SWB_fx && max_SWB > BWD_LT_THRESH * st->lt_mean_WB_fx && max_WB > BWD_LT_THRESH * st->lt_mean_NB_fx )*/
+ IF( L_msu( L_deposit_h(max_FB),BWD_LT_THRESH_FX,st->lt_mean_SWB_fx) > 0 && L_msu( L_deposit_h(max_SWB),BWD_LT_THRESH_FX,st->lt_mean_WB_fx) > 0 && L_msu( L_deposit_h(max_WB),BWD_LT_THRESH_FX,st->lt_mean_NB_fx) > 0 )
+ {
+ /*if( 2 * max_FB > max_SWB )*/
+ L_tmp = L_mult(8192,max_FB); /* 2.0 in Q12 x Q11 -> Q24*/
+ if( L_msu(L_tmp,max_SWB,4096) > 0 )
+ {
+ st->count_FB_fx = add(st->count_FB_fx,1);
+ }
+ }
+ ELSE
+ {
+ /*if( 3 * mean_FB < mean_SWB )*/
+ L_tmp = L_mult(12288,mean_FB); /* 3.0 in Q12 x Q11 -> Q24*/
+ test();
+ test();
+ if( L_msu(L_tmp,mean_SWB,4096) < 0 && !(EQ_16(mean_FB,-1)&&EQ_16(mean_SWB,-1)))
+ {
+ st->count_FB_fx = sub(st->count_FB_fx,1);
+ }
+ }
+ }
+
+ st->count_WB_fx = s_min(st->count_WB_fx,BWD_COUNT_MAX);
+ move16();
+ st->count_SWB_fx = s_min(st->count_SWB_fx,BWD_COUNT_MAX);
+ move16();
+ st->count_FB_fx = s_min(st->count_FB_fx,BWD_COUNT_MAX);
+ move16();
+ st->count_WB_fx = s_max(st->count_WB_fx,0);
+ move16();
+ st->count_SWB_fx = s_max(st->count_SWB_fx,0);
+ move16();
+ st->count_FB_fx = s_max(st->count_FB_fx,0);
+ move16();
+
+ /*---------------------------------------------------------------------*
+ * check against thresholds
+ * detect a band-width change
+ *---------------------------------------------------------------------*/
+
+ /* switching to a higher BW */
+ IF( EQ_16(st->last_input_bwidth_fx,NB))
+ {
+ IF( GT_16(st->count_WB_fx, bwd_count_wider_bw))
+ {
+ st->input_bwidth_fx = WB;
+ move16();
+ st->count_WB_fx = BWD_COUNT_MAX;
+ move16();
+
+ IF( GT_16(st->count_SWB_fx, bwd_count_wider_bw))
+ {
+ st->input_bwidth_fx = SWB;
+ move16();
+ st->count_SWB_fx = BWD_COUNT_MAX;
+ move16();
+
+ IF( GT_16(st->count_FB_fx, bwd_count_wider_bw))
+ {
+ st->input_bwidth_fx = FB;
+ move16();
+ st->count_FB_fx = BWD_COUNT_MAX;
+ move16();
+ }
+ }
+ }
+ }
+
+ test();
+ IF( EQ_16(st->last_input_bwidth_fx,WB)&>_32(st->input_Fs_fx,16000))
+ {
+ IF( GT_16(st->count_SWB_fx, bwd_count_wider_bw))
+ {
+ st->input_bwidth_fx = SWB;
+ move16();
+ st->count_SWB_fx = BWD_COUNT_MAX;
+ move16();
+
+ IF( GT_16(st->count_FB_fx, bwd_count_wider_bw))
+ {
+ st->input_bwidth_fx = FB;
+ move16();
+ st->count_FB_fx = BWD_COUNT_MAX;
+ move16();
+ }
+ }
+ }
+
+ test();
+ IF( EQ_16(st->last_input_bwidth_fx,SWB)&>_32(st->input_Fs_fx,32000))
+ {
+ IF( GT_16(st->count_FB_fx, bwd_count_wider_bw))
+ {
+ st->input_bwidth_fx = FB;
+ move16();
+ st->count_FB_fx = BWD_COUNT_MAX;
+ move16();
+ }
+ }
+
+ /* switching to a lower BW */
+ IF( EQ_16(st->last_input_bwidth_fx,FB))
+ {
+ IF( LT_16(st->count_FB_fx,10))
+ {
+ st->input_bwidth_fx = SWB;
+ move16();
+ st->count_FB_fx = 0;
+ move16();
+ }
+ IF( LT_16(st->count_SWB_fx,10))
+ {
+ st->input_bwidth_fx = WB;
+ move16();
+ st->count_SWB_fx = 0;
+ move16();
+ st->count_FB_fx = 0;
+ move16();
+ }
+ IF( LT_16(st->count_WB_fx,10))
+ {
+ st->input_bwidth_fx = NB;
+ move16();
+ st->count_WB_fx = 0;
+ move16();
+ st->count_SWB_fx = 0;
+ move16();
+ st->count_FB_fx = 0;
+ move16();
+ }
+ }
+
+ IF( EQ_16(st->last_input_bwidth_fx,SWB))
+ {
+ IF( LT_16(st->count_SWB_fx,10))
+ {
+ st->input_bwidth_fx = WB;
+ move16();
+ st->count_SWB_fx = 0;
+ move16();
+ st->count_FB_fx = 0;
+ move16();
+ }
+ IF( LT_16(st->count_WB_fx,10))
+ {
+ st->input_bwidth_fx = NB;
+ move16();
+ st->count_WB_fx = 0;
+ move16();
+ st->count_SWB_fx = 0;
+ move16();
+ st->count_FB_fx = 0;
+ move16();
+ }
+
+ }
+
+ IF( EQ_16(st->last_input_bwidth_fx,WB))
+ {
+ IF( LT_16(st->count_WB_fx,10))
+ {
+ st->input_bwidth_fx = NB;
+ move16();
+ st->count_WB_fx = 0;
+ move16();
+ st->count_SWB_fx = 0;
+ move16();
+ st->count_FB_fx = 0;
+ move16();
+ }
+ }
+ }
+ }
+
+
+ /* verify that maximum encoded bandwidth (specified on the command line) is not exceeded */
+ IF( GT_16(st->input_bwidth_fx,st->max_bwidth_fx))
+ {
+ st->input_bwidth_fx = st->max_bwidth_fx;
+ move16();
+ }
+ IF (EQ_16(st->element_mode, EVS_MONO) )
+ {
+ set_bw_fx(-1, -1, st, st->codec_mode);
+ }
+
+
+ return;
+}
+/*-------------------------------------------------------------------*
+ * set_bw_fx()
+ *
+ * Set and limit the encoded bandwidth
+ *-------------------------------------------------------------------*/
+
+void set_bw_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word32 element_brate, /* i : element bitrate */
+ Encoder_State_fx* st, /* i/o: Encoder State */
+ const Word16 codec_mode /* i : codec mode */
+)
+{
+ Word32 total_brate_fx, L_tmp;
+ /* initialization */
+ st->bwidth_fx = st->input_bwidth_fx;
+ move16();
+
+ /* Set and limit the encoded bandwidth */
+ IF(EQ_16(st->codec_mode, MODE1))
+ {
+
+ st->bwidth_fx = st->input_bwidth_fx;
+ move16();
+
+ total_brate_fx = L_add(st->total_brate_fx, 0);
+
+ /* change the encoded bandwidth, if not supported at particular bitrate */
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF (GT_16(element_mode, IVAS_SCE))
+ {
+ //PMT("this IVAS_SCE section has not been verified ")
+ IF (LT_32(element_brate, MIN_BRATE_SWB_STEREO))
+ {
+ st->bwidth_fx = WB;
+ move16();
+ }
+ ELSE
+ {
+ test();
+ IF (st->idchan == 0 || EQ_16(element_mode, IVAS_CPE_MDCT))
+ {
+ IF (GE_32(element_brate, MIN_BRATE_FB_STEREO))
+ {
+ st->bwidth_fx = s_min(st->bwidth_fx, FB);
+ }
+ ELSE
+ {
+ st->bwidth_fx = s_min(st->bwidth_fx, SWB);
+ }
+ st->bwidth_fx = s_max(st->bwidth_fx, WB);
+ }
+ ELSE
+ {
+ st->bwidth_fx = WB;
+ move16();
+ }
+ }
+ }
+ ELSE IF (EQ_16(element_mode, IVAS_SCE))
+ {
+ test();
+ IF ( LT_32(element_brate, MIN_BRATE_SWB_SCE) || LT_16(st->bwidth_fx, WB) )
+ {
+ st->bwidth_fx = WB;
+ move16();
+ }
+ ELSE IF (GT_16(st->bwidth_fx, SWB) && ((LT_32(element_brate, MIN_BRATE_FB_STEREO) && !st->is_ism_format) || (LT_32(element_brate, MIN_BRATE_FB_ISM) && st->is_ism_format)))
+ {
+ st->bwidth_fx = SWB;
+ move16();
+ }
+ ELSE IF (GT_32(element_brate, BWD_MAX_BRATE_WIDER_BW_ISM))
+ {
+ st->bwidth_fx = st->max_bwidth_fx; move16();
+ }
+ }
+ /* element_mode == EVS_MONO */
+ ELSE IF(LE_32(total_brate_fx, ACELP_9k60) && GT_16(st->bwidth_fx, WB) )
+ {
+ st->bwidth_fx = WB;
+ move16();
+ }
+ ELSE IF(GE_32(st->total_brate_fx, ACELP_13k20) && LE_32(st->total_brate_fx, ACELP_16k40) && GT_16(st->bwidth_fx, SWB))
+ {
+ st->bwidth_fx = SWB;
+ move16();
+ }
+ ELSE IF(GE_32(st->total_brate_fx, ACELP_32k) && LT_16(st->bwidth_fx, WB))
+ {
+ st->bwidth_fx = WB;
+ move16();
+ }
+ }
+ ELSE IF (EQ_16(codec_mode , MODE2) )
+ {
+ Word16 n, bits_frame_nominal;
+
+ UWord16 lsb;
+ Word16 tmpbandwidthMin;
+
+ Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */
+ bits_frame_nominal = extract_l(L_shr(L_tmp, 3)); /* Q0 */
+
+ FOR(n = 0; n < FRAME_SIZE_NB; n++)
+ {
+ IF(EQ_16(FrameSizeConfig[n].frame_bits,bits_frame_nominal))
+ {
+ BREAK;
+ }
+ }
+ if (n == FRAME_SIZE_NB)
+ {
+ assert(!"Bitrate not supported: not part of EVS");
+ }
+ tmpbandwidthMin = FrameSizeConfig[n].bandwidth_min;
+ if (EQ_16(st->rf_mode,1))
+ {
+ tmpbandwidthMin = WB;
+ }
+ st->bwidth_fx = s_max(s_min(st->input_bwidth_fx, FrameSizeConfig[n].bandwidth_max), tmpbandwidthMin);
+ }
+}
+#ifdef IVAS_CODE_BWD
+
+/*-------------------------------------------------------------------*
+ * set_bw_stereo()
+ *
+ * Set encoded bandwidth for stereo (CPE) channels
+ *-------------------------------------------------------------------*/
+
+void set_bw_stereo(
+ CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structures */
+)
+{
+ Encoder_State** sts = hCPE->hCoreCoder;
+
+ if (hCPE->element_brate > BWD_MAX_BRATE_WIDER_BW_MDCT)
+ {
+ sts[0]->bwidth = sts[0]->max_bwidth;
+ sts[1]->bwidth = sts[1]->max_bwidth;
+ }
+ else if (hCPE->element_mode == IVAS_CPE_MDCT)
+ {
+ /* ensure that both CPE channels have the same audio band-width */
+ if (sts[0]->input_bwidth == sts[1]->input_bwidth)
+ {
+ sts[0]->bwidth = sts[0]->input_bwidth;
+ sts[1]->bwidth = sts[0]->input_bwidth;
+ }
+ else
+ {
+ sts[0]->bwidth = max(sts[0]->input_bwidth, sts[1]->input_bwidth);
+ sts[1]->bwidth = max(sts[0]->input_bwidth, sts[1]->input_bwidth);
+ }
+ }
+
+ sts[0]->bwidth = max(sts[0]->bwidth, WB);
+ sts[1]->bwidth = max(sts[1]->bwidth, WB);
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * set_bw_mct()
+ *
+ * Set encoded bandwidth for MCT
+ *-------------------------------------------------------------------*/
+
+ /*! r: flag indicating whether the coded BW has changed */
+int16_t set_bw_mct(
+ CPE_ENC_HANDLE hCPE[MCT_MAX_BLOCKS], /* i/o: CPE encoder structures */
+ const int16_t nCPE /* i : number of CPEs */
+)
+{
+ Encoder_State* sts[MCT_MAX_CHANNELS];
+ int16_t ch, cpe_id;
+ int16_t mct_bwidth, last_mct_bwidth, bw_changed;
+
+ mct_bwidth = WB; /* minimum coded audio band-width */
+ last_mct_bwidth = hCPE[0]->hCoreCoder[0]->last_bwidth; /* supposes that LFE is not in the first channel */
+
+ for (cpe_id = 0; cpe_id < nCPE; cpe_id++)
+ {
+ for (ch = 0; ch < CPE_CHANNELS; ch++)
+ {
+ sts[ch] = hCPE[cpe_id]->hCoreCoder[ch];
+ if (st->mct_chan_mode == MCT_CHAN_MODE_IGNORE)
+ {
+ continue;
+ }
+
+ mct_bwidth = max(mct_bwidth, sts[ch]->input_bwidth);
+ }
+ }
+ for (cpe_id = 0; cpe_id < nCPE; cpe_id++)
+ {
+ if (hCPE[cpe_id]->element_brate > BWD_MAX_BRATE_WIDER_BW_MDCT)
+ {
+ mct_bwidth = max(mct_bwidth, hCPE[cpe_id]->hCoreCoder[0]->max_bwidth);
+ }
+ }
+ bw_changed = 0;
+ if (mct_bwidth != last_mct_bwidth)
+ {
+ bw_changed = 1;
+
+ for (cpe_id = 0; cpe_id < nCPE; cpe_id++)
+ {
+ for (ch = 0; ch < CPE_CHANNELS; ch++)
+ {
+ sts[ch] = hCPE[cpe_id]->hCoreCoder[ch];
+ sts[ch]->bwidth = mct_bwidth;
+ }
+ }
+ }
+
+ return bw_changed;
+}
+
+#endif
\ No newline at end of file
diff --git a/lib_enc/cng_enc_fx.c b/lib_enc/cng_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..d66280e385b8b36666d47f563ece6448accae15b
--- /dev/null
+++ b/lib_enc/cng_enc_fx.c
@@ -0,0 +1,1574 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_enc.h" /* Encoder static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+//#include "basop_mpy.h"
+
+#include
+/*---------------------------------------------------------------------*
+* Local constants
+*---------------------------------------------------------------------*/
+
+#define MAX_DELTA 1
+#define MIN_CNT 50 /* Minimum frame number before SID interval adaptation */
+#define INT_H 50
+#define INT_L 8
+
+/*---------------------------------------------------------------------*
+ * Local function prototypes
+ *---------------------------------------------------------------------*/
+static void shb_CNG_encod_fx(Encoder_State_fx *st_fx, const Word16 update_fx );
+static Word16 shb_DTX_fx(Encoder_State_fx *st_fx, const Word16 *shb_speech_fx, const Word16 *syn_12k8_16k );
+/*---------------------------------------------------------------------*
+* CNG_enc()
+*
+* Confort noise generation for the coder
+*---------------------------------------------------------------------*/
+void CNG_enc_fx(
+ Encoder_State_fx *st_fx,/* i/o: State structure */
+ Word16 Aq[], /* o : LP coefficients Q12 */
+ const Word16 *speech, /* i : pointer to current frame input speech buffer Q_new */
+ Word32 L_enr, /* i : residual energy from Levinson-Durbin Q6 */
+ const Word16* lsp_mid, /* i : mid frame LSPs Q15 */
+ Word16 *lsp_new, /* i/o: current frame ISPs Q15 */
+ Word16 *lsf_new, /* i/o: current frame ISFs Qlog2(2.56) */
+ Word16 *allow_cn_step, /* o : allow CN step Q0 */
+ Word16 Q_new, /* i : Q value of speech */
+ Word32 *q_env,
+ Word16 *sid_bw
+)
+{
+ Word16 enr_index;
+ Word16 i, j, ptr;
+ Word16 m1;
+ Word16 res[L_FRAME16k];
+ Word16 step_inv=0;
+ Word16 hi, lo;
+ Word16 maxl=0;
+ Word16 num_bits=0;
+ Word16 step=0;
+ Word16 *pt_res;
+ const Word16 *pt_sp;
+ Word16 enr;
+ Word32 L_tmp, L_ener;
+ Word16 k, tmp1;
+ Word16 weights;
+ Word16 sp_enr;
+ Word32 L_tmp1;
+ Word16 exp;
+ Word16 m = 0;
+ Word16 tmp[HO_HIST_SIZE*M];
+ Word16 ll, s_ptr;
+ Word16 tmpv, maxv, scale, att = 1;
+ Word16 lsf_tmp[M];
+ Word32 C[M];
+ Word32 max_val[2];
+ Word16 max_idx[2];
+ Word16 ftmp_fx;
+ Word16 lsp_tmp[M];
+ Word16 dev;
+ Word16 max_dev;
+ Word16 dist;
+ Word16 max_idx1[2]= {0,0};
+ Word16 fft_io[L_FRAME16k];
+ Word16 *ptR,*ptI;
+ Word32 enr1=0;
+ Word32 env[NUM_ENV_CNG];
+ Word32 min1;
+ Word16 min1_idx;
+ Word32 d;
+ Word16 res1[L_FRAME16k];
+ Word32 tmp_env[HO_HIST_SIZE*NUM_ENV_CNG];
+ Word16 fra;
+ Word16 temp_lo_fx, temp_hi_fx;
+ Word16 exp_pow;
+ Word16 force_cn_step=0;
+ Word16 tmp_loop;
+ Word16 st_lp_sp_enr;
+ DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+ st_lp_sp_enr = hTdCngEnc->lp_sp_enr_fx;
+ Word16 lp_ener_thr_scale;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ /* Temp variables for floating point functions */
+
+ lp_ener_thr_scale = 8; /* 4.0f*/ /*IVAS_CODE Q2 */
+ move16();
+ if (NE_16(st_fx->element_mode, EVS_MONO))
+ {
+ lp_ener_thr_scale = 7; /* 3.5f;*/
+ move16();
+ }
+ /*sp_enr = (float) log10( sum2_f( speech, L_frame )/L_frame + 0.1f )/ (float)log10(2.0f);*//*9.1 */
+ pt_sp = speech;
+ L_ener = L_deposit_l(1);
+ /* L_ener = L_add(L_shr(sum2_f_fx( speech, L_frame ), 8) , L_ener);*/
+ IF( EQ_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ FOR (j=0; j<128; j++)
+ {
+ L_tmp = L_mult0(*pt_sp, *pt_sp);
+ pt_sp++;
+ L_tmp = L_mac0(L_tmp, *pt_sp, *pt_sp);
+ pt_sp++;
+ L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* 2*Q_new + 1, divide by L_frame done here */
+ }
+ }
+ ELSE /* L_FRAME16k */
+ {
+ FOR (i=0; i<2; i++)
+ {
+ FOR (j=0; j<80; j++)
+ {
+ L_tmp = L_mult0(*pt_sp, *pt_sp);
+ pt_sp++;
+ L_tmp = L_mac0(L_tmp, *pt_sp, *pt_sp);
+ pt_sp++;
+ L_ener = L_add(L_ener, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*Q_new + 1, divide by L_frame done here */
+ }
+ }
+ }
+
+ hi = norm_l(L_ener);
+ lo = Log2_norm_lc(L_shl(L_ener, hi));
+ hi = sub(29, hi); /* log2 exp in Q2*Q_new */
+ hi = sub(hi, shl(Q_new, 1)); /* Q0 */
+ L_tmp = L_Comp(hi, lo); /* Q16 */
+ sp_enr = round_fx(L_shl(L_tmp, 8)); /* Q8 (16+8-16) */
+
+ if (sp_enr < 0)
+ {
+ sp_enr = 0;
+ move16();
+ }
+ test();
+ IF (hDtxEnc->first_CNG == 0 || hTdCngEnc->old_enr_index < 0 )
+ {
+ hTdCngEnc->lp_sp_enr_fx = sp_enr;
+ move16(); /* Q8 */
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ test();
+ IF( GT_32(st_fx->last_core_brate_fx, SID_2k40) && ( EQ_16( st_fx->last_core_fx, HQ_CORE ) || st_fx->hTdCngEnc->burst_ho_cnt > 0 ) && LT_16(hTdCngEnc->lp_sp_enr_fx, 1536) &&
+ GT_16(sub(sp_enr, hTdCngEnc->lp_sp_enr_fx), 1024) && GT_16(sp_enr, 1536) )
+ {
+ hTdCngEnc->lp_sp_enr_fx = sp_enr;
+ move16();
+ force_cn_step = 1;
+ move16();
+ }
+ ELSE
+ {
+ hTdCngEnc->lp_sp_enr_fx = round_fx(L_mac(L_mult(29491 /* 0.9, Q15 */,hTdCngEnc->lp_sp_enr_fx), 3277 /* 0.1, Q15 */,sp_enr)); /* Q8 (8+15+1-16) */
+ }
+ }
+ /* update the pointer to circular buffer of old LSP vectors */
+ hTdCngEnc->cng_hist_ptr = add(hTdCngEnc->cng_hist_ptr,1);
+ if(EQ_16(hTdCngEnc->cng_hist_ptr, DTX_HIST_SIZE))
+ {
+ hTdCngEnc->cng_hist_ptr = 0;
+ move16();
+ }
+
+ /* update the circular buffer of old LSP vectors with the new LSP vector */
+ Copy( lsp_new, &(hTdCngEnc->cng_lsp_hist_fx[(hTdCngEnc->cng_hist_ptr)*M]), M );
+
+ /*-----------------------------------------------------------------*
+ * Find CNG spectral envelope
+ * Find LSP median
+ *-----------------------------------------------------------------*/
+ test();
+ test();
+ IF( (EQ_32(st_fx->core_brate_fx, SID_2k40) || EQ_32(st_fx->core_brate_fx,SID_1k75)) && GE_16(hDtxEnc->cng_cnt,sub(hDtxEnc->cng_hist_size,1)))
+ {
+ set32_fx( max_val, 0, 2 );
+ set16_fx( max_idx, 0, 2 );
+
+ FOR( i=0; i< hDtxEnc->cng_hist_size; i++ )
+ {
+ IF ( EQ_16(st_fx->L_frame_fx,L_FRAME))
+ {
+ lsp2lsf_fx( &hTdCngEnc->cng_lsp_hist_fx[i*M], lsf_tmp, M, INT_FS_FX );
+ ftmp_fx = 964;
+ move16();/*QX2.56 */
+ tmpv = sub(16384,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */
+ L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */
+ }
+ ELSE
+ {
+ lsp2lsf_fx( &hTdCngEnc->cng_lsp_hist_fx[i*M], lsf_tmp, M, INT_FS_16k );
+ ftmp_fx = 1205;
+ move16();/*QX2.56 */
+ tmpv = sub(20480,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */
+ L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */
+ }
+
+ tmpv = sub(lsf_tmp[0],ftmp_fx); /*QX2.56 */
+ L_tmp = L_mac0(L_tmp,tmpv,tmpv); /*QX6.5536 */
+ FOR ( j=0; jcng_hist_size; j++ )
+ {
+ L_tmp = L_add(L_tmp,L_deposit_l(hTdCngEnc->cng_lsp_hist_fx[j*M+i])); /*Q15 */
+ }
+
+ L_tmp = L_sub(L_tmp,L_add(L_deposit_l(hTdCngEnc->cng_lsp_hist_fx[max_idx[0]*M+i]),L_deposit_l(hTdCngEnc->cng_lsp_hist_fx[max_idx[1]*M+i]))); /*Q15 */
+ tmpv= div_s(1,sub(hDtxEnc->cng_hist_size,2)); /*Q15 */
+ L_tmp = Mpy_32_16_1(L_tmp,tmpv); /*Q15 */
+ lsp_new[i] = extract_l(L_tmp); /*Q15 */
+ }
+ max_idx1[0] = max_idx[0];
+ move16();
+ max_idx1[1] = max_idx[1];
+ move16();
+ }
+
+ /*-----------------------------------------------------------------*
+ * Quantize CNG spectral envelope (only in SID frame)
+ * Quantize the LSF vector
+ *-----------------------------------------------------------------*/
+ *allow_cn_step = 0;
+ move16();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF( ((hDtxEnc->cng_cnt == 0) &&
+ GT_16(hTdCngEnc->lp_sp_enr_fx, 1536) &&
+ (LT_16(add(st_lp_sp_enr, 1024 /* 4.0, Q8 */), sp_enr)) &&
+ (hDtxEnc->first_CNG != 0) &&
+ (hTdCngEnc->old_enr_index >= 0) &&
+ (GT_32(st_fx->last_core_brate_fx, SID_2k40))) ||
+ EQ_16(force_cn_step, 1))
+ {
+ *allow_cn_step = 1;
+ move16();
+ }
+
+ /* Initialize the CNG spectral envelope in case of the very first CNG frame */
+ IF(hDtxEnc->first_CNG == 0)
+ {
+ Copy(st_fx->lsp_old_fx, hDtxEnc->lspCNG_fx, M);
+
+ /* Average the CNG spectral envelope in case of the very first CNG frame */
+ IF (NE_16(st_fx->element_mode, EVS_MONO))
+ {
+ FOR (i = 0; i < M; i++)
+ {
+ /*lsp_new[i] = 0.5f * (lsp_mid[i] + lsp_new[i]);*/
+ lsp_new[i] = mac_r(L_mult(lsp_mid[i], 16384), lsp_new[i], 16384);
+ move16();
+ }
+ }
+ }
+
+
+ test();
+ IF( EQ_32(st_fx->core_brate_fx, SID_2k40) || EQ_32(st_fx->core_brate_fx,SID_1k75))
+ {
+ /* LSF quantization */
+ IF ( st_fx->Opt_AMR_WB_fx != 0 )
+ {
+ isf_enc_amr_wb_fx( st_fx, lsf_new, lsp_new, 0);
+ }
+ ELSE
+ {
+#ifdef LSF_RE_USE_SECONDARY_CHANNEL
+ lsf_enc_fx(st_fx, lsf_new, lsp_new, NULL, NULL, 100, 0, 0, NULL, Q_new);
+#else
+ lsf_enc_fx( st_fx, lsf_new, lsp_new, NULL, NULL,100, 0, 0, Q_new );
+#endif
+ }
+ /* Reset CNG history if CNG frame length is changed */
+ test();
+ test();
+ if ( EQ_16(st_fx->bwidth_fx,WB) && hDtxEnc->first_CNG!=0 && NE_16(st_fx->L_frame_fx, hDtxEnc->last_CNG_L_frame))
+ {
+ hTdCngEnc->ho_hist_size = 0;
+ move16();
+ }
+ }
+ ELSE
+ {
+ /* Use old LSP vector */
+ Copy( st_fx->lsp_old_fx, lsp_new, M );
+ Copy( st_fx->lsf_old_fx, lsf_new, M );
+ }
+
+ /*---------------------------------------------------------------------*
+ * CNG spectral envelope update
+ * Find A(z) coefficients
+ *---------------------------------------------------------------------*/
+
+ IF( LE_32(st_fx->last_core_brate_fx, SID_2k40))
+ {
+ /* Reset hangover counter if not first SID period */
+ if( GT_32(st_fx->core_brate_fx,FRAME_NO_DATA))
+ {
+ hTdCngEnc->num_ho = 0;
+ move16();
+ }
+ /* Update LSPs if last SID energy not outlier or insufficient number of hangover frames */
+ test();
+ IF( LT_16(hTdCngEnc->num_ho,3) || LT_32(Mult_32_16(hTdCngEnc->Enew_fx,21845 /*1/1.5f, Q15*/), hTdCngEnc->lp_ener_fx))
+ {
+ FOR( i=0; ilspCNG_fx[i] = mac_r(L_mult(CNG_ISF_FACT_FX, hDtxEnc->lspCNG_fx[i]),32768-CNG_ISF_FACT_FX,lsp_new[i]);
+ move16(); /* Q15 (15+15+1-16) */
+ }
+ }
+ }
+ ELSE
+ {
+ /* Update CNG_mode if allowed */
+ test();
+ test();
+ test();
+ IF( EQ_16(st_fx->element_mode, EVS_MONO) && (( st_fx->Opt_AMR_WB_fx || EQ_16(st_fx->bwidth_fx,WB))
+ && ( !hDtxEnc->first_CNG || GE_16(hTdCngEnc->act_cnt2,MIN_ACT_CNG_UPD) ) ) )
+ {
+ IF (GT_32(hDtxEnc->last_active_brate, ACELP_16k40))
+ {
+ hDtxEnc->CNG_mode = -1;
+ move16();
+ }
+ ELSE
+ {
+ hDtxEnc->CNG_mode = get_cng_mode(hDtxEnc->last_active_brate);
+ }
+ }
+
+ /* If first sid after active burst update LSF history from circ buffer */
+ hTdCngEnc->burst_ho_cnt = s_min(hTdCngEnc->burst_ho_cnt, hTdCngEnc->ho_circ_size);
+ hTdCngEnc->act_cnt = 0;
+ move16();
+ s_ptr = add(sub(hTdCngEnc->ho_circ_ptr, hTdCngEnc->burst_ho_cnt),1);
+
+ if( s_ptr < 0 )
+ {
+ s_ptr = add(s_ptr, hTdCngEnc->ho_circ_size);
+ }
+
+ FOR( ll = hTdCngEnc->burst_ho_cnt; ll > 0; ll-- )
+ {
+ hTdCngEnc->ho_hist_ptr = add(hTdCngEnc->ho_hist_ptr,1);
+ if( EQ_16(hTdCngEnc->ho_hist_ptr, HO_HIST_SIZE))
+ {
+ hTdCngEnc->ho_hist_ptr = 0;
+ move16();
+ }
+
+ /* Conversion between 12.8k and 16k LSPs */
+ test();
+ test();
+ IF( EQ_16(st_fx->L_frame_fx,L_FRAME )&&EQ_16(hTdCngEnc->ho_16k_lsp[s_ptr],1))
+ {
+ /* Conversion from 16k LPSs to 12k8 */
+ lsp_convert_poly_fx( &(hTdCngEnc->ho_lsp_circ_fx[s_ptr*M]), st_fx->L_frame_fx, 0 );
+ }
+ ELSE IF ( EQ_16(st_fx->L_frame_fx,L_FRAME16k)&& hTdCngEnc->ho_16k_lsp[s_ptr]==0)
+ {
+ /* 16k LSPs already converted and stored, just copy to the other buffer */
+ Copy(&(hTdCngEnc->ho_lsp_circ2_fx[s_ptr*M]), &(hTdCngEnc->ho_lsp_circ_fx[s_ptr*M]), M );
+ }
+ /* update the circular buffers */
+ Copy(&(hTdCngEnc->ho_lsp_circ_fx[s_ptr*M]), &(hTdCngEnc->ho_lsp_hist_fx[hTdCngEnc->ho_hist_ptr*M]), M );
+ Copy32(&(hTdCngEnc->ho_ener_circ_fx[s_ptr]), &(hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr]), 1 );
+ hTdCngEnc->ho_sid_bw = L_shl(L_and(hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1);
+ Copy32(&(hTdCngEnc->ho_env_circ_fx[s_ptr*NUM_ENV_CNG]), &(hTdCngEnc->ho_env_hist_fx[hTdCngEnc->ho_hist_ptr*NUM_ENV_CNG]), NUM_ENV_CNG );
+
+ hTdCngEnc->ho_hist_size = add(hTdCngEnc->ho_hist_size,1);
+ if (GT_16(hTdCngEnc->ho_hist_size, HO_HIST_SIZE))
+ {
+ hTdCngEnc->ho_hist_size = HO_HIST_SIZE;
+ move16();
+ }
+
+ s_ptr = add(s_ptr,1);
+
+ if( EQ_16(s_ptr, hTdCngEnc->ho_circ_size))
+ {
+ s_ptr = 0;
+ move16();
+ }
+ }
+
+ IF(hTdCngEnc->burst_ho_cnt > 0)
+ {
+ /**allow_cn_step |= ( hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] > 4 * hTdCngEnc->lp_ener_fx ); */
+#if 1
+ /*allow_cn_step |= (hDtxEnc->first_CNG || st->element_mode == EVS_MONO) && (hTdCngEnc->ho_ener_hist[hTdCngEnc->ho_hist_ptr] > lp_ener_thr_scale * hTdCngEnc->lp_ener);*/
+ /* (hTdCngEnc->ho_ener_hist[hTdCngEnc->ho_hist_ptr] > lp_ener_thr_scale * hTdCngEnc->lp_ener); */
+ L_tmp1 = L_shr(hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr], 2);
+ IF(NE_16(lp_ener_thr_scale, 8))
+ {
+ L_tmp1 = L_add(L_tmp1, L_shr(hTdCngEnc->lp_ener_fx, 8));
+ }
+ L_tmp1 = L_sub(L_tmp1, hTdCngEnc->lp_ener_fx);
+#else
+ L_tmp1 = L_shr(hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr],2);
+ L_tmp1 = L_sub(L_tmp1,hTdCngEnc->lp_ener_fx);
+#endif
+ test();test();
+ IF((hDtxEnc->first_CNG > 0 || EQ_16(st_fx->element_mode, EVS_MONO)) && L_tmp1>0)
+ {
+ *allow_cn_step = s_or(*allow_cn_step,1);
+ }
+ }
+ test();
+ IF ( *allow_cn_step == 0 && hTdCngEnc->ho_hist_size > 0 )
+ {
+ /* Use average of energies below last energy */
+ ptr = hTdCngEnc->ho_hist_ptr;
+ move16();
+ Copy( &(hTdCngEnc->ho_lsp_hist_fx[ptr*M]), tmp, M );
+ m1 = 0;
+ move16();
+ IF( L_and(hTdCngEnc->ho_sid_bw, (Word32) 0x1) == 0 )
+ {
+ Copy32( &hTdCngEnc->ho_env_hist_fx[ptr*NUM_ENV_CNG], tmp_env, NUM_ENV_CNG );
+ m1 = 1;
+ move16();
+ }
+ L_enr = Mult_32_16(hTdCngEnc->ho_ener_hist_fx[ptr],W_DTX_HO_FX[0]) ;/* Q6+15-15->Q6 */
+
+ weights = W_DTX_HO_FX[0]; /* Q15 */
+
+ m = 1;
+ move16();
+ FOR( k=1; kho_hist_size; k++ )
+ {
+ ptr = sub(ptr,1);
+ if( ptr < 0 )
+ {
+ ptr = HO_HIST_SIZE - 1;
+ move16();
+ }
+
+ test();
+ IF ( LT_32(Mult_32_16(hTdCngEnc->ho_ener_hist_fx[ptr],ONE_OVER_BUF_H_NRG_FX),hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr])&&
+ GT_32(hTdCngEnc->ho_ener_hist_fx[ptr],Mult_32_16(hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr], BUF_L_NRG_FX)) )
+ {
+ /*enr += W_DTX_HO[k] * st_fx->ho_ener_hist[ptr]; */
+ L_tmp1 = Mult_32_16(hTdCngEnc->ho_ener_hist_fx[ptr],W_DTX_HO_FX[k]) ; /* Q6+15-15->Q6 */
+ L_enr = L_add(L_enr,L_tmp1); /* Q6 */
+
+ /*weights += W_DTX_HO[k]; */
+ weights = add( weights, W_DTX_HO_FX[k]); /* Q15 */
+
+ Copy( &hTdCngEnc->ho_lsp_hist_fx[ptr*M], &tmp[m*M], M );
+ IF( L_and(hTdCngEnc->ho_sid_bw, L_shl((Word32)0x1,k)) == 0 )
+ {
+ Copy32( &hTdCngEnc->ho_env_hist_fx[ptr*NUM_ENV_CNG], &tmp_env[m1*NUM_ENV_CNG], NUM_ENV_CNG );
+ m1 = add(m1,1);
+ }
+ m = add(m,1);
+ }
+ }
+
+ /*enr /= weights; */
+ exp = norm_s(weights);
+ tmp1 = div_s(shl(1,sub(14,exp)),weights); /* Q(15+14-exp-15) */
+ L_tmp1 = Mult_32_16(L_enr,tmp1); /* Q(14-exp+6-15)->Q(5-exp) */
+ L_enr = L_shl(L_tmp1,add(exp,1)); /* Q6 */
+
+ hTdCngEnc->lp_ener_fx = L_enr;
+ move32();/* Q6 */
+
+ set32_fx( max_val, 0, 2 );
+ set16_fx( max_idx, 0, 2 );
+
+ FOR( i=0; iL_frame_fx,L_FRAME))
+ {
+ lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_FX );
+ ftmp_fx = 964;
+ move16();/*QX2.56 */
+ tmpv = sub(16384,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */
+ L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */
+ }
+ ELSE
+ {
+ lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_16k );
+ ftmp_fx = 1205;
+ move16();/*QX2.56 */
+ tmpv = sub(20480,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */
+ L_tmp = L_mult0(tmpv,tmpv); /*QX6.5536 */
+ }
+
+ tmpv = sub(lsf_tmp[0],ftmp_fx); /*QX2.56 */
+ L_tmp = L_mac0(L_tmp,tmpv,tmpv); /*QX6.5536 */
+ FOR ( j=0; jlspCNG_fx[i] = lsp_tmp[i];
+ move16(); /*Q15 */
+ }
+ }
+ ELSE
+ {
+ FOR( i=0; ilspCNG_fx[i] = add(mult_r(26214,lsp_tmp[i]),mult_r(6554,lsp_new[i]));
+ move16();
+ }
+ }
+ IF( m1 > 0 )
+ {
+ FOR ( i=0; ilp_ener_fx; */
+ IF(EQ_16(m1,1))
+ {
+ L_tmp = L_sub(L_tmp,L_add(hTdCngEnc->lp_ener_fx,hTdCngEnc->lp_ener_fx));
+ }
+ ELSE
+ {
+ tmp1 = div_s(1,m1);
+ L_tmp = Mult_32_16(L_tmp,tmp1);
+ L_tmp = L_sub(L_tmp,L_add(hTdCngEnc->lp_ener_fx,hTdCngEnc->lp_ener_fx));
+ }
+
+ env[i] = L_tmp;
+ move32();
+ }
+ Copy32(env, hTdCngEnc->lp_env_fx, NUM_ENV_CNG);
+ }
+ }
+ ELSE
+ {
+ Copy( lsp_new, hDtxEnc->lspCNG_fx, M ); /* use newly analyzed ISFs */
+ }
+ }
+ IF ( st_fx->Opt_AMR_WB_fx != 0 )
+ {
+ E_LPC_f_isp_a_conversion(hDtxEnc->lspCNG_fx, Aq, M );
+ }
+ ELSE
+ {
+ E_LPC_f_lsp_a_conversion(hDtxEnc->lspCNG_fx, Aq, M ); /* Find A(z) (not interpolated) */
+ }
+
+ tmp_loop = shr(st_fx->L_frame_fx,6);
+ FOR( i=1; iL_frame_fx, 0);
+ Copy(res, res1, st_fx->L_frame_fx);
+ test();
+ IF (EQ_16(st_fx->element_mode, IVAS_CPE_DFT) || EQ_16(st_fx->element_mode, IVAS_CPE_TD))
+ {
+ //PMT("Code to be completed")
+#ifdef IVAS_CODE
+ att = powf(10.0f, hTdCngEnc->CNG_att / 20.0f);
+ v_multc(res1, att, res1, st->L_frame);
+#endif
+ }
+ ELSE IF( NE_16(st_fx->bwidth_fx,NB))
+ {
+ test();
+ IF( EQ_16(st_fx->bwidth_fx,WB) && hDtxEnc->CNG_mode>=0)
+ {
+ ftmp_fx = HO_ATT_FX[hDtxEnc->CNG_mode];
+ }
+ ELSE
+ {
+ ftmp_fx = 19661;
+ move16();
+ }
+
+ att = mult(ftmp_fx,5461);/* Q15 */
+ L_tmp = L_mult(att,8);/* Q16 */
+ tmp1 = extract_l(L_shr(L_tmp,2));/* Q14 */
+ tmp1 = add(16384,tmp1);
+ att = div_s(16374,tmp1); /* Q15 */
+
+ att = s_max(att, ftmp_fx);
+ FOR( i = 0; i < st_fx->L_frame_fx; i++ )
+ {
+ /*res1[i] *= att;*/
+ res1[i] = mult(res1[i],att);
+ move16();/* Q_new */
+ }
+ att = shr(att,7);/* Q8 */
+ }
+
+ /* calculate the spectrum of residual signal */
+ Copy(res1, fft_io, st_fx->L_frame_fx);
+
+ IF ( EQ_16(st_fx->L_frame_fx,L_FRAME16k))
+ {
+ modify_Fs_fx( fft_io, L_FRAME16k, 16000, fft_io, 12800, hTdCngEnc->exc_mem2_fx,0);
+ }
+
+ fft_rel_fx(fft_io, L_FFT, LOG2_L_FFT);
+ ptR = &fft_io[1];
+ ptI = &fft_io[L_FFT-1];
+ FOR ( i=0; icng_res_env_fx[(hTdCngEnc->cng_hist_ptr)*NUM_ENV_CNG]), NUM_ENV_CNG );
+
+ /* calculate the residual signal energy */
+ /*enr = dotp( res, res, L_frame ) / L_frame; */
+ maxv = 0;
+ move16();
+ FOR(i = 0; i < st_fx->L_frame_fx; i++)
+ {
+ maxv = s_max(maxv, abs_s(res[i]));
+ }
+ scale = norm_s(maxv);
+ pt_res = res;
+ L_ener = L_deposit_l(1);
+ IF( EQ_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ FOR (j=0; j<128; j++)
+ {
+ tmpv = shl(*pt_res,scale);
+ L_tmp = L_mult0(tmpv, tmpv);
+ pt_res++;
+ tmpv = shl(*pt_res,scale);
+ L_tmp = L_mac0(L_tmp, tmpv, tmpv); /* 2*(Q_new+scale) */
+ pt_res++;
+ L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* 2*(Q_new+scale)+1, divide by L_frame done here */
+ }
+ }
+ ELSE /* L_FRAME16k */
+ {
+ FOR (j=0; j<160; j++)
+ {
+ tmpv = shl(*pt_res,scale);
+ L_tmp = L_mult0(tmpv, tmpv);
+ pt_res++;
+ tmpv = shl(*pt_res,scale);
+ L_tmp = L_mac0(L_tmp, tmpv, tmpv); /* 2*(Q_new+scale) */
+ pt_res++;
+ L_ener = L_add(L_ener, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */
+ }
+ }
+ /* convert log2 of residual signal energy */
+ /*enr = (float)log10( enr + 0.1f ) / (float)log10( 2.0f ); */
+ hi = norm_l(L_ener);
+ lo = Log2_norm_lc(L_shl(L_ener, hi));
+ hi = sub(29, hi); /* log2 exp in Q2*(Q_new+scale) */
+ hi = sub(hi, shl(add(Q_new,scale), 1)); /* Q0 */
+ L_tmp = L_Comp(hi, lo); /* Q16 */
+ enr = round_fx(L_shl(L_tmp, 8)); /* Q8 (16+8-16) */
+
+ /* update the circular buffer of old energies */
+ hTdCngEnc->cng_ener_hist_fx[hTdCngEnc->cng_hist_ptr] = enr;
+ move16(); /* Q8 */
+
+ /*-----------------------------------------------------------------*
+ * Quantize residual signal energy (only in SID frame)
+ *-----------------------------------------------------------------*/
+ test();
+ IF( EQ_32(st_fx->core_brate_fx, SID_2k40)||EQ_32(st_fx->core_brate_fx,SID_1k75))
+ {
+ IF( GE_16(hDtxEnc->cng_cnt,sub(hDtxEnc->cng_hist_size,1)))
+ {
+ /* average the envelope except outliers */
+ FOR ( i=0; icng_hist_size; j++ )
+ {
+ L_tmp1 = L_add(L_tmp1,hTdCngEnc->cng_res_env_fx[j*NUM_ENV_CNG+i]);
+ }
+ L_tmp = L_add(hTdCngEnc->cng_res_env_fx[max_idx1[0]*NUM_ENV_CNG+i],hTdCngEnc->cng_res_env_fx[max_idx1[1]*NUM_ENV_CNG+i]);
+ L_tmp1 = L_sub(L_tmp1,L_tmp);
+
+ /* env[i] /= (float)(st_fx->cng_hist_size - 2); */
+ tmp1 = sub(hDtxEnc->cng_hist_size,2);
+ IF(GT_16(tmp1,1))
+ {
+ tmp1 = div_s(1,tmp1);
+ L_tmp1 = Mult_32_16(L_tmp1,tmp1);
+ }
+
+ env[i] = L_tmp1;
+ move32();
+ }
+ /* compute average excitation energy */
+ L_tmp = L_deposit_l(0);
+ ptr = hTdCngEnc->cng_hist_ptr;
+ move16();
+
+ FOR (k=0; k< hDtxEnc->cng_hist_size; k++)
+ {
+ /* enr += W_HIST[k]*cng_ener_hist[ptr] */
+ L_tmp = L_mac0(L_tmp, W_HIST_FX[k], hTdCngEnc->cng_ener_hist_fx[ptr]); /* Q24 (8+16) */
+ ptr = sub(ptr, 1);
+ if (ptr < 0) /* check for circular pointer */
+ {
+ ptr = DTX_HIST_SIZE - 1;
+ move16();
+ }
+ }
+ /*-----------------------------------------------------------
+ * here we want to divide L_tmp by the sum
+ * of all the coefs used W_HIST[0..cng_hist_size-1]
+ * The table W_HIST_S already contains the inverted sum.
+ * That is
+ * W_HIST_S[k] 1
+ * ------------- = ---------------------------
+ * 4096 W_HIST[0] + ... + W_HIST[k]
+ *
+ * 1 / Sum(W_HIST[0..k]) is always > 1 since the sum
+ * of the coefs 0..k is always < 1 but > 0
+ * enr is in Q8 since the history buffer constains Q8 energies
+ *-----------------------------------------------------------*/
+ /*L_tmp = Mpy_32_16_1(L_tmp, W_HIST_S_FX[k-1]); */ /* normalize average value */
+ L_tmp = Mult_32_16(L_tmp, W_HIST_S_FX[k-1]); /* Q21 (24+12+1-16) */
+ L_tmp = L_shl(L_tmp, 3); /* Q24 */
+ enr = round_fx(L_tmp); /* Q8 */
+ }
+ /* decrease the energy in case of WB input */
+ IF ( EQ_16(st_fx->element_mode, IVAS_SCE) || EQ_16(st_fx->element_mode, IVAS_CPE_DFT))
+ {
+ //PMT("CNG IVAS_SCE and IVAS_CPE_DFT code missing")
+ //IVAS_CODE
+ //enr += hTdCngEnc->CNG_att * FAC_LOG2 / 10.0f;
+ }
+ ELSE IF( NE_16(st_fx->bwidth_fx, NB))
+ {
+ IF( EQ_16(st_fx->bwidth_fx,WB))
+ {
+ IF(hDtxEnc->CNG_mode >= 0 )
+ {
+ /* Bitrate adapted attenuation */
+ att = ENR_ATT_fx[hDtxEnc->CNG_mode];
+ move16();
+ }
+ ELSE
+ {
+ /* Use least attenuation for higher bitrates */
+ att = ENR_ATT_fx[4];
+ move16();
+ }
+ }
+ ELSE
+ {
+ att = 384;
+ move16();/*Q8*/
+ }
+ enr = sub(enr, att );
+ }
+ /* intialize the energy quantization parameters */
+ IF( st_fx->Opt_AMR_WB_fx == 0 )
+ {
+ step = STEP_SID_FX;
+ move16();
+ step_inv = ISTEP_SID_FX;
+ move16();
+ maxl = 127;
+ move16();
+ num_bits = 7;
+ move16();
+ }
+ ELSE
+ {
+ step = STEP_AMR_WB_SID_FX;
+ move16();
+ step_inv = ISTEP_AMR_WB_SID_FX;
+ move16();
+ maxl = 63;
+ move16();
+ num_bits = 6;
+ move16();
+ }
+
+ /* calculate the energy quantization index */
+ enr_index = add(enr, 512 /* Q8(2.0) */); /* enr + 2.0 */
+ enr_index = extract_l(L_shr(L_mult0(enr_index, step), 12+8)); /* Q0 (8+12-(8+12)) */
+
+ /* limit the energy quantization index */
+ enr_index = s_min(enr_index, maxl);
+ enr_index = s_max(enr_index, 0);
+
+ /* allow only slow energy increase */
+ test();
+ IF( hTdCngEnc->old_enr_index >= 0 && GT_16(enr_index, add(hTdCngEnc->old_enr_index, MAX_DELTA)))
+ {
+ IF( *allow_cn_step != 0 )
+ {
+ tmp1 = mult(27853 /* Q15(0.85) */,sub(enr_index,hTdCngEnc->old_enr_index));
+ enr_index = add(hTdCngEnc->old_enr_index,tmp1);
+ }
+ ELSE
+ {
+ enr_index = add(hTdCngEnc->old_enr_index, MAX_DELTA);
+ }
+ }
+ hTdCngEnc->old_enr_index = enr_index;
+ move16();
+
+ push_indice_fx( hBstr, IND_ENERGY, enr_index, num_bits );
+ if ( enr_index == 0 )
+ {
+ enr_index = -5;
+ move16();
+ }
+ /* Find quantized energy */
+ /* *Enew = (float)enr_index / step - 2.0 */
+ /* *Enew = (float)pow(2.0, *Enew) */
+ L_tmp = L_mult(enr_index, step_inv); /* Q16(0+15+1) */
+ /* substract by 2 not done to leave Energy in Q2 */
+ lo = L_Extract_lc(L_tmp, &hi);
+ hTdCngEnc->Enew_fx = Pow2(add(hi, 4), lo); /* Q6 */
+ IF ( EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ /* enr1 = (float)log10( st->Enew*L_frame + 0.1f ) / (float)log10( 2.0f );*/
+ exp = norm_l(hTdCngEnc->Enew_fx);
+ L_tmp = L_shl(hTdCngEnc->Enew_fx,exp); /*Q(exp+6) */
+ L_tmp = Mult_32_16(L_tmp,shl(st_fx->L_frame_fx,5));/* Q(exp+6+5-15=exp-4) */
+ L_tmp = L_shr(L_tmp,sub(exp,10)); /* Q6 */
+
+ exp = norm_l(L_tmp);
+ fra = Log2_norm_lc(L_shl(L_tmp,exp));
+ exp = sub(sub(30,exp),6);
+ L_tmp = L_Comp(exp,fra);
+ enr1 = L_shr(L_tmp,10);/* Q6 */
+
+ FOR ( i=0; iEnew;*/
+ L_tmp1 = L_add(env[i], 0);
+ L_tmp = L_add(hTdCngEnc->Enew_fx,hTdCngEnc->Enew_fx);
+ L_tmp1 = L_sub(L_tmp1,L_tmp); /*Q6*/
+
+ IF ( L_tmp1 < 0 )
+ {
+ L_tmp1 = L_deposit_l(6); /* (0.1)Q6 */
+ }
+ /* env[i] = (float)log10( env[i] + 0.1f ) / (float)log10( 2.0f ); */
+ exp = norm_l(L_tmp1);
+ fra = Log2_norm_lc(L_shl(L_tmp1,exp));
+ exp = sub(sub(30,exp),6);
+ L_tmp = L_Comp(exp,fra);
+ L_tmp1 = L_shr(L_tmp,10); /* Q6 */
+
+ L_tmp = L_shr(L_deposit_l(att),2);/* Q6 */
+ L_tmp1 = L_sub(L_tmp1,L_tmp);
+
+ IF ( L_tmp1 < 0 )
+ {
+ L_tmp1 = L_deposit_l(0);
+ }
+
+ L_tmp1 = L_sub(enr1,L_tmp1);
+
+ env[i] = L_tmp1;
+ move32();
+ }
+
+ /* codebook search */
+ min1 = L_add(1310588928, 0); /* Q17 */
+ min1_idx = 0;
+ move16();
+
+ FOR ( i=0; i<64; i++ )
+ {
+ d = L_deposit_l(0);
+ FOR ( j=0; jEnew_fx,21845 /*1/1.5f, Q15*/), hTdCngEnc->lp_ener_fx))
+ {
+ /* update the pointer to circular buffer of old LSP vectors */
+ hTdCngEnc->ho_hist_ptr = add(hTdCngEnc->ho_hist_ptr, 1);
+ if( EQ_16(hTdCngEnc->ho_hist_ptr,HO_HIST_SIZE))
+ {
+ hTdCngEnc->ho_hist_ptr = 0;
+ move16();
+ }
+
+ /* update the circular buffer of old LSP vectors with the new LSP vector */
+ Copy( lsp_new, &(hTdCngEnc->ho_lsp_hist_fx[(hTdCngEnc->ho_hist_ptr)*M]), M );
+
+ /* update the hangover energy buffer */
+ hTdCngEnc->ho_ener_hist_fx[hTdCngEnc->ho_hist_ptr] = hTdCngEnc->Enew_fx;
+ move32();
+ IF ( EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ FOR ( i=0; iEnew;*/
+ L_tmp = L_sub(enr1,q_env[i]);/* Q6 */
+ L_tmp = L_shl(L_tmp, 10);/* 16 */
+ temp_lo_fx = L_Extract_lc(L_tmp, &temp_hi_fx);
+
+ exp_pow = sub(14, temp_hi_fx);
+ L_tmp = Pow2(14, temp_lo_fx); /* Qexp_pow */
+ env[i] = L_shl(L_tmp, sub(6, exp_pow));
+ move32(); /* Q6 */
+ L_tmp = L_add(hTdCngEnc->Enew_fx,hTdCngEnc->Enew_fx);
+ env[i] = L_add(env[i],L_tmp);
+ move32();/* Q6 */
+ }
+ Copy32( env, &(hTdCngEnc->ho_env_hist_fx[(hTdCngEnc->ho_hist_ptr)*NUM_ENV_CNG]), NUM_ENV_CNG );
+ }
+ hTdCngEnc->ho_hist_size = add(hTdCngEnc->ho_hist_size,1);
+ if( GT_16(hTdCngEnc->ho_hist_size,HO_HIST_SIZE))
+ {
+ hTdCngEnc->ho_hist_size = HO_HIST_SIZE;
+ move16();
+ }
+ }
+ }
+ /* dithering bit for AMR-WB IO mode is always set to 0 */
+ IF( EQ_32(st_fx->core_brate_fx, SID_1k75))
+ {
+ push_indice_fx( hBstr, IND_DITHERING, 0, 1 );
+ }
+ IF ( EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ IF(EQ_16(st_fx->L_frame_fx, L_FRAME16k))
+ {
+ push_indice_fx( hBstr, IND_ACELP_16KHZ, 1, 1 );
+ }
+ ELSE
+ {
+ push_indice_fx( hBstr, IND_ACELP_16KHZ, 0, 1 );
+ }
+
+ push_indice_fx( hBstr, IND_CNG_HO, s_min(hTdCngEnc->burst_ho_cnt, 7 ), 3 );
+ hTdCngEnc->num_ho = m;
+ move16();
+ push_indice_fx( hBstr, IND_SID_TYPE, 0, 1 );
+
+ IF ( LT_32(st_fx->input_Fs_fx, 32000) && NE_16(st_fx->element_mode, IVAS_CPE_DFT))
+ {
+ push_indice_fx( hBstr, IND_SID_BW, 0, 1 );
+ *sid_bw = 0;
+ move16();
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Updates
+ *-----------------------------------------------------------------*/
+ /* update the SID frames counter */
+ test();
+ IF( EQ_32(st_fx->core_brate_fx, SID_2k40)||EQ_32(st_fx->core_brate_fx,SID_1k75))
+ {
+ hDtxEnc->cng_cnt = 0;
+ move16();
+ hTdCngEnc->cng_hist_ptr = -1;
+ move16();
+ /* update frame length memory */
+ hDtxEnc->last_CNG_L_frame = st_fx->L_frame_fx;
+ move16();
+ }
+ ELSE
+ {
+ hDtxEnc->cng_cnt = add(hDtxEnc->cng_cnt,1);
+ }
+
+ return;
+}
+/*---------------------------------------------------------------------*
+ * swb_CNG_enc()
+ *
+ * SWB DTX/CNG encoding
+ *---------------------------------------------------------------------*/
+void swb_CNG_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: State structure */
+ const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz (Q0) */
+ const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz (st_fx->Q_syn = 0) */
+)
+{
+ Word16 shb_SID_updt_fx=0;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+
+ test();
+ IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)||st_fx->core_brate_fx==FRAME_NO_DATA)
+ {
+ IF (EQ_16(st_fx->cng_type_fx,LP_CNG))
+ {
+ IF (GE_32(st_fx->input_Fs_fx, L_FRAME32k * FRAMES_PER_SEC))
+ {
+ /* decide if SHB SID encoding or not */
+ shb_SID_updt_fx = shb_DTX_fx(st_fx, shb_speech_fx, syn_12k8_16k_fx);
+
+ /* SHB CNG encoding */
+ shb_CNG_encod_fx(st_fx, shb_SID_updt_fx);
+ }
+ ELSE IF (EQ_16(st_fx->element_mode, IVAS_CPE_DFT) && EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ //PMT("CNG IVAS_CPE_DFT code not implemented")
+#ifdef IVAS_CODE
+ /* LF-boost not used in DFT-stereo, instead the bandwidth is transmitted */
+ delete_indice(st->hBstr, IND_CNG_ENV1);
+ push_indice(st->hBstr, IND_BWIDTH, st->bwidth, 2);
+ push_indice(st->hBstr, IND_UNUSED, 0, 4);
+ push_indice(st->hBstr, IND_SID_BW, 1, 1);
+#endif
+ }
+ }
+ hTdCngEnc->last_vad = 0;
+ move16();
+ }
+ ELSE
+ {
+ hTdCngEnc->last_vad = 1;
+ move16();
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * shb_CNG_encod()
+ *
+ * SID parameters encoding for SHB signal
+ *---------------------------------------------------------------------*/
+static void shb_CNG_encod_fx(
+ Encoder_State_fx *st_fx, /* i/o: State structure */
+ const Word16 update_fx /* i : SID update flag */
+)
+{
+ Word16 idx_ener_fx;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+#ifdef IVAS_CODE
+ Word16 ener_mid_dec_thr;
+#endif
+
+ idx_ener_fx = 0;
+ move16();
+ IF ( EQ_16(update_fx, 1))
+ {
+ /* SHB energy quantization */
+ IF (EQ_16(st_fx->element_mode, EVS_MONO))
+ {
+ idx_ener_fx = shr(add(mult(hTdCngEnc->mov_shb_cng_ener_fx, 9797), 1510), 8); /* Q0 */
+ }
+ ELSE
+ {
+ /*idx_ener = (int16_t)(0.7f * (0.1f * st->hTdCngEnc->mov_shb_cng_ener / (float)log10(2.0f) + 6.0f) + 0.5f);*/
+ //PMT("shb_CNG_encod_fx quantization in missing")
+#if 0
+ idx_ener_fx = shr(add(mult(hTdCngEnc->mov_shb_cng_ener_fx, 9797), 1510), 8); /* Q0 */
+#endif
+ }
+
+ if ( LT_16(st_fx->bwidth_fx, SWB))
+ {
+ idx_ener_fx = 0;
+ move16();
+ }
+
+ IF ( GT_16(idx_ener_fx, 15))
+ {
+ idx_ener_fx = 15;
+ move16();
+ }
+ ELSE
+ {
+ idx_ener_fx = s_max(idx_ener_fx,0);
+ }
+#ifdef IVAS_CODE
+ /* prevent toggling of idx_ener by adding small dead-zone interval around decision thresholds */
+ if (st->element_mode != EVS_MONO)
+ {
+ if (abs(idx_ener - st->hTdCngEnc->last_idx_ener) == 1)
+ {
+ ener_mid_dec_thr = 0.5f * ((st->hTdCngEnc->last_idx_ener / 0.7f - 6.0f) / 0.1f) * (float)log10(2.0f);
+ ener_mid_dec_thr += 0.5f * ((idx_ener / 0.7f - 6.0f) / 0.1f) * (float)log10(2.0f);
+
+ if (fabs(st->hTdCngEnc->mov_shb_cng_ener - ener_mid_dec_thr) / ener_mid_dec_thr < ENER_MID_DEAD_ZONE)
+ {
+ idx_ener = st->hTdCngEnc->last_idx_ener;
+ }
+ }
+ }
+
+ st->hTdCngEnc->last_idx_ener = idx_ener;
+#endif
+ push_indice_fx( hBstr, IND_SHB_CNG_GAIN, idx_ener_fx, 4);
+ push_indice_fx( hBstr, IND_SID_BW, 1, 1 );
+#ifndef IVAS_CODE
+ hBstr->nb_bits_tot_fx = sub(hBstr->nb_bits_tot_fx, hBstr->ind_list_fx[IND_CNG_ENV1].nb_bits);
+ hBstr->ind_list_fx[IND_CNG_ENV1].nb_bits = -1;
+#else
+ delete_indice(hBstr, IND_CNG_ENV1);
+#endif
+ move16();
+#ifdef IVAS_CODE
+ if (st->element_mode == IVAS_CPE_DFT)
+ {
+ push_indice(st->hBstr, IND_BWIDTH, st->bwidth, 2);
+ }
+ else
+#endif
+ {
+ push_indice_fx(hBstr, IND_UNUSED, 0, 2);
+ }
+ hTdCngEnc->ho_sid_bw = L_shl(L_and(hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1);
+ hTdCngEnc->ho_sid_bw = L_or(hTdCngEnc->ho_sid_bw, 0x1L);
+ }
+ ELSE
+ {
+ IF ( EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ hTdCngEnc->ho_sid_bw = L_shl(L_and(hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1);
+ push_indice_fx( hBstr, IND_SID_BW, 0, 1 );
+ }
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+* shb_DTX()
+*
+* Decide if encoding SHB SID or not
+*---------------------------------------------------------------------*/
+static Word16 shb_DTX_fx(
+ Encoder_State_fx *st_fx, /* i/o: State structure */
+ const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz (Q0) */
+ const Word16 *syn_12k8_16k /* i : ACELP core synthesis at 12.8kHz or 16kHz (st_fx->Q_syn = 0) */
+)
+{
+ Word16 i;
+ Word16 update_fx;
+ Word16 shb_old_speech_fx[(ACELP_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/4];
+ Word16 *shb_new_speech_fx;
+ Word32 wb_ener_fx;
+ Word32 shb_ener_fx;
+ Word16 log_wb_ener_fx;
+ Word16 log_shb_ener_fx;
+ Word16 tmp;
+ Word16 exp;
+ Word16 fra;
+ Word16 att; /*Q8*/
+ Word16 allow_cn_step_fx=0;
+ DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+ TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ shb_new_speech_fx = shb_old_speech_fx + (ACELP_LOOK_12k8 + L_SUBFR) * 5/4;
+ Copy(hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, (ACELP_LOOK_12k8 + L_SUBFR) * 5/4 );
+ Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k );
+ Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, (ACELP_LOOK_12k8 + L_SUBFR) * 5/4 );
+
+ shb_ener_fx = L_deposit_l(0);
+ FOR ( i=0; iL_frame_fx; i++ )
+ {
+#ifdef BASOP_NOGLOB
+ wb_ener_fx = L_mac_o(wb_ener_fx, syn_12k8_16k[i], syn_12k8_16k[i], &Overflow);
+#else
+ wb_ener_fx = L_mac(wb_ener_fx, syn_12k8_16k[i], syn_12k8_16k[i]);
+#endif
+ }
+
+ wb_ener_fx = L_add(Mpy_32_16_1(wb_ener_fx, 128), 1); /* 128 in Q15, wb_ener_fx in Q1 */
+
+ exp = norm_l(wb_ener_fx);
+ fra = Log2_norm_lc(L_shl(wb_ener_fx, exp));
+ exp = sub(30-1, exp);
+ wb_ener_fx = Mpy_32_16(exp, fra, LG10);
+#ifdef BASOP_NOGLOB
+ log_wb_ener_fx = round_fx_o(L_shl_o(wb_ener_fx, 10, &Overflow), &Overflow); /* log_wb_ener_fx in Q8 */
+#else
+ log_wb_ener_fx = round_fx(L_shl(wb_ener_fx, 10)); /* log_wb_ener_fx in Q8 */
+#endif
+ exp = norm_l(shb_ener_fx);
+ fra = Log2_norm_lc(L_shl(shb_ener_fx, exp));
+ exp = sub(30-1, exp);
+ shb_ener_fx = Mpy_32_16(exp, fra, LG10);
+
+ test();
+ IF (EQ_16(st_fx->element_mode, IVAS_SCE) || EQ_16(st_fx->element_mode, IVAS_CPE_DFT))
+ {
+ att = 0;
+ move16();
+ //PMT("apply_scale is not implemented")
+#if 0
+ apply_scale(&att, st->hFdCngEnc->hFdCngCom->CngBandwidth, st->hFdCngEnc->hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO);
+#endif
+ }
+ else
+ {
+ att = 1664; /*6.5 in Q8*/
+ move16();
+ }
+
+#ifdef BASOP_NOGLOB
+ log_shb_ener_fx = sub_o(round_fx_o(L_shl_o(shb_ener_fx, 10, &Overflow), &Overflow), att, &Overflow); /* log_shb_ener_fx in Q8 */
+#else
+ log_shb_ener_fx = sub(round_fx(L_shl(shb_ener_fx, 10)), att); /* log_shb_ener_fx in Q8 */
+#endif
+ IF (hDtxEnc->first_CNG == 0 )
+ {
+ hTdCngEnc->mov_wb_cng_ener_fx = log_wb_ener_fx;
+ move16();
+ hTdCngEnc->mov_shb_cng_ener_fx = log_shb_ener_fx;
+ move16();
+ hTdCngEnc->last_wb_cng_ener_fx = log_wb_ener_fx;
+ move16();
+ hTdCngEnc->last_shb_cng_ener_fx = log_shb_ener_fx;
+ move16();
+ }
+
+ if ( GT_16(abs_s(sub(log_wb_ener_fx, hTdCngEnc->mov_wb_cng_ener_fx)), 3072))
+ {
+ allow_cn_step_fx = 1;
+ move16();
+ }
+#ifdef IVAS_CODE
+ /* Also allow step if shb energy has dropped 12 dB */
+ if ((st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD) && ((hTdCngEnc->mov_shb_cng_ener - log_shb_ener) > 12.0f))
+ {
+ allow_cn_step = 1;
+ }
+#endif
+ IF ( EQ_16(allow_cn_step_fx, 1))
+ {
+ hTdCngEnc->mov_wb_cng_ener_fx = log_wb_ener_fx;
+ move16();
+ hTdCngEnc->mov_shb_cng_ener_fx = log_shb_ener_fx;
+ move16();
+ }
+ ELSE
+ {
+ tmp = sub(log_wb_ener_fx, hTdCngEnc->mov_wb_cng_ener_fx); /* Q8 */
+ tmp = mult(tmp, 29491); /* Q8 */
+ hTdCngEnc->mov_wb_cng_ener_fx = add(hTdCngEnc->mov_wb_cng_ener_fx, tmp); /* Q8 */
+
+ tmp = sub(log_shb_ener_fx, hTdCngEnc->mov_shb_cng_ener_fx);
+ tmp = mult(tmp, 8192); /* Q8 */
+ hTdCngEnc->mov_shb_cng_ener_fx = add(hTdCngEnc->mov_shb_cng_ener_fx, tmp); /* Q8 */
+ }
+ hTdCngEnc->shb_NO_DATA_cnt = add(hTdCngEnc->shb_NO_DATA_cnt, 1);
+
+ update_fx = 0;
+ move16();
+ IF ( EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ test();
+ test();
+ IF (hDtxEnc->first_CNG == 0 || EQ_16(hTdCngEnc->last_vad, 1)||GE_16(hTdCngEnc->shb_NO_DATA_cnt,100))
+ {
+ update_fx = 1;
+ move16();
+ }
+ ELSE
+ {
+ IF ( hTdCngEnc->shb_cng_ini_cnt > 0 )
+ {
+ update_fx = 1;
+ move16();
+ hTdCngEnc->shb_cng_ini_cnt = sub(hTdCngEnc->shb_cng_ini_cnt, 1);
+ }
+ ELSE
+ {
+ IF ( GT_16(abs_s(sub(sub(hTdCngEnc->mov_wb_cng_ener_fx, hTdCngEnc->mov_shb_cng_ener_fx), sub(hTdCngEnc->last_wb_cng_ener_fx, hTdCngEnc->last_shb_cng_ener_fx))), 768))
+ {
+ update_fx = 1;
+ move16();
+ }
+ ELSE
+ {
+ test();
+ IF ( GE_16(st_fx->bwidth_fx, SWB)&<_16(hTdCngEnc->last_SID_bwidth,SWB))
+ {
+ update_fx = 1;
+ move16();
+ }
+ ELSE
+ {
+ test();
+ IF ( LT_16(st_fx->bwidth_fx, SWB)&&GE_16(hTdCngEnc->last_SID_bwidth,SWB))
+ {
+ update_fx = 1;
+ move16();
+ }
+ }
+ }
+ }
+ }
+
+ hTdCngEnc->last_SID_bwidth = st_fx->bwidth_fx;
+ move16();
+ }
+ /* LF-boost not yet implemented in decoder which means that the specific wb_sid information is not used */
+ test();test();
+ if ((EQ_16(st_fx->element_mode, IVAS_CPE_DFT) || EQ_16(st_fx->element_mode, IVAS_CPE_TD)) && EQ_32(st_fx->core_brate_fx, SID_2k40))
+ {
+ update_fx = 1;
+ move16();
+ }
+
+ IF ( EQ_16(update_fx, 1))
+ {
+ hTdCngEnc->last_wb_cng_ener_fx = hTdCngEnc->mov_wb_cng_ener_fx;
+ move16();
+ hTdCngEnc->last_shb_cng_ener_fx = hTdCngEnc->mov_shb_cng_ener_fx;
+ move16();
+ hTdCngEnc->shb_NO_DATA_cnt = 0;
+ move16();
+ }
+
+
+ return (update_fx);
+}
+
+/*---------------------------------------------------------------------*
+ * calculate_hangover_attenuation_gain_fx()
+ *
+ *
+ *---------------------------------------------------------------------*/
+
+void calculate_hangover_attenuation_gain_fx(
+ Encoder_State_fx* st, /* i : encoder state structure */
+ Word16* att, /* o : attenuation factor */
+ const Word16 vad_hover_flag /* i : VAD hangover flag */
+)
+{
+ Word16 offset;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc;
+
+ *att = 32767;
+
+ move16();
+ /* smoothing in case of CNG */
+ IF (hTdCngEnc != NULL)
+ {
+ test();test();test();
+ IF( hTdCngEnc->burst_ho_cnt > 0 && (vad_hover_flag != 0) && (NE_16(st->bwidth_fx, NB) || GT_16(st->element_mode, EVS_MONO))) /* corresponds to line 504 in FLT acelp_core_enc.c */
+ {
+#ifdef IVAS_CODE
+ if (st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD)
+ {
+ *att = powf(10.0f, (st->hTdCngEnc->CNG_att / 160.0f) * st->hTdCngEnc->burst_ho_cnt);
+ }
+ else
+#endif
+ {
+ offset = 5;
+ test();
+ if (EQ_16(st->bwidth_fx, WB) && st->hDtxEnc->CNG_mode >= 0)
+ {
+ offset = st->hDtxEnc->CNG_mode;
+ move16();
+ }
+ assert(hTdCngEnc->burst_ho_cnt > 0);
+ *att = CNG_burst_att_fx[offset][sub(hTdCngEnc->burst_ho_cnt, 1)]; /*Q15*/
+ move16();
+ }
+ }
+
+
+ }
+ return;
+}
diff --git a/lib_enc/cod2t32_fx.c b/lib_enc/cod2t32_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..dfbe4806ed9e736142be28b6f1207ffc5c445863
--- /dev/null
+++ b/lib_enc/cod2t32_fx.c
@@ -0,0 +1,421 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_com.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+* Local Constants
+*-------------------------------------------------------------------*/
+
+#define STEP 2
+#define MSIZE 1024
+
+/*----------------------------------------------------------------------------------
+* Function acelp_2t32()
+*
+* 12 bits algebraic codebook.
+* 2 tracks x 32 positions per track = 64 samples.
+*
+* 12 bits --> 2 pulses in a frame of 64 samples.
+*
+* All pulses can have two (2) possible amplitudes: +1 or -1.
+* Each pulse can have 32 possible positions.
+*----------------------------------------------------------------------------------*/
+
+void acelp_2t32_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
+ const Word16 dn[], /* i : corr. between target and h[]. */
+ const Word16 h[], /* i : impulse response of weighted synthesis filter */
+ Word16 code[], /* o : algebraic (fixed) codebook excitation */
+ Word16 y[] /* o : filtered fixed codebook excitation */
+)
+{
+ Word16 i, j, k, i0, i1, ix, iy, pos, pos2, sign0, sign1,index;
+ Word16 ps1, ps2, alpk, alp1, alp2;
+ Word16 sq,psk;
+ Word16 pol[L_SUBFR], dn_p[L_SUBFR];
+ Word16 ii,jj;
+ Word16 *p0, *p1, *p2;
+ const Word16 *ptr_h1, *ptr_h2, *ptr_hf;
+
+ Word32 s, L_cor;
+ Word32 L_tmp;
+ Word16 rrixix[NB_TRACK_FCB_2T][NB_POS_FCB_2T];
+ Word16 rrixiy[MSIZE];
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ /*----------------------------------------------------------------*
+ * Compute rrixix[][] needed for the codebook search.
+ *----------------------------------------------------------------*/
+
+ /* Init pointers to last position of rrixix[] */
+ p0 = &rrixix[0][NB_POS_FCB_2T - 1];
+ move16();
+ p1 = &rrixix[1][NB_POS_FCB_2T - 1];
+ move16();
+
+ ptr_h1 = h;
+ move16();
+ L_cor = L_deposit_h(1);
+ FOR (i = 0; i < NB_POS_FCB_2T; i++)
+ {
+#ifdef BASOP_NOGLOB
+ L_cor = L_mac_o(L_cor, *ptr_h1, *ptr_h1, &Overflow);
+#else
+ L_cor = L_mac(L_cor, *ptr_h1, *ptr_h1);
+#endif
+ ptr_h1++;
+ *p1-- = extract_h(L_cor);
+ move16(); /*Q9 Q7*/
+#ifdef BASOP_NOGLOB
+ L_cor = L_mac_o(L_cor, *ptr_h1, *ptr_h1, &Overflow);
+#else
+ L_cor = L_mac(L_cor, *ptr_h1, *ptr_h1);
+#endif
+ ptr_h1++;
+ *p0-- = extract_h(L_cor);
+ move16(); /*Q9 Q7*/
+ }
+
+ p0 = rrixix[0];
+ move16();
+ p1 = rrixix[1];
+ move16();
+
+ FOR (i = 0; i < NB_POS_FCB_2T; i++)
+ {
+ *p0 = shr(*p0, 1);
+ move16();
+ p0++;
+ *p1 = shr(*p1, 1);
+ move16();
+ p1++;
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixiy[][] needed for the codebook search.
+ *------------------------------------------------------------*/
+
+ pos = MSIZE - 1;
+ move16();
+ pos2 = MSIZE - 2;
+ move16();
+ ptr_hf = h + 1;
+ move16();
+
+ FOR (k = 0; k < NB_POS_FCB_2T; k++)
+ {
+ /* Init pointers to last position of diagonals */
+ p1 = &rrixiy[pos];
+ move16();
+ p0 = &rrixiy[pos2];
+ move16();
+
+ ptr_h1 = h;
+ move16();
+ ptr_h2 = ptr_hf;
+ move16();
+
+ L_cor = L_mult(*ptr_h1++, *ptr_h2++);
+ FOR (i = k; i < NB_POS_FCB_2T-1; i++)
+ {
+#ifdef BASOP_NOGLOB
+ * p1 = round_fx_o(L_cor, &Overflow);
+ L_cor = L_mac_o(L_cor, *ptr_h1++, *ptr_h2++, &Overflow);
+#else
+ * p1 = round_fx(L_cor);
+ L_cor = L_mac(L_cor, *ptr_h1++, *ptr_h2++);
+#endif
+#ifdef BASOP_NOGLOB
+ * p0 = round_fx_o(L_cor, &Overflow);
+ L_cor = L_mac_o(L_cor, *ptr_h1++, *ptr_h2++, &Overflow);
+#else
+ * p0 = round_fx(L_cor);
+ L_cor = L_mac(L_cor, *ptr_h1++, *ptr_h2++);
+#endif
+ p1 -= (NB_POS_FCB_2T + 1);
+ move16();
+ p0 -= (NB_POS_FCB_2T + 1);
+ move16();
+ }
+
+#ifdef BASOP_NOGLOB
+ *p1 = round_fx_o(L_cor, &Overflow);
+#else
+ *p1 = round_fx(L_cor);
+#endif
+ pos -= NB_POS_FCB_2T;
+ move16();
+ pos2--;
+ ptr_hf += STEP;
+ move16();
+ }
+
+ /*----------------------------------------------------------------*
+ * computing reference vector and pre-selection of polarities
+ *----------------------------------------------------------------*/
+
+ L_tmp = L_deposit_h(dn[0]);
+ FOR(i=0; i=0)
+ {
+ pol[i] = 1;
+ move16();
+ dn_p[i] = dn[i];
+ move16();
+ }
+ ELSE
+ {
+ pol[i] = -1;
+ move16();
+ dn_p[i] = negate(dn[i]);
+ move16();
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * compute denominator ( multiplied by polarity )
+ *----------------------------------------------------------------*/
+
+ k=0;
+ ii=0;
+ move16();
+ move16();
+ FOR(i=0; i 0)
+ {
+ psk = sq;
+ move16();
+ alpk = alp2;
+ move16();
+ pos = i1;
+ move16();
+ }
+ }
+ p1 -= NB_POS_FCB_2T;
+ move16();
+
+ IF (pos >= 0)
+ {
+ ix = i0;
+ move16();
+ iy = pos;
+ move16();
+ }
+ }
+
+ i0 = shr(ix,1);
+ i1 = shr(iy,1);
+
+ sign0 = shl(pol[ix],9);
+ sign1 = shl(pol[iy],9);
+
+ /*-------------------------------------------------------------------*
+ * Build the codeword, the filtered codeword and index of codevector.
+ *-------------------------------------------------------------------*/
+
+ set16_fx( code, 0, L_SUBFR );
+
+ code[ix] = sign0;
+ move16();
+ code[iy] = sign1;
+ move16();
+
+ index = add(shl(i0, 6), i1);
+
+
+ if (sign0 < 0)
+ {
+ index = add(index, 0x800);
+ }
+ if (sign1 < 0)
+ {
+ index = add(index, 0x20); /* move16();*/
+ }
+
+ set16_fx( y, 0, L_SUBFR );
+ /* y_Q9 = sign_Q9<<3 * h_Q12 */
+
+ sign0 = shl(sign0, 3);
+ sign1 = shl(sign1, 3);
+
+ FOR(i=ix; i0)
+ {
+ y[i] = shr_r(h[i-pos],3);
+ move16();
+ }
+ ELSE
+ {
+ y[i] = negate(shr_r(h[i-pos],3));
+ move16();
+ }
+ }
+
+ index = pos;
+ move16();
+ if( sgn > 0 )
+ {
+ index = add(index,L_subfr);
+ }
+ IF (EQ_16(L_subfr, L_SUBFR) )
+ {
+ push_indice_fx( hBstr, IND_ALG_CDBK_1T64, index, 7 );
+ }
+ ELSE /* L_subfr == 2*L_SUBFR */
+ {
+ push_indice_fx(hBstr, IND_ALG_CDBK_1T64, index, 8);
+ }
+
+ return;
+}
diff --git a/lib_enc/cod4t64_fx.c b/lib_enc/cod4t64_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb272c77175e86ef76bd48abb79ad7e60ff1a5d3
--- /dev/null
+++ b/lib_enc/cod4t64_fx.c
@@ -0,0 +1,1180 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* VMR-WB compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_enc.h" /* Encoder static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define STEP 4
+#define MSIZE 256
+#define NB_MAX 8
+
+/*-------------------------------------------------------------------*
+ * Local function prototypes
+ *-------------------------------------------------------------------*/
+static Word16 quant_1p_N1_fx(const Word16 pos,const Word16 N);
+static Word16 quant_2p_2N1_fx(const Word16 pos1, const Word16 pos2, const Word16 N);
+static Word16 quant_3p_3N1_fx( const Word16 pos1, const Word16 pos2, const Word16 pos3, const Word16 N );
+static Word32 quant_4p_4N_fx( const Word16 pos[], const Word16 N );
+static Word32 quant_5p_5N_fx( const Word16 pos[], const Word16 N );
+static Word32 quant_6p_6N_2_fx( const Word16 pos[], const Word16 N );
+
+
+
+static Word32 fcb_encode_position_fx(const Word16 pos_vector[],Word32 n, const Word32 pos_num, const Word32 flag);
+static Word32 fcb_encode_class_fx(const Word32 sector_6p_num[], const Word32 pulse_num, const Word32 pulse_pos_num);
+static Word32 fcb_encode_PI_fx(const Word16 v[], const Word32 pulse_num);
+static Word32 pre_process_fx( const Word16 v[], Word16 sector_6p[], Word32 sector_6p_num[], Word32 *pulse_pos_num );
+
+/*---------------------------------------------------------------------*
+ * ACELP_4t64()
+ *
+ * 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook.
+ * 4 tracks x 16 positions per track = 64 samples.
+ *
+ * 20 bits --> 4 pulses in a frame of 64 samples.
+ * 36 bits --> 8 pulses in a frame of 64 samples.
+ * 44 bits 13 + 9 + 13 + 9 --> 10 pulses in a frame of 64 samples.
+ * 52 bits 13 + 13 + 13 + 13 --> 12 pulses in a frame of 64 samples.
+ * 64 bits 2 + 2 + 2 + 2 + 14 + 14 + 14 + 14 -->
+ * 16 pulses in a frame of 64 samples.
+ * 72 bits 10 + 2 + 10 + 2 + 10 + 14 + 10 + 14 -->
+ * 18 pulses in a frame of 64 samples.
+ * 88 bits 11 + 11 + 11 + 11 + 11 + 11 + 11 + 11 -->
+ * 24 pulses in a frame of 64 samples.
+ * All pulses can have two (2) possible amplitudes: +1 or -1.
+ * Each pulse can have sixteen (16) possible positions.
+ *---------------------------------------------------------------------*/
+
+Word16 acelp_4t64_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
+ Word16 dn[], /* i : corr. between target and h[]. */
+ const Word16 cn[], /* i : residual after long term prediction Q_new*/
+ const Word16 H[], /* i : impulse response of weighted synthesis filter Q12*/
+ Word16 R[], /* i : autocorrelation values */
+ const Word16 acelpautoc, /* i : autocorrealtion flag */
+ Word16 code[], /* o : algebraic (fixed) codebook excitation Q9*/
+ Word16 y[], /* o : filtered fixed codebook excitation Q9*/
+ Word16 nbbits, /* i : number of bits per codebook */
+ const Word16 cmpl_flag, /* i : complexity reduction flag */
+ const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */
+)
+{
+
+ Word16 i, k, index, track;
+ Word32 L_index;
+ Word16 ind[NPMAXPT*NB_TRACK_FCB_4T+32]; /* VE3: why +32 ???*/
+ Word16 codvec[NB_PULSE_MAX+4]= {0};
+ Word16 saved_bits = 0;
+
+ PulseConfig config;
+ Word16 indexing_indices[6], wordcnt, bitcnt;
+
+ set16_fx(codvec, 0, NB_PULSE_MAX+4);
+ SWITCH (nbbits)
+ {
+
+ case 20: /* EVS/AMR-WB pulse indexing: 20 bits, 4 pulses, 4 tracks */
+ config.nbiter = 4;
+ move16(); /* 4x12x16=768 loop */
+ config.alp = 16384;
+ move16(); /* 2 in Q13*/
+ config.nb_pulse = 4;
+ move16();
+ config.fixedpulses = 0;
+ move16();
+ config.nbpos[0] = 4;
+ move16();
+ config.nbpos[1] = 8;
+ move16();
+ BREAK;
+
+ case 28: /* EVS pulse indexing: 28 bits, 6 pulses, 4 tracks */
+ config.nbiter = 4;
+ move16(); /* 4x20x16=1280 loops */
+ config.alp = 8192;
+ move16(); /* coeff FOR sign setting */
+ config.nb_pulse = 6;
+ move16();
+ config.fixedpulses = 0;
+ move16();
+ config.nbpos[0] = 6;
+ move16();
+ config.nbpos[1] = 6;
+ move16();
+ config.nbpos[2] = 8;
+ move16();
+ BREAK;
+
+ case 36: /* EVS/AMR-WB pulse indexing: 36 bits, 8 pulses, 4 tracks */
+ config.nbiter = 4;
+ move16(); /* 4x20x16=1280 loops */
+ config.alp = 8192;
+ move16(); /* coeff FOR sign setting */
+ config.nb_pulse = 8;
+ move16();
+ config.fixedpulses = 2;
+ move16();
+ config.nbpos[0] = 4;
+ move16();
+ config.nbpos[1] = 8;
+ move16();
+ config.nbpos[2] = 8;
+ move16();
+ BREAK;
+
+ case 43: /* EVS pulse indexing: 43 bits, 10 pulses, 4 tracks */
+ case 44: /* AMR-WB pulse indexing: 44 bits, 10 pulses, 4 tracks */
+ config.nbiter = 4;
+ move16(); /* 4x26x16=1664 loops */
+ config.alp = 8192;
+ move16();
+ config.nb_pulse = 10;
+ move16();
+ config.fixedpulses = 2;
+ move16();
+ config.nbpos[0] = 4;
+ move16();
+ config.nbpos[1] = 6;
+ move16();
+ config.nbpos[2] = 8;
+ move16();
+ config.nbpos[3] = 8;
+ move16();
+ BREAK;
+
+ case 50: /* EVS pulse indexing: 50 bits, 12 pulses, 4 tracks */
+ case 52: /* AMR-WB pulse indexing: 52 bits, 12 pulses, 4 tracks */
+ config.nbiter = 4;
+ move16(); /* 4x26x16=1664 loops */
+ config.alp = 8192;
+ move16();
+ config.nb_pulse = 12;
+ move16();
+ config.fixedpulses = 4;
+ move16();
+ config.nbpos[0] = 4;
+ move16();
+ config.nbpos[1] = 6;
+ move16();
+ config.nbpos[2] = 8;
+ move16();
+ config.nbpos[3] = 8;
+ move16();
+ BREAK;
+
+ case 62: /* EVS pulse indexing: 62 bits, 16 pulses, 4 tracks */
+ case 64: /* AMR-WB pulse indexing: 64 bits, 16 pulses, 4 tracks */
+ config.nbiter = 3;
+ move16(); /* 3x36x16=1728 loops */
+ config.alp = 6554;
+ move16();
+ config.nb_pulse = 16;
+ move16();
+ config.fixedpulses = 4;
+ move16();
+ config.nbpos[0] = 4;
+ move16();
+ config.nbpos[1] = 4;
+ move16();
+ config.nbpos[2] = 6;
+ move16();
+ config.nbpos[3] = 6;
+ move16();
+ config.nbpos[4] = 8;
+ move16();
+ config.nbpos[5] = 8;
+ move16();
+ BREAK;
+
+ case 72: /* AMR-WB pulse indexing: 72 bits, 18 pulses, 4 tracks */
+ config.nbiter = 3;
+ move16(); /* 3x35x16=1680 loops */
+ config.alp = 6144;
+ move16();
+ config.nb_pulse = 18;
+ move16();
+ config.fixedpulses = 4;
+ move16();
+ config.nbpos[0] = 2;
+ move16();
+ config.nbpos[1] = 3;
+ move16();
+ config.nbpos[2] = 4;
+ move16();
+ config.nbpos[3] = 5;
+ move16();
+ config.nbpos[4] = 6;
+ move16();
+ config.nbpos[5] = 7;
+ move16();
+ config.nbpos[6] = 8;
+ move16();
+ BREAK;
+
+ case 88: /* AMR-WB pulse indexing: 88 bits, 24 pulses, 4 tracks */
+ config.nbiter = 2;
+ move16(); /* 2x53x16=1696 loop */
+ config.alp = 4096;
+ move16();
+ config.nb_pulse = 24;
+ move16();
+ config.fixedpulses = 4;
+ move16();
+ config.nbpos[0] = 2;
+ move16();
+ config.nbpos[1] = 2;
+ move16();
+ config.nbpos[2] = 3;
+ move16();
+ config.nbpos[3] = 4;
+ move16();
+ config.nbpos[4] = 5;
+ move16();
+ config.nbpos[5] = 6;
+ move16();
+ config.nbpos[6] = 7;
+ move16();
+ config.nbpos[7] = 8;
+ move16();
+ config.nbpos[8] = 8;
+ move16();
+ config.nbpos[9] = 8;
+ move16();
+ BREAK;
+
+ case 87: /* EVS pulse indexing: 87 bits, 26 pulses, 4 tracks */
+ config.nbiter = 1;
+ move16();
+ config.alp = 4096;
+ move16();
+ config.nb_pulse = 26;
+ move16();
+ config.fixedpulses = 4;
+ move16();
+ config.nbpos[0] = 4;
+ move16();
+ config.nbpos[1] = 6;
+ move16();
+ config.nbpos[2] = 6;
+ move16();
+ config.nbpos[3] = 8;
+ move16();
+ config.nbpos[4] = 8;
+ move16();
+ config.nbpos[5] = 8;
+ move16();
+ config.nbpos[6] = 8;
+ move16();
+ config.nbpos[7] = 8;
+ move16();
+ config.nbpos[8] = 8;
+ move16();
+ config.nbpos[9] = 8;
+ move16();
+ config.nbpos[10] = 8;
+ move16();
+ BREAK;
+ }
+
+ /* reduce the number of iterations as a compromise between the performance and complexity */
+ if( cmpl_flag > 0 )
+ {
+ config.nbiter = cmpl_flag;
+ move16();
+ }
+
+ config.codetrackpos = TRACKPOS_FIXED_FIRST;
+ move16();
+ config.bits = nbbits;
+ move16();
+
+ IF (acelpautoc)
+ {
+ E_ACELP_4tsearchx_fx( dn, cn, R, code, &config, ind );
+
+ /* Generate weighted code */
+ E_ACELP_weighted_code(code, H, 12, y);
+ }
+ ELSE
+ {
+ E_ACELP_4tsearch_fx(dn, cn, H, code, &config, ind, y);
+
+ FOR(i=0; i it doesn't need to be operated by Basic Operators */
+
+ n_1 = (Word16) (N - 1);
+ move16();
+ nb_pos = shl(1, n_1); /* nb_pos = (1< 1, Q0 */
+ IF (v[k]>0)
+ {
+ sign = L_shl(sign, 1);
+ }
+ ELSE
+ {
+ sign = L_add(L_shl( sign, 1), 1);
+ }
+ j =add(j, 1);
+ }
+ }
+ *pulse_pos_num = L_deposit_l(j);
+
+ return sign;
+}
+
+
+/*--------------------------------------------------------------------------*
+* E_ACELP_code43bit_fx
+*
+* Fixed bit-length arithmetic coding of pulses
+* v - (input) pulse vector
+* s - (output) encoded state
+* n - (output) range of possible states (0...n-1)
+* p - (output) number of pulses found
+* len - (input) length of pulse vector
+* trackstep - (input) step between tracks
+*--------------------------------------------------------------------------*/
+
+Word16 E_ACELP_code43bit_fx(
+ const Word16 code[],
+ UWord32 *ps,
+ Word16 *p,
+ UWord16 idxs[]
+)
+{
+ Word16 i,j,k,track;
+ Word16 ind[32];
+
+ Word16 tmp;
+ Word32 L_tmp;
+ Word32 joint_index;
+ static const Word32 joint_offset = 3611648; /*offset for 3 pulses per track*/
+ Word16 saved_bits = 0;
+
+ FOR (track = 0; track < 2; track++)
+ {
+ ps[track] = fcb_encode_PI_fx(code+track, 3);
+ move32();
+ p[track] = 3;
+ move16();
+ }
+
+ FOR (track = 2; track < NB_TRACK_FCB_4T; track++)
+ {
+ i = j = i_mult2(track, NPMAXPT);
+ move16();
+ FOR (k = track; k < 64; k += 4)
+ {
+ IF (code[k])
+ {
+ tmp = shr(k, 2);
+ if (code[k] < 0)
+ {
+ tmp = add(tmp, 16);
+ }
+ ind[j] = tmp;
+ move16();
+ IF (GT_16(abs_s(code[k]), 512))
+ {
+ ind[j + 1] = tmp;
+ move16();
+ BREAK;
+ }
+ j = add(j, 1);
+ }
+ }
+ ps[track] = quant_2p_2N1_fx(ind[i], ind[i+1], 4);
+ move32();
+ p[track] = 2;
+ move16();
+ }
+ /* joint_index = ps[0]*5472 + ps[1]; */
+ L_tmp = L_shl(ps[0], 12);
+ L_tmp = L_add(L_tmp, L_shl(ps[0], 10));
+ L_tmp = L_add(L_tmp, L_shl(ps[0], 8));
+ L_tmp = L_add(L_tmp, L_shl(ps[0], 6));
+ L_tmp = L_add(L_tmp, L_shl(ps[0], 5));
+ joint_index = L_add(L_tmp, ps[1]);
+ L_tmp = L_sub(joint_index, joint_offset);
+ if (L_tmp >= 0)
+ {
+ joint_index = L_add(joint_index, joint_offset);
+ }
+ if (L_tmp < 0)
+ {
+ saved_bits = add(saved_bits, 1);
+ }
+ idxs[0] = extract_l(L_add(L_shl(ps[2], 9), ps[3]));
+ idxs[1] = extract_l(L_add(L_shl(joint_index, 2), L_shr(ps[2], 7)));
+ idxs[2] = extract_l(L_shr(joint_index, 14));
+
+ return saved_bits;
+}
diff --git a/lib_enc/cod_ace_fx.c b/lib_enc/cod_ace_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..19bcdba0b83bbdef1e9ecf6fdef6b13be1deb8f3
--- /dev/null
+++ b/lib_enc/cod_ace_fx.c
@@ -0,0 +1,498 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+//#include "prot_fx.h"
+#include "basop_util.h"
+#include "options.h"
+#include "rom_basop_util.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * coder_acelp_fx()
+ *
+ * Encode ACELP frame
+ *-------------------------------------------------------------------*/
+
+Word16 coder_acelp_fx( /* o : SEGSNR for CL decision */
+ const Word16 A[], /* i : coefficients 4xAz[M+1] */
+ const Word16 Aq[], /* i : coefficients 4xAz_q[M+1] */
+ const Word16 speech[], /* i : speech[-M..lg] */
+ Word16 *prm, /* o : acelp parameters */
+ Word16 stab_fac,
+ Encoder_State_fx *st,
+ PLC_ENC_EVS_HANDLE hPlc_Ext,
+ const Word16 target_bits, /* i/o: coder memory state */
+ const Word16 Q_new,
+ const Word16 shift,
+ Word16 *pitch_buf, /* o : pitch values for each subfr.*/
+ Word16 *voice_factors, /* o : voicing factors */
+ Word16 *bwe_exc /* o : excitation for SWB TBE */
+)
+{
+#ifndef SIMPLIFY_CODE_BE
+ Word16 i, j, i_subfr, j_subfr;
+ Word16 tmp, tmp2, Es_pred;
+ Word32 gain_code_vect[2];
+#else
+ Word16 i, i_subfr, j_subfr;
+ Word16 tmp, Es_pred;
+#endif
+ Word16 T0, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res;
+ Word16 T0_frac;
+ Word16 gain_pit, voice_fac;
+ Word32 gain_code, Ltmp, Ltmp2;
+ ACELP_CbkCorr g_corr;
+ const Word16 *p_A, *p_Aq;
+ Word16 h1[L_SUBFR]; /* weighted impulse response of LP */
+ Word16 code[L_SUBFR];
+ Word16 xn_exp;
+ Word16 Q_xn;
+ Word16 Q_new_p5;
+ Word16 cn[L_SUBFR];
+ Word16 xn[L_SUBFR];
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 res_save;
+ Word16 exc_buf[L_EXC_MEM+L_DIV_MAX+1], *exc;
+ Word16 exc2[L_SUBFR];
+ Word16 *syn,syn_buf[M+L_DIV_MAX+L_DIV_MAX/2]; /*128 for the memory, L_DIV for the current synth and 128 for the ZIR for next TCX*/
+ Word16 syn2[L_DIV_MAX];
+ Word16 gain_inov;
+ Word32 past_gcode;
+ Word16 L_frame;
+ Word16 clip_gain;
+ Word32 gain_code2;
+ Word16 code2[L_SUBFR];
+ Word16 y22[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 error = 0;
+ Word16 gain_preQ = 0; /* Gain of prequantizer excitation */
+ Word16 code_preQ[L_SUBFR]; /* Prequantizer excitation */
+
+ Word16 dummy = 0;
+ ACELP_config* acelp_cfg;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ acelp_cfg = &(st->acelp_cfg);
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+ RF_ENC_HANDLE hRF = st->hRF;
+ TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ set16_fx(code_preQ, 0, L_SUBFR);
+
+
+ T0 = 0; /* to avoid compilation warnings */
+ T0_frac = 0; /* to avoid compilation warnings */
+ T0_res = 0; /* to avoid compilation warnings */
+ gain_pit = 0; /* to avoid compilation warnings */
+
+
+ /* Configure ACELP */
+ hLPDmem->nbits = BITS_ALLOC_config_acelp( target_bits, st->coder_type, acelp_cfg, st->narrowBand, st->nb_subfr );
+
+ /* Init Framing parameters */
+ move16();
+ move16();
+ move16();
+ L_frame = st->L_frame_fx;
+
+
+ /*------------------------------------------------------------------------*
+ * Previous frame is TCX (for non-EVS modes)(deactivated permanently) *
+ *------------------------------------------------------------------------*/
+
+ /*------------------------------------------------------------------------*
+ * Initialize buffers *
+ *------------------------------------------------------------------------*/
+
+ /* Rescale ACELP memories, which were not scaled yet*/
+ xn_exp = sub(sub(15+1, Q_new),shift);
+ Q_xn = add(sub(Q_new,1),shift);
+ Q_new_p5 = add(Q_new, 5);
+
+ /* Reset phase dispersion */
+ IF (GT_16(st->last_core_fx, ACELP_CORE))
+ {
+ move16();
+ move16();
+ move16();
+
+ hLPDmem->dm_fx.prev_gain_code = 0;
+ set16_fx(hLPDmem->dm_fx.prev_gain_pit, 0, 6);
+ hLPDmem->dm_fx.prev_state = 0;
+
+ }
+
+ /* set excitation memory*/
+ move16();
+ move16();
+ exc = exc_buf+L_EXC_MEM;
+ Copy(hLPDmem->old_exc, exc_buf, L_EXC_MEM);
+ *(exc+st->L_frame_fx) = 0;
+
+ /* Init syn buffer */
+ move16();
+ syn = syn_buf + M;
+ Copy(hLPDmem->mem_syn, syn_buf, M);
+
+
+ /* calculate residual */
+ calc_residu_fx(st, speech, exc, Aq);
+ /*------------------------------------------------------------------------*
+ * Find and quantize mean_ener_code for gain quantizer *
+ *------------------------------------------------------------------------*/
+
+ Es_pred=0;
+ move16();
+ IF (acelp_cfg->nrg_mode>0)
+ {
+ Es_pred_enc_fx(&Es_pred, prm, L_frame, exc, st->voicing_fx, acelp_cfg->nrg_bits, acelp_cfg->nrg_mode>1, Q_new);
+ prm++;
+ }
+
+ IF (EQ_16(st->L_frame_fx,L_FRAME))
+ {
+ Copy(Aq+2*(M+1), hBWE_TD->cur_sub_Aq_fx, (M+1));
+ }
+ ELSE
+ {
+ Copy(Aq+3*(M+1), hBWE_TD->cur_sub_Aq_fx, (M+1));
+ }
+
+
+ /*------------------------------------------------------------------------*
+ * Loop for every subframe in the analysis frame *
+ *------------------------------------------------------------------------*
+ * To find the pitch and innovation parameters. The subframe size is *
+ * L_SUBFR and the loop is repeated L_FRAME_PLUS/L_SUBFR *
+ * times. *
+ * - compute impulse response of weighted synthesis filter (h1[]) *
+ * - compute the target signal for pitch search *
+ * - find the closed-loop pitch parameters *
+ * - encode the pitch delay *
+ * - update the impulse response h1[] by including fixed-gain pitch *
+ * - find target vector for codebook search *
+ * - correlation between target vector and impulse response *
+ * - codebook search *
+ * - encode codebook address *
+ * - VQ of pitch and codebook gains *
+ * - find synthesis speech *
+ * - update states of weighting filter *
+ *------------------------------------------------------------------------*/
+ move16();
+ move16();
+ p_A = A;
+ p_Aq = Aq;
+
+ move16();
+ res_save = exc[0];
+
+ j_subfr = 0;
+ move16();
+ FOR (i_subfr=0; i_subfrmem_w0, p_Aq, exc, L_SUBFR, p_A, st->preemph_fac, xn, cn, h1);
+
+ /*---------------------------------------------------------------*
+ * Compute impulse response, h1[], of weighted synthesis filter *
+ *---------------------------------------------------------------*/
+ Scale_sig(h1, L_SUBFR, add(1,shift)); /* Q13+1-shift */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(xn, L_SUBFR, shift);
+
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ * or in case of floating point encoder & fixed p. decoder
+ *-----------------------------------------------------------------*/
+
+ clip_gain = Mode2_gp_clip( st->voicing_fx, i_subfr, st->coder_type, xn, st->clip_var_fx, L_SUBFR, Q_xn );
+
+ /*-----------------------------------------------------------------*
+ * - find unity gain pitch excitation (adaptive codebook entry) *
+ * with fractional interpolation. *
+ * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) *
+ * - compute pitch gain1 *
+ *-----------------------------------------------------------------*/
+
+ IF ( acelp_cfg->ltp_bits!=0 )
+ {
+ /* Adaptive Codebook (GC and VC) */
+
+ Mode2_pit_encode_fx( acelp_cfg->ltp_mode, i_subfr, &prm, &exc[i_subfr], st->pitch_fx, &T0_min, &T0_min_frac, &T0_max, &T0_max_frac,
+ &T0, &T0_frac, &T0_res, h1, xn, st->pit_min, st->pit_fr1, st->pit_fr1b, st->pit_fr2, st->pit_max, st->pit_res_max);
+
+ E_ACELP_adaptive_codebook( exc, T0, T0_frac, T0_res, st->pit_res_max, acelp_cfg->ltf_mode, i_subfr, L_SUBFR, L_frame, h1, clip_gain, xn,
+ y1, &g_corr, &prm, &gain_pit, xn_exp, 0, 0, &dummy);
+
+ }
+ ELSE IF ( acelp_cfg->ltp_bits==0 )
+ {
+ /* No adaptive codebook (UC) */
+ gain_pit=0;
+ g_corr.xy1=0;
+ g_corr.xy1_e=0;
+ g_corr.y1y1=0;
+ g_corr.y1y1_e=0;
+ set16_fx(y1,0,L_SUBFR);
+ set16_fx(exc+i_subfr,0,L_SUBFR);
+ T0 = L_SUBFR;
+ T0_frac = 0;
+ T0_res = 1;
+ move16(); move16(); move16(); move16(); move16(); move16(); move16(); move16();
+ }
+
+ IF( st->igf != 0 )
+ {
+ tbe_celp_exc(L_frame, i_subfr, T0, T0_frac, &error, bwe_exc);
+ }
+
+ pitch_buf[i_subfr/L_SUBFR] = shl(add(shl(T0,2),T0_frac), 4);
+
+ /*----------------------------------------------------------------------*
+ * Encode the algebraic innovation *
+ *----------------------------------------------------------------------*/
+
+ E_ACELP_innovative_codebook_fx( exc, T0, T0_frac, T0_res, gain_pit, hLPDmem->tilt_code, acelp_cfg, i_subfr, p_Aq, h1, xn, cn, y1, y2, st->acelp_autocorr, &prm, code, shift ,st->L_frame_fx, st->last_L_frame_fx, st->total_brate_fx);
+
+ E_ACELP_xy2_corr(xn, y1, y2, &g_corr, L_SUBFR, Q_xn);
+
+ g_corr.y2y2_e = sub(g_corr.y2y2_e, 18); /* -18 (y2*y2: Q9*Q9) */
+ g_corr.xy2_e = sub(g_corr.xy2_e, add(Q_xn,9)); /* -(Q_xn+9) (xn: Q_xn y2: Q9) */
+ g_corr.y1y2_e = sub(g_corr.y1y2_e, add(Q_xn,9)); /* -(Q_xn+9) (y1: Q_xn y2: Q9) */
+ g_corr.xx_e = sub(g_corr.xx_e, add(Q_xn,Q_xn)); /* -(Q_xn+Q_xn) (xn: Q_xn) */
+
+
+ /*----------------------------------------------------------------------*
+ * Add Gaussian excitation *
+ *----------------------------------------------------------------------*/
+
+ IF (EQ_16(acelp_cfg->gains_mode[j_subfr], 7))
+ {
+ assert(gain_pit == 0);
+ gauss_L2_fx(h1, code2, y2, y22, &gain_code2, &g_corr, gain_pit, hLPDmem->tilt_code, p_Aq, acelp_cfg->formant_enh_num, &(st->seed_acelp), shift );
+ }
+ ELSE
+ {
+ gain_code2 = L_deposit_l(0);
+ set16_fx(code2, 0, L_SUBFR);
+ set16_fx(y22, 0, L_SUBFR);
+ }
+
+ /*----------------------------------------------------------*
+ * - Compute the fixed codebook gain *
+ * - quantize fixed codebook gain *
+ *----------------------------------------------------------*/
+
+ encode_acelp_gains_fx( code, acelp_cfg->gains_mode[j_subfr], Es_pred, clip_gain, &g_corr, &gain_pit, &gain_code, &prm,
+ &past_gcode, &gain_inov, L_SUBFR, code2, &gain_code2, st->flag_noisy_speech_snr );
+
+ gp_clip_test_gain_pit_fx(st->element_mode, st->core_brate_fx, gain_pit, st->clip_var_fx );
+
+#ifndef SIMPLIFY_CODE_BE
+ gain_code_vect[0] = gain_code;
+ move32();
+ gain_code_vect[1] = gain_code;
+ move32();
+#endif
+ /*----------------------------------------------------------*
+ * - voice factor (for pitch enhancement) *
+ *----------------------------------------------------------*/
+ E_UTIL_voice_factor( exc, i_subfr, code, gain_pit, gain_code, &voice_fac, &(hLPDmem->tilt_code), L_SUBFR, acelp_cfg->voice_tilt, Q_new, shift);
+
+ IF(st->Opt_RF_ON)
+ {
+ hRF->rf_tilt_buf[i_subfr / L_SUBFR] = hLPDmem->tilt_code;
+ }
+ /*-----------------------------------------------------------------*
+ * Update memory of the weighting filter
+ *-----------------------------------------------------------------*/
+ /* st_fx->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); */
+ Ltmp = Mpy_32_16_1(gain_code, y2[L_SUBFR-1]);
+ Ltmp = L_shl(Ltmp, add(5,Q_xn));
+ Ltmp = L_mac(Ltmp, y1[L_SUBFR-1], gain_pit);
+ /* Add Gaussian contribution*/
+ Ltmp2 = Mpy_32_16_1(gain_code2, y22[L_SUBFR-1]);
+ Ltmp2 = L_shl(Ltmp2, add(5,Q_xn));
+ Ltmp = L_add(Ltmp, Ltmp2);
+ hLPDmem->mem_w0 =sub(xn[L_SUBFR-1], round_fx(L_shl(Ltmp, 1)));
+ move16();
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ hLPDmem->mem_w0 =shr(hLPDmem->mem_w0, shift); /*Qnew-1*/
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ /*-------------------------------------------------------*
+ * - Find the total excitation. *
+ *-------------------------------------------------------*/
+#ifndef SIMPLIFY_CODE_BE
+ tmp2 = shr(L_SUBFR, 1);
+ FOR (j = 0; j < 2; j++)
+ {
+ FOR (i = sub(tmp2, shr(L_SUBFR, 1)); i < tmp2; i++)
+ {
+ /* code in Q9, gain_pit in Q14; exc Q_new */
+ Ltmp = Mpy_32_16_1(gain_code2, code2[i]);
+ Ltmp = L_shl(Ltmp, Q_new_p5);
+ Ltmp = L_mac(Ltmp, gain_pit, exc[i+i_subfr]);
+ BASOP_SATURATE_WARNING_OFF_EVS
+ exc2[i] = round_fx(L_shl(Ltmp, 1));
+ BASOP_SATURATE_WARNING_ON_EVS
+
+ Ltmp2 = Mpy_32_16_1(gain_code_vect[j], code[i]);
+ Ltmp2 = L_shl(Ltmp2, Q_new_p5);
+ Ltmp = L_add(Ltmp, Ltmp2);
+ BASOP_SATURATE_WARNING_OFF_EVS
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+ BASOP_SATURATE_WARNING_ON_EVS
+ exc[i + i_subfr] = round_fx(Ltmp);
+ }
+ tmp2 = L_SUBFR;
+ move16();
+ }
+#else
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ /* code in Q9, gain_pit in Q14; exc Q_new */
+ Ltmp = Mpy_32_16_1(gain_code2, code2[i]);
+ Ltmp = L_shl(Ltmp, Q_new_p5);
+ Ltmp = L_mac(Ltmp, gain_pit, exc[i+i_subfr]);
+#ifdef BASOP_NOGLOB
+ exc2[i] = round_fx(L_shl_o(Ltmp, 1, &Overflow));
+#else
+ BASOP_SATURATE_WARNING_OFF_EVS
+ exc2[i] = round_fx(L_shl(Ltmp, 1));
+ BASOP_SATURATE_WARNING_ON_EVS
+#endif
+
+ Ltmp2 = Mpy_32_16_1(gain_code, code[i]);
+ Ltmp2 = L_shl(Ltmp2, Q_new_p5);
+ Ltmp = L_add(Ltmp, Ltmp2);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(Ltmp, 1, &Overflow); /* saturation can occur here */
+ exc[i + i_subfr] = round_fx_o(Ltmp, &Overflow);
+#else
+ BASOP_SATURATE_WARNING_OFF_EVS
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+ BASOP_SATURATE_WARNING_ON_EVS
+ exc[i + i_subfr] = round_fx(Ltmp);
+#endif
+ }
+#endif
+ /*-----------------------------------------------------------------*
+ * Prepare TBE excitation
+ *-----------------------------------------------------------------*/
+
+ IF( st->igf != 0 )
+ {
+ prep_tbe_exc_fx( L_frame, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR],
+ bwe_exc, gain_preQ, code_preQ, Q_new, T0, T0_frac, st->coder_type, st->core_brate_fx );
+ }
+
+ /*---------------------------------------------------------*
+ * Enhance the excitation *
+ *---------------------------------------------------------*/
+
+ E_UTIL_enhancer( voice_fac, stab_fac, past_gcode, gain_inov, &hLPDmem->gc_threshold, code, exc2, gain_pit, &hLPDmem->dm_fx.prev_gain_code,
+ hLPDmem->dm_fx.prev_gain_pit, &hLPDmem->dm_fx.prev_state, st->coder_type, acelp_cfg->fixed_cdk_index[j_subfr], L_SUBFR, L_frame, Q_new);
+
+ /*----------------------------------------------------------*
+ * - compute the synthesis speech *
+ *----------------------------------------------------------*/
+
+ E_UTIL_synthesis(1, p_Aq, exc2, &syn2[i_subfr], L_SUBFR, hLPDmem->mem_syn2, 1, M);
+
+ /*Save data for BPF*/
+
+ move16();
+ move16();
+ /* st->bpf_T[j_subfr] = (int)((float)T0+(float)T0_frac/(float)T0_res+0.5f); */
+ st->bpf_T[j_subfr] = add(T0, shr(div_s(T0_frac, T0_res), 14));
+ st->bpf_gainT[j_subfr] = gain_pit;
+
+ E_UTIL_synthesis(1, p_Aq, &exc[i_subfr], &syn[i_subfr], L_SUBFR, &syn[i_subfr-M], 0, M);
+
+ /*----------------------------------------------------------*
+ * Update *
+ *----------------------------------------------------------*/
+ move16();
+ move16();
+ p_A += (M+1);
+ p_Aq += (M+1);
+
+ IF( hPlc_Ext != NULL )
+ {
+ hPlc_Ext->T0_4th = T0;
+ move16();
+ }
+
+ move32();
+ st->gain_code[j_subfr] = gain_code;
+
+ j_subfr = add(j_subfr, 1);
+ } /* end of subframe loop */
+
+ p_A -= (M+1);
+ p_Aq -= (M+1);
+
+
+ /*----------------------------------------------------------*
+ * Update LPD memory *
+ *----------------------------------------------------------*/
+ Copy (exc+L_frame-L_EXC_MEM, hLPDmem->old_exc, L_EXC_MEM);
+ Copy(syn+L_frame-M, hLPDmem->mem_syn, M);
+ Copy(syn+L_frame-L_SYN_MEM, hLPDmem->mem_syn_r, L_SYN_MEM);
+
+ IF( hPlc_Ext != NULL )
+ {
+ hPlc_Ext->Q_exp = sub( Q_new, hPlc_Ext->Q_new );
+ move16();
+ hPlc_Ext->Q_new = Q_new;
+ move16();
+ Copy( exc+L_frame-L_EXC_MEM-8, hPlc_Ext->old_exc_Qold, 8);
+ }
+
+ /*----------------------------------------------------------*
+ * ZIR at the end of the ACELP frame (for TCX) *
+ *----------------------------------------------------------*/
+ Copy(syn2, syn, L_frame);
+ move16();
+ tmp = hLPDmem->syn[M];
+ E_UTIL_deemph2(sub(Q_new,1), syn, st->preemph_fac, L_frame, &tmp);
+
+ if (st->hTcxEnc != NULL)
+ {
+ bufferCopyFx(syn + L_frame - (L_frame / 2), hTcxEnc->Txnq, shr(L_frame, 1), 0 /*Qf_syn*/, -1 /*Qf_Txnq*/, 0 /*Q_syn*/, 0 /*Q_Txnq*/);
+ }
+ Copy(syn+L_frame-M-1, hLPDmem->syn, 1+M); /*Q0*/
+ Copy(syn, st->synth, L_frame);
+
+ assert(T0_res <= 6);
+
+ /*Update MODE1*/
+ Copy(p_Aq, st->old_Aq_12_8_fx, M+1 );
+ st->old_Es_pred_fx = Es_pred;
+
+ return 0;
+}
diff --git a/lib_enc/cod_tcx_fx.c b/lib_enc/cod_tcx_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..4510615a88689c2f4734f2f45ae920e0f8cb58c7
--- /dev/null
+++ b/lib_enc/cod_tcx_fx.c
@@ -0,0 +1,2969 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include
+#include
+#include "rom_com.h"
+#include "stat_com.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h"
+#include "basop_util.h"
+#include "stl.h"
+//#include "basop_mpy.h"
+#include "prot_fx_enc.h"
+
+
+
+/* Up to the Autocorrelation it is the same code as in GetMDCT, with the difference in the parameters in the call to tcx_windowing_analysis */
+void HBAutocorrelation_fx(
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
+ Word16 left_overlap_mode, /* input: overlap mode of left window half */
+ Word16 right_overlap_mode, /* input: overlap mode of right window half */
+ Word16 speech[], /* input: speech[-LFAC..L_frame+LFAC] */
+ Word16 L_frame, /* input: frame length */
+ Word32 *r, /* output: autocorrelations vector */
+ Word16 m /* input : order of LP filter */
+)
+{
+ Word16 i, j, left_overlap, right_overlap;
+ Word16 len, norm, shift, fact;
+ Word32 L_tmp, L_sum;
+ Word16 y[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX];
+
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /*-----------------------------------------------------------*
+ * Windowing *
+ *-----------------------------------------------------------*/
+
+ WindowSignal(hTcxCfg, hTcxCfg->tcx_offset, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, speech, &L_frame, y, 1, 0);
+
+ /*-----------------------------------------------------------*
+ * Autocorrelation *
+ *-----------------------------------------------------------*/
+
+ len = add(L_frame, shr(add(left_overlap, right_overlap), 1));
+
+ /* calculate shift */
+ shift = 0;
+ move16();
+ L_sum = L_deposit_l(0);
+ Overflow = 0;
+ move16();
+ FOR (i = 0; i < len; i+=1)
+ {
+ /* Test Addition */
+#ifdef BASOP_NOGLOB /* Critical Overflow, all operations below needs to check for Overflow if we want to ensure bit exactness */
+ L_mac0_o(L_sum, y[i], y[i], &Overflow);
+#else /* BASOP_NOGLOB */
+ L_mac0(L_sum, y[i], y[i]);
+#endif /* BASOP_NOGLOB */
+ IF (Overflow)
+ {
+ Overflow = 0;
+ move16();
+ shift = 1;
+ move16();
+ L_tmp = L_msu0( 0, y[i], y[i] );
+ L_tmp = L_shr( L_tmp, 1 );
+#ifdef BASOP_NOGLOB /* Only the sub can overflow if the current L_sum is negative and already close to MIN */
+ L_sum = L_add( L_shr( L_sub_o( L_sum, 1, &Overflow ), 1 ), 1 );
+#else
+ L_sum = L_add( L_shr( L_sub( L_sum, 1 ), 1 ), 1 );
+#endif
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ L_sum = L_sub_o( L_sum, L_tmp, &Overflow );
+#else
+ L_sum = L_sub( L_sum, L_tmp );
+#endif
+ FOR (j = add(i,1); j 0)
+ {
+ fact = lshr(-32768, shift);
+ FOR (i = 0; i < len; i++)
+ {
+ y[i] = mult_r(y[i], fact);
+ move16();
+ }
+ }
+
+ /* Compute and normalize r[0] */
+ L_sum = L_mac0(1, y[0], y[0]);
+ FOR (i = 1; i < len; i++)
+ {
+ L_sum = L_mac0(L_sum, y[i], y[i]);
+ }
+
+ norm = norm_l(L_sum);
+ L_sum = L_shl(L_sum, norm);
+ r[0] = L_sum;
+ move32();
+
+ /* Compute r[1] to r[m] */
+ FOR (i = 1; i <= m; i++)
+ {
+ L_sum = L_mult0(y[0],y[i]);
+ FOR (j = 1; j < len - i; j++)
+ {
+ L_sum = L_mac0(L_sum, y[j], y[j + i]);
+ }
+
+ L_sum = L_shl(L_sum, norm);
+ r[i] = L_sum;
+ move32();
+ }
+
+}
+#ifdef ADD_IVAS_TNS
+
+/*-------------------------------------------------------------------*
+ * TNSAnalysisStereo()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+#define SIMILAR_TNS_THRESHOLD ( 0.04f )
+#define TNS_GAIN_THRESHOLD_FOR_WHITE ( 3.0f )
+
+void TNSAnalysisStereo(
+ Encoder_State** sts, /* i : encoder state handle */
+ float* mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* o : MDST spectrum */
+ const int16_t bWhitenedDomain, /* i : whitened domain flag */
+ int16_t tnsSize[MCT_MAX_CHANNELS][NB_DIV], /* i : number of tns parameters put into prm */
+ int16_t tnsBits[MCT_MAX_CHANNELS][NB_DIV], /* i : number of tns bits in the frame */
+ int16_t param_core[][NB_DIV * NPRM_DIV], /* o : TNS parameters */
+ const int16_t mct_on /* i : flag mct block (1) or stereo (0) */
+)
+{
+ int16_t ch, k, L_spec, L_frame, nSubframes, iFilter;
+ float* spectrum;
+ Encoder_State* st = NULL;
+ TCX_ENC_HANDLE hTcxEnc = NULL;
+ int16_t individual_decision[NB_DIV];
+ float maxPredictionGain = 0.f, meanPredictionGain;
+
+ individual_decision[0] = 0;
+ individual_decision[1] = 0;
+ L_spec = -1;
+ L_frame = -1;
+
+ /* TNS filter analysis, loop over channels */
+ for (ch = 0; ch < CPE_CHANNELS; ch++)
+ {
+ st = sts[ch];
+ if (st->mct_chan_mode == MCT_CHAN_MODE_IGNORE)
+ {
+ continue;
+ }
+
+ hTcxEnc = st->hTcxEnc;
+
+ nSubframes = (hTcxEnc->tcxMode == TCX_20) ? 1 : NB_DIV;
+
+ for (k = 0; k < nSubframes; k++)
+ {
+ /* reset tns on whitened domain flag */
+ if (!bWhitenedDomain)
+ {
+ hTcxEnc->bTnsOnWhithenedSpectra[k] = 0;
+ hTcxEnc->fUseTns[k] = 0;
+ }
+
+ if (st->hTcxCfg->fIsTNSAllowed && (!bWhitenedDomain || hTcxEnc->bTnsOnWhithenedSpectra[k]))
+ {
+
+ spectrum = hTcxEnc->spectrum[k];
+ L_frame = hTcxEnc->L_frameTCX;
+ st->hTcxCfg->pCurrentTnsConfig = &st->hTcxCfg->tnsConfig[hTcxEnc->transform_type[k] == TCX_20][(k == 0) && (st->last_core == ACELP_CORE)];
+ L_spec = st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0];
+
+ /*-----------------------------------------------------------*
+ * Temporal Noise Shaping analysis *
+ *-----------------------------------------------------------*/
+
+ if (hTcxEnc->transform_type[k] == TCX_5)
+ {
+ /* rearrange LF sub-window lines prior to TNS analysis & filtering */
+ tcx5TnsGrouping(L_frame >> 2, L_spec >> 1, spectrum);
+ }
+
+ /* WMOPS: All initializations are either for safety or static (tables) and thus not to be counted */
+ ResetTnsData(&hTcxEnc->tnsData[k]);
+ if (st->hTcxCfg->pCurrentTnsConfig->maxOrder <= 0)
+ {
+ break;
+ }
+
+ CalculateTnsFilt(st->hTcxCfg->pCurrentTnsConfig, spectrum, &hTcxEnc->tnsData[k], NULL);
+ }
+ }
+ }
+
+ if (!mct_on)
+ {
+ /* TNS decision */
+ /* if framing differs between channels, keep the filter decision per channel */
+ if ((sts[0]->hTcxEnc->transform_type[0] != sts[1]->hTcxEnc->transform_type[0] &&
+ sts[0]->hTcxEnc->transform_type[1] != sts[1]->hTcxEnc->transform_type[1]) ||
+ sts[0]->hTcxCfg->fIsTNSAllowed != sts[1]->hTcxCfg->fIsTNSAllowed)
+ {
+ individual_decision[0] = individual_decision[1] = 1;
+ }
+ else if (bWhitenedDomain)
+ {
+ nSubframes = (sts[0]->hTcxEnc->tcxMode == TCX_20) ? 1 : NB_DIV;
+ for (k = 0; k < nSubframes; k++)
+ {
+ if (sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] != sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k])
+ {
+ individual_decision[k] = 1;
+ }
+ }
+ }
+
+ /* framing equal, check for similar filters, if very similar (also indicator for and M signal),
+ * use at least the same decision, maybe use the same filter
+ */
+ {
+ int16_t isTCX10;
+ isTCX10 = (sts[0]->hTcxEnc->tcxMode == TCX_20) ? 0 : 1;
+
+ nSubframes = (sts[0]->hTcxEnc->tcxMode == TCX_20) ? 1 : NB_DIV;
+
+ for (k = 0; k < nSubframes; k++)
+ {
+ if (sts[0]->hTcxCfg->fIsTNSAllowed && individual_decision[k] != 1 && (!bWhitenedDomain || sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k]))
+ {
+ float maxPredGain = -1.0f;
+ sts[0]->hTcxCfg->pCurrentTnsConfig = &sts[0]->hTcxCfg->tnsConfig[sts[0]->hTcxEnc->transform_type[k] == TCX_20][(k == 0) && (sts[0]->last_core == ACELP_CORE)];
+ sts[1]->hTcxCfg->pCurrentTnsConfig = &sts[1]->hTcxCfg->tnsConfig[sts[1]->hTcxEnc->transform_type[k] == TCX_20][(k == 0) && (sts[1]->last_core == ACELP_CORE)];
+
+#ifdef DEBUGGING
+ assert(sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters == sts[1]->hTcxCfg->pCurrentTnsConfig->nMaxFilters);
+#endif
+ for (iFilter = sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter--)
+ {
+ STnsFilter* pFilter[2];
+ struct TnsParameters const* pTnsParameters[2];
+ pFilter[0] = sts[0]->hTcxEnc->tnsData[k].filter + iFilter;
+ pTnsParameters[0] = sts[0]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter;
+ pFilter[1] = sts[1]->hTcxEnc->tnsData[k].filter + iFilter;
+ pTnsParameters[1] = sts[1]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter;
+
+#ifdef DEBUGGING
+ assert(pTnsParameters[0]->startLineFrequency == pTnsParameters[1]->startLineFrequency);
+ assert(pTnsParameters[0]->nSubdivisions == pTnsParameters[1]->nSubdivisions);
+#endif
+ /* if prediction gain and avgSqrCoef are both close we are pretty sure the filters are quite similar, use the avg of
+ * both filters for the decision
+ */
+ meanPredictionGain = (pFilter[0]->predictionGain + pFilter[1]->predictionGain) * 0.5f;
+ maxPredictionGain = max(maxPredictionGain, meanPredictionGain);
+
+ if ((pFilter[0]->predictionGain > pTnsParameters[0]->minPredictionGain) && (sts[0]->element_brate < IVAS_80k) &&
+ (pFilter[1]->predictionGain > pTnsParameters[1]->minPredictionGain) && (sts[0]->hTcxEnc->tnsData[k].nFilters == sts[1]->hTcxEnc->tnsData[k].nFilters))
+ {
+ pFilter[0]->predictionGain = pFilter[1]->predictionGain = meanPredictionGain; /* more TNS filter sync at 48kbps */
+ }
+ if ((fabs(pFilter[0]->predictionGain - pFilter[1]->predictionGain) < SIMILAR_TNS_THRESHOLD * meanPredictionGain) &&
+ (sts[0]->hTcxEnc->tnsData[k].nFilters == sts[1]->hTcxEnc->tnsData[k].nFilters))
+ {
+ float maxAvgSqrCoef = max(pFilter[0]->avgSqrCoef, pFilter[1]->avgSqrCoef);
+ float meanLtpGain = (sts[0]->hTcxEnc->tcxltp_gain + sts[1]->hTcxEnc->tcxltp_gain) * 0.5f;
+ maxPredGain = max(maxPredGain, meanPredictionGain);
+ if ((meanPredictionGain > pTnsParameters[0]->minPredictionGain) || (maxAvgSqrCoef > pTnsParameters[0]->minAvgSqrCoef))
+ {
+ if (sts[0]->hTcxEnc->tnsData[k].nFilters > 0 || sts[1]->hTcxEnc->tnsData[k].nFilters > 0 || isTCX10 || meanLtpGain < 0.6f)
+ {
+ ++sts[0]->hTcxEnc->tnsData[k].nFilters;
+ pFilter[0]->filterType = TNS_FILTER_ON;
+ ++sts[1]->hTcxEnc->tnsData[k].nFilters;
+ pFilter[1]->filterType = TNS_FILTER_ON;
+ }
+ else
+ {
+ const float maxEnergyChange = (GetTCXMaxenergyChange(sts[0]->hTranDet, isTCX10, NSUBBLOCKS, 3) + GetTCXMaxenergyChange(sts[1]->hTranDet, isTCX10, NSUBBLOCKS, 3)) * 0.5f;
+
+ if (maxEnergyChange >= pTnsParameters[0]->minEnergyChange)
+ {
+ ++sts[0]->hTcxEnc->tnsData[k].nFilters;
+ pFilter[0]->filterType = TNS_FILTER_ON;
+ ++sts[1]->hTcxEnc->tnsData[k].nFilters;
+ pFilter[1]->filterType = TNS_FILTER_ON;
+ }
+ else
+ {
+ pFilter[0]->filterType = TNS_FILTER_OFF;
+ pFilter[1]->filterType = TNS_FILTER_OFF;
+ }
+ }
+ }
+ else if (sts[0]->hTcxEnc->tnsData[k].nFilters > 0 && sts[1]->hTcxEnc->tnsData[k].nFilters > 0) /* If a previous filter is turned on */
+ {
+ pFilter[0]->filterType = TNS_FILTER_ON_ZERO;
+ pFilter[1]->filterType = TNS_FILTER_ON_ZERO;
+ ++sts[0]->hTcxEnc->tnsData[k].nFilters;
+ ++sts[1]->hTcxEnc->tnsData[k].nFilters;
+ }
+ else if (sts[0]->hTcxEnc->tnsData[k].nFilters != sts[1]->hTcxEnc->tnsData[k].nFilters) /* sanity check */
+ {
+ assert(0);
+ }
+ else
+ {
+ pFilter[0]->filterType = TNS_FILTER_OFF;
+ pFilter[1]->filterType = TNS_FILTER_OFF;
+ }
+ if ((pFilter[0]->filterType == TNS_FILTER_ON) && (pFilter[1]->filterType == TNS_FILTER_ON) && (sts[0]->element_brate < IVAS_80k))
+ {
+ int16_t tmpIntValue = 0;
+ int16_t tmpCoeff[TNS_MAX_FILTER_ORDER];
+ int16_t i, maxOrder = max(pFilter[0]->order, pFilter[1]->order);
+
+ set_s(tmpCoeff, 0, TNS_MAX_FILTER_ORDER);
+ for (i = 0; i < maxOrder; i++)
+ {
+ tmpIntValue = (int16_t)max(tmpIntValue, abs(pFilter[0]->coefIndex[i] - pFilter[1]->coefIndex[i]));
+ }
+ if (tmpIntValue == 1) /* the TNS coefficients are sufficiently similar to equalize the two filters */
+ {
+ for (i = maxOrder - 1; i >= 0; i--)
+ {
+ tmpCoeff[i] = (abs(pFilter[0]->coefIndex[i]) < abs(pFilter[1]->coefIndex[i]) ? pFilter[0]->coefIndex[i] : pFilter[1]->coefIndex[i]);
+ if ((tmpIntValue > 0) && (tmpCoeff[i] == 0))
+ {
+ maxOrder--;
+ }
+ else
+ {
+ tmpIntValue = 0;
+ }
+ }
+ /* make sure that maxOrder is non zero and not all coefficients are zero (could happen in rare cases) */
+ if (maxOrder > 0)
+ {
+ for (i = TNS_MAX_FILTER_ORDER - 1; i >= 0; i--)
+ {
+ pFilter[0]->coefIndex[i] = pFilter[1]->coefIndex[i] = tmpCoeff[i];
+ }
+
+ pFilter[0]->order = pFilter[1]->order = maxOrder;
+ }
+ }
+ }
+ }
+ else
+ {
+ individual_decision[k] = 1;
+ }
+ }
+
+ if (individual_decision[k] == 0)
+ {
+ sts[0]->hTcxEnc->fUseTns[k] = (sts[0]->hTcxEnc->tnsData[k].nFilters > 0) ? 1 : 0;
+ sts[1]->hTcxEnc->fUseTns[k] = (sts[1]->hTcxEnc->tnsData[k].nFilters > 0) ? 1 : 0;
+ }
+ else
+ {
+ sts[0]->hTcxEnc->tnsData[k].nFilters = 0;
+ sts[1]->hTcxEnc->tnsData[k].nFilters = 0;
+ sts[0]->hTcxEnc->fUseTns[k] = 0;
+ sts[1]->hTcxEnc->fUseTns[k] = 0;
+ for (iFilter = sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter--)
+ {
+ sts[0]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF;
+ sts[1]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF;
+ }
+ }
+
+ if (!bWhitenedDomain && individual_decision[k] == 0 && maxPredGain < TNS_GAIN_THRESHOLD_FOR_WHITE && sts[0]->hTcxEnc->transform_type[k] != TCX_5)
+ {
+ sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1;
+ sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1;
+ sts[0]->hTcxEnc->tnsData[k].nFilters = 0;
+ sts[1]->hTcxEnc->tnsData[k].nFilters = 0;
+ sts[0]->hTcxEnc->fUseTns[k] = 0;
+ sts[1]->hTcxEnc->fUseTns[k] = 0;
+ for (iFilter = sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter--)
+ {
+ ClearTnsFilterCoefficients(sts[0]->hTcxEnc->tnsData[k].filter + iFilter);
+ ClearTnsFilterCoefficients(sts[1]->hTcxEnc->tnsData[k].filter + iFilter);
+ }
+ }
+ maxPredictionGain = max(maxPredictionGain, maxPredGain);
+ }
+ }
+ }
+ }
+
+ /* individual decision for each channel */
+ for (ch = 0; ch < CPE_CHANNELS; ch++)
+ {
+ if (sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE)
+ {
+ continue;
+ }
+
+ int16_t isTCX10;
+ isTCX10 = (sts[ch]->hTcxEnc->tcxMode == TCX_20) ? 0 : 1;
+
+ nSubframes = (sts[ch]->hTcxEnc->tcxMode == TCX_20) ? 1 : NB_DIV;
+
+ for (k = 0; k < nSubframes; k++)
+ {
+ if (sts[ch]->hTcxCfg->fIsTNSAllowed && (individual_decision[k] || mct_on) &&
+ (!bWhitenedDomain || sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k]))
+ {
+ float maxPredGain = -1.0f;
+
+ sts[ch]->hTcxCfg->pCurrentTnsConfig = &sts[ch]->hTcxCfg->tnsConfig[sts[ch]->hTcxEnc->transform_type[k] == TCX_20][(k == 0) && (sts[ch]->last_core == ACELP_CORE)];
+
+ for (iFilter = sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter--)
+ {
+ STnsFilter* pFilter;
+ const struct TnsParameters* pTnsParameters;
+ pFilter = sts[ch]->hTcxEnc->tnsData[k].filter + iFilter;
+ pTnsParameters = sts[ch]->hTcxCfg->pCurrentTnsConfig->pTnsParameters + iFilter;
+ maxPredGain = max(maxPredGain, pFilter->predictionGain);
+
+ if ((pFilter->predictionGain > pTnsParameters->minPredictionGain) || (pFilter->avgSqrCoef > pTnsParameters->minAvgSqrCoef))
+ {
+ if (sts[ch]->hTcxEnc->tnsData[k].nFilters > 0 || isTCX10 || sts[ch]->hTcxEnc->tcxltp_gain < 0.6f)
+ {
+ ++sts[ch]->hTcxEnc->tnsData[k].nFilters;
+ pFilter->filterType = TNS_FILTER_ON;
+ }
+ else
+ {
+ const float maxEnergyChange = GetTCXMaxenergyChange(sts[ch]->hTranDet, isTCX10, NSUBBLOCKS, 3);
+
+ if (maxEnergyChange >= pTnsParameters->minEnergyChange)
+ {
+ ++sts[ch]->hTcxEnc->tnsData[k].nFilters;
+ pFilter->filterType = TNS_FILTER_ON;
+ }
+ else
+ {
+ pFilter->filterType = TNS_FILTER_OFF;
+ }
+ }
+ }
+ else if (sts[ch]->hTcxEnc->tnsData[k].nFilters > 0) /* If a previous filter is turned on */
+ {
+ pFilter->filterType = TNS_FILTER_ON_ZERO;
+ ++sts[ch]->hTcxEnc->tnsData[k].nFilters;
+ }
+ else
+ {
+ pFilter->filterType = TNS_FILTER_OFF;
+ }
+ }
+
+ sts[ch]->hTcxEnc->fUseTns[k] = (sts[ch]->hTcxEnc->tnsData[k].nFilters > 0) ? 1 : 0;
+
+ if (!bWhitenedDomain && maxPredGain < TNS_GAIN_THRESHOLD_FOR_WHITE && sts[ch]->hTcxEnc->transform_type[k] != TCX_5)
+ {
+ sts[ch]->hTcxEnc->fUseTns[k] = 0;
+ sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k] = 1;
+ sts[ch]->hTcxEnc->tnsData[k].nFilters = 0;
+ for (iFilter = sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter--)
+ {
+ ClearTnsFilterCoefficients(sts[ch]->hTcxEnc->tnsData[k].filter + iFilter);
+ sts[ch]->hTcxEnc->tnsData[k].filter[iFilter].filterType = TNS_FILTER_OFF;
+ }
+ }
+ maxPredictionGain = max(maxPredictionGain, maxPredGain);
+ }
+ }
+ }
+
+
+ /* we have the decision, set filter data accordingly */
+ for (ch = 0; ch < CPE_CHANNELS; ch++)
+ {
+ if (sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE)
+ {
+ continue;
+ }
+
+ nSubframes = (sts[ch]->hTcxEnc->tcxMode == TCX_20) ? 1 : NB_DIV;
+
+ for (k = 0; k < nSubframes; k++)
+ {
+ if (sts[ch]->hTcxCfg->fIsTNSAllowed && (!bWhitenedDomain || sts[ch]->hTcxEnc->bTnsOnWhithenedSpectra[k]))
+ {
+ sts[ch]->hTcxCfg->pCurrentTnsConfig = &sts[ch]->hTcxCfg->tnsConfig[sts[ch]->hTcxEnc->transform_type[k] == TCX_20][(k == 0) && (sts[ch]->last_core == ACELP_CORE)];
+
+ for (iFilter = sts[ch]->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter--)
+ {
+ STnsFilter* pFilter;
+ pFilter = sts[ch]->hTcxEnc->tnsData[k].filter + iFilter;
+ switch (pFilter->filterType)
+ {
+ case TNS_FILTER_OFF:
+ ClearTnsFilterCoefficients(sts[ch]->hTcxEnc->tnsData[k].filter + iFilter);
+ break;
+ case TNS_FILTER_ON_ZERO:
+ /* Since TNS filter of order 0 is not allowed we have to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */
+ ClearTnsFilterCoefficients(pFilter);
+ pFilter->order = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* Apply filters, loop over channels */
+ for (ch = 0; ch < CPE_CHANNELS; ch++)
+ {
+ st = sts[ch];
+ if (st->mct_chan_mode == MCT_CHAN_MODE_IGNORE)
+ {
+ continue;
+ }
+
+ nSubframes = (st->hTcxEnc->tcxMode == TCX_20) ? 1 : NB_DIV;
+
+ for (k = 0; k < nSubframes; k++)
+ {
+ if (bWhitenedDomain && (ch > 0) && /* test for identical TNS filter data in both channels */
+ sts[0]->hTcxCfg->fIsTNSAllowed && sts[0]->hTcxEnc->fUseTns[k] &&
+ sts[1]->hTcxCfg->fIsTNSAllowed && sts[1]->hTcxEnc->fUseTns[k])
+ {
+ int16_t equalFilterData = (sts[0]->hTcxCfg->pCurrentTnsConfig->nMaxFilters == sts[1]->hTcxCfg->pCurrentTnsConfig->nMaxFilters &&
+ sts[0]->hTcxEnc->bTnsOnWhithenedSpectra[k] == sts[1]->hTcxEnc->bTnsOnWhithenedSpectra[k] &&
+ sts[0]->hTcxEnc->tnsData[k].nFilters == sts[1]->hTcxEnc->tnsData[k].nFilters)
+ ? 1
+ : 0;
+ if (equalFilterData)
+ {
+ for (iFilter = st->hTcxCfg->pCurrentTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter--)
+ {
+ const int16_t* pDataCh0 = (const int16_t*)&sts[0]->hTcxEnc->tnsData[k].filter[iFilter];
+ const int16_t* pDataCh1 = (const int16_t*)&sts[1]->hTcxEnc->tnsData[k].filter[iFilter];
+ int16_t i = 2 + TNS_MAX_FILTER_ORDER; /* excl. informative float data. Portable? */
+
+ while ((i >= 0) && (pDataCh0[i] == pDataCh1[i]))
+ {
+ i--;
+ }
+ if (i >= 0)
+ {
+ equalFilterData = 0;
+ break;
+ }
+ }
+ if (equalFilterData)
+ {
+ st->hTcxEnc->tnsData[k].nFilters *= -1; /* signals common TNS */
+ }
+ }
+ }
+ if (st->hTcxCfg->fIsTNSAllowed && (!bWhitenedDomain || st->hTcxEnc->bTnsOnWhithenedSpectra[k]))
+ {
+ L_spec = st->hTcxCfg->pCurrentTnsConfig->iFilterBorders[0];
+ spectrum = st->hTcxEnc->spectrum[k];
+ /* If TNS should be used then get the residual after applying it inplace in the spectrum */
+ if (st->hTcxEnc->fUseTns[k])
+ {
+ st->hTcxCfg->pCurrentTnsConfig = &st->hTcxCfg->tnsConfig[st->hTcxEnc->transform_type[k] == TCX_20][(k == 0) && (st->last_core == ACELP_CORE)];
+
+ ApplyTnsFilter(st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], spectrum, 1);
+ }
+
+ if (st->hTcxEnc->transform_type[k] == TCX_5)
+ {
+ tcx5TnsUngrouping(L_frame >> 2, L_spec >> 1, st->hTcxEnc->spectrum[k], ENC);
+ }
+
+ st->hTcxEnc->tnsData[k].tnsOnWhitenedSpectra = st->hTcxEnc->bTnsOnWhithenedSpectra[k];
+
+ EncodeTnsData(st->hTcxCfg->pCurrentTnsConfig, &st->hTcxEnc->tnsData[k], param_core[ch] + k * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, tnsSize[ch] + k, tnsBits[ch] + k);
+ }
+
+ if (st->hTcxEnc->transform_type[k] == TCX_5)
+ {
+ tcx5SpectrumInterleaving(st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum[k]);
+ tcx5SpectrumInterleaving(st->hTcxCfg->tcx5SizeFB, mdst_spectrum[ch][k]);
+ }
+ }
+ }
+
+ return;
+}
+
+
+#endif
+void TNSAnalysis_fx(
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
+ Word16 L_frame, /* input: frame length */
+ Word16 L_spec,
+ Word16 tcxMode, /* input: TCX mode for the frame/subframe - TCX20 | TCX10 | TCX 5 (meaning 2 x TCX 5) */
+ Word8 isAfterACELP, /* input: Flag indicating if the last frame was ACELP. For the second TCX subframe it should be 0 */
+ Word32 spectrum[], /* input: MDCT spectrum */
+ STnsData * pTnsData, /* output: Tns data */
+ Word8 * pfUseTns, /* output: Flag indicating if TNS is used */
+ Word16 *predictionGain
+)
+{
+ Word32 buff[8];
+ Word16 tmp = 0; /* initialization only to avoid compiler warning, not counted */
+ Word16 tmp2 = 0; /* initialization only to avoid compiler warning, not counted */
+
+
+ /* Init TNS */
+ *pfUseTns = 0;
+ move16();
+
+ IF (hTcxCfg->fIsTNSAllowed != 0)
+ {
+ hTcxCfg->pCurrentTnsConfig = &hTcxCfg->tnsConfig[sub(tcxMode, TCX_20) == 0][isAfterACELP];
+ test();
+ L_spec = hTcxCfg->pCurrentTnsConfig->iFilterBorders[0];
+ move16();
+
+ /*-----------------------------------------------------------*
+ * Temporal Noise Shaping analysis *
+ *-----------------------------------------------------------*/
+
+ IF (EQ_16(tcxMode, TCX_5))
+ {
+ tmp = shr(L_frame,2);
+
+ /* rearrange LF sub-window lines prior to TNS analysis & filtering */
+ tmp2 = shr(L_spec,1);
+
+ IF (LT_16(tmp2, tmp))
+ {
+ Copy32(spectrum+8, spectrum+16, sub(tmp2, 8));
+ Copy32(spectrum+tmp, spectrum+8, 8);
+ Copy32(spectrum+tmp+8, spectrum+tmp2+8, sub(tmp2, 8));
+ }
+ ELSE
+ {
+ Copy32(spectrum+tmp, buff, 8);
+ Copy32(spectrum+8, spectrum+16, sub(tmp, 8));
+ Copy32(buff, spectrum+8, 8);
+ }
+ }
+
+ move16();
+ *pfUseTns = (Word8)DetectTnsFilt_fx(hTcxCfg->pCurrentTnsConfig, spectrum, pTnsData, predictionGain);
+
+ /* If TNS should be used then get the residual after applying it inplace in spectrum */
+ IF (*pfUseTns != 0)
+ {
+ ApplyTnsFilter(hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 1);
+ }
+
+ IF (EQ_16(tcxMode, TCX_5))
+ {
+ /* undo rearrangement of LF sub-window lines prior to TNS analysis */
+ IF (LT_16(tmp2, tmp))
+ {
+ Copy32(spectrum+tmp2+8, spectrum+tmp+8, sub(tmp2, 8));
+ Copy32(spectrum+8, spectrum+tmp, 8);
+ Copy32(spectrum+16, spectrum+8, sub(tmp2, 8));
+ set32_fx(spectrum+tmp2, 0, sub(tmp,tmp2));
+ set32_fx(spectrum+tmp+tmp2, 0, sub(tmp,tmp2));
+ }
+ ELSE
+ {
+ Copy32(spectrum+8, buff, 8);
+ Copy32(spectrum+16, spectrum+8, sub(tmp, 8));
+ Copy32(buff, spectrum+tmp, 8);
+ }
+ }
+ }
+
+}
+
+void ShapeSpectrum_fx(
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
+ Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */
+ Word16 gainlpc[], /* output: MDCT gains for the previous frame */
+ Word16 gainlpc_e[], /* output: MDCT gains exponents */
+ Word16 L_frame_glob,/* input: frame length */
+ Word16 L_spec,
+ Word32 spectrum[], /* i/o: MDCT spectrum */
+ Word8 pfUseTns, /* output: Flag indicating if TNS is used */
+ Encoder_State_fx *st
+)
+{
+ Word16 L_frame;
+ Word16 Ap[M+2];
+ Word16 gamma1;
+ Word16 gainlpc_noinv[FDNS_NPTS];
+ Word16 gainlpc_noinv_e[FDNS_NPTS];
+ Word16 i;
+ Word32 max_low_pre = 0, max_high_pre = 0;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ /*-----------------------------------------------------------*
+ * Init *
+ *-----------------------------------------------------------*/
+
+ /* Init lengths */
+ L_frame = L_frame_glob;
+ move16();
+ gamma1 = st->gamma;
+ move16();
+ if (st->enableTcxLpc != 0)
+ {
+ gamma1 = 0x7FFF;
+ move16();
+ }
+
+ /* if past frame is ACELP */
+
+ IF (st->last_core_fx == ACELP_CORE)
+ {
+ L_frame = add(L_frame, hTcxCfg->tcx_offset);
+ L_spec = add(L_spec, shr(hTcxCfg->tcx_coded_lines, 2));
+ if(hTcxCfg->lfacNext<0)
+ {
+ L_frame = sub(L_frame,hTcxCfg->lfacNext);
+ move16();
+ }
+ }
+
+ test();
+ tcxGetNoiseFillingTilt(A,
+ M,
+ L_frame,
+ (GE_32(st->total_brate_fx, ACELP_13k20) && st->rf_mode == 0 ),
+ &hTcxEnc->noiseTiltFactor);
+
+ /* Calculate Spectrum Flatness Measure for the TCX Concealment */
+ IF (st->enablePlcWaveadjust)
+ {
+ hTcxCfg->SFM2 = SFM_Cal_fx(spectrum, s_min(200, L_frame));
+ }
+
+ test();
+ test();
+ test();
+ IF( (EQ_32(st->total_brate_fx, ACELP_9k60)&&EQ_16(st->bwidth_fx,SWB))||
+ (EQ_32(st->total_brate_fx, ACELP_13k20) && EQ_16(st->bwidth_fx, SWB) ) )
+ {
+ max_low_pre = 0;
+ move32();
+ FOR (i = 0; i < L_frame; i++)
+ {
+ Word32 tmp = L_abs(spectrum[i]);
+ if( GT_32(tmp, max_low_pre))
+ {
+ max_low_pre = tmp;
+ move32();
+ }
+ }
+
+ max_high_pre = 0;
+ move32();
+ for (i = 0; i < L_spec - L_frame; i++)
+ {
+ Word32 tmp = L_abs(spectrum[L_frame + i]);
+ if( GT_32( tmp, max_high_pre))
+ {
+ max_high_pre = tmp;
+ move32();
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------*
+ * Pre-shaping in frequency domain using weighted LPC (Wz) *
+ *-----------------------------------------------------------*/
+
+ weight_a_fx( A, Ap, gamma1, M );
+
+ lpc2mdct( Ap, M, gainlpc_noinv, gainlpc_noinv_e, gainlpc, gainlpc_e, FDNS_NPTS, 0);
+
+ mdct_shaping( spectrum, L_frame, gainlpc_noinv, gainlpc_noinv_e );
+ FOR (i = L_frame; i < L_spec; i++)
+ {
+ spectrum[i] = L_shl(Mpy_32_16_1(spectrum[i], gainlpc_noinv[FDNS_NPTS-1]), gainlpc_noinv_e[FDNS_NPTS-1]);
+ move32();
+ }
+
+ /* reduce the peaks in the IGF region, to make life of the core-coder easier... */
+ test();
+ IF( ( EQ_32(st->total_brate_fx, ACELP_9k60)&&EQ_16(st->bwidth_fx,SWB))||
+ ( EQ_32(st->total_brate_fx, ACELP_13k20)&&EQ_16(st->bwidth_fx, SWB)) )
+ {
+ Word16 sf_width;
+ Word16 dist_low, dist_high;
+ Word16 max_fac_s, max_fac_m;
+ Word32 max_low, max_low1, max_low2, max_high;
+ Word16 headroom, shift, tmp16;
+
+
+ max_fac_m = 24576;
+ move16();
+ /* max_fac = 3 */
+ max_fac_s = 2;
+ move16();
+ if(hTcxEnc->tcx_lpc_shaped_ari )
+ {
+ /* max_fac = 1.5 */
+ max_fac_s = 1;
+ move16();
+ }
+
+ sf_width = shr(L_frame, 1);
+
+ max_low2 = 0;
+ move32();
+ dist_low = 0;
+ move16();
+ FOR (i = 0; i < sf_width; i++)
+ {
+ Word32 tmp = L_abs(spectrum[L_frame - 1 - i]);
+ IF( GT_32(tmp, max_low2))
+ {
+ max_low2 = tmp;
+ move32();
+ dist_low = i;
+ move16();
+ }
+ }
+
+ max_low1 = 0;
+ move32();
+ FOR (i = 0; i < sub(L_frame, sf_width); i++)
+ {
+ Word32 tmp = L_abs(spectrum[L_frame - sf_width - 1 - i]);
+ if( GT_32(tmp, max_low1))
+ {
+ max_low1 = tmp;
+ move32();
+ }
+ if( tmp > max_low2 )
+ {
+ dist_low = add(sf_width, i);
+ }
+ }
+
+ max_low = L_max(max_low1, max_low2);
+
+ max_high = 0;
+ move32();
+ dist_high = 0;
+ move16();
+ FOR (i = 0; i < sub(L_spec, L_frame); i++)
+ {
+ Word32 tmp = L_abs(spectrum[L_frame + i]);
+ if( GT_32(tmp, max_high))
+ {
+ max_high = tmp;
+ move32();
+ dist_high = i;
+ move16();
+ }
+ }
+
+ /* at least 9 bits headroom are needed for below multiplicitions */
+ shift = 0;
+ move16();
+ headroom = 31;
+ move16();
+
+ tmp16 = norm_l(max_low);
+ if(max_low != 0) headroom = s_min(headroom, tmp16);
+
+ tmp16 = norm_l(max_low2);
+ if(max_low2 != 0) headroom = s_min(headroom, tmp16);
+
+ tmp16 = norm_l(max_high);
+ if(max_high != 0) headroom = s_min(headroom, tmp16);
+
+ if( LT_16(headroom, 9))
+ {
+ shift = sub(9, headroom);
+ }
+ max_low = L_shr(max_low, shift);
+ max_low2 = L_shr(max_low2, shift);
+ max_high = L_shr(max_high, shift);
+
+ test();
+ test();
+ IF( GT_32(imult3216(max_high, dist_high), imult3216(L_shr(max_low, 2), dist_low))&&(GT_32(max_low_pre,L_shr(max_high_pre,4)))&&(GT_32(max_high,L_shl(Mpy_32_16_r(max_low2,max_fac_m),max_fac_s))))
+ {
+ Word16 fac;
+ fac = divide3232(max_low2, max_high);
+ fac = shl(mult_r( fac, max_fac_m ), max_fac_s);
+
+ FOR (i = 0; i < sub(L_spec, L_frame); i++)
+ {
+ spectrum[L_frame + i] = Mpy_32_16_1(spectrum[L_frame + i], fac);
+ }
+ }
+ }
+
+
+ test();
+ test();
+ test();
+ IF( st->tcxonly && hTcxEnc->tcxltp && (hTcxEnc->tcxltp_gain > 0) && !pfUseTns )
+ {
+ PsychAdaptLowFreqEmph_fx(spectrum, gainlpc, gainlpc_e);
+ }
+
+}
+#ifdef ADD_IVAS_TNS
+/*-----------------------------------------------------------*
+ * EstimateStereoTCXNoiseLevel()
+ *
+ * Estimate and quantize stereo noise factors
+ *-----------------------------------------------------------*/
+
+void EstimateStereoTCXNoiseLevel(
+ Encoder_State** sts, /* i : state handle */
+ float* q_spectrum[CPE_CHANNELS][NB_DIV], /* i : quantized MDCT spectrum */
+ float gain_tcx[][NB_DIV], /* i : global gain */
+ int16_t L_frame[][NB_DIV], /* i : frame length */
+ int16_t noiseFillingBorder[][NB_DIV], /* i : noise filling border */
+ int16_t hm_active[][NB_DIV], /* i : flag indicating if the harmonic model is active */
+ const int16_t ignore_chan[], /* i : flag indicating whether the channel should be ignored */
+ float fac_ns[][NB_DIV], /* o : noise filling level */
+ int16_t param_core[][NB_DIV * NPRM_DIV], /* o : quantized noise filling level */
+ const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */
+)
+{
+ int16_t ch, n;
+ int16_t nSubframes, maxNfCalcBw, iStart, noiseTransWidth;
+ float smooth_gain;
+ float combined_q_spectrum[N_MAX];
+ int16_t* fac_ns_q;
+ int32_t total_brate;
+
+ for (ch = 0; ch < CPE_CHANNELS; ch++)
+ {
+ Encoder_State* st = sts[ch];
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ nSubframes = (st->hTcxEnc->tcxMode == TCX_20) ? 1 : NB_DIV;
+
+ if (ignore_chan[ch])
+ {
+ continue;
+ }
+ total_brate = (st->element_mode == IVAS_CPE_MDCT && !MCT_flag) ? st->element_brate : st->total_brate;
+
+ for (n = 0; n < nSubframes; n++)
+ {
+ fac_ns_q = param_core[ch] + n * NPRM_DIV + 1;
+ maxNfCalcBw = min(noiseFillingBorder[ch][n], (int16_t)(hTcxEnc->measuredBwRatio * (float)L_frame[ch][n] + 0.5f));
+ if ((total_brate >= HQ_96k && (st->element_mode <= IVAS_SCE || st->bwidth < SWB)) || total_brate > IVAS_192k)
+ {
+ fac_ns[ch][n] = 0.0f;
+ *fac_ns_q = 0;
+ }
+ else
+ {
+ iStart = L_frame[ch][n] / ((total_brate >= ACELP_13k20 && !st->rf_mode) ? 6 : 8); /* noise filling start bin*/
+
+ if (n == 0)
+ {
+ mvr2r(hTcxEnc->ltpGainMemory, &hTcxEnc->ltpGainMemory[1], N_LTP_GAIN_MEMS - 1);
+ hTcxEnc->ltpGainMemory[0] = st->hTcxEnc->tcxltp_gain;
+ }
+
+ smooth_gain = dotp(hTcxEnc->ltpGainMemory, nf_tw_smoothing_coeffs, N_LTP_GAIN_MEMS);
+
+ noiseTransWidth = GetTransWidth(st->tcxonly, (L_frame[ch][n] == st->L_frame >> 1), smooth_gain, (st->hTcxCfg->ctx_hm && st->last_core != ACELP_CORE && hm_active[ch][n]));
+
+ mvr2r(q_spectrum[ch][n], combined_q_spectrum, L_frame[ch][n]);
+ tcx_noise_factor(hTcxEnc->spectrum[n], combined_q_spectrum, iStart, maxNfCalcBw, noiseTransWidth, L_frame[ch][n], gain_tcx[ch][n], hTcxEnc->noiseTiltFactor, &fac_ns[ch][n], fac_ns_q, st->element_mode);
+
+ /* hysteresis for very tonal passages (more stationary noise filling level) */
+ if (*fac_ns_q == 1)
+ {
+ hTcxEnc->noiseLevelMemory_cnt = (int16_t)min(INT16_MAX, 1 + abs(hTcxEnc->noiseLevelMemory_cnt)); /* update counter */
+ }
+ else
+ {
+ if ((*fac_ns_q == 2) && (abs(hTcxEnc->noiseLevelMemory_cnt) > 5))
+ {
+ *fac_ns_q = 1; /* reduce noise filling level by one step */
+ fac_ns[ch][n] = 0.75f / (1 << NBITS_NOISE_FILL_LEVEL);
+
+ /* signal that noise level is changed by inverting sign of level memory */
+ hTcxEnc->noiseLevelMemory_cnt = (hTcxEnc->noiseLevelMemory_cnt < 0) ? 5 : -1 - hTcxEnc->noiseLevelMemory_cnt;
+ }
+ else
+ {
+ hTcxEnc->noiseLevelMemory_cnt = 0; /* reset memory since level is too different */
+ }
+ }
+ } /* bitrate */
+ }
+#ifdef DEBUG_MODE_MDCT
+ dbgwrite(&smooth_gain, sizeof(float), 1, 1, "./res/smooth_gain");
+ dbgwrite(&st->hTcxEnc->tcxltp_gain, sizeof(float), 1, 1, "./res/tcxltp_gain");
+ dbgwrite(&noiseTransWidth, sizeof(int16_t), 1, 1, "./res/noiseTrans");
+ dbgwrite(&fac_ns[ch][0], sizeof(float), 2, 1, "./res/fac_ns");
+#endif
+ }
+
+ return;
+}
+
+
+/*-----------------------------------------------------------*
+ * DecideTonalSideInfo()
+ *
+ *
+ *-----------------------------------------------------------*/
+
+static int16_t DecideTonalSideInfo(
+ const float spectrum[],
+ const int16_t L_frame_glob,
+ float SFM2)
+{
+ float SFM, K, K2;
+ int16_t Tonal_SideInfo;
+
+ SFM = SFM_Cal(spectrum, min(200, L_frame_glob));
+
+ if (L_frame_glob <= 256)
+ {
+ K = 0.4f;
+ K2 = 0.1f;
+ }
+ else if (L_frame_glob == 320 || L_frame_glob == 512)
+ {
+ K = 0.4f;
+ K2 = 0.1f;
+ }
+ else /*FrameSize_Core == 640*/
+ {
+ K = 0.35f;
+ K2 = 0.04f;
+ }
+
+
+ Tonal_SideInfo = 0;
+ if (SFM < K)
+ {
+ Tonal_SideInfo = 1;
+ }
+
+ if (SFM2 < K2)
+ {
+ Tonal_SideInfo = 1;
+ }
+
+ return Tonal_SideInfo;
+}
+#endif
+
+void QuantizeSpectrum_fx(
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
+ Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */
+ Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */
+ Word16 gainlpc[], /* input: MDCT gains of the previous frame */
+ Word16 gainlpc_e[], /* input: MDCT gains exponents */
+ Word16 synth[],
+ Word16 L_frame_glob, /* input: frame length */
+ Word16 L_frameTCX_glob,
+ Word16 L_spec,
+ Word16 nb_bits, /*input: bit budget*/
+ Word8 tcxonly, /*input: only TCX flag*/
+ Word32 spectrum[], /* i/o: MDCT spectrum, input is shaped MDCT spectrum */
+ Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */
+ STnsData * pTnsData, /* input: Tns data */
+ Word8 fUseTns, /* input: Flag indicating if TNS is used */
+ Word16 tnsSize, /* input: number of tns parameters put into prm */
+ Word16 prm[], /* output: tcx parameters */
+ Word16 frame_cnt, /* input: frame counter in the super_frame */
+ Encoder_State_fx *st,
+ CONTEXT_HM_CONFIG *hm_cfg
+)
+{
+ Word16 i, L_frame, tcx_offset;
+ Word16 stop;
+ Word16 tmp1, tmp2, tmp3, tmp4, s;
+ Word32 tmp32;
+ Word8 tmp8;
+ Word16 *tmpP16;
+ Word16 L_frameTCX;
+ Word16 fac_ns;
+ Word16 nf_seed;
+ Word32 ener;
+ Word16 ener_e;
+ Word16 gain_tcx, gain_tcx_e;
+ Word16 sqBits;
+ Word16 overlap;
+ Word16 noiseFillingSize;
+ Word16 noiseTransWidth;
+ Word32 *OriginalSpectrum;
+ Word16 OriginalSpectrum_e;
+ Word16 ctxHmBits;
+ Word16 resQBits;
+ Word16 *signs;
+ Word16 signaling_bits;
+ Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *prm_target;
+ Word16 Aq_old[M+1];
+ Word32 SFM;
+ Word32 K, K2;
+ Word16 aldo; /* ALDO flag in current frame*/
+ Word16 nz; /* non-zero length in ALDO window*/
+ CONTEXT_HM_CONFIG * phm_cfg;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+ Flag Carry = 0;
+#endif
+
+ /* Stack memory is split between encoder and internal decoder to reduce max
+ stack memory usage. */
+ {
+ Word16 sqTargetBits;
+ Word16 gain_tcx_opt, gain_tcx_opt_e;
+ Word16 sqGain, sqGain_e;
+ Word16 sqBits_noStop;
+ Word16 nEncoded;
+ Word16 maxNfCalcBw;
+ Word16 PeriodicityIndex;
+ Word16 NumIndexBits;
+ Word16 nEncodedCtxHm, stopCtxHm, sqBitsCtxHm, Selector;
+ Word16 lastnz, lastnzCtxHm;
+ Word16 RelativeScore;
+ Word32 x_orig[N_MAX];
+ Word16 x_orig_e;
+ Word16 resQTargetBits;
+ Word16 xn_buf16[L_FRAME_PLUS];
+ Word16 *sqQ;
+ Word16 LtpPitchLag;
+
+
+ sqGain = 0x4000;
+ move16();
+ sqGain_e = 1;
+ move16();
+ noiseTransWidth = MIN_NOISE_FILLING_HOLE;
+ move16();
+ resQTargetBits = 0;
+ move16();
+
+ /*-----------------------------------------------------------*
+ * Init *
+ *-----------------------------------------------------------*/
+
+ /* Init lengths */
+ L_frame = L_frame_glob;
+ move16();
+ L_frameTCX = L_frameTCX_glob;
+ move16();
+ overlap = hTcxCfg->tcx_mdct_window_length;
+ move16();
+ aldo = 0;
+ move16();
+ nz = NS2SA_fx2(st->sr_core, N_ZERO_MDCT_NS);
+ move16();
+ /* Modified the overlap to the delay in case of short blocks*/
+ tcx_offset = hTcxCfg->tcx_offset;
+ move16();
+
+ OriginalSpectrum = NULL;
+ signs = NULL; /* silence warning */
+ NumIndexBits = 0;
+ move16();
+ sqBits = 0;
+ move16();
+ ctxHmBits = 0;
+ move16();
+ resQBits = 0;
+ move16();
+ prm_ltp = &prm[1+NOISE_FILL_RANGES];
+ move16();
+ prm_tns = prm_ltp + LTPSIZE;
+ move16();
+ prm_hm = prm_tns + tnsSize;
+ move16();
+ prm_lastnz = prm_hm + 2;
+ move16();
+ sqQ = prm_hm + NPRM_CTX_HM;
+ move16();
+
+ /* if past frame is ACELP */
+
+ IF (st->last_core_fx == ACELP_CORE)
+ {
+ hTcxCfg->last_aldo = 0;
+ move16();
+
+ L_frame = add(L_frame, tcx_offset);
+ L_frameTCX = add(L_frameTCX, hTcxCfg->tcx_offsetFB);
+ L_spec = add(L_spec, shr(hTcxCfg->tcx_coded_lines, 2));
+ tcx_offset = 0;
+ move16();
+ IF(hTcxCfg->lfacNext<0)
+ {
+ L_frame = sub(L_frame,hTcxCfg->lfacNext);
+ L_frameTCX = sub(L_frameTCX, hTcxCfg->lfacNextFB);
+ tcx_offset = hTcxCfg->lfacNext;
+ move16();
+ }
+ hTcxEnc->noiseLevelMemory_cnt = 0;
+ move16();
+ }
+
+
+ E_LPC_f_lsp_a_conversion(st->lsp_old_fx, Aq_old, M);
+
+ /* target bitrate for SQ */
+ sqTargetBits = sub(nb_bits, 7 + NBITS_NOISE_FILL_LEVEL);
+
+ /*Unquantized spectrum here*/
+ IF (st->enablePlcWaveadjust)
+ {
+
+
+ SFM = SFM_Cal_fx(spectrum, s_min(200, L_frame_glob));
+ test();
+ IF (LE_16(L_frame_glob, 256))
+ {
+ K = 0x33333333;
+ move32();
+ K2 = 0xCCCCCCD;
+ move32();
+ }
+ ELSE IF (EQ_16(L_frame_glob,320)||EQ_16(L_frame_glob,512))
+ {
+ K = 0x33333333;
+ move32();
+ K2 = 0xCCCCCCD;
+ move32();
+ }
+ ELSE /*FrameSize_Core == 640*/
+ {
+ K = 0x2CCCCCCD;
+ move32();
+ K2 = 0x51EB852;
+ move32();
+ }
+
+
+ IF ( LT_32(SFM, K))
+ {
+ st->Tonal_SideInfo = 1;
+ move16();
+ }
+ ELSE
+ {
+ st->Tonal_SideInfo = 0;
+ move16();
+ }
+
+ if ( LT_32(hTcxCfg->SFM2, K2))
+ {
+ st->Tonal_SideInfo = 1;
+ move16();
+ }
+ }
+
+ /* Save pre-shaped spectrum*/
+ Copy32(spectrum, x_orig, L_spec);
+ x_orig_e = *spectrum_e;
+ move16();
+
+ /*-----------------------------------------------------------*
+ * Bandwidth Limitation *
+ *-----------------------------------------------------------*/
+
+ noiseFillingSize = L_spec;
+ move16();
+ IF (st->igf != 0)
+ {
+ noiseFillingSize = st->hIGFEnc->infoStartLine;
+ move16();
+ }
+ ELSE
+ {
+ st->hIGFEnc->infoStopLine = noiseFillingSize;
+ move16();
+ }
+
+ FOR (i=st->hIGFEnc->infoStopLine; itcx_lpc_shaped_ari == 0) /* old arithmetic coder */
+ {
+
+ /* Fast estimation of the scalar quantizer step size */
+ test();
+ IF ((hTcxCfg->ctx_hm != 0) && (st->last_core_fx != ACELP_CORE))
+ {
+ LtpPitchLag = -1;
+ move16();
+
+ test();
+ IF ((tcxonly == 0) && (LT_16(hTcxEnc->tcxltp_pitch_int, st->L_frame_fx)))
+ {
+ tmp32 = L_shl(L_mult0(st->L_frame_fx, st->pit_res_max), 1+kLtpHmFractionalResolution+1);
+ tmp1 = add(imult1616(hTcxEnc->tcxltp_pitch_int, st->pit_res_max), hTcxEnc->tcxltp_pitch_fr);
+ LtpPitchLag = div_l(tmp32, tmp1);
+ }
+
+ ctxHmBits = add(ctxHmBits, 1); /* ContextHM flag */
+ sqTargetBits = sub(sqTargetBits, 1); /* ContextHM flag */
+
+ OriginalSpectrum = spectrum;
+ OriginalSpectrum_e = *spectrum_e;
+ move16();
+
+ tmp1 = -1;
+ move16();
+ if (hTcxEnc->tcxltp != 0)
+ {
+ tmp1 = hTcxEnc->tcxltp_gain;
+ move16();
+ }
+ PeriodicityIndex = SearchPeriodicityIndex_fx(
+ OriginalSpectrum,
+ NULL,
+ L_spec,
+ sqTargetBits,
+ LtpPitchLag,
+ tmp1,
+ &RelativeScore
+ );
+
+ ConfigureContextHm(
+ L_spec,
+ sqTargetBits,
+ PeriodicityIndex,
+ LtpPitchLag,
+ hm_cfg
+ );
+
+ tmp1 = 1;
+ move16();
+ if (LT_16(L_spec, 256))
+ {
+ tmp1 = 0;
+ move16();
+ }
+ NumIndexBits = CountIndexBits( tmp1, PeriodicityIndex);
+
+
+
+ /* Quantize original spectrum */
+
+ sqGain = SQ_gain_fx(OriginalSpectrum, OriginalSpectrum_e,
+ shl(mult(hTcxEnc->tcx_target_bits_fac, sqTargetBits), 1),
+ L_spec,
+ &sqGain_e);
+
+ tcx_scalar_quantization_fx(OriginalSpectrum, OriginalSpectrum_e,
+ sqQ,
+ L_spec,
+ sqGain, sqGain_e,
+ hTcxCfg->sq_rounding,
+ hTcxEnc->memQuantZeros_fx,
+ tcxonly);
+
+ /* Estimate original bitrate */
+ stop = 0;
+ move16();
+
+ sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx(sqQ,
+ L_spec,
+ &lastnz,
+ &nEncoded,
+ sqTargetBits,
+ &stop,
+ NULL);
+
+ /* Estimate context mapped bitrate */
+
+ stopCtxHm = 0;
+ move16();
+
+ /* Context Mapping */
+ sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx(sqQ,
+ L_spec,
+ &lastnzCtxHm,
+ &nEncodedCtxHm,
+ sub(sqTargetBits, NumIndexBits),
+ &stopCtxHm,
+ hm_cfg
+ );
+
+ /* Decide whether or not to use context mapping */
+ Selector = sub(s_max(stop, sqBits), add(s_max(stopCtxHm, sqBitsCtxHm), NumIndexBits));
+
+ test();
+ test();
+ IF ((GT_16(Selector, 2))||((LE_16(abs_s(Selector),2))&&
+ (LT_16(kCtxHmOlRSThr, RelativeScore) )))
+ {
+ /* CtxHm is likely better */
+ sqTargetBits = sub(sqTargetBits, NumIndexBits);
+ ctxHmBits = add(ctxHmBits, NumIndexBits);
+ prm_hm[0] = 1;
+ move16();
+ prm_hm[1] = PeriodicityIndex;
+ move16();
+ *prm_lastnz = lastnzCtxHm;
+ move16();
+ sqBits_noStop = sqBits = sqBitsCtxHm;
+ move16();
+ move16();
+ nEncoded = nEncodedCtxHm;
+ move16();
+ stop = stopCtxHm;
+ move16();
+ }
+ ELSE /* Original is better or not much difference */
+ {
+ prm_hm[0] = 0;
+ move16();
+ prm_hm[1] = PeriodicityIndex;
+ move16();
+ *prm_lastnz = lastnz;
+ move16();
+ PeriodicityIndex = -1;
+ move16();
+
+ sqBits_noStop = sqBits;
+ move16();
+ }
+
+
+ if (stop != 0)
+ {
+
+ sqBits = stop;
+ move16();
+ }
+ }
+ ELSE /* no context hm*/
+ {
+ PeriodicityIndex = -1;
+ move16();
+
+ sqGain = SQ_gain_fx(spectrum, *spectrum_e,
+ shl(mult(hTcxEnc->tcx_target_bits_fac, sqTargetBits), 1),
+ L_spec,
+ &sqGain_e);
+
+ /* Quantize spectrum */
+
+ tcx_scalar_quantization_fx(spectrum, *spectrum_e,
+ sqQ,
+ L_spec,
+ sqGain, sqGain_e,
+ hTcxCfg->sq_rounding,
+ hTcxEnc->memQuantZeros_fx,
+ tcxonly
+ );
+
+ /* Estimate bitrate */
+ stop = 0;
+ move16();
+ sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx(sqQ,
+ L_spec,
+ prm_lastnz, /* lastnz */
+ &nEncoded,
+ sqTargetBits,
+ &stop,
+ NULL);
+
+ sqBits_noStop = sqBits;
+ move16();
+
+ if (stop != 0)
+ {
+ sqBits = stop;
+ move16();
+ }
+ } /* end of if (ctx_hm) */
+
+ /* Adjust correction factor */
+ tmp1 = sqBits;
+ move16();
+
+ if (s_and(L_spec, sub(L_spec, 1)) == 0) /* power-of-2 */
+ {
+ tmp1 = add(tmp1, 1);
+ }
+
+ tmp1 = BASOP_Util_Divide1616_Scale(sqTargetBits, tmp1, &tmp2);
+ BASOP_SATURATE_WARNING_OFF_EVS
+#ifdef BASOP_NOGLOB
+ hTcxEnc->tcx_target_bits_fac = shl_o(mult(hTcxEnc->tcx_target_bits_fac, tmp1), tmp2, &Overflow);
+#else /* BASOP_NOGLOB */
+ hTcxEnc->tcx_target_bits_fac = shl(mult(hTcxEnc->tcx_target_bits_fac, tmp1), tmp2);
+#endif /* BASOP_NOGLOB */
+ BASOP_SATURATE_WARNING_ON_EVS
+
+ if (GT_16(hTcxEnc->tcx_target_bits_fac, 0x5000))
+ {
+ hTcxEnc->tcx_target_bits_fac = 0x5000;
+ move16();
+ }
+ if (LT_16(hTcxEnc->tcx_target_bits_fac, 0x3000))
+ {
+ hTcxEnc->tcx_target_bits_fac = 0x3000;
+ move16();
+ }
+
+ /* Refine quantizer step size with a rate-control-loop (optional) */
+ phm_cfg = NULL;
+ move16();
+ if (PeriodicityIndex >= 0)
+ {
+ phm_cfg = hm_cfg;
+ move16();
+ }
+ sqBits = tcx_scalar_quantization_rateloop_fx(spectrum, *spectrum_e,
+ sqQ,
+ L_spec,
+ &sqGain, &sqGain_e,
+ hTcxCfg->sq_rounding,
+ hTcxEnc->memQuantZeros_fx,
+ prm_lastnz, /* lastnz */
+ sqTargetBits,
+ &nEncoded,
+ &stop,
+ sqBits_noStop,
+ sqBits,
+ hTcxCfg->tcxRateLoopOpt,
+ tcxonly,
+ phm_cfg
+ );
+
+ IF (ctxHmBits > 0) /* Mapping tool is enabled */
+ {
+ /* Truncate spectrum */
+ set16_fx(sqQ+nEncoded, 0, sub(L_spec, nEncoded));
+
+ IF (PeriodicityIndex >= 0) /* Mapping is used */
+ {
+ /* Estimate non-mapped bitrate */
+ stopCtxHm = 1;
+ move16();
+
+ sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx(sqQ,
+ L_spec,
+ &lastnz,
+ &nEncodedCtxHm,
+ sqTargetBits,
+ &stopCtxHm,
+ NULL);
+
+ /* Decide whether or not to revert mapping */
+ Selector = sub(sqBits, add(sqBitsCtxHm, NumIndexBits));
+
+ test();
+ IF (stopCtxHm == 0 && Selector > 0) /* Non-mapped is better */
+ {
+ sqTargetBits = add(sqTargetBits, NumIndexBits);
+ ctxHmBits = sub(ctxHmBits, NumIndexBits);
+ prm_hm[0] = 0;
+ move16();
+ *prm_lastnz = lastnz;
+ move16();
+ PeriodicityIndex = -1;
+ move16();
+ sqBits_noStop = sqBits = sqBitsCtxHm;
+ move16();
+ move16();
+ nEncoded = nEncodedCtxHm;
+ move16();
+ stop = stopCtxHm;
+ move16();
+ }
+ }
+ ELSE /* Mapping is not used */
+ {
+ /* Estimate mapped bitrate */
+ stopCtxHm = 1;
+ move16();
+ sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx(sqQ,
+ L_spec,
+ &lastnzCtxHm,
+ &nEncodedCtxHm,
+ sub(sqTargetBits, NumIndexBits),
+ &stopCtxHm,
+ hm_cfg
+ );
+
+ /* Decide whether or not to use mapping */
+ Selector = sub(sqBits, add(sqBitsCtxHm, NumIndexBits));
+
+ test();
+ IF (stopCtxHm == 0 && Selector > 0) /* Mapped is better */
+ {
+ sqTargetBits = sub(sqTargetBits, NumIndexBits);
+ ctxHmBits = add(ctxHmBits, NumIndexBits);
+ prm_hm[0] = 1;
+ move16();
+ *prm_lastnz = lastnzCtxHm;
+ move16();
+ PeriodicityIndex = prm_hm[1];
+ move16();
+ sqBits_noStop = sqBits = sqBitsCtxHm;
+ move16();
+ move16();
+ nEncoded = nEncodedCtxHm;
+ move16();
+ stop = stopCtxHm;
+ move16();
+ }
+ }
+ }
+
+ /* Limit low sqGain for avoiding saturation of the gain quantizer*/
+#ifdef BASOP_NOGLOB
+ tmp1 = mult_r(shl_o(L_spec, 5, &Overflow), 26214/*128.f/NORM_MDCT_FACTOR Q15*/);
+#else
+ tmp1 = mult_r(shl(L_spec, 5), 26214/*128.f/NORM_MDCT_FACTOR Q15*/);
+#endif
+ s = 15-5-7;
+ IF( L_spec >= 1024 )
+ {
+ /*reduce precision for avoiding overflow*/
+ tmp1 = mult_r(shl(L_spec, 4), 26214/*128.f/NORM_MDCT_FACTOR Q15*/);
+ s = 15-4-7;
+ }
+ tmp1 = ISqrt16(tmp1, &s);
+
+ tmp2 = sub(sqGain_e, s);
+ IF (tmp2 >= 0)
+ {
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ tmp2 = sub(sqGain, shr(tmp1, tmp2));
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+ ELSE
+ {
+ tmp2 = sub(shl(sqGain, s_max(-15, tmp2)), tmp1);
+ }
+
+ IF (tmp2 < 0)
+ {
+ sqGain = tmp1;
+ sqGain_e = s;
+
+ tcx_scalar_quantization_fx( spectrum, *spectrum_e,
+ sqQ,
+ L_spec,
+ sqGain, sqGain_e,
+ hTcxCfg->sq_rounding,
+ hTcxEnc->memQuantZeros_fx,
+ tcxonly
+ );
+
+ move16();
+ stop=1;
+
+ phm_cfg = NULL;
+ move16();
+ if (PeriodicityIndex >= 0)
+ {
+ phm_cfg = hm_cfg;
+ move16();
+ }
+ sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx(sqQ,
+ L_spec,
+ prm_lastnz,
+ &nEncoded,
+ sqTargetBits,
+ &stop,
+ phm_cfg
+ );
+ }
+
+ /* Truncate spectrum (for CBR) */
+ IF (stop != 0)
+ {
+ set16_fx(sqQ+nEncoded, 0, sub(L_spec, nEncoded));
+ }
+
+ /* Save quantized Values */
+ tmp32 = L_deposit_l(0);
+ FOR(i=0; itcx_lpc_shaped_ari,
+ gainlpc, gainlpc_e,
+ L_frame
+ );
+
+ prm_target = sqQ;
+ move16();
+ sqQ = prm_target + 1;
+ move16();
+ signs = hm_cfg->indexBuffer;
+ move16();
+
+ LtpPitchLag = -1;
+ move16();
+
+ IF (LT_16(hTcxEnc->tcxltp_pitch_int, st->L_frame_fx))
+ {
+ tmp32 = L_shl(L_mult0(st->L_frame_fx, st->pit_res_max), 1+kLtpHmFractionalResolution+1);
+ tmp1 = add(imult1616(hTcxEnc->tcxltp_pitch_int, st->pit_res_max), hTcxEnc->tcxltp_pitch_fr);
+ LtpPitchLag = div_l(tmp32, tmp1);
+ }
+
+ tmp8 = 1;
+ move16();
+ if (EQ_16(st->last_core_fx, ACELP_CORE))
+ {
+ tmp8 = 0;
+ move16();
+ }
+
+ tcx_arith_encode_envelope_fx(
+ spectrum,
+ spectrum_e,
+ signs,
+ L_frame,
+ L_spec,
+ st,
+ Aqind,
+ sqTargetBits,
+ sqQ,
+ tmp8,
+ prm_hm, /* HM parameter area */
+ LtpPitchLag,
+ &sqBits,
+ &signaling_bits,
+ &nf_seed
+ , shr(st->bwidth_fx, 1) /* equivalent to: (st->bwidth_fx > WB)?1:0 */
+ );
+
+ sqTargetBits = sub(sqTargetBits, signaling_bits);
+ *prm_target = sqTargetBits;
+ move16();
+ }
+
+ /*-----------------------------------------------------------*
+ * Compute optimal TCX gain. *
+ *-----------------------------------------------------------*/
+ /* initialize LF deemphasis factors in xn_buf */
+ set16_fx(xn_buf16, 0x4000, L_spec);
+
+ IF (tcxonly == 0)
+ {
+
+ AdaptLowFreqDeemph(spectrum, *spectrum_e,
+ hTcxEnc->tcx_lpc_shaped_ari,
+ gainlpc, gainlpc_e,
+ L_frame,
+ xn_buf16 /* LF deemphasis factors */
+ );
+ }
+
+ tcx_get_gain(x_orig, x_orig_e,
+ spectrum, *spectrum_e,
+ L_spec,
+ &gain_tcx_opt, &gain_tcx_opt_e,
+ &ener, &ener_e);
+
+ IF (gain_tcx_opt <= 0)
+ {
+ gain_tcx_opt = sqGain;
+ move16();
+ gain_tcx_opt_e = sqGain_e;
+ move16();
+ }
+ gain_tcx = gain_tcx_opt;
+ move16();
+ gain_tcx_e = gain_tcx_opt_e;
+ move16();
+
+ /* Save gains for FAC and Residual Q*/
+
+ /*-----------------------------------------------------------*
+ * Quantize TCX gain *
+ *-----------------------------------------------------------*/
+
+ IF (GE_32(st->total_brate_fx, ACELP_13k20)&&st->rf_mode==0)
+ {
+ QuantizeGain(L_spec, &gain_tcx, &gain_tcx_e, &prm[0]);
+ }
+
+
+ /*-----------------------------------------------------------*
+ * Residual Quantization *
+ *-----------------------------------------------------------*/
+
+ IF (hTcxCfg->resq)
+ {
+
+ resQTargetBits = sub(sqTargetBits, sqBits);
+
+ IF (hTcxEnc->tcx_lpc_shaped_ari) /* new arithmetic coder */
+ {
+ Word16 *prm_resq;
+
+ prm_resq = sqQ + sqTargetBits - resQTargetBits;
+
+ resQBits = tcx_ari_res_Q_spec_fx(x_orig, x_orig_e, signs, spectrum, *spectrum_e, L_spec, gain_tcx, gain_tcx_e,
+ prm_resq,
+ resQTargetBits,
+ resQBits,
+ hTcxCfg->sq_rounding,
+ xn_buf16 /* LF deemphasis factors */ );
+
+ /* Transmit zeros when there bits remain after RESQ */
+ set16_fx(prm_resq+resQBits, 0, sub(resQTargetBits, resQBits));
+ }
+ ELSE /* old arithmetic coder */
+ {
+ move16();
+ tmpP16 = NULL;
+ if (tcxonly == 0)
+ {
+ move16();
+ tmpP16 = xn_buf16;
+ }
+
+ resQBits = tcx_res_Q_gain_fx(gain_tcx_opt, gain_tcx_opt_e,
+ &gain_tcx, &gain_tcx_e,
+ &sqQ[L_spec],
+ resQTargetBits);
+
+ resQBits = tcx_res_Q_spec_fx(x_orig, x_orig_e,
+ spectrum, *spectrum_e,
+ L_spec,
+ gain_tcx, gain_tcx_e,
+ &sqQ[L_spec],
+ resQTargetBits,
+ resQBits,
+ hTcxCfg->sq_rounding,
+ tmpP16 /* LF deemphasis factors */ );
+ }
+
+
+ }
+
+
+ /*-----------------------------------------------------------*
+ * ALFE tcx only bitrates *
+ *-----------------------------------------------------------*/
+
+ IF (st->tcxonly != 0)
+ {
+ test();
+ test();
+ IF (hTcxEnc->tcxltp != 0 && (hTcxEnc->tcxltp_gain > 0) && fUseTns == 0)
+ {
+
+ PsychAdaptLowFreqDeemph(spectrum, gainlpc, gainlpc_e, NULL);
+ }
+ }
+
+ /*-----------------------------------------------------------*
+ * TCX SNR for Analysis purposes *
+ *-----------------------------------------------------------*/
+
+ {
+ maxNfCalcBw = s_min(noiseFillingSize, round_fx(L_shl(L_mult(hTcxEnc->measuredBwRatio, L_frame), 1)));
+
+ /*-----------------------------------------------------------*
+ * Estimate and quantize noise factor *
+ *-----------------------------------------------------------*/
+
+ IF (GE_32(st->total_brate_fx, HQ_96k))
+ {
+ fac_ns = 0;
+ move16();
+ prm[1] = 0;
+ move16();
+ }
+ ELSE
+ {
+ /* noise filling start bin */
+ i = shr(L_frame, 3);
+ IF (GE_32(st->total_brate_fx, ACELP_13k20)&&st->rf_mode==0)
+ {
+ i = idiv1616U(L_frame, 6);
+ }
+
+ IF (tcxonly)
+ {
+ tmp1 = 0;
+ move16();
+ test();
+ test();
+ if ((hTcxCfg->ctx_hm != 0) && (st->last_core_fx != ACELP_CORE) && (prm_hm[0] != 0))
+ {
+ tmp1 = 10240/*0.3125f Q15*/;
+ move16();
+ }
+ noiseTransWidth = HOLE_SIZE_FROM_LTP(s_max(hTcxEnc->tcxltp_gain, tmp1));
+
+ if (EQ_16(L_frame, shr(st->L_frame_fx, 1)))
+ {
+ /* minimum transition for noise filling in TCX-10 */
+ noiseTransWidth = 3;
+ move16();
+ }
+ }
+
+ tcx_noise_factor_fx( x_orig, x_orig_e,
+ spectrum,
+ i,
+ maxNfCalcBw,
+ noiseTransWidth,
+ L_frame,
+ gain_tcx, gain_tcx_e,
+ hTcxEnc->noiseTiltFactor,
+ &fac_ns, &prm[NOISE_FILL_RANGES] );
+
+ /* hysteresis for very tonal passages (more stationary noise filling level) */
+
+ IF (EQ_16(prm[NOISE_FILL_RANGES], 1))
+ {
+ hTcxEnc->noiseLevelMemory_cnt = add(1, abs_s(hTcxEnc->noiseLevelMemory_cnt)); /* update counter */
+ }
+ ELSE {
+ test();
+ IF ((EQ_16(prm[NOISE_FILL_RANGES], 2))&&
+ (GT_16(abs_s(hTcxEnc->noiseLevelMemory_cnt), 5)))
+ {
+ /* reduce noise filling level by one step */
+ prm[NOISE_FILL_RANGES] = 1;
+ move16();
+ fac_ns = shr(0x6000, NBITS_NOISE_FILL_LEVEL);
+
+ /* signal that noise level is changed by inverting sign of level memory */
+ tmp1 = 5;
+ move16();
+ if (hTcxEnc->noiseLevelMemory_cnt >= 0)
+ {
+ tmp1 = sub(-1, hTcxEnc->noiseLevelMemory_cnt);
+ }
+ hTcxEnc->noiseLevelMemory_cnt = tmp1;
+ }
+ ELSE {
+ /* reset memory since level is too different */
+ hTcxEnc->noiseLevelMemory_cnt = 0;
+ move16();
+ }
+ }
+
+ } /* bitrate */
+ }
+
+ /* Free encoder specific stack to use it below for the internal TCX decoder. */
+ }
+
+ /*-----------------------------------------------------------*
+ * Internal TCX decoder *
+ *-----------------------------------------------------------*/
+ {
+ /* Overlay of a 16-bit buffer xn_buf16 with a 32-bit buffer xn_buf32 */
+ /* The size is determined by the requirements of the 16-bit buffer. */
+ Word32 xn_buf32[(L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2];
+ Word16 *xn_buf16 = (Word16*)xn_buf32;
+
+ /*Enable internal TCX decoder to run always to update LPD memory for rate switching */
+
+ IF (tcxonly == 0)
+ {
+ }
+
+ /*-----------------------------------------------------------*
+ * Noise Filling. *
+ *-----------------------------------------------------------*/
+
+ /* Replication of ACELP formant enhancement for low rates */
+ IF ( LT_32(st->total_brate_fx, ACELP_13k20)||st->rf_mode!=0)
+ {
+ tcxFormantEnhancement(xn_buf16, gainlpc, gainlpc_e, spectrum, spectrum_e, L_frame, L_spec);
+ }
+
+ IF (fac_ns > 0)
+ {
+ tmp1 = 0;
+ move16();
+ if ( GE_32(st->total_brate_fx, ACELP_13k20)&&st->rf_mode==0)
+ {
+ tmp1 = 1;
+ move16();
+ }
+
+ i = tcxGetNoiseFillingTilt(A,
+ M,
+ L_frame,
+ tmp1,
+ &hTcxEnc->noiseTiltFactor);
+
+ tcx_noise_filling(spectrum, *spectrum_e,nf_seed /* seed */, i, noiseFillingSize, noiseTransWidth, L_frame, hTcxEnc->noiseTiltFactor, fac_ns, NULL, st->element_mode );
+ }
+
+ IF (LT_32(st->total_brate_fx, ACELP_13k20)||st->rf_mode!=0)
+ {
+ /* partially recompute global gain (energy part), taking noise filling and formant enhancement into account */
+ s = sub(getScaleFactor32(spectrum, L_spec), 4);
+ tmp32 = L_deposit_l(1);
+
+ FOR (i = 0; i < L_spec; i++)
+ {
+ tmp1 = round_fx(L_shl(spectrum[i], s));
+ tmp32 = L_mac0(tmp32, tmp1, tmp1);
+ }
+
+ tmp1 = BASOP_Util_Divide3232_Scale(ener, tmp32, &tmp2);
+ tmp2 = add(tmp2, sub(ener_e, add(shl(sub(*spectrum_e, s), 1), 1)));
+ tmp1 = Sqrt16(tmp1, &tmp2);
+
+ gain_tcx = mult(gain_tcx, tmp1);
+ gain_tcx_e = add(gain_tcx_e, tmp2);
+
+ QuantizeGain(L_spec, &gain_tcx, &gain_tcx_e, &prm[0]);
+ }
+
+ /*end of noise filling*/
+
+ /*-----------------------------------------------------------*
+ * Noise shaping in frequency domain (1/Wz) *
+ *-----------------------------------------------------------*/
+
+ /* LPC gains already available */
+ mdct_shaping(spectrum, L_frame, gainlpc, gainlpc_e);
+
+ /*-----------------------------------------------------------*
+ * Apply gain *
+ *-----------------------------------------------------------*/
+ IF (EQ_16(st->hTcxCfg->coder_type, INACTIVE))
+ {
+ gain_tcx = mult_r(gain_tcx, hTcxCfg->na_scale);
+ }
+
+ FOR (i = 0; i < L_spec; i++)
+ {
+ spectrum[i] = Mpy_32_16_1(spectrum[i], gain_tcx);
+ move32();
+ }
+ *spectrum_e = add(*spectrum_e, gain_tcx_e);
+ move16();
+
+ stop = hTcxCfg->tcx_last_overlap_mode; /* backup last TCX overlap mode */ move16();
+
+ test();
+ IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(tcxonly!=0))
+ {
+ Word16 L = L_frame;
+ move16();
+
+ test();
+ test();
+ if (((hTcxCfg->fIsTNSAllowed != 0) && (fUseTns != 0)) || (GT_16(L_spec, L_frame)))
+ {
+ L = L_spec;
+ move16();
+ }
+
+ tcxInvertWindowGrouping(hTcxCfg,
+ xn_buf32,
+ spectrum,
+ L,
+ fUseTns,
+ st->last_core_fx,
+ stop,
+ frame_cnt,
+ 0);
+ }
+
+ /*-----------------------------------------------------------*
+ * Temporal Noise Shaping Synthesis *
+ *-----------------------------------------------------------*/
+
+ IF (hTcxCfg->fIsTNSAllowed != 0)
+ {
+ test();
+ test();
+ test();
+ SetTnsConfig(hTcxCfg, sub(L_frame_glob, st->L_frame_fx) == 0, (st->last_core_fx == ACELP_CORE) && (frame_cnt == 0));
+
+ /* Apply TNS to get the reconstructed signal */
+ IF (fUseTns != 0)
+ {
+ ApplyTnsFilter(hTcxCfg->pCurrentTnsConfig, pTnsData, spectrum, 0);
+
+ test();
+ IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(tcxonly!=0))
+ {
+ test();
+ test();
+ test();
+ IF ( (hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP) ||
+ ((hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP) && (frame_cnt == 0) && (stop == 0)) )
+ {
+ tmp1 = shr(L_spec, 1);
+ /* undo rearrangement of LF sub-window lines for TNS synthesis filter */
+ assert(L_frame <= L_spec);
+ Copy32(spectrum+8, xn_buf32, 8);
+ Copy32(spectrum+16, spectrum+8, sub(tmp1,8));
+ Copy32(xn_buf32, spectrum+tmp1, 8);
+ }
+ }
+ }
+ }
+
+ {
+ /* normalize spectrum to minimize IMDCT noise */
+ s = getScaleFactor32(spectrum, L_frame);
+ FOR (i = 0; i < L_frame; i++)
+ {
+ spectrum[i] = L_shl(spectrum[i], s);
+ move32();
+ }
+ *spectrum_e = sub(*spectrum_e, s);
+
+ /*-----------------------------------------------------------*
+ * Compute inverse MDCT of spectrum[]. *
+ *-----------------------------------------------------------*/
+ test();
+ IF ((EQ_16(L_frame, shr(st->L_frame_fx, 1)))&&(tcxonly!=0))
+ {
+ IF (hTcxCfg->tcx_last_overlap_mode != FULL_OVERLAP)
+ {
+ Word16 win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2];
+ Word16 L_win, L_spec_TCX5, L_ola, w;
+
+ /* minimum or half overlap, two transforms, grouping into one window */
+ L_win = shr(L_frame, 1);
+ L_spec_TCX5 = shr(s_max(L_frame, L_spec), 1);
+ L_ola = hTcxCfg->tcx_mdct_window_half_length;
+ move16();
+ if ( EQ_16(hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP))
+ {
+ L_ola = hTcxCfg->tcx_mdct_window_min_length;
+ move16();
+ }
+
+ set16_fx(win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2);
+ set16_fx(xn_buf16, 0, add(tcx_offset, shr(L_ola, 1))); /* zero left end of buffer */
+
+ FOR (w = 0; w < 2; w++)
+ {
+
+ IF (EQ_16(hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP))
+ {
+ TCX_MDCT_Inverse(spectrum + L_mult0(w, L_spec_TCX5), sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM),
+ win, L_ola, sub(L_win, L_ola), L_ola, st->element_mode);
+ }
+ ELSE
+ {
+ TCX_MDCT_Inverse(spectrum + L_mult0(w, L_spec_TCX5), sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM), win,
+ L_ola, sub(L_win, L_ola), L_ola, st->element_mode);
+ }
+
+ tmp1 = hTcxCfg->tcx_last_overlap_mode;
+ move16();
+ test();
+ test();
+ if ((w > 0) || ((w == 0) && (EQ_16(stop, 2))))
+ {
+ tmp1 = MIN_OVERLAP;
+ move16();
+ }
+
+ tmp2 = 0;
+ move16();
+ test();
+ if ((w == 0) && (st->last_core_fx == ACELP_CORE))
+ {
+ tmp2 = 1;
+ move16();
+ }
+
+ tmp3 = st->last_core_fx;
+ move16();
+ if (w > 0)
+ {
+ tmp3 = 1;
+ move16();
+ }
+
+ tmp4 = 0;
+ move16();
+ if (tcx_offset < 0)
+ {
+ tmp4 = negate(tcx_offset);
+ }
+
+ tcx_windowing_synthesis_current_frame(win,
+ hTcxCfg->tcx_aldo_window_2,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ L_ola,
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ tmp2,
+ tmp1,
+ hTcxEnc->acelp_zir,
+ hTcxEnc->Txnq,
+ NULL,
+ Aq_old,
+ hTcxCfg->tcx_mdct_window_trans,
+ L_win,
+ tmp4,
+ tmp3,
+ 0,
+ 0
+ );
+
+ tmp1 = add(tcx_offset, imult1616(w, L_win));
+ move16();
+ tmpP16 = xn_buf16 + sub(tmp1, shr(L_ola, 1));
+
+ IF (w > 0)
+ {
+ tcx_windowing_synthesis_past_frame(tmpP16,
+ hTcxCfg->tcx_aldo_window_1_trunc,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ L_ola,
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ 2
+ );
+ }
+ /* add part of current sub-window overlapping with previous window */
+ FOR (i = 0; i < L_ola; i++)
+ {
+ tmpP16[i] = add(tmpP16[i], win[i]);
+ move16();
+ }
+ /* copy new sub-window region not overlapping with previous window */
+ Copy(win + L_ola, xn_buf16 + add(tmp1, shr(L_ola, 1)), L_win);
+ }
+ /* To assure that no garbage values are copied to hLPDmem->Txnq */
+ set16_fx(xn_buf16 + add(add(L_frame, tcx_offset), shr(L_ola, 1)),
+ 0, sub(sub(overlap, tcx_offset), shr(L_ola, 1)));
+
+
+ }
+ ELSE IF ( s_and(frame_cnt == 0, (hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP)) )
+ {
+ /* special overlap attempt, two transforms, grouping into one window */
+ Word16 win[(L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2];
+ Word16 L_win, L_spec_TCX5, L_ola, w;
+
+ L_win = shr(L_frame, 1);
+ L_spec_TCX5 = shr(s_max(L_frame, L_spec), 1);
+ L_ola = hTcxCfg->tcx_mdct_window_min_length;
+ move16();
+
+ set16_fx(win, 0, (L_FRAME_PLUS+L_MDCT_OVLP_MAX)/2);
+
+ /* Resize overlap (affect only asymmetric window)*/
+ overlap = st->hTcxCfg->tcx_mdct_window_delay;
+ /* 1st TCX-5 window, special MDCT with minimum overlap on right side */
+ TCX_MDCT_Inverse(spectrum, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM),
+ win + L_win, 0, sub(L_win, shr(L_ola, 1)), L_ola, st->element_mode);
+
+ /* copy new sub-window region not overlapping with previous window */
+ Copy(win+L_win, xn_buf16+shr(overlap, 1), add(L_win, shr(L_ola, 1)));
+
+ /* 2nd TCX-5 window, regular MDCT with minimum overlap on both sides */
+
+ TCX_MDCT_Inverse(spectrum + L_spec_TCX5, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM),
+ win, L_ola, sub(L_win, L_ola), L_ola, st->element_mode);
+
+ tmp4 = 0;
+ move16();
+ if (tcx_offset <0)
+ {
+ tmp4 = negate(tcx_offset);
+ }
+ tcx_windowing_synthesis_current_frame(win,
+ hTcxCfg->tcx_aldo_window_2,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ L_ola,
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ 0, /* left_rect */
+ 2, /* left_mode */
+ hTcxEnc->acelp_zir,
+ hTcxEnc->Txnq,
+ NULL,
+ Aq_old,
+ hTcxCfg->tcx_mdct_window_trans,
+ L_win,
+ tmp4,
+ 1, /* not LPDmem->mode */
+ 0,
+ 0
+ );
+
+
+ move16();
+ tmpP16 = xn_buf16 + add(sub(L_win, shr(L_ola, 1)), shr(overlap,1));
+
+ tcx_windowing_synthesis_past_frame(tmpP16,
+ hTcxCfg->tcx_aldo_window_1_trunc,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ L_ola,
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ 2
+ );
+
+ /* add part of current sub-window overlapping with previous window */
+ FOR (i = 0; i < L_ola; i++)
+ {
+ tmpP16[i] = add(tmpP16[i], win[i]);
+ move16();
+ }
+
+ /* copy new sub-window region not overlapping with previous window */
+ Copy(win + L_ola,
+ xn_buf16 + add(add(shr(overlap,1), shr(L_ola, 1)), L_win),
+ L_win);
+
+ /* extra folding-out on left side of win, for perfect reconstruction */
+ FOR (w = shr(overlap,1); w < overlap; w++)
+ {
+ xn_buf16[overlap-1-w] = negate(xn_buf16[w]);
+ move16();
+ }
+
+ tmp4 = 0;
+ move16();
+ if (tcx_offset < 0)
+ {
+ tmp4 = negate(tcx_offset);
+ }
+ tcx_windowing_synthesis_current_frame(xn_buf16,
+ hTcxCfg->tcx_aldo_window_2,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ overlap,
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ st->last_core_fx==ACELP_CORE,
+ 0,
+ hTcxEnc->acelp_zir,
+ hTcxEnc->Txnq,
+ NULL,
+ Aq_old,
+ hTcxCfg->tcx_mdct_window_trans,
+ L_win,
+ tmp4,
+ st->last_core_fx,
+ 0,
+ 0
+ );
+ }
+ ELSE /* default, i.e. maximum overlap, single transform, no grouping */
+ {
+
+ TCX_MDCT_Inverse(spectrum, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM),
+ xn_buf16,overlap, sub(L_frame, overlap), overlap, st->element_mode);
+
+ tmp1 = stop;
+ move16();
+ test();
+ test();
+ if ((frame_cnt > 0) && (stop == 0) && (st->last_core_fx != ACELP_CORE))
+ {
+ tmp1 = 2;
+ move16();
+ }
+
+ tmp4 = 0;
+ move16();
+ if (tcx_offset <0)
+ {
+ tmp4 = negate(tcx_offset);
+ }
+ tcx_windowing_synthesis_current_frame(xn_buf16,
+ hTcxCfg->tcx_aldo_window_2,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ overlap, /*hTcxCfg->tcx_mdct_window_length*/
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ st->last_core_fx==ACELP_CORE,
+ tmp1,
+ hTcxEnc->acelp_zir,
+ hTcxEnc->Txnq,
+ NULL,
+ Aq_old,
+ hTcxCfg->tcx_mdct_window_trans,
+ shr(L_frame_glob, 1),
+ tmp4,
+ st->last_core_fx,
+ 0,
+ 0
+ );
+
+ } /* tcx_last_overlap_mode > 0 */
+
+ }
+ ELSE /* frame is TCX-20 or not TCX-only */
+ {
+ IF (NE_16(st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP))
+ {
+ Word32 tmp_buf[L_FRAME_PLUS];
+ Word16 Q;
+
+ /* DCT */
+ Q = sub(31, *spectrum_e);
+ edct_fx(spectrum, tmp_buf, L_frame, &Q);
+
+ /* scale by sqrt(L / NORM_MDCT_FACTOR) */
+ tmp1 = mult_r(shl(L_frame, 4), 26214/*128.f / NORM_MDCT_FACTOR Q15*/); /* 4Q11 */
+ tmp2 = 4;
+ move16();
+ tmp1 = Sqrt16(tmp1, &tmp2);
+
+ FOR (i = 0; i < L_frame; i++)
+ {
+ tmp_buf[i] = Mpy_32_16_1(tmp_buf[i], tmp1);
+ move32();
+ }
+ Q = sub(Q, tmp2);
+
+
+ window_ola_fx(tmp_buf,
+ xn_buf16,
+ &Q,
+ hTcxEnc->old_out_fx,
+ &hTcxEnc->Q_old_out,
+ L_frame,
+ hTcxCfg->tcx_last_overlap_mode,
+ hTcxCfg->tcx_curr_overlap_mode,
+ 0,
+ 0,
+ NULL);
+
+ /* scale output */
+ FOR (i = 0; i < L_frame; i++)
+ {
+#ifdef BASOP_NOGLOB
+ xn_buf16[i] = shr_o(xn_buf16[i], Q, &Overflow);
+#else /* BASOP_NOGLOB */
+ xn_buf16[i] = shr(xn_buf16[i], Q);
+#endif /* BASOP_NOGLOB */
+ move16();
+ }
+
+ aldo = 1;
+ move16();
+ }
+ ELSE
+ {
+
+ TCX_MDCT_Inverse(spectrum, sub(*spectrum_e, TCX_IMDCT_SCALE+TCX_IMDCT_HEADROOM),
+ xn_buf16, overlap, sub(L_frame, overlap), overlap, st->element_mode);
+
+ /*-----------------------------------------------------------*
+ * Windowing, overlap and add *
+ *-----------------------------------------------------------*/
+
+ /* Window current frame */
+ tmp4 = 0;
+ move16();
+ if (tcx_offset<0)
+ {
+ tmp4 = negate(tcx_offset);
+ }
+ tcx_windowing_synthesis_current_frame(xn_buf16,
+ hTcxCfg->tcx_aldo_window_2,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ overlap, /*hTcxCfg->tcx_mdct_window_length*/
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ st->last_core_fx==ACELP_CORE,
+ hTcxCfg->tcx_last_overlap_mode, /*left mode*/
+ hTcxEnc->acelp_zir,
+ hTcxEnc->Txnq,
+ NULL,
+ Aq_old,
+ hTcxCfg->tcx_mdct_window_trans,
+ shr(L_frame_glob, 1),
+ tmp4,
+ st->last_core_fx,
+ 0,
+ 0
+ );
+ }
+ } /* TCX-10 and TCX-only */
+
+ /* Window and overlap-add past frame if past frame is TCX */
+ test();
+ test();
+ test();
+ IF ((st->last_core_fx > ACELP_CORE) && (((EQ_16(L_frameTCX, shr(hTcxEnc->L_frameTCX, 1)))&&(st->tcxonly!=0))||(EQ_16(st->hTcxCfg->tcx_last_overlap_mode,TRANSITION_OVERLAP))))
+ {
+
+ IF (hTcxCfg->last_aldo != 0)
+ {
+ tmp2 = add(hTcxEnc->Q_old_out, TCX_IMDCT_HEADROOM);
+
+ tmp1 = sub(overlap, hTcxCfg->tcx_mdct_window_min_length);
+ FOR (i=0; i < tmp1; i++)
+ {
+ xn_buf16[i] = shl(add(xn_buf16[i], shr(hTcxEnc->old_out_fx[i+nz], tmp2)), TCX_IMDCT_HEADROOM);
+ move16();
+ }
+
+ /* fade truncated ALDO window */
+ tmp1 = sub(overlap, shr(hTcxCfg->tcx_mdct_window_min_length, 1));
+ FOR ( ; i < tmp1; i++)
+ {
+ tmp3 = mult_r(shr(hTcxEnc->old_out_fx[i+nz], tmp2), hTcxCfg->tcx_mdct_window_minimum[i-overlap+hTcxCfg->tcx_mdct_window_min_length].v.re);
+ xn_buf16[i] = shl(add(xn_buf16[i], tmp3), TCX_IMDCT_HEADROOM);
+ move16();
+ }
+ FOR ( ; i < overlap; i++)
+ {
+ tmp3 = mult_r(shr(hTcxEnc->old_out_fx[i+nz], tmp2), hTcxCfg->tcx_mdct_window_minimum[overlap-1-i].v.im);
+ xn_buf16[i] = shl(add(xn_buf16[i], tmp3), TCX_IMDCT_HEADROOM);
+ move16();
+ }
+
+ FOR ( ; i < L_frame; i++)
+ {
+ xn_buf16[i] = shl(xn_buf16[i], TCX_IMDCT_HEADROOM);
+ move16();
+ }
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ if ((frame_cnt > 0) && (stop == 0) && (hTcxCfg->tcx_curr_overlap_mode == 0) && (st->last_core_fx != ACELP_CORE))
+ {
+ stop = 2; /* use minimum overlap between the two TCX-10 windows */ move16();
+ }
+
+ tmp1 = stop;
+ move16();
+ test();
+ if ((stop == 0) || (EQ_16(hTcxCfg->tcx_last_overlap_mode, MIN_OVERLAP)))
+ {
+ tmp1 = hTcxCfg->tcx_last_overlap_mode;
+ move16();
+ }
+
+ tcx_windowing_synthesis_past_frame(hTcxEnc->Txnq,hTcxCfg->tcx_aldo_window_1_trunc,hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,overlap,hTcxCfg->tcx_mdct_window_half_length,hTcxCfg->tcx_mdct_window_min_length,tmp1);
+
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ FOR (i=0; iTxnq[i]), TCX_IMDCT_HEADROOM);
+ move16();
+ }
+
+ IF (LT_16(i, L_frame))
+ {
+ FOR ( ; i < L_frame; i++)
+ {
+ xn_buf16[i] = shl(xn_buf16[i], TCX_IMDCT_HEADROOM);
+ move16();
+ }
+ }
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+ }
+ ELSE
+ {
+ IF (aldo == 0)
+ {
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ FOR (i = 0; i < L_frame; i++)
+ {
+#ifdef BASOP_NOGLOB
+ xn_buf16[i] = shl_o(xn_buf16[i], TCX_IMDCT_HEADROOM, &Overflow);
+#else /* BASOP_NOGLOB */
+ xn_buf16[i] = shl(xn_buf16[i], TCX_IMDCT_HEADROOM);
+#endif
+ move16();
+ }
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+ }
+
+ test();
+ test();
+ test();
+ IF ( (aldo == 0) &&
+ ((EQ_16(L_frameTCX, shr(hTcxEnc->L_frameTCX, 1)) && frame_cnt > 0) ||
+ NE_16(L_frameTCX, shr(hTcxEnc->L_frameTCX, 1)) ) )
+ {
+ /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/
+ FOR (i = 0; i < nz; i++)
+ {
+ hTcxEnc->old_out_fx[i] = shr(xn_buf16[L_frame-nz+i], TCX_IMDCT_HEADROOM);
+ move16();
+ }
+ Copy(xn_buf16+L_frame, hTcxEnc->old_out_fx+nz, overlap);
+ set16_fx(hTcxEnc->old_out_fx+nz+overlap, 0, nz);
+
+ tcx_windowing_synthesis_past_frame(hTcxEnc->old_out_fx+nz,
+ hTcxCfg->tcx_aldo_window_1_trunc,
+ hTcxCfg->tcx_mdct_window_half,
+ hTcxCfg->tcx_mdct_window_minimum,
+ overlap,
+ hTcxCfg->tcx_mdct_window_half_length,
+ hTcxCfg->tcx_mdct_window_min_length,
+ hTcxCfg->tcx_curr_overlap_mode
+ );
+
+ /* If current overlap mode = FULL_OVERLAP -> ALDO_WINDOW */
+ IF (EQ_16(hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP))
+ {
+ FOR (i=0; iold_out_fx[nz+overlap+i] = shr(mult_r(xn_buf16[L_frame-1-i], hTcxCfg->tcx_aldo_window_1[nz-1-i]), TCX_IMDCT_HEADROOM);
+ move16();
+ }
+ hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW;
+ move16();
+ }
+
+ hTcxEnc->Q_old_out = -TCX_IMDCT_HEADROOM;
+ move16();
+ }
+ hTcxCfg->last_aldo = aldo;
+ move16();
+
+ /* Update Txnq */
+ IF (hTcxCfg->last_aldo == 0)
+ {
+ Copy(xn_buf16 + L_frame, hTcxEnc->Txnq, overlap);
+ }
+
+
+ /* Output */
+ Copy(xn_buf16+shr(overlap,1)-tcx_offset, synth, L_frame_glob);
+
+ }
+
+ /* Free internal TCX decoder stack memory */
+ }
+
+ /* Update L_frame_past */
+ st->L_frame_past = L_frame;
+ move16();
+
+}
+
+
+void coder_tcx_fx(
+ Word16 n,
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */
+ Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */
+ Word16 Aqind[], /* input: frame-independent quantized coefficients (M+1) */
+ Word16 synth[],
+ Word16 L_frame_glob, /* input: frame length */
+ Word16 L_frameTCX_glob,
+ Word16 L_spec,
+ Word16 nb_bits, /*input: bit budget*/
+ Word8 tcxonly, /*input: only TCX flag*/
+ Word32 spectrum[], /* i/o: MDCT spectrum */
+ Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */
+ Word16 prm[], /* output: tcx parameters */
+ Encoder_State_fx *st,
+ CONTEXT_HM_CONFIG *hm_cfg
+)
+{
+ Word16 L_frame;
+ Word16 left_overlap, right_overlap;
+ Word16 tnsSize; /* number of tns parameters put into prm */
+ Word16 tnsBits; /* number of tns bits in the frame */
+ Word16 ltpBits;
+ Word16 gainlpc[FDNS_NPTS], gainlpc_e[FDNS_NPTS];
+ Word16 win[N_MAX+L_MDCT_OVLP_MAX];
+ Word32 powerSpec[N_MAX];
+ Word16 powerSpec_e;
+ Word16 winMDST[N_MAX+L_MDCT_OVLP_MAX];
+ Word16 *pWinMDST;
+ Word16 left_overlap_mode, right_overlap_mode;
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ left_overlap = right_overlap = -1;
+ move16();
+ move16();
+ tnsSize = 0;
+ move16();
+ tnsBits = 0;
+ move16();
+ ltpBits = 0;
+ move16();
+
+ L_frame = L_frameTCX_glob;
+ move16();
+
+ /*-----------------------------------------------------------*
+ * Windowing *
+ *-----------------------------------------------------------*/
+ IF (EQ_16(st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP))
+ {
+
+ WindowSignal(hTcxCfg, hTcxCfg->tcx_offsetFB, hTcxCfg->tcx_last_overlap_mode, hTcxCfg->tcx_curr_overlap_mode, &left_overlap, &right_overlap,
+ hTcxEnc->speech_TCX, &L_frame, win ,1, 1);
+
+ /*-----------------------------------------------------------*
+ * Compute MDCT *
+ *-----------------------------------------------------------*/
+
+ *spectrum_e = 16;
+ move16();
+ TCX_MDCT(win, spectrum, spectrum_e, left_overlap, sub(L_frame, shr(add(left_overlap, right_overlap), 1)), right_overlap, st->element_mode);
+ }
+ ELSE
+ {
+ Word32 tmp_buf[L_FRAME_PLUS];
+ Word16 Q, tmp1, tmp2, i;
+
+ Q = 0;
+ move16();
+
+ wtda_fx(hTcxEnc->new_speech_TCX,&Q,tmp_buf,NULL,NULL,hTcxCfg->tcx_last_overlap_mode,hTcxCfg->tcx_curr_overlap_mode,L_frame);
+
+ left_overlap_mode = hTcxCfg->tcx_last_overlap_mode;
+ move16();
+ if (EQ_16(left_overlap_mode, ALDO_WINDOW))
+ {
+ left_overlap_mode = FULL_OVERLAP;
+ move16();
+ }
+ right_overlap_mode = hTcxCfg->tcx_curr_overlap_mode;
+ move16();
+ if (EQ_16(right_overlap_mode, ALDO_WINDOW))
+ {
+ right_overlap_mode = FULL_OVERLAP;
+ move16();
+ }
+
+ WindowSignal( hTcxCfg, hTcxCfg->tcx_offsetFB, left_overlap_mode, right_overlap_mode, &left_overlap, &right_overlap, hTcxEnc->speech_TCX, &L_frame, winMDST, 1, 1 );
+
+ /* scale by NORM_MDCT_FACTOR / L */
+ tmp1 = mult_r(shl(L_frame, 4), 26214/*128.f / NORM_MDCT_FACTOR Q15*/); /* 4Q11 */
+ tmp2 = 4;
+ move16();
+ tmp1 = ISqrt16(tmp1, &tmp2);
+
+ FOR (i = 0; i < L_frame; i++)
+ {
+ tmp_buf[i] = Mpy_32_16_1(tmp_buf[i], tmp1);
+ move32();
+ }
+ Q = sub(Q, tmp2);
+
+ /* DCT */
+ edct_fx(tmp_buf, spectrum, L_frame, &Q);
+ *spectrum_e = sub(31, Q);
+ }
+
+
+ /*-----------------------------------------------------------*
+ * Attenuate upper end of NB spectrum, *
+ * to simulate ACELP behavior *
+ *-----------------------------------------------------------*/
+
+ IF (st->narrowBand != 0)
+ {
+ attenuateNbSpectrum_fx(L_frame, spectrum);
+ }
+
+ /*-----------------------------------------------------------*
+ * Compute noise-measure flags for spectrum filling *
+ * and quantization (0: tonal, 1: noise-like). *
+ * Detect low pass if present. *
+ *-----------------------------------------------------------*/
+
+ pWinMDST = winMDST;
+ move16();
+ if (EQ_16(st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP))
+ {
+ pWinMDST = win;
+ move16();
+ }
+
+ AnalyzePowerSpectrum_fx(st,
+ round_fx(L_shl(Mpy_32_16_1(L_mult0(L_frame,st->L_frame_fx)/*Q0*/,
+ getInvFrameLen(hTcxEnc->L_frameTCX)/*Q21*/)/*Q6*/,16-6)),
+ L_frame,
+ left_overlap, right_overlap,
+ spectrum, *spectrum_e,
+ pWinMDST,
+ powerSpec, &powerSpec_e);
+ IF (hTcxCfg->fIsTNSAllowed != 0)
+ {
+ test();
+ test();
+ SetTnsConfig(hTcxCfg, sub(L_frame_glob, st->L_frame_fx) == 0, st->last_core_fx == 0);
+
+ TNSAnalysis_fx(hTcxCfg, L_frame, L_spec, TCX_20, st->last_core_fx == 0, spectrum, hTcxEnc->tnsData, hTcxEnc->fUseTns_fx
+ , &st->hIGFEnc->tns_predictionGain
+ );
+
+ }
+ ELSE
+ {
+ hTcxEnc->fUseTns_fx[0] = hTcxEnc->fUseTns_fx[1] = 0;
+ move16();
+ move16();
+ }
+
+ IF(st->igf)
+ {
+ ProcessIGF_fx(st->hIGFEnc, st, spectrum, spectrum_e, powerSpec, &powerSpec_e, 1, hTcxEnc->fUseTns_fx[0], (st->last_core_fx == ACELP_CORE), 0);
+ }
+
+ ShapeSpectrum_fx(hTcxCfg, A, gainlpc, gainlpc_e,
+ L_frame_glob,
+ L_spec,
+ spectrum,
+ hTcxEnc->fUseTns_fx[0],
+ st
+ );
+ if(st->igf)
+ {
+ nb_bits = sub(nb_bits, st->hIGFEnc->infoTotalBitsPerFrameWritten);
+ }
+ IF (hTcxCfg->fIsTNSAllowed != 0)
+ {
+ EncodeTnsData_fx(hTcxCfg->pCurrentTnsConfig, hTcxEnc->tnsData, prm+1+NOISE_FILL_RANGES+LTPSIZE, &tnsSize, &tnsBits);
+ }
+
+ QuantizeSpectrum_fx(hTcxCfg,
+ A,
+ Aqind,
+ gainlpc, gainlpc_e,
+ synth,
+ L_frame_glob,
+ L_frameTCX_glob,
+ L_spec,
+ sub(sub(nb_bits, tnsBits), ltpBits),
+ tcxonly,
+ spectrum, spectrum_e,
+ hTcxEnc->tnsData,
+ hTcxEnc->fUseTns_fx[0],
+ tnsSize,
+ prm,
+ n,
+ st,
+ hm_cfg
+ );
+
+ hLPDmem->nbits = add(hLPDmem->nbits, add(tnsBits, ltpBits));
+
+}
+
+
+/*-------------------------------------------------------------------*
+* coder_tcx_post_fx()
+*
+*
+*-------------------------------------------------------------------*/
+
+void coder_tcx_post_fx(
+ Encoder_State_fx *st,
+ LPD_state *LPDmem,
+ TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 *synth,
+ const Word16 *A,
+ const Word16 *Ai,
+ Word16 *wsig,
+ Word16 Q_new,
+ Word16 shift
+)
+{
+ Word16 xn_buf[L_FRAME_MAX];
+
+ /* TCX output */
+ Copy( synth, xn_buf, st->L_frame_fx );
+
+
+ /*-----------------------------------------------------------*
+ * Memory update *
+ *-----------------------------------------------------------*/
+
+ /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */
+ tcx_encoder_memory_update_fx( wsig, xn_buf, st->L_frame_fx, Ai, A, hTcxCfg->preemph_fac, LPDmem, st, synth, Q_new, shift );
+
+ return;
+}
diff --git a/lib_enc/cod_uv_fx.c b/lib_enc/cod_uv_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..e091a1ce94ee1804f9d8819bd8cdbdbd93b18f02
--- /dev/null
+++ b/lib_enc/cod_uv_fx.c
@@ -0,0 +1,91 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+#include
+//#include "prot_fx.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * gauss_L2_fx:
+ *
+ * encode an additional Gaussian excitation for unvoiced subframes and compute
+ * associated xcorrelations for gains computation
+ *
+ * Gaussian excitation is generated by a white noise and shapes it with LPC-derived filter
+ *-------------------------------------------------------------------*/
+void gauss_L2_fx(
+ const Word16 h[], /* i : weighted LP filter impulse response Q14+s */
+ Word16 code[], /* o : gaussian excitation Q9 */
+ const Word16 y2[], /* i : zero-memory filtered code. excitation Q9 */
+ Word16 y11[], /* o : zero-memory filtered gauss. excitation Q9 */
+ Word32 *gain, /* o : excitation gain Q16 */
+ ACELP_CbkCorr *g_corr, /*i/o : correlation structure for gain coding */
+ const Word16 gain_pit, /* i : unquantized gain of code Q14 */
+ const Word16 tilt_code, /* i : tilt of code Q15 */
+ const Word16 *Aq, /* i : quantized LPCs Q12 */
+ const Word16 formant_enh_num, /* i : formant enhancement numerator factor Q15 */
+ Word16 *seed_acelp, /*i/o : random seed Q0 */
+ const Word16 shift
+)
+{
+ Word16 i, tmp16;
+ Word32 tmp32, tmp32_2;
+
+
+ assert(gain_pit==0);
+
+ /*-----------------------------------------------------------------*
+ * Find new target for the Gaussian codebook
+ *-----------------------------------------------------------------*/
+
+ /*Generate white gaussian noise using central limit theorem method (N only 4 as E_util_random is not purely uniform)*/
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ *seed_acelp = own_random2_fx(*seed_acelp);
+ tmp32 = L_mac(0, *seed_acelp, 1<<9);
+
+ *seed_acelp = own_random2_fx(*seed_acelp);
+ tmp32 = L_mac(tmp32, *seed_acelp, 1<<9);
+
+ *seed_acelp = own_random2_fx(*seed_acelp);
+ code[i] = mac_r(tmp32, *seed_acelp, 1<<9);
+ move16();
+ }
+
+ /*Shape the gaussian excitation*/
+ cb_shape_fx( 1, 0, 0, 1, 0, formant_enh_num, FORMANT_SHARPENING_G2, Aq, code, tilt_code, 0, 1 , L_SUBFR);
+
+ /*compute 0s memory weighted synthesis contribution and find gain*/
+ E_UTIL_f_convolve(code, h, y11, L_SUBFR); /* y11: Q8+shift */
+ Scale_sig(y11, L_SUBFR, sub(1, shift)); /* Q9 */
+ *gain = L_deposit_l(0);
+
+ /*Update correlations for gains coding */
+ tmp32 = L_shr(21474836l/*0.01f Q31*/, 31-18); /* Q18 */
+ tmp32_2 = L_shr(21474836l/*0.01f Q31*/, 31-18); /* Q18 */
+
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ tmp32 = L_mac0(tmp32, y11[i], y11[i]); /* Q18 */
+ tmp32_2 = L_mac0(tmp32_2, y11[i], y2[i]); /* Q18 */
+ }
+
+ tmp16 = norm_l(tmp32);
+ g_corr->y1y1 = round_fx(L_shl(tmp32, tmp16));
+ g_corr->y1y1_e = sub(31-18, tmp16);
+ move16();
+
+ tmp16 = norm_l(tmp32_2);
+ g_corr->y1y2 = round_fx(L_shl(tmp32_2, tmp16));
+ g_corr->y1y2_e = sub(31-18, tmp16);
+ move16();
+
+}
+
diff --git a/lib_enc/comvad_decision_fx.c b/lib_enc/comvad_decision_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..ebd736e80c35b9d5cfbd376f8ae546b986351d1c
--- /dev/null
+++ b/lib_enc/comvad_decision_fx.c
@@ -0,0 +1,885 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include "options.h"
+#include "cnst.h" /* Common constants */
+#include "basop_util.h"
+#include "vad_basop.h"
+//#include "prot_fx.h"
+#include "rom_enc.h" /* Encoder static table prototypes */
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+#include "prot_fx_enc.h"
+
+
+
+/*-------------------------------------------------------------------*
+ * local function prototypes
+ *-------------------------------------------------------------------*/
+
+/* only one is activated in below preprocessing*/
+/*#define CLDFB_VAD*/ /* test on the CLDFB-VAD */
+
+static Word16 comvad_hangover(
+ const Word32 lt_snr_org, /* i : original long time SNR*/
+ const Word32 snr, /* i : frequency domain SNR */
+ const Word32 l_snr, /* i : long time frequency domain SNR calculated by l_speech_snr and l_silence_snr*/
+ const Word32 snr_flux, /* i : average tsnr*/
+ const Word16 bw_index, /* i : band width index*/
+ const Word16 vad_flag,
+ const Word16 pre_res_hang_num, /* i : residual amount of previous hangover */
+ const Word16 continuous_speech_num2, /* i : amount of continuous speech frames*/
+ const Word16 noisy_type /* i : noisy type*/
+)
+{
+ Word32 l_snr_add;
+ Word16 speech_flag;
+
+
+ speech_flag = pre_res_hang_num;
+ move16();
+
+ IF(EQ_16(bw_index, CLDFBVAD_SWB_ID))
+ {
+ IF(vad_flag)
+ {
+ speech_flag = 4;
+ move16();
+ if(GT_32(lt_snr_org, 117440509/* 3.5 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+
+ test();
+ test();
+ IF((LT_16(continuous_speech_num2, 8))&&(LT_32(lt_snr_org,134217724/* 4.0 Q25 */)))
+ {
+ speech_flag = sub(8, continuous_speech_num2);
+ }
+ ELSE IF((GT_32(snr_flux, 26843545/* 0.8 Q25 */))&&(GT_16(continuous_speech_num2,24)))
+ {
+ IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 87241521/* 2.6 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 53687090/* 1.6 Q25 */))
+ {
+ speech_flag = 4;
+ move16();
+ }
+ ELSE
+ {
+ speech_flag = 5;
+ move16();
+ }
+ speech_flag = sub(speech_flag,1);
+ }
+
+ IF(LT_16(continuous_speech_num2, 120))
+ {
+ test();
+ IF(GT_32(snr, 50331647/* 1.5 Q25 */))
+ {
+ speech_flag = 9;
+ move16();
+ }
+ ELSE IF(GT_32(snr, 33554431/* 1.0 Q25 */)&<_16(speech_flag,7))
+ {
+ speech_flag = 7;
+ move16();
+ }
+ ELSE IF(LT_16(speech_flag,3))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ if(GT_16(speech_flag,3))
+ {
+ speech_flag =sub(speech_flag,2);
+ }
+ }
+ ELSE
+ {
+ IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */))
+ {
+ speech_flag = 1;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 100663293/* 3.0 Q25 */))
+ {
+ speech_flag = 2;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 83886078/* 2.5 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 67108862/* 2.0 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 50331647/* 1.5 Q25 */))
+ {
+ speech_flag = 4;
+ move16();
+ }
+ ELSE
+ {
+ speech_flag = 5;
+ move16();
+ }
+ }
+
+ if(EQ_16(noisy_type, SILENCE))
+ {
+ speech_flag = 6;
+ move16();
+ }
+ }
+ }
+ ELSE IF(EQ_16(bw_index, CLDFBVAD_WB_ID))
+ {
+ IF(vad_flag)
+ {
+ IF(GT_32(lt_snr_org, 117440509/* 3.5 Q25 */))
+ {
+ speech_flag = 1;
+ move16();
+ }
+ ELSE
+ {
+ speech_flag = 2;
+ move16();
+ }
+
+ test();
+ test();
+ IF((LT_16(continuous_speech_num2, 8))&&(LT_32(lt_snr_org,134217724/* 4.0 Q25 */)))
+ {
+ speech_flag = sub(8, continuous_speech_num2);
+ }
+ ELSE IF((GT_32(snr_flux, 30198988/* 0.9 Q25 */))&&(GT_16(continuous_speech_num2,50)))
+ {
+ IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */))
+ {
+ speech_flag = 1;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 87241521/* 2.6 Q25 */))
+ {
+ speech_flag = 5;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 53687090/* 1.6 Q25 */))
+ {
+ speech_flag = 6;
+ move16();
+ }
+ ELSE
+ {
+ speech_flag = 7;
+ move16();
+ }
+ IF(GT_16(speech_flag , 1))
+ {
+ speech_flag = sub(speech_flag , 1);
+ }
+ }
+
+ IF(LT_16(continuous_speech_num2, 120))
+ {
+ test();
+ test();
+ test();
+ IF(GT_32(snr, 50331647/* 1.5 Q25 */))
+ {
+ speech_flag = 6;
+ move16();
+ }
+ ELSE IF(GT_32(snr, 33554431/* 1.0 Q25 */)&<_16(speech_flag,5))
+ {
+ speech_flag = 5;
+ move16();
+ }
+ ELSE IF(GT_32(snr, 26843545/* 0.8 Q25 */)&<_32(lt_snr_org,67108862/* 2.0 Q25 */)&<_16(speech_flag,4))
+ {
+ speech_flag = 4;
+ move16();
+ }
+ ELSE IF(LT_16(speech_flag, 3))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ }
+ ELSE
+ {
+ IF(GT_32(lt_snr_org,120795952/* 3.6 Q25 */))
+ {
+ speech_flag = 1;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 100663293/* 3.0 Q25 */))
+ {
+ speech_flag = 2;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 83886078/* 2.5 Q25 */))
+ {
+ speech_flag = 2;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 67108862/* 2.0 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE {
+ speech_flag = 3;
+ move16();
+ }
+ }
+
+ if(EQ_16(noisy_type, SILENCE))
+ {
+ speech_flag = 6;
+ move16();
+ }
+ }
+ }
+ ELSE /* NB */
+ {
+ IF(vad_flag)
+ {
+ l_snr_add = L_add(0x0199999a,MUL_F(l_snr,0x0ccd));
+
+ IF(GT_32(lt_snr_org, 117440509/* 3.5 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE
+ {
+ speech_flag = 4;
+ move16();
+ }
+
+ test();
+ test();
+ IF((LT_16(continuous_speech_num2,8))&&(LT_32(lt_snr_org,134217724/* 4.0 Q25 */)))
+ {
+ speech_flag = sub(8, continuous_speech_num2);
+ }
+ ELSE IF((GT_32(snr_flux, l_snr_add))&&(GT_16(continuous_speech_num2,24)))
+ {
+ IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 87241521/* 2.6 Q25 */))
+ {
+ speech_flag = 8;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 40265317/* 1.2 Q25 */))
+ {
+ speech_flag = 10;
+ move16();
+ }
+ ELSE
+ {
+ speech_flag = 12;
+ move16();
+ }
+
+ IF(GT_16(speech_flag ,2))
+ {
+ speech_flag = sub(speech_flag,2);
+ }
+ }
+
+ IF(LT_16(continuous_speech_num2, 120))
+ {
+ test();
+ test();
+ IF(GT_32(snr, 50331647/* 1.5 Q25 */))
+ {
+ speech_flag = 10;
+ move16();
+ }
+ ELSE IF(GT_32(snr, 33554431/* 1.0 Q25 */)&<_16(speech_flag,7))
+ {
+ speech_flag = 7;
+ move16();
+ }
+ ELSE IF(LT_16(speech_flag, 3)&>_16(continuous_speech_num2,12))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ }
+ ELSE
+ {
+ IF(GT_32(lt_snr_org, 120795952/* 3.6 Q25 */))
+ {
+ speech_flag = 2;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 100663293/* 3.0 Q25 */))
+ {
+ speech_flag = 2;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 83886078/* 2.5 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 67108862/* 2.0 Q25 */))
+ {
+ speech_flag = 3;
+ move16();
+ }
+ ELSE IF(GT_32(lt_snr_org, 50331647/* 1.5 Q25 */))
+ {
+ speech_flag = 4;
+ move16();
+ }
+ ELSE
+ {
+ speech_flag = 4;
+ move16();
+ }
+ }
+
+ if(EQ_16(noisy_type, SILENCE))
+ {
+ speech_flag = 2;
+ move16();
+ }
+ }
+ }
+
+
+ IF((EQ_16(vad_flag,1)))
+ {
+ IF((NE_16(noisy_type, SILENCE)))
+ {
+ speech_flag--;
+ }
+ ELSE
+ {
+ speech_flag = sub(speech_flag, 3);
+ }
+ speech_flag = s_max(speech_flag, 0);
+ }
+
+
+ return speech_flag;
+}
+
+
+
+Word16 comvad_decision_fx(
+ VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */
+ const Word32 l_snr, /* i : long time frequency domain*/
+ const Word32 lt_snr_org, /* i : original long time SNR*/
+ const Word32 lt_snr, /* i : long time SNR calculated by fg_energy and bg_energy*/
+ const Word32 snr_flux, /* i : average tsnr of several frames*/
+ const Word32 snr, /* i : frequency domain SNR */
+ Word32 tsnr, /* i : time domain SNR */
+ const Word32 frame_energy, /* i : current frame energy */
+ const Word16 music_backgound_f, /* i : background music flag*/
+ const Word16 frame_energy_Q, /* i : the Scaling of current frame energy*/
+ Word16 *cldfb_addition, /* o : adjust the harmonized hangover */
+ const Word16 vada_flag
+)
+{
+ Word16 speech_flag;
+ Word32 fg_energy;
+ Word32 bg_energy;
+ Word32 tmp_snr;
+ Word16 vad_flag;
+ Word16 vadb_flag;
+ Word32 l_silence_snr_count;
+ Word32 snr_sub;
+ Word32 snr_div_fix32;
+ Word32 l_silence_snr;
+
+ Word16 snr_div_fix;
+ Word16 Qnorm_silence,Qnorm_silence_count;
+ Word16 tmpout;
+ Word16 noisy_type;
+ Word32 lt_snr_org_cmp;
+
+
+
+ /* avoid overflows in the following if conditions */
+ tsnr = L_shr(tsnr,1);
+
+ noisy_type = UNKNOWN_NOISE;
+ move16();
+ speech_flag = hVAD_CLDFB ->speech_flag;
+ move16();
+ fg_energy = hVAD_CLDFB ->fg_energy;
+ move32();
+ bg_energy = hVAD_CLDFB ->bg_energy;
+ move32();
+
+ Qnorm_silence = 0;
+ move16();
+ Qnorm_silence_count = 0;
+ move16();
+
+ test();
+ IF(GT_32(hVAD_CLDFB ->lf_snr_smooth, LS_MIN_SILENCE_SNR[hVAD_CLDFB ->bw_index - CLDFBVAD_NB_ID] )&>_32(lt_snr_org,LT_MIN_SILENCE_SNR_FX[hVAD_CLDFB ->bw_index-CLDFBVAD_NB_ID]))
+ {
+ noisy_type = SILENCE;
+ move16();
+ }
+
+ tmp_snr = construct_snr_thresh_fx( hVAD_CLDFB ->sp_center, snr_flux, lt_snr, l_snr, hVAD_CLDFB ->continuous_speech_num,
+ hVAD_CLDFB ->continuous_noise_num, hVAD_CLDFB ->fg_energy_est_start, hVAD_CLDFB ->bw_index);
+
+
+ vad_flag = 0;
+ move16();
+ if(GT_32(snr, tmp_snr))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ if(GT_32(tsnr, 67108862/* 4.0/2.0 Q25 */))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ IF(GT_16(hVAD_CLDFB ->frameloop, 25))
+ {
+ test();
+ IF(EQ_16(vad_flag, 1)&&EQ_32(hVAD_CLDFB ->fg_energy_est_start,1))
+ {
+ Word32 frame_energy_mult_fix32,bg_energy_mult_fix32;
+ Word16 frame_energy_mult_Q,bg_energy_mult_Q;
+
+ IF(EQ_16(hVAD_CLDFB ->fg_energy_count, 512))
+ {
+ fg_energy = MUL_F(fg_energy, 0x6000);
+ hVAD_CLDFB ->fg_energy_count = 384;
+ move16();
+ }
+
+ frame_energy_mult_fix32 = MUL_F(frame_energy, hVAD_CLDFB ->bg_energy_count);
+ frame_energy_mult_Q = sub(frame_energy_Q, 15);
+
+ bg_energy_mult_fix32 = MUL_F(bg_energy, 6);
+ bg_energy_mult_Q = sub(hVAD_CLDFB ->bg_energy_scale, 15);
+
+ IF(GT_16(frame_energy_mult_Q, bg_energy_mult_Q))
+ {
+ frame_energy_mult_fix32 = L_shr(frame_energy_mult_fix32,sub(frame_energy_mult_Q, bg_energy_mult_Q));
+ }
+ IF(LT_16(frame_energy_mult_Q, bg_energy_mult_Q))
+ {
+ bg_energy_mult_fix32 = L_shr(bg_energy_mult_fix32,limitScale32(sub(bg_energy_mult_Q, frame_energy_mult_Q)));
+ }
+
+ IF(GT_32(frame_energy_mult_fix32, bg_energy_mult_fix32))
+ {
+ fg_energy = VAD_L_ADD(fg_energy, hVAD_CLDFB ->fg_energy_scale, frame_energy, frame_energy_Q, &hVAD_CLDFB ->fg_energy_scale);
+ hVAD_CLDFB ->fg_energy_count = add(hVAD_CLDFB ->fg_energy_count, 1);
+ move16();
+ }
+ }
+ }
+
+ if(music_backgound_f)
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ IF(EQ_16(vad_flag, 1))
+ {
+ IF (hVAD_CLDFB ->l_silence_snr == 0)
+ {
+ snr_div_fix = 0;
+ move16();
+ }
+ ELSE
+ {
+ Qnorm_silence=sub(norm_l(hVAD_CLDFB ->l_silence_snr), 1);
+ Qnorm_silence_count=norm_l(hVAD_CLDFB ->l_silence_snr_count);
+ l_silence_snr = L_shl(hVAD_CLDFB ->l_silence_snr,Qnorm_silence);
+ l_silence_snr_count = L_shl(hVAD_CLDFB ->l_silence_snr_count,Qnorm_silence_count);
+ snr_div_fix = div_l(l_silence_snr,extract_h(l_silence_snr_count));
+ }
+ snr_sub = L_sub(snr, 0x3000000);
+ snr_div_fix32 = L_deposit_l(snr_div_fix);
+ snr_div_fix32 = L_shr(snr_div_fix32, add(6, sub(Qnorm_silence, Qnorm_silence_count)));
+
+
+ IF(GT_32(snr_sub, snr_div_fix32))
+ {
+ IF(EQ_32(hVAD_CLDFB ->l_speech_snr_count, 512))
+ {
+ hVAD_CLDFB ->l_speech_snr = L_add(MUL_F(hVAD_CLDFB ->l_speech_snr, 0x6000), L_shr(snr, 9));
+ move32();
+ hVAD_CLDFB ->l_speech_snr_count = L_deposit_l(384+1);
+ move32();
+ }
+ ELSE
+ {
+ hVAD_CLDFB ->l_speech_snr = L_add(hVAD_CLDFB ->l_speech_snr, L_shr(snr, 9));
+ move32();
+ hVAD_CLDFB ->l_speech_snr_count = L_add(hVAD_CLDFB ->l_speech_snr_count, 1);
+ move32();
+ }
+ }
+ }
+
+ lt_snr_org_cmp = L_sub(lt_snr_org, 117440509/* 3.5 Q25 */);
+
+ IF(EQ_16(hVAD_CLDFB ->bw_index, CLDFBVAD_NB_ID))
+ {
+ Word32 lt_snr_add;
+
+ lt_snr_add = L_add(0x03cccccd, MUL_F(lt_snr, 0x23d7));
+
+ if(GT_32(snr_flux, lt_snr_add))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if( (GT_32(snr_flux, 50331647/* 1.5 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],1637/* 1.6 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if( (GT_32(snr_flux, 40265317/* 1.2 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],1944/* 1.9 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if((GT_32(snr_flux, 33554431/* 1.0 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],3274/* 3.2 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+ }
+ ELSE IF(EQ_16(hVAD_CLDFB ->bw_index, CLDFBVAD_WB_ID))
+ {
+ Word32 lt_snr_add;
+
+ lt_snr_add = L_add(0x04333333, MUL_F(lt_snr, 0x1eb8));
+
+ if(GT_32(snr_flux, lt_snr_add))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if((GT_32(snr_flux, 53687090/* 1.6 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],2558/* 2.5 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if((GT_32(snr_flux, 40265317/* 1.2 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],2864/* 2.8 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if((GT_32(snr_flux, 33554431/* 1.0 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],4604/* 4.5 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+ }
+ ELSE
+ {
+ Word32 lt_snr_add;
+
+ lt_snr_add = L_add(0x04333333, MUL_F(lt_snr, 0x28f5));
+
+ if((GT_32(snr_flux, lt_snr_add)))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if((GT_32(snr_flux, 56371444/* 1.68 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],2823/* 2.76 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if((GT_32(snr_flux, 41607494/* 1.24 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],2987/* 2.92 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+
+ test();
+ test();
+ if((GT_32(snr_flux, 36909874/* 1.10 Q25 */))&&(GT_16(hVAD_CLDFB ->sp_center[3],4706/* 4.6 Q10 */))&&(lt_snr_org_cmp<0))
+ {
+ vad_flag = 1;
+ move16();
+ }
+ }
+
+
+ IF(hVAD_CLDFB ->fg_energy_est_start==0)
+ {
+ tmpout = VAD_L_CMP(frame_energy, frame_energy_Q, 50, 0);
+
+ test();
+ test();
+ if(GT_16(hVAD_CLDFB ->ltd_stable_rate[0], 2621/* 0.08 Q15 */)&&EQ_16(vad_flag,1)&&(tmpout>0))
+ {
+ hVAD_CLDFB ->fg_energy_est_start = L_deposit_l(1);
+ }
+ }
+
+ speech_flag = comvad_hangover( lt_snr_org,
+ snr,
+ l_snr,
+ snr_flux,
+ hVAD_CLDFB ->bw_index,
+ vad_flag,
+ speech_flag,
+ hVAD_CLDFB ->continuous_speech_num2,
+ noisy_type);
+
+
+
+ test();
+ IF(vad_flag == 0 && speech_flag > 0)
+ {
+ speech_flag = sub(speech_flag, 1);
+ vad_flag = 1;
+ move16();
+ }
+ vadb_flag = vad_flag;
+
+ IF(EQ_16(hVAD_CLDFB ->bw_index, CLDFBVAD_SWB_ID))
+ {
+ test();
+ test();
+ test();
+ IF(EQ_16(SILENCE, noisy_type)
+ && GT_32(snr, 6710886/* 0.2 Q25 */)
+ && vad_flag == 0)
+ {
+ vad_flag = vada_flag;
+ move16();
+ }
+ ELSE IF(LT_32(hVAD_CLDFB ->lf_snr_smooth,352321526/* 10.5 Q25 */)||NE_16(SILENCE,noisy_type))
+ {
+ test();
+ test();
+ test();
+ IF(GT_32(snr_flux, 83886078/* 2.5 Q25 */)
+ || ( hVAD_CLDFB ->continuous_speech_num2 > 40 && GT_32(snr_flux, 67108862/* 2.0 Q25 */) )
+ || music_backgound_f == 1)
+ {
+ vad_flag = s_or(vad_flag, vada_flag);
+ }
+ ELSE IF(EQ_16(SILENCE, noisy_type))
+ {
+ vad_flag = vada_flag;
+ }
+ }
+
+ }
+ ELSE IF(EQ_16(hVAD_CLDFB ->bw_index, CLDFBVAD_WB_ID))
+ {
+ test();
+ test();
+ test();
+ IF(EQ_16(SILENCE, noisy_type)
+ && GT_32(snr, 6710886/* 0.2 Q25 */)
+ && vad_flag == 0)
+ {
+ vad_flag = vada_flag;
+ move16();
+ }
+ ELSE IF(LT_32(hVAD_CLDFB ->lf_snr_smooth,352321526/* 10.5 Q25 */)||NE_16(SILENCE,noisy_type))
+ {
+ test();
+ test();
+ test();
+ IF(GT_32(snr_flux, 73819748/* 2.2 Q25 */)
+ || (hVAD_CLDFB ->continuous_speech_num2 > 40 && GT_32(snr_flux, 57042532/* 1.7 Q25 */) )
+ || music_backgound_f == 1)
+ {
+ vad_flag = s_or(vad_flag, vada_flag);
+ }
+ ELSE IF(EQ_16(SILENCE, noisy_type))
+ {
+ vad_flag = vada_flag;
+ }
+
+ }
+
+ }
+ ELSE
+ {
+ IF(EQ_16(SILENCE, noisy_type))
+ {
+ test();
+ IF(GT_32(hVAD_CLDFB ->lf_snr_smooth , 419430388/* 12.5 Q25 */)
+ && music_backgound_f == 0)
+ {
+ vad_flag = vada_flag;
+ }
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ IF(GT_32(snr_flux, 67108862/* 2.0 Q25 */)
+ || (hVAD_CLDFB ->continuous_speech_num2 > 30 && GT_32(snr_flux, 50331647/* 1.5 Q25 */) )
+ || music_backgound_f == 1)
+ {
+ vad_flag = s_or(vad_flag, vada_flag);
+ }
+ }
+ }
+
+ IF(vad_flag == 0)
+ {
+ IF(EQ_32(hVAD_CLDFB ->l_silence_snr_count, 512))
+ {
+ hVAD_CLDFB ->l_silence_snr = L_add(MUL_F(hVAD_CLDFB ->l_silence_snr, 0x6000),L_shr(snr, 9));
+ move32();
+ hVAD_CLDFB ->l_silence_snr_count = L_deposit_l(384+1);
+ move32();
+ }
+ ELSE IF(LT_32(snr, 26843545/* 0.8 Q25 */))
+ {
+ hVAD_CLDFB ->l_silence_snr = L_add(hVAD_CLDFB ->l_silence_snr, L_shr(snr,9));
+ move32();
+ hVAD_CLDFB ->l_silence_snr_count = L_add(hVAD_CLDFB ->l_silence_snr_count, 1);
+ move32();
+ }
+ }
+
+ IF(vad_flag == 0)
+ {
+ IF(EQ_16(hVAD_CLDFB ->bg_energy_count, 512))
+ {
+ bg_energy = MUL_F(bg_energy, 0x6000);
+ hVAD_CLDFB ->bg_energy_count = 384;
+ move16();
+ }
+
+ IF(LT_32(tsnr, 16777216/* 1.0/2.0 Q25 */))
+ {
+ bg_energy = VAD_L_ADD(bg_energy, hVAD_CLDFB ->bg_energy_scale, frame_energy, frame_energy_Q, &hVAD_CLDFB ->bg_energy_scale);
+ hVAD_CLDFB ->bg_energy_count = add(hVAD_CLDFB ->bg_energy_count, 1);
+ move16();
+ }
+ }
+
+ test();
+ hVAD_CLDFB ->vad_flag_for_bk_update = vad_flag;
+ IF(LT_16(hVAD_CLDFB ->update_count, 12)&&EQ_16(vadb_flag,1))
+ {
+ hVAD_CLDFB ->warm_hang_num = s_max(20, speech_flag);
+ }
+ test();
+ IF(vad_flag == 0 && hVAD_CLDFB ->warm_hang_num > 0)
+ {
+ hVAD_CLDFB ->warm_hang_num = sub(hVAD_CLDFB ->warm_hang_num, 1);
+ vad_flag = 1;
+ move16();
+ }
+
+
+
+
+ hVAD_CLDFB ->lt_snr_org = lt_snr_org;
+ move32();
+ hVAD_CLDFB ->fg_energy = fg_energy;
+ move32();
+ hVAD_CLDFB ->bg_energy = bg_energy;
+ move32();
+
+ hVAD_CLDFB ->speech_flag = speech_flag;
+ move16();
+
+ move16();
+ test();
+ IF(EQ_16(noisy_type, SILENCE)
+ && NE_16(hVAD_CLDFB ->bw_index, CLDFBVAD_NB_ID))
+ {
+ *cldfb_addition = 2;
+ }
+ ELSE
+ {
+ *cldfb_addition = 0;
+
+ if(EQ_16(hVAD_CLDFB ->bw_index, CLDFBVAD_WB_ID))
+ {
+ *cldfb_addition = 3;
+ move16();
+ }
+ if(EQ_16(hVAD_CLDFB ->bw_index, CLDFBVAD_SWB_ID))
+ {
+ *cldfb_addition = 1;
+ move16();
+ }
+ if(EQ_16(hVAD_CLDFB ->bw_index, CLDFBVAD_NB_ID))
+ {
+ *cldfb_addition = 1;
+ move16();
+ }
+
+ }
+
+
+
+
+ return vad_flag;
+}
+
diff --git a/lib_enc/cor_shif_fx.c b/lib_enc/cor_shif_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..94a1a58b7751b85f69ea27241f301c6520f6c8d7
--- /dev/null
+++ b/lib_enc/cor_shif_fx.c
@@ -0,0 +1,52 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+/*-------------------------------------------------------------------*
+ * correlation_shift_fx
+ *
+ * Find normalized correlation correction dependent on estimated noise
+ * Note: this variable is basically active only if noise suppression
+ * is desactivated. Otherwise, for default NS = 14 dB and up to 10dB SNR
+ * it can be assumed about 0
+ *-------------------------------------------------------------------*/
+
+Word16 correlation_shift_fx( /* o : noise dependent voicing correction Q15 */
+ const Word16 totalNoise_fx /* i/o: noise estimate over all critical bands Q8 */
+)
+{
+ Word16 corr_shift_fx, e_Noise, f_Noise, wtmp;
+ Word32 Ltmp;
+
+ corr_shift_fx = 0;
+ move16();
+
+ IF (GT_16(totalNoise_fx, 7215)) /* to make corr_shift > 0.0 */
+ {
+ /*------------------------------------------------------------*
+ * useful values range from 0 to 1 (can saturate at 1.0) Q31 value
+ * corr_shift = 2.4492E-4 * exp(0.1596 * totalNoise) - 0.022
+ * Result in Q14
+ *------------------------------------------------------------*/
+ Ltmp = L_mult(totalNoise_fx, 7545); /* Q24 */
+ Ltmp = L_shr(Ltmp, 8); /* Q24 -> Q16 */
+ f_Noise = L_Extract_lc(Ltmp, &e_Noise);
+ wtmp = extract_l(Pow2(14, f_Noise)); /* Put 14 as exponent */
+
+ e_Noise = sub(e_Noise, 14); /* Retreive exponent of wtmp */
+ Ltmp = Mpy_32_16(8, 837, wtmp); /* 2.4492e-4(Q31) * exp(0.1596*totalNoise) */
+ Ltmp = L_shl(Ltmp,add(e_Noise, 15)); /* Result in Q31 */
+ corr_shift_fx = round_fx(L_sub(Ltmp, 47244640)); /* Represents corr_shift in Q15 */
+ }
+ corr_shift_fx = s_min(corr_shift_fx,16384); /* limit to 0.5 */
+
+ return corr_shift_fx;
+}
diff --git a/lib_enc/core_enc_2div_fx.c b/lib_enc/core_enc_2div_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f0aadd8db893646011a14ff8752404bda3a42f1
--- /dev/null
+++ b/lib_enc/core_enc_2div_fx.c
@@ -0,0 +1,350 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include
+#include "options.h"
+#include "cnst.h" /* Common constants */
+#include "ivas_cnst.h" /* Common constants */
+//#include "prot_fx.h"
+#include "basop_util.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+ /*-------------------------------------------------------------------*
+ * core_encode_twodiv_fx()
+ *
+ * Two-div core encoder
+ *-------------------------------------------------------------------*/
+
+void core_encode_twodiv_fx(
+ const Word16 new_samples[], /* i : new samples */
+ Encoder_State_fx *st, /* i/o: coder memory state */
+ const Word16 coder_type, /* i : coding type */
+ Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/
+ const Word16 vad_hover_flag, /* i : VAD hangover flag */
+ Word16 *Q_new,
+ Word16 *shift
+)
+{
+ Word16 n;
+ Word16 lsp_new[M], lsp_mid[M];
+ Word16 lsf_q[M], lsp_q[M], lspmid_q[M];
+ Word16 A_q[M+1];
+ Word16 param_lpc[NPRM_LPC_NEW];
+ Word16 nbits_lpc[2];
+ Word16 param_core[2*NPRM_DIV];
+ Word16 target_bits;
+ Word16 gainlpc[2][FDNS_NPTS];
+ Word16 gainlpc_e[2][FDNS_NPTS];
+ Word16 tnsSize[2]; /* number of tns parameters put into prm */
+ Word16 tnsBits[2]; /* number of tns bits in the frame */
+ Word16 ltpBits;
+ Word16 bitsAvailable;
+ Word32 spectrum_buf[N_MAX];
+ Word32 *spectrum[2]; /* MDCT spectrum */
+ Word16 spectrum_e[2];
+ Word16 indexBuffer[2*((N_MAX/2)+1)];
+ CONTEXT_HM_CONFIG hm_cfg[2];
+ Word16 i, T_op[3];
+ Word16 bits_param_lpc[10], no_param_lpc;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */
+ hLPDmem = st->hLPDmem;
+
+ spectrum[0] = spectrum_buf;
+ spectrum[1] = spectrum_buf + N_TCX10_MAX;
+
+ hm_cfg[0].indexBuffer = &indexBuffer[0];
+ move16();
+ hm_cfg[1].indexBuffer = &indexBuffer[N_MAX/2+1];
+ move16();
+
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ tnsSize[0] = 0;
+ tnsSize[1] = 0;
+ tnsBits[0] = 0;
+ tnsBits[1] = 0;
+ ltpBits = 0;
+
+ FOR( i = 0; i < 3; i++ )
+ {
+ move16();
+ T_op[i] = st->pitch_fx[i];
+
+ /* check minimum pitch for quantization */
+ IF ( LT_16(T_op[i], PIT_MIN_SHORTER))
+ {
+ move16();
+ T_op[i] = shl(T_op[i], 1);
+ }
+
+ /* convert pitch values to core sampling-rate */
+ IF ( NE_16(st->L_frame_fx, L_FRAME))
+ {
+ move16();
+ /* T_op[i] = (short)(T_op[i] * (float)st->L_frame_fx/(float)L_FRAME + 0.5f); */
+ T_op[i] = round_fx(L_shr(L_mult0(T_op[i], st->L_frame_fx), 8 - 16));
+ }
+ }
+
+ /*--------------------------------------------------------------*
+ * TCX20/TCX10 switching decision
+ *---------------------------------------------------------------*/
+
+ move16();
+ st->core_fx = TCX_10_CORE;
+ if ( EQ_16(hTcxEnc->tcxMode,TCX_20))
+ {
+ move16();
+ st->core_fx = TCX_20_CORE;
+ }
+ assert(hTcxEnc->tcxMode == TCX_20 || hTcxEnc->tcxMode == TCX_10);
+
+ /*--------------------------------------------------------------*
+ * Core Signal Analysis: MDCT, TNS, LPC analysis
+ *---------------------------------------------------------------*/
+
+ core_signal_analysis_high_bitrate_fx( new_samples,
+ T_op,
+ lsp_new,
+ lsp_mid,
+ st,
+ tnsSize,
+ tnsBits,
+ param_core,
+ <pBits,
+ st->L_frame_fx,
+ hTcxEnc->L_frameTCX,
+ EVS_MONO,
+ vad_hover_flag,
+ spectrum,
+ spectrum_e,
+ Q_new
+ );
+
+ /*--------------------------------------------------------------*
+ * LPC Quantization
+ *---------------------------------------------------------------*/
+ lpc_quantization_fx( st, lsp_new, lsp_mid, lsp_q, lsf_q, lspmid_q, NULL, st->clip_var_fx, coder_type,
+ 0, param_lpc, nbits_lpc, bits_param_lpc, &no_param_lpc, add(*Q_new, Q_SCALE - 2) );
+
+ /*--------------------------------------------------------------*
+ * Rate switching
+ *---------------------------------------------------------------*/
+ IF( st->rate_switching_reset!=0 )
+ {
+ Copy( lsp_q, st->lsp_old_fx, M );
+ Copy( lsf_q, st->lsf_old_fx, M );
+ }
+
+
+
+ /*--------------------------------------------------------------*
+ * Run Two TCX10
+ *---------------------------------------------------------------*/
+
+ IF ( EQ_16(st->core_fx,TCX_10_CORE))
+ {
+ Word16 last_ace_mode;
+
+
+ move16();
+ last_ace_mode = st->last_core_fx;
+
+
+ FOR (n = 0; n < 2; n++)
+ {
+ IF(n == 0)
+ {
+ E_LPC_f_lsp_a_conversion(lspmid_q, A_q, M);
+ }
+ ELSE
+ {
+ E_LPC_f_lsp_a_conversion(lsp_q, A_q, M);
+ }
+
+ /* Shape spectrum */
+ ShapeSpectrum_fx(st->hTcxCfg,
+ A_q,
+ gainlpc[n],
+ gainlpc_e[n],
+ shr(st->L_frame_fx, 1),
+ shr(st->hTcxCfg->tcx_coded_lines, 1),
+ spectrum[n],
+ hTcxEnc->fUseTns_fx[n],
+ st
+ );
+
+ st->last_core_fx = st->core_fx;
+ move16();
+ }
+ st->last_core_fx = last_ace_mode;
+ move16();
+
+
+ /* Calculate target bits */
+ bitsAvailable = sub(sub(sub(st->bits_frame_core, nbits_lpc[0]), nbits_lpc[1]), st->nb_bits_header_tcx);
+
+ /* subtract bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */
+ bitsAvailable = sub(bitsAvailable,1);
+ test();
+ if (EQ_16(st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP)||EQ_16(st->hTcxCfg->tcx_curr_overlap_mode,MIN_OVERLAP))
+ {
+ bitsAvailable = sub(bitsAvailable,1);
+ }
+
+ bitsAvailable = sub(bitsAvailable, st->hIGFEnc->infoTotalBitsWritten);
+
+ /* calculate noise-filling over whole spectrum for TCX10 frames */
+ move16();
+ hTcxEnc->measuredBwRatio = 0x4000;
+
+ FOR (n = 0; n < 2; n++)
+ {
+ target_bits = sub(shr(sub(add(bitsAvailable, 1), n),1), tnsBits[n]);
+
+ if (n == 0)
+ {
+ target_bits = sub(target_bits, ltpBits);
+ }
+
+ test();
+ if(st->enablePlcWaveadjust && n)
+ {
+ target_bits = sub(target_bits, 1);
+ }
+
+
+ /* Run TCX10 encoder */
+
+ QuantizeSpectrum_fx(
+ st->hTcxCfg,
+ A_q,
+ NULL,
+ gainlpc[n],
+ gainlpc_e[n],
+ st->synth+n*st->L_frame_fx/2,
+ shr(st->L_frame_fx, 1),
+ shr(hTcxEnc->L_frameTCX, 1),
+ shr(st->hTcxCfg->tcx_coded_lines, 1),
+ target_bits,
+ st->tcxonly,
+ spectrum[n],
+ &spectrum_e[n],
+ hTcxEnc->tnsData+n,
+ hTcxEnc->fUseTns_fx[n],
+ tnsSize[n],
+ param_core+n*NPRM_DIV,
+ n,
+ st,
+ &hm_cfg[n]
+ );
+
+ /* Update tcx overlap mode */
+ test();
+ if ((n > 0) || (st->tcxonly==0))
+ {
+ move16();
+ st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode;
+ }
+
+ }
+
+ coder_tcx_post_fx( st, hLPDmem, st->hTcxCfg, st->synth, A_q, Aw, st->wspeech_enc, *Q_new, *shift );
+ }
+
+ /*--------------------------------------------------------------*
+ * Run One TCX20
+ *---------------------------------------------------------------*/
+
+ IF ( EQ_16(st->core_fx,TCX_20_CORE))
+ {
+
+ E_LPC_f_lsp_a_conversion(lsp_q, A_q, M);
+
+
+ ShapeSpectrum_fx(st->hTcxCfg,
+ A_q,
+ gainlpc[0],
+ gainlpc_e[0],
+ st->L_frame_fx,
+ st->hTcxCfg->tcx_coded_lines,
+ spectrum[0],
+ hTcxEnc->fUseTns_fx[0],
+ st
+ );
+
+ /*_DIFF_FLOAT_FIX_ -> The line below is present in float */
+ //hTcxEnc->measuredBwRatio = 0x4000;
+ /* Calculate target bits */
+
+ target_bits = sub(sub(sub(sub(st->bits_frame_core, tnsBits[0]), nbits_lpc[0]), st->nb_bits_header_tcx), ltpBits);
+ /* subtract bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */
+ target_bits = sub(target_bits,1);
+ test();
+ if (EQ_16(st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP)||EQ_16(st->hTcxCfg->tcx_curr_overlap_mode,MIN_OVERLAP))
+ {
+ target_bits = sub(target_bits,1);
+ }
+
+ target_bits = sub(target_bits, st->hIGFEnc->infoTotalBitsPerFrameWritten);
+
+
+ if(st->enablePlcWaveadjust)
+ {
+ target_bits = sub(target_bits, 1);
+ }
+
+
+ QuantizeSpectrum_fx(
+ st->hTcxCfg,
+ A_q,
+ NULL,
+ gainlpc[0],
+ gainlpc_e[0],
+ st->synth,
+ st->L_frame_fx,
+ hTcxEnc->L_frameTCX,
+ st->hTcxCfg->tcx_coded_lines,
+ target_bits,
+ st->tcxonly,
+ spectrum[0],
+ &spectrum_e[0],
+ &hTcxEnc->tnsData[0],
+ hTcxEnc->fUseTns_fx[0],
+ tnsSize[0],
+ param_core,
+ 0,
+ st,
+ &hm_cfg[0]
+ );
+
+ coder_tcx_post_fx( st, hLPDmem, st->hTcxCfg, st->synth, A_q, Aw, st->wspeech_enc, *Q_new, *shift );
+
+ }
+
+ /* Update lsp/lsf memory */
+ Copy(lsf_q, st->lsf_old_fx, M);
+ Copy(lsp_q, st->lsp_old_fx, M);
+
+
+
+ /*--------------------------------------------------------------*
+ * Generate Bitstream
+ *---------------------------------------------------------------*/
+
+ enc_prm_fx( coder_type, param_core, param_lpc, st, st->L_frame_fx, hm_cfg, bits_param_lpc, no_param_lpc );
+
+}
+
diff --git a/lib_enc/core_enc_init_fx.c b/lib_enc/core_enc_init_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..37bce06a423c2e62099fe7028febe2466c72fa42
--- /dev/null
+++ b/lib_enc/core_enc_init_fx.c
@@ -0,0 +1,909 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+//#include "prot_fx.h"
+//#include "basop_mpy.h"
+#include "options.h"
+#include "cnst.h" /* Common constants */
+#include "stl.h"
+#include "count.h"
+#include "basop_util.h"
+#include "rom_com_fx.h"
+#include "ivas_cnst.h"
+#include
+#include "rom_com.h" /* Common constants */
+#include "prot.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+
+/*-----------------------------------------------------------------------*
+ * Local functions
+ *-----------------------------------------------------------------------*/
+
+static void init_tcx_fx( Encoder_State_fx *st, Word16 L_frame_old, const Word32 total_brate, const Word32 last_total_brate, const Word16 MCT_flag);
+static void init_core_sig_ana_fx(Encoder_State_fx *st );
+static void init_acelp_fx(Encoder_State_fx *st, Word16 L_frame_old, const Word16 shift);
+static void init_modes_fx(Encoder_State_fx *st, const Word32 Last_total_brate );
+static void init_sig_buffers_fx(Encoder_State_fx *st, const Word16 L_frame_old, const Word16 L_subfr);
+
+/*-----------------------------------------------------------------------*
+ * init_coder_ace_plus_fx()
+ *
+ * Initialization of state variables
+ *-----------------------------------------------------------------------*/
+
+void init_coder_ace_plus_fx(
+ Encoder_State_fx *st,
+ const Word32 last_total_brate, /* i : last total bitrate */
+ const Word16 shift,
+ const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */
+)
+{
+ Word16 L_frame_old; /*keep old frame size for switching */
+ Word16 L_subfr;
+ TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ /* Bitrate */
+ st->tcxonly = (Word8)getTcxonly(
+#ifdef IVAS_CODE_SWITCHING
+ st->element_mode,
+#endif
+ st->total_brate_fx
+#ifdef IVAS_CODE_SWITCHING
+ , MCT_flag, st->is_ism_format
+#endif
+ );
+ move16();
+
+ /* Core Sampling Rate */
+ st->sr_core = getCoreSamplerateMode2(st->element_mode, st->total_brate_fx, st->bwidth_fx, st->flag_ACELP16k, st->rf_mode, st->is_ism_format);
+ st->fscale = sr2fscale(st->sr_core);
+ move16();
+
+ /* Narrowband? */
+ st->narrowBand = 0;
+ move16();
+ if( EQ_16(st->bwidth_fx, NB))
+ {
+ st->narrowBand = 1;
+ move16();
+ }
+
+ /* Core Framing */
+ L_frame_old = st->last_L_frame_fx;
+ move16();
+ st->L_frame_fx = extract_l(Mult_32_16(st->sr_core , 0x0290));
+ st->L_frame_past = -1;
+ move16();
+
+ hTcxEnc->L_frameTCX = extract_l(Mult_32_16(st->input_Fs_fx , 0x0290));
+
+ st->nb_subfr = NB_SUBFR;
+ move16();
+ L_subfr = shr(st->L_frame_fx, 2);
+ test();
+ IF ( EQ_16(st->L_frame_fx, L_FRAME16k)&&LE_32(st->total_brate_fx,32000))
+ {
+ st->nb_subfr = NB_SUBFR16k;
+ move16();
+ L_subfr = mult(st->L_frame_fx, 0x199A); /*1/5 = 0x199A Q15*/ move16();
+ }
+
+ /* Core Lookahead */
+ st->encoderLookahead_enc = NS2SA_fx2(st->sr_core, ACELP_LOOK_NS);
+ move16();
+ st->encoderLookahead_FB = NS2SA_fx2(st->input_Fs_fx, ACELP_LOOK_NS);
+ move16();
+
+ IF ( st->ini_frame_fx == 0 )
+ {
+ st->acelpFramesCount = 0;
+ move16();
+ st->prevTempFlatness_fx = 128/*1.0f Q7*/;
+ move16();
+ }
+
+ /* Initialize TBE */
+ hBWE_TD->prev_coder_type = GENERIC;
+ move16();
+ set16_fx(hBWE_TD->prev_lsf_diff_fx, 16384, LPC_SHB_ORDER-2 );
+ hBWE_TD->prev_tilt_para_fx = 0;
+ move16();
+ set16_fx(hBWE_TD->cur_sub_Aq_fx, 0, M+1 );
+
+ st->currEnergyHF_fx = 0;
+ move16();
+ st->currEnergyHF_e_fx = 0;
+ move16();
+ st->energyCoreLookahead_Fx = 0;
+ move16();
+
+ /* Initialize LPC analysis/quantization */
+ st->lpcQuantization = 0;
+ move16();
+ test();
+ if( LE_32(st->sr_core,16000)&&st->tcxonly==0)
+ {
+ st->lpcQuantization = 1;
+ move16();
+ }
+
+
+ st->next_force_safety_net_fx = 0;
+ move16();
+ test();
+ test();
+ IF ( NE_16(st->last_L_frame_fx,st->L_frame_fx)||EQ_16(st->last_core_fx,AMR_WB_CORE)||EQ_16(st->last_core_fx,HQ_CORE))
+ {
+ set16_fx( st->mem_MA_fx, 0, M );
+ Copy(GEWB_Ave_fx, st->mem_AR_fx, M);
+ }
+
+ /* Initialize IGF */
+ if (st->hIGFEnc != NULL)
+ {
+ st->hIGFEnc->infoStopFrequency = -1;
+ }
+ move16();
+ IF( st->igf )
+ {
+ IGFEncSetMode_fx(st->hIGFEnc, st->total_brate_fx, st->bwidth_fx, st->element_mode, st->rf_mode);
+ }
+ ELSE IF (st->hIGFEnc != NULL)
+ {
+ st->hIGFEnc->infoTotalBitsWritten = 0;
+ if (EQ_16(MCT_flag, -10))
+ {
+ st->hIGFEnc->infoTotalBitsPerFrameWritten = 0;
+ }
+ /* the line above is needed for some transition, but when going from low rate to high rate, ex 7k2 to 96k, EVS fix point doesn't do the reset (or it does somewhere else */
+ }
+
+ /* Initialize TCX */
+ if (hTcxEnc != NULL)
+ {
+ init_tcx_fx(st, L_frame_old, st->total_brate_fx, last_total_brate, MCT_flag);
+ }
+ /* Initialize Core Signal Analysis Module */
+ init_core_sig_ana_fx( st );
+
+ /* Initialize Signal Buffers */
+ init_sig_buffers_fx( st, L_frame_old, L_subfr );
+
+ /* Initialize ACELP */
+ init_acelp_fx( st, L_frame_old , shift);
+
+ if(st->ini_frame_fx == 0)
+ {
+ st->tec_tfa = 0;
+ move16();
+ }
+ IF(st->tec_tfa == 0)
+ {
+ resetTecEnc_Fx(st->hTECEnc, 0);
+ }
+ ELSE
+ {
+ resetTecEnc_Fx(st->hTECEnc, 1);
+ }
+ st->tec_tfa = 0;
+ move16();
+ test();
+ test();
+ if( EQ_16(st->bwidth_fx, SWB)&&(EQ_32(st->total_brate_fx,ACELP_16k40)||EQ_32(st->total_brate_fx,ACELP_24k40)))
+ {
+ st->tec_tfa = 1;
+ move16();
+ }
+
+ st->tec_flag = 0;
+ move16();
+ st->tfa_flag = 0;
+ move16();
+ /* Initialize DTX */
+ IF( st->ini_frame_fx == 0 )
+ {
+
+ vad_init_fx(&st->vad_st);
+ }
+
+ st->glr = 0;
+ move16();
+
+ test();
+ test();
+ test();
+ if( (EQ_32(st->total_brate_fx, ACELP_9k60))||(EQ_32(st->total_brate_fx,ACELP_16k40))||
+ (EQ_32(st->total_brate_fx, ACELP_24k40))||(EQ_32(st->total_brate_fx, ACELP_32k)))
+ {
+ st->glr = 1;
+ move16();
+ }
+
+ st->glr_reset = 0;
+ move16();
+
+ /* Initialize ACELP/TCX Modes */
+ init_modes_fx( st, last_total_brate);
+
+ /* Init I/O */
+
+
+ /* Adaptive BPF */
+ set16_fx(st->mem_bpf.noise_buf, 0, 2*L_FILT16k);
+ set16_fx(st->mem_bpf.error_buf, 0, L_FILT16k);
+ set16_fx(st->bpf_gainT, 0, NB_SUBFR16k);
+
+ set16_fx(st->bpf_T, PIT_MIN_12k8, NB_SUBFR16k);
+
+ st->mem_bpf.noise_shift_old = 0;
+ move16();
+
+ IF ( st->ini_frame_fx == 0 )
+ {
+ st->Q_max_enc[0] = 15;
+ move16();
+ st->Q_max_enc[1] = 15;
+ move16();
+ }
+
+ st->enablePlcWaveadjust = 0;
+ move16();
+ if (GE_32(st->total_brate_fx, 48000))
+ {
+ st->enablePlcWaveadjust = 1;
+ move16();
+ }
+
+ init_PLC_enc_fx( st->hPlcExt, st->sr_core );
+
+ st->glr_idx[0] = 0;
+ move16();
+ st->glr_idx[1] = 0;
+ move16();
+ move16();
+ move16(); /* casts */
+ st->mean_gc[0] = L_deposit_h(0);
+ st->mean_gc[1] = L_deposit_h(0);
+ st->prev_lsf4_mean = 0;
+ move16();
+
+ st->last_stab_fac = 0;
+ move16();
+
+
+ return;
+}
+
+static void init_tcx_fx(
+ Encoder_State_fx *st,
+ Word16 L_frame_old,
+ const Word32 total_brate,
+ const Word32 last_total_brate,
+ const Word16 MCT_flag
+)
+{
+ Word16 i;
+ Word16 fscaleFB;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING
+ (void)MCT_flag;
+ (void)total_brate;
+ (void)last_total_brate;
+#endif
+//PMT("init_tcx_fx needs an entire review to adapt to IVAS")
+ fscaleFB = div_l(L_shl(st->input_Fs_fx, LD_FSCALE_DENOM+1), 12800);
+
+ init_TCX_config(st->hTcxCfg, st->L_frame_fx, st->fscale, hTcxEnc->L_frameTCX, fscaleFB );
+
+ st->hTcxCfg->tcx_mdct_window_length_old = st->hTcxCfg->tcx_mdct_window_length;
+ move16();
+
+ /* TCX Offset */
+ st->hTcxCfg->tcx_offset = shr(st->hTcxCfg->tcx_mdct_window_delay, 1);
+ move16();
+ st->hTcxCfg->tcx_offsetFB = shr(st->hTcxCfg->tcx_mdct_window_delayFB, 1);
+ move16();
+
+ /*<0 rectangular transition with optimized window size = L_frame+L_frame/4*/
+ st->hTcxCfg->lfacNext = sub(st->hTcxCfg->tcx_offset, shr(st->L_frame_fx, 2));
+ move16();
+ st->hTcxCfg->lfacNextFB = sub(st->hTcxCfg->tcx_offsetFB, shr(hTcxEnc->L_frameTCX, 2));
+
+ IF ( st->ini_frame_fx == 0 )
+ {
+ st->hTcxCfg->tcx_curr_overlap_mode = st->hTcxCfg->tcx_last_overlap_mode = ALDO_WINDOW;
+ move16();
+ move16();
+ }
+
+ /* Init TCX target bits correction factor */
+ hTcxEnc->tcx_target_bits_fac = 0x4000; /*1.0f in 1Q14*/ move16();
+ hTcxEnc->measuredBwRatio = 0x4000; /*1.0f in 1Q14*/ move16();
+ hTcxEnc->noiseTiltFactor = 9216; /*0.5625f in 1Q14*/ move16();
+ hTcxEnc->noiseLevelMemory_cnt = 0;
+ move16();
+ /*SQ deadzone & memory quantization*/
+
+ /*0.375f: deadzone of 1.25->rounding=1-1.25/2 (No deadzone=0.5)*/
+ st->hTcxCfg->sq_rounding = 12288/*0.375f Q15*/;
+ move16();
+
+ FOR (i = 0; i < L_FRAME_PLUS; i++)
+ {
+ hTcxEnc->memQuantZeros_fx[i] = 0;
+ move16();
+ }
+
+ /* TCX rate loop */
+ st->hTcxCfg->tcxRateLoopOpt = 0;
+ move16();
+
+ if ( st->tcxonly != 0 )
+ {
+ st->hTcxCfg->tcxRateLoopOpt = 2;
+ move16();
+ }
+
+ /* TCX bandwidth */
+ move16();
+ st->hTcxCfg->bandwidth = getTcxBandwidth(st->bwidth_fx);
+
+
+ /* set number of coded lines */
+ st->hTcxCfg->tcx_coded_lines = getNumTcxCodedLines(st->bwidth_fx);
+
+ /* TNS in TCX */
+ move16();
+ move16();
+ st->hTcxCfg->fIsTNSAllowed = (Word8)getTnsAllowed(st->total_brate_fx ,st->igf, st->element_mode);
+
+ st->hTcxCfg->pCurrentTnsConfig = NULL;
+
+ IF ( st->hTcxCfg->fIsTNSAllowed != 0 )
+ {
+ InitTnsConfigs(st->bwidth_fx, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFEnc->infoStopFrequency, st->total_brate_fx, st->element_mode, 0/*is_mct*/);
+ }
+
+ /* TCX-LTP */
+ hTcxEnc->tcxltp = getTcxLtp(st->sr_core);
+
+ test();
+ test();
+ test();
+ test();
+ IF( st->ini_frame_fx == 0 )
+ {
+
+ hTcxEnc->tcxltp_pitch_int_past = st->L_frame_fx;
+ move16();
+ hTcxEnc->tcxltp_pitch_fr_past = 0;
+ move16();
+ hTcxEnc->tcxltp_gain_past = 0;
+ move16();
+ hTcxEnc->tcxltp_norm_corr_past = 0;
+ move16();
+ }
+ ELSE IF ( NE_16(st->L_frame_fx,L_frame_old)&&!((st->total_brate_fx==16400||st->total_brate_fx==24400)&&(st->total_brate_fx==st->last_total_brate_fx)&&(st->last_bwidth_fx==st->bwidth_fx)))
+ {
+ Word16 pitres, pitres_old;
+ Word16 pit, pit_old;
+
+ pitres_old = 4;
+ move16();
+ if (EQ_16(160,shr(L_frame_old,sub(7,norm_s(L_frame_old))))) /*if ( L_frame_old%160==0 )*/
+ {
+ pitres_old = 6;
+ move16();
+ }
+
+ /*pit_old = (float)st->tcxltp_pitch_int_past + (float)st->tcxltp_pitch_fr_past/(float)pitres_old;*/
+ pit_old = add(hTcxEnc->tcxltp_pitch_int_past, mult_r(hTcxEnc->tcxltp_pitch_fr_past, div_s(1,pitres_old)));
+
+ pitres = 4;
+ move16();
+ if (EQ_16(160,shr(st->L_frame_fx,sub(7,norm_s(st->L_frame_fx))))) /*if ( st->L_frame_fx%160==0 )*/
+ {
+ pitres = 6;
+ move16();
+ }
+
+ /*pit = pit_old * (float)st->L_frame_fx/(float)L_frame_old;*/
+ pit = shl(mult_r(pit_old, div_s(st->L_frame_fx, shl(L_frame_old, 2))), 2);
+ /* assert(pit <= st->L_frame_fx);*/
+
+ hTcxEnc->tcxltp_pitch_int_past = pit;
+ move16();
+ move16();
+ hTcxEnc->tcxltp_pitch_fr_past = i_mult2(sub(pit, hTcxEnc->tcxltp_pitch_int_past),pitres);
+ move16();
+ }
+
+ /* Residual Coding*/
+ st->hTcxCfg->resq = getResq(st->total_brate_fx);
+ move16();
+
+ test();
+ if ( st->hTcxCfg->resq != 0 && st->tcxonly == 0)
+ {
+ st->hTcxCfg->tcxRateLoopOpt = 1;
+ move16();
+ }
+
+ st->hTcxCfg->ctx_hm = getCtxHm(st->element_mode, st->total_brate_fx, st->rf_mode );
+
+ hTcxEnc->tcx_lpc_shaped_ari = getTcxLpcShapedAri(st->total_brate_fx,st->rf_mode, st->element_mode);
+
+}
+
+void init_sig_buffers_fx( Encoder_State_fx *st, const Word16 L_frame_old, const Word16 L_subfr )
+{
+
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ /* Encoder Past Samples at encoder-sampling-rate */
+ st->encoderPastSamples_enc = shr(imult1616(st->L_frame_fx, 9), 4);
+
+ /* Initialize Signal Buffers and Pointers at encoder-sampling-rate */
+ IF ( st->ini_frame_fx == 0 )
+ {
+ set16_fx(st->buf_speech_enc, 0, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k);
+ set16_fx(st->buf_speech_enc_pe, 0, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k);
+ set16_fx(hTcxEnc->buf_speech_ltp, 0, L_PAST_MAX_32k+L_FRAME32k+L_NEXT_MAX_32k);
+ set16_fx(st->buf_wspeech_enc, 0, L_FRAME16k+L_SUBFR+L_FRAME16k+L_NEXT_MAX_16k);
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF ( NE_16(st->L_frame_fx,L_frame_old)&&!((EQ_32(st->total_brate_fx,ACELP_16k40)||EQ_32(st->total_brate_fx,ACELP_24k40))&&(EQ_32(st->total_brate_fx,st->last_total_brate_fx))&&(EQ_16(st->last_bwidth_fx,st->bwidth_fx))))
+ {
+ lerp( st->buf_speech_enc, st->buf_speech_enc, st->L_frame_fx, L_frame_old );
+ test();
+ IF( NE_16(st->last_core_fx,TCX_20_CORE)&&NE_16(st->last_core_fx,TCX_10_CORE)) /* condition should be checked again */
+ {
+ Copy( st->buf_speech_enc, hTcxEnc->buf_speech_ltp, st->L_frame_fx );
+ }
+
+ Copy_Scale_sig( st->old_wsp_fx, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM,L_WSP_MEM, sub(st->prev_Q_new, st->prev_Q_old));
+
+ /*Resamp buffers needed only for ACELP*/
+ test();
+ test();
+ IF( EQ_16(st->L_frame_fx,L_FRAME)&&!st->tcxonly)
+ {
+ Copy_Scale_sig( st->old_inp_12k8_fx, st->buf_speech_enc_pe+st->L_frame_fx-L_INP_MEM,L_INP_MEM, sub(st->prev_Q_new, st->prev_Q_old));
+
+ }
+ ELSE IF( EQ_16(st->L_frame_fx,L_FRAME16k)&&!st->tcxonly)
+ {
+ lerp( st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-310, 310, L_WSP_MEM );
+ Copy( st->old_inp_16k_fx, st->buf_speech_enc_pe+st->L_frame_fx-L_INP_MEM,L_INP_MEM);
+
+ }
+
+ st->mem_preemph_enc = st->buf_speech_enc[st->encoderPastSamples_enc+st->encoderLookahead_enc-1];
+ move16();
+ st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame_fx+L_SUBFR-1];
+ move16();
+ }
+ /*coming from TCXonly modes*/
+ ELSE IF( !st->tcxonly && GE_32(st->last_total_brate_fx,ACELP_32k))
+ {
+
+ Copy_Scale_sig( st->old_wsp_fx, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM,L_WSP_MEM, sub(st->prev_Q_new, st->prev_Q_old));
+
+ /*Resamp buffers needed only for ACELP*/
+ IF( EQ_16(st->L_frame_fx,L_FRAME16k))
+ {
+ lerp( st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-L_WSP_MEM, st->buf_wspeech_enc+st->L_frame_fx + L_SUBFR-310, 310, L_WSP_MEM );
+ }
+ hLPDmem->mem_w0 = 0;
+ move16();
+ st->mem_wsp_enc = st->buf_wspeech_enc[st->L_frame_fx+L_SUBFR-1];
+ move16();
+ }
+ }
+
+ st->new_speech_enc = st->buf_speech_enc + st->encoderPastSamples_enc + st->encoderLookahead_enc;
+ st->new_speech_enc_pe = st->buf_speech_enc_pe + st->encoderPastSamples_enc + st->encoderLookahead_enc;
+ hTcxEnc->new_speech_ltp = hTcxEnc->buf_speech_ltp + st->encoderPastSamples_enc + st->encoderLookahead_enc;
+ hTcxEnc->new_speech_TCX = st->input_buff + L_FRAME48k + NS2SA(48000, DELAY_FIR_RESAMPL_NS) - NS2SA(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS);
+
+ st->speech_enc = st->buf_speech_enc + st->encoderPastSamples_enc;
+ st->speech_enc_pe = st->buf_speech_enc_pe + st->encoderPastSamples_enc;
+ hTcxEnc->speech_ltp = hTcxEnc->buf_speech_ltp + st->encoderPastSamples_enc;
+ hTcxEnc->speech_TCX = hTcxEnc->new_speech_TCX - st->encoderLookahead_FB;
+
+ st->wspeech_enc = st->buf_wspeech_enc + st->L_frame_fx + L_subfr;
+
+ test();
+ test();
+ IF( st->ini_frame_fx == 0 || NE_16(st->L_frame_fx,L_frame_old)||EQ_16(st->last_codec_mode,MODE1))
+ {
+ set16_fx(st->buf_synth, 0, OLD_SYNTH_SIZE_ENC+L_FRAME32k);
+ }
+
+ st->synth = st->buf_synth + st->L_frame_fx + L_subfr;
+
+
+ return;
+}
+
+static void init_core_sig_ana_fx( Encoder_State_fx *st )
+{
+
+ /* Pre-emphasis factor and memory */
+
+ st->preemph_fac = PREEMPH_FAC_SWB; /*SWB*/ move16();
+ IF ( LT_16(st->fscale, (16000*FSCALE_DENOM)/12800))
+ {
+ st->preemph_fac = PREEMPH_FAC; /*WB*/ move16();
+ }
+ ELSE IF ( LT_16(st->fscale, (24000*FSCALE_DENOM)/12800))
+ {
+ st->preemph_fac = PREEMPH_FAC_16k; /*WB*/ move16();
+ }
+
+ st->hTcxCfg->preemph_fac=st->preemph_fac;
+ move16();
+
+ st->gamma = GAMMA1;
+ move16();
+ st->inv_gamma = GAMMA1_INV;
+ move16();
+ IF ( EQ_32(st->sr_core, 16000))
+ {
+ st->gamma = GAMMA16k;
+ move16();
+ st->inv_gamma = GAMMA16k_INV;
+ move16();
+ }
+
+
+ st->min_band_fx = 1;
+ move16();
+ st->max_band_fx = 16;
+ move16();
+
+ IF ( st->narrowBand == 0)
+ {
+ st->min_band_fx = 0;
+ move16();
+ st->max_band_fx = 19;
+ move16();
+ }
+
+
+ return;
+}
+
+static void init_acelp_fx( Encoder_State_fx *st, Word16 L_frame_old , const Word16 shift)
+{
+ Word16 mem_syn_r_size_old;
+ Word16 mem_syn_r_size_new;
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ /* Init pitch lag */
+ st->pit_res_max = initPitchLagParameters(st->sr_core, &st->pit_min, &st->pit_fr1, &st->pit_fr1b, &st->pit_fr2, &st->pit_max);
+
+
+ /* Init LPDmem */
+ IF( st->ini_frame_fx == 0 )
+ {
+ set16_fx( hLPDmem->syn, 0, 1+M );
+
+ set16_fx(hTcxEnc->Txnq, 0, L_FRAME32k/2+64);
+ hTcxEnc->acelp_zir = hTcxEnc->Txnq + shr(st->L_frame_fx,1);
+ set16_fx( hLPDmem->mem_syn_r, 0, L_SYN_MEM );
+ }
+ ELSE /*Rate switching*/
+ {
+ IF( EQ_16(st->last_core_fx,ACELP_CORE))
+ {
+ lerp(hTcxEnc->Txnq,hTcxEnc->Txnq, shr(st->L_frame_fx,1), shr(L_frame_old,1) );
+ }
+ ELSE
+ {
+ lerp(hTcxEnc->Txnq,hTcxEnc->Txnq, st->hTcxCfg->tcx_mdct_window_length, st->hTcxCfg->tcx_mdct_window_length_old );
+ }
+ hTcxEnc->acelp_zir = hTcxEnc->Txnq + shr(st->L_frame_fx,1);
+
+ /* Rate switching */
+ IF( EQ_16(st->last_codec_mode,MODE1))
+ {
+ Copy(hLPDmem->mem_syn1_fx, hLPDmem->mem_syn2, M );
+ set16_fx(hTcxEnc->Txnq, 0, L_FRAME32k/2+64);
+ set16_fx( hLPDmem->syn, 0, M );
+ }
+
+ /*AMR-WBIO->MODE2*/
+ IF( EQ_16(st->last_core_fx,AMR_WB_CORE))
+ {
+ st->next_force_safety_net_fx=1;
+ move16();
+ st->last_core_fx = ACELP_CORE;
+ move16();
+ }
+ /*HQ-CORE->MODE2*/
+ test();
+ IF( EQ_16(st->last_codec_mode,MODE1)&&EQ_16(st->last_core_fx,HQ_CORE))
+ {
+ /*Reset of ACELP memories*/
+ st->next_force_safety_net_fx=1;
+ move16();
+ st->rate_switching_reset = 1;
+ move16();
+ hLPDmem->tilt_code = TILT_CODE;
+ move16();
+ set16_fx( hLPDmem->old_exc, 0, L_EXC_MEM );
+ set16_fx( hLPDmem->syn, 0, 1+M );
+ hLPDmem->mem_w0 = 0;
+ move16();
+ set16_fx( hLPDmem->mem_syn, 0, M );
+ set16_fx( hLPDmem->mem_syn2, 0, M );
+
+ /* unquantized LPC*/
+ test();
+ IF ( !((EQ_32(st->total_brate_fx,ACELP_16k40)||EQ_32(st->total_brate_fx,ACELP_24k40))&&(EQ_32(st->total_brate_fx,st->last_total_brate_fx))&&(EQ_16(st->last_bwidth_fx,st->bwidth_fx))))
+ {
+ Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); /*lsp old @12.8kHz*/
+ IF( EQ_16(st->L_frame_fx,L_FRAME16k))
+ {
+ lsp_convert_poly_fx( st->lspold_enc_fx, st->L_frame_fx, 0 );
+ }
+ }
+ Copy( st->lspold_enc_fx, st->lsp_old_fx, M ); /*used unquantized values for mid-LSF Q*/
+ IF( st->tcxonly == 0 )
+ {
+ lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core );
+ }
+ ELSE
+ {
+ E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M );
+ }
+ st->last_core_fx = TCX_20_CORE;
+ move16();
+
+ st->hTcxCfg->last_aldo=1; /*It was previously ALDO*/
+ st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW;
+ /*ALDO overlap windowed past: also used in MODE1 but for other MDCT-FB*/
+ set16_fx(hTcxEnc->old_out_fx, 0, st->L_frame_fx );
+ }
+ ELSE
+ {
+ test();
+ test();
+ IF( (NE_16(st->L_frame_fx,L_frame_old))&&(LE_16(st->L_frame_fx,L_FRAME16k))&&(LE_16(L_frame_old,L_FRAME16k)))
+ {
+ /* convert quantized LSP vector */
+ st->rate_switching_reset=lsp_convert_poly_fx( st->lsp_old_fx, st->L_frame_fx, 0 );
+ IF( st->tcxonly == 0 )
+ {
+ lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core );
+ }
+ ELSE
+ {
+ E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M );
+ }
+ IF( EQ_16(st->L_frame_fx,L_FRAME16k))
+ {
+ Copy( st->lsp_old_fx, st->lspold_enc_fx, M );
+ }
+ ELSE
+ {
+ Copy( st->lsp_old1_fx, st->lspold_enc_fx, M );
+ }
+
+ synth_mem_updt2( st->L_frame_fx, st->last_L_frame_fx, hLPDmem->old_exc, hLPDmem->mem_syn_r, hLPDmem->mem_syn2, hLPDmem->mem_syn, ENC );
+
+ /*Mem of deemphasis stay unchanged : hLPDmem->syn*/
+ {
+ Word16 tmp, A[M+1], Ap[M+1],tmp_buf[M+1];
+ /* Update wsyn */
+ /* lsp2a_stab( st->lsp_old, A, M ); */
+ E_LPC_f_lsp_a_conversion(st->lsp_old_fx, A, M);
+ weight_a_fx( A, Ap, GAMMA1, M );
+ tmp=0;
+ move16();
+ tmp_buf[0]=0;
+ move16();
+ Copy( hLPDmem->mem_syn2, tmp_buf+1, M );
+ deemph_fx( tmp_buf+1, st->preemph_fac, M, &tmp );
+ Residu3_fx( Ap, tmp_buf+M, &tmp, 1, 1 );
+ hLPDmem->mem_w0 = sub(shr(st->wspeech_enc[-1],shift), tmp);
+ }
+ }
+ ELSE IF((NE_16(st->L_frame_fx,L_frame_old)))
+ {
+ /*Partial reset of ACELP memories*/
+ st->next_force_safety_net_fx=1;
+ move16();
+ st->rate_switching_reset = 1;
+ move16();
+
+ /*reset partly some memories*/
+ hLPDmem->tilt_code = TILT_CODE;
+ move16();
+ set16_fx( hLPDmem->old_exc, 0, L_EXC_MEM );
+ move16();
+
+ /*Resamp others memories*/
+ /*Size of LPC syn memory*/
+ /* 1.25/20.0 = 1.0/16.0 -> shift 4 to the right. */
+ mem_syn_r_size_old = shr(L_frame_old, 4);
+ mem_syn_r_size_new = shr(st->L_frame_fx, 4);
+
+ lerp( hLPDmem->mem_syn_r+L_SYN_MEM-mem_syn_r_size_old, hLPDmem->mem_syn_r+L_SYN_MEM-mem_syn_r_size_new, mem_syn_r_size_new, mem_syn_r_size_old );
+ Copy( hLPDmem->mem_syn_r+L_SYN_MEM-M, hLPDmem->mem_syn, M);
+ Copy( hLPDmem->mem_syn, hLPDmem->mem_syn2, M );
+
+ /*Untouched memories : hLPDmem->syn & hLPDmem->mem_w0*/
+ hLPDmem->mem_w0 = 0;
+ move16();
+
+ /* unquantized LPC*/
+ Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); /*lsp old @12.8kHz*/
+ IF( EQ_16(st->L_frame_fx,L_FRAME16k))
+ {
+ lsp_convert_poly_fx( st->lspold_enc_fx, st->L_frame_fx, 0 );
+ }
+ Copy( st->lspold_enc_fx, st->lsp_old_fx, M ); /*used unquantized values for mid-LSF Q*/
+ IF( st->tcxonly == 0 )
+ {
+ lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core );
+ }
+ ELSE
+ {
+ E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsf_old_fx, M );
+ }
+ }
+ ELSE IF( !st->tcxonly && EQ_16(st->L_frame_fx,L_FRAME16k)&>_32(st->last_total_brate_fx,ACELP_32k))
+ {
+ lsp2lsf_fx( st->lsp_old_fx, st->lsf_old_fx, M, st->sr_core );
+ }
+ }
+ }
+
+ test();
+ test();
+ if(EQ_16(st->last_bwidth_fx,NB)&&NE_16(st->bwidth_fx,NB)&&st->ini_frame_fx!=0)
+ {
+ st->rate_switching_reset=1;
+ move16();
+ }
+
+ /* Post-processing */
+ hLPDmem->dm_fx.prev_gain_code = L_deposit_l(0);
+ set16_fx(hLPDmem->dm_fx.prev_gain_pit, 0, 6);
+ hLPDmem->dm_fx.prev_state = 0;
+
+ move16();
+ hLPDmem->gc_threshold = 0;
+ move16();
+
+ /* Pulse Search configuration */
+ st->acelp_autocorr = 1;
+ move16();
+
+ /*Use for 12.8 kHz sampling rate and low bitrates, the conventional pulse search->better SNR*/
+ if ((LE_32(st->total_brate_fx, ACELP_9k60)||st->rf_mode!=0)&&(EQ_32(st->sr_core,12800)))
+ {
+ st->acelp_autocorr = 0;
+ move16();
+ }
+
+
+ /*BPF parameters for adjusting gain in function of background noise*/
+ IF( EQ_16(st->codec_mode,MODE2))
+ {
+ st->mem_bpf.lp_error_ener = L_deposit_l(0);
+ if( st->last_codec_mode == MODE1 )
+ {
+ st->mem_bpf.lp_error = L_deposit_l(0);
+ }
+ }
+
+
+ return;
+}
+
+static void init_modes_fx(
+ Encoder_State_fx *st,
+ const Word32 last_total_brate
+)
+{
+ Word8 n;
+ Word32 tmp32;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+
+ /* Restrict ACE/TCX20/TCX10 mode */
+ move16();
+ st->restrictedMode = getRestrictedMode(st->element_mode, st->total_brate_fx, st->Opt_AMR_WB_fx);
+ move16();
+ st->acelpEnabled = 0;
+ move16();
+ st->tcx20Enabled = 0;
+ move16();
+ st->tcx10Enabled = 0;
+
+ if (EQ_16(s_and(st->restrictedMode,1),1))
+ {
+ st->acelpEnabled = 1;
+ move16();
+ }
+ if (EQ_16(s_and(st->restrictedMode,2),2))
+ {
+ st->tcx20Enabled = 1;
+ move16();
+ }
+ if (EQ_16(s_and(st->restrictedMode,4),4))
+ {
+ st->tcx10Enabled = 1;
+ move16();
+ }
+
+
+ /* TCX mode (TCX20 TCX10_10 or NO_TCX) */
+ hTcxEnc->tcxMode = NO_TCX;
+ move16();
+
+ /* Bits Budget */
+ /*st->bits_frame_nominal = (int)( (float)st->L_frame_fx * (float)FSCALE_DENOM * (float)st->bitrate / ( (float)st->fscale * 12800.0f ) );*/
+ /*st->bits_frame_nominal = (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f );*/
+ /*328 = 0.010009765625 in 0Q15*/
+ /* st->bits_frame_nominal = extract_h(L_add(L_mult(div_l(L_mult(shl(st->L_frame_fx,2),st->bitrate),st->fscale),328),16056)); */
+
+ /* st->bits_frame_nominal = (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f ); */
+ assert(FSCALE_DENOM == 512);
+ assert(st->fscale == 2 * st->L_frame_fx); /* this assumption is true if operated in 20ms frames with FSCALE_DENOM == 512, which is the current default */
+ tmp32 = L_shl(st->total_brate_fx, 1); /* (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate */
+ st->bits_frame_nominal = extract_l(L_shr(Mpy_32_16_1(tmp32, 20972), 6)); /* 20972 = 0.01 * 64 * 32768 */
+ assert(st->bits_frame_nominal == (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate_fx/100.0f + 0.49f ));
+
+ IF (st->Opt_AMR_WB_fx)
+ {
+ st->bits_frame = st->bits_frame_nominal;
+ st->bits_frame_core = st->bits_frame_nominal;
+ st->frame_size_index = 0;
+ move16();
+ }
+ ELSE
+ {
+ FOR (n=0; nbits_frame_nominal))
+ {
+ move16();
+ move16();
+ move16();
+ st->frame_size_index = n;
+ st->bits_frame = FrameSizeConfig[n].frame_bits;
+ st->bits_frame_core = FrameSizeConfig[n].frame_net_bits;
+ BREAK;
+ }
+ }
+ if (n==FRAME_SIZE_NB)
+ {
+ assert(!"Bitrate not supported: not part of EVS");
+ }
+ }
+
+ /* Reconfigure core */
+ core_coder_reconfig_fx( st, last_total_brate);
+
+
+ return;
+}
diff --git a/lib_enc/core_enc_ol_fx.c b/lib_enc/core_enc_ol_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..e83c9e26b7059ce689e342b1555f05bc714b96f5
--- /dev/null
+++ b/lib_enc/core_enc_ol_fx.c
@@ -0,0 +1,1604 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h"
+#include "basop_util.h"
+#include "rom_com_fx.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+
+/*-------------------------------------------------------------------*
+ * Local function prototypes
+ *-------------------------------------------------------------------*/
+
+static void closest_centroid_rf(const Word16 *data, const Word16 *weights, const Word16 *quantizer, const Word16 centroids, const Word16 length, Word16 *ind_vec);
+static void BITS_ALLOC_ACELP_config_rf(const Word16 coder_type, Word16* tilt_code, Word16* rf_frame_type, Word16* rf_target_bits, Word16 nb_subfr, Word16 rf_fec_indicator, Word16* pitch_buf);
+static void BITS_ALLOC_TCX_config_rf(Word16* rf_frame_type, Word16* rf_target_bits, Word16 PLC_Mode, Word16 coder_type, Word16 last_core, Word16 TD_mode);
+
+
+
+/*-------------------------------------------------------------------*
+ * core_encode_openloop_fx()
+ *
+ * Open-loop core encoder
+ *-------------------------------------------------------------------*/
+
+void core_encode_openloop_fx(
+ Encoder_State_fx *st, /* i/o: encoder state structure */
+ const Word16 coder_type, /* i : coding type */
+ const Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/
+ const Word16 *lsp_new, /* i : LSPs at the end of the frame */
+ const Word16 *lsp_mid, /* i : LSPs at the middle of the frame */
+ Word16 *pitch_buf, /* i/o: floating pitch values for each subfr*/
+ Word16 *voice_factors, /* o : voicing factors */
+ Word16 *ptr_bwe_exc, /* o : excitation for SWB TBE */
+ const Word16 vad_hover_flag,
+ const Word16 vad_flag_dtx,
+ Word16 Q_new,
+ Word16 shift
+)
+{
+ Word16 lsf_q[M], lsp_q[M], lspmid_q[M], lsf_tcx_q[M], lsp_tcx_q[M];
+ Word16 lspq_ind[M];
+ Word16 A_q_ind[M+1];
+ Word16 tcx_lpc_cdk;
+ Word16 A_w[M+1];
+ Word16 A_q[NB_SUBFR16k*(M+1)];
+ Word16 param_lpc[NPRM_LPC_NEW];
+ Word16 nbits_lpc;
+ Word16 param_core[2*NPRM_DIV];
+ Word16 target_bits;
+ Word16 stab_fac;
+ Word32 spectrum_long[N_MAX]; /* MDCT output for a long block */
+ Word16 spectrum_long_e;
+ Word16 indexBuffer[N_MAX+1];
+ CONTEXT_HM_CONFIG hm_cfg;
+ Word16 bits_param_lpc[10], no_param_lpc;
+
+ Word16 i;
+ /* lsf quant parameters */
+ Word16 lsp_q_rf[M];
+ Word16 Aq_rf[NB_SUBFR*(M+1)];
+ Word16 stab_fac_rf;
+ Word16 *exc_rf;
+ Word16 *syn_rf;
+ Word16 tmp;
+ Word16 rf_PLC_Mode;
+ Word16 TD_mode;
+ Word16 xsp[M], xsf[M];
+ Word16 rf_mem_MA[M];
+
+ Word16 exc_buf_rf[L_EXC_MEM + L_FRAME + 1];
+ Word16 syn_buf_rf[M+L_FRAME16k+L_FRAME16k/2];
+
+ Word16 w_rf[M+1], lsf_uq_rf[M+1];
+ Word16 lsf_q_1st_rf[M+1], lsf_q_d_rf[M+1], lsf_q_rf[M+1];
+ Word16 lsp_old_q_rf[M+1], lsf_old_q_rf[M+1];
+#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING
+ (void)vad_hover_flag;
+ (void)vad_flag_dtx;
+#endif
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+ RF_ENC_HANDLE hRF = st->hRF;
+
+ LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */
+ hLPDmem = st->hLPDmem;
+ DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc;
+
+ /* copy primary memories to use later during partial copy assembly */
+
+ /* These primary memories are already scaled by (Q_new-st->prev_Q_new) inside pre_proc_fx()
+ and copied to the partial frame at start of each frame to be used in computing partial copy params.
+ But then they are discarded, not need for continuation
+ The idea is to not maintain these memories seperately, and have the ability to generate the
+ primary copy memories using the partial copy parameters at decode, so same in enc
+ */
+
+ /* back up the old LSPs and LSFs */
+ Copy(st->lsp_old_fx, lsp_old_q_rf, M);
+ Copy(st->lsf_old_fx, lsf_old_q_rf, M);
+
+ /* back up old exc before primary encoding */
+ set16_fx( exc_buf_rf, 0, (L_EXC_MEM+L_FRAME+1) );
+ exc_rf = exc_buf_rf + L_EXC_MEM;
+ Copy(hLPDmem->old_exc, exc_buf_rf, L_EXC_MEM);
+
+ /* back up old synthesis before primary encoding */
+ set16_fx( syn_buf_rf, 0, (M+L_FRAME16k+L_FRAME16k/2) );
+ syn_rf = syn_buf_rf + M;
+ Copy(hLPDmem->mem_syn, syn_buf_rf, M);
+
+ /* back up syn2 mem */
+ Copy(hLPDmem->mem_syn2, hRF->rf_mem_syn2, M);
+
+ /* back up LPD mem_w0 target generation memory */
+ hRF->rf_mem_w0 = hLPDmem->mem_w0;
+
+ /* back up clip gain memory */
+ Copy( st->clip_var_fx, hRF->rf_clip_var, 6 );
+
+ /* back up tilt code */
+ hRF->rf_tilt_code = hLPDmem->tilt_code;
+
+ /* back up dispMem */
+ hRF->rf_dm_fx.prev_state = hLPDmem->dm_fx.prev_state;
+ hRF->rf_dm_fx.prev_gain_code = hLPDmem->dm_fx.prev_gain_code;
+ FOR(i=0; i<6; i++)
+ {
+ hRF->rf_dm_fx.prev_gain_pit[i] = hLPDmem->dm_fx.prev_gain_pit[i];
+ }
+ /* back up gc_threshold for noise addition */
+ hRF->rf_gc_threshold = hLPDmem->gc_threshold;
+
+
+ /* initialization */
+ tcx_lpc_cdk = 0;
+ move16();
+ set16_fx( param_lpc, 0, NPRM_LPC_NEW );
+ set16_fx( param_core, 0, 2*NPRM_DIV );
+ Copy(hTcxEnc->tcxltp_param, ¶m_core[1+NOISE_FILL_RANGES], LTPSIZE );
+
+ no_param_lpc = 0;
+ move16(); /* avoid MSVC warnings */
+ nbits_lpc = 0;
+ move16(); /* avoid MSVC warnings */
+ stab_fac = 0;
+ move16(); /* avoid MSVC warnings */
+
+ set32_fx(spectrum_long, 0, N_MAX);
+
+ hm_cfg.indexBuffer = indexBuffer;
+ move16();
+
+ /*--------------------------------------------------------------*
+ * LPC Quantization
+ *---------------------------------------------------------------*/
+
+ st->acelp_cfg.midLpc = st->acelp_cfg.midLpc_enable;
+ move16();
+ test();
+ if ( EQ_16(st->lpcQuantization, 1) && EQ_16(coder_type,VOICED))
+ {
+ st->acelp_cfg.midLpc = 0;
+ move16();
+ }
+
+ test();
+ IF ( st->core_fx==ACELP_CORE || !st->enableTcxLpc )
+ {
+ IF (st->envWeighted)
+ {
+ /* Unweight the envelope */
+ E_LPC_lsp_unweight( st->lsp_old_fx, st->lsp_old_fx, st->lsf_old_fx, st->inv_gamma, M );
+ st->envWeighted = 0;
+ move16();
+ }
+
+ IF(EQ_16(st->core_fx,TCX_20_CORE))
+ {
+ lpc_quantization_fx( st, lsp_new, lsp_mid, lsp_q, lsf_q, lspmid_q, lspq_ind, st->clip_var_fx,
+ AUDIO, st->acelp_cfg.midLpc, param_lpc, &nbits_lpc, bits_param_lpc, &no_param_lpc, add(Q_new, Q_SCALE - 2) );
+
+ }
+ ELSE
+ {
+
+ lpc_quantization_fx( st, lsp_new, lsp_mid, lsp_q, lsf_q, lspmid_q, lspq_ind, st->clip_var_fx, coder_type,
+ st->acelp_cfg.midLpc, param_lpc, &nbits_lpc, bits_param_lpc, &no_param_lpc, add(Q_new, Q_SCALE - 2) );
+ }
+
+ /*-------------------------------------------------------------*
+ * Rate switching: reset
+ *---------------------------------------------------------------*/
+ IF( st->rate_switching_reset!=0 )
+ {
+ Copy( lsp_q, st->lsp_old_fx, M );
+ Copy( lsf_q, st->lsf_old_fx, M );
+ Copy( lsp_q, lspmid_q, M );
+ }
+
+ stab_fac = lsf_stab_fx(lsf_q, st->lsf_old_fx, 0, st->L_frame_fx);
+ }
+
+
+
+
+ /*--------------------------------------------------------------*
+ * Run ACELP
+ *---------------------------------------------------------------*/
+ IF ( st->core_fx==ACELP_CORE )
+ {
+ IF ( st->acelp_cfg.midLpc != 0 )
+ {
+ int_lsp4_fx( st->L_frame_fx, st->lsp_old_fx, lspmid_q, lsp_q, A_q, M, 0 );
+ }
+ ELSE
+ {
+ int_lsp_fx( st->L_frame_fx, st->lsp_old_fx, lsp_q, A_q, M, interpol_frac_fx, 0 );
+ }
+
+ /* Calculate target bits */
+ target_bits = sub(sub(st->bits_frame_core, nbits_lpc), st->nb_bits_header_ace);
+
+ if(EQ_16(st->rf_mode,1))
+ {
+ /* joint bit allocation for redundant frame and TBE */
+ /* calculate target bits for core coding */
+ target_bits = sub(target_bits, st->rf_target_bits_write);
+ }
+ IF( st->igf != 0 )
+ {
+ target_bits = sub( target_bits, get_tbe_bits_fx( st->total_brate_fx, st->bwidth_fx, st->rf_mode ) );
+
+ }
+
+ if ( st->acelp_cfg.midLpc != 0)
+ {
+ target_bits = sub(target_bits, MIDLSF_NBITS );
+ }
+
+ if( st->hPlcExt->enableGplc )
+ {
+ target_bits = sub(target_bits, st->hPlcExt->nBits);
+ }
+
+ /* reset TBE buffers previous frame frame wasn't ACELP*/
+ IF( NE_16( st->last_core_fx, ACELP_CORE ))
+ {
+ TBEreset_enc_fx( st, st->bwidth_fx );
+ }
+
+
+ /* Run ACELP encoder */
+ coder_acelp_fx( Aw, A_q, st->speech_enc_pe, param_core, stab_fac, st, st->hPlcExt, target_bits,
+ Q_new, shift, pitch_buf, voice_factors, ptr_bwe_exc);
+ IF (st->hPlcExt)
+ {
+ st->glr_idx[0] = encSideSpecPowDiffuseDetector_fx(st->hPlcExt->last_lsf_ref, st->hPlcExt->last_lsf_con, st->last_sr_core, &(st->prev_lsf4_mean), st->glr, coder_type);
+ Copy(lsf_q, st->hPlcExt->last_lsf_ref, M);
+ Copy(st->hPlcExt->lsf_con, st->hPlcExt->last_lsf_con, M);
+
+ updateSpecPowDiffuseIdx_fx(st);
+
+ if (GT_16(st->last_stab_fac, 655/*0.02f Q15*/))
+ {
+ move16();
+ st->glr_idx[0] = 0;
+ }
+ move16();
+ move16();
+ st->hPlcExt->LPDmem = hLPDmem;
+ encoderSideLossSimulation_fx( st,st->hPlcExt, lsf_q, stab_fac, st->hPlcExt->calcOnlylsf, st->L_frame_fx);
+ }
+ st->last_stab_fac = stab_fac;
+
+
+ hTcxEnc->tcxltp_norm_corr_past = st->voicing_fx[1];
+ move16();
+
+ st->hTcxCfg->tcx_curr_overlap_mode = st->hTcxCfg->tcx_last_overlap_mode = ALDO_WINDOW;
+ move16();
+
+ }
+
+
+
+ /*--------------------------------------------------------------*
+ * Run TCX20
+ *---------------------------------------------------------------*/
+
+ IF ( EQ_16(st->core_fx, TCX_20_CORE))
+ {
+ IF (st->enableTcxLpc)
+ {
+ IF( EQ_16(st->rf_mode,1))
+ {
+ Copy(st->mem_MA_fx, rf_mem_MA, M);
+ }
+
+ tcx_lpc_cdk = tcxlpc_get_cdk(st->hTcxCfg->coder_type);
+
+ /* Get the envelope corresponding to the current frame */
+ E_LPC_int_lpc_tcx( st->lspold_enc_fx, lsp_new, A_q );
+
+ /* Weight the envelope */
+ weight_a_fx(A_q, A_q, st->gamma, M);
+
+ /* Save the weighted envelope */
+ Copy(A_q, A_w, M+1);
+
+ /* Convert to xSP and xSF */
+ E_LPC_a_lsp_conversion(A_q, xsp, lsp_new, M );
+ E_LPC_lsp_lsf_conversion(xsp, xsf, M);
+
+ /* Quantize */
+ Q_lsf_tcxlpc_fx( xsf, lsf_tcx_q, lspq_ind, param_lpc, M, st->narrowBand, tcx_lpc_cdk, st-> mem_MA_fx,
+ st->hTcxCfg->coder_type, st->Bin_E_fx, add(Q_new, Q_SCALE-2) );
+
+ /* Account for consumed bits */
+ nbits_lpc = TCXLPC_NUMBITS;
+ move16();
+ if (param_lpc[0])
+ {
+ nbits_lpc = add(nbits_lpc, TCXLPC_IND_NUMBITS);
+ }
+
+ /* Convert quantized xSF to xSP and A */
+ E_LPC_lsf_lsp_conversion(lsf_tcx_q, lsp_tcx_q, M);
+ E_LPC_f_lsp_a_conversion(lsp_tcx_q, A_q, M);
+ }
+ ELSE
+ {
+ E_LPC_int_lpc_tcx( st->lsp_old_fx, lsp_q, A_q );
+ }
+
+ IF (hTcxEnc->tcx_lpc_shaped_ari != 0)
+ {
+ E_LPC_f_lsp_a_conversion(lspq_ind, A_q_ind, M);
+ }
+
+ /* Calculate target bits */
+ target_bits = sub(sub(st->bits_frame_core, nbits_lpc), st->nb_bits_header_tcx);
+ if(EQ_16(st->rf_mode,1))
+ {
+ /* joint bit allocation for redundant frame and TBE */
+ /* calculate target bits for core coding */
+ target_bits = sub(target_bits, st->rf_target_bits_write);
+ }
+
+ IF (EQ_16(st->mdct_sw, MODE1))
+ {
+ /* Account for core signaling bits difference: bandwidth and ACELP/TCX signaling bit are replaced */
+ target_bits = add(target_bits, sub(add(FrameSizeConfig[st->frame_size_index].bandwidth_bits, 1), signalling_mode1_tcx20_enc(st, 0)));
+ }
+ ELSE if ( EQ_16(st->mdct_sw_enable, MODE2))
+ {
+ target_bits = sub(target_bits, 1);
+ }
+
+ if( st->hPlcExt->enableGplc )
+ {
+ target_bits = sub(target_bits, st->hPlcExt->nBits);
+ }
+
+ /* subtract bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */
+ target_bits = sub(target_bits,1);
+ test();
+ if (EQ_16(st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP)||EQ_16(st->hTcxCfg->tcx_curr_overlap_mode,MIN_OVERLAP))
+ {
+ target_bits = sub(target_bits,1);
+ }
+
+ target_bits = sub(target_bits, hTcxEnc->tcxltp_bits);
+
+
+ coder_tcx_fx(
+ 0,
+ st->hTcxCfg,
+ A_q,
+ A_q_ind,
+ st->synth,
+ st->L_frame_fx,
+ hTcxEnc->L_frameTCX,
+ st->hTcxCfg->tcx_coded_lines,
+ target_bits,
+ st->tcxonly,
+ spectrum_long,
+ &spectrum_long_e,
+ param_core,
+ st,
+ &hm_cfg
+ );
+
+ coder_tcx_post_fx( st, hLPDmem, st->hTcxCfg, st->synth, A_q, Aw, st->wspeech_enc, Q_new, shift );
+
+
+ move16();
+ IF(st->hPlcExt)
+ {
+ st->hPlcExt->LPDmem = hLPDmem;
+
+ GplcTcxEncSetup_fx(st,st->hPlcExt, Q_new);
+ }
+ IF (st->enableTcxLpc)
+ {
+ E_LPC_lsp_unweight( lsp_tcx_q, lsp_q, lsf_q, st->inv_gamma, M );
+ }
+ IF(st->hPlcExt)
+ {
+ encoderSideLossSimulation_fx(st,st->hPlcExt, lsf_q, stab_fac, 1, st->L_frame_fx);
+ }
+
+ }
+
+
+
+ /* Update lsp/lsf memory */
+ Copy( lsp_new, st->lspold_enc_fx, M );
+
+ test();
+ IF ( st->enableTcxLpc && st->core_fx != ACELP_CORE )
+ {
+ /* Update lsf/lsp memory */
+ Copy(lsf_tcx_q, st->lsf_old_fx, M);
+ Copy(lsp_tcx_q, st->lsp_old_fx, M);
+ st->envWeighted = 1;
+ move16();
+
+ /* Update ACELP quantizer state */
+ lsf_update_memory( st->narrowBand, st->lsf_old_fx, st-> mem_MA_fx, st-> mem_MA_fx, M );
+
+ st->pstreaklen_fx = 0;
+ st->streaklimit_fx = 32767;
+ /* check resonance for pitch clipping algorithm */
+ gp_clip_test_lsf_fx(st->element_mode, st->lsf_old_fx, st->clip_var_fx, 0 );
+ Copy(st->lsf_old_fx, st->mem_AR_fx, M);
+ }
+ ELSE
+ {
+ /* Update ISP/ISF memory */
+ Copy(lsf_q, st->lsf_old_fx, M);
+ Copy(lsp_q, st->lsp_old_fx, M);
+ }
+
+ /*--------------------------------------------------------------*
+ * Update LP_CNG parameters
+ *--------------------------------------------------------------*/
+ IF( st->Opt_DTX_ON_fx != 0 )
+ {
+ /* update CNG parameters in active frames */
+ IF ( EQ_16(st->bwidth_fx,NB)&&st->enableTcxLpc&&st->core_fx!=ACELP_CORE)
+ {
+ Word16 buf[L_LP], res[L_FRAME], A[M+1], r_l[M+1], r_h[M+1], lsptmp[M], Q_r;
+ assert(st->L_frame_fx==L_FRAME);
+ Copy(st->synth+L_FRAME-L_LP, buf, L_LP);
+ tmp = st->synth[L_FRAME-L_LP-1];
+ E_UTIL_f_preemph2(Q_new-1, buf, st->preemph_fac, L_LP, &tmp);
+ autocorr_fx( buf, M, r_h, r_l, &Q_r, L_LP, Assym_window_W16fx, 0, 0 );
+ lag_wind(r_h, r_l, M, INT_FS_FX, LAGW_WEAK);
+ E_LPC_lev_dur(r_h, r_l, A, NULL, M, NULL);
+ E_LPC_a_lsp_conversion(A, lsptmp, lsp_new, M);
+ Residu3_fx(A, buf+L_LP-L_FRAME, res, L_FRAME, 1);
+ cng_params_upd_fx( lsptmp, res, st->L_frame_fx, &hTdCngEnc->ho_circ_ptr,
+ hTdCngEnc->ho_ener_circ_fx, &hTdCngEnc->ho_circ_size, hTdCngEnc->ho_lsp_circ_fx,
+ Q_new, ENC, NULL, &hTdCngEnc->cng_buf_cnt, hTdCngEnc->cng_exc2_buf,
+ hTdCngEnc->cng_Qexc_buf, hTdCngEnc->cng_brate_buf, hDtxEnc->last_active_brate );
+ }
+ ELSE
+ {
+ cng_params_upd_fx( lsp_new, hLPDmem->old_exc+L_EXC_MEM-st->L_frame_fx,
+ st->L_frame_fx, &hTdCngEnc->ho_circ_ptr, hTdCngEnc->ho_ener_circ_fx,
+ &hTdCngEnc->ho_circ_size, hTdCngEnc->ho_lsp_circ_fx, Q_new, ENC, NULL,
+ &hTdCngEnc->cng_buf_cnt, hTdCngEnc->cng_exc2_buf, hTdCngEnc->cng_Qexc_buf, hTdCngEnc->cng_brate_buf,
+ hDtxEnc->last_active_brate );
+ }
+
+ IF( EQ_16(st->L_frame_fx,L_FRAME))
+ {
+ /* store LSPs@16k, potentially to be used in CNG@16k */
+ Copy( st->lsp_old16k_fx, &(hTdCngEnc->ho_lsp_circ2_fx[(hTdCngEnc->ho_circ_ptr)*M]), M );
+ }
+
+ /* Set 16k LSP flag for CNG buffer */
+ hTdCngEnc->ho_16k_lsp[hTdCngEnc->ho_circ_ptr] = 1;
+ move16();
+ if ( EQ_16(st->L_frame_fx,L_FRAME))
+ {
+ hTdCngEnc->ho_16k_lsp[hTdCngEnc->ho_circ_ptr] = 0;
+ move16();
+ }
+
+ /* efficient DTX hangover control */
+ IF ( GT_16(hTdCngEnc->burst_ho_cnt, 1))
+ {
+ dtx_hangover_control_fx( st, lsp_new );
+ }
+ }
+
+ /*--------------------------------------------------------------*
+ * Adaptive Bass Post-filter
+ *---------------------------------------------------------------*/
+
+ test();
+ IF (GT_16(st->core_fx, ACELP_CORE)||(st->rate_switching_reset!=0))
+ {
+ /*TCX mode: copy values*/
+ set16_fx(st->mem_bpf.noise_buf, 0, 2*L_FILT16k); /*TCX->no gain*/
+ set16_fx(st->mem_bpf.error_buf, 0, L_FILT16k); /*TCX->no gain*/
+ st->bpf_gain_param=0;
+ }
+ ELSE IF (st->acelp_cfg.bpf_mode > 0)
+ {
+ /*ACELP: estimate bpf parameter with delay=0*/
+
+ /*Estimate bpf parameter*/
+ bass_pf_enc_fx( st->speech_enc, st->synth, st->bpf_T, st->bpf_gainT, st->L_frame_fx, L_SUBFR, &(st->bpf_gain_param), st->acelp_cfg.bpf_mode, &(st->mem_bpf) );
+ }
+
+
+
+
+ /*--------------------------------------------------------------*
+ * Analysis Print Out
+ *---------------------------------------------------------------*/
+
+
+ /*--------------------------------------------------------------*
+ * Generate Bitstream
+ *---------------------------------------------------------------*/
+
+ enc_prm_fx( coder_type, param_core, param_lpc, st, st->L_frame_fx, &hm_cfg, bits_param_lpc, no_param_lpc );
+
+ /* Channel-aware mode - encode partial copy */
+ IF( EQ_16(st->rf_mode,1))
+ {
+ set16_fx(lsf_q_1st_rf, 0, M);
+ IF (EQ_16(st->core_fx, ACELP_CORE))
+ {
+ /* convert LSPs to LP coefficients */
+ lsp2lsf_fx( lsp_new, lsf_uq_rf, M, st->sr_core );
+ /*i: lsp_new Q15 */
+ /*o: lsf_uq_rf Qx2.56*/
+
+ /* first stage VQ, 8 bits; reuse TCX high rate codebook */
+ hRF->rf_indx_lsf[0][0] = vlpc_1st_cod_fx(lsf_uq_rf, lsf_q_1st_rf, w_rf, st->rf_mode);
+ /*v_sub(lsf_uq_rf, lsf_q_1st_rf, lsf_q_d_rf, M);*/
+ FOR (i=0; irf_indx_lsf[0][1]);
+ /*i: lsf_q_d_rf in Q6 */
+ /*o: quantization index Q0 */
+
+ /* quantized lsf from two stages */
+ /*v_add(lsf_q_1st_rf, lsf_q_diff_cb_8b_rf + M * st->rf_indx_lsf[0][1], lsf_q_rf, M);*/
+ FOR (i=0; irf_indx_lsf[0][1]]; /*tmp = quantized lsf_q_d_rf in Q6*/
+ tmp = shr(mult_r(tmp,20972),4); /* bring lsf_q_d_rf to Qx2.56 for addition */
+ lsf_q_rf[i] = add(lsf_q_1st_rf[i], tmp);
+ }
+
+ v_sort( lsf_q_rf, 0, M-1 );
+ reorder_lsf_fx( lsf_q_rf, LSF_GAP_FX, M, st->sr_core );
+ }
+ ELSE
+ {
+ Word16 rf_tcx_lpc_cdk;
+
+ rf_tcx_lpc_cdk = tcxlpc_get_cdk( GENERIC );
+ /* Quantize */
+ Q_lsf_tcxlpc_fx( xsf, lsf_tcx_q, lspq_ind, param_lpc, M, st->narrowBand, rf_tcx_lpc_cdk, rf_mem_MA, GENERIC, st->Bin_E_fx, add(Q_new, Q_SCALE-2) );
+
+ /* VQ, 5+4+4 bits; reuse TCX low rate codebook */
+ hRF->rf_indx_lsf[0][0] = param_lpc[1];
+ hRF->rf_indx_lsf[0][1] = param_lpc[2];
+ hRF->rf_indx_lsf[0][2] = param_lpc[3];
+ }
+
+ IF (EQ_16(st->core_fx, ACELP_CORE))
+ {
+ /* current n-th ACELP frame and its corresponding partial copy */
+
+ /*lsf2lsp( lsf_q_rf, lsp_q_rf, M, st->sr_core );*/
+ E_LPC_lsf_lsp_conversion( lsf_q_rf, lsp_q_rf, M );
+ /*i: lsf_q_rf in Qx2.56*/
+ /*o: lsp_q_rf in Q15*/
+
+ /* Interpolate LSPs and convert to LPC */
+ int_lsp_fx( st->L_frame_fx, lsp_old_q_rf, lsp_q_rf, Aq_rf, M, interpol_frac_fx, 0 );
+
+ /* stability estimation */
+ stab_fac_rf = lsf_stab_fx( lsf_q_rf, lsf_old_q_rf, 0, st->L_frame_fx ); /*Q15*/
+
+ /* Configure partial copy estimation of the current n-th frame to be packed in future with n+fec_offset frame */
+ /* o: rf_frame_type, o: rf_target_bits */
+ BITS_ALLOC_ACELP_config_rf( coder_type, hRF->rf_tilt_buf, &hRF->rf_frame_type, &hRF->rf_target_bits, st->nb_subfr, st->rf_fec_indicator, pitch_buf );
+
+ /* RF frame type in the buffer */
+ hRF->rf_indx_frametype[0] = hRF->rf_frame_type;
+ hRF->rf_targetbits_buff[0] = hRF->rf_target_bits;
+
+ IF( NE_16(hRF->rf_frame_type,RF_NO_DATA))
+ {
+ /* coder_acelp_rf_fx does the partial copy encoding based on the rf frame type chosen for the RF encoding */
+ coder_acelp_rf_fx(&(hRF->acelp_cfg_rf), coder_type, Aw, Aq_rf, st->speech_enc_pe, st->voicing_fx, st->pitch_fx,
+ stab_fac_rf, st, hRF->rf_target_bits, hRF->rf_frame_type, exc_rf, syn_rf, Q_new, shift);
+ }
+ }
+ ELSE
+ {
+ hRF->rf_clas[0] = st->clas_fx;
+ move16();
+ hRF->rf_gain_tcx[0] = param_core[0];
+ move16();
+
+ /* attenuate somewhat the gain for onset when the correlation with previous frame is too low: avoid preecho */
+ tmp = mult_r(shl(hRF->rf_gain_tcx[1], 1), 26214/*0.8f Q15*/);
+
+ test();
+ test();
+ IF( (hRF->rf_gain_tcx[1] != 0) && (GT_16(hRF->rf_gain_tcx[0], tmp))&&(LE_16(hTcxEnc->tcxltp_gain,6554/*0.2 Q15*/)))
+ {
+ hRF->rf_gain_tcx[0] = tmp;
+ move16();
+
+ if( GT_16(tmp, 127))
+ {
+ hRF->rf_gain_tcx[0] = 127;
+ move16();
+ }
+ }
+
+ /* get concealment decision*/
+ rf_PLC_Mode = 0;
+ move16();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF(
+ (EQ_16(st->core_fx, TCX_20_CORE) )/*(st->core == TCX_20_CORE)*/
+ && (EQ_16(st->last_core_fx,TCX_20_CORE) )/*&&(st->last_core == TCX_20_CORE)*/
+ && (EQ_16(hRF->rf_second_last_core, TCX_20_CORE) )/*&& (st->rf_second_last_core == TCX_20_CORE)*/
+ && ( (LE_16(hTcxEnc->tcxltp_pitch_int, shr(st->L_frame_fx, 1)) ) || ( LE_16(hTcxEnc->tcxltp_gain, 13107/*0.4f Q15*/) ) )/*&& ((st->tcxltp_pitch_int <= 0.5f*st->L_frame) || ( st->tcxltp_gain <= 0.4f))*/
+ && (EQ_16(hTcxEnc->tcxltp_pitch_int, hRF->rf_tcxltp_pitch_int_past) )/*&& (st->tcxltp_pitch_int == st->rf_tcxltp_pitch_int_past)*/
+ && (hRF->rf_last_tns_active == 0)/*!st->rf_last_tns_active*/
+ && (hRF->rf_second_last_tns_active == 0)/*!st->rf_second_last_tns_active*/
+ && ( (st->hTcxCfg->fIsTNSAllowed & hTcxEnc->fUseTns_fx[0]) == 0)/*!(st->hTcxCfg->fIsTNSAllowed & st->fUseTns[0])*/
+ )
+ {
+ rf_PLC_Mode = 1;
+ move16();
+ }
+ ELSE IF (st->last_core_fx != 0)
+ {
+ test();
+ test();
+ test();
+ IF ( ((LE_16(st->clas_fx, UNVOICED_TRANSITION))||(LE_16(st->last_clas_fx,UNVOICED_TRANSITION))||(LE_16(hTcxEnc->tcxltp_gain,13107/*0.4f Q15*/)))
+ && NE_16(st->last_core_fx, -1) )
+ {
+ rf_PLC_Mode = st->last_core_fx;
+ move16();
+ }
+ }
+
+ /* call TD1 when the gain drop compare to previous frame*/
+ test();
+ test();
+ test();
+ test();
+ IF( rf_PLC_Mode == 0 && hRF->rf_gain_tcx[1] != 0 &&
+ ( (st->transientDetection.transientDetector.bIsAttackPresent != 0 && LT_16(hRF->rf_gain_tcx[0], mult_r(hRF->rf_gain_tcx[1], 31785/*0.97f Q15*/)) ) ||
+ LT_16(hRF->rf_gain_tcx[0], mult_r(hRF->rf_gain_tcx[1], 29491/*0.90f Q15*/)) )
+ )
+ {
+ TD_mode = 0;
+ }
+ ELSE
+ {
+ TD_mode = 1;
+ }
+
+ /* updates */
+ hRF->rf_tcxltp_pitch_int_past = hTcxEnc->tcxltp_pitch_int;
+ move16();
+ hRF->rf_second_last_tns_active = hRF->rf_last_tns_active;
+ move16();
+ hRF->rf_last_tns_active = (st->hTcxCfg->fIsTNSAllowed & hTcxEnc->fUseTns_fx[0]);
+ move16();
+ hRF->rf_second_last_core = st->last_core_fx;
+ move16();
+
+ hRF->rf_tcxltp_param[0] = hTcxEnc->tcxltp_param[1];
+ move16();
+
+ /* Configure partial copy estimation of the current n-th frame to be packed in future with n+fec_offset frame */
+ /* o: rf_frame_type, o: rf_target_bits */
+ BITS_ALLOC_TCX_config_rf( &hRF->rf_frame_type, &hRF->rf_target_bits, rf_PLC_Mode, coder_type, st->last_core_fx, TD_mode);
+
+ /* RF frame type in the buffer */
+ hRF->rf_indx_frametype[0] = hRF->rf_frame_type;
+ move16();
+ hRF->rf_targetbits_buff[0] = hRF->rf_target_bits;
+ move16();
+
+ }
+ }
+
+
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+* closest_centroid_rf()
+*
+* Determine a set of closest VQ centroids for a given input
+*-------------------------------------------------------------------*/
+static void closest_centroid_rf(
+ const Word16 *data, /* i : input data Qx */
+ const Word16 *weights, /* i : weights */
+ const Word16 *quantizer, /* i : quantizer table Qx */
+ const Word16 centroids, /* i : number of centroids */
+ const Word16 length, /* i : dimension of quantiser */
+ Word16 *ind_vec /* o : list of best match indice vectors */
+)
+{
+ Word16 i,j;
+ Word16 tmp, tmpL;
+ Word64 werr_64;
+ Word32 L_tmp, best_werr, werr;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ ind_vec[0] = 0;
+ move16();
+ best_werr = MAX_32;
+ move32();
+
+ FOR( i = 0; i < centroids; i++ )
+ {
+ werr_64 = 0;
+ move64();
+
+ tmpL = i_mult2(i, length);
+ FOR( j = 0; j < length; j++ )
+ {
+#ifdef BASOP_NOGLOB
+ tmp = sub_o( data[j], quantizer[tmpL + j], &Overflow );
+ L_tmp = L_mult_o(tmp, tmp, &Overflow);
+#else
+ tmp = sub( data[j], quantizer[tmpL + j] );
+ L_tmp = L_mult(tmp, tmp);
+#endif
+ werr_64 = W_mac_32_16( werr_64, L_tmp, weights[j] );
+ }
+ werr = W_sat_m( werr_64);
+ if( LT_32( werr, best_werr) )
+ {
+ ind_vec[0] = i;
+ move16();
+ }
+ best_werr = L_min( best_werr, werr );
+ }
+
+ return;
+}
+
+
+void core_acelp_tcx20_switching_fx(
+ Encoder_State_fx *st, /* i/o: encoder state structure */
+ Word16 non_staX, /* i : unbound non-stationarity for sp/mu clas */
+ Word16 *pitch_fr, /* i/o: fraction pitch values */
+ Word16 *voicing_fr, /* i/o: fractional voicing values */
+ const Word16 currFlatness, /* i : flatness */
+ const Word16 lsp_mid[M], /* i : LSPs at the middle of the frame */
+ const Word16 stab_fac, /* i : LP filter stability */
+ Word16 Q_new,
+ Word16 shift
+)
+{
+ Word16 i, j, iter;
+ Word16 xn_buf[L_MDCT_OVLP_MAX+L_FRAME_PLUS+L_MDCT_OVLP_MAX];
+ Word16 Ap[M+1];
+ Word16 gainlpc[FDNS_NPTS];
+ Word16 gainlpc_e[FDNS_NPTS];
+ Word32 en[N_MAX/4];
+ Word32 ener, tmp32, fac, offset;
+ Word32 offset_tcx;
+ Word16 ener_e;
+ Word16 L_frame;
+ Word16 overlap;
+ Word16 x_e;
+ Word16 tcx_offset;
+ Word32 spectrum_long[N_MAX];
+ Word32 *x = spectrum_long;
+ Word32 target;
+ Word32 tcx_snr;
+ Word16 tmp16, s;
+ Word16 L_frame_4;
+ Word16 i2, T0;
+ Word32 gain, signal, noise;
+ Word16 A_q_tcx[(NB_SUBFR16k+1)*(M+1)];
+ Word16 snr_tcx, snr_acelp, dsnr;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+ SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /* Check minimum pitch for quantization */
+ FOR( i = 0; i < 3; i++ )
+ {
+ tmp16 = st->pitch_fx[i];
+ move16();
+ /* check minimum pitch for quantization */
+ if (LT_16(tmp16, PIT_MIN_SHORTER))
+ {
+ tmp16 = shl(tmp16, 1);
+ }
+
+ /* convert pitch values to 16kHz domain */
+ s = mult_r(tmp16, 8192/*0.25f Q15*/);
+ if (EQ_16(st->L_frame_fx, L_FRAME16k))
+ {
+ /*pitch[i] = (short)(pitch[i] * 1.25f + 0.5f);*/
+ tmp16 = add(tmp16, s);
+ }
+ st->pitch_fx[i] = tmp16;
+ move16();
+ }
+ IF (st->narrowBand != 0)
+ {
+ pitchDoubling_det_fx( st->wspeech_enc, st->pitch_fx, pitch_fr, voicing_fr );
+ }
+
+ E_LPC_f_lsp_a_conversion(lsp_mid, A_q_tcx, M);
+
+
+ /* LTP */
+
+ tcx_ltp_encode_fx(hTcxEnc->tcxltp,
+ st->tcxonly,
+ TCX_20,
+ st->L_frame_fx,
+ L_SUBFR,
+ st->speech_enc + st->encoderLookahead_enc,
+ hTcxEnc->speech_ltp + st->encoderLookahead_enc,
+ st->wspeech_enc + st->encoderLookahead_enc,
+ st->pitch_fx[1],
+ hTcxEnc->tcxltp_param,
+ &hTcxEnc->tcxltp_bits,
+ &hTcxEnc->tcxltp_pitch_int,
+ &hTcxEnc->tcxltp_pitch_fr,
+ &hTcxEnc->tcxltp_gain,
+ &hTcxEnc->tcxltp_pitch_int_past,
+ &hTcxEnc->tcxltp_pitch_fr_past,
+ &hTcxEnc->tcxltp_gain_past,
+ &hTcxEnc->tcxltp_norm_corr_past,
+ st->last_core_fx,
+ st->pit_min,
+ st->pit_fr1,
+ st->pit_fr2,
+ st->pit_max,
+ st->pit_res_max,
+ &st->transientDetection,
+ 0,
+ A_q_tcx,
+ M
+ );
+
+ /* Force TCX when TCX20 in MODE1 is selected */
+ IF ( EQ_16(st->mdct_sw, MODE1))
+ {
+ st->core_fx = TCX_20_CORE;
+ move16();
+ }
+ ELSE
+ {
+ /*--------------------------------------------------------------*
+ * Estimate TCX SNR
+ *---------------------------------------------------------------*/
+
+ L_frame = st->L_frame_fx;
+ move16();
+ tcx_offset = st->hTcxCfg->tcx_offset;
+ move16();
+
+ target = L_add(0x14C315C, 0); /* 1000.f * log2(10)/10 (15Q16) */
+ test();
+ if (EQ_32(st->sr_core, INT_FS_16k)||EQ_32(st->sr_core, INT_FS_12k8))
+ {
+ target = L_add(0x11A5D28, 0); /* 850.f * log2(10)/10 (15Q16) */
+ }
+ if ( st->narrowBand != 0 )
+ {
+ target = L_add(0xA618AE, 0); /* 500f * log2(10)/10 (15Q16) */
+ }
+
+ IF (st->last_core_fx == ACELP_CORE)
+ {
+ L_frame = add(L_frame, tcx_offset);
+ tcx_offset = s_min(st->hTcxCfg->lfacNext, 0);
+ L_frame = sub(L_frame, tcx_offset);
+ }
+ L_frame_4 = shr(L_frame, 2);
+ overlap = st->hTcxCfg->tcx_mdct_window_delay;
+ move16();
+ Copy(hTcxEnc->speech_ltp + sub(tcx_offset, shr(overlap, 1)), xn_buf, add(L_frame, overlap));
+
+ tmp16 = shr(overlap, 1);
+ IF (EQ_16(st->last_core_fx,ACELP_CORE))
+ {
+ IF (tcx_offset < 0)
+ {
+ set16_fx(xn_buf, 0, tmp16);
+ }
+ }
+ ELSE
+ {
+ FOR (i = 0; i < tmp16; i++)
+ {
+ xn_buf[i] = mult_r(xn_buf[i], st->hTcxCfg->tcx_mdct_window[i].v.im);
+ move16();
+ }
+ FOR ( ; i < overlap; i++)
+ {
+ xn_buf[i] = mult_r(xn_buf[i], st->hTcxCfg->tcx_mdct_window[overlap-1-i].v.re);
+ move16();
+ }
+ }
+
+ FOR (i = 0; i < tmp16; i++)
+ {
+ xn_buf[L_frame+i] = mult_r(xn_buf[L_frame+i], st->hTcxCfg->tcx_mdct_window[i].v.re);
+ move16();
+ }
+ FOR ( ; i < overlap; i++)
+ {
+ xn_buf[L_frame+i] = mult_r(xn_buf[L_frame+i], st->hTcxCfg->tcx_mdct_window[overlap-1-i].v.im);
+ move16();
+ }
+
+ x_e = 16;
+ move16();
+ TCX_MDCT(xn_buf, x, &x_e, overlap, sub(L_frame, overlap), overlap, st->element_mode);
+ tmp16 = mult_r(shl(L_frame, 5), 29309/*16*0.0559017 Q15*/); /* L_frame / sqrt(2*NORM_MDCT_FACTOR); Q9 */
+ FOR (i = 0; i < L_frame; i++)
+ {
+ x[i] = Mpy_32_16_1(x[i], tmp16);
+ move32();
+ }
+ x_e = add(x_e, 6);
+
+ weight_a_fx(A_q_tcx, Ap, st->gamma, M);
+
+ lpc2mdct(Ap, M, gainlpc, gainlpc_e, NULL, NULL, FDNS_NPTS, 0);
+
+ mdct_shaping(x, L_frame, gainlpc, gainlpc_e);
+
+ IF ( st->narrowBand )
+ {
+ j = mult( L_frame, 20480 );
+ set32_fx(&x[j], 0, sub(L_frame, j));
+ }
+
+ FOR (i = 0; i < L_frame_4; i++)
+ {
+ /* normalization */
+ s = 31;
+ move16();
+
+ tmp16 = norm_l(x[0]);
+ if (x[0] != 0) s = s_min(s, tmp16);
+
+ tmp16 = norm_l(x[1]);
+ if (x[1] != 0) s = s_min(s, tmp16);
+
+ tmp16 = norm_l(x[2]);
+ if (x[2] != 0) s = s_min(s, tmp16);
+
+ tmp16 = norm_l(x[3]);
+ if (x[3] != 0) s = s_min(s, tmp16);
+
+ s = sub(s, 2); /* 2 bits headroom */
+
+ /* calc quadruple energy */
+ ener = L_deposit_l(1);
+
+ tmp16 = extract_h(L_shl(x[0], s));
+ ener = L_mac(ener, tmp16, tmp16);
+
+ tmp16 = extract_h(L_shl(x[1], s));
+ ener = L_mac(ener, tmp16, tmp16);
+
+ tmp16 = extract_h(L_shl(x[2], s));
+ ener = L_mac(ener, tmp16, tmp16);
+
+ tmp16 = extract_h(L_shl(x[3], s));
+ ener = L_mac(ener, tmp16, tmp16);
+
+ s = shl(sub(x_e, s), 1);
+
+ tmp32 = L_add(BASOP_Util_Log2(ener), L_shl(L_deposit_l(s), 25)); /* log2, 6Q25 */
+ tmp32 = L_shr(tmp32, 9); /* 15Q16 */
+ en[i] = L_add(tmp32, 0x2FD5F); /* 0x2FD5F -> 9.f * log2(10)/10 (15Q16) */ move32();
+
+ x += 4;
+ }
+
+ fac = L_add(0x2A854B, 0); /* 0x2A854B -> 128.f * log2(10)/10 (15Q16) */
+ offset = L_add(fac, 0);
+
+ FOR (iter = 0; iter < 10; iter++)
+ {
+ fac = L_shr(fac, 1);
+ offset = L_sub(offset, fac);
+ ener = L_deposit_l(0);
+
+ assert(L_frame_4 % 4 == 0);
+ FOR (i=0; i < L_frame_4; i+=4)
+ {
+ tmp32 = L_sub(en[i], offset);
+
+ if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */
+ {
+ ener = L_add(ener, tmp32);
+ }
+
+ tmp32 = L_sub(en[i+1], offset);
+
+ if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */
+ {
+ ener = L_add(ener, tmp32);
+ }
+
+ tmp32 = L_sub(en[i+2], offset);
+
+ if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */
+ {
+ ener = L_add(ener, tmp32);
+ }
+
+ tmp32 = L_sub(en[i+3], offset);
+
+ if (GT_32(tmp32, 0xFF20)) /* 0xFF20 -> 3.f * log2(10)/10 */
+ {
+ ener = L_add(ener, tmp32);
+ }
+
+ IF (GT_32(ener, target))
+ {
+ offset = L_add(offset, fac);
+ BREAK;
+ }
+ }
+ }
+
+ if (LE_32(offset, 0xAA153)) /* 0xAA153 -> 32.f * log2(10)/10 */
+ {
+ offset = L_add(0xFFD57AB5, 0); /* 0xFFD57AB5 -> -128.f * log2(10)/10; */
+ }
+ offset_tcx = offset;
+ move32();
+
+ s = add(extract_h(offset), 1);
+ offset = L_sub(L_and(offset, 0xFFFF), 0x10000);
+ ener = BASOP_Util_InvLog2(L_shl(offset, 9));
+
+ ener = Mpy_32_16_1(Mpy_32_16_1(ener, 0x78AE), getInvFrameLen(L_frame)); /* 0x78AE -> sqrt(2)/12 (Q18) */
+ ener_e = sub(s, 9);
+
+ tcx_snr = L_deposit_l(0);
+
+ FOR (i = 0; i < st->L_frame_fx; i += L_SUBFR)
+ {
+ tmp32 = L_deposit_l(0);
+
+ FOR (j = 0; j < L_SUBFR; j++)
+ {
+#ifdef BASOP_NOGLOB
+ tmp32 = L_mac0_o(tmp32, st->wspeech_enc[i+j], st->wspeech_enc[i+j], &Overflow);
+#else
+ tmp32 = L_mac0(tmp32, st->wspeech_enc[i+j], st->wspeech_enc[i+j]);
+#endif
+ }
+ tmp32 = L_shr(BASOP_Util_Log2(tmp32), 9); /* 15Q16 */
+ tmp32 = L_add(tmp32, L_sub( 0x1F0000, L_shl( L_deposit_h( add( Q_new, sub( shift, 1 ) ) ), 1 ) ) ); /* wspeech_enc scaling */
+ if (LT_32(tmp32, (Word32)0xFFEC1185))
+ {
+ tmp32 = 0xFFEC1185; /* 0xFFEC1185 -> log2(1e-6) in 15Q16 */
+ move32();
+ }
+
+ tcx_snr = L_add(tcx_snr, tmp32);
+ }
+ tcx_snr = Mpy_32_16_1(tcx_snr, div_s(L_SUBFR, st->L_frame_fx));
+ tcx_snr = L_sub(tcx_snr, L_shr(BASOP_Util_Log2(Mpy_32_16_1(ener, L_SUBFR)), 9));
+ tcx_snr = L_sub(tcx_snr, L_deposit_h(add(ener_e, 15)));
+ tcx_snr = L_shl(Mpy_32_16_1(tcx_snr, 0x6054), 2); /* 0x6054 -> 10/log2(10) (2Q13) */
+
+ BASOP_SATURATE_WARNING_OFF_EVS
+#ifdef BASOP_NOGLOB
+ snr_tcx = round_fx_o(L_shl_o(tcx_snr, 8, &Overflow), &Overflow); /* 7Q8 */
+#else /* BASOP_NOGLOB */
+ snr_tcx = round_fx(L_shl(tcx_snr, 8)); /* 7Q8 */
+#endif /* BASOP_NOGLOB */
+ BASOP_SATURATE_WARNING_ON_EVS
+
+ /*--------------------------------------------------------------*
+ * Estimate ACELP SNR
+ *---------------------------------------------------------------*/
+
+ tmp32 = L_deposit_l(0);
+
+ /*
+ snr_acelp = 1/nSubFrames + sum( 10*log10( signal / (noise*0.055) )
+ snr_acelp = sum( (log2(signal) - log2(noise)) * 10/log2(10) )/nSubFrames - 10*log10(0.055)
+ */
+
+ i2 = 0;
+ move16();
+ FOR (i = 0; i < st->L_frame_fx; i += L_SUBFR)
+ {
+ IF ( EQ_32( st->sr_core, INT_FS_16k))
+ {
+ T0 = shr(add( add(pitch_fr[mult_r(i2,26214/*(float)L_FRAME/(float)L_FRAME16k Q15*/)], shr(pitch_fr[mult_r(i2,26214/*(float)L_FRAME/(float)L_FRAME16k Q15*/)], 2)) , (1 << 5) ), 6);
+ }
+ ELSE
+ {
+ T0 = shr(add( pitch_fr[i2] , (1 << 5) ), 6);
+ }
+
+ gain = get_gain( st->wspeech_enc + i, st->wspeech_enc + sub(i, T0), L_SUBFR );
+
+ signal = L_deposit_l(1);
+ noise = L_deposit_l(1);
+
+ FOR (j = 0; j < L_SUBFR; j++)
+ {
+#ifdef BASOP_NOGLOB
+ signal = L_mac0_o(signal, st->wspeech_enc[i+j], st->wspeech_enc[i+j], &Overflow);
+
+ tmp16 = round_fx_o(L_shl_o(Mpy_32_16_r(gain, st->wspeech_enc[i+j-T0]), 15, &Overflow), &Overflow);
+ tmp16 = sub_o(st->wspeech_enc[i+j], tmp16, &Overflow);
+ noise = L_mac0_o(noise, tmp16, tmp16, &Overflow);
+#else
+ signal = L_mac0(signal, st->wspeech_enc[i+j], st->wspeech_enc[i+j]);
+
+ tmp16 = round_fx(L_shl(Mpy_32_16_r(gain, st->wspeech_enc[i+j-T0]), 15));
+ tmp16 = sub(st->wspeech_enc[i+j], tmp16);
+ noise = L_mac0(noise, tmp16, tmp16);
+#endif
+ }
+ /* Assume always 4 sub frames. */
+ /*assert( (st->L_frame_fx / L_SUBFR) == 4);*/
+ tmp32 = L_add(tmp32, Mpy_32_16_1(L_sub(BASOP_Util_Log2(signal), BASOP_Util_Log2(noise)), 12330/*3.0102999566398119521373889472449 Q12*/));
+ i2 = add(i2, 1);
+ }
+
+ if(EQ_16(st->L_frame_fx,L_FRAME16k))
+ {
+ tmp32 = Mpy_32_16_1(tmp32,26214/*(float)L_FRAME/(float)L_FRAME16k Q15*/);
+ }
+
+ offset = -211332072l/*-12.5963731051575616 Q24*/; /* 10*log10(0.055f) */
+ move32();
+ if (EQ_32(st->sr_core, INT_FS_16k))
+ {
+ offset = -173847554l/*-10.362121726544446 Q24*/; /* 10*log10(0.092f) */
+ move32();
+ }
+ if (EQ_32(st->sr_core, INT_FS_12k8))
+ {
+ offset = -206216813l/*-12.291479883578557 Q24*/; /* 10*log10(0.059f) */
+ move32();
+ }
+ if (st->narrowBand != 0)
+ {
+ offset = -138228949l/*-8.2390874094431865 Q24*/; /* 10*log10(0.15f) */
+ move32();
+ }
+
+ tmp32 = L_sub(tmp32, offset);
+
+ snr_acelp = round_fx(tmp32); /* 7Q8 */
+
+ /*--------------------------------------------------------------*
+ * Switching Decision
+ *---------------------------------------------------------------*/
+
+ dsnr = 0;
+ move16();
+ /* hysteresis for very small SNR differences between ACELP and TCX */
+
+ /* try to use TCX instead of ACELP on temporally stationary frames */
+ test();test();test();test();test();test();test();
+ if ((GT_16(snr_acelp, snr_tcx))&&
+ (LT_16(snr_acelp, add(snr_tcx, 512/*2.0f Q8*/)) ) &&
+#ifdef BASOP_NOGLOB
+ (LT_16(add_o(st->prevTempFlatness_fx, currFlatness, &Overflow), 416/*3.25f Q7*/) || EQ_16(stab_fac, 0x7fff) ||
+#else /* BASOP_NOGLOB */
+ (LT_16(add(st->prevTempFlatness_fx, currFlatness), 416/*3.25f Q7*/) || EQ_16(stab_fac, 0x7fff) ||
+#endif
+ (EQ_32(st->sr_core, INT_FS_12k8) && EQ_16(st->sp_aud_decision0,1) && LT_16(add(st->prevTempFlatness_fx, currFlatness), 2560/*20.f Q7*/) )) &&
+ (LE_16(st->acelpFramesCount, 6) ))
+ {
+ dsnr = -512/*-2.0f Q8*/;
+ move16();
+ }
+
+ /* try to use ACELP instead of TCX on transient and "buzzy" frames */
+ test();test();test();
+ if ((LT_16(snr_acelp, snr_tcx))&&
+ (GT_16(snr_acelp, sub(snr_tcx, 512/*2.0f Q8*/)) ) &&
+ (GT_16(add(st->prevTempFlatness_fx, currFlatness), 416/*3.25f Q7*/) ) &&
+ (GE_16(st->acelpFramesCount, 6) ))
+ {
+ dsnr = 512/*2.0f Q8*/;
+ move16();
+ }
+
+ tmp16 = 0;
+ move16();
+ FOR(i = 0; i < 4; i++)
+ {
+ tmp16 = add(tmp16, shr(voicing_fr[i],2)); /*mean of voicing_fr in Q15*/
+ }
+
+ test();test();test();test();
+ test();test();test();test();test();test();
+ if( EQ_32(st->sr_core, INT_FS_12k8) && (offset_tcx<0x18950F) && GT_16(non_staX,1280 /*5.0f Q8*/ ) && (snr_acelp>=snr_tcx-1024 /*4.0f in Q8*/) && GE_16(st->acelpFramesCount,1) && ((GT_16(hSpMusClas->lps_fx, hSpMusClas->lpm_fx) && GE_16(tmp16,9830))
+ || (GE_16(st->acelpFramesCount,6) && (hSpMusClas->lps_fx> hSpMusClas->lpm_fx-768))) && (st->sp_aud_decision0==0) && st->vad_flag!=0)
+ {
+ /* Fine tuned across various databases based on various metrics to detect TCX frames in speech.*/
+ dsnr = 1024;
+ move16();
+ }
+
+ IF ( st->flag_noisy_speech_snr )
+ {
+ test();
+ IF ( st->vad_flag || st->Opt_DTX_ON_fx )
+ {
+ dsnr = add(dsnr, 512/*2.0f Q8*/);
+ }
+ ELSE
+ {
+ dsnr = sub(dsnr, 512/*2.0f Q8*/);
+ }
+ }
+
+ test();test();test();
+ test();test();test();
+ if (EQ_32(st->sr_core, INT_FS_12k8) && (LT_16(non_staX,512/*2.0f Q8*/) ||
+ (st->flag_noisy_speech_snr==0 && EQ_16(st->vad_flag,1) && (offset_tcx==L_add(0xFFD57AB5,0)) && GE_16(st->acelpFramesCount,6))) &&
+ (st->last_core_fx==ACELP_CORE || st->last_core_fx==TCX_20_CORE))
+ {
+ st->core_fx = st->last_core_fx;
+ }
+ ELSE IF ( GT_16(add(snr_acelp, dsnr), snr_tcx))
+ {
+ st->core_fx = ACELP_CORE;
+ move16();
+ st->acelpFramesCount = s_min(32767-1, add(st->acelpFramesCount, 1));
+ }
+ ELSE
+ {
+ st->core_fx = TCX_20_CORE;
+ move16();
+ st->acelpFramesCount = 0;
+ move16();
+ }
+
+ }
+
+ /* Fixed Decision (using -C) */
+ test();
+ if ( st->acelpEnabled != 0 && st->tcx20Enabled == 0 )
+ {
+ st->core_fx = ACELP_CORE;
+ move16();
+ }
+
+ test();
+ if ( st->acelpEnabled == 0 && st->tcx20Enabled != 0 )
+ {
+ st->core_fx = TCX_20_CORE;
+ move16();
+ }
+
+ st->prevTempFlatness_fx = currFlatness;
+ move16();
+ return;
+}
+
+
+
+
+/*-------------------------------------------------------------------*
+ * BITS_ALLOC_ACELP_config_rf()
+ *
+ * configure channel aware mode
+ *-------------------------------------------------------------------*/
+static void BITS_ALLOC_ACELP_config_rf(
+ const Word16 coder_type,
+ Word16 *tilt_code,
+ Word16 *rf_frame_type,
+ Word16 *rf_target_bits,
+ Word16 nb_subfr,
+ Word16 rf_fec_indicator,
+ Word16 *pitch_buf
+)
+{
+ Word16 mean_tc, min_tilt_code, max_tilt_code;
+ Word16 nrgMode, ltfMode, ltpMode, gainsMode;
+ Word32 L_tmp;
+
+ Word16 en_partial_red = 1;
+ Word16 dpit1, dpit2, dpit3;
+
+ /* Init */
+ *rf_target_bits = 0;
+ move16();
+
+ /* ----------------------------------------*
+ * RF frame type selection *
+ *-----------------------------------------*/
+ /* Mean tilt code estimation */
+ mean_tc = 0;
+ move16();
+ /*mean_tc = mean_fx(tilt_code, nb_subfr);*/
+ IF( EQ_16(nb_subfr, 4))
+ {
+ /* subframe 4 case */
+ L_tmp = L_mult(tilt_code[0], 8192);
+ L_tmp = L_mac(L_tmp, tilt_code[1], 8192 );
+ L_tmp = L_mac(L_tmp, tilt_code[2], 8192 );
+ mean_tc = mac_r(L_tmp, tilt_code[3], 8192 ); /* mean_tc in Q15 */
+ }
+ ELSE
+ {
+ /* subframe 5 case */
+ L_tmp = L_mult(tilt_code[0], 6554);
+ L_tmp = L_mac(L_tmp, tilt_code[1], 6554 );
+ L_tmp = L_mac(L_tmp, tilt_code[2], 6554 );
+ L_tmp = L_mac(L_tmp, tilt_code[3], 6554 );
+ mean_tc = mac_r(L_tmp, tilt_code[4], 6554 ); /* mean_tc in Q15 */
+ }
+
+ /* Maximum tilt code estimation */
+ max_tilt_code = tilt_code[0];
+ move16();
+ maximum_fx(tilt_code, nb_subfr, &max_tilt_code);
+
+ /* Minimum tilt code estimation */
+ min_tilt_code=tilt_code[0];
+ move16();
+ minimum_fx(tilt_code, nb_subfr, &min_tilt_code);
+
+ /* Estimate the frame's criticality and decide
+ whether to transmit partial redundancy information */
+ dpit1 = abs_s( sub(pitch_buf[1], pitch_buf[0]));
+ dpit2 = abs_s( sub(pitch_buf[2], pitch_buf[1]));
+ dpit3 = abs_s( sub(pitch_buf[3], pitch_buf[2]));
+
+ IF ( EQ_16( rf_fec_indicator, 1 ))
+ {
+ test();
+ test();
+ test();
+ test();
+ IF ( GT_16( max_tilt_code, 15729/*0.48f Q15*/ )&&LE_16(dpit1,0)&&LE_16(dpit2,0)&&LE_16(dpit3,0)&&EQ_16(coder_type,VOICED))
+ {
+ en_partial_red = 0;
+ move16();
+ }
+ ELSE IF ( GT_16( max_tilt_code, 15401/*0.47f Q15*/ )&&LE_16(dpit1,64)&&LE_16(dpit2,64)&&LE_16(dpit3,64)&&EQ_16(coder_type,GENERIC))
+ {
+ en_partial_red = 0;
+ move16();
+ }
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ test();
+ IF ( GT_16( max_tilt_code, 15401/*0.47f Q15*/ )&&LE_16(dpit1,16)&&LE_16(dpit2,16)&&LE_16(dpit3,16)&&EQ_16(coder_type,VOICED))
+ {
+ en_partial_red = 0;
+ move16();
+ }
+ ELSE IF ( GT_16( max_tilt_code, 14746/*0.45f Q15*/ )&&LE_16(dpit1,80)&&LE_16(dpit2,80)&&LE_16(dpit3,80)&&EQ_16(coder_type,GENERIC))
+ {
+ en_partial_red = 0;
+ move16();
+ }
+ }
+
+ /* ---------------------------------------------------------*
+ * Identify number of bits required as per rf frame type *
+ * ---------------------------------------------------------*/
+
+ /* rf_mode, 1 bit */
+ *rf_target_bits = add(*rf_target_bits,1);
+
+ /* rf_fec_offset 2 bits */
+ *rf_target_bits = add(*rf_target_bits,2);
+
+ /* rf_frame_type, 3 bits */
+ *rf_target_bits = add(*rf_target_bits,3);
+
+ /* LSF bits 8 + 8 bits */
+ *rf_target_bits = add(*rf_target_bits,16);
+
+ /* Intialize the RF mode frame type to all-pred */
+ *rf_frame_type = RF_ALLPRED;
+
+ test();
+ IF( EQ_16(coder_type,INACTIVE)||en_partial_red==0)
+ {
+ *rf_frame_type = RF_NO_DATA;
+ }
+ ELSE IF ( EQ_16(coder_type,UNVOICED)||EQ_16(coder_type,INACTIVE))
+ {
+ *rf_frame_type = RF_NELP;
+ }
+ ELSE IF( EQ_16(coder_type,GENERIC)&<_16(max_tilt_code,1638/*0.05f Q15*/))
+ {
+ *rf_frame_type = RF_NOPRED;
+ }
+ ELSE IF( EQ_16(coder_type,GENERIC)&<_16(mean_tc,9830/*0.3f Q15*/))
+ {
+ *rf_frame_type = RF_GENPRED;
+ }
+
+ nrgMode = ACELP_NRG_MODE[1][1][*rf_frame_type];
+ ltfMode = ACELP_LTF_MODE[1][1][*rf_frame_type];
+ ltpMode = ACELP_LTP_MODE[1][1][*rf_frame_type];
+ gainsMode = ACELP_GAINS_MODE[1][1][*rf_frame_type];
+
+ /* Number of RF bits for different RF coder types */
+ SWITCH (*rf_frame_type)
+ {
+ case RF_ALLPRED:
+ /* Es_pred bits 3 bits, LTF: 1, pitch: 8,5,5,5, FCB: 0, gain: 7,0,7,0, Diff GFr: 4*/
+ *rf_target_bits += ( ACELP_NRG_BITS[nrgMode]
+ + ACELP_LTF_BITS[ltfMode]
+ + ACELP_LTP_BITS_SFR[ltpMode][0] + ACELP_LTP_BITS_SFR[ltpMode][1] + ACELP_LTP_BITS_SFR[ltpMode][2] + ACELP_LTP_BITS_SFR[ltpMode][3]
+ + ACELP_GAINS_BITS[gainsMode] + ACELP_GAINS_BITS[gainsMode]
+ + 2 /*2 bits for PartialCopy GainFrame*/
+ );
+ BREAK;
+
+ case RF_NOPRED:
+ /* Es_pred bits 3 bits, LTF: 0, pitch: 0, FCB: 7,7,7,7, gain: 6,0,6,0, Diff GFr: 2*/
+ /*bits += (3 + 0 + 0 + 28 + 12 + 2); *//* 64 rf bits */
+ *rf_target_bits += ( ACELP_NRG_BITS[nrgMode]
+ + ACELP_LTF_BITS[ltfMode]
+ + 28
+ + ACELP_GAINS_BITS[gainsMode] + ACELP_GAINS_BITS[gainsMode]
+ + 2 /*2 bits for PartialCopy GainFrame*/
+ );
+ BREAK;
+
+ case RF_GENPRED:
+ /* Es_pred bits 3 bits, LTF: 0, pitch: 8,0,8,0, FCB: 6,7,5,5, gain: 5,0,5,0, Diff GFr: 0*/
+ /*bits += (3 + 0 + 16 + 23 + 10 + 0); */ /* 72 rf bits */
+ *rf_target_bits += ( ACELP_NRG_BITS[nrgMode]
+ + ACELP_LTF_BITS[ltfMode]
+ + ACELP_LTP_BITS_SFR[ltpMode][0] + ACELP_LTP_BITS_SFR[ltpMode][1] + ACELP_LTP_BITS_SFR[ltpMode][2] + ACELP_LTP_BITS_SFR[ltpMode][3]
+ + 14
+ + ACELP_GAINS_BITS[gainsMode] + ACELP_GAINS_BITS[gainsMode]
+ + 2 /*2 bits for PartialCopy GainFrame*/
+ );
+ BREAK;
+
+ case RF_NELP:
+ /* gain: 19, Diff GFr: 5 */
+ /*bits += (19 + 5); */
+ *rf_target_bits += (19 + NUM_BITS_SHB_FRAMEGAIN);
+ BREAK;
+
+ case RF_NO_DATA:
+ *rf_target_bits = 6;
+ BREAK;
+
+ default:
+ assert(!"RF_Frame_type does not belong to ACELP Partial copy frame types possible!");
+ break;
+ }
+
+ return;
+
+}
+
+/*-------------------------------------------------------------------*
+ * BITS_ALLOC_TCX_config_rf()
+ *
+ * configure channel aware mode
+ *-------------------------------------------------------------------*/
+static void BITS_ALLOC_TCX_config_rf(
+ Word16 *rf_frame_type,
+ Word16 *rf_target_bits,
+ Word16 PLC_Mode,
+ Word16 coder_type,
+ Word16 last_core,
+ Word16 TD_mode
+)
+{
+ Word16 bits;
+
+ /* Init: rf_mode + rf_fec_offset + rf_frame_type */
+ bits = 1 + 2 + 3;
+ move16();
+
+ test();
+ IF( EQ_16(coder_type, INACTIVE)||EQ_16(last_core,ACELP_CORE))
+ {
+ *rf_frame_type = RF_NO_DATA;
+ move16();
+ }
+ ELSE
+ {
+ /* classification */
+ bits = add(bits, 2);
+
+ IF( PLC_Mode != 0 )
+ {
+ /* TCX global gain = 7 bits */
+ bits = add(bits, 7);
+ *rf_frame_type = RF_TCXFD;
+ move16();
+ }
+ ELSE
+ {
+ /* pitch and gain */
+ /* LTP data */
+ IF( TD_mode != 0)
+ {
+ bits = add(bits, 9);
+ *rf_frame_type = RF_TCXTD2;
+ move16();
+ }
+ ELSE
+ {
+ bits = add(bits, 9);
+ *rf_frame_type = RF_TCXTD1;
+ move16();
+ }
+ }
+
+ if( EQ_16(*rf_frame_type, RF_TCXFD))
+ {
+ /* TCXFD: LSF bits 5 + 4 + 4 bits */
+ /* only embed LSF for FD concealment */
+ bits = add(bits, TCXLPC_NUMBITS);
+ }
+ }
+
+ *rf_target_bits = bits;
+ move16();
+
+ return;
+}
+
+
+
+
+
+
diff --git a/lib_enc/core_enc_reconf_fx.c b/lib_enc/core_enc_reconf_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..2bed3d9d0852f42b67b6cc68a87505b3a63de91a
--- /dev/null
+++ b/lib_enc/core_enc_reconf_fx.c
@@ -0,0 +1,317 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+//#include "prot_fx.h"
+#include "cnst.h" /* Common constants */
+#include "rom_com_fx.h"
+#include "rom_enc.h" /* Encoder static table prototypes */
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+/*-----------------------------------------------------------------*
+ * Funtion core_coder_reconfig_fx *
+ * ~~~~~~~~~~~~~~~~~~~ *
+ * - reconfig core coder when switching to another frame type *
+ *-----------------------------------------------------------------*/
+void core_coder_reconfig_fx(
+ Encoder_State_fx* st,
+ const Word32 last_total_brate
+)
+{
+ Word16 i, bwidth, index;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING
+ (void)last_total_brate;
+#endif
+ /*Configuration of ACELP*/
+ BITS_ALLOC_init_config_acelp(st->total_brate_fx, st->narrowBand, st->nb_subfr, &(st->acelp_cfg));
+
+ /*Configuration of partial copy*/
+ if (st->Opt_RF_ON)
+ {
+ st->hRF->acelp_cfg_rf.mode_index = 1;
+ st->hRF->acelp_cfg_rf.midLpc = 0;
+ st->hRF->acelp_cfg_rf.midLpc_enable = 0;
+ st->hRF->acelp_cfg_rf.pre_emphasis = 0;
+ st->hRF->acelp_cfg_rf.formant_enh = 1;
+ st->hRF->acelp_cfg_rf.formant_tilt = 1;
+ st->hRF->acelp_cfg_rf.voice_tilt = 1;
+ st->hRF->acelp_cfg_rf.formant_enh_num = FORMANT_SHARPENING_G1;
+ st->hRF->acelp_cfg_rf.formant_enh_den = FORMANT_SHARPENING_G2;
+ move16(); move16(); move16(); move16();
+ move16(); move16(); move16(); move16();
+
+ }
+ st->nb_bits_header_tcx = 2; /*Mode(1) + Last_mode(1)*/ move16();
+
+ IF(EQ_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ st->nb_bits_header_tcx = 2; /* signal class */
+ }
+ ELSE IF(st->tcxonly == 0)
+ {
+ move16();
+ st->nb_bits_header_ace = 4;
+ st->nb_bits_header_tcx = st->nb_bits_header_ace;
+ move16();
+ IF (st->hTcxCfg != NULL)
+ {
+ if (st->hTcxCfg->lfacNext <= 0)
+ {
+ /*st->nb_bits_header_ace--;*/ /*No Last_mode*/
+ st->nb_bits_header_ace = sub(st->nb_bits_header_ace, 1);
+ }
+ }
+ }
+
+ if (st->tcxonly)
+ {
+ st->nb_bits_header_tcx = add(st->nb_bits_header_tcx, 2);
+ }
+
+
+ /*Switch off TCX or ACELP?*/
+ IF(EQ_32(st->sr_core, INT_FS_12k8))
+ {
+ st->acelpEnabled = 0;
+ move16();
+
+ if (s_and(st->restrictedMode, 1) != 0)
+ {
+ st->acelpEnabled = 1;
+ move16();
+ }
+
+ st->tcx20Enabled = 0;
+ move16();
+ if (s_and(st->restrictedMode, 2) != 0)
+ {
+
+ st->tcx20Enabled = 1;
+ move16();
+ }
+ }
+ move32();
+ move32();
+ move16();
+ st->prevEnergyHF_fx = st->currEnergyHF_fx = 1073725440l/*65535.0f Q14*/; /* prevent block switch */
+ st->currEnergyHF_e_fx = 17;
+
+ /*Sanity check : don't need to be instrumented*/
+ if (st->tcxonly == 0)
+ {
+ assert(st->acelpEnabled || st->tcx20Enabled || st->frame_size_index == 0);
+ }
+ else
+ {
+ assert(st->tcx10Enabled || st->tcx20Enabled || st->frame_size_index == 0);
+ }
+
+ /* TCX-LTP */
+ IF(st->hTcxEnc != NULL)
+ {
+ hTcxEnc->tcxltp = getTcxLtp(st->sr_core);
+ }
+
+ /*Use for 12.8 kHz sampling rate and low bitrates, the conventional pulse search->better SNR*/
+
+ st->acelp_autocorr = 1;
+ move16();
+
+ test();
+ if ((LE_32(st->total_brate_fx, ACELP_9k60)) && (EQ_32(st->sr_core, INT_FS_12k8)))
+ {
+ st->acelp_autocorr = 0;
+ move16();
+ }
+
+ /*Get bandwidth mode*/
+ IF(st->narrowBand)
+ {
+ move16();
+ bwidth = 0;
+ }
+ ELSE IF(LE_32(st->sr_core, INT_FS_16k))
+ {
+ move16();
+ bwidth = 1;
+ }
+ ELSE
+ {
+ move16();
+ bwidth = 2;
+ }
+
+ /*Scale TCX for non-active frames to adjust loudness with ACELP*/
+ IF (st->hTcxCfg != NULL)
+ {
+ st->hTcxCfg->na_scale = 32767/*1.0f Q15*/;
+
+ test();
+ IF(LT_16(bwidth, 2) && (st->tcxonly == 0))
+ {
+ /*const Word16 scaleTableSize = sizeof(scaleTcxTable) / sizeof(scaleTcxTable[0]);*/
+
+ FOR(i = 0; i < SIZE_SCALE_TABLE_TCX; i++)
+ {
+
+ test();
+ test();
+ IF(EQ_16(bwidth, scaleTcxTable[i].bwmode) &&
+ GE_32(st->total_brate_fx, scaleTcxTable[i].bitrateFrom) &&
+ LT_32(st->total_brate_fx, scaleTcxTable[i].bitrateTo))
+ {
+ if (st->rf_mode)
+ {
+ i--;
+ }
+ move16();
+ st->hTcxCfg->na_scale = scaleTcxTable[i].scale;
+ BREAK;
+ }
+ }
+ }
+ }
+ st->enableTcxLpc = 0;
+ move16();
+ IF (GT_16(st->element_mode, IVAS_SCE))
+ {
+ test();test();
+ st->enableTcxLpc = (EQ_16(st->lpcQuantization, 1) && (LE_32(st->total_brate_fx, LOWRATE_TCXLPC_MAX_BR_CPE) || st->rf_mode));
+ move16();
+ }
+ ELSE
+ {
+ test();test();
+ if (EQ_16(st->lpcQuantization, 1) && (LE_32(st->total_brate_fx, LOWRATE_TCXLPC_MAX_BR) || st->rf_mode != 0))
+ {
+ st->enableTcxLpc = 1;
+ move16();
+ }
+ }
+ test();
+ IF ( st->ini_frame_fx == 0 || EQ_16(st->last_codec_mode, MODE1))
+ {
+ st->envWeighted = 0;
+ move16();
+ }
+
+ test();
+ test();
+ IF( EQ_16(st->bwidth_fx, SWB)&&
+ (EQ_32(st->total_brate_fx, ACELP_16k40) || EQ_32(st->total_brate_fx, ACELP_24k40)) )
+ {
+ IF(st->tec_tfa == 0)
+ {
+ FOR (i = 0; i < MAX_TEC_SMOOTHING_DEG; i++)
+ {
+ st->hTECEnc->loBuffer[i] = 0;
+ move16();
+ }
+ }
+ st->tec_tfa = 1;
+ move16();
+ }
+ ELSE
+ {
+ st->tec_tfa = 0;
+ move16();
+ }
+
+ st->enablePlcWaveadjust = 0;
+ move16();
+ IF (GE_32(st->total_brate_fx, 48000))
+ {
+ st->enablePlcWaveadjust = 1;
+ move16();
+ }
+
+
+ move16();
+ st->glr = 0;
+ test();
+ test();
+ test();
+ test();
+ if( (EQ_32(st->total_brate_fx, ACELP_9k60) || EQ_32(st->total_brate_fx, ACELP_16k40) || EQ_32(st->total_brate_fx, ACELP_24k40)) && EQ_16(st->element_mode, EVS_MONO) )
+ {
+ move16();
+ st->glr = 1;
+ }
+
+ if(st->glr)
+ {
+
+ st->nb_bits_header_ace = add(st->nb_bits_header_ace, G_LPC_RECOVERY_BITS);
+ }
+ IF (hTcxEnc != NULL)
+ {
+ test();
+ IF(EQ_16(st->bwidth_fx, NB) || EQ_16(st->bwidth_fx, WB))
+ {
+ test();
+ IF(st->rf_mode == 0)
+ {
+ index = s_min(N_TCX_STARTLINE_NOISE_WB - 1, s_max(3, st->frame_size_index));
+ }
+ ELSE
+ {
+ index = s_min(N_TCX_STARTLINE_NOISE_WB - 1, s_max(3, st->frame_size_index - 1));
+ }
+ hTcxEnc->nmStartLine = startLineWB[index];
+ move16();
+ }
+ ELSE /* (st->bwidth_fx == SWB || st->bwidth_fx == FB) */
+ {
+ IF(st->rf_mode == 0)
+ {
+ index = s_min(N_TCX_STARTLINE_NOISE_SWB - 1, sub(s_max(3, st->frame_size_index), 3));
+ }
+ ELSE
+ {
+ index = s_min(N_TCX_STARTLINE_NOISE_SWB - 1, sub(s_max(3, st->frame_size_index - 1), 3));
+ }
+ test();test();
+ if (GE_32(st->total_brate_fx, IVAS_96k) && LE_32(st->total_brate_fx, IVAS_192k) && GT_16(st->element_mode, IVAS_SCE))
+ {
+ index = sub(index, 1);
+ }
+ hTcxEnc->nmStartLine = startLineSWB[index];
+ move16();
+ if (EQ_32(st->total_brate_fx, IVAS_48k) && EQ_16(st->element_mode, IVAS_CPE_MDCT) && LT_16(add(hTcxEnc->nmStartLine, shl(hTcxEnc->nmStartLine,2)) , shl(st->L_frame_fx, 2)) )
+ {
+ hTcxEnc->nmStartLine = shr(add(hTcxEnc->nmStartLine, shl(hTcxEnc->nmStartLine, 2)), 2); /* low-rate stereo is more efficient than dual-mono due to stereo processing */
+ }
+ }
+ }
+
+ IF(hTcxEnc != NULL)
+ {
+ test(); test();
+ test(); test(); test();
+ IF((LT_32(st->total_brate_fx, ACELP_24k40)) && ((GT_32(st->total_brate_fx, st->last_total_brate_fx)) || (EQ_16(st->last_codec_mode, MODE1))))
+ {
+ /* low-freq memQuantZeros_fx must be reset partially if bitrate increased */
+ FOR(i = 0; i < hTcxEnc->nmStartLine; i++)
+ {
+ hTcxEnc->memQuantZeros_fx[i] = 0;
+ move16();
+ }
+ }
+ ELSE IF((GE_32(st->total_brate_fx, ACELP_24k40)) && (LE_32(st->total_brate_fx, ACELP_32k)) && (GE_32(st->last_total_brate_fx, ACELP_13k20)) && (LT_32(st->last_total_brate_fx, ACELP_24k40)))
+ {
+ FOR(i = 0; i < st->L_frame_fx; i++) /* memQuantZeros_fx won't be updated */
+ {
+ hTcxEnc->memQuantZeros_fx[i] = 0;
+ move16();
+ }
+ }
+ }
+}
+
diff --git a/lib_enc/core_enc_switch_fx.c b/lib_enc/core_enc_switch_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..22ead67bc30008e6b0e110355e37f025df9f803d
--- /dev/null
+++ b/lib_enc/core_enc_switch_fx.c
@@ -0,0 +1,228 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include
+#include "options.h"
+#include "prot.h"
+//#include "prot_fx.h"
+//#include "basop_mpy.h"
+#include "cnst.h" /* Common constants */
+#include "ivas_cnst.h"
+#include "rom_com_fx.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+
+void core_coder_mode_switch_fx(
+ Encoder_State_fx *st,
+ const Word32 last_total_bitrate,
+ const Word16 MCT_flag,
+ const Word16 shift
+)
+{
+ Word16 i, fscale, switchWB;
+ Word16 bSwitchFromAmrwbIO, tcxonly_tmp;
+ Word32 tmp32;
+ Word32 sr_core;
+ TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ move16();move16();
+ move16();move16();
+
+ switchWB = 0;
+ bSwitchFromAmrwbIO = 0;
+ if ( EQ_16(st->last_core_fx, AMR_WB_CORE))
+ {
+ move16();
+ bSwitchFromAmrwbIO = 1;
+ }
+
+ sr_core = getCoreSamplerateMode2(st->element_mode, st->total_brate_fx, st->bwidth_fx, st->flag_ACELP16k, st->rf_mode, st->is_ism_format);
+ move16();
+ fscale = sr2fscale(sr_core);
+ move16();
+
+ if( EQ_16(st->last_codec_mode,MODE1))
+ {
+ move16();
+ switchWB = 1; /*force init when coming from MODE1*/
+ }
+
+#ifdef IVAS_CODE_SWITCHING
+ tcxonly_tmp = getTcxonly(st->element_mode, st->total_brate_fx, MCT_flag, st->is_ism_format);
+#else
+ tcxonly_tmp = getTcxonly(st->total_brate_fx);
+#endif
+
+ test();
+ if( NE_16(tcxonly_tmp, st->tcxonly))
+ {
+ move16();
+ switchWB = 1; /*force init when coming from MODE1*/
+ }
+
+ test();
+ test();
+ IF ( (EQ_16(fscale, st->fscale)) && (bSwitchFromAmrwbIO==0) && (switchWB==0))
+ {
+ /*st->total_brate_fx = bitrate; */
+ move32();
+ st->sr_core = sr_core;
+ move32();
+ st->L_frame_fx = extract_l(Mult_32_16(st->sr_core , 0x0290));
+ assert(st->L_frame_fx == st->sr_core / 50);
+#ifdef IVAS_CODE_SWITCHING
+ st->tcxonly = getTcxonly(st->element_mode, st->total_brate_fx, MCT_flag, st->is_ism_format);
+#else
+ st->tcxonly = (Word8)getTcxonly(st->total_brate_fx);
+#endif
+ /* st->bits_frame_nominal = (int)( (float)st->L_frame_fx/(float)st->fscale ) * (float)FSCALE_DENOM/128.0f * (float)st->bitrate/100.0f + 0.49f ; */
+ /* st->bits_frame_nominal = extract_l(L_shr(Mpy_32_16_1( L_shl(st->bitrate,8), mult_r(div_s(st->fscale, shl(st->L_frame_fx,4)), FL2WORD16(FSCALE_DENOM/12800.f))), 6)); */
+ tmp32 = L_shl(st->total_brate_fx, 1); /* (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->bitrate */
+ st->bits_frame_nominal = extract_l(L_shr(Mpy_32_16_1(tmp32, 20972), 6)); /* 20972 = 0.01 * 64 * 32768 */
+ assert(st->bits_frame_nominal == (int)( (float)st->L_frame_fx/(float)st->fscale * (float)FSCALE_DENOM/128.0f * (float)st->total_brate_fx/100.0f + 0.49f ));
+
+ st->igf = getIgfPresent_fx(st->element_mode, st->total_brate_fx, st->bwidth_fx, st->rf_mode);
+
+ /* switch IGF configuration */
+ IF (st->igf)
+ {
+ IGFEncSetMode_fx(st->hIGFEnc, st->total_brate_fx, st->bwidth_fx, st->element_mode, st->rf_mode);
+ }
+
+ st->hTcxCfg->tcx_coded_lines = getNumTcxCodedLines(st->bwidth_fx);
+ move16();
+ st->hTcxCfg->bandwidth = getTcxBandwidth(st->bwidth_fx);
+ move16();
+ move16();
+ st->hTcxCfg->tcxRateLoopOpt = 0;
+ if (st->tcxonly)
+ {
+ move16();
+ st->hTcxCfg->tcxRateLoopOpt = 2;
+ }
+
+ st->hTcxCfg->ctx_hm = getCtxHm(st->element_mode, st->total_brate_fx, st->rf_mode );
+ move16();
+ st->hTcxCfg->resq = getResq(st->total_brate_fx);
+ move16();
+ hTcxEnc->tcx_lpc_shaped_ari = getTcxLpcShapedAri(st->total_brate_fx, st->rf_mode, st->element_mode);
+
+ test();
+ if (st->hTcxCfg->resq != 0 && st->tcxonly == 0)
+ {
+ st->hTcxCfg->tcxRateLoopOpt = 1;
+ move16();
+ }
+ st->hTcxCfg->fIsTNSAllowed = getTnsAllowed(st->total_brate_fx, st->igf, st->element_mode);
+ IF (st->hTcxCfg->fIsTNSAllowed != 0)
+ {
+ InitTnsConfigs(st->bwidth_fx, st->hTcxCfg->tcx_coded_lines, st->hTcxCfg->tnsConfig, st->hIGFEnc->infoStopFrequency, st->total_brate_fx, st->element_mode, MCT_flag);
+#ifdef IVAS_CODE
+ SetAllowTnsOnWhite(st->hTcxCfg->tnsConfig, EQ_16(st->element_mode, IVAS_CPE_MDCT));
+#endif
+ }
+ move16();
+
+ st->narrowBand = 0;
+ move16();
+ if(EQ_16(st->bwidth_fx, NB))
+ {
+ st->narrowBand = 1;
+ move16();
+ }
+ IF ( st->narrowBand )
+ {
+ st->min_band_fx = 1;
+ move16();
+ st->max_band_fx = 16;
+ move16();
+ }
+ ELSE
+ {
+ st->min_band_fx = 0;
+ move16();
+ st->max_band_fx = 19;
+ move16();
+ }
+
+ FOR (i=0; ibits_frame_nominal))
+ {
+ move16();
+ move16();
+ move16();
+ st->frame_size_index = i;
+ st->bits_frame = FrameSizeConfig[i].frame_bits;
+ st->bits_frame_core = FrameSizeConfig[i].frame_net_bits;
+ BREAK;
+ }
+ }
+
+ st->restrictedMode = getRestrictedMode(st->element_mode, st->total_brate_fx, 0);
+
+ core_coder_reconfig_fx( st, last_total_bitrate);
+ }
+ ELSE
+ {
+ st->igf = getIgfPresent_fx(st->element_mode, st->total_brate_fx, st->bwidth_fx, st->rf_mode);
+ init_coder_ace_plus_fx(st, last_total_bitrate, shift, MCT_flag);
+ }
+
+ test();
+ IF( st->igf != 0 && st->hBWE_TD != NULL)
+ {
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF( (EQ_16(st->bwidth_fx, WB)&&NE_16(st->last_extl_fx,WB_TBE))||
+ (EQ_16(st->bwidth_fx, SWB) && NE_16(st->last_extl_fx, SWB_TBE) ) ||
+ (EQ_16(st->bwidth_fx, FB) && NE_16(st->last_extl_fx, FB_TBE) ) )
+ {
+ /* reset TBE buffers as previous frame wasn't using TBE */
+ TBEreset_enc_fx( st, st->bwidth_fx );
+ }
+ ELSE
+ {
+ set16_fx(hBWE_TD->state_lpc_syn_fx, 0, LPC_SHB_ORDER );
+ set16_fx(hBWE_TD->state_syn_shbexc_fx, 0, L_SHB_LAHEAD );
+ set16_fx(hBWE_TD->mem_stp_swb_fx, 0, LPC_SHB_ORDER );
+ set16_fx(hBWE_TD->mem_zero_swb_fx, 0, LPC_SHB_ORDER );
+ hBWE_TD->gain_prec_swb_fx = 16384;
+ move16(); /*Q14 = 1 */
+ }
+ }
+
+ IF ( s_and(st->envWeighted!=0, st->enableTcxLpc==0) )
+ {
+ /* Unweight the envelope */
+ E_LPC_lsp_unweight(st->lsp_old_fx, st->lsp_old_fx, st->lsf_old_fx, st->inv_gamma, M );
+ move16();
+ st->envWeighted = 0;
+ }
+
+ st->enablePlcWaveadjust = 0;
+ move16();
+ if (GE_32(st->total_brate_fx, HQ_48k))
+ {
+ st->enablePlcWaveadjust = 1;
+ move16();
+ }
+
+ test();
+ IF( (GT_32(last_total_bitrate, HQ_32k) || EQ_32(st->last_codec_mode,MODE1)) && EQ_16(st->element_mode, EVS_MONO))
+ {
+ move16();
+ st->glr_reset = 1;
+ }
+}
+
diff --git a/lib_enc/core_enc_updt_fx.c b/lib_enc/core_enc_updt_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..f1dd62c400598628c1aac5652f997105be9e71a4
--- /dev/null
+++ b/lib_enc/core_enc_updt_fx.c
@@ -0,0 +1,213 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+//#include "prot_fx.h"
+#include "options.h"
+#include "cnst.h" /* Common constants */
+#include "basop_util.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+void core_encode_update_fx(Encoder_State_fx *st
+ )
+{
+ Word16 n;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ /*--------------------------------------------------------------*
+ * Update Buffers
+ *---------------------------------------------------------------*/
+
+ /* Update Input Signal Buffers */
+
+ n = add(st->encoderPastSamples_enc, st->encoderLookahead_enc);
+
+ Copy(st->buf_speech_enc +st->L_frame_fx, st->buf_speech_enc, n);
+ Copy(st->buf_speech_enc_pe+st->L_frame_fx, st->buf_speech_enc_pe, n);
+
+
+ IF(!st->tcxonly)
+ {
+ n = add(st->L_frame_fx, shr(st->L_frame_fx,2));
+ Copy(st->buf_wspeech_enc+st->L_frame_fx, st->buf_wspeech_enc, n);
+ }
+
+
+ IF (hTcxEnc != NULL)
+ {
+ IF(EQ_16(st->core_fx, ACELP_CORE) || EQ_32(st->core_brate_fx, SID_2k40) || EQ_32(st->core_brate_fx, FRAME_NO_DATA) || EQ_32(st->core_fx, AMR_WB_CORE))
+ {
+ Copy(st->buf_speech_enc + st->L_frame_fx, hTcxEnc->buf_speech_ltp + st->L_frame_fx, st->L_frame_fx);
+ }
+ }
+ n = add(st->encoderPastSamples_enc, st->encoderLookahead_enc);
+ Copy(st->buf_synth+st->L_frame_fx, st->buf_synth, add(st->L_frame_fx,L_SUBFR));
+ if (hTcxEnc != NULL)
+ {
+ Copy(hTcxEnc->buf_speech_ltp+st->L_frame_fx, hTcxEnc->buf_speech_ltp, n);
+
+#ifdef IVAS_CODE
+ IF (NE_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ st->hTcxEnc->kernel_switch_corr_past = 0.f;
+ st->hTcxEnc->kernel_type[0] = MDCT_IV;
+ st->hTcxEnc->kernel_symmetry_past = 0;
+ st->hTcxEnc->enc_ste_pre_corr_past = 0;
+ move16();move16();move16();move16();
+ }
+#endif
+ }
+ /* Update previous mode */
+
+ //move16();
+ //st->last_core_fx = st->core_fx; /* _DIFF_FLOAT_FIX_ not in float -> remove? */
+
+
+ test();
+ test();
+ test();
+ IF( ( st->Opt_DTX_ON_fx && LE_32(st->core_brate_fx,SID_2k40) && EQ_16(st->cng_type_fx,FD_CNG)) || (st->tcxonly && EQ_16(st->codec_mode,MODE2)))
+ {
+ /* reset LP memories */
+ set16_fx( st->mem_MA_fx,0, M );
+ Copy( GEWB_Ave_fx, st->mem_AR_fx, M );
+ }
+
+}
+/*-------------------------------------------------------------------*
+ * core_encode_update_cng_fx()
+ *
+ * Common updates in case of CNG
+ *-------------------------------------------------------------------*/
+void core_encode_update_cng_fx(
+ Encoder_State_fx *st,
+ Word16 *timeDomainBuffer,
+ Word16 *A,
+ Word16 *Aw,
+ Word16 Q_new,
+ Word16 shift
+)
+{
+ Word16 i;
+ Word16 lsp[M];
+ Word16 lsf[M]; /* 14Q1 * 1.28 */
+ Word16 *synth, synth_buf[M+1+L_FRAME_PLUS+L_FRAME_PLUS/2], wsyn[L_FRAME_PLUS];
+ Word16 *p_A, tmp;
+ Word16 enr_index;
+ Word16 enr;
+ DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc;
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+ /* LPC -> LSP/lsp */
+ /* LSP/lsp -> LSF/lsf */
+ E_LPC_a_lsp_conversion( A, lsp, st->lsp_old_fx, M );
+ IF(EQ_16(st->L_frame_fx, L_FRAME16k))
+ {
+ lsp2lsf_fx( lsp, lsf, M, INT_FS_16k_FX );
+ }
+ ELSE
+ {
+ E_LPC_lsp_lsf_conversion( lsp, lsf, M );
+ }
+
+ /* Update synth memory */
+ move16();
+ synth = synth_buf + (1+M);
+ Copy( hLPDmem->syn, synth_buf, 1+M );
+ Copy( timeDomainBuffer, synth, st->L_frame_fx );
+ Copy( synth+st->L_frame_fx-(1+M), hLPDmem->syn, 1+M );
+ Copy( synth, st->synth, st->L_frame_fx );
+
+ /* Update ZIR */
+ set16_fx( synth+st->L_frame_fx, 0, shr(st->L_frame_fx,1) );
+ E_UTIL_synthesis(1, A, synth+st->L_frame_fx, synth+st->L_frame_fx, shr(st->L_frame_fx,1), &synth[st->L_frame_fx-M], 0, M );
+ IF (hTcxEnc != NULL)
+ {
+ Copy(synth + st->L_frame_fx - (st->L_frame_fx / 2), hTcxEnc->Txnq, shr(st->L_frame_fx, 1));
+ }
+ /* Update pe-synth memory */
+ move16();
+ tmp = synth[-(1+M)];
+ E_UTIL_f_preemph2( Q_new-1, synth-M, st->preemph_fac, M+st->L_frame_fx, &tmp );
+ Copy( synth+st->L_frame_fx-M, hLPDmem->mem_syn, M );
+ Copy( synth+st->L_frame_fx-M, hLPDmem->mem_syn2, M );
+
+ /* Update excitation memory */
+ Copy( hLPDmem->old_exc+st->L_frame_fx, hLPDmem->old_exc, s_max(L_EXC_MEM-st->L_frame_fx, 0 ));
+ Residu3_fx( A, synth, hLPDmem->old_exc+s_max(L_EXC_MEM-st->L_frame_fx, 0), st->L_frame_fx, 1 );
+
+ /* Update LP_CNG memory */
+ IF( EQ_32(st->core_brate_fx, SID_2k40))
+ {
+ /*IVAS_CODE CNG_att is missing */
+ enr = cng_energy_fx(st->element_mode, st->bwidth_fx, hDtxEnc->CNG_mode, /*st->hTdCngEnc->CNG_att*/0, hLPDmem->old_exc + s_max(L_EXC_MEM - st->L_frame_fx, 0), st->L_frame_fx, Q_new);
+
+ /* calculate the energy quantization index */
+ enr_index = add(enr, 512 /* Q8(2.0) */); /* enr + 2.0 */
+ enr_index = extract_l(L_shr(L_mult0(enr_index, STEP_SID_FX), 12+8)); /* Q0 (8+12-(8+12)) */
+
+ /* limit the energy quantization index */
+ enr_index = s_min(enr_index, 127);
+ enr_index = s_max(enr_index, 0);
+
+ hTdCngEnc->old_enr_index = enr_index;
+ }
+
+ /* Update weighted synthesis memory */
+ move16();
+ p_A = Aw;
+ FOR ( i = 0; i < st->L_frame_fx; i += L_SUBFR )
+ {
+ Residu3_fx( p_A, &synth[i], &wsyn[i], L_SUBFR, 0);
+ p_A += (M+1);
+ }
+ move16();
+
+
+ tmp = sub(st->wspeech_enc[-1],shl(hLPDmem->mem_w0,shift));
+ E_UTIL_deemph2( -shift, wsyn, st->preemph_fac, st->L_frame_fx, &tmp );
+ hLPDmem->mem_w0 = sub(st->wspeech_enc[st->L_frame_fx-1], tmp);
+ hLPDmem->mem_w0 =shr(hLPDmem->mem_w0, shift);
+
+ /* Update LPC-related memories */
+
+ Copy( lsp, st->lsp_old_fx, M );
+ Copy( lsf, st->lsf_old_fx, M );
+ move16();
+ st->envWeighted = 0;
+ Copy( A, st->old_Aq_12_8_fx, M+1 );
+ st->old_Es_pred_fx=0;
+
+
+ /* Reset acelp memories */
+ move16();
+ move16();
+ hLPDmem->dm_fx.prev_gain_code = L_deposit_l(0);
+ set16_fx(hLPDmem->dm_fx.prev_gain_pit,0,6);
+ hLPDmem->dm_fx.prev_state = 0;
+ hLPDmem->tilt_code = TILT_CODE;
+ hLPDmem->gc_threshold = L_deposit_l(0);
+
+ /* Update ace/tcx mode */
+ move16();
+ st->core_fx = ACELP_CORE;
+
+ /* Reset TCX overlap */
+ st->hTcxCfg->tcx_curr_overlap_mode = st->hTcxCfg->tcx_last_overlap_mode = ALDO_WINDOW;
+ move16();
+
+ IF(hDtxEnc->first_CNG == 0 )
+ {
+ Copy( st->lsp_old_fx, hDtxEnc->lspCNG_fx, M );
+ }
+
+ return;
+}
+
diff --git a/lib_enc/core_switching_enc_fx.c b/lib_enc/core_switching_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..cb5455aad8cb690fc3ccb7575c9ef24b3b8f0e00
--- /dev/null
+++ b/lib_enc/core_switching_enc_fx.c
@@ -0,0 +1,651 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_enc.h" /* Encoder static table prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+/*---------------------------------------------------------------------*
+* core_switching_pre_enc()
+*
+* Preprocessing (preparing) for ACELP/HQ core switching
+*---------------------------------------------------------------------*/
+
+void core_switching_pre_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 *old_inp_12k8, /* i : old input signal @12.8kHz */
+ const Word16 *old_inp_16k, /* i : old input signal @16kHz */
+ const Word16 active_cnt, /* i : active frame counter */
+ const Word16 last_element_mode /* i : last_element_mode */
+)
+{
+ Word16 Sample_Delay_HP, Sample_Delay_LP;
+ Word16 tmp16;
+ Word16 tmp;
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+ HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core;
+ TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD;
+ TCX_ENC_HANDLE hTcxEnc = st_fx->hTcxEnc;
+ FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD;
+
+ /* Mode switching */
+ test();test();test();
+ IF( EQ_16(st_fx->last_codec_mode,MODE2) || (((EQ_16(st_fx->last_core_fx, TCX_20_CORE)
+ || EQ_16(st_fx->last_core_fx, TCX_10_CORE)) && GT_16(st_fx->element_mode, EVS_MONO))))
+ {
+ IF (hLPDmem != NULL)
+ {
+ st_fx->mem_deemph_fx = hLPDmem->syn[M];
+ move16();
+ Copy( hLPDmem->mem_syn2, hLPDmem->mem_syn1_fx, M );
+ }
+
+ if (NE_16(st_fx->element_mode, IVAS_CPE_MDCT))
+ {
+ st_fx->igf = 0;
+ move16();
+ }
+
+ IF (hBWE_TD != NULL)
+ {
+ IF(NE_16(st_fx->last_core_fx, ACELP_CORE))
+ {
+ /* reset BWE memories */
+ set16_fx(hBWE_TD->old_bwe_exc_fx, 0, PIT16k_MAX * 2);
+ hBWE_TD->bwe_non_lin_prev_scale_fx = L_deposit_l(0);
+ }
+
+ set16_fx(hBWE_FD->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS));
+ }
+ test();
+ IF( EQ_16(st_fx->last_core_fx,TCX_20_CORE)||EQ_16(st_fx->last_core_fx,TCX_10_CORE))
+ {
+ if (EQ_16(st_fx->element_mode, EVS_MONO))
+ {
+ st_fx->last_core_fx = HQ_CORE;
+ move16();
+ }
+ IF (hHQ_core != NULL)
+ {
+ set32_fx(hHQ_core->last_ni_gain_fx, 0, BANDS_MAX);
+ set16_fx(hHQ_core->last_env_fx, 0, BANDS_MAX);
+ hHQ_core->last_max_pos_pulse = 0;
+ move16();
+
+ hHQ_core->mode_count = 0;
+ move16();
+ hHQ_core->mode_count1 = 0;
+ move16();
+
+ set16_fx(hHQ_core->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM);
+ hHQ_core->prev_frm_hfe2 = 0;
+ move16();
+ hHQ_core->prev_stab_hfe2 = 0;
+ move16();
+ }
+ /*ALDO overlap windowed past: also used in MODE2 but for other MDCT-LB*/
+ IF (EQ_16(st_fx->element_mode, EVS_MONO) && hTcxEnc != NULL)
+ {
+ set16_fx(hTcxEnc->old_out_fx, 0, L_FRAME32k);
+ }
+ }
+
+ test();
+ IF( (EQ_16(st_fx->L_frame_fx,L_FRAME16k))&&(EQ_16(st_fx->last_L_frame_fx,L_FRAME)))
+ {
+ Copy( st_fx->lsp_old_fx, st_fx->lsp_old16k_fx, M );
+
+ st_fx->rate_switching_reset_16kHz = lsp_convert_poly_fx( st_fx->lsp_old16k_fx, st_fx->L_frame_fx, 0 );
+ }
+
+ st_fx->use_acelp_preq = 0;
+ move16();
+
+ }
+
+ test();test();test();
+ IF( EQ_16(st_fx->last_core_fx, -1) && ( EQ_16(st_fx->core_fx, HQ_CORE) || EQ_16(st_fx->core_fx, TCX_20_CORE) || EQ_16(st_fx->core_fx, TCX_10_CORE)))
+ {
+ /* very first frame is HQ_CORE */
+ st_fx->last_core_fx = HQ_CORE;
+ move16();
+ }
+
+ test();
+ test();
+ IF( EQ_16(st_fx->core_fx, HQ_CORE)&&(EQ_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))) /* HQ init */
+ {
+ set32_fx(hHQ_core->last_ni_gain_fx, 0, BANDS_MAX );
+ set16_fx(hHQ_core->last_env_fx, 0, BANDS_MAX );
+ hHQ_core->last_max_pos_pulse = 0;
+ move16();
+
+ hHQ_core->mode_count = 0;
+ move16();
+ hHQ_core->mode_count1 = 0;
+ move16();
+
+ set16_fx(hHQ_core->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM );
+ hHQ_core->prev_frm_hfe2 = 0;
+ move16();
+ hHQ_core->prev_stab_hfe2 = 0;
+ move16();
+
+ if (hTcxEnc != NULL)
+ {
+ set16_fx(hTcxEnc->old_out_fx, 0, L_FRAME32k);
+ }
+ }
+
+ /* Here we only handle cases where last_ppp and last_nelp not updated when coming from CodecB or other cores
+ within ACELP_CORE if switching from another bitarate to vbr, last_ppp and last_nelp is always updated in the previous frame */
+ test();
+ test();
+ IF( EQ_16(st_fx->core_fx, ACELP_CORE)&&(NE_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_codec_mode,MODE2)))
+ {
+ IF (hSC_VBR != NULL)
+ {
+ hSC_VBR->last_last_ppp_mode = 0;
+ move16();
+ hSC_VBR->last_ppp_mode = 0;
+ move16();
+ hSC_VBR->last_nelp_mode = 0;
+ move16();
+ }
+ }
+
+ test();
+ test();
+ test();
+ IF( EQ_16(st_fx->core_fx, ACELP_CORE)&&(NE_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_codec_mode,MODE2)||LE_32(st_fx->last_total_brate_fx,PPP_NELP_2k80)))
+ {
+ st_fx->act_count_fx = 3;
+ move16();
+ st_fx->uv_count_fx = 0;
+ move16();
+ }
+
+ test();
+ test();
+ IF( ( ( EQ_16(st_fx->core_fx, ACELP_CORE)||EQ_16(st_fx->core_fx,AMR_WB_CORE))&&EQ_16(st_fx->last_core_fx,HQ_CORE)) ||
+ ((EQ_16(st_fx->element_mode, IVAS_CPE_DFT) || EQ_16(st_fx->element_mode, IVAS_CPE_TD) || (EQ_16(st_fx->element_mode, IVAS_CPE_MDCT)
+ && EQ_16(last_element_mode, IVAS_CPE_DFT))) && EQ_16(active_cnt, 1)))
+ {
+ IF(EQ_16(st_fx->L_frame_fx, L_FRAME16k))
+ {
+ Copy( TRWB2_Ave_fx, st_fx->lsf_old_fx, M ); /* init of LSP */
+ lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, INT_FS_16k );
+ }
+ ELSE
+ {
+ Copy( TRWB_Ave_fx, st_fx->lsf_old_fx, M ); /* init of LSP */
+ lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old_fx, M, INT_FS_FX );
+ }
+
+ st_fx->mem_deemph_fx = 0;
+ /* Reset ACELP parameters */
+ IF (hLPDmem != NULL)
+ {
+ move16();
+ hLPDmem->syn[M] = 0;
+ move16();
+ set16_fx(hLPDmem->mem_syn2, 0, M);
+ set16_fx(hLPDmem->mem_syn, 0, M);
+ set16_fx(hLPDmem->mem_syn1_fx, 0, M);
+ hLPDmem->mem_w0 = 0;
+ move16();
+ hLPDmem->tilt_code = 0;
+ move16();
+ hLPDmem->gc_threshold = 0;
+ move32();
+ /* set16_fx( st_fx->dispMem, 0, 8 ); */
+ set16_fx(hLPDmem->dm_fx.prev_gain_pit, 0, 6);
+ hLPDmem->dm_fx.prev_state = 0;
+ move16();
+ hLPDmem->dm_fx.prev_gain_code = L_deposit_l(0);
+ }
+ st_fx->Nb_ACELP_frames_fx = 0;
+ move16();
+
+ set16_fx( st_fx->mem_MA_fx,0, M );
+ Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M );
+ init_gp_clip_fx( st_fx->clip_var_fx );
+ st_fx->last_coder_type_fx = GENERIC;
+ move16();
+
+ tmp16 = add(NB_SUBFR,1);
+ move16();
+
+ if( EQ_16(st_fx->L_frame_fx,L_FRAME))
+ {
+ tmp16=NB_SUBFR;
+ move16();
+ }
+
+ Copy( st_fx->old_pitch_buf_fx + tmp16, st_fx->old_pitch_buf_fx, tmp16 );
+ set16_fx( st_fx->old_pitch_buf_fx + tmp16, L_SUBFR,tmp16);
+
+ /* Reset old ACELP buffers */
+ test();
+ IF (EQ_16(st_fx->element_mode, EVS_MONO) && hLPDmem != NULL)
+ {
+ set16_fx(hLPDmem->old_exc, 0, L_EXC_MEM);
+ }
+ IF (hBWE_TD != NULL)
+ {
+ set16_fx(hBWE_TD->old_bwe_exc_fx, 0, PIT16k_MAX * 2);
+
+ /* reset BWE memories */
+ hBWE_TD->bwe_non_lin_prev_scale_fx = 0;
+ }
+ IF(hBWE_FD != NULL)
+ {
+ set16_fx(hBWE_FD->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) );
+ }
+ }
+ test();test();test();
+ IF ((EQ_16(st_fx->core_fx, ACELP_CORE) || EQ_16(st_fx->core_fx, AMR_WB_CORE)) && (EQ_16(st_fx->last_core_fx, TCX_20_CORE) || EQ_16(st_fx->last_core_fx, TCX_10_CORE)))
+ {
+ /* Reset the ACELP core in case of TCX->ACELP core switching */
+ st_fx->Nb_ACELP_frames_fx = 0; move16();
+
+ IF (hLPDmem != NULL)
+ {
+ hLPDmem->mem_w0 = 0;
+ move16();
+ hLPDmem->tilt_code = 0;
+ move16();
+ hLPDmem->gc_threshold = 0;
+ move32();
+ init_gp_clip_fx(st_fx->clip_var_fx);
+ set16_fx(hLPDmem->dm_fx.prev_gain_pit, 0, 6);
+ hLPDmem->dm_fx.prev_state = 0;
+ move16();
+ hLPDmem->dm_fx.prev_gain_code = L_deposit_l(0);
+ }
+
+ st_fx->last_coder_type_fx = GENERIC; move16();
+
+ tmp16 = shr(st_fx->L_frame_fx, 6);
+ Copy(st_fx->old_pitch_buf_fx + tmp16, st_fx->old_pitch_buf_fx, tmp16);
+ set16_fx(st_fx->old_pitch_buf_fx + tmp16, L_SUBFR, tmp16);
+
+ /* Reset old TD BWE buffers */
+ IF (hBWE_TD != NULL)
+ {
+ set16_fx(hBWE_TD->old_bwe_exc_fx, 0, PIT16k_MAX * 2);
+ hBWE_TD->bwe_non_lin_prev_scale_fx = 0; move16();
+ }
+
+ /* reset BWE memories */
+ IF (hBWE_FD != NULL)
+ {
+ set16_fx(hBWE_FD->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS));/* TODO : this might not be needed */
+ }
+ }
+ test();test();test();
+ IF( GE_32(st_fx->input_Fs_fx, 16000)&&NE_16(st_fx->last_extl_fx,WB_BWE)&&EQ_16(st_fx->extl_fx,WB_BWE) && hBWE_FD != NULL)
+ {
+ test();
+ IF( NE_16(st_fx->last_extl_fx, SWB_BWE)&&NE_16(st_fx->last_extl_fx,FB_BWE))
+ {
+ hBWE_FD->prev_mode = NORMAL;
+ move16();
+ hBWE_FD->modeCount = 0;
+ move16();
+ }
+
+ hBWE_FD->prev_L_swb_norm1 = 8;
+ move16();
+ }
+
+ test();test();test();test();test();
+ IF( ( GE_32(st_fx->input_Fs_fx, 32000)&&NE_16(st_fx->last_extl_fx,SWB_BWE)&&EQ_16(st_fx->extl_fx,SWB_BWE))||
+ ( GE_32(st_fx->input_Fs_fx, 48000) && NE_16(st_fx->last_extl_fx, FB_BWE) && EQ_16(st_fx->extl_fx, FB_BWE) ) )
+ {
+ /* we are switching to SWB BWE - reset SWB BWE buffers */
+
+ IF( EQ_16(st_fx->L_frame_fx, L_FRAME))
+ {
+ Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS );
+ Sample_Delay_LP = NS2SA( 12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS );
+ IF (GT_16(st_fx->element_mode, EVS_MONO))
+ {
+ IF (EQ_16(st_fx->element_mode, IVAS_CPE_TD))
+ {
+ Sample_Delay_HP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS - L_MEM_RECALC_TBE_NS);
+ }
+ Sample_Delay_HP = sub(Sample_Delay_HP , NS2SA(16000, DELAY_FIR_RESAMPL_NS));
+ }
+ Copy( old_inp_12k8 + sub(L_INP_MEM + L_FRAME, Sample_Delay_LP), hBWE_FD->old_input_lp_fx, Sample_Delay_LP );
+ }
+ ELSE
+ {
+ Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS );
+ Sample_Delay_LP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS );
+ IF(GT_16(st_fx->element_mode, EVS_MONO))
+ {
+ IF(EQ_16(st_fx->element_mode, IVAS_CPE_TD))
+ {
+ Sample_Delay_HP = NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS - L_MEM_RECALC_TBE_NS);
+ }
+ Sample_Delay_HP = sub(Sample_Delay_HP,NS2SA(16000, DELAY_FIR_RESAMPL_NS));
+ }
+
+ Copy( old_inp_16k + sub(L_INP_MEM + L_FRAME, Sample_Delay_LP), hBWE_FD->old_input_lp_fx, Sample_Delay_LP );
+ }
+
+ tmp = sub(L_LOOK_16k + L_SUBFR16k, Sample_Delay_HP);
+ Copy( &hBWE_TD->old_speech_shb_fx[tmp], hBWE_FD->new_input_hp_fx, Sample_Delay_HP );
+ add(0,0);
+
+ IF (NE_16(st_fx->last_extl_fx,WB_BWE))
+ {
+ hBWE_FD->prev_mode = NORMAL;
+ move16();
+ hBWE_FD->modeCount = 0;
+ move16();
+ }
+ hBWE_FD->EnergyLF_fx = L_deposit_l(0);
+ hBWE_FD->prev_L_swb_norm1 = 8;
+ move16();/*8.0 in Q0 */
+ st_fx->EnergyLT_fx_exp = 30;
+ move16(); /* Set to a High Exponent so it is 1^-30 */
+
+ }
+ /*---------------------------------------------------------------------*
+ * band-width switching from WB -> SWB/FB
+ *---------------------------------------------------------------------*/
+#ifdef IVAS_CODE
+ IF (GT_16(st_fx->element_mode, EVS_MONO))
+ {
+ IF (st_fx->bwidth_sw_cnt_fx == 0)
+ {
+ IF (GE_16(st_fx->bwidth_fx, SWB) && EQ_16(st_fx->last_bwidth_fx,WB))
+ {
+ st_fx->bwidth_sw_cnt_fx = add(st_fx->bwidth_sw_cnt_fx, 1);
+ }
+ }
+ ELSE
+ {
+ st_fx->bwidth_sw_cnt_fx = add(st_fx->bwidth_sw_cnt_fx, 1);
+
+ IF (EQ_16(st_fx->bwidth_sw_cnt_fx, BWS_TRAN_PERIOD))
+ {
+ st_fx->bwidth_sw_cnt_fx = 0;
+ move16();
+ }
+ }
+ }
+#endif
+
+ return;
+}
+
+
+
+/*---------------------------------------------------------------------*
+* core_switching_post_enc()
+*
+* Postprocessing for ACELP/HQ core switching
+*---------------------------------------------------------------------*/
+void core_switching_post_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 old_inp_12k8[], /* i : input signal @12.8 kHz Qinp */
+ const Word16 old_inp_16k[], /* i : input signal @16 kHz Qinp */
+ const Word16 A[], /* i : unquant. LP filter coefs. (Q12) */
+ Word16 Qshift,
+ Word16 Q_new,
+ const Word16 Qsp, /* i/o : Q from acelp synthsis */
+ Word16 *Qmus /* i/o : Q from mdct synthsis / Q of output synthesis */
+)
+{
+ TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD;
+ FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD;
+
+ IF( EQ_16(st_fx->core_fx, HQ_CORE))
+ {
+ st_fx->use_acelp_preq = 0;
+ move16();
+
+ test();test();
+ IF( ( EQ_16(st_fx->last_core_fx, ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE)) && EQ_16(st_fx->element_mode, EVS_MONO) ) /* core switching ==> CELP subframe encoding */
+ {
+ acelp_core_switch_enc_fx( st_fx, old_inp_12k8 + L_INP_MEM - NS2SA_fx2(INT_FS_FX, ACELP_LOOK_NS),
+ old_inp_16k + L_INP_MEM - NS2SA_fx2(INT_FS_16k, ACELP_LOOK_NS), A, Qshift, Q_new );
+ }
+
+ hBWE_TD->bwe_non_lin_prev_scale_fx = L_deposit_l(0);
+ hBWE_FD->mem_deemph_old_syn_fx = 0;
+ move16();
+
+ }
+ ELSE
+ {
+ *Qmus=Qsp; /* Write Qout */
+ move16();
+ IF (hBWE_TD == NULL)
+ {
+ return;
+ }
+
+ /* reset SWB TBE buffers */
+ test();
+ IF( EQ_16(st_fx->extl_fx, WB_TBE)&&NE_16(st_fx->last_extl_fx,WB_TBE))
+ {
+ wb_tbe_extras_reset_fx(hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, hBWE_TD->mem_genSHBexc_filt_down_wb3_fx );
+
+ IF ( NE_16(st_fx->last_extl_fx, WB_BWE))
+ {
+ set16_fx(hBWE_TD->decim_state1_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 );
+ set16_fx(hBWE_TD->decim_state2_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 );
+ }
+
+ set16_fx(hBWE_TD->state_syn_shbexc_fx, 0, L_SHB_LAHEAD/4 );
+ set16_fx(hBWE_TD->syn_overlap_fx, 0, L_SHB_LAHEAD );
+ set32_fx(hBWE_TD->mem_csfilt_fx, 0, 2 );
+ }
+
+ test();test();test();test();
+ test();test();test();test();test();test();
+ test();IF( (EQ_16(st_fx->extl_fx, SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))&&
+ ( EQ_16(st_fx->last_core_fx,HQ_CORE) || NE_16(st_fx->L_frame_fx, st_fx->last_L_frame_fx) ||
+ ( NE_16(st_fx->last_extl_fx, SWB_TBE) && NE_16(st_fx->last_extl_fx, FB_TBE) && NE_16(st_fx->last_core_fx, TCX_20_CORE) && NE_16(st_fx->last_core_fx, TCX_10_CORE)) )
+ )
+ {
+ set16_fx(hBWE_TD->state_ana_filt_shb_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) );
+ set16_fx(hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k );
+
+#ifdef IVAS_CODE
+ set16_fx(hBWE_TD->mem_shb_res_fx, 0, MAX_LEN_MA_FILTER);
+ set16_fx(hBWE_TD->old_EnvSHBres_fx, 0, L_FRAME4k);
+ hBWE_TD->old_mean_EnvSHBres_fx = 0;
+ hBWE_TD->prev_enr_EnvSHBres_fx = 32767; /*Q15 ??? */
+ hBWE_TD->prev_shb_env_tilt_fx = 0;
+ hBWE_TD->prev_pow_exc16kWhtnd_fx = 32767; /*Q15 ??? */
+ hBWE_TD->prev_mix_factor_fx = 32767; /*Q15 ??? */
+ hBWE_TD->prev_Env_error_fx = 0;
+ move16();move16();move16();move16();move16();move16();
+#endif
+ swb_tbe_reset_fx(hBWE_TD->mem_csfilt_fx, hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->state_lpc_syn_fx,
+ hBWE_TD->syn_overlap_fx, hBWE_TD->state_syn_shbexc_fx, &(hBWE_TD->tbe_demph_fx), &(hBWE_TD->tbe_premph_fx),
+ hBWE_TD->mem_stp_swb_fx, &(hBWE_TD->gain_prec_swb_fx));
+
+ set16_fx(hBWE_TD->dec_2_over_3_mem_fx,0, 12 );
+ set16_fx(hBWE_TD->dec_2_over_3_mem_lp_fx,0, 6 );
+ }
+ ELSE IF( ( EQ_16(st_fx->extl_fx, SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))&&
+ ( NE_32(st_fx->last_total_brate_fx, st_fx->total_brate_fx) || NE_16(st_fx->last_bwidth_fx, st_fx->bwidth_fx) ||
+ NE_16(st_fx->last_codec_mode, MODE1) || NE_16(st_fx->rf_mode, st_fx->rf_mode_last) ) )
+ {
+ set16_fx(hBWE_TD->state_lpc_syn_fx, 0, LPC_SHB_ORDER );
+ set16_fx(hBWE_TD->state_syn_shbexc_fx, 0, L_SHB_LAHEAD );
+ set16_fx(hBWE_TD->mem_stp_swb_fx, 0, LPC_SHB_ORDER );
+ set16_fx(hBWE_TD->mem_zero_swb_fx, 0, LPC_SHB_ORDER );
+ hBWE_TD->gain_prec_swb_fx = 16384;
+ move16(); /*Q14 = 1 */
+ }
+ ELSE IF (EQ_16(st_fx->last_core_fx, TCX_20_CORE) || EQ_16(st_fx->last_core_fx, TCX_10_CORE))
+ {
+ TBEreset_enc_fx( st_fx, st_fx->bwidth_fx);
+ }
+ test();
+ test();
+ IF( EQ_16(st_fx->extl_fx, FB_TBE) && ((NE_16(st_fx->last_extl_fx, FB_TBE) && NE_16(st_fx->last_core_fx, TCX_20_CORE) && NE_16(st_fx->last_core_fx, TCX_10_CORE)) || NE_16(st_fx->L_frame_fx, st_fx->last_L_frame_fx)))
+ {
+ set16_fx(hBWE_TD->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER );
+ hBWE_TD->fb_tbe_demph_fx = 0;
+ fb_tbe_reset_enc_fx(hBWE_TD->elliptic_bpf_2_48k_mem_fx, &hBWE_TD->prev_fb_energy_fx, hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q,&hBWE_TD->prev_fb_energy_fx_Q);
+ }
+ /* Fade towards init value for non HQ_CORE */
+ IF (st_fx->hHQ_core != NULL)
+ {
+#ifdef IVAS_CODE
+ st_fx->hHQ_core->crest_lp = HQ_CREST_FAC_SM * (st_fx->hHQ_core->crest_lp) + (1.0f - HQ_CREST_FAC_SM) * HQ_CREST_THRESHOLD;
+ st_fx->hHQ_core->crest_mod_lp = HQ_CREST_FAC_SM * (st_fx->hHQ_core->crest_mod_lp) + (1.0f - HQ_CREST_FAC_SM) * HQ_CREST_MOD_THRESHOLD;
+#endif
+ }
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+* core_switching_hq_prepare_enc()
+*
+* Preprocessing in the first HQ frame after ACELP frame
+* - modify bit allocation for HQcore removing CELP subframe budget
+* - update st->old_wtda to modify windows at the encoder
+*---------------------------------------------------------------------*/
+
+void core_switching_hq_prepare_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ Word16 *num_bits, /* i/o: bit budget update */
+ const Word16 input_frame, /* i : frame length */
+ Word32 *wtda_audio, /* shall be q_audio + 15, audio allready scalled in wtda function */
+ const Word16 *audio
+)
+{
+ Word16 delta, Loverlapp, i;
+ Word16 tmp16;
+ Word32 cbrate, *pt_32;
+ const Word16 *pt_cos, *pt_16;
+ Word16 n;
+ TCX_ENC_HANDLE hTcxEnc = st_fx->hTcxEnc;
+
+ SWITCH (input_frame)
+ {
+ case L_FRAME8k:
+ delta = 1;
+ move16();
+ pt_cos= sin_switch_8;
+ BREAK;
+ case L_FRAME16k:
+ delta = 2;
+ move16();
+ pt_cos= sin_switch_16;
+ BREAK;
+ case L_FRAME32k:
+ delta = 4;
+ move16();
+ pt_cos= sin_switch_32;
+ BREAK;
+ default :
+ delta = 6;
+ move16();
+ pt_cos= sin_switch_48;
+ BREAK;
+ }
+
+ /* set switching frame bitrate */
+ IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME))
+ {
+ IF( GT_32(st_fx->core_brate_fx, ACELP_24k40))
+ {
+ cbrate = L_add(ACELP_24k40, 0);
+ }
+ ELSE
+ {
+ cbrate = L_add(st_fx->core_brate_fx, 0);
+ }
+
+ /* subtract ACELP switching frame bits */
+ IF( GE_32(st_fx->core_brate_fx, ACELP_11k60))
+ {
+ (*num_bits) = sub((*num_bits), 1); /* LP_FLAG bit */
+ }
+ *num_bits = sub( (*num_bits), ACB_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, GENERIC, 0, 0)] ); /* pitch bits*/
+ *num_bits = sub( (*num_bits), gain_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, TRANSITION, 0, 0)] ); /* gain bits */
+ *num_bits = sub( (*num_bits), FCB_bits_tbl[BIT_ALLOC_IDX_fx(cbrate, GENERIC, 0, 0)] ); /* FCB bits */
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ IF( LE_32(st_fx->core_brate_fx, ACELP_8k00))
+ {
+ cbrate = L_add(ACELP_8k00, 0);
+ }
+ ELSE IF( LE_32(st_fx->core_brate_fx, ACELP_14k80))
+ {
+ cbrate = L_add(ACELP_14k80, 0);
+ }
+ ELSE
+ {
+ cbrate = L_min(st_fx->core_brate_fx, ACELP_22k60);
+ }
+
+ /* subtract ACELP switching frame bits */
+ IF( GE_32(st_fx->core_brate_fx, ACELP_11k60))
+ {
+ (*num_bits) = sub((*num_bits), 1); /* LP_FLAG bit */
+ }
+ *num_bits = sub((*num_bits), ACB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* pitch bits*/
+ *num_bits = sub((*num_bits), gain_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* gain bits */
+ *num_bits = sub((*num_bits), FCB_bits_16kHz_tbl[BIT_ALLOC_IDX_16KHZ_fx(cbrate, GENERIC, 0, 0)]); /* FCB bits */
+ }
+
+ /* subtract BWE bits */
+ test();
+ test();
+ IF( !( ( EQ_16(inner_frame_tbl[st_fx->bwidth_fx], L_FRAME16k)&&EQ_16(st_fx->last_L_frame_fx,L_FRAME16k))||EQ_16(inner_frame_tbl[st_fx->bwidth_fx],L_FRAME8k)))
+ {
+ *num_bits = sub((*num_bits), (NOOFGAINBITS1 + AUDIODELAYBITS));
+ }
+
+ /* Transition window at the encoder */
+ n=i_mult2(N_ZERO_8,delta);
+ Loverlapp=i_mult2(SWITCH_OVERLAP_8k,delta);
+ /*Overflow=0; */
+
+ pt_32 = wtda_audio+shr(input_frame,1);
+ pt_16 = audio+sub(n,1);
+ tmp16 = sub(shr(input_frame,1),Loverlapp);
+
+ FOR( i = 0; i < tmp16; i++ )
+ {
+ /* wtda_audio[i+input_frame/2] = - audio[n-i-1]; */
+ *pt_32++=L_negate(L_shr(L_deposit_h(*pt_16--),1)); /* Q +16 -1 */
+ }
+
+ pt_cos = pt_cos + Loverlapp - 1;
+ FOR( i = tmp16; i < shr(input_frame,1); i++ )
+ {
+ /* *pt_32++ = - audio[n-i-1] *(float)cos((i+1-input_frame/2+Loverlapp)*EVS_PI/(2*(Loverlapp+1))); win=cos() */
+ *pt_32++=L_negate(L_mult0(*pt_16--,*pt_cos--));
+ }
+
+ IF(hTcxEnc != NULL)
+ {
+ /* reset state of old_out if switching */
+ set16_fx(hTcxEnc->old_out_fx, 0, L_FRAME32k);
+ }
+ return;
+}
diff --git a/lib_enc/corr_xh_fx.c b/lib_enc/corr_xh_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..ead9e753a610eb58f284e6b87bcdab6b8af235a1
--- /dev/null
+++ b/lib_enc/corr_xh_fx.c
@@ -0,0 +1,83 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h"
+#include "cnst.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * local constants
+ * -----------------------------------------------------------------*/
+
+#define NB_TRACK 4
+#define STEP NB_TRACK
+
+/*-------------------------------------------------------------------*
+ * corr_xh_fx:
+ *
+ * Compute the correlation between the target signal and the impulse
+ * response of the weighted synthesis filter.
+ *
+ * y[i]=sum(j=i,l-1) x[j]*h[j-i], i=0,l-1
+ *-------------------------------------------------------------------*/
+void corr_xh_fx(
+ const Word16 x[], /* i : target signal */
+ Word16 dn[], /* o : correlation between x[] and h[] */
+ const Word16 h[] /* i : impulse response (of weighted synthesis filter) */
+)
+{
+ Word16 i, j, k;
+ Word32 L_tmp, y32[L_SUBFR], L_maxloc, L_tot;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /* first keep the result on 32 bits and find absolute maximum */
+ L_tot = L_deposit_l(1);
+
+ FOR (k = 0; k < NB_TRACK; k++)
+ {
+ L_maxloc = L_deposit_l(0);
+ FOR (i = k; i < L_SUBFR; i += STEP)
+ {
+ L_tmp = L_mac(1L, x[i], h[0]); /* 1 -> to avoid null dn[] */
+ FOR (j = i; j < L_SUBFR-1; j++)
+ {
+#ifdef BASOP_NOGLOB
+ L_tmp = L_mac_o(L_tmp, x[j+1], h[j+1 - i], &Overflow);
+#else
+ L_tmp = L_mac(L_tmp, x[j+1], h[j+1 - i]);
+#endif
+ }
+
+ y32[i] = L_tmp;
+ move32();
+ L_tmp = L_abs(L_tmp);
+ L_maxloc = L_max(L_tmp, L_maxloc);
+ }
+ /* tot += 3*max / 8 */
+ L_maxloc = L_shr(L_maxloc, 2);
+#ifdef BASOP_NOGLOB
+ L_tot = L_add_o(L_tot, L_maxloc, &Overflow); /* +max/4 */
+ L_tot = L_add_o(L_tot, L_shr(L_maxloc, 1), &Overflow); /* +max/8 */
+#else
+ L_tot = L_add(L_tot, L_maxloc); /* +max/4 */
+ L_tot = L_add(L_tot, L_shr(L_maxloc, 1)); /* +max/8 */
+#endif
+ }
+
+ /* Find the number of right shifts to do on y32[] so that */
+ /* 6.0 x sumation of max of dn[] in each track not saturate. */
+
+ j = sub(norm_l(L_tot), 4); /* 4 -> 16 x tot */
+
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ dn[i] = round_fx(L_shl(y32[i], j));
+ }
+ return;
+}
diff --git a/lib_enc/decision_matrix_enc_fx.c b/lib_enc/decision_matrix_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ceddcdaefdf981cb32c9d1ec0cc47fd5fce41ed
--- /dev/null
+++ b/lib_enc/decision_matrix_enc_fx.c
@@ -0,0 +1,791 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h"
+#include "stat_enc.h"
+#include "rom_com_fx.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+
+/*-----------------------------------------------------------------*
+ * decision_matrix_enc()
+ *
+ * Select operating point (combination of technologies) based on input signal properties and command-line parameters:
+ *
+ * 7.20 8.00 9.60 13.20 16.40 24.40 32 48 64 96 128
+ * Mode 1 1 2 1 2 2 2 2 1 2 2
+ * ----------------------------------------------------------------------------------------------------------------------------------------------------------------
+ * NB
+ * speech ACELP@12k8 ACELP@12k8 ACELP@12k8 ACELP@12k8
+ * audio LR MDCT LR MDCT TCX LR MDCT
+ * inactive GSC@12k8 GSC@12k8 TCX GSC@12k8
+ * ----------------------------------------------------------------------------------------------------------------------------------------------------------------
+ * WB
+ * speech ACELP@12k8 ACELP@12k8 ACELP@12k8 ACELP@12k8 ACELP@16k ACELP@16k ACELP@16k TCX ACELP@16k TCX TCX
+ * +0b WB BWE +0b WB BWE +TD WB BWE +TD WB BWE
+ * audio GSC@12k8 GSC@12k8 TCX LR MDCT TCX TCX HQ TCX HQ TCX TCX
+ * +0b WB BWE +0b WB BWE +IGF
+ * inactive GSC@12k8 GSC@12k8 TCX GSC@12k8 TCX TCX AVQ@16k TCX AVQ@16k TCX TCX
+ * +0b WB BWE +0b WB BWE +IGF +FD WB BWE
+ * ----------------------------------------------------------------------------------------------------------------------------------------------------------------
+ * SWB
+ * speech ACELP@12k8 ACELP@16k ACELP@16k ACELP@16k TCX ACELP@16k TCX TCX
+ * +TD SWB BWE +TD SWB BWE +TD SWB BWE +TD SWB BWE +IGF +HR SWB BWE
+ * audio LR MDCT/GSC TCX TCX HQ TCX HQ TCX TCX
+ * +FD SWB BWE +IGF +IGF +FD SWB BWE +IGF
+ * inactive GSC@12k8 TCX TCX AVQ@16k TCX AVQ@16k TCX TCX
+ * +FD SWB BWE +IGF +IGF +FD SWB BWE +IGF +HR SWB BWE
+ * ----------------------------------------------------------------------------------------------------------------------------------------------------------------
+ * FB
+ * speech ACELP@16k ACELP@16k ACELP@16k TCX ACELP@16k TCX TCX
+ * +TD FB BWE +TD FB BWE +TD FB BWE +IGF +HR FB BWE
+ * audio TCX TCX HQ TCX HQ TCX TCX
+ * +IGF +IGF +FD FB BWE +IGF
+ * inactive TCX TCX AVQ@16k TCX AVQ@16k TCX TCX
+ * +IGF +IGF +FD FB BWE +IGF +HR FB BWE
+ * ---------------------------------------------------------------------------------------------------------------------------------------------------------------
+ *
+ * Note: the GSC technology is part of the ACELP core as AUDIO st_fx->coder_type (it is used also at 13.2 and 16.4 kbps for SWB unvoiced noisy speech)
+ * Note2: FB processing is optional and is activated via "-band FB" option on the encoder command line
+ * Note3: NB (0-4kHz), WB (0-8kHz), SWB (0-16kHz), FB (0-20kHz)
+ *
+ * Signalling of modes (x marks a mode that must be signalled in the bitstream)
+ *
+ * 7.20 8.00 9.6 13.2 16.4 24.4 32 48 64
+ * NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB NB WB SWB FB
+ * GC, 12k8 x x x x x x x x x x x x x
+ * UC, 12k8 x x x x x x
+ * VC, 12k8 x x x x x x x x x x x x x
+ * TC, 12k8 x x x x x x x x x x x x x
+ * GC, 16k x x x x x x x x x x x x
+ * TC, 16k x x x x x x x x x x x x
+ * AC(GSC) x x x x x x x x x x x x x
+ * IC x x x x x x x x x x x x x x x x x x x x x x x x x
+ *
+ * GC, 12k8, FS x x x x x x x x x x x x x
+ * GC, 16k, FS x x x x x x x x x x x
+ * VC, 12k8, FS x x x x x x x
+ * TC, 12k8, FS x
+ * TC, 16k, FS x x x x x x x x x x x
+ *
+ * LR MDCT x x x x x x x x x x x
+ *
+ *-----------------------------------------------------------------*/
+
+void decision_matrix_enc_fx(
+ Encoder_State_fx *st_fx, /* i : encoder state structure */
+ Word16 *hq_core_type /* o : HQ core type */
+)
+{
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+
+ /* initialization */
+ st_fx->core_fx = -1;
+ move16();
+ st_fx->extl_fx = -1;
+ move16();
+ st_fx->extl_brate_fx = 0;
+ move16();
+ *hq_core_type = -1;
+ move16();
+ st_fx->igf = 0;
+ move16();
+ /* SID and FRAME_NO_DATA frames */
+ test();
+ test();
+ IF( st_fx->Opt_DTX_ON_fx && (EQ_32(st_fx->core_brate_fx,SID_2k40)||EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)))
+ {
+ st_fx->core_fx = ACELP_CORE;
+ move16();
+
+ test();
+ if( GE_32(st_fx->input_Fs_fx,32000)&&GE_16(st_fx->bwidth_fx,SWB))
+ {
+ st_fx->extl_fx = SWB_CNG;
+ move16();
+ }
+
+ st_fx->rf_mode = 0;
+ move16();
+
+ return;
+ }
+
+ st_fx->core_brate_fx = L_deposit_l(0);
+
+ /* SC-VBR */
+ IF ( st_fx->Opt_SC_VBR_fx )
+ {
+ /* SC-VBR */
+ st_fx->core_fx = ACELP_CORE;
+ move16();
+ st_fx->core_brate_fx = ACELP_7k20;
+ move32();
+ st_fx->total_brate_fx = ACELP_7k20;
+ move32();
+
+ test();
+ test();
+ test();
+ IF ( EQ_16(hSC_VBR->ppp_mode,1))
+ {
+ /* PPP mode */
+ st_fx->core_brate_fx = PPP_NELP_2k80;
+ move16();
+ }
+ ELSE IF ( ( ( EQ_16(st_fx->coder_type,UNVOICED)||EQ_16(st_fx->coder_type,TRANSITION))&&st_fx->sp_aud_decision1==0)||NE_16(st_fx->bwidth_fx,NB))
+ {
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF ( EQ_16(st_fx->coder_type,UNVOICED)&&EQ_16(st_fx->vad_flag,1)&&
+ ( ( GE_16(st_fx->last_bwidth_fx,SWB) && st_fx->last_Opt_SC_VBR_fx == 1 ) || LT_16(st_fx->last_bwidth_fx, SWB) ) &&
+ ( NE_16(st_fx->last_core_fx,HQ_CORE) || NE_16(st_fx->bwidth_fx, NB) ) )
+ {
+ /* NELP mode */
+ hSC_VBR->nelp_mode = 1;
+ move16();
+ st_fx->core_brate_fx = PPP_NELP_2k80;
+ move32();
+ }
+ ELSE IF ( EQ_16(st_fx->coder_type,TRANSITION)||(EQ_16(st_fx->coder_type,UNVOICED)&&NE_16(hSC_VBR->nelp_mode,1))||
+ ( ( EQ_16(st_fx->coder_type,AUDIO) || EQ_16(st_fx->coder_type,INACTIVE) ) && NE_16(st_fx->bwidth_fx, NB) ) )
+
+ {
+ /* silence portions */
+ st_fx->core_brate_fx = ACELP_8k00;
+ move32();
+ st_fx->total_brate_fx = ACELP_8k00;
+ move32();
+ }
+ }
+
+ return;
+ }
+
+ /*---------------------------------------------------------------------*
+ * NB
+ *---------------------------------------------------------------------*/
+
+ ELSE IF ( EQ_16(st_fx->bwidth_fx,NB))
+ {
+ st_fx->core_fx = ACELP_CORE;
+ move16();
+
+ test();
+ if ( GE_32(st_fx->total_brate_fx,HQCORE_NB_MIN_RATE)&&EQ_16(st_fx->sp_aud_decision1,1))
+ {
+ st_fx->core_fx = HQ_CORE;
+ move16();
+ }
+ }
+
+ /*---------------------------------------------------------------------*
+ * WB
+ *---------------------------------------------------------------------*/
+
+ ELSE IF ( EQ_16(st_fx->bwidth_fx,WB))
+ {
+ st_fx->core_fx = ACELP_CORE;
+ move16();
+
+ test();
+ test();
+ IF ( ( GE_32(st_fx->total_brate_fx,HQCORE_WB_MIN_RATE)&&EQ_16(st_fx->sp_aud_decision1,1))||
+ GE_32(st_fx->total_brate_fx,HQ_96k) )
+ {
+ st_fx->core_fx = HQ_CORE;
+ move16();
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ test();
+ IF ( EQ_16(st_fx->bwidth_fx,WB)&<_32(st_fx->total_brate_fx,ACELP_9k60))
+ {
+ st_fx->extl_fx = WB_BWE;
+ move16();
+ }
+ ELSE IF ( EQ_16(st_fx->bwidth_fx,WB)&&GE_32(st_fx->total_brate_fx,ACELP_9k60)&&LE_32(st_fx->total_brate_fx,ACELP_16k40))
+ {
+ /* Note: WB BWE is used exceptionally at 13.2 kbps if GSC is selected instead of LR-MDCT */
+ test();
+ test();
+ test();
+ IF ( EQ_16(st_fx->sp_aud_decision1,1)||EQ_16(st_fx->coder_type,INACTIVE)||(st_fx->sp_aud_decision1==0&&EQ_16(st_fx->sp_aud_decision2,1)))
+ {
+ st_fx->extl_fx = WB_BWE;
+ move16();
+ st_fx->extl_brate_fx = WB_BWE_0k35;
+ move32();
+ }
+ ELSE
+ {
+ st_fx->extl_fx = WB_TBE;
+ move16();
+ st_fx->extl_brate_fx = WB_TBE_1k05;
+ move32();
+ }
+ }
+ }
+ }
+
+ /*---------------------------------------------------------------------*
+ * SWB and FB
+ *---------------------------------------------------------------------*/
+
+ ELSE IF ( EQ_16(st_fx->bwidth_fx,SWB)||EQ_16(st_fx->bwidth_fx,FB))
+ {
+ test();
+ test();
+ IF ( ( GE_32(st_fx->total_brate_fx,HQCORE_SWB_MIN_RATE)&&EQ_16(st_fx->sp_aud_decision1,1))||
+ GE_32(st_fx->total_brate_fx,HQ_96k) )
+ {
+ st_fx->core_fx = HQ_CORE;
+ move16();
+ }
+ ELSE
+ {
+ st_fx->core_fx = ACELP_CORE;
+ move16();
+
+ test();
+ test();
+ IF ( GE_32(st_fx->total_brate_fx,ACELP_13k20)&<_32(st_fx->total_brate_fx,ACELP_48k))
+ {
+ /* Note: SWB BWE is not used in case of GSC noisy speech */
+ /* Note: SWB BWE is used exceptionally at 13.2 kbps if GSC is selected instead of LR-MDCT */
+ test();
+ test();
+ test();
+ test();
+ IF ( (EQ_16(st_fx->sp_aud_decision1,1)||EQ_16(st_fx->coder_type,INACTIVE)||(st_fx->sp_aud_decision1==0&&EQ_16(st_fx->sp_aud_decision2,1)))&&st_fx->GSC_noisy_speech_fx==0)
+ {
+ st_fx->extl_fx = SWB_BWE;
+ move16();
+ st_fx->extl_brate_fx = SWB_BWE_1k6;
+ move32();
+
+ test();
+ IF ( EQ_16(st_fx->bwidth_fx,FB)&&GE_32(st_fx->total_brate_fx,ACELP_24k40))
+ {
+ st_fx->extl_fx = FB_BWE;
+ move16();
+ st_fx->extl_brate_fx = FB_BWE_1k8;
+ move32();
+ }
+ }
+ ELSE
+ {
+ st_fx->extl_fx = SWB_TBE;
+ move16();
+ st_fx->extl_brate_fx = SWB_TBE_1k6;
+ move32();
+ if( GE_32(st_fx->total_brate_fx,ACELP_24k40))
+ {
+ st_fx->extl_brate_fx = SWB_TBE_2k8;
+ move32();
+ }
+
+ test();
+ IF ( EQ_16(st_fx->bwidth_fx,FB)&&GE_32(st_fx->total_brate_fx,ACELP_24k40))
+ {
+ st_fx->extl_fx = FB_TBE;
+ move16();
+ {
+ st_fx->extl_brate_fx = FB_TBE_3k0;
+ move32();
+ }
+ }
+ }
+ }
+ ELSE IF ( GE_32(st_fx->total_brate_fx,ACELP_48k))
+ {
+ st_fx->extl_fx = SWB_BWE_HIGHRATE;
+ move16();
+ st_fx->extl_brate_fx = SWB_BWE_16k;
+ move32();
+
+ if( EQ_16(st_fx->bwidth_fx,FB))
+ {
+ st_fx->extl_fx = FB_BWE_HIGHRATE;
+ move32();
+ }
+ }
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Set HQ core type
+ *-----------------------------------------------------------------*/
+
+ IF( EQ_16(st_fx->core_fx,HQ_CORE))
+ {
+ *hq_core_type = NORMAL_HQ_CORE;
+ move16();
+
+ test();
+ test();
+ IF( (EQ_16(st_fx->bwidth_fx,SWB)||EQ_16(st_fx->bwidth_fx,WB))&&LE_32(st_fx->total_brate_fx,LRMDCT_CROSSOVER_POINT))
+ {
+ /* note that FB (bitrate >= 24400 bps) is always coded with NORMAL_HQ_CORE */
+ *hq_core_type = LOW_RATE_HQ_CORE;
+ move16();
+ }
+ ELSE IF( EQ_16(st_fx->bwidth_fx,NB))
+ {
+ *hq_core_type = LOW_RATE_HQ_CORE;
+ move16();
+ }
+ }
+
+ /* set core bitrate */
+ st_fx->core_brate_fx = L_sub(st_fx->total_brate_fx, st_fx->extl_brate_fx);
+
+ IF ( st_fx->ini_frame_fx == 0 )
+ {
+ /* avoid switching in the very first frame */
+ st_fx->last_core_fx = st_fx->core_fx;
+ move16();
+ st_fx->last_core_brate_fx = st_fx->core_brate_fx;
+ move32();
+ st_fx->last_extl_fx = st_fx->extl_fx;
+ move16();
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * signalling_mode1_tcx20_enc()
+ *
+ * write MODE1 TCX20 signalling information into the bitstream
+ *---------------------------------------------------------------------*/
+
+Word16 signalling_mode1_tcx20_enc(
+ Encoder_State_fx *st, /* i : encoder state structure */
+ Word16 push
+)
+{
+ Word16 num_bits;
+ Word16 nBits, idx, start_idx;
+ BSTR_ENC_HANDLE hBstr;
+
+ hBstr = st->hBstr;
+ assert(st->core_fx == TCX_20_CORE);
+
+ num_bits = 0;
+ move16();
+
+ /* Use ACELP signaling for LR MDCT */
+ IF ( LE_32(st->total_brate_fx, ACELP_16k40))
+ {
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ idx = 0;
+ move16();
+ WHILE ( NE_32(acelp_sig_tbl[idx], st->total_brate_fx))
+ {
+ idx = add(idx, 1);
+ }
+
+ /* retrieve the number of bits for signalling */
+ idx = add(idx, 1);
+ nBits = extract_l(acelp_sig_tbl[idx]);
+
+ /* retrieve the signalling index */
+ idx = add(idx, 1);
+ start_idx = idx;
+ move16();
+ WHILE ( NE_32(acelp_sig_tbl[idx], SIG2IND_fx(LR_MDCT, st->bwidth_fx, 0, 0)))
+ {
+ idx = add(idx, 1);
+ }
+
+ num_bits = add(num_bits, nBits);
+ IF (push != 0)
+ {
+ push_indice_fx(hBstr, IND_ACELP_SIGNALLING, sub(idx, start_idx), nBits );
+ }
+
+ /* HQ/TCX core switching flag */
+ num_bits = add(num_bits, 1);
+ IF (push != 0)
+ {
+ push_indice_fx(hBstr, IND_MDCT_CORE, 1, 1 );
+ }
+ }
+ ELSE
+ {
+ IF ( LE_32(st->core_brate_fx, ACELP_64k))
+ {
+ /* write ACELP/HQ core indication flag */
+ num_bits = add(num_bits, 1);
+ IF (push != 0)
+ {
+ push_indice_fx(hBstr, IND_CORE, 1, 1 );
+ }
+ }
+
+ /* HQ/TCX core switching flag */
+ num_bits = add(num_bits, 1);
+ IF (push != 0)
+ {
+ push_indice_fx(hBstr, IND_MDCT_CORE, 1, 1 );
+ }
+
+ num_bits = add(num_bits, 2);
+ IF (push != 0)
+ {
+ /* write band-width (needed for different I/O sampling rate support) */
+ IF ( EQ_16(st->bwidth_fx, NB))
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 0, 2 );
+ }
+ ELSE IF ( EQ_16(st->bwidth_fx, WB))
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 1, 2 );
+ }
+ ELSE IF ( EQ_16(st->bwidth_fx, SWB))
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 2, 2 );
+ }
+ ELSE /* st->bwidth == FB */
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 3, 2 );
+ }
+ }
+ }
+
+ return num_bits;
+}
+
+/*---------------------------------------------------------------------*
+ * signalling_enc()
+ *
+ * write signalling information into the bit-stream
+ *---------------------------------------------------------------------*/
+
+void signalling_enc_fx(
+ Encoder_State_fx *st_fx /* i : encoder state structure */
+)
+{
+ Word16 nBits, idx, start_idx;
+ Word32 k, total_brate_temp;
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ BSTR_ENC_HANDLE hBstr;
+
+ hBstr = st_fx->hBstr;
+
+ IF (EQ_16(st_fx->mdct_sw, MODE2))
+ {
+
+ assert(!st_fx->tcxonly);
+ assert(st_fx->core_fx == HQ_CORE);
+
+ push_next_indice_fx(hBstr, 1, 1); /* TCX */
+ push_next_indice_fx(hBstr, 1, 1); /* HQ_CORE */
+
+ /* write ACELP->HQ core switching flag */
+ test();
+ IF ( EQ_16(st_fx->last_core_fx, ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))
+ {
+ push_indice_fx(hBstr, IND_HQ_SWITCHING_FLG, 1, 1 );
+
+ /* write ACELP L_frame info */
+ IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME))
+ {
+ push_indice_fx(hBstr, IND_LAST_L_FRAME, 0, 1 );
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_LAST_L_FRAME, 1, 1 );
+ }
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_HQ_SWITCHING_FLG, 0, 1 );
+ }
+
+ return;
+ }
+ IF( EQ_16(st_fx->core_fx,ACELP_CORE ))
+ {
+ Word16 ppp_mode, nelp_mode, sig;
+
+ ppp_mode = 0;
+ nelp_mode = 0;
+ move16(); move16();
+ IF(st_fx->Opt_SC_VBR_fx)
+ {
+ ppp_mode = hSC_VBR->ppp_mode;
+ nelp_mode = hSC_VBR->nelp_mode;
+ move16(); move16();
+ }
+
+ test();
+ test();
+ IF( EQ_16(ppp_mode,1) || EQ_16(nelp_mode,1))
+ {
+ /* 1 bit to distinguish between 2.8kbps PPP/NELP frame and SID frame */
+ push_indice_fx(hBstr, IND_CORE, 0, 1 );
+ /* SC-VBR: 0 - PPP_NB, 1 - PPP_WB, 2 - NELP_NB, 3 - NELP_WB */
+ test();test();test();test();test();test();test();test();
+ IF ( EQ_16(st_fx->coder_type,VOICED)&&EQ_16(st_fx->bwidth_fx,NB)&&EQ_16(ppp_mode,1))
+ {
+ push_indice_fx(hBstr, IND_PPP_NELP_MODE, 0, 2 );
+ }
+ ELSE IF ( EQ_16(st_fx->coder_type,VOICED)&&NE_16(st_fx->bwidth_fx,NB)&&EQ_16(ppp_mode,1))
+ {
+ push_indice_fx(hBstr, IND_PPP_NELP_MODE, 1, 2 );
+ }
+ ELSE IF ( EQ_16(st_fx->coder_type,UNVOICED)&&EQ_16(st_fx->bwidth_fx,NB)&&EQ_16(nelp_mode,1))
+ {
+ push_indice_fx(hBstr, IND_PPP_NELP_MODE, 2, 2);
+ }
+ ELSE IF ( EQ_16(st_fx->coder_type,UNVOICED)&&NE_16(st_fx->bwidth_fx,NB)&&EQ_16(nelp_mode,1))
+ {
+ push_indice_fx(hBstr, IND_PPP_NELP_MODE, 3, 2 );
+ }
+ }
+ ELSE IF( NE_32(st_fx->core_brate_fx,SID_2k40)&&NE_32(st_fx->core_brate_fx,FRAME_NO_DATA))
+ {
+ /* write the ACELP/HQ core selection bit */
+ IF (GE_32(st_fx->total_brate_fx,ACELP_24k40))
+ {
+ push_indice_fx(hBstr, IND_CORE, 0, 1 );
+ }
+
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ idx = 0;
+ move16();
+ WHILE (LT_16(idx, MAX_ACELP_SIG))
+ {
+ IF (LE_32(st_fx->total_brate_fx, brate_tbl[idx]))
+ {
+ BREAK;
+ }
+ idx++;
+ }
+ total_brate_temp = brate_tbl[idx];
+ move32();
+
+ idx = 0;
+ move16();
+ WHILE ( NE_32(acelp_sig_tbl[idx], total_brate_temp))
+ {
+ idx++;
+ }
+
+ /* retrieve the number of bits for signalling */
+ nBits = (Word16)acelp_sig_tbl[++idx];
+ move16();
+
+ /* retrieve the signalling index */
+#if 0
+ start_idx = ++idx;
+ k = SIG2IND_fx(st_fx->coder_type, st_fx->bwidth_fx, st_fx->sharpFlag, st_fx->rf_mode);
+ WHILE( NE_32(acelp_sig_tbl[idx], k))
+#else
+ start_idx = ++idx;
+ move16();
+ IF (EQ_16(st_fx->element_mode, IVAS_CPE_TD) && EQ_16(st_fx->bwidth_fx, SWB) && LE_32(st_fx->total_brate_fx, ACELP_9k60))
+ {
+ /* patch to signal SWB as NB in Stereo */
+ sig = (Word16)SIG2IND(st_fx->coder_type, NB, st_fx->sharpFlag, st_fx->rf_mode);
+ }
+ ELSE
+ {
+ sig = (Word16)SIG2IND(st_fx->coder_type, st_fx->bwidth_fx, st_fx->sharpFlag, st_fx->rf_mode);
+ }
+
+ WHILE (NE_16((Word16)acelp_sig_tbl[idx] , sig))
+#endif
+ {
+ idx++;
+ }
+
+ push_indice_fx(hBstr, IND_ACELP_SIGNALLING, idx - start_idx, nBits );
+ }
+
+ /* write extension layer flag to distinguish between TBE (0) and BWE (1) */
+ IF( st_fx->extl_brate_fx > 0 )
+ {
+ test();
+ test();
+ test();
+ test();
+ IF( EQ_16(st_fx->extl_fx,WB_TBE)||EQ_16(st_fx->extl_fx,SWB_TBE)||EQ_16(st_fx->extl_fx,FB_TBE))
+ {
+ push_indice_fx(hBstr, IND_BWE_FLAG, 0, 1 );
+ }
+ ELSE IF( EQ_16(st_fx->extl_fx,WB_BWE)||EQ_16(st_fx->extl_fx,SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE))
+ {
+ push_indice_fx(hBstr, IND_BWE_FLAG, 1, 1 );
+ }
+ }
+ }
+ ELSE /* HQ core */
+ {
+ /* write ACELP->HQ switching frame flag */
+ test();
+ IF( EQ_16(st_fx->last_core_fx,ACELP_CORE)||EQ_16(st_fx->last_core_fx,AMR_WB_CORE))
+ {
+ push_indice_fx(hBstr, IND_HQ_SWITCHING_FLG, 1, 1 );
+ /* write ACELP L_frame info */
+ IF( EQ_16(st_fx->last_L_frame_fx, L_FRAME))
+ {
+ push_indice_fx(hBstr, IND_LAST_L_FRAME, 0, 1 );
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_LAST_L_FRAME, 1, 1 );
+ }
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_HQ_SWITCHING_FLG, 0, 1 );
+ }
+
+ /* HQ/TCX core switching flag */
+ push_indice_fx(hBstr, IND_MDCT_CORE, 0, 1 );
+
+ /* Use ACELP signaling for LR MDCT */
+ IF ( LE_32(st_fx->total_brate_fx,ACELP_16k40))
+ {
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ idx = 0;
+ WHILE ( NE_32(acelp_sig_tbl[idx],st_fx->total_brate_fx))
+ {
+ idx++;
+ }
+
+ /* retrieve the number of bits for signalling */
+ nBits = extract_l(acelp_sig_tbl[++idx]);
+
+ /* retrieve the signalling index */
+ start_idx = ++idx;
+ move16();
+ k = SIG2IND_fx(LR_MDCT, st_fx->bwidth_fx, 0, 0);
+ WHILE( NE_32(acelp_sig_tbl[idx], k))
+ {
+ idx++;
+ }
+
+ push_indice_fx(hBstr, IND_ACELP_SIGNALLING, idx - start_idx, nBits );
+ }
+ ELSE
+ {
+
+ IF( LE_32(st_fx->core_brate_fx,ACELP_64k))
+ {
+ /* write ACELP/HQ core indication flag */
+ push_indice_fx(hBstr, IND_CORE, 1, 1 );
+ }
+
+ /* write band-width (needed for different I/O sampling rate support) */
+ IF( EQ_16(st_fx->bwidth_fx,NB))
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 0, 2 );
+ }
+ ELSE IF( EQ_16(st_fx->bwidth_fx,WB))
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 1, 2 );
+ }
+ ELSE IF( EQ_16(st_fx->bwidth_fx,SWB))
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 2, 2 );
+ }
+ ELSE /* st_fx->bwidth_fx == FB */
+ {
+ push_indice_fx(hBstr, IND_HQ_BWIDTH, 3, 2 );
+ }
+ }
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * signalling_enc_rf()
+ *
+ * write channel-aware signalling information into the bitstream
+ *---------------------------------------------------------------------*/
+
+void signalling_enc_rf(
+ Encoder_State_fx *st /* i : encoder state structure */
+)
+{
+ Word16 i;
+ Word16 sfr;
+ RF_ENC_HANDLE hRF = st->hRF;
+
+ /* write partial copy into bitstream */
+ IF(EQ_16(st->rf_mode,1))
+ {
+ enc_prm_rf_fx(st, hRF->rf_indx_frametype[st->rf_fec_offset], st->rf_fec_offset);
+ hRF->rf_indx_tbeGainFr[0] = hRF->RF_bwe_gainFr_ind;
+ }
+
+ /* Shift the RF indices such that the partial copy associated with
+ (n-fec_offset)th frame is included in the bitstream in nth frame. */
+
+ FOR(i = st->rf_fec_offset; i >= 0 ; i--)
+ {
+ /* rf frame type */
+ hRF->rf_indx_frametype[i+1] = hRF->rf_indx_frametype[i];
+ /* rf target bits buffer */
+ hRF->rf_targetbits_buff[i+1] = hRF->rf_targetbits_buff[i];
+
+ /* lsf indx */
+ hRF->rf_indx_lsf[i+1][0] = hRF->rf_indx_lsf[i][0];
+ hRF->rf_indx_lsf[i+1][1] = hRF->rf_indx_lsf[i][1];
+ hRF->rf_indx_lsf[i+1][2] = hRF->rf_indx_lsf[i][2];
+
+ /* ES pred energy */
+ hRF->rf_indx_EsPred[i+1] = hRF->rf_indx_EsPred[i];
+
+ /* LTF mode, sfr params: pitch, fcb and gain */
+ FOR(sfr = 0; sfr < st->nb_subfr; sfr++)
+ {
+ hRF->rf_indx_ltfMode[i+1][sfr] = hRF->rf_indx_ltfMode[i][sfr];
+ hRF->rf_indx_pitch[i+1][sfr] = hRF->rf_indx_pitch[i][sfr];
+ hRF->rf_indx_fcb[i+1][sfr] = hRF->rf_indx_fcb[i][sfr];
+ hRF->rf_indx_gain[i+1][sfr] = hRF->rf_indx_gain[i][sfr];
+ }
+
+ /* shift the nelp indices */
+ hRF->rf_indx_nelp_iG1[i+1] = hRF->rf_indx_nelp_iG1[i];
+ hRF->rf_indx_nelp_iG2[i+1][0] = hRF->rf_indx_nelp_iG2[i][0];
+ hRF->rf_indx_nelp_iG2[i+1][1] = hRF->rf_indx_nelp_iG2[i][1];
+ hRF->rf_indx_nelp_fid[i+1] = hRF->rf_indx_nelp_fid[i];
+
+ /* tbe gain Fr shift */
+ hRF->rf_indx_tbeGainFr[i+1] = hRF->rf_indx_tbeGainFr[i];
+ hRF->rf_clas[i+1] = hRF->rf_clas[i];
+ hRF->rf_gain_tcx[i+1] = hRF->rf_gain_tcx[i];
+ hRF->rf_tcxltp_param[i+1] = hRF->rf_tcxltp_param[i];
+ }
+
+ return;
+}
+
+
diff --git a/lib_enc/detect_transient_fx.c b/lib_enc/detect_transient_fx.c
index 6d3957921b08a763046f205188ae6f50c50a6f9f..b5516175c402735da55e7e5ecb8a6c1c4b638c82 100644
--- a/lib_enc/detect_transient_fx.c
+++ b/lib_enc/detect_transient_fx.c
@@ -37,7 +37,9 @@
#include "options.h" /* Compilation switches */
#include "cnst.h" /* Common constants */
#include "rom_com.h" /* Static table prototypes */
-#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
/*--------------------------------------------------------------------------*/
/* Function hp_filter */
@@ -113,7 +115,7 @@ Word16 detect_transient_fx(
const Word16 *in_fx, /*Q_new */
const Word16 L,
Word16 Q_new,
- Encoder_State *st_fx
+ Encoder_State_fx *st_fx
)
{
Word32 Energy, L_tmp;
@@ -138,9 +140,9 @@ Word16 detect_transient_fx(
IsTransient = 0;
move16();
- IF(NE_16(st_fx->last_extl, st_fx->extl))
+ IF(NE_16(st_fx->last_extl_fx, st_fx->extl_fx))
{
- st_fx->TransientHangOver = 0;
+ st_fx->TransientHangOver_fx = 0;
move16();
st_fx->old_hpfilt_in_fx = 0;
move16();
@@ -155,7 +157,7 @@ Word16 detect_transient_fx(
test();
test();
test();
- IF(NE_16(st_fx->last_extl, st_fx->extl) || (EQ_16(st_fx->last_extl, st_fx->extl) && NE_16(st_fx->last_core, st_fx->core)) || EQ_16(st_fx->last_codec_mode, MODE2))
+ IF(NE_16(st_fx->last_extl_fx, st_fx->extl_fx) || (EQ_16(st_fx->last_extl_fx, st_fx->extl_fx) && NE_16(st_fx->last_core_fx, st_fx->core_fx)) || EQ_16(st_fx->last_codec_mode, MODE2))
{
/*EnergyLT = EPSILON_FX; */
EnergyLT = L_deposit_l(0);
@@ -267,13 +269,13 @@ Word16 detect_transient_fx(
Energy = L_add(L_shr(L_tmp, shift), L_shr(L_tmp2, shift));
#endif
test();
- IF(EQ_16(st_fx->extl,SWB_BWE) || EQ_16(st_fx->extl,FB_BWE))
+ IF(EQ_16(st_fx->extl_fx,SWB_BWE) || EQ_16(st_fx->extl_fx,FB_BWE))
{
/*Calculate shift to get to Q0*/
test();
test();
IF((GT_32(Mult_32_16(Energy, shl(2427, shift)), EnergyLT)) || (GT_32(Mult_32_16(Energy,shl(3277,shift)),EnergyLT)
- && EQ_16(st_fx->core,ACELP_CORE) && EQ_16(st_fx->coder_type,INACTIVE)))
+ && EQ_16(st_fx->core_fx,ACELP_CORE) && EQ_16(st_fx->coder_type,INACTIVE)))
{
IsTransient = 1;
move16();
@@ -284,7 +286,7 @@ Word16 detect_transient_fx(
ELSE
{
test();
- IF(LE_32(st_fx->total_brate,HQ_16k40) && EQ_16(st_fx->bwidth,SWB))
+ IF(LE_32(st_fx->total_brate_fx,HQ_16k40) && EQ_16(st_fx->bwidth_fx,SWB))
{
thr = 2427;
move16();
@@ -322,8 +324,8 @@ Word16 detect_transient_fx(
test();
test();
test();
- if ((NE_16(st_fx->last_extl, SWB_BWE) && NE_16(st_fx->last_extl, SWB_TBE) && EQ_16(st_fx->extl, SWB_BWE)) ||
- (NE_16(st_fx->last_extl, FB_BWE) && NE_16(st_fx->last_extl, FB_TBE) && EQ_16(st_fx->extl, FB_BWE)))
+ if ((NE_16(st_fx->last_extl_fx, SWB_BWE) && NE_16(st_fx->last_extl_fx, SWB_TBE) && EQ_16(st_fx->extl_fx, SWB_BWE)) ||
+ (NE_16(st_fx->last_extl_fx, FB_BWE) && NE_16(st_fx->last_extl_fx, FB_TBE) && EQ_16(st_fx->extl_fx, FB_BWE)))
{
IsTransient = 0;
move16();
@@ -372,12 +374,12 @@ Word16 detect_transient_fx(
move16();
}
}
- IF(EQ_32(st_fx->core_brate, ACELP_24k40))
+ IF(EQ_32(st_fx->core_brate_fx, ACELP_24k40))
{
test();
- IF(NE_16(st_fx->last_core, HQ_CORE) || NE_32(st_fx->last_core_brate, ACELP_24k40))
+ IF(NE_16(st_fx->last_core_fx, HQ_CORE) || NE_32(st_fx->last_core_brate_fx, ACELP_24k40))
{
- st_fx->TransientHangOver = 0;
+ st_fx->TransientHangOver_fx = 0;
move16();
IsTransient = 0;
move16();
@@ -389,15 +391,15 @@ Word16 detect_transient_fx(
IF(EQ_16(position,3))
{
/* Set Hangover */
- st_fx->TransientHangOver = 1;
+ st_fx->TransientHangOver_fx = 1;
move16();
}
}
ELSE
{
- IF(st_fx->TransientHangOver)
+ IF(st_fx->TransientHangOver_fx)
{
- st_fx->TransientHangOver = 0;
+ st_fx->TransientHangOver_fx = 0;
move16();
IsTransient = 1;
move16();
@@ -409,14 +411,14 @@ Word16 detect_transient_fx(
{
IF(IsTransient)
{
- st_fx->TransientHangOver = 1;
+ st_fx->TransientHangOver_fx = 1;
move16();
}
ELSE
{
- IF(st_fx->TransientHangOver)
+ IF(st_fx->TransientHangOver_fx)
{
- st_fx->TransientHangOver = 0;
+ st_fx->TransientHangOver_fx = 0;
move16();
IsTransient = 1;
move16();
diff --git a/lib_enc/diffcod_fx.c b/lib_enc/diffcod_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..53275e2f38677aad7d2d323e8b15341a8a69498f
--- /dev/null
+++ b/lib_enc/diffcod_fx.c
@@ -0,0 +1,141 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Compilation switches */
+#include "rom_com_fx.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function Prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*--------------------------------------------------------------------------*/
+/* Function diffcod */
+/* ~~~~~~~~~~~~~~~~~ */
+/* */
+/* Differential coding for indices of quantized norms */
+/*--------------------------------------------------------------------------*/
+
+void diffcod_fx(
+ const Word16 N, /* i : number of sub-vectors */
+ Word16 *y, /* i/o: indices of quantized norms */
+ Word16 *difidx /* o : differential code */
+)
+{
+ Word16 i, k, r;
+
+ FOR (i=N-1; i>0; i--)
+ {
+ r = sub(i, 1);
+ k = sub(y[i], y[r]);
+ if ( LT_16(k, -15))
+ {
+ y[r] = add(y[i], 15);
+ move16();
+ }
+ }
+
+ FOR (i=1; i0; i--)
+ {
+ r = sub(i, 1);
+ k = sub(y[i], y[r]);
+ move16();
+ if ( LT_16(k, thr_l))
+ {
+ y[r] = sub(y[i], thr_l);
+ move16();
+ }
+ }
+
+ FOR (i=1; i
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com_fx.h"
+#include "rom_com.h"
+//#include "basop_mpy.h"
+#include
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+#define ALPHA_ENER_FAST_FX 29491 /* Fast adaptation (noise down, speech up) */
+#define ALPHA_ENER_SLOW_FX 32440 /* Fast adaptation (noise down, speech up) */
+
+#define MIN_CNT 50 /* Minimum frame number before SID interval adaptation */
+
+#define SNR_H_FX 13056 /* Estimated SNR and corresponding SID interval */
+#define SNR_L_FX 9216 /* 51dB corresponds to 25dB SNR before noise supressor */
+#define INT_H 50
+#define INT_L 8
+#define RATIO (INT_H - INT_L)/((SNR_H_FX - SNR_L_FX)/256)
+
+#define LTE_VAR_FX -1024 /* Q8, -4.0f */
+
+#define CNG_TYPE_HO 20 /* hangover for switching between CNG types */
+
+ /* _DIFF_FLOAT_FIX_ : lp_noise_fx threshold is different between float (15) and fix (5*256) */
+#define LP_NOISE_LV 5 /* LP_NOISE level */
+
+#define MAX_BRATE_DTX_EVS ACELP_24k40 /* maximum bitrate to which the default DTX is applied in EVS; otherwise DTX is applied only in silence */
+#define MAX_BRATE_DTX_IVAS IVAS_64k /* maximum bitrate to which the default DTX is applied in IVAS; otherwise DTX is applied only in silence */
+
+/*-------------------------------------------------------------------*
+ * Local function prototypes
+ *-------------------------------------------------------------------*/
+
+static void update_SID_cnt(DTX_ENC_HANDLE hDtxEnc, const Word32 core_brate, const Word16 Opt_AMR_WB);
+
+
+/*==================================================================================*/
+/* FUNCTION : dtx_fx() */
+/*----------------------------------------------------------------------------------*/
+/* PURPOSE : Discontinuous transmission operation */
+/*----------------------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ (Encoder_State_Fx) st_fx : encoder state structure */
+/* _ (Word16) vad : vad flag Q0 */
+/* _ (Word16[]) speech_fx : Pointer to the speech frame qSpeech */
+/* _ (Word16) qSpeech : speech buffer qformat value */
+/* _ (Word16*) qener : frame_ener/lt_ener_voiced/lt_ener_noise buf qformat */
+/*----------------------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16*) qener : frame_ener/lt_ener_voiced/lt_ener_noise buf qformat */
+/* _ (Encoder_State_Fx) st_fx : encoder state structure */
+/*----------------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*==================================================================================*/
+void dtx_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 vad, /* i : vad flag for DTX */
+ const Word16 speech[], /* i : Pointer to the speech frame */
+ Word16 Q_speech /* i : Q factor for speech */
+
+)
+{
+ Word16 alpha,j,i,Q_speech2;
+ Word32 L_tmp;
+ DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+
+ Word16 last_br_cng_flag, last_br_flag, br_dtx_flag;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+#ifdef IVAS_CODE
+ IF (st_fx->dtx_sce_sba != 0)
+#else
+ if (0)
+#endif
+ {
+ last_br_cng_flag = 1;
+ last_br_flag = 1;
+ br_dtx_flag = 1;
+ move16();move16();move16();
+ }
+ ELSE
+ {
+ /* _DIFF_FLOAT_FIX_ : lp_noise_fx threshold is different between float (15) and fix (5*256) */
+ last_br_cng_flag = LE_32(st_fx->last_total_brate_cng_fx, ACELP_24k40) || LT_16(st_fx->lp_noise_fx, LP_NOISE_LV *256) || (EQ_16(st_fx->element_mode, IVAS_SCE) && LE_32(st_fx->last_total_brate_cng_fx, ACELP_32k));
+
+ last_br_flag = LE_32(st_fx->last_total_brate_fx, ACELP_24k40) || LT_16(st_fx->lp_noise_fx, LP_NOISE_LV * 256) || (EQ_16(st_fx->element_mode, IVAS_SCE) && LE_32(st_fx->last_total_brate_fx, ACELP_32k));
+ br_dtx_flag = 0;
+ move16();
+ }
+ /* Initialization */
+ IF( st_fx->ini_frame_fx == 0 )
+ {
+ st_fx->active_fr_cnt_fx = CNG_TYPE_HO;
+ move16();
+
+ st_fx->cng_type_fx = FD_CNG;
+ move16();
+ test();
+ if( (EQ_16( st_fx->codec_mode, MODE1 )||st_fx->Opt_AMR_WB_fx) && EQ_16(st_fx->element_mode, IVAS_SCE) && EQ_16(st_fx->element_mode, IVAS_CPE_MDCT))
+ {
+ st_fx->cng_type_fx = LP_CNG;
+ move16();
+ }
+ }
+ test();
+ test();
+ IF( st_fx->Opt_DTX_ON_fx && vad == 0 &&
+ GT_16(st_fx->ini_frame_fx,2) && /* CNG coding starts after 2 frames */
+ st_fx->fd_cng_reset_flag == 0 &&
+ NE_16(st_fx->last_core_fx, AMR_WB_CORE) &&
+ st_fx->Opt_AMR_WB_fx == 0 )
+ {
+ test();
+ test();
+ test();
+ IF ( GT_32(st_fx->last_core_brate_fx,SID_2k40) && NE_32(st_fx->last_total_brate_cng_fx,-1) &&
+ NE_32(st_fx->last_total_brate_cng_fx,st_fx->total_brate_fx) && last_br_cng_flag)
+ {
+ st_fx->total_brate_fx = st_fx->last_total_brate_cng_fx;
+ move32();
+ test();
+ if( !(EQ_32(st_fx->total_brate_fx,ACELP_7k20)&&st_fx->Opt_SC_VBR_fx))
+ {
+ st_fx->Opt_SC_VBR_fx = 0;
+ move16();
+ }
+ st_fx->rf_mode = st_fx->last_rf_mode_cng;
+ move16();
+ st_fx->bwidth_fx = st_fx->last_bwidth_cng_fx;
+ move16();
+ st_fx->codec_mode = st_fx->last_codec_mode_cng;
+ move16();
+ }
+ test();
+ test();
+ IF ( LE_32(st_fx->last_core_brate_fx,SID_2k40) && NE_32(st_fx->last_total_brate_fx,st_fx->total_brate_fx) && last_br_flag)
+
+ {
+ st_fx->total_brate_fx = st_fx->last_total_brate_fx;
+ move32();
+ test();
+ if( !(EQ_32(st_fx->total_brate_fx,ACELP_7k20)&&st_fx->Opt_SC_VBR_fx))
+ {
+ st_fx->Opt_SC_VBR_fx = 0;
+ move16();
+ }
+
+ st_fx->Opt_RF_ON = 0;
+ move16();
+ test();
+ test();
+ test();
+ if( st_fx->rf_mode && st_fx->rf_fec_offset > 0 && EQ_32(st_fx->total_brate_fx,ACELP_13k20)&&NE_16(st_fx->bwidth_fx,NB))
+ {
+ st_fx->Opt_RF_ON = 1;
+ move16();
+ }
+ st_fx->rf_mode = st_fx->Opt_RF_ON;
+ move16();
+ st_fx->bwidth_fx = st_fx->last_bwidth_fx;
+ move32();
+ IF (GT_16(st_fx->element_mode, EVS_MONO))
+ {
+ st_fx->codec_mode = MODE1;
+ move16();
+ }
+ ELSE
+ {
+ st_fx->codec_mode = get_codec_mode(st_fx->total_brate_fx);
+ }
+ }
+ }
+
+ /*------------------------------------------------------------------------*
+ * Select SID or FRAME_NO_DATA frame if DTX is enabled
+ *------------------------------------------------------------------------*/
+#ifdef IVAS_CODE
+ if (st_fx->dtx_sce_sba == 0)
+#endif
+ {
+ br_dtx_flag = LE_32(st_fx->total_brate_fx, ACELP_24k40) || LT_16(st_fx->lp_noise_fx, LP_NOISE_LV * 256) || (EQ_16(st_fx->element_mode, IVAS_SCE) && LE_32(st_fx->total_brate_fx, ACELP_32k)) ||
+ EQ_16(st_fx->element_mode, IVAS_CPE_DFT) || (EQ_16(st_fx->element_mode, IVAS_CPE_MDCT) && (LE_32(st_fx->element_brate, IVAS_64k) || LT_16(st_fx->lp_noise_fx, LP_NOISE_LV * 256)));
+ }
+ test();
+ test();
+ test();
+ test();
+ IF( st_fx->Opt_DTX_ON_fx && vad == 0 &&
+ GT_16(st_fx->ini_frame_fx,2) && /* CNG coding starts after 2 frames */
+ br_dtx_flag &&
+ st_fx->fd_cng_reset_flag == 0 )
+ {
+ /* reset counter */
+ st_fx->active_fr_cnt_fx = 0;
+ move16();
+
+ IF( st_fx->Opt_AMR_WB_fx )
+ {
+ st_fx->last_total_brate_cng_fx = -1;
+ st_fx->last_rf_mode_cng = st_fx->rf_mode;
+ move16();
+ }
+ ELSE
+ {
+ st_fx->last_total_brate_cng_fx = st_fx->total_brate_fx;
+ st_fx->last_bwidth_cng_fx = st_fx->bwidth_fx;
+ st_fx->last_codec_mode_cng = st_fx->codec_mode;
+ }
+
+ IF(hDtxEnc->cnt_SID == 0 )
+ {
+ /* this will be a SID frame */
+ IF ( st_fx->Opt_AMR_WB_fx )
+ {
+ st_fx->core_brate_fx = SID_1k75;
+ move32();
+ }
+ ELSE
+ {
+ st_fx->core_brate_fx = SID_2k40;
+ move32();
+ }
+ }
+ ELSE
+ {
+ /* this will be a no data frame */
+ st_fx->core_brate_fx = FRAME_NO_DATA;
+ move32();
+ }
+
+ test();
+ test();
+ IF( EQ_32(st_fx->core_brate_fx,FRAME_NO_DATA)&&NE_16(st_fx->last_core_fx,ACELP_CORE)&&!st_fx->Opt_AMR_WB_fx)
+ {
+ /* force SID frame when switching from HQ core or AMR-WB IO mode into inactive frame in ACELP core when DTX is on */
+ st_fx->core_brate_fx = SID_2k40;
+ move32();
+ }
+ //PMT("dtx_sce_sba code is missing")
+#ifdef IVAS_CODE
+ IF ((NE_16(st_fx->last_core_fx, ACELP_CORE) || EQ_16(st_fx->cng_type_fx, FD_CNG)) && EQ_16(st_fx->dtx_sce_sba, 1))
+ {
+ st_fx->cng_type_fx = FD_CNG; move16();
+ if (EQ_16(st_fx->element_mode, EVS_MONO) && (EQ_32(st_fx->total_brate_fx, ACELP_9k60) || EQ_32(st_fx->total_brate_fx, ACELP_16k40) || EQ_32(st_fx->total_brate_fx, ACELP_24k40) || EQ_32(st_fx->total_brate_fx, ACELP_48k) || EQ_32(st_fx->total_brate_fx, HQ_96k) || EQ_32(st_fx->total_brate_fx, HQ_128k)))
+ {
+ st_fx->codec_mode = MODE2; move16();
+ }
+ }
+ ELSE
+#endif
+ {
+ test(); test(); test(); test();
+ IF((EQ_16(st_fx->cng_type_fx,FD_CNG) && (LE_32(st_fx->total_brate_fx,ACELP_24k40) || (NE_16(st_fx->element_mode, EVS_MONO) && LE_32(st_fx->total_brate_fx, ACELP_32k)))) || (EQ_16(st_fx->element_mode, IVAS_CPE_MDCT))) /* at highest bitrates, use exclusively LP_CNG */
+ {
+ test(); test();
+ IF(EQ_16(st_fx->element_mode, EVS_MONO) && (EQ_32(st_fx->total_brate_fx,ACELP_9k60) || EQ_32(st_fx->total_brate_fx,ACELP_16k40) || EQ_32(st_fx->total_brate_fx,ACELP_24k40)))
+ {
+ st_fx->codec_mode = MODE2;
+ move16();
+ }
+ }
+ ELSE
+ {
+ st_fx->cng_type_fx = LP_CNG;
+ move16();
+ IF(st_fx->codec_mode == MODE2)
+ {
+ hTdCngEnc->lp_cng_mode2 = 1;
+ move16();
+ }
+ st_fx->codec_mode = MODE1;
+ move16();
+ }
+ }
+
+#if 1//def IVAS_CODE
+ /* reset the bitstream (IVAS format signalling was already written) */
+ IF (NE_16(st_fx->element_mode, IVAS_CPE_MDCT) && st_fx->hBstr != NULL)
+ {
+#ifndef IVAS_CODE_BITSTREAM
+ reset_indices_enc_fx(st_fx->hBstr);
+#else
+ reset_indices_enc(st_fx->hBstr, st_fx->hBstr->nb_ind_tot);
+#endif
+ }
+#endif
+ }
+
+ /*------------------------------------------------------------------------*
+ * Reset counters when in active frame (not in SID or FRAME_NO_DATA frame)
+ *------------------------------------------------------------------------*/
+ /* NB core bit rate can be "-1" at startup , so one can not use core_brate_fx <=2400 */
+ test();
+ test();
+ IF ( (NE_32(st_fx->core_brate_fx ,SID_2k40)) && (NE_32(st_fx->core_brate_fx,SID_1k75)) && (NE_32(st_fx->core_brate_fx, FRAME_NO_DATA)))
+ {
+ IF(hDtxEnc != NULL)
+ {
+ hDtxEnc->cnt_SID = 0;
+ move16();
+
+ /* change SID update rate */
+ /* first SID update is only 8 (3) frames after the active speech end */
+ IF(!st_fx->Opt_AMR_WB_fx)
+ {
+ hDtxEnc->max_SID = FIXED_SID_RATE;
+ move16();
+ }
+ ELSE
+ {
+ hDtxEnc->max_SID = 3;
+ move16(); /* first SID update is only 3 frames after the active speech end */
+ }
+
+ IF(LT_16(hDtxEnc->interval_SID, hDtxEnc->max_SID))
+ {
+ hDtxEnc->max_SID = hDtxEnc->interval_SID;
+ move16();/* change SID update rate */
+ }
+
+ hDtxEnc->cng_cnt = 0;
+ move16(); /* reset the counter of CNG frames for averaging */
+ }
+ test();
+ IF( GE_16(st_fx->active_fr_cnt_fx,CNG_TYPE_HO) && st_fx->Opt_AMR_WB_fx==0 && NE_16(st_fx->element_mode, IVAS_CPE_MDCT))
+ {
+ IF (EQ_16(st_fx->element_mode, IVAS_SCE))
+ {
+#ifdef IVAS_CODE
+ Word16 lp_thresh, fd_thresh;
+ PMT("lp_thresh scaling is to be found")
+ test();
+ IF (st_fx->Opt_DTX_ON_fx && EQ_16(st_fx->dtx_sce_sba, 1) )
+ {
+ lp_thresh = 5.f;
+ fd_thresh = 2.f;
+ }
+ ELSE
+
+ {
+ lp_thresh = 10.f;
+ fd_thresh = 5.f;
+ }
+
+ /*More conservative selection of LP-CNG for SCE*/
+ if (st->cng_type == LP_CNG && (st->bckr_tilt_lt > lp_thresh))
+ {
+ st->cng_type = FD_CNG;
+ }
+ else if (st->cng_type == FD_CNG && (st->bckr_tilt_lt < fd_thresh) && (st->lp_noise > 2.f))
+ {
+ st->cng_type = LP_CNG;
+ }
+#endif
+ }
+ ELSE
+ {
+ test(); test(); test(); test(); test(); test(); test(); test();
+ IF(EQ_16(st_fx->cng_type_fx, LP_CNG) && ((EQ_16(st_fx->input_bwidth_fx, NB) && GT_32(st_fx->bckr_tilt_lt, 589824l/*9.f Q16*/)) || (GT_16(st_fx->input_bwidth_fx, NB) && GT_32(st_fx->bckr_tilt_lt, 2949120l/*45.f Q16*/))))
+ {
+ st_fx->cng_type_fx = FD_CNG;
+ move16();
+ }
+ ELSE IF(EQ_16(st_fx->cng_type_fx, FD_CNG) && ((EQ_16(st_fx->input_bwidth_fx, NB) && LT_32(st_fx->bckr_tilt_lt, 131072l/*2.f Q16*/)) || (GT_16(st_fx->input_bwidth_fx, NB) && LT_32(st_fx->bckr_tilt_lt, 655360l/*10.f Q16*/))))
+ {
+ st_fx->cng_type_fx = LP_CNG;
+ move16();
+ }
+ }
+ st_fx->last_total_brate_cng_fx = -1;
+ }
+ ELSE IF( st_fx->Opt_AMR_WB_fx )
+ {
+ st_fx->cng_type_fx = LP_CNG;
+ move16();
+ }
+ st_fx->active_fr_cnt_fx = add( st_fx->active_fr_cnt_fx, 1 );
+ st_fx->active_fr_cnt_fx = s_min(st_fx->active_fr_cnt_fx, 200);
+ }
+
+ /*------------------------------------------------------------------------*
+ * Update speech and background noise long-term energy
+ *------------------------------------------------------------------------*/
+ IF (hDtxEnc != NULL)
+ {
+ hDtxEnc->frame_ener_fx = L_deposit_l(0);
+
+ IF(st_fx->Opt_DTX_ON_fx)
+ {
+ Q_speech2 = add(shl(Q_speech, 1), 7);
+ FOR(j = 0; j < 16; j++)
+ {
+ L_tmp = L_mult0(*speech, *speech);
+ speech++;
+ FOR(i = 1; i < L_FRAME / 16; i++)
+ {
+#ifdef BASOP_NOGLOB
+ L_tmp = L_mac0_o(L_tmp, *speech, *speech, &Overflow);
+#else /* BASOP_NOGLOB */
+ L_tmp = L_mac0(L_tmp, *speech, *speech);
+#endif /* BASOP_NOGLOB */
+ speech++;
+ }
+ hDtxEnc->frame_ener_fx = L_add(hDtxEnc->frame_ener_fx, L_shr(L_tmp, Q_speech2));/*Q(-7) */
+ }
+
+ /* Active speech (voiced) */
+
+ IF(EQ_16(st_fx->clas_fx, VOICED_CLAS))
+ {
+ alpha = ALPHA_ENER_SLOW_FX;
+ move16();
+ if (GT_32(hDtxEnc->frame_ener_fx, hDtxEnc->lt_ener_voiced_fx))
+ {
+ alpha = ALPHA_ENER_FAST_FX;
+ move16();/*Q15 */
+ }
+
+ /*st_fx->lt_ener_voiced_fx = alpha * st_fx->lt_ener_voiced_fx + (1.0f-alpha) * st_fx->frame_ener_fx;*/
+ L_tmp = L_sub(hDtxEnc->lt_ener_voiced_fx, hDtxEnc->frame_ener_fx);
+ L_tmp = Mult_32_16(L_tmp, alpha);
+ hDtxEnc->lt_ener_voiced_fx = L_add(L_tmp, hDtxEnc->frame_ener_fx); /*Q(-7) */
+
+ hDtxEnc->VarDTX_cnt_voiced = add(hDtxEnc->VarDTX_cnt_voiced, 1);
+
+ hDtxEnc->VarDTX_cnt_voiced = s_min(hDtxEnc->VarDTX_cnt_voiced, MIN_CNT);
+ }
+ /* Background noise */
+ ELSE IF(!st_fx->Opt_AMR_WB_fx)
+ {
+ alpha = ALPHA_ENER_SLOW_FX;
+ move16();
+ if (LT_32(hDtxEnc->frame_ener_fx, hDtxEnc->lt_ener_noise_fx))
+ {
+ alpha = ALPHA_ENER_FAST_FX;
+ move16();
+ }
+
+ /*st_fx->lt_ener_noise_fx = alpha * st_fx->lt_ener_noise_fx + (1.0f-alpha) * st_fx->frame_ener_fx;*/
+ L_tmp = L_sub(hDtxEnc->lt_ener_noise_fx, hDtxEnc->frame_ener_fx);
+ L_tmp = Mult_32_16(L_tmp, alpha);
+ hDtxEnc->lt_ener_noise_fx = L_add(L_tmp, hDtxEnc->frame_ener_fx);
+ move32();/*Q(-7) */
+
+ hDtxEnc->VarDTX_cnt_noise = add(hDtxEnc->VarDTX_cnt_noise, 1);
+
+ hDtxEnc->VarDTX_cnt_noise = s_min(hDtxEnc->VarDTX_cnt_noise, MIN_CNT);
+ }
+ }
+ }
+
+ /* Update of the SID counter */
+ update_SID_cnt(hDtxEnc, st_fx->core_brate_fx, st_fx->Opt_AMR_WB_fx);
+
+ /* Update encoded bandwidth */
+ test();
+ test();
+ IF( st_fx->Opt_DTX_ON_fx && (st_fx->core_brate_fx == SID_2k40 || st_fx->core_brate_fx == FRAME_NO_DATA ) )
+ {
+
+ st_fx->bwidth_fx = st_fx->last_bwidth_fx;
+ move16();
+ test();
+ if( GT_32(st_fx->last_core_brate_fx, SID_2k40)&&NE_32(st_fx->last_total_brate_cng_fx,-1))
+ {
+ st_fx->bwidth_fx = st_fx->last_bwidth_cng_fx;
+ move16();
+ }
+
+ test();
+ test();
+ IF( st_fx->Opt_RF_ON && (EQ_32(st_fx->total_brate_fx, ACELP_13k20))&&(EQ_16(st_fx->bwidth_fx,NB)))
+ {
+ st_fx->codec_mode = MODE1;
+ move16();
+ reset_rf_indices_fx(st_fx);
+ st_fx->Opt_RF_ON = 0;
+ move16();
+ st_fx->rf_mode = 0;
+ move16();
+ }
+
+ test();
+ test();
+ IF( st_fx->Opt_RF_ON && NE_32(st_fx->total_brate_fx, ACELP_13k20) )
+ {
+ reset_rf_indices_fx(st_fx);
+ move16();
+ st_fx->Opt_RF_ON = 0;
+ move16();
+ st_fx->rf_mode = 0;
+ }
+
+ /* Set and limit the encoded bandwidth */
+ IF ( EQ_16(st_fx->codec_mode, MODE2))
+ {
+ Word16 n, bits_frame_nominal;
+
+ UWord16 lsb;
+ Word16 tmpbandwidthMin;
+
+ Mpy_32_16_ss(st_fx->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */
+ bits_frame_nominal = extract_l(L_shr(L_tmp, 3)); /* Q0 */
+
+ FOR (n=0; nrf_mode,1))
+ {
+ tmpbandwidthMin = WB;
+ }
+ st_fx->bwidth_fx = s_max(s_min(st_fx->bwidth_fx, FrameSizeConfig[n].bandwidth_max), tmpbandwidthMin);
+ }
+
+ }
+
+ return;
+}
+
+/*---------------------------------------------------------------------*
+ * update_SID_cnt()
+ *
+ * Update of the SID counter
+ *---------------------------------------------------------------------*/
+
+static void update_SID_cnt(
+ DTX_ENC_HANDLE hDtxEnc, /* i/o: common DTX handle */
+ const Word32 core_brate, /* i : core coder core bitrate */
+ const Word16 Opt_AMR_WB /* i : AMR BW IO mode? */
+)
+{
+ Word16 EstimatedSNR, delta, frac, exp;
+ Word32 L_tmp1, L_tmp2;
+
+ test();
+ test();
+ IF( EQ_32(core_brate, SID_2k40)||EQ_32(core_brate,SID_1k75)||core_brate==FRAME_NO_DATA)
+ {
+ /* Adapt the SID interval */
+ test();
+ test();
+ IF (hDtxEnc->var_SID_rate_flag != 0 && EQ_16(hDtxEnc->VarDTX_cnt_voiced, MIN_CNT)&&EQ_16(hDtxEnc->VarDTX_cnt_noise,MIN_CNT))
+ {
+ /* EstimatedSNR = 10.0f * (float)log10( (0.01f + st_fx->lt_ener_voiced) / (0.01f + st_fx->lt_ener_noise) ); */
+
+ L_tmp1 = L_max(hDtxEnc->lt_ener_voiced_fx, 1);
+ exp = norm_l(L_tmp1);
+ frac = Log2_norm_lc(L_shl(L_tmp1, exp));
+ exp = sub(30, exp);
+ L_tmp1 = L_Comp(exp, frac);
+ L_tmp2 = L_max(hDtxEnc->lt_ener_noise_fx, 1);
+ exp = norm_l(L_tmp2);
+ frac = Log2_norm_lc(L_shl(L_tmp2, exp));
+ exp = sub(30, exp);
+ L_tmp1 = L_sub(L_tmp1, L_Comp(exp, frac));
+ /* 10 x Log10(a/b) = 10 x Log10(2) x [Log2(a) - Log2(b)] */
+ /* 10 x Log10(2) = ~3.0103 */
+ L_tmp1 = Mpy_32_16_1(L_tmp1, 24660); /* mult by 3.0103 / 4 in Q15 */
+ L_tmp1 = L_shl(L_tmp1, 2+8); /* mult by 4 and shift left 8 to go in Q24 */
+ EstimatedSNR = round_fx(L_tmp1); /* now in Q8 */
+ IF ( GT_16(EstimatedSNR,SNR_H_FX))
+ {
+ hDtxEnc->interval_SID = INT_H;
+ move16();
+ }
+ ELSE IF ( LT_16(EstimatedSNR,SNR_L_FX))
+ {
+ hDtxEnc->interval_SID = INT_L;
+ move16();
+ }
+ ELSE
+ {
+ hDtxEnc->interval_SID = extract_h(L_mac(INT_L*65536L-SNR_L_FX/256*65536L*RATIO,(32768/256)*RATIO, EstimatedSNR));
+ }
+ hDtxEnc->interval_SID = s_min(s_max(hDtxEnc->interval_SID, INT_L), INT_H);
+
+ test();
+
+ if( Opt_AMR_WB== 0 || NE_16(hDtxEnc->max_SID,3))
+ {
+ hDtxEnc->max_SID = hDtxEnc->interval_SID;
+ move16(); /* change SID update rate */
+ }
+ }
+ test();
+ IF( hDtxEnc->cnt_SID != 0 )
+ {
+ L_tmp1 = L_max(hDtxEnc->lt_ener_noise_fx, 1);
+ exp = norm_l(L_tmp1);
+ frac = Log2_norm_lc(L_shl(L_tmp1, exp));
+ exp = sub(30, exp);
+ L_tmp1 = L_Comp(exp, frac);
+ L_tmp2 = L_max(hDtxEnc->lt_ener_last_SID_fx, 1);
+ exp = norm_l(L_tmp2);
+ frac = Log2_norm_lc(L_shl(L_tmp2, exp));
+ exp = sub(30, exp);
+ L_tmp1 = L_sub(L_tmp1, L_Comp(exp, frac));
+ /* 10 x Log10(a/b) = 10 x Log10(2) x [Log2(a) - Log2(b)] */
+ /* 10 x Log10(2) = ~3.0103 */
+ L_tmp1 = Mpy_32_16_1(L_tmp1, 24660); /* mult by 3.0103 / 4 in Q15 */
+ L_tmp1 = L_shl(L_tmp1, 2+8); /* mult by 4 and shift left 8 to go in Q24 */
+ delta = round_fx(L_tmp1); /* now in Q8 */
+ test();
+ test();
+ if ( LT_16(delta,LTE_VAR_FX)&&EQ_16(hDtxEnc->VarDTX_cnt_voiced,MIN_CNT)&&EQ_16(hDtxEnc->VarDTX_cnt_noise,MIN_CNT))
+ {
+ /* Send SID frame, and reset lt_ener_noise */
+ hDtxEnc->lt_ener_noise_fx = hDtxEnc->frame_ener_fx;
+ move32();
+ }
+ }
+ ELSE
+ {
+ /* If SID frame was sent, update long-term energy */
+ hDtxEnc->lt_ener_last_SID_fx = hDtxEnc->lt_ener_noise_fx;
+ move32();
+ }
+ hDtxEnc->cnt_SID = add(hDtxEnc->cnt_SID,1);
+
+ IF(hDtxEnc->var_SID_rate_flag )
+ {
+ test();
+ test();
+ test();
+
+ if( Opt_AMR_WB!= 0 && EQ_16(hDtxEnc->max_SID,3)&&EQ_16(hDtxEnc->cnt_SID,3))
+ {
+ /* set the size of CNG history buffer for averaging to DTX_HIST_SIZE frames */
+ /* be sure that DTX_HIST_SIZE >= INT_L */
+ hDtxEnc->cng_hist_size = 3;
+ move16();
+ }
+ test();
+ /*else if ( st_fx->max_SID != 3 && st_fx->cnt_SID == DTX_HIST_SIZE )//compile error */
+ if( NE_16(hDtxEnc->max_SID,3)&&EQ_16(hDtxEnc->cnt_SID,DTX_HIST_SIZE))
+ {
+ /* set the size of CNG history buffer for averaging to 3 frames */
+ hDtxEnc->cng_hist_size = DTX_HIST_SIZE;
+ move16();
+ }
+ }
+ test();
+ IF(hDtxEnc->var_SID_rate_flag == 0 && GT_16(hDtxEnc->interval_SID,1))
+ {
+ /* set the size of CNG history buffer for averaging to interval_SID frames */
+ hDtxEnc->cng_hist_size = hDtxEnc->interval_SID;
+ move16();
+ if ( GT_16(hDtxEnc->cng_hist_size, DTX_HIST_SIZE))
+ {
+ hDtxEnc->cng_hist_size = DTX_HIST_SIZE;
+ move16();
+ }
+ }
+ IF( GE_16(hDtxEnc->cnt_SID, hDtxEnc->max_SID))
+ {
+ /* adaptive SID update interval */
+ hDtxEnc->max_SID = hDtxEnc->interval_SID;
+ move16();
+ hDtxEnc->cnt_SID = 0;
+ move16();
+ }
+ }
+
+ return;
+}
+
+
+void dtx_hangover_control_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 lsp_new_fx[M] /* i : current frame LSPs */
+)
+{
+ Word16 ptr;
+ Word16 i,j,m;
+ Word16 tmp_lsp[/*max(DTX_HIST_SIZE,*/HO_HIST_SIZE/*)*/*M];
+ Word32 tmp_enr[/*max(DTX_HIST_SIZE,*/HO_HIST_SIZE/*)*/];
+ Word16 tmp[/*max(DTX_HIST_SIZE,*/HO_HIST_SIZE/*)*/*M];
+ Word16 enr_new;
+ Word16 weights;
+ Word32 enr_est;
+ Word16 enr_est_log;
+ Word16 lsp_est[M];
+ Word16 Dlsp,Denr;
+ Word16 lsf_tmp[M];
+ Word32 C[M];
+ Word32 max_val[2];
+ Word16 max_idx[2];
+ Word16 ftmp_fx;
+ Word16 Dlsp_n2e,Denr_n2e;
+ Word16 exp,fra,exp2,fra2;
+ Word16 S_max;
+ Word16 S_tmp;
+ Word32 L_tmp;
+ VAD_HANDLE hVAD = st_fx->hVAD;
+ DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /* get current frame exc energy in log2 */
+ exp = norm_l(hTdCngEnc->ho_ener_circ_fx[hTdCngEnc->ho_circ_ptr]);
+ fra = Log2_norm_lc(L_shl(hTdCngEnc->ho_ener_circ_fx[hTdCngEnc->ho_circ_ptr],exp));
+ exp = sub(sub(30,exp),6);
+ L_tmp = L_Comp(exp,fra);
+ enr_new = round_fx(L_shl(L_tmp,8)); /*Q8 */
+
+ if ( enr_new < 0 )
+ {
+ enr_new = 0;
+ move16(); /*Q8 */
+ }
+
+ /* get energies and lsps of hangover frames */
+ ptr = sub(hTdCngEnc->ho_circ_ptr,sub(hTdCngEnc->burst_ho_cnt,1));
+ IF ( ptr < 0 )
+ {
+ ptr = add(hTdCngEnc->ho_circ_size,ptr);
+ }
+
+ FOR ( i=0; i< hTdCngEnc->burst_ho_cnt-1; i++ )
+ {
+ Copy( &(hTdCngEnc->ho_lsp_circ_fx[ptr*M]), &(tmp_lsp[i*M]), M );
+ tmp_enr[i] = hTdCngEnc->ho_ener_circ_fx[ptr];
+ move32();/*Q6 */
+
+ ptr = add(ptr,1);
+ if ( EQ_16(ptr, hTdCngEnc->ho_circ_size))
+ {
+ ptr = 0;
+ move16();
+ }
+ }
+
+ /* get estimated CNG energy and lsps assuming terminate hangover at current frame */
+ ptr = sub(hTdCngEnc->burst_ho_cnt,2);
+ enr_est = Mpy_32_16_1(tmp_enr[ptr],W_DTX_HO_FX[0]); /*Q6 */
+ weights = W_DTX_HO_FX[0];
+ move16();/*Q15 */
+ Copy( &(tmp_lsp[ptr*M]), tmp, M );
+ m = 1;
+ move16();
+
+ FOR ( i=1; i< hTdCngEnc->burst_ho_cnt-2; i++ )
+ {
+ test();
+ IF ( LT_32(Mpy_32_16_1(tmp_enr[ptr-i],ONE_OVER_BUF_H_NRG_FX),tmp_enr[ptr])&&
+ GT_32(tmp_enr[ptr-i],Mpy_32_16_1(tmp_enr[ptr], BUF_L_NRG_FX)) )
+ {
+ enr_est = L_add(enr_est,Mpy_32_16_1(tmp_enr[ptr-i],W_DTX_HO_FX[i])); /*Q6 */
+ weights = add(weights,W_DTX_HO_FX[i]); /*Q15 */
+ Copy( &tmp_lsp[(ptr-i)*M], &tmp[m*M], M );
+ m = add(m,1);
+ }
+ }
+
+ exp = norm_l(enr_est);
+ fra = round_fx(L_shl(enr_est,exp));
+ exp2 = norm_s(weights);
+ fra2 = shl(weights,exp2);
+ exp = sub(sub(exp,16),exp2);
+ IF ( GT_16(fra,fra2))
+ {
+ fra = shr(fra,1);
+ exp = sub(exp,1);
+ }
+ L_tmp = L_deposit_l(div_s(fra,fra2));
+ enr_est = L_shr(L_tmp,exp); /*Q6 */
+
+ if ( LT_32(enr_est,64))
+ {
+ enr_est = 64;
+ move16();/*Q6 */
+ }
+
+ exp = norm_l(enr_est);
+ fra = Log2_norm_lc(L_shl(enr_est,exp));
+ exp = sub(sub(30,exp),6);
+ L_tmp = L_Comp(exp,fra);
+ enr_est_log = round_fx(L_shl(L_tmp,8)); /*Q8 */
+ Denr_n2e = abs_s(sub(enr_new,enr_est_log)); /*Q8 */
+
+ IF ( LT_16(m,3))
+ {
+ enr_est = L_add(Mpy_32_16_1(enr_est,26214),Mpy_32_16_1(hTdCngEnc->ho_ener_circ_fx[hTdCngEnc->ho_circ_ptr],6554)); /*Q6 */
+ }
+ ELSE
+ {
+ enr_est = L_add(Mpy_32_16_1(enr_est,31130),Mpy_32_16_1(hTdCngEnc->ho_ener_circ_fx[hTdCngEnc->ho_circ_ptr],1638)); /*Q6 */
+ }
+
+ exp = norm_l(enr_est);
+ fra = Log2_norm_lc(L_shl(enr_est,exp));
+ exp = sub(sub(30,exp),6);
+ L_tmp = L_Comp(exp,fra);
+ enr_est_log = round_fx(L_shl(L_tmp,8)); /*Q8 */
+
+ if ( enr_est_log < 0 )
+ {
+ enr_est_log = 0;
+ move16();
+ }
+
+ set32_fx( max_val, 0, 2 );
+ set16_fx( max_idx, 0, 2 );
+
+ FOR( i=0; iL_frame_fx,L_FRAME))
+ {
+ lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_FX );
+ ftmp_fx = 964;
+ move16();/*QX2.56 */
+ S_tmp = sub(16384,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */
+ C[i] = L_mult0(S_tmp,S_tmp); /*QX6.5536 */
+ }
+ ELSE
+ {
+ lsp2lsf_fx( &tmp[i*M], lsf_tmp, M, INT_FS_16k );
+ ftmp_fx = 1205;
+ move16();/*QX2.56 */
+ S_tmp = sub(20480,add(lsf_tmp[M-1],ftmp_fx)); /*QX2.56 */
+ C[i] = L_mult0(S_tmp,S_tmp); /*QX6.5536 */
+ }
+
+ S_tmp = sub(lsf_tmp[0],ftmp_fx); /*QX2.56 */
+ C[i] = L_mac0(C[i],S_tmp,S_tmp); /*QX6.5536 */
+ FOR ( j=0; jlspCNG_fx[i],lsp_est[i])); /*Q15 */
+#ifdef BASOP_NOGLOB
+ Dlsp = add_o(Dlsp,S_tmp, &Overflow); /*Q15 */
+#else /* BASOP_NOGLOB */
+ Dlsp = add(Dlsp,S_tmp); /*Q15 */
+#endif
+ IF ( GT_16(S_tmp,S_max))
+ {
+ S_max = S_tmp; /*Q15 */
+ }
+ }
+
+ exp = norm_l(hTdCngEnc->lp_ener_fx);
+ fra = Log2_norm_lc(L_shl(hTdCngEnc->lp_ener_fx,exp));
+ exp = sub(sub(30,exp),6);
+ L_tmp = L_Comp(exp,fra);
+ S_tmp = round_fx(L_shl(L_tmp,8)); /*Q8 */
+ Denr = abs_s(sub(S_tmp,enr_est_log)); /*Q8 */
+
+ /* make decision if DTX hangover can be terminated */
+ hVAD->hangover_terminate_flag = 0;
+ move16(); /*Q0 */
+
+ test();test();test();test();test();test();test();test();test();test();test();
+ IF ( ( LT_16(Dlsp,13107)&<_16(Denr,359)&<_16(S_max,3277)
+ && LT_16(Dlsp_n2e,13107) && LT_16(Denr_n2e,308) && st_fx->Opt_SC_VBR_fx == 1 ) ||
+ ( LT_16(Dlsp,13107) && LT_16(Denr,205) && LT_16(S_max,3277)
+ && LT_16(Dlsp_n2e,13107) && LT_16(Denr_n2e,205) && st_fx->Opt_SC_VBR_fx == 0 ) )
+
+ {
+ hVAD->hangover_terminate_flag = 1;
+ move16(); /*Q0 */
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * td_cng_enc_init_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void td_cng_enc_init_fx(
+ TD_CNG_ENC_HANDLE hTdCngEnc, /* i/o: DTX/TD CNG data handle */
+ const Word16 Opt_DTX_ON, /* i : flag indicating DTX operation */
+ const Word16 max_bwidth /* i : maximum encoded bandwidth */
+)
+{
+
+ hTdCngEnc->cng_seed = RANDOM_INITSEED;
+ hTdCngEnc->cng_ener_seed = RANDOM_INITSEED;
+ hTdCngEnc->cng_ener_seed1 = RANDOM_INITSEED;
+ hTdCngEnc->lp_ener_fx = 0;
+ hTdCngEnc->old_enr_index = -1;
+ hTdCngEnc->Enew_fx = 0;
+
+ hTdCngEnc->lp_sp_enr_fx = 0;
+ hTdCngEnc->last_allow_cn_step = 0;
+ move16();move32();move16();move16();move32();move16();move16();
+
+ IF (Opt_DTX_ON)
+ {
+ hTdCngEnc->cng_hist_ptr = -1;
+ move16();
+ set16_fx(hTdCngEnc->cng_lsp_hist_fx, 0, DTX_HIST_SIZE * M);
+ set16_fx(hTdCngEnc->cng_ener_hist_fx, 0, DTX_HIST_SIZE);
+
+ hTdCngEnc->ho_hist_ptr = -1;
+ move16();
+ hTdCngEnc->ho_sid_bw = L_deposit_l(0);
+ set16_fx(hTdCngEnc->ho_lsp_hist_fx, 0, HO_HIST_SIZE * M);
+ set32_fx(hTdCngEnc->ho_ener_hist_fx, 0, HO_HIST_SIZE);
+ set32_fx(hTdCngEnc->ho_env_hist_fx, 0, HO_HIST_SIZE * NUM_ENV_CNG);
+ hTdCngEnc->ho_hist_size = 0;
+ move16();
+ hTdCngEnc->act_cnt = 0;
+ move16();
+
+ }
+
+ set16_fx(hTdCngEnc->ho_16k_lsp, 0, HO_HIST_SIZE);
+ hTdCngEnc->act_cnt2 = 0;
+ hTdCngEnc->num_ho = 0;
+ move16();
+ move16();
+
+ hTdCngEnc->ho_circ_ptr = -1;
+ move16();
+ set16_fx(hTdCngEnc->ho_lsp_circ_fx, 0, HO_HIST_SIZE * M);
+ set32_fx(hTdCngEnc->ho_ener_circ_fx, 0, HO_HIST_SIZE);
+ set32_fx(hTdCngEnc->ho_env_circ_fx, 0, HO_HIST_SIZE * NUM_ENV_CNG);
+ hTdCngEnc->ho_circ_size = 0;
+ hTdCngEnc->burst_ho_cnt = 0;
+ move16();
+ move16();
+
+#ifdef IVAS_CODE
+ hTdCngEnc->CNG_att_fx = 0;
+ hTdCngEnc->last_idx_ener_fx = 0;
+#endif
+
+ hTdCngEnc->cng_buf_cnt = 0;
+
+
+ set32_fx(hTdCngEnc->lp_env_fx, 0, 20);
+ set32_fx(hTdCngEnc->cng_res_env_fx, 0, 20 * 8);
+ set16_fx(hTdCngEnc->exc_mem_fx, 0, 24);
+ set16_fx(hTdCngEnc->exc_mem1_fx, 0, 30);
+ set16_fx(hTdCngEnc->exc_mem2_fx, 0, 30);
+ set32_fx(hTdCngEnc->old_env_fx, 0, NUM_ENV_CNG);
+
+ /* SWB CNG/DTX */
+ hTdCngEnc->last_wb_cng_ener_fx = -1541;
+ move16(); /* Q8 */
+ hTdCngEnc->last_shb_cng_ener_fx = -1541;
+ move16(); /* Q8 */
+ hTdCngEnc->mov_wb_cng_ener_fx = -1541;
+ move16(); /* Q8 */
+ hTdCngEnc->mov_shb_cng_ener_fx = -1541;
+ move16(); /* Q8 */
+ hTdCngEnc->shb_cng_ini_cnt = 1;
+ move16();
+ hTdCngEnc->shb_NO_DATA_cnt = 0;
+ move16();
+ hTdCngEnc->last_SID_bwidth = s_min(max_bwidth, SWB);
+ hTdCngEnc->last_vad = 0;
+ move16();
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * dtx_enc_init_fx()
+ *
+ * Initialize DTX parameters
+ *-------------------------------------------------------------------*/
+
+void dtx_enc_init_fx(
+ Encoder_State_fx* st, /* i : Encoder state handle */
+ const Word16 var_SID_rate_flag, /* i : flag for variable SID update rate */
+ const Word16 interval_SID /* i : interval for SID update */
+)
+{
+ DTX_ENC_HANDLE hDtxEnc;
+ hDtxEnc = st->hDtxEnc;
+
+ hDtxEnc->first_CNG = 0; move16();
+ hDtxEnc->cnt_SID = 0; move16();
+ hDtxEnc->max_SID = 2; move16();
+ hDtxEnc->CNG_mode = -1; move16();
+ Copy(st->lsp_old1_fx, hDtxEnc->lspCNG_fx, M);
+ hDtxEnc->VarDTX_cnt_voiced = 0; move16();
+ hDtxEnc->VarDTX_cnt_noise = 0; move16();
+ hDtxEnc->lt_ener_voiced_fx = 0; move16();
+ hDtxEnc->lt_ener_noise_fx = 0; move16();
+ hDtxEnc->frame_ener_fx = 0; move16();
+ hDtxEnc->lt_ener_last_SID_fx = 0; move16();
+ hDtxEnc->last_CNG_L_frame = L_FRAME; move16();
+ hDtxEnc->var_SID_rate_flag = var_SID_rate_flag; move16();
+ hDtxEnc->last_active_brate = ACELP_7k20; move16();
+ hDtxEnc->cng_cnt = 0; move16();
+
+ IF (hDtxEnc->var_SID_rate_flag)
+ {
+ hDtxEnc->interval_SID = 12; move16(); move16();
+ hDtxEnc->cng_hist_size = DTX_HIST_SIZE;
+ }
+ ELSE
+ {
+ hDtxEnc->interval_SID = interval_SID; move16();
+ if (GE_16(hDtxEnc->interval_SID, DTX_HIST_SIZE))
+ {
+ hDtxEnc->cng_hist_size = hDtxEnc->interval_SID; move16();
+ }
+ }
+ return;
+}
\ No newline at end of file
diff --git a/lib_enc/enc_acelp_fx.c b/lib_enc/enc_acelp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..d234a1dd9d2c4c2890f93f5bad5e657cbd5751db
--- /dev/null
+++ b/lib_enc/enc_acelp_fx.c
@@ -0,0 +1,2211 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "typedef.h"
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+//#include "prot_fx.h"
+#include "basop_util.h"
+#include "rom_com_fx.h"
+#include "rom_com.h"
+#include "rom_enc.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+#define _2_ 0x4000 /*Q12*/
+#define _1_ 0x2000 /*Q12*/
+#define _1_Q9 0x200
+
+static void E_ACELP_codearithp_fx(const Word16 v[], UWord32 *n, UWord32 *ps, Word16 *p);
+
+/*
+ * E_ACELP_h_vec_corrx
+ *
+ * Parameters:
+ * h I: scaled impulse response
+ * vec I: vector to correlate with h[]
+ * track I: track to use
+ * sign I: sign vector
+ * rrixix I: correlation of h[x] with h[x]
+ * cor O: result of correlation (16 elements)
+ *
+ * Function:
+ * Calculate the correlations of h[] with vec[] for the specified track
+ *
+ * Returns:
+ * void
+ */
+void E_ACELP_h_vec_corr1(Word16 h[], Word16 vec[], UWord8 track,
+ Word16 sign[], Word16 (*rrixix)[16],
+ Word16 cor[], Word16 dn2_pos[],
+ Word16 nb_pulse)
+{
+ Word16 i, j;
+ Word16 dn, corr;
+ Word16 *dn2;
+ Word16 *p0, *p1, *p2;
+ Word32 L_sum;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ dn2 = &dn2_pos[shl(track,3)];
+ p0 = rrixix[track];
+
+ FOR (i = 0; i < nb_pulse; i++)
+ {
+ dn = dn2[i];
+ move16();
+ L_sum = L_deposit_l(0);
+ p1 = h;
+ p2 = &vec[dn];
+ FOR(j = dn; j < L_SUBFR - 1; j++)
+ {
+#ifdef BASOP_NOGLOB
+ L_sum = L_mac_o(L_sum, *p1++, *p2++, &Overflow);
+#else
+ L_sum = L_mac(L_sum, *p1++, *p2++);
+#endif
+ }
+
+#ifdef BASOP_NOGLOB
+ corr = mac_ro(L_sum, *p1++, *p2++, &Overflow); /*Q9*/
+#else /* BASOP_NOGLOB */
+ corr = mac_r(L_sum, *p1++, *p2++); /*Q9*/
+#endif /* BASOP_NOGLOB */
+
+ /*cor[dn >> 2] = sign[dn] * s + p0[dn >> 2];*/
+ j = shr(dn,2);
+ if(sign[dn] > 0)
+ {
+#ifdef BASOP_NOGLOB
+ corr = add_o(p0[j], corr, &Overflow);
+#else
+ corr = add(p0[j], corr);
+#endif
+ }
+ if(sign[dn] < 0)
+ {
+#ifdef BASOP_NOGLOB
+ corr = sub_o(p0[j], corr, &Overflow);
+#else /* BASOP_NOGLOB */
+ corr = sub(p0[j], corr);
+#endif /* BASOP_NOGLOB */
+ }
+
+ cor[j] = corr;
+ move16();
+ }
+ return;
+}
+
+void E_ACELP_h_vec_corr2(Word16 h[], Word16 vec[], UWord8 track,
+ Word16 sign[], Word16 (*rrixix)[16],
+ Word16 cor[])
+{
+ Word16 i, j, pos, corr;
+ Word16 *p0, *p1, *p2;
+ Word32 L_sum;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ p0 = rrixix[track];
+
+ pos = track;
+ move16();
+ FOR (i = 0; i < 16; i++)
+ {
+ L_sum = L_deposit_l(0);
+ p1 = h;
+ p2 = &vec[pos];
+ FOR(j = pos; j < L_SUBFR - 1; j++)
+ {
+#ifdef BASOP_NOGLOB
+ L_sum = L_mac_o(L_sum, *p1++, *p2++, &Overflow);
+#else
+ L_sum = L_mac(L_sum, *p1++, *p2++);
+#endif
+ }
+#ifdef BASOP_NOGLOB
+ corr = mac_ro(L_sum, *p1++, *p2++, &Overflow); /*Q9*/
+#else /* BASOP_NOGLOB */
+ corr = mac_r(L_sum, *p1++, *p2++); /*Q9*/
+#endif /* BASOP_NOGLOB */
+
+ /*cor[i] = s * sign[track] + p0[i];*/
+
+ if(sign[pos] > 0)
+ {
+#ifdef BASOP_NOGLOB
+ corr = add_o(*p0++, corr, &Overflow);
+#else
+ corr = add(*p0++, corr);
+#endif
+ }
+ if(sign[pos] < 0)
+ {
+#ifdef BASOP_NOGLOB
+ corr = sub_o(*p0++, corr, &Overflow);
+#else
+ corr = sub(*p0++, corr);
+#endif
+ }
+ cor[i] = corr;
+ move16();
+
+ pos = add(pos,4);
+ }
+ return;
+}
+
+
+/*
+ * E_ACELP_2pulse_search
+ *
+ * Parameters:
+ * nb_pos_ix I: nb of pos for pulse 1 (1..8)
+ * track_x I: track of pulse 1
+ * track_y I: track of pulse 2
+ * ps I/O: correlation of all fixed pulses
+ * alp I/O: energy of all fixed pulses
+ * ix O: position of pulse 1
+ * iy O: position of pulse 2
+ * dn I: corr. between target and h[]
+ * dn2 I: vector of selected positions
+ * cor_x I: corr. of pulse 1 with fixed pulses
+ * cor_y I: corr. of pulse 2 with fixed pulses
+ * rrixiy I: corr. of pulse 1 with pulse 2
+ *
+ * Function:
+ * Find the best positions of 2 pulses in a subframe
+ *
+ * Returns:
+ * void
+ */
+static void E_ACELP_2pulse_search(Word16 nb_pos_ix, UWord8 track_x,
+ UWord8 track_y, Word16 *ps, Word16 *alp,
+ Word16 *ix, Word16 *iy, Word16 dn[],
+ Word16 *dn2, Word16 cor_x[],
+ Word16 cor_y[], Word16 (*rrixiy)[256])
+{
+ Word16 x, x2, y, i, *pos_x;
+ Word16 ps0, ps1, alp2_16, ps2, sq;
+ Word32 alp0, alp1, alp2, s;
+ Word16 *p1, *p2;
+ Word16 sqk[2], alpk[2], ik;
+ Word32 xy_save;
+ Word16 check = 0; /* debug code not instrumented */
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+ /* eight dn2 max positions per track */
+ /*pos_x = &dn2[track_x << 3]; SHIFT(1); PTR_INIT(1);*/
+ pos_x = &dn2[shl(track_x, 3)];
+ move16();
+
+ /* save these to limit memory searches */
+ alp0 = L_deposit_h(*alp);
+ ps0 = *ps;
+ move16();
+
+ alpk[0] = 1;
+ move16();
+ sqk[0] = -1;
+ move16();
+ x2 = shr(pos_x[0], 2);
+#ifdef BASOP_NOGLOB
+ if (mac_ro(L_mac_o(L_mac_o(alp0, cor_x[x2], _1_, &Overflow), cor_y[0], _1_, &Overflow), rrixiy[track_x][shl(x2,4)], _1_, &Overflow) < 0)
+#else /* BASOP_NOGLOB */
+ if (mac_r(L_mac(L_mac(alp0, cor_x[x2], _1_), cor_y[0], _1_), rrixiy[track_x][shl(x2,4)], _1_) < 0)
+#endif /* BASOP_NOGLOB */
+ {
+ sqk[0] = 1;
+ move16();
+ }
+ ik = 0;
+ move16();
+ xy_save = L_mac0(L_deposit_l(track_y), track_x, L_SUBFR);
+
+ /* loop track 1 */
+ FOR (i = 0; i < nb_pos_ix; i++)
+ {
+ x = pos_x[i];
+ move16();
+ x2 = shr(x, 2);
+ /* dn[x] has only nb_pos_ix positions saved */
+ /*ps1 = ps0 + dn[x];*/
+ ps1 = add(ps0, dn[x]);
+
+ /*alp1 = alp0 + cor_x[x2];*/
+#ifdef BASOP_NOGLOB
+ alp1 = L_mac_o(alp0, cor_x[x2], _1_, &Overflow); /*Q22*/
+#else /* BASOP_NOGLOB */
+ alp1 = L_mac(alp0, cor_x[x2], _1_); /*Q22*/
+#endif /* BASOP_NOGLOB */
+
+ p1 = cor_y;
+ p2 = &rrixiy[track_x][shl(x2,4)];
+
+ FOR (y = track_y; y < L_SUBFR; y += 4)
+ {
+ /*ps2 = ps1 + dn[y];*/
+ ps2 = add(ps1, dn[y]);
+
+ /*alp2 = alp1 + (*p1++) + (*p2++);*/
+#ifdef BASOP_NOGLOB
+ alp2 = L_mac_o(alp1, *p1++, _1_, &Overflow);
+ alp2_16 = mac_ro(alp2, *p2++, _1_, &Overflow); /*Q6*/
+#else /* BASOP_NOGLOB */
+ alp2 = L_mac(alp1, *p1++, _1_);
+ alp2_16 = mac_r(alp2, *p2++, _1_); /*Q6*/
+#endif /* BASOP_NOGLOB */
+ alpk[1-ik] = alp2_16;
+ move16();
+
+ /*sq = ps2 * ps2;*/
+ sq = mult(ps2, ps2);
+ sqk[1-ik] = sq;
+ move16();
+
+ /*s = (alpk[ik] * sq) - (sqk[0] * alp2);*/
+ s = L_msu(L_mult(alpk[ik], sq), sqk[ik], alp2_16); /*Q16*/
+
+ if (s > 0)
+ {
+ ik = sub(1, ik);
+ check = 1; /* debug code not instrumented */
+ }
+ if (s > 0)
+ {
+ xy_save = L_mac0(y, x, L_SUBFR);
+ }
+ }
+ }
+
+ assert(check); /* debug code not instrumented */
+
+ ps2 = extract_l(xy_save);
+ *iy = s_and(ps2, L_SUBFR-1);
+ move16();
+ *ix = lshr(ps2, 6);
+ move16();
+
+ /**ps = ps0 + dn[*ix] + dn[*iy];*/
+ *ps = add(ps0, add(dn[*ix], dn[*iy]));
+ move16();
+
+ *alp = alpk[ik];
+ move16();
+ return;
+}
+
+
+
+/*
+ * E_ACELP_1pulse_search
+ *
+ * Parameters:
+ * track_x I: track of pulse 1
+ * track_y I: track of pulse 2
+ * ps I/O: correlation of all fixed pulses
+ * alp I/O: energy of all fixed pulses
+ * ix O: position of pulse 1
+ * dn I: corr. between target and h[]
+ * cor_x I: corr. of pulse 1 with fixed pulses
+ * cor_y I: corr. of pulse 2 with fixed pulses
+ *
+ * Function:
+ * Find the best positions of 1 pulse in a subframe
+ *
+ * Returns:
+ * void
+ */
+static void E_ACELP_1pulse_search(UWord8 tracks[2],
+ Word16 *ps,
+ Word16 *alp,
+ Word16 *ix,
+ Word16 dn[],
+ Word16 cor_x[],
+ Word16 cor_y[])
+{
+ Word16 x, x_save = 0;
+ Word16 ps0;
+ Word16 ps1, sq;
+ Word16 alp1;
+ Word32 s, alp0;
+ Word16 sqk[2], alpk[2], ik;
+ Word16 ntracks, t;
+ Word16 check = 0; /* debug code not instrumented */
+
+ /* save these to limit memory searches */
+ alp0 = L_deposit_h(*alp);
+ ps0 = *ps;
+ move16();
+
+ alpk[0] = 1;
+ move16();
+ sqk[0] = -1;
+ move16();
+ if (mac_r(alp0, cor_x[shr(tracks[0],2)], _1_) < 0)
+ {
+ sqk[0] = 1;
+ move16();
+ }
+ ik = 0;
+ move16();
+
+ ntracks = 1;
+ if (NE_16(tracks[1], tracks[0]))
+ {
+ ntracks = 2;
+ move16();
+ }
+ FOR (t=0; t>2]; SHIFT(1);ADD(1);*/
+ alp1 = mac_r(alp0, cor_x[shr(x,2)], _1_); /*Q6*/
+ alpk[1-ik] = alp1;
+ move16();
+
+ /*sq = ps1 * ps1; MULT(1);*/
+ sq = mult(ps1, ps1);
+ sqk[1-ik] = sq;
+ move16();
+
+ /*s = (alpk * sq) - (sqk * alp1); MULT(1);MAC(1); */
+ s = L_msu(L_mult(alpk[ik], sq), sqk[ik], alp1);/*Q16*/
+
+ if (s > 0)
+ {
+ ik = sub(1, ik);
+ check = 1; /* debug code not instrumented */
+ }
+ if (s > 0)
+ {
+ x_save = x;
+ move16();
+ }
+ }
+
+ assert( check ); /* debug code not instrumented */
+ }
+ *ps = add(ps0, dn[x_save]);
+ move16();
+ *alp = alpk[ik];
+ move16();
+ *ix = x_save;
+ move16();
+ return;
+}
+
+
+/*
+ * E_ACELP_xh_corr
+ *
+ * Parameters:
+ * h I: impulse response (of weighted synthesis filter) (Q12)
+ * x I: target signal (Q0)
+ * y O: correlation between x[] and h[] <12b
+ *
+ * Function:
+ * Compute the correlation between the target signal and the impulse
+ * response of the weighted synthesis filter.
+ *
+ * y[i]=sum(j=i,l-1) x[j]*h[j-i], i=0,l-1
+ *
+ * Vector size is L_SUBFR
+ *
+ * Returns:
+ * void
+ */
+static void E_ACELP_xh_corr(Word16 *x, Word16 *y, Word16 *h, Word16 L_subfr)
+{
+ Word16 i, j,k;
+ Word32 L_tmp, y32[L_SUBFR16k], L_maxloc, L_tot;
+
+ assert(L_subfr <= L_SUBFR16k);
+
+ /* first keep the result on 32 bits and find absolute maximum */
+ L_tot = L_deposit_l(1);
+
+ FOR (k = 0; k < 4; k++)
+ {
+ L_maxloc = L_deposit_l(0);
+ FOR (i = k; i < L_subfr; i += 4)
+ {
+ L_tmp = L_mac0(1L, x[i], h[0]); /* 1 -> to avoid null dn[] */
+ FOR (j = i; j < L_subfr-1; j++)
+ {
+ L_tmp = L_mac0(L_tmp, x[j+1], h[j+1 - i]);
+ }
+
+ y32[i] = L_tmp;
+ move32();
+ L_tmp = L_abs(L_tmp);
+ L_maxloc = L_max(L_tmp, L_maxloc);
+ }
+ /* tot += 3*max / 8 */
+ L_maxloc = L_shr(L_maxloc, 2);
+ /* Do not warn saturation of L_tot, since its for headroom estimation. */
+ BASOP_SATURATE_WARNING_OFF_EVS
+ L_tot = L_add(L_tot, L_maxloc); /* +max/4 */
+ L_tot = L_add(L_tot, L_shr(L_maxloc, 1)); /* +max/8 */
+ BASOP_SATURATE_WARNING_ON_EVS
+ }
+
+ /* Find the number of right shifts to do on y32[] so that */
+ /* 6.0 x sumation of max of dn[] in each track not saturate. */
+
+ j = sub(norm_l(L_tot), 4+16); /* 4 -> 16 x tot */
+
+ Copy_Scale_sig_32_16(y32, y, L_subfr, j);
+ return;
+}
+
+/**
+ * \brief calculate autocorrelation of vector x
+ * \param x input vector 4Q11
+ * \param y output (autocorrelation coefficients)
+ * \param L_subfr length of x (and y)
+ * \param bits amount of target headroom bits for y
+ * \return exponent of y
+ */
+Word16 E_ACELP_hh_corr(Word16 *x, Word16 *y, Word16 L_subfr, Word16 bits)
+{
+ Word16 i, j, k = 0; /* initialize just to avoid compiler warning */
+ Word32 L_tmp, L_sum;
+
+ FOR (i = 0; i < L_subfr-1; i++)
+ {
+ Word64 L_tmp_64;
+ Word64 L_sum_64;
+
+ L_tmp_64 = W_mult0_16_16( x[i], x[0] );
+ FOR (j = i+2; j < L_subfr; j+=2)
+ {
+ L_tmp_64 = W_mac0_16_16( L_tmp_64, x[j], x[j-i] );
+ }
+ L_sum_64 = L_tmp_64;
+ move64();
+
+ L_tmp_64 = W_mult0_16_16( x[i+1], x[1] );
+ FOR (j = i+3; j < L_subfr; j+=2)
+ {
+ L_tmp_64 = W_mac0_16_16( L_tmp_64, x[j], x[j-i] );
+ }
+ L_sum_64 = W_add_nosat( W_shr(L_sum_64,1), W_shr(L_tmp_64,1) );
+ L_sum = W_sat_l( L_sum_64 );
+ /* L_sum = L_shr( L_sum, 1 ); */
+ if (i == 0)
+ {
+ k = norm_l(L_sum);
+ }
+ if (i == 0)
+ {
+ k = sub(k, bits);
+ }
+
+ y[i] = round_fx( L_shl( L_sum, k ) );
+ }
+
+ L_tmp = L_mult0( x[i], x[0] );
+ L_sum = L_shr( L_tmp, 1 );
+ y[i] = round_fx( L_shl( L_sum, k ) );
+
+ k = add(1, k);
+
+ return k;
+}
+
+/*
+ * E_ACELP_xy1_corr
+ *
+ * Parameters:
+ * xn I: target signal
+ * y1 I: filtered adaptive codebook excitation
+ * g_coeff O: correlations and -2
+ * norm_flag I: flag to trigger normalization of the result
+ * L_subfr I: length of data
+ * exp_xn I: common exponent of xn[] and y1[]
+ *
+ * Function:
+ * Find the correlations between the target xn[] and the filtered adaptive
+ * codebook excitation y1[]. ( and -2 )
+ * Subframe size = L_SUBFR
+ *
+ * Returns:
+ * pitch gain (0 ... 1.2F) (Q14)
+ */
+Word16 E_ACELP_xy1_corr(Word16 xn[], Word16 y1[], ACELP_CbkCorr *g_corr, Word16 norm_flag, Word16 L_subfr, Word16 exp_xn)
+{
+ Word16 i, Q_xn;
+ Word16 xy, yy, exp_xy, exp_yy, gain;
+ Word32 L_off;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ L_off = L_shr(10737418l/*0.01f/2.0f Q31*/, s_min(add(exp_xn,exp_xn), 31));
+ L_off = L_max(1,L_off); /* ensure at least a '1' */
+
+#ifdef BASOP_NOGLOB
+ /* Compute scalar product t1: */
+ yy = round_fx_o(Dot_product15_offs(y1, y1, L_subfr, &exp_yy, L_off), &Overflow);
+
+ /* Compute scalar product t0: */
+ xy = round_fx_o(Dot_product12_offs(xn, y1, L_subfr, &exp_xy, L_off), &Overflow);
+#else
+ /* Compute scalar product t1: */
+ yy = round_fx(Dot_product15_offs(y1, y1, L_subfr, &exp_yy, L_off));
+
+ /* Compute scalar product t0: */
+ xy = round_fx(Dot_product12_offs(xn, y1, L_subfr, &exp_xy, L_off));
+#endif
+ /* Compute doubled format out of the exponent */
+ Q_xn = shl(sub(15,exp_xn),1);
+ g_corr->y1y1 = yy;
+ move16();
+ g_corr->y1y1_e = sub(exp_yy, Q_xn);
+ move16();
+ g_corr->xy1 = xy;
+ move16();
+ g_corr->xy1_e = sub(exp_xy, Q_xn);
+ move16();
+
+ /* If (xy < 0) gain = 0 */
+ IF (xy < 0)
+ {
+ move16();
+ gain = 0;
+ GOTO bail;
+ }
+
+ /* compute gain = xy/yy */
+
+ xy = mult_r(xy,0x4000); /* Be sure xy < yy */
+ gain = div_s(xy, yy);
+
+ i = add(exp_xy, 1 - 1); /* -1 -> gain in Q14 */
+ i = sub(i, exp_yy);
+ BASOP_SATURATE_WARNING_OFF_EVS
+#ifdef BASOP_NOGLOB
+ gain = shl_o(gain, i, &Overflow); /* saturation can occur here */
+#else /* BASOP_NOGLOB */
+ gain = shl(gain, i); /* saturation can occur here */
+#endif /* BASOP_NOGLOB */
+ BASOP_SATURATE_WARNING_ON_EVS
+ /* gain = s_max(0, gain); */ /* see above xy < 0. */
+
+ /* if (gain > 1.2) gain = 1.2 in Q14 */
+
+ gain = s_min(19661/*1.2f Q14*/ /* 19661 */, gain);
+
+ /*Limit the energy of pitch contribution*/
+ IF (norm_flag)
+ {
+ Word16 tmp, exp_tmp, exp_div;
+
+ /* Compute scalar product */
+#ifdef BASOP_NOGLOB
+ tmp = round_fx_o(Dot_product12_offs(xn, xn, L_subfr, &exp_tmp, 1), &Overflow);
+#else
+ tmp = round_fx(Dot_product12_offs(xn, xn, L_subfr, &exp_tmp, 1));
+#endif
+ /* gain_p_snr = sqrt(/) */
+ tmp = BASOP_Util_Divide1616_Scale(tmp, yy, &exp_div);
+ exp_tmp = add(sub(exp_tmp, exp_yy), exp_div);
+
+ tmp = Sqrt16(tmp, &exp_tmp);
+
+ /* Note: shl works as shl or shr. */
+ exp_tmp = sub(exp_tmp,1);
+ BASOP_SATURATE_WARNING_OFF_EVS
+#ifdef BASOP_NOGLOB
+ tmp = round_fx_o(L_shl_o(Mpy_32_16_1( 1717986944l/*ACELP_GAINS_CONST Q31*/, tmp), exp_tmp, &Overflow), &Overflow);
+#else /* BASOP_NOGLOB */
+ tmp = round_fx(L_shl(Mpy_32_16_1( 1717986944l/*ACELP_GAINS_CONST Q31*/, tmp), exp_tmp));
+#endif /* BASOP_NOGLOB */
+ BASOP_SATURATE_WARNING_ON_EVS
+
+ gain = s_min(gain, tmp);
+ }
+
+bail:
+
+
+ return (gain);
+}
+
+/*
+ * E_ACELP_xy2_corr
+ *
+ * Parameters:
+ * xn I: target signal in Q_xn
+ * y1 I: filtered adaptive codebook excitation in Q_xn
+ * y2 I: filtered fixed codebook excitation in Q9
+ * g_corr O: correlations , -2, 2
+ * L_subfr I: subframe size
+ *
+ * Function:
+ * Find the correlations between the target xn[], the filtered adaptive
+ * codebook exc. y1[], and the filtered fixed codebook innovation y2[].
+ * ( , -2 and 2 )
+ * Subrame size = L_SUBFR
+ *
+ * Returns:
+ * pitch gain (0 ... 1.2F)
+ */
+void E_ACELP_xy2_corr(Word16 xn[], Word16 y1[], Word16 y2[],
+ ACELP_CbkCorr *g_corr, Word16 L_subfr, Word16 exp_xn)
+{
+ Word16 xny2, y2y2, y1y2, xx, exp_xny2, exp_y2y2, exp_y1y2, exp_xx;
+ Word32 L_off;
+
+ BASOP_SATURATE_ERROR_ON_EVS;
+
+ /* Compute scalar product */
+ y2y2 = extract_h(Dot_product15_offs(y2, y2, L_subfr, &exp_y2y2, 5243l/*0.01f Q19*/));
+
+ /* L_off = 1L; */
+ L_off = L_shr(10737418l/*0.01f/2.0f Q31*/, sub(30-9, exp_xn));
+
+ /* Compute scalar product */
+ xny2 = extract_h(Dot_product12_offs(xn, y2, L_subfr, &exp_xny2, L_off));
+
+ /* Compute scalar product */
+ y1y2 = extract_h(Dot_product12_offs(y1, y2, L_subfr, &exp_y1y2, L_off));
+
+ /* Compute scalar product */
+ L_off = L_shr(21474836l/*0.01f Q31*/, s_min(31, sub(30, shl(exp_xn, 1))));
+ xx = extract_h(Dot_product12_offs(xn, xn, L_subfr, &exp_xx, L_off));
+
+
+ g_corr->y2y2 = y2y2;
+ move16();
+ g_corr->y2y2_e = exp_y2y2;
+ move16();
+ g_corr->xy2 = xny2;
+ move16();
+ g_corr->xy2_e = exp_xny2;
+ move16();
+ g_corr->y1y2 = y1y2;
+ move16();
+ g_corr->y1y2_e = exp_y1y2;
+ move16();
+ g_corr->xx = xx;
+ move16();
+ g_corr->xx_e = exp_xx;
+ move16();
+
+
+ BASOP_SATURATE_ERROR_OFF_EVS;
+ return;
+}
+
+
+
+/*
+ * E_ACELP_codebook_target_update
+ *
+ * Parameters:
+ * x I: old target (for pitch search) (Q_xn)
+ * x2 O: new target (for codebook search) (Q_xn)
+ * y I: filtered adaptive codebook vector (Q_xn)
+ * gain I: adaptive codebook gain (Q14)
+ *
+ * Function:
+ * Update the target vector for codebook search.
+ * Subframe size = L_SUBFR
+ * Returns:
+ * void
+ */
+void E_ACELP_codebook_target_update(Word16 *x, Word16 *x2, Word16 *y,
+ Word16 gain, Word16 L_subfr)
+{
+ Word16 i, Q15_flag;
+ Word32 L_tmp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ assert(gain >= 0);
+
+ Q15_flag = 0;
+ move16();
+ if (LT_16(gain, 1<<14))
+ {
+ Q15_flag = 1;
+ move16();
+ }
+ gain = shl(gain, Q15_flag);
+
+ FOR (i = 0; i < L_subfr; i++)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ if (Q15_flag == 0)
+ {
+#ifdef BASOP_NOGLOB
+ L_tmp = L_msu_o(L_tmp, y[i], gain, &Overflow);
+#else
+ L_tmp = L_msu(L_tmp, y[i], gain);
+#endif
+ }
+#ifdef BASOP_NOGLOB
+ x2[i] = msu_ro(L_tmp, y[i], gain, &Overflow);
+#else
+ x2[i] = msu_r(L_tmp, y[i], gain);
+#endif
+ move16();
+ }
+}
+
+
+/*
+ * E_ACELP_pulsesign
+ *
+ * Parameters:
+ * cn I: residual after long term prediction <12b
+ * dn I: corr. between target and h[]. <12b
+ * dn2 I/O: dn2[] = mix of dn[] and cn[]
+ * sign O: sign of pulse 0 or -1
+ * vec O: negative sign of pulse
+ * alp I: energy of all fixed pulses Q13
+ * sign_val I: value for signs
+ * L_subfr I: subframe length
+ *
+ * Function:
+ * Determine sign of each pulse position, store them in "sign"
+ * and change dn to all positive.
+ * Subframe size = L_SUBFR
+ * Returns:
+ * void
+ */
+void E_ACELP_pulsesign(const Word16 cn[], Word16 dn[], Word16 dn2[], Word16 sign[], Word16 vec[], const Word16 alp, const Word16 sign_val, const Word16 L_subfr)
+{
+ Word16 i;
+ Word32 Lval, Lcor;
+ Word16 k_cn, k_dn, sign_neg, e_dn, e_cn;
+ Word16 signs[3];
+ Word16 *ptr16;
+ Word16 val, index;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+ /* calculate energy for normalization of cn[] and dn[] */
+ Lval = L_mac0(1, cn[0], cn[0]);
+ Lcor = L_mac0(1, dn[0], dn[0]);
+
+ FOR (i = 1; i < L_subfr; i++)
+ {
+#ifdef BASOP_NOGLOB
+ Lval = L_mac0_o(Lval, cn[i], cn[i], &Overflow);
+#else /* BASOP_NOGLOB */
+ Lval = L_mac0(Lval, cn[i], cn[i]);
+#endif /* BASOP_NOGLOB */
+ Lcor = L_mac0(Lcor, dn[i], dn[i]);
+ }
+
+ e_dn = 31;
+ move16();
+ e_cn = 31;
+ move16();
+
+ Lval = Sqrt32(Lval, &e_dn);
+ Lcor = Sqrt32(Lcor, &e_cn);
+ i = sub(e_dn,e_cn);
+ if(i < 0)
+ Lval = L_shl(Lval, i);
+ if(i > 0)
+ Lcor = L_shr(Lcor, i);
+
+#ifdef BASOP_NOGLOB
+ k_dn = round_fx_o(Lval, &Overflow);
+ k_cn = round_fx_o(Lcor, &Overflow);
+#else /* BASOP_NOGLOB */
+ k_dn = round_fx(Lval);
+ k_cn = round_fx(Lcor);
+#endif /* BASOP_NOGLOB */
+
+ k_cn = mult_r(0x2000, k_cn); /* 1 in Q13 */
+ k_dn = mult_r(alp, k_dn); /* alp in Q13 */
+
+ sign_neg = negate(sign_val);
+
+ signs[0] = sign_neg;
+ move16();
+ signs[1] = sign_val;
+ move16();
+ signs[2] = sign_neg;
+ move16();
+ ptr16 = &signs[1];
+
+ FOR (i = 0; i < L_subfr; i++)
+ {
+ /*cor = (s * cn[i]) + (alp * dn[i]); MULT(1);MAC(1);*/
+ Lcor = L_mult(cn[i], k_cn);
+ Lcor = L_mac(Lcor, dn[i], k_dn);
+#ifdef BASOP_NOGLOB
+ val = round_fx_o(L_shl_o(Lcor,4, &Overflow), &Overflow); /*shifting by 4 may overflow but improves accuracy*/
+#else
+ val = round_fx(L_shl(Lcor,4)); /*shifting by 4 may overflow but improves accuracy*/
+#endif
+
+ index = shr(val, 15);
+ sign[i] = ptr16[index];
+ move16(); /* yields -1 (when ps < 0) or 0 (when ps >= 0) */
+ vec[i] = ptr16[index+1];
+ move16();
+
+ if (val < 0)
+ {
+ dn[i] = negate(dn[i]);
+ move16();
+ }
+ dn2[i] = abs_s(val);
+ move16(); /* dn2[] = mix of dn[] and cn[] */
+ }
+}
+
+
+void E_ACELP_findcandidates(Word16 dn2[], Word16 dn2_pos[], Word16 pos_max[])
+{
+ Word16 i, k, j, i8;
+ Word16 *ps_ptr;
+
+ FOR (i = 0; i < 4; i++)
+ {
+ i8 = shl(i, 3);
+ FOR (k = i8; k < i8+8; k++)
+ {
+ ps_ptr = &dn2[i];
+
+ FOR (j = i+4; j < L_SUBFR; j += 4)
+ {
+ if (GT_16(dn2[j], *ps_ptr))
+ {
+ ps_ptr = &dn2[j];
+ move16();
+ }
+ }
+
+ *ps_ptr = -1; /* dn2 < 0 when position is selected */ move16();
+ dn2_pos[k] = (Word16)(ps_ptr - dn2);
+ move16();
+ }
+ pos_max[i] = dn2_pos[i8];
+ move16();
+ }
+}
+
+
+static void E_ACELP_apply_sign(Word16 *p0, Word16 *psign0)
+{
+ p0[0] = mult_r( p0[0] , psign0[ 0]);
+ move16();
+ p0[1] = mult_r( p0[1] , psign0[ 4]);
+ move16();
+ p0[2] = mult_r( p0[2] , psign0[ 8]);
+ move16();
+ p0[3] = mult_r( p0[3] , psign0[12]);
+ move16();
+ p0[4] = mult_r( p0[4] , psign0[16]);
+ move16();
+ p0[5] = mult_r( p0[5] , psign0[20]);
+ move16();
+ p0[6] = mult_r( p0[6] , psign0[24]);
+ move16();
+ p0[7] = mult_r( p0[7] , psign0[28]);
+ move16();
+ p0[8] = mult_r( p0[8] , psign0[32]);
+ move16();
+ p0[9] = mult_r( p0[9] , psign0[36]);
+ move16();
+ p0[10] = mult_r( p0[10] , psign0[40]);
+ move16();
+ p0[11] = mult_r( p0[11] , psign0[44]);
+ move16();
+ p0[12] = mult_r( p0[12] , psign0[48]);
+ move16();
+ p0[13] = mult_r( p0[13] , psign0[52]);
+ move16();
+ p0[14] = mult_r( p0[14] , psign0[56]);
+ move16();
+ p0[15] = mult_r( p0[15] , psign0[60]);
+ move16();
+}
+
+void E_ACELP_vec_neg(Word16 h[], Word16 h_inv[], Word16 L_subfr)
+{
+ Word16 i;
+
+ FOR(i = 0; i < L_subfr; i ++)
+ {
+ h_inv[i] = negate(h[i]);
+ move16();
+ }
+}
+
+
+void E_ACELP_corrmatrix(Word16 h[], Word16 sign[], Word16 vec[], Word16 rrixix[4][16], Word16 rrixiy[4][256])
+{
+
+ Word16 *p0, *p1, *p2, *p3, *psign0, *psign1, *psign2, *psign3;
+ Word16 *ptr_h1, *ptr_h2, *ptr_hf;
+ Word32 cor;
+ Word16 i, /* j, */ k,pos;
+
+ /*
+ * Compute rrixix[][] needed for the codebook search.
+ */
+
+ /* storage order --> i3i3, i2i2, i1i1, i0i0 */
+
+ /* Init pointers to last position of rrixix[] */
+ p0 = &rrixix[0][16 - 1]; /* Q9 */
+ p1 = &rrixix[1][16 - 1];
+ p2 = &rrixix[2][16 - 1];
+ p3 = &rrixix[3][16 - 1];
+
+ ptr_h1 = h;
+ cor = L_deposit_l(0);
+ FOR (i = 0; i < 16; i++)
+ {
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p3-- = round_fx(L_shr(cor, 1));
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p2-- = round_fx(L_shr(cor, 1));
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p1-- = round_fx(L_shr(cor, 1));
+ cor = L_mac(cor, *ptr_h1, *ptr_h1);
+ ptr_h1++;
+ *p0-- = round_fx(L_shr(cor, 1)); /* Q9 */
+ }
+
+
+ /*
+ * Compute rrixiy[][] needed for the codebook search.
+ */
+
+ /* storage order --> i2i3, i1i2, i0i1, i3i0 */
+
+ pos = 256 - 1;
+ ptr_hf = h + 1;
+ FOR (k = 0; k < 16; k++)
+ {
+ p3 = &rrixiy[2][pos];
+ p2 = &rrixiy[1][pos];
+ p1 = &rrixiy[0][pos];
+ p0 = &rrixiy[3][pos - 16];
+
+ cor = L_deposit_h(0);
+ ptr_h1 = h;
+ ptr_h2 = ptr_hf;
+
+ FOR (i = k; i < 16-1; i++)
+ {
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p3 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p2 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p1 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p0 = round_fx(cor);
+
+ p3 -= (16 + 1);
+ p2 -= (16 + 1);
+ p1 -= (16 + 1);
+ p0 -= (16 + 1);
+ }
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p3 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p2 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p1 = round_fx(cor);
+
+ pos -= 16;
+ ptr_hf += 4;
+ }
+
+ /* storage order --> i3i0, i2i3, i1i2, i0i1 */
+
+ pos = 256 - 1;
+ ptr_hf = h + 3;
+ FOR (k = 0; k < 16; k++)
+ {
+ p3 = &rrixiy[3][pos];
+ p2 = &rrixiy[2][pos - 1];
+ p1 = &rrixiy[1][pos - 1];
+ p0 = &rrixiy[0][pos - 1];
+
+ cor = L_deposit_h(0);
+ ptr_h1 = h;
+ ptr_h2 = ptr_hf;
+ FOR (i = k; i < 16-1; i++)
+ {
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p3 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p2 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p1 = round_fx(cor);
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p0 = round_fx(cor);
+
+ p3 -= (16 + 1);
+ p2 -= (16 + 1);
+ p1 -= (16 + 1);
+ p0 -= (16 + 1);
+ }
+ cor = L_mac(cor, *ptr_h1++, *ptr_h2++);
+ *p3 = round_fx(cor);
+
+ pos--;
+ ptr_hf += 4;
+ }
+
+ /*
+ * Modification of rrixiy[][] to take signs into account.
+ */
+
+ p0 = &rrixiy[0][0];
+
+ /* speed-up: 11% */
+ p1 = &rrixiy[1][0];
+ p2 = &rrixiy[2][0];
+ p3 = &rrixiy[3][0];
+
+ FOR(i = 0; i < L_SUBFR; i += 4)
+ {
+
+ psign0 = &vec[1];
+ if (sign[i+0] > 0 ) psign0 = &sign[1];
+
+ psign1 = &vec[2];
+ if (sign[i+1] > 0 ) psign1 = &sign[2];
+
+ psign2 = &vec[3];
+ if (sign[i+2] > 0 ) psign2 = &sign[3];
+
+ psign3 = &vec[0];
+ if (sign[i+3] > 0 ) psign3 = &sign[0];
+
+ E_ACELP_apply_sign(p0, psign0);
+ p0 += 16;
+
+ E_ACELP_apply_sign(p1, psign1);
+ p1 += 16;
+
+ E_ACELP_apply_sign(p2, psign2);
+ p2 += 16;
+
+ E_ACELP_apply_sign(p3, psign3);
+ p3 += 16;
+ }
+ return;
+}
+
+void E_ACELP_4tsearch_fx(Word16 dn[], const Word16 cn[], const Word16 H[], Word16 code[],
+ const PulseConfig *config, Word16 ind[], Word16 y[])
+{
+ Word16 sign[L_SUBFR], vec[L_SUBFR];
+ Word16 cor_x[16], cor_y[16], h_buf[4 * L_SUBFR];
+ Word16 rrixix[4][16];
+ Word16 rrixiy[4][256];
+ Word16 dn2[L_SUBFR];
+ Word16 psk, ps, alpk, alp = 0;
+ Word16 codvec[NB_PULSE_MAX];
+ Word16 pos_max[4];
+ Word16 dn2_pos[8 * 4];
+ UWord8 ipos[NB_PULSE_MAX];
+ Word16 *p0, *p1, *p2, *p3;
+ Word16 *h, *h_inv;
+ Word16 i, j, k, l, st, pos;
+ Word16 val, tmp, scale;
+ Word32 s, L_tmp;
+ Word16 nb_pulse, nb_pulse_m2;
+ Word16 check = 0; /* debug code not instrumented */
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+ alp = config->alp; /* Q13 */ /* initial value for energy of all fixed pulses */ move16();
+ nb_pulse = config->nb_pulse;
+ move16();
+ nb_pulse_m2 = sub(nb_pulse, 2);
+
+ set16_fx(codvec, 0, nb_pulse);
+
+ /*
+ * Find sign for each pulse position.
+ */
+
+ E_ACELP_pulsesign(cn, dn, dn2, sign, vec, alp, 0x7fff, L_SUBFR);
+
+ /*
+ * Select the most important 8 position per track according to dn2[].
+ */
+ E_ACELP_findcandidates(dn2, dn2_pos, pos_max);
+
+ /*
+ * Compute h_inv[i].
+ */
+ set16_fx(h_buf, 0, L_SUBFR);
+
+ set16_fx(h_buf + (2 * L_SUBFR),0,L_SUBFR);
+
+ h = h_buf + L_SUBFR;
+ h_inv = h_buf + (3 * L_SUBFR);
+
+ /*Check the energy if it is too high then scale to prevent an overflow*/
+ scale = 0;
+ move16();
+ L_tmp = L_deposit_l(0);
+ BASOP_SATURATE_WARNING_OFF_EVS
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+#ifdef BASOP_NOGLOB
+ L_tmp = L_mac_o(L_tmp, H[i], H[i], &Overflow);
+#else
+ L_tmp = L_mac(L_tmp, H[i], H[i]);
+#endif
+ }
+ val = extract_h(L_tmp);
+ BASOP_SATURATE_WARNING_ON_EVS
+
+ if (GT_16(val, 0x2000))
+ {
+ scale = -1;
+ move16();
+ }
+ if (GT_16(val, 0x7000))
+ {
+ scale = -2;
+ move16();
+ }
+
+ Copy_Scale_sig(H, h, L_SUBFR, scale);
+
+ E_ACELP_vec_neg(h, h_inv, L_SUBFR);
+
+
+ /*
+ * Compute correlation matrices needed for the codebook search.
+ */
+ E_ACELP_corrmatrix(h, sign, vec, rrixix, rrixiy);
+
+
+ /*
+ * Deep first search:
+ * ------------------
+ * 20 bits (4p): 4 iter x ((4x16)+(8x16)) = 768 tests
+ * 36 bits (8p): 4 iter x ((1x1)+(4x16)+(8x16)+(8x16)) = 1280 tests
+ * 52 bits (12p): 3 iter x ((1x1)+(1x1)+(4x16)+(6x16)
+ * +(8x16)+(8x16)) = 1248 tests
+ * 64 bits (16p): 2 iter x ((1x1)+(1x1)+(4x16)+(6x16)
+ * +(6x16)+(8x16)+(8x16)+(8x16)) = 1280 tests
+ */
+ psk = -1;
+ move16();
+ alpk = 1;
+ move16();
+
+ /*Number of iterations*/
+ FOR (k = 0; k < config->nbiter; k++)
+ {
+ E_ACELP_setup_pulse_search_pos(config, k, ipos);
+
+ /* format of alp changes to Q(15-ALP2_E) */
+
+ pos = config->fixedpulses;
+ move16();
+
+ IF (config->fixedpulses == 0) /* 1100, 11, 1110, 1111, 2211 */
+ {
+ ps = 0;
+ move16();
+ alp = 0;
+ move16();
+ set16_fx(vec, 0, L_SUBFR);
+ }
+ ELSE IF (EQ_16(config->fixedpulses, 2)) /* 2222 and 3322 */
+ {
+ /* first stage: fix 2 pulses */
+ ind[0] = pos_max[ipos[0]];
+ move16();
+ ind[1] = pos_max[ipos[1]];
+ move16();
+ ps = add(dn[ind[0]], dn[ind[1]]);
+
+ /*alp = rrixix[ipos[0]][ind[0] >> 2] + rrixix[ipos[1]][ind[1] >> 2] +
+ rrixiy[ipos[0]][((ind[0] >> 2) << 4) + (ind[1] >> 2)];*/
+
+ i = shr(ind[0], 2);
+ j = shr(ind[1], 2);
+ l = add(shl(i, 4), j);
+ s = L_mult(rrixix[ipos[0]][i], _1_); /* Q9+Q12+1 */
+ s = L_mac(s, rrixix[ipos[1]][j], _1_);
+ alp = mac_r(s, rrixiy[ipos[0]][l], _1_);
+
+ p0 = h - ind[0];
+ if (sign[ind[0]] < 0)
+ {
+ p0 = h_inv - ind[0];
+ }
+
+ p1 = h - ind[1];
+ if (sign[ind[1]] < 0)
+ {
+ p1 = h_inv - ind[1];
+ }
+
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = add(*p0++, *p1++);
+ move16();
+ }
+ }
+ ELSE /* 3333 and above */
+ {
+ /* first stage: fix 4 pulses */
+
+ ind[0] = pos_max[ipos[0]];
+ move16();
+ ind[1] = pos_max[ipos[1]];
+ move16();
+ ind[2] = pos_max[ipos[2]];
+ move16();
+ ind[3] = pos_max[ipos[3]];
+ move16();
+
+ /*ps = dn[ind[0]] + dn[ind[1]] + dn[ind[2]] + dn[ind[3]];*/
+ ps = add(add(add(dn[ind[0]], dn[ind[1]]), dn[ind[2]]), dn[ind[3]]);
+
+ p0 = h - ind[0];
+ if (sign[ind[0]] < 0)
+ {
+ p0 = h_inv - ind[0];
+ }
+
+ p1 = h - ind[1];
+ if (sign[ind[1]] < 0)
+ {
+ p1 = h_inv - ind[1];
+ }
+
+ p2 = h - ind[2];
+ if (sign[ind[2]] < 0)
+ {
+ p2 = h_inv - ind[2];
+ }
+
+ p3 = h - ind[3];
+ if (sign[ind[3]] < 0)
+ {
+ p3 = h_inv - ind[3];
+ }
+
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = add(add(add(*p0++, *p1++), *p2++), *p3++);
+ move16();
+ }
+
+ L_tmp = L_mult(vec[0], vec[0]);
+ FOR (i = 1; i < L_SUBFR; i++)
+#ifdef BASOP_NOGLOB
+ L_tmp = L_mac_o(L_tmp, vec[i], vec[i], &Overflow);
+#else
+ L_tmp = L_mac(L_tmp, vec[i], vec[i]);
+#endif
+
+ alp = round_fx(L_shr(L_tmp, 3));
+
+ /*alp *= 0.5F; */
+ }
+
+ /* other stages of 2 pulses */
+ st = 0;
+ move16();
+ FOR (j = pos; j < nb_pulse; j += 2)
+ {
+ IF (GE_16(nb_pulse_m2, j)) /* pair-wise search */
+ {
+ /*
+ * Calculate correlation of all possible positions
+ * of the next 2 pulses with previous fixed pulses.
+ * Each pulse can have 16 possible positions.
+ */
+ E_ACELP_h_vec_corr1(h, vec, ipos[j], sign, rrixix, cor_x, dn2_pos, config->nbpos[st]);
+
+ E_ACELP_h_vec_corr2(h, vec, ipos[j + 1], sign, rrixix, cor_y);
+
+ /*
+ * Find best positions of 2 pulses.
+ */
+ E_ACELP_2pulse_search(config->nbpos[st], ipos[j], ipos[j + 1], &ps, &alp,
+ &ind[j], &ind[j+1], dn, dn2_pos, cor_x, cor_y, rrixiy);
+
+ }
+ ELSE /* single pulse search */
+ {
+ E_ACELP_h_vec_corr2(h, vec, ipos[j], sign, rrixix, cor_x);
+
+ E_ACELP_h_vec_corr2(h, vec, ipos[j + 1], sign, rrixix, cor_y);
+
+ E_ACELP_1pulse_search(&ipos[j], &ps, &alp,
+ &ind[j], dn, cor_x, cor_y);
+ }
+
+ IF (GT_16(nb_pulse_m2, j))
+ {
+ p0 = h - ind[j];
+ if (sign[ind[j]] < 0)
+ {
+ p0 = h_inv - ind[j];
+ }
+
+ p1 = h - ind[j + 1];
+ if (sign[ind[j + 1]] < 0)
+ {
+ p1 = h_inv - ind[j + 1];
+ }
+
+
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ tmp = add(*p0++, *p1++);
+#ifdef BASOP_NOGLOB
+ vec[i] = add_o(vec[i], tmp, &Overflow); /* can saturate here. */ move16();
+#else
+ vec[i] = add(vec[i], tmp); /* can saturate here. */ move16();
+#endif
+ }
+
+ }
+ st = add(st, 1);
+ }
+
+ /* memorise the best codevector */
+
+ /*ps = ps * ps; MULT(1);*/
+ ps = mult(ps, ps);
+ /*s = (alpk * ps) - (psk * alp); MULT(2);ADD(1);*/
+ s = L_msu(L_mult(alpk, ps), psk, alp); /*Q9+Q6+1=Q16*/
+
+ if (psk < 0)
+ {
+ s = 1;
+ }
+ IF (s > 0)
+ {
+ psk = ps;
+ move16();
+ alpk = alp;
+ move16();
+ Copy(ind,codvec, nb_pulse);
+ check = 1; /* debug code not instrumented */
+ }
+ }
+
+ assert( check ); /* debug code not instrumented */
+
+ /*
+ * Build the codeword, the filtered codeword and index of codevector, as well as store weighted correlations.
+ */
+
+ E_ACELP_build_code(nb_pulse, codvec, sign, code, ind);
+
+ set16_fx(y, 0, L_SUBFR);
+ FOR (k = 0; k 0)
+ {
+ p0 -= 2*L_SUBFR;
+ }
+ FOR (i=0; i 4 pulses in a frame of 64 samples.
+ * 36 bits 9 + 9 + 9 + 9 --> 8 pulses in a frame of 64 samples.
+ * 44 bits 13 + 9 + 13 + 9 --> 10 pulses in a frame of 64 samples.
+ * 52 bits 13 + 13 + 13 + 13 --> 12 pulses in a frame of 64 samples.
+ * 64 bits 2 + 2 + 2 + 2 + 14 + 14 + 14 + 14 -->
+ * 16 pulses in a frame of 64 samples.
+ * 72 bits 10 + 2 + 10 + 2 + 10 + 14 + 10 + 14 -->
+ * 18 pulses in a frame of 64 samples.
+ * 88 bits 11 + 11 + 11 + 11 + 11 + 11 + 11 + 11 -->
+ * 24 pulses in a frame of 64 samples.
+ *
+ * All pulses can have two (2) possible amplitudes: +1 or -1.
+ * Each pulse can sixteen (16) possible positions.
+ *
+ * Returns:
+ * void
+ */
+void E_ACELP_4t_fx(
+ Word16 dn[], Word16 cn[] /* Q_xn */, Word16 H[],
+ Word16 R[], Word8 acelpautoc,
+ Word16 code[],
+ Word16 cdk_index, Word16 _index[]
+ ,const Word16 L_frame,
+ const Word16 last_L_frame,
+ const Word32 total_brate,
+ const Word16 i_subfr,
+ const int16_t cmpl_flag
+)
+{
+ PulseConfig config;
+ Word16 ind[NPMAXPT*4];
+ Word16 y[L_SUBFR];
+
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ memcpy(&config, &PulseConfTable[cdk_index], sizeof(PulseConfTable[cdk_index]));
+
+
+ if (cmpl_flag > 0)
+ {
+ config.nbiter = cmpl_flag;
+ move16();
+ }
+ test();
+ test();
+ IF( NE_16(L_frame,last_L_frame)&&EQ_32(total_brate,ACELP_24k40)&<_32(i_subfr,5*L_SUBFR))
+ {
+ config.nbiter = sub(config.nbiter, 1);
+ config.nbiter = s_max(config.nbiter, 1);
+ }
+
+ IF (acelpautoc)
+ {
+ E_ACELP_4tsearchx_fx(dn, cn, R, code, &config, ind);
+ }
+ ELSE
+ {
+ E_ACELP_4tsearch_fx(dn, cn, H, code, &config, ind, y);
+ }
+ E_ACELP_indexing_fx(code, &config, NB_TRACK_FCB_4T, _index);
+ return;
+}
+
+static void E_ACELP_indexing_shift(
+ Word16 wordcnt, /* i: 16-bit word count including the newly shifted-in bits */
+ Word16 shift_bits, /* i: number of bits to shift in from the lsb */
+ UWord16 lsb_bits, /* i: bits to shift in from the lsb */
+ const UWord16 src[], /* i: source buffer */
+ UWord16 dst[] /* o: destination buffer */
+)
+{
+ Word16 right_shift, i;
+
+ assert(shift_bits <= 16);
+
+ right_shift = sub(16, shift_bits);
+
+ FOR (i=sub(wordcnt, 1); i>0; --i)
+ {
+ dst[i] = s_or(lshl(src[i], shift_bits), lshr(src[i-1], right_shift));
+ move16();
+ }
+ dst[i] = s_or(lshl(src[i], shift_bits), lsb_bits);
+ move16();
+ return;
+}
+
+#define MAX_IDX_LEN 9
+
+Word16 E_ACELP_indexing_fx(
+ const Word16 code[],
+ const PulseConfig *config,
+ Word16 num_tracks,
+ Word16 prm[]
+)
+{
+ Word16 track, shift_bits;
+ Word16 p[NB_TRACK_FCB_4T], wordcnt;
+ UWord32 s[NB_TRACK_FCB_4T], n[NB_TRACK_FCB_4T];
+ UWord16 idx[MAX_IDX_LEN];
+ Word16 saved_bits;
+
+ assert(num_tracks == NB_TRACK_FCB_4T);
+
+ saved_bits = 0;
+ move16();
+
+ /*
+ * Code state of pulses of all tracks
+ * */
+ wordcnt = shr(add(config->bits, 15), 4); /* ceil(bits/16) */
+
+ set16_fx((Word16*)idx, 0, wordcnt);
+
+ IF (EQ_16(config->bits, 43)) /* EVS pulse indexing */
+ {
+ saved_bits = E_ACELP_code43bit_fx(code, s, p, idx);
+ }
+ ELSE
+ {
+ FOR (track = 0; track < num_tracks; track++)
+ {
+ /* Code track of length 2^4 where step between tracks is 4. */
+ E_ACELP_codearithp_fx(code+track, &n[track], &s[track], &p[track]);
+ }
+ fcb_pulse_track_joint_fx(idx, wordcnt, s, p, num_tracks);
+ }
+
+ /* check if we need to code track positions */
+ track = 0;
+ move16();
+ shift_bits = 0;
+ move16();
+ SWITCH (config->codetrackpos)
+ {
+ case TRACKPOS_FIXED_TWO:
+ /* Code position of consecutive tracks with single extra pulses */
+ /* Find track with one pulse less. */
+ if (NE_16(p[0], p[1]))
+ {
+ /* Either 0110 or 1001 */
+ track = 1;
+ move16();
+ }
+ if (GT_16(p[3], p[1]))
+ {
+ track = add(track, 2);
+ }
+ shift_bits = 2;
+ move16();
+ BREAK;
+
+ case TRACKPOS_FREE_THREE:
+ /* Code position of track with one pulse less than others */
+ /* Find track with one pulse less. */
+ if (LT_16(p[1], p[0]))
+ {
+ track = 1;
+ move16();
+ }
+ if (LT_16(p[2], p[0]))
+ {
+ track = 2;
+ move16();
+ }
+ if (LT_16(p[3], p[0]))
+ {
+ track = 3;
+ move16();
+ }
+ shift_bits = 2;
+ move16();
+ BREAK;
+
+ case TRACKPOS_FREE_ONE:
+ /* Code position of track with one pulse less than others */
+ /* Find track with one pulse less. */
+ if (GT_16(p[1], p[0]))
+ {
+ track = 1;
+ move16();
+ }
+ if (GT_16(p[2], p[0]))
+ {
+ track = 2;
+ move16();
+ }
+ if (GT_16(p[3], p[0]))
+ {
+ track = 3;
+ move16();
+ }
+ shift_bits = 2;
+ move16();
+ BREAK;
+
+ case TRACKPOS_FIXED_EVEN:
+ case TRACKPOS_FIXED_FIRST:
+ BREAK;
+
+ default:
+ printf("Codebook mode not implemented.\n");
+ assert(0); /* mode not yet implemented*/
+ BREAK;
+ }
+
+ E_ACELP_indexing_shift(wordcnt, shift_bits, track, idx, (UWord16*)prm);
+
+ return saved_bits;
+}
+
+/*--------------------------------------------------------------------------*
+ * E_ACELP_adaptive_codebook
+ *
+ * Find adaptive codebook.
+ *--------------------------------------------------------------------------*/
+void E_ACELP_adaptive_codebook(
+ Word16 *exc, /* i/o: pointer to the excitation frame Q_new */
+ Word16 T0, /* i : integer pitch lag Q0 */
+ Word16 T0_frac, /* i : fraction of lag */
+ Word16 T0_res, /* i : pitch resolution */
+ Word16 T0_res_max, /* i : maximum pitch resolution */
+ Word16 mode, /* i : filtering mode (0: no, 1: yes, 2: adaptive) */
+ Word16 i_subfr, /* i : subframe index */
+ Word16 L_subfr, /* i : subframe length */
+ Word16 L_frame, /* i : subframe length */
+ Word16 *h1, /* i : impulse response of weighted synthesis filter 1Q14+shift */
+ Word16 clip_gain, /* i : flag to indicate ??? */
+ Word16 *xn, /* i : Close-loop Pitch search target vector Q_xn */
+ Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_xn */
+ ACELP_CbkCorr *g_corr,/* o : ACELP correlation values */
+ Word16 **pt_indice, /* i/o: quantization indices pointer */
+ Word16 *pitch_gain, /* o : adaptive codebook gain 1Q14 */
+ Word16 exp_xn /* i : exponent of xn (Q_xn-15) */
+ ,Word16 rf_mode
+ ,Word16 rf_coder_type
+ ,Word16* lp_select
+
+)
+{
+ Word16 y2[L_SUBFR], xn2[L_SUBFR], code[L_SUBFR];
+ ACELP_CbkCorr g_corr2;
+ Word16 gain1 = 0, gain2 = 0, fac_m, fac_n;
+ Word16 i, select, exp_ener;
+ Word32 L_tmp, L_ener;
+ const Word16 *pitch_inter;
+ Word16 pit_L_interpol, pit_up_samp;
+ Word16 use_prev_sf_pit_gain = 0;
+
+ if( rf_mode == 1 && rf_coder_type == 100)
+ {
+ use_prev_sf_pit_gain = 1;
+ }
+
+ BASOP_SATURATE_ERROR_ON_EVS;
+
+ L_ener = L_deposit_l(0);
+
+ /* find pitch excitation */
+ /*for &exc[i_subfr]*/
+ if (EQ_16(T0_res, shr(T0_res_max, 1)))
+ {
+ T0_frac = shl(T0_frac, 1);
+ }
+
+ IF (EQ_16(T0_res_max, 6)&&rf_mode==0)
+ {
+ pitch_inter = pitch_inter6_2;
+ pit_L_interpol = PIT_L_INTERPOL6_2;
+ move16();
+ pit_up_samp = PIT_UP_SAMP6;
+ move16();
+ }
+ ELSE
+ {
+ pitch_inter = pitch_inter4_2;
+ pit_L_interpol = L_INTERPOL2;
+ move16();
+ pit_up_samp = PIT_UP_SAMP;
+ move16();
+ }
+
+ pred_lt4( &exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, pitch_inter, pit_L_interpol, pit_up_samp);
+
+ test();
+ IF(EQ_16(mode,NORMAL_OPERATION)||(EQ_16(mode,FULL_BAND)))
+ {
+ E_UTIL_f_convolve(&exc[i_subfr], h1, y1,L_subfr);
+
+ IF(use_prev_sf_pit_gain == 0)
+ {
+ gain1 = E_ACELP_xy1_corr(xn, y1, g_corr,1,L_subfr,exp_xn);
+
+ /* clip gain if necessary to avoid problem at decoder */ test();
+ if (clip_gain && GT_16(gain1,15565/*0.95 Q14*/))
+ {
+ gain1 = 15565/*0.95f Q14*/;
+ move16();
+ }
+ *pitch_gain = gain1;
+ move16();
+ }
+
+ /* find energy of new target xn2[] */
+ E_ACELP_codebook_target_update(xn, xn2, y1, gain1, L_subfr);
+ L_ener = Dot_product12_offs(xn2, xn2, L_subfr, &exp_ener, 0);
+ L_ener = L_shr(L_ener,sub(31,exp_ener));
+ }
+
+ /*-----------------------------------------------------------------*
+ * - find pitch excitation filtered by 1st order LP filter. *
+ * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) *
+ * - compute pitch gain2 *
+ *-----------------------------------------------------------------*/ test();
+ IF(EQ_16(mode,NORMAL_OPERATION)||EQ_16(mode,LOW_PASS))
+ {
+ /* find pitch excitation with lp filter */
+ fac_m = 20972/*0.64f Q15*/;
+ move16();
+ if ( EQ_16(L_frame,L_FRAME16k))
+ {
+ fac_m = 19005/*0.58f Q15*/;
+ move16();
+ }
+ /* fac_n = 0.5*(1.0-fac_m); */
+ fac_n = mult_r(sub(0x7FFF,fac_m),0x4000);
+ FOR (i=0; iy1y1 = g_corr2.y1y1;
+ move16();
+ g_corr->xy1 = g_corr2.xy1;
+ move16();
+ g_corr->y1y1_e = g_corr2.y1y1_e;
+ move16();
+ g_corr->xy1_e = g_corr2.xy1_e;
+ move16();
+ }
+ ELSE
+ {
+ /* no filter used for pitch excitation prediction */
+ select = FULL_BAND;
+ move16();
+ *pitch_gain = gain1;
+ move16();
+ }
+
+ IF(EQ_16(mode,NORMAL_OPERATION))
+ {
+ **pt_indice = select;
+ (*pt_indice)++;
+ move16();
+ }
+ }
+ ELSE
+ {
+ /* no filter used for pitch excitation prediction */
+ select = FULL_BAND;
+ move16();
+ }
+ *lp_select=select;
+
+ BASOP_SATURATE_ERROR_OFF_EVS;
+}
+
+
+/*--------------------------------------------------------------------------*
+ * E_ACELP_innovative_codebook_fx
+ *
+ * Find innovative codebook.
+ *--------------------------------------------------------------------------*/
+void E_ACELP_innovative_codebook_fx(
+ Word16 *exc, /* i : pointer to the excitation frame Q_new */
+ Word16 T0, /* i : integer pitch lag Q0 */
+ Word16 T0_frac, /* i : fraction of lag Q0 */
+ Word16 T0_res, /* i : pitch resolution Q0 */
+ Word16 pitch_gain, /* i : adaptive codebook gain 1Q14 */
+ Word16 tilt_code, /* i : tilt factor Q15 */
+ ACELP_config* acelp_cfg,/* i/o: configuration of the ACELP */
+ Word16 i_subfr, /* i : subframe index */
+ const Word16 *Aq, /* i : quantized LPC coefficients 3Q12 */
+ Word16 *h1, /* i : impulse response of weighted synthesis filter 1Q14+shift */
+ Word16 *xn, /* i : Close-loop Pitch search target vector Q_xn */
+ Word16 *cn, /* i : Innovative codebook search target vector Q_new */
+ Word16 *y1, /* i : zero-memory filtered adaptive excitation Q_xn */
+ Word16 *y2, /* o : zero-memory filtered algebraic excitation Q9 */
+ Word8 acelpautoc, /* i : autocorrelation mode enabled */
+ Word16 **pt_indice, /* i/o: quantization indices pointer */
+ Word16 *code, /* o : innovative codebook Q9 Q9 */
+ Word16 shift, /* i : Scaling to get 12 bits */
+ const Word16 L_frame, /* i : length of the frame */
+ const Word16 last_L_frame,/* i : length of the last frame */
+ const Word32 total_brate /* i : ttoal bit-rate */
+)
+{
+ Word16 xn2[L_SUBFR] /* Q_xn */, cn2[L_SUBFR] /* Q_xn */, dn[L_SUBFR] /* Rw2*cn2 */, h2[L_SUBFR] /* 4Q11 */;
+ Word16 Rw2[L_SUBFR];
+ Word16 pitch, idx;
+
+
+ pitch = T0;
+ move16();
+ idx = shr(i_subfr, 6);
+ if (GT_16(T0_frac, shr(T0_res, 1)))
+ {
+ pitch = add(pitch,1);
+ }
+
+ BASOP_SATURATE_ERROR_ON_EVS;
+
+ /* Update target vector for ACELP codebook search */
+ E_ACELP_codebook_target_update(xn, xn2, y1, pitch_gain, L_SUBFR);
+
+ /* Include fixed-gain pitch contribution into impulse resp. h1[] */
+ Copy_Scale_sig(h1, h2, L_SUBFR, sub(-3, shift)); /*h2 1Q14+shift -> 4Q11, 1bit of headroom for Residu and xh_corr*/
+
+ cb_shape_fx(acelp_cfg->pre_emphasis, acelp_cfg->pitch_sharpening, acelp_cfg->phase_scrambling, acelp_cfg->formant_enh, acelp_cfg->formant_tilt,
+ acelp_cfg->formant_enh_num, acelp_cfg->formant_enh_den, Aq, h2, tilt_code, pitch, 1, L_SUBFR);
+
+ /* Correlation between target xn2[] and impulse response h1[] */
+ IF (acelpautoc)
+ {
+ /* h2: 4Q11, Rw2: (Rw2_e)Q */
+ /* Rw2_e = */ E_ACELP_hh_corr(h2, Rw2, L_SUBFR, 3);
+
+ E_ACELP_conv(xn2, h2, cn2);
+
+ /* dn_e -> Rw2_e*Q_xn */
+ /*dn_e = */ E_ACELP_toeplitz_mul_fx(Rw2,cn2,dn,L_SUBFR,sub((Word16)PulseConfTable[acelp_cfg->fixed_cdk_index[idx]].nb_pulse, 24) > 0);
+
+ }
+ ELSE
+ {
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ E_ACELP_codebook_target_update(cn, cn2, &exc[i_subfr], pitch_gain, L_SUBFR);
+ BASOP_SATURATE_WARNING_ON_EVS;
+ Scale_sig(cn2, L_SUBFR, shift);
+ E_ACELP_xh_corr(xn2, dn, h2, L_SUBFR);
+ }
+
+ /* Innovative codebook search */
+ assert(acelp_cfg->fixed_cdk_index[idx] < ACELP_FIXED_CDK_NB);
+
+ E_ACELP_4t_fx( dn, cn2, h2, Rw2, acelpautoc, code, acelp_cfg->fixed_cdk_index[idx], *pt_indice, L_frame, last_L_frame, total_brate, i_subfr, 0 );
+
+ *pt_indice += 8;
+
+ /* Generate weighted code */
+ E_ACELP_weighted_code(code, h2, 11, y2);
+
+ /*-------------------------------------------------------*
+ * - Add the fixed-gain pitch contribution to code[]. *
+ *-------------------------------------------------------*/
+
+ cb_shape_fx(acelp_cfg->pre_emphasis, acelp_cfg->pitch_sharpening, acelp_cfg->phase_scrambling, acelp_cfg->formant_enh, acelp_cfg->formant_tilt,
+ acelp_cfg->formant_enh_num, acelp_cfg->formant_enh_den, Aq, code, tilt_code, pitch, 1, L_SUBFR);
+
+ BASOP_SATURATE_ERROR_OFF_EVS;
+ return;
+}
+
+
+
+/*--------------------------------------------------------------------------*
+ * E_ACELP_codearithp_fx
+ *
+ * Fixed bit-length arithmetic coding of pulses
+ * v - (input) pulse vector
+ * ps - (output) encoded state
+ * n - (output) range of possible states (0...n-1)
+ * p - (output) number of pulses found
+ *--------------------------------------------------------------------------*/
+static void E_ACELP_codearithp_fx(const Word16 v[], UWord32 *n, UWord32 *ps, Word16 *p)
+{
+ Word16 k, nb_pulse, i, t, pos[NPMAXPT], posno;
+ Word16 sign, m;
+ UWord32 s;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+ Flag Carry = 0;
+#endif
+
+ /* Collect different pulse positions to pos[], number of them to posno */
+ posno = 0;
+ move16();
+ t = 0;
+ move16();
+ FOR (k=0; k= 0 )
+ {
+ BREAK;
+ }
+ }
+
+ /* Iterate over the different pulse positions */
+ s = L_deposit_l(0);
+ t = 0;
+ move16();
+ nb_pulse = 0;
+ move16();
+ FOR (k=0; k 0 )
+ {
+ BREAK;
+ }
+ }
+
+ /* Code sign */
+ /* We use L_add_c since we want to work with unsigned UWord32 */
+ /* Therefore, we have to clear carry */
+ Carry = 0;
+ s = L_lshl(s, 1);
+ if (sign < 0)
+ {
+#ifdef BASOP_NOGLOB
+ s = L_add_co(s, 1, &Carry, &Overflow);
+#else /* BASOP_NOGLOB */
+ s = L_add_c(s, 1);
+#endif /* BASOP_NOGLOB */
+ }
+
+ /* Code last pulse */
+ Carry = 0;
+#ifdef BASOP_NOGLOB
+ s = L_add_co(s, pulsestostates[pos[k]][t], &Carry, &Overflow);
+#else /* BASOP_NOGLOB */
+ s = L_add_c(s, pulsestostates[pos[k]][t]);
+#endif
+ t = add(t, 1);
+ }
+
+ *ps = s;
+ move32();
+ *n = L_deposit_l(0);
+ if (nb_pulse)
+ {
+ *n = pulsestostates[NB_POS_FCB_4T][nb_pulse-1];
+ move32();
+ }
+
+ *p = nb_pulse;
+ move16();
+ return;
+}
+
+void fcb_pulse_track_joint_fx(UWord16 *idxs, Word16 wordcnt, UWord32 *index_n, Word16 *pulse_num, Word16 track_num)
+{
+ Word16 hi_to_low[10];
+ UWord32 index, index_mask;
+ Word32 indx_tmp;
+ Word16 indx_flag, indx_flag_1;
+ Word16 track, track_num1, pulse_num0, pulse_num1;
+ Word16 indx_flag_2;
+
+ Copy(hi_to_low_tmpl, hi_to_low, 10);
+
+ indx_flag = 0;
+ move16();
+ indx_flag_1 = 0;
+ move16();
+ indx_flag_2 = 0;
+ move16();
+
+ FOR (track = 0; track < track_num; track++)
+ {
+ indx_flag = add(indx_flag, shr(pulse_num[track], 2));
+ indx_flag_1 = add(indx_flag_1, shr(pulse_num[track], 1));
+ indx_flag_2 = add(indx_flag_2, shr(pulse_num[track], 3));
+ }
+
+ IF (GE_16(indx_flag_2, 1))
+ {
+ hi_to_low[7] = 9;
+ move16();
+ index_mask = 0xFFFFFF;
+ move32();
+ }
+ ELSE
+ {
+ if (LT_16(indx_flag, track_num))
+ {
+ hi_to_low[4] = 1;
+ move16();
+ }
+ index_mask = L_shr(0xFFFF, sub(9, hi_to_low[4]));
+ }
+
+ IF (GE_16(indx_flag_1, track_num))
+ {
+ indx_tmp = L_deposit_l(0);
+ index = L_shr(index_n[0], low_len[pulse_num[0]]);
+ FOR (track = 1; track < track_num; track++)
+ {
+ pulse_num0 = pulse_num[track - 1];
+ move16();
+ pulse_num1 = pulse_num[track];
+ move16();
+ indx_tmp = L_lshr(index_n[track], low_len[pulse_num1]);
+ /* index = index * indx_fact[pulse_num1] + indx_tmp; */
+ index = UL_Mpy_32_32(index, UL_deposit_l(indx_fact[pulse_num1]));
+ index = UL_addNsD(index, indx_tmp);
+ index_n[track - 1] = L_add(L_and(index_n[track - 1], low_mask[pulse_num0]),
+ L_and(L_lshl(index, low_len[pulse_num0]), index_mask));
+
+ index = L_lshr(index, hi_to_low[pulse_num0]);
+ }
+ track_num1 = sub(track_num, 1);
+ pulse_num1 = pulse_num[track_num1];
+ move16();
+ index_n[track_num1] = L_and(L_add(L_and(index_n[track_num1], low_mask[pulse_num1]),
+ L_lshl(index, low_len[pulse_num1])), index_mask);
+ index = L_lshr(index, hi_to_low[pulse_num1]);
+ IF (GE_16(indx_flag, track_num))
+ {
+ IF (GE_16(indx_flag_2, 1))
+ {
+ idxs[0] = extract_l(index_n[0]);
+ idxs[1] = extract_l(L_add(L_lshl(index_n[1], 8), L_lshr(index_n[0], 16)));
+ idxs[2] = extract_l(L_lshr(index_n[1], 8));
+ idxs[3] = extract_l(index_n[2]);
+ idxs[4] = extract_l(L_add(L_lshl(index_n[3], 8), L_lshr(index_n[2], 16)));
+ idxs[5] = extract_l(L_lshr(index_n[3], 8));
+ track = 6;
+ move16();
+ }
+ ELSE
+ {
+ FOR (track = 0; track < track_num; track++)
+ {
+ idxs[track] = extract_l(index_n[track]);
+ }
+ }
+ }
+ ELSE
+ {
+ idxs[0] = extract_l(L_add(L_lshl(index_n[0], 8), index_n[1]));
+ idxs[1] = extract_l(L_add(L_lshl(index_n[2], 8), index_n[3]));
+ track = 2;
+ move16();
+ }
+ }
+ ELSE
+ {
+ index = index_n[0];
+ move32();
+ FOR (track = 1; track < 4; track++)
+ {
+ pulse_num1 = pulse_num[track];
+ index = L_add(L_lshl(index, index_len[pulse_num1]), index_n[track]);
+ }
+ track = 0;
+ move16();
+ }
+ FOR (; track < wordcnt; track++)
+ {
+ idxs[track] = extract_l(index);
+ index = L_lshr(index, 16);
+ }
+ return;
+}
diff --git a/lib_enc/enc_acelp_tcx_main_fx.c b/lib_enc/enc_acelp_tcx_main_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..c7ce2b0ee9a41de1007df43b9d1f9210278de307
--- /dev/null
+++ b/lib_enc/enc_acelp_tcx_main_fx.c
@@ -0,0 +1,110 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+//#include "prot_fx.h"
+#include "cnst.h" /* Common constants */
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * enc_acelp_tcx_main_fx()
+ *
+ * encoder function for coding ACELP/TCX
+ *--------------------------------------------------------------------*/
+void enc_acelp_tcx_main_fx(
+ const Word16 new_samples[], /* i : new samples */
+ Encoder_State_fx *st, /* i/o: encoder state structure */
+ Word16 Aw[NB_SUBFR16k*(M+1)], /* i : weighted A(z) unquant. for subframes*/
+ const Word16 lsp_new[M], /* i : LSPs at the end of the frame */
+ const Word16 lsp_mid[M], /* i : LSPs at the middle of the frame */
+ Word32 bwe_exc_extended[], /* i/o: bandwidth extended excitation */
+ Word16 *voice_factors, /* o : voicing factors */
+ Word16 pitch_buf[], /* o : floating pitch for each subframe */
+ Word16 vad_hover_flag, /* i : VAD hangover flag */
+ Word16 *Q_new,
+ Word16 *shift
+)
+{
+ Word16 old_bwe_exc[(PIT16k_MAX + (L_FRAME16k + 1) + L_SUBFR16k) * 2]; /* excitation buffer */
+ Word16 *ptr_bwe_exc;
+ TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD;
+
+ ptr_bwe_exc = old_bwe_exc + PIT16k_MAX * 2;
+
+ IF( EQ_16( st->last_core_fx, ACELP_CORE))
+ {
+ set16_fx( old_bwe_exc + PIT16k_MAX * 2, 0, ((L_FRAME16k + 1) + L_SUBFR16k) * 2 );
+ Copy(hBWE_TD->old_bwe_exc_fx, old_bwe_exc, PIT16k_MAX * 2 );
+ }
+ ELSE
+ {
+ set16_fx( old_bwe_exc, 0, ((L_FRAME16k + 1) + L_SUBFR16k + PIT16k_MAX) * 2 );
+ }
+
+ if (st->hPlcExt)
+ {/* PLC: [Guided ACELP PLC] */
+ gPLC_encInfo_fx(st->hPlcExt ,st->total_brate_fx, st->bwidth_fx, st->clas_fx, st->coder_type);
+ }
+ IF ( s_and(st->core_brate_fx!=FRAME_NO_DATA, st->core_brate_fx!=SID_2k40) )
+ {
+
+ /* Run Core Coder */
+ IF (st->tcxonly == 0)
+ {
+ core_encode_openloop_fx( st, st->coder_type, Aw, lsp_new, lsp_mid, pitch_buf, voice_factors, ptr_bwe_exc,
+ vad_hover_flag, st->vad_flag, *Q_new, *shift );
+ }
+ ELSE
+ {
+ core_encode_twodiv_fx( new_samples, st,st->coder_type, Aw, vad_hover_flag, Q_new, shift );
+ }
+ /*-----------------------------------------------------------------*
+ * Apply non linearity to the SHB excitation
+ *-----------------------------------------------------------------*/
+
+
+ test();
+ IF( EQ_16( st->core_fx, ACELP_CORE )&&st->igf!=0)
+ {
+ non_linearity_fx( ptr_bwe_exc, bwe_exc_extended, L_FRAME32k, &hBWE_TD->bwe_non_lin_prev_scale_fx, *Q_new
+ , st->coder_type, voice_factors, st->L_frame_fx);
+
+ /* update the old BWE exe memory */
+ Copy( &old_bwe_exc[L_FRAME32k], hBWE_TD->old_bwe_exc_fx, PIT16k_MAX * 2 );
+ }
+ ELSE
+ {
+ set16_fx(hBWE_TD->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET );
+ set16_fx(hBWE_TD->old_bwe_exc_fx, 0, PIT16k_MAX * 2 );
+ hBWE_TD->bwe_non_lin_prev_scale_fx = 0;
+ }
+ }
+ ELSE
+ {
+ /* Run SID Coder */
+ IF ( st->core_brate_fx == SID_2k40 )
+ {
+ FdCng_encodeSID_fx( st->hFdCngEnc_fx, st, st->preemph_fac );
+ }
+
+ /* Generate Comfort Noise */
+ generate_comfort_noise_enc_fx( st, *Q_new, 1 );
+
+ /* Update Core Encoder */
+ core_encode_update_cng_fx( st, st->hFdCngEnc_fx->hFdCngCom->timeDomainBuffer, st->hFdCngEnc_fx->hFdCngCom->A_cng, Aw, *Q_new, *shift );
+ }
+
+ /* coreSwitching update of MODE1 parameters in the last frame */
+ st->last_coder_type_fx = st->coder_type;
+ move16();
+
+
+ return;
+}
diff --git a/lib_enc/enc_acelpx_fx.c b/lib_enc/enc_acelpx_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..075b078ba3374ac79ba8e436683ad9c52cac7b3f
--- /dev/null
+++ b/lib_enc/enc_acelpx_fx.c
@@ -0,0 +1,617 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+//#include "prot_fx.h"
+#include "basop_util.h"
+#include "options.h"
+#include "rom_enc.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*--------------------------------------------------------------------------------------*
+ * Local constant
+ *--------------------------------------------------------------------------------------*/
+
+#define _1_Q11 (2048/*1.0f Q11*/) /* 1.0f in 4Q11 */
+/*--------------------------------------------------------------------------------------*
+ * E_ACELP_update_cor
+ *--------------------------------------------------------------------------------------*/
+static void E_ACELP_update_cor(
+ const Word16 pos[], /* i */
+ Word16 nb_pulse, /* i */
+ const Word16 sign[], /* i */
+ const Word16 R[], /* i */
+ const Word16 cor_in[], /* i */
+ Word16 cor_out[] /* o */
+)
+{
+ Word16 sign_x, sign_y;
+ const Word16 *pRx, *pRy;
+ Word16 i, tmp;
+
+ IF (EQ_16(nb_pulse, 2))
+ {
+ /* Update product of autocorrelation and already fixed pulses. with the
+ * two newly found ones */
+ sign_x = sign[pos[0]];
+ move16();
+ sign_y = sign[pos[1]];
+ move16();
+
+ IF (s_xor(sign_x, sign_y) < 0)
+ {
+ i = 1;
+ move16();
+ if (sign_x > 0)
+ {
+ i = 0;
+ move16();
+ }
+ pRx = R-pos[i];
+ pRy = R-pos[1-i];
+ /* different sign x and y */
+ FOR (i=0; i 0)
+ {
+ /* sign x and y is positive */
+ FOR (i=0; i 0 in the first iteration, the actual values do not matter. */
+ sqk[0] = -1;
+ move16();
+ alpk[0] = 1;
+ move16();
+ x = pos_x[0];
+ move16();
+ sgnx = sign[track_y];
+ move16();
+ if (sign[x] < 0)
+ {
+ sgnx = negate(sgnx);
+ }
+#ifdef BASOP_NOGLOB
+ if (mac_ro(L_mac_o(L_mac_o(alp0, cor[x], sign[x], &Overflow), cor[track_y], sign[track_y], &Overflow), R[track_y-x], sgnx, &Overflow) < 0)
+#else
+ if (mac_r(L_mac(L_mac(alp0, cor[x], sign[x]), cor[track_y], sign[track_y]), R[track_y-x], sgnx) < 0)
+#endif
+
+ {
+ sqk[0] = 1;
+ move16();
+ }
+ ik = 0;
+ move16();
+
+ xy_save = L_mac0(L_deposit_l(track_y), track_x, L_SUBFR);
+
+ /* loop track 1 */
+ FOR (i=0; i 0)
+ {
+#ifdef BASOP_NOGLOB
+ alp2_16 = mac_ro(alp2, pR[y], sign[y], &Overflow); /* Qalp = (Q_R=Q_cor)*Q_signval */
+#else
+ alp2_16 = mac_r(alp2, pR[y], sign[y]); /* Qalp = (Q_R=Q_cor)*Q_signval */
+#endif
+ }
+ if (sgnx < 0)
+ {
+#ifdef BASOP_NOGLOB
+ alp2_16 = msu_ro(alp2, pR[y], sign[y], &Overflow); /* Qalp = (Q_R=Q_cor)*Q_signval */
+#else
+ alp2_16 = msu_r(alp2, pR[y], sign[y]); /* Qalp = (Q_R=Q_cor)*Q_signval */
+#endif
+ }
+ alpk[1-ik] = alp2_16;
+ move16();
+
+ /*sq = ps2 * ps2; MULT(1);*/
+ sq = mult_r(ps2, ps2); /* (3+3)Q -> 6Q9 */
+ sqk[1-ik] = sq;
+ move16();
+
+
+ /*s = (alpk * sq) - (sqk * alp2); MULT(1);MAC(1);*/
+#ifdef BASOP_NOGLOB
+ s = L_msu_o(L_mult(alpk[ik], sq), sqk[ik], alp2_16, &Overflow); /* Q_sq = Q_sqk, Q_alpk = Q_alp */
+#else
+ s = L_msu(L_mult(alpk[ik], sq), sqk[ik], alp2_16); /* Q_sq = Q_sqk, Q_alpk = Q_alp */
+#endif
+ if (s > 0)
+ {
+ ik = sub(1, ik);
+ }
+ if (s > 0)
+ {
+ xy_save = L_mac0(y, x, L_SUBFR);
+ }
+ assert( ((s >= 0 && i==0 && y == track_y)) || (y > track_y) || (i > 0));
+ }
+ }
+ ps1 = extract_l(xy_save);
+ pos[1] = s_and(ps1, L_SUBFR-1);
+ move16();
+ pos[0] = lshr(ps1, 6);
+ move16();
+ /* Update numerator */
+ *ps = add(add(ps0,dn[pos[0]]),dn[pos[1]]);
+ move16();
+
+ /* Update denominator */
+ *alp = alpk[ik];
+ move16();
+
+ E_ACELP_update_cor(pos, 2, sign, R, cor, cor);
+
+ *ix = pos[0];
+ move16();
+ *iy = pos[1];
+ move16();
+
+ assert(((pos[0] & 3) == track_x) && ((pos[1] & 3) == track_y)); /* sanity check */
+}
+
+/*--------------------------------------------------------------------------------------*
+ * E_ACELP_1pulse_searchx
+ *--------------------------------------------------------------------------------------*/
+static void E_ACELP_1pulse_searchx(
+ UWord8 tracks[2],
+ Word16 *R,
+ Word16 *ps,
+ Word16 *alp,
+ Word16 *ix,
+ Word16 dn[],
+ Word16 cor[],
+ Word16 sign[],
+ Word16 sign_val_1
+)
+{
+ Word16 x, x_save = 0;
+ Word16 ps0;
+ Word32 alp0;
+ Word16 ps1, sq;
+ Word16 alp1;
+ Word32 s;
+ Word16 ntracks, t;
+ Word16 sqk[2], alpk[2], ik;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ /* save these to limit memory searches */
+ /*alp0 = *alp + R[0]; INDIRECT(1);*/
+ ps0 = *ps;
+ move16();
+ alp0 = L_deposit_h(*alp);
+ alp0 = L_mac(alp0, R[0], sign_val_1); /* Qalp = (Q_R=Q_cor)*Q_signval */
+
+ /* Ensure that in the loop below s > 0 in the first iteration, the actual values do not matter. */
+ move16();
+ move16();
+ alpk[0] = 1;
+ sqk[0] = -1;
+ ik = 0;
+ move16();
+#ifdef BASOP_NOGLOB
+ if (mac_ro(alp0, cor[tracks[0]], sign[tracks[0]], &Overflow) < 0)
+#else
+ if (mac_r(alp0, cor[tracks[0]], sign[tracks[0]]) < 0)
+#endif
+ {
+ sqk[0] = 1;
+ move16();
+ }
+
+ x_save = tracks[0];
+ move16();
+
+ ntracks = 1;
+ if (NE_16(tracks[1], tracks[0]))
+ {
+ ntracks = 2;
+ move16();
+ }
+ FOR (t=0; t 0)
+ {
+ ik = sub(1, ik);
+ }
+ if (s > 0)
+ {
+ x_save = x;
+ move16();
+ }
+ assert( t>0 || ((s >= 0) && (x == tracks[t])) || x > tracks[t]);
+ }
+ }
+
+ *ps = add(ps0, dn[x_save]);
+ move16();
+ *alp = alpk[ik];
+ move16();
+ *ix = x_save;
+ move16();
+}
+
+/*--------------------------------------------------------------------------------------*
+ * E_ACELP_4tsearchx_fx
+ * Autocorrelation method for searching pulse positions effectively
+ * Algorithm is identical to traditional covariance method
+ *--------------------------------------------------------------------------------------*/
+void E_ACELP_4tsearchx_fx(
+ Word16 dn[],
+ const Word16 cn[],
+ Word16 Rw[],
+ Word16 code[],
+ const PulseConfig *config,
+ Word16 ind[]
+)
+{
+ Word16 sign[L_SUBFR], vec[L_SUBFR];
+ Word16 cor[L_SUBFR];
+ Word16 R_buf[2*L_SUBFR-1], *R;
+ Word16 dn2[L_SUBFR];
+ Word16 ps2k, ps /* same format as dn[] */, ps2, alpk, alp = 0 /* Q13 and later Q_Rw*Q_signval=Q_cor*Q_signval */;
+ Word32 s;
+ Word16 codvec[NB_PULSE_MAX];
+ Word16 pos_max[4];
+ Word16 dn2_pos[8 * 4];
+ UWord8 ipos[NB_PULSE_MAX];
+ Word16 i, j, k, st, pos = 0;
+ Word16 scale;
+ Word16 sign_val_1, sign_val_2;
+ Word16 nb_pulse, nb_pulse_m2;
+
+ ps = 0; /* to avoid compilation warnings */
+
+
+
+ alp = config->alp; /* Q13 */ move16();
+ nb_pulse = config->nb_pulse;
+ move16();
+ move16();
+ nb_pulse_m2 = sub(nb_pulse, 2);
+
+ /* Init to avoid crash when the search does not find a solution */
+ FOR (k=0; k 0 in the first iteration, the actual values do not matter. */
+ ps2k = -1;
+ move16();
+ alpk = 1;
+ move16();
+
+ /* Number of iterations */
+ FOR (k = 0; k < config->nbiter; k++)
+ {
+ E_ACELP_setup_pulse_search_pos(config, k, ipos);
+
+ /* index to first non-fixed position */
+ pos = config->fixedpulses;
+ move16();
+
+ IF (config->fixedpulses == 0)/* 1100, 11, 1110, 1111, 2211 */
+ {
+ ps = 0;
+ move16();
+ alp = 0;
+ move16();
+ set16_fx(cor, 0, L_SUBFR);
+ }
+ ELSE
+ {
+ assert(config->fixedpulses == 2 || config->fixedpulses == 4);
+
+ /* set fixed positions */
+ FOR (i=0; ifixedpulses, sign, R, NULL, cor);
+
+ /* normalisation contribution of fixed part */
+ s = L_mult0(cor[ind[0]], sign[ind[0]]);
+ ps = dn[ind[0]];
+ move16();
+ FOR (i=1; i>1 sign = 2*/
+ }
+
+ /* other stages of 2 pulses */
+ st = 0;
+ move16();
+ FOR (j = pos; j < nb_pulse; j += 2)
+ {
+ IF (GE_16(nb_pulse_m2, j)) /* pair-wise search */
+ {
+ /*
+ * Calculate correlation of all possible positions
+ * of the next 2 pulses with previous fixed pulses.
+ * Each pulse can have 16 possible positions.
+ */
+
+ E_ACELP_2pulse_searchx(config->nbpos[st], ipos[j], ipos[j + 1], R, &ps, &alp,
+ &ind[j], &ind[j+1], dn, dn2_pos, cor, sign, sign_val_2);
+
+ }
+ ELSE /* single pulse search */
+ {
+ E_ACELP_1pulse_searchx(&ipos[j], R, &ps, &alp,
+ &ind[j], dn, cor, sign, sign_val_1);
+ }
+
+
+ st = add(st, 1);
+ }
+
+ /* memorise the best codevector */
+ /*ps2 = ps * ps; MULT(1);*/
+ ps2 = mult(ps, ps);
+
+ /*s = (alpk * ps2) - (ps2k * alp); MULT(2);ADD(1);*/
+ s = L_msu(L_mult(alpk, ps2), ps2k, alp);
+
+ IF (s > 0)
+ {
+ ps2k = ps2;
+ move16();
+ alpk = alp;
+ move16();
+ Copy(ind, codvec, nb_pulse);
+ }
+ }
+
+
+ /*
+ * Store weighted energy of code, build the codeword and index of codevector.
+ */
+ E_ACELP_build_code(nb_pulse, codvec, sign, code, ind);
+}
diff --git a/lib_enc/enc_amr_wb_fx.c b/lib_enc/enc_amr_wb_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..257f0901d9ea30ee987af6a29c6a5bbac3833207
--- /dev/null
+++ b/lib_enc/enc_amr_wb_fx.c
@@ -0,0 +1,267 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * encod_amr_wb()
+ *
+ * Encode excitation signal in AMR-WB IO mode
+ *-------------------------------------------------------------------*/
+void encod_amr_wb_fx(
+ Encoder_State_fx *st, /* i/o: state structure */
+ const Word16 speech[], /* i : input speech */
+ const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */
+ const Word16 Aq[], /* i : 12k8 Lp coefficient */
+ const Word16 *res, /* i : residual signal */
+ Word16 *syn, /* i/o: core synthesis */
+ Word16 *exc, /* i/o: current non-enhanced excitation */
+ Word16 *exc2, /* i/o: current enhanced excitation */
+ Word16 *pitch_buf, /* i/o: floating pitch values for each subframe */
+ Word16 hf_gain_fx[NB_SUBFR],/* o : decoded HF gain */
+ const Word16 *speech16k_fx, /* i : input speech @16kHz */
+ Word16 shift,
+ Word16 Q_new
+)
+{
+ Word16 xn[L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
+ Word16 cn[L_SUBFR]; /* Target vector in residual domain */
+ Word16 h1[L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 h2[L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 code[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */
+ Word16 gain_pit ; /* Pitch gain */
+ Word16 voice_fac; /* Voicing factor */
+ Word32 gain_code; /* Gain of code */
+ Word16 gain_inov; /* inovation gain */
+ Word16 i, i_subfr; /* tmp variables */
+ Word16 T0, T0_frac; /* close loop integer pitch and fractional part */
+ Word16 T0_min, T0_max; /* pitch variables */
+ Word16 *pt_pitch; /* pointer to floating pitch buffer */
+ Word16 g_corr[10]; /* ACELP correl, values + gain pitch */
+ Word16 clip_gain; /* LSF clip gain */
+ const Word16 *p_Aw, *p_Aq; /* pointer to LP filter coeff. vector*/
+ Word16 unbits;
+ Word32 norm_gain_code;
+ Word16 pitch_limit_flag;
+ Word16 shift_wsp;
+ Word32 L_tmp;
+ Word16 gcode16;
+ Word32 Ltmp;
+ Word32 Lgcode;
+ Word16 T_op[3]; /* pitch period for quantization */
+ Word16 lp_select, lp_flag;
+ VAD_HANDLE hVAD = st->hVAD;
+ AMRWB_IO_ENC_HANDLE hAmrwb_IO = st->hAmrwb_IO;
+ BSTR_ENC_HANDLE hBstr = st->hBstr;
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /*------------------------------------------------------------------*
+ * Initializations
+ *------------------------------------------------------------------*/
+
+ set16_fx( y2, 0, L_SUBFR );
+ set16_fx( code, 0, L_SUBFR );
+
+ pitch_limit_flag = 0;
+ move16(); /* always restrained pitch Q range in IO mode */
+ T0_max = PIT_MAX;
+ move16();
+ T0_min = PIT_MIN;
+ move16();
+ unbits = 0;
+ move16();
+
+ p_Aw = Aw;
+ p_Aq = Aq;
+ pt_pitch = pitch_buf;
+ shift_wsp = add(Q_new,shift);
+
+ Copy(st->pitch_fx, T_op, 2 );
+ if (LE_16(T_op[0],PIT_MIN))
+ {
+ T_op[0] = shl(T_op[0],1);
+ move16();
+ }
+
+ if (LE_16(T_op[1],PIT_MIN))
+ {
+ /*T_op[1] *= 2;*/
+ T_op[1] = shl(T_op[1],1);
+ move16();
+ }
+ st->acelp_cfg.fcb_mode = 0; /* flag used in inov_encode() */
+
+ /*-----------------------------------------------------------------*
+ * Select LP filtering flag
+ *-----------------------------------------------------------------*/
+
+ lp_flag = NORMAL_OPERATION;
+ if (LT_32(st->core_brate_fx, ACELP_11k60))
+ {
+ lp_flag = LOW_PASS;
+ move16();
+ }
+
+ /*------------------------------------------------------------------*
+ * ACELP subframe loop
+ *------------------------------------------------------------------*/
+ FOR ( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR )
+ {
+ /*----------------------------------------------------------------*
+ * Bandwidth expansion of A(z) filter coefficients
+ * Find the the excitation search target "xn" and innovation
+ * target in residual domain "cn"
+ * Compute impulse response, h1[], of weighted synthesis filter
+ *----------------------------------------------------------------*/
+ Copy( &res[i_subfr], &exc[i_subfr], L_SUBFR );
+
+ find_targets_fx( speech, hLPDmem->mem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq,
+ res, L_SUBFR, p_Aw, TILT_FAC_FX, xn, cn, h1 );
+
+ Copy_Scale_sig(h1, h2, L_SUBFR, -2);
+ Scale_sig(h1, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(xn, L_SUBFR, shift);
+
+ /*----------------------------------------------------------------*
+ * Close-loop pitch search and quantization
+ * Adaptive exc. construction
+ *----------------------------------------------------------------*/
+
+ *pt_pitch = pit_encode_fx(hBstr, st->acelp_cfg.pitch_bits, st->core_brate_fx, 1, L_FRAME, -1, &pitch_limit_flag, i_subfr, exc,
+ L_SUBFR, T_op, &T0_min, &T0_max, &T0, &T0_frac, h1, xn
+ , 0 /*hStereoTD->tdm_Pitch_reuse_flag*/, NULL /*hStereoTD->tdm_Pri_pitch_buf*/);
+
+ /*-----------------------------------------------------------------*
+ * Find adaptive exitation
+ *-----------------------------------------------------------------*/
+
+ pred_lt4(&exc[i_subfr], &exc[i_subfr], T0, T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP);
+
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ * or in case of floating point encoder & fixed p. decoder
+ *-----------------------------------------------------------------*/
+
+ clip_gain = gp_clip_fx(st->element_mode, st->core_brate_fx, st->voicing_fx, i_subfr, 0, xn, st->clip_var_fx, sub(shift_wsp,1));
+
+ /*-----------------------------------------------------------------*
+ * LP filtering of the adaptive excitation, codebook target computation
+ *-----------------------------------------------------------------*/
+
+ lp_select = lp_filt_exc_enc_fx( MODE1, -1, i_subfr, exc, h1,
+ xn, y1, xn2, L_SUBFR, L_FRAME, g_corr, clip_gain, &gain_pit, &lp_flag );
+
+ IF( EQ_16(lp_flag,NORMAL_OPERATION))
+ {
+ push_indice_fx(hBstr, IND_LP_FILT_SELECT, lp_select, 1 );
+ }
+
+ /*-----------------------------------------------------------------*
+ * Innovation encoding
+ *-----------------------------------------------------------------*/
+ inov_encode_fx( st, st->core_brate_fx, 1, L_FRAME, st->last_L_frame_fx, -1, -1, 0, i_subfr, -1, p_Aq, gain_pit, cn,
+ exc, h2, hLPDmem->tilt_code, *pt_pitch, xn2, code, y2, &unbits, L_SUBFR, shift );
+ /*-----------------------------------------------------------------*
+ * Gain encoding
+ * Pitch gain clipping test
+ * Estimate spectrum tilt and voicing
+ *-----------------------------------------------------------------*/
+ gain_enc_amr_wb_fx(hBstr, xn, shift_wsp, y1, y2, code, st->core_brate_fx, &gain_pit, &gain_code,
+ &gain_inov, &norm_gain_code, g_corr, clip_gain, hAmrwb_IO->past_qua_en_fx );
+
+ gp_clip_test_gain_pit_fx(st->element_mode, st->core_brate_fx, gain_pit, st->clip_var_fx );
+#ifdef BASOP_NOGLOB
+ Lgcode = L_shl_o(gain_code, Q_new, &Overflow); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx_o(Lgcode, &Overflow);
+#else /* BASOP_NOGLOB */
+ Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx(Lgcode);
+#endif /* BASOP_NOGLOB */
+
+ hLPDmem->tilt_code = Est_tilt2( exc+i_subfr, gain_pit, code, Lgcode, &voice_fac, shift );
+
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+#ifdef BASOP_NOGLOB
+ exc2[i+i_subfr] = round_fx_o(L_shl_o(L_mult(gain_pit,exc[i+i_subfr]),1, &Overflow), &Overflow);
+#else /* BASOP_NOGLOB */
+ exc2[i+i_subfr] = round_fx(L_shl(L_mult(gain_pit,exc[i+i_subfr]),1));
+#endif /* BASOP_NOGLOB */
+ }
+
+ /*-----------------------------------------------------------------*
+ * Update memory of the weighting filter
+ *-----------------------------------------------------------------*/
+
+ /*st->mem_w0 = xn[L_SUBFR-1] - gain_pit * y1[L_SUBFR-1] - gain_code * y2[L_SUBFR-1];*/
+ Ltmp = L_mult(gcode16, y2[L_SUBFR - 1]);
+ Ltmp = L_shl(Ltmp, add(5, shift));
+ Ltmp = L_negate(Ltmp);
+ Ltmp = L_mac(Ltmp, xn[L_SUBFR - 1], 16384);
+ Ltmp = L_msu(Ltmp, y1[L_SUBFR - 1], gain_pit);
+ Ltmp = L_shl(Ltmp, sub(1, shift));
+ hLPDmem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */
+
+ /*-----------------------------------------------------------------*
+ * Find the total excitation
+ *-----------------------------------------------------------------*/
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = L_mult(gcode16, code[i]);
+ L_tmp = L_shl(L_tmp, 5);
+ L_tmp = L_mac(L_tmp, exc[i + i_subfr], gain_pit);
+#ifdef BASOP_NOGLOB
+ L_tmp = L_shl_o(L_tmp, 1, &Overflow); /* saturation can occur here */
+ exc[i + i_subfr] = round_fx_o(L_tmp, &Overflow);
+#else /* BASOP_NOGLOB */
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ exc[i + i_subfr] = round_fx(L_tmp);
+#endif
+ }
+
+ /*-----------------------------------------------------------------*
+ * Synthesize speech to update mem_syn[]
+ * Update A(z) filters
+ *-----------------------------------------------------------------*/
+ Syn_filt_s(1, p_Aq, M, &exc[i_subfr], &syn[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1 );
+
+ /*-----------------------------------------------------------------*
+ * HF gain modification factors at 23.85 kbps
+ *-----------------------------------------------------------------*/
+
+ IF ( EQ_32(st->core_brate_fx,ACELP_23k85))
+ {
+ IF( GE_32(st->input_Fs_fx,16000))
+ {
+ hf_cod_fx( st->core_brate_fx, &speech16k_fx[i_subfr * L_SUBFR16k/L_SUBFR], Aq, &exc[i_subfr], &syn[i_subfr],
+ &hAmrwb_IO->seed2_enc, hAmrwb_IO->mem_hp400_enc_fx, hAmrwb_IO->mem_syn_hf_enc_fx, hAmrwb_IO->mem_hf_enc_fx, hAmrwb_IO->mem_hf2_enc_fx,
+ hVAD->hangover_cnt, &hAmrwb_IO->gain_alpha_fx, &hf_gain_fx[i_subfr/L_SUBFR], add(Q_new,1), st->Q_syn);
+ }
+
+ push_indice_fx(hBstr, IND_HF_GAIN_MODIFICATION, hf_gain_fx[i_subfr/L_SUBFR], 4 );
+ }
+
+ p_Aw += (M+1);
+ p_Aq += (M+1);
+ pt_pitch++;
+ }
+
+ return;
+}
diff --git a/lib_enc/enc_gain_fx.c b/lib_enc/enc_gain_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..3cd54b0065327944179a44c11546cb7ca6ce46e3
--- /dev/null
+++ b/lib_enc/enc_gain_fx.c
@@ -0,0 +1,398 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+//#include "prot_fx.h"
+#include "rom_com_fx.h"
+#include "rom_com.h"
+#include "rom_enc.h"
+#include "basop_util.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*
+ * E_GAIN_norm_corr
+ *
+ * Parameters:
+ * exc I: excitation buffer (Q_new)
+ * xn I: target signal (Q_new+shift-1)
+ * h I: weighted synthesis filter impulse response (Q14+shift)
+ * t0_min I: minimum value in the searched range
+ * t0_max I: maximum value in the searched range
+ * corr_norm O: normalized correlation (Q15+(Q_new+shift-1)+scale)
+ *
+ * Function:
+ * Find the normalized correlation between the target vector and the
+ * filtered past excitation (correlation between target and filtered
+ * excitation divided by the square root of energy of filtered excitation)
+ * Size of subframe = L_SUBFR.
+ *
+ * Returns:
+ * void
+ */
+void E_GAIN_norm_corr(Word16 exc[], Word16 xn[], Word16 h[],
+ Word16 t_min, Word16 t_max, Word16 corr_norm[], Word16 L_subfr)
+{
+ Word16 excf[L_SUBFR]; /* filtered past excitation (Q_new+shift-1) */
+ Word16 ps, norm, exp_alp, exp_ps, scale, L_subfr2;
+ Word16 t, j, k;
+ Word32 L_tmp, L_tmp2;
+
+
+ k = negate(t_min);
+ L_subfr2 = shr(L_subfr, 1);
+
+ /* compute the filtered excitation for the first delay t_min */
+ E_UTIL_f_convolve(&exc[k], h, excf,L_subfr);
+
+ /* Compute rounded down 1/sqrt(energy of xn[]) */
+ Dot_product12_offs(xn, xn, L_subfr, &scale, 1);
+
+ scale = add(scale, 2+1); /* energy of xn[] x 2 + rounded up */
+ scale = negate(shr(scale, 1)); /* (1< 0; j--)
+ {
+ /*excf[j] = excf[j - 1] + exc[k] * h[j]; MAC(1); STORE(1);*/
+ /* saturation can occur in add() */
+ excf[j] = add(mult_r(exc[k], h[j]), excf[j - 1]);
+ move16();
+
+ }
+ excf[0] = mult_r(exc[k],h[0]);
+ move16();
+ }
+ /* Last reduced iteration for t=t_max */
+ L_tmp = Dot_product12_offs(xn, excf, L_subfr, &exp_ps, 1);
+ ps = extract_h(L_tmp);
+
+
+ /* Compute 1/sqrt(energy of excf[]) */
+ L_tmp = Dot_product12_offs(excf, excf, L_subfr2, NULL, 1);
+ L_tmp2 = Dot_product12_offs(excf+L_subfr2, excf+L_subfr2, L_subfr2, NULL, 1);
+ exp_alp = sub(s_min(norm_l(L_tmp), norm_l(L_tmp2)), 1);
+ L_tmp = L_add(L_shl(L_tmp, exp_alp), L_shl(L_tmp2, exp_alp));
+ exp_alp = sub(31+1, exp_alp);
+
+
+ /*norm = (Float32)(1.0F / sqrt(alp)); SQRT(1);*/
+ L_tmp = ISqrt32(L_tmp, &exp_alp);
+ norm = extract_h(L_tmp);
+
+ /* Normalize correlation = correlation * (1/sqrt(energy)) */
+ /*corr_norm[t-t_min] = ps * norm; MULT(1); STORE(1);*/
+ L_tmp = L_mult(ps, norm);
+ L_tmp = L_shl(L_tmp, add(add(exp_ps, exp_alp), scale));
+ corr_norm[t-t_min] = round_fx(L_tmp);
+
+ return;
+}
+
+
+/*
+ * E_GAIN_norm_corr_interpolate
+ *
+ * Parameters:
+ * x I: input vector
+ * frac I: fraction (-4..+3)
+ *
+ * Function:
+ * Interpolating the normalized correlation
+ *
+ * Returns:
+ * interpolated value
+ */
+static Word16 E_GAIN_norm_corr_interpolate(Word16 *x, Word16 frac)
+{
+ Word16 *x1, *x2, i;
+ const Word16 *c1, *c2;
+ Word32 s;
+
+ IF (frac < 0)
+ {
+ frac = add(frac,4);
+ x--;
+ }
+
+ x1 = &x[0];
+ x2 = &x[1];
+ c1 = &E_ROM_inter4_1_fx[frac];
+ c2 = &E_ROM_inter4_1_fx[4 - frac];
+
+ /*s = x1[0] * c1[0] + x2[0] * c2[0];
+ s += x1[-1] * c1[4] + x2[1] * c2[4];
+ s += x1[-2] * c1[8] + x2[2] * c2[8];
+ s += x1[-3] * c1[12] + x2[3] * c2[12];*/
+
+ s = L_deposit_l(0);
+ FOR (i = 0; i < 4; i++)
+ {
+ s = L_mac(s,*x1--,*c1);
+ s = L_mac(s,*x2++,*c2);
+ c1 += 4;
+ c2 += 4;
+ }
+
+ return round_fx(L_shl(s, 1));
+}
+
+static Word16 E_GAIN_norm_corr_interpolate6(Word16 *x, Word16 frac)
+{
+ Word16 *x1, *x2, i;
+ const Word16 *c1, *c2;
+ Word32 s;
+
+ IF (frac < 0)
+ {
+ frac = add(frac,6);
+ x--;
+ }
+
+ x1 = &x[0];
+ x2 = &x[1];
+ c1 = &E_ROM_inter6_1_fx[frac];
+ c2 = &E_ROM_inter6_1_fx[6 - frac];
+
+ /*s = x1[0] * c1[0] + x2[0] * c2[0];
+ s += x1[-1] * c1[6] + x2[1] * c2[6];
+ s += x1[-2] * c1[12] + x2[2] * c2[12];
+ s += x1[-3] * c1[18] + x2[3] * c2[18];*/
+ s = L_deposit_l(0);
+ FOR (i = 0; i < 4; i++)
+ {
+ s = L_mac(s,*x1--,*c1);
+ s = L_mac(s,*x2++,*c2);
+ c1 += 6;
+ c2 += 6;
+ }
+
+ return round_fx(L_shl(s, 1));
+}
+
+/*
+ * E_GAIN_closed_loop_search_fx
+ *
+ * Parameters:
+ * exc I: excitation buffer
+ * xn I: target signal
+ * h I: weighted synthesis filter impulse response
+ * dn I: residual domain target signal
+ * t0_min I: minimum value in the searched range
+ * t0_max I: maximum value in the searched range
+ * pit_frac O: chosen fraction
+ * i_subfr I: flag to first subframe
+ * t0_fr2 I: minimum value for resolution 1/2
+ * t0_fr1 I: minimum value for resolution 1
+ *
+ * Function:
+ * Find the closed loop pitch period with 1/4 subsample resolution.
+ *
+ * Returns:
+ * chosen integer pitch lag
+ */
+Word16 E_GAIN_closed_loop_search_fx(Word16 exc[],
+ Word16 xn[], Word16 h[],
+ Word16 t0_min, Word16 t0_min_frac, Word16 t0_max, Word16 t0_max_frac, Word16 t0_min_max_res, Word16 *pit_frac, Word16 *pit_res, Word16 pit_res_max,
+ Word16 i_subfr, Word16 pit_min, Word16 pit_fr2, Word16 pit_fr1, Word16 L_subfr)
+{
+ Word16 corr_v[32 + 2 * L_INTERPOL1 + 1];
+ Word16 cor_max, max, temp;
+ Word16 *corr;
+ Word16 i, fraction, frac1, frac2, step;
+ Word16 t0, t_min, t_max;
+
+ set16_fx(corr_v, 0, 32 + 2 * L_INTERPOL1 + 1);
+ /* Find interval to compute normalized correlation */
+ if (t0_min_frac>0)
+ {
+ t0_min = add(t0_min,1);
+ }
+ t_min = sub(t0_min,L_INTERPOL1);
+ t_max = add(t0_max,L_INTERPOL1);
+
+ /* allocate memory to normalized correlation vector */
+ corr = &corr_v[negate(t_min)]; /* corr[t_min..t_max] */
+
+ /* Compute normalized correlation between target and filtered excitation */
+ E_GAIN_norm_corr(exc, xn, h, t_min, t_max, corr_v, L_subfr);
+
+ /* find integer pitch */
+ max = corr[t0_min];
+ move16();
+ t0 = t0_min;
+ move16();
+
+ FOR(i = t0_min + 1; i <= t0_max; i++)
+ {
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ if( GE_16(corr[i],max))
+ {
+ t0 = i;
+ move16();
+ }
+ max = s_max(max, corr[i]);
+ BASOP_SATURATE_WARNING_ON_EVS;
+ }
+
+
+
+ /* If first subframe and t0 >= pit_fr1, do not search fractionnal pitch */
+ test();
+ IF((i_subfr == 0) && GE_16(t0,pit_fr1))
+ {
+ *pit_frac = 0;
+ move16();
+ *pit_res = 1;
+ move16();
+ return(t0);
+ }
+
+
+ /*
+ * Search fractionnal pitch
+ * Test the fractions around t0 and choose the one which maximizes
+ * the interpolated normalized correlation.
+ */
+
+ IF ( EQ_16(t0_min_max_res,shr(pit_res_max,1)))
+ {
+ t0_min_frac = shl(t0_min_frac,1);
+ t0_max_frac = shl(t0_max_frac,1);
+ }
+
+ step = 1;
+ frac1 = sub(1,pit_res_max);
+ frac2 = sub(pit_res_max,1);
+
+ test();
+ test();
+ IF (((i_subfr == 0) && GE_16(t0,pit_fr2))||LE_16(pit_fr2,pit_min))
+ {
+ step = 2;
+ frac1 = sub(2,pit_res_max);
+ frac2 = sub(pit_res_max,2);
+ }
+ test();
+ IF ( (EQ_16(t0,t0_min))&&(t0_min_frac==0))
+ {
+ frac1 = t0_min_frac;
+ move16();
+ }
+ ELSE
+ {
+ test();
+ IF ( (EQ_16(t0,t0_min))&&(LT_16(add(frac1,pit_res_max),t0_min_frac)))
+ {
+ frac1 = sub(t0_min_frac,pit_res_max);
+ }
+ }
+
+ if (EQ_16(t0,t0_max))
+ {
+ frac2 = t0_max_frac;
+ move16();
+ }
+ assert(frac1<=0 && frac2>=0 && frac2>frac1);
+
+ IF (EQ_16(pit_res_max,6))
+ {
+ cor_max = E_GAIN_norm_corr_interpolate6(&corr[t0], frac1);
+ fraction = frac1;
+
+ FOR (i = (frac1 + step); i <= frac2; i += step)
+ {
+ temp = E_GAIN_norm_corr_interpolate6(&corr[t0], i);
+ IF (GT_16(temp,cor_max))
+ {
+ cor_max = temp;
+ move16();
+ fraction = i;
+ move16();
+ }
+
+ }
+ }
+ ELSE
+ {
+ cor_max = E_GAIN_norm_corr_interpolate(&corr[t0], frac1);
+ fraction = frac1;
+
+ FOR (i = (frac1 + step); i <= frac2; i += step)
+ {
+ temp = E_GAIN_norm_corr_interpolate(&corr[t0], i);
+ IF (GT_16(temp,cor_max))
+ {
+ cor_max = temp;
+ move16();
+ fraction = i;
+ move16();
+ }
+
+ }
+ }
+
+ /* limit the fraction value */
+ IF (fraction < 0)
+ {
+ fraction = add(fraction,pit_res_max);
+ t0 = sub(t0,1);
+ }
+ test();
+ test();
+ IF (((i_subfr == 0) && GE_16(t0,pit_fr2))||LE_16(pit_fr2,pit_min))
+ {
+ *pit_res = shr(pit_res_max,1);
+ move16();
+ *pit_frac = shr(fraction,1);
+ move16();
+ }
+ ELSE
+ {
+ *pit_res = pit_res_max;
+ move16();
+ *pit_frac = fraction;
+ move16();
+ }
+ return (t0);
+}
+
diff --git a/lib_enc/enc_gen_voic_fx.c b/lib_enc/enc_gen_voic_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..9d341bd3ebc7f39d1ad65bf2c46582fb8057810a
--- /dev/null
+++ b/lib_enc/enc_gen_voic_fx.c
@@ -0,0 +1,428 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+/*======================================================================*/
+/* FUNCTION : encod_gen_voic_fx() */
+/*----------------------------------------------------------------------*/
+/* PURPOSE : encode generic (GC), voiced (VC) and AMR-WB IO frames */
+/* */
+/*----------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ (Struct) st_fx : encoder static memory */
+/* _ (Word16) L_frame_fx : length of the frame Q0 */
+
+/* _ (Word16[]) speech_fx : input speech Q0 */
+/* _ (Word16[]) Aq_fx : LP filter coefficient Q12 */
+/* _ (Word16[]) A_fx : unquantized A(z) filter */
+/* with bandwidth expansion Q12 */
+/* _ (Word16) coder_type_fx : coding type */
+/* _ (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */
+/* _ (Word16[]) T_op_fx : open loop pitch Q0 */
+/* _ (Word16[]) voicing_fx : floating pitch values for each subframe Q15*/
+/* _ (Word16[]) res_fx : residual signal Q_new */
+/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */
+/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q0) */
+/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/
+/* _ (Word16) shift : shift */
+/* _ (Word16) Q_new : */
+/*-----------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */
+/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Q0) */
+/* _ (Word16[]) syn_fx :core synthesis Q_new */
+/* _ (Word16[]) voice_factors_fx: voicing factors Q15 */
+/* _ (Word16[]) bwe_exc_fx : excitation for SWB TBE Q0 */
+/*-----------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*=======================================================================*/
+
+void encod_gen_voic_fx(
+ Encoder_State_fx *st_fx, /* i/o: state structure */
+ const Word16 speech_fx[], /* i : input speech */
+ const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */
+ const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */
+ const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */
+ const Word16 *res_fx, /* i : residual signal */
+ Word16 *syn_fx, /* i/o: core synthesis */
+ Word16 *exc_fx, /* i/o: current non-enhanced excitation */
+ Word16 *exc2_fx, /* i/o: current enhanced excitation */
+ Word16 *pitch_buf_fx, /* i/o: floating pitch values for each subframe */
+ Word16 *voice_factors_fx, /* o : voicing factors */
+ Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */
+ Word16 *unbits_fx, /* i/o: number of unused bits */
+ const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */
+ const Word16 tdm_Pri_pitch_buf[], /* i : primary channel pitch buffer */
+ Word16 shift,
+ Word16 Q_new
+)
+{
+ Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2_fx[L_SUBFR]; /* Target vector for codebook search */
+ Word16 cn_fx[L_SUBFR]; /* Target vector in residual domain */
+ Word16 h1_fx[L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 h2_fx[L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 code_fx[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y1_fx[L_SUBFR]= {0}; /* Filtered adaptive excitation */
+ Word16 y2_fx[L_SUBFR]; /* Filtered algebraic excitation */
+ Word16 gain_pit_fx = 0; /* Pitch gain */
+ Word16 voice_fac_fx; /* Voicing factor */
+ Word32 gain_code_fx = 0; /* Gain of code */
+ Word16 gain_inov_fx=0; /* inovation gain */
+ Word32 gc_mem[NB_SUBFR-1]; /* gain_code from previous subframes */
+ Word16 gp_mem[NB_SUBFR-1]; /* gain_pitch from previous subframes*/
+ Word16 i, i_subfr_fx; /* tmp variables */
+ Word16 T0_fx=0, T0_frac_fx=0; /* close loop integer pitch and fractional part */
+ Word16 T0_min_fx, T0_max_fx; /* pitch variables */
+ Word16 *pt_pitch_fx; /* pointer to floating pitch buffer */
+ Word16 g_corr_fx[10]; /* ACELP correl, values + gain pitch */
+ Word16 clip_gain_fx; /* LSF clip gain */
+ const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector*/
+ Word16 error_fx = 0;
+ Word16 gain_preQ_fx = 0; /* Gain of prequantizer excitation */
+ Word16 code_preQ_fx[L_SUBFR]; /* Prequantizer excitation */
+ Word16 unbits_PI_fx = 0; /* number of unused bits for PI */
+ Word32 norm_gain_code_fx=0;
+ Word16 pitch_limit_flag;
+ Word16 gcode16;
+ Word32 Ltmp;
+ Word32 Ltmp1;
+ Word32 Lgcode;
+ Word16 tmp1_fx;
+ Word16 shift_wsp;
+ Word16 harm_flag_acelp;
+ Word16 lp_select, lp_flag, L_frame;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+ SP_MUS_CLAS_HANDLE hSpMusClas = st_fx->hSpMusClas;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+
+ /*------------------------------------------------------------------*
+ * Initializations
+ *------------------------------------------------------------------*/
+
+ gain_pit_fx = 0;
+ move16();
+ gain_code_fx = L_deposit_l(0);
+ gain_preQ_fx = 0;
+ move16();
+ unbits_PI_fx = 0;
+ move16();
+ error_fx = 0;
+ move16();
+ L_frame = st_fx->L_frame_fx;
+ move16();
+
+
+ IF( EQ_16(L_frame,L_FRAME))
+ {
+ T0_max_fx = PIT_MAX;
+ move16();
+ T0_min_fx = PIT_MIN;
+ move16();
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ T0_max_fx = PIT16k_MAX;
+ move16();
+ T0_min_fx = PIT16k_MIN;
+ move16();
+ }
+ lp_flag = st_fx->acelp_cfg.ltf_mode;
+ move16();
+
+ *unbits_fx = 0;
+ move16();
+
+ p_Aw_fx = Aw_fx;
+ p_Aq_fx = Aq_fx;
+ pt_pitch_fx = pitch_buf_fx;
+ gain_preQ_fx = 0;
+ move16();
+ set16_fx( code_preQ_fx, 0, L_SUBFR );
+
+ shift_wsp = add(Q_new,shift);
+
+ /* set and write harmonicity flag */
+ harm_flag_acelp = 0;
+ move16();
+ test();
+ test();
+ IF( GE_32(st_fx->core_brate_fx, MIN_BRATE_AVQ_EXC) && LE_32(st_fx->core_brate_fx, MAX_BRATE_AVQ_EXC_TD) && EQ_16(st_fx->coder_type,GENERIC))
+ {
+ if( GT_16(st_fx->last_harm_flag_acelp_fx,2))
+ {
+ harm_flag_acelp = 1;
+ move16();
+ }
+
+ push_indice_fx(hBstr, IND_HARM_FLAG_ACELP, harm_flag_acelp, 1 );
+ }
+
+ /*------------------------------------------------------------------*
+ * ACELP subframe loop
+ *------------------------------------------------------------------*/
+
+ FOR( i_subfr_fx=0; i_subfr_fxmem_syn, i_subfr_fx, &hLPDmem->mem_w0, p_Aq_fx,
+ res_fx, L_SUBFR, p_Aw_fx, st_fx->preemph_fac, xn_fx, cn_fx, h1_fx );
+
+ Copy_Scale_sig( h1_fx, h2_fx, L_SUBFR, -2 );
+ Scale_sig( h1_fx, L_SUBFR, add(1, shift) ); /* set h1[] in Q14 with scaling for convolution */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig( xn_fx, L_SUBFR, shift );
+
+ *pt_pitch_fx = pit_encode_fx(hBstr, st_fx->acelp_cfg.pitch_bits, st_fx->core_brate_fx, 0, L_frame, st_fx->coder_type, &pitch_limit_flag, i_subfr_fx, exc_fx,
+ L_SUBFR, st_fx->pitch_fx, &T0_min_fx, &T0_max_fx, &T0_fx, &T0_frac_fx, h1_fx, xn_fx , tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf);
+
+ tbe_celp_exc(L_frame,i_subfr_fx,T0_fx, T0_frac_fx, &error_fx, bwe_exc_fx);
+
+ /*-----------------------------------------------------------------*
+ * Find adaptive exitation
+ *-----------------------------------------------------------------*/
+
+ pred_lt4(&exc_fx[i_subfr_fx], &exc_fx[i_subfr_fx], T0_fx, T0_frac_fx, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP);
+
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ *-----------------------------------------------------------------*/
+
+ clip_gain_fx = gp_clip_fx(st_fx->element_mode, st_fx->core_brate_fx, st_fx->voicing_fx,i_subfr_fx,st_fx->coder_type,xn_fx,st_fx->clip_var_fx,sub(shift_wsp, 1));
+
+ if( EQ_16(st_fx->coder_type,INACTIVE))
+ {
+ /* in case of AVQ inactive, limit the gain to 0.65 */
+ clip_gain_fx = 2;
+ move16();
+ }
+
+ /*-----------------------------------------------------------------*
+ * LP filtering of the adaptive excitation, codebook target computation
+ *-----------------------------------------------------------------*/
+
+ lp_select = lp_filt_exc_enc_fx( MODE1, st_fx->coder_type, i_subfr_fx, exc_fx, h1_fx,
+ xn_fx, y1_fx, xn2_fx, L_SUBFR, L_frame, g_corr_fx, clip_gain_fx, &gain_pit_fx, &lp_flag );
+
+ IF( EQ_16(lp_flag,NORMAL_OPERATION))
+ {
+ push_indice_fx(hBstr, IND_LP_FILT_SELECT, lp_select, 1 );
+ }
+
+ /*st_fx->lowrate_pitchGain = 0.9f * st_fx->lowrate_pitchGain + 0.1f * gain_pit_fx;*/
+#ifdef BASOP_NOGLOB
+ hSpMusClas->lowrate_pitchGain = round_fx_o(L_mac_o(L_mult(29491, hSpMusClas->lowrate_pitchGain), 6554, gain_pit_fx, &Overflow), &Overflow); /*Q14*Q16(0.1) + Q15 -> Q15*/
+#else
+ hSpMusClas->lowrate_pitchGain = round_fx(L_mac(L_mult(29491, hSpMusClas->lowrate_pitchGain), 6554, gain_pit_fx)); /*Q14*Q16(0.1) + Q15 -> Q15*/
+#endif
+
+ /*-----------------------------------------------------------------*
+ * Transform domain contribution encoding - active frames
+ *-----------------------------------------------------------------*/
+
+ test();
+ IF( GE_32(st_fx->core_brate_fx, MIN_BRATE_AVQ_EXC )&& NE_16(st_fx->coder_type,INACTIVE))
+ {
+ transf_cdbk_enc_fx( st_fx, harm_flag_acelp, i_subfr_fx, cn_fx, exc_fx, p_Aq_fx, p_Aw_fx, h1_fx, xn_fx,
+ xn2_fx, y1_fx, y2_fx, Es_pred_fx, &gain_pit_fx, gain_code_fx, g_corr_fx, clip_gain_fx, &gain_preQ_fx, code_preQ_fx, unbits_fx, Q_new, shift);
+ }
+
+ /*-----------------------------------------------------------------*
+ * Innovation encoding
+ *-----------------------------------------------------------------*/
+
+ inov_encode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame, st_fx->last_L_frame_fx,
+ st_fx->coder_type, st_fx->bwidth_fx, st_fx->sharpFlag, i_subfr_fx, -1, p_Aq_fx,
+ gain_pit_fx, cn_fx, exc_fx, h2_fx, hLPDmem->tilt_code, *pt_pitch_fx, xn2_fx, code_fx, y2_fx, &unbits_PI_fx, L_SUBFR, shift );
+
+ /*-----------------------------------------------------------------*
+ * Gain encoding
+ *-----------------------------------------------------------------*/
+
+ IF ( LE_32(st_fx->core_brate_fx,ACELP_8k00))
+ {
+ gain_enc_lbr_fx(hBstr, st_fx->acelp_cfg.gains_mode, st_fx->coder_type, i_subfr_fx, xn_fx, y1_fx, shift_wsp, y2_fx, code_fx,
+ &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx, g_corr_fx, gc_mem, gp_mem, clip_gain_fx, L_SUBFR );
+ }
+ ELSE IF ( GT_32(st_fx->core_brate_fx,ACELP_32k))
+ {
+ gain_enc_SQ_fx(hBstr, st_fx->acelp_cfg.gains_mode, i_subfr_fx, xn_fx, y1_fx, y2_fx, code_fx, Es_pred_fx,
+ &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx, g_corr_fx, clip_gain_fx, shift_wsp );
+ }
+ ELSE
+ {
+ gain_enc_mless_fx(hBstr, st_fx->acelp_cfg.gains_mode, st_fx->element_mode, L_frame, i_subfr_fx, -1, xn_fx, y1_fx, shift_wsp, y2_fx, code_fx, Es_pred_fx,
+ &gain_pit_fx, &gain_code_fx, &gain_inov_fx, &norm_gain_code_fx, g_corr_fx, clip_gain_fx );
+ }
+ IF (st_fx->Opt_SC_VBR_fx)
+ {
+ if (EQ_16(hSC_VBR->last_ppp_mode, 1))
+ {
+ /* SC-VBR - all other st->clip_var values will be updated even in a PPP frame */
+ st_fx->clip_var_fx[1] = gain_pit_fx;
+ move16();
+ }
+ }
+ gp_clip_test_gain_pit_fx(st_fx->element_mode, st_fx->core_brate_fx, gain_pit_fx, st_fx->clip_var_fx );
+
+#ifdef BASOP_NOGLOB
+ Lgcode = L_shl_o(gain_code_fx, Q_new, &Overflow); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx_o(Lgcode, &Overflow);
+#else
+ Lgcode = L_shl(gain_code_fx, Q_new); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx(Lgcode);
+#endif
+
+ hLPDmem->tilt_code = Est_tilt2(&exc_fx[i_subfr_fx], gain_pit_fx, code_fx, Lgcode, &voice_fac_fx, shift);
+
+ /*-----------------------------------------------------------------*
+ * Transform domain contribution encoding - inactive frames
+ *-----------------------------------------------------------------*/
+
+ test();
+ IF ( GE_32(st_fx->core_brate_fx, MAX_GSC_INACTIVE_BRATE) && EQ_16(st_fx->coder_type,INACTIVE))
+ {
+ transf_cdbk_enc_fx( st_fx, 0, i_subfr_fx, cn_fx, exc_fx, p_Aq_fx, p_Aw_fx, h1_fx, xn_fx, xn2_fx, y1_fx, y2_fx,
+ Es_pred_fx, &gain_pit_fx, gain_code_fx, g_corr_fx, clip_gain_fx, &gain_preQ_fx, code_preQ_fx, unbits_fx, Q_new, shift);
+ }
+
+ /*-----------------------------------------------------------------*
+ * Update memory of the weighting filter
+ *-----------------------------------------------------------------*/
+
+ /* st_fx->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); */
+ Ltmp = L_mult(gcode16, y2_fx[L_SUBFR - 1]);
+ Ltmp = L_shl(Ltmp, add(5, shift));
+ Ltmp = L_negate(Ltmp);
+ Ltmp = L_mac(Ltmp, xn_fx[L_SUBFR - 1], 16384);
+ Ltmp = L_msu(Ltmp, y1_fx[L_SUBFR - 1], gain_pit_fx);
+ Ltmp = L_shl(Ltmp, sub(1, shift));
+ hLPDmem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */
+
+ IF(gain_preQ_fx != 0 )
+ {
+ tmp1_fx = add(16-(2+Q_AVQ_OUT_DEC+1),Q_new);
+
+ FOR( i = 0; i < L_SUBFR; i++ )
+ {
+#ifdef BASOP_NOGLOB
+ /* Contribution from AVQ layer */
+ Ltmp1 = L_mult_o(gain_preQ_fx, code_preQ_fx[i], &Overflow); /* Q2 + Q6 -> Q9*/
+ Ltmp1 = L_shl_o(Ltmp1, tmp1_fx, &Overflow); /* Q16 + Q_exc */
+
+ /* Compute exc2 */
+ Ltmp = L_shl_o(L_mult(gain_pit_fx,exc_fx[i+i_subfr_fx]),1, &Overflow);
+ exc2_fx[i+i_subfr_fx] = round_fx_o(L_add_o(Ltmp, Ltmp1, &Overflow), &Overflow);
+#else
+ /* Contribution from AVQ layer */
+ Ltmp1 = L_mult(gain_preQ_fx, code_preQ_fx[i]); /* Q2 + Q6 -> Q9*/
+ Ltmp1 = L_shl(Ltmp1, tmp1_fx); /* Q16 + Q_exc */
+
+ /* Compute exc2 */
+ Ltmp = L_shl(L_mult(gain_pit_fx,exc_fx[i+i_subfr_fx]),1);
+ exc2_fx[i+i_subfr_fx] = round_fx(L_add(Ltmp, Ltmp1));
+#endif
+
+ /* code in Q9, gain_pit in Q14 */
+ Ltmp = L_mult(gcode16, code_fx[i]);
+ Ltmp = L_shl(Ltmp, 5);
+ Ltmp = L_mac(Ltmp, exc_fx[i + i_subfr_fx], gain_pit_fx);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(Ltmp, 1, &Overflow); /* saturation can occur here */
+ exc_fx[i + i_subfr_fx] = round_fx_o(L_add_o(Ltmp, Ltmp1, &Overflow), &Overflow);
+#else
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+
+ exc_fx[i+i_subfr_fx] = round_fx(L_add(Ltmp, Ltmp1));
+#endif
+ }
+
+ }
+ ELSE
+ {
+ /*-----------------------------------------------------------------*
+ * Construct adaptive part of the excitation
+ * Save the non-enhanced excitation for FEC_exc
+ *-----------------------------------------------------------------*/
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ /* code in Q9, gain_pit in Q14 */
+ Ltmp = L_mult(gcode16, code_fx[i]);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(Ltmp, 5, &Overflow);
+ Ltmp = L_mac_o(Ltmp, exc_fx[i + i_subfr_fx], gain_pit_fx, &Overflow);
+ Ltmp = L_shl_o(Ltmp, 1, &Overflow); /* saturation can occur here */
+ exc_fx[i + i_subfr_fx] = round_fx_o(Ltmp, &Overflow);
+#else
+ Ltmp = L_shl(Ltmp, 5);
+ Ltmp = L_mac(Ltmp, exc_fx[i + i_subfr_fx], gain_pit_fx);
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+ exc_fx[i + i_subfr_fx] = round_fx(Ltmp);
+#endif
+ }
+ }
+ /*-----------------------------------------------------------------*
+ * Prepare TBE excitation
+ *-----------------------------------------------------------------*/
+
+ prep_tbe_exc_fx( L_frame, i_subfr_fx, gain_pit_fx, gain_code_fx, code_fx, voice_fac_fx,
+ &voice_factors_fx[i_subfr_fx/L_SUBFR], bwe_exc_fx, gain_preQ_fx, code_preQ_fx, Q_new,
+ T0_fx, T0_frac_fx, st_fx->coder_type, st_fx->core_brate_fx );
+
+ /*-----------------------------------------------------------------*
+ * Synthesize speech to update mem_syn[].
+ * Update A(z) filters
+ *-----------------------------------------------------------------*/
+
+ Syn_filt_s( 1, p_Aq_fx, M, &exc_fx[i_subfr_fx], &syn_fx[i_subfr_fx], L_SUBFR, hLPDmem->mem_syn, 1 );
+
+ p_Aw_fx += (M+1);
+ p_Aq_fx += (M+1);
+ pt_pitch_fx++;
+ }
+
+ /* write reserved bits */
+ WHILE( unbits_PI_fx > 0 )
+ {
+ i = s_min(unbits_PI_fx, 16);
+ push_indice_fx(hBstr, IND_UNUSED, 0, i );
+ unbits_PI_fx -= i;
+ }
+ IF (st_fx->Opt_SC_VBR_fx)
+ {
+ /* SC-VBR */
+ hSC_VBR->prev_ppp_gain_pit_fx = gain_pit_fx;
+ move16();
+ hSC_VBR->prev_tilt_code_fx = hLPDmem->tilt_code;
+ move16();
+ }
+ return;
+
+}
diff --git a/lib_enc/enc_gen_voic_rf_fx.c b/lib_enc/enc_gen_voic_rf_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..1365e59c3c4c0678149584e84c8428e58ae6db7d
--- /dev/null
+++ b/lib_enc/enc_gen_voic_rf_fx.c
@@ -0,0 +1,544 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h"
+#include "cnst.h"
+//#include "prot_fx.h"
+#include "rom_com_fx.h"
+#include "stl.h"
+#include "rom_basop_util.h"
+//#include "basop_mpy.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+
+
+void reset_rf_indices_fx(
+ Encoder_State_fx *st /* i: state structure - contains partial RF indices */
+)
+{
+ RF_ENC_HANDLE hRF = st->hRF;
+ Word16 i, j;
+ if (hRF != NULL)
+ {
+ hRF->rf_frame_type = 0; /* since this function is called every frame this will happen even for a SID frame, hence treating it as GSC frame, i.e no RF encoding */
+ hRF->rf_mem_w0 = 0;
+ move16();
+ st->rf_target_bits_write = 0;
+ move16();
+ set16_fx(hRF->rf_clip_var, 0 ,6);
+ hRF->rf_tilt_code = 0;
+ move16();
+ set16_fx(hRF->rf_mem_syn2, 0, M);
+ hRF->rf_dm_fx.prev_state = 0;
+ move16();
+ hRF->rf_dm_fx.prev_gain_code = 0;
+ move32();
+
+ FOR(i=0; i<6; i++)
+ {
+ hRF->rf_dm_fx.prev_gain_pit[i] = 0;
+ move16();
+ }
+
+ hRF->rf_gc_threshold = 0;
+ move32();
+ set16_fx(hRF->rf_tilt_buf, 0, NB_SUBFR16k);
+
+ hRF->rf_target_bits = 0;
+ move16();
+ hRF->rf_tcxltp_pitch_int_past = st->L_frame_fx;
+ move16();
+ hRF->rf_last_tns_active = 0;
+ move16();
+ hRF->rf_second_last_tns_active = 0;
+ move16();
+ hRF->rf_second_last_core= 0;
+ move16();
+
+ FOR( i = 0; i < MAX_RF_FEC_OFFSET; i++)
+ {
+ hRF->rf_indx_frametype[i] = RF_NO_DATA;
+ move16(); /* rf_mode: 1, rf_frame_type: 3, and fec_offset: 2 */
+ hRF->rf_targetbits_buff[i] = 6;
+ move16();
+ hRF->rf_indx_lsf[i][0] = 0;
+ move16();
+ hRF->rf_indx_lsf[i][1] = 0;
+ move16();
+ hRF->rf_indx_lsf[i][2] = 0;
+ move16();
+ hRF->rf_indx_EsPred[i] = 0;
+ move16();
+ hRF->rf_indx_nelp_fid[i] = 0;
+ move16();
+ hRF->rf_indx_nelp_iG1[i] = 0;
+ move16();
+ hRF->rf_indx_nelp_iG2[i][0] = 0;
+ move16();
+ hRF->rf_indx_nelp_iG2[i][1] = 0;
+ move16();
+
+ FOR( j = 0; j < NB_SUBFR16k; j++)
+ {
+ hRF->rf_indx_ltfMode[i][j] = 0;
+ move16();
+ hRF->rf_indx_pitch[i][j] = 0;
+ move16();
+ hRF->rf_indx_fcb[i][j] = 0;
+ move16();
+ hRF->rf_indx_gain[i][j] = 0;
+ move16();
+ }
+
+ hRF->rf_clas[i] = UNVOICED_CLAS;
+ move16();
+ hRF->rf_gain_tcx[i] = 0;
+ move16();
+ hRF->rf_tcxltp_param[i] = 0;
+ move16();
+
+ hRF->rf_indx_tbeGainFr[i] = 0;
+ move16();
+ }
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * coder_acelp_rf_fx()
+ *
+ * Encode excitation signal (partial redundancy)
+ *-------------------------------------------------------------------*/
+void coder_acelp_rf_fx(
+ ACELP_config *acelp_cfg, /*input/output: configuration of the ACELP coding*/
+ const Word16 coder_type, /* input: coding type */
+ const Word16 A[], /* input: coefficients 4xAz[M+1] */
+ const Word16 Aq[], /* input: coefficients 4xAz_q[M+1] */
+ Word16 speech[], /* input: speech[-M..lg] */
+ const Word16 voicing[], /* input: open-loop LTP gain */
+ const Word16 T_op[], /* input: open-loop LTP lag */
+ Word16 stab_fac,
+ Encoder_State_fx *st,
+ Word16 target_bits, /* i/o : coder memory state */
+ const Word16 rf_frame_type, /* i : rf_frame_type */
+ Word16 *exc_rf, /* i/o: pointer to RF excitation */
+ Word16 *syn_rf, /* i/o: pointer to RF synthesis */
+ Word16 Q_new,
+ Word16 shift
+)
+{
+ Word16 i, j, i_subfr, j_subfr;
+ Word16 T0, T0_min, T0_min_frac, T0_max, T0_max_frac, T0_res;
+ Word16 T0_frac;
+ Word16 tmp2;
+ Word16 gain_pit, voice_fac;
+ Word32 gain_code, Ltmp, Ltmp2;
+ ACELP_CbkCorr g_corr;
+ const Word16 *p_A, *p_Aq;
+ Word16 h1[L_SUBFR]; /* weighted impulse response of LP */
+ Word16 code[L_SUBFR];
+ Word16 xn_exp;
+ Word16 Q_xn;
+ Word16 Q_new_p5;
+ Word16 cn[L_SUBFR];
+ Word16 xn[L_SUBFR];
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 res_save;
+ Word16 exc_nelp[L_FRAME];
+ Word16 exc2[L_SUBFR];
+ Word16 syn2[L_DIV_MAX];
+ Word16 gain_inov;
+ Word32 past_gcode;
+ Word16 L_frame;
+ Word16 clip_gain;
+ Word32 gain_code2;
+ Word16 code2[L_SUBFR];
+ Word16 y22[L_SUBFR]; /* Filtered adaptive excitation */
+ Word32 gain_code_vect[2];
+ Word16 *prm_rf;
+ Word16 Es_pred_rf;
+ Word16 nSubfr;
+ Word16 prev_gain_pit;
+ Word16 rf_coder_type;
+ Word16 lp_select;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ RF_ENC_HANDLE hRF = st->hRF;
+
+ /* to avoid compilation warnings */
+ past_gcode = 0;
+ gain_inov = 0;
+ T0 = 0;
+ T0_frac = 0;
+ T0_res = 0;
+ gain_pit = 0;
+ gain_code = 0;
+ voice_fac = 0;
+ prev_gain_pit=0;
+ Es_pred_rf = 0;
+ set16_fx(code, 0, L_SUBFR);
+
+ /*-----------------------------------------------------------------------*
+ * Configure ACELP partial copy *
+ *------------------------------------------------------------------------*/
+ tmp2 = BITS_ALLOC_config_acelp( target_bits, rf_frame_type, &(hRF->acelp_cfg_rf), 0, st->nb_subfr );
+
+ /* Init Framing parameters */
+ L_frame = st->L_frame_fx;
+
+ /*------------------------------------------------------------------------*
+ * Initialize buffers *
+ *------------------------------------------------------------------------*/
+
+ /* Rescale ACELP memories, which were not scaled yet*/
+ xn_exp = sub(sub(15+1, Q_new),shift);
+ Q_xn = add(sub(Q_new,1),shift);
+ Q_new_p5 = add(Q_new, 5);
+
+ /* Reset phase dispersion */
+ IF (GT_16(st->last_core_fx, ACELP_CORE))
+ {
+ hRF->rf_dm_fx.prev_gain_code = 0;
+ set16_fx(hRF->rf_dm_fx.prev_gain_pit, 0, 6);
+ hRF->rf_dm_fx.prev_state = 0;
+ }
+
+ /* calculate residual */
+ calc_residu_fx(st, speech, exc_rf, Aq);
+
+ /*------------------------------------------------------------------------*
+ * Find and quantize mean_ener_code for gain quantizer *
+ *------------------------------------------------------------------------*/
+
+ Es_pred_rf = 0;
+ IF( acelp_cfg->nrg_mode > 0 && NE_16(rf_frame_type,RF_NELP))
+ {
+ Es_pred_enc_fx(&Es_pred_rf, &hRF->rf_indx_EsPred[0], L_frame, exc_rf, voicing,
+ acelp_cfg->nrg_bits, acelp_cfg->nrg_mode>1, Q_new);
+ }
+
+ /*------------------------------------------------------------------------*
+ * Loop for every subframe in the analysis frame *
+ *------------------------------------------------------------------------*
+ * To find the pitch and innovation parameters. The subframe size is *
+ * L_SUBFR and the loop is repeated L_FRAME_PLUS/L_SUBFR *
+ * times. *
+ * - compute impulse response of weighted synthesis filter (h1[]) *
+ * - compute the target signal for pitch search *
+ * - find the closed-loop pitch parameters *
+ * - encode the pitch delay *
+ * - update the impulse response h1[] by including fixed-gain pitch *
+ * - find target vector for codebook search *
+ * - correlation between target vector and impulse response *
+ * - codebook search *
+ * - encode codebook address *
+ * - VQ of pitch and codebook gains *
+ * - find synthesis speech *
+ * - update states of weighting filter *
+ *------------------------------------------------------------------------*/
+ p_A = A;
+ p_Aq = Aq;
+
+ res_save = exc_rf[0];
+ nSubfr = 0;
+ j_subfr = 0;
+
+ FOR (i_subfr=0; i_subfrrf_mem_w0), p_Aq,
+ exc_rf, L_SUBFR, p_A, st->preemph_fac, xn, cn ,h1 );
+
+ /*---------------------------------------------------------------*
+ * Compute impulse response, h1[], of weighted synthesis filter *
+ *---------------------------------------------------------------*/
+ Scale_sig(h1, L_SUBFR, add(1,shift)); /* Q13+1-shift */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(xn, L_SUBFR, shift);
+
+ }
+
+
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ * or in case of floating point encoder & fixed p. decoder
+ *-----------------------------------------------------------------*/
+ /* full frame nelp partial copy encoding */
+ IF( EQ_16(rf_frame_type,RF_NELP))
+ {
+ IF( i_subfr == 0 )
+ {
+ nelp_encoder_fx( st, exc_rf, exc_nelp, &Q_new,0);
+ }
+ Copy( &exc_nelp[i_subfr], exc2, L_SUBFR );
+ Copy( &exc_nelp[i_subfr], exc_rf, L_SUBFR );
+
+ }
+ ELSE
+ {
+ clip_gain = Mode2_gp_clip( voicing, i_subfr, coder_type, xn, hRF->rf_clip_var, L_SUBFR, Q_xn );
+
+ /*-----------------------------------------------------------------*
+ * - find unity gain pitch excitation (adaptive codebook entry) *
+ * with fractional interpolation. *
+ * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) *
+ * - compute pitch gain1 *
+ *-----------------------------------------------------------------*/
+ if( acelp_cfg->gains_mode[i_subfr/L_SUBFR] == 0 )
+ {
+ gain_pit = prev_gain_pit;
+ move16();
+ }
+
+ IF ( acelp_cfg->ltp_bits!=0 )
+ {
+ prm_rf = &hRF->rf_indx_pitch[0][nSubfr];
+
+ /* Adaptive Codebook (GC and VC) */
+ Mode2_pit_encode_fx( acelp_cfg->ltp_mode, i_subfr, &prm_rf, &exc_rf[i_subfr],
+ T_op, &T0_min, &T0_min_frac, &T0_max, &T0_max_frac, &T0,
+ &T0_frac, &T0_res, h1, xn, st->pit_min, st->pit_fr1, st->pit_fr1b,
+ st->pit_fr2, st->pit_max,st->pit_res_max);
+
+ /* find ACB excitation */
+ rf_coder_type = 100;
+ move16();
+ if( acelp_cfg->gains_mode[i_subfr/L_SUBFR] > 0 )
+ {
+ rf_coder_type = acelp_cfg->gains_mode[i_subfr/L_SUBFR];
+ move16();
+ }
+
+ E_ACELP_adaptive_codebook( exc_rf, T0, T0_frac, T0_res, st->pit_res_max, acelp_cfg->ltf_mode,
+ i_subfr, L_SUBFR, L_frame, h1,clip_gain, xn, y1, &g_corr, &prm_rf,
+ &gain_pit, xn_exp, st->rf_mode, rf_coder_type, &lp_select);
+
+
+
+ if( EQ_16(acelp_cfg->ltf_mode, NORMAL_OPERATION) )
+ {
+ hRF->rf_indx_ltfMode[0][nSubfr] = lp_select;
+ move16();
+ }
+ }
+ ELSE IF ( acelp_cfg->ltp_bits==0 )
+ {
+ /* No adaptive codebook (UC) */
+ gain_pit=0;
+ g_corr.xy1=0;
+ g_corr.xy1_e=0;
+ g_corr.y1y1=0x4000; /* set to 0x4000 instead of 0 to avoid assert failue in gain_enc : assert(coeff0 >= 0x4000) */
+ g_corr.y1y1_e=0;
+ set16_fx(y1,0,L_SUBFR);
+ set16_fx(exc_rf+i_subfr,0,L_SUBFR);
+ T0 = L_SUBFR;
+ T0_frac = 0;
+ T0_res = 1;
+ move16();move16();move16();move16();move16();move16();move16();move16();
+ }
+
+
+ /*----------------------------------------------------------------------*
+ * Encode the algebraic innovation *
+ *----------------------------------------------------------------------*/
+ IF( acelp_cfg->fixed_cdk_index[i_subfr/L_SUBFR] >= 0 )
+ {
+ prm_rf = &hRF->rf_indx_fcb[0][nSubfr];
+
+ E_ACELP_innovative_codebook_fx( exc_rf,T0,T0_frac,T0_res, gain_pit, hRF->rf_tilt_code,
+ acelp_cfg, i_subfr,p_Aq,h1,xn,cn,y1,y2,st->acelp_autocorr,
+ &prm_rf,code,shift,st->L_frame_fx, st->last_L_frame_fx,st->total_brate_fx);
+ }
+ ELSE
+ {
+ set16_fx(code, 0, L_SUBFR);
+ set16_fx(y2, 0, L_SUBFR);
+ }
+
+ IF( LT_16(i_subfr, sub(L_frame,L_SUBFR)) )
+ {
+ E_ACELP_xy2_corr(xn, y1, y2, &g_corr, L_SUBFR, Q_xn);
+
+ g_corr.y2y2_e = sub(g_corr.y2y2_e, 18); /* -18 (y2*y2: Q9*Q9) */
+ g_corr.xy2_e = sub(g_corr.xy2_e, add(Q_xn,9)); /* -(Q_xn+9) (xn: Q_xn y2: Q9) */
+ g_corr.y1y2_e = sub(g_corr.y1y2_e, add(Q_xn,9)); /* -(Q_xn+9) (y1: Q_xn y2: Q9) */
+ g_corr.xx_e = sub(g_corr.xx_e, add(Q_xn,Q_xn)); /* -(Q_xn+Q_xn) (xn: Q_xn) */
+
+ /*----------------------------------------------------------------------*
+ * Add Gaussian excitation *
+ *----------------------------------------------------------------------*/
+ gain_code2 = L_deposit_l(0);
+ set16_fx(code2, 0, L_SUBFR);
+ set16_fx(y22, 0, L_SUBFR);
+
+ /*----------------------------------------------------------*
+ * - Compute the fixed codebook gain *
+ * - quantize fixed codebook gain *
+ *----------------------------------------------------------*/
+ IF( acelp_cfg->gains_mode[i_subfr/L_SUBFR] != 0 )
+ {
+ prm_rf = &hRF->rf_indx_gain[0][nSubfr];
+
+ encode_acelp_gains_fx( code, acelp_cfg->gains_mode[j_subfr], Es_pred_rf,
+ clip_gain, &g_corr, &gain_pit, &gain_code, &prm_rf, &past_gcode,
+ &gain_inov, L_SUBFR, code2, &gain_code2, st->flag_noisy_speech_snr );
+ }
+
+
+
+ gp_clip_test_gain_pit_fx(st->element_mode, st->core_brate_fx, gain_pit, hRF->rf_clip_var );
+
+ gain_code_vect[0] = gain_code;
+ move32();
+ gain_code_vect[1] = gain_code;
+ move32();
+
+ /*----------------------------------------------------------*
+ * - voice factor (for pitch enhancement) *
+ *----------------------------------------------------------*/
+ E_UTIL_voice_factor( exc_rf, i_subfr, code, gain_pit, gain_code,
+ &voice_fac, &(hRF->rf_tilt_code), L_SUBFR, acelp_cfg->voice_tilt, Q_new, shift);
+
+
+ /*-----------------------------------------------------------------*
+ * Update memory of the weighting filter
+ *-----------------------------------------------------------------*/
+ /* st_fx->_rf_mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); */
+ Ltmp = Mpy_32_16_1(gain_code, y2[L_SUBFR-1]);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(Ltmp, add(5,Q_xn), &Overflow);
+ Ltmp = L_mac_o(Ltmp, y1[L_SUBFR-1], gain_pit, &Overflow);
+#else
+ Ltmp = L_shl(Ltmp, add(5,Q_xn));
+ Ltmp = L_mac(Ltmp, y1[L_SUBFR-1], gain_pit);
+#endif
+ /* Add Gaussian contribution*/
+ Ltmp2 = Mpy_32_16_1(gain_code2, y22[L_SUBFR-1]);
+#ifdef BASOP_NOGLOB
+ Ltmp2 = L_shl_o(Ltmp2, add(5,Q_xn), &Overflow);
+ Ltmp = L_add_o(Ltmp, Ltmp2, &Overflow);
+ hRF->rf_mem_w0 =sub_o(xn[L_SUBFR-1], round_fx_o(L_shl_o(Ltmp, 1, &Overflow), &Overflow), &Overflow);
+ move16();
+ hRF->rf_mem_w0 =shr_o(hRF->rf_mem_w0, shift, &Overflow); /*Qnew-1*/
+#else
+ Ltmp2 = L_shl(Ltmp2, add(5,Q_xn));
+ Ltmp = L_add(Ltmp, Ltmp2);
+ hRF->rf_mem_w0 =sub(xn[L_SUBFR-1], round_fx(L_shl(Ltmp, 1)));
+ move16();
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ hRF->rf_mem_w0 =shr(hRF->rf_mem_w0, shift); /*Qnew-1*/
+ BASOP_SATURATE_WARNING_ON_EVS;
+#endif
+
+
+ /*-------------------------------------------------------*
+ * - Find the total excitation. *
+ *-------------------------------------------------------*/
+
+ tmp2 = shr(L_SUBFR, 1);
+ FOR (j = 0; j < 2; j++)
+ {
+ FOR (i = sub(tmp2, shr(L_SUBFR, 1)); i < tmp2; i++)
+ {
+ /* code in Q9, gain_pit in Q14; exc Q_new */
+ Ltmp = Mpy_32_16_1(gain_code2, code2[i]);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(Ltmp, Q_new_p5, &Overflow);
+ Ltmp = L_mac_o(Ltmp, gain_pit, exc_rf[i+i_subfr], &Overflow);
+ exc2[i] = round_fx_o(L_shl_o(Ltmp, 1, &Overflow), &Overflow);
+#else
+ Ltmp = L_shl(Ltmp, Q_new_p5);
+ Ltmp = L_mac(Ltmp, gain_pit, exc_rf[i+i_subfr]);
+ BASOP_SATURATE_WARNING_OFF_EVS
+ exc2[i] = round_fx(L_shl(Ltmp, 1));
+ BASOP_SATURATE_WARNING_ON_EVS
+#endif
+ Ltmp2 = Mpy_32_16_1(gain_code_vect[j], code[i]);
+#ifdef BASOP_NOGLOB
+ Ltmp2 = L_shl_o(Ltmp2, Q_new_p5, &Overflow);
+ Ltmp = L_add_o(Ltmp, Ltmp2, &Overflow);
+ Ltmp = L_shl_o(Ltmp, 1, &Overflow); /* saturation can occur here */
+ exc_rf[i + i_subfr] = round_fx_o(Ltmp, &Overflow);
+#else
+ Ltmp2 = L_shl(Ltmp2, Q_new_p5);
+ Ltmp = L_add(Ltmp, Ltmp2);
+ BASOP_SATURATE_WARNING_OFF_EVS
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+ BASOP_SATURATE_WARNING_ON_EVS
+ exc_rf[i + i_subfr] = round_fx(Ltmp);
+#endif
+ }
+ tmp2 = L_SUBFR;
+ }
+
+
+
+ /*---------------------------------------------------------*
+ * Enhance the excitation *
+ *---------------------------------------------------------*/
+ E_UTIL_enhancer( voice_fac, stab_fac, past_gcode, gain_inov,
+ &hRF->rf_gc_threshold, code, exc2, gain_pit, &hRF->rf_dm_fx.prev_gain_code,
+ hRF->rf_dm_fx.prev_gain_pit, &hRF->rf_dm_fx.prev_state, coder_type,
+ acelp_cfg->fixed_cdk_index[j_subfr], L_SUBFR, L_frame, Q_new );
+ }
+ }
+
+ IF( i_subfr < sub(L_frame,L_SUBFR) || NE_16(rf_frame_type,RF_NELP) )
+ {
+
+ /*----------------------------------------------------------*
+ * - compute the synthesis speech *
+ *----------------------------------------------------------*/
+
+ E_UTIL_synthesis(1, p_Aq, exc2, &syn2[i_subfr], L_SUBFR, hRF->rf_mem_syn2, 1, M);
+
+ E_UTIL_synthesis(1, p_Aq, &exc_rf[i_subfr], &syn_rf[i_subfr], L_SUBFR, &syn_rf[i_subfr-M], 0, M);
+
+ /*----------------------------------------------------------*
+ * Update *
+ *----------------------------------------------------------*/
+ p_A += (M+1);
+ p_Aq += (M+1);
+ nSubfr++;
+
+ st->gain_code[j_subfr] = gain_code;
+ j_subfr = add(j_subfr, 1);
+
+ /* copy current gain for next subframe use, in case there is no explicit encoding */
+ prev_gain_pit = gain_pit;
+
+ }
+
+
+
+ } /* end of subframe loop */
+
+
+ return;
+}
+
+
diff --git a/lib_enc/enc_higher_acelp_fx.c b/lib_enc/enc_higher_acelp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..aa0f93037ab22d2165b8bf3e684f07dadb03f325
--- /dev/null
+++ b/lib_enc/enc_higher_acelp_fx.c
@@ -0,0 +1,506 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#include "prot_fx_enc.h"
+
+/*---------------------------------------------------------------------*
+ * Local function prototype
+ *---------------------------------------------------------------------*/
+static void find_cn_fx( const Word16 xn[], const Word16 Ap[], const Word16 *p_Aq, Word16 cn[] );
+
+/*-----------------------------------------------------------------*
+ * Transform domain contribution encoding
+ *-----------------------------------------------------------------*/
+#define Q_MINUS 4
+void transf_cdbk_enc_fx(
+ Encoder_State_fx *st_fx, /* i/o: encoder state structure */
+ const Word16 harm_flag_acelp,/* i : harmonic flag for higher rates ACELP */
+ const Word16 i_subfr, /* i : subframe index */
+ Word16 cn[], /* i/o: target vector in residual domain */
+ Word16 exc[], /* i/o: pointer to excitation signal frame */
+ const Word16 *p_Aq, /* i : 12k8 Lp coefficient */
+ const Word16 Ap[], /* i : weighted LP filter coefficients */
+ const Word16 h1[], /* i : weighted filter input response */
+ Word16 xn[], /* i/o: target vector */
+ Word16 xn2[], /* i/o: target vector for innovation search */
+ Word16 y1[], /* i/o: zero-memory filtered adaptive excitation */
+ const Word16 y2[], /* i : zero-memory filtered innovative excitation */
+ const Word16 Es_pred, /* i : predicited scaled innovation energy */
+ Word16 *gain_pit, /* i/o: adaptive excitation gain */
+ const Word32 gain_code, /* i : innovative excitation gain */
+ Word16 g_corr[], /* o : ACELP correlation values */
+ const Word16 clip_gain, /* i : adaptive gain clipping flag */
+ Word16 *gain_preQ, /* o : prequantizer excitation gain */
+ Word16 code_preQ[], /* o : prequantizer excitation */
+ Word16 *unbits, /* o : number of AVQ unused bits */
+ const Word16 Q_new, /* i : Current frame scaling */
+ const Word16 shift /* i : shifting applied to y1, xn,... */
+)
+{
+ Word16 i, index, nBits, Nsv, Es_pred_loc;
+ Word16 x_in[L_SUBFR], x_tran[L_SUBFR], gcode16, stmp;
+ Word16 e_corr, m_corr, e_ener, m_ener, m_den, e_den;
+ Word16 x_norm[L_SUBFR+L_SUBFR/WIDTH_BAND];
+ Word32 L_corr, L_ener, Ltmp, Ltmp1;
+ Word16 nq[L_SUBFR/WIDTH_BAND];
+ Word32 out32[L_SUBFR];
+ Word16 Qdct;
+ Word16 avq_bit_sFlag;
+ Word16 trgtSvPos;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ avq_bit_sFlag = 0;
+ move16();
+ if (GT_16(st_fx->element_mode, EVS_MONO))
+ {
+ avq_bit_sFlag = 1;
+ move16();
+ }
+
+ /*--------------------------------------------------------------*
+ * Set bit-allocation
+ *--------------------------------------------------------------*/
+
+ Nsv = 8;
+ move16();
+ nBits = st_fx->acelp_cfg.AVQ_cdk_bits[shr(i_subfr, 6)];
+ move16();
+
+ /* increase # of AVQ allocated bits by unused bits from the previous subframe */
+ nBits = add(nBits, *unbits);
+
+ /*--------------------------------------------------------------*
+ * Compute/Update target
+ * For inactive frame, find target in residual domain
+ * Deemphasis
+ *--------------------------------------------------------------*/
+ IF (EQ_16(st_fx->coder_type,INACTIVE))
+ {
+#ifdef BASOP_NOGLOB
+ gcode16 = round_fx_o(L_shl_o(gain_code, Q_new, &Overflow), &Overflow);
+#else
+ gcode16 = round_fx(L_shl(gain_code, Q_new));
+#endif
+ FOR( i=0; imem_deemp_preQ_fx) );
+
+ /*--------------------------------------------------------------*
+ * DCT-II
+ *--------------------------------------------------------------*/
+
+ test();
+ test();
+ test();
+ IF( NE_16(st_fx->coder_type,INACTIVE) && LE_32(st_fx->core_brate_fx, MAX_BRATE_AVQ_EXC_TD) && GE_32(st_fx->core_brate_fx, MIN_BRATE_AVQ_EXC) && !harm_flag_acelp)
+ {
+ Copy_Scale_sig( x_in, x_tran, L_SUBFR,-Q_MINUS+1 ); /*Q_new-1 -> Q_new-4*/
+ /*Copy( x_in, x_tran, L_SUBFR );*/
+ Qdct = sub(Q_new,Q_MINUS);
+ }
+ ELSE
+ {
+ Qdct = 0;
+ move16();
+ edct2_fx( L_SUBFR, -1, x_in, out32, &Qdct, ip_edct2_64, w_edct2_64_fx );
+ Qdct = negate(Qdct);
+ Copy_Scale_sig_32_16(out32, x_tran, L_SUBFR, sub(Qdct,Q_MINUS-1)); /* Output in Q_new-4 */
+ Qdct = sub(Q_new,Q_MINUS);
+ }
+
+ /*--------------------------------------------------------------*
+ * Split algebraic vector quantizer based on RE8 lattice
+ *--------------------------------------------------------------*/
+ AVQ_cod_fx( x_tran, x_norm, nBits, Nsv, 0 );
+
+ /*--------------------------------------------------------------*
+ * Find prequantizer excitation gain
+ * Quantize the gain
+ *--------------------------------------------------------------*/
+ L_corr = L_deposit_l(0);
+ L_ener = L_deposit_l(0);
+ FOR (i = 0; i < Nsv*8; i++)
+ {
+ /*fcorr += fx_tran[i]*(float)ix_norm[i];*/
+ /*fener += (float)ix_norm[i]*(float)ix_norm[i];*/
+ stmp = shl(x_norm[i],Q_AVQ_OUT );
+ L_corr = L_mac(L_corr, x_tran[i], stmp);
+ L_ener = L_mac(L_ener, stmp, stmp);
+ }
+ L_ener = L_max(L_ener,1);
+
+ /* No negative gains allowed in the quantizer*/
+ L_corr = L_max(L_corr,0);
+
+ e_corr = norm_l(L_corr);
+ m_corr = extract_h(L_shl(L_corr, e_corr));
+ e_corr = sub(30, add(e_corr,sub(Qdct,Q_AVQ_OUT)));
+ e_ener = norm_l(L_ener);
+ m_ener = extract_h(L_shl(L_ener, e_ener));
+ e_ener = sub(30, e_ener);
+
+ IF(GT_16(m_corr,m_ener))
+ {
+ m_corr = shr(m_corr,1);
+ e_corr = add(e_corr,1);
+ }
+ m_corr = div_s(m_corr, m_ener);
+ e_corr = sub(e_corr, e_ener);
+ Ltmp = L_shl(m_corr, s_min(add(e_corr,1),31)); /* Lgain in Q16 */
+ IF ( EQ_16(st_fx->coder_type,INACTIVE))
+ {
+ Ltmp1 = L_max(gain_code,1);
+ e_den = norm_l(Ltmp1);
+ m_den = extract_h(L_shl(Ltmp1, e_den));
+ /* ensure m_corr < m_den */
+ test();
+ IF( m_corr>0 && m_den >0)
+ {
+ m_corr = div_s(16384, m_den);
+ e_corr = sub(14+4, e_den);
+ Ltmp = L_shr(Mult_32_16(Ltmp, m_corr), e_corr); /*Q12*/
+#ifdef BASOP_NOGLOB
+ stmp = round_fx_o(L_shl_o(Ltmp,16, &Overflow), &Overflow);
+#else
+ stmp = round_fx(L_shl(Ltmp,16));
+#endif
+ }
+ ELSE
+ {
+ stmp = 0;
+ move16();
+ }
+ IF( GT_32(st_fx->core_brate_fx,56000))
+ {
+ index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_64k_Q12, G_AVQ_DELTA_INACT_64k_Q12>>1, (1 << G_AVQ_BITS) );
+ }
+ ELSE IF( GT_32(st_fx->core_brate_fx,42000))
+ {
+ index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_48k_Q12, G_AVQ_DELTA_INACT_48k_Q12>>1, (1 << G_AVQ_BITS) );
+ }
+ ELSE
+ {
+ index = usquant_fx( stmp, &stmp, G_AVQ_MIN_INACT_Q12, G_AVQ_DELTA_INACT_Q12>>1, (1 << G_AVQ_BITS) );
+ }
+ Ltmp = Mult_32_16(gain_code,stmp); /* Q16 * Q12 - 15 -> Q13*/
+ Ltmp = L_shl(Ltmp,5); /* Q13 -> Q18*/
+ *gain_preQ = round_fx(Ltmp); /* Q2*/
+ }
+ ELSE
+ {
+ IF( Es_pred < 0 )
+ {
+ Es_pred_loc = shr(negate(Es_pred),2);
+ }
+ ELSE
+ {
+ Es_pred_loc = Es_pred;
+ move16();
+ }
+
+ e_den = norm_s(Es_pred_loc);
+ m_den = shl(Es_pred_loc, e_den);
+ /* ensure m_corr < m_den */
+ test();
+ IF( m_corr>0 && m_den >0)
+ {
+ m_corr = div_s(16384, m_den);
+ e_corr = sub(14-8, e_den);
+ Ltmp = L_shr(Mult_32_16(Ltmp, m_corr), e_corr);
+ }
+ ELSE
+ {
+ Ltmp = L_deposit_l(0);
+ }
+ test();
+ IF( LE_32(st_fx->core_brate_fx,42000) && GT_32(st_fx->core_brate_fx ,ACELP_24k40))
+ {
+ index = gain_quant_fx(&Ltmp, &stmp, LG10_G_AVQ_MIN_32kbps_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den );
+ }
+ ELSE
+ {
+ index = gain_quant_fx(&Ltmp, &stmp, LG10_G_AVQ_MIN_Q14, LG10_G_AVQ_MAX_Q13, G_AVQ_BITS, &e_den );
+ }
+ Ltmp = L_mult(stmp,Es_pred_loc); /* Q0*Q8 -> Q9*/
+ Ltmp = L_shl(Ltmp,add(e_den,9)); /* Q18*/
+ *gain_preQ = round_fx(Ltmp); /* Q2*/
+ }
+ push_indice_fx( st_fx->hBstr, IND_AVQ_GAIN, index, G_AVQ_BITS );
+
+ /*--------------------------------------------------------------*
+ * Encode and multiplex subvectors into bit-stream
+ *--------------------------------------------------------------*/
+ trgtSvPos = Nsv - 1;
+ move16();
+ test();test();test();test();test();
+ IF (avq_bit_sFlag && GT_16(nBits, 85) && !harm_flag_acelp && (EQ_16(st_fx->coder_type, GENERIC) ||
+ EQ_16(st_fx->coder_type, TRANSITION) || EQ_16(st_fx->coder_type, INACTIVE) ))
+ {
+ trgtSvPos = 2;
+ avq_bit_sFlag = 2;
+ move16();move16();
+ }
+
+ AVQ_encmux_fx( st_fx->hBstr, -1, x_norm, &nBits, Nsv, nq, avq_bit_sFlag, trgtSvPos);
+
+ /* save # of AVQ unused bits for next subframe */
+ *unbits = nBits;
+ move16();
+
+ /* at the last subframe, write AVQ unused bits */
+ test();
+ test();
+ IF( EQ_16(i_subfr,4*L_SUBFR) && NE_16(st_fx->extl_fx,SWB_BWE_HIGHRATE) && NE_16(st_fx->extl_fx,FB_BWE_HIGHRATE))
+ {
+ WHILE( *unbits > 0 )
+ {
+ i = s_min(*unbits, 16);
+ push_indice_fx( st_fx->hBstr, IND_UNUSED, 0, i );
+ *unbits -= i;
+ }
+ }
+
+ /*--------------------------------------------------------------*
+ * DCT transform
+ *--------------------------------------------------------------*/
+
+ FOR( i=0; icoder_type,INACTIVE) && LE_32(st_fx->core_brate_fx, MAX_BRATE_AVQ_EXC_TD) && GE_32(st_fx->core_brate_fx, MIN_BRATE_AVQ_EXC) && !harm_flag_acelp)
+ {
+ Copy( x_tran, code_preQ, L_SUBFR );
+ }
+ ELSE
+ {
+ Qdct = 0;
+ move16();
+ edct2_fx( L_SUBFR, 1, x_tran, out32, &Qdct, ip_edct2_64, w_edct2_64_fx );
+ /*qdct = sub(Q_AVQ_OUT_DEC,qdct+Q_AVQ_OUT_DEC);*/
+ Qdct = negate(Qdct);
+ Copy_Scale_sig_32_16(out32, code_preQ, L_SUBFR, Qdct); /* Output in Q_AVQ_OUT_DEC */
+ /*qdct = Q_AVQ_OUT_DEC;*/
+ }
+
+ /*--------------------------------------------------------------*
+ * Preemphasise
+ *--------------------------------------------------------------*/
+ /* in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */
+ test();
+ if( (nq[7] != 0) && (GT_16( sub(st_fx->last_nq_preQ_fx, nq[0]), 7)))
+ {
+ /* *mem_preemp /= 16; */
+ st_fx->mem_preemp_preQ_fx = shr(st_fx->mem_preemp_preQ_fx,4);
+ move16();
+ }
+ st_fx->last_nq_preQ_fx = nq[7];
+ move16();
+#ifdef IVAS_CODE
+ /* TD pre-quantizer: in extreme cases at subframe boundaries, lower the preemphasis memory to avoid a saturation */
+ if (st->element_mode > EVS_MONO && st->coder_type != INACTIVE && st->core_brate >= MIN_BRATE_AVQ_EXC && st->core_brate <= MAX_BRATE_AVQ_EXC_TD && !harm_flag_acelp && code_preQ[0] != 0)
+ {
+ if ((float)abs(st->last_code_preq) > 16.0f * (float)fabs(code_preQ[0]))
+ {
+ st->mem_preemp_preQ /= 16;
+ }
+ else if ((float)abs(st->last_code_preq) > 8.0f * (float)fabs(code_preQ[0]))
+ {
+ st->mem_preemp_preQ /= 8;
+ }
+ }
+
+ st->last_code_preq = (int16_t)code_preQ[L_SUBFR - 1];
+#endif
+ preemph_fx( code_preQ, FAC_PRE_AVQ_FX, L_SUBFR, &(st_fx->mem_preemp_preQ_fx));
+
+ /*--------------------------------------------------------------*
+ * For inactive segments
+ * - Zero-memory filtered pre-filter excitation
+ * - Update of targets and gain_pit
+ * For inactive segments
+ * - Update xn[L_subfr-1] for updating the memory of the weighting filter
+ *--------------------------------------------------------------*/
+
+ IF ( EQ_16(st_fx->coder_type,INACTIVE))
+ {
+ /*ftemp = fcode_preQ[0] *fh1[L_SUBFR-1];*/
+ Ltmp = L_mult(code_preQ[0], h1[L_SUBFR-1]); /*1+14+shift + Q_AVQ_OUT */
+ FOR( i=1; i Q_new + shift -1 */
+ }
+ ELSE
+ {
+ conv_fx( code_preQ, h1, x_tran, L_SUBFR );
+ updt_tar_HR_fx( cn, cn, code_preQ, *gain_preQ, sub(Q_new, add(-15+2,Q_AVQ_OUT_DEC)), L_SUBFR );
+
+ updt_tar_HR_fx( xn, xn, x_tran, *gain_preQ, sub(Q_new, add(-15+2,Q_AVQ_OUT_DEC)), L_SUBFR );
+#ifdef BASOP_NOGLOB
+ *gain_pit = corr_xy1_fx( xn, y1, g_corr, L_SUBFR, 0, &Overflow );
+#else
+ *gain_pit = corr_xy1_fx( xn, y1, g_corr, L_SUBFR, 0 );
+#endif
+ /* clip gain if necessary to avoid problems at decoder */
+ test();
+ if( EQ_16(clip_gain,1)&>_16(*gain_pit,15565))
+ {
+ *gain_pit = 15565;
+ move16();
+ }
+ updt_tar_fx( xn, xn2, y1, *gain_pit, L_SUBFR );
+ }
+
+ st_fx->use_acelp_preq = 1;
+ move16();
+
+ return;
+
+}
+/*-------------------------------------------------------------------*
+ * Find target in residual domain - cn[]
+ *-------------------------------------------------------------------*/
+
+static void find_cn_fx(
+ const Word16 xn[], /* i : target signal */
+ const Word16 Ap[], /* i : weighted LP filter coefficients */
+ const Word16 *p_Aq, /* i : 12k8 LP coefficients */
+ Word16 cn[] /* o : target signal in residual domain */
+)
+{
+ Word16 tmp, tmp_fl[L_SUBFR+M];
+
+ set16_fx( tmp_fl, 0, M );
+ Copy( xn, tmp_fl+M, L_SUBFR );
+ tmp = 0;
+ move16();
+ preemph_fx( tmp_fl+M, PREEMPH_FAC_16k, L_SUBFR, &tmp );
+ syn_filt_s_lc_fx(0, Ap, tmp_fl+M, tmp_fl+M, L_SUBFR);
+ Residu3_lc_fx( p_Aq, M, tmp_fl+M, cn, L_SUBFR, 1 );
+
+ return;
+}
+
+
+/*-----------------------------------------------------------------*
+ * Transform domain contribution encoding
+ *-----------------------------------------------------------------*/
+Word16 gain_quant_fx( /* o: quantization index */
+ Word32 *gain, /* i: quantized gain (Q16) */
+ Word16 *gain16, /* o: quantized gain (expg) */
+ const Word16 c_min, /* i: log10 of lower limit in Q14 */
+ const Word16 c_max, /* i: log10 of upper limit in Q13 */
+ const Word16 bits, /* i: number of bits to quantize */
+ Word16 *expg /* o: output exponent of gain16 */
+)
+{
+ Word16 index, levels;
+ Word16 c_gain;
+ Word16 e_tmp, f_tmp, exp;
+ Word16 tmp, tmp1, tmp2, frac;
+ Word32 L_tmp;
+
+ levels = shl(1, bits);
+ /* Prevent gain to be smaller than 0.0003. */
+ /* This is to avoid an overflow when the gain is very small */
+ /* the log10 give a high negative value in Q13 that overflow */
+ /* on this code (the resulting value of 'index' is not affected. */
+ /* tmp2 = msu_r(L_deposit_h(c_gain),c_min,16384) */
+ L_tmp = L_max(*gain, 20);
+
+ /*c_min = (float)log10(min);*/
+ /*c_mult = (float) ((levels-1)/(log10(max)-c_min));*/
+
+ /*tmp = c_mult * ((float)log10(*gain) - c_min);
+ = ((levels-1)/(log10(max)-log10(min)))*((float)log10(*gain) - log10(min));*/
+
+ e_tmp = norm_l(L_tmp);
+ f_tmp = Log2_norm_lc(L_shl(L_tmp, e_tmp));
+ e_tmp = sub(30-16,e_tmp);/*Q(min)=16*/
+ L_tmp = Mpy_32_16(e_tmp, f_tmp, 9864); /* Q16 */ /*log10(2) in Q15*/
+ c_gain = round_fx(L_shl(L_tmp, 13)); /* Q13 */
+
+ /*tmp1 = sub(c_max,c_min); Q14*/
+ /*tmp2 = sub(c_gain,c_min); Q14*/
+
+ tmp1 = msu_r(L_deposit_h(c_max/*in Q13 already*/),c_min, 16384); /*Q13*/
+ tmp2 = msu_r(L_deposit_h(c_gain/*in Q13 already*/),c_min,16384); /*Q13*/
+ IF(tmp1 != 0)
+ {
+ exp = norm_s(tmp1);
+ frac = div_s(shl(1,sub(14,exp)),tmp1); /*Q(15-exp)*/
+ L_tmp = L_mult(tmp2,frac); /*Q(30-exp)*/
+ L_tmp = Mult_32_16(L_tmp,sub(levels,1)); /*Q(15-exp)*/
+ index = extract_l(L_shr(L_add(L_tmp,shr(1<<14,exp)),sub(15,exp)));
+ }
+ ELSE
+ {
+ L_tmp = L_mult(tmp2,sub(levels,1)); /*Q15*/
+ index = extract_l(L_shr(L_add(L_tmp,1<<14),15));
+ }
+
+ index = s_max(index ,0);
+ index = s_min(index ,sub(levels,1));
+
+ /**gain = (float)pow( 10.0, (((float)index)/c_mult) + c_min );
+ y = index/c_mult + c_min;
+ = (index/(levels-1))*(log10(max) - log10(min)) + log10(min);
+ = z*log10(max) + (1-z)*log10(min)
+ z = (index/(levels-1))*/
+ tmp = div_s(index,sub(levels,1)); /*Q15*/
+ L_tmp = L_mult(tmp,c_max);/*Q29*/
+ L_tmp = L_mac0(L_tmp,sub(32767,tmp),c_min); /*Q29*/
+
+ L_tmp = Mult_32_16(L_tmp,27213); /*Q27, 3.321928 in Q13*/
+ L_tmp = L_shr(L_tmp,11); /*Q27->Q16*/
+
+ frac = L_Extract_lc(L_tmp, expg); /* Extract exponent of gcode0 */
+
+ *gain16 = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */
+ /* output of Pow2() will be: */
+ /* 16384 < Pow2() <= 32767 */
+ *expg = sub(*expg, 14);
+ move16();
+
+ return(index);
+}
diff --git a/lib_enc/enc_nelp_fx.c b/lib_enc/enc_nelp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..4dee03b80dfeb2cf128945e2ce3a08b89db45784
--- /dev/null
+++ b/lib_enc/enc_nelp_fx.c
@@ -0,0 +1,174 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h"
+
+/*==============================================================================*/
+/* FUNCTION : encod_nelp_fx() */
+/*------------------------------------------------------------------------------*/
+/* PURPOSE : Encode Unvoiced frames in SC-VBR */
+/*------------------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ (Encoder_State_fx) st_fx: state structure */
+/* _ (Word16[]) speech_fx : input speech Q_new-1 */
+/* _ (Word16[]) Aq_fx : 12k8 Lp coefficient Q12 */
+/* _ (Word16[]) A_fx : unquantized A(z) filter */
+/* with bandwidth expansion Q12 */
+/* _ (Word16) coder_type_fx : coding type */
+/* _ (Word16[]) res_fx : residual signal Q_new */
+/* _ (Word16*) Q_new : res qformat */
+/* _ (Word16) shift */
+/*------------------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16[]) synth_fx : core synthesis */
+/* _ (Word16[]) tmp_noise_fx: long-term noise energy Q0 */
+/* _ (Word16[]) exc_fx : current non-enhanced excitation Q_new */
+/* _ (Word16[]) exc2_fx : current enhanced excitation Q_new */
+/* _ (Word16[]) pitch_buf_fx: floating pitch values for each subframe Q6 */
+/* _ (Word16*) voice_factors : voicing factors */
+/* _ (Word16*) bwe_exc : excitation for SWB TBE */
+/*------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*==============================================================================*/
+void encod_nelp_fx(
+ Encoder_State_fx *st_fx, /* i/o: state structure */
+ const Word16 *speech_fx, /* i : input speech */
+ const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */
+ const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */
+ Word16 *res_fx, /* o : residual signal */
+ Word16 *synth_fx, /* o : core synthesis */
+ Word16 *tmp_noise_fx, /* o : long-term noise energy */
+ Word16 *exc_fx, /* i/o: current non-enhanced excitation */
+ Word16 *exc2_fx, /* i/o: current enhanced excitation */
+ Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */
+ Word16* voice_factors_fx, /* o : voicing factors */
+ Word16* bwe_exc_fx, /* o : excitation for SWB TBE */
+ Word16 Q_new,
+ Word16 shift
+
+)
+{
+ Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */
+ Word16 h1_fx[L_SUBFR]; /* Impulse response vector */
+ Word16 exc_nelp_fx[L_FRAME];
+
+ Word16 i_subfr, j;
+
+ const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector */
+ Word16 saved_Q_new = Q_new;
+
+ Word16 reduce_gains = 0;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+
+ IF ( EQ_16(st_fx->bwidth_fx, NB)&&GE_32(st_fx->input_Fs_fx,16000))
+ {
+ IF (hSC_VBR->last_nelp_mode == 0)
+ {
+ set16_fx(hSC_VBR->nelp_lp_fit_mem, 0, NELP_LP_ORDER*2 );
+ }
+ Scale_sig(hSC_VBR->nelp_lp_fit_mem, NELP_LP_ORDER*2, sub(Q_new, st_fx->prev_Q_new));
+
+ pz_filter_sp_fx( num_nelp_lp_fx, den_nelp_lp_fx, res_fx, res_fx, hSC_VBR->nelp_lp_fit_mem, NELP_LP_ORDER, NELP_LP_ORDER, L_FRAME, 3); /*16-Q of filter coeff*/
+
+ }
+
+ p_Aw_fx = Aw_fx;
+ p_Aq_fx = Aq_fx;
+
+
+ FOR (i_subfr=0; i_subfrmem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq_fx,
+ res_fx, L_SUBFR, p_Aw_fx, TILT_FAC_FX, xn_fx, NULL, h1_fx);
+
+ /* scale xn[] and h1[] to avoid overflow in dot_product12() */
+ Scale_sig(xn_fx, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
+
+ IF (i_subfr == 0)
+ {
+ test();
+ IF ( EQ_16(hSC_VBR->Local_VAD, 1 ) && EQ_16(st_fx->bwidth_fx,NB))
+ {
+ reduce_gains = 1;
+ }
+
+ nelp_encoder_fx( st_fx, res_fx, exc_nelp_fx, &Q_new, reduce_gains);
+
+ Scale_sig(exc_nelp_fx, L_FRAME, (saved_Q_new - Q_new));
+ }
+
+
+ *tmp_noise_fx = 0;
+ move16();
+
+ /*-----------------------------------------------------------------*
+ * Synthesize speech to update mem_syn[].
+ * Update A(z) filters
+ *-----------------------------------------------------------------*/
+ Syn_filt_s(1, p_Aq_fx, M, &exc_nelp_fx[i_subfr], &synth_fx[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1);
+
+ p_Aw_fx += (M+1);
+ move16();
+ p_Aq_fx += (M+1);
+ move16();
+ *pitch_buf_fx = L_SUBFR_Q6;
+ move16();
+
+ pitch_buf_fx++;
+ move16();
+ }
+
+ Copy(exc_nelp_fx, exc_fx, L_FRAME);
+
+ /*-----------------------------------------------------------------*
+ * Updates: last value of new target is stored in mem_w0
+ *-----------------------------------------------------------------*/
+
+ hLPDmem->mem_w0 = sub(shr(xn_fx[L_SUBFR-1],shift), shr(exc_fx[L_FRAME-1],1));
+ move16();/*Q_new-1 */
+ hLPDmem->tilt_code = 0;
+ move16();/* purely unvoiced */
+ hSC_VBR->prev_tilt_code_fx = hLPDmem->tilt_code;
+ move16();
+
+ Copy(exc_fx, exc2_fx, L_FRAME);
+
+ hSC_VBR->prev_ppp_gain_pit_fx = 0;
+ move16();
+
+ hLPDmem->dm_fx.prev_state = 0;
+ move16();
+ hLPDmem->dm_fx.prev_gain_pit[0] = hSC_VBR->prev_ppp_gain_pit_fx;
+ move16();
+
+ FOR(j=1; j<5; j++)
+ {
+ hLPDmem->dm_fx.prev_gain_pit[j] = hLPDmem->dm_fx.prev_gain_pit[j-1];
+ move16();
+ }
+ interp_code_5over2_fx( exc2_fx, bwe_exc_fx, L_FRAME );
+ set16_fx( voice_factors_fx, 0, NB_SUBFR16k );
+
+ return;
+}
diff --git a/lib_enc/enc_pit_exc_fx.c b/lib_enc/enc_pit_exc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6e9fc0a908c7b6819b56fb521ba61eff19ccb1d
--- /dev/null
+++ b/lib_enc/enc_pit_exc_fx.c
@@ -0,0 +1,540 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*======================================================================*/
+/* FUNCTION : enc_pit_exc_fx() */
+/*----------------------------------------------------------------------*/
+/* PURPOSE : Encode pitch only contribution */
+/* */
+/*----------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ (Struct) st_fx : encoder static memory */
+/* _ (Word16[]) speech_fx : input speech Qnew-1 */
+/* _ (Word16[]) Aq_fx : LP filter coefficient Q12 */
+/* _ (Word16[]) A_fx : unquantized A(z) filter */
+/* with bandwidth expansion Q12 */
+/* _ (Word16) coder_type_fx : coding type */
+/* _ (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */
+/* _ (Word16[]) T_op_fx : open loop pitch Q0 */
+/* _ (Word16[]) voicing_fx : floating pitch values for each subframe Q15*/
+/* _ (Word16[]) res_fx : residual signal Q_new */
+/* _ (Word16[]) exc_fx : adapt. excitation exc (Qnew) */
+/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Qnew) */
+/* _ (Word16[]) pitch_buf_fx : floating pitch values for each subframe Q6*/
+/* _ (Word16[]) *wH1, : Weighted impulses response mask */
+/* _ (Word16) shift : shift */
+/* _ (Word16) Q_new : */
+/*-----------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16[]) exc_fx : adapt. excitation exc (Qnew) */
+/* _ (Word16[]) exc2_fx : adapt. excitation/total exc (Qnew) */
+/* _ (Word16[]) syn_fx :core synthesis */
+/* _ (Word16[]) voice_factors_fx: voicing factors Q15 */
+/* _ (Word16[]) bwe_exc_fx : excitation for SWB TBE Q0 */
+/*-----------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*=======================================================================*/
+void enc_pit_exc_fx(
+ Encoder_State_fx *st_fx, /* i/o: State structure */
+ const Word16 *speech, /* i : Input speech */
+ const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */
+ const Word16 Aq[], /* i : 12k8 Lp coefficient */
+ const Word16 Es_pred, /* i : predicted scaled innov. energy */
+ const Word16 *res, /* i : residual signal */
+ Word16 *synth, /* i/o: core synthesis */
+ Word16 *exc, /* i/o: current non-enhanced excitation */
+ Word16 *T0, /* i/o: close loop integer pitch */
+ Word16 *T0_frac, /* i/o: close-loop pitch period - fractional part */
+ Word16 *pitch_buf, /* i/o: Fractionnal per subframe pitch */
+ const Word16 nb_subfr, /* i : Number of subframe considered */
+ Word16 *gpit, /* o : pitch mean gpit */
+ Word16 *saved_bit_pos, /* o : saved position in the bitstream before pitch contribution */
+ const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */
+ const Word16 tdm_Pri_pitch_buf[], /* i : primary channel pitch buffer */
+ Word16 Q_new,
+ Word16 shift
+)
+{
+ Word16 xn[PIT_EXC_L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2[PIT_EXC_L_SUBFR]; /* Target vector for codebook search */
+ Word16 h1[PIT_EXC_L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 y1[PIT_EXC_L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 code[2*L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y2[2*L_SUBFR]; /* Filtered algebraic excitation */
+ Word16 voice_fac; /* Voicing factor */
+ Word32 gain_code; /* Gain of code */
+ Word16 gain_inov; /* inovation gain */
+ Word16 gain_pit; /* Pitch gain */
+ Word16 pit_idx, i_subfr; /* tmp variables */
+ Word16 T0_min, T0_max; /* pitch variables */
+ Word16 g_corr[10]; /* ACELP correlation values + gain pitch */
+ Word16 clip_gain, i; /* LSF clip gain and LP flag */
+ const Word16 *p_Aw, *p_Aq; /* pointer to LP filter coefficient vector */
+ Word16 cn1[L_SUBFR], *cn; /* (Used only when L_subfr == L_SUBFR) Target vector in residual domain */
+ Word16 *pt_pitch; /* pointer to floating pitch */
+ Word16 L_subfr;
+ Word16 cum_gpit, gpit_tmp;
+ Word32 Local_BR, Pitch_BR;
+ Word16 Pitch_CT, unbits_PI = 0; /* saved bits for PI */
+ Word32 norm_gain_code;
+ Word16 pitch_limit_flag;
+ Word16 h2[PIT_EXC_L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word32 Ltmp;
+ Word32 Lgcode;
+ Word16 gcode16;
+ Word16 shift_wsp;
+ Word16 lp_select, lp_flag;
+ Word16 use_fcb;
+ Word32 gc_mem[NB_SUBFR - 1]; /* gain_code from previous subframes */
+ Word16 gp_mem[NB_SUBFR - 1]; /* gain_pitch from previous subframes*/
+ SP_MUS_CLAS_HANDLE hSpMusClas = st_fx->hSpMusClas;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+ GSC_ENC_HANDLE hGSCEnc = st_fx->hGSCEnc;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /*------------------------------------------------------------------*
+ * Initialization
+ *------------------------------------------------------------------*/
+
+ pitch_limit_flag = 1;
+ move16(); /* always extended pitch Q range */
+ use_fcb = 0;
+ unbits_PI = 0;
+ test();test();
+ Pitch_CT = GENERIC;
+ move16();
+
+ IF (st_fx->GSC_IVAS_mode > 0 && (st_fx->GSC_noisy_speech_fx || GT_32(st_fx->core_brate_fx, GSC_H_RATE_STG)))
+ {
+ Local_BR = ACELP_8k00;
+ Pitch_BR = ACELP_8k00;
+ move32();move32();
+ IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k))
+ {
+ Local_BR = ACELP_14k80;
+ move32();
+ if (st_fx->GSC_IVAS_mode > 0)
+ {
+ Local_BR = ACELP_9k60;
+ move32();
+ }
+ Pitch_BR = st_fx->core_brate_fx;
+ move32();
+ }
+ }
+ ELSE IF( st_fx->GSC_noisy_speech_fx )
+ {
+ Local_BR = ACELP_7k20;
+ move32();
+ Pitch_BR = ACELP_7k20;
+ move32();
+ Pitch_CT = GENERIC;
+ move16();
+ if (EQ_16(st_fx->L_frame_fx, L_FRAME16k))
+ {
+ Pitch_BR = st_fx->core_brate_fx;
+ move32();
+ }
+ }
+ ELSE
+ {
+
+ Local_BR = ACELP_7k20;
+ move32();
+ Pitch_BR = st_fx->core_brate_fx;
+ move32();
+ Pitch_CT = AUDIO;
+ move16();
+
+ if (EQ_16(st_fx->L_frame_fx, L_FRAME16k))
+ {
+ Local_BR = ACELP_13k20;
+ move32();
+ Pitch_CT = GENERIC;
+ move16();
+ }
+ }
+ gain_code = 0;
+ move16();
+
+ IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k))
+ {
+ T0_max = PIT16k_MAX;
+ T0_min = PIT16k_MIN;
+ }
+ ELSE
+ {
+ T0_max = PIT_MAX;
+ move16();
+ T0_min = PIT_MIN;
+ move16();
+ }
+ cum_gpit = 0;
+ move16();
+
+ L_subfr = mult_r(st_fx->L_frame_fx,div_s(1,nb_subfr));
+
+ lp_flag = st_fx->acelp_cfg.ltf_mode;
+
+ test();test();test();test();test();test();test();test();
+ IF (((GE_32(st_fx->core_brate_fx, MIN_RATE_FCB) || (EQ_16(st_fx->GSC_noisy_speech_fx, 1) &&
+ ((EQ_16(st_fx->L_frame_fx, L_FRAME) && GE_32(st_fx->core_brate_fx, ACELP_13k20)) ||
+ (EQ_16(st_fx->L_frame_fx, L_FRAME16k) && GE_32(st_fx->core_brate_fx, GSC_H_RATE_STG)) || st_fx->GSC_IVAS_mode == 0))) && EQ_16(L_subfr, L_SUBFR)))
+ {
+ use_fcb = 1;
+ move16();
+ }
+ ELSE IF (st_fx->GSC_IVAS_mode > 0 && EQ_16(L_subfr, 2 * L_SUBFR) && LT_16(st_fx->GSC_IVAS_mode, 3))
+ {
+ use_fcb = 2;
+ st_fx->acelp_cfg.fcb_mode = 1;
+ move16();move16();
+ set16_fx(st_fx->acelp_cfg.gains_mode, 6, NB_SUBFR);
+ set16_fx(st_fx->acelp_cfg.pitch_bits, 9, NB_SUBFR);
+ set16_fx(st_fx->acelp_cfg.fixed_cdk_index, 14, NB_SUBFR16k);
+ }
+
+ *saved_bit_pos = st_fx->next_bit_pos_fx;
+ move16();
+
+ /*------------------------------------------------------------------*
+ * ACELP subframe loop
+ *------------------------------------------------------------------*/
+ cn = NULL;
+ if(EQ_16(L_subfr, L_SUBFR))
+ {
+ cn = cn1;
+ move16();
+ }
+ p_Aw = Aw;
+
+ p_Aq = Aq;
+ pt_pitch = pitch_buf; /* pointer to the pitch buffer */
+ shift_wsp = add(Q_new,shift);
+ FOR ( i_subfr = 0; i_subfr < st_fx->L_frame_fx; i_subfr += L_subfr )
+ {
+
+ /*----------------------------------------------------------------*
+ * Bandwidth expansion of A(z) filter coefficients
+ * Find the the excitation search target "xn" and innovation
+ * target in residual domain "cn"
+ * Compute impulse response, h1[], of weighted synthesis filter
+ *----------------------------------------------------------------*/
+ Copy( &res[i_subfr], &exc[i_subfr], L_subfr );
+ /* condition on target (compared to float) has been put outside the loop */
+#if 1//ndef BUG_FIX
+ find_targets_fx( speech, hLPDmem->mem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq,
+ res, L_subfr, p_Aw, st_fx->preemph_fac, xn, cn,h1);
+#else
+ find_targets_fx(speech, hGSCEnc->mem_syn_tmp_fx, i_subfr, &hLPDmem->mem_w0, p_Aq, /*_DIFF_FLOAT_FIX_ --> Here I think mem_syn_tmp_fx should be used */
+ res, L_subfr, p_Aw, st_fx->preemph_fac, xn, cn, h1);
+#endif
+ Copy_Scale_sig(h1, h2, L_subfr, -2);
+ Scale_sig(h1, L_subfr, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(xn, L_subfr, shift);
+
+ /*----------------------------------------------------------------*
+ * Close-loop pitch search and quantization
+ * Adaptive exc. construction
+ *----------------------------------------------------------------*/
+ *pt_pitch = pit_encode_fx(hBstr, st_fx->acelp_cfg.pitch_bits, Pitch_BR, 0, st_fx->L_frame_fx, Pitch_CT, &pitch_limit_flag, i_subfr, exc,
+ L_subfr, st_fx->pitch_fx, &T0_min, &T0_max, T0, T0_frac, h1, xn, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf);
+ /*-----------------------------------------------------------------*
+ * Find adaptive exitation
+ *-----------------------------------------------------------------*/
+
+ pred_lt4(&exc[i_subfr], &exc[i_subfr], *T0, *T0_frac, L_subfr+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP);
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ * or in case of floating point encoder & fixed p. decoder
+ *-----------------------------------------------------------------*/
+
+ clip_gain = gp_clip_fx(st_fx->element_mode, st_fx->core_brate_fx, st_fx->voicing_fx, i_subfr, AUDIO, xn, st_fx->clip_var_fx,sub(shift_wsp, 1));
+
+ /*-----------------------------------------------------------------*
+ * Codebook target computation
+ * (No LP filtering of the adaptive excitation)
+ *-----------------------------------------------------------------*/
+
+ lp_select = lp_filt_exc_enc_fx( MODE1, AUDIO, i_subfr, exc, h1,
+ xn, y1, xn2, L_subfr, st_fx->L_frame_fx, g_corr, clip_gain, &gain_pit, &lp_flag );
+
+ IF( EQ_16(lp_flag,NORMAL_OPERATION))
+ {
+ push_indice_fx(hBstr, IND_LP_FILT_SELECT, lp_select, 1 );
+ }
+
+ /*st_fx->lowrate_pitchGain = 0.9f * st_fx->lowrate_pitchGain + 0.1f * gain_pit;*/
+#ifdef BASOP_NOGLOB
+ hSpMusClas->lowrate_pitchGain = round_fx_o(L_mac_o(L_mult(29491, hSpMusClas->lowrate_pitchGain), 6554, gain_pit, &Overflow), &Overflow); /*Q14*Q16(0.1) + Q15 -> Q15*/
+#else
+ hSpMusClas->lowrate_pitchGain = round_fx(L_mac(L_mult(29491, hSpMusClas->lowrate_pitchGain), 6554, gain_pit)); /*Q14*Q16(0.1) + Q15 -> Q15*/
+#endif
+
+ gpit_tmp = gain_pit;
+ move16(); /*Q14*/
+ test();
+ IF(use_fcb > 0)
+ {
+ /* h2 in Q12 for codebook search */
+ /* h1 has been scaled with 1 + shift so we need to remove 2 and (1+shift) = -3 - shift*/
+ Copy_Scale_sig(h1, h2, L_subfr, sub(-2 - 1, shift));
+ }
+
+ IF(use_fcb == 0)
+ {
+ IF (GE_32(st_fx->core_brate_fx, MIN_RATE_FCB))
+ {
+ pit_idx = vquant_fx(&gain_pit, mean_gp_fx, &gain_pit, dic_gp_fx, 1, 32);
+ push_indice_fx(hBstr, IND_PIT_IDX, pit_idx, 5);
+ }
+ ELSE
+ {
+ pit_idx = vquant_fx(&gain_pit, mean_gp_fx, &gain_pit, dic_gp_fx, 1, 16);
+ push_indice_fx(hBstr, IND_PIT_IDX, pit_idx, 4);
+ }
+ }
+ else if (use_fcb == 2)
+ {
+ /*-----------------------------------------------------------------*
+ * Innovation encoding
+ *-----------------------------------------------------------------*/
+
+ inov_encode_fx(st_fx, st_fx->core_brate_fx, 0, st_fx->L_frame_fx, st_fx->last_L_frame_fx, GENERIC, st_fx->bwidth_fx, 0, i_subfr, -1, p_Aq,
+ gain_pit, cn, exc, h2, st_fx->hLPDmem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI, 2 * L_SUBFR, shift);
+//PMT("code to be validated")
+ /*-----------------------------------------------------------------*
+ * Gain encoding
+ *-----------------------------------------------------------------*/
+
+ gain_enc_lbr_fx(st_fx->hBstr, st_fx->acelp_cfg.gains_mode, GENERIC, i_subfr, xn, y1, shift_wsp, y2, code, &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, gc_mem, gp_mem, clip_gain, 2 * L_SUBFR);
+ }
+ ELSE
+ {
+ /*-----------------------------------------------------------------*
+ * Innovation & gain encoding
+ *-----------------------------------------------------------------*/
+
+ inov_encode_fx(st_fx, Local_BR, 0, st_fx->L_frame_fx, st_fx->last_L_frame_fx, LOCAL_CT, WB, 1, i_subfr, -1, p_Aq,
+ gain_pit, cn, exc, h2, hLPDmem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI, L_SUBFR, shift);
+ /*-----------------------------------------------------------------*
+ * Gain encoding
+ *-----------------------------------------------------------------*/
+ gain_enc_mless_fx(hBstr, st_fx->acelp_cfg.gains_mode, st_fx->element_mode, L_FRAME, i_subfr, -1, xn, y1, shift_wsp, y2, code, Es_pred,
+ &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain);
+ }
+ gp_clip_test_gain_pit_fx(st_fx->element_mode, st_fx->core_brate_fx, gain_pit, st_fx->clip_var_fx );
+
+ Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx(Lgcode);
+ IF( use_fcb != 0)
+ {
+ hLPDmem->tilt_code = Est_tilt2(&exc[i_subfr], gain_pit, code, Lgcode, &voice_fac, shift);
+ move16();
+ }
+ ELSE
+ {
+ hLPDmem->tilt_code = 0;
+ move16();
+ }
+ /*-----------------------------------------------------------------*
+ * Update memory of the weighting filter
+ *-----------------------------------------------------------------*/
+ IF(use_fcb != 0)
+ {
+ Ltmp = L_mult(gcode16, y2[L_subfr - 1]);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(Ltmp, add(5, shift), &Overflow);
+ Ltmp = L_negate(Ltmp);
+ Ltmp = L_mac_o(Ltmp, xn[L_subfr - 1], 16384, &Overflow);
+ Ltmp = L_msu_o(Ltmp, y1[L_subfr - 1], gain_pit, &Overflow);
+ Ltmp = L_shl_o(Ltmp, sub(1, shift), &Overflow);
+ hLPDmem->mem_w0 = round_fx_o(Ltmp, &Overflow); /*Q_new-1 */
+#else
+ Ltmp = L_mult(gcode16, y2[L_subfr - 1]);
+ Ltmp = L_shl(Ltmp, add(5, shift));
+ Ltmp = L_negate(Ltmp);
+ Ltmp = L_mac(Ltmp, xn[L_subfr - 1], 16384);
+ Ltmp = L_msu(Ltmp, y1[L_subfr - 1], gain_pit);
+ Ltmp = L_shl(Ltmp, sub(1, shift));
+ hLPDmem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */
+#endif
+ }
+ ELSE
+ {
+ Ltmp = L_mult(xn[L_subfr - 1], 16384);
+ Ltmp = L_msu(Ltmp, y1[L_subfr - 1], gain_pit);
+ Ltmp = L_shl(Ltmp, sub(1, shift));
+ hLPDmem->mem_w0 = round_fx(Ltmp); /*Q_new-1 */
+ }
+
+ /*-----------------------------------------------------------------*
+ * Construct adaptive part of the excitation
+ * Save the non-enhanced excitation for FEC_exc
+ *-----------------------------------------------------------------*/
+ IF(use_fcb != 0)
+ {
+ FOR ( i = 0; i < L_subfr; i++ )
+ {
+ /* code in Q9, gain_pit in Q14 */
+ Ltmp = L_mult(gcode16, code[i]);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(Ltmp, 5, &Overflow);
+ Ltmp = L_mac_o(Ltmp, exc[i + i_subfr], gain_pit, &Overflow);
+ Ltmp = L_shl_o(Ltmp, 1, &Overflow); /* saturation can occur here */
+ exc[i + i_subfr] = round_fx_o(Ltmp, &Overflow);
+#else
+ Ltmp = L_mult(gcode16, code[i]);
+ Ltmp = L_shl(Ltmp, 5);
+ Ltmp = L_mac(Ltmp, exc[i + i_subfr], gain_pit);
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+ exc[i + i_subfr] = round_fx(Ltmp);
+#endif
+ }
+ }
+ ELSE
+ {
+ FOR ( i = 0; i < L_subfr; i++ )
+ {
+
+ Ltmp = L_mult(exc[i + i_subfr], gain_pit);
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+ exc[i + i_subfr] = round_fx(Ltmp);
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Synthesize speech to update mem_syn[].
+ * Update A(z) filters
+ *-----------------------------------------------------------------*/
+
+ Syn_filt_s( 1, p_Aq, M, &exc[i_subfr], &synth[i_subfr], L_subfr, hGSCEnc->mem_syn_tmp_fx, 1 );
+
+ IF (EQ_16(L_subfr, 5 * L_SUBFR))
+ {
+ cum_gpit = gpit_tmp;
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch - 1);
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch - 1);
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch - 1);
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch - 1);
+ move16();
+ pt_pitch++;
+
+ p_Aw += 5 * (M + 1);
+ p_Aq += 5 * (M + 1);
+ }
+ ELSE IF (EQ_16(L_subfr, 5 * L_SUBFR / 2))
+ {
+ IF (i_subfr == 0)
+ {
+ cum_gpit = mult_r(gpit_tmp, 13107); /* .4f*/
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch - 1);
+ move16();
+ pt_pitch++;
+ p_Aw += 2 * (M + 1);
+ p_Aq += 2 * (M + 1);
+ }
+ ELSE
+ {
+ cum_gpit = add(cum_gpit, mult_r(gpit_tmp, 19660)); /*0.6*/
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch - 1);
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch - 1);
+ move16();
+ pt_pitch++;
+ p_Aw += 3 * (M + 1);
+ p_Aq += 3 * (M + 1);
+ }
+ }
+ ELSE IF( EQ_16(L_subfr,2*L_SUBFR))
+ {
+ IF( i_subfr == 0 )
+ {
+ cum_gpit = mult_r(gpit_tmp,16384);
+ }
+ ELSE
+ {
+ cum_gpit = add(cum_gpit,mult_r(gpit_tmp,16384));
+ }
+ p_Aw += 2*(M+1);
+ move16();
+ p_Aq += 2*(M+1);
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch-1);
+ move16();
+ pt_pitch++;
+ }
+ ELSE IF(EQ_16(L_subfr,4*L_SUBFR))
+ {
+ cum_gpit = gpit_tmp;
+ move16();
+
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch-1);
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch-1);
+ move16();
+ pt_pitch++;
+ *pt_pitch = *(pt_pitch-1);
+ pt_pitch++;
+ p_Aw += 4*(M+1);
+ p_Aq += 4*(M+1);
+ }
+ ELSE
+ {
+ IF( i_subfr == 0 )
+ {
+
+ cum_gpit = mult_r(gpit_tmp,8192);
+ }
+ ELSE
+ {
+ cum_gpit = add(cum_gpit,mult_r(gpit_tmp,8192));
+ }
+
+ pt_pitch++;
+ p_Aw += (M+1);
+ p_Aq += (M+1);
+ }
+ }
+
+#ifdef BASOP_NOGLOB
+ cum_gpit = shl_o(cum_gpit,1, &Overflow); /*Q15*/
+#else /* BASOP_NOGLOB */
+ cum_gpit = shl(cum_gpit,1); /*Q15*/
+#endif
+ *gpit = round_fx(L_mac(L_mult(3277 , *gpit), 29491, cum_gpit)); /*Q15*/
+
+
+}
diff --git a/lib_enc/enc_ppp_fx.c b/lib_enc/enc_ppp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..da31fa71df75da31740f552a6954aaa13427d40f
--- /dev/null
+++ b/lib_enc/enc_ppp_fx.c
@@ -0,0 +1,240 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+/*Temporary location to be move in prot* when merge is done */
+void E_LPC_f_lsp_a_conversion(const Word16 *lsp, Word16 *a, const Word16 m);
+
+/*=======================================================================================*/
+/* FUNCTION : encod_ppp_fx() */
+/*---------------------------------------------------------------------------------------*/
+/* PURPOSE : */
+/*---------------------------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ (Word16) speech_fx[], i : input speech Q_new */
+/* _ (Word16) Aq_fx[], i : 12k8 Lp coefficient Q12 */
+/* _ (Word16) A_fx[], i : unquantized A(z) filter with bandwidth expansion Q12*/
+/* _ (Word16) coder_type_fx, i : coding type */
+/* _ (Word16) T_op_fx[], i : open loop pitch */
+/* _ (Word16) voicing_fx[], i : voicing Q15 */
+/* _ (Word16) *res_fx, i : residual signal Q_new */
+/* _ (Word16) Q_new i : Q factor for res */
+/* _ (Word16) vadsnr_fx i : SNR for current frame Q7 */
+/*---------------------------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16) *exc2_fx, o : current enhanced excitation Q0 */
+/* _ (Word16) *pitch_buf_fx, o : floating pitch values for each subframe Q6 */
+/* _ (Word16) *synth_fx, o : core synthesis Q-1 */
+/* _ Encoder_State_fx *st_fx: */
+/* _ lastLgainE_fx - Q11 */
+/* _ lastHgainE_fx - Q11 */
+/* _ lasterbE_fx - Q13 */
+/*---------------------------------------------------------------------------------------*/
+/* INPUT/OUTPUT ARGUMENTS : */
+/* _ Encoder_State_fx *st_fx: */
+/* _ st_fx->dtfs_enc_xxxx */
+/* _ a nd b in st_fx->dtfs_enc_Q */
+/* rest all in Q0 */
+/* - bump_up_fx - Q0 */
+/* _ (Word16) *exc_fx, o : current enhanced excitation Q0 */
+/*---------------------------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None. */
+/*---------------------------------------------------------------------------------------*/
+/* CALLED FROM : TX */
+/*=======================================================================================*/
+ivas_error encod_ppp_fx(
+ Encoder_State_fx* st_fx, /* i/o: state structure */
+ const Word16 speech_fx[], /* i : input speech Q_new*/
+ const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */
+ const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */
+ Word16 *res_fx, /* i : residual signal Q_new*/
+ Word16 *synth_fx, /* o : core synthesis Q-1*/
+ Word16 *exc_fx, /* i/o: current non-enhanced excitation Q_new*/
+ Word16 *exc2_fx, /* o : current enhanced excitation Q0*/
+ Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe Q6*/
+ Word16 *voice_factors, /* o : voicing factors */
+ Word16 *bwe_exc, /* o : excitation for SWB TBE */
+ Word16 Q_new,
+ Word16 shift
+)
+{
+ Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */
+ Word16 h1_fx[L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 i_subfr; /* tmp variables */
+ const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector*/
+
+ Word16 k;
+ Word16 p_Aq_old_fx[M+1], excQ_ppp_fx[L_FRAME] ,p_Aq_curr_fx[M], pitch_fx[NB_SUBFR];
+ Word16 LPC_de_old_fx[M+1], LPC_de_curr_fx[M+1];
+ Word16 shift_wsp = add(Q_new,shift);
+ Word16 rate_ctrl_fx;
+ Word16 saved_Q_new = Q_new;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+ ivas_error error;
+
+ error = IVAS_ERR_OK;
+ move16();
+ rate_ctrl_fx = hSC_VBR->rate_control;
+ move16();
+
+ /*------------------------------------------------------------------*
+ * ACELP subframe loop
+ *------------------------------------------------------------------*/
+ p_Aw_fx = Aw_fx;
+ p_Aq_fx = Aq_fx;
+ FOR (i_subfr=0; i_subfrmem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq_fx,
+ res_fx, L_SUBFR, p_Aw_fx, TILT_FAC_FX, xn_fx, NULL, h1_fx);
+
+ /* scale xn[] and h1[] to avoid overflow in dot_product12() */
+ Scale_sig(xn_fx, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
+
+ /* call voiced encoder at this point */
+ IF (i_subfr == 0) /* generate the L_FRAME exc */
+ {
+ FOR(k=0; klsp_old_fx, p_Aq_old_fx, M );
+ deemph_lpc_fx( p_Aq_curr_fx, p_Aq_old_fx, LPC_de_curr_fx, LPC_de_old_fx ,1);
+ /* both outputs LPC_de_curr_fx and LPC_de_old_fx are in Q12 */
+
+
+ /* last frame-end lpc and curr frame-end lpc */
+ IF((error = ppp_voiced_encoder_fx(hBstr, hSC_VBR, st_fx->bwidth_fx, st_fx->last_coder_type_raw_fx, st_fx->old_pitch_buf_fx, res_fx,
+ excQ_ppp_fx, st_fx->pitch_fx[1], LPC_de_old_fx, LPC_de_curr_fx, exc_fx, pitch_fx, Q_new)) != IVAS_ERR_OK)
+ {
+ return error;
+ }
+
+ Scale_sig(exc_fx, L_FRAME, (saved_Q_new - Q_new));
+ if (EQ_16(hSC_VBR->bump_up,1))
+ {
+ i_subfr = L_FRAME;
+ move16();
+ }
+ }
+
+ IF( NE_16(hSC_VBR->bump_up,1))
+ {
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ * or in case of floating point encoder & fixed p. decoder
+ *-----------------------------------------------------------------*/
+ gp_clip_fx(st_fx->element_mode, st_fx->core_brate_fx, st_fx->voicing_fx, i_subfr, st_fx->coder_type, xn_fx, st_fx->clip_var_fx, sub(shift_wsp,1));
+
+
+ /* run the above to maintain gain clipping memories */
+ gp_clip_test_gain_pit_fx(st_fx->element_mode, st_fx->core_brate_fx, hSC_VBR->prev_ppp_gain_pit_fx, st_fx->clip_var_fx );
+
+
+ /*-----------------------------------------------------------------*
+ * Synthesize speech to update mem_syn[].
+ * Update A(z) filters
+ *-----------------------------------------------------------------*/
+
+ Syn_filt_s( 1, p_Aq_fx, M, &excQ_ppp_fx[i_subfr], &synth_fx[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1 );
+
+
+ p_Aw_fx += (M+1);
+ p_Aq_fx += (M+1);
+ }
+
+ } /* end of subframe loop */
+
+ IF(hSC_VBR->bump_up )
+ {
+ /* PPP failed, bump up */
+ hSC_VBR->ppp_mode = 0;
+ move16();
+ st_fx->core_brate_fx = ACELP_7k20;
+ move16();
+ hSC_VBR->pppcountE = 0;
+ move16();
+
+ IF (hSC_VBR->set_ppp_generic )
+ {
+ st_fx->coder_type = GENERIC;
+ move16();
+ }
+ ELSE
+ {
+ st_fx->coder_type = VOICED;
+ move16();
+ }
+
+ /* We write signalling indices again only in case of bump_up */
+ /* delete previous indices */
+#ifndef IVAS_CODE_BITSTREAM
+ reset_indices_enc_fx(hBstr);
+#else
+ reset_indices_enc_fx(hBstr, hBstr->nb_ind_tot );
+#endif
+
+ /* signalling matrix (writing of signalling bits) */
+ signalling_enc_fx( st_fx);
+ }
+ ELSE
+ {
+ Copy(excQ_ppp_fx, exc_fx, L_FRAME);
+
+ /*-----------------------------------------------------------------*
+ * Updates: last value of new target is stored in mem_w0
+ *-----------------------------------------------------------------*/
+
+ hLPDmem->mem_w0 = sub(shr(xn_fx[L_SUBFR-1],shift), shr(exc_fx[L_FRAME-1],1)); /*Q_new-1 */
+
+ Copy(exc_fx, exc2_fx, L_FRAME);
+
+ hLPDmem->dm_fx.prev_state = 2;
+ move16();/*Q0 dispMem index 0 */
+ hLPDmem->dm_fx.prev_gain_pit[0] = hSC_VBR->prev_ppp_gain_pit_fx;
+ move16();/*Q14 dispMem index 2 */
+
+ FOR( k=1; k<5; k++ )
+ {
+ hLPDmem->dm_fx.prev_gain_pit[k] = hLPDmem->dm_fx.prev_gain_pit[k-1];
+ move16();
+ }
+
+ hLPDmem->tilt_code = hSC_VBR->prev_tilt_code_fx;
+ move16();
+ Copy(pitch_fx, pitch_buf_fx, NB_SUBFR);
+ pitch_buf_fx[ NB_SUBFR16k -1 ] = pitch_fx[ NB_SUBFR - 1 ];
+
+ interp_code_5over2_fx( exc2_fx, bwe_exc, L_FRAME );
+ set16_fx( voice_factors, 0, NB_SUBFR16k );
+ }
+
+ hSC_VBR->rate_control = rate_ctrl_fx;
+ move16();
+
+ set16_fx(hSC_VBR->nelp_lp_fit_mem, 0, NELP_LP_ORDER * 2);
+
+ return error;
+}
diff --git a/lib_enc/enc_prm_fx.c b/lib_enc/enc_prm_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..f8a51682aabef070fa97fdca264b5539bf60447e
--- /dev/null
+++ b/lib_enc/enc_prm_fx.c
@@ -0,0 +1,926 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+#include "rom_com_fx.h"
+#include "rom_com.h"
+#include "stl.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+static void enc_prm_hm(
+ Word16 *prm_hm,
+ Encoder_State_fx *st,
+ Word16 L_frame
+)
+{
+ Word8 flag;
+ BSTR_ENC_HANDLE hBstr = st->hBstr;
+
+
+ /* Disable HM for non-GC,VC modes */
+ test();
+ IF (NE_16(st->hTcxCfg->coder_type, VOICED)&&NE_16(st->hTcxCfg->coder_type,GENERIC))
+ {
+ return;
+ }
+
+ /* Flag */
+ push_next_indice_fx(hBstr, prm_hm[0], 1);
+
+ IF (prm_hm[0])
+ {
+ /* Periodicy index */
+ flag = 0;
+ move16();
+ if ( GE_16(L_frame, 256))
+ {
+ flag = 1;
+ move16();
+ }
+ EncodeIndex_fx(flag, prm_hm[1], hBstr);
+
+ IF (EQ_16(st->hTcxCfg->coder_type, VOICED))
+ {
+ /* Gain index */
+ push_next_indice_fx(hBstr, prm_hm[2], kTcxHmNumGainBits);
+ }
+ }
+}
+
+/*-----------------------------------------------------------------*
+ * Function enc_prm_rf_fx() *
+ * ~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * encode RF parameters for ACELP and TCX partial copy *
+ *-----------------------------------------------------------------*/
+
+void enc_prm_rf_fx( Encoder_State_fx *st,
+ const Word16 rf_frame_type,
+ const Word16 fec_offset
+ )
+{
+ Word16 sfr, nb_subfr, n, index;
+ Word16 ltp_mode, ltf_mode, gains_mode;
+ RF_ENC_HANDLE hRF = st->hRF;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+ BSTR_ENC_HANDLE hBstr = st->hBstr;
+
+
+ nb_subfr = st->nb_subfr;
+
+ /* partial copy bitstream writing */
+ test();
+ IF ( GE_16(rf_frame_type,RF_TCXFD)&&LE_16(rf_frame_type,RF_TCXTD2))
+ {
+ /* TCX frames partial copy write */
+
+ /* LSF indices */
+ IF( EQ_16(rf_frame_type, RF_TCXFD))
+ {
+ push_next_indice_fx( hBstr, hRF->rf_indx_lsf[fec_offset][0], lsf_numbits[0]); /* VQ 1 */
+ push_next_indice_fx( hBstr, hRF->rf_indx_lsf[fec_offset][1], lsf_numbits[1]); /* VQ 2 */
+ push_next_indice_fx( hBstr, hRF->rf_indx_lsf[fec_offset][2], lsf_numbits[2]); /* VQ 3 */
+ }
+
+ /* classification */
+ test();
+ test();
+ IF( EQ_16(hRF->rf_clas[fec_offset], UNVOICED_CLAS))
+ {
+ index = 0;
+ move16();
+ }
+ ELSE IF( (EQ_16(hRF->rf_clas[fec_offset], VOICED_TRANSITION))||(EQ_16(hRF->rf_clas[fec_offset],UNVOICED_TRANSITION)))
+ {
+ index = 1;
+ move16();
+ }
+ ELSE IF( EQ_16(hRF->rf_clas[fec_offset], VOICED_CLAS))
+ {
+ index = 2;
+ move16();
+ }
+ ELSE
+ {
+ index = 3;
+ move16();
+ }
+ push_next_indice_fx( hBstr, index, 2);
+
+ IF( EQ_16(rf_frame_type, RF_TCXFD))
+ {
+ /* TCX global gain = 7 bits */
+ push_next_indice_fx( hBstr, hRF->rf_gain_tcx[fec_offset], 7);
+ /*window info
+ 1 bit for long overlap
+ 2 if minimum or half overlap*/
+ }
+ ELSE
+ {
+ /*gains adapt
+ gains inov*/
+
+ /*LPC on full rate -> excitation */
+ /* pitch and gain */
+ /* LTP data */
+ test();
+ IF ( (EQ_16(rf_frame_type, RF_TCXTD1)||EQ_16(rf_frame_type,RF_TCXTD2))&& hTcxEnc->tcxltp!=0)
+ {
+ push_next_indice_fx( hBstr, hRF->rf_tcxltp_param[fec_offset], 9);
+ }
+ }
+ }
+ ELSE IF( EQ_16(rf_frame_type,7)) /* NELP bitstream writing */
+ {
+ /* LSF indices */
+ push_next_indice_fx( hBstr, hRF->rf_indx_lsf[fec_offset][0], 8); /* VQ 1 */
+ push_next_indice_fx( hBstr, hRF->rf_indx_lsf[fec_offset][1], 8); /* VQ 2 */
+
+ /* NELP gain indices */
+ push_next_indice_fx( hBstr, hRF->rf_indx_nelp_iG1[fec_offset], 5 );
+ push_next_indice_fx( hBstr, hRF->rf_indx_nelp_iG2[fec_offset][0], 6 );
+ push_next_indice_fx( hBstr, hRF->rf_indx_nelp_iG2[fec_offset][1], 6 );
+
+ /* NELP filter selection index */
+ push_next_indice_fx( hBstr, hRF->rf_indx_nelp_fid[fec_offset], 2 );
+
+ /* tbe gainFr */
+ push_next_indice_fx( hBstr, hRF->rf_indx_tbeGainFr[fec_offset], 5 );
+ }
+ ELSE IF ( GE_16(rf_frame_type,4)) /* rf_frame_type ALL_PRED: 4, NO_PRED: 5, GEN_PRED: 6 */
+ {
+ /* LSF indices */
+ push_next_indice_fx( hBstr, hRF->rf_indx_lsf[fec_offset][0], 8); /* VQ 1 */
+ push_next_indice_fx( hBstr, hRF->rf_indx_lsf[fec_offset][1], 8); /* VQ 2 */
+
+ /* ES pred */
+ push_next_indice_fx( hBstr, hRF->rf_indx_EsPred[fec_offset], 3);
+
+ ltp_mode = ACELP_LTP_MODE[1][1][rf_frame_type];
+ ltf_mode = ACELP_LTF_MODE[1][1][rf_frame_type];
+ gains_mode = ACELP_GAINS_MODE[1][1][rf_frame_type];
+
+ /* Subframe parameters */
+ FOR( sfr = 0; sfr < nb_subfr; sfr++ )
+ {
+ /* Pitch lag (5, or 8 bits) */
+ n = ACELP_LTP_BITS_SFR[ltp_mode][sfr];
+ IF (n != 0)
+ {
+ push_next_indice_fx( hBstr, hRF->rf_indx_pitch[fec_offset][sfr], n);
+ }
+
+ /* Adaptive codebook filtering (1 bit) */
+ IF( EQ_16(ltf_mode,2))
+ {
+ push_next_indice_fx( hBstr, hRF->rf_indx_ltfMode[fec_offset][sfr], 1);
+ }
+
+ /*Innovative codebook*/
+ test();
+ test();
+ test();
+ IF( (EQ_16(rf_frame_type,RF_NOPRED))||
+ (EQ_16(rf_frame_type,RF_GENPRED) &&
+ (sfr == 0 || EQ_16(sfr,2))) )
+ {
+ push_next_indice_fx( hBstr, hRF->rf_indx_fcb[fec_offset][sfr], 7);
+ }
+
+ /* Gains (5b, 6b or 7b / subfr) */
+ test();
+ IF( sfr == 0 || EQ_16(sfr,2))
+ {
+ n = ACELP_GAINS_BITS[gains_mode];
+ push_next_indice_fx( hBstr, hRF->rf_indx_gain[fec_offset][sfr], n);
+ }
+ }
+ /* tbe gainFr */
+ push_next_indice_fx( hBstr, hRF->rf_indx_tbeGainFr[fec_offset], 2 );
+ }
+
+ /***************/
+ /*IMPORTANT: The last three bits are always the rf_frame_type in the bitstream (for both acelp and tcx partial copy);
+ the rf_frame_type indicates the length of the partial copy payload at the decoder.
+ The 2 bits before the rf_frame_type contains the fec_offset */
+
+ /***************/
+ /* write FEC offset just before the rf_frame_type */
+ test();
+ test();
+ IF(EQ_16(fec_offset,2))
+ {
+ push_next_indice_fx( hBstr, 0, 2);
+ }
+ ELSE IF(EQ_16(fec_offset,3)||EQ_16(fec_offset,5)||EQ_16(fec_offset,7))
+ {
+ push_next_indice_fx( hBstr, (fec_offset - 1)/2, 2);
+ }
+
+ /* write RF frame type last in the bitstream */
+ push_next_indice_fx( hBstr, rf_frame_type, 3);
+
+}
+
+
+
+
+/*-----------------------------------------------------------------*
+ * Funtion enc_prm_fx() *
+ * ~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * encode parameters according to selected mode including *
+ * the FAC parameters when transition occurs. *
+ *-----------------------------------------------------------------*/
+
+void enc_prm_fx(
+ const Word16 coder_type, /* (i) : coding type */
+ Word16 param[], /* (i) : parameters */
+ Word16 param_lpc[], /* (i) : LPC parameters */
+ Encoder_State_fx *st, /* i/o : quantization Analysis values */
+ Word16 L_frame,
+ CONTEXT_HM_CONFIG hm_cfg[]
+ ,Word16 * bits_param_lpc,
+ Word16 no_param_lpc
+)
+{
+ Word16 j, k, n, sfr, core, last_core, *prm, tmp;
+ Word16 nbits_start, total_nbbits;
+ Word16 nbits_header;
+ Word16 nbits_lpc;
+ Word16 nbits_tcx;
+ Word16 lg,nb_subfr;
+ Word16 lgFB;
+ Word16 nTnsParams;
+ Word16 nTnsBits;
+ Word16 ix, j_old, wordcnt, bitcnt;
+ Word16 hm_size;
+ Word16 numlpc;
+ Word8 flag_ctx_hm;
+ Word16 index;
+ Word32 tmp32;
+ CONTEXT_HM_CONFIG * phm_cfg;
+ Word16 idx;
+ Word16 start_idx;
+ Word16 nBits;
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+ BSTR_ENC_HANDLE hBstr = st->hBstr;
+
+ /*--------------------------------------------------------------------------------*
+ * INIT
+ *--------------------------------------------------------------------------------*/
+
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ move16();
+ nbits_lpc=0;
+ nbits_tcx = 0;
+
+ flag_ctx_hm = 0;
+
+ /* Useful parameters */
+ move16();
+ move16();
+ move16();
+ nb_subfr = st->nb_subfr;
+ core = st->core_fx;
+ last_core = st->last_core_fx;
+
+ /* Initialize pointers */
+ move16();
+ prm = param;
+
+ /* Init counters */
+ move16();
+ move16();
+ j = 0;
+ nbits_start = hBstr->nb_bits_tot_fx;
+
+
+ /*--------------------------------------------------------------------------------*
+ * HEADER
+ *--------------------------------------------------------------------------------*/
+
+ IF (EQ_16(st->mdct_sw, MODE1))
+ {
+ /* Adjust st->bits_frame_core not to subtract MODE2 bandwidth signaling */
+ st->bits_frame_core = add(st->bits_frame_core, FrameSizeConfig[st->frame_size_index].bandwidth_bits);
+
+ /* Write MODE1 core mode signaling */
+ signalling_mode1_tcx20_enc(st, 1);
+ }
+
+ /* Modes (ACE_GC, ACE_UC, TCX20, TCX10...) */
+
+ IF ( st->tcxonly )
+ {
+ push_next_indice_fx( hBstr, core==TCX_10_CORE, 1);
+ {
+ index = 3;
+ move16();
+ test();
+ IF( EQ_16(st->clas_fx, UNVOICED_CLAS))
+ {
+ index = 0;
+ move16();
+ }
+ ELSE IF( (EQ_16(st->clas_fx, VOICED_TRANSITION))||(EQ_16(st->clas_fx,UNVOICED_TRANSITION)))
+ {
+ index = 1;
+ move16();
+ }
+ ELSE IF( EQ_16(st->clas_fx, VOICED_CLAS))
+ {
+ index = 2;
+ move16();
+ }
+ push_next_indice_fx( hBstr, index, 2);
+ }
+ }
+ ELSE
+ {
+ IF ( core==ACELP_CORE )
+ {
+ /* write the RF signalling information */
+ IF( EQ_16(st->rf_mode,1))
+ {
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ idx = 0;
+ WHILE ( NE_32(acelp_sig_tbl[idx],st->total_brate_fx)) /* total bitrate is kept at 13.2kbps */
+ {
+ idx = add(idx,1);
+ }
+
+ /* retrieve the number of bits for signalling */
+ nBits = (Word16) acelp_sig_tbl[++idx];
+
+ /* retrieve the signalling index */
+ idx = add(idx,1);
+ start_idx = idx;
+ tmp32 = SIG2IND_fx(coder_type, st->bwidth_fx, st->sharpFlag, st->rf_mode);
+ WHILE( NE_32(acelp_sig_tbl[idx], tmp32))
+ {
+ idx = add(idx,1);
+ }
+ push_next_indice_fx( hBstr, idx - start_idx, nBits);
+ push_next_indice_fx( hBstr, 0, 1); /* Indicate to the decoder that the core is ACELP*/
+ nbits_start = 3;
+ }
+ ELSE
+ {
+ push_next_indice_fx( hBstr, coder_type, 3);
+ }
+ }
+ ELSE
+ {
+ IF (EQ_16(st->mdct_sw, MODE1))
+ {
+ /* 2 bits instead of 3 as TCX is already signaled */
+ push_next_indice_fx( hBstr, st->hTcxCfg->coder_type, 2 );
+ }
+ ELSE
+ {
+ IF (EQ_16(st->mdct_sw_enable, MODE2))
+ {
+ push_next_indice_fx( hBstr, 1, 1); /* TCX */
+ push_next_indice_fx( hBstr, 0, 1); /* not HQ_CORE */
+ push_next_indice_fx( hBstr, st->hTcxCfg->coder_type, 2);
+ }
+ ELSE
+ {
+ /*write the RF signalling information*/
+ IF( EQ_16(st->rf_mode,1))
+ {
+ /* find the section in the ACELP signalling table corresponding to bitrate */
+ idx = 0;
+ WHILE (NE_32(acelp_sig_tbl[idx],st->total_brate_fx))
+ {
+ idx = add(idx,1);
+ }
+
+ /* retrieve the number of bits for signalling */
+ nBits = (Word16) acelp_sig_tbl[++idx];
+
+ test();
+ test();
+ IF(EQ_16(st->hTcxCfg->coder_type,VOICED)||
+ EQ_16(st->hTcxCfg->coder_type,GENERIC)||
+ EQ_16(st->hTcxCfg->coder_type,TRANSITION))
+ {
+ st->sharpFlag=1;
+ }
+ ELSE
+ {
+ st->sharpFlag=0;
+ }
+
+ /* retrieve the signalling index */
+ idx = add(idx,1);
+ start_idx = idx;
+ tmp32 = SIG2IND_fx(st->hTcxCfg->coder_type, st->bwidth_fx, st->sharpFlag, st->rf_mode);
+ WHILE( NE_32(acelp_sig_tbl[idx], tmp32))
+ {
+ idx = add(idx,1);
+ }
+ push_next_indice_fx( hBstr, idx - start_idx, nBits);
+ push_next_indice_fx( hBstr, 1, 1); /* Indicate to the decoder that the core is TCX*/
+ nbits_start = 3;
+ }
+ ELSE
+ {
+ push_next_indice_fx( hBstr, 4+st->hTcxCfg->coder_type, 3 );
+ }
+ }
+ }
+ }
+ }
+
+ /* Encode previous mode for error concealment */
+ test();
+ IF (!(core==ACELP_CORE&&st->hTcxCfg->lfacNext<=0))
+ {
+ tmp = 0;
+ move16();
+ test();
+ IF( NE_16(last_core, ACELP_CORE)||EQ_16(core,TCX_10_CORE))
+
+ {
+ tmp = TCX_20_CORE;
+ move16();
+ }
+ push_next_indice_fx( hBstr, tmp, 1);
+ }
+
+ /* write TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */
+ IF ( core!=ACELP_CORE )
+ {
+ Word16 overlap_code;
+ assert(st->hTcxCfg->tcx_curr_overlap_mode != NOT_SUPPORTED && st->hTcxCfg->tcx_curr_overlap_mode <= ALDO_WINDOW && st->hTcxCfg->tcx_curr_overlap_mode >= FULL_OVERLAP); /*1 is not allowed!*/
+ IF (EQ_16(st->hTcxCfg->tcx_curr_overlap_mode, MIN_OVERLAP))
+ {
+ nbits_tcx = 2;
+ move16();
+ overlap_code = 2;
+ move16();
+ }
+ ELSE IF (EQ_16(st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP))
+ {
+ nbits_tcx = 2;
+ move16();
+ overlap_code = 3;
+ move16();
+ }
+ ELSE
+ {
+ nbits_tcx = 1;
+ move16();
+ overlap_code = 0;
+ move16();
+ }
+ push_next_indice_fx( hBstr, overlap_code, nbits_tcx);
+ }
+
+ IF( st->hPlcExt->enableGplc )
+ {
+ /* encode side information. */
+ enc_prm_side_Info_fx( st->hPlcExt, st );
+ }
+
+ IF( st->glr != 0)
+ {
+ test();
+ test();
+ test();
+ test();
+ if (core != ACELP_CORE || EQ_16(coder_type,INACTIVE)||(st->last_core_fx==ACELP_CORE&&EQ_16(st->last_coder_type_raw_fx,INACTIVE))||st->glr_reset!=0)
+ {
+ st->glr_idx[0] = 0;
+ move16();
+ }
+
+ IF( EQ_16(core,ACELP_CORE))
+ {
+ push_next_indice_fx( hBstr, st->glr_idx[0], G_LPC_RECOVERY_BITS);
+ }
+ }
+
+ st->glr_reset = 0;
+ move16();
+
+ nbits_header = sub(hBstr->nb_bits_tot_fx, nbits_start);
+
+
+ /*--------------------------------------------------------------------------------*
+ * LPC PARAMETERS
+ *--------------------------------------------------------------------------------*/
+
+ IF ( s_and(st->enableTcxLpc!=0, core != ACELP_CORE) )
+ {
+ /* Encode the indices */
+ nbits_lpc = enc_lsf_tcxlpc_fx(¶m_lpc, hBstr);
+ }
+ ELSE
+ {
+ IF (st->lpcQuantization == 0)
+ {
+ /* LPC quantizer */
+ numlpc = 2;
+ move16();
+ if(EQ_16(core, TCX_20_CORE))
+ {
+ numlpc = 1;
+ move16();
+ }
+
+ nbits_lpc = encode_lpc_avq_fx(hBstr, numlpc, param_lpc, st->core_fx, st->element_mode);
+ }
+ ELSE IF (EQ_16(st->lpcQuantization, 1))
+ {
+ test();
+ test();
+ IF(EQ_32(st->sr_core, 16000)&&EQ_16(coder_type,VOICED)&&EQ_16(core,ACELP_CORE))
+ {
+ nbits_lpc = lsf_bctcvq_encprm_fx(hBstr, param_lpc, bits_param_lpc, no_param_lpc);
+ }
+ ELSE
+ {
+ nbits_lpc = lsf_msvq_ma_encprm_fx(hBstr, param_lpc, core, coder_type, st->acelp_cfg.midLpc, bits_param_lpc, no_param_lpc );
+ }
+ }
+ ELSE
+ {
+ assert(0 && "LPC quant not supported!");
+ }
+ }
+
+
+ /*--------------------------------------------------------------------------------*
+ * PRINT BIT ALLOCATION
+ *--------------------------------------------------------------------------------*/
+
+
+
+ /*--------------------------------------------------------------------------------*
+ * ACELP
+ *--------------------------------------------------------------------------------*/
+
+ IF (core == ACELP_CORE)
+ {
+ /* Adaptive BPF (2 bits)*/
+ n = ACELP_BPF_BITS[st->acelp_cfg.bpf_mode];
+
+ IF(n!=0)
+ {
+ push_next_indice_fx( hBstr, st->bpf_gain_param, n);
+ }
+
+ /* Mean energy (2 or 3 bits) */
+ n = ACELP_NRG_BITS[st->acelp_cfg.nrg_mode];
+
+ IF(n!=0)
+ {
+ push_next_indice_fx( hBstr, prm[j++], n);
+ }
+
+ /* Subframe parameters */
+
+ FOR (sfr=0; sfracelp_cfg.ltp_mode][sfr];
+
+ IF (n!=0)
+ {
+ push_next_indice_fx( hBstr, prm[j++], n);
+ }
+
+ /* Adaptive codebook filtering (1 bit) */
+
+ IF(EQ_16(st->acelp_cfg.ltf_mode,2))
+ {
+ push_next_indice_fx( hBstr, prm[j++], 1);
+ }
+
+ /*Innovative codebook*/
+ {
+ move16();
+ j_old = j;
+
+ if ((st->acelp_cfg.fixed_cdk_index[sfr] >= ACELP_FIXED_CDK_NB) || (st->acelp_cfg.fixed_cdk_index[sfr] < 0))
+ {
+ fprintf(stderr,"ACELP bits allocation: wrong fixed cdk bit allocation\n");
+ assert(0);
+ }
+
+
+ wordcnt = shr(ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]), 4);
+
+ bitcnt = s_and(ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[sfr]), 15);
+
+
+ FOR (ix = 0; ix < wordcnt; ix++)
+ {
+ push_next_indice_fx( hBstr, prm[j++], 16);
+ }
+
+ IF (bitcnt)
+ {
+ push_next_indice_fx( hBstr, prm[j++], bitcnt);
+ }
+
+ j = add(j_old, 8);
+ }
+
+ /* Gains (5b, 6b or 7b / subfr) */
+ n = ACELP_GAINS_BITS[st->acelp_cfg.gains_mode[sfr]];
+ push_next_indice_fx( hBstr, prm[j++], n);
+ }/*end of for(sfr)*/
+ }/*end of mode[0]==0*/
+
+
+ /*--------------------------------------------------------------------------------*
+ * TCX20
+ *--------------------------------------------------------------------------------*/
+ IF ( s_or((Word16)EQ_16(core,TCX_20_CORE),(Word16)EQ_16(core,HQ_CORE)))
+ {
+ flag_ctx_hm = 0;
+ move16();
+ IF(st->enablePlcWaveadjust)
+ {
+ push_next_indice_fx( hBstr, st->Tonal_SideInfo, 1);
+ }
+
+ /* TCX Gain = 7 bits */
+ push_next_indice_fx( hBstr, prm[j++], 7);
+
+ /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */
+ push_next_indice_fx( hBstr, prm[j++], NBITS_NOISE_FILL_LEVEL);
+
+ /* LTP data */
+ test();
+ IF (hTcxEnc->tcxltp || GT_32(st->sr_core, 25600))
+ {
+ IF ( prm[j] )
+ {
+ push_next_indice_fx( hBstr, 1 , 1);
+ push_next_indice_fx( hBstr, prm[j+1], 9);
+ push_next_indice_fx( hBstr, prm[j+2], 2);
+ }
+ ELSE
+ {
+ push_next_indice_fx( hBstr, 0 , 1);
+ }
+ }
+ j = add(j, 3);
+
+ /* TCX spectral data */
+ lg = L_frame;
+ move16();
+ lgFB = st->hTcxCfg->tcx_coded_lines;
+ move16();
+
+ IF ( last_core==ACELP_CORE )
+ {
+ /* ACE->TCX transition */
+ lg = add(lg, st->hTcxCfg->tcx_offset);
+ lgFB = add(lgFB, shr(lgFB, 2));
+ if(st->hTcxCfg->lfacNext<0)
+ {
+ lg = sub(lg,st->hTcxCfg->lfacNext);
+ }
+ }
+
+ /* TNS data */
+ nTnsParams = 0;
+ move16();
+ nTnsBits = 0;
+ move16();
+
+ IF (st->hTcxCfg->fIsTNSAllowed)
+ {
+ WriteTnsData_fx(st->hTcxCfg->pCurrentTnsConfig, prm+j, &nTnsParams, st, &nTnsBits);
+ j = add(j, nTnsParams);
+ }
+
+ hm_size = shl(mult(st->hTcxCfg->bandwidth, lg), 1);
+ test();
+ IF (hTcxEnc->tcx_lpc_shaped_ari && NE_16(last_core, ACELP_CORE))
+ {
+ enc_prm_hm(&prm[j], st, hm_size);
+ }
+
+ /*Context HM flag*/
+ test();
+ IF ( st->hTcxCfg->ctx_hm && NE_16(last_core, ACELP_CORE))
+ {
+ push_next_indice_fx( hBstr, prm[j], 1);
+
+ IF (prm[j])
+ {
+ EncodeIndex_fx(sub(hm_size,256) >= 0, prm[j+1], hBstr);
+ flag_ctx_hm = 1;
+ move16();
+ }
+ }
+ j = add(j, NPRM_CTX_HM);
+
+ IF (st->igf)
+ {
+ st->hIGFEnc->infoTotalBitsPerFrameWritten = 0;
+ move16();
+ IF (EQ_16(st->last_core_fx, ACELP_CORE))
+ {
+ IGFEncWriteBitstream_fx( st->hIGFEnc, hBstr, &st->hIGFEnc->infoTotalBitsPerFrameWritten, IGF_GRID_LB_TRAN, 1 );
+ }
+ ELSE
+ {
+ IGFEncWriteBitstream_fx( st->hIGFEnc, hBstr, &st->hIGFEnc->infoTotalBitsPerFrameWritten, IGF_GRID_LB_NORM, 1 );
+ }
+ }
+ total_nbbits = sub(hBstr->nb_bits_tot_fx, nbits_start);
+ if(EQ_16(st->rf_mode,1))
+ {
+ total_nbbits = add(total_nbbits,st->rf_target_bits_write);
+ }
+ nbits_tcx = sub(st->bits_frame_core, total_nbbits);
+
+ IF (hTcxEnc->tcx_lpc_shaped_ari != 0)
+ {
+ push_next_bits_fx(hBstr, &prm[++j], nbits_tcx);
+ j = add(j, nbits_tcx);
+ }
+ ELSE
+ {
+ phm_cfg = NULL;
+ move16();
+ if (flag_ctx_hm)
+ {
+ phm_cfg = hm_cfg;
+ move16();
+ }
+ ACcontextMapping_encode2_no_mem_s17_LC_fx(hBstr, prm+j,
+ lgFB,
+ prm[j-1], /* lastnz */
+ nbits_tcx, NPRM_RESQ * st->hTcxCfg->resq, phm_cfg);
+ }
+
+ }
+
+
+ /*--------------------------------------------------------------------------------*
+ * TCX10
+ *--------------------------------------------------------------------------------*/
+
+
+ IF (EQ_16(core,TCX_10_CORE))
+ {
+ Word16 nbits_igf = 0;
+ move16();
+ IF (st->igf)
+ {
+ nbits_igf = IGFEncWriteConcatenatedBitstream_fx( st->hIGFEnc, hBstr );
+ }
+ FOR (k = 0; k < 2; k++)
+ {
+ flag_ctx_hm = 0;
+ move16();
+
+ move16();
+ move16();
+ prm = param + (k*NPRM_DIV);
+
+ j = 0;
+
+ move16();
+ nbits_tcx = total_nbbits = sub(hBstr->nb_bits_tot_fx, nbits_start);
+
+ test();
+ IF(st->enablePlcWaveadjust && k)
+ {
+ push_next_indice_fx( hBstr, st->Tonal_SideInfo, 1);
+ }
+
+ /* TCX Gain = 7 bits */
+ push_next_indice_fx( hBstr, prm[j++], 7);
+
+ /* TCX Noise Filling = NBITS_NOISE_FILL_LEVEL bits */
+ push_next_indice_fx( hBstr, prm[j++], NBITS_NOISE_FILL_LEVEL);
+
+ /* LTP data */
+ test();
+ test();
+ IF ( (k == 0) && (hTcxEnc->tcxltp!=0 || GT_32(st->sr_core, 25600)))/* PLC pitch info for HB */
+ {
+ IF ( prm[j] )
+ {
+ push_next_indice_fx( hBstr, 1 , 1);
+ push_next_indice_fx( hBstr, prm[j+1], 9);
+ push_next_indice_fx( hBstr, prm[j+2], 2);
+ }
+ ELSE
+ {
+ push_next_indice_fx( hBstr, 0 , 1);
+ }
+ }
+ j = add(j, 3);
+
+ /* TCX spectral data */
+ lg = shr(L_frame, 1);
+ lgFB = shr(st->hTcxCfg->tcx_coded_lines, 1);
+
+ IF ( s_and(k==0, last_core==ACELP_CORE) )
+ {
+ /* ACE->TCX transition */
+ lg = add(lg, st->hTcxCfg->tcx_offset);
+ lgFB = add(lgFB, shr(lgFB, 1));
+ if(st->hTcxCfg->lfacNext<0)
+ {
+ lg = sub(lg,st->hTcxCfg->lfacNext);
+ }
+ }
+
+ /* TNS data */
+ move16();
+ move16();
+ nTnsParams = 0;
+ nTnsBits = 0;
+
+ IF (st->hTcxCfg->fIsTNSAllowed)
+ {
+
+ SetTnsConfig(st->hTcxCfg, 0, (last_core == ACELP_CORE) && (k == 0));
+
+ WriteTnsData_fx(st->hTcxCfg->pCurrentTnsConfig, prm+j, &nTnsParams, st, &nTnsBits);
+ j = add(j, nTnsParams);
+ }
+
+ hm_size = shl(mult(st->hTcxCfg->bandwidth, lgFB), 1);
+
+ /*Context HM flag*/
+ test();
+ test();
+ IF ( st->hTcxCfg->ctx_hm && !(last_core == ACELP_CORE && k == 0) )
+ {
+ push_next_indice_fx( hBstr, prm[j], 1);
+
+ IF (prm[j])
+ {
+ EncodeIndex_fx(sub(hm_size,256) >= 0, prm[j+1], hBstr);
+ flag_ctx_hm = 1;
+ move16();
+ }
+ }
+ j = add(j, NPRM_CTX_HM);
+
+ total_nbbits = sub(hBstr->nb_bits_tot_fx, nbits_start);
+
+ nbits_tcx = sub(shr(sub(add(sub(sub(sub(st->bits_frame_core, nbits_header), nbits_lpc), nbits_igf), 1), k), 1), sub(total_nbbits, nbits_tcx));
+
+ phm_cfg = NULL;
+ move16();
+ if (flag_ctx_hm)
+ {
+ phm_cfg = &hm_cfg[k];
+ move16();
+ }
+ ACcontextMapping_encode2_no_mem_s17_LC_fx(hBstr, prm+j,
+ lgFB,
+ prm[j-1], /* lastnz */
+ nbits_tcx, NPRM_RESQ * st->hTcxCfg->resq, phm_cfg);
+
+ } /* k, window index */
+ }
+
+
+ /*--------------------------------------------------------------------------------*
+ * END
+ *--------------------------------------------------------------------------------*/
+
+
+ total_nbbits = sub(hBstr->nb_bits_tot_fx, nbits_start);
+
+
+ /* Check if total encoded bits does not exceed CBR target bits (->this must never happen) */
+ if (st->bits_frame_core&&(total_nbbits>st->bits_frame_core))
+ {
+ fprintf(stderr,"AllocatedBits: %d Used bits: %d \n", st->bits_frame_core,total_nbbits);
+ assert(!"Core totalbits > CBR target bitrate");
+ }
+
+ return;
+}
+
diff --git a/lib_enc/enc_tran_fx.c b/lib_enc/enc_tran_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac6d6e3bf392a123273c98241c012287ae567ff4
--- /dev/null
+++ b/lib_enc/enc_tran_fx.c
@@ -0,0 +1,443 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Compilation switches */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*=================================================================================*/
+/* FUNCTION : void encod_tran_fx () */
+/*---------------------------------------------------------------------------------*/
+/* PURPOSE : */
+/*---------------------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* (Word16) L_frame_fx : length of the frame Q0 */
+/* (Word16[]) speech_fx : input speech Q0 */
+/* (Word16[]) Aq_fx : 12k8 Lp coefficient Q12 */
+/* (Word16[]) A_fx : unquantized A(z) filter with bandwidth expansion Q12 */
+/* (Word16) coder_type : coding type Q0 */
+/* (Word16) Es_pred_fx : predicted scaled innov. energy Q8 */
+/* (Word16[]) T_op_fx : open loop pitch Q0 */
+/* (Word16[]) voicing_fx : voicing Q15 */
+/* (Word16*) res_fx : residual signal Q_new*/
+/* (Word16) gsc_attack_flag : Flag to indicate when an audio attack is deal with TM*/
+/* (Word16) shift : shift factor */
+/* (Word16[]) Q_new : input scaling */
+/*---------------------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* (Word16*) voice_factors : voicing factors Q15 */
+/*---------------------------------------------------------------------------------*/
+/* INPUT/OUTPUT ARGUMENTS : */
+/* Encoder_State_fx *st_fx :Encoder state structure */
+/* (Word16*) syn_fx :core synthesis Qnew */
+/* (Word16*) exc_fx :current non-enhanced excitation Q0 */
+/* (Word16*) exc2_fx :current enhanced excitation Q0 */
+/* (Word16*) pitch_buf_fx :floating pitch values for each subframe Q6 */
+/* (Word16*) bwe_exc_fx :excitation for SWB TBE Q0 */
+/*---------------------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*---------------------------------------------------------------------------------*/
+
+Word16 encod_tran_fx(
+ Encoder_State_fx *st_fx, /* i/o: state structure */
+ const Word16 speech_fx[], /* i : input speech */
+ const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */
+ const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */
+ const Word16 Es_pred_fx, /* i : predicted scaled innov. energy */
+ const Word16 *res_fx, /* i : residual signal */
+ Word16 *syn_fx, /* i/o: core synthesis */
+ Word16 *exc_fx, /* i/o: current non-enhanced excitation */
+ Word16 *exc2_fx, /* i/o: current enhanced excitation */
+ Word16 *pitch_buf_fx, /* i/o: floating pitch values for each subframe */
+ Word16 *voice_factors, /* o : voicing factors */
+ Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */
+ Word16 tc_subfr, /* i/o: TC subframe classification */
+ Word16 position, /* i : maximum of residual signal index */
+ Word16 *unbits, /* i/o: number of unused bits */
+ const Word16 shift, /* i : Scaling to get 12 bits */
+ const Word16 Q_new /* i : Input scaling */
+)
+{
+ Word16 xn[L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
+ Word16 cn[L_SUBFR]; /* Target vector in residual domain */
+ Word16 h1[L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 h2_fx[L_SUBFR+(M+1)]; /* Impulse response vector */
+ Word16 code[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered algebraic excitation */
+ Word16 gain_pit = 0,Gain_pitX2,gcode16; /* Pitch gain */
+ Word16 voice_fac; /* Voicing factor */
+ Word32 gain_code = 0; /* Gain of code */
+ Word32 Lgcode;
+ Word16 gain_inov=0; /* inovation gain */
+ Word16 i, i_subfr,tmp1_fx,tmp_fx; /* tmp variables */
+ Word16 unbits_ACELP;
+ Word16 T0_min, T0_max; /* pitch and TC variables */
+ Word16 T0, T0_frac; /* close loop integer pitch and fractional part */
+ Word16 *pt_pitch; /* pointer to floating pitch buffer */
+ Word16 g_corr[10]; /* ACELP correlation values and gain pitch */
+ Word16 clip_gain; /* LSF clip gain */
+ const Word16 *p_Aw, *p_Aq; /* pointer to LP filter coefficient vector */
+ Word16 gain_preQ = 0; /* Gain of prequantizer excitation */
+ Word16 code_preQ[L_SUBFR]; /* Prequantizer excitation */
+ Word16 Jopt_flag; /* joint optimization flag */
+ Word16 unbits_PI = 0; /* saved bits for PI */
+ Word32 norm_gain_code=0;
+ Word16 L_frame_fx;
+ Word16 shift_wsp;
+ Word32 L_tmp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+
+ L_frame_fx = st_fx->L_frame_fx;
+ move16();
+ /*------------------------------------------------------------------*
+ * Initializations
+ *------------------------------------------------------------------*/
+ gain_pit = 0;
+ move16();
+ gain_code = L_deposit_l(0);
+ gain_preQ = 0;
+ move16();
+ unbits_PI = 0;
+ move16();
+ IF( EQ_16(L_frame_fx,L_FRAME))
+ {
+ T0_max = PIT_MAX;
+ move16();
+ T0_min = PIT_MIN;
+ move16();
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ T0_max = PIT16k_MAX;
+ move16();
+ T0_min = PIT16k_MIN;
+ move16();
+ }
+
+ /**unbits = 0;move16();*/
+ Jopt_flag = 0;
+ move16();
+ unbits_ACELP = *unbits;
+ move16();
+ *unbits = 0;
+ move16();
+
+ p_Aw = Aw_fx;
+ p_Aq = Aq_fx;
+ pt_pitch = pitch_buf_fx;
+ gain_preQ = 0;
+ move16();
+ set16_fx( code_preQ, 0, L_SUBFR );
+ shift_wsp = add(Q_new,shift);
+
+ /*----------------------------------------------------------------*
+ * ACELP subframe loop
+ *----------------------------------------------------------------*/
+
+ FOR ( i_subfr=0; i_subfrmem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq,
+ res_fx, L_SUBFR, p_Aw, st_fx->preemph_fac, xn, cn, h1 );
+
+ Copy_Scale_sig(h1, h2_fx, L_SUBFR, -2);
+ Scale_sig(h1, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(xn, L_SUBFR, shift);
+
+ /*-----------------------------------------------------------------*
+ * TC: subframe determination &
+ * adaptive/glottal part of excitation construction
+ *-----------------------------------------------------------------*/
+
+ transition_enc_fx( st_fx, i_subfr, &tc_subfr, &Jopt_flag, &position, &T0, &T0_frac, &T0_min, &T0_max, exc_fx, y1,
+ h1, xn, xn2, st_fx->clip_var_fx, &gain_pit, g_corr, &clip_gain, &pt_pitch, bwe_exc_fx ,&unbits_ACELP, Q_new,shift);
+
+ /*-----------------------------------------------------------------*
+ * Transform domain contribution encoding - active frames
+ *-----------------------------------------------------------------*/
+
+ IF( GE_32(st_fx->core_brate_fx, MIN_BRATE_AVQ_EXC))
+ {
+ transf_cdbk_enc_fx( st_fx, 0, i_subfr, cn, exc_fx, p_Aq, Aw_fx, h1, xn, xn2, y1, y2, Es_pred_fx,
+ &gain_pit, gain_code, g_corr, clip_gain, &gain_preQ, code_preQ, unbits, Q_new, shift);
+ }
+
+ /*-----------------------------------------------------------------*
+ * ACELP codebook search + pitch sharpening
+ *-----------------------------------------------------------------*/
+
+ inov_encode_fx( st_fx, st_fx->core_brate_fx, 0, L_frame_fx, st_fx->last_L_frame_fx, st_fx->coder_type, st_fx->bwidth_fx, st_fx->sharpFlag,
+ i_subfr, tc_subfr, p_Aq, gain_pit, cn, exc_fx, h2_fx, hLPDmem->tilt_code, *pt_pitch, xn2, code, y2, &unbits_PI, L_SUBFR, shift );
+
+ test();
+ test();
+ test();
+ if( (EQ_16(st_fx->L_frame_fx,L_FRAME16k))&&(tc_subfr==0)&&(EQ_16(i_subfr,L_SUBFR))&&(EQ_16(T0,2*L_SUBFR)))
+ {
+ Jopt_flag = 1;
+ move16();
+ }
+ /*-----------------------------------------------------------------*
+ * Quantize the gains
+ * Test quantized gain of pitch for pitch clipping algorithm
+ * Update tilt of code: 0.0 (unvoiced) to 0.5 (voiced)
+ *-----------------------------------------------------------------*/
+ IF( Jopt_flag == 0 )
+ {
+ /* SQ gain_code */
+ gain_enc_tc_fx(hBstr, st_fx->acelp_cfg.gains_mode, i_subfr, xn, y2, code, Es_pred_fx,
+ &gain_pit, &gain_code, &gain_inov, &norm_gain_code, shift_wsp );
+ }
+ ELSE
+ {
+ IF ( GT_32(st_fx->core_brate_fx,ACELP_32k))
+ {
+ /* SQ gain_pit and gain_code */
+ gain_enc_SQ_fx(hBstr, st_fx->acelp_cfg.gains_mode, i_subfr, xn, y1, y2, code, Es_pred_fx,
+ &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain, shift_wsp );
+ }
+ ELSE
+ {
+ /* VQ gain_pit and gain_code */
+ gain_enc_mless_fx(hBstr, st_fx->acelp_cfg.gains_mode, st_fx->element_mode, L_frame_fx, i_subfr, tc_subfr, xn, y1, shift_wsp, y2, code, Es_pred_fx,
+ &gain_pit, &gain_code, &gain_inov, &norm_gain_code, g_corr, clip_gain );
+ }
+ }
+ gp_clip_test_gain_pit_fx(st_fx->element_mode, st_fx->core_brate_fx, gain_pit, st_fx->clip_var_fx );
+
+#ifdef BASOP_NOGLOB
+ Lgcode = L_shl_o(gain_code, Q_new, &Overflow); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx_o(Lgcode, &Overflow);
+#else
+ Lgcode = L_shl(gain_code, Q_new); /* scaled gain_code with Qnew -> Q16*/
+ gcode16 = round_fx(Lgcode);
+#endif
+ hLPDmem->tilt_code = Est_tilt2(&exc_fx[i_subfr], gain_pit, code, Lgcode, &voice_fac, shift);
+ /*-----------------------------------------------------------------*
+ * Update memory of the weighting filter
+ *-----------------------------------------------------------------*/
+
+ /*st->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]);*/
+ L_tmp = L_mult(gcode16, y2[L_SUBFR - 1]);
+ L_tmp = L_shl(L_tmp, add(5, shift));
+ L_tmp = L_negate(L_tmp);
+ L_tmp = L_mac(L_tmp, xn[L_SUBFR - 1], 16384);
+ L_tmp = L_msu(L_tmp, y1[L_SUBFR - 1], gain_pit);
+ L_tmp = L_shl(L_tmp, sub(1, shift));
+ hLPDmem->mem_w0 = round_fx(L_tmp); /*Q_new-1*/
+
+ /*-----------------------------------------------------------------*
+ * Construct adaptive part of the excitation
+ * Save the non-enhanced excitation for FEC_exc
+ *-----------------------------------------------------------------*/
+
+ /* Here, all these conditions have one purpose: to use */
+ /* the most efficient loop (the one with the least ops) */
+ /* This is done by upscaling gain_pit_fx and/or gain_code16 */
+ /* when they don't use all 16 bits of precision */
+
+ /* exc Q_exc, gpit Q14, code Q12, gcode Q0 */
+ IF (norm_s(gain_pit) == 0)
+ {
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ exc2_fx[i+i_subfr] = round_fx(L_shl(L_mult(gain_pit,exc_fx[i+i_subfr]),1));
+ }
+ }
+ ELSE
+ {
+ Gain_pitX2 = shl(gain_pit, 1);
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ exc2_fx[i+i_subfr] = mult_r(Gain_pitX2,exc_fx[i+i_subfr]);
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Construct adaptive part of the excitation
+ * Save the non-enhanced excitation for FEC_exc
+ *-----------------------------------------------------------------*/
+ FOR (i = 0; i < L_SUBFR; i++)
+ {
+ /* code in Q9, gain_pit in Q14 */
+ L_tmp = L_mult(gcode16, code[i]);
+#ifdef BASOP_NOGLOB
+ L_tmp = L_shl_o(L_tmp, 5, &Overflow);
+ L_tmp = L_mac_o(L_tmp, exc_fx[i + i_subfr], gain_pit, &Overflow);
+ L_tmp = L_shl_o(L_tmp, 1, &Overflow); /* saturation can occur here */
+ exc_fx[i + i_subfr] = round_fx_o(L_tmp, &Overflow);
+#else
+ L_tmp = L_shl(L_tmp, 5);
+ L_tmp = L_mac(L_tmp, exc_fx[i + i_subfr], gain_pit);
+ L_tmp = L_shl(L_tmp, 1); /* saturation can occur here */
+ exc_fx[i + i_subfr] = round_fx(L_tmp);
+#endif
+ }
+
+ /*-----------------------------------------------------------------*
+ * Add the ACELP pre-quantizer contribution
+ *-----------------------------------------------------------------*/
+
+ IF( GE_32(st_fx->core_brate_fx, MIN_BRATE_AVQ_EXC))
+ {
+ tmp1_fx = add(16-(2+Q_AVQ_OUT_DEC+1),Q_new);
+ FOR( i = 0; i < L_SUBFR; i++ )
+ {
+ L_tmp = L_mult(gain_preQ, code_preQ[i]); /* Q2 + Q10 -> Q13*/
+#ifdef BASOP_NOGLOB
+ L_tmp = L_shl_o(L_tmp,tmp1_fx, &Overflow); /* Q16 + Q_exc */
+ tmp_fx = round_fx_o(L_tmp, &Overflow);
+
+ exc2_fx[i+i_subfr] = add_o(exc2_fx[i+i_subfr],tmp_fx, &Overflow);
+ move16();
+ exc_fx[i+i_subfr] = add_o(exc_fx[i+i_subfr],tmp_fx, &Overflow);
+ move16();
+#else
+ L_tmp = L_shl(L_tmp,tmp1_fx); /* Q16 + Q_exc */
+ tmp_fx = round_fx(L_tmp);
+
+ exc2_fx[i+i_subfr] = add(exc2_fx[i+i_subfr],tmp_fx);
+ move16();
+ exc_fx[i+i_subfr] = add(exc_fx[i+i_subfr],tmp_fx);
+ move16();
+#endif
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Prepare TBE excitation
+ *-----------------------------------------------------------------*/
+
+ prep_tbe_exc_fx( L_frame_fx, i_subfr, gain_pit, gain_code, code, voice_fac, &voice_factors[i_subfr/L_SUBFR],
+ bwe_exc_fx, gain_preQ, code_preQ, Q_new, T0, T0_frac, st_fx->coder_type, st_fx->core_brate_fx );
+
+ /*-----------------------------------------------------------------*
+ * Synthesize speech to update mem_syn[].
+ * Update A(z) filters
+ *-----------------------------------------------------------------*/
+
+ Syn_filt_s( 1, p_Aq, M, &exc_fx[i_subfr], &syn_fx[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1 );
+
+ p_Aw += (M+1);
+ p_Aq += (M+1);
+ pt_pitch++;
+ }
+
+ /* write reserved bits */
+ WHILE( unbits_PI > 0 )
+ {
+ i = s_min(unbits_PI, 16);
+ push_indice_fx( hBstr, IND_UNUSED, 0, i );
+ unbits_PI -= i;
+ }
+
+ /* write TC configuration */
+ IF( EQ_16(L_frame_fx,L_FRAME))
+ {
+ IF( EQ_16(tc_subfr,TC_0_0))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ }
+ ELSE IF( EQ_16(tc_subfr,TC_0_64))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ }
+ ELSE IF( EQ_16(tc_subfr,TC_0_128))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ }
+ ELSE IF( EQ_16(tc_subfr,TC_0_192))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ }
+ ELSE IF( EQ_16(tc_subfr,L_SUBFR))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ }
+ ELSE IF( EQ_16(tc_subfr,2*L_SUBFR))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ }
+ ELSE IF( EQ_16(tc_subfr,3*L_SUBFR))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ }
+
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ IF( tc_subfr == 0 )
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 2 );
+ }
+ ELSE IF( EQ_16(tc_subfr,L_SUBFR))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 2 );
+ }
+ ELSE IF( EQ_16(tc_subfr,2*L_SUBFR))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 2, 2 );
+ }
+ ELSE IF( EQ_16(tc_subfr,3*L_SUBFR))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 3, 2 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 0, 1 );
+ }
+ ELSE IF( EQ_16(tc_subfr,4*L_SUBFR))
+ {
+ push_indice_fx( hBstr, IND_TC_SUBFR, 3, 2 );
+ push_indice_fx( hBstr, IND_TC_SUBFR, 1, 1 );
+ }
+
+ }
+
+ IF(st_fx->Opt_SC_VBR_fx)
+ {
+ /* SC-VBR */
+ hSC_VBR->prev_ppp_gain_pit_fx = gain_pit;
+ move16();
+ hSC_VBR->prev_tilt_code_fx = hLPDmem->tilt_code;
+ move16();
+ }
+
+ return tc_subfr;
+}
diff --git a/lib_enc/enc_uv_fx.c b/lib_enc/enc_uv_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..622502d101d733b1141c9ce370e21dadca0b7384
--- /dev/null
+++ b/lib_enc/enc_uv_fx.c
@@ -0,0 +1,257 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * encod_unvoiced()
+ *
+ * Encode unvoiced (UC) frames
+ *-------------------------------------------------------------------*/
+/*fixed point implementation of unvoiced_encoder*/
+void encod_unvoiced_fx(
+ Encoder_State_fx *st_fx, /* i/o: state structure */
+ const Word16 *speech_fx, /* i : Input speech */
+ const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */
+ const Word16 *Aq_fx, /* i : 12k8 Lp coefficient */
+ const Word16 Es_pred, /* i : predicted scaled innov. energy */
+ const Word16 uc_two_stage_flag, /* i : flag indicating two-stage UC */
+ const Word16 *res_fx, /* i : residual signal */
+ Word16 *syn_fx, /* o : core synthesis */
+ Word16 *tmp_noise_fx, /* o : long-term noise energy */
+ Word16 *exc_fx, /* i/o: current non-enhanced excitation */
+ Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */
+ Word16 *voice_factors_fx, /* o : voicing factors */
+ Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE */
+ const Word16 Q_new,
+ const Word16 shift
+)
+{
+ Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */
+ Word16 h1_fx[L_SUBFR]; /* Impulse response vector */
+ Word16 code_fx[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y2_fx[L_SUBFR]; /* Filtered algebraic excitation */
+ Word16 *pt_pitch_fx; /* pointer to floating pitch buffer */
+ Word16 gain_pit_fx; /* Pitch gain */
+ Word16 voice_fac_fx; /* Voicing factor */
+ Word32 L_gain_code_fx; /* gain of code */
+ Word16 gain_inov_fx; /* inovative gain */
+ Word16 cn_fx[L_SUBFR]; /* Target vector in residual domain */
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 code2[L_SUBFR]; /* Gaussian excitation */
+ Word16 y22[L_SUBFR]; /* Filtered Gaussian excitation */
+ Word16 prm_t[2 * NPRM_DIV], *prm = prm_t;
+ const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector */
+ Word32 norm_gain_code_fx;
+ ACELP_config* acelp_cfg;
+ ACELP_CbkCorr g_corr;
+ Word32 gain_code2;
+ Word32 gain_code_vect[2], Ltmp, Ltmp2;
+#if 0
+ Word16 i_subfr, clip_gain, Q_xn, Q_new_p5, tmp2, j, i;
+ Word16 exc2[L_SUBFR], index, i_subfr_idx;
+#else
+ Word16 i_subfr, Q_xn, Q_new_p5, tmp2, j, i;
+ Word16 index, i_subfr_idx;
+#endif
+ acelp_cfg = &(st_fx->acelp_cfg);
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+ LPD_state_HANDLE hLPDmem = st_fx->hLPDmem;
+
+ /*------------------------------------------------------------------*
+ * Initializations
+ *------------------------------------------------------------------*/
+ gain_pit_fx = 0;
+ move16();
+
+ test();
+ test();
+ test();
+ IF( st_fx->Opt_SC_VBR_fx && st_fx->vad_flag == 0 && (EQ_16(hSC_VBR->last_ppp_mode,1) || EQ_16(hSC_VBR->last_nelp_mode,1)))
+ {
+ /* SC_VBR - reset the encoder, to avoid memory not updated issue for the
+ case when UNVOICED mode is used to code inactive speech */
+ CNG_reset_enc_fx( st_fx, hLPDmem, pitch_buf_fx, voice_factors_fx, 1 );
+ }
+
+ p_Aw_fx = Aw_fx;
+ p_Aq_fx = Aq_fx;
+ pt_pitch_fx = pitch_buf_fx;
+ move16();
+ Q_xn = add(sub(Q_new, 1), shift);
+ Q_new_p5 = add(Q_new, 5);
+
+
+ FOR (i_subfr=0; i_subfrmem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq_fx,
+ res_fx, L_SUBFR, p_Aw_fx, st_fx->preemph_fac, xn_fx, cn_fx, h1_fx);
+
+ /*Copy_Scale_sig(h1_fx, h2_fx, L_SUBFR, -2);*/
+ Scale_sig(h1_fx, L_SUBFR, add(1, shift)); /* set h1[] in Q14 with scaling for convolution */
+
+ /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(xn_fx, L_SUBFR, shift);
+ /*----------------------------------------------------------------*
+ * Unvoiced subframe processing
+ *----------------------------------------------------------------*/
+ IF (!uc_two_stage_flag)
+ {
+ *pt_pitch_fx = gaus_encode_fx(st_fx, i_subfr, h1_fx, xn_fx, exc_fx, &hLPDmem->mem_w0, st_fx->clip_var_fx,
+ &hLPDmem->tilt_code, code_fx, &L_gain_code_fx, y2_fx, &gain_inov_fx,
+ &voice_fac_fx, &gain_pit_fx, Q_new, shift, &norm_gain_code_fx);
+ }
+ ELSE
+ {
+ /*----------------------------------------------------------------*
+ * Unvoiced subframe processing in two stages
+ *----------------------------------------------------------------*/
+ //PMT("The code below needs validation, never been tested")
+ /* No adaptive codebook (UC) */
+ set16_fx(y1, 0, L_SUBFR);
+ set16_fx(exc_fx + i_subfr, 0, L_SUBFR);
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure
+ * or in case of floating point encoder & fixed p. decoder
+ *-----------------------------------------------------------------*/
+#if 0
+ clip_gain = Mode2_gp_clip(st_fx->voicing_fx, i_subfr, st_fx->coder_type, xn_fx, st_fx->clip_var_fx, L_SUBFR, Q_xn);
+#else
+ Mode2_gp_clip(st_fx->voicing_fx, i_subfr, st_fx->coder_type, xn_fx, st_fx->clip_var_fx, L_SUBFR, Q_xn);
+#endif
+ *pt_pitch_fx = L_SUBFR;
+ move16();
+ /*----------------------------------------------------------------------*
+ * Encode the algebraic innovation *
+ *----------------------------------------------------------------------*/
+
+ E_ACELP_innovative_codebook_fx(exc_fx, *pt_pitch_fx, 0, 1, gain_pit_fx, hLPDmem->tilt_code, acelp_cfg, i_subfr, p_Aq_fx, h1_fx, xn_fx, cn_fx, y1, y2_fx, st_fx->acelp_autocorr, &prm, code_fx, shift, st_fx->L_frame_fx, st_fx->last_L_frame_fx, st_fx->total_brate_fx);
+
+ E_ACELP_xy2_corr(xn_fx, y1, y2_fx, &g_corr, L_SUBFR, Q_xn);
+
+ g_corr.y2y2_e = sub(g_corr.y2y2_e, 18); /* -18 (y2*y2: Q9*Q9) */
+ g_corr.xy2_e = sub(g_corr.xy2_e, add(Q_xn, 9)); /* -(Q_xn+9) (xn: Q_xn y2: Q9) */
+ g_corr.y1y2_e = sub(g_corr.y1y2_e, add(Q_xn, 9)); /* -(Q_xn+9) (y1: Q_xn y2: Q9) */
+ g_corr.xx_e = sub(g_corr.xx_e, add(Q_xn, Q_xn)); /* -(Q_xn+Q_xn) (xn: Q_xn) */
+
+ assert(gain_pit_fx == 0);
+ gauss_L2_fx(h1_fx, code2, y2_fx, y22, &gain_code2, &g_corr, gain_pit_fx, hLPDmem->tilt_code, p_Aq_fx, acelp_cfg->formant_enh_num, &(st_fx->seed_acelp), shift);
+
+ /*----------------------------------------------------------*
+ * - Compute the fixed codebook gain *
+ * - quantize fixed codebook gain *
+ *----------------------------------------------------------*/
+
+ index = gain_enc_uv_fx(code_fx, code2, L_SUBFR, &gain_pit_fx, &L_gain_code_fx, &gain_code2,
+ st_fx->flag_noisy_speech_snr, &g_corr, Es_pred, &norm_gain_code_fx, &gain_inov_fx, FUNC_GAIN_ENC_GACELP_UV);
+
+#ifdef DEBUGGING
+ assert(st_fx->acelp_cfg.gains_mode[i_subfr_idx] == 7 && "Error: UC two-stage, only 5+2 gain Q is supported");
+#endif
+ push_indice_fx(st_fx->hBstr, IND_GAIN, index, st_fx->acelp_cfg.gains_mode[i_subfr_idx]);
+
+ gp_clip_test_gain_pit_fx(st_fx->element_mode, st_fx->core_brate_fx, gain_pit_fx, st_fx->clip_var_fx);
+
+ gain_code_vect[0] = L_gain_code_fx;
+ move32();
+ gain_code_vect[1] = L_gain_code_fx;
+ move32();
+
+ /*----------------------------------------------------------*
+ * - voice factor (for pitch enhancement) *
+ *----------------------------------------------------------*/
+ E_UTIL_voice_factor(exc_fx, i_subfr, code_fx, gain_pit_fx, L_gain_code_fx, &voice_fac_fx, &(hLPDmem->tilt_code), L_SUBFR, acelp_cfg->voice_tilt, Q_new, shift);
+
+ IF(st_fx->Opt_RF_ON)
+ {
+ st_fx->hRF->rf_tilt_buf[i_subfr_idx] = hLPDmem->tilt_code;
+ }
+ /*-----------------------------------------------------------------*
+ * Update memory of the weighting filter
+ *-----------------------------------------------------------------*/
+ /* st_fx->mem_w0 = xn[L_SUBFR-1] - (gain_pit*y1[L_SUBFR-1]) - (gain_code*y2[L_SUBFR-1]); */
+ Ltmp = Mpy_32_16_1(L_gain_code_fx, y2_fx[L_SUBFR - 1]);
+ Ltmp = L_shl(Ltmp, add(5, Q_xn));
+ Ltmp = L_mac(Ltmp, y1[L_SUBFR - 1], gain_pit_fx);
+ /* Add Gaussian contribution*/
+ Ltmp2 = Mpy_32_16_1(gain_code2, y22[L_SUBFR - 1]);
+ Ltmp2 = L_shl(Ltmp2, add(5, Q_xn));
+ Ltmp = L_add(Ltmp, Ltmp2);
+ hLPDmem->mem_w0 = sub(xn_fx[L_SUBFR - 1], round_fx(L_shl(Ltmp, 1)));
+ move16();
+ BASOP_SATURATE_WARNING_OFF_EVS;
+ hLPDmem->mem_w0 = shr(hLPDmem->mem_w0, shift); /*Qnew-1*/
+ BASOP_SATURATE_WARNING_ON_EVS;
+
+ /*-------------------------------------------------------*
+ * - Find the total excitation. *
+ *-------------------------------------------------------*/
+
+ tmp2 = shr(L_SUBFR, 1);
+ FOR(j = 0; j < 2; j++)
+ {
+ FOR(i = sub(tmp2, shr(L_SUBFR, 1)); i < tmp2; i++)
+ {
+ /* code in Q9, gain_pit in Q14; exc Q_new */
+ Ltmp = Mpy_32_16_1(gain_code2, code2[i]);
+ Ltmp = L_shl(Ltmp, Q_new_p5);
+ Ltmp = L_mac(Ltmp, gain_pit_fx, exc_fx[i + i_subfr]);
+#if 0
+ BASOP_SATURATE_WARNING_OFF_EVS
+ exc2[i] = round_fx(L_shl(Ltmp, 1));
+ BASOP_SATURATE_WARNING_ON_EVS
+#endif
+ Ltmp2 = Mpy_32_16_1(gain_code_vect[j], code_fx[i]);
+ Ltmp2 = L_shl(Ltmp2, Q_new_p5);
+ Ltmp = L_add(Ltmp, Ltmp2);
+ BASOP_SATURATE_WARNING_OFF_EVS
+ Ltmp = L_shl(Ltmp, 1); /* saturation can occur here */
+ BASOP_SATURATE_WARNING_ON_EVS
+ exc_fx[i + i_subfr] = round_fx(Ltmp);
+ }
+ tmp2 = L_SUBFR;
+ move16();
+ }
+ }
+
+ *tmp_noise_fx = extract_h(norm_gain_code_fx);
+ voice_factors_fx[i_subfr/L_SUBFR] = 0;
+ move16();
+
+ interp_code_5over2_fx( &exc_fx[i_subfr], &bwe_exc_fx[i_subfr * HIBND_ACB_L_FAC], L_SUBFR );
+
+ /*-----------------------------------------------------------------*
+ * Synthesize speech to update mem_syn[].
+ * Update A(z) filters
+ *-----------------------------------------------------------------*/
+ Syn_filt_s(1, p_Aq_fx, M, &exc_fx[i_subfr], &syn_fx[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1 );
+
+ p_Aw_fx += (M+1);
+ p_Aq_fx += (M+1);
+ pt_pitch_fx++;
+ }
+
+ /* SC-VBR */
+ hSC_VBR->prev_ppp_gain_pit_fx = gain_pit_fx;
+ move16();
+ hSC_VBR->prev_tilt_code_fx = hLPDmem->tilt_code;
+ move16();
+
+ return;
+}
diff --git a/lib_enc/energy_fx.c b/lib_enc/energy_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..06638aa5e973fe8132f11c7c5b8adcbd702555c4
--- /dev/null
+++ b/lib_enc/energy_fx.c
@@ -0,0 +1,487 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include "options.h"
+#include "basop_util.h"
+#include "rom_enc.h"
+#include "vad_basop.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+/*-------------------------------------------------------------------*
+ * est_energy_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+void est_energy_fx(
+ Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy vector per band */
+ Word16 enerBuffer_exp, /* i : exponent of energy vector */
+ Word32 *frame_sb_energy, /* o : energy of sub-band divided non-uniformly*/
+ Word32 *frame_energy2_p, /* o : frame energy 2*/
+ Word32 *HB_Power_p, /* o : high frequency energy*/
+ Word32 *frame_energy_p, /* o : frame energy 1*/
+ Word16 *sb_power_Q, /* o : the scaling of sb_power*/
+ Word16 *frame_energy2_Q, /* o : the scaling of frame_energy*/
+ Word16 *HB_Power_Q, /* o : the scaling of HB_Power*/
+ Word16 *frame_energy_Q, /* o : the Scaling of frame_energy*/
+ Word16 *frame_sb_energy_scale, /* o : the Scaling of frame_sb_energy[]*/
+ const Word32 bandwidth /* i : band width*/
+)
+{
+ Word32 i,j;
+ Word32 frame_energy2,HB_Power,tmpspec_amp;
+ Word32 sb_power_tmp;
+ Word32 frame_energy,s32CopyPower;
+ Word32 SNR_sb_num;
+ Word16 shr_tmp;
+ Word32 BandNum;
+ Word16 widthsb,s16MaxCoefNorm;
+ const Word16 *Nregion_index;
+ Word32 *sb_power = enerBuffer;
+ Word32 Ltmp32 = 0;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ move32();
+ SNR_sb_num = SNR_SUB_BAND_NUM[bandwidth-CLDFBVAD_NB_ID];
+ move16();
+ Nregion_index = REGION_INDEX[bandwidth-CLDFBVAD_NB_ID];
+ move16();
+
+ shr_tmp = BAND_SCALE_AJ[bandwidth];
+ move16();
+ BandNum = BAND_NUM_TAB[bandwidth];
+ move16();
+
+ frame_energy2 = L_shr(sb_power[1], shr_tmp);
+ HB_Power = L_shr(sb_power[6], shr_tmp);
+ FOR(i = 2; i < BandNum; i++)
+ {
+ Ltmp32 = L_shr(sb_power[i],shr_tmp);
+ frame_energy2 = L_add(frame_energy2, Ltmp32 );
+ if(i > 6) HB_Power = L_add(HB_Power, Ltmp32 );
+ }
+ frame_energy2 = L_sub(frame_energy2, Ltmp32 );
+
+ sb_power_tmp = L_shr(sb_power[0],shr_tmp);
+
+ IF(EQ_32(bandwidth,1))
+ {
+ frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x147a));
+ }
+ ELSE IF(EQ_32(bandwidth,2))
+ {
+ frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x1eb8));
+ }
+ ELSE IF(EQ_32(bandwidth,3))
+ {
+ frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x23d7));
+ }
+ ELSE IF(EQ_32(bandwidth,4))
+ {
+ frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x23d7));
+ }
+ ELSE
+ {
+ frame_energy = L_add(frame_energy2,MUL_F(sb_power_tmp,0x23d7));
+ }
+
+ *frame_energy2_p = frame_energy2;
+ move32();
+ *HB_Power_p = HB_Power;
+ move32();
+ *frame_energy_p = frame_energy;
+ move32();
+ /* enerBuffer(float) = enerBuffer(fixed) * 2^(-(31-enerBuffer_exp)) */
+ /* +30 is to keep original precision */
+ *sb_power_Q = sub(31+30,enerBuffer_exp);
+ move16();
+ *frame_energy2_Q = sub(*sb_power_Q,shr_tmp);
+ move16();
+ *HB_Power_Q = sub(*sb_power_Q,shr_tmp);
+ move16();
+ *frame_energy_Q = sub(*sb_power_Q,shr_tmp);
+ move16();
+
+ FOR(i=0; i<6; i++)
+ {
+ frame_sb_energy[i] = sb_power[i];
+ move32();
+ }
+
+ FOR(i=6; if_tonality_rate;
+ Word16 *ltd_stable_rate = hVAD_CLDFB->ltd_stable_rate;
+ Word32 bandwith = hVAD_CLDFB->bw_index;
+ Word16 cmp_tmp;
+ T_VAD_EXP exp_frame_energy_amendment;
+
+ move32();
+ move16();
+ move16();
+
+
+ tmp = L_deposit_l(-1);
+
+ CONST32fix.s16Exp = 44;
+ move16();
+ CONST32fix.s32Mantissa = 1759218560;
+ move32();
+ SNR_sb_num = SNR_SUB_BAND_NUM[bandwith - CLDFBVAD_NB_ID];
+ move16();
+ scale_sb_energy = hVAD_CLDFB->sb_bg_energy_scale;
+ move16();
+
+ sb_bg_energy = hVAD_CLDFB->sb_bg_energy;
+ move32();
+ frame_sb_energy = hVAD_CLDFB->frame_sb_energy;
+ move32();
+ t_bg_energy = hVAD_CLDFB->t_bg_energy;
+ move32();
+
+ t_bg_energy_sum = hVAD_CLDFB->t_bg_energy_sum;
+ move32();
+ normscal = norm_l(frame_energy);
+ exp_frame_energy.s16Exp = add(scale,normscal);
+ exp_frame_energy.s32Mantissa = L_shl(frame_energy,normscal);
+ exp_frame_energy = VAD_AddExp(exp_frame_energy,CONST32fix);
+ cmp_lt_frame = VAD_L_CMP(exp_frame_energy.s32Mantissa,exp_frame_energy.s16Exp,46,0);
+
+ FOR(i=0; iframeloop, 60)) && (GT_16(hVAD_CLDFB->frameloop,5)) && (LT_16(f_tonality_rate[0],9174/* 0.56 Q14 */))
+ && (LT_16(f_tonality_rate[1],8192/* 0.5 Q14 */)) && (LT_16(ltd_stable_rate[1],1966/* 0.06 Q15 */))
+ && LT_32(snr, 83886080) )
+ {
+ IF( LT_16(hVAD_CLDFB->frameloop, 50) )
+ {
+ exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout);
+ exp_frame_energy_amendment.s16Exp = q_divout;
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment);
+ }
+ ELSE
+ {
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy);
+ }
+ update_sb_bg_energy(sb_bg_energy, &hVAD_CLDFB->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, hVAD_CLDFB->frame_sb_energy_scale,
+ 29490/* 0.90 Q15 */, 3, 5242/* 0.01 Q19 */);//5243
+ }
+
+ test();
+ test();
+ IF((EQ_32(update_flag,1)) && (GT_16(hVAD_CLDFB->frameloop,2)) && music_backgound_f==0)
+ {
+ IF(LT_16(hVAD_CLDFB->bg_update_count, 16))
+ {
+ IF( LT_16(hVAD_CLDFB->frameloop, 50) )
+ {
+ exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout);
+ exp_frame_energy_amendment.s16Exp = q_divout;
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment);
+ }
+ ELSE
+ {
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy);
+ }
+ update_sb_bg_energy(sb_bg_energy, &hVAD_CLDFB->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, hVAD_CLDFB->frame_sb_energy_scale,
+ 31456/* 0.96 Q15 */, 4, 20971/* 0.04 Q19 */);
+
+ hVAD_CLDFB->bg_update_count = add(hVAD_CLDFB->bg_update_count, 1);
+ }
+ ELSE
+ {
+
+ cmp_lt_frame = VAD_L_CMP(t_bg_energy, hVAD_CLDFB->scale_t_bg_energy, exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp);
+ cmp_pre_frame = VAD_L_CMP(MUL_F(hVAD_CLDFB->frame_energy_smooth, 24576), sub(hVAD_CLDFB->frame_energy_smooth_scale, 5), exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp);
+ cmp_tmp = VAD_L_CMP(MUL_F(t_bg_energy, 24576), sub(hVAD_CLDFB->scale_t_bg_energy, 4), exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp);
+
+ test();
+ IF( (cmp_lt_frame < 0) && (cmp_pre_frame < 0) )
+ {
+ tmpQ = add(9, hVAD_CLDFB->frame_sb_energy_scale);
+ FOR(i=0; iframeloop, 50) )
+ {
+ exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout);
+ exp_frame_energy_amendment.s16Exp = q_divout;
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment);
+ }
+ ELSE
+ {
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy);
+ }
+ update_sb_bg_energy(sb_bg_energy, &hVAD_CLDFB->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, hVAD_CLDFB->frame_sb_energy_scale,
+ 31456/* 0.96 Q15 */, 4, 20971/* 0.04 Q19 */);
+
+ }
+ ELSE
+ {
+ cmp_pre_frame = VAD_L_CMP(t_bg_energy, hVAD_CLDFB->scale_t_bg_energy, exp_frame_energy.s32Mantissa, exp_frame_energy.s16Exp);
+ IF(cmp_pre_frame>0)
+ {
+ IF( LT_16(hVAD_CLDFB->frameloop, 50) )
+ {
+ exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout);
+ exp_frame_energy_amendment.s16Exp = q_divout;
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment);
+ }
+ ELSE
+ {
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy);
+ }
+ update_sb_bg_energy(sb_bg_energy, &hVAD_CLDFB->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, hVAD_CLDFB->frame_sb_energy_scale,
+ 31129/* 0.95 Q15 */, 4, 26214/* 0.05 Q19 */);
+
+ }
+ ELSE
+ {
+ IF( LT_16(hVAD_CLDFB->frameloop, 50) )
+ {
+ exp_frame_energy_amendment.s32Mantissa = VAD_L_div(exp_frame_energy.s32Mantissa, 10, exp_frame_energy.s16Exp, 0, &q_divout);
+ exp_frame_energy_amendment.s16Exp = q_divout;
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy_amendment);
+ }
+ ELSE
+ {
+ t_bg_energy_sum = VAD_AddExp(t_bg_energy_sum,exp_frame_energy);
+ }
+ update_sb_bg_energy(sb_bg_energy, &hVAD_CLDFB->tbg_energy_count, p_scale_sb_energy, SNR_sb_num, frame_sb_energy, hVAD_CLDFB->frame_sb_energy_scale,
+ 31456/* 0.96 Q15 */, 4, 20971/* 0.04 Q19 */);
+
+ }
+ }
+ }
+ }
+ ELSE
+ {
+ cmp_pre_frame = VAD_L_CMP(t_bg_energy, hVAD_CLDFB->scale_t_bg_energy, MUL_F(exp_frame_energy.s32Mantissa, 32000), sub(exp_frame_energy.s16Exp, 9));
+ cmp_lt_frame = VAD_L_CMP(sb_bg_energy[0], scale_sb_energy, MUL_F(frame_sb_energy[0], 20480), sub(hVAD_CLDFB->frame_sb_energy_scale, 4));
+
+ test();
+ IF( (cmp_pre_frame > 0) && (cmp_lt_frame > 0) )
+ {
+ tmpQ = add(3, hVAD_CLDFB->frame_sb_energy_scale);
+ FOR(i=0; iscale_t_bg_energy, MUL_F(exp_frame_energy.s32Mantissa, 20480), sub(exp_frame_energy.s16Exp, 4));
+ IF( cmp_pre_frame > 0 )
+ {
+ tmpQ = add(9, hVAD_CLDFB->frame_sb_energy_scale);
+ FOR(i=0; itbg_energy_count);
+ cmp_pre_frame = VAD_L_CMP(t_bg_energy_sum.s32Mantissa, t_bg_energy_sum.s16Exp, tmp, 0);
+ IF(cmp_pre_frame > 0)
+ {
+ i = norm_l(tmp);
+ t_bg_energy_sum.s32Mantissa = L_shl(tmp, i);
+ t_bg_energy_sum.s16Exp = i;
+ move16();
+ }
+ NormEnergyWord32(sb_bg_energy, SNR_sb_num, p_scale_sb_energy, &scale_sb_energy);
+ cmp_pre_frame = VAD_L_CMP(t_bg_energy, hVAD_CLDFB->scale_t_bg_energy, 1, 0);
+
+ test();
+ test();
+ test();
+ IF( (EQ_16(music_backgound_f, 1))&&(LT_32(hVAD_CLDFB->lt_snr_org,107374179/* 3.2 Q25 */))
+ && (cmp_pre_frame > 0) && update_flag == 0)
+ {
+ tmp = L_shr(2147/* 0.000001 Q31 */, sub(31, scale_sb_energy));
+ FOR(i=0; iscale_t_bg_energy, 15));
+ IF(cmp_pre_frame < 0)
+ {
+ tmp = L_shr(2147/* 0.000001 Q31 */, sub(31, scale_sb_energy));
+ FOR(i=0; itbg_energy_count, 64)))
+ {
+ hVAD_CLDFB->tbg_energy_count = 48;
+ move16();
+ t_bg_energy_sum.s32Mantissa = MUL_F(t_bg_energy_sum.s32Mantissa, 24575/* 0.75 Q15 */);
+ }
+
+ t_bg_energy = VAD_L_div(t_bg_energy_sum.s32Mantissa, hVAD_CLDFB->tbg_energy_count, t_bg_energy_sum.s16Exp, 0, &q_divout);
+ hVAD_CLDFB->scale_t_bg_energy = q_divout;
+ move16();
+ hVAD_CLDFB->t_bg_energy = t_bg_energy;
+ move32();
+ hVAD_CLDFB->sb_bg_energy_scale = scale_sb_energy;
+ move16();
+ hVAD_CLDFB->t_bg_energy_sum = t_bg_energy_sum;
+ move16();
+ move32();
+
+ return;
+}
+
diff --git a/lib_enc/eval_pit_contr_fx.c b/lib_enc/eval_pit_contr_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..f66c2987659ae0c0e139ce02d1f05a72abdff8f6
--- /dev/null
+++ b/lib_enc/eval_pit_contr_fx.c
@@ -0,0 +1,437 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * Local constantes
+ *-------------------------------------------------------------------*/
+#define NB_VOIC_FX 13
+#define DIV_NB_VOIC_FX 2521
+
+#define ALPA_FX 31130
+#define ALPAM1_FX (32768-ALPA_FX)
+
+#define BETA_FX 819
+#define AFREQ_THR 2
+
+#define HANGOVER_DELAY 2
+
+/*======================================================================*/
+/* FUNCTION : Pit_exc_contribution_len_fx() */
+/*----------------------------------------------------------------------*/
+/* PURPOSE : Determine up to which band the pit contribution is significant*/
+/*----------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ (Struct) st_fx : encoder static memory */
+/* _ (Word16[]) dct_res : DCT of residual Qnew */
+/* _ (Word16[]) dct_pitex : DCT of pitch contribution Qnew */
+/* _ (Word16[]) pitch_buf : Pitch per subframe Q6 */
+/* _ (Word16[]) nb_subfr : Number of subframe considered */
+/* _ (Word16) hangover : hangover for the time contribution switching*/
+/* _ (Word16) Qnew : */
+/*-----------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ (Word16[]) dct_res : DCT of residual Qnew */
+/* _ (Word16[]) dct_pitex : DCT of pitch contribution Qnew */
+/*-----------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : */
+/* _ None */
+/*=======================================================================*/
+
+Word16 Pit_exc_contribution_len_fx( /* o : bin where pitch contribution is significant */
+ Encoder_State_fx *st_fx, /* i/o: state structure */
+ const Word16 *dct_res, /* i : DCT of residual */
+ Word16 *dct_pitex, /* i/o: DCT of pitch contribution */
+ Word16 *pitch_buf, /* i/o: Pitch per subframe */
+ const Word16 nb_subfr, /* i : Number of subframe considered */
+ Word16 *hangover, /* i : hangover for the time contribution switching */
+ Word16 Qnew
+)
+{
+
+ Word16 corr_dct_pit[MBANDS_LOC];
+ Word32 corr_tmp,L_tmp;
+ Word16 av_corr, min_corr, ftmp, tmp_ex, tmp_res;
+ Word16 freq, i, j;
+ Word16 last_pit_band, pit_contr_idx, last_pit_bin;
+ Word32 ener_res;
+ Word32 ener_pit;
+ Word16 low_pit, F1st_harm, F8th_harm;
+ Word16 corr_dct_pit_tmp[MBANDS_LOC];
+ Word16 time_flg = 0;
+ Word16 Len, max_len;
+ Word16 tmp_dec;
+ Word16 Mbands_loc = MBANDS_LOC-2;
+ Word16 exp1,tmp,exp2;
+ Word32 L_tmp1, ener_init;
+ Word16 exp_norm;
+ Word16 norm;
+ Word16 val_thrs;
+ SP_MUS_CLAS_HANDLE hSpMusClas = st_fx->hSpMusClas;
+ BSTR_ENC_HANDLE hBstr = st_fx->hBstr;
+ GSC_ENC_HANDLE hGSCEnc = st_fx->hGSCEnc;
+
+ if( EQ_16(st_fx->L_frame_fx,L_FRAME16k))
+ {
+ Mbands_loc = MBANDS_LOC;
+ move16();
+ }
+
+ minimum_fx( pitch_buf, nb_subfr, &low_pit);
+ exp1 = norm_s(low_pit);
+ tmp = shl(low_pit,exp1);
+ tmp_dec = 12800; move16();
+ if (EQ_16(st_fx->L_frame_fx, L_FRAME16k))
+ {
+ tmp_dec = 16000; move16();
+ }
+ /*F1st_harm = (12800.0f|160000.f)/low_pit;*/
+ tmp = div_s(tmp_dec,tmp); /*15-6-exp1(->9-exp1)*/
+ F1st_harm = shr_r(tmp,sub(5,exp1)); /*Q4*/
+
+ /*F8th_harm = 8.0f*F1st_harm;*/
+ F8th_harm = extract_l(L_shr_r(L_mult0(F1st_harm,8),2)); /*Q2*/
+
+ freq = 0;
+ move16();
+ ener_init = L_shl(3,2*Qnew-5); /*(0.1->3 in Q5) 2*Qnew*/
+ FOR (i = 0; i L_frame_fx, L_FRAME16k))
+ {
+ /*av_corr *= 1.25f;*/
+ av_corr = add(av_corr, shr(av_corr, 2));
+ }
+ test();
+ if (GE_16(st_fx->GSC_IVAS_mode, 1)|| LT_32(st_fx->core_brate_fx, ACELP_9k60))
+ {
+ av_corr = shl(av_corr,1); /*Q2 Correlation really poor at low rate, time domain still valide*/
+ }
+ min_corr = abs_s(sub(mfreq_loc_Q2fx[0],av_corr)); /*Q2*/
+
+ FOR (i = 1; i GSC_IVAS_mode, 1))
+ {
+ last_pit_band = s_max(last_pit_band, 7);
+ }
+ test();
+ test();
+ test();
+ IF( GT_16(last_pit_band,7+BAND1k2)&&(LT_32(st_fx->core_brate_fx,CFREQ_BITRATE)||EQ_16(st_fx->bwidth_fx,NB)))/*Added for 9.1*/
+ {
+ last_pit_band = 7+BAND1k2;
+ move16();
+ }
+ ELSE IF ( GT_16(last_pit_band,10+BAND1k2)&&GE_32(st_fx->core_brate_fx,CFREQ_BITRATE))
+ {
+ last_pit_band = add(10,BAND1k2);
+ }
+
+ time_flg = 0;
+ move16();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF( (hGSCEnc->mem_last_pit_band > 0 && GT_16(st_fx->old_corr_fx,16384)&>_16(hSpMusClas->mold_corr_fx,16384)&&GE_16(hGSCEnc->lt_gpitch_fx,19661)/*1.5f*GPIT_THR*/)
+ || (GT_16(last_pit_band,6) )
+ || (GE_16(last_pit_band,4) && GE_16(hGSCEnc->lt_gpitch_fx,19661) /*1.5f*GPIT_THR*/ && GT_16(st_fx->old_corr_fx,22938) )
+ || (GT_16(last_pit_band,BAND1k2) && GT_16(hSpMusClas->mold_corr_fx,26214) && GE_16(hGSCEnc->lt_gpitch_fx,13107) /*GPIT_THR*/)
+ )
+ {
+ tmp_dec = 1;
+ move16();
+ }
+ ELSE
+ {
+ tmp_dec = 0;
+ move16();
+ }
+
+ /* Different past and current decision */
+ test();
+ test();
+ test();
+ IF ( (hGSCEnc->mem_last_pit_band == 0 && EQ_16(tmp_dec,1))||(hGSCEnc->mem_last_pit_band>0&&tmp_dec==0))
+ {
+ IF( *hangover == 0 )
+ {
+ time_flg = tmp_dec;
+ move16();
+ *hangover = HANGOVER_DELAY;
+ move16();
+ }
+ ELSE
+ {
+ time_flg = 0;
+ move16();
+ if(hGSCEnc->mem_last_pit_band > 0 )
+ {
+ time_flg = 1;
+ move16();
+ }
+
+ (*hangover) = sub((*hangover),1);
+ if( *hangover < 0 )
+ {
+ *hangover = 0;
+ move16();
+ }
+ }
+ }
+ ELSE
+ {
+ time_flg = tmp_dec;
+ move16();
+ *hangover = HANGOVER_DELAY;
+ move16();
+ }
+
+ /* Decicison on final length of time contribution */
+ pit_contr_idx = 0;
+ move16();
+ test();
+ test();
+ IF( EQ_16(time_flg,1) || NE_16(st_fx->coder_type,INACTIVE) || st_fx->GSC_noisy_speech_fx)
+ {
+ test();
+ test();
+ /*if(st_fx->core_brate_fx core_brate_fx,ACELP_9k60) && LT_16(low_pit,4096))
+ {
+ last_pit_band = add(9 , BAND1k2);
+ if(EQ_16(st_fx->bwidth_fx,NB))
+ {
+ last_pit_band = add(7,BAND1k2);
+ }
+ }
+ ELSE IF(LT_32(st_fx->core_brate_fx,ACELP_9k60) && LT_16(low_pit,8192))
+ {
+ last_pit_band = add(5 , BAND1k2);
+ }
+ ELSE IF(LT_32(st_fx->core_brate_fx,ACELP_9k60))
+ {
+ last_pit_band = add(3 , BAND1k2);
+ }
+ ELSE IF( LT_16(last_pit_band,add(BAND1k2,1)))
+ {
+ last_pit_band = add(BAND1k2,1);
+ }
+ last_pit_bin = mfreq_loc_div_25[last_pit_band];
+ move16();
+
+ st_fx->bpf_off_fx = 0;
+ move16();
+
+ max_len = sub(st_fx->L_frame_fx,last_pit_bin);
+
+ if( EQ_16(st_fx->bwidth_fx,NB))
+ {
+ max_len = sub(160,last_pit_bin);
+ }
+
+ Len = 80;
+ move16();
+ if(LT_16(max_len,80))
+ {
+ Len = max_len;
+ move16();
+ }
+ test();
+ IF((EQ_32(st_fx->core_brate_fx,ACELP_8k00)) && (NE_16(st_fx->bwidth_fx,NB)))
+ {
+ move16(); /*ptr init*/
+ FOR (i=0; i < max_len; i++)
+ {
+ dct_pitex[i+last_pit_bin] = 0;
+ move16();
+ }
+ }
+ ELSE
+ {
+
+ FOR (i = 0; i < Len; i++)
+ {
+ dct_pitex[i+last_pit_bin] = mult_r(dct_pitex[i+last_pit_bin],sm_table_fx[i]);
+ }
+ FOR (; i < max_len; i++)
+ {
+ dct_pitex[i+last_pit_bin] = 0;
+ move16();
+ }
+ }
+ hGSCEnc->mem_last_pit_band = last_pit_band;
+ move16();
+ pit_contr_idx = sub(last_pit_band,BAND1k2);
+ }
+ ELSE
+ {
+ set16_fx(dct_pitex, 0, st_fx->L_frame_fx);
+ st_fx->bpf_off_fx = 1;
+ move16();
+ last_pit_bin = 0;
+ move16();
+ last_pit_band = 0;
+ move16();
+ pit_contr_idx = 0;
+ move16();
+ hGSCEnc->mem_last_pit_band = 0;
+ move16();
+
+ set16_fx( pitch_buf, shl(L_SUBFR,6), NB_SUBFR16k );
+ /* pitch contribution useless - delete all previously written indices belonging to pitch contribution */
+ FOR ( i = TAG_ACELP_SUBFR_LOOP_START; i < TAG_ACELP_SUBFR_LOOP_END; i++ )
+ {
+#ifndef IVAS_CODE_BITSTREAM
+ IF (hBstr->ind_list_fx[i].nb_bits != -1 )
+ {
+ hBstr->nb_bits_tot_fx = sub(hBstr->nb_bits_tot_fx, hBstr->ind_list_fx[i].nb_bits);
+ hBstr->ind_list_fx[i].nb_bits = -1;
+ move16();
+ }
+#else
+ delete_indice(hBstr, i);
+#endif
+ }
+
+#ifndef IVAS_CODE_BITSTREAM
+ IF (hBstr->ind_list_fx[IND_ES_PRED].nb_bits != -1 )
+ {
+ hBstr->nb_bits_tot_fx = sub(hBstr->nb_bits_tot_fx, hBstr->ind_list_fx[IND_ES_PRED].nb_bits);
+ hBstr->ind_list_fx[IND_ES_PRED].nb_bits = -1;
+ move16();
+ }
+#else
+ delete_indice(hBstr, i);
+#endif
+ }
+ IF( LT_32(st_fx->core_brate_fx,CFREQ_BITRATE))
+ {
+ IF(LT_32(st_fx->core_brate_fx,ACELP_9k60))
+ {
+ if(pit_contr_idx>0)
+ {
+ pit_contr_idx=1;
+ move16();
+ }
+
+ IF( EQ_16(st_fx->coder_type,INACTIVE))
+ {
+ push_indice_fx(hBstr, IND_PIT_CONTR_IDX, pit_contr_idx, 1 );
+ }
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_PIT_CONTR_IDX, pit_contr_idx, 3 );
+ }
+ }
+ ELSE
+ {
+ push_indice_fx(hBstr, IND_PIT_CONTR_IDX, pit_contr_idx, 4 );
+ }
+
+ return last_pit_bin;
+
+}
diff --git a/lib_enc/evs_enc_fx.c b/lib_enc/evs_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..f2ad9d07c4e7fb3920a0e6c90e17b8f7b699d9ed
--- /dev/null
+++ b/lib_enc/evs_enc_fx.c
@@ -0,0 +1,746 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include
+#include "options.h" /* Compilation switches */
+#include "prot.h"
+#include "cnst.h" /* Common constants */
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+#include "prot_fx_enc.h"
+
+/*-------------------------------------------------------------------*
+ * Local function prototypes
+ *-------------------------------------------------------------------*/
+
+static void initFrameHeader_loc( Encoder_State_fx *st );
+static void writeFrameHeader_loc(Encoder_State_fx *st );
+static void configure_core_coder_loc(Encoder_State_fx *st );
+
+/*-------------------------------------------------------------------*
+ * evs_enc()
+ *
+ * Principal encoder routine
+ *-------------------------------------------------------------------*/
+
+ivas_error evs_enc_fx(
+ Encoder_State_fx *st, /* i/o: encoder state structure */
+ const Word16 *data, /* i : input signal */
+ Word32 * mem_hp20_in_fx, /* i/o: hp20 filter memory */
+ const Word16 n_samples /* i : number of input samples */
+)
+{
+ Word16 i, input_frame, delay;
+ Word16 old_inp_12k8[L_INP_12k8], *inp = 0; /* buffer of input signal @ 12k8 */
+ Word16 old_inp_16k[L_INP]; /* buffer of input signal @ 16kHz */
+ Word32 fr_bands[2*NB_BANDS]; /* energy in frequency bands */
+ Word16 Etot; /* total energy; correlation shift */
+ Word32 ener; /* residual energy from Levinson-Durbin */
+ Word16 A[NB_SUBFR16k*(M+1)]; /* A(z) unquantized for subframes */
+ Word16 Aw[NB_SUBFR16k*(M+1)]; /* weighted A(z) unquantized for subframes */
+ Word16 epsP_h[M+1]; /* LP prediction errors */
+ Word16 epsP_l[M+1]; /* LP prediction errors */
+ Word32 epsP[M+1]; /* LP prediction errors */
+ Word16 lsp_new[M]; /* LSPs at the end of the frame */
+ Word16 lsp_mid[M]; /* ISPs in the middle of the frame */
+ Word16 vad_hover_flag;
+ Word16 hq_core_type; /* HQ core type (HQ, or LR-MDCT) */
+
+ Word16 attack_flag; /* attack flag (GSC or TC) */
+ Word16 new_inp_resamp16k[L_FRAME16k]; /* new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */
+ Word16 old_syn_12k8_16k[L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */
+ Word16 shb_speech[L_FRAME16k];
+ Word16 hb_speech[L_FRAME16k/4];
+ Word16 new_swb_speech[L_FRAME48k];
+ Word32 bwe_exc_extended[L_FRAME32k + NL_BUFF_OFFSET]; /* non-linear bandwidth extension buffer */
+ Word16 voice_factors[NB_SUBFR16k];
+ Word16 fb_exc[L_FRAME16k];
+ Word16 Voicing_flag;
+ Word16 pitch_buf[NB_SUBFR16k] = { 0 };
+ Word16 unbits;
+
+ Word16 padBits;
+ Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* real buffer */
+ Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; /* imag buffer */
+ CLDFB_SCALE_FACTOR cldfbScale;
+ Word16 Q_new, shift, Q_synth;
+ Word16 Q_r[2];
+ Word16 Q_shb_spch, Q_fb_exc;
+ Word32 L_tmp;
+ UWord16 lsb;
+ Word16 tmp;
+#ifndef FIX_I4_OL_PITCH
+ Word16 pitch_orig[3]; /* original open-loop pitch values that might be altered in core_acelp_tcx20_switching_fx() within MODE2 */
+#endif
+ ivas_error error;
+ SC_VBR_ENC_HANDLE hSC_VBR = st->hSC_VBR;
+ //NOISE_EST_HANDLE hNoiseEst = st->hNoiseEst;
+ //VAD_HANDLE hVAD = st->hVAD;
+ //DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc;
+ LPD_state_HANDLE hLPDmem = st->hLPDmem;
+ TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD;
+ BSTR_ENC_HANDLE hBstr = st->hBstr;
+ RF_ENC_HANDLE hRF = st->hRF;
+
+ error = IVAS_ERR_OK;
+
+
+ Q_shb_spch = 0;
+ move16(); /* to avoid compiler warnings */
+
+
+
+
+ /*------------------------------------------------------------------*
+ * Initializiation
+ *-----------------------------------------------------------------*/
+
+ input_frame = st->input_frame_fx;
+ move16();
+ st->core_fx = -1;
+ move16();
+ st->extl_fx = -1;
+ move16();
+ st->core_brate_fx = -1;
+ move32();
+ st->input_bwidth_fx = st->last_input_bwidth_fx;
+ move16();
+ st->bwidth_fx = st->last_bwidth_fx;
+ move16();
+ hq_core_type = -1;
+ move16();
+ unbits = 0;
+ move16();
+
+ st->bits_frame_core = 0;
+ move16(); /* For getting bit consumption in core coder */
+ hTdCngEnc->lp_cng_mode2 = 0;
+ move16();
+ st->mdct_sw_enable = 0;
+ move16();
+ st->mdct_sw = 0;
+ move16();
+ shift = st->old_wsp_shift;
+ move16();
+ st->rate_switching_reset = 0;
+ move16();
+
+ st->idchan = 0;
+ move16();
+ st->flag_ACELP16k = set_ACELP_flag(EVS_MONO, -1, st->total_brate_fx, 0, 0, -1, -1);
+ move16();
+
+
+ /*----------------------------------------------------------------*
+ * set input samples buffer
+ *----------------------------------------------------------------*/
+
+ /* get delay to synchronize ACELP and MDCT frame */
+ delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS);
+
+ Copy( st->input - delay, st->old_input_signal_fx, input_frame+delay );
+
+ /*----------------------------------------------------------------*
+ * convert 'short' input data to 'float'
+ *----------------------------------------------------------------*/
+
+ Copy(data, st->input, input_frame);
+ IF( LT_16(n_samples,input_frame))
+ {
+ set16_fx( st->input + n_samples, 0, sub(input_frame, n_samples) );
+ }
+
+ /*----------------------------------------------------------------*
+ * HP filtering
+ *----------------------------------------------------------------*/
+
+ hp20( st->input, 1, input_frame, mem_hp20_in_fx, st->input_Fs_fx );
+
+ /*----------------------------------------------------------------*
+ * Updates in case of AMR-WB IO mode -> EVS primary mode switching
+ *----------------------------------------------------------------*/
+
+ IF( EQ_16(st->last_core_fx, AMR_WB_CORE))
+ {
+ updt_IO_switch_enc_fx( st, input_frame );
+ set16_fx(hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k);
+#if defined IVAS_CODE
+PMT("find scaling factor for prev_enr_EnvSHBres, prev_pow_exc16kWhtnd and prev_mix_factor ")
+ set16_fx(st->hBWE_TD->old_speech_shb, 0, L_LOOK_16k + L_SUBFR16k);
+ set16_fx(st->hBWE_TD->mem_shb_res, 0, MAX_LEN_MA_FILTER);
+ set16_fx(st->hBWE_TD->old_EnvSHBres, 0, L_FRAME4k);
+ st->hBWE_TD->old_mean_EnvSHBres = 0;
+ st->hBWE_TD->prev_enr_EnvSHBres = 1.0f;
+ st->hBWE_TD->prev_shb_env_tilt = 0;
+ st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f;
+ st->hBWE_TD->prev_mix_factor = 1.0f;
+ st->hBWE_TD->prev_Env_error = 0;
+#endif
+ cldfb_reset_memory( st->cldfbAna_Fx );
+ cldfb_reset_memory( st->cldfbSyn_Fx );
+ }
+
+ /*---------------------------------------------------------------------*
+ * Pre-processing
+ *---------------------------------------------------------------------*/
+#ifdef FIX_I4_OL_PITCH
+ pre_proc(st, input_frame, old_inp_12k8, old_inp_16k, &inp, fr_bands, &Etot, &ener, A, Aw, epsP, lsp_new, lsp_mid, &vad_hover_flag, &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &hq_core_type);
+#else
+ pre_proc_fx( st, input_frame, old_inp_12k8, old_inp_16k, &inp, fr_bands, &Etot, &ener,
+ pitch_orig, A, Aw, epsP_h, epsP_l, epsP, lsp_new, lsp_mid, &vad_hover_flag,
+ &attack_flag, new_inp_resamp16k, &Voicing_flag, realBuffer, imagBuffer, &cldfbScale, hLPDmem->old_exc,
+ &hq_core_type, &Q_new, &shift, Q_r );
+#endif
+ //st->sharpFlag = sharpFlag;
+
+ IF (EQ_16(st->mdct_sw,MODE2))
+ {
+
+ Mpy_32_16_ss(st->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */
+ st->bits_frame_nominal = extract_l(L_shr(L_tmp, 3)); /* Q0 */
+
+ initFrameHeader_loc( st );
+ writeFrameHeader_loc( st );
+
+ test();
+ test();
+ test();
+ IF ((GT_32(st->total_brate_fx,ACELP_24k40)&<_32(st->total_brate_fx,HQ_96k))||(EQ_32(st->total_brate_fx,ACELP_24k40)&&GE_16(st->bwidth_fx,WB)))
+ {
+ st->L_frame_fx = L_FRAME16k;
+ move16();
+ st->gamma = GAMMA16k;
+ move16();
+ st->preemph_fac = PREEMPH_FAC_16k;
+ move16();
+
+ weight_a_subfr_fx( NB_SUBFR16k, A, Aw, GAMMA16k, M );
+ test();
+ IF (EQ_16(st->last_L_frame_fx,L_FRAME)&&st->ini_frame_fx!=0)
+ {
+ /* this is just an approximation, but it is sufficient */
+ Copy( st->lsp_old1_fx, st->lspold_enc_fx, M );
+ }
+ }
+ ELSE
+ {
+ st->L_frame_fx = L_FRAME;
+ move16();
+ st->gamma = GAMMA1;
+ move16();
+ st->preemph_fac = PREEMPH_FAC;
+ move16();
+ }
+
+ st->sr_core = L_mult0(FRAMES_PER_SEC,st->L_frame_fx);
+ st->core_brate_fx = st->total_brate_fx;
+ move32();
+
+ st->igf = 0;
+ move16();
+ hq_core_type = NORMAL_HQ_CORE;
+ move16();
+ test();
+ test();
+ IF( (EQ_16(st->bwidth_fx,SWB)||EQ_16(st->bwidth_fx,WB))&&LE_32(st->total_brate_fx,LRMDCT_CROSSOVER_POINT))
+ {
+ /* note that FB (bitrate >= 24400bps) is always coded with NORMAL_HQ_CORE */
+ hq_core_type = LOW_RATE_HQ_CORE;
+ move16();
+ }
+ ELSE IF( EQ_16(st->bwidth_fx,NB))
+ {
+ hq_core_type = LOW_RATE_HQ_CORE;
+ move16();
+ }
+ }
+
+ IF( EQ_16(st->codec_mode,MODE1))
+ {
+ /*---------------------------------------------------------------------*
+ * Write signalling info into the bitstream
+ *---------------------------------------------------------------------*/
+
+ signalling_enc_fx( st);
+
+ /*---------------------------------------------------------------------*
+ * Preprocessing (preparing) for ACELP/HQ core switching
+ *---------------------------------------------------------------------*/
+
+ core_switching_pre_enc_fx( st, old_inp_12k8, old_inp_16k, 0, 0);
+
+ /*---------------------------------------------------------------------*
+ * ACELP core encoding
+ *---------------------------------------------------------------------*/
+
+ IF( EQ_16(st->core_fx,ACELP_CORE))
+ {
+ acelp_core_enc_fx( st, inp, ener, A, Aw, epsP_h, epsP_l, lsp_new, lsp_mid, vad_hover_flag,
+ attack_flag, bwe_exc_extended, voice_factors, old_syn_12k8_16k, pitch_buf, &unbits, Q_new, shift
+#ifdef ADD_LRTD
+ ,NULL, NULL
+#endif
+ );
+ }
+ /*---------------------------------------------------------------------*
+ * HQ core encoding
+ *---------------------------------------------------------------------*/
+
+ IF( EQ_16(st->core_fx,HQ_CORE))
+ {
+ hq_core_enc_fx( st, st->input - delay, input_frame, hq_core_type, Voicing_flag, vad_hover_flag);
+ }
+
+ /*---------------------------------------------------------------------*
+ * Postprocessing for ACELP/HQ core switching
+ *---------------------------------------------------------------------*/
+ core_switching_post_enc_fx( st, old_inp_12k8, old_inp_16k, A, shift, Q_new, st->Q_syn2, &Q_synth );
+#ifndef FIX_I4_OL_PITCH
+ IF (EQ_16(st->core_fx, HQ_CORE))
+ {
+ Copy(pitch_orig, st->pitch_fx, 3); /* original open-loop pitch values might be altered in core_acelp_tcx20_switching_fx() */
+ }
+#endif
+ }
+ ELSE /* MODE2 */
+ {
+ /*----------------------------------------------------------------*
+ * Configuration of core coder/SID
+ * Write Frame Header
+ *----------------------------------------------------------------*/
+
+ configure_core_coder_loc( st);
+
+ IF (st->mdct_sw != MODE1)
+ {
+ writeFrameHeader_loc( st );
+ }
+
+ /*----------------------------------------------------------------*
+ * Core-Coder
+ *----------------------------------------------------------------*/
+
+ /* Call main encoding function */
+ enc_acelp_tcx_main_fx( old_inp_16k + L_INP_MEM, st, Aw, lsp_new, lsp_mid,
+ bwe_exc_extended, voice_factors, pitch_buf,
+ vad_hover_flag, &Q_new, &shift );
+#ifndef FIX_I4_OL_PITCH
+ Copy(pitch_orig, st->pitch_fx, 3); /* populate the original OL pitch values back */
+#endif
+
+ /*---------------------------------------------------------------------*
+ * Postprocessing for codec switching
+ *---------------------------------------------------------------------*/
+ /* TBE interface */
+ test();
+ IF ( st->igf != 0 && GT_32(st->core_brate_fx,SID_2k40))
+ {
+ IF( EQ_16(st->core_fx,ACELP_CORE))
+ {
+ SWITCH (st->bwidth_fx)
+ {
+ case WB:
+ st->extl_fx = WB_TBE;
+ move16();
+ st->extl_brate_fx = WB_TBE_0k35;
+ move32();
+ BREAK;
+
+ case SWB:
+ st->extl_fx = SWB_TBE;
+ move16();
+ st->extl_brate_fx = SWB_TBE_1k6;
+ move32();
+ IF (LT_32(st->total_brate_fx, ACELP_13k20))
+ {
+ st->extl_brate_fx = SWB_TBE_0k95;
+ move32();
+ }
+ ELSE IF (GE_32(st->total_brate_fx, ACELP_24k40))
+ {
+ st->extl_brate_fx = SWB_TBE_2k8;
+ move32();
+ }
+ BREAK;
+ case FB:
+ st->extl_fx = FB_TBE;
+ move16();
+ st->extl_brate_fx = FB_TBE_1k8;
+ move32();
+
+ if (GE_32(st->total_brate_fx, ACELP_24k40))
+ {
+ st->extl_brate_fx = FB_TBE_3k0;
+ move32();
+ }
+ BREAK;
+ }
+ }
+ ELSE
+ {
+ st->coder_type = -1;
+ move16();
+ st->extl_fx = IGF_BWE;
+ move16();
+ st->extl_brate_fx = 0;
+ move32();
+ }
+
+ st->core_brate_fx = L_sub(st->total_brate_fx, st->extl_brate_fx);
+
+ IF( EQ_16(st->tec_tfa, 1))
+ {
+ st->core_brate_fx = L_sub(st->core_brate_fx, BITS_TEC);
+ st->core_brate_fx = L_sub(st->core_brate_fx, BITS_TFA);
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ * Complete Bitstream Writing
+ *----------------------------------------------------------------*/
+
+ padBits = 0;
+
+ test();
+ test();
+ IF( st->igf != 0 && EQ_16(st->core_fx,ACELP_CORE)&>_32(st->core_brate_fx,SID_2k40))
+ {
+ /* padBits = ((st->bits_frame+7)/8)*8 - (st->nb_bits_tot + (st->rf_target_bits_write - ((st->Opt_RF_ON==1)?1:0) ) + get_tbe_bits(st->total_brate, st->bwidth, st->rf_mode )); */
+ tmp = add(get_tbe_bits_fx(st->total_brate_fx, st->bwidth_fx, st->rf_mode), sub(st->rf_target_bits_write, st->rf_mode));
+ padBits = sub(sub(shl(shr(add(st->bits_frame,7),3),3), hBstr->nb_bits_tot_fx), tmp);
+ }
+ ELSE
+ {
+ /* padBits = ((st->bits_frame+7)/8)*8 - (st->nb_bits_tot + (st->rf_target_bits_write - ((st->Opt_RF_ON==1)?1:0) )); */
+ tmp = sub(st->rf_target_bits_write, st->rf_mode);
+ padBits = sub(shl(shr(add(st->bits_frame,7),3),3), add(hBstr->nb_bits_tot_fx, tmp));
+ }
+
+ FOR( i = 0; iinput_Fs_fx,16000 )&&(LT_16(st->bwidth_fx,SWB)))
+ {
+ /* Common pre-processing for WB TBE and WB BWE */
+ wb_pre_proc_fx( st, new_inp_resamp16k, hb_speech );
+ /* o: new_inp_resamp16k at Q = -1 */
+ }
+
+ IF ( EQ_16(st->extl_fx,WB_TBE))
+ {
+ /* WB TBE encoder */
+ wb_tbe_enc_fx( st, st->coder_type, hb_speech, bwe_exc_extended, Q_new, voice_factors, pitch_buf, st->voicing_fx);
+
+ IF( EQ_16(st->codec_mode,MODE2))
+ {
+ tbe_write_bitstream_fx( st );
+ }
+ }
+ ELSE IF ( EQ_16(st->extl_fx, WB_BWE))
+ {
+ /* WB BWE encoder */
+ wb_bwe_enc_fx( st, new_inp_resamp16k, st->coder_type );
+
+ }
+
+ /*---------------------------------------------------------------------*
+ * SWB(FB) TBE encoding
+ * SWB BWE encoding
+ *---------------------------------------------------------------------*/
+ test();
+ IF (!st->Opt_SC_VBR_fx && GE_32(st->input_Fs_fx,32000))
+ {
+ /* Common pre-processing for SWB(FB) TBE and SWB BWE */
+ swb_pre_proc_fx(st, st->input, new_swb_speech, shb_speech, &Q_shb_spch, realBuffer, imagBuffer, &cldfbScale );
+ }
+ ELSE IF( GE_32(st->input_Fs_fx,32000))
+ {
+ set16_fx(hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k );
+ set16_fx( shb_speech, 0, L_FRAME16k );
+#if defined IVAS_CODE
+ set_f(st->hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER);
+ set_f(st->hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k);
+ st->hBWE_TD->old_mean_EnvSHBres = 0.0f;
+ st->hBWE_TD->prev_enr_EnvSHBres = 1.0f;
+ st->hBWE_TD->prev_shb_env_tilt = 0.0f;
+ st->hBWE_TD->prev_pow_exc16kWhtnd = 1.0f;
+ st->hBWE_TD->prev_mix_factor = 1.0f;
+ st->hBWE_TD->prev_Env_error = 0.0f;
+#endif
+ }
+
+ /* SWB TBE encoder */
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF ( EQ_16(st->extl_fx, SWB_TBE)||EQ_16(st->extl_fx,FB_TBE)||(st->igf!=0&&EQ_16(st->core_fx,ACELP_CORE)&&NE_16(st->extl_fx,WB_TBE)))
+ {
+ test();
+ IF( NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40))
+ {
+ swb_tbe_enc_fx( st, st->coder_type, shb_speech, bwe_exc_extended, voice_factors, fb_exc, &Q_fb_exc, Q_new, Q_shb_spch, st->voicing_fx, pitch_buf );
+
+ IF ( EQ_16(st->extl_fx,FB_TBE))
+ {
+ /* FB TBE encoder */
+ fb_tbe_enc_fx( st, st->input, fb_exc, Q_fb_exc );
+ }
+
+ IF( EQ_16(st->codec_mode,MODE2))
+ {
+ IF( EQ_16(st->tec_tfa, 1))
+ {
+ tecEnc_TBE_fx(&(st->hTECEnc->corrFlag), st->voicing_fx, st->coder_type);
+
+ IF( EQ_16(st->coder_type, INACTIVE))
+ {
+ st->tec_flag = 0;
+ move16();
+ st->hTECEnc->corrFlag = 0;
+ move16();
+ }
+ st->tfa_flag = tfaEnc_TBE_fx( st->tfa_enr, st->last_core_fx, st->voicing_fx, pitch_buf, shl(Q_shb_spch, 1));
+ set_TEC_TFA_code_fx( st->hTECEnc->corrFlag, &st->tec_flag, &st->tfa_flag );
+ }
+ ELSE
+ {
+ st->tec_flag = 0;
+ move16();
+ st->hTECEnc->corrFlag = 0;
+ move16();
+ st->tfa_flag = 0;
+ move16();
+ }
+
+ tbe_write_bitstream_fx( st );
+ }
+ }
+ }
+ ELSE IF ( EQ_16(st->extl_fx,SWB_BWE)||EQ_16(st->extl_fx,FB_BWE))
+ {
+ /* SWB BWE encoder */
+ swb_bwe_enc_fx( st, old_inp_12k8, old_inp_16k, old_syn_12k8_16k, new_swb_speech, shb_speech, st->coder_type, Q_shb_spch, sub(Q_new, 1) );
+ }
+ ELSE IF( EQ_16(st->extl_fx,SWB_BWE_HIGHRATE)||EQ_16(st->extl_fx,FB_BWE_HIGHRATE))
+ {
+ /* SWB HR BWE encoder */
+ swb_bwe_enc_hr_fx(st, st->input - delay, st->Q_syn2, input_frame, unbits );
+ }
+
+ /*---------------------------------------------------------------------*
+ * SWB DTX/CNG encoding
+ *---------------------------------------------------------------------*/
+
+ test();
+ IF ( st->Opt_DTX_ON_fx && GE_16(input_frame,L_FRAME32k))
+ {
+ swb_CNG_enc_fx( st, shb_speech, old_syn_12k8_16k );
+ }
+
+ /*---------------------------------------------------------------------*
+ * Channel-aware mode - write signaling information into the bitstream
+ *---------------------------------------------------------------------*/
+
+ signalling_enc_rf( st );
+
+ updt_enc_common_fx(st, Etot, Q_new);
+
+ if( EQ_16(st->mdct_sw,MODE1))
+ {
+ st->codec_mode = MODE1;
+ move16();
+ }
+ if(hTdCngEnc->lp_cng_mode2 )
+ {
+ st->codec_mode = MODE2;
+ move16();
+ }
+
+ IF (EQ_16(st->rf_mode,1))
+ {
+ IF (EQ_16(hRF->rf_frame_type,RF_NELP))
+ {
+ hSC_VBR->last_nelp_mode = 1;
+ }
+ ELSE
+ {
+ hSC_VBR->last_nelp_mode = 0;
+ }
+ }
+
+ /* RF mode updates */
+ st->rf_mode_last = st->rf_mode;
+ IF(EQ_16(st->Opt_RF_ON,1))
+ {
+ st->L_frame_fx = L_FRAME;
+ st->rf_mode = 1;
+ }
+#ifdef MY_DEBUG
+ dbgwrite_indices(st);
+#endif
+ return error;
+}
+
+
+/*-------------------------------------------------------------------*
+ * initFrameHeader()
+ *
+ * Initialize MODE2 frame header
+ *-------------------------------------------------------------------*/
+static void initFrameHeader_loc(Encoder_State_fx *st )
+{
+
+ Word16 n;
+
+ IF( EQ_32(st->core_brate_fx, SID_2k40))
+ {
+ /*Get size of frame*/
+ st->bits_frame = FRAME_2_4;
+ move16();
+ st->bits_frame_core = add(st->bits_frame_core, FRAME_2_4-4); /*1 bit for SID on/off + 3 bits for bandwith in case of SID.*/
+ st->frame_size_index = 2;
+ move16();
+ }
+ ELSE IF( EQ_32(st->core_brate_fx,FRAME_NO_DATA))
+ {
+ st->bits_frame = FRAME_0;
+ move16();
+ st->bits_frame_core = add(st->bits_frame_core,st->bits_frame);
+ st->frame_size_index = 0;
+ move16();
+ }
+ ELSE
+ {
+ //PMT("Frame header needs review")
+ FOR( n=0; nbits_frame_nominal))
+ {
+ st->frame_size_index = n;
+ move16();
+ st->bits_frame = FrameSizeConfig[n].frame_bits;
+ move16();
+ st->bits_frame_core = FrameSizeConfig[n].frame_net_bits;
+ move16();
+ BREAK;
+ }
+ }
+ }
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * writeFrameHeader()
+ *
+ * Write MODE2 frame header
+ *-------------------------------------------------------------------*/
+static void writeFrameHeader_loc(Encoder_State_fx *st )
+{
+
+ BSTR_ENC_HANDLE hBstr = st->hBstr;
+
+ IF( NE_32(st->core_brate_fx,FRAME_NO_DATA))
+ {
+ /* SID flag at 2.4kbps */
+ IF( EQ_32(st->core_brate_fx,SID_2k40))
+ {
+ IF ( EQ_16(st->cng_type_fx,FD_CNG))
+ {
+ /* write SID/CNG type flag */
+ push_next_indice_fx(hBstr, 1, 1 );
+
+ /* write bandwidth mode */
+ push_next_indice_fx(hBstr, st->bwidth_fx, 2 );
+
+ /* write L_frame */
+ IF( EQ_16(st->L_frame_fx,L_FRAME))
+ {
+ push_next_indice_fx(hBstr, 0, 1 );
+ }
+ ELSE
+ {
+ push_next_indice_fx(hBstr, 1, 1 );
+ }
+ }
+ }
+ ELSE /* active frames */
+ {
+ IF(st->rf_mode == 0)
+ {
+ push_next_indice_fx(hBstr, sub(st->bwidth_fx,FrameSizeConfig[st->frame_size_index].bandwidth_min), FrameSizeConfig[st->frame_size_index].bandwidth_bits);
+ }
+ }
+
+ /* Write reserved bit */
+ test();
+ IF( FrameSizeConfig[st->frame_size_index].reserved_bits && st->rf_mode == 0)
+ {
+ push_next_indice_fx(hBstr, 0, FrameSizeConfig[st->frame_size_index].reserved_bits );
+ }
+ }
+
+ return;
+}
+
+/*------------------------------------------------------------------------*
+* Configuration of core coder/SID
+*------------------------------------------------------------------------*/
+
+static void configure_core_coder_loc(
+ Encoder_State_fx *st /* i/o: encoder state structure */
+)
+{
+
+ initFrameHeader_loc( st );
+
+ test();
+ IF( NE_32(st->core_brate_fx, SID_2k40)&&NE_32(st->core_brate_fx,FRAME_NO_DATA))
+ {
+ if( st->tcxonly )
+ {
+ st->coder_type = GENERIC;
+ move16();
+ }
+
+ st->hTcxCfg->coder_type = st->coder_type;
+ move16();
+
+
+ test();
+ test();
+ if( !st->tcxonly && !st->localVAD && EQ_16(st->hTcxCfg->coder_type,GENERIC))
+ {
+ st->hTcxCfg->coder_type = UNVOICED;
+ move16();
+ }
+ }
+
+ st->igf = getIgfPresent_fx(st->element_mode, st->total_brate_fx, st->bwidth_fx, st->rf_mode);
+
+ test();
+ if( NE_32(st->core_brate_fx,SID_2k40)&&NE_32(st->core_brate_fx,FRAME_NO_DATA))
+ {
+ st->core_brate_fx = st->total_brate_fx;
+ move32();
+ }
+
+ return;
+}
diff --git a/lib_enc/ext_sig_ana_fx.c b/lib_enc/ext_sig_ana_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..4da307b5963e15ddad2458c8ef5cbe1d824c522d
--- /dev/null
+++ b/lib_enc/ext_sig_ana_fx.c
@@ -0,0 +1,607 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+#include
+#include
+#include "options.h"
+#include "cnst.h"
+//#include "prot_fx.h"
+#include "rom_com.h"
+#include "basop_util.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+
+/*-------------------------------------------------------------------*
+ * core_signal_analysis_high_bitrate_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+void core_signal_analysis_high_bitrate_fx(
+ const Word16 *new_samples, /*i: 0Q15*/
+ const Word16 T_op[3], /* i : open-loop pitch values for quantiz. */
+ Word16 lsp_new[],
+ Word16 lsp_mid[],
+ Encoder_State_fx *st,
+ Word16 pTnsSize[],
+ Word16 pTnsBits[],
+ Word16 param_core[],
+ Word16 *ltpBits,
+ const Word16 L_frame,
+ const Word16 L_frameTCX,
+ const Word16 last_element_mode,
+ const Word16 vad_hover_flag, /* i : VAD hangover flag */
+ Word32 **spectrum,
+ Word16 *spectrum_e,
+ Word16 *Q_new
+)
+{
+ const Word16 last_overlap = st->hTcxCfg->tcx_last_overlap_mode;
+ const Word16 curr_overlap = st->hTcxCfg->tcx_curr_overlap_mode;
+ Word16 i, frameno;
+ Word16 L_subframe;
+ Word16 left_overlap, right_overlap, folding_offset;
+ Word32 buf[N_MAX]; /* Buffer for TCX20/TCX10 windowing, power spectrum */
+ Word16 A[M+1];
+ Word16 mdstWin[N_MAX+L_MDCT_OVLP_MAX]; /* Buffer for MDST windowing */
+ Word16 * pMdstWin;
+ Word16 lpc_left_overlap_mode, lpc_right_overlap_mode;
+ Word16 * tcx20Win = (Word16*)buf;
+ Word32 powerSpec[N_MAX];
+ Word16 powerSpec_e;
+ Word32 interleaveBuf[N_TCX10_MAX];
+ Word16 *tcx5Win = (Word16*)interleaveBuf; /* Buffer for TCX5 windowing and interleaving. */
+ Word16 r_h[NB_DIV][M+1], r_l[NB_DIV][M+1];
+ Word32 r[M+1], epsP[M+1];
+ Word16 *lsp[2];
+ Word8 tmp8;
+ Word16 alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc = -1;
+ Word16 alw_voicing[2] , alw_voicing_wc = -1;
+ Word16 nSubframes;
+ Word16 overlap_mode[3];
+ Word16 transform_type[2];
+ Word16 tcx10SizeFB;
+ Word16 tcx5SizeFB;
+ Word16 tcx10Size;
+ Word16 tmp, *tmpP16;
+ Word32 *tmpP32;
+ Word16 Q_exp;
+
+#ifdef IVAS_CODE
+ int16_t disable_ltp = 0;
+#endif
+ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
+
+#ifndef IVAS_CODE
+ (void)vad_hover_flag;
+ (void)last_element_mode;
+#endif
+#ifdef IVAS_CODE
+ if (NE_16(last_element_mode, st->element_mode) )
+ {
+ disable_ltp = 1; /* disable TCX-LTP in stereo switching to avoid discontinuities in synthesis */
+ move16();
+ }
+#endif
+ left_overlap = -1;
+ move16();
+ right_overlap = -1;
+ move16();
+
+ tcx10SizeFB = shl(st->hTcxCfg->tcx5SizeFB, 1);
+ tcx5SizeFB = st->hTcxCfg->tcx5SizeFB;
+ move16();
+ tcx10Size = shl(st->hTcxCfg->tcx5Size, 1);
+
+ /*--------------------------------------------------------------*
+ * Input Signal Processing: copy, HP filter, pre-emphasis
+ *---------------------------------------------------------------*/
+
+ /* Copy Samples */
+ IF (st->tcxonly && NE_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ Copy(new_samples, st->new_speech_enc, L_frame);
+ Scale_sig(st->new_speech_enc, L_frame, 1);
+ }
+
+ /*--------------------------------------------------------------*
+ * TCX-LTP
+ *---------------------------------------------------------------*/
+
+ tmp8 = 0;
+ move16();
+ if(GT_32(st->sr_core, 25600))
+ {
+ tmp8 = 1;
+ move16();
+ }
+ IF (EQ_16(st->element_mode, IVAS_CPE_DFT))
+ {
+ //PMT("tcx_ltp_encode_fx should be verified for IVAS")
+ tcx_ltp_encode_fx(hTcxEnc->tcxltp, st->tcxonly, hTcxEnc->tcxMode,
+ L_frame, L_SUBFR, st->speech_enc + st->encoderLookahead_enc,
+ hTcxEnc->speech_ltp + st->encoderLookahead_enc, st->speech_enc + st->encoderLookahead_enc,
+ T_op[1], ¶m_core[1 + NOISE_FILL_RANGES], ltpBits,
+ &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, &hTcxEnc->tcxltp_gain,
+ &hTcxEnc->tcxltp_pitch_int_past, &hTcxEnc->tcxltp_pitch_fr_past, &hTcxEnc->tcxltp_gain_past,
+ &hTcxEnc->tcxltp_norm_corr_past, st->last_core_fx, st->pit_min, st->pit_fr1,
+ st->pit_fr2, st->pit_max, st->pit_res_max, &st->transientDetection,
+ tmp8, NULL, M);
+ }
+ ELSE
+ {
+ tcx_ltp_encode_fx(hTcxEnc->tcxltp, st->tcxonly, hTcxEnc->tcxMode,
+ L_frame, L_SUBFR, st->speech_enc + st->encoderLookahead_enc,
+ hTcxEnc->speech_ltp + st->encoderLookahead_enc, st->speech_enc + st->encoderLookahead_enc,
+ T_op[1], ¶m_core[1 + NOISE_FILL_RANGES], ltpBits,
+ &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, &hTcxEnc->tcxltp_gain,
+ &hTcxEnc->tcxltp_pitch_int_past, &hTcxEnc->tcxltp_pitch_fr_past, &hTcxEnc->tcxltp_gain_past,
+ &hTcxEnc->tcxltp_norm_corr_past, st->last_core_fx, st->pit_min, st->pit_fr1,
+ st->pit_fr2, st->pit_max, st->pit_res_max, &st->transientDetection,
+ tmp8, NULL, M);
+ }
+
+ test();
+ IF(st->tcxonly&& NE_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ Copy(st->speech_enc + st->encoderLookahead_enc, st->new_speech_enc_pe, L_frame);
+
+ Preemph_scaled(st->new_speech_enc_pe, Q_new, &(st->mem_preemph_enc),
+ st->Q_max_enc, st->preemph_fac, 1, 0, 2, L_frame, st->coder_type_raw_fx, 1);
+ }
+ Q_exp = sub(*Q_new, st->prev_Q_new);
+ move16();
+
+ /* Rescale Memory */
+ Scale_sig(st->old_inp_16k_fx, L_INP_MEM, sub(*Q_new,st->Q_old));
+ IF (Q_exp != 0)
+ {
+ Scale_sig(st->buf_speech_enc_pe, st->encoderPastSamples_enc+st->encoderLookahead_enc, Q_exp);
+ Scale_sig(&(st->mem_wsp_enc), 1, Q_exp);
+ }
+
+ IF (EQ_16(hTcxEnc->tcxMode,TCX_10))
+ {
+ Copy( ¶m_core[1+NOISE_FILL_RANGES], ¶m_core[NPRM_DIV+1+NOISE_FILL_RANGES], LTPSIZE );
+ }
+
+
+ /*-------------------------------------------------------------------------*
+ * Decision matrix for the transform and overlap length
+ *--------------------------------------------------------------------------*/
+ IF(NE_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ lsp[0] = lsp_new;
+ lsp[1] = lsp_mid;
+ alw_pitch_lag_12k8[0] = st->pitch_fx[0];
+ move16();
+ alw_pitch_lag_12k8[1] = st->pitch_fx[1];
+ move16();
+ alw_voicing[0] = st->voicing_fx[0];
+ move16();
+ alw_voicing[1] = st->voicing_fx[1];
+ move16();
+
+ alw_pitch_lag_12k8_wc = s_min(alw_pitch_lag_12k8[0], alw_pitch_lag_12k8[1]);
+ alw_voicing_wc = s_max(alw_voicing[0], alw_voicing[1]);
+ }
+ overlap_mode[0] = last_overlap; /* Overlap between the last and the current frame */ move16();
+
+ IF (EQ_16(hTcxEnc->tcxMode, TCX_20))
+ {
+ nSubframes = 1;
+ move16();
+ transform_type[0] = TCX_20;
+ transform_type[1] = TCX_20;
+ move16();
+ overlap_mode[1] = curr_overlap; /* Overlap between the current and the next frame */ move16();
+
+ IF(NE_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ alw_pitch_lag_12k8[0] = alw_pitch_lag_12k8_wc;
+ move16();
+ alw_voicing[0] = alw_voicing_wc;
+ move16();
+ }
+ }
+ ELSE
+ {
+ nSubframes = 2;
+ move16();
+ IF (EQ_16(curr_overlap, FULL_OVERLAP))
+ {
+ transform_type[0] = TCX_5;
+ move16();
+ transform_type[1] = TCX_10;
+ move16();
+
+ overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ move16();
+ if (EQ_16(last_overlap, HALF_OVERLAP))
+ {
+ overlap_mode[1] = HALF_OVERLAP;
+ move16();
+ }
+ }
+ ELSE IF (EQ_16(last_overlap, FULL_OVERLAP))
+ {
+ transform_type[0] = TCX_10;
+ move16();
+ transform_type[1] = TCX_5;
+ move16();
+
+ overlap_mode[1] = MIN_OVERLAP; /* Overlap between 1st and 2nd sub-frame */ move16();
+ if (EQ_16(curr_overlap, HALF_OVERLAP))
+ {
+ overlap_mode[1] = HALF_OVERLAP;
+ move16();
+ }
+ }
+ ELSE
+ {
+ transform_type[0] = transform_type[1] = TCX_5;
+ move16();
+ move16();
+
+ overlap_mode[1] = MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ move16();
+ test();
+ if (EQ_16(last_overlap, HALF_OVERLAP)&&EQ_16(curr_overlap,HALF_OVERLAP))
+ {
+ overlap_mode[1] = HALF_OVERLAP;
+ move16();
+ }
+ }
+ overlap_mode[2] = curr_overlap; /* Overlap between the current and the next frame */ move16();
+ }
+ IF (NE_16(transform_type[0], TCX_20))
+ {
+ IGFEncResetTCX10BitCounter_fx(st->hIGFEnc);
+ }
+ /*-------------------------------------------------------------------------*
+ * Get MDCT output and TNS parameters. Apply TNS in the spectrum if needed
+ *--------------------------------------------------------------------------*/
+
+ FOR(frameno = 0; frameno < nSubframes; frameno++)
+ {
+ L_subframe = L_frameTCX;
+ move16();
+ if (NE_16(nSubframes, 1))L_subframe = shr(L_frameTCX, 1);
+
+ lpc_left_overlap_mode = overlap_mode[frameno];
+ move16();
+ lpc_right_overlap_mode = overlap_mode[frameno + 1];
+ move16();
+ if (EQ_16(lpc_left_overlap_mode, ALDO_WINDOW))
+ {
+ lpc_left_overlap_mode = FULL_OVERLAP;
+ move16();
+ }
+ if (EQ_16(lpc_right_overlap_mode, ALDO_WINDOW))
+ {
+ lpc_right_overlap_mode = FULL_OVERLAP;
+ move16();
+ }
+
+ test();
+ IF((NE_16(transform_type[frameno], TCX_20)) || (EQ_16(st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP)))
+ {
+ /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */
+ WindowSignal(st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno],
+ overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB],
+ &L_subframe, tcx20Win, st->element_mode != IVAS_CPE_MDCT /* truncate_aldo */, 1);
+#ifdef IVAS_CODE
+ if (windowed_samples != NULL) /* save windowed speech_TCX samples */
+ {
+ assert(L_subframe + (left_overlap + right_overlap) / 2 < 2 * L_FRAME_MAX / nSubframes - L_FRAME_MAX / 8);
+ windowed_samples[frameno * L_FRAME_MAX + 0] = (float)overlap_mode[frameno];
+ windowed_samples[frameno * L_FRAME_MAX + 1] = (float)overlap_mode[frameno + 1];
+ mvr2r(tcx20Win, windowed_samples + frameno * L_FRAME_MAX + 2, L_subframe + (left_overlap + right_overlap) / 2);
+ }
+#endif
+ }
+
+ IF(EQ_16(transform_type[frameno], TCX_5))
+ {
+ folding_offset = shr(left_overlap, 1);
+
+ /* Outter left folding */
+ FOR(i = 0; i < folding_offset; i++)
+ {
+ tcx20Win[folding_offset + i] = sub(tcx20Win[folding_offset + i], tcx20Win[folding_offset - 1 - i]);
+ move16();
+ }
+#ifdef IVAS_CODE
+ if (st->element_mode == IVAS_CPE_MDCT && frameno == 0 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen)
+ {
+ for (i = minWindowLen; i >= 0; i--) /* outer left folding of shortened long ALDO slope */
+ {
+ tcx20Win[left_overlap + i] -= hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i];
+ }
+ }
+#endif
+ /* Outter right folding */
+ tmp = shr(right_overlap, 1);
+ FOR(i = 0; i < tmp; i++)
+ {
+ tcx20Win[L_subframe + folding_offset - 1 - i] = add(tcx20Win[L_subframe + folding_offset - 1 - i], tcx20Win[L_subframe + folding_offset + i]);
+ move16();
+ }
+ /* 2xTCX5 */
+ L_subframe = tcx5SizeFB;
+ move16();
+
+ tmpP16 = tcx20Win;
+ tmpP32 = spectrum[frameno];
+ assert(st->mct_chan_mode != MCT_CHAN_MODE_LFE);
+ FOR(i = 0; i < 2; i++)
+ {
+ test();
+ test();
+ WindowSignal(st->hTcxCfg,
+ folding_offset,
+ mac_r(-(1 << 16), 3 << 8, shl(i, 7)), /* equivalent to: i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP */
+ mac_r(2 << 16, -(3 << 8), shl(i, 7)), /* equivalent to: sub(i, 1) == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP */
+ &left_overlap, &right_overlap, tmpP16, &L_subframe, tcx5Win, st->element_mode != IVAS_CPE_MDCT, 1);
+
+ spectrum_e[frameno] = 16;
+ move16();
+ TCX_MDCT(tcx5Win,
+ tmpP32,
+ &spectrum_e[frameno],
+ left_overlap,
+ sub(L_subframe, shr(add(left_overlap, right_overlap), 1)),
+ right_overlap, st->element_mode);
+
+ tmpP16 += tcx5SizeFB;
+ tmpP32 += tcx5SizeFB;
+#ifdef IVAS_CODE
+ /* high-band gain control in case of BWS */
+ if (st->bwidth_sw_cnt > 0)
+ {
+ v_multc(hTcxEnc->spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / (2 * nSubframes), (float)(st->bwidth_sw_cnt) / (float)BWS_TRAN_PERIOD, hTcxEnc->spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / (2 * nSubframes), L_subframe - L_FRAME16k / (2 * nSubframes));
+ }
+#endif
+ }
+
+ }
+ ELSE /* transform_type[frameno] != TCX_5 */
+ {
+ assert(transform_type[frameno] == TCX_10 || transform_type[frameno] == TCX_20);
+
+ /* TCX20/TCX10 */
+ spectrum_e[frameno] = 16;
+ move16();
+ test(); test();
+ IF((EQ_16(transform_type[frameno], TCX_20)) && (NE_16(st->hTcxCfg->tcx_last_overlap_mode,TRANSITION_OVERLAP)) && NE_16(st->mct_chan_mode, MCT_CHAN_MODE_LFE))
+ {
+ Word32 tmp_buf[L_FRAME_PLUS];
+ Word16 Q, tmp1, tmp2;
+
+ Q = 0;
+ move16();
+
+ wtda_fx(hTcxEnc->new_speech_TCX,&Q, tmp_buf, NULL, NULL, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX);
+
+ WindowSignal(st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, lpc_left_overlap_mode, lpc_right_overlap_mode, &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, st->element_mode != IVAS_CPE_MDCT, 1);
+
+ /* scale by NORM_MDCT_FACTOR / L */
+ tmp1 = mult_r(shl(L_subframe, 4), 26214/*128.f / NORM_MDCT_FACTOR Q15*/); /* 4Q11 */
+ tmp2 = 4;
+ move16();
+ tmp1 = ISqrt16(tmp1, &tmp2);
+
+ FOR(i = 0; i < L_subframe; i++)
+ {
+ tmp_buf[i] = Mpy_32_16_1(tmp_buf[i], tmp1);
+ move32();
+ }
+ Q = sub(Q, tmp2);
+
+ /* DCT */
+ edct_fx(tmp_buf, spectrum[frameno], L_subframe, &Q);
+ *spectrum_e = sub(31, Q);
+ }
+ ELSE
+ {
+#ifdef IVAS_CODE
+ if (st->element_mode == IVAS_CPE_MDCT && frameno == 0 && transform_type[0] == TCX_10 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen)
+ {
+ for (i = minWindowLen; i >= 0; i--) /* outer left folding of shortened long ALDO slope */
+ {
+ tcx20Win[left_overlap + i] -= hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i];
+ }
+ }
+#endif
+ TCX_MDCT(tcx20Win,spectrum[frameno], &spectrum_e[frameno], left_overlap, sub(L_subframe, shr(add(left_overlap, right_overlap), 1)), right_overlap, st->element_mode);
+ }
+
+ /* For TCX20 at bitrates up to 64 kbps we need the power spectrum */
+
+ /* high-band gain control in case of BWS */
+#ifdef IVAS_CODE
+ if (st->bwidth_sw_cnt > 0)
+ {
+ v_multc(hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, (float)(st->bwidth_sw_cnt) / (float)BWS_TRAN_PERIOD, hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes);
+ }
+
+ if (st->mct_chan_mode == MCT_CHAN_MODE_LFE)
+ {
+ set_f(&hTcxEnc->spectrum[frameno][MCT_LFE_MAX_LINE], 0.f, L_subframe - MCT_LFE_MAX_LINE);
+ st->hTcxCfg->tcx_coded_lines = MCT_LFE_MAX_LINE;
+ }
+#endif
+ IF(NE_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ test(); test();
+ IF(EQ_16(hTcxEnc->tcxMode, TCX_20) && ((LT_32(st->total_brate_fx, HQ_96k)) || st->igf))
+ {
+
+ pMdstWin = tcx20Win;
+ test();
+ if (((EQ_16(hTcxEnc->tcxMode, TCX_20)) && (NE_16(st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP))))
+ {
+ pMdstWin = mdstWin;
+ }
+
+ /* Compute noise-measure flags for spectrum filling and quantization */
+ AnalyzePowerSpectrum_fx(st, div_l(L_mult(L_subframe, st->L_frame_fx), hTcxEnc->L_frameTCX),
+ L_subframe, left_overlap, right_overlap, spectrum[frameno], spectrum_e[frameno],
+ pMdstWin, powerSpec, &powerSpec_e);
+ }
+ }
+#ifdef IVAS_CODE
+ if (st->element_mode == IVAS_CPE_MDCT)
+ {
+ L_subframe = L_frameTCX / nSubframes;
+
+ if (transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP && st->mct_chan_mode != MCT_CHAN_MODE_LFE)
+ {
+ wtda_ext(hTcxEnc->new_speech_TCX, mdstWin, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX, 3);
+ }
+ else
+ {
+ /* Windowing for the MDST */
+ WindowSignal(st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 0, 1);
+ }
+
+ if (transform_type[frameno] == TCX_5)
+ {
+ /* Outer left folding */
+ for (i = 0; i < left_overlap / 2; i++)
+ {
+ mdstWin[left_overlap / 2 + i] += mdstWin[left_overlap / 2 - 1 - i];
+ }
+
+ if (frameno == 0 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen)
+ {
+ for (i = minWindowLen; i >= 0; i--) /* outer left folding of shortened long ALDO slope */
+ {
+ mdstWin[left_overlap + i] += hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i];
+ }
+ }
+
+ /* Outer right folding */
+ for (i = 0; i < right_overlap / 2; i++)
+ {
+ mdstWin[L_subframe + left_overlap / 2 - 1 - i] -= mdstWin[L_subframe + left_overlap / 2 + i];
+ }
+
+ /* 2xTCX5 */
+ L_subframe = tcx5SizeFB;
+ folding_offset = left_overlap / 2;
+
+ for (i = 0; i < 2; i++)
+ {
+ assert(st->mct_chan_mode != MCT_CHAN_MODE_LFE);
+ WindowSignal(st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, mdstWin + i * tcx5SizeFB, &L_subframe, tcx5Win, 0, 1);
+
+ TCX_MDST(tcx5Win, mdst_spectrum[frameno] + i * tcx5SizeFB, left_overlap, L_subframe - (left_overlap + right_overlap) / 2, right_overlap, st->element_mode);
+ /* high-band gain control in case of BWS */
+ if (st->bwidth_sw_cnt > 0)
+ {
+ v_multc(mdst_spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / (2 * nSubframes), (float)(st->bwidth_sw_cnt) / (float)BWS_TRAN_PERIOD, mdst_spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / (2 * nSubframes), L_subframe - L_FRAME16k / (2 * nSubframes));
+ }
+ }
+ }
+ else /* transform_type[frameno] != TCX_5 */
+ {
+ if (transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP && st->mct_chan_mode != MCT_CHAN_MODE_LFE)
+ {
+ edst(mdstWin, mdst_spectrum[frameno], L_subframe, st->element_mode);
+
+ v_multc(mdst_spectrum[frameno], (float)sqrt((float)NORM_MDCT_FACTOR / L_subframe), mdst_spectrum[frameno], L_subframe);
+ }
+ else
+ {
+ if (frameno == 0 && transform_type[0] == TCX_10 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen)
+ {
+ for (i = minWindowLen; i >= 0; i--) /* outer left folding of shortened long ALDO slope */
+ {
+ mdstWin[left_overlap + i] += hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i];
+ }
+ }
+
+ TCX_MDST(mdstWin, mdst_spectrum[frameno], left_overlap, L_subframe - (left_overlap + right_overlap) / 2, right_overlap, st->element_mode);
+ }
+
+ /* high-band gain control in case of BWS */
+ if (st->bwidth_sw_cnt > 0)
+ {
+ v_multc(mdst_spectrum[frameno] + L_FRAME16k / nSubframes, (float)(st->bwidth_sw_cnt) / (float)BWS_TRAN_PERIOD, mdst_spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes);
+ }
+ }
+
+ if (st->mct_chan_mode == MCT_CHAN_MODE_LFE)
+ {
+ set_f(&mdst_spectrum[frameno][MCT_LFE_MAX_LINE], 0.f, L_subframe - MCT_LFE_MAX_LINE);
+ }
+#endif
+ }
+ IF(NE_16(st->element_mode, IVAS_CPE_MDCT))
+ {
+ test();
+ test();
+ TNSAnalysis_fx(st->hTcxCfg, L_frameTCX,
+ st->hTcxCfg->tcx_coded_lines,
+ transform_type[frameno], (frameno == 0) && (st->last_core_fx == ACELP_CORE),
+ spectrum[frameno], &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns_fx[frameno], NULL
+ );
+#ifdef IVAS_CODE
+ IF (st->hTcxCfg->fIsTNSAllowed)
+#endif
+ {
+ EncodeTnsData_fx(st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frameno],
+ param_core + frameno * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, pTnsSize + frameno, pTnsBits + frameno);
+ }
+ IF(EQ_16(transform_type[frameno], TCX_5))
+ {
+ /* group sub-windows: interleave bins according to their frequencies */
+ FOR(i = 0; i < tcx5SizeFB; i++)
+ {
+ interleaveBuf[2 * i] = spectrum[frameno][i];
+ move32();
+ interleaveBuf[2 * i + 1] = spectrum[frameno][tcx5SizeFB + i];
+ move32();
+ }
+ Copy32(interleaveBuf, spectrum[frameno], tcx10SizeFB);
+ }
+
+ /*--------------------------------------------------------------*
+ * LPC analysis
+ *---------------------------------------------------------------*/
+
+#ifdef IVAS_CODE
+ IF(st->tcxonly)
+#endif
+ {
+ HBAutocorrelation_fx(st->hTcxCfg, lpc_left_overlap_mode, lpc_right_overlap_mode, &st->speech_enc_pe[frameno * tcx10Size],
+ shr(L_frame, sub(nSubframes, 1)), r, M);
+
+ FOR(i = 0; i <= M; i++)
+ {
+ move16();
+ move16();
+ r_l[frameno][i] = L_Extract_lc(r[i], &r_h[frameno][i]);
+ }
+
+ adapt_lag_wind(r_h[frameno], r_l[frameno], M, alw_pitch_lag_12k8[frameno], alw_voicing[frameno], st->sr_core);
+
+ E_LPC_lev_dur(r_h[frameno], r_l[frameno], A, epsP, M, NULL);
+
+ E_LPC_a_lsp_conversion(A, lsp[nSubframes - 1 - frameno], st->lspold_enc_fx, M);
+ }
+ IF(st->igf)
+ {
+ ProcessIGF_fx(st->hIGFEnc, st, spectrum[frameno], &(spectrum_e[frameno]), powerSpec, &powerSpec_e, transform_type[frameno] == TCX_20, hTcxEnc->fUseTns_fx[frameno], (st->last_core_fx == ACELP_CORE), frameno);
+ }
+
+ /* Copy memory */
+ mvr2r_Word16(lsp_new, st->lspold_enc_fx, M);
+ }
+ }
+
+}
+
diff --git a/lib_enc/fd_cng_enc_fx.c b/lib_enc/fd_cng_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..391184792db927650b16cb29dae6c655d8c5ff85
--- /dev/null
+++ b/lib_enc/fd_cng_enc_fx.c
@@ -0,0 +1,1648 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include "stl.h"
+#include "options.h"
+#include "cnst.h"
+#include "stl.h"
+#include "rom_com_fx.h"
+#include "rom_com.h"
+#include "rom_enc.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h"
+#include "prot_fx_enc.h"
+#include "basop_util.h"
+#include "rom_basop_util.h"
+
+
+/********************************
+* External functions *
+********************************/
+#ifndef swap
+ #define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;}
+#endif
+
+/*************************************
+* Create an instance of type FD_CNG *
+*************************************/
+void createFdCngEnc_fx(HANDLE_FD_CNG_ENC_FX* hFdCngEnc)
+{
+ HANDLE_FD_CNG_ENC_FX hs;
+
+ /* Allocate memory */
+ hs = (HANDLE_FD_CNG_ENC_FX) calloc(1, sizeof (FD_CNG_ENC));
+ move16();
+
+
+ createFdCngCom(&(hs->hFdCngCom));
+ *hFdCngEnc = hs;
+ move16();
+
+ return;
+}
+
+void initFdCngEnc_fx(HANDLE_FD_CNG_ENC_FX hsEnc, Word32 input_Fs, Word16 scale)
+{
+ Word16 j;
+ HANDLE_FD_CNG_COM hsCom = hsEnc->hFdCngCom;
+
+ /* Initialize common */
+
+ initFdCngCom( hsCom, scale );
+
+ /* Configure the Noise Estimator */
+
+ hsCom->numSlots = 16;
+ move16();
+ hsCom->numCoreBands = 16;
+ move16();
+ hsCom->regularStopBand = idiv1616U( extract_l( L_shr( input_Fs, 5 ) ), 25 );
+ if ( GT_16( hsCom->regularStopBand, 40 ))
+ {
+ hsCom->regularStopBand = 40;
+ move16();
+ }
+
+ hsCom->startBand = 2;
+ move16();
+ IF ( EQ_16( hsCom->regularStopBand, 10 ))
+ {
+ hsCom->stopFFTbin = 160;
+ move16();
+ hsCom->stopBand = 160;
+ move16();
+ hsCom->nFFTpart = 17;
+ move16();
+ }
+ ELSE
+ {
+ hsCom->stopFFTbin = 256;
+ move16();
+ hsCom->stopBand = add( sub( hsCom->regularStopBand, hsCom->numCoreBands ), hsCom->stopFFTbin );
+ hsCom->nFFTpart = 20;
+ move16();
+ }
+
+ initPartitions( sidparts_encoder_noise_est, 24, hsCom->startBand, hsCom->stopBand, hsCom->part, &hsCom->npart, hsCom->midband, hsCom->psize, hsCom->psize_norm, &hsCom->psize_norm_exp, hsCom->psize_inv, 0);
+
+ hsCom->nCLDFBpart = sub( hsCom->npart, hsCom->nFFTpart );
+ FOR(j=0; jnCLDFBpart; j++)
+ {
+ hsCom->CLDFBpart[j] = sub( hsCom->part[j+hsCom->nFFTpart], sub( 256, hsCom->startBand ) );
+ hsCom->CLDFBpsize_inv[j] = hsCom->psize_inv[j+hsCom->nFFTpart];
+ }
+
+ /* Initialize noise estimation algorithm */
+ set32_fx( hsEnc->msPeriodog, 0, NPART );
+ hsEnc->msPeriodog_exp_fft = 0;
+ move16();
+ hsEnc->msPeriodog_exp_cldfb = 0;
+ move16();
+ set32_fx( hsEnc->msAlpha, 0, NPART );
+ set32_fx( hsEnc->msBminWin, 0, NPART );
+ set32_fx( hsEnc->msBminSubWin, 0, NPART );
+
+ set32_fx( hsEnc->msNoiseEst, 0, NPART );
+ hsEnc->msNoiseEst_exp = 0;
+ move16();
+ set32_fx( hsEnc->energy_ho, 0, NPART );
+ set32_fx( hsEnc->msNoiseEst_old, 0, NPART );
+
+ set16_fx( hsEnc->msLogPeriodog, 0, NPART );
+ set16_fx( hsEnc->msLogNoiseEst, 0, NPART );
+ set16_fx( hsEnc->msPsd, 0, NPART );
+ set16_fx( hsEnc->msNoiseFloor, 0, NPART );
+ set32_fx( hsEnc->msMinBuf, 2147483647l/*1.0 Q31*/, MSNUMSUBFR*NPART );
+ set32_fx( hsEnc->msCurrentMin, 2147483647l/*1.0 Q31*/, NPART );
+ set32_fx( hsEnc->msCurrentMinOut, 2147483647l/*1.0 Q31*/, NPART );
+ set32_fx( hsEnc->msCurrentMinSubWindow, 2147483647l/*1.0 Q31*/, NPART );
+ set16_fx( hsEnc->msPsdFirstMoment, 0, NPART );
+ set16_fx( hsEnc->msPeriodogBuf, 0, MSBUFLEN*NPART );
+
+ set16_fx( hsEnc->msLocalMinFlag, 0, NPART );
+ set16_fx( hsEnc->msNewMinFlag, 0, NPART );
+ hsEnc->msPeriodogBufPtr = 0;
+ move16();
+ set32_fx( hsEnc->msPsdSecondMoment, 0, NPART );
+
+
+ return;
+}
+
+/************************************
+* Configure FD_CNG *
+************************************/
+void configureFdCngEnc_fx(HANDLE_FD_CNG_ENC_FX hsEnc, /* i/o: Contains the variables related to the FD-based CNG process */
+ Word16 bandwidth, /* i: bandwidth */
+ Word32 bitrate
+ )
+{
+ HANDLE_FD_CNG_COM hsCom = hsEnc->hFdCngCom;
+ Word16 psizeDec[NPART];
+ Word16 psizeDec_norm[NPART];
+ Word16 psizeDec_norm_exp;
+ Word16 psize_invDec[NPART];
+
+ set16_fx(psizeDec, 0, NPART);
+
+ hsCom->CngBandwidth = bandwidth;
+ move16();
+ IF ( EQ_16( hsCom->CngBandwidth, FB ))
+ {
+ hsCom->CngBandwidth = SWB;
+ }
+ hsCom->CngBitrate = bitrate;
+ move32();
+
+ /* NB configuration */
+ IF ( EQ_16(bandwidth,NB))
+ {
+ hsCom->FdCngSetup = FdCngSetup_nb; /* PTR assignation -> no move needed*/
+ }
+
+ /* WB configuration */
+ ELSE IF ( EQ_16(bandwidth,WB))
+ {
+ /* FFT 6.4kHz, no CLDFB */
+ IF ( LE_32(bitrate,ACELP_8k00))
+ {
+ hsCom->FdCngSetup = FdCngSetup_wb1;
+ }
+ /* FFT 6.4kHz, CLDFB 8.0kHz */
+ ELSE IF ( LE_32(bitrate,ACELP_13k20))
+ {
+ hsCom->FdCngSetup = FdCngSetup_wb2;
+ }
+ /* FFT 8.0kHz, no CLDFB */
+ ELSE
+ {
+ hsCom->FdCngSetup = FdCngSetup_wb3;
+ }
+ }
+
+ /* SWB/FB configuration */
+ ELSE
+ {
+ /* FFT 6.4kHz, CLDFB 14kHz */
+ IF ( LE_32(bitrate,ACELP_13k20))
+ {
+ hsCom->FdCngSetup = FdCngSetup_swb1;
+ }
+ /* FFT 8.0kHz, CLDFB 16kHz */
+ ELSE
+ {
+ hsCom->FdCngSetup = FdCngSetup_swb2;
+ }
+ }
+ hsCom->fftlen = hsCom->FdCngSetup.fftlen;
+ move16();
+ hsEnc->stopFFTbinDec = hsCom->FdCngSetup.stopFFTbin;
+ move16();
+
+ /* Configure the SID quantizer and the Confort Noise Generator */
+
+ hsEnc->startBandDec = hsCom->startBand;
+ move16();
+ hsEnc->stopBandDec = add( hsCom->FdCngSetup.sidPartitions[hsCom->FdCngSetup.numPartitions-1], 1 );
+ move16();
+ initPartitions( hsCom->FdCngSetup.sidPartitions,
+ hsCom->FdCngSetup.numPartitions,
+ hsEnc->startBandDec,
+ hsEnc->stopBandDec,
+ hsEnc->partDec,
+ &hsEnc->npartDec,
+ hsEnc->midbandDec,
+ psizeDec,
+ psizeDec_norm,
+ &psizeDec_norm_exp,
+ psize_invDec,
+ 0
+ );
+ IF ( EQ_16(hsEnc->stopFFTbinDec,160))
+ {
+ hsEnc->nFFTpartDec = 17;
+ move16();
+ }
+ ELSE IF ( EQ_16(hsEnc->stopFFTbinDec,256))
+ {
+ hsEnc->nFFTpartDec = 20;
+ move16();
+ }
+ ELSE
+ {
+ hsEnc->nFFTpartDec = 21;
+ move16();
+ }
+
+ SWITCH (hsCom->fftlen)
+ {
+ case 512:
+ hsCom->fftlenShift = 8;
+ move16();
+ hsCom->fftlenFac = 32767/*1.0 Q15*/;
+ move16();
+ BREAK;
+ case 640:
+ hsCom->fftlenShift = 9;
+ move16();
+ hsCom->fftlenFac = 20480/*0.625 Q15*/;
+ move16();
+ BREAK;
+ default:
+ assert(!"Unsupported FFT length for FD-based CNG");
+ BREAK;
+ }
+ BASOP_getTables( &hsCom->olapWinAna, NULL, NULL, shr(hsCom->fftlen, 1));
+ BASOP_getTables( &hsCom->olapWinSyn, NULL, NULL, shr(hsCom->fftlen, 2));
+ hsCom->frameSize = shr( hsCom->fftlen, 1 );
+
+}
+
+/**************************************
+* Delete the instance of type FD_CNG *
+**************************************/
+void deleteFdCngEnc_fx(HANDLE_FD_CNG_ENC_FX * hFdCngEnc)
+{
+
+ HANDLE_FD_CNG_ENC_FX hsEnc;
+ hsEnc = *hFdCngEnc;
+ move16();
+ IF (hsEnc != NULL)
+ {
+ deleteFdCngCom(&(hsEnc->hFdCngCom));
+ free(hsEnc);
+ *hFdCngEnc = NULL;
+ move16();
+ }
+}
+
+
+void resetFdCngEnc_fx(
+ Encoder_State_fx * st
+)
+{
+ Word16 tmpTest;
+ Word16 n;
+ Word16 totalNoiseIncrease;
+ Word16 thresh = 5 * 256; /* 5.0 in Q8 */
+ NOISE_EST_HANDLE hNoiseEst = st->hNoiseEst;
+
+ /* st->totalNoise_fx; Q8 Noise estimator - total noise energy */
+
+ /* Detect fast increase of totalNoise */
+ totalNoiseIncrease = sub(hNoiseEst->totalNoise_fx, st->last_totalNoise_fx);
+ st->last_totalNoise_fx = hNoiseEst->totalNoise_fx;
+ move16();
+ IF ( totalNoiseIncrease > 0 )
+ {
+ IF ( EQ_16(st->totalNoise_increase_len_fx,TOTALNOISE_HIST_SIZE))
+ {
+ FOR ( n = 0; n < TOTALNOISE_HIST_SIZE-1; n++ )
+ {
+ st->totalNoise_increase_hist_fx[n] = st->totalNoise_increase_hist_fx[n+1];
+ move16();
+ }
+ st->totalNoise_increase_hist_fx[TOTALNOISE_HIST_SIZE-1] = totalNoiseIncrease;
+ move16();
+ }
+ ELSE
+ {
+ st->totalNoise_increase_hist_fx[st->totalNoise_increase_len_fx] = totalNoiseIncrease;
+ move16();
+ st->totalNoise_increase_len_fx = add(st->totalNoise_increase_len_fx, 1);
+ }
+ }
+ ELSE
+ {
+ st->totalNoise_increase_len_fx = 0;
+ move16();
+ }
+ totalNoiseIncrease = 0;
+ move16();
+ FOR ( n = 0; n < st->totalNoise_increase_len_fx; n++ )
+ {
+ totalNoiseIncrease = add(totalNoiseIncrease, st->totalNoise_increase_hist_fx[n]);
+ }
+
+ test();
+ test();
+ tmpTest = ((GT_16 (totalNoiseIncrease,thresh) ) && (EQ_16(st->totalNoise_increase_len_fx,TOTALNOISE_HIST_SIZE)) && (GT_16(st->ini_frame_fx,150)) );
+
+ test();
+ IF ( tmpTest || ( GT_16(st->input_bwidth_fx,st->last_input_bwidth_fx) ) || EQ_16(st->last_core_fx,AMR_WB_CORE))
+ {
+ st->fd_cng_reset_flag = 1;
+ move16();
+ st->hFdCngEnc_fx->hFdCngCom->msFrCnt_init_counter = 0;
+ move16();
+ st->hFdCngEnc_fx->hFdCngCom->init_old = 32767;
+ move16();
+ }
+ ELSE IF ( s_and((st->fd_cng_reset_flag > 0),(Word16)(LT_16(st->fd_cng_reset_flag,10))))
+ {
+ st->fd_cng_reset_flag = add(st->fd_cng_reset_flag,1);
+ }
+ ELSE
+ {
+ st->fd_cng_reset_flag = 0;
+ move16();
+ }
+}
+
+/*
+ perform_noise_estimation_enc_fx
+
+ Parameters:
+
+ band_energies i: energy in critical bands without minimum noise floor MODE2_E_MIN
+ band_energies_exp i: exponent for energy in critical bands without minimum noise floor MODE2_E_MIN
+ cldfbBufferReal, i: real part of the CLDFB buffer
+ cldfbBufferImag, i: imaginary part of the CLDFB buffer
+ cldfbBufferExp, i: exponent for CLDFB buffer
+ bitrate i: bitrate
+ st i/o: FD_CNG structure containing all buffers and variables
+
+ Function:
+ Perform noise estimation
+
+ Returns:
+ void
+*/
+void perform_noise_estimation_enc_fx(Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */
+ Word16 band_energies_exp, /* i: exponent for energy in critical bands without minimum noise floor MODE2_E_MIN */
+ Word32 *enerBuffer,
+ Word16 enerBuffer_exp,
+ HANDLE_FD_CNG_ENC_FX st /* i/o: FD_CNG structure containing all buffers and variables */
+ )
+{
+ Word16 i, j, s, s1, s2;
+ Word16 nFFTpart;
+ Word16 nCLDFBpart;
+ Word16 numBands;
+ Word16 numCoreBands;
+ Word16 regularStopBand;
+ Word16 numSlots;
+ Word32 tmp;
+ Word32 *periodog;
+ Word32 *ptr_per;
+ Word32 *msPeriodog;
+
+
+
+ nFFTpart = st->hFdCngCom->nFFTpart;
+ move16();
+ nCLDFBpart = st->hFdCngCom->nCLDFBpart;
+ move16();
+ numCoreBands = st->hFdCngCom->numCoreBands;
+ move16();
+ regularStopBand = st->hFdCngCom->regularStopBand;
+ move16();
+ numSlots = st->hFdCngCom->numSlots;
+ move16();
+ periodog = st->hFdCngCom->periodog;
+ move16();
+ ptr_per = periodog;
+ move16();
+ msPeriodog = st->msPeriodog;
+ move16();
+
+ assert(numSlots == 16);
+
+ /* preemphasis compensation and grouping of per bin energies into msPeriodog */
+ FOR (i=0; i < nFFTpart; i++)
+ {
+ tmp = L_add(L_shr(band_energies[i], 1), L_shr(band_energies[i+NB_BANDS], 1));
+ msPeriodog[i] = Mpy_32_16_1(tmp, preemphCompensation_fx[i]);
+ move32();
+ }
+
+ /* exponent for fft part of msPeriodog */
+ st->msPeriodog_exp_fft = add(band_energies_exp, PREEMPH_COMPENSATION_EXP);
+ move16();
+
+ numBands = sub(regularStopBand, numCoreBands);
+
+ IF ( numBands > 0 )
+ {
+ /* Adjust to the desired time resolution by averaging the periodograms over the CLDFB time slots */
+
+ FOR (j=numCoreBands; j < regularStopBand; j++)
+ {
+ *ptr_per = Mpy_32_16_1(enerBuffer[j], st->hFdCngCom->scalingFactor);
+ move32();
+
+ ptr_per++;
+ }
+
+ /* exponent for cldfb part of msPeriodog */
+ st->hFdCngCom->exp_cldfb_periodog = add( sub(enerBuffer_exp, 4), CLDFBscalingFactor_EXP );
+
+ /* Adjust CLDFB filterbank to the desired frequency resolution by averaging over spectral partitions for SID transmission */
+ bandcombinepow (
+ periodog,
+ st->hFdCngCom->exp_cldfb_periodog,
+ numBands,
+ st->hFdCngCom->CLDFBpart,
+ st->hFdCngCom->nCLDFBpart,
+ st->hFdCngCom->CLDFBpsize_inv,
+ &msPeriodog[nFFTpart],
+ &st->msPeriodog_exp_cldfb
+ );
+
+ /* find common exponent for fft part and cldfb part of msperiodog */
+ s1 = getScaleFactor32 (msPeriodog,nFFTpart);
+ s2 = getScaleFactor32 (&msPeriodog[nFFTpart],nCLDFBpart);
+
+ s = s_max(sub(st->msPeriodog_exp_fft,s1), sub(st->msPeriodog_exp_cldfb,s2));
+ s1 = sub(s,st->msPeriodog_exp_fft);
+ s2 = sub(s,st->msPeriodog_exp_cldfb);
+
+ st->msPeriodog_exp_fft = s;
+ move16();
+ st->msPeriodog_exp_cldfb = s;
+ move16();
+
+ FOR (i=0; i < nFFTpart; i++)
+ {
+ msPeriodog[i] = L_shr(msPeriodog[i],s1);
+ move32();
+ }
+
+ FOR (i=0; i < nCLDFBpart; i++)
+ {
+ msPeriodog[nFFTpart+i] = L_shr(msPeriodog[nFFTpart+i],s_min(31,s2));
+ move32();
+ }
+ }
+
+ /* exponent for entire msPeriodog vector */
+ st->msPeriodog_exp = st->msPeriodog_exp_fft;
+ move16();
+
+ /* Compress MS inputs */
+ compress_range(st->msPeriodog, st->msPeriodog_exp, st->msLogPeriodog, st->hFdCngCom->npart);
+
+ /* Call the minimum statistics routine for noise estimation */
+ minimum_statistics (
+ st->hFdCngCom->npart,
+ st->hFdCngCom->nFFTpart,
+ st->hFdCngCom->psize_norm,
+ st->msLogPeriodog,
+ st->msNoiseFloor,
+ st->msLogNoiseEst,
+ st->msAlpha,
+ st->msPsd,
+ st->msPsdFirstMoment,
+ st->msPsdSecondMoment,
+ st->msMinBuf,
+ st->msBminWin,
+ st->msBminSubWin,
+ st->msCurrentMin,
+ st->msCurrentMinOut,
+ st->msCurrentMinSubWindow,
+ st->msLocalMinFlag,
+ st->msNewMinFlag,
+ st->msPeriodogBuf,
+ &(st->msPeriodogBufPtr),
+ st->hFdCngCom
+ );
+
+ /* Expand MS outputs */
+ expand_range(st->msLogNoiseEst, st->msNoiseEst, &st->msNoiseEst_exp, st->hFdCngCom->npart);
+
+
+}
+
+/*
+ AdjustFirstSID_fx
+
+ Parameters:
+
+ npart i : number of parts
+ msPeriodog i : pointer to periodog vector
+ msPeriodog_exp i : exponent of periodog vector
+ energy_ho i/o : pointer to energy
+ energy_ho_exp i/o : pointer to exponent of energy
+ msNoiseEst i/o : pointer to estimated noise
+ msNoiseEst_exp i/o : pointer to exponent of estimated noise
+ msNoiseEst_old i/o : pointer to old estimated noise
+ msNoiseEst_old_exp i/o : pointer to exponent of old estimated noise
+ active_frame_counter i/o : pointer to active frame counter
+ stcod i : pointer to Coder_State structure
+
+ Function:
+ Adjust the noise estimator at the beginning of each CNG phase (encoder-side)
+
+ Returns:
+ void
+*/
+Word16
+AdjustFirstSID_fx(
+ Word16 npart, /* i : number of parts */
+ Word32 *msPeriodog, /* i : pointer to periodog vector */
+ Word16 msPeriodog_exp, /* i : exponent of periodog vector */
+ Word32 *energy_ho, /* i/o : pointer to energy */
+ Word16 *energy_ho_exp, /* i/o : pointer to exponent of energy */
+ Word32 *msNoiseEst, /* i/o : pointer to estimated noise */
+ Word16 *msNoiseEst_exp, /* i/o : pointer to exponent of estimated noise */
+ Word32 *msNoiseEst_old, /* i/o : pointer to old estimated noise */
+ Word16 *msNoiseEst_old_exp, /* i/o : pointer to exponent of old estimated noise */
+ Word16 *active_frame_counter, /* i/o : pointer to active frame counter */
+ Encoder_State_fx *stcod /* i : pointer to Coder_State_Plus structure */
+)
+{
+ Word16 i, sc, s1, s2, lambda, lambdaM1, invFac;
+ Word32 tmp32, energy_ho_local, msNoiseEst_local;
+ DTX_ENC_HANDLE hDtxEnc = stcod->hDtxEnc;
+
+ test();
+ IF ( EQ_16(hDtxEnc->cnt_SID,1)&>_32(stcod->last_core_brate_fx,SID_2k40))
+ {
+ /* Detect the hangover period and the first SID frame at the beginning of each CNG phase */
+
+ /* First hangover frame */
+ Copy32 (msPeriodog, energy_ho, npart);
+ *energy_ho_exp = msPeriodog_exp;
+ move16();
+
+ /* Set first SID to current input level but add some smoothing */
+ IF ( GE_16(*active_frame_counter,254))
+ {
+ lambda = 0;
+ move16();
+ lambdaM1 = 0x7FFF;
+ move16();
+ }
+ ELSE
+ {
+ /* -0.94229902485 = 1024.0*log10(0.96)/log10(2.0)/64.0 */
+ /* active_frame_counter scaled by (1/1024.0) for compensation */
+ tmp32 = L_shl(L_deposit_l(add(*active_frame_counter, 1)), WORD32_BITS-1-10);
+ tmp32 = BASOP_Util_InvLog2(Mpy_32_16_1(tmp32, -30877/*-0.94229902485 Q15*/));
+ lambda = extract_h(tmp32);
+ lambdaM1 = extract_h(L_sub(0x7FFFFFFF, tmp32));
+ }
+
+ invFac = getNormReciprocalWord16(1);
+
+ /* one bit headroom for addition */
+ sc = add(s_max(*msNoiseEst_old_exp, *energy_ho_exp), 1);
+ s1 = limitScale32(sub(sc, *msNoiseEst_old_exp));
+ s2 = limitScale32(sub(sc, *energy_ho_exp));
+ *energy_ho_exp = sc;
+ move16();
+
+ FOR (i=0; i 0 )
+ {
+ tmp32 = 1;
+ move32();
+ }
+ }
+ /* Set exponent to zero if msNoiseEst is zero */
+ if ( tmp32==0 )
+ {
+ *msNoiseEst_exp = 0;
+ move16();
+ }
+
+ *active_frame_counter = 0;
+ move16();
+ }
+ test();
+ IF ( NE_32(stcod->core_brate_fx,SID_2k40)&&NE_32(stcod->core_brate_fx,FRAME_NO_DATA))
+ {
+ /* Count the number of active frames in a row */
+ *active_frame_counter = add(*active_frame_counter, 1);
+ move16();
+ }
+ ELSE
+ {
+ /* Store the noise estimate obtained in the CNG phases */
+ Copy32 (msNoiseEst, msNoiseEst_old, npart);
+ *msNoiseEst_old_exp = *msNoiseEst_exp;
+ move16();
+
+ }
+
+
+ return 0;
+}
+
+
+/*
+ msvq_encoder
+
+ Parameters:
+
+ cb i : Codebook (indexed cb[stages][levels][p]) format Q9.7
+ u[] i : Vector to be encoded (prediction and mean removed) format Q9.7
+ levels i : Number of levels in each stage
+ maxC i : Tree search size
+ stages i : Number of stages
+ N i : Vector dimension
+ maxN i : Codebook vector dimension
+ Idx o : Indices
+
+
+ Function:
+ multi stage vector quantisation
+
+ Returns:
+ void
+*/
+static void msvq_encoder (const Word16 * const cb[], /* i : Codebook (indexed cb[*stages][levels][p]) scaled with 8 bits */
+ Word16 u[], /* i : Vector to be encoded (prediction and mean removed) */
+ const Word16 levels[], /* i : Number of levels in each stage */
+ Word16 maxC, /* i : Tree search size */
+ Word16 stages, /* i : Number of stages */
+ Word16 N, /* i : Vector dimension */
+ Word16 maxN, /* i : Codebook vector dimension */
+ Word16 Idx[] /* o : Indices */
+ )
+{
+ Word32 *dist[2];
+ Word32 t1, en, ss2, tmp;
+ const Word16 *cbp, *cb_stage, *p2;
+ Word16 *p1, *pTmp;
+ Word16 *indices[2], *resid[2], Tmp[M_MAX];
+ Word16 i, j, m, s, c, c2, p_max;
+ Word16 parents[MBEST_MAX];
+ Word32 dist_buf[2*MBEST_MAX];
+ Word16 resid_buf[2*MBEST_MAX*M_MAX];
+ Word16 idx_buf[2*MBEST_MAX*NSTAGES_MAX];
+
+
+
+ /*----------------------------------------------------------------*
+ * Allocate memory for previous (parent) and current nodes.
+ * Parent node is indexed [0], current node is indexed [1].
+ *----------------------------------------------------------------*/
+
+ indices[0] = idx_buf;
+ indices[1] = idx_buf + maxC*stages;
+ set16_fx(idx_buf, 0, 2*stages*maxC);
+
+ resid[0] = resid_buf;
+ resid[1] = resid_buf + maxC*N;
+
+ dist[0] = dist_buf;
+ dist[1] = dist_buf + maxC;
+
+ set16_fx(parents, 0, maxC);
+
+ /*----------------------------------------------------------------*
+ * ISF weights are normalized, so it is always better to multiply it first
+ * Set up inital distance vector
+ *----------------------------------------------------------------*/
+
+ ss2 = L_mult(u[0], u[0]);
+ FOR (j=1; j < N; j++)
+ {
+ ss2 = L_mac(ss2, u[j], u[j]);
+ }
+
+ FOR (j=0; j < maxC; j++)
+ {
+ dist[1][j] = ss2;
+ move32();
+ }
+
+ /* Set up inital error (residual) vectors */
+ pTmp = resid[1];
+ FOR (c=0; chBstr;
+ HANDLE_FD_CNG_COM st;
+ Word16 maxC_37bits = FD_CNG_maxC_37bits, stages_37bits = FD_CNG_stages_37bits, maxN_37bits = FD_CNG_maxN_37bits;
+#ifdef IVAS_CODE_CNG
+ float* invTrfMatrix;
+ float tmpRAM[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC];
+ float dct_target[FDCNG_VQ_DCT_MAXTRUNC];
+ float tot_sig_ext[FDCNG_VQ_MAX_LEN];
+ const float gain_q_offset = (st->element_mode == EVS_MONO) ? GAIN_Q_OFFSET_EVS : GAIN_Q_OFFSET_IVAS;
+ /* Init */
+ N = hFdCngEnc->npartDec;
+
+ invTrfMatrix = (float*)tmpRAM; /* dynamically filled */
+ set_zero(v, FDCNG_VQ_MAX_LEN);
+#endif
+
+
+ /* Init */
+ st = stenc->hFdCngCom;
+
+ E_Exp = stenc->msNoiseEst_exp;
+ move16();
+ E_ExpLd64 = L_shl(E_Exp, WORD32_BITS-1-LD_DATA_SCALE);
+ E = stenc->msNoiseEst;
+
+ N = stenc->npartDec;
+ move16();
+
+ normFacN = getNormReciprocalWord16(N);
+ normShiftN = BASOP_util_norm_s_bands2shift(N);
+
+ normFacGain = getNormReciprocalWord16(N_GAIN_MAX-N_GAIN_MIN);
+ normShiftGain = BASOP_util_norm_s_bands2shift(N_GAIN_MAX-N_GAIN_MIN);
+
+ /* Convert to LOG */
+
+ /* e: Q14.23 format, v: Q9.23 format */
+ e = L_deposit_l(0);
+ tmp = Mpy_32_32_r(L_shl(1, sub(31, E_Exp)), 214748); /* 1e-4f, Q31-E_Exp */
+ FOR (i=0; ielement_mode != EVS_MONO)
+ {
+ /* DCT domain compressed/truncated indices used for first stage */
+ /* quantization with stage1 stored in DCT24 domain, stages 2 through 6 directly dearched
+ in FDCNG band domain
+ */
+ if (N == FDCNG_VQ_MAX_LEN_WB)
+ {
+ create_IDCT_N_Matrix(invTrfMatrix, N, FDCNG_VQ_DCT_MAXTRUNC, sizeof(tmpRAM) / (sizeof(float)));
+ /* truncated DCT21 analysis */
+ dctT2_N_apply_matrix((const float*)v, dct_target, FDCNG_VQ_DCT_MAXTRUNC, N, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, DCT_T2_21_XX);
+ /* truncated IDCT21 extension to 24 bands */
+ extend_dctN_input(v, dct_target, N, tot_sig_ext, FDCNG_VQ_MAX_LEN, invTrfMatrix, FDCNG_VQ_DCT_MAXTRUNC, IDCT_T2_XX_21);
+
+ mvr2r(tot_sig_ext, v, FDCNG_VQ_MAX_LEN); /* write extended result as input to VQ stage #1 */
+ }
+ create_IDCT_N_Matrix(invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof(tmpRAM) / (sizeof(float)));
+ msvq_enc_fx(cdk_37bits_ivas, NULL, NULL, v, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, w, N, FD_CNG_maxN_37bits, 1, invTrfMatrix, indices);
+ msvq_dec(cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N, FD_CNG_maxN_37bits, indices, 1, invTrfMatrix, v, NULL);
+ }
+ ELSE
+#endif
+ {
+ /* MSVQ encoder */
+ msvq_encoder(cdk_37bits, v16, levels_37bits, maxC_37bits, stages_37bits, N, maxN_37bits, indices );
+
+ /* MSVQ decoder */
+ msvq_decoder(cdk_37bits, stages_37bits, N, maxN_37bits, indices, v16);
+ }
+ FOR (i=0; ielement_mode > EVS_MONO)
+ {
+ apply_scale(&gain, hFdCngCom->CngBandwidth, hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO);
+ }
+ else
+#endif
+ {
+ apply_scale(&gain, st->CngBandwidth, st->CngBitrate, scaleTableMono, SIZE_SCALE_TABLE_MONO);
+ }
+
+#ifdef IVAS_CODE_CNG
+ /* Quantize gain, Q14.23 format */
+ gain = L_add(gain, L_shr(gain, 1));
+ gain = L_add(gain, gain_q_offset/*gain_q_offset+.5 Q23*/);
+ index = extract_l(L_shr(gain, WORD32_BITS - 1 - 8));
+#else
+ /* Quantize gain, Q14.23 format */
+ gain = L_add(gain, L_shr(gain,1));
+ gain = L_add(gain, 507510784l/*60.5 Q23*/);
+ index = extract_l(L_shr(gain,WORD32_BITS-1-8));
+#endif
+
+ if ( index < 0 )
+ {
+ index = 0;
+ move16();
+ }
+
+ if ( GT_16(index,127))
+ {
+ index = 127;
+ move16();
+ }
+#ifndef IVAS_CODE_CNG
+ /* gain Q14.23 format */
+ gain = L_shl(L_deposit_l(index), WORD32_BITS - 1 - 8);
+ gain = L_sub(gain, 503316480l/*60.0 Q23*/);
+ gain = Mpy_32_16_1(gain, 21845/*2.0f/3.0f Q15*/);
+#else
+ /* gain Q14.23 format */
+ gain = L_shl(L_deposit_l(index), WORD32_BITS-1-8);
+ gain = L_sub(gain, gain_q_offset/*60.0 Q23*/);
+ gain = Mpy_32_16_1(gain, 21845/*2.0f/3.0f Q15*/);
+#endif
+
+ /* Apply gain and undo log */
+
+ /* sidNoiseEst: format Q6.26, 0.66438561897 = log10(10)/log10(2.0) / 10.0 * 2.0 */
+
+ /* calculate worst case for scaling */
+ maxVal = 0x80000000/*-1.0 Q31*/;
+ move32();
+ FOR (i=0; i= 0)
+ {
+ maxVal = L_sub(maxVal, 33554432l/*0.015625 Q31*/);
+ sidNoiseEst_Exp = add(sidNoiseEst_Exp,1);
+ }
+ st->sidNoiseEstExp = sidNoiseEst_Exp;
+ move16();
+ E_ExpLd64 = L_shl(sidNoiseEst_Exp, WORD32_BITS-1-LD_DATA_SCALE);
+
+ FOR (i=0; isidNoiseEst[i] = BASOP_Util_InvLog2(tmp);
+ move32();
+ }
+
+ /* NB last band energy compensation */
+ IF ( EQ_16(st->CngBandwidth,NB))
+ {
+ st->sidNoiseEst[N-1] = Mpy_32_16_1(st->sidNoiseEst[N-1], NB_LAST_BAND_SCALE);
+ move32();
+ }
+
+ test();
+ if (EQ_16( st->CngBandwidth,SWB)&&LE_32(st->CngBitrate,ACELP_13k20))
+ {
+ st->sidNoiseEst[N-1] = Mpy_32_16_1(st->sidNoiseEst[N-1], SWB_13k2_LAST_BAND_SCALE);
+ move32();
+ }
+
+
+ /* Write bitstream */
+ IF ( EQ_16(corest->codec_mode, MODE2))
+ {
+ FOR (i=0; ibwidth_fx, 2 );
+ IF (EQ_16(corest->L_frame_fx, L_FRAME16k))
+ {
+ push_indice_fx( hBstr, IND_ACELP_16KHZ, 1, 1 );
+ }
+ ELSE
+ {
+ push_indice_fx( hBstr, IND_ACELP_16KHZ, 0, 1 );
+ }
+ FOR (i=0; i cngNoiseLevel: Q6.26 format */
+ scalebands(st->sidNoiseEst, stenc->partDec, stenc->npartDec, stenc->midbandDec, stenc->nFFTpartDec, sub(stenc->stopBandDec,stenc->startBandDec), st->cngNoiseLevel, 1);
+ st->cngNoiseLevelExp = st->sidNoiseEstExp;
+ move16();
+
+
+ lpc_from_spectrum(st, stenc->startBandDec, stenc->stopFFTbinDec, preemph_fac );
+
+
+}
+
+
+void generate_comfort_noise_enc_fx(Encoder_State_fx *stcod,
+ Word16 Q_new,
+ Word16 gen_exc
+ )
+{
+ Word16 i, s, sn, cnt;
+ Word16 startBand2;
+ Word16 stopFFTbin2;
+ Word16 preemph_fac;
+ Word32 sqrtNoiseLevel;
+ Word16 randGaussExp;
+ Word16 fftBufferExp;
+ Word16 cngNoiseLevelExp;
+ Word16 *seed;
+ Word16 *timeDomainOutput;
+ Word32 *ptr_r, *ptr_i;
+ Word32 *cngNoiseLevel;
+ Word32 *ptr_level;
+ Word32 *fftBuffer;
+ Word16 old_syn_pe_tmp[16];
+ Word16 tcx_transition = 0;
+ HANDLE_FD_CNG_ENC_FX stenc = stcod->hFdCngEnc_fx;
+ HANDLE_FD_CNG_COM st = stenc->hFdCngCom;
+ DTX_ENC_HANDLE hDtxEnc = stcod->hDtxEnc;
+ TD_CNG_ENC_HANDLE hTdCngEnc = stcod->hTdCngEnc;
+
+ LPD_state_HANDLE hLPDmem = stcod->hLPDmem;
+ TCX_ENC_HANDLE hTcxEnc = stcod->hTcxEnc;
+
+ /* Warning fix */
+ s = 0;
+
+ /* pointer initialization */
+
+ cngNoiseLevel = st->cngNoiseLevel;
+ cngNoiseLevelExp = st->cngNoiseLevelExp;
+ ptr_level = cngNoiseLevel;
+ seed = &(st->seed);
+ fftBuffer = st->fftBuffer;
+ timeDomainOutput = st->timeDomainBuffer;
+
+ /*
+ Generate Gaussian random noise in real and imaginary parts of the FFT bins
+ Amplitudes are adjusted to the estimated noise level cngNoiseLevel in each bin
+ scaling Gaussian random noise: format Q3.29
+ */
+ sn = 0;
+ move16();
+ IF ( s_and(cngNoiseLevelExp,1) != 0 )
+ {
+ sn = add(sn,1);
+ cngNoiseLevelExp = add(cngNoiseLevelExp,sn);
+ move16();
+ }
+
+ randGaussExp = CNG_RAND_GAUSS_SHIFT;
+ move16();
+ cnt = sub(stenc->stopFFTbinDec, stenc->startBandDec);
+ IF ( stenc->startBandDec == 0 )
+ {
+ /* DC component in FFT */
+ s = 0;
+ move16();
+ sqrtNoiseLevel = Sqrt32(L_shr(*ptr_level,sn), &s);
+
+ fftBuffer[0] = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s);
+ move32();
+
+ /* Nyquist frequency is discarded */
+ fftBuffer[1] = L_deposit_l(0);
+
+ ptr_level = ptr_level + 1;
+ ptr_r = fftBuffer + 2;
+ cnt = sub(cnt, 1);
+ }
+ ELSE
+ {
+ startBand2 = shl(stenc->startBandDec,1);
+ set32_fx(fftBuffer, 0, startBand2);
+ ptr_r = fftBuffer + startBand2;
+ }
+
+ sn = add(sn,1);
+ ptr_i = ptr_r + 1;
+ FOR (i=0; i < cnt; i++)
+ {
+ s = 0;
+ move16();
+ sqrtNoiseLevel = Sqrt32(L_shr(*ptr_level,sn), &s);
+
+ /* Real part in FFT bins */
+ *ptr_r = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s);
+ move32();
+
+ /* Imaginary part in FFT bins */
+ *ptr_i = L_shl(Mpy_32_32(rand_gauss(seed),sqrtNoiseLevel),s);
+ move32();
+
+ ptr_r = ptr_r + 2;
+ ptr_i = ptr_i + 2;
+ ptr_level = ptr_level + 1;
+ }
+
+ /* Remaining FFT bins are set to zero */
+ stopFFTbin2 = shl(stenc->stopFFTbinDec,1);
+ set32_fx(fftBuffer+stopFFTbin2, 0, sub(st->fftlen,stopFFTbin2));
+
+ fftBufferExp = add(shr(cngNoiseLevelExp,1),randGaussExp);
+
+ /* If previous frame is active, reset the overlap-add buffer */
+ IF ( GT_32(stcod->last_core_brate_fx,SID_2k40))
+ {
+ set16_fx(st->olapBufferSynth, 0, st->fftlen);
+ test();
+ test();
+ IF ( (GT_32(stcod->last_core_fx,ACELP_CORE)&&EQ_16(stcod->codec_mode,MODE2))||EQ_16(stcod->codec_mode,MODE1))
+ {
+ tcx_transition = 1;
+ move16();
+ }
+ }
+
+ /* Perform STFT synthesis */
+ SynthesisSTFT (fftBuffer, fftBufferExp, timeDomainOutput, st->olapBufferSynth, st->olapWinSyn,
+ tcx_transition,st, gen_exc, &Q_new, -1, -1);
+ {
+ Word32 Lener, att;
+ Word16 exp;
+ /* update CNG excitation energy for LP_CNG */
+
+ /* calculate the residual signal energy */
+ /*enr = dotp( st->exc_cng, st->exc_cng, st->frameSize ) / st->frameSize;*/
+ Lener = Dot_productSq16HQ(1,st->exc_cng,stcod->L_frame_fx,&exp);
+ exp = add(sub(shl(sub(15,Q_new),1),8),exp); /*8 = log2(256)*/
+
+ /* convert log2 of residual signal energy */
+ /*(float)log10( enr + 0.1f ) / (float)log10( 2.0f );*/
+ Lener = BASOP_Util_Log2(Lener);
+ Lener = L_add(Lener,L_shl(L_deposit_l(exp),WORD32_BITS-1-LD_DATA_SCALE)); /*Q25*/
+ if(EQ_16(stcod->L_frame_fx,L_FRAME16k))
+ {
+ Lener = L_sub(Lener, 10802114l/*0.3219280949f Q25*/); /*log2(320) = 8.3219280949f*/
+ }
+ /* decrease the energy in case of WB input */
+ IF( NE_16(stcod->bwidth_fx, NB))
+ {
+ IF( EQ_16(stcod->bwidth_fx,WB))
+ {
+ IF(hDtxEnc->CNG_mode >= 0 )
+ {
+ /* Bitrate adapted attenuation */
+ att = L_shl(L_deposit_l(ENR_ATT_fx[hDtxEnc->CNG_mode]),17);
+ }
+ ELSE
+ {
+ /* Use least attenuation for higher bitrates */
+ att = L_shl(L_deposit_l(ENR_ATT_fx[4]),17);
+ }
+ }
+ ELSE
+ {
+ att = 384<<17;
+ move32();/*1.5 Q8<<17=Q25*/
+ }
+ Lener = L_sub(Lener, att );
+ }
+ /*stdec->lp_ener = 0.8f * stcod->lp_ener + 0.2f * pow( 2.0f, enr );*/
+ Lener = BASOP_util_Pow2(Lener, 6, &exp);
+ Lener = Mult_32_16(Lener, 6554/*0.2f Q15*/);
+ exp = sub(25,exp);
+ Lener = L_shr(Lener, exp); /*Q6*/
+ hTdCngEnc->lp_ener_fx = L_add(Mult_32_16(hTdCngEnc->lp_ener_fx, 26214/*0.8f Q15*/), Lener); /*Q6*/
+ }
+
+ /* Overlap-add when previous frame is active */
+ test();
+ IF ( ( GT_32(stcod->last_core_brate_fx,SID_2k40))&&(EQ_16(stcod->codec_mode,MODE2)))
+ {
+ Word32 old_exc_ener, gain, noise32;
+ Word16 seed_loc, lpcorder, old_syn, tmp, gain16, N, N2, N4, N8;
+ Word16 old_exc_ener_exp, gain_exp;
+ Word16 normFacE, normShiftE, normShiftEM1;
+ Word16 normFacG, normShiftG, normShiftGM1;
+ Word16 noiseExp, *old_exc, old_Aq[M+1], *old_syn_pe;
+ Word16 noise[640], normShiftP2;
+ Word16 Q_exc, Q_syn;
+
+
+ assert(st->frameSize <= 640);
+
+ seed_loc = st->seed;
+ move16();
+ N = st->frameSize;
+ move16();
+ N2 = shr(st->frameSize,1);
+
+ IF ( GT_16(stcod->last_core_fx,ACELP_CORE))
+ {
+ Word16 left_overlap_mode;
+ left_overlap_mode = stcod->hTcxCfg->tcx_last_overlap_mode;
+ move16();
+ if (EQ_16(left_overlap_mode, ALDO_WINDOW))
+ {
+ left_overlap_mode = FULL_OVERLAP;
+ move16();
+ }
+
+ tcx_windowing_synthesis_current_frame( timeDomainOutput,
+ stcod->hTcxCfg->tcx_mdct_window, /*Keep sine windows for limiting Time modulation*/
+ stcod->hTcxCfg->tcx_mdct_window_half,
+ stcod->hTcxCfg->tcx_mdct_window_minimum,
+ stcod->hTcxCfg->tcx_mdct_window_length,
+ stcod->hTcxCfg->tcx_mdct_window_half_length,
+ stcod->hTcxCfg->tcx_mdct_window_min_length,
+ 0,
+ left_overlap_mode,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ N/2,
+ shr(sub(abs_s(stcod->hTcxCfg->tcx_offset), stcod->hTcxCfg->tcx_offset), 1), /* equivalent to: stdec->hTcxCfg->tcx_offset<0?-stdec->hTcxCfg->tcx_offset:0 */
+ 1,
+ 0,
+ 0
+ );
+
+ IF (stcod->hTcxCfg->last_aldo != 0)
+ {
+ FOR (i=0; iframeSize; i++)
+ {
+ timeDomainOutput[i] = add(timeDomainOutput[i], shr_r(hTcxEnc->old_out_fx[i+NS2SA(stcod->sr_core, N_ZERO_MDCT_NS)], hTcxEnc->Q_old_out));
+ move16();
+ }
+ }
+ ELSE
+ {
+ tcx_windowing_synthesis_past_frame(hTcxEnc->Txnq,
+ stcod->hTcxCfg->tcx_aldo_window_1_trunc,
+ stcod->hTcxCfg->tcx_mdct_window_half,
+ stcod->hTcxCfg->tcx_mdct_window_minimum,
+ stcod->hTcxCfg->tcx_mdct_window_length,
+ stcod->hTcxCfg->tcx_mdct_window_half_length,
+ stcod->hTcxCfg->tcx_mdct_window_min_length,
+ stcod->hTcxCfg->tcx_last_overlap_mode
+ );
+
+ FOR (i=0; iTxnq[i],TCX_IMDCT_HEADROOM));
+ move16();
+ }
+ }
+ }
+ ELSE
+ {
+
+ /*
+ - the scaling of the LPCs (e.g. old_Aq) is always Q12 (encoder or decoder)
+
+ - the scaling of the deemphasized signals (e.g. old_syn) is always Q0 (encoder or decoder)
+
+ - the scaling of the excitation signals in the encoder (e.g. old_exc) is Q_new
+ - the scaling of the preemphasized signals in the encoder (e.g. old_syn_pe) is Q_new-1
+
+ - the scaling of the excitation signals in the decoder (e.g. old_exc) is Q_exc (or stdec->Q_exc)
+ - the scaling of the preemphasized signals in the decoder (e.g. old_syn_pe) is Q_syn (or stdec->Q_syn)
+ */
+
+ lpcorder = M;
+ move16();
+ E_LPC_f_lsp_a_conversion(stcod->lsp_old_fx, old_Aq, M);
+ old_exc = hLPDmem->old_exc+sub(L_EXC_MEM,N2);
+ old_syn_pe = hLPDmem->mem_syn2;
+ old_syn = hLPDmem->syn[lpcorder];
+ move16();
+ preemph_fac = stcod->preemph_fac;
+ move16();
+ Q_exc = Q_new;
+ Q_syn = sub(Q_new,1);
+
+ /* shift to be in the range of values supported by getNormReciprocalWord16() */
+ N8 = shr(N2, CNG_NORM_RECIPROCAL_RANGE_SHIFT);
+
+ assert( N2 == (N8<olapWinSyn[i].v.re);
+ timeDomainOutput[i] = add(timeDomainOutput[i],tmp);
+ move16();
+ tmp = mult(noise[i+N4],st->olapWinSyn[N4-1-i].v.im);
+ timeDomainOutput[i+N4] = add(timeDomainOutput[i+N4],tmp);
+ move16();
+ }
+ }
+ }
+
+}
+
+/*-------------------------------------------------------------------*
+ * cng_energy_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+
+ /*! r: CNG energy */
+Word16 cng_energy_fx(
+ const Word16 element_mode, /* i : element mode */
+ const Word16 bwidth, /* i : audio bandwidh */
+ const Word16 CNG_mode, /* i : mode for DTX configuration */
+ const Word16 CNG_att, /* i : attenuation factor for CNG */
+ const Word16* exc, /* i : input signal */
+ const Word16 len, /* i : vector length */
+ const Word16 Q_new /* i : Input scaling */
+)
+{
+ Word16 i, maxv, scale;
+ Word16 hi, lo, enr, tmp16, att;
+ const Word16* pt_res;
+ Word32 L_ener, L_tmp;
+
+ maxv = 0;
+ move16();
+ FOR(i = 0; i < len; i++)
+ {
+ maxv = s_max(maxv, abs_s(exc[i]));
+ }
+ scale = norm_s(maxv);
+ pt_res = exc;
+ L_ener = L_deposit_l(1);
+ IF(EQ_16(len, L_FRAME))
+ {
+ FOR(i = 0; i < 128; i++)
+ {
+ tmp16 = shl(*pt_res, scale);
+ L_tmp = L_mult0(tmp16, tmp16);
+ pt_res++;
+ tmp16 = shl(*pt_res, scale);
+ L_tmp = L_mac0(L_tmp, tmp16, tmp16); /* 2*(Q_new+scale) */
+ pt_res++;
+ L_ener = L_add(L_ener, L_shr(L_tmp, 7)); /* 2*(Q_new+scale)+1, divide by L_frame done here */
+ }
+ }
+ ELSE /* L_FRAME16k */
+ {
+ FOR(i = 0; i < 160; i++)
+ {
+ tmp16 = shl(*pt_res,scale);
+ L_tmp = L_mult0(tmp16, tmp16);
+ pt_res++;
+ tmp16 = shl(*pt_res,scale);
+ L_tmp = L_mac0(L_tmp, tmp16, tmp16); /* 2*(Q_new+scale) */
+ pt_res++;
+ L_ener = L_add(L_ener, L_shr(Mult_32_16(L_tmp,26214 /* 256/320, Q15 */), 7)); /* 2*(Q_new+scale)+15+1-16+1, divide by L_frame done here */
+ }
+ }
+
+ hi = norm_l(L_ener);
+ lo = Log2_norm_lc(L_shl(L_ener, hi));
+ hi = sub(30, add(hi, shl(add(Q_new, scale), 1))); /* log2 exp in Q2*(Q_new+scale) */
+ L_tmp = L_Comp(hi, lo); /* Q16 */
+ enr = round_fx(L_shl(L_tmp, 8)); /* Q8 (16+8-16) */
+
+ /* decrease the energy in case of WB input */
+ test();
+ IF (EQ_16(element_mode, IVAS_CPE_DFT) || EQ_16(element_mode, IVAS_CPE_TD))
+ {
+ //PMT(" IVAS CNG ener computing is missing")
+#ifdef IVAS_CODE
+ enr += CNG_att * FAC_LOG2 / 10.0f;
+#else
+ (void)CNG_att;
+#endif
+ }
+ ELSE IF(NE_16(bwidth, NB))
+ {
+ IF(EQ_16(bwidth, WB))
+ {
+ IF(CNG_mode >= 0)
+ {
+ /* Bitrate adapted attenuation */
+ att = ENR_ATT_fx[CNG_mode];
+ }
+ ELSE
+ {
+ /* Use least attenuation for higher bitrates */
+ att = ENR_ATT_fx[4];
+ }
+ }
+ ELSE
+ {
+ att = 384;
+ move16();/*Q8*/
+ }
+ enr = sub(enr, att);
+ }
+ return enr;
+}
diff --git a/lib_enc/find_tar_fx.c b/lib_enc/find_tar_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..dedc4ff4b145ff4813da586e765d82d1915eab8c
--- /dev/null
+++ b/lib_enc/find_tar_fx.c
@@ -0,0 +1,191 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "cnst.h" /* Common constants */
+#include "basop_util.h"
+#include "stl.h"
+
+
+
+void find_targets_fx(
+ const Word16 *speech, /* i : pointer to the speech frame Q_new-1*/
+ const Word16 *mem_syn, /* i : memory of the synthesis filter Q_new-1*/
+ const Word16 i_subfr, /* i : subframe index */
+ Word16 *mem_w0, /* i/o: weighting filter denominator memory Q_new-1*/
+ const Word16 *p_Aq, /* i : interpolated quantized A(z) filter Q12*/
+ const Word16 *res, /* i : residual signal Q_new*/
+ const Word16 L_subfr, /* i : length of vectors for gain quantization */
+ const Word16 *Ap, /* i : unquantized A(z) filter with bandwidth expansion Q12*/
+ Word16 tilt_fac, /* i : tilt factor Q15 */
+ Word16 *xn, /* o : Close-loop Pitch search target vector Q_new-1*/
+ Word16 *cn, /* o : target vector in residual domain Q_new*/
+ Word16 *h1 /* o : impulse response of weighted synthesis filter */
+)
+{
+ Word16 i;
+ Word16 temp[M+6*L_SUBFR]; /* error of quantization */
+ Word16 scale,scaleq,j,d,s,s2,tmp;
+ Word16 Aqs[M+1];
+ Word32 Ltmp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ /*------------------------------------------------------------------------*
+ * Find the target vector for excitation search:
+ *
+ * |------| res[n]
+ * speech[n]---| A(z) |--------
+ * |------| | |--------| error[n] |------|
+ * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target
+ * exc |--------| |------|
+ *
+ * Instead of subtracting the zero-input response of filters from
+ * the weighted input speech, the above configuration is used to
+ * compute the target vector.
+ *-----------------------------------------------------------------------*/
+ FOR (i=0; i cn[] */
+ temp[0] = 0;
+ move16();
+ preemph_copy_fx(xn, cn, tilt_fac, L_SUBFR/2, temp);
+ syn_filt_s_lc_fx(1, Ap, cn, temp, L_SUBFR/2); /* Q-1 -> Q-2 */
+ Residu3_lc_fx(p_Aq, M, temp, cn, L_SUBFR/2, 1); /* Q-2 -> Q-1 */
+ Scale_sig(cn, L_SUBFR/2,1);
+
+ /* second half: res[] --> cn[] (approximated and faster) */
+ Copy(&res[i_subfr+(L_SUBFR/2)], cn+(L_SUBFR/2), L_SUBFR/2);
+ }
+
+ /*---------------------------------------------------------------*
+ * Compute impulse response, h1[], of weighted synthesis filter *
+ *---------------------------------------------------------------*/
+
+ scale = norm_s( Ap[0] );
+ scaleq = norm_s( p_Aq[0] );
+ d = sub( scaleq, scale );
+ IF ( d >= 0 )
+ {
+ Copy( p_Aq, Aqs, M+1 );
+ s = add( scaleq, 1 );
+ s2 = shr( 16384, d );
+ }
+ ELSE
+ {
+ Copy_Scale_sig( p_Aq, Aqs, M+1, d );
+ s = add( scale, 1 );
+ s2 = 16384;
+ }
+ Overflow = 0;
+ move16();
+ FOR (i = 0; i < M; i++)
+ {
+ Ltmp = L_mult(Ap[i], s2);
+ FOR (j = 1; j <= i; j++)
+ {
+#ifdef BASOP_NOGLOB /* Critical Overflow , as well as those below*/
+ Ltmp = L_msu_o(Ltmp, Aqs[j], h1[i - j], &Overflow);
+#else
+ Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]);
+#endif
+ }
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ h1[i] = round_fx_o(L_shl_o(Ltmp, s, &Overflow), &Overflow);
+#else
+ h1[i] = round_fx(L_shl(Ltmp, s));
+#endif
+ }
+ Ltmp = L_mult(Ap[i], s2);
+ FOR (j = 1; j <= M; j++)
+ {
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ Ltmp = L_msu_o(Ltmp, Aqs[j], h1[i-j], &Overflow);
+#else
+ Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]);
+#endif
+ }
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ h1[M] = round_fx_o(L_shl_o(Ltmp, s, &Overflow), &Overflow);
+#else
+ h1[M] = round_fx(L_shl(Ltmp, s));
+#endif
+
+//PMT("should we used extended basop here for when the L_subfr > L_SUBFR, to prevent saturation/overflow and the subsequent loop\n")
+ FOR (i=M+1; i < L_subfr; i++)
+ {
+ Ltmp = L_msu(0, Aqs[1], h1[i-1]);
+ FOR (j = 2; j <= M; j++)
+ {
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ Ltmp = L_msu_o(Ltmp, Aqs[j], h1[i-j], &Overflow);
+#else
+ Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]);
+#endif
+ }
+#ifdef BASOP_NOGLOB /* Critical Overflow */
+ h1[i] = round_fx_o(L_shl_o(Ltmp, s, &Overflow), &Overflow);
+#else
+ h1[i] = round_fx(L_shl(Ltmp, s));
+#endif
+ }
+ IF(Overflow)
+ {
+ s2 = shr(s2, 1);
+ FOR (i = 0; i < M; i++)
+ {
+ Ltmp = L_mult(Ap[i], s2);
+ FOR (j = 1; j <= i; j++)
+ {
+ Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]);
+ }
+#ifdef BASOP_NOGLOB
+ h1[i] = round_fx(L_shl_o(Ltmp, s, &Overflow));
+#else
+ h1[i] = round_fx(L_shl(Ltmp, s));
+#endif
+ }
+ Ltmp = L_mult(Ap[i], s2);
+ FOR (j = 1; j <= M; j++)
+ {
+ Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]);
+ }
+ h1[M] = round_fx(L_shl(Ltmp, s));
+ FOR (i=M+1; i < L_subfr; i++)
+ {
+ Ltmp = L_msu(0, Aqs[1], h1[i-1]);
+ FOR (j = 2; j <= M; j++)
+ {
+ Ltmp = L_msu(Ltmp, Aqs[j], h1[i-j]);
+ }
+ h1[i] = round_fx(L_shl(Ltmp, s));
+ }
+ }
+
+ tmp = 0;
+ Deemph2(h1, tilt_fac, L_subfr, &tmp);
+
+ return;
+
+}
diff --git a/lib_enc/find_tilt_fx.c b/lib_enc/find_tilt_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..57a59a883ba0091da1edab13f4c764fd9e337981
--- /dev/null
+++ b/lib_enc/find_tilt_fx.c
@@ -0,0 +1,259 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h"
+
+/*-------------------------------------------------------------------*
+ * find_tilt()
+ *
+ * Find LF/HF energy ratio
+ *-------------------------------------------------------------------*/
+
+void find_tilt_fx(
+ const Word32 fr_bands[], /* i : energy in frequency bands Q_new + Q_SCALE*/
+ const Word32 bckr[], /* i : per band background noise energy estimate Q_new + Q_SCALE*/
+ Word32 ee[2], /* o : lf/hf E ration for present frame Q6*/
+ const Word16 pitch[3], /* i : open loop pitch values for 3 half-frames Q0*/
+ const Word16 voicing[3], /* i : normalized correlation for 3 half-frames Q15*/
+ const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new + Q_SCALE - 2*/
+ const Word16 corr_shift, /* i : normalized correlation correction Q15*/
+ const Word16 bwidth, /* i : input signal bandwidth */
+ const Word16 max_band, /* i : maximum critical band */
+ Word32 hp_E[], /* o : energy in HF Q_new + Q_SCALE*/
+ const Word16 codec_mode, /* i : MODE1 or MODE2 */
+ const Word16 Q_new, /* i : scaling factor */
+ Word32 *bckr_tilt_lt /* i/o: lf/hf E ratio of background noise Q16 */
+ ,Word16 Opt_vbr_mode
+)
+{
+ Word32 lp_bckr = 0, hp_bckr = 0, lp_E, Ltmp;
+ const Word32 *pt_E, *pt_bands, *pt_bckr, *hf_bands, *tmp_E;
+ Word16 tmp, freq, f0, f1, f2, mean_voi, bin;
+ Word16 i, nb_bands;
+ Word16 e_tmp, m_tmp;
+ Word16 m_Fs, e_Fs;
+ Word16 m_cnt, e_cnt;
+ Word16 m_hpE, e_hpE;
+ Word16 scaling;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ /*-----------------------------------------------------------------*
+ * Initializations
+ *-----------------------------------------------------------------*/
+
+ scaling = add(Q_new, QSCALE);
+ IF( NE_16(bwidth,NB))
+ {
+ /* WB processing */
+ bin = BIN4_FX;
+ move16(); /* First useful frequency bin ~ 50 Hz */
+ pt_bands = fr_bands;
+ tmp_E = lf_E;
+ pt_bckr = bckr;
+ nb_bands = 10;
+ move16();
+ }
+ ELSE
+ {
+ /* NB processing */
+ bin = add(shl(BIN4_FX,1), BIN4_FX); /* First useful frequency bin ~ 150 Hz */
+ pt_bands = fr_bands+1; /* Exlcude 1st critical band */
+ tmp_E = lf_E + 2; /* Start at the 3rd bin (150 Hz) */
+ pt_bckr = bckr+1; /* Exlcude 1st critical band */
+ nb_bands = 9;
+ move16(); /* Nb. of "low" frequency bands taken into account in NB processing */
+ }
+
+ /*-----------------------------------------------------------------*
+ * Find spectrum tilt
+ *-----------------------------------------------------------------*/
+
+ pt_E = tmp_E; /* Point at the 1st useful element of the per-bin energy vector */
+ hf_bands = fr_bands;
+
+ /* bckr + voicing */
+ /*lp_bckr = mean( pt_bckr, nb_bands );*/ /* estimated noise E in first critical bands, up to 1270 Hz */
+ lp_bckr = Mean32(pt_bckr, nb_bands);
+ /*hp_bckr = 0.5f * (bckr[max_band-1] + bckr[max_band]);*/ /* estimated noise E in last 2 critical bands */
+ hp_bckr = L_shr(L_add(bckr[max_band-1] , bckr[max_band]),1);
+ if (hp_bckr == 0) /* Avoid division by zero. */
+ {
+ hp_bckr = L_deposit_l(1);
+ }
+ tmp = BASOP_Util_Divide3232_Scale( lp_bckr, hp_bckr, &e_tmp );
+ Ltmp = L_shr_r( L_deposit_h( tmp ), sub( 15, e_tmp ) );
+ *bckr_tilt_lt = L_add( Mpy_32_16_r( *bckr_tilt_lt, 29491 ), Mpy_32_16_r( Ltmp, 3277 ) );
+
+ test();
+ IF ( EQ_16(codec_mode,MODE2)||Opt_vbr_mode==1)
+ {
+ /*lp_bckr *= FACT;*/
+ /*hp_bckr *= FACT;*/
+ lp_bckr = L_add(L_shl(lp_bckr,1),lp_bckr);
+ hp_bckr = L_add(L_shl(hp_bckr,1),hp_bckr);
+ }
+ /*mean_voi = 0.5f * (voicing[1] + voicing[2]) + corr_shift;*/
+ Ltmp = L_mult(voicing[1], 16384);
+ Ltmp = L_mac(Ltmp, voicing[2], 16384);
+#ifdef BASOP_NOGLOB
+ Ltmp = L_mac_o(Ltmp,corr_shift, 32767, &Overflow);
+ mean_voi = round_fx_o(Ltmp, &Overflow);
+#else
+ Ltmp = L_mac(Ltmp,corr_shift, 32767);
+ mean_voi = round_fx(Ltmp);
+#endif
+
+ /*f0 = INT_FS_FX / pitch[2];*/
+ e_tmp = norm_s(pitch[2]);
+ m_tmp = shl(pitch[2], e_tmp);
+
+ m_Fs = div_s(INT_FS_FX, m_tmp);
+ e_Fs = sub(15, e_tmp);
+ f0 = shr(m_Fs, sub(e_Fs,4)); /* Q4 */
+
+ FOR( i=0; i<2; i++ )
+ {
+ /*hp_E[i] = 0.5f * (hf_bands[max_band-1] + hf_bands[max_band]) - hp_bckr; *//* averaged E in last 2 critical bands */
+ Ltmp = L_add(L_shr(hf_bands[max_band-1], 1), L_shr(hf_bands[max_band], 1));
+ hp_E[i] = L_sub(Ltmp, hp_bckr);
+ IF ( Opt_vbr_mode == 0 )
+ {
+ hp_E[i] = L_max(hp_E[i], L_shl(E_MIN_FX, Q_new));
+ move32();
+ }
+ ELSE
+ {
+ hp_E[i] = L_max(hp_E[i], L_shl(1, scaling));
+ move32();
+ }
+
+ test();
+ IF(GT_16(mean_voi,TH_COR_FX)&<_16(pitch[2],TH_PIT_FX)) /* High-pitched voiced frames */
+ {
+ freq = bin;
+ move16(); /* 1st useful frequency bin */
+ m_cnt = 0;
+ move16();
+ lp_E = L_deposit_l(0);
+
+ f1 = add(shr(f0,1),f0); /* Middle between 2 harmonics */
+ f2 = f0;
+ move16();
+ WHILE(LE_16(freq, 20320)) /* End frequency of 10th critical band */
+ {
+ FOR (; freq <= f1; freq += BIN4_FX)
+ {
+ /* include only bins sufficiently close to harmonics */
+ tmp = sub(freq, f2);
+ IF(L_mac0(-(Word32)TH_D_FX*TH_D_FX, tmp, tmp) < 0)
+ {
+#ifdef BASOP_NOGLOB
+ lp_E = L_add_o(*pt_E, lp_E, &Overflow);
+#else
+ lp_E = L_add(*pt_E, lp_E);
+#endif
+ m_cnt = add(m_cnt, 1);
+ }
+ pt_E++;
+ }
+#ifdef BASOP_NOGLOB
+ f1 = add_o(f1,f0, &Overflow);
+ f2 = add_o(f2, f0, &Overflow);
+#else
+ f1 = add(f1,f0);
+ f2 = add(f2,f0);
+#endif
+ }
+ /*lp_E = lp_E / (float)cnt - lp_bckr;*/
+ e_tmp = sub(norm_l(lp_E), 1);
+ m_tmp = extract_h(L_shl(lp_E, e_tmp));
+
+ e_tmp = sub(e_tmp,2); /* lf_e divided by 4 in anal_sp */
+
+ e_cnt = norm_s(m_cnt);
+ m_cnt = shl(m_cnt, e_cnt);
+
+ m_tmp = div_s(m_tmp, m_cnt);
+ e_tmp = sub(e_tmp, e_cnt);
+
+#ifdef BASOP_NOGLOB
+ lp_E = L_sub_o(L_shr_o(m_tmp, sub(e_tmp, 1), &Overflow), lp_bckr, &Overflow);
+#else
+ lp_E = L_sub(L_shr(m_tmp, sub(e_tmp, 1)), lp_bckr);
+#endif
+
+ pt_E = tmp_E + VOIC_BINS; /* Update for next half-frame */
+ }
+ ELSE /* Other than high-pitched voiced frames */
+ {
+ /*lp_E = mean( pt_bands, nb_bands ) - lp_bckr;*/ /* averaged E in first critical bands, up to 1270 Hz */
+ lp_E = L_sub(Mean32( pt_bands, nb_bands ) , lp_bckr);
+ }
+ IF ( Opt_vbr_mode == 0 )
+ {
+ lp_E = L_max(lp_E, L_shl(E_MIN_FX,Q_new));
+ }
+ ELSE
+ {
+ lp_E = L_max(lp_E, 0);
+ }
+ /*ee[i] = lp_E / hp_E[i];*/ /* LF/HF ratio */
+ test();
+ IF (lp_E != 0 && hp_E[i] != 0)
+ {
+ e_tmp = sub(norm_l(lp_E), 1);
+ m_tmp = extract_h(L_shl(lp_E, e_tmp));
+ e_hpE = norm_l(hp_E[i]);
+ m_hpE = extract_h(L_shl(hp_E[i], e_hpE));
+ m_tmp = div_s(m_tmp, m_hpE);
+ e_tmp = sub(e_tmp, e_hpE);
+
+#ifdef BASOP_NOGLOB
+ ee[i] = L_shr_o(m_tmp, add(e_tmp, 15-6), &Overflow); /* ee in Q6 */
+#else /* BASOP_NOGLOB */
+ ee[i] = L_shr(m_tmp, add(e_tmp, 15-6)); /* ee in Q6 */
+#endif
+ }
+ ELSE IF (lp_E == 0)
+ {
+ ee[i] = L_deposit_l(0);
+ }
+ ELSE
+ {
+ ee[i] = MAX_32;
+ }
+
+ IF( EQ_16(bwidth,NB)) /* For NB input, compensate for the missing bands */
+ {
+#ifdef BASOP_NOGLOB
+ Ltmp = L_shl_o(ee[i], 3, &Overflow);
+#else
+ Ltmp = L_shl(ee[i], 3);
+#endif
+ IF (EQ_32(Ltmp, MAX_32)) /* if Overflow: Compute with less precision */
+ {
+ Ltmp = Mult_32_16(ee[i], 24576); /* 6/8 */
+ ee[i] = L_shl(Ltmp, 3);
+ move32(); /* x8 */
+ }
+ ELSE
+ {
+ ee[i] = Mult_32_16(Ltmp, 24576);
+ move32();/* 6/8 */
+ }
+ }
+
+ pt_bands += NB_BANDS; /* Update for next half-frame */
+ hf_bands += NB_BANDS;
+ }
+
+ return;
+}
diff --git a/lib_enc/find_uv_fx.c b/lib_enc/find_uv_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..d9ef93c1f4c4c553f9d52fd2e1efbab79939d9f9
--- /dev/null
+++ b/lib_enc/find_uv_fx.c
@@ -0,0 +1,652 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+//#include "prot_fx.h" /* Function prototypes */
+#include "rom_com.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define L_ENR (NB_SSF+2)
+
+
+
+/*-------------------------------------------------------------------*
+ * find_ener_decrease_fx()
+ *
+ * Find maximum energy ration between short subblocks in case
+ * energy is trailing off after a spike
+ *-------------------------------------------------------------------*/
+
+static Word16 find_ener_decrease_fx( /* o : maximum energy ratio Q10 */
+ const Word16 ind_deltaMax, /* i : index of the beginning of maximum energy search */
+ const Word32 *pt_enr_ssf /* i : Pointer to the energy buffer */
+)
+{
+ Word16 i, j, end, flag;
+ Word16 wtmp0, wtmp1;
+ Word32 maxEnr, minEnr;
+ Word16 dE2, exp0, exp1;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ dE2 = 0;
+ move16();
+
+ j = ind_deltaMax+2;
+ move16();
+ end = j+L_ENR;
+ move16();
+ maxEnr = L_add(pt_enr_ssf[j], 0);
+ j = add(j, 1);
+ flag = 0;
+ move16();
+ FOR( i=j; ihNoiseEst;
+ SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ Word16 Last_Resort;
+ Word16 vadnoise;
+
+ IF (hSC_VBR != NULL)
+ {
+ Last_Resort = hSC_VBR->Last_Resort;
+ vadnoise = hSC_VBR->vadnoise_fx;
+ }
+ ELSE
+ {
+ Last_Resort = 0;
+ vadnoise = 0;
+ }
+
+ Q_in = sub(Q_new,1);
+
+ /*-----------------------------------------------------------------*
+ * Detect sudden energy increases to catch voice and music
+ * temporal events (dE1)
+ *
+ * - Find maximum energy per short subblocks.
+ * Two subblock sets are used shifted by half the subblock length
+ * - Find maximum energy ratio between adjacent subblocks
+ *-----------------------------------------------------------------*/
+
+ /* Find maximum energy per short subblocks */
+ pt_speech = speech - SSF;
+ pt_enr_ssf = enr_ssf + 2*NB_SSF;
+ FOR( i=0 ; i < 2*(NB_SSF+1) ; i++ )
+ {
+ emaximum_fx(Q_in, pt_speech, SSF, pt_enr_ssf );
+ pt_speech += (SSF/2);
+ pt_enr_ssf++;
+ }
+
+ dE1 = 0;
+ move16();
+ ind_deltaMax = 0;
+ move16();
+ pt_enr_ssf = enr_ssf + 2*NB_SSF;
+ pt_enr_ssf1 = pt_enr_ssf + 2;
+
+ /* Test on energy increase between adjacent sub-subframes */
+ exp1 = 0;
+ move16();
+ FOR( i=0; i < 2*NB_SSF; i++ )
+ {
+ /*fac = *pt_enr_ssf1 / (*pt_enr_ssf + 1);*/
+ Ltmp0 = L_max(*pt_enr_ssf, 1);
+ exp0 = norm_l(Ltmp0);
+ wtmp0 = extract_h(L_shl(Ltmp0, exp0));
+ exp1 = sub(norm_l(*pt_enr_ssf1),1);
+ wtmp1 = extract_h(L_shl(*pt_enr_ssf1, exp1));
+ fac = div_s(wtmp1,wtmp0);
+#ifdef BASOP_NOGLOB
+ fac_32 = L_shr_o(L_deposit_l(fac), add(sub(exp1, exp0),15-13), &Overflow); /* fac32 in Q13*/
+#else /* BASOP_NOGLOB */
+ fac_32 = L_shr(L_deposit_l(fac), add(sub(exp1, exp0),15-13)); /* fac32 in Q13*/
+#endif /* BASOP_NOGLOB */
+
+ if(GT_32(fac_32, dE1 ))
+ {
+ ind_deltaMax = i;
+ move16();
+ }
+
+ dE1 = L_max(dE1, fac_32);
+
+ pt_enr_ssf++;
+ pt_enr_ssf1++;
+ }
+#ifdef IVAS_CODE
+ IF (hStereoClassif != NULL)
+ {
+ IF (st_fx->idchan == 0)
+ {
+ hStereoClassif->dE1_ch1 = dE1;
+ }
+ ELSE
+ {
+ hStereoClassif->dE1_ch2 = dE1;
+ }
+ }
+
+ if (dE1X != NULL)
+ {
+ *dE1X = dE1;
+ move32();
+ }
+#endif
+ /*-----------------------------------------------------------------*
+ * Average spectral tilt
+ * Average voicing (normalized correlation)
+ *-----------------------------------------------------------------*/
+
+ /*mean_ee = 1.0f/3.0f * (st->ee_old + ee[0] + ee[1]); */ /* coefficients take into account the position of the window */
+#ifdef BASOP_NOGLOB
+ mean_ee = L_add_o(L_add_o(st_fx->ee_old_fx, ee[0], &Overflow), ee[1], &Overflow);
+#else /* BASOP_NOGLOB */
+ mean_ee = L_add(L_add(st_fx->ee_old_fx, ee[0]), ee[1]);
+#endif /* BASOP_NOGLOB */
+ mean_ee = Mult_32_16(mean_ee, 10923); /*Q6*/
+
+ /* mean_voi3 = 1.0f/3.0f * (voicing[0] + voicing[1] + voicing[2]);*/
+ Ltmp0 = L_mult( st_fx->voicing_fx[0], 10923);
+ Ltmp0 = L_mac(Ltmp0, st_fx->voicing_fx[1], 10923);
+ mean_voi3 = mac_r(Ltmp0, st_fx->voicing_fx[2], 10923); /*Q15*/
+
+ /*-----------------------------------------------------------------*
+ * Total frame energy difference (dE3)
+ *-----------------------------------------------------------------*/
+
+ dE3 = sub(Etot, hNoiseEst->Etot_last_fx); /*Q8*/
+
+ /*-----------------------------------------------------------------*
+ * Energy decrease after spike (dE2)
+ *-----------------------------------------------------------------*/
+
+ /* set different thresholds and conditions for NB and WB input */
+ dE2_th = 30<<10;
+ move32();
+ nb_cond = 1;
+ move16(); /* no additional condition for WB input */
+ IF ( EQ_16(st_fx->input_bwidth_fx,NB))
+ {
+ dE2_th = 21<<10;
+ move32();
+#ifdef BASOP_NOGLOB
+ if(GE_16(add_o(mean_voi3, corr_shift, &Overflow), 22282)) /*( mean_voi3 + corr_shift ) >= 0.68f*/
+#else
+ if(GE_16(add(mean_voi3, corr_shift), 22282)) /*( mean_voi3 + corr_shift ) >= 0.68f*/
+#endif
+ {
+ nb_cond = 0;
+ move16();
+ }
+ }
+
+ /* calcualte maximum energy decrease */
+ dE2 = 0;
+ move16(); /* Test on energy decrease after an energy spike */
+ pt_enr_ssf = enr_ssf + 2*NB_SSF;
+
+ test();
+ IF( GT_32(dE1, 30<<13)&&nb_cond) /*>30 Q13*/
+ {
+ IF( LT_16(sub(shl(NB_SSF,1), ind_deltaMax),L_ENR))
+ {
+ st_fx->old_ind_deltaMax_fx = ind_deltaMax;
+ move16();
+ Copy32( pt_enr_ssf, st_fx->old_enr_ssf_fx, 2*NB_SSF );
+ }
+ ELSE
+ {
+ st_fx->old_ind_deltaMax_fx = -1;
+ move16();
+ dE2 = find_ener_decrease_fx( ind_deltaMax, pt_enr_ssf ); /*Q10*/
+
+ if( GT_32(dE2,dE2_th))
+ {
+ st_fx->spike_hyst_fx = 0;
+ move16();
+ }
+ }
+ }
+ ELSE
+ {
+ IF( st_fx->old_ind_deltaMax_fx >= 0 )
+ {
+ Copy32( st_fx->old_enr_ssf_fx, enr_ssf, 2*NB_SSF );
+ dE2 = find_ener_decrease_fx( st_fx->old_ind_deltaMax_fx, enr_ssf );
+
+ if( GT_32(dE2,dE2_th))
+ {
+ st_fx->spike_hyst_fx = 1;
+ move16();
+ }
+ }
+
+ st_fx->old_ind_deltaMax_fx = -1;
+ move16();
+ }
+
+ /*-----------------------------------------------------------------*
+ * Detection of voiced offsets (tmp_offset_flag)
+ *-----------------------------------------------------------------*/
+
+ tmp_offset_flag = 1;
+ move16();
+
+ IF ( NE_16(st_fx->input_bwidth_fx, NB))
+ {
+ ee0_th = 154; /*2.4 in Q6 */ move16();
+ voi_th = 24248; /*0.74f Q15 */ move16();
+ }
+ ELSE
+ {
+ ee0_th = 627; /*9.8f Q6 */ move16();
+ voi_th = 24904; /*0.76f Q15*/ move16();
+ }
+
+ test();
+ test();
+ test();
+#ifdef BASOP_NOGLOB
+ if( ( EQ_16(st_fx->last_coder_type_raw_fx,UNVOICED))|| /* previous frame was unvoiced */
+ ( ( LT_32(ee[0],ee0_th) ) && ( GT_32(hp_E[0],L_shl(E_MIN_FX,Q_new)) ) && /* energy is concentrated in high frequencies provided that some energy is present in HF */
+ ( LT_16(add_o(st_fx->voicing_fx[0],corr_shift, &Overflow),voi_th)))) /* normalized correlation is low */
+#else /* BASOP_NOGLOB */
+ if( ( EQ_16(st_fx->last_coder_type_raw_fx,UNVOICED))|| /* previous frame was unvoiced */
+ ( ( LT_32(ee[0],ee0_th) ) && ( GT_32(hp_E[0],L_shl(E_MIN_FX,Q_new)) ) && /* energy is concentrated in high frequencies provided that some energy is present in HF */
+ ( LT_16(add(st_fx->voicing_fx[0],corr_shift),voi_th)))) /* normalized correlation is low */
+#endif /* BASOP_NOGLOB */
+ {
+ tmp_offset_flag = 0;
+ move16();
+ }
+
+ /*-----------------------------------------------------------------*
+ * Decision about UC
+ *-----------------------------------------------------------------*/
+
+ /* SC-VBR - set additional parameters and thresholds for SC-VBR */
+ mean_voi3_offset = 0;
+ move16();
+ flag_low_relE = 0;
+ move16();
+ ee1_th = 608; /*9.5 Q6*/ move16();
+ IF ( st_fx->Opt_SC_VBR_fx || (EQ_16(st_fx->idchan, 1) && EQ_16(st_fx->element_mode, IVAS_CPE_TD))) /* Allow the low energy flag for the secondary channel */
+ {
+ ee1_th = 544; /*8.5f Q6*/ move16();
+
+ /* SC-VBR - determine the threshold on relative energy as a function of lp_noise */
+ IF ( NE_16(st_fx->input_bwidth_fx,NB))
+ {
+ /*relE_thres = 0.700f * st->lp_noise - 33.5f; (lp_noise in Q8, constant Q8<<16) */
+ L_tmp = L_mac(-562036736, 22938, st_fx->lp_noise_fx);
+ if ( Last_Resort == 0 )
+ {
+ /*relE_thres = 0.650f * st->lp_noise - 33.5f; (lp_noise in Q8, constant Q8<<16)*/
+ L_tmp = L_mac(-562036736, 21299, st_fx->lp_noise_fx);
+ }
+ relE_thres = round_fx(L_tmp);
+ }
+ ELSE
+ {
+
+ /*relE_thres = 0.60f * st->lp_noise - 28.2f; (lp_noise in Q8, constant Q8<<16)*/
+ L_tmp = L_mac(-473117491, 19661, st_fx->lp_noise_fx);
+ relE_thres = round_fx(L_tmp);
+ }
+ relE_thres = s_max(relE_thres , -6400); /* Q8 */
+
+ /* SC-VBR = set flag on low relative energy */
+ if ( LT_16(relE,relE_thres))
+ {
+ flag_low_relE = 1;
+ move16();
+ }
+
+ /* SC-VBR - correction of voicing threshold for NB inputs (important only in noisy conditions) */
+ test();
+ if ( EQ_16(st_fx->input_bwidth_fx,NB)&<_16( vadnoise ,20<<8)) /* vadnoise in Q8, constant Q0<<8 */
+ {
+ mean_voi3_offset = 1638; /*0.05f Q15*/ move16();
+ }
+ }
+
+ /* make decision whether frame is unvoiced */
+ E_min_th = L_shl(E_MIN_FX,Q_new);
+ coder_type = GENERIC;
+ move16();
+ IF ( EQ_16(st_fx->input_bwidth_fx,NB))
+ {
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+#ifdef BASOP_NOGLOB
+ if( ( ( LT_16(add_o(mean_voi3, corr_shift, &Overflow),add(22282,mean_voi3_offset)))&& /* normalized correlation low */
+ ( LT_16(add_o(st_fx->voicing_fx[2], corr_shift, &Overflow),25887) ) && /* normalized correlation low on look-ahead - onset detection */
+ ( LT_32(ee[0], 640) ) && ( GT_32(hp_E[0], E_min_th) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */
+ ( LT_32(ee[1], ee1_th) ) && ( GT_32(hp_E[1], E_min_th) ) && /* ... biased towards look-ahead to detect onsets */
+ ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */
+ /*( st_fx->music_hysteresis_fx == 0 ) &&*/ /* ... and in segment after AUDIO frames */
+ ( LE_32(dE1, 237568) ) && /* Avoid on sharp energy spikes */
+ ( LE_32(st_fx->old_dE1_fx,237568) ) && /* + one frame hysteresis */
+ ( st_fx->spike_hyst_fx < 0 ) ) || /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */
+ flag_low_relE ) /* low relative frame energy (only for SC-VBR) */
+#else
+ if( ( ( LT_16(add(mean_voi3, corr_shift),add(22282,mean_voi3_offset)))&& /* normalized correlation low */
+ ( LT_16(add(st_fx->voicing_fx[2], corr_shift),25887) ) && /* normalized correlation low on look-ahead - onset detection */
+ ( LT_32(ee[0], 640) ) && ( GT_32(hp_E[0], E_min_th) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */
+ ( LT_32(ee[1], ee1_th) ) && ( GT_32(hp_E[1], E_min_th) ) && /* ... biased towards look-ahead to detect onsets */
+ ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */
+ /*( st_fx->music_hysteresis_fx == 0 ) &&*/ /* ... and in segment after AUDIO frames */
+ ( LE_32(dE1, 237568) ) && /* Avoid on sharp energy spikes */
+ ( LE_32(st_fx->old_dE1_fx,237568) ) && /* + one frame hysteresis */
+ ( st_fx->spike_hyst_fx < 0 ) ) || /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */
+ flag_low_relE ) /* low relative frame energy (only for SC-VBR) */
+#endif
+ {
+ coder_type = UNVOICED;
+ move16();
+ }
+ }
+ ELSE
+ {
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+#ifdef BASOP_NOGLOB
+ if( ( ( LT_16(add_o(mean_voi3, corr_shift, &Overflow), add(22774,mean_voi3_offset)))&& /* normalized correlation low */
+#else /* BASOP_NOGLOB */
+ if( ( ( LT_16(add(mean_voi3, corr_shift),add(22774,mean_voi3_offset)))&& /* normalized correlation low */
+#endif
+ ( LT_16(add(st_fx->voicing_fx[2], corr_shift),25887) ) && /* normalized correlation low on look-ahead - onset detection */
+ ( LT_32(ee[0], 397) ) && ( GT_32(hp_E[0], E_min_th) ) && /* energy concentrated in high frequencies provided that some energy is present in HF... */
+ ( LT_32(ee[1], 397) ) && ( GT_32(hp_E[1], E_min_th) ) && /* ... biased towards look-ahead to detect onsets */
+ ( tmp_offset_flag == 0 ) && /* Take care of voiced offsets */
+ /*( st_fx->music_hysteresis_fx == 0 ) && */ /* ... and in segment after AUDIO frames */
+ ( LE_32(dE1, 245760) ) && /* Avoid on sharp energy spikes */
+ ( LE_32(st_fx->old_dE1_fx,245760) ) && /* + one frame hysteresis */
+ ( st_fx->spike_hyst_fx < 0 ) ) /* Avoid after sharp energy spikes followed by decay (e.g. castanets) */
+ || ( flag_low_relE
+ && ( LE_32(st_fx->old_dE1_fx,245760) )
+ )
+ ) /* low relative frame energy (only for SC-VBR) */
+ {
+ coder_type = UNVOICED;
+ move16();
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Decision about VC
+ *-----------------------------------------------------------------*/
+ if (st_fx->Opt_SC_VBR_fx)
+ {
+ hSC_VBR->set_ppp_generic = 0;
+ }
+ move16();
+
+ test();
+ test();
+ IF( EQ_16(st_fx->localVAD,1)&&EQ_16(coder_type,GENERIC)&&NE_16(last_core_orig,AMR_WB_CORE))
+ {
+ dpit1 = abs_s( sub(T_op_fr[1], T_op_fr[0]));
+ dpit2 = abs_s( sub(T_op_fr[2], T_op_fr[1]));
+ dpit3 = abs_s( sub(T_op_fr[3], T_op_fr[2]));
+
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF( ( GT_16(voicing_fr[0],19825))&& /* normalized correlation high in 1st sf. */
+ ( GT_16(voicing_fr[1],19825) ) && /* normalized correlation high in 2st sf. */
+ ( GT_16(voicing_fr[2],19825) ) && /* normalized correlation high in 3st sf. */
+ ( GT_16(voicing_fr[3],19825) ) && /* normalized correlation high in 4st sf. */
+ ( GT_32(mean_ee,256) ) && /* energy concentrated in low frequencies */
+ ( LT_16(dpit1,3<<6) ) &&
+ ( LT_16(dpit2,3<<6) ) &&
+ ( LT_16(dpit3,3<<6) ) )
+ {
+ coder_type = VOICED;
+ move16();
+ }
+ ELSE IF ( st_fx->Opt_SC_VBR_fx && EQ_16(st_fx->input_bwidth_fx,NB) && LT_16(vadnoise,20<<8))
+ {
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF( GT_16(voicing_fr[0],8192)&& /* normalized correlation high in 1st sf. */
+ ( GT_16(voicing_fr[1],8192) ) && /* normalized correlation high in 2st sf. */
+ ( GT_16(voicing_fr[2],8192) ) && /* normalized correlation high in 3st sf. */
+ ( GT_16(voicing_fr[3],8192) ) && /* normalized correlation high in 4st sf. */
+ ( GT_32(mean_ee,64) ) && /* energy concentrated in low frequencies */
+ ( LT_16(dpit1,5<<6) ) &&
+ ( LT_16(dpit2,5<<6) ) &&
+ ( LT_16(dpit3,5<<6) ) )
+ {
+ hSC_VBR->set_ppp_generic = 1;
+ move16();
+ coder_type = VOICED;
+ move16();
+ }
+ }
+
+ /* set VOICED mode for frames with very stable pitch and high correlation
+ and avoid to switch to AUDIO/MUSIC later */
+ voicing_m = mac_r(L_mac(L_mac(L_mult(voicing_fr[3], 8192), voicing_fr[2], 8192),voicing_fr[1], 8192),voicing_fr[0], 8192);
+ test();
+ test();
+ test();
+ test();
+ test();
+ IF ( *flag_spitch || ( LE_16(dpit1,3<<6)&&LE_16(dpit2,3<<6)&&LE_16(dpit3,3<<6)&&
+ GT_16(voicing_m, 31130) && GT_16(st_fx->voicing_sm_fx, 31785) ) )
+ {
+ coder_type = VOICED;
+ move16();
+ *flag_spitch = 1;
+ move16();/*to avoid switch to AUDIO/MUSIC later*/
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Channel-aware mode - set RF mode and total bitrate
+ *-----------------------------------------------------------------*/
+
+ st_fx->rf_mode = st_fx->Opt_RF_ON;
+ move16();
+
+ IF ( EQ_16 ( coder_type, GENERIC ) )
+ {
+ test();
+ test();
+ test();
+ test();
+ IF( ( LT_16(voicing_fr[0],6554))&& /* normalized correlation high in 2st sf. */
+ ( LT_16(voicing_fr[1],6554) ) && /* normalized correlation high in 2st sf. */
+ ( LT_16(voicing_fr[2],6554) ) && /* normalized correlation high in 3rd sf. */
+ ( LT_16(voicing_fr[3],6554) ) && /* normalized correlation high in 4th sf. */
+ ( GT_16(vadnoise, 25 << 8 ) )) /* when speech is clean */
+
+ {
+ st_fx->rf_mode = 0;
+ move16();
+ /* Current frame cannot be compressed to pack the partial redundancy;*/
+
+ if( st_fx->rf_mode != st_fx->Opt_RF_ON )
+ {
+ core_coder_mode_switch_fx( st_fx, st_fx->last_total_brate_fx, 0, shift );
+ }
+ }
+ }
+#ifdef IVAS_CODE
+ /*-----------------------------------------------------------------*
+ * UNCLR classifier
+ *-----------------------------------------------------------------*/
+
+ if (hStereoClassif != NULL)
+ {
+ if (st->element_mode > EVS_MONO && (coder_type == GENERIC || coder_type == UNVOICED || coder_type == INACTIVE || st->localVAD == 0) && hStereoClassif->unclr_sw_enable_cnt[st->idchan] < MAX_UV_CNT)
+ {
+ hStereoClassif->unclr_sw_enable_cnt[st->idchan]++;
+ }
+ else
+ {
+ hStereoClassif->unclr_sw_enable_cnt[st->idchan] = 0;
+ }
+ }
+#endif
+
+
+ /*-----------------------------------------------------------------*
+ * Updates
+ *-----------------------------------------------------------------*/
+
+ /* update spike hysteresis parameters */
+ test();
+ if( st_fx->spike_hyst_fx >= 0 && LT_16(st_fx->spike_hyst_fx,2))
+ {
+ st_fx->spike_hyst_fx = add(st_fx->spike_hyst_fx,1);
+ }
+
+ /* reset spike hysteresis */
+ test();
+ test();
+ test();
+ if( ( GT_16(st_fx->spike_hyst_fx,1))&&
+ ( GT_16(dE3,5<<8) || /* energy increases */
+ ( GT_16(relE, -3328)&&(GT_16(add(mean_voi3,corr_shift),22774))))) /* normalized correlation is high */
+ {
+ st_fx->spike_hyst_fx = -1;
+ move16();
+ }
+
+ /* update tilt parameters */
+ st_fx->ee_old_fx = ee[1];
+ move32(); /*Q6*/
+ st_fx->old_dE1_fx = dE1;
+ move32(); /*Q13*/
+
+ /* save the raw coder_type for various modules later in the codec (the reason is that e.g. UNVOICED is lost at higher rates) */
+ st_fx->coder_type_raw_fx = coder_type;
+ move16();
+
+ return coder_type;
+}
diff --git a/lib_enc/find_wsp_fx.c b/lib_enc/find_wsp_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..a4279d4b0da8ce9089dc81d3bee57873fc90f709
--- /dev/null
+++ b/lib_enc/find_wsp_fx.c
@@ -0,0 +1,86 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include "options.h"
+#include "cnst.h"
+//#include "prot_fx.h"
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+
+
+/*
+ * find_wsp_fx
+ *
+ * Parameters:
+ * Az I: A(z) filter coefficients Q12
+ * speech I: pointer to the denoised speech frame Q_new - preemph_bits
+ * wsp O: pointer to the weighted speech frame Q_new - preemph_bits
+ * mem_wsp I/O: W(z) denominator memory
+ * preemph_fac I: pre-emphasis factor Q15
+ * L_frame I: length of the frame
+ * lookahead I: length of a look-ahead
+ * L_subfr I: length of the sub-frame
+ *
+ * Function:
+ * Find weighted speech (formula from AMR-WB)
+ *
+ * Returns:
+ * void
+ */
+void find_wsp_fx(
+ const Word16 Az[], /* i : A(z) filter coefficients */
+ const Word16 speech[], /* i : pointer to the denoised speech frame */
+ Word16 wsp[], /* o : poitnter to the weighted speech frame */
+ Word16 *mem_wsp, /* i/o: W(Z) denominator memory */
+ const Word16 preemph_fac, /* i : pre - emphasis factor Q15 */
+ const Word16 L_frame, /* i : length of the frame */
+ const Word16 lookahead, /* i : look-ahead */
+ const Word16 L_subfr, /* i : length of subframe */
+ Word16 *Aw, /* o : weighted A(z) filter coefficients */
+ const Word16 gamma, /* i : weighting factor */
+ const Word16 nb_subfr /* i : number of subframes */
+)
+{
+ Word16 i_subfr, wtmp;
+ const Word16 *p_Az;
+ /*-----------------------------------------------------------------*
+ * Compute weighted A(z) unquantized for subframes
+ *-----------------------------------------------------------------*/
+
+ weight_a_subfr_fx( nb_subfr, Az, Aw, gamma, M );
+
+
+ /*----------------------------------------------------------------*
+ * Compute weighted speech for all subframes
+ *----------------------------------------------------------------*/
+ BASOP_SATURATE_WARNING_OFF_EVS
+ p_Az = Aw; /*move16();*/
+ FOR (i_subfr = 0; i_subfr < L_frame; i_subfr += L_subfr)
+ {
+ Residu3_fx(p_Az, &speech[i_subfr], &wsp[i_subfr], L_subfr, 0);
+ p_Az += (M+1);
+ }
+ p_Az -= (M+1);
+ BASOP_SATURATE_WARNING_ON_EVS
+ /*----------------------------------------------------------------*
+ * Weighted speech computation is extended on look-ahead
+ *----------------------------------------------------------------*/
+ deemph_fx(wsp, preemph_fac, L_frame, mem_wsp); /* use Deemph2 to prevent saturation */
+
+ IF ( lookahead != 0 )
+ {
+ Residu3_fx(p_Az, &speech[L_frame], &wsp[L_frame], lookahead, 0);
+ wtmp = *mem_wsp;
+ move16();
+ deemph_fx(&wsp[L_frame], preemph_fac, lookahead, &wtmp);
+ }
+
+}
+
+
+
diff --git a/lib_enc/frame_spec_dif_cor_rate_fx.c b/lib_enc/frame_spec_dif_cor_rate_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..f9ed3e7899d2b5fbb7713b7416d113efcd104447
--- /dev/null
+++ b/lib_enc/frame_spec_dif_cor_rate_fx.c
@@ -0,0 +1,121 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+
+
+#include
+#include "options.h"
+#include "cnst.h"
+#include "basop_util.h"
+#include "vad_basop.h"
+//#include "prot_fx.h"
+#include "rom_com.h" /* Common constants */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+#include "basop_util.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * frame_spec_dif_cor_rate_fx()
+ *
+ *
+ *-------------------------------------------------------------------*/
+void frame_spec_dif_cor_rate_fx(
+ VAD_CLDFB_HANDLE_FX hVAD_CLDFB , /* i/o: CLDFB VAD state */
+ Word32 *spec_amp, /* i : spectral amplitude*/
+ Word16 sacle, /* i : the scaling of spec_amp*/
+ Word16 f_tonality_rate[3] /* o : tonality rate*/
+)
+
+{
+ Word32 i,tmp;
+ Word16 spec_low_dif_tmp,tmpq,tmpq2,*p_dx_Q,dx_Q=0;
+ Word32 tmpspec_low_dif[PRE_SPEC_DIF_NUM];
+ Word32 maxVal;
+ Word16 resu;
+ Word16 scalefactor,spec_dif_cor_rate;
+ Word32 m,dx,dy;
+ Word16 *pre_spec_low_dif = hVAD_CLDFB->pre_spec_low_dif;
+ const Word32 FIX_cost1 = 2147484/* 0.001f Q31 */;
+
+
+
+ p_dx_Q = &dx_Q;
+ maxVal = 0; move32();
+ FOR(i=0; i< PRE_SPEC_DIF_NUM; i++)
+ {
+ tmp = L_sub(spec_amp[i+6] ,spec_amp[i+5]);
+ if ( tmp < 0 )
+ {
+ tmp = 0;
+ move32();
+ }
+ tmpspec_low_dif[i] = tmp;
+ move32();
+ maxVal = L_max(maxVal,tmp);
+ }
+ resu = 31;
+ move16();
+ if ( maxVal )
+ {
+ resu = norm_l(maxVal);
+ }
+
+ m = 0; move32();
+ dx = 0; move32();
+ dy = 0; move32();
+
+ scalefactor = sub(resu,3);
+
+ FOR (i = 0; i < PRE_SPEC_DIF_NUM; i++)
+ {
+ spec_low_dif_tmp = round_fx(L_shl(tmpspec_low_dif[i],scalefactor));
+ m = L_mac0(m,spec_low_dif_tmp,pre_spec_low_dif[i]);
+ dx = L_mac0(dx, spec_low_dif_tmp, spec_low_dif_tmp);
+ dy = L_mac0(dy, pre_spec_low_dif[i], pre_spec_low_dif[i]);
+ pre_spec_low_dif[i] = spec_low_dif_tmp;
+ move16();
+ }
+ dx = L_mult0(round_fx(dx),round_fx(dy));
+ tmpq = add(sacle,scalefactor);
+ tmpq = sub(tmpq,16);
+ tmpq2 = add(tmpq,hVAD_CLDFB->scale_spec_low_dif);
+ *p_dx_Q = shl(tmpq2,1);
+ move16();
+ *p_dx_Q = sub(*p_dx_Q ,32);
+ move16();
+ IF(LT_16(*p_dx_Q , 31))
+ {
+ dx = L_add(dx,L_shr(FIX_cost1,limitScale32(sub(31,*p_dx_Q))));
+ }
+ ELSE
+ {
+ dx = L_add(L_shr(dx,limitScale32(sub(*p_dx_Q,31))),FIX_cost1);
+ *p_dx_Q = 31;
+ move16();
+ }
+
+ dx = vad_Sqrt_l(dx,p_dx_Q);
+
+ m = L_shr(m,limitScale32(add(sub(tmpq2,*p_dx_Q),1)));
+ spec_dif_cor_rate = 16384;
+ move16();
+
+ if(dx)
+ {
+ spec_dif_cor_rate = divide3232(m,dx);
+ }
+
+ f_tonality_rate[0] = spec_dif_cor_rate;
+ move16();
+ tmp = L_mac0(L_mult0(f_tonality_rate[1],31456/* 0.96 Q15 */), spec_dif_cor_rate,1311/* 0.04 Q15 */);
+ f_tonality_rate[1] = shl(round_fx(tmp),1);
+ move16();
+ tmp = L_mac0(L_mult0(f_tonality_rate[2],29490/* 0.90 Q15 */), spec_dif_cor_rate,3277/* 0.1 Q15 */);
+ f_tonality_rate[2] = shl(round_fx(tmp),1);
+ move16();
+ hVAD_CLDFB->scale_spec_low_dif = tmpq;
+ move16();
+
+}
+
diff --git a/lib_enc/gain_enc_fx.c b/lib_enc/gain_enc_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..dfdfda24e201c50d8f1c8cea12e7afff38168122
--- /dev/null
+++ b/lib_enc/gain_enc_fx.c
@@ -0,0 +1,2024 @@
+/*====================================================================================
+ EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
+ ====================================================================================*/
+#include
+#include "options.h" /* Compilation switches */
+#include "cnst.h" /* Common constants */
+#include "rom_com_fx.h" /* Static table prototypes */
+#include "rom_com.h" /* Static table prototypes */
+//#include "prot_fx.h" /* Function prototypes */
+#include "prot_fx1.h" /* Function prototypes */
+#include "prot_fx2.h" /* Function prototypes */
+#include "prot_fx_enc.h" /* Function prototypes */
+
+/*-------------------------------------------------------------------*
+ * Local constants
+ *-------------------------------------------------------------------*/
+
+#define RANGE 64
+#define NB_QUA_GAIN7B 128 /* Number of quantization levels */
+
+/*-------------------------------------------------------------------*
+ * Local function prototype
+ *-------------------------------------------------------------------*/
+
+static Word16 Find_Opt_gainQ_fx(Word16 *coeff, Word16 *exp_coeff, Word16 *gain_pit, Word32 *gain_code,
+ Word16 gcode0,Word16 exp_gcode0,const Word16 *cdbk, const Word16 size );
+
+/*==========================================================================*/
+/* FUNCTION : Es_pred_enc_fx() */
+/*--------------------------------------------------------------------------*/
+/* PURPOSE : Calculation and quantization of average predicted innovation energy to be*/
+/*--------------------------------------------------------------------------*/
+/* INPUT ARGUMENTS : */
+/* _ Word16 L_frame, i : length of the frame Q0 */
+/* _ Word16 *res, i : residual signal Q_new */
+/* _ Word16 *voicing, i : normalized correlation in three 1/2frames Q15*/
+/* _ Word16 coder_type, i : coder_type Q0 */
+/* _ Word16 bwidth, i : input signal bandwidth Q0 */
+/* _ Word32 core_brate, i : core bitrate Q0 */
+/* _ Word16 Q_new i : Scaling in speech Q0 */
+/*--------------------------------------------------------------------------*/
+/* OUTPUT ARGUMENTS : */
+/* _ Word16 *Es_pred, o : predicited scaled innovation energy Q8 */
+/*--------------------------------------------------------------------------*/
+/* INPUT/OUTPUT ARGUMENTS : */
+/* _ None. */
+/*--------------------------------------------------------------------------*/
+/* RETURN ARGUMENTS : _ None. */
+/*--------------------------------------------------------------------------*/
+/* CALLED FROM : TX */
+/*==========================================================================*/
+
+void Es_pred_enc_fx(
+ Word16 *Es_pred, /* o : predicited scaled innovation energy Q8 */
+ Word16 *indice, /* o : indice of quantization */
+ const Word16 L_frame, /* i : length of the frame */
+ const Word16 *res, /* i : residual signal */
+ const Word16 *voicing, /* i : normalized correlation in three 1/2frames */
+ const Word16 nb_bits, /* i : allocated number of bits */
+ const Word16 no_ltp, /* i : no_ltp flag */
+ Word16 Q_new /* i : Scaling in speech Q0 */
+)
+{
+ Word16 i, i_subfr,size, tmp16, tmp16_2, Q_res;
+ Word16 weight;
+ Word16 s0,s1, ener_dB, mean_ener_code16;
+ const Word16 *qua_table;
+ Word32 ener_fx, Lmean_ener_code, Ltmp;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ Lmean_ener_code = L_deposit_l(0);
+ Q_res = sub(shl(Q_new, 1), 3);
+
+ IF( EQ_16(L_frame,L_FRAME))
+ {
+ weight = 8192;
+ move16();/*0.25f in Q15*/
+ }
+ ELSE /* L_frame == L_FRAME16k */
+ {
+ weight = 6554;
+ move16();/*0.2f in Q15*/
+ }
+
+ /*----------------------------------------------------------*
+ * calculate the average residual signal energy in four sframes
+ *----------------------------------------------------------*/
+
+ FOR (i_subfr = 0; i_subfr < L_frame; i_subfr += L_SUBFR)
+ {
+ /* calculate the energy of residual signal */
+ tmp16 = mult_r(res[i_subfr+0], 8192); /* remove 2bits */
+ ener_fx = L_mult(tmp16, tmp16);
+ FOR (i=1; i, -2,, -2 and 2 */
+ const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */
+ )
+{
+
+ Word16 index, size, nBits, nBits2;
+ Word16 gcode0, Ei, gain_code16;
+ const Word16 *qua_table;
+ Word16 coeff[5], exp_coeff[5];
+ Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp;
+ Word32 L_tmp, L_tmp1, L_tmp2;
+ Word16 tmp1, expg;
+ Word16 exp1, exp2;
+ Word16 exp_num, exp_den, exp_div, frac_den;
+ Word32 L_frac_num, L_frac_den, L_div;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /*-----------------------------------------------------------------*
+ * calculate the rest of the correlation coefficients
+ * c2 = , c3 = -2, c4 = 2
+ *-----------------------------------------------------------------*/
+
+ coeff[0] = g_corr[0];
+ move16();
+ exp_coeff[0] = g_corr[1];
+ move16();
+ coeff[1] = negate(g_corr[2]);
+ move16(); /* coeff[1] = -2 xn yy1 */
+ exp_coeff[1] = add(g_corr[3], 1);
+ move16();
+
+ /* Compute scalar product */
+ coeff[2] = extract_h(Dot_product12(y2, y2, L_SUBFR, &exp));
+ exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1));
+ move16(); /* -18 (y2 Q9) */
+
+ /* Compute scalar product -2* */
+ coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_SUBFR, &exp)));
+ exp_coeff[3] = add(sub(exp, 9 - 1), Q_xn);
+ move16(); /* -9 (y2 Q9), +1 (2 xn y2) */
+
+ /* Compute scalar product 2* */
+ coeff[4] = extract_h(Dot_product12(y1, y2, L_SUBFR, &exp));
+ exp_coeff[4] = add(sub(exp, 9 - 1), Q_xn);
+ move16(); /* -9 (y2 Q9), +1 (2 y1 y2) */
+
+ /*-----------------------------------------------------------------*
+ * calculate the unscaled innovation energy
+ * calculate the predicted gain code
+ *-----------------------------------------------------------------*/
+
+ /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
+ L_tmp = Dot_product12(code, code, L_SUBFR, &exp_code);
+ exp_inov = sub(exp_code, 18+6);
+ exp_code = sub(exp_code, 30);
+
+ /*Ei = 10 * log10((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
+
+ /*----------------------------------------------------------------*
+ * calculate the predicted gain code
+ *----------------------------------------------------------------*/
+ tmp = norm_l(L_tmp);
+ frac = Log2_norm_lc(L_shl(L_tmp, tmp));
+ tmp = add(30-18-6-1, sub(exp_code, tmp)); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */
+ L_tmp1 = Mpy_32_16(tmp, frac, 12330); /* Q13 */
+ Ei = round_fx(L_shl(L_tmp1, 11)); /* Q8 */
+
+ /* predicted codebook gain */
+ gcode0 = sub(Es_pred, Ei); /* Q8 */
+
+ /*---------------------------------------------------------------*
+ * Decode codebook gain and the adaptive excitation low-pass
+ * filtering factor (Finalize computation )
+ *---------------------------------------------------------------*/
+ /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
+ L_tmp = Isqrt_lc(L_tmp, &exp_inov);
+ *gain_inov = extract_h(L_shl(L_tmp, sub(exp_inov, 3))); /* gain_inov in Q12 */
+
+ /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */
+ /*----------------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20)
+ * = pow(2, 3.321928*gcode0/20)
+ * = pow(2, 0.166096*gcode0)
+ *----------------------------------------------------------------*/
+
+ L_tmp = L_mult(gcode0, 21771); /* *0.166096 in Q17 -> Q26 */
+ L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */
+ frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */
+
+ gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponent so that */
+ /* output of Pow2() will be: */
+ /* 16384 < Pow2() <= 32767 */
+ exp_gcode0 = sub(exp_gcode0, 14);
+
+ /*-----------------------------------------------------------------*
+ * select the codebook, size and number of bits
+ * set the gains searching range
+ *-----------------------------------------------------------------*/
+ nBits = gains_mode[shr(i_subfr, 6)];
+ move16();
+
+ test();test();test();test();test();
+ IF( (EQ_16(tc_subfr,3*L_SUBFR)&&EQ_16(i_subfr,3*L_SUBFR)&&EQ_16(L_frame,L_FRAME))||
+ (EQ_16(tc_subfr,4*L_SUBFR) && EQ_16(i_subfr,4*L_SUBFR) && EQ_16(L_frame,L_FRAME16k) ) )
+ {
+ /* *gain_pit = (g_corr[2]*tmp2) - (0.5f*g_corr[4]*tmp3);
+ = ((-0.5f*g_corr[1]*g_corr[2]) - (-0.25*g_corr[3]*g_corr[4]))/tmp1;
+ = ((0.25*g_corr[3]*g_corr[4]) - (0.5*g_corr[1]*g_corr[2]))/tmp1; */
+
+ /* *gain_code = (g_corr[0]*tmp3) - (0.5f*g_corr[4]*tmp2);
+ = ((-0.5*g_corr[3]*g_corr[0]) - (-0.25*g_corr[1]*g_corr[4]))/tmp1;
+ = ((0.25*g_corr[1]*g_corr[4]) - (0.5*g_corr[0]*g_corr[3]))/tmp1; */
+
+ L_tmp1 = L_mult(coeff[0],coeff[2]); /*Q31*/
+ exp1 = add(exp_coeff[0], exp_coeff[2]);
+
+ L_tmp2 = L_shr(L_mult(coeff[4],coeff[4]),2); /*Q31*/
+ exp2 = add(exp_coeff[4], exp_coeff[4]);
+
+ IF(GT_16(exp1,exp2))
+ {
+ L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/
+ exp_den = exp1;
+ move16();
+ }
+ ELSE
+ {
+ L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/
+ exp_den = exp2;
+ move16();
+ }
+ L_frac_den = L_sub(L_tmp1,L_tmp2); /*Q31*/
+
+ frac_den = extract_h(L_frac_den);
+ frac_den = s_max(frac_den,1);
+ L_frac_den = L_max(L_frac_den,1);
+ exp = norm_l(L_frac_den);
+ tmp = div_s(shl(1,sub(14,exp)),frac_den); /*Q(14-exp)*/
+
+ L_tmp1 = L_shr(L_mult(coeff[3],coeff[4]),2); /*Q31*/
+ exp1 = add(exp_coeff[3], exp_coeff[4]);
+
+ L_tmp2 = L_shr(L_mult(coeff[1],coeff[2]),1); /*Q31*/
+ exp2 = add(exp_coeff[1], exp_coeff[2]);
+
+ IF(GT_16(exp1,exp2))
+ {
+ L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/
+ exp_num = exp1;
+ move16();
+ }
+ ELSE
+ {
+ L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/
+ exp_num = exp2;
+ move16();
+ }
+ L_frac_num = L_sub(L_tmp1,L_tmp2); /*Q31*/
+
+ L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/
+ exp_div = sub(exp_num,exp_den);
+
+#ifdef BASOP_NOGLOB
+ *gain_pit = round_fx_o(L_shl_o(L_div,add(exp,exp_div), &Overflow), &Overflow); /*Q14*/
+#else
+ *gain_pit = round_fx(L_shl(L_div,add(exp,exp_div))); /*Q14*/
+#endif
+
+ L_tmp1 = L_shr(L_mult(coeff[1],coeff[4]),2); /*Q31*/
+ exp1 = add(exp_coeff[1], exp_coeff[4]);
+
+ L_tmp2 = L_shr(L_mult(coeff[0],coeff[3]),1); /*Q31*/
+ exp2 = add(exp_coeff[0], exp_coeff[3]);
+
+ IF(GT_16(exp1,exp2))
+ {
+ L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/
+ exp_num = exp1;
+ }
+ ELSE
+ {
+ L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/
+ exp_num = exp2;
+ }
+ L_frac_num = L_sub(L_tmp1,L_tmp2); /*Q31*/
+
+ L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/
+ exp_div = sub(exp_num,exp_den);
+
+#ifdef BASOP_NOGLOB
+ *gain_code = L_shl_o(L_div,sub(add(exp,exp_div),14), &Overflow);
+#else
+ *gain_code = L_shl(L_div,sub(add(exp,exp_div),14));
+#endif
+ move32();/*Q16*/
+
+ *gain_pit = s_max(G_PITCH_MIN_TC192_Q14,s_min(*gain_pit,G_PITCH_MAX_TC192_Q14));
+
+ /* set number of bits for two SQs */
+ nBits2 = shr(add(nBits,1),1);
+ nBits = shr(nBits,1);
+
+ /* gain_pit Q */
+
+ tmp1 = mult_r(G_PITCH_MAX_MINUS_MIN_TC192_Q13,div_s(1,sub(shl(1, nBits), 1))); /*Q13*/ /* set quantization step */
+ index = usquant_fx( *gain_pit, gain_pit, G_PITCH_MIN_TC192_Q14, tmp1, shl(1, nBits) );
+ move16();
+ push_indice_fx( hBstr, IND_GAIN_PIT, index, nBits );
+
+ /* gain_code Q */
+ /**gain_code /= gcode0;*/
+ IF(gcode0 != 0)
+ {
+ tmp = div_s(16384,gcode0); /*Q15*/
+ L_tmp = Mult_32_16(*gain_code,tmp); /*Q16*/
+ *gain_code = L_shr(L_tmp,add(14,exp_gcode0)); /*Q16*/
+ }
+
+ index = gain_quant_fx( gain_code, &gain_code16, LG10_G_CODE_MIN_TC192_Q14, LG10_G_CODE_MAX_TC192_Q13, nBits2, &expg );
+ push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits2 );
+ L_tmp = L_mult(gain_code16,gcode0); /*Q0*Q0 -> Q1*/
+#ifdef BASOP_NOGLOB
+ *gain_code = L_shl_o(L_tmp,add(add(expg,exp_gcode0),15), &Overflow); /*Q16*/
+#else
+ *gain_code = L_shl(L_tmp,add(add(expg,exp_gcode0),15)); /*Q16*/
+#endif
+ }
+ ELSE
+ {
+ size = shl(1,nBits);
+
+ SWITCH ( nBits )
+ {
+ case 7:
+ {
+ qua_table = gain_qua_mless_7b_fx;
+ move16();
+ if (EQ_16(clip_gain, 1))
+ {
+ size = sub(size, 30);
+ }
+ BREAK;
+ }
+ case 6:
+ {
+ qua_table = gain_qua_mless_6b_fx;
+ if (GT_16(element_mode, EVS_MONO))
+ {
+#ifdef IVAS_CODE
+ qua_table = gain_qua_mless_6b_stereo;
+#else
+ //PMTE()
+#endif
+ }
+ move16();
+ if (EQ_16(clip_gain, 1))
+ {
+ size = sub(size, 14);
+ }
+ BREAK;
+ }
+ case 5:
+ {
+ qua_table = gain_qua_mless_5b_fx;
+ move16();
+ if (EQ_16(clip_gain, 1))
+ {
+ size = sub(size, 6);
+ }
+ BREAK;
+ }
+ default:
+ {
+ qua_table = gain_qua_mless_6b_fx;
+ move16();
+ if (EQ_16(clip_gain, 1))
+ {
+ size = sub(size, 14);
+ }
+ BREAK;
+ }
+ }
+
+ /* in case of AVQ inactive, limit the gain_pit to 0.65 */
+ test();
+ IF( EQ_16(clip_gain,2)&&EQ_16(nBits,6))
+ {
+ size = sub(size,36);
+ nBits = sub(nBits,1);
+ }
+
+ /*-----------------------------------------------------------------*
+ * search for the best quantizer
+ *-----------------------------------------------------------------*/
+ index = Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, qua_table, size);
+ push_indice_fx( hBstr, IND_GAIN, index, nBits );
+ }
+
+ /* *norm_gain_code = *gain_code / *gain_inov; */
+ exp = sub(norm_s(*gain_inov),1);
+ exp = s_max(exp, 0);
+
+ tmp = div_s(shr(8192,exp),*gain_inov);
+ *norm_gain_code = L_shr(Mult_32_16(*gain_code, tmp),sub(1,exp));
+ move32();
+
+ return;
+}
+
+
+/*---------------------------------------------------------------------*
+* gain_enc_SQ()
+*
+* Scalar Quantization of pitch and codebook gains without prediction
+* - an initial predicted gain, gcode0, is first determined based on
+* the predicted scaled innovation energy
+* - a correction factor gamma = g_code / gcode0 is then vector quantized
+* along with gain_pit
+* - the mean-squared weighted error criterion is used for codebook search
+*---------------------------------------------------------------------*/
+
+void gain_enc_SQ_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
+ const Word16 gains_mode[], /* i : gain bits */
+ const Word16 i_subfr, /* i : subframe index */
+ const Word16 *xn, /* i : target vector Q_xn */
+ const Word16 *yy1, /* i : zero-memory filtered adaptive excitation Q_xn */
+ const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9 */
+ const Word16 *code, /* i : algebraic excitation Q9 */
+ const Word16 Es_pred, /* i : predicted scaled innovation energy Q8 */
+ Word16 *gain_pit, /* o : quantized pitch gain Q14 */
+ Word32 *gain_code, /* o : quantized codebook gain Q16 */
+ Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12 */
+ Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16 */
+ Word16 *g_corr, /* i/o: correlations , ,, -2 and 2 */
+ const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */
+ const Word16 Q_xn /* i : xn and y1 scaling */
+)
+{
+ Word16 index, nBits_pitch, nBits_code;
+ Word16 gcode0, Ei, gain_code16;
+ Word16 coeff[5], exp_coeff[5];
+ Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp;
+
+ Word32 L_tmp, L_tmp1, L_tmp2;
+ Word16 tmp1, expg;
+ Word16 exp1, exp2;
+ Word16 exp_num, exp_den, exp_div, frac_den;
+ Word32 L_frac_num, L_frac_den, L_div;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+ /*-----------------------------------------------------------------*
+ * calculate the rest of the correlation coefficients
+ * c2 = , c3 = -2, c4 = 2
+ *-----------------------------------------------------------------*/
+ /*g_corr[1] *= -0.5;*/
+ /*g_corr[2] = dotp( y2, y2, L_SUBFR ) + 0.01f;*/
+ /*g_corr[3] = dotp( xn, y2, L_SUBFR ) - 0.02f;*/
+ /*g_corr[4] = dotp( yy1, y2, L_SUBFR ) + 0.02f;*/
+
+ coeff[0] = g_corr[0];
+ move16();
+ exp_coeff[0] = g_corr[1];
+ move16();
+ coeff[1] = g_corr[2];
+ move16(); /* coeff[1] = xn yy1 */
+ exp_coeff[1] = g_corr[3];
+ move16();
+
+ /* Compute scalar product */
+ coeff[2] = extract_h(Dot_product12(y2, y2, L_SUBFR, &exp));
+ exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1));
+ move16(); /* -18 (y2 Q9) */
+
+ /* Compute scalar product */
+ coeff[3] = extract_h(Dot_product12(xn, y2, L_SUBFR, &exp));
+ exp_coeff[3] = add(sub(exp, 9 ), Q_xn);
+ move16(); /* -9 (y2 Q9), (xn y2) */
+
+ /* Compute scalar product */
+ coeff[4] = extract_h(Dot_product12(yy1, y2, L_SUBFR, &exp));
+ exp_coeff[4] = add(sub(exp, 9), Q_xn);
+ move16(); /* -9 (y2 Q9), (y1 y2) */
+
+ /*-----------------------------------------------------------------*
+ * calculate the unscaled innovation energy
+ * calculate the predicted gain code
+ * calculate optimal gains
+ *-----------------------------------------------------------------*/
+ /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR;*/
+ /**gain_inov = 1.0f / (float)sqrt( Ecode );*/
+
+ L_tmp = Dot_product12(code, code, L_SUBFR, &exp_code);
+ exp_inov = sub(exp_code, 18+6);
+ exp_code = sub(exp_code, 30);
+
+ /*Ei = 10 * log10((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
+ /*----------------------------------------------------------------*
+ * calculate the predicted gain code
+ *----------------------------------------------------------------*/
+ tmp = norm_l(L_tmp);
+ frac = Log2_norm_lc(L_shl(L_tmp, tmp));
+ tmp = add(30-18-6-1, sub(exp_code, tmp)); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */
+ L_tmp1 = Mpy_32_16(tmp, frac, 12330); /* Q13 */
+ Ei = round_fx(L_shl(L_tmp1, 11)); /* Q8 */
+
+ /* predicted codebook gain */
+ gcode0 = sub(Es_pred, Ei); /* Q8 */
+
+ /*---------------------------------------------------------------*
+ * Decode codebook gain and the adaptive excitation low-pass
+ * filtering factor (Finalize computation )
+ *---------------------------------------------------------------*/
+ /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
+ L_tmp = Isqrt_lc(L_tmp, &exp_inov);
+ *gain_inov = extract_h(L_shl(L_tmp, sub(exp_inov, 3))); /* gain_inov in Q12 */
+
+ /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */
+ /*----------------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20)
+ * = pow(2, 3.321928*gcode0/20)
+ * = pow(2, 0.166096*gcode0)
+ *----------------------------------------------------------------*/
+
+ L_tmp = L_mult(gcode0, 21771); /* *0.166096 in Q17 -> Q26 */
+ L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */
+ frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */
+
+ gcode0 = extract_l(Pow2(14, frac)); /* Put 14 as exponent so that */
+ /* output of Pow2() will be: */
+ /* 16384 < Pow2() <= 32767 */
+ exp_gcode0 = sub(exp_gcode0, 14);
+
+
+ /*tmp1 = (g_corr[0]*g_corr[2]) - (g_corr[4]*g_corr[4]);
+ tmp2 = g_corr[1]/tmp1;
+ tmp1 = g_corr[3]/tmp1;
+
+ *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp1);
+ *gain_code = (g_corr[0]*tmp1) - (g_corr[4]*tmp2);*/
+
+ /* *gain_pit = (g_corr[2]*tmp2) - (g_corr[4]*tmp3);
+ = ((g_corr[1]*g_corr[2]) - (g_corr[3]*g_corr[4]))/tmp1;*/
+
+ /* *gain_code = (g_corr[0]*tmp3) - (g_corr[4]*tmp2);
+ = ((g_corr[3]*g_corr[0]) - (g_corr[1]*g_corr[4]))/tmp1;*/
+
+ L_tmp1 = L_mult(coeff[0],coeff[2]); /*Q31*/
+ exp1 = add(exp_coeff[0], exp_coeff[2]);
+
+#ifdef BASOP_NOGLOB
+ L_tmp2 = L_mult_o(coeff[4],coeff[4], &Overflow); /*Q31*/
+#else
+ L_tmp2 = L_mult(coeff[4],coeff[4]); /*Q31*/
+#endif
+ exp2 = add(exp_coeff[4], exp_coeff[4]);
+
+ IF(GT_16(exp1,exp2))
+ {
+ L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/
+ exp_den = exp1;
+ move16();
+ }
+ ELSE
+ {
+ L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/
+ exp_den = exp2;
+ move16();
+ }
+ L_frac_den = L_sub(L_tmp1,L_tmp2); /*Q31*/
+
+ frac_den = extract_h(L_frac_den);
+ frac_den = s_max(frac_den,1);
+ L_frac_den = L_max(L_frac_den,1);
+ exp = norm_l(L_frac_den);
+ tmp = div_s(shl(1,sub(14,exp)),frac_den); /*Q(14-exp)*/
+
+
+
+ L_tmp1 = L_mult(coeff[3],coeff[4]); /*Q31*/
+ exp1 = add(exp_coeff[3], exp_coeff[4]);
+
+ L_tmp2 = L_mult(coeff[1],coeff[2]); /*Q31*/
+ exp2 = add(exp_coeff[1], exp_coeff[2]);
+
+ IF(GT_16(exp1,exp2))
+ {
+ L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/
+ exp_num = exp1;
+ move16();
+ }
+ ELSE
+ {
+ L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/
+ exp_num = exp2;
+ move16();
+ }
+#ifdef BASOP_NOGLOB
+ L_frac_num = L_sub_o(L_tmp2, L_tmp1, &Overflow); /*Q31*/
+#else /* BASOP_NOGLOB */
+ L_frac_num = L_sub(L_tmp2, L_tmp1); /*Q31*/
+#endif /* BASOP_NOGLOB */
+
+ L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/
+ exp_div = sub(exp_num,exp_den);
+
+#ifdef BASOP_NOGLOB
+ *gain_pit = round_fx_o(L_shl_o(L_div,add(exp,exp_div), &Overflow), &Overflow); /*Q14*/
+#else /* BASOP_NOGLOB */
+ *gain_pit = round_fx(L_shl(L_div,add(exp,exp_div))); /*Q14*/
+#endif /* BASOP_NOGLOB */
+
+ L_tmp1 = L_mult(coeff[1],coeff[4]); /*Q31*/
+ exp1 = add(exp_coeff[1], exp_coeff[4]);
+
+ L_tmp2 = L_mult(coeff[0],coeff[3]); /*Q31*/
+ exp2 = add(exp_coeff[0], exp_coeff[3]);
+
+ IF(GT_16(exp1,exp2))
+ {
+ L_tmp2 = L_shr(L_tmp2,sub(exp1,exp2)); /*Q31*/
+ exp_num = exp1;
+ }
+ ELSE
+ {
+ L_tmp1 = L_shr(L_tmp1,sub(exp2,exp1)); /*Q31*/
+ exp_num = exp2;
+ }
+#ifdef BASOP_NOGLOB
+ L_frac_num = L_sub_o(L_tmp2, L_tmp1, &Overflow); /*Q31*/
+#else /* BASOP_NOGLOB */
+ L_frac_num = L_sub(L_tmp2, L_tmp1); /*Q31*/
+#endif /* BASOP_NOGLOB */
+
+ L_div = Mult_32_16(L_frac_num,tmp); /*Q(30-exp)*/
+ exp_div = sub(exp_num,exp_den);
+
+ *gain_code = L_shl(L_div,s_max(-31,sub(add(exp,exp_div),14)));
+ move32();/*Q16*/
+
+ *gain_pit = s_max(G_PITCH_MIN_Q14,s_min(*gain_pit,G_PITCH_MAX_Q14));
+
+ /*-----------------------------------------------------------------*
+ * limit the pitch gain searching range (if indicated by clip_gain)
+ *-----------------------------------------------------------------*/
+
+ test();
+ test();
+ IF( EQ_16(clip_gain,1)&>_16(*gain_pit,15565))
+ {
+ *gain_pit = 15565;
+ move16();
+ }
+ ELSE IF( EQ_16(clip_gain,2)&>_16(*gain_pit,10650))
+ {
+ *gain_pit = 10650;
+ move16();
+ }
+
+ /*-----------------------------------------------------------------*
+ * search for the best quantized values
+ *-----------------------------------------------------------------*/
+
+ nBits_pitch = gains_mode[shr(i_subfr,6)];
+
+ /* set number of bits for two SQs */
+ nBits_code = shr(add(nBits_pitch,1),1);
+ nBits_pitch = shr(nBits_pitch,1);
+
+ /* gain_pit Q */
+ /*tmp1 = (G_PITCH_MAX - G_PITCH_MIN) / ((1 << nBits_pitch) - 1);*/ /* set quantization step */
+ tmp1 = mult_r(G_PITCH_MAX_Q13,div_s(1,sub(shl(1, nBits_pitch), 1))); /*Q13*/ /* set quantization step */
+
+ index = usquant_fx( *gain_pit, gain_pit, G_PITCH_MIN_Q14, tmp1, shl(1, nBits_pitch) );
+ move16();
+ push_indice_fx( hBstr, IND_GAIN_PIT, index, nBits_pitch );
+
+ /* gain_code Q */
+ /* *gain_code /= gcode0; */
+ IF(gcode0 != 0)
+ {
+ tmp = div_s(16384,gcode0); /*Q15*/
+ L_tmp = Mult_32_16(*gain_code,tmp); /*Q16*/
+ *gain_code = L_shr(L_tmp,add(14,exp_gcode0)); /*Q16*/
+ }
+
+ index = gain_quant_fx( gain_code, &gain_code16, LG10_G_CODE_MIN_Q14, LG10_G_CODE_MAX_Q13, nBits_code, &expg );
+ push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits_code );
+ L_tmp = L_mult(gain_code16,gcode0); /*Q0*Q0 -> Q1*/
+ *gain_code = L_shl(L_tmp,add(add(expg,exp_gcode0),15));
+ move32(); /*Q16*/
+
+ /* *norm_gain_code = *gain_code / *gain_inov; */
+ exp = sub(norm_s(*gain_inov),1);
+ exp = s_max(exp, 0);
+
+ tmp = div_s(shr(8192,exp),*gain_inov);
+ *norm_gain_code = L_shr(Mult_32_16(*gain_code, tmp),sub(1,exp));
+ move32();
+
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * gain_enc_gaus()
+ *
+ * Quantization of gain for Gaussian codebook
+ *-------------------------------------------------------------------*/
+Word16 gain_enc_gaus_fx( /* o : Return index of quantization */
+ Word32 *gain, /* i/o: Code gain to quantize */
+ const Word16 bits, /* i : number of bits to quantize */
+ const Word16 lowBound, /* i : lower bound of quantizer (dB) Q8 */
+ const Word16 stepSize, /* i : Step size choice Q14 */
+ const Word16 inv_stepSize /* i : Step size choice Q15 */
+)
+{
+ Word16 index, exp_gain, frac_gain, wtmp;
+ Word16 enr_q, wenr;
+ Word32 Ltmp, enr;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+ /*enr = 20.0 * log10(*gain + 0.001) codebook gain in dB */
+ exp_gain = norm_l(*gain);
+ frac_gain = Log2_norm_lc(L_shl(*gain, exp_gain));
+ exp_gain = sub(30-16, exp_gain);
+
+ enr = Mpy_32_16(exp_gain, frac_gain, LG10); /* Output in Q13 */
+ wenr = extract_h(L_shl(enr, 8+3));
+
+ /*----------------------------------------------------------------*
+ * Quantize linearly the log E
+ *----------------------------------------------------------------*/
+
+ wtmp = sub(wenr, lowBound); /* Q8 */
+
+ index = extract_l(L_shr(L_mac(8388608, wtmp, inv_stepSize),16+8));
+
+ /* index [0 (1< Q26 */
+ enr = L_shr(enr, 10); /*Q26->Q16*/
+ frac_gain = L_Extract_lc(enr, &exp_gain);
+
+ Ltmp = Pow2(14, frac_gain); /* Put 14 as exponent */
+ exp_gain= sub(exp_gain, 14); /* Retreive exponent of wtmp */
+#ifdef BASOP_NOGLOB
+ *gain = L_shl_o(Ltmp ,add(16,exp_gain), &Overflow);
+#else
+ *gain = L_shl(Ltmp ,add(16,exp_gain));
+#endif
+ move32(); /*Q16*/
+
+ return index;
+}
+/*-----------------------------------------------------------------*
+ * gain_enc_tc()
+ *
+ * Search and quantization of gain_code for subframes (in the
+ * beginning of frame) without pulses in TC - 3b coding.
+ * In this case:
+ * - gain_pit = 0
+ * - gain_code - scalar quantization (no prediciton history used)
+ *-----------------------------------------------------------------*/
+void gain_enc_tc_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
+ const Word16 gains_mode[], /* i : gain bits */
+ const Word16 i_subfr, /* i : subframe index */
+ const Word16 xn_fx[], /* i : target vector */
+ const Word16 y2_fx[], /* i : zero-memory filtered algebraic codebook excitation */
+ const Word16 code_fx[], /* i : algebraic excitation */
+ const Word16 Es_pred_fx, /* i : predicted scaled innovation energy */
+ Word16 *gain_pit_fx, /* o : Pitch gain / Quantized pitch gain */
+ Word32 *gain_code_fx, /* o : quantized codebook gain */
+ Word16 *gain_inov_fx, /* o : innovation gain */
+ Word32 *norm_gain_code_fx, /* o : norm. gain of the codebook excitation */
+ const Word16 Q_xn /* i : xn and y1 scaling Q0 */
+)
+{
+ Word16 i, index=0, nBits, num, den, exp_num, exp_den;
+ Word16 Ei_fx, g_code_fx, gcode0_fx;
+ Word16 expg, expg2, e_tmp, f_tmp, exp_gcode0, tmp_fx, frac,tmp16;
+ Word32 L_tmp, L_tmp1;
+ Word16 wgain_code=0, gain_code16;
+ *gain_pit_fx = 0;
+ move16();
+ /*----------------------------------------------------------------*
+ * get number of bits for gain quantization
+ *----------------------------------------------------------------*/
+ nBits = gains_mode[shr(i_subfr,6)];
+
+ /*----------------------------------------------------------------*
+ * find the code pitch (for current subframe)
+ *----------------------------------------------------------------*/
+
+ /**gain_code = dotp( xn, y2, L_SUBFR )/( dotp( y2, y2, L_SUBFR ) + 0.01f );*/
+ /* Compute scalar product */
+ L_tmp = Dot_product(y2_fx, y2_fx, L_SUBFR); /* -18 (y2 Q9) */
+ exp_den = norm_l(L_tmp);
+ den = extract_h(L_shl(L_tmp, exp_den));
+ exp_den = sub(add(exp_den, 18), shl(Q_xn, 1));
+
+ /* Compute scalar product */
+ L_tmp1 = Dot_product(xn_fx, y2_fx, L_SUBFR); /* -9 (y2 Q9) */
+ exp_num = sub(norm_l(L_tmp1),1);
+ num = extract_h(L_shl(L_tmp1, exp_num));
+ exp_num = sub(add(exp_num, 8 ), Q_xn);
+
+ tmp16 = s_or(shr(num, 16), 1); /* extract sign if num < 0 tmp16 = -1 else tmp16 = 1 */
+ num = abs_s(num);
+
+ /*----------------------------------------------------------------*
+ * compute gain = xy/yy
+ *----------------------------------------------------------------*/
+ g_code_fx = div_s(num, den);
+
+ i = sub(exp_num, exp_den); /* Gain_trans in Q7 */
+ g_code_fx = i_mult2(g_code_fx, tmp16); /* apply sign */
+ *gain_code_fx = L_shr(L_deposit_l(g_code_fx),i);
+ move32();
+
+ /*----------------------------------------------------------------*
+ * calculate the predicted gain code
+ * decode codebook gain
+ *----------------------------------------------------------------*/
+
+ *gain_pit_fx = 0;
+ move16();
+
+ /*Ecode = (dotp( code, code, L_SUBFR) + 0.01f) / L_SUBFR;
+ *gain_inov = 1.0f / (float)sqrt( Ecode );*/
+
+ L_tmp = Dot_product12(code_fx, code_fx, L_SUBFR, &expg);
+ expg = sub(expg, 18 + 6); /* exp: -18 (code in Q9), -6 (/L_SUBFR) */
+ expg2 = expg;
+ move16();
+ L_tmp1 = L_tmp; /* sets to 'L_tmp' in 1 clock */
+ move32();
+ L_tmp = Isqrt_lc(L_tmp, &expg);
+
+ *gain_inov_fx = extract_h(L_shl(L_tmp, sub(expg, 3)));
+ move16();/* gain_inov in Q12 */
+
+ /*Ei = 10 * (float)log10( Ecode );*/
+ e_tmp = norm_l(L_tmp1);
+ f_tmp = Log2_norm_lc(L_shl(L_tmp1, e_tmp));
+ e_tmp = sub(expg2,add(1,e_tmp));
+ L_tmp1 = Mpy_32_16(e_tmp, f_tmp, 12330); /* Q13 */ /* 10*log10(2) in Q12*/
+ Ei_fx = round_fx(L_shl(L_tmp1, 11)); /* Q8 */
+ /*gcode0 = (float) pow(10, 0.05 * (Es_pred - Ei));*/
+ gcode0_fx = sub(Es_pred_fx, Ei_fx); /* Q8 */
+ /*-----------------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20)
+ * = pow(2, 3.321928*gcode0/20)
+ * = pow(2, 0.166096*gcode0)
+ *-----------------------------------------------------------------*/
+ L_tmp = L_mult(gcode0_fx, 21771); /* *0.166096 in Q17 -> Q26 */
+ L_tmp = L_shr(L_tmp, 10); /* From Q26 to Q16 */
+ frac = L_Extract_lc(L_tmp, &exp_gcode0); /* Extract exponent of gcode0 */
+ gcode0_fx = extract_l(Pow2(14, frac));/* Put 14 as exponent so that */
+ exp_gcode0 = sub(exp_gcode0, 14);
+ IF( GT_16(nBits,3))
+ {
+ /*g_code = *gain_code / gcode0;*/
+ IF(gcode0_fx != 0)
+ {
+ tmp16 = div_s(16384,gcode0_fx); /*Q15*/
+ L_tmp = Mult_32_16(*gain_code_fx,tmp16); /*Q16*/
+ *gain_code_fx = L_shr(L_tmp,add(14,exp_gcode0)); /*Q16*/
+ }
+ ELSE
+ {
+ *gain_code_fx = MAX_32;
+ move32();
+ }
+
+ /*index = gain_quant( &g_code, G_CODE_MIN, G_CODE_MAX, nBits );*/
+ index = gain_quant_fx( gain_code_fx, &gain_code16, LG10_G_CODE_MIN_TC_Q14, LG10_G_CODE_MAX_TC_Q13, nBits, &expg );
+
+ /**gain_code = g_code * gcode0;*/
+ L_tmp = L_mult(gain_code16,gcode0_fx); /*Q0*Q0 -> Q1*/
+ *gain_code_fx = L_shl(L_tmp,add(add(expg,exp_gcode0),15)); /*Q16*/ move32();
+
+ push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits );
+ }
+ ELSE
+ {
+ index = N_GAIN_CODE_TC-1;
+ move16();
+ FOR( i=0; i < N_GAIN_CODE_TC-1; i++ )
+ {
+ L_tmp = L_mult(tbl_gain_code_tc_quant_mean[i], gcode0_fx); /* Q13*Q0 -> Q14 */
+ L_tmp = L_shl(L_tmp, add(exp_gcode0, 2)); /* Q14 -> Q16 */
+
+ IF( LT_32(*gain_code_fx, L_tmp))
+ {
+ index = i;
+ move16();
+ BREAK;
+ }
+ }
+ /*----------------------------------------------------------------*
+ * 3-bit -> 2-bit encoding
+ *----------------------------------------------------------------*/
+ IF( EQ_16(nBits,2))
+ {
+ /* 2-bit -> 3-bit decoding */
+ index = shr(index ,1);
+ wgain_code = tbl_gain_code_tc_fx[shl(index,1)];
+ move16();
+ /**gain_code *= gcode0;*/
+ L_tmp = L_mult(wgain_code, gcode0_fx); /* Q13*Q0 -> Q14 */
+ *gain_code_fx= L_shl(L_tmp, add(exp_gcode0, 2));
+ move32(); /* Q14 -> Q16 */
+ push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits );
+ }
+ ELSE /* nBits == 3 */
+ {
+ wgain_code = tbl_gain_code_tc_fx[index];
+ move16();
+ /**gain_code *= gcode0;*/
+ L_tmp = L_mult(wgain_code, gcode0_fx); /* Q13*Q0 -> Q14 */
+ *gain_code_fx= L_shl(L_tmp, add(exp_gcode0, 2));
+ move32(); /* Q14 -> Q16 */
+ push_indice_fx( hBstr, IND_GAIN_CODE, index, nBits );
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * decode normalized codebook gain
+ *-----------------------------------------------------------------*/
+ /**norm_gain_code = *gain_code / *gain_inov;*/
+ expg = sub(norm_s(*gain_inov_fx),1);
+ expg = s_max(expg, 0);
+
+ tmp_fx = div_s(shr(8192,expg),*gain_inov_fx);
+ *norm_gain_code_fx = L_shr(Mult_32_16(*gain_code_fx, tmp_fx),sub(1,expg));
+ move32();
+ return;
+}
+/*-----------------------------------------------------------------*
+ * Find_Opt_gainQ_fx()
+ *
+ * Find the best quantizer
+ *-----------------------------------------------------------------*/
+static Word16 Find_Opt_gainQ_fx(
+ Word16 *coeff,
+ Word16 *exp_coeff,
+ Word16 *gain_pit,
+ Word32 *gain_code,
+ Word16 gcode0,
+ Word16 exp_gcode0,
+ const Word16 *cdbk, /* i : Codebook used */
+ const Word16 size /* i : size of Codebook used */
+)
+{
+ Word16 index, i, j;
+ const Word16 *p;
+ Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo;
+ Word32 dist_min;
+ Word16 coeff_lo[5];
+ Word16 exp_max[5];
+ Word16 exp_code, e_max;
+ Word32 L_tmp, L_tmp1;
+#ifdef BASOP_NOGLOB_DECLARE_LOCAL
+ Flag Overflow = 0;
+#endif
+
+
+ /*----------------------------------------------------------------*
+ * Find the best quantizer
+ * ~~~~~~~~~~~~~~~~~~~~~~~
+ * Before doing the computation we need to align exponents of coeff[]
+ * to be sure to have the maximum precision.
+ *
+ * In the table the pitch gains are in Q14, the code gains are in Q9 and
+ * are multiply by gcode0 which have been multiply by 2^exp_gcode0.
+ * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code
+ * we divide by 2^15.
+ * Considering all the scaling above we have:
+ *
+ * exp_code = exp_gcode0-9+15 = exp_gcode0+6
+ *
+ * g_pitch*g_pitch = -14-14+15
+ * g_pitch = -14
+ * g_code*g_code = (2*exp_code)+15
+ * g_code = exp_code
+ * g_pitch*g_code = -14 + exp_code +15
+ *
+ * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13
+ * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14
+ * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code)
+ * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code
+ * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code
+ *----------------------------------------------------------------*/
+
+ exp_code = add(exp_gcode0, 6);
+
+ exp_max[0] = sub(exp_coeff[0], 13);
+ move16();
+ exp_max[1] = sub(exp_coeff[1], 14);
+ move16();
+ exp_max[2] = add(exp_coeff[2], add(15, shl(exp_code, 1)));
+ move16();
+ exp_max[3] = add(exp_coeff[3], exp_code);
+ move16();
+ exp_max[4] = add(exp_coeff[4], add(1, exp_code));
+ move16();
+
+ /* Find maximum exponant */
+ e_max = exp_max[0];
+ move16();
+ FOR (i = 1; i < 5; i++)
+ {
+ e_max = s_max(exp_max[i], e_max);
+ }
+
+ /* align coeff[] and save in special 32 bit double precision */
+ FOR (i = 0; i < 5; i++)
+ {
+ j = add(sub(e_max, exp_max[i]), 2); /* /4 to avoid overflow */
+ L_tmp = L_deposit_h(coeff[i]);
+ L_tmp = L_shr(L_tmp, j);
+ L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
+ coeff_lo[i] = shr(coeff_lo[i], 3);/* lo >> 3 */ move16();
+ }
+
+ /* searching of codebook */
+ p = cdbk;
+ move16();
+ dist_min = L_deposit_h(MAX_16);
+ index = 0;
+ move16();
+ FOR (i = 0; i < size; i++)
+ {
+ g_pitch = *p++;
+ move16();
+ g_code = *p++;
+ move16();
+
+ g_code = mult_r(g_code, gcode0);
+ g2_pitch = mult_r(g_pitch, g_pitch);
+ g_pit_cod = mult_r(g_code, g_pitch);
+ L_tmp = L_mult(g_code, g_code);
+ g2_code_lo = L_Extract_lc(L_tmp, &g2_code);
+
+ L_tmp = L_mult(coeff[2], g2_code_lo);
+ L_tmp = L_shr(L_tmp, 3);
+ L_tmp = L_mac(L_tmp, coeff_lo[0], g2_pitch);
+ L_tmp = L_mac(L_tmp, coeff_lo[1], g_pitch);
+ L_tmp = L_mac(L_tmp, coeff_lo[2], g2_code);
+ L_tmp = L_mac(L_tmp, coeff_lo[3], g_code);
+ L_tmp = L_mac(L_tmp, coeff_lo[4], g_pit_cod);
+ L_tmp = L_shr(L_tmp, 12);
+ L_tmp = L_mac(L_tmp, coeff[0], g2_pitch);
+ L_tmp = L_mac(L_tmp, coeff[1], g_pitch);
+ L_tmp = L_mac(L_tmp, coeff[2], g2_code);
+ L_tmp = L_mac(L_tmp, coeff[3], g_code);
+ L_tmp = L_mac(L_tmp, coeff[4], g_pit_cod);
+
+#ifdef BASOP_NOGLOB
+ L_tmp1 = L_sub_o(L_tmp, dist_min, &Overflow);
+#else /* BASOP_NOGLOB */
+ L_tmp1 = L_sub(L_tmp, dist_min);
+#endif /* BASOP_NOGLOB */
+ if (L_tmp1 < 0)
+ {
+ index = i;
+ move16();
+ }
+ dist_min = L_min(L_tmp, dist_min);
+ }
+
+ p = &cdbk[add(index, index)];
+ move16();
+
+ *gain_pit = *p++; /* selected pitch gain in Q14 */ move16();
+ g_code = *p++; /* selected code gain in Q9 */ move16();
+
+ L_tmp = L_mult(g_code, gcode0); /* Q9*Q0 -> Q10 */
+ L_tmp = L_shl(L_tmp, add(exp_gcode0, 6)); /* Q10 -> Q16 */
+
+ *gain_code = L_tmp; /* gain of code in Q16 */ move16();
+ return index;
+}
+/*---------------------------------------------------------------------*
+ * gain_enc_lbr()
+ *
+ * Quantization of pitch and codebook gains without prediction (memory-less)
+ * in ACELP at 6.6 and 7.5 kbps
+ * - the gain codebooks and gain estimation constants are different in each subframe
+ * - the estimated gain, gcode0, is first determined based on
+ * classification and/or previous quantized gains (from previous subframes in the current frame)
+ * - a correction factor gamma = g_code / gcode0 is then vector quantized
+ * along with gain_pit
+ * - the mean-squared error criterion is used for codebook search
+ *---------------------------------------------------------------------*/
+
+void gain_enc_lbr_fx(
+ BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */
+ const Word16 gains_mode[], /* i : gain bits */
+ const Word16 coder_type, /* i : coding type */
+ const Word16 i_subfr, /* i : subframe index */
+ const Word16 *xn, /* i : target vector Q_xn*/
+ const Word16 *y1, /* i : zero-memory filtered adaptive excitation Q_xn*/
+ const Word16 Q_xn, /* i : xn and y1 format */
+ const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation Q9*/
+ const Word16 *code, /* i : algebraic excitation Q9*/
+ Word16 *gain_pit, /* o : quantized pitch gain Q14*/
+ Word32 *gain_code, /* o : quantized codebook gain Q16*/
+ Word16 *gain_inov, /* o : gain of the innovation (used for normalization) Q12*/
+ Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation Q16*/
+ Word16 *g_corr, /* i/o: correlations , -2,, -2 and 2 mant/exp*/
+ Word32 gc_mem[], /* i/o: gain_code from previous subframes */
+ Word16 gp_mem[], /* i/o: gain_pitch from previous subframes */
+ const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */
+ const int16_t L_subfr /* i : subframe length */
+)
+{
+
+ Word16 index = 0, size, nBits, n_pred, ctype;
+ const Word16 *b, *cdbk = 0;
+ Word16 gcode0, aux[10];
+ Word16 coeff[5], exp_coeff[5];
+ Word16 exp, exp_code, exp_inov, exp_gcode0, frac, tmp, L_subfr_sf;
+ Word32 L_tmp, L_tmp1, L_inov;
+
+ L_subfr_sf = 6;
+ move16();
+ if (GT_16(L_subfr, L_SUBFR))
+ {
+ L_subfr_sf = 7;
+ move16();
+ }
+ /*-----------------------------------------------------------------*
+ * calculate the rest of the correlation coefficients
+ * c2 = , c3 = -2, c4 = 2