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, c5* = + * c5* - not necessary to calculate + *-----------------------------------------------------------------*/ + + 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 */ +#ifdef DEBUG + if (L_subfr != L_SUBFR) + { + PMT("Entire function needs review to accommode for L_subfr > L_SUBFR"); + } +#endif + coeff[2] = extract_h(Dot_product12(y2, y2, L_subfr, &exp)); + exp_coeff[2] = add(sub(exp, 18), shl(Q_xn, 1)); /* -18 (y2 Q9) */ move16(); + + /* 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); /* -9 (y2 Q9), +1 (2 xn y2) */ move16(); + + /* 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); /* -9 (y2 Q9), +1 (2 yy1 y2) */ move16(); + + /*g_corr[2] += 0.01F; g_corr[3] -= 0.02F; g_corr[4] += 0.02F;*/ + + /*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); + L_inov = L_tmp; /* sets to 'L_tmp' in 1 clock */ + move32(); + /* exp_code: -18 (code in Q9), -6 (/L_SUBFR), -31 (L_tmp Q31->Q0) */ + /* output gain_inov*/ + exp_inov = sub(exp_code, add(18, L_subfr_sf)); + L_inov = Isqrt_lc(L_inov, &exp_inov); + *gain_inov = extract_h(L_shl(L_inov, sub(exp_inov, 3))); /* gain_inov in Q12 */ + + + /*-----------------------------------------------------------------* + * select the codebook, size and number of bits + * set the gains searching range + *-----------------------------------------------------------------*/ + + nBits = gains_mode[shr(i_subfr, L_subfr_sf)]; + move16(); + size = shl(1, nBits); + + ctype = shl(sub(coder_type, 1), 1); + + /*-----------------------------------------------------------------* + * calculate prediction of gcode + * search for the best codeword + *-----------------------------------------------------------------*/ + IF (i_subfr == 0) + { + b = b_1sfr_fx; + move16(); + n_pred = 2; + move16(); + + SWITCH ( nBits ) + { + case 8: + { + cdbk = gp_gamma_1sfr_8b_fx; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 60); + } + move16(); + BREAK; + } + case 7: + { + cdbk = gp_gamma_1sfr_7b_fx; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 27); + } + move16(); + BREAK; + } + case 6: + { + cdbk = gp_gamma_1sfr_6b_fx; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 10); + } + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + + /* gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.5f * (float)log10(Ecode)); + gcode0 = (float)pow(10, dotp(b, aux, n_pred) - 0.05f * 10 * (float)log10(Ecode)); + gcode0 = (float)pow(10, 0.05(20 * dotp(b, aux, n_pred) - 10 * (float)log10(Ecode))); */ + + exp_code = sub(exp_code, 18 + 6 + 1); + exp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(exp_code,exp); + L_tmp1 = Mpy_32_16(exp, frac, 24660); /* Q14 */ /* 10*log10(2) in Q13*/ + + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp,320);/*Q14, 20 in Q4*/ + L_tmp = L_sub(L_tmp,L_tmp1);/*Q14*/ + + gcode0 = round_fx(L_shl(L_tmp, 10)); /* Q8 */ + + /*-----------------------------------------------------------------* + * 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); + index= Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + + gc_mem[0] = *gain_code; + move16(); /*Q16*/ + gp_mem[0] = *gain_pit; + move16();/*Q14*/ + } + ELSE IF (EQ_16(i_subfr,L_SUBFR) || EQ_16(L_subfr, 2 * L_SUBFR)) + { + b = b_2sfr_fx; + move16(); + n_pred = 4; + move16(); + + switch ( nBits ) + { + case 7: + { + cdbk = gp_gamma_2sfr_7b_fx; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 30); + } + move16(); + BREAK; + } + case 6: + { + cdbk = gp_gamma_2sfr_6b_fx; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 12); + } + move16(); + BREAK; + } + } + + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l(gc_mem[0]); + frac = Log2_norm_lc(L_shl(gc_mem[0], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_1sfr_fx)=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); + move16(); /* Q16 */ + aux[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux[3] = shr(gp_mem[0],2); + move16();/*Q12*/ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 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); + + index= Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + gc_mem[1] = *gain_code; + move32(); + gp_mem[1] = *gain_pit; + move16(); + } + ELSE IF (EQ_16(i_subfr,2*L_SUBFR)) + { + b = b_3sfr_fx; + move16(); + n_pred = 6; + move16(); + IF(EQ_16(nBits, 7)) + { +#ifdef IVAS_CODE + cdbk = gp_gamma_3sfr_7b_fx; + if (clip_gain == 1) + { + size -= 28; + } +#else + //PMT("gp_gamma_3sfr_7b_fx is missing") +#endif + } + ELSE + { + cdbk = gp_gamma_3sfr_6b_fx; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 11); + } + } + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l(gc_mem[0]); + frac = Log2_norm_lc(L_shl(gc_mem[0], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + exp = norm_l(gc_mem[1]); + frac = Log2_norm_lc(L_shl(gc_mem[1], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[3] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux[4] = shr(gp_mem[0],2); + move16();/*Q12*/ + aux[5] = shr(gp_mem[1],2); + move16();/*Q12*/ + + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 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); + + /*----------------------------------------------------------------* + * 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 + *----------------------------------------------------------------*/ + + index= Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + + gc_mem[2] = *gain_code; + move32(); + gp_mem[2] = *gain_pit; + move16(); + } + ELSE IF (EQ_16(i_subfr,3*L_SUBFR)) + { + b = b_4sfr_fx; + move16(); + n_pred = 8; + move16(); + IF(EQ_16(nBits, 7)) + { +#ifdef IVAS_CODE + cdbk = gp_gamma_4sfr_7b_fx; + if (clip_gain == 1) + { + size -= 25; + } +#else + //PMT("gp_gamma_4sfr_7b_fx is missing") +#endif + } + ELSE + { + cdbk = gp_gamma_4sfr_6b_fx; + move16(); + if (EQ_16(clip_gain,1)) + { + size = sub(size,11); + move16(); + } + } + /* calculate predicted gain */ + aux[0] = 4096; + move16(); + aux[1] = shl(ctype,12); + move16(); + + /*aux[2] = (float)log10(gc_mem[0]); + = log2(gc_mem[0])*log10(2);*/ + exp = norm_l(gc_mem[0]); + frac = Log2_norm_lc(L_shl(gc_mem[0], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[0])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[2] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + /*aux[3] = (float)log10(gc_mem[1]); + = log2(gc_mem[1])*log10(2);*/ + exp = norm_l(gc_mem[1]); + frac = Log2_norm_lc(L_shl(gc_mem[1], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[1])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[3] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + + /*aux[4] = (float)log10(gc_mem[2]); + = log2(gc_mem[2])*log10(2);*/ + exp = norm_l(gc_mem[2]); + frac = Log2_norm_lc(L_shl(gc_mem[2], exp)); + exp = sub(sub(30,exp),16); /*Q_format(gc_mem[2])=16*/ + L_tmp1 = Mpy_32_16(exp, frac, 9864); /* Q16 */ + aux[4] = round_fx(L_shl(L_tmp1, 12)); /* Q12 */ + + aux[5] = shr(gp_mem[0],2); + move16();/*Q12*/ + aux[6] = shr(gp_mem[1],2); + move16();/*Q12*/ + aux[7] = shr(gp_mem[2],2); + move16();/*Q12*/ + /*-----------------------------------------------------------------* + * gcode0 = pow(10.0, dotp(b, aux, n_pred) + * = pow(2, 3.321928*dotp(b, aux, n_pred) + *-----------------------------------------------------------------*/ + L_tmp = Dot_product(b, aux, n_pred); /*Q25*/ + L_tmp = Mult_32_16(L_tmp, 27213); /* *3.321928 in Q13 -> Q23 */ + L_tmp = L_shr(L_tmp, 7); /* From Q23 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); + + index = Find_Opt_gainQ_fx(coeff, exp_coeff, gain_pit, gain_code, gcode0, exp_gcode0, cdbk, size); + } + + /* *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(); + { + push_indice_fx( hBstr, IND_GAIN, index, nBits ); + } + return; +} + +/*-------------------------------------------------------------------* + * gain_enc_amr_wb() + * + * Quantization of pitch and codebook gains (used also in AMR-WB IO mode) + * MA prediction is performed on the innovation energy (in dB with mean removed). + * An initial predicted gain, gcode0, is first determined and the correction + * factor alpha = g_code / gcode0 is quantized. + * The pitch gain and the correction factor are vector quantized and the + * mean-squared weighted error criterion is used in the quantizer search. + *-------------------------------------------------------------------*/ + + +void gain_enc_amr_wb_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *xn, /* i : target vector */ + const Word16 Q_xn, /* i : xn and yy1 format Q0 */ + const Word16 *yy1, /* i : zero-memory filtered adaptive excitation */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 *code, /* i : algebraic excitation */ + const Word32 core_brate, /* i : core bitrate */ + Word16 *gain_pit, /* i/o: pitch gain / Quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16 *g_coeff, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + Word16 *past_qua_en /* i/o: gain quantization memory (4 words) */ +) +{ + + Word16 i, j, index, min_ind, size; + Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, exp_inov, qua_ener; + Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo; + Word16 coeff[5], coeff_lo[5], exp_coeff[5]; + Word16 exp_max[5], tmp, nBits; + Word32 L_tmp, dist_min, L_inov, L_tmp1; + const Word16 *t_qua_gain, *p; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*----------------------------------------------------------------* + * Find the initial quantization pitch index + * Set gains search range + *----------------------------------------------------------------*/ + IF (core_brate>= ACELP_12k65) + { + t_qua_gain = t_qua_gain7b_fx; + move16(); + /* pt at 1/4th of table */ + p = t_qua_gain7b_fx + RANGE; + move16(); + + j = NB_QUA_GAIN7B - RANGE; + move16(); + + IF (EQ_16(clip_gain, 1)) + { + j = sub(j, 27); /* limit gain pitch to 1.0 */ + } + min_ind = 0; + move16(); + g_pitch = *gain_pit; + move16(); + + FOR (i = 0; i < j; i++) + { + if (GT_16(g_pitch, *p)) + { + min_ind = add(min_ind, 1); + } + p += 2; + } + size = RANGE; + move16(); + nBits = 7; + } + ELSE + { + t_qua_gain = t_qua_gain6b_fx; + min_ind = 0; + move16(); + size = RANGE; + move16(); + if (EQ_16(clip_gain, 1)) + { + size = sub(size, 16); /* limit gain pitch to 1.0 */ + } + nBits = 6; + } + /*----------------------------------------------------------------* + * Compute coefficients needed for the quantization. + * + * coeff[0] = yy1 yy1 + * coeff[1] = -2 xn yy1 + * coeff[2] = y2 y2 + * coeff[3] = -2 xn y2 + * coeff[4] = 2 yy1 y2 + * + * Product and have been computed in Adpt_enr() and + * are in vector g_coeff[]. + *----------------------------------------------------------------*/ + coeff[0] = g_coeff[0]; + move16(); + exp_coeff[0] = g_coeff[1]; + move16(); + coeff[1] = negate(g_coeff[2]); + move16(); /* coeff[1] = -2 xn yy1 */ + exp_coeff[1] = add(g_coeff[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)); /* -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); /* -9 (y2 Q9), +1 (2 xn y2) */ + + /* Compute scalar product 2* */ + coeff[4] = extract_h(Dot_product12(yy1, y2, L_SUBFR, &exp)); + exp_coeff[4] = add(sub(exp, 9 - 1), Q_xn); /* -9 (y2 Q9), +1 (2 yy1 y2) */ + + /*----------------------------------------------------------------* + * Find energy of code and compute: + * + * L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr) + * = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr) + *----------------------------------------------------------------*/ + L_tmp = Dot_product12(code, code, L_SUBFR, &exp_code); + L_inov = L_add(L_tmp, 0); + /* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */ + /* output gain_inov*/ + exp_inov = sub(exp_code, 18 + 6); + L_inov = Isqrt_lc(L_inov, &exp_inov); + *gain_inov = extract_h(L_shl(L_inov, sub(exp_inov, 3))); /* gain_inov in Q12 */ + + exp_code = sub(exp_code, 18 + 6 + 31); + frac = Log2_lc(L_tmp, &exp); + exp = add(exp, exp_code); + L_tmp = Mpy_32_16(exp, frac, -24660); /* x -3.0103(Q13) -> Q14 */ + + L_tmp = L_mac(L_tmp, MEAN_ENER, 8192); /* + MEAN_ENER in Q14 */ + + /*----------------------------------------------------------------* + * predicted codebook gain + *----------------------------------------------------------------*/ + L_tmp = L_shl(L_tmp, 10); /* From Q14 to Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[0], past_qua_en[0]); /* Q14*Q10 -> Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[1], past_qua_en[1]); /* Q14*Q10 -> Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[2], past_qua_en[2]); /* Q14*Q10 -> Q24 */ + L_tmp = L_mac0(L_tmp, pred_gain_fx[3], past_qua_en[3]); /* Q14*Q10 -> Q24 */ + + gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */ + + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + L_tmp = L_mult(gcode0, 5443); /* *0.166096 in Q15 -> Q24 */ + L_tmp = L_shr(L_tmp, 8); /* From Q24 to Q16 */ + L_Extract(L_tmp, &exp_gcode0, &frac); /* 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); + + /*----------------------------------------------------------------* + * Find the best quantizer + * ~~~~~~~~~~~~~~~~~~~~~~~ + * Before doing the computation we need to aling 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 Q11 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-11+15 = exp_gcode0+4 + * + * 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, 4); + + 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(); + } + + /* Codebook search */ + dist_min = L_add(MAX_32, 0); + p = &t_qua_gain[shl(min_ind, 1)]; + move16(); + + 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); + L_Extract(L_tmp, &g2_code, &g2_code_lo); + + 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 */ + /* splitting the if cost half the complexity of using IF macro */ + if (L_tmp1 < 0) + { + dist_min = L_add(L_tmp, 0); + } + if (L_tmp1 < 0) + { + index = i; + move16(); + } + + } + /* Read the quantized gains */ + index = add(index, min_ind); + + p = &t_qua_gain[add(index, index)]; + move16(); + *gain_pit = *p++; /* selected pitch gain in Q14 */ move16(); + g_code = *p++; /* selected code gain in Q11 */ move16(); + + L_tmp = L_mult(g_code, gcode0); /* Q11*Q0 -> Q12 */ +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o(L_tmp, add(exp_gcode0, 4), &Overflow); /* Q12 -> Q16 */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shl(L_tmp, add(exp_gcode0, 4)); /* Q12 -> Q16 */ +#endif + + *gain_code = L_tmp; /* gain of code in Q16 */ move16(); + + /*---------------------------------------------------* + * qua_ener = 20*log10(g_code) + * = 6.0206*log2(g_code) + * = 6.0206*(log2(g_codeQ11) - 11) + *---------------------------------------------------*/ + L_tmp = L_deposit_l(g_code); + frac = Log2_lc(L_tmp, &exp); + exp = sub(exp, 11); + L_tmp = Mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */ + + qua_ener = extract_l(L_shr(L_tmp, 3)); /* result in Q10 */ + + /*----------------------------------------------------------------* + * update table of past quantized energies + *----------------------------------------------------------------*/ + + past_qua_en[3] = past_qua_en[2]; + move16(); + past_qua_en[2] = past_qua_en[1]; + move16(); + past_qua_en[1] = past_qua_en[0]; + move16(); + past_qua_en[0] = qua_ener; + move16(); + + + 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(); + + push_indice_fx(hBstr, IND_GAIN, index, nBits ); + + return; +} diff --git a/lib_enc/gaus_enc_fx.c b/lib_enc/gaus_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..f4ef82cdbc07b1cfbe308da7807001a2165678b9 --- /dev/null +++ b/lib_enc/gaus_enc_fx.c @@ -0,0 +1,691 @@ +/*==================================================================================== + 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 */ +//#include "basop_mpy.h" + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define NMAX 8 /* Control of the routine's complexity */ +/* #define FAC_DELTA 16.0f */ +#define SFAC_DELTA 11 + +/*-------------------------------------------------------------------* + * Local functions + *-------------------------------------------------------------------*/ + +static Word16 cod_2pos_fx( const Word16 ind1, const Word16 ind2, const Word16 sign1, const Word16 sign2, const Word16 n ); + +static void gauss2v_fx(BSTR_ENC_HANDLE hBstr, const Word16 h[], const Word16 xn[], const Word16 dn[], Word16 code[], + Word16 y1[], Word32 *gain, const Word16 lg, const Word16 shift, const Word16 Q_new, const Word16 nb_bits ); + +/*-------------------------------------------------------------------* + * Gaus_encode + * + * Encoder UnVoiced excitation coding using Gaussian codebooks + * - ACELP quantized Gaussian excitation + * - gain quantization + * - Total excitation for UnVoiced coders + * - Updates + *-------------------------------------------------------------------*/ +Word16 gaus_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn, /* i : target vector */ + Word16 *exc, /* o : pointer to excitation signal frame */ + Word16 *mem_w0, /* o : weighting filter denominator memory */ + Word16 *clip_gain, /* o : memory of gain of pitch clipping algorithm */ + Word16 *tilt_code, /* o : synthesis excitation spectrum tilt */ + Word16 *code, /* o : algebraic excitation Q9 */ + Word32 *gain_code, /* o : Code gain. Q16 */ + Word16 *y2, /* o : zero-memory filtered adaptive excitation Q9 */ + Word16 *gain_inov, /* o : innovation gain Q12 */ + Word16 *voice_fac, /* o : voicing factor Q15 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + const Word16 Q_new, /* i : scaling factor */ + const Word16 shift, /* i : scaling factor */ + Word32 *norm_gain_code /* o : normalized innovative cb. gain Q16 */ +) +{ + Word16 nb_bits, idx; + Word16 i=0; + Word32 Ltmp; + Word16 dn[L_SUBFR], exp_code, gcode; /* Correlation between xn and h1 */ + Word16 exp,tmp,tmp_idx; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*----------------------------------------------------------------* + * Encode gaussian excitation + *----------------------------------------------------------------*/ + + /* Correlation between target xn2[] and impulse response h1[] */ + corr_xh_fx(xn, dn, h1); + + tmp_idx = shr(i_subfr, 6); + nb_bits = st_fx->acelp_cfg.fixed_cdk_index[tmp_idx]; move16(); + + gauss2v_fx(st_fx->hBstr, h1, xn, dn, code, y2, gain_code, L_SUBFR, shift, Q_new, shr(nb_bits,1)); + + /*----------------------------------------------------------------* + * Encode gaussian gain + *----------------------------------------------------------------*/ + + /* codeword energy computation */ + Ltmp = Dot_product12(code, code, L_SUBFR, &exp_code); + + exp_code = sub(exp_code, 18 + 6); /* exp: -18 (code in Q9), -6 (L_subfr = 64) */ + Ltmp = Isqrt_lc(Ltmp, &exp_code); + *gain_inov = extract_h(L_shl(Ltmp, sub(exp_code, 3))); /* g_code_inov in Q12 */ + + nb_bits = st_fx->acelp_cfg.gains_mode[tmp_idx]; move16(); + /* low bound = -30; stepSize = 1.71875; inv_stepSize = 0.5818181 */ + idx = gain_enc_gaus_fx(gain_code, nb_bits, -7680, 28160, 19065); + push_indice_fx( st_fx->hBstr, IND_GAIN, idx, nb_bits ); + + /*----------------------------------------------------------------* + * Total excitation for Unvoiced coders + *----------------------------------------------------------------*/ +#ifdef BASOP_NOGLOB + gcode = round_fx_o(L_shl_o(*gain_code, Q_new, &Overflow), &Overflow); /* scaled gain_code with Qnew */ +#else /* BASOP_NOGLOB */ + gcode = round_fx(L_shl(*gain_code, Q_new)); /* scaled gain_code with Qnew */ +#endif /* BASOP_NOGLOB */ + FOR (i = 0; i < L_SUBFR; i++) + { + exc[i+i_subfr] = round_fx(L_shl(L_mult(gcode, code[i]), 15-9)); + } + + /*----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *----------------------------------------------------------------*/ + + Ltmp = L_mult(gcode, 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_shl(Ltmp, sub(1, shift)); + *mem_w0 = round_fx(Ltmp); + init_gp_clip_fx(clip_gain); /* reset pitch clipping parameters */ + + *gain_pit = 0; + *tilt_code = 0; + move16(); /* purely unvoiced */ + *voice_fac = -32768; + move16(); /* purely unvoiced */ + 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)); + move16(); + + return (L_SUBFR<<6); +} + +/*-------------------------------------------------------------------* + * gauss2v() + * + * encoder of Gaussian Codebook for unvoiced + * consisting of addition of 2 Gaussian vectors + * + * One Gaussian vector of 192 values vectors delayed by 2 + *-------------------------------------------------------------------*/ +void gauss2v_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */ + const Word16 h[], /* i : weighted LP filter impulse response Q15 */ + const Word16 xn[], /* i : target signal Q12 */ + const Word16 dn[], /* i : backward filtered target Q12 */ + Word16 code[], /* o : gaussian excitation Q9 */ + Word16 y1[], /* o : zero-memory filtered gauss. excitation Q8 */ + Word32 *gain, /* o : excitation gain. 32-bit number in Q16 */ + const Word16 lg, /* i : subframe size Q0 */ + const Word16 shift, /* i : Scaling factor Q0 */ + const Word16 Q_new, /* i : Scaling factor Q0 */ + const Word16 nb_bits /* i : nb ob bits per track (max 6) */ +) +{ + Word16 i, j, ind1, ind2; + Word16 nvec, step; + Word32 cor, cora, dotprod; + Word16 enerw; + Word32 eneri,cor2; + Word32 enerw32,cor2w32; + Word16 *cpt1; + Word16 *pt1, *pt2; + Word32 max_val[NMAX+1]; + Word16 *pos[NMAX+1]; + Word32 sign[NMAX+1]; + Word32 ener[NMAX+1], corr[NMAX+1], ener1; + Word16 dico2[L_SUBFR*NMAX]; + Word16 exp_num; + Word16 exp_den; + Word16 Num; + Word16 Den; + Word32 GainPortion1; + Word32 GainPortion2; + Word32 cor_abs; + Word16 cor_neg; + Word16 div_result; + Word32 ener_sqrt; + Word32 Portion; + Word16 sign1,sign2; + Word16 enerw_norm,enerw_mantissa; + Word16 cor2w_norm,cor2w_mantissa; + Word16 eneri_norm,eneri_mantissa; + Word16 cor2_norm ,cor2_mantissa; + Word16 difference_norm; + Word32 cor32; /* 32-bit intermediate value*/ + Word16 hi1, lo1; + Word16 update_best; + Word16 idx; + Word32 Lc0,Lc1, Lnum, Lden; + Word16 gxx, gcc,index_delta, delta, m_sign, inv_delta; + Word16 hg[190],Gaus_dico2[190]; + Word16 shiftP3; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*----------------------------------------------------------------* + * Encode the tilt of gaussian excitation + *----------------------------------------------------------------*/ + + /* Compute spectral tilt of target */ + Lc0 = L_mult(xn[1], xn[1]); + Lc1 = L_mult(xn[1], xn[0]); + FOR (i=2; i 0) /* Adapt spectral tilt of initial codebook */ + { + /* Computation of 1 / (1+fdelta*fdelta) */ + inv_delta = inv_delta_tab[sub(index_delta, 1)]; + move16(); /* Q15 */ + + /* fgaus_dico2[0] = gaus_dico[0] */ + Gaus_dico2[0] = gaus_dico_fx[0]; + FOR (i=1; i<190; i++) + { + /* fgaus_dico2[i] = (gaus_dico[i] - fdelta*gaus_dico[i-1]) / (1 + fdelta*fdelta) */ + Lnum = L_msu(L_deposit_h(gaus_dico_fx[i]), delta, gaus_dico_fx[i-1]); + Gaus_dico2[i] = round_fx(Mpy_32_16_1(Lnum, inv_delta)); + } + } + ELSE + { + FOR (i=0; i<190; i++) + { + /* fgaus_dico2[i] = gaus_dico[i] */ + Gaus_dico2[i] = gaus_dico_fx[i]; + move16(); + } + } + + /*----------------------------------------------------------------* + * Initializations + *----------------------------------------------------------------*/ + + ind1 = 0; + move16(); + ind2 = 0; + move16(); + + nvec = shl(1, nb_bits); + step = shr(0x80, nb_bits); + + /*----------------------------------------------------------------* + * dot product between dn and gaussian codevectors, + * keep NMAX best vectors + *----------------------------------------------------------------*/ + + set32_fx(max_val, 0, NMAX+1); + set32_fx(sign, 0, NMAX+1); + + FOR (i = 0; i < NMAX+1; i++) + { + pos[i] = (Word16 *)Gaus_dico2; + } + + cpt1 = Gaus_dico2; + move16(); + + FOR (i=0; i< nvec; i++) + { + /* Dot product without normalization, because values are compared with each other afterwards. */ + cor = Dot_product(cpt1, dn, lg); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31*/ + cora = L_abs(cor); + j = NMAX-1; + move16(); + + DO + { + IF (GE_32(cora, max_val[j])) + { + max_val[j+1] = max_val[j]; + move32(); /*Q31*/ + pos[j+1] = pos[j]; + move16(); /*Pointer*/ + sign[j+1] = sign[j]; + move32(); /*Q31*/ + max_val[j] = cora; + move32(); /*Q31*/ + pos[j] = cpt1; + move16(); /*Pointer*/ + sign[j] = cor; + move32(); /*Q31*/ + } + j--; + } + WHILE (j >= 0); + cpt1 += step; + } + + /*----------------------------------------------------------------* + * filter selected vectors + * put sign + * compute energy + *----------------------------------------------------------------*/ + + pt1 = dico2; + move16(); + FOR (i=0; i Q31 */ + corr[i] = Dot_product(pt1,xn,lg); /* must be equal to sign[i] !! */ + move32(); /* pt1 points into dico2, in Q12. xn is in Q12 */ + /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */ + pt1 += L_SUBFR; + } + + /*------------------------------------------------------------------------* + * try all combinations of NMAX best vectors + *------------------------------------------------------------------------*/ + + pt1 = dico2; + move16(); + + /* Initial values for search algorithm */ + enerw32 = L_deposit_h(0x80); + cor2w32 = L_deposit_l(-2); + enerw_norm = norm_l(enerw32); + cor2w_norm = norm_l(cor2w32); + cor2w_mantissa = round_fx(L_shl(cor2w32,cor2w_norm)); + enerw_mantissa = round_fx(L_shl(enerw32,enerw_norm)); + + FOR (i=0; i< NMAX; i++) + { + pt2 = pt1; + move16(); + FOR (j=i; j Q31 */ + + /* eneri = round_fx(ener[i]) + round_fx(ener[j]) + 2*round_fx(dotprod) */ + /* Use ScalingShift to stay aligned with ener[] */ + eneri=L_shl(dotprod, 1); /* One left shift added for factor of 2 */ + eneri=L_add(ener[i], eneri); + eneri=L_add(ener[j], eneri); /* Q31 */ + + lo1 = L_Extract_lc(cor32, &hi1); + cor2 = Sad_32(0, hi1, lo1); /* Square + Add */ + + cor2_norm = norm_l(cor2); + eneri_norm = norm_l(eneri); +#ifdef BASOP_NOGLOB + cor2_mantissa = round_fx_o(L_shl_o(cor2, cor2_norm, &Overflow), &Overflow); + eneri_mantissa = round_fx_o(L_shl_o(eneri, eneri_norm, &Overflow), &Overflow); +#else + cor2_mantissa = round_fx(L_shl(cor2, cor2_norm)); + eneri_mantissa = round_fx(L_shl(eneri, eneri_norm)); +#endif + difference_norm = sub(add(cor2_norm, enerw_norm), add(cor2w_norm, eneri_norm)); + + update_best = 0; + move16(); + + IF (difference_norm > 0) + { + if (GT_32(L_shr(L_mult(cor2_mantissa, enerw_mantissa), difference_norm), + L_mult(cor2w_mantissa, eneri_mantissa))) + { + update_best = 1; + move16(); + } + } + ELSE + { + if (L_msu(L_shl(L_mult(cor2w_mantissa, eneri_mantissa), difference_norm), cor2_mantissa, enerw_mantissa) < 0) + { + update_best=1; + move16(); + } + } + IF (update_best != 0) + { + cor2w_mantissa = cor2_mantissa; + move16(); + cor2w_norm = cor2_norm; + move16(); + enerw_mantissa = eneri_mantissa; + move16(); + enerw_norm = eneri_norm; + move16(); + ind1 = i; + move16(); + ind2 = j; + move16(); + } + pt2 += L_SUBFR; + } + pt1 += L_SUBFR; + } + + enerw = round_fx(L_shr(L_deposit_h(enerw_mantissa), enerw_norm)); + + /*----------------------------------------------------------------* + * Compute zero-memory filtered gauss. excitation y + *----------------------------------------------------------------*/ + + pt1 = dico2 + ind1*L_SUBFR; + move16(); /*Pointer arithmetic*/ + pt2 = dico2 + ind2*L_SUBFR; + move16(); + + shiftP3 = add(shift, 3); + FOR (i=0; i= 0) + { + sign1 = 32767; + move16(); + } + + sign2 = (-32768); + move16(); + if (sign[ind2] >= 0) + { + sign2 = 32767; + move16(); + } + + /*----------------------------------------------------------------* + * Compute code + *----------------------------------------------------------------*/ + + pt1 = pos[ind1]; + move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */ + pt2 = pos[ind2]; + move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */ + + /* sign[ind1] and sign[ind2] */ + FOR (i=0; i Q31 */ + + exp_num = sub(norm_s(enerw), 1); + exp_den = norm_l(ener1); + Num = shl(enerw, exp_num); + Den = round_fx(L_shl(ener1, exp_den)); + + GainPortion2 = L_deposit_l(0); /* Unexpected division by zero. Eliminate this gain contribution */ + IF (Den != 0) /* Protection against division by zero */ + { + div_result = div_s(Num, Den); /* Q15 */ + + /* Re-scale to compensate for normalization*/ + GainPortion2 = L_shr(L_deposit_l(div_result), sub(exp_num, exp_den)); + } + + ener_sqrt = Isqrt(L_shl(GainPortion2, 1)); /* Make value a Q16 prior to division (align on power of 4) */ + ener_sqrt = L_shr(ener_sqrt, 8); /* Left-shift Q23 result to make a Q15 result */ + + Portion = Mult_32_16(GainPortion1, 19661); /* Performs GainPortion1*.6 */ + Portion = Madd_32_16(Portion, ener_sqrt, 13107); /* Performs ener_sqrt*.4 */ + + /* Gain must be output in a 32-bit variable as a Q16 */ + /* Compensate for Q_new */ +#ifdef BASOP_NOGLOB + *gain = L_shl_o(Portion, sub(13, Q_new), &Overflow); +#else + *gain = L_shl(Portion, sub(13, Q_new)); +#endif + move32(); + + return; +} + + +/*---------------------------------------------------------------------* + * Put selected codevector positions and signs into quantization index + *---------------------------------------------------------------------*/ +static Word16 cod_2pos_fx(/* o : codebook quantization index */ + const Word16 ind1, /* i : index of 1st gaussian vector */ + const Word16 ind2, /* i : index of 2nd gaussian vector */ + const Word16 sign1, /* i : sign of 1st gaussian vector */ + const Word16 sign2, /* i : sign of 2nd gaussian vector */ + const Word16 n /* i : nb. of codebook vectors */ +) +{ + Word16 i1, i2, index, s1, s2; + s1 = 1; + move16(); + + if (sign1 > 0) + { + s1 = 0; + move16(); + } + s2 = 1; + move16(); + if (sign2 > 0) + { + s2 = 0; + move16(); + } + + IF (EQ_16(s1, s2)) + { + IF (LE_16(ind1, ind2)) + { + i1 = ind1; + move16(); + i2 = ind2; + move16(); + } + ELSE + { + i1 = ind2; + move16(); + i2 = ind1; + move16(); + } + } + ELSE + { + IF (GT_16(ind1, ind2)) + { + i1 = ind1; + move16(); + i2 = ind2; + move16(); + } + ELSE + { + i1 = ind2; + move16(); + i2 = ind1; + move16(); + s1 = s2; + move16(); + } + } + + index = extract_l(L_mult(i1, n)); + index = add(index, shl(i2, 1)); + index = add(index, s1); + + return index; +} diff --git a/lib_enc/gp_clip_fx.c b/lib_enc/gp_clip_fx.c index 66108aad3924f3a9207082cf185f1266c0a936a8..d7e9125014c770c47b013050fabb823563e97712 100644 --- a/lib_enc/gp_clip_fx.c +++ b/lib_enc/gp_clip_fx.c @@ -37,7 +37,9 @@ #include #include "options.h" /* Compilation switches */ #include "cnst.h" /* Common constants */ -#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 */ #include "basop_util.h" /*-------------------------------------------------------------------* diff --git a/lib_enc/gs_enc_fx.c b/lib_enc/gs_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..a32d4892052d153fb393682eebbd0024bd2565fd --- /dev/null +++ b/lib_enc/gs_enc_fx.c @@ -0,0 +1,769 @@ +/*==================================================================================== + 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 "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 */ + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ + +static Word16 edyn_fx(const Word16 *vec, const Word16 lvec, Word16 Qnew); + +/*-------------------------------------------------------------------* + * encod_audio() + * + * Encode audio (AC) frames + *-------------------------------------------------------------------*/ +void encod_audio_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + const Word16 speech[], /* i : input speech Q_new */ + const Word16 Aw[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq[], /* i : 12k8 Lp coefficient */ + const Word16 *res, /* i : residual signal Q_new */ + Word16 *synth, /* i/o: core synthesis Q-1 */ + Word16 *exc, /* i/o: current non-enhanced excitation Q_new */ + Word16 *pitch_buf, /* i/o: floating pitch values for each subframe Q6 */ + Word16 *voice_factors, /* o : voicing factors Q15 */ + Word16 *bwe_exc, /* o : excitation for SWB TBE Q0 */ + const Word16 attack_flag, /* i : Flag that point to an attack coded with AC mode (GSC) */ + Word16 *lsf_new, /* i : current frame ISF vector */ + Word16 *tmp_noise, /* o : noise energy */ + 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 +) +{ + const Word16 *p_Aq; + Word16 i, i_subfr, nb_subfr, last_pit_bin; + Word16 T0_tmp, T0_frac_tmp, nb_subfr_flag; + Word16 tmp_nb_bits_tot = 0; + Word16 Es_pred; + Word16 dct_res[L_FRAME16k], dct_epit[L_FRAME16k]; + Word16 m_mean = 0; + Word16 saved_bit_pos; + Word16 exc_wo_nf[L_FRAME16k]; + Word32 Lm_mean; + Word16 nb_bits; + Word16 indice; + SP_MUS_CLAS_HANDLE hSpMusClas = st_fx->hSpMusClas; + GSC_ENC_HANDLE hGSCEnc = st_fx->hGSCEnc; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + LPD_state_HANDLE hLPDmem = st_fx->hLPDmem; + + m_mean = 0; + move16(); + tmp_nb_bits_tot = 0; + move16(); + + T0_tmp = 64; + move16(); + T0_frac_tmp = 0; + move16(); + Copy(hLPDmem->mem_syn, hGSCEnc->mem_syn_tmp_fx, M); + hGSCEnc->mem_w0_tmp_fx = hLPDmem->mem_w0; + move16(); + Es_pred = 0; + move16(); + + /*---------------------------------------------------------------* + * Encode GSC IVAS mode + * Encode GSC attack flag (used to reduce possible pre-echo) + * Encode GSC SWB speech flag + *---------------------------------------------------------------*/ +#ifdef GSC_IVAS // TVB -->>>>>> + test(); + if (GT_16( st_fx->element_mode, EVS_MONO) && st_fx->idchan == 0) + { + push_indice_fx(hBstr, IND_GSC_IVAS_SP, st_fx->GSC_IVAS_mode, 2); + } +#endif + IF (attack_flag > 0) + { + push_indice_fx(hBstr, IND_GSC_ATTACK, 1, 1); + } + ELSE + { + push_indice_fx(hBstr, IND_GSC_ATTACK, 0, 1); + } + + + test(); test(); test(); + test();test();test(); + IF (GE_16(st_fx->GSC_IVAS_mode, 1) || (NE_16(st_fx->coder_type, INACTIVE) && ((EQ_16(st_fx->element_mode, EVS_MONO) && GE_32(st_fx->total_brate_fx, ACELP_13k20)) || + (GT_16(st_fx->element_mode, EVS_MONO) && GT_32(st_fx->total_brate_fx, MIN_BRATE_GSC_NOISY_FLAG) && GE_16(st_fx->bwidth_fx, SWB) && !st_fx->flag_ACELP16k)))) + { + push_indice_fx(hBstr,IND_GSC_SWB_SPEECH, st_fx->GSC_noisy_speech_fx, 1); + } + /*---------------------------------------------------------------* + * Find and encode the number of subframes + *---------------------------------------------------------------*/ + test(); + IF ( GE_32(st_fx->core_brate_fx,ACELP_9k60) && LE_32(st_fx->core_brate_fx,ACELP_13k20)) + { + FOR( i = 0; i < 5; i++) + { + test(); + if( GT_16(abs_s(hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT-i-1]),1536)&&EQ_16(hGSCEnc->cor_strong_limit,1)) + { + hGSCEnc->cor_strong_limit = 0; + move16(); + } + } + } + test(); + IF(GE_16(st_fx->GSC_IVAS_mode, 1) || (st_fx->GSC_noisy_speech_fx && st_fx->GSC_IVAS_mode == 0)) + { + nb_subfr = NB_SUBFR; + move16(); + test();test(); + if (st_fx->GSC_IVAS_mode > 0 && LT_16(st_fx->GSC_IVAS_mode, 3) && LT_32(st_fx->core_brate_fx, GSC_L_RATE_STG)) + { + nb_subfr = 2; + move16(); + } + hGSCEnc->cor_strong_limit = 0; + move16(); + nb_subfr_flag = 1; + move16(); + } + ELSE IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k) && (LE_32(st_fx->core_brate_fx, ACELP_13k20) || EQ_16(st_fx->coder_type, INACTIVE))) + { + hGSCEnc->cor_strong_limit = 0; + nb_subfr = SWNB_SUBFR; + nb_subfr_flag = 1; + move16();move16();move16(); + + } + ELSE + { + test(); + test(); + IF( (hGSCEnc->cor_strong_limit == 0 || EQ_16(st_fx->coder_type,INACTIVE)) && GE_32(st_fx->core_brate_fx,ACELP_9k60)) + { + nb_subfr = 2; + move16(); + nb_subfr_flag = 0; + move16(); + hGSCEnc->cor_strong_limit = 0; + move16(); + } + ELSE + { + nb_subfr = SWNB_SUBFR; + move16(); + nb_subfr_flag = 1; + move16(); + } + IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k) && (GT_16(hSpMusClas->mold_corr_fx, 26214) && GE_32(st_fx->core_brate_fx, MIN_RATE_4SBFR) && NE_16(st_fx->coder_type, INACTIVE))) + { + nb_subfr = shl(nb_subfr, 1); + nb_subfr_flag |= 0x2; logic16(); + } + + IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k) && GE_32(st_fx->core_brate_fx, MIN_RATE_4SBFR)) + { + push_indice_fx(hBstr, IND_HF_NOISE, nb_subfr_flag, 2); + } + ELSE IF( GE_32(st_fx->core_brate_fx,ACELP_9k60)) + { + /* nb_subfr_flag can only have the value 0 or 1 */ + push_indice_fx(hBstr, IND_HF_NOISE, nb_subfr_flag, 1); + } + } + test(); + if (EQ_16(st_fx->L_frame_fx, L_FRAME16k) && EQ_16(nb_subfr, NB_SUBFR)) + { + nb_subfr = NB_SUBFR16k; + move16(); + } + + /*---------------------------------------------------------------* + * Compute adaptive (pitch) excitation contribution + *---------------------------------------------------------------*/ + + test(); + IF (!(st_fx->GSC_IVAS_mode > 0 && EQ_16(st_fx->L_frame_fx, i_mult(nb_subfr, 2 * L_SUBFR)) && LT_16(st_fx->GSC_IVAS_mode, 3)) && + ((GE_32(st_fx->core_brate_fx, MIN_RATE_FCB) || st_fx->GSC_noisy_speech_fx) && + ((EQ_16(nb_subfr, NB_SUBFR) && EQ_16(st_fx->L_frame_fx, L_FRAME)) || (EQ_16(nb_subfr, NB_SUBFR16k) && EQ_16(st_fx->L_frame_fx, L_FRAME16k))))) + { + IF (GT_16(st_fx->element_mode, EVS_MONO)) + { + nb_bits = 5; + } + ELSE + { + nb_bits = Es_pred_bits_tbl[BIT_ALLOC_IDX_fx(st_fx->core_brate_fx, GENERIC, -1, -1)]; + move16(); + } + Es_pred_enc_fx(&Es_pred, &indice, st_fx->L_frame_fx, res, st_fx->voicing_fx, nb_bits, 0, Q_new); + push_indice_fx(hBstr, IND_ES_PRED, indice, nb_bits ); + } + + enc_pit_exc_fx( st_fx, speech, Aw, Aq,Es_pred, res, synth, exc, &T0_tmp, + &T0_frac_tmp, pitch_buf, nb_subfr, &hGSCEnc->lt_gpitch_fx, &saved_bit_pos, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf, Q_new, shift ); + + /*---------------------------------------------------------------* + * DCT transform + *---------------------------------------------------------------*/ + edct_16fx( exc, dct_epit, st_fx->L_frame_fx, 7, st_fx->element_mode); + edct_16fx( res, dct_res, st_fx->L_frame_fx, 7, st_fx->element_mode); + /*---------------------------------------------------------------* + * Calculate energy dynamics + *---------------------------------------------------------------*/ + Lm_mean = L_deposit_l(0); + FOR( i = 7; i < 15; i++ ) + { + /*m_mean = add(m_mean,edyn_fx( dct_res+i*16, 16, Q_new )); */ + Lm_mean = L_mac(Lm_mean, edyn_fx( dct_res+i*16, 16, Q_new ), 4096);/*Q7*/ + } + m_mean = round_fx(Lm_mean);/*Q7*/ + + IF( GT_16(m_mean, hGSCEnc->mid_dyn_fx)) + { + /*st_fx->mid_dyn_fx = 0.2f * st_fx->mid_dyn_fx + 0.8f * m_mean;*/ + hGSCEnc->mid_dyn_fx = round_fx(L_mac(L_mult(26214,m_mean),6554, hGSCEnc->mid_dyn_fx));/*Q7*/ + } + ELSE + { + /*st_fx->mid_dyn_fx = 0.6f * st_fx->mid_dyn_fx + 0.4f * m_mean;*/ + hGSCEnc->mid_dyn_fx = round_fx(L_mac(L_mult(13107,m_mean),19661,hGSCEnc->mid_dyn_fx));/*Q7*/ + } + IF( NE_16(st_fx->coder_type,INACTIVE)) + { + hGSCEnc->noise_lev = sub((NOISE_LEVEL_SP3+1), usquant_fx(hGSCEnc->mid_dyn_fx, &m_mean, MIN_DYNAMIC_FX, shr(GSF_NF_DELTA_FX,1), GSC_NF_STEPS)); + + hGSCEnc->noise_lev = s_min(hGSCEnc->noise_lev, NOISE_LEVEL_SP3); + } + + hGSCEnc->past_dyn_dec = hGSCEnc->noise_lev; + move16(); + IF (GE_16(st_fx->GSC_IVAS_mode, 1)) + { + hGSCEnc->noise_lev = NOISE_LEVEL_SP2; + IF (EQ_16(st_fx->GSC_IVAS_mode, 3) ) /* Music like */ + { + hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); + } + ELSE IF (st_fx->GSC_noisy_speech_fx == 0) + { + hGSCEnc->noise_lev = NOISE_LEVEL_SP3; + move16(); + } + } + ELSE IF( LE_32(st_fx->core_brate_fx,ACELP_8k00)) + { + hGSCEnc->noise_lev = s_max(hGSCEnc->noise_lev, NOISE_LEVEL_SP2); + push_indice_fx(hBstr, IND_NOISE_LEVEL, sub(hGSCEnc->noise_lev, NOISE_LEVEL_SP2), 2 ); + } + ELSE IF( st_fx->GSC_noisy_speech_fx ) + { + hGSCEnc->noise_lev = NOISE_LEVEL_SP3; + move16(); + } + ELSE + { + push_indice_fx(hBstr, IND_NOISE_LEVEL, sub(hGSCEnc->noise_lev, NOISE_LEVEL_SP0), 3 ); + } + + /*---------------------------------------------------------------* + * Find and encode the last band where the adaptive (pitch) contribution is significant + *---------------------------------------------------------------*/ + + last_pit_bin = Pit_exc_contribution_len_fx( st_fx, dct_res, dct_epit, pitch_buf, nb_subfr, &hGSCEnc->pit_exc_hangover, Q_new ); + + IF( last_pit_bin == 0 ) + { + hLPDmem->tilt_code = 0; + move16(); + } + ELSE + { + /*last_pit_bin++;*/ + last_pit_bin = add(last_pit_bin,1); + } + + /*--------------------------------------------------------------------------------------* + * GSC encoder + *--------------------------------------------------------------------------------------*/ + + /* Find the current total number of bits used */ + tmp_nb_bits_tot = hBstr->nb_bits_tot_fx; + move16(); + + + if( st_fx->extl_brate_fx > 0 ) + { + /* subtract 1 bit for TBE/BWE BWE flag (bit counted in extl_brate) */ + tmp_nb_bits_tot = sub(tmp_nb_bits_tot,1); + } + test(); test(); + if( EQ_16(st_fx->coder_type,INACTIVE) && LE_32(st_fx->core_brate_fx,ACELP_9k60) && st_fx->idchan == 0) + { + /* add 5 bits for noisiness */ + tmp_nb_bits_tot = add(tmp_nb_bits_tot,5); + } + + gsc_enc_fx( st_fx, dct_res, dct_epit, last_pit_bin, tmp_nb_bits_tot, nb_subfr, lsf_new, exc_wo_nf, tmp_noise, Q_new ); + + /*--------------------------------------------------------------------------------------* + * iDCT transform + *--------------------------------------------------------------------------------------*/ + + edct_16fx( dct_epit, exc, st_fx->L_frame_fx , 7, st_fx->element_mode); + edct_16fx( exc_wo_nf, exc_wo_nf, st_fx->L_frame_fx , 7, st_fx->element_mode); + /*--------------------------------------------------------------------------------------* + * Remove potential pre-echo in case an onset has been detected + *--------------------------------------------------------------------------------------*/ + + pre_echo_att_fx( &hGSCEnc->Last_frame_ener_fx, exc, attack_flag, Q_new, st_fx->last_coder_type_fx, st_fx->L_frame_fx); + + /*--------------------------------------------------------------------------------------* + * Update BWE excitation + *--------------------------------------------------------------------------------------*/ + IF (st_fx->hBWE_TD != NULL) + { + IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + set16_fx(voice_factors, 0, NB_SUBFR16k); + interp_code_4over2_fx(exc, bwe_exc, L_FRAME16k); + } + ELSE + { + set16_fx(voice_factors, 0, NB_SUBFR); + interp_code_5over2_fx(exc, bwe_exc, L_FRAME); + } + } + /*--------------------------------------------------------------------------------------* + * Synthesis + *--------------------------------------------------------------------------------------*/ + + p_Aq = Aq; + FOR (i_subfr=0; i_subfr< st_fx->L_frame_fx; i_subfr+=L_SUBFR) + { + Syn_filt_s( 1, p_Aq, M, &exc_wo_nf[i_subfr], &synth[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1 ); + p_Aq += (M+1); + } + + /*--------------------------------------------------------------------------------------* + * Updates + *--------------------------------------------------------------------------------------*/ + + hLPDmem->mem_w0 = hGSCEnc->mem_w0_tmp_fx; /*_DIFF_FLOAT_FIX_ The way it is written in the original fix point is that at this point mem_w0 falls back to its original value (before enc_pit_exc, seems not the case in float */ + move16(); + Copy( exc_wo_nf, exc, st_fx->L_frame_fx); + + return; +} + +/*================================================================================*/ +/* FUNCTION : void gsc_enc_fx () */ +/*--------------------------------------------------------------------------------*/ +/* PURPOSE : Generic audio signal encoder */ +/*--------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) res_dct_in : dct of residual signal Q_exc */ +/* _ (Word16) Diff_len : Lenght of the difference signal Q0 */ +/* _ (Word16) coder_type : coding type Q0 */ +/* _ (Word16) bits_used : Number of bit used before frequency Q Q0 */ +/* _ (Word16) nb_subfr : Number of subframe considered Q0 */ +/* _ (Word16) Qexc : Q format of exc_dct_in */ +/*--------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx:Encoder State Structure */ +/* _ (Word16[]) exc_dct_in : dctof pitch-only excitation / total excitation Q_exc */ +/*--------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _None */ +/*================================================================================*/ + + +void gsc_enc_fx( + Encoder_State_fx *st_fx, /* i/o: State structure */ + Word16 res_dct_in[], /* i : dct of residual signal */ + Word16 exc_dct_in[], /* i/o: dct of pitch-only excitation / total excitation */ + const Word16 Diff_len, + const Word16 bits_used, + const Word16 nb_subfr, + Word16 *lsf_new, /* i : ISFs at the end of the frame */ + Word16 *exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + Word16 *tmp_noise, /* o : noise energy */ + Word16 Q_exc +) +{ + Word16 y2_filt[L_FRAME16k]; + Word16 exc_diffQ[L_FRAME16k]; + Word16 exc_diff[L_FRAME16k]; + Word16 bit,tmp; + Word16 nb_subbands; + Word16 pvq_len, i; + Word16 bits_per_bands[MBANDS_GN_BITALLOC16k]; + Word16 tmp_band; + Word16 concat_in[L_FRAME16k]; + Word16 concat_out[L_FRAME16k]; + Word16 max_ener_band[MBANDS_GN_BITALLOC16k], j; + Word16 Ener_per_bd_iQ[MBANDS_GN_BITALLOC16k]; + Word16 last_bin, mean_gain; + Word16 bitallocation_band[MBANDS_GN_BITALLOC16k]; + Word16 bitallocation_exc[2]; + + Word16 inpulses_fx[NB_SFM]; + Word16 imaxpulse_fx[NB_SFM]; + Word16 Q_tmp; + Word16 seed_init; +#ifdef ADD_LRTD + Word16 max_eq_val; + Word32 max_eq; +#endif + GSC_ENC_HANDLE hGSCEnc = st_fx->hGSCEnc; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + set16_fx( inpulses_fx, 0, NB_SFM ); + set16_fx( imaxpulse_fx, 0, NB_SFM ); + + /*--------------------------------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------------------------------*/ + + bit = bits_used; + test();test();test(); + if (EQ_16(st_fx->coder_type, INACTIVE) && (EQ_16(st_fx->tdm_LRTD_flag, 1) || EQ_16(st_fx->element_mode, IVAS_SCE)) && LE_32(st_fx->core_brate_fx, GSC_LRES_GAINQ_LIMIT)) + { + bit = add(bit, GSC_LRES_NB_NITS); + } + move16(); + set16_fx( exc_diffQ, 0, st_fx->L_frame_fx ); + set16_fx( y2_filt, 0, st_fx->L_frame_fx ); + + /*--------------------------------------------------------------------------------------* + * Calculate the difference between the residual spectrum and the spectrum of adaptive excitation + * (non valuable temporal content present in exc_dct_in is already zeroed) + *--------------------------------------------------------------------------------------*/ + + Vr_subt( res_dct_in, exc_dct_in, exc_diff, st_fx->L_frame_fx ); + exc_diff[0] = 0; + move16(); + + /*--------------------------------------------------------------------------------------* + * Multiply the difference spectrum with the normalized spectral shape of the residual signal + * This improves the stability of the differnece spectrum since the spectral shape of the + * residual signal is less suseptible to rapid changes than the difference spectrum + *--------------------------------------------------------------------------------------*/ + IF( Diff_len == 0 ) + { + tmp_band = 0; + move16(); + } + ELSE + { + tmp_band = hGSCEnc->mem_last_pit_band; + move16(); + } + + Ener_per_band_comp_fx( exc_diff, Ener_per_bd_iQ, Q_exc, MBANDS_GN, 1/*, st_fx->L_frame_fx IVAS_CODE*/ ); + + /*--------------------------------------------------------------------------------------* + * Gain quantizaion + *--------------------------------------------------------------------------------------*/ +#if 0 + mean_gain = gsc_gainQ_fx(hBstr, Ener_per_bd_iQ, Ener_per_bd_iQ, st_fx->core_brate_fx, st_fx->coder_type, st_fx->bwidth_fx ); +#else + i = 0; move16(); + WHILE (LT_16(i, SIZE_BRATE_INTERMED_TBL)) + { + IF (LE_32(st_fx->core_brate_fx, brate_intermed_tbl[i])) + { + break; + } + i++; + } + if (GT_16(st_fx->element_mode, EVS_MONO) && EQ_16(st_fx->coder_type, AUDIO) && + LE_32(st_fx->core_brate_fx, STEREO_GSC_BIT_RATE_ALLOC) && EQ_32(brate_intermed_tbl[i], ACELP_9k60)) /* Bit allocation should be mapped to 8 kb/s instead of 9.6 kb/s in this case */ + { + i--; + } + + mean_gain = gsc_gainQ_fx(hBstr, /*st_fX->element_mode, st_fx->idchan,IVAS_CODE*/ Ener_per_bd_iQ, Ener_per_bd_iQ, brate_intermed_tbl[i], st_fx->coder_type, st_fx->bwidth_fx/*, st_fx->L_frame_fx, st_fx->tdm_LRTD_flag, st_fx->core_brate_fx*/); + +#endif + *tmp_noise = mult_r(320,mean_gain); /*10 in Q5 lp_gainc in Q3 */ + + /*--------------------------------------------------------------------------------------* + * Frequency encoder + *--------------------------------------------------------------------------------------*/ + + bands_and_bit_alloc_fx(hGSCEnc->cor_strong_limit, hGSCEnc->noise_lev, st_fx->core_brate_fx, Diff_len, bit, &bit, Ener_per_bd_iQ, + max_ener_band, bits_per_bands, &nb_subbands, exc_diff, concat_in, &pvq_len, st_fx->coder_type, st_fx->bwidth_fx, + st_fx->GSC_noisy_speech_fx, st_fx->L_frame_fx, st_fx->element_mode, st_fx->GSC_IVAS_mode); + + Q_tmp = Q_exc; + move16(); + IF (bit == 0) + { + set16_fx(concat_out, 0, L_FRAME16k); + } + ELSE + { + tmp = pvq_core_enc_fx(hBstr, concat_in, concat_out, &Q_tmp, bit, nb_subbands, gsc_sfm_start, gsc_sfm_end, + gsc_sfm_size, bits_per_bands, NULL, inpulses_fx, imaxpulse_fx, ACELP_CORE); + Scale_sig(concat_out, gsc_sfm_end[nb_subbands - 1], sub(Q_PVQ_OUT, Q_tmp)); + bit = sub(bit, tmp); + } + /* write unused bits */ + WHILE( bit > 0 ) + { + i = s_min( bit, 16 ); + push_indice_fx(hBstr, IND_UNUSED, 0, i ); + bit = sub(bit,i); + } + /* Reorder Q bands */ + seed_init = 0; + move16(); + last_bin = 0; + move16(); + set16_fx( bitallocation_band, 0, MBANDS_GN_BITALLOC16k); + +#ifdef ADD_LRTD + max_eq = 0; + max_eq_val = 1.0f; + + IF ((((LT_32(st_fx->core_brate_fx, ACELP_7k20) && EQ_16(st_fx->GSC_noisy_speech_fx, 1)) || LT_32(st_fx->core_brate_fx, 6000)) && LE_16(st_fx->coder_type, UNVOICED)) || GE_16(st_fx->GSC_IVAS_mode, 1)) + { + j = emaximum(concat_out, nb_subbands * 16, &max_eq); + max_eq = max_eq_val / (fabsf(concat_out[j]) + 0.01f); + max_eq = min(max_eq_val, max_eq); + } +#endif + + FOR(j = 0; j < nb_subbands; j++) + { + Copy( concat_out+j*16, exc_diffQ + max_ener_band[j]*16, 16 );/*Q12*/ + + last_bin = s_max(last_bin , max_ener_band[j]); + + bitallocation_band[ max_ener_band[j]] = 1; + move16(); + + seed_init = add(seed_init,inpulses_fx[j]); + move16(); + } + test(); + IF( NE_16(st_fx->last_coder_type_fx, AUDIO) /* First audio frame */ + && NE_16(st_fx->last_coder_type_fx, UNVOICED) )/* last_coder_type == INACTIVE is overwritten in update_enc to UNVOICED */ + { + FOR( j = 0; j < shl(nb_subbands,4); j++ ) + { + IF( concat_out[j] > 0 ) + { + seed_init = extract_l(L_shl(seed_init,3)); + } + IF( concat_out[j] < 0 ) + { + seed_init = add(seed_init,3); + move16(); + } + } + hGSCEnc->seed_tcx = seed_init; + move16(); + } + test(); + IF( EQ_32(st_fx->core_brate_fx,ACELP_8k00)&&NE_16(st_fx->bwidth_fx,NB)) + { + bitallocation_exc[0] = 0; + move16(); + bitallocation_exc[1] = 0; + move16(); + if( exc_diffQ[L_FRAME8k - 2] != 0 ) + { + bitallocation_exc[0] = 1; + move16(); + } + if( exc_diffQ[L_FRAME8k - 1] != 0 ) + { + bitallocation_exc[1] = 1; + move16(); + } + } + + /*--------------------------------------------------------------------------------------* + * Skip adaptive (pitch) contribution frequency band (no noise added over the adaptive (pitch) contribution) + * Find x pulses between 1.6-3.2kHz to code in the spectrum of the residual signal + * Gain is based on the inter-correlation gain between the pulses found and residual signal + *--------------------------------------------------------------------------------------*/ +#ifdef ADD_LRTD + test();test();test(); + IF (GE_16(st_fx->GSC_IVAS_mode, 1) && EQ_16(st_fx->GSC_noisy_speech_fx, 1)) + { + FOR (i = 64; i < st->L_frame; i++) + { + exc_diffQ[i] *= max_eq; + } + } + ELSE IF (LT_32(st_fx->core_brate_fx, ACELP_7k20) && EQ_16(st_fx->GSC_noisy_speech_fx, 1) && LE_16(st_fx->coder_type, UNVOICED)) + { + FOR (i = 0; i < L_FRAME; i++) + { + exc_diffQ[i] *= max_eq; + } + } + else +#endif + { + freq_dnw_scaling_fx(hGSCEnc->cor_strong_limit, st_fx->coder_type, hGSCEnc->noise_lev, st_fx->core_brate_fx, exc_diffQ, Q_PVQ_OUT, st_fx->L_frame_fx); + } + /*--------------------------------------------------------------------------------------* + * Estimate noise level + *--------------------------------------------------------------------------------------*/ + + highband_exc_dct_in_fx( st_fx->core_brate_fx, mfreq_bindiv_loc, last_bin, Diff_len, hGSCEnc->noise_lev, tmp_band, exc_diffQ, + &hGSCEnc->seed_tcx, Ener_per_bd_iQ, nb_subfr, exc_dct_in, st_fx->last_coder_type_fx, bitallocation_band, lsf_new, + hGSCEnc->last_exc_dct_in_fx, &st_fx->last_ener_fx, hGSCEnc->last_bitallocation_band, bitallocation_exc, 0, st_fx->coder_type, + st_fx->bwidth_fx, exc_wo_nf, Q_PVQ_OUT, Q_exc, st_fx->GSC_noisy_speech_fx, NULL, st_fx->L_frame_fx, st_fx->element_mode, st_fx->GSC_IVAS_mode); + + exc_dct_in[0] = 0; + move16(); + + return; +} + +/*======================================================================*/ +/* FUNCTION : edyn_fx() */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Calculate energy dynamics in a vector */ +/* (ratio of energy maximum to energy mean) */ +/* */ +/*----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 *) vec : ratio of max to mean Qnew */ +/* _ (Word16) lvec : input vector */ +/* _ (Word16) Q_new : */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) dyn : ratio of energy maximum to energy mean (Q7) */ +/*-----------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ + +static Word16 edyn_fx( /* o : ratio of max to mean */ + const Word16 *vec, /* i : input vector */ + const Word16 lvec, /* i : length of input vector */ + Word16 Qnew +) +{ + Word16 j=0; + Word16 dyn; + Word32 L_tmp, ener_max, ener_mean; + Word16 tmp,exp2,tmp2,tmp1,exp1,exp3; + Word16 scale; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + ener_mean = L_shl(1,shl(Qnew,1)); /*2*Qnew*/ + ener_max = L_shl(1,shl(Qnew,1)); + + FOR( j=0; j 0) + { + exp1 = norm_l(ener_mean); +#ifdef BASOP_NOGLOB + tmp1 = round_fx_o(L_shl(ener_mean,exp1), &Overflow); +#else /* BASOP_NOGLOB */ + tmp1 = round_fx(L_shl(ener_mean,exp1)); +#endif + exp1 = sub(30,exp1); + + exp2 = norm_l(ener_max); + tmp2 = extract_h(L_shl(ener_max,exp2)); + exp2 = sub(30,exp2); + + scale = shr(sub(tmp1, tmp2), 15); + tmp2 = shl(tmp2, scale); + exp2 = sub(exp2, scale); + + exp3 = sub(exp1,exp2); + + tmp = div_s(tmp2, tmp1); /*Q(15+exp3)*/ + + L_tmp = L_shr_r(L_mult(tmp,10),exp3); + dyn = round_fx(L_shl(L_tmp,7)); /*Q7*/ + } + ELSE + { + dyn = 1280; + move16(); + } + return dyn; + +} + + +/*-------------------------------------------------------------------* + * GSC_enc_init_fx() + * + * Initialize GSC encoder state structure + *-------------------------------------------------------------------*/ + +void GSC_enc_init_fx( + GSC_ENC_HANDLE hGSCEnc /* i/o: GSC data handle */ +) +{ + /* AC mode */ + hGSCEnc->seed_tcx = 15687; + move16(); + hGSCEnc->cor_strong_limit = 1; + move16(); + set16_fx(hGSCEnc->last_exc_dct_in_fx, 0, L_FRAME16k); + //hGSCEnc->last_ener = 0.0f; IVAS_CODE + set16_fx(hGSCEnc->last_bitallocation_band, 0, 6); + + hGSCEnc->mem_last_pit_band = BAND1k2 + 1; + hGSCEnc->Last_frame_ener_fx = MAX_32; + move32(); + hGSCEnc->lt_gpitch_fx = 0; + move16(); + move16(); + hGSCEnc->pit_exc_hangover = 0; + move16(); + + hGSCEnc->mem_w0_tmp_fx = 0; + move16(); + + set16_fx(hGSCEnc->mem_syn_tmp_fx, 0, M); + hGSCEnc->mid_dyn_fx = 5120; + move16(); /*40 -> Q7 */ + hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); + hGSCEnc->past_dyn_dec = 0; + move16(); + + + return; +} diff --git a/lib_enc/guided_plc_enc_fx.c b/lib_enc/guided_plc_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..ab1bcc5f5441451ef079e3ff9f0fa96da05b45ef --- /dev/null +++ b/lib_enc/guided_plc_enc_fx.c @@ -0,0 +1,490 @@ +/*==================================================================================== + 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 */ +#include "stat_enc.h" +#include "basop_util.h" + + +/*-------------------------------------------------------------------* + * coderLookAheadInnovation() + * + * + *-------------------------------------------------------------------*/ +void coderLookAheadInnovation( + Word16 A_3Q12[], /* input: coefficients NxAz[M+1] */ + Word16 *pT, /* out: pitch */ + PLC_ENC_EVS_HANDLE st, /* i/o: coder memory state */ + Word16 *speechLookAhead_Qx, /* i: input speech in Q(st->Qold) */ + Word16 *old_exc, /* i: input excitation in Q(st->Qold) */ + Word16 L_frame +) +{ + Word16 i; + Word16 prev_pitch, T0_fx; + Word16 *exc_Qx, exc_buf_Qx[L_EXC_MEM+2*L_SUBFR+8]; + Word32 mantissa_max = -0x7fffffffL; + Word16 subfr_len = 0; + Word16 search_range = 9; + Word16 exc_max; + Word16 exc_sh; + Word32 ps,alp, alp_ini; + Word32 alp_s1, alp_s2; + Word16 k; + Word16 ps_e,alp_e; + Word32 max_ps, max_ps_tmp; + Word16 max_ps_e; + Word16 tmp_loop; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + /* Debug init (not instrumented) */ + T0_fx = -3000; + subfr_len = shl(L_SUBFR,1); /* 2*L_SUBFR */ + if( GT_16( L_FRAME16k, L_frame )) + { + subfr_len = add(L_SUBFR,48); /* 1.75*L_SUBFR */ + } + set16_fx(exc_buf_Qx, 0, L_EXC_MEM + 2 * L_SUBFR + 8); + + /*------------------------------------------------------------------------* + * - BASOP specific initialization. * + *------------------------------------------------------------------------*/ + /* initialization */ + exc_Qx = exc_buf_Qx + L_EXC_MEM + 8; + FOR( i=0; iT0_4th; + move16(); + /* find best candidate of pitch lag */ + T0_fx = st->T0_4th; + move16(); + mantissa_max = -0x7fffffffL; + move32(); + max_ps = -0x7fffffffL; + move32(); + max_ps_e = 16; + move16(); + + /*find maximum*/ + exc_max = 0; + move16(); + tmp_loop = s_min(-prev_pitch+search_range+subfr_len,0); + FOR(i=-prev_pitch-search_range; i < tmp_loop; i++) + { + exc_max = s_max(exc_Qx[i],exc_max); + } + FOR(i= 0; ipit_max)||LT_16(add(prev_pitch,i),st->pit_min)) + { + CONTINUE; + } + ps = L_deposit_l(0); + alp_s1 = L_deposit_l(0); + alp_s2 = L_deposit_l(0); + + FOR(k=0; kT0_4th; + move16(); + } + + /* Update excitation */ + pT[0] = T0_fx; + move16(); + + return; +} + +/************************************************************/ +/* Static functions */ +/************************************************************/ +/*-------------------------------------------------------------------* + * enc_prm_side_Info_fx() + * + * + *-------------------------------------------------------------------*/ +void enc_prm_side_Info_fx( + PLC_ENC_EVS_HANDLE hPlc_Ext, + Encoder_State_fx *st +) +{ + Word16 diff_pitch; + Word16 bits_per_subfr, search_range; + + bits_per_subfr = 4; + move16(); + search_range = 8; + move16(); + + IF( GT_16(hPlc_Ext->nBits,1)) + { + + push_next_indice_fx(st->hBstr, 1, 1); + + diff_pitch = sub(hPlc_Ext->T0, hPlc_Ext->T0_4th); + test(); + if( (GT_16(diff_pitch,sub(search_range,1)))||(LT_16(diff_pitch,add(-search_range,1)))) + { + diff_pitch = -8; + move16(); + } + + push_next_indice_fx(st->hBstr, add(diff_pitch, search_range), bits_per_subfr); + } + ELSE + { + push_next_indice_fx(st->hBstr, 0, 1); + } + + return; +} + +/*-------------------------------------------------------------------* + * encoderSideLossSimulation_fx() + * + * Encoder side loss simulation + *-------------------------------------------------------------------*/ +void encoderSideLossSimulation_fx( + Encoder_State_fx *st, + PLC_ENC_EVS_HANDLE hPlc_Ext, + Word16 *lsf_q, /* Q1*1.28 */ + const Word16 stab_fac, /* Q15 */ + const Word8 calcOnlyISF, + const Word16 L_frame +) +{ + Word16 lspLocal_Q15[M]; + Word16 const* xsfBase; /* base for differential XSF coding */ + + + /* Decoder State Update */ + IF( EQ_16(L_frame,L_FRAME_16k)) + { + lsf2lsp_fx( lsf_q, lspLocal_Q15, M, INT_FS_16k_FX ); + } + ELSE + { + lsf2lsp_fx( lsf_q, lspLocal_Q15, M, INT_FS_FX ); + } + + + xsfBase = PlcGetLsfBase (st->lpcQuantization, + st->narrowBand, + st->sr_core); + + Copy( st->mem_MA_fx, hPlc_Ext->mem_MA_14Q1, M ); + Copy( st->mem_AR_fx, hPlc_Ext->mem_AR, M ); + + + /* ISF parameter processing for concealment */ + updateLSFForConcealment( hPlc_Ext, lsf_q); + hPlc_Ext->stab_fac_Q15 = stab_fac; + move16(); + + Copy( lsf_q, hPlc_Ext->lsfold_14Q1, M ); + Copy( lspLocal_Q15, hPlc_Ext->lspold_Q15, M ); + + + IF (calcOnlyISF != 0) + { + /* ISF concealment simulation */ + getConcealedLSF( hPlc_Ext, xsfBase, st->clas_fx, L_frame ); + hPlc_Ext->T0 = hPlc_Ext->T0_4th; + move16(); + } + ELSE + { + Word16 old_exc_Qx[L_EXC_MEM+8]; + Word16 A_3Q12[(NB_SUBFR16k+1)*(M+1)]; + Word16 *speechLookAhead_Qx; + + /* calculate Q-value for input speech */ + speechLookAhead_Qx = &(st->speech_enc_pe[L_frame]); + + Copy( hPlc_Ext->old_exc_Qold, old_exc_Qx, 8 ); + Copy( hPlc_Ext->LPDmem->old_exc, &old_exc_Qx[8], L_EXC_MEM ); + Scale_sig( old_exc_Qx, 8, hPlc_Ext->Q_exp ); + + /* ISF concealment simulation */ + getConcealedLP( hPlc_Ext, A_3Q12, xsfBase, st->clas_fx, L_frame ); + + /* apply encoder side PLC simulation */ + hPlc_Ext->pit_min = st->pit_min; + move16(); + hPlc_Ext->pit_max = st->pit_max; + move16(); + coderLookAheadInnovation( A_3Q12, &(hPlc_Ext->T0), hPlc_Ext, speechLookAhead_Qx, old_exc_Qx, L_frame ); + } + return; +} + +/*-------------------------------------------------------------------* + * GplcTcxEncSetup_fx() + * + * + *-------------------------------------------------------------------*/ + +void GplcTcxEncSetup_fx( + Encoder_State_fx *st, + PLC_ENC_EVS_HANDLE hPlc_Ext, + Word16 Q_new +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + hPlc_Ext->T0_4th = hTcxEnc->tcxltp_pitch_int; + move16(); + hPlc_Ext->Q_exp = sub( Q_new, hPlc_Ext->Q_new); + move16(); + hPlc_Ext->Q_new = Q_new; + move16(); + set16_fx( hPlc_Ext->old_exc_Qold, 0, 8); +} +/*-------------------------------------------------------------------* + * encSideSpecPowDiffuseDetector_fx() + * + * + *-------------------------------------------------------------------*/ +Word16 encSideSpecPowDiffuseDetector_fx( + Word16 *lsf_ref, + Word16 *lsf_con, + const Word32 sr_core, + Word16 *prev_lsf4_mean, + const Word8 sw, + const Word16 coder_type +) +{ + Word16 tmp; + Word16 lsf_mod[M]; + Word32 dist1, dist2, cum_dist1, cum_dist2; + Word16 lsf4_mean; + Word16 th; + Word16 idx; + Word16 cnt_imprv, i; + Word32 L_tmp; + Word16 th_dif; + + /* calculate the mean of the lowest 4 LSFs */ + + L_tmp = L_mult(lsf_ref[0], 8192/*1.0/4.0 Q15*/); + L_tmp = L_mac(L_tmp, lsf_ref[1], 8192/*1.0/4.0 Q15*/); + L_tmp = L_mac(L_tmp, lsf_ref[2], 8192/*1.0/4.0 Q15*/); + lsf4_mean = mac_r(L_tmp, lsf_ref[3], 8192/*1.0/4.0 Q15*/); + + IF(sw) + { + Copy(lsf_con, lsf_mod, M); + + modify_lsf(lsf_mod, M, sr_core, 1 ); + + move16(); + move16(); + cum_dist1 = 0; + cum_dist2 = 0; + + cnt_imprv = 0; + + IF( EQ_32( sr_core, INT_FS_16k)) + { + th = 2560; + move16(); /* LSF */ + th_dif = 288; + move16(); /* LSF */ + } + ELSE + { + th = 2048; + move16(); /* LSF */ + th_dif = 230; + move16(); /* LSF */ + } + + FOR(i = 0; i < M; i++) + { + tmp = sub(lsf_con[i], lsf_ref[i]); + dist1 = L_mult(tmp, tmp); + tmp = sub(lsf_mod[i], lsf_ref[i]); + dist2 = L_mult(tmp, tmp); + + if(GT_32(dist1, dist2)) + { + cnt_imprv = add(cnt_imprv, 1); + } + cum_dist1 = L_add(cum_dist1, dist1); + cum_dist2 = L_add(cum_dist2, dist2); + } + + idx = 0; + move16(); + + test(); + test(); + test(); + if(GT_32(cum_dist1, L_add(cum_dist2, Mpy_32_16_1(cum_dist2, 4915))) + && GT_16(sub(lsf4_mean, *prev_lsf4_mean), th_dif) + && LT_16(*prev_lsf4_mean, th) + && GT_16(cnt_imprv, 2) + && EQ_16(coder_type, GENERIC) ) + { + idx = 1; + move16(); + } + + } + ELSE + { + move16(); + idx = 0; + } + /* update parameters */ + move16(); + *prev_lsf4_mean = lsf4_mean; + + return idx; +} +/*-------------------------------------------------------------------* + * updateSpecPowDiffuseIdx_fx() + * + * + *-------------------------------------------------------------------*/ +void updateSpecPowDiffuseIdx_fx( + Encoder_State_fx *st +) +{ + Word16 min_gp; + Word16 k; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + move32(); + move16(); + st->mean_gc[1] = st->gain_code[0]; + min_gp = st->bpf_gainT[0]; + + FOR(k = 1; k < 4; k++) + { +#ifdef BASOP_NOGLOB + st->mean_gc[1] = L_add_o(st->mean_gc[1], st->gain_code[k], &Overflow); +#else /* BASOP_NOGLOB */ + st->mean_gc[1] = L_add(st->mean_gc[1], st->gain_code[k]); +#endif + min_gp = s_min(min_gp, st->bpf_gainT[k]); + } + + /* Suppress saturation warning in threshold comparison. */ + test(); +#ifdef BASOP_NOGLOB + if(LT_32(st->mean_gc[1], L_add_o(st->mean_gc[0], Mpy_32_16_r(st->mean_gc[0], 3211/*0.098 Q15*/), &Overflow))||GT_16(min_gp, 13435/*0.82 Q14*/)) +#else + if(LT_32(st->mean_gc[1], L_add(st->mean_gc[0], Mpy_32_16_r(st->mean_gc[0], 3211/*0.098 Q15*/)))||GT_16(min_gp, 13435/*0.82 Q14*/)) +#endif + { + move16(); + st->glr_idx [0]= 0; + } + move16(); + st->mean_gc[0] = st->mean_gc[1]; + +} diff --git a/lib_enc/hf_cod_amrwb_fx.c b/lib_enc/hf_cod_amrwb_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..ac65954d2aaed2f0cfc6b9cfd1fa0b488757cf49 --- /dev/null +++ b/lib_enc/hf_cod_amrwb_fx.c @@ -0,0 +1,247 @@ +/*==================================================================================== + 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" +#include "rom_com_fx.h" +#include "cnst.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 */ + + /*---------------------------------------------------------------------* + * hf_cod_init() + * + * + *---------------------------------------------------------------------*/ +void hf_cod_init_fx( + Word16 *mem_hp400_enc, /* o: memory of hp 400 Hz filter */ + Word16 *mem_hf1_enc, /* o: HF band-pass filter memory */ + Word16 *mem_syn_hf_enc, /* o: HF synthesis memory */ + Word16 *mem_hf2_enc, /* o: HF band-pass filter memory */ + Word16 *gain_alpha_fx /* o: smoothing gain for transitions between active and inactive frames */ +) +{ + set16_fx( mem_hp400_enc, 0, 6); + set16_fx( mem_hf1_enc, 0, L_FIR-1 ); + set16_fx( mem_syn_hf_enc, 0, M ); + set16_fx( mem_hf2_enc, 0, L_FIR-1 ); + + *gain_alpha_fx = 16384; + move16(); + + return; +} + +/*---------------------------------------------------------------------* + * hf_cod() + * + * + *---------------------------------------------------------------------*/ + +void hf_cod_fx( + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 *speech16k_fx, /* i : original speech at 16 kHz */ + const Word16 Aq_fx[], /* i : quantized Aq */ + const Word16 exc_fx[], /* i : excitation at 12.8 kHz */ + Word16 synth_fx[], /* i : 12.8kHz synthesis signal */ + Word16 *seed2_enc_fx, /* i/o: random seed for HF noise gen */ + Word16 *mem_hp400_enc_fx, /* i/o: memory of hp 400 Hz filter */ + Word16 *mem_syn_hf_enc_fx, /* i/o: HF synthesis memory */ + Word16 *mem_hf1_enc_fx, /* i/o: HF band-pass filter memory */ + Word16 *mem_hf2_enc_fx, /* i/o: HF band-pass filter memory */ + const Word16 dtxHangoverCount_fx, + Word16 *gain_alpha_fx, /* i/o: smoothing gain for transitions between active and inactive frames */ + Word16 *hf_gain_fx, /* o : HF gain to be transmitted to decoder */ + Word16 Q_exc, + Word16 Q_syn +) +{ + /*------------------------Scaling------------------------------------------------- + speech16k - Q0 + Aq - Q12 + exc - Q_exc + synth - Q_syn + mem_hp400_enc - Q_syn + mem_syn_hf_enc - Q0 + mem_hf1_enc - Q0 + mem_hf2_enc - Q0 + gain_alpha_fx - Q14 + ener - all dynamic + fac, scale - Q12 + Ap - Q12 + HF_SP - Q0 + ---------------------------------------------------------------------------------*/ + + Word16 i, q1, q2, sign; + Word16 shift; + Word16 ener_hf_fx, ener_exc_fx, ener_input_fx, fac_fx, tmp_fx, ener_fx, scale_fx; + Word16 Ap_fx[M+1]; + Word16 HF_SP_fx[L_SUBFR16k]; + Word16 HF_est_gain_fx, HF_calc_gain_fx, HF_corr_gain_fx, HF_gain_ind_fx; + Word32 dist_min_fx, dist_fx; + Word16 HF_fx[L_SUBFR16k], HF_syn_fx[L_SUBFR16k]; /* o : HF excitation */ + Word32 L_tmp; + Word16 *pt1; + const Word16 *pt2; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /* Original speech signal as reference for high band gain quantisation */ + Copy(speech16k_fx, HF_SP_fx, L_SUBFR16k); + + /*-----------------------------------------------------------------* + * generate white noise vector + *-----------------------------------------------------------------*/ + + Random_Fill(seed2_enc_fx, L_SUBFR16k, HF_fx, 3); /*Q(-3) */ + + /*-----------------------------------------------------------------* + * calculate energy scaling factor so that white noise would have the + * same energy as exc12k8 + *-----------------------------------------------------------------*/ + + ener_exc_fx = dot_prod_satcontr(exc_fx, exc_fx, Q_exc, Q_exc, &q1, L_SUBFR); + ener_hf_fx = dot_prod_satcontr(HF_fx, HF_fx, -3, -3, &q2, L_SUBFR16k); + + scale_fx = div_s(shl(1, 14), ener_exc_fx); /*Q(29-q1) */ + L_tmp = L_mult(ener_hf_fx, scale_fx); /*30-q1+q2 */ + q2 = sub(q1, q2); /*30-q2 */ +#ifdef BASOP_NOGLOB + scale_fx = round_fx(Isqrt(L_shl_o(L_tmp, sub(q2, 26), &Overflow))); /*Q13 */ +#else /* BASOP_NOGLOB */ + scale_fx = round_fx(Isqrt(L_shl(L_tmp, sub(q2, 26)))); /*Q13 */ +#endif /* BASOP_NOGLOB */ + + + pt1 = HF_fx; + FOR( i = 0; i < L_SUBFR16k; i++ ) + { + *pt1 = round_fx(L_shl(L_mult((*pt1), scale_fx), 5)); /*Q0 */ + pt1++; + } + + /*-----------------------------------------------------------------* + * calculate energy scaling factor to respect tilt of synth12k8 + * (tilt: 1=voiced, -1=unvoiced) + *-----------------------------------------------------------------*/ + + hp400_12k8_fx( synth_fx, L_SUBFR, mem_hp400_enc_fx ); /*synth_fx: Q(Q_syn-4) */ + + ener_fx = dot_prod_satcontr(&synth_fx[1], &synth_fx[1], sub(Q_syn, 4), sub(Q_syn, 4), &q1, sub(L_SUBFR, 1)); + tmp_fx = dot_prod_satcontr(&synth_fx[1], synth_fx, sub(Q_syn ,4), sub(Q_syn, 4), &q2, sub(L_SUBFR, 1)); + + IF ( GE_16(abs_s(tmp_fx), ener_fx )) + { + tmp_fx = shr(tmp_fx, 1); + q2 = sub(q2, 1); + } + + sign = 0; + move16(); + IF ( tmp_fx < 0 ) + { + tmp_fx = abs_s(tmp_fx); + sign = 1; + move16(); + } + + fac_fx = div_s(tmp_fx, ener_fx); /*Q(15+q2-q1) */ + shift = sub(q1, add(q2, 5)); + fac_fx = shl(fac_fx, shift); /*Q10 */ + IF (sign) + { + fac_fx = s_xor(fac_fx, -1); + } + + HF_est_gain_fx = sub(1024, fac_fx); /*Q12 */ + + test(); + IF( EQ_32(core_brate_fx, SID_1k75)||core_brate_fx==FRAME_NO_DATA) + { + HF_est_gain_fx = round_fx(L_shl(L_mult(HF_est_gain_fx, 20480), 1)); /*Q10 */ + } + + HF_est_gain_fx = s_max(HF_est_gain_fx, 102); + HF_est_gain_fx = s_min(HF_est_gain_fx, 1024); + + /*-----------------------------------------------------------------* + * synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz + *-----------------------------------------------------------------*/ + + weight_a_lc_fx( Aq_fx, Ap_fx, Gamma_19661_Tbl_fx, M ); + Syn_filt_s( 0, Ap_fx, M, HF_fx, HF_syn_fx, L_SUBFR16k, mem_syn_hf_enc_fx, 1 ); /*Q0 */ + + /*-----------------------------------------------------------------* + * high pass filtering (0.9375ms of delay = 15 samples@16k) + *-----------------------------------------------------------------*/ + + fir_fx(HF_syn_fx, fir_6k_8k_fx, HF_syn_fx, mem_hf1_enc_fx, L_SUBFR16k, L_FIR-1, 1, 0); + fir_fx(HF_SP_fx, fir_6k_8k_fx, HF_SP_fx, mem_hf2_enc_fx, L_SUBFR16k, L_FIR-1, 1, 0); + + /* check the gain difference */ + + ener_hf_fx = dot_prod_satcontr(HF_syn_fx, HF_syn_fx, 0, 0, &q2, L_SUBFR16k); + ener_input_fx = dot_prod_satcontr(HF_SP_fx, HF_SP_fx, 0, 0, &q1, L_SUBFR16k); + + HF_calc_gain_fx = div_s(shl(1, 14), ener_input_fx); /*Q(29-q1) */ + L_tmp = L_mult(ener_hf_fx, HF_calc_gain_fx); /*30-q1+q2 */ + q2 = sub(q1, q2); /*30-q2 */ +#ifdef BASOP_NOGLOB + HF_calc_gain_fx = round_fx_o(Isqrt(L_shl(L_tmp, sub(q2, 20))), &Overflow); /*Q10 */ +#else /* BASOP_NOGLOB */ + HF_calc_gain_fx = round_fx(Isqrt(L_shl(L_tmp, sub(q2, 20)))); /*Q10 */ +#endif + + + /* set energy of HF synthesis to energy of original HF: + cross-fade between HF levels in active and inactive frame in hangover period */ + + IF ( GT_16(4, dtxHangoverCount_fx)) + { + *gain_alpha_fx = 16384; + move16(); + } + ELSE + { + L_tmp = L_shl(L_mult(sub(10, dtxHangoverCount_fx), 4681), 15);/*Q31 */ + L_tmp = Mult_32_16(L_tmp, *gain_alpha_fx); /*Q30 */ + *gain_alpha_fx = round_fx(L_tmp); /*Q14 */ + } + L_tmp = L_mult(sub(16384, *gain_alpha_fx), HF_est_gain_fx); /*Q25 */ + L_tmp = L_mac(L_tmp, *gain_alpha_fx, HF_calc_gain_fx); /*Q25 */ + IF (GE_32(L_tmp,67108863)) + { + L_tmp = 67108863; + move32(); + } + L_tmp = L_shl(L_tmp, 5); + HF_corr_gain_fx = extract_h(L_tmp); /*Q14; HF_corr_gain_fx/2 in Q15 */ + + /* Quantize the correction gain */ + dist_min_fx = 2147483647; + move32(); + HF_gain_ind_fx = 0; + move16(); + pt2 = HP_gain_fx; + FOR ( i = 0; i < 16; i++ ) + { + dist_fx = L_mult(sub(HF_corr_gain_fx, *pt2), sub(HF_corr_gain_fx, *pt2)); + pt2++; + IF ( GT_32(dist_min_fx, dist_fx)) + { + dist_min_fx = L_add(dist_fx, 0); + HF_gain_ind_fx = i; + move16(); + } + } + *hf_gain_fx = HF_gain_ind_fx; + move16(); + + return; +} diff --git a/lib_enc/hq_classifier_enc_fx.c b/lib_enc/hq_classifier_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..75422d5694a2581b4483fc22276f955c56ad81f1 --- /dev/null +++ b/lib_enc/hq_classifier_enc_fx.c @@ -0,0 +1,869 @@ +/*==================================================================================== + 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 */ + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define SHARP_DIST_THRES_FX 1420 /* Q6, 22.2 */ + +#define HALF_WIN_LENGTH 10 +#define L_SPEC_HB 320 +#define PEAK_THRESHOLD 3277 /*Q15 0.1f*/ +#define LOW_COUNT_THRESHOLD 220 + + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +void hvq_classifier_fx( const Word32 *input, Word16 *prev_Npeaks, Word16 *prev_peaks, + Word16 *hqswb_clas, Word16 *Npeaks, Word16 *peaks, const Word32 L_core_brate, + const Word16 last_core, Word32 *L_nf_gains, Word16 *hvq_hangover, Word32 *L_pe_gains ); + +/*--------------------------------------------------------------------------* + * hq_classifier_enc_fx() + * + * HQ mode selector (decision_matrix) + *--------------------------------------------------------------------------*/ + +Word16 hq_classifier_enc_fx( /* o : Consumed bits Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 length, /* i : Frame length Q0 */ + const Word32 *coefs, /* i : Spectral coefficients Q12 */ + const Word16 is_transient, /* i : Transient flag Q0 */ + Word16 *Npeaks, /* o : Number of identified peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + Word32 *pe_gains, /* o : Peak gains Q12 */ + Word32 *nf_gains, /* o : Noise-fill gains Q12 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +) +{ +#ifndef SOLVED_COMP_ENC_DEC + Word16 bits; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + + *hqswb_clas = HQ_NORMAL; + IF(EQ_16(is_transient, 1)) + { + *hqswb_clas = HQ_TRANSIENT; + move16(); + } + + /* classification and limit bandwidth for bit allocation */ + test(); + test(); + test(); + IF(EQ_16(length, L_FRAME32k) && NE_16(is_transient, 1) && LE_32(st_fx->core_brate_fx, HQ_32k) && EQ_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) + { + /* Detect HQ_HARMONIC mode */ + *hqswb_clas = peak_avrg_ratio_fx(st_fx->total_brate_fx, coefs, NUMC_N + 96, &hHQ_core->mode_count, &hHQ_core->mode_count1, 12); + + /* Detect harmonic VQ mode HQ_HVQ */ + hvq_classifier_fx(coefs, &hHQ_core->prev_Npeaks, hHQ_core->prev_peaks, hqswb_clas, Npeaks, peaks, st_fx->core_brate_fx, st_fx->last_core_fx, + nf_gains, &hHQ_core->hvq_hangover, pe_gains); + } + + test(); + test(); + test(); + IF(EQ_16(length, L_FRAME48k) && NE_16(is_transient, 1) && LE_32(st_fx->core_brate_fx, HQ_32k) && EQ_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) + { + /* Detect HQ_HARMONIC mode */ + *hqswb_clas = peak_avrg_ratio_fx(st_fx->total_brate_fx, coefs, NUMC_N + 96, &hHQ_core->mode_count, &hHQ_core->mode_count1, 12); + /* Detect harmonic VQ mode HQ_HVQ */ + hvq_classifier_fx(coefs, &hHQ_core->prev_Npeaks, hHQ_core->prev_peaks, hqswb_clas, Npeaks, peaks, + st_fx->core_brate_fx, st_fx->last_core_fx, nf_gains, &hHQ_core->hvq_hangover, pe_gains); + } + + test(); + test(); + IF(EQ_16(length, L_FRAME48k) && LE_32(st_fx->core_brate_fx, HQ_32k) && EQ_16(*hqswb_clas, HQ_NORMAL)) + { + *hqswb_clas = HQ_GEN_FB; + move16(); + } + + test(); + IF(GE_16(length, L_FRAME32k) && LE_32(st_fx->core_brate_fx, HQ_32k)) + { + bits = 2; + move16(); + } + ELSE + { + bits = 1; + move16(); + } + + test(); + IF(EQ_16(length, L_FRAME48k) && LE_32(st_fx->core_brate_fx, HQ_32k)) + { + IF(GE_16(*hqswb_clas, HQ_GEN_SWB)) + { + push_indice_fx(st_fx->hBstr, IND_HQ_SWB_CLAS, *hqswb_clas - 5, bits); + } + ELSE + { + push_indice_fx(st_fx->hBstr, IND_HQ_SWB_CLAS, *hqswb_clas, bits); + } + } + ELSE + { + push_indice_fx(st_fx->hBstr, IND_HQ_SWB_CLAS, *hqswb_clas, bits); + } + + test(); + test(); + IF(EQ_16(*hqswb_clas, HQ_NORMAL) && EQ_16(length, L_FRAME32k) && LE_32(st_fx->core_brate_fx, HQ_32k)) + { + *hqswb_clas = HQ_GEN_SWB; + move16(); + } +#else + + Word16 bits; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + Word32 max_brate; + Word16 harmonic_decision; + + + max_brate = HQ_32k; move32(); + if (GT_16(st_fx->element_mode, EVS_MONO)) + { + max_brate = HQ_48k; + move32(); + } + + *hqswb_clas = HQ_NORMAL; + bits = 1; move16(); + IF( EQ_16( is_transient, 1)) + { + *hqswb_clas = HQ_TRANSIENT; + move16(); + } + + /* classification and limit bandwidth for bit allocation */ + test(); + IF (EQ_16(length, L_SPEC32k) || EQ_16(length, L_SPEC48k)) + { + IF(LE_32(st_fx->core_brate_fx, max_brate)) + { + test(); + IF(!is_transient && EQ_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) + { + /* Detect HQ_HARMONIC mode */ + *hqswb_clas = peak_avrg_ratio_fx(st_fx->total_brate_fx, coefs, NUMC_N + 96, &hHQ_core->mode_count, &hHQ_core->mode_count1, 12); + +#ifdef ADD_IVAS_HQ_CODE + harmonic_decision = hf_spectrum_sparseness(st, coefs); +#else + harmonic_decision = 0; +#endif + test(); + IF(EQ_16(*hqswb_clas, HQ_HARMONIC) && !harmonic_decision) + { + *hqswb_clas = HQ_NORMAL; + move16(); + } + ELSE + { + /* Detect harmonic VQ mode HQ_HVQ */ + hvq_classifier_fx(coefs, &hHQ_core->prev_Npeaks, hHQ_core->prev_peaks, hqswb_clas, Npeaks, peaks, st_fx->core_brate_fx, st_fx->last_core_fx, + nf_gains, &hHQ_core->hvq_hangover, pe_gains); + } + } + bits = 2; move16(); + } + } + ELSE IF(EQ_16(length, L_SPEC16k_EXT) || EQ_16(length, L_SPEC48k_EXT)) + { + bits = 0; /* HQ_NORMAL only -- no signalling needed */ + move16(); + } + /* write signalling info to the bitstream */ + push_indice_fx(st_fx->hBstr, IND_HQ_SWB_CLAS, *hqswb_clas, bits); + + IF (LE_32(st_fx->core_brate_fx, HQ_32k) && EQ_16(*hqswb_clas, HQ_NORMAL)) + { + IF (EQ_16(length, L_SPEC32k)) + { + *hqswb_clas = HQ_GEN_SWB; move16(); + } + ELSE IF (EQ_16(length, L_SPEC48k)) + { + *hqswb_clas = HQ_GEN_FB; move16(); + } + } +#endif + return bits; +} + +/*--------------------------------------------------------------------------* + * peak_avrg_ratio() + * + * Classify the input signal and decide if it has a harmonic structure + *--------------------------------------------------------------------------*/ +Word16 peak_avrg_ratio_fx( + const Word32 total_brate, /* i : total bitrate */ + const Word32 *input_hi_fx, /* i : input signal */ + const Word16 length, /* i : number of coefficients */ + Word16 *mode_count, /* i/o: HQ_HARMONIC mode count */ + Word16 *mode_count1, /* i/o: HQ_NORMAL mode count */ + Word16 Q_coeff +) +{ + Word16 i, j, q, k, k1, hqswb_clas; + Word32 mean_fx, peak_fx; + Word32 input_abs_fx[L_FRAME32k]; + Word32 peak_th_fx; + + FOR ( i = 96; i < length; i++) + { + input_abs_fx[i] = L_abs(input_hi_fx[i]); + } + + hqswb_clas = HQ_NORMAL; + move16(); + peak_th_fx = L_shl(10L, sub(Q_coeff, 5)); /* 5 is safe shift */ + + k = 0; + move16(); + k1 = 0; + move16(); + q = 96; /* q used for indexing */ + + FOR( i = 3; i < 17; i ++ ) + { + peak_fx = L_deposit_l(0); + mean_fx = L_deposit_l(1); + + /*for(j = 0; j < 32; j ++, q ++) */ + FOR(j = 0; j < 32; j ++) + { + input_abs_fx[q] =L_shr(input_abs_fx[q],5); /*Q_coeff-5 */ + mean_fx =L_add(mean_fx,input_abs_fx[q]); /*Q_coeff-5 */ + IF (GT_32(input_abs_fx[q] , peak_fx)) + { + peak_fx =input_abs_fx[q] ; /*Q_coeff-5 */ + } + q ++; + } + + IF(LT_16(i,8)) + { + if(GT_32(peak_fx, Mult_32_16(mean_fx, 4608))) /* Q15 0.140625 */ + { + k = add(k,1); + } + } + ELSE + { + test(); + if(GT_32(peak_fx, Mult_32_16(mean_fx, 3686)) /*Q15 0.1125 */ + && GT_32(peak_fx, peak_th_fx)) /*Q27 10 */ + { + k1 = add(k1,1); + } + } + } + + test(); + IF( GE_16(add(k,k1),10)&>_16(k1,5)) + { + if( LT_16(*mode_count,8)) + { + *mode_count = add(*mode_count,1); + } + + if( *mode_count1 > 0 ) + { + *mode_count1 = sub(*mode_count1,1); + } + } + ELSE + { + if( LT_16(*mode_count1,8)) + { + *mode_count1 = add(*mode_count1,1); + } + + if( *mode_count > 0 ) + { + *mode_count = sub(*mode_count,1); + } + } + + test(); + test(); + test(); + test(); + test(); + test(); +#ifndef SOLVED_COMP_ENC_DEC /*This affect BE even if it shouldn't*/ + if ((GE_16(add(k, k1), 5) && GT_16(k1, 2) && EQ_32(total_brate, HQ_24k40)) + || (((GE_16(add(k, k1), 10) && GT_16(k1, 5)) || GE_16(*mode_count, 5)) && LT_16(*mode_count1, 5))) +#else + if ((GE_16(add(k, k1), 5) && GT_16(k1,2) && LT_32(total_brate, HQ_BWE_CROSSOVER_BRATE)) + || (((GE_16(add(k, k1), 10) && GT_16(k1, 5) ) || GE_16(*mode_count, 5) ) && LT_16(*mode_count1, 5) )) +#endif + { + hqswb_clas = HQ_HARMONIC; + move16(); + } + + return hqswb_clas; +} + +/*--------------------------------------------------------------------------* + * hvq_classifier() + * + * Classification of harmonic low band content for Harmonic VQ + *--------------------------------------------------------------------------*/ + +void hvq_classifier_fx( + const Word32 *input, /* i : input signal Q12 */ + Word16 *prev_Npeaks, /* i/o: Peak number memory Q0 */ + Word16 *prev_peaks, /* i/o: Peak indices memory Q0 */ + Word16 *hqswb_clas, /* i/o: HQ class Q0 */ + Word16 *Npeaks, /* o : Number of peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + const Word32 L_core_brate, /* i : Core bit-rate Q0 */ + const Word16 last_core, /* i : Last core used Q0 */ + Word32 *L_nf_gains, /* o : Noisefloor gains Q12 */ + Word16 *hvq_hangover, /* i/o: Mode-switch hangover Q0 */ + Word32 *L_pe_gains /* o : peak gains Q12 */ +) +{ + const Word16 *p_adj; + UWord16 lsb; + + Word32 L_input_abs[L_FRAME32k]; + Word32 L_input_max; + Word32 L_thr[L_FRAME16k]; + Word32 L_thr_tmp; + Word32 L_m; + Word32 L_tmp; + Word32 L_d; + Word32 L_peak; + Word32 L_nf, L_pe; + Word32 L_pe_mean[HVQ_NSUB_32k], L_nf_mean[HVQ_NSUB_32k]; + + Word16 inv_nsub; + Word16 sharp_dist; + Word16 exp1, exp2; + Word16 tmp; + Word16 shift; + Word16 idx; + Word16 frac; + Word16 inv_nf_mean; + Word16 inv_gains_nsub; + Word16 nf_mean_norm; + Word16 num_sharp_bands, i, j, k, q, peak_th, nsub, pindx, N, offset; + Word16 num_peak_cands, high, low; + Word16 sharp[HVQ_NSUB_32k]; + Word16 peak_cand_idx[HVQ_THRES_BIN_32k], avail_peaks[HVQ_NSUB_32k]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + L_input_max = L_deposit_l(0); + set32_fx(L_thr, 0, L_FRAME16k); + +#ifndef SOLVED_COMP_ENC_DEC + IF(EQ_32(L_core_brate, HQ_24k40)) +#else + IF ( LT_32(L_core_brate, HQ_BWE_CROSSOVER_BRATE)) +#endif + { + nsub = HVQ_NSUB_24k; + move16(); + inv_nsub = 4681; + move16(); /* 1/7 in Q15 */ + inv_gains_nsub = 10923; + move16(); /* 1/3 in Q15 */ + } + ELSE + { + nsub = HVQ_NSUB_32k; + move16(); + inv_nsub = 3277; + move16(); /* 1/10 in Q15 */ + inv_gains_nsub = 6554; + move16(); /* 1/5 in Q15 */ + } + + N = shl(nsub, 5); /* Mult by 32 (HVQ_BW) */ + + test(); + test(); + IF ( EQ_16(*hqswb_clas, HQ_HARMONIC)&&last_core!=ACELP_CORE&&NE_16(last_core,AMR_WB_CORE)) + { + FOR ( i = 0; i < N; i++ ) + { + L_input_abs[i] = L_abs(input[i]); + if (L_input_abs[i] > L_input_max) + { + L_input_max = L_input_abs[i]; + move16(); + } + } + + exp1 = norm_l(L_input_max); + + *Npeaks = 0; + move16(); + L_nf = 3276800; + move32(); /* 800 in Q12 */ + L_pe = 3276800; + move32(); /* 800 in Q12 */ + num_sharp_bands = 0; + move16(); + k = 0; + move16(); + q = 0; + move16(); + sharp_dist = 0; + move16(); + + /* Find peak threshold */ + FOR ( i = 0; i < nsub; i++ ) + { + L_peak = 0; + L_nf_mean[i] = 0; + L_pe_mean[i] = 0; + FOR ( j = 0; j < HVQ_BW; j++ ) + { + L_d = L_input_abs[q]; + IF ( GT_32(L_d, L_nf)) + { + /*nf = HVQ_NF_WEIGHT1 * nf + (1 - HVQ_NF_WEIGHT1) * d; */ + Mpy_32_16_ss(L_d, HVQ_NF_WEIGHT1B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_nf, HVQ_NF_WEIGHT1_FX, &L_nf, &lsb); /* 12+15-15=12 */ + L_nf = L_add(L_nf, L_tmp); /*Q12 */ + } + ELSE + { + /*nf = HVQ_NF_WEIGHT2 * nf + (1 - HVQ_NF_WEIGHT2) * d; */ + Mpy_32_16_ss(L_d, HVQ_NF_WEIGHT2B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_nf, HVQ_NF_WEIGHT2_FX, &L_nf, &lsb); /* 12+15-15=12 */ + L_nf = L_add(L_nf, L_tmp); /*Q12 */ + } + + IF ( GT_32(L_d, L_pe)) + { + /*pe = HVQ_PE_WEIGHT1 * pe + (1 - HVQ_PE_WEIGHT1) * d; */ + Mpy_32_16_ss(L_d, HVQ_PE_WEIGHT1B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_pe, HVQ_PE_WEIGHT1_FX, &L_pe, &lsb); /* 12+15-15=12 */ + L_pe = L_add(L_pe, L_tmp); /*Q12 */ + } + ELSE + { + /*pe = HVQ_PE_WEIGHT2 * pe + (1 - HVQ_PE_WEIGHT2) * d; */ + Mpy_32_16_ss(L_d, HVQ_PE_WEIGHT2B, &L_tmp, &lsb); /* 12+15-15=12 */ + Mpy_32_16_ss(L_pe, HVQ_PE_WEIGHT2_FX, &L_pe, &lsb); /* 12+15-15=12 */ + L_pe = L_add(L_pe, L_tmp); /*Q12 */ + } + + L_nf_mean[i] = L_add(L_nf_mean[i], L_nf); + L_pe_mean[i] = L_add(L_pe_mean[i], L_pe); + + IF ( GT_32(L_d, L_peak)) + { + L_peak = L_add(L_d, 0); + } + + q = add(q, 1); + } + L_nf_mean[i] = L_shr(L_nf_mean[i], 5); /* Divide by 5 (HVQ_BW) */ + L_pe_mean[i] = L_shr(L_pe_mean[i], 5); /* Divide by 5 (HVQ_BW) */ + + /*thr_tmp = (float)pow( pe_mean[i]/nf_mean[i], HVQ_THR_POW ) * nf_mean[i]; */ + exp1 = norm_l(L_nf_mean[i]); + nf_mean_norm = extract_h(L_shl(L_nf_mean[i], exp1)); /* 12+s-16=s-4 */ + IF ( nf_mean_norm == 0 ) + { + inv_nf_mean = 0; + } + ELSE + { + inv_nf_mean = div_s(1<<14, nf_mean_norm); /* 15+14-s+4=33-s */ + } + Mpy_32_16_ss(L_pe_mean[i], inv_nf_mean, &L_tmp, &lsb); /*12+33-s-15=30-s */ + + exp2 = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp2)); /* Q15 */ + exp2 = exp1 - exp2; /* Q0 */ + L_tmp = Mpy_32_16(exp2, tmp, 32767); /* 1 in Q15. Q16 */ + Mpy_32_16_ss(L_tmp, 28836, &L_tmp, &lsb); /* 16+15-15=16 */ + frac = L_Extract_lc(L_tmp, &tmp); /* Q15 and Q0 */ + L_tmp = Pow2(14, frac); /* Q14 */ + L_tmp = L_shl(L_tmp, tmp); /* Q14 */ + + Mpy_32_16_ss(L_tmp, nf_mean_norm, &L_tmp, &lsb); /*14+s-4-15=s-5 */ + shift = sub(17, exp1); /* 16-(s-5)=17-s */ + L_thr_tmp = L_shl(L_tmp, shift); /* Q16 */ + L_thr_tmp = L_add(L_thr_tmp, lshr(lsb, sub(16, shift))); /*Q16 */ + + set32_fx(&L_thr[k], L_thr_tmp, HVQ_BW); + k = add(k, HVQ_BW); + + /*sharp[i] = peak/nf_mean[i]; */ + Mpy_32_16_ss(L_peak, inv_nf_mean, &L_tmp, &lsb); /* 12+33-s-15=30-s */ + shift = sub(exp1, 8); + sharp[i] = extract_h(L_shl(L_tmp, shift)); /* 30-s+s-8-16 -> Q6 */ + + /*sharp_dist += (sharp[i]-HVQ_SHARP_THRES); */ +#ifdef BASOP_NOGLOB + sharp_dist = add_o(sharp_dist, sub(sharp[i], HVQ_SHARP_THRES_FX), &Overflow); +#else + sharp_dist = add(sharp_dist, sub(sharp[i], HVQ_SHARP_THRES_FX)); +#endif + if ( GT_16(sharp[i], HVQ_SHARP_THRES_FX)) + { + num_sharp_bands = add(num_sharp_bands, 1); + } + } + + /* Estimate noise floor gains */ + offset = s_and(nsub, 1); + FOR ( i = 0; i < s_and(nsub, (Word16)0xFFFE); i++ ) + { + /*(2*i+1)/nsub */ + idx = mult(add(shl(i, 1), 1), add(inv_nsub, 1)); /*0+15-15 = 0 */ + L_nf_gains[idx] = L_add(L_nf_gains[idx], L_nf_mean[i+offset]); + L_pe_gains[idx] = L_add(L_pe_gains[idx], L_pe_mean[i+offset]); + } + + FOR ( i = 0; i < HVQ_NF_GROUPS; i++ ) + { + Mpy_32_16_ss(L_nf_gains[i], inv_gains_nsub, &L_nf_gains[i], &lsb); /*12+15-15=12 */ + Mpy_32_16_ss(L_pe_gains[i], inv_gains_nsub, &L_pe_gains[i], &lsb); /*12+15-15=12 */ + } + + /* Allocate available peaks */ + FOR ( i = 0; i < nsub; i++ ) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP1; + move16(); + idx = mult(add(shl(i, 1), 1), add(inv_nsub, 1)); /*0+15-15 = 0 */ + Mpy_32_16_ss(L_nf_gains[idx], HVQ_PA_FAC_FX, &L_tmp, &lsb); /* 12+15-15 -> Q12 */ + IF( LT_32(L_nf_mean[i], L_tmp)) + { + IF ( LT_16(sharp[i], HVQ_PA_SHARP_THRES3_FX)) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP3; + move16(); + } + ELSE IF( LT_16(sharp[i], HVQ_PA_SHARP_THRES2_FX)) + { + avail_peaks[i] = HVQ_PA_PEAKS_SHARP2; + move16(); + } + } + } + + + + /* Adjust threshold around previous peaks */ + FOR ( i = 0; i < *prev_Npeaks; i++ ) + { + j = sub(prev_peaks[i], 2); + k = add(prev_peaks[i], 2); + p_adj = hvq_thr_adj_fx; + + FOR( q = j; q < k; q++ ) + { + Mpy_32_16_ss(L_thr[q], *p_adj++, &L_thr[q], &lsb); /* 12+15-15=12 */ + move32(); + } + } + + num_peak_cands = 0; + move16(); + + /* Remove everything below threshold for peak search */ + L_input_abs[0] = L_deposit_l(0); + L_input_abs[1] = L_deposit_l(0); + L_input_abs[N-2] = L_deposit_l(0); + L_input_abs[N-1] = L_deposit_l(0); + FOR ( i = 0; i < N-2; i++ ) + { + IF ( LT_32(L_input_abs[i], L_thr[i])) + { + L_input_abs[i] = L_deposit_l(0); + } + ELSE + { + L_input_abs[num_peak_cands] = L_input_abs[i]; + move32(); + peak_cand_idx[num_peak_cands] = i; + move16(); + num_peak_cands = add(num_peak_cands, 1); + } + } +#ifndef ADD_IVAS_HQ_CODE + IF ( EQ_32(L_core_brate, HQ_24k40)) + { + peak_th = HVQ_MAX_PEAKS_24k_CLAS; + move16(); + } + ELSE + { + peak_th = HVQ_MAX_PEAKS_32k; + move16(); + } +#else + peak_th = (int16_t)((core_brate * HVQ_PEAKS_PER_DELTA_THR + HVQ_PEAKS_PER_DELTA_THR_OFFS) / HVQ_PEAKS_BPS_DELTA); +#endif + /* Find peaks */ + pindx = maximum_32_fx(L_input_abs, num_peak_cands, &L_m); + i = 0; + move16(); + + WHILE ( L_m > 0 && LT_16(i, peak_th+1)) + { + idx = mult(peak_cand_idx[pindx], INV_HVQ_BW); /* 0+15-15=0 */ + IF ( avail_peaks[idx] > 0 ) + { + peaks[i++] = peak_cand_idx[pindx]; + avail_peaks[idx]--; + } + + j = sub(pindx, 2); + k = add(pindx, 2); + + if ( j < 0 ) + { + j = 0; + move16(); + } + + tmp = sub(num_peak_cands, 1); + if ( GT_16(k, tmp)) + { + k = tmp; + move16(); + } + + low = sub(peak_cand_idx[pindx], 2); + high = add(peak_cand_idx[pindx], 2); + + if ( low < 0 ) + { + low = 0; + move16(); + } + + tmp = sub(N, 1); + if ( GT_16(high, tmp)) + { + high = tmp; + move16(); + } + + FOR( q = j; q <= pindx; q++ ) + { + IF( GE_16(peak_cand_idx[q], low)) + { + peak_cand_idx[q] = 0; + move16(); + L_input_abs[q] = 0; + move16(); + } + } + + FOR( q = pindx + 1; q <= k; q++ ) + { + IF ( LE_16(peak_cand_idx[q], high)) + { + peak_cand_idx[q] = 0; + move16(); + L_input_abs[q] = 0; + move16(); + } + } + + pindx = maximum_32_fx(L_input_abs, num_peak_cands, &L_m); + } + + *Npeaks = i; + move16(); + IF ( GT_16(*Npeaks, HVQ_MIN_PEAKS)) + { + test(); + IF ( GT_16(num_sharp_bands, sub(nsub, 3))&&LE_16(*Npeaks,peak_th)) + { + sharp_dist = mult(sharp_dist, inv_nsub); /*x+15-15=x */ + test(); + IF ( LE_16(sharp_dist, SHARP_DIST_THRES_FX)&&*hvq_hangover<0) + { + *hvq_hangover = add(*hvq_hangover, 1); + } + ELSE + { + *hqswb_clas = HQ_HVQ; + move16(); + *hvq_hangover = 2; + move16(); + } + + /* update memory */ + *prev_Npeaks = *Npeaks; + move16(); + Copy( peaks, prev_peaks, *Npeaks ); + } + ELSE + { + IF( *hvq_hangover > 0 ) + { + *hqswb_clas = HQ_HVQ; + move16(); + *hvq_hangover = sub(*hvq_hangover, 1); + move16(); + } + ELSE + { + *hvq_hangover = -1; + move16(); + } + } + } + ELSE + { + /* Zero peaks, likely silence input. */ + *hvq_hangover = -1; + move16(); + } + +#ifndef ADD_IVAS_HQ_CODE + IF ( EQ_32(L_core_brate, HQ_24k40)) + { + *Npeaks = s_min( HVQ_MAX_PEAKS_24k, *Npeaks ); + move16(); + } + ELSE + { + *Npeaks = s_min( HVQ_MAX_PEAKS_32k, *Npeaks ); + move16(); + } +#else + *Npeaks = (int16_t)(min((core_brate * HVQ_PEAKS_PER_DELTA + HVQ_PEAKS_PER_DELTA_OFFS) / HVQ_PEAKS_BPS_DELTA, *Npeaks)); +#endif + } + ELSE + { + *prev_Npeaks = 0; + move16(); + *hvq_hangover = 0; + move16(); + } + + + return; +} + +#ifdef ADD_IVAS_HQ_CODE +/*--------------------------------------------------------------------------* +* hf_spectrum_sparseness() +* +* Detection of sparse spectrum in high band for activation of harmonic +* modes HQ_HARMONIC and HQ_HVQ +*--------------------------------------------------------------------------*/ +/*! r: Harmonic decision for high band */ +static int16_t hf_spectrum_sparseness( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const float* coefs /* i : MDCT spectrum */ +) +{ + int16_t i; + float thr; + int16_t low_count; + float A[L_SPEC_HB]; + float Amax; + float movmean; + float inv_rms; + float crest; + float crest_mod; + const float* p_num; + float* crest_lp; + float* crest_mod_lp; + int16_t result; + + crest_lp = &st->hHQ_core->crest_lp; + crest_mod_lp = &st->hHQ_core->crest_mod_lp; + + result = TRUE; + if (st->element_mode != EVS_MONO) + { + for (i = 0; i < L_SPEC_HB; i++) + { + A[i] = (float)fabsf(coefs[i + L_SPEC_HB]); + } + low_count = 0; + inv_rms = 0.0f; + crest_mod = 0.0f; + maximum(A, L_SPEC_HB, &Amax); + thr = Amax * PEAK_THRESHOLD; + movmean = 0.0f; /* avoid uninitialized warning */ + p_num = &inv_tbl[HALF_WIN_LENGTH + 1]; /* Table for division 1./(11:21) */ + for (i = 0; i < L_SPEC_HB; i++) + { + inv_rms += A[i] * A[i]; + if (A[i] < thr) + { + low_count += 1; + } + if (i <= HALF_WIN_LENGTH) + { + if (i == 0) + { + movmean = sum_f(&A[0], i + HALF_WIN_LENGTH + 1) * (*p_num); + } + else + { + p_num++; + movmean = movmean + (A[i + HALF_WIN_LENGTH] - movmean) * (*p_num); + } + } + else + { + if (L_SPEC_HB <= i + HALF_WIN_LENGTH) + { + p_num--; + movmean = movmean + (movmean - A[i - HALF_WIN_LENGTH - 1]) * (*p_num); + } + else + { + movmean = movmean + (A[i + HALF_WIN_LENGTH] - A[i - HALF_WIN_LENGTH - 1]) * (*p_num); + } + } + if (crest_mod < movmean) + { + crest_mod = movmean; + } + } + inv_rms = 1.0f / (float)sqrtf(inv_rms / L_SPEC_HB); + crest = Amax * inv_rms; + crest_mod = crest_mod * inv_rms; + *crest_lp = HQ_CREST_FAC_SM * (*crest_lp) + (1.0f - HQ_CREST_FAC_SM) * crest; + *crest_mod_lp = HQ_CREST_FAC_SM * (*crest_mod_lp) + (1.0f - HQ_CREST_FAC_SM) * crest_mod; + + if (((*crest_lp) > HQ_CREST_THRESHOLD) && ((*crest_mod_lp) > HQ_CREST_MOD_THRESHOLD) && (low_count > LOW_COUNT_THRESHOLD)) + { + result = FALSE; + } + } + + return result; +} +#endif diff --git a/lib_enc/hq_core_enc_fx.c b/lib_enc/hq_core_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..f280eac7973e8b5878f77493405c4c3945ecd6a4 --- /dev/null +++ b/lib_enc/hq_core_enc_fx.c @@ -0,0 +1,367 @@ +/*==================================================================================== + 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 */ + +/*-------------------------------------------------------------------------- + * hq_core_enc() + * + * HQ core encoder + *--------------------------------------------------------------------------*/ + +void hq_core_enc_fx( + Encoder_State_fx *st_fx, + const Word16 *audio, /* i : input audio signal Q0 */ + const Word16 input_frame_orig, /* i : frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 Voicing_flag, /* i : Voicing flag for FER method selection */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +) +{ + Word16 i, is_transient, num_bits, extra_unused; + Word32 wtda_audio[2 * L_FRAME48k]; + Word32 t_audio[L_FRAME48k_EXT]; /* Q12 */ + Word16 Q_audio = 0; + Word16 inner_frame, input_frame; + Word16 ener_match; /* Q13/Q15 */ + + Word16 tmp; + Word32 L_tmp; + UWord16 lsb; +#ifdef ADD_IVAS_HQ_CODE_L_SPEC + Word16 L_spec; +#endif +#ifdef ADD_IVAS_HQ_CODE + Word16 left_overlap, right_overlap; + Word16 overlap, nz, tcx_offset, L_frame; + Word16 Aq_old[M + 1]; + Word16 output[L_FRAME16k]; +#endif + Word16 two_frames_buffer[2*L_FRAME48k]; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + set32_fx( t_audio, 0, L_FRAME48k ); + st_fx->Nb_ACELP_frames_fx = 0; + move16(); + + /* set input_frame length */ + input_frame = input_frame_orig; + move16(); + /* Sanity check, it should never happen at the encoder side (no BFI) */ + IF (EQ_16(st_fx->hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP)) + { + st_fx->hTcxCfg->tcx_last_overlap_mode = ALDO_WINDOW;; + move16(); + } + ELSE + { + st_fx->hTcxCfg->tcx_last_overlap_mode = st_fx->hTcxCfg->tcx_curr_overlap_mode; + move16(); + } + st_fx->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); + + /*-------------------------------------------------------------------------- + * Preprocessing in the first HQ frame after ACELP frame + * Find the number of bits for PVQ coding + * Write signalling information + *--------------------------------------------------------------------------*/ + + /*num_bits = (short)(st->total_brate / 50); */ + Mpy_32_16_ss(st_fx->total_brate_fx, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + num_bits = extract_l(L_shr(L_tmp, 3)); /*Q0 */ + extra_unused = 0; + move16(); + + /*-------------------------------------------------------------------------- + * Detect signal transition + *--------------------------------------------------------------------------*/ + + is_transient = detect_transient_fx( audio, input_frame, 0, st_fx); + +#ifdef ADD_IVAS_HQ_CODE + test();test();test(); + IF (GT_16(st_fx->element_mode, EVS_MONO) && (EQ_16(st_fx->last_core_fx, ACELP_CORE) || EQ_16(st_fx->last_core_fx, AMR_WB_CORE))) + { + /*-------------------------------------------------------------------------- + * IVAS switching frame + *--------------------------------------------------------------------------*/ + + L_spec = input_frame; + left_overlap = -1; + right_overlap = -1; + move16();move16();move16(); + + WindowSignal(&(st_fx->tcx_cfg), st_fx->hTcxCfg->tcx_offsetFB, TRANSITION_OVERLAP, FULL_OVERLAP, &left_overlap, &right_overlap, st_fx->hTcxEnc->speech_TCX, &L_spec, wtda_audio, 1, 1); + Q_audio = 16; move16(); /*tbv inspired from core_enc_ol*/ + TCX_MDCT(wtda_audio, t_audio, &Q_audio, left_overlap, sub(L_spec, shr( add(left_overlap, right_overlap), 1)), right_overlap, st_fx->element_mode); + + inner_frame = inner_frame_tbl[st_fx->bwidth_fx]; + L_spec = l_spec_ext_tbl[st_fx->bwidth_fx]; + is_transient = 0; + move16();move16();move16(); + } + ELSE +#endif + { + /*-------------------------------------------------------------------------- + * Windowing and time-domain aliasing + * DCT transform + *--------------------------------------------------------------------------*/ + + Copy(st_fx->old_input_signal_fx, two_frames_buffer, input_frame); + Copy(audio, two_frames_buffer + input_frame, input_frame); + + wtda_fx(two_frames_buffer + input_frame, &Q_audio, wtda_audio, NULL, 0, + st_fx->hTcxCfg->tcx_last_overlap_mode, st_fx->hTcxCfg->tcx_curr_overlap_mode, input_frame); + + test(); + IF(st_fx->last_core_fx == ACELP_CORE || EQ_16(st_fx->last_core_fx, AMR_WB_CORE)) + { + /* Preprocessing in the first HQ frame after ACELP frame */ + core_switching_hq_prepare_enc_fx(st_fx, &num_bits, input_frame, wtda_audio, two_frames_buffer + input_frame); + + /* During ACELP->HQ core switching, limit the HQ core bitrate to 48kbps */ + IF(GT_16(num_bits, ACELP_48k_BITS)) + { + extra_unused = sub(num_bits, ACELP_48k_BITS); + num_bits = ACELP_48k_BITS; + move16(); + } + } +#ifndef ADD_IVAS_HQ_CODE + /* subtract signalling bits */ + num_bits = sub(num_bits, hBstr->nb_bits_tot_fx); +#endif + direct_transform_fx(wtda_audio, t_audio, is_transient, input_frame, &Q_audio, st_fx->element_mode); + + /* scale coefficients to their nominal level (8kHz) */ + IF(NE_16(input_frame, NORM_MDCT_FACTOR)) + { + IF(EQ_16(input_frame, L_FRAME32k)) + { + Q_audio = add(Q_audio, 1); /* Divide by 2 */ + } + ELSE + { + tmp = mult_r(input_frame, 410 / 2); /* 1/8000 in Q15 */ + ener_match = hq_nominal_scaling[tmp]; + FOR(i = 0; i < input_frame; i++) + { + /*t_audio_q[i] *= ener_match; */ + Mpy_32_16_ss(t_audio[i], ener_match, &t_audio[i], &lsb); + move16(); /* Q12 */ + } + } + } + + /* limit encoded band-width according to the command-line OR BWD limitation */ + inner_frame = inner_frame_tbl[st_fx->bwidth_fx]; + move16(); +#ifdef ADD_IVAS_HQ_CODE_L_SPEC + L_spec = l_spec_tbl[st_fx->bwidth_fx]; + move16(); +#endif + IF(GT_16(input_frame, inner_frame)) + { + IF(EQ_16(is_transient, 1)) + { + FOR(i = 1; i < NUM_TIME_SWITCHING_BLOCKS; i++) + { + tmp = i_mult2(i, shr(input_frame, 2)); + tmp = shr(inner_frame, 2); + Copy32(t_audio + i_mult2(i, shr(input_frame, 2)), t_audio + i_mult2(i, tmp), tmp); + } + } + + set32_fx(t_audio + inner_frame, 0, sub(input_frame, inner_frame)); + } + } +#ifdef ADD_IVAS_HQ_CODE_L_SPEC + /* subtract signalling bits */ + num_bits = sub(num_bits, hBstr->nb_bits_tot_fx); +#endif + + /*-------------------------------------------------------------------------- + * High-band gain control in case of BWS + *--------------------------------------------------------------------------*/ +#ifdef ADD_IVAS_HQ_CODE + + IF (st_fx->bwidth_sw_cnt > 0) + { + IF (is_transient) + { + FOR (i = 0; i < NUM_TIME_SWITCHING_BLOCKS; i++) + { + v_multc(t_audio + i * inner_frame / NUM_TIME_SWITCHING_BLOCKS + L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS, (float)(st->bwidth_sw_cnt) / (float)BWS_TRAN_PERIOD, t_audio + i * inner_frame / NUM_TIME_SWITCHING_BLOCKS + L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS, inner_frame / NUM_TIME_SWITCHING_BLOCKS - L_FRAME16k / NUM_TIME_SWITCHING_BLOCKS); + } + } + ELSE + { + v_multc(t_audio + L_FRAME16k, (float)(st->bwidth_sw_cnt) / (float)BWS_TRAN_PERIOD, t_audio + L_FRAME16k, L_spec - L_FRAME16k); + } + } +#endif + /*-------------------------------------------------------------------------- + * Classify whether to put extra bits for FER mitigation + *--------------------------------------------------------------------------*/ + + test(); + IF ((EQ_16(st_fx->last_core_fx, TCX_20_CORE) || EQ_16(st_fx->last_core_fx, TCX_10_CORE) || EQ_16(st_fx->last_core_fx, HQ_CORE)) && GT_32(st_fx->core_brate_fx, MINIMUM_RATE_TO_ENCODE_VOICING_FLAG)) + { + IF ( Voicing_flag > 0 ) + { + push_indice_fx(hBstr, IND_HQ_VOICING_FLAG, 1, 1 ); + num_bits = sub(num_bits, 1); + + } + ELSE + { + push_indice_fx(hBstr, IND_HQ_VOICING_FLAG, 0, 1 ); + num_bits = sub(num_bits, 1); + } + } + + /*-------------------------------------------------------------------------- + * Transform-domain encoding + *--------------------------------------------------------------------------*/ + + IF ( EQ_16(hq_core_type, LOW_RATE_HQ_CORE)) + { + /* HQ low rate encoder */ + FOR (i = 0; i < inner_frame; i++) + { + t_audio[i] = L_shr(t_audio[i], sub(Q_audio, 12)); /* Q12 */ + } + hq_lr_enc_fx( st_fx, t_audio, inner_frame, &num_bits, is_transient ); + Q_audio = 12; + move16(); + } + ELSE + { + /* HQ high rate encoder */ + FOR (i = 0; i < inner_frame; i++) + { + t_audio[i] = L_shr(t_audio[i], sub(Q_audio, 12)); /* Q12 */ + } + +#ifdef ADD_IVAS_HQ_CODE_L_SPEC + hq_hr_enc_fx( st_fx, t_audio, L_spec, &num_bits, is_transient, vad_hover_flag); +#else + hq_hr_enc_fx(st_fx, t_audio, inner_frame, &num_bits, is_transient, vad_hover_flag); +#endif + Q_audio = 12; + move16(); + } + + /* write all unused bits to the bitstream */ + num_bits = add(num_bits, extra_unused); + + WHILE( num_bits >= 16 ) + { + push_indice_fx(hBstr, IND_UNUSED, 0, 16 ); + num_bits = sub(num_bits, 16); + } + + IF ( num_bits != 0 ) + { + push_indice_fx(hBstr, IND_UNUSED, 0, num_bits ); + } +#ifdef ADD_IVAS_HQ_CODE + if (st->element_mode > EVS_MONO && (st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE)) + { + overlap = st->hTcxCfg->tcx_mdct_window_length; + nz = NS2SA(st->sr_core, N_ZERO_MDCT_NS); + L_frame = (int16_t)(st->L_frame + st->hTcxCfg->tcx_offset - st->hTcxCfg->lfacNext); + tcx_offset = st->hTcxCfg->lfacNext; + set_f(Aq_old, 0, M + 1); /* Dummy filter */ + Aq_old[0] = 1; + + /* Code taken from InternalTCXDecoder() */ + TCX_MDCT_Inverse(t_audio, wtda_audio, overlap, L_frame - overlap, overlap, st->element_mode); + + /* Window current frame */ + tcx_windowing_synthesis_current_frame(wtda_audio, st->hTcxCfg->tcx_aldo_window_2, st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, overlap, /*st->hTcxCfg->tcx_mdct_window_length*/ st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, st->last_core == ACELP_CORE, st->hTcxCfg->tcx_last_overlap_mode, /*left mode*/ st->hTcxEnc->acelp_zir, st->hTcxEnc->Txnq, NULL, Aq_old, st->hTcxCfg->tcx_mdct_window_trans, st->L_frame >> 1, tcx_offset < 0 ? -tcx_offset : 0, st->last_core, 0, 0); + + /*Compute windowed synthesis in case of switching to ALDO windows in next frame*/ + mvr2r(wtda_audio + L_frame - nz, st->hTcxEnc->old_out, nz + overlap); + set_zero(st->hTcxEnc->old_out + nz + overlap, nz); + + tcx_windowing_synthesis_past_frame(st->hTcxEnc->old_out + nz, st->hTcxCfg->tcx_aldo_window_1_trunc, st->hTcxCfg->tcx_mdct_window_half, st->hTcxCfg->tcx_mdct_window_minimum, overlap, st->hTcxCfg->tcx_mdct_window_half_length, st->hTcxCfg->tcx_mdct_window_min_length, FULL_OVERLAP); + + for (i = 0; i < nz; i++) + { + st->hTcxEnc->old_out[nz + overlap + i] = wtda_audio[L_frame - 1 - i] * st->hTcxCfg->tcx_aldo_window_1_trunc[-1 - i]; + } + mvr2r(wtda_audio + (overlap >> 1) - tcx_offset, output, st->L_frame); + } + else + { + ener_match = (float)sqrt((float)L_FRAME16k / (float)NORM_MDCT_FACTOR); + v_multc(t_audio, ener_match, t_audio, inner_frame); + + inverse_transform(t_audio, wtda_audio, is_transient, L_FRAME16k, inner_frame, st->element_mode); + + window_ola(wtda_audio, output, st->hTcxEnc->old_out, L_FRAME16k, st->hTcxCfg->tcx_last_overlap_mode, st->hTcxCfg->tcx_curr_overlap_mode, 0, 0, NULL); + } + + if (st->element_mode > EVS_MONO) + { + /* Store LB synthesis in case of switch to ACELP */ + mvr2r(output, st->hLPDmem->old_exc, L_FRAME16k); + } +#endif + + return; +} + +/*-------------------------------------------------------------------* + * hq_core_enc_init() + * + * Initialize HQ core state structure + *-------------------------------------------------------------------*/ + +void HQ_core_enc_init_fx( + HQ_ENC_HANDLE hHQ_core /* i/o: HQ core data handle */ +) +{ + hHQ_core->mode_count = 0; + move16(); + hHQ_core->mode_count1 = 0; + move16(); + + hHQ_core->hq_generic_speech_class = 0; + move16(); + hHQ_core->prev_Npeaks = 0; + set16_fx(hHQ_core->prev_peaks, 0, HVQ_MAX_PEAKS); + hHQ_core->hvq_hangover = 0; + hHQ_core->prev_hqswb_clas = HQ_NORMAL; + + set16_fx(hHQ_core->prev_SWB_peak_pos, 0, SPT_SHORTEN_SBNUM); + set16_fx(hHQ_core->prev_frm_index, -1, NB_SWB_SUBBANDS_HAR_SEARCH_SB); + hHQ_core->prev_frm_hfe2 = 0; + move16(); + hHQ_core->prev_stab_hfe2 = 0; + move16(); + hHQ_core->prev_ni_ratio_fx = 16384; + move16(); /* 0.5 */ + set16_fx(hHQ_core->prev_En_sb_fx, 0, NB_SWB_SUBBANDS); + set16_fx(hHQ_core->last_bitalloc_max_band, 0, 2); + 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->crest_lp = HQ_CREST_THRESHOLD; IVAS_CODE + //hHQ_core->crest_mod_lp = HQ_CREST_MOD_THRESHOLD;IVAS_CODE + + return; +} diff --git a/lib_enc/hq_env_enc_fx.c b/lib_enc/hq_env_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..0dc9ac76174f5b025f3562233e735ebc4b56e4fa --- /dev/null +++ b/lib_enc/hq_env_enc_fx.c @@ -0,0 +1,602 @@ +/*==================================================================================== + 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 "rom_enc.h" +#include "rom_com.h" +#include "stl.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*--------------------------------------------------------------------------------------* + * encode_envelope_indices_fx() + * + * Encode envelope indices + *--------------------------------------------------------------------------------------*/ + +Word16 encode_envelope_indices_fx( /* o : Number of bits if flag_pack=0,0 if flag_pack=1 Q0 */ + BSTR_ENC_HANDLE hBstr, /* i : handle to the bitstream */ + const Word16 num_sfm, /* i : Number of subbands Q0 */ + const Word16 numnrmibits, /* i : Bitrate of fall-back coding mode Q0 */ + Word16 *difidx, /* i/o: Diff indices/encoded diff indices Q0 */ + Word16 *LCmode, /* o : Coding mode if flag_pack=0, i : if flag_pack=1 Q0 */ + const Word16 flag_pack, /* i : indicator of packing or estimating bits Q0 */ + const Word16 flag_HQ2, /* i : indicator of HQ2 core Q0 */ + const Word16 is_transient /* i : indicator of HQ_TRANSIENT Q0 */ +) +{ + Word16 bits; + Word16 prevj; + Word16 hcode_l; + Word16 i,j; + Word16 difidx_flag; + Word16 index_max, index_min, index_rad; + Word16 difidx_org[NB_SFM]; /* length of this buffer is max(BANDS_MAX,NB_SFM) */ + Word16 m, r; + Word16 v, k; + + + set16_fx( difidx_org, 0, NB_SFM ); + difidx_flag = 0; + move16(); + + /*------------------------------------------------------------------* + * Check Huffman encoding for QNorm indices + *------------------------------------------------------------------*/ + + /* LC mode index is changed to synchronize LR_MDCT signaling */ + /* LC mode 0 = Context based coding */ + /* LC mode 1 = resized huffman coding */ + /* LC mode 2 = normal Huffman Coding */ + /* LC mode 3 = bit packing */ + IF ( flag_pack == 0 ) + { + test(); + IF( is_transient && EQ_16(flag_HQ2, LOW_RATE_HQ_CORE_TRAN)) + { + bits = 0; + move16(); + index_max = 0; + move16(); + index_min = 31; + move16(); + FOR( i = 0; i< num_sfm; i++ ) + { + IF( GT_16(difidx[i], index_max)) + { + index_max = difidx[i]; + move16(); + } + IF( LT_16(difidx[i], index_min)) + { + index_min = difidx[i]; + move16(); + } + } + test(); + IF(GT_16(index_min, 10)&<_16(index_max,22)) + { + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + bits = add(bits, huffsizn_tran[j]); + } + } + hcode_l= 0; + move16(); + *LCmode = 0; + move16(); + prevj = add(difidx[0], OFFSET_NORM); + /* LC mode 0 = Context based coding */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + hcode_l = add(hcode_l, huffsizn_n[31-j]); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + hcode_l = add(hcode_l, huffsizn_n[j]); + } + ELSE + { + /* equal */ + hcode_l = add(hcode_l, huffsizn_e[j]); + } + } + prevj = j; + move16(); + } + test(); + IF( GE_16(hcode_l, bits)&&bits!=0) + { + /* LC mode 1 Transient Huffman Coding */ + *LCmode = 1; + move16(); + hcode_l = bits; + move16(); + } + } + ELSE + { + /* Check bits if LC mode == 3 -> Check bits if LC mode == 0 */ + hcode_l= 0; + move16(); + prevj = add(difidx[0], OFFSET_NORM); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + hcode_l = add(hcode_l, huffsizn_n[sub(31,j)]); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + hcode_l = add(hcode_l, huffsizn_n[j]); + } + ELSE + { + /* equal */ + hcode_l = add(hcode_l, huffsizn_e[j]); + } + } + prevj = j; + move16(); + } + + *LCmode = 0; + move16(); + + /* LR-MDCT core doesn't have coding mode 2 and 3 */ + IF( flag_HQ2 == NORMAL_HQ_CORE ) + { + /* Check bits if LC mode == 1 -> Check bits if LC mode == 2 */ + bits = 0; + move16(); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + bits = add(bits, huffsizn[j]); + } + + /*------------------------------------------------------------------------------* + * comparing bit expenses of coding mode 2 with that of the optimal coding mode + *------------------------------------------------------------------------------*/ + + if( GT_16(hcode_l, bits)) + { + *LCmode = 2; + move16(); + } + hcode_l = s_min(hcode_l, bits); + } + + /* Check bits if LC mode == 2 -> Check bits if LC mode == 1 */ + bits = 0; + move16(); + index_max = 0; + move16(); + index_min = 31; + move16(); + FOR( i = 1; i < num_sfm; i++ ) + { + difidx_org[i] = difidx[i]; + move16(); + } + + difidx_flag = 0; + move16(); + FOR( i = 2; i < num_sfm; i++ ) + { + IF( GT_16(difidx_org[i-1], 17)) + { + difidx[i] = add(difidx_org[i], s_min(sub(difidx_org[i-1],17),3)); + move16(); + IF( GT_16(difidx[i], 31)) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + + IF( LT_16(difidx_org[i-1], 13)) + { + difidx[i] = add(difidx_org[i], s_max(sub(difidx_org[i-1],13),-3)); + move16(); + IF( difidx[i] < 0 ) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + } + + index_rad = 0; + move16(); + IF( difidx_flag == 0 ) + { + FOR( i = 1; i< num_sfm; i++ ) + { + index_max = s_max(index_max, difidx[i]); + index_min = s_min(index_min, difidx[i]); + } + + index_rad = s_max(sub(15, index_min),sub(index_max, 15)); + + IF( LE_16(index_rad, HUFF_THR)) + { + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + bits = add(bits, resize_huffsizn[j]); + } + + /*------------------------------------------------------------------* + * comparing bit expenses of coding mode 1 with that of coding mode 0 + *------------------------------------------------------------------*/ + + if( GT_16(hcode_l, bits)) + { + *LCmode = 1; + move16(); + } + hcode_l = s_min(hcode_l, bits); + + } + } + + /* LR-MDCT core doesn't have coding mode 2 and 3 */ + IF( flag_HQ2 == NORMAL_HQ_CORE ) + { + /*------------------------------------------------------------------------------* + * comparing bit expenses of coding mode 3 with that of the optimal coding mode + *------------------------------------------------------------------------------*/ + + if( GE_16(hcode_l, numnrmibits)) + { + *LCmode = 3; + move16(); + } + hcode_l = s_min(hcode_l, numnrmibits); + } + + test(); + test(); + IF( (NE_16(*LCmode, 1)&&flag_HQ2==NORMAL_HQ_CORE)||EQ_16(flag_HQ2,LOW_RATE_HQ_CORE)) + { + FOR(i = 2; i< num_sfm; i++) + { + difidx[i] = difidx_org[i]; + move16(); + } + } + } + } + ELSE + { + test(); + IF( EQ_16(flag_HQ2, LOW_RATE_HQ_CORE_TRAN)||EQ_16(flag_HQ2,LOW_RATE_HQ_CORE)) + { + push_indice_fx( hBstr, IND_HQ2_DENG_HMODE, *LCmode, BITS_DE_HMODE); + push_indice_fx( hBstr, IND_HQ2_DIFF_ENERGY, difidx[0], BITS_DE_FCOMP); + } + ELSE + { + push_indice_fx( hBstr, IND_LC_MODE, *LCmode, 2 ); + push_indice_fx( hBstr, IND_YNRM, difidx[0], NORM0_BITS ); + } + + test(); + IF(is_transient && EQ_16(flag_HQ2, LOW_RATE_HQ_CORE_TRAN)) + { + hcode_l = 0; + move16(); + IF ( EQ_16(*LCmode, 1)) + { + /* LC mode 0 Transient Huffman Coding */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + m = huffnorm_tran[j]; + move16(); + r = huffsizn_tran[j]; + move16(); + v = 0; + move16(); + + /* Bit reverse */ + FOR( k = 0; k < r; k++ ) + { + v = lshl(v, 1); + v = s_or(v, s_and(m, 1)); + m = lshr(m, 1); + } + + push_indice_fx(hBstr, IND_HQ2_DIFF_ENERGY, v, r); + } + } + ELSE + { + /* LC mode 1 context based Coding */ + prevj = add(difidx[0], OFFSET_NORM); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + r = huffsizn_n[sub(31,j)]; + move16(); + m = huffnorm_n[sub(31,j)]; + move16(); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + r = huffsizn_n[j]; + move16(); + m = huffnorm_n[j]; + move16(); + } + ELSE + { + /* equal */ + r = huffsizn_e[j]; + move16(); + m = huffnorm_e[j]; + move16(); + } + } + push_indice_fx(hBstr, IND_HQ2_DIFF_ENERGY, m, r); + prevj = j; + move16(); + } + } + } + ELSE + { + hcode_l = 0; + move16(); + IF ( *LCmode == 0 ) + { + /* LC mode 3 -> LC mode 0 */ + prevj = add(difidx[0], OFFSET_NORM); + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + IF( GT_16(prevj, HTH_NORM)) + { + /* above */ + r = huffsizn_n[sub(31,j)]; + move16(); + m = huffnorm_n[sub(31,j)]; + move16(); + } + ELSE + { + IF( LT_16(prevj, LTH_NORM)) + { + /* less */ + r = huffsizn_n[j]; + move16(); + m = huffnorm_n[j]; + move16(); + } + ELSE + { + /* equal */ + r = huffsizn_e[j]; + move16(); + m = huffnorm_e[j]; + move16(); + } + } + + IF( EQ_16(flag_HQ2, LOW_RATE_HQ_CORE)) + { + push_indice_fx(hBstr, IND_HQ2_DIFF_ENERGY, m, r); + } + ELSE + { + push_indice_fx( hBstr, IND_YNRM, m, r ); + } + + prevj = j; + move16(); + } + } + ELSE IF( EQ_16(*LCmode, 1)) + { + IF ( EQ_16(flag_HQ2, 1)) + { + index_max = 0; + move16(); + index_min = 31; + move16(); + FOR(i = 1; i< num_sfm; i++) + { + difidx_org[i] = difidx[i]; + move16(); + } + + FOR(i = 2; i< num_sfm; i++) + { + IF(GT_16(difidx_org[i-1], 17)) + { + difidx[i] = add(difidx_org[i], s_min(sub(difidx_org[i-1],17),3)); + move16(); + IF(GT_16(difidx[i], 31)) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + + IF(LT_16(difidx_org[i-1], 13)) + { + difidx[i] = add(difidx_org[i], s_max(sub(difidx_org[i-1],13),-3)); + move16(); + IF(difidx[i] < 0) + { + difidx_flag = 1; + move16(); + BREAK; + } + } + } + + IF( difidx_flag == 0 ) + { + FOR(i = 1; i< num_sfm; i++) + { + index_max = s_max(index_max, difidx[i]); + index_min = s_min(index_min, difidx[i]); + } + + index_rad = s_max(sub(15, index_min),sub(index_max, 15)); + + IF(LE_16(index_rad, HUFF_THR)) + { + FOR (i = 1; i < num_sfm; i++) + { + j = difidx[i]; + move16(); + } + } + } + } + + /* LC mode 2 -> LC mode 1 */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + m = resize_huffnorm[j]; + move16(); + r = resize_huffsizn[j]; + move16(); + v = 0; + move16(); + + /* Bit reverse */ + FOR( k = 0; k < r; k++ ) + { + v = lshl(v, 1); + v = s_or(v,s_and(m, 1)); + m = lshr(m, 1); + } + + IF ( flag_HQ2 == 0 ) + { + push_indice_fx( hBstr, IND_YNRM, v, r ); + } + ELSE + { + push_indice_fx( hBstr, IND_HQ2_DIFF_ENERGY, v, r); + } + } + } + ELSE IF( EQ_16(*LCmode, 2)) + { + /* LC mode 1 -> LC mode 2 */ + FOR( i = 1; i < num_sfm; i++ ) + { + j = difidx[i]; + move16(); + + m = huffnorm[j]; + move16(); + r = huffsizn[j]; + move16(); + + push_indice_fx( hBstr, IND_YNRM, m, r ); + } + } + ELSE + { + FOR( i = 1; i < num_sfm; i++ ) + { + push_indice_fx( hBstr, IND_YNRM, difidx[i], NORMI_BITS ); + } + } + } + } + + return hcode_l; +} + +/*--------------------------------------------------------------------------* + * diff_envelope_coding_fx() + * + * Differential envelope coding + *--------------------------------------------------------------------------*/ + +void diff_envelope_coding_fx( + const Word16 is_transient, /* i : transient indicator Q0 */ + const Word16 num_env_bands, /* i : number of envelope bands to code Q0 */ + const Word16 start_norm, /* i : start of envelope coding Q0 */ + Word16 *ynrm, /* i/o: quantization indices for norms Q0 */ + Word16 *normqlg2, /* i/o: quantized norms Q0 */ + Word16 *difidx /* o : differential code Q0 */ +) +{ + Word16 i, tmp; + Word16 idxbuf[NB_SFM]; + Word16 normbuf[NB_SFM]; + + /* Differential coding for indices of quantized norms */ + IF( is_transient != 0 ) + { + /* Reorder quantization indices and quantized norms */ + reordernorm_fx( ynrm, normqlg2, idxbuf, normbuf, num_env_bands ); + diffcod_fx( num_env_bands, idxbuf, &difidx[1] ); + difidx[0] = idxbuf[0]; + move16(); + recovernorm_fx( idxbuf, ynrm, normqlg2, num_env_bands ); + } + ELSE + { + diffcod_fx( num_env_bands, &ynrm[start_norm], &difidx[1] ); + difidx[0] = ynrm[start_norm]; + move16(); + + tmp = add(start_norm, num_env_bands); + FOR( i = start_norm; i < tmp; i++ ) + { + normqlg2[i] = dicnlg2[ynrm[i]]; + move16(); + move16(); + } + } + + return; +} diff --git a/lib_enc/hq_hr_enc_fx.c b/lib_enc/hq_hr_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..912f6dd6317c0ba1ba8e5b0716cb66834d6c90e4 --- /dev/null +++ b/lib_enc/hq_hr_enc_fx.c @@ -0,0 +1,257 @@ +/*==================================================================================== + 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 */ + +/*--------------------------------------------------------------------------* + * hq_hr_enc_fx() + * + * HQ High rate encoding routine + *--------------------------------------------------------------------------*/ +void hq_hr_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure fx */ + Word32 *t_audio, /* i/o: transform-domain coefficients Q12 */ + const Word16 length, /* i : length of spectrum Q0 */ + Word16 *num_bits, /* i : number of available bits Q0 */ + const Word16 is_transient, /* i : transient flag Q0 */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +) +{ + Word16 nb_sfm; /* Q0 */ + Word16 sum, hcode_l; /* Q0 */ + Word16 difidx[NB_SFM]; /* Q0 */ + Word16 normqlg2[NB_SFM], ynrm[NB_SFM]; /* Q0 */ + Word16 nf_idx; /* Q0 */ + Word16 bits; /* */ + Word16 LCmode; /* Q0 */ + Word16 shape_bits, num_sfm, numnrmibits; /* Q0 */ + Word16 hqswb_clas; /* Q0 */ + Word16 num_env_bands; /* Q0 */ + Word16 Npeaks, start_norm; /* Q0 */ + Word16 difidx_org[NB_SFM]; /* Q0 */ + Word16 R[NB_SFM]; /* Q0 */ + Word16 peaks[HVQ_MAX_PEAKS]; /* Q0 */ + Word16 sfmsize[NB_SFM], sfm_start[NB_SFM], sfm_end[NB_SFM]; /* Q0 */ + Word16 npulses[NB_SFM], maxpulse[NB_SFM]; /* Q0 */ + Word16 Rsubband[NB_SFM]; /* Q3 */ + Word32 t_audio_q[L_SPEC48k_EXT]; /* Q12 */ + Word32 nf_gains[HVQ_NF_GROUPS]; /* Q12 */ + Word32 pe_gains[HVQ_NF_GROUPS]; /* Q12 */ + Word16 noise_level[HVQ_BWE_NOISE_BANDS]; /* Q15 */ + Word16 hq_generic_offset; /* Q0 */ + Word16 hq_generic_fenv[HQ_FB_FENV]; /* Q1 */ + Word16 hq_generic_exc_clas = 0; /* Q0 */ + Word16 core_sfm; /* Q0 */ + Word16 har_freq_est1, har_freq_est2; + Word16 flag_dis; + const Word16 *subband_search_offset; + Word16 wBands[2]; + + Word16 t_audio_norm[L_FRAME48k]; + Word16 t_audio_q_norm[L_FRAME48k]; + Word16 Q_audio; + Word16 i; + Word16 b_delta_env; + Word16 Q_shift; + Word16 att; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + + Npeaks = 0; + Q_audio = 0; /* to avoid compilation warnings */ + + set16_fx( npulses, 0, NB_SFM ); + set16_fx( maxpulse, 0, NB_SFM ); + set16_fx( difidx_org, 0, NB_SFM ); + set32_fx( t_audio_q, 0, L_FRAME48k ); + set32_fx( nf_gains, 0, HVQ_NF_GROUPS ); + set32_fx( pe_gains, 0, HVQ_NF_GROUPS ); + flag_dis = 1; + move16(); + har_freq_est1 = 0; + move16(); + har_freq_est2 = 0; + move16(); + + /*------------------------------------------------------------------* + * Classification + *------------------------------------------------------------------*/ + + bits = hq_classifier_enc_fx( st_fx, length, t_audio, is_transient, &Npeaks, peaks, pe_gains, nf_gains, &hqswb_clas ); + + *num_bits = sub(*num_bits, bits); + + /*------------------------------------------------------------------* + * set quantization parameters + *------------------------------------------------------------------*/ + + hq_configure_evs_fx( length, hqswb_clas, st_fx->core_brate_fx, &num_sfm, &nb_sfm, &start_norm, &num_env_bands, &numnrmibits, &hq_generic_offset, + sfmsize, sfm_start, sfm_end ); + + /*------------------------------------------------------------------* + * Transient frame handling + *------------------------------------------------------------------*/ + + /* Interleave MLT coefficients of 4 sub-vectors in case of transient */ + IF( EQ_16( is_transient, 1 )) + { + interleave_spectrum_fx( t_audio, length ); + } + + test(); + IF (EQ_16(st_fx->element_mode, IVAS_CPE_DFT) || EQ_16(st_fx->element_mode, IVAS_CPE_TD)) + { + calculate_hangover_attenuation_gain_fx(st_fx, &att, vad_hover_flag); + v_multc_att32(t_audio, att, t_audio, sfm_end[sub(num_sfm, 1)]); + } + /*------------------------------------------------------------------* + * Scalar quantization of norms + * Encode norm indices + *------------------------------------------------------------------*/ + + /* calculate and quantize norms */ + calc_norm_fx( t_audio, 12, ynrm, normqlg2, start_norm, num_env_bands, sfmsize, sfm_start ); + + /* create differential code of quantized norm indices */ + diff_envelope_coding_fx(is_transient, num_env_bands, start_norm, ynrm, normqlg2, difidx); + + /* Find coding mode and calculate bit rate */ + hcode_l = encode_envelope_indices_fx( st_fx->hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 0, NORMAL_HQ_CORE, is_transient ); + *num_bits = sub(*num_bits, add( hcode_l, NORM0_BITS + FLAGS_BITS ) ); + + /* Encode norm indices */ + encode_envelope_indices_fx( st_fx->hBstr, num_env_bands, numnrmibits, difidx, &LCmode, 1, NORMAL_HQ_CORE, is_transient ); + + /*------------------------------------------------------------------* + * HQ Generic HF encoding + *------------------------------------------------------------------*/ + + test(); + IF ( EQ_16( hqswb_clas, HQ_GEN_SWB )||EQ_16(hqswb_clas,HQ_GEN_FB)) + { + hq_generic_encoding_fx(t_audio, hq_generic_fenv, hq_generic_offset, st_fx, &hq_generic_exc_clas/*, length*/); + IF (EQ_16(hq_generic_exc_clas , HQ_GENERIC_SP_EXC)) + { + *num_bits = add(*num_bits,1); /* conditional 1 bit saving for representing FD3 BWE excitation class */ + } + map_hq_generic_fenv_norm_fx( hqswb_clas, hq_generic_fenv, ynrm, normqlg2, num_env_bands, nb_sfm, hq_generic_offset ); + } + + /*------------------------------------------------------------------* + * Bit allocation + *------------------------------------------------------------------*/ + + hq_bit_allocation_fx( st_fx->core_brate_fx, length, hqswb_clas, num_bits, normqlg2, nb_sfm, sfmsize, noise_level, + R, Rsubband, &sum, &core_sfm, num_env_bands ); + + /*------------------------------------------------------------------* + * Normalize coefficients with quantized norms + *------------------------------------------------------------------*/ + IF( hqswb_clas != HQ_HVQ ) + { + test(); + IF (hqswb_clas == HQ_GEN_SWB || hqswb_clas == HQ_GEN_FB) + { + b_delta_env = calc_nor_delta_hf_fx( st_fx->hBstr, t_audio, ynrm, Rsubband, num_env_bands, nb_sfm, sfmsize, sfm_start, core_sfm ); + sum -= b_delta_env; + } + normalizecoefs_fx( t_audio, ynrm, nb_sfm, sfm_start, sfm_end, t_audio_norm ); + Q_audio = 12; + } + + /*------------------------------------------------------------------* + * Quantize/code spectral fine structure using PVQ or HVQ + *------------------------------------------------------------------*/ + IF( EQ_16( hqswb_clas, HQ_HVQ)) + { + sum = hvq_enc_fx( st_fx, st_fx->core_brate_fx, *num_bits, Npeaks, ynrm, R, peaks, nf_gains, noise_level, pe_gains, t_audio, t_audio_q ); + *num_bits = sub(*num_bits, sum); + } + ELSE + { + shape_bits = pvq_core_enc_fx( st_fx->hBstr, t_audio_norm, t_audio_q_norm, &Q_audio, sum, nb_sfm, sfm_start, sfm_end, sfmsize, Rsubband, R, + npulses, maxpulse, HQ_CORE ); + *num_bits = add( *num_bits, sub( sum, shape_bits) ); + } + + test(); + IF ( EQ_16(hqswb_clas, HQ_HVQ)||EQ_16(hqswb_clas,HQ_HARMONIC)) + { + subband_search_offset = subband_search_offsets_13p2kbps_Har; + wBands[0] = SWB_SB_BW_LEN0_16KBPS_HAR; + move16(); + wBands[1] = SWB_SB_BW_LEN1_16KBPS_HAR; + move16(); + + IF (EQ_16(hqswb_clas, HQ_HARMONIC)) + { + Q_shift = sub(SWB_BWE_LR_Qs, Q_audio); + FOR (i = 0; i < 300; i++) + { + t_audio_q[i] = L_shl(L_deposit_l(t_audio_q_norm[i]), Q_shift); /* Q12 */ + } + } + + har_est_fx( t_audio_q, 300, &har_freq_est1, &har_freq_est2, &flag_dis, &hHQ_core->prev_frm_hfe2, subband_search_offset, wBands, &hHQ_core->prev_stab_hfe2 ); + + hHQ_core->prev_frm_hfe2 = har_freq_est2; + move16(); + } + + test(); + test(); + hHQ_core->prev_frm_hfe2 = 0; /*reset*/ move16(); + hHQ_core->prev_stab_hfe2 = 0; /*reset*/ move16(); + + nf_idx = 0; + move16(); + test(); + test(); + test(); + IF ( NE_16(is_transient,1 ) && NE_16(hqswb_clas,HQ_HVQ) && !(EQ_16(length,L_FRAME16k) && LE_32(st_fx->core_brate_fx,HQ_32k))) + { + test(); + IF (EQ_16(hqswb_clas, HQ_GEN_SWB)||EQ_16(hqswb_clas,HQ_GEN_FB)) + { + nf_idx = noise_adjust_fx( t_audio_norm, 12, R, sfm_start, sfm_end, s_max(core_sfm,sub(num_env_bands,1))); + push_indice_fx( st_fx->hBstr, IND_NF_IDX, nf_idx, 2 ); + } + ELSE + { + nf_idx = noise_adjust_fx( t_audio_norm, 12, R, sfm_start, sfm_end, core_sfm ); + push_indice_fx( st_fx->hBstr, IND_NF_IDX, nf_idx, 2 ); + } + } + /* updates */ + hHQ_core->prev_hqswb_clas = hqswb_clas; + move16(); + + /* Prepare synthesis for LB generation in case of switch to ACELP */ +#ifdef ADD_IVAS_HQ_CODE + IF (NE_16(hqswb_clas, HQ_HVQ)) + { + apply_envelope_enc(t_audio_q, ynrm, num_sfm, sfm_start, sfm_end); + } + + IF (is_transient) + { + de_interleave_spectrum(t_audio_q, length); + } + Copy32(t_audio_q, t_audio, length); +#endif + + + return; +} + diff --git a/lib_enc/hq_lr_enc_fx.c b/lib_enc/hq_lr_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..3b1730bef3d6146b4ce18d951f53ca0c9f74b6db --- /dev/null +++ b/lib_enc/hq_lr_enc_fx.c @@ -0,0 +1,1976 @@ +/*==================================================================================== + 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 "rom_enc.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 */ + +/*--------------------------------------------------------------------------* + * Local function prototypes + *--------------------------------------------------------------------------*/ + +static Word16 band_energy_quant_fx(BSTR_ENC_HANDLE hBstr, const Word32 *L_t_audio, const Word16 band_start_fx[], const Word16 band_end_fx[], Word32 L_band_energy[], + const Word16 bands_fx, const Word32 L_qint, const Word16 eref_fx, const Word16 is_transient_fx ); + +static Word16 p2a_threshold_quant_fx(BSTR_ENC_HANDLE hBstr, const Word32 *L_t_audio, const Word16 band_start[], const Word16 band_end[], const Word16 band_width[], + const Word16 bands, const Word16 p2a_bands, const Word16 p2a_th, Word16 *p2a_flags ); + +static void mdct_spectrum_fine_gain_enc_fx( Encoder_State_fx *st_fx, const Word32 L_ybuf[], Word32 L_y2[], const Word16 band_start[], const Word16 band_end[], + const Word16 k_sort[], const Word16 bands, const Word32 L_qint, const Word16 Ngq, const Word16 gqlevs, const Word16 gqbits ); + +/*--------------------------------------------------------------------------* + * spt_shorten_domain_set() + * + * Track the spectral peak based on peak -avg analysis + *--------------------------------------------------------------------------*/ + +static void spt_shorten_domain_set_fx( + Encoder_State_fx *st_fx, /* i: encoder state structure */ + const Word32 L_t_audio[], /* i: input spectrum */ + const Word16 p2a_flags[], /* i: p2a anlysis information */ + const Word16 new_band_start[], /* i: new band start position */ + const Word16 new_band_end[], /* i: new band end position */ + const Word16 new_band_width[], /* i: new subband band width */ + const Word16 bands, /* i: total number of subbands */ + Word16 band_start[], /* i/o: band start position */ + Word16 band_end[], /* i/o: band end position */ + Word16 band_width[], /* i: sub band band width */ + Word16 *bit_budget /* i/o: bit budget */ +) +{ + Word16 i, j, k; + Word16 kpos; + Word32 L_max_y2; + Word16 max_y2_pos; + Word16 spt_shorten_flag[SPT_SHORTEN_SBNUM]; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + + kpos = 0; + j = 0; + move16(); + FOR(k=sub(bands,SPT_SHORTEN_SBNUM); kprev_SWB_peak_pos[kpos] != 0) + { + L_max_y2 = L_deposit_l(0); + max_y2_pos = 0; + move16(); + FOR(i=band_start[k]; i<=band_end[k]; i++) + { + IF( LT_32( L_max_y2, L_abs(L_t_audio[i]))) + { + L_max_y2 = L_abs(L_t_audio[i]); + max_y2_pos = i; + move16(); + } + } + test(); + IF( GE_16(max_y2_pos, new_band_start[j])&&LE_16(max_y2_pos,new_band_end[j])) + { + band_start[k] = new_band_start[j]; + move16(); + band_end[k] = new_band_end[j]; + move16(); + band_width[k] = new_band_width[j]; + move16(); + spt_shorten_flag[j] = 1; + move16(); + } + } + push_indice_fx(st_fx->hBstr, IND_HQ2_SPT_SHORTEN, spt_shorten_flag[j], 1); + *bit_budget = sub(*bit_budget, 1); + } + + kpos = add(kpos, 1); + j = add(j, 1); + } + + return; +} + +/*--------------------------------------------------------------------------* + * hq_lr_enc_fx() + * + * HQ Low rate encoding routine + *--------------------------------------------------------------------------*/ + +void hq_lr_enc_fx( + Encoder_State_fx *st_fx, /* i/o: : encoder state structure */ + Word32 L_t_audio[], /* i/o: Q12 : transform-domain coefs. */ + const Word16 inner_frame_fx,/* i : Q0 : inner frame length */ + Word16 *num_bits_fx, /* i/o: Q0 : number of available bits */ + const Word16 is_transient_fx/* i : Q0 : transient flag */ +) +{ + Word16 i, k1_fx, k2_fx; + Word16 bit_budget_fx, pbits_fx; + Word16 bands_fx, length_fx, ni_seed_fx, gqlevs_fx, gqbits_fx, Ngq_fx, p2a_bands_fx; + Word16 p2a_flags_fx[BANDS_MAX]; + Word16 band_start[BANDS_MAX], band_end[BANDS_MAX], band_width[BANDS_MAX]; + Word32 L_band_energy[BANDS_MAX], L_Rk[BANDS_MAX]; + Word16 ebits_fx; + + Word32 L_qint; + /*Word16 Qqint=29;*/ + Word16 eref_fx/*, Qeref=10*/; + Word16 bit_alloc_weight_fx/*, Qbaw=13*/; + Word16 ld_slope_fx/*, Qldslope=15*/; + Word16 p2a_th_fx/*, Qp2ath=11*/; + Word16 pd_thresh_fx/*, Qpdth=15*/; + Word16 ni_coef_fx/*, Qnicoef=14*/; + + Word16 k_sort_fx[BANDS_MAX]; + Word16 npulses_fx[BANDS_MAX]; + Word16 inp_vector_fx[L_FRAME48k]; + Word32 L_y2[L_FRAME48k]; + Word32 L_y2_ni[L_FRAME48k]; + Word16 hqswb_clas_fx; + Word16 lowlength_fx; + Word16 highlength_fx; + Word32 L_m[L_FRAME32k]; + Word16 har_bands_fx; + Word16 bw_low, bw_high; + Word32 L_band_energy_tmp[BANDS_MAX]; + Word32 L_bwe_br; + Word16 trans_bit; + Word16 adjustFlag; + Word16 prev_SWB_peak_pos_tmp_fx[SPT_SHORTEN_SBNUM]; + Word16 k,j; + Word16 flag_spt_fx; + Word16 org_band_start[SPT_SHORTEN_SBNUM]; + Word16 org_band_end[SPT_SHORTEN_SBNUM]; + Word16 org_band_width[SPT_SHORTEN_SBNUM]; + Word16 new_band_start[SPT_SHORTEN_SBNUM]; + Word16 new_band_end[SPT_SHORTEN_SBNUM]; + Word16 new_band_width[SPT_SHORTEN_SBNUM]; + + Word16 k1_step_fx, k2_step_fx; + Word16 exp_norm; + + Word16 lowband,highband,p2a_flags_tmp[BANDS_MAX]; + Word32 L_tmp,L_tmp2,L_tmp3; + Word16 exp,exp2,tmp,tmp1,tmp2,tmp3,frac1,alpha_fx,Q_band_energy; + Word32 enerH_fx; + Word32 enerL_fx; + Word32 Ep_fx[BANDS_MAX]; + Word32 Ep_avrg_fx, Ep_vari_fx; + Word32 Ep_avrgL_fx; + Word32 Ep_peak_fx; + Word32 Ep_tmp_fx[BANDS_MAX]; + Word16 gama_fx;/*Q15 0.85f;// */ + Word16 beta_fx;/*Q14 1.05f; */ + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + set32_fx( L_y2, 0x0L, L_FRAME48k ); + set16_fx( inp_vector_fx, 0, inner_frame_fx ); + flag_spt_fx = 0; + move16(); + set16_fx(prev_SWB_peak_pos_tmp_fx, 0, SPT_SHORTEN_SBNUM); + adjustFlag = 0; + move16(); + bw_low = 0; + move16(); + bw_high = 20; + move16(); + enerL_fx = L_deposit_l(0); + enerH_fx = L_deposit_l(0); + + tmp2 = 0; /* to avoid compilation warnings */ + + L_bwe_br = L_add(st_fx->core_brate_fx, 0); + hqswb_clas_fx = HQ_NORMAL; + move16(); + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + IF ( EQ_16(is_transient_fx, 1)) + { + hqswb_clas_fx = HQ_TRANSIENT; + move16(); + } + ELSE + { + hqswb_clas_fx = peak_avrg_ratio_fx( st_fx->total_brate_fx, L_t_audio, NUMC_N, &hHQ_core->mode_count, &hHQ_core->mode_count1, SWB_BWE_LR_Qs ); + } + + /* write the classification information into the bitstream */ + push_indice_fx( hBstr, IND_HQ2_SWB_CLAS, hqswb_clas_fx, 2 ); + (*num_bits_fx) = sub(*num_bits_fx, 2); + if( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + flag_spt_fx = 1; + move16(); + } + } + ELSE + { + /* write the transient bit into the bitstream */ + push_indice_fx( st_fx->hBstr, IND_HQ2_SWB_CLAS, is_transient_fx, 1 ); + + /* subtract one bit for the transient flag */ + (*num_bits_fx)--; + } + + hq2_core_configure_fx( inner_frame_fx, *num_bits_fx, is_transient_fx, &bands_fx, &length_fx, band_width, band_start, band_end, + &L_qint, &eref_fx, &bit_alloc_weight_fx, &gqlevs_fx, &Ngq_fx, &p2a_bands_fx, &p2a_th_fx, &pd_thresh_fx, &ld_slope_fx, &ni_coef_fx + ,L_bwe_br); + + highlength_fx = band_end[sub(bands_fx, 1)]; + move16(); + har_bands_fx = bands_fx; + move16(); + + test(); + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&is_transient_fx==0&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + /* reserve bits for HQ_NORMAL2 and HQ_HARMONIC modes */ + test(); + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)||EQ_16(hqswb_clas_fx,HQ_HARMONIC)) + { + (*num_bits_fx) = sub(*num_bits_fx, get_usebit_npswb_fx(hqswb_clas_fx)); + } + } + + test(); + test(); + IF(( EQ_32(L_bwe_br, HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))&&EQ_16(st_fx->bwidth_fx,SWB)) + { + IF( NE_16(hHQ_core->prev_hqswb_clas, HQ_NORMAL)) + { + j = 0; + move16(); + FOR(k=sub(bands_fx,SPT_SHORTEN_SBNUM); kprev_SWB_peak_pos[j] = 0; + move16(); + j = add(j, 1); + } + } + } + + /* Check if input frame is larger than coded bandwidth */ + test(); + IF ( GT_16(inner_frame_fx, length_fx)&&is_transient_fx) + { + /* If so, collapse transient frame (4 short transforms) to remove uncoded coefficients */ + + k1_step_fx = shr(length_fx, 2); /* k1 = length/NUM_TIME_SWITCHING_BLOCKS */ + k2_step_fx = shr(inner_frame_fx, 2); /* k2 = inner_frame/NUM_TIME_SWITCHING_BLOCKS */ + k1_fx = k1_step_fx; + k2_fx = k2_step_fx; + FOR (i = 1; i < NUM_TIME_SWITCHING_BLOCKS; i++) + { + /*k1 = i*length/NUM_TIME_SWITCHING_BLOCKS; */ + /*k2 = i*inner_frame/NUM_TIME_SWITCHING_BLOCKS; */ + + Copy32( &L_t_audio[k2_fx], &L_t_audio[k1_fx], k1_step_fx ); + + k1_fx = add(k1_fx, k1_step_fx); + k2_fx = add(k2_fx, k2_step_fx); + } + } + + /* Spectral energy calculation/quantization */ + ebits_fx = band_energy_quant_fx( hBstr, L_t_audio, band_start, band_end, L_band_energy, bands_fx, + L_qint, eref_fx, is_transient_fx ); + + /* First pass bit budget for TCQ of spectral band information */ + exp_norm = norm_s(gqlevs_fx); /* gqbits_fx = (short int) log2_f ((float) gqlevs_fx); */ + gqbits_fx = sub(14, exp_norm); + + bit_budget_fx = sub(sub(*num_bits_fx, ebits_fx), round_fx(L_shl(L_mult(Ngq_fx, gqbits_fx), 15))); /* (*num_bits) - (short) ceil (ebits) - Ngq * gqbits; */ + + + pbits_fx = 0; + move16(); + + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + IF( EQ_16(hqswb_clas_fx, HQ_HARMONIC)) + { + set16_fx( p2a_flags_fx, 1, har_bands_fx ); + } + ELSE + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits_fx = p2a_threshold_quant_fx(hBstr, L_t_audio, band_start, band_end, band_width, bands_fx, p2a_bands_fx, p2a_th_fx, p2a_flags_fx ); + bit_budget_fx = sub(bit_budget_fx, pbits_fx); + + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + return_bits_normal2_fx( &bit_budget_fx, p2a_flags_fx, bands_fx, bits_lagIndices_modeNormal ); + } + } + } + ELSE + { + /* High band tonality detector based on per band peak-to-average ratio */ + pbits_fx = p2a_threshold_quant_fx(hBstr, L_t_audio, band_start, band_end, band_width, bands_fx, p2a_bands_fx, p2a_th_fx, p2a_flags_fx ); + bit_budget_fx = sub(bit_budget_fx, pbits_fx); + } + + IF(EQ_16(flag_spt_fx, 1)) + { + spt_shorten_domain_band_save_fx(bands_fx, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width); + spt_shorten_domain_pre_fx(band_start, band_end, hHQ_core->prev_SWB_peak_pos, bands_fx, L_bwe_br, new_band_start, new_band_end, new_band_width); + spt_shorten_domain_set_fx(st_fx, L_t_audio, p2a_flags_fx, new_band_start, new_band_end, new_band_width, bands_fx, band_start, band_end, band_width, &bit_budget_fx); + } + + /* Estimate number of bits per band */ + Q_band_energy = SWB_BWE_LR_Qbe; + + FOR(i = 0; i < bands_fx; i++) + { + L_tmp = L_shl(L_band_energy[i],sub(16,Q_band_energy));/*Q16 */ + + frac1 = L_Extract_lc(L_tmp, &exp); /* Extract exponent of L_tmp */ + L_tmp = Pow2(30, frac1); + exp = sub(exp, 30); + Ep_fx[i] = L_shl(L_tmp , s_max(sub(exp,6), -31)); /* Q -6 */ + } + + FOR( i = 0; i < bands_fx; i++ ) + { + L_tmp2 = Ep_fx[i]; + L_tmp = L_max(1, L_tmp2); + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + + L_tmp3 = (Word32)band_width[i]; + exp2 = norm_l(L_tmp3); + tmp2 = extract_h(L_shl(L_tmp3, exp2)); + + exp2 = sub(exp, exp2); /* Denormalize and substract */ + + tmp3 = sub(tmp2, tmp); + if (tmp3 > 0) + { + tmp2 = shr(tmp2, 1); + } + if (tmp3 > 0) + { + exp2 = add(exp2, 1); + } + tmp = div_s(tmp2, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp2);/*Q(31-exp2) */ + Ep_tmp_fx[i] = L_shr(L_tmp,sub(15,exp2));/*Q13 */ + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( is_transient_fx == 0 && EQ_16(inner_frame_fx, L_FRAME8k)&&LE_32(st_fx->core_brate_fx,ACELP_13k20)) + { + lowband = 6; + move16(); + trans_bit = 2; + move16(); + bit_budget_fx =sub(bit_budget_fx,trans_bit); + gama_fx = 27852; /*Q15 0.85f;// */ + beta_fx = 17203; + move16();/*Q14 1.05f; */ + + set16_fx( &p2a_flags_tmp[sub(bands_fx,trans_bit)], 0, 2 ); + + IF( EQ_32(st_fx->core_brate_fx, ACELP_13k20)) + { + beta_fx = 13107; + move16();/*14 1.25f; */ + gama_fx = 31130; + move16();/*0.95f; */ + Copy(&p2a_flags_fx[sub(bands_fx,trans_bit)], &p2a_flags_tmp[sub(bands_fx,trans_bit)], trans_bit); + } + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + Ep_vari_fx = L_deposit_l(0); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR( i = 0; i < bands_fx; i++ ) + { + IF( GE_16(i,lowband)) + { + Ep_vari_fx = L_add(Ep_vari_fx,L_abs(L_sub(Ep_tmp_fx[i],Ep_tmp_fx[sub(i,1)])));/*Q15 */ + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ + IF(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q15 */ + } + } + } + /* modify the last p2a_bands subbands band_energies */ + Copy32( L_band_energy,L_band_energy_tmp,bands_fx ); /*Q_band_energy */ + L_tmp = Mult_32_16(Ep_peak_fx,24576);/*Q(13+14-15 = 12) 1.5 lowband = 6; */ + L_tmp2 =Mult_32_16(Ep_peak_fx,shl(sub(bands_fx,lowband),9));/*Q(13+9-15 = 7) */ + L_tmp3 =Mult_32_16(Ep_avrg_fx,1126);/*Q(13+9-15 = 7) */ + + test(); + test(); + test(); + test(); + IF(( (LT_32(L_tmp, L_shr(Ep_avrgL_fx,1))&&EQ_32(st_fx->core_brate_fx,ACELP_13k20))||LT_32(st_fx->core_brate_fx,ACELP_13k20))&& + LT_32(L_tmp2, L_tmp3) && GT_32(L_tmp2, L_shr(Ep_avrg_fx,7)) ) + { + FOR(i = lowband; i < bands_fx; i++) + { + L_tmp = Mult_32_16(Ep_avrg_fx,24576);/*Q(13+14-15 = 12) 1.5 */ + IF(LT_32(L_shr(Ep_tmp_fx[i],1), L_tmp)) + { + L_tmp = Mult_32_16(Ep_peak_fx,sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = extract_h(L_shl(L_tmp,14));/*Q-4 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = L_shl(Mult_32_16(Ep_avrg_fx,tmp),sub(13,exp));/*Q(13+exp-15 +13-exp +4 = 15) */ + L_tmp2 = L_add(L_tmp,13107); /*15 */ + tmp2 = extract_l(L_min(L_max(L_tmp2,16384),gama_fx)); /*15 = 15 */ + L_band_energy_tmp[i] = Mult_32_16(L_band_energy_tmp[i],tmp2);/*Q(Q_band_energy+15-15 = Q_band_energy) */ + } + } + } + ELSE + { + j = 0; + FOR(i = sub(bands_fx,trans_bit); i < bands_fx; i++) + { + alpha_fx = 16384; + move16();/*Q14 */ + IF( EQ_16(p2a_flags_tmp[i],1)) + { + L_tmp = Mult_32_16(Ep_tmp_fx[i],sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = extract_h(L_shl(L_tmp,14));/*Q-4 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp =Mult_32_16(Ep_vari_fx,3277);/*13+15-15=13 */ +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o(Mult_32_16(L_tmp,tmp),sub(12,exp), &Overflow);/*Q(13+exp-15 +12-exp +4 = 14) */ +#else + L_tmp = L_shl(Mult_32_16(L_tmp,tmp),sub(12,exp));/*Q(13+exp-15 +12-exp +4 = 14) */ +#endif + tmp2 = extract_h(Ep_avrg_fx);/*Q13-16=-3 */ + IF(tmp2 != 0) + { + exp = norm_s(tmp2); + tmp2 = shl(tmp2,exp);/*Q(exp) */ + tmp2 = div_s(16384,tmp2);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp2 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp2 =Mult_32_16(Ep_vari_fx,6554);/*13+15-15=13 */ +#ifdef BASOP_NOGLOB + L_tmp2 = L_shl_o(Mult_32_16(L_tmp2,tmp2),sub(13,exp), &Overflow);/*Q(13+exp-15 +13-exp +3 = 14) */ +#else + L_tmp2 = L_shl(Mult_32_16(L_tmp2,tmp2),sub(13,exp));/*Q(13+exp-15 +13-exp +3 = 14) */ +#endif + L_tmp=L_min(L_tmp,L_tmp2);/*14 */ + tmp=extract_l(L_min(L_tmp,13107));/*14 */ + alpha_fx =add(16384,tmp); + + } + IF(EQ_16(hHQ_core->last_bitalloc_max_band[j++], 1)) + { + L_tmp = Mult_32_16(Ep_tmp_fx[i],sub(bands_fx,lowband));/*Q(13+0-15 = -2) */ + tmp = extract_h(L_shl(L_tmp,14));/*Q-2 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o(Mult_32_16(Ep_avrg_fx,tmp),sub(14,exp), &Overflow);/*Q(13+exp-15 +14-exp+2 = 14) */ +#else + L_tmp = L_shl(Mult_32_16(Ep_avrg_fx,tmp),sub(14,exp));/*Q(13+exp-15 +14-exp+2 = 14) */ +#endif + L_tmp =L_max(L_tmp,16384); /*14 */ + tmp=extract_l(L_min(L_tmp,beta_fx)); /*14 */ + alpha_fx=shl(mult(alpha_fx,tmp),1);/*14+14-15 +1=14 */ + } + ELSE + { + tmp2 = extract_h(Ep_avrg_fx);/*13 -16 =-3 */ + IF(tmp2 != 0) + { + exp = norm_s(tmp2); + tmp2 = shl(tmp2,exp);/*Q(exp) */ + tmp2 = div_s(16384,tmp2);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp2 = 0x7fff; + move16(); + exp = 0; + move16(); + } +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o(Mult_32_16(Ep_tmp_fx[i],tmp2),sub(19,exp), &Overflow);/*Q(13+exp-15 +19-exp +3 = 20) */ +#else + L_tmp = L_shl(Mult_32_16(Ep_tmp_fx[i],tmp2),sub(19,exp));/*Q(13+exp-15 +19-exp +3 = 20) */ +#endif + L_tmp = Mult_32_16(L_tmp,shl(sub(bands_fx,lowband),9));/*20 +9 -15 =14 */ + L_tmp =L_max(L_tmp,13926); /*14 */ + tmp2 =extract_l(L_min(L_tmp,16384)); /*14 */ + alpha_fx=shl(mult(alpha_fx,tmp2),1);/*14+14-15+1 =14 */ + } + L_band_energy_tmp[i] = L_shl(Mult_32_16(L_band_energy_tmp[i],alpha_fx),1);/*Q(Q_band_energy+14-15 +1= Q_band_energy) */ + } + } + lowband = 3; + move16(); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR(i = 0; i < bands_fx; i++) + { + IF(GE_16(i,lowband)) + { + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ + } + ELSE + { + Ep_avrgL_fx = L_add(Ep_avrgL_fx,L_shr(Ep_tmp_fx[i],1));/*Q12 */ + IF(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q13 */ + } + } + } + L_tmp = Mult_32_16(Ep_peak_fx,28262);/*Q(13+14-15 = 12) 1.725 lowband = 3; */ + L_tmp2 =Mult_32_16(Ep_avrgL_fx,24576);/*Q(12+14-15 = 11) */ + test(); + test(); + IF( GT_32(L_shr(Ep_avrg_fx,2), L_tmp2)&<_32(L_shr(Ep_avrg_fx,4),L_tmp2)&>_32(L_tmp,Ep_avrgL_fx)) + { + adjustFlag = 1; + move16(); + FOR (i = 0; i < lowband; i++) + { + tmp = extract_h(Ep_avrgL_fx);/*Q-4 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + /*when the divisor is zero, happens rarely*/ + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_peak_fx,tmp);/*Q(13+exp-15+4 = exp+2) */ + L_tmp = Mult_32_16(L_tmp,lowband);/*Q(exp+2+0-15 = exp-13) */ + L_tmp = Mult_32_16(L_tmp,18842);/*Q(exp-13+16-16 = exp-13) */ + L_tmp = L_shl(L_tmp,sub(27,exp));/*Q14 0.5 */ + tmp2=extract_l(L_min(L_tmp,19661));/*14 */ + L_tmp = Mult_32_16(L_band_energy_tmp[i],tmp2);/*Q(Q_band_energy+14-15 = Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + hq2_bit_alloc_fx( L_band_energy_tmp, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + *num_bits_fx, hqswb_clas_fx, st_fx->bwidth_fx, is_transient_fx ); + + /* encode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + FOR(i = 0; i < 2; i++) + { + push_indice_fx ( st_fx->hBstr, IND_HQ2_LAST_BA_MAX_BAND, hHQ_core->last_bitalloc_max_band[i], 1 ); + } + } + ELSE IF( is_transient_fx == 0 && EQ_16(inner_frame_fx, L_FRAME16k)) + { + bit_budget_fx = sub(bit_budget_fx,2);/* bits in high bands to indicate the last 2 subbands is allocated bits or not */ + FOR( i = 0; i < bands_fx; i++ ) + { +#ifdef BASOP_NOGLOB + Ep_tmp_fx[i] = L_shl_o(Ep_tmp_fx[i],2, &Overflow); +#else /* BASOP_NOGLOB */ + Ep_tmp_fx[i] = L_shl(Ep_tmp_fx[i],2); +#endif /* BASOP_NOGLOB */ + } + IF( EQ_32( st_fx->core_brate_fx, ACELP_13k20 )) + { + lowband = 8; + move16(); + highband = 15; + move16(); + bw_low = sub(band_start[highband],band_start[lowband]); + bw_high = sub(add(band_end[sub(bands_fx,1)],1),band_start[highband]); + } + ELSE + { + lowband = 8; + move16(); + highband = 16; + move16(); + bw_low = sub(band_start[highband],band_start[lowband]); + bw_high = sub(add(band_end[sub(bands_fx,1)],1),band_start[highband]); + } + /* calculate the the low band/high band energy and the variance/avrage of the envelopes */ + enerL_fx = L_deposit_l(0); + enerH_fx = L_deposit_l(0); + Ep_vari_fx = L_deposit_l(0); + Ep_avrg_fx = L_deposit_l(0); + FOR( i = 0; i < bands_fx; i++ ) + { + test(); + IF( GE_16(i,lowband)&&add(sub(i,bands_fx),p2a_bands_fx)<0) + { + Ep_vari_fx = L_add(Ep_vari_fx,L_abs(L_sub(Ep_tmp_fx[i],Ep_tmp_fx[sub(i,1)])));/*Q15 */ +#ifdef BASOP_NOGLOB + Ep_avrg_fx = L_add_o(Ep_avrg_fx,Ep_tmp_fx[i], &Overflow);/*Q15 */ +#else /* BASOP_NOGLOB */ + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ +#endif /* BASOP_NOGLOB */ + } + + IF(GE_16(i,highband)) + { + enerH_fx = L_add(enerH_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + ELSE IF(GE_16(i,lowband)) + { + enerL_fx = L_add(enerL_fx,L_shl(Ep_fx[i],2));/*Q0 */ + } + } + + /* modify the last p2a_bands subbands band_energies */ + Copy32( L_band_energy,L_band_energy_tmp,bands_fx ); /*Q_band_energy */ + L_tmp = L_max(enerH_fx,enerL_fx); + tmp = s_max(bw_low,bw_high); + i = norm_l(L_tmp); + j = norm_s(tmp); + L_tmp = Mult_32_16(L_shl(enerH_fx,i), shl(bw_low,j)); /* i + j -15 */ + L_tmp2 = Mult_32_16(L_shl(enerL_fx,i), shl(bw_high,j)); /*i + j -15 */ + L_tmp2 = L_sub(L_tmp,L_tmp2); + FOR( i = sub(bands_fx,p2a_bands_fx); i < bands_fx; i++ ) + { + test(); + IF( EQ_16(p2a_flags_fx[i],1)||L_tmp2>0) + { + tmp = sub(bands_fx,p2a_bands_fx); + tmp = sub(tmp,lowband);/*Q0 */ + + tmp1 = extract_h(L_shl(Ep_avrg_fx,1));/*Q0 */ + IF(tmp1 != 0) + { + exp = norm_s(tmp1); + tmp1 = shl(tmp1,exp);/*Q(exp) */ + tmp1 = div_s(16384,tmp1);/*Q(15+14-exp = 29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp1 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+0-15 = exp-15) */ + L_tmp = Mult_32_16(L_tmp,16384);/*Q(exp-15+13-15 = exp-17) */ + L_tmp = L_shl(L_tmp,sub(32,exp));/*Q15 */ + tmp = extract_l(L_min(L_tmp,6554));/*Q15 */ + L_tmp = Mult_32_16(Ep_vari_fx,tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+15-15 = exp) */ + L_tmp = L_shl(L_tmp,sub(15,exp));/*Q15 */ + tmp = extract_l(L_shr(L_min(L_tmp,13107),1));/*Q14 */ + alpha_fx = add(tmp,16384);/*Q14 */ + } + ELSE + { + alpha_fx = 16384; + move16();/*Q14 */ + } + + IF(add(sub(i,bands_fx),p2a_bands_fx) > 0) + { + tmp = sub(bands_fx,p2a_bands_fx); + IF(EQ_16(hHQ_core->last_bitalloc_max_band[sub(i, add(tmp, 1))], 1)) + { + tmp = sub(tmp,lowband); + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp);/*Q(15+0-15 = 0) */ +#ifdef BASOP_NOGLOB + tmp = extract_h(L_shl_o(L_tmp,16, &Overflow));/*Q0 */ +#else /* BASOP_NOGLOB */ + tmp = extract_h(L_shl(L_tmp,16));/*Q0 */ +#endif /* BASOP_NOGLOB */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_avrg_fx,tmp);/*Q(15+exp-15 = exp) */ + L_tmp = L_shl(L_tmp,sub(14,exp));/*Q14 */ + tmp = extract_l(L_min(L_max(L_tmp,16384),20480));/*Q14 */ + L_tmp = L_mult(alpha_fx,tmp);/*Q(14+14+1=29) */ + alpha_fx = extract_l(L_shr(L_tmp,15)); /*Q14 */ + } + ELSE + { + tmp = sub(tmp,lowband); + + tmp1 = extract_h(L_shl(Ep_avrg_fx,1));/*Q0 */ + IF(tmp1 != 0) + { + exp = norm_s(tmp1); + tmp1 = shl(tmp1,exp);/*Q(exp) */ + tmp1 = div_s(16384,tmp1);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp1 = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_tmp_fx[i],tmp1);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,tmp);/*Q(exp+0-15 = exp-15) */ + L_tmp = L_shl(L_tmp,sub(29,exp));/*Q14 */ + tmp = extract_l(L_min(L_max(L_tmp,13926),16384));/*Q14 */ + L_tmp = L_mult(alpha_fx,tmp);/*Q(14+14+1=29) */ + alpha_fx = extract_l(L_shr(L_tmp,15)); /*Q14 */ + } + } + L_tmp = Mult_32_16(L_band_energy_tmp[i],alpha_fx);/*Q(Q_band_energy+14-15=Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1);/*Q Q_band_energy */ + } + lowband = 6; + move16(); + Ep_avrg_fx = L_deposit_l(0); + Ep_avrgL_fx = L_deposit_l(0); + Ep_peak_fx = L_deposit_l(0); + FOR(i = 0; i < bands_fx; i++) + { + IF(GE_16(i,lowband)) + { +#ifdef BASOP_NOGLOB + Ep_avrg_fx = L_add_o(Ep_avrg_fx,Ep_tmp_fx[i], &Overflow);/*Q15 */ +#else /* BASOP_NOGLOB */ + Ep_avrg_fx = L_add(Ep_avrg_fx,Ep_tmp_fx[i]);/*Q15 */ +#endif /* BASOP_NOGLOB */ + } + ELSE + { +#ifdef BASOP_NOGLOB + Ep_avrgL_fx = L_add_o(Ep_avrgL_fx,Ep_tmp_fx[i], &Overflow);/*Q15 */ +#else /* BASOP_NOGLOB */ + Ep_avrgL_fx = L_add(Ep_avrgL_fx,Ep_tmp_fx[i]);/*Q15 */ +#endif + IF(GT_32(Ep_tmp_fx[i],Ep_peak_fx)) + { + Ep_peak_fx = L_add(Ep_tmp_fx[i], 0); /*Q15 */ + } + } + } + + L_tmp = Mult_32_16(Ep_peak_fx,24576);/*Q(15+12-15 = 12) lowband = 6; */ + L_tmp2 =Mult_32_16(Ep_peak_fx,19661);/*Q(15+14-15 = 14) */ + L_tmp3 =Mult_32_16(Ep_avrgL_fx,24576);/*Q(15+12-15 = 12) */ + + test(); + test(); + test(); + test(); + test(); + IF( (GT_32(L_shr(Ep_avrgL_fx,1), Ep_avrg_fx)&>_32(L_tmp,L_shr(Ep_avrgL_fx,2))&<_32(L_shr(Ep_avrgL_fx,1),L_tmp2))|| + (GT_32(L_shr(Ep_avrg_fx,1), Ep_avrgL_fx) && LT_32(L_shr(Ep_avrg_fx,3),L_tmp3) && GT_32(L_tmp,L_shr(Ep_avrgL_fx,2)) ) ) + { + adjustFlag = 1; + move16(); + FOR (i = 0; i < lowband; i++) + { + tmp = extract_h(L_shl(Ep_avrgL_fx,1));/*Q0 */ + IF(tmp != 0) + { + exp = norm_s(tmp); + tmp = shl(tmp,exp);/*Q(exp) */ + tmp = div_s(16384,tmp);/*Q(15+14-exp=29-exp) */ + exp = sub(29,exp); + } + ELSE + { + tmp = 0x7fff; + move16(); + exp = 0; + move16(); + } + L_tmp = Mult_32_16(Ep_peak_fx,tmp);/*Q(15+exp-15 = exp) */ + L_tmp = Mult_32_16(L_tmp,lowband);/*Q(exp+0-15 = exp-15) */ + L_tmp = L_shl(L_tmp,sub(28,exp));/*Q14 0.5 */ + tmp = extract_l(L_min(L_tmp,19661));/*//Q14 */ + L_tmp = Mult_32_16(L_band_energy_tmp[i],tmp);/*Q(Q_band_energy+14-15 = Q_band_energy-1) */ + L_band_energy_tmp[i] = L_shl(L_tmp,1); /*Q_band_energy */ + } + } + + hq2_bit_alloc_fx( L_band_energy_tmp, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + *num_bits_fx, hqswb_clas_fx, st_fx->bwidth_fx, is_transient_fx ); + + /* encode the last p2a_bands-1 subbands bit-allocation index of the previous frame */ + FOR(i = 0; i < 2; i++) + { + push_indice_fx( st_fx->hBstr, IND_HQ2_LAST_BA_MAX_BAND, hHQ_core->last_bitalloc_max_band[i], 1 ); + } + } + ELSE IF( EQ_16(st_fx->bwidth_fx, SWB)&&EQ_16(hqswb_clas_fx,HQ_HARMONIC)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + /* bit allocation for harmonic mode */ + hq2_bit_alloc_har_fx( L_band_energy, bit_budget_fx, bands_fx, L_Rk, p2a_bands_fx, L_bwe_br, p2a_flags_fx, band_width ); + } + ELSE + { + + /* estimate number of bits per band */ + hq2_bit_alloc_fx( + L_band_energy, bands_fx, L_Rk, &bit_budget_fx, p2a_flags_fx, bit_alloc_weight_fx, band_width, + *num_bits_fx, hqswb_clas_fx, st_fx->bwidth_fx, is_transient_fx ); + } + + tcq_core_LR_enc_fx( hBstr, /*st_fx->idchan, */inp_vector_fx, /*t_audio, */L_t_audio, /*y2, */L_y2, bit_budget_fx, bands_fx, band_start, band_end, band_width, /*Rk*/L_Rk, npulses_fx, k_sort_fx, + p2a_flags_fx, p2a_bands_fx, hHQ_core->last_bitalloc_max_band, inner_frame_fx, adjustFlag, is_transient_fx ); + + IF((EQ_16(inner_frame_fx, L_FRAME8k)&&LE_32(st_fx->core_brate_fx,ACELP_13k20))||EQ_16(inner_frame_fx,L_FRAME16k)) + { + j = 0; + FOR(i = 2; i > 0; i--) + { + IF(npulses_fx[bands_fx-i] > 0) + { + hHQ_core->last_bitalloc_max_band[j] = 1; + } + ELSE + { + hHQ_core->last_bitalloc_max_band[j] = 0; + } + j++; + } + } + + /* Denormalize the coded MDCT spectrum */ + mdct_spectrum_denorm_fx( inp_vector_fx, L_y2, band_start, band_end, band_width, L_band_energy, npulses_fx, bands_fx, ld_slope_fx, pd_thresh_fx ); + + /* Apply fine gain quantization to denormalized coded spectrum */ + mdct_spectrum_fine_gain_enc_fx( st_fx, L_t_audio, L_y2, band_start, band_end, k_sort_fx, bands_fx, + L_qint, Ngq_fx, gqlevs_fx, gqbits_fx ); + + + /* Restore the band information */ + IF( EQ_16(flag_spt_fx, 1)) + { + spt_shorten_domain_band_restore_fx(bands_fx, band_start, band_end, band_width, org_band_start, org_band_end, org_band_width); + } + + /* Inject noise into components having relatively low pulse energy per band */ + ni_seed_fx = add(add(add(npulses_fx[0], npulses_fx[1]), npulses_fx[2]), npulses_fx[3]); + + Copy32(L_y2, L_y2_ni, band_end[bands_fx-1]+1); + hq2_noise_inject_fx( L_y2_ni, band_start, band_end, band_width, Ep_fx, L_Rk, npulses_fx, ni_seed_fx, bands_fx, 0, bw_low, bw_high, enerL_fx, enerH_fx, + hHQ_core->last_ni_gain_fx, hHQ_core->last_env_fx, &hHQ_core->last_max_pos_pulse, p2a_flags_fx, p2a_bands_fx, + hqswb_clas_fx, st_fx->bwidth_fx, L_bwe_br ); + + test(); + test(); + IF( EQ_16(st_fx->bwidth_fx, SWB)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))) + { + test(); + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)||EQ_16(hqswb_clas_fx,HQ_HARMONIC)) + { + preset_hq2_swb_fx( hqswb_clas_fx, band_end, &har_bands_fx, p2a_bands_fx,length_fx, bands_fx, &lowlength_fx, &highlength_fx, L_m ); + + swb_bwe_enc_lr_fx( st_fx, L_y2, SWB_BWE_LR_Qs, L_t_audio, L_m, L_bwe_br, + bands_fx, band_start, band_end, L_band_energy, SWB_BWE_LR_Qbe, p2a_flags_fx, hqswb_clas_fx, lowlength_fx, highlength_fx, + hHQ_core->prev_frm_index, har_bands_fx, &hHQ_core->prev_frm_hfe2, &hHQ_core->prev_stab_hfe2, band_width, L_y2_ni, &ni_seed_fx); + + post_hq2_swb_fx( L_m, lowlength_fx, highlength_fx, hqswb_clas_fx, har_bands_fx, bands_fx, p2a_flags_fx, band_start, band_end, L_y2, npulses_fx ); + + IF( EQ_16(hqswb_clas_fx, HQ_NORMAL)) + { + spt_swb_peakpos_tmp_save_fx(L_y2, bands_fx, band_start, band_end, prev_SWB_peak_pos_tmp_fx); + FOR( k=0; kbwidth_fx, is_transient_fx, hqswb_clas_fx, &hHQ_core->prev_hqswb_clas, + hHQ_core->prev_SWB_peak_pos, prev_SWB_peak_pos_tmp_fx, &hHQ_core->prev_frm_hfe2, &hHQ_core->prev_stab_hfe2, 0 ); + + IF( NE_16(st_fx->bwidth_fx, SWB)) + { + /* reset HQ classifier memories */ + hHQ_core->mode_count = 0; + move16(); + hHQ_core->mode_count1 = 0; + move16(); + } + + test(); + test(); + test(); + IF( NE_16(hqswb_clas_fx, HQ_HARMONIC)&&(EQ_32(L_bwe_br,HQ_16k40)||EQ_32(L_bwe_br,HQ_13k20))&&EQ_16(st_fx->bwidth_fx,SWB)) + { + hHQ_core->prev_frm_index[0] = -1; + move16(); + hHQ_core->prev_frm_index[1] = -1; + move16(); + } + + /* update number of unused bits */ + *num_bits_fx = 0; + move16(); + + hHQ_core->hvq_hangover = 0; + move16(); + + return; +} + +/*--------------------------------------------------------------------------* + * small_symbol_enc_tran() + * + * Huffman encoding of differential energies, estimating or packing bits + * if flag_pack = 0, LC mode info. is output else LC mode info. is input + * if flag_pack = 0, estimatng else packing bits + *--------------------------------------------------------------------------*/ + +static Word16 small_symbol_enc_tran_fx( /* o : bits */ + BSTR_ENC_HANDLE hBstr, /* i : handle to the bitstream */ + const Word16 *qbidx, /* i : input of dequantized differential energy */ + const Word16 BANDS, /* i : number of bands */ + Word16 *hLCmode, /* i/o: LC mode info */ + const Word16 flag_pack, /* i : indicator of packing or estimating bits */ + const Word16 is_transient +) +{ + Word16 i, bits; + Word16 difidx[BANDS_MAX]; + + FOR( i=0; i= -(2<<(i+1))) */ + test(); + IF ( LE_16(max_q, sub(shl(2, add(i,1)), 1))&& GE_16(min_q,-shl(2,add(i,1)))) + { + BREAK; + } + } + basic_shift = i; + move16(); + + min_bits = 1000; + move16(); + min_bits_pos = basic_shift; + move16(); + tmp = add(basic_shift, 3); + FOR( offset0=basic_shift; offset0 0 ) + { + FOR( i=0; i QE) */ + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + /*E += yos[i] * yos[i]; */ + temp_fx = round_fx(L_shl(L_t_audio[i], exp_norm)); + L_E = L_mac(L_E, temp_fx, temp_fx); /* (Qs+exp_norm-16)*2+1 */ + } + + /*band_energy[k] = (float) log2_f (E + 1.0e-1f); */ + exp_norm2 = norm_l(L_E); + exp = add(add(shl(sub(add(SWB_BWE_LR_Qs, exp_norm), 16), 1), 1), exp_norm2); + L_E = L_shl(L_E, exp_norm2); + frac = Log2_norm_lc(L_E); + exp = sub(30, exp); + L_tmp = L_Comp(exp, frac); + L_band_energy[k] = L_shr(L_tmp, 2); /* Q16->Qbe(Q14) */ + } + + IF (is_transient_fx) + { + reverse_transient_frame_energies_fx( L_band_energy, bands_fx ); + } + + + /* Quantize the reference and band energies */ + exp_normd = norm_l(L_qint); + rev_qint_fx = div_s(0x4000, round_fx(L_shl(L_qint, exp_normd))); /* Q14-(29+exp_normd-16)+15 */ + Qrev_qint = sub(14-(29-16)+15, exp_normd); + + bq0_fx = round_fx(L_shl(L_mult(eref_fx, rev_qint_fx), sub(5, Qrev_qint))); /* 16-(10+Qrev_qint+1) */ + FOR (k = 0; k < bands_fx; k++) + { + /*bq1[k] = round_f (band_energy[k] / qint); */ + L_tmp = Mpy_32_16_1(L_band_energy[k], rev_qint_fx); /* Q14+Qrev_qint-15 */ + bq1_fx[k] = round_fx( L_shl(L_tmp, sub(17, Qrev_qint)) ); /* 16-(14+Qrev_qint-15) */ + } + + IF(is_transient_fx) + { + + Copy(bq1_fx, bq1_temp_fx, bands_fx); + + /* Calculate the differential energies */ + diffcod_lrmdct_fx(bands_fx, bq0_fx, bq1_temp_fx, bq2_temp_fx, is_transient_fx); + } + + /* Calculate the differential energies */ + bq2_fx[0] = sub(bq1_fx[0], bq0_fx); + FOR (k = 1; k < bands_fx; k++) + { + bq2_fx[k] = sub(bq1_fx[k], bq1_fx[k - 1]); + move16(); + } + + /* Modifying qbidx to be located in the range -256~255 */ + FOR( i=0; i Qbe(Q14) */ + } + + IF (is_transient_fx) + { + reverse_transient_frame_energies_fx( L_band_energy, bands_fx ); + } + + return( deng_bits ); +} + + +/*-------------------------------------------------------------------* + * p2a_threshold_quant() + * + * + *-------------------------------------------------------------------*/ + +static Word16 p2a_threshold_quant_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: : bit stream */ + const Word32 *L_t_audio, /* i : Q12 : input spectrum */ + const Word16 band_start[], /* i : Q0 : table of start freq for every subband */ + const Word16 band_end[], /* i : Q0 : table of end freq for every subband */ + const Word16 band_width[], /* i : Q0 : table of bandwidth for every subband */ + const Word16 bands, /* i : Q0 : number of subbands */ + const Word16 p2a_bands, /* i : Q0 : tonality indicator */ + const Word16 p2a_th_fx, /* i : Q11 : threshold tonal or not */ + Word16 *p2a_flags_fx /* i/o: Q0 : tonality flag */ +) +{ + Word16 i, j, k; + Word32 L_a, L_p, L_e; + Word16 Qa; + Word32 L_tmp; + Word16 temp_fx; + Word16 exp_norm; + Word16 exp_safe; + Word16 exp_normn, exp_normd; + + Word16 norm_a_fx,Qnorm_a; + Word16 pa_fx, Qpa; + + Word16 exp, frac; + + Word32 L_p2a; + Word16 p2a_fx; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + exp_safe=4; /* never happen overflow. */ + + set16_fx(p2a_flags_fx, 1, bands); + + j = 0; + move16(); + FOR (k = sub(bands, p2a_bands); k < bands; k++) + { + L_a = L_deposit_l(0); + L_p = L_deposit_l(0); + + L_tmp = L_deposit_l(0); + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + L_tmp = L_or(L_tmp, L_abs(L_t_audio[i])); + } + exp_norm = norm_l(L_tmp); + exp_norm = sub(exp_norm, exp_safe); + + FOR (i = band_start[k]; i <= band_end[k]; i++) + { + temp_fx = round_fx(L_shl(L_t_audio[i], exp_norm)); /* Q12+exp_norm-16 -> exp_norm-4 */ + L_e = L_mult(temp_fx, temp_fx); + + if ( GT_32(L_e, L_p)) + { + L_p = L_add(L_e, 0); + } + L_a = L_add(L_a, L_e); + } + Qa = sub(shl(exp_norm, 1), 7); /* (exp_norm-4)*2+1 */ + + IF ( L_a > 0x0L ) + { + /* a /= band_width[k]; */ + exp_normn = norm_l(L_a); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(band_width[k]); + norm_a_fx = div_l(L_shl(L_a, exp_normn), shl(band_width[k], exp_normd)); + Qnorm_a = sub(sub(add(Qa, exp_normn), exp_normd), 1); /* (Qa+exp_normn)-exp_normd-1); */ + + /*p2a = 10.0f * (float) log10 (p / a); */ + p2a_fx = 0; + move16(); + IF ( norm_a_fx > 0 ) + { + exp_normn = norm_l(L_p); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(norm_a_fx); + pa_fx = div_l(L_shl(L_p, exp_normn), shl(norm_a_fx, exp_normd)); + Qpa = sub(sub(add(Qa, exp_normn), add(Qnorm_a, exp_normd)), 1); + + L_tmp = L_deposit_h(pa_fx); + Qpa = add(Qpa, 16); + exp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(30, exp); + exp = sub(exp, Qpa); + L_tmp = L_Comp(exp, frac); + + /* 10/( log(10)/log(2) ) = 3.01029995663981195211 24660(Q13) */ + L_p2a = Mpy_32_16_1(L_tmp, 24660); /* 16+13-15 -> Q14 */ + +#ifdef BASOP_NOGLOB + p2a_fx = round_fx_o(L_shl_o(L_p2a, 13, &Overflow), &Overflow); /* 27 -16 -> 11 */ +#else + p2a_fx = round_fx(L_shl(L_p2a, 13)); /* 27 -16 -> 11 */ +#endif + } + + if ( LE_16(p2a_fx, p2a_th_fx)) + { + p2a_flags_fx[k] = 0; + move16(); + } + } + ELSE + { + p2a_flags_fx[k] = 0; + move16(); + } + + push_indice_fx( hBstr, IND_HQ2_P2A_FLAGS, p2a_flags_fx[k], 1 ); + j = add(j, 1); + } + + return( j ); +} + +/*-------------------------------------------------------------------* + * mdct_spectrum_fine_gain_enc() + * + * + *-------------------------------------------------------------------*/ + +static void mdct_spectrum_fine_gain_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 L_ybuf[], /* i : Q12 : input spectrum */ + Word32 L_y2[], /* i/o: Q12 : decoded spectrum */ + const Word16 band_start[], /* i : Q0 : table of start freq for every subband */ + const Word16 band_end[], /* i : Q0 : table of end freq for every subband */ + const Word16 k_sort[], /* i : Q0 : sort table by band_energy */ + const Word16 bands, /* i : Q0 : nubmber of subbands */ + const Word32 L_qint, /* i : Q29 : */ + const Word16 Ngq, /* i : Q0 : */ + const Word16 gqlevs, /* i : Q0 : quantized level */ + const Word16 gqbits /* i : Q0 : quantized bits */ +) +{ + Word16 i, k; + + Word16 delta_fx, Qdelta; + Word32 L_delta; + Word32 L_q; + + Word16 gain_table_fx[MAX_GQLEVS]; + Word16 Qgt; + Word16 gamma_fx; + Word16 Qgamma; + + Word16 exp_safe; + Word16 exp_normn, exp_normd; + Word16 exp_norm; + + Word32 L_temp; + Word16 temp_lo_fx, temp_hi_fx, temp_fx, temp2_fx; + + Word32 L_Eyy, L_Exy; + /*Word16 QE; */ + + Word16 d_fx; + Word16 dmin_fx; + Word16 imin_fx; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /* Fine gain quantization on only the most significant energy bands */ + + /*delta = qint / gqlevs; */ + exp_normn = norm_l(L_qint); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_s(gqlevs); + delta_fx = div_l(L_shl(L_qint, exp_normn), shl(gqlevs, exp_normd)); + Qdelta = add(sub(exp_normn, exp_normd), 28); /* 29+exp_normn-(exp_normd)-1; */ + L_delta = L_shl(L_deposit_h(delta_fx), sub(13, Qdelta)); + /*q = (-qint + delta) / 2.0f; */ + L_q = L_shr(L_sub(L_delta, L_qint), 1); + + FOR (i = 0; i < gqlevs; i++) + { + /*gain_table[i] = (float) pow (2.0f, q * 0.5f); */ + L_temp = L_shr(L_shr(L_q, 1), sub(29, 16)); + temp_lo_fx = L_Extract_lc(L_temp, &temp_hi_fx); + Qgt = sub(14, temp_hi_fx); + gain_table_fx[i] = extract_l(Pow2(14, temp_lo_fx)); /* Qgt */ + + /*q += delta; */ + L_q = L_add(L_q, L_delta); + gain_table_fx[i] = shl(gain_table_fx[i], sub(14, Qgt)); /* Qgt -> Q14 */ + } + + FOR (k = sub(bands, Ngq); k < bands; k++) + { + /*Eyy = 0.0f; */ + /*Exy = 0.0f; */ + /*for (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) */ + /*{ */ + /* Eyy += y2[i] * y2[i]; */ + /* Exy += ybuf[i] * y2[i]; */ + /*} */ + exp_safe = 4; + move16(); /* 4 is too large. but never happen overflow */ + L_temp = L_deposit_l(0); + FOR (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + L_temp = L_or(L_temp, L_abs(L_y2[i])); + L_temp = L_or(L_temp, L_abs(L_ybuf[i])); + } + exp_norm = norm_l(L_temp); + exp_norm = sub(exp_norm, exp_safe); /* safe_shift */ + + L_Eyy = L_deposit_l(0); + L_Exy = L_deposit_l(0); + /*QE = add(shl(add(Qs-16, exp_norm), 1), 1); //(Qs+exp_norm-16)*2+1; */ + FOR (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + /*Eyy += y2[i] * y2[i]; */ + temp_fx = round_fx(L_shl(L_y2[i], exp_norm)); + L_Eyy = L_mac(L_Eyy, temp_fx, temp_fx); + + /*Exy += ybuf[i] * y2[i]; */ + temp2_fx = round_fx(L_shl(L_ybuf[i], exp_norm)); + L_Exy = L_mac(L_Exy, temp2_fx, temp_fx); + } + + test(); + IF ( L_Eyy > 0x0L && L_Exy > 0x0L ) + { + /*gamma = Exy / Eyy; */ + exp_normn = norm_l(L_Exy); + exp_normn = sub(exp_normn, 1); + exp_normd = norm_l(L_Eyy); +#ifdef BASOP_NOGLOB + gamma_fx = div_l(L_shl_o(L_Exy, exp_normn, &Overflow), round_fx_o(L_shl_o(L_Eyy, exp_normd, &Overflow), &Overflow)); +#else + gamma_fx = div_l(L_shl(L_Exy, exp_normn), round_fx(L_shl(L_Eyy, exp_normd))); +#endif + Qgamma = add(sub(exp_normn, exp_normd), 15); /* exp_normn - (exp_normd-16) - 1; */ + gamma_fx = shl(gamma_fx, sub(14, Qgamma)); /* Qgamma -> Q14 */ + + dmin_fx = 32767; + move16(); + imin_fx = -1; + move16(); + FOR (i = 0; i < gqlevs; i++) + { + d_fx = abs_s (sub(gamma_fx, gain_table_fx[i])); + IF ( LT_16(d_fx, dmin_fx)) + { + dmin_fx = d_fx; + move16(); + imin_fx = i; + move16(); + } + } + + gamma_fx = gain_table_fx[imin_fx]; + move16(); /* Q14 */ + + FOR (i = band_start[k_sort[k]]; i <= band_end[k_sort[k]]; i++) + { + /*y2[i] *= gamma; */ + /* This IF statement for keeping same mantissa evenif y2 is plus or minus */ + IF ( L_y2[i] >= 0x0 ) + { + L_y2[i] = L_shl(Mpy_32_16_1(L_y2[i], gamma_fx), 1); + } + ELSE + { + L_y2[i] = L_negate(L_shl(Mpy_32_16_1(L_abs(L_y2[i]), gamma_fx), 1)); + } + } + } + ELSE + { + imin_fx = 0; + move16(); + } + + push_indice_fx( st_fx->hBstr, IND_HQ2_SUBBAND_GAIN, imin_fx, gqbits ); + } + + return; +} diff --git a/lib_enc/hvq_enc_fx.c b/lib_enc/hvq_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..af93e08abfd748eb8f89f3ab86768489a8d881ee --- /dev/null +++ b/lib_enc/hvq_enc_fx.c @@ -0,0 +1,252 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst.h" +//#include "prot_fx.h" +#include "rom_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +#define HVQ_ENC_NOISE_DELTA ((Word16)3277) /* 0.1 in Q15 */ + +static Word16 quant_lc(const Word16, Word16 *); + + +/*--------------------------------------------------------------------------* + * hvq_enc_fx() + * + * Harmonic VQ encoder + *--------------------------------------------------------------------------*/ + +Word16 hvq_enc_fx( /*o : Consumed bits */ + Encoder_State_fx *st_fx, /*i/o: encoder state structure */ + const Word32 core_brate, /*i : Total bit rate */ + const Word16 hvq_bits, /*i : HVQ bit budget */ + const Word16 Npeaks, /*i : Number of peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *peaks, /* i : Peak pos. / Encoded peak pos. */ + Word32 *nf_gains, /* i/o: Noise fill gains / Quant. nf gains */ + Word16 *noise_level, /* o : Quantized noise level */ + const Word32 *pe_gains, /* i : Peak gains */ + const Word32 *coefs, /* i : spectrum coefficients in Q12 */ + Word32 *coefs_out /* o : encoded spectrum coefficients in Q12 */ +) +{ + const Word32 *pCoefs; + Word16 bin_th,j,i,n; + Word16 nf_cnt; + Word16 q_noise_level_idx[HVQ_BWE_NOISE_BANDS]; + Word16 q_noise_level[HVQ_BWE_NOISE_BANDS]; + Word32 d, nf_mean; + Word32 nf, pe, pe_mean; + Word16 bits_used, nBits; + Word16 lb_nfpe; + UWord16 dontCare; + Word32 acc, numerator, denominator; + Word16 expPeMean, expNfMean, expNfpe, expNfpe3, expo, expo3; + Word16 manPeMean, manNfMean, manNfpe, man; + Word16 tmp16, adjust; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + bits_used = 0; + move16(); + + IF ( LT_32(core_brate, HQ_BWE_CROSSOVER_BRATE)) + { + bin_th = HVQ_THRES_BIN_24k; + move16(); + n = (L_FRAME32k - HVQ_THRES_BIN_24k)/HVQ_BWE_NOISE_BANDS; + move16(); + } + ELSE + { + bin_th = HVQ_THRES_BIN_32k; + move16(); + n = (L_FRAME32k - HVQ_THRES_BIN_32k)/HVQ_BWE_NOISE_BANDS; + move16(); + } + + nf = 800*4096L; /* Q12 */ move32(); + pe = 800*4096L; /* Q12 */ move32(); + pCoefs = &coefs[bin_th]; + + /* Find HB noise level */ + FOR( i = 0; i < HVQ_BWE_NOISE_BANDS; i++ ) + { + nf_cnt = 0; + move16(); + nf_mean = L_deposit_l(0); + pe_mean = L_deposit_l(0); + FOR( j = 0; j < n; j++) + { + d = L_abs(*pCoefs++); /* Q12 */ + + IF( GT_32(d, pe)) + { + /* W*pe + (1 - W)*d = (pe - d)*W + d */ + acc = L_sub(pe, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare); + pe = L_add(acc, d); /* in Q12 and always positive */ + } + ELSE + { + /* W*pe + (1 - W)*d = (pe - d)*W + d */ + acc = L_sub(pe, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare); + pe = L_add(acc, d); /* in Q12 and always positive */ + + IF( GT_32(d, nf)) + { + acc = L_sub(nf, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT1_FX, &acc, &dontCare); + nf = L_add(acc, d); /* in Q12 and always positive */ + } + ELSE + { + acc = L_sub(nf, d); + Mpy_32_16_ss(acc, HVQ_BWE_WEIGHT2_FX, &acc, &dontCare); + nf = L_add(acc, d); /* in Q12 always positive */ + } + nf_mean = L_add(nf_mean, nf); /* in Q12 and always positive */ + nf_cnt = add(nf_cnt, 1); /* Q0 */ + } + +#ifdef BASOP_NOGLOB + pe_mean = L_add_o(pe_mean, pe, &Overflow); /* in Q12 and always positive */ +#else + pe_mean = L_add(pe_mean, pe); /* in Q12 and always positive */ +#endif + } + + IF (pe_mean > 0) + { + expPeMean = norm_l(pe_mean); /* exponent */ + manPeMean = extract_h(L_shl(pe_mean, expPeMean)); /* mantissa */ + expNfMean = norm_l(nf_mean); /* exponent */ + manNfMean = extract_h(L_shl(nf_mean, expNfMean)); /* mantissa */ + + numerator = L_mult0(manNfMean, n); + IF ( nf_cnt > 0 ) + { + denominator = L_mult0(manPeMean, nf_cnt); /* in Q15 */ + } + ELSE + { + denominator = L_mult0(manPeMean, 1); /* in Q15 */ + } + manNfpe = ratio(numerator, denominator, &expo); /* manNfpe in Q14 */ + expNfpe = add(sub(expNfMean, expPeMean), expo); + + tmp16 = mult_r(manNfpe, manNfpe); /* in Q(14+14+1-16) = Q13 */ + tmp16 = mult_r(tmp16, manNfpe); /* in Q(13+14+1-16) = Q12 */ + acc = L_mult(tmp16, HVQ_NFPE_FACTOR_CUBE_FX); /* in Q(12+6+1) = Q19 */ + expNfpe3 = extract_l(L_mult0(expNfpe, 3)); /* Cube operation */ + /* Number of bits required to adjust to Q15 */ + adjust = add(19 - (15 + 16), expNfpe3); /* +16 is due to the following extract_h(). */ +#ifdef BASOP_NOGLOB + noise_level[i] = extract_h(L_shr_o(acc, adjust, &Overflow)); /* noise_level[] in Q15 */ +#else + noise_level[i] = extract_h(L_shr(acc, adjust)); /* noise_level[] in Q15 */ +#endif + q_noise_level_idx[i] = quant_lc( noise_level[i], &q_noise_level[i] ); + } + ELSE + { + q_noise_level_idx[i] = 0; + move16(); + q_noise_level[i] = 0; + move16(); + } + push_indice_fx(st_fx->hBstr, IND_HVQ_BWE_NL, q_noise_level_idx[i], 2 ); + bits_used = add(bits_used, 2); + + noise_level[i] = q_noise_level[i]; /* in Q15 */ + } + + FOR( i = 0; i < HVQ_NF_GROUPS; i ++ ) + { + IF (pe_gains[i] != 0) + { + /* Neither pe_gains[] nor nf_gains[] is zero. */ + man = ratio(nf_gains[i], pe_gains[i], &expo); /* man in Q14 */ + tmp16 = mult_r(man, man); /* in Q(14+14+1-16) = Q13 */ + tmp16 = mult_r(tmp16, man); /* in Q(13+14+1-16) = Q12 */ + acc = L_mult(tmp16, HVQ_LB_NFPE_FACTOR_CUBE_FX); /* in Q(12+9+1) = Q22 */ + expo3 = extract_l(L_mult0(expo, 3)); /* Cube operation. */ + /* Number of bits required to adjust to Q15 */ + adjust = add(22 - (15 + 16), expo3); /* +16 is due to the following extract_h(). */ +#ifdef BASOP_NOGLOB + lb_nfpe = extract_h(L_shr_o(acc, adjust, &Overflow)); /* noise_level[] in Q15 */ +#else + lb_nfpe = extract_h(L_shr(acc, adjust)); /* noise_level[] in Q15 */ +#endif + IF( lb_nfpe > 16384 ) /* in Q15 */ + { + lb_nfpe = 16384; + move16(); + } +#ifdef BASOP_NOGLOB + Mpy_32_16_ss(nf_gains[i], shl_o(lb_nfpe, 1, &Overflow), &nf_gains[i], &dontCare); /* nf_gains[] in Q12 */ +#else + Mpy_32_16_ss(nf_gains[i], shl(lb_nfpe, 1), &nf_gains[i], &dontCare); /* nf_gains[] in Q12 */ +#endif + } + ELSE + { + nf_gains[i] = 0; + move16(); + } + } + nBits = peak_vq_enc_fx( st_fx->hBstr, st_fx->bwidth_fx, coefs, coefs_out, core_brate, sub(hvq_bits, bits_used), + Npeaks, ynrm, R, peaks, &nf_gains[0] ); + bits_used = add(bits_used, nBits); + return bits_used; +} + +/*----------------------------------------------------------------------------- + * quant() + * + * Quantize the noise to one of the levels in {0, 0.1, 0.2, 0.3} + *----------------------------------------------------------------------------*/ +static Word16 quant_lc(const Word16 x, Word16 *qx) +{ + Word16 indx; + + IF (LT_16(x, HVQ_ENC_NOISE_DELTA/2)) + { + indx = 0; + move16(); + *qx = 0; + move16(); + } + ELSE IF (LT_16(x, 3*HVQ_ENC_NOISE_DELTA/2)) + { + indx = 1; + move16(); + *qx = HVQ_ENC_NOISE_DELTA; + move16(); + } + ELSE IF (LT_16(x, 5*HVQ_ENC_NOISE_DELTA/2)) + { + indx = 2; + move16(); + *qx = 2*HVQ_ENC_NOISE_DELTA; + move16(); + } + ELSE + { + indx = 3; + move16(); + *qx = 3*HVQ_ENC_NOISE_DELTA; + move16(); + } + + return indx; +} + diff --git a/lib_enc/igf_enc_fx.c b/lib_enc/igf_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..1efb50d021af87b054f61d33460d65610d787999 --- /dev/null +++ b/lib_enc/igf_enc_fx.c @@ -0,0 +1,1446 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include +#include "options.h" +#include "cnst.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 */ +#include "stat_enc.h" +#include "basop_util.h" + +/**********************************************************************/ /* +write single bit to stream +**************************************************************************/ +static void IGF_write_bit( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *bitCount, /**< in/out: | bit counter */ + Word16 bit /**< in: | value of bit */ +) +{ + IGFCommonFuncsWriteSerialBit(hBstr, bitCount, bit); + +} + +/**********************************************************************/ /* +write bits to stream +**************************************************************************/ +static void IGF_write_bits( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *bitCount, /**< in/out: | bit counter */ + Word16 value, /**< in: | value to be written */ + Word16 bits /**< in: Q0 | number of bits */ +) +{ + Word16 tmp; + + WHILE (bits) + { + bits = sub(bits, 1); + tmp = s_and(value, shl(1, bits)); + IF (tmp == 0) + { + IGF_write_bit(hBstr, bitCount, 0); + } + ELSE + { + IGF_write_bit(hBstr, bitCount, 1); + } + } + + return; +} + + +/**********************************************************************/ /* +envelope estimation +**************************************************************************/ +static void IGF_CalculateEnvelope(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word32 *pMDCTSpectrum, /**< in: Q31 | MDCT spectrum */ + Word16 MDCTSpectrum_e, /**< in: | exponent of MDCT spectrum */ + Word32 *pPowerSpectrum, /**< in: Q31 | MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 PowerSpectrum_e, /**< in: | exponent of MDCT^2 + MDST^2 spectrum, or estimate */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 *swb_offset; + Word16 sfb; /* this is the actual scalefactor band */ + Word16 width; /* this is width in subbands of the actual scalefactor band */ + Word16 tile_idx; + Word16 strt_cpy; + Word16 gain; /* the gain which has to be applied to the source tile to get the destination energy */ + Word16 gain_exp; + Word16 tb; + Word16 zeroNrg; /* Q0 | flag indicating if the signal contains almost no energy */ + Word32 sfbEnergyR[IGF_MAX_SFB]; + Word16 sfbEnergyR_exp[IGF_MAX_SFB]; + Word32 sfbEnergyC[IGF_MAX_SFB]; /* the energy of the destination region of the tile */ + Word16 sfbEnergyC_exp[IGF_MAX_SFB]; + Word32 sfbEnergyTileR[IGF_MAX_SFB]; + Word16 sfbEnergyTileR_exp[IGF_MAX_SFB]; + Word32 sfbEnergyTileC[IGF_MAX_SFB]; /* the energy of the destination region of the tile */ + Word16 sfbEnergyTileC_exp[IGF_MAX_SFB]; + Word32 LFMDCTSpectrum[N_MAX]; + Word16 LFMDCTSpectrum_exp; + Word32 LFPowerSpectrum[N_MAX]; + Word16 tmp; + Word16 tmp_exp; + Word32 L_tmp; + Word16 shift; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /* initialize variables */ + Copy32(pMDCTSpectrum + IGF_START_MN, hInstance->spec_be_igf, hInstance->infoStopLine-IGF_START_MN); + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + swb_offset = hGrid->swb_offset; + move16(); + hInstance->spec_be_igf_e = MDCTSpectrum_e; + move16(); + zeroNrg = 0; + move16(); + + + IF (pPowerSpectrum != NULL) + { + FOR (tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + FOR (sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++) + { + FOR (tb = swb_offset[ sfb ]; tb < swb_offset[ sfb+1 ]; tb++) + { + LFMDCTSpectrum[tb] = pMDCTSpectrum[strt_cpy]; + move32(); + LFPowerSpectrum[tb] = pPowerSpectrum[strt_cpy]; + move32(); + strt_cpy = add(strt_cpy, 1); + } + } + } + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + pPowerSpectrum, + &PowerSpectrum_e, + sfbEnergyC, + sfbEnergyC_exp); + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + LFPowerSpectrum, + &PowerSpectrum_e, + sfbEnergyTileC, + sfbEnergyTileC_exp); + IGFCommonFuncsMDCTSquareSpec(hGrid->startLine, + hGrid->stopLine, + LFMDCTSpectrum, + MDCTSpectrum_e, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + 0); + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + sfbEnergyTileR, + sfbEnergyTileR_exp); + } + ELSE + { + IGFCommonFuncsMDCTSquareSpec(hGrid->startLine, + hGrid->stopLine, + pMDCTSpectrum, + MDCTSpectrum_e, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + 0); + IGFCommonFuncsCalcSfbEnergyPowerSpec(hGrid->startSfb, + hGrid->stopSfb, + hGrid->swb_offset, + LFMDCTSpectrum, + &LFMDCTSpectrum_exp, + sfbEnergyR, + sfbEnergyR_exp); + } + + FOR (tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++) + { + + FOR(sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++) + { + + + width = sub(swb_offset[sfb + 1], swb_offset[sfb]); + L_tmp = 0; + move16(); + gain_exp = 0; + move16(); + + IF (pPowerSpectrum) + { + IF (sfbEnergyTileR[sfb] == 0) + { + sfbEnergyTileR[sfb] = 0x00010000; + move32(); + sfbEnergyTileR_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + IF (sfbEnergyTileC[sfb] == 0) + { + sfbEnergyTileC[sfb] = 0x00010000; + move32(); + sfbEnergyTileC_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + IF (sfbEnergyC[sfb] == 0) + { + sfbEnergyC[sfb] = 0x00010000; + move32(); + sfbEnergyC_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + +#ifdef BASOP_NOGLOB + BASOP_Util_Divide_MantExp(round_fx_o(sfbEnergyTileR[sfb], &Overflow),sfbEnergyTileR_exp[sfb], width, 15, &gain, &gain_exp); + BASOP_Util_Divide_MantExp(round_fx_o(sfbEnergyC[sfb], &Overflow), sfbEnergyC_exp[sfb], round_fx_o(sfbEnergyTileC[sfb], &Overflow), sfbEnergyTileC_exp[sfb], &tmp, &tmp_exp); +#else + BASOP_Util_Divide_MantExp(round_fx(sfbEnergyTileR[sfb]), + sfbEnergyTileR_exp[sfb], + width, + 15, + &gain, + &gain_exp); + BASOP_Util_Divide_MantExp(round_fx(sfbEnergyC[sfb]), + sfbEnergyC_exp[sfb], + round_fx(sfbEnergyTileC[sfb]), + sfbEnergyTileC_exp[sfb], + &tmp, + &tmp_exp); +#endif + L_tmp = L_mult(gain, tmp); + gain_exp = add(gain_exp, tmp_exp); + + + } + ELSE + { + IF(sfbEnergyR[sfb] == 0) + { + sfbEnergyR[sfb] = 0x00010000; + move32(); + sfbEnergyR_exp[sfb] = 0; + move16(); + zeroNrg = 1; + move16(); + } + BASOP_Util_Divide_MantExp(round_fx(sfbEnergyR[sfb]), + sfbEnergyR_exp[sfb], + width, + 15, + &gain, + &gain_exp); + L_tmp = L_deposit_h(gain); + + + } + + /* gain = 0.5f + (float)((2.885390081777927f * log(gain) + 16.f)); */ + L_tmp = BASOP_Util_Log2(L_tmp); + L_tmp = L_add(L_tmp, L_deposit_h(shl(gain_exp, 15-6))); + shift = norm_l(L_tmp); +#ifdef BASOP_NOGLOB + gain = round_fx_o(L_shl_o(L_tmp, shift, &Overflow), &Overflow); +#else + gain = round_fx(L_shl(L_tmp, shift)); +#endif + gain_exp = sub(7, shift); + gain_exp = BASOP_Util_Add_MantExp(gain, gain_exp, 32767/*16 Q11*/, 4, &gain); + gain_exp = BASOP_Util_Add_MantExp(gain, gain_exp, 0x4000, 0, &gain); + gain = shr(gain, s_min(sub(15, gain_exp), 15)); + + if (gain > 91) + { + gain = s_min(gain, 91); /* 13+15+63, see arithocde encode residual */ + } + if (gain < 0) + { + gain = s_max(gain, 0); + } + + /* set gain to zero if the signal contains too less energy */ + if (zeroNrg != 0) + { + gain = 0; + move16(); + } + + hPrivateData->igfScfQuantized[sfb] = gain; + move16(); + } + } + + return; +} + +/**********************************************************************/ /* +writes IGF SCF values +**************************************************************************/ +static void IGF_WriteEnvelope( /**< out: Q0 | number of bits writen */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + const Word16 igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 isIndepFlag, /**< in: Q0 | if 1 frame is independent, 0 = frame is coded with data from previous frame */ + Word16 *igfAllZero /**< in: Q0 | returns 1 if all IGF scfs are zero, else 0 */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 sfb; + + *igfAllZero = 1; + move16(); + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + FOR (sfb = hGrid->startSfb; sfb < hGrid->stopSfb; sfb++) + { + IF (hPrivateData->igfScfQuantized[sfb] != 0) + { + *igfAllZero = 0; + move16(); + BREAK; + } + } + + IF (*igfAllZero != 0) + { + IGF_write_bit(hBstr, pBitOffset, 1); + IF (NULL == hBstr) + { + IGFSCFEncoderSaveContextState_fx(&hPrivateData->hIGFSCFArithEnc, igfGridIdx); + } + IGFSCFEncoderReset_fx(&hPrivateData->hIGFSCFArithEnc); + IF (NULL == hBstr) + { + IGFSCFEncoderRestoreContextState_fx(&hPrivateData->hIGFSCFArithEnc, igfGridIdx); + } + } + ELSE + { + IGF_write_bit(hBstr, pBitOffset, 0); + IF (NULL == hBstr) + { + IGFSCFEncoderSaveContextState_fx(&hPrivateData->hIGFSCFArithEnc, igfGridIdx); + } + + *pBitOffset = IGFSCFEncoderEncode_fx(&hPrivateData->hIGFSCFArithEnc, hBstr, *pBitOffset, &hPrivateData->igfScfQuantized[hGrid->startSfb], igfGridIdx, isIndepFlag); + move16(); + + IF (NULL == hBstr) + { + IGFSCFEncoderRestoreContextState_fx(&hPrivateData->hIGFSCFArithEnc, igfGridIdx); + } + } + +} + +/**********************************************************************/ /* +identifies significant spectral content +**************************************************************************/ +static void IGF_ErodeSpectrum(Word16 *highPassEner_exp, /**< out: | exponent of highPassEner */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word32 *pSpectrum, /**< in/out: | MDCT spectrum */ + Word32 *pPowerSpectrum, /**< in/out: | power spectrum */ + Word16 pPowerSpectrum_exp, /**< in: | exponent of power spectrum */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 i; + Word16 igfBgn; + Word16 igfEnd; + Word32 highPassEner; /* Q31 */ + Word32 lastLine; + Word32 nextLine; + Word32 L_c; + Word32 highPassEner_Ovfl; + Word16 s; + Word16 tmploop; + Word16 *swb_offset; + Word16 sfb; + Word16 startSfb; + Word16 stopSfb; + Word16 line; + Word16 flag; + Word16 *igfScaleF; + Word16 tmp; + Word32 L_tmp; + +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + Flag Carry = 0; +#endif + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + igfBgn = hGrid->startLine; + move16(); + igfEnd = hGrid->stopLine; + move16(); + swb_offset = hGrid->swb_offset; + move16(); + startSfb = hGrid->startSfb; + move16(); + stopSfb = hGrid->stopSfb; + move16(); + igfScaleF = hPrivateData->igfScfQuantized; + move16(); + *highPassEner_exp = 0; + move16(); + highPassEner = 0; + move32(); + + IF (NULL == pPowerSpectrum) + { + FOR (i = igfBgn; i< hGrid->infoGranuleLen; i++) + { + pSpectrum[i] = L_deposit_l(0); + } + return; + } + + IF (igfBgn > 0) + { + L_c = 0; move32(); + FOR (i = 0; i < igfBgn; i++) + { + Carry = 0; +#ifdef BASOP_NOGLOB + highPassEner = L_add_co(highPassEner, Mpy_32_16_1(pPowerSpectrum[i], shl(i,4)/*Q4*/)/*Q20, pPowerSpectrum_exp*/, &Carry, &Overflow); +#else /* BASOP_NOGLOB */ + highPassEner = L_add_c(highPassEner, Mpy_32_16_1(pPowerSpectrum[i], shl(i,4)/*Q4*/)/*Q20, pPowerSpectrum_exp*/); +#endif /* BASOP_NOGLOB */ + Overflow = 0; +#ifdef BASOP_NOGLOB + L_c = L_macNs_co(L_c, 0, 0, &Carry, &Overflow); +#else /* BASOP_NOGLOB */ + L_c = L_macNs(L_c, 0, 0); +#endif /* BASOP_NOGLOB */ + } + + highPassEner = norm_llQ31(L_c, highPassEner, highPassEner_exp); /*Q20, highPassEner_exp*/ + *highPassEner_exp = add(*highPassEner_exp, pPowerSpectrum_exp); + test(); + test(); + if ( NE_16(hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_9600)&& + NE_16(hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_RF_SWB_13200) && + NE_16(hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_13200 ) ) + { + igfBgn = shl(igfBgn, 1); + } + highPassEner = L_deposit_l(BASOP_Util_Divide3216_Scale(highPassEner/*Q20, highPassEner_exp*/, igfBgn /*Q0*/,&s)); /*Q15, highPassEner_exp+11-16+s*/ + *highPassEner_exp = add(add(*highPassEner_exp,s),12 - 16 + (31 - 15)); /*Q15->Q31,highPassEner_exp*/ + lastLine = pSpectrum[i - 1]; + move32(); + nextLine = 0; + move32(); + + /* May overflow - just for threshold comparison */ + /* negate because the negated may be 1 larger in abs, */ + /* so whenever compared to the negation of a maximum possible pPowerspectrum, it is still larger */ +#ifdef BASOP_NOGLOB + highPassEner_Ovfl = L_shl_o(L_negate(highPassEner), sub(*highPassEner_exp, pPowerSpectrum_exp), &Overflow); + L_tmp = L_add_o(pPowerSpectrum[i - 1], highPassEner_Ovfl, &Overflow); +#else + BASOP_SATURATE_WARNING_OFF_EVS + highPassEner_Ovfl = L_shl(L_negate(highPassEner), sub(*highPassEner_exp, pPowerSpectrum_exp)); + L_tmp = L_add(pPowerSpectrum[i - 1], highPassEner_Ovfl); + BASOP_SATURATE_WARNING_ON_EVS +#endif + + if (L_tmp >= 0) + { + nextLine = pSpectrum[i]; + move32(); + } + tmploop = sub(igfEnd,1); + FOR (/*i*/; i < tmploop; i++) + { + /* May overflow - just for threshold comparison */ + BASOP_SATURATE_WARNING_OFF_EVS + L_tmp = L_add(pPowerSpectrum[i], highPassEner_Ovfl); + BASOP_SATURATE_WARNING_ON_EVS + + IF (L_tmp < 0) + { + lastLine = pSpectrum[i]; + move32(); + pSpectrum[i] = nextLine; + move32(); + nextLine = 0; + move32(); + } + ELSE + { + pSpectrum[i-1] = lastLine; + move32(); + lastLine = pSpectrum[i]; + move32(); + nextLine = pSpectrum[i+1]; + move32(); + } + } + + /* May overflow - just for threshold comparison */ + BASOP_SATURATE_WARNING_OFF_EVS + L_tmp = L_add(pPowerSpectrum[i], highPassEner_Ovfl); + BASOP_SATURATE_WARNING_ON_EVS + IF (L_tmp < 0) + { + pSpectrum[i] = L_deposit_l(0); + } + } + + /* delete spectrum above igfEnd: */ + FOR (i = igfEnd; i < hGrid->infoGranuleLen; i++) + { + pSpectrum[i] = L_deposit_l(0); + pPowerSpectrum[i] = L_deposit_l(0); + } + + FOR (sfb = startSfb; sfb < stopSfb; sfb++) + { + flag = 0; + move16(); + FOR (line = swb_offset[sfb]; line < swb_offset[sfb+1]; line++) + { + if (pSpectrum[line] != 0) + { + flag = 1; + move16(); + } + } + tmp = igfScaleF[sfb]; + move16(); + if(flag) + { + tmp = sub(igfScaleF[sfb], 1); + } + if (igfScaleF[sfb]) + { + igfScaleF[sfb] = tmp; + move16(); + } + } + +} + +/**********************************************************************/ /* +crest factor calculation +**************************************************************************/ +static Word16 IGF_getCrest( /**< out: Q15| crest factor */ + Word16 *crest_exp, /**< out: | exponent of crest factor */ + const Word32 *powerSpectrum, /**< in: Q31 | power spectrum */ + const Word16 powerSpectrum_exp, /**< in: | exponent of power spectrum */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ +) +{ + Word16 i; + Word16 x; + Word16 s; + Word32 x_eff32; + Word16 x_max; + Word16 crest; + Word16 tmp; + Word32 tmp32; + + x_eff32 = 0; move32(); + x_max = 0; + move16(); + crest = 16384/*.5f Q15*/; + move16(); + *crest_exp = 1; + move16(); + + FOR (i = start; i < stop; i++) + { + /*x = max(0, (int)(log(powerSpectrum[i]) * INV_LOG_2));*/ + + /*see IGF_getSFM for more comment */ + x = sub(sub(powerSpectrum_exp, norm_l(powerSpectrum[i])), 1); /*Q0*/ + if (powerSpectrum[i] == 0) /*special case: energy is zero*/ + { + x = 0; + move16(); + } + x = s_max(0, x); + x_eff32 = L_mac0(x_eff32, x ,x); /*Q0*/ + x_max = s_max(x_max, x); /*Q0*/ + } + + /*x_eff /= (stop - start);*/ + x_eff32 = BASOP_Util_Divide3216_Scale(x_eff32, sub(stop,start), &s); /*Q-1, s*/ + s = add(s, 32); /*make x_eff Q31*/ + + /*trunkate to int*/ + x_eff32 = L_shr(x_eff32, sub(31, s)); + x_eff32 = L_shl(x_eff32, sub(31, s)); + + test(); + IF (x_eff32 > 0 && x_max > 0) + { + /*crest = max(1.f, (float)x_max/sqrt(x_eff));*/ + tmp32 = ISqrt32(x_eff32, &s); /*Q31, s*/ + tmp32 = Mpy_32_16_1(tmp32/*Q31, s*/, x_max/*Q0*/); /*Q16, s*/ + i = norm_l(tmp32); + tmp32 = L_shl(tmp32, i); /*Q31, s-i+15*/ + crest = extract_h(tmp32); + *crest_exp = add(sub(s, i), 15); + + /* limit crest factor to a lower bound of 1, may overflow */ + BASOP_SATURATE_WARNING_OFF_EVS + tmp = shl(-1, sub(15, *crest_exp)); /* build negative threshold */ + tmp = add(crest, tmp); + BASOP_SATURATE_WARNING_ON_EVS + if (tmp < 0) + { + crest = 1; + move16(); + } + if (tmp < 0) + { + *crest_exp = 15; + move16(); + } + } + + return crest; +} + +/************************************************************************* +calculates spectral flatness measurment +**************************************************************************/ +static Word16 IGF_getSFM( /**< out: Q15| SFM value */ + Word16 *SFM_exp, /**< out: | exponent of SFM Factor */ + const Word32 *energy, /**< in: Q31| energies */ + const Word16 *energy_exp, /**< in: | exponent of energies */ + const Word16 start, /**< in: Q0 | start subband index */ + const Word16 stop /**< in: Q0 | stop subband index */ +) +{ + Word16 n,i, s; + Word32 num; + Word32 denom; + Word16 denom_exp; + Word16 invDenom_exp, numf_exp; + Word16 numf; + Word32 SFM32; + Word32 L_c; + Word16 invDenom, SFM; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + Flag Carry = 0; +#endif + + L_c = 0; move32(); + num = 0; move32(); + denom = L_shr(2147483 /*0,001 in Q31 - float is "1", here*/,s_min(*energy_exp, 31)); + denom = L_max(denom, 1); + *SFM_exp = 0; + move16(); + SFM = 32767/*1.0f Q15*/; + move16(); + + FOR (i = start; i < stop; i++) + { + /*ln(x * 2^-Qx * 2^xExp) = ln(x) - Qx + xExp*/ + + /* n = sub(sub(31,norm_l(tmp32)),1); */ /*<- ld */ + /* n = sub(n,31); */ /*<- -Qx */ + /* n = add(n,*energy_exp); */ /*<- +xExp */ + + n = sub(sub(*energy_exp, norm_l(energy[i])), 1); /*<-- short form*/ + + if (energy[i] == 0) /*special case: energy is zero*/ + { + n = 0; + move16(); + } + + n = s_max(0, n); + num = L_add(num, L_deposit_l(n)); /*Q0*/ + + Carry = 0; +#ifdef BASOP_NOGLOB + denom = L_add_co(energy[i], denom, &Carry, &Overflow); +#else /* BASOP_NOGLOB */ + denom = L_add_c(energy[i], denom); +#endif /* BASOP_NOGLOB */ + Overflow = 0; + +#ifdef BASOP_NOGLOB + L_c = L_macNs_co(L_c, 0, 0, &Carry, &Overflow); +#else /* BASOP_NOGLOB */ + L_c = L_macNs(L_c, 0, 0); +#endif + } + + denom = norm_llQ31(L_c, denom, &denom_exp); /*Q31*/ + denom_exp = add(denom_exp, *energy_exp); + + /* calculate SFM only if signal is present */ + IF (denom != 0) + { + /*numf = (float)num / (float)(stop - start);*/ + numf = BASOP_Util_Divide3216_Scale(num, /*Q0*/ + sub(stop,start), /*Q0*/ + &s); /*Q-1 s*/ + numf_exp = add(s,16); /*-> numf Q15 numf_exp*/ + /*denom /= (float)(stop - start);*/ + /*return ((float)pow(2.0, numf + 0.5f) / denom);*/ + + /*SFM= ((float)pow(2.0, numf + 0.5f) * invDenom);*/ + invDenom = BASOP_Util_Divide3232_uu_1616_Scale(L_deposit_l(sub(stop, start)) /*Q0*/, + denom /*Q31, denom_exp*/, + &s); /*Q-16, s-denom_exp*/ + invDenom_exp = add(sub(s, denom_exp), 31); /*invDenom: Q15, invDenom_exp*/ + + /*add .5f to numf*/ + SFM32 = L_add(L_shl(L_deposit_l(numf), numf_exp) /*16Q15*/,16384l/*.5f Q15*/); /*16Q15*/ + s = norm_l(SFM32); + SFM32 = L_shl(SFM32, s); + s = sub(16, s); /*SFM32(numf) is Q31 now*/ + + /*do the pow2 and the mult*/ + SFM32 = BASOP_util_Pow2(SFM32, s, &s); + SFM32 = Mpy_32_16_1(SFM32, invDenom); + *SFM_exp = add(s, invDenom_exp); + + /*Transform to Q15*/ + s = norm_l(SFM32); + SFM = round_fx(L_shl(SFM32, s)); + *SFM_exp = sub(*SFM_exp, s); + + /**SFM_exp = s_min(*SFM_exp, 0);*/ + IF (*SFM_exp > 0) + { + *SFM_exp = 0; + move16(); + SFM = 32767/*1.0f Q15*/; + move16(); + } + } + + return SFM /*Q15*/; +} + +/**********************************************************************/ /* +calculates the IGF whitening levels by SFM and crest +**************************************************************************/ +static void IGF_Whitening(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word32 *powerSpectrum, /**< in: Q31 | MDCT/MDST power spectrum */ + const Word16 powerSpectrum_exp, /**< in: | exponent of powerspectrum */ + const Word16 igfGridIdx, /**< in: Q0 | IGF grid index */ + Word16 isTransient, /**< in: Q0 | boolean, indicating if transient is detected */ + Word16 last_core_acelp /**< in: Q0 | indictaor if last frame was acelp coded */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 p; /*Q0*/ + Word16 tmp; + Word16 SFM; + Word16 crest; + Word16 SFM_exp; + Word16 crest_exp; + Word16 s; + Word32 tmp32; + Word32 SFM32; + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + + IF (igfGridIdx != IGF_GRID_LB_NORM) + { + FOR (p = 0; p < hGrid->nTiles; p++) + { + /* reset filter */ + hPrivateData->prevSFM_FIR[p] = L_deposit_l(0); + hPrivateData->prevSFM_IIR[p] = 0; + move16(); + + /* preset values: */ + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_OFF; + move16(); + } + } + FOR (p = 0; p < IGF_MAX_TILES; p++) + { + /* update prev data: */ + hPrivateData->igfPrevWhiteningLevel[p] = hPrivateData->igfCurrWhiteningLevel[p]; + move16(); + /* preset values: */ + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_OFF; + move16(); + } + + IF (!s_or(isTransient, hPrivateData->wasTransient)) + { + IF (powerSpectrum) + { + Word16 nT = hGrid->nTiles; + SWITCH (hPrivateData->igfInfo.bitRateIndex) + { + case IGF_BITRATE_WB_9600: + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_SWB_16400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + nT = sub(nT, 1); + BREAK; + default: + BREAK; + } + FOR (p = 0; p < nT; p++) + { + /*tmp = IGF_getSFM(powerSpectrum, hGrid->tile[p], hGrid->tile[p+1]) / IGF_getCrest(powerSpectrum, hGrid->tile[p], hGrid->tile[p+1]);*/ + SFM = IGF_getSFM(&SFM_exp, powerSpectrum, &powerSpectrum_exp, hGrid->tile[p], hGrid->tile[p + 1]); + crest = IGF_getCrest(&crest_exp, powerSpectrum, powerSpectrum_exp, hGrid->tile[p], hGrid->tile[p + 1]); + + tmp = BASOP_Util_Divide1616_Scale(SFM, crest, &s); /* Q15 */ + s = add(s, sub(SFM_exp, crest_exp)); + tmp32 = L_shl(L_deposit_l(tmp)/*16Q15, s*/,add(s,1)); /* 15Q16 */ + + test(); + IF (last_core_acelp || hPrivateData->wasTransient) + { + hPrivateData->prevSFM_FIR[p] = tmp32; /* 15Q16 */ move32(); + hPrivateData->prevSFM_IIR[p] = shr(tmp, 2); /* 2Q13 */ move16(); + } + + /*SFM = tmp + hPrivateData->prevSFM_FIR[p] + 0.5f * hPrivateData->prevSFM_IIR[p];*/ + SFM32 = L_add(tmp32,hPrivateData->prevSFM_FIR[p]); + SFM32 = L_mac0(SFM32,hPrivateData->prevSFM_IIR[p]/*Q13*/,4/*.5f Q3*/);/*15Q16*/ + + BASOP_SATURATE_WARNING_OFF_EVS + /*SFM = min(2.7f, SFM);*/ + /*Overflow possible in shift, intended*/ + SFM = s_min(22118/*2.7f Q13*/,extract_h(L_shr(SFM32,16-29)/*->Q29*/)/*->Q13*/ ); + BASOP_SATURATE_WARNING_ON_EVS + + hPrivateData->prevSFM_FIR[p] = tmp32; /*15Q16*/ move32(); + hPrivateData->prevSFM_IIR[p] = SFM; + move16(); + + IF (GT_16(SFM , hGrid->whiteningThreshold[1][p])) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_STRONG; + move16(); + } + ELSE IF (GT_16(SFM , hGrid->whiteningThreshold[0][p])) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_MID; + move16(); + } + } + SWITCH (hPrivateData->igfInfo.bitRateIndex) + { + case IGF_BITRATE_WB_9600: + case IGF_BITRATE_RF_WB_13200: + case IGF_BITRATE_RF_SWB_13200: + case IGF_BITRATE_SWB_9600: + case IGF_BITRATE_SWB_16400: + case IGF_BITRATE_SWB_24400: + case IGF_BITRATE_SWB_32000: + case IGF_BITRATE_FB_16400: + case IGF_BITRATE_FB_24400: + case IGF_BITRATE_FB_32000: + move16(); + hPrivateData->igfCurrWhiteningLevel[hGrid->nTiles - 1] = hPrivateData->igfCurrWhiteningLevel[hGrid->nTiles - 2]; + BREAK; + default: + BREAK; + } + } + ELSE + { + FOR (p = 0; p < hGrid->nTiles; p++) + { + hPrivateData->igfCurrWhiteningLevel[p] = IGF_WHITENING_MID; + move16(); + } + } + } + ELSE + { + /* reset filter */ + FOR (p = 0; p < IGF_MAX_TILES; p++) + { + hPrivateData->prevSFM_FIR[p] = L_deposit_l(0); + hPrivateData->prevSFM_IIR[p] = 0; + move16(); + } + } + hPrivateData->wasTransient = isTransient; + move16(); + +} + +/**********************************************************************/ /* +write whitening levels into bitstream +**************************************************************************/ +static void IGF_WriteWhiteningTile( /**< out: Q0 | number of bits written */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + Word16 whiteningLevel /**< in: Q0 | whitening levels to write */ +) +{ + IF (EQ_32(whiteningLevel, IGF_WHITENING_MID)) + { + IGF_write_bits(hBstr, pBitOffset, 0, 1); + } + ELSE + { + IGF_write_bits(hBstr, pBitOffset, 1, 1); + IF (EQ_32(whiteningLevel , IGF_WHITENING_OFF)) + { + IGF_write_bits(hBstr, pBitOffset, 0, 1); + } + ELSE + { + IGF_write_bits(hBstr, pBitOffset, 1, 1); + } + } +} + +/**********************************************************************/ /* +writes the whitening levels +**************************************************************************/ +static void IGF_WriteWhiteningLevels( /**< out: Q0 | total number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF encoder */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + const Word16 igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 isIndepFlag /**< in: Q0 | if 1 frame is independent, 0 = frame is coded with data from previous frame */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 p; + Word16 nTiles; + Word16 isSame; + Word32 tmp32; + + + isSame = 1; + move16(); + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + nTiles = hGrid->nTiles; + move16(); + + IF (isIndepFlag) + { + isSame = 0; + move16(); + } + ELSE + { + p = 0; + move16(); + tmp32 = 0; + move32(); + + WHILE ((LT_16(p, nTiles))&&(tmp32==0)) + { + test(); + tmp32 = L_sub(hPrivateData->igfCurrWhiteningLevel[p] , hPrivateData->igfPrevWhiteningLevel[p]); + if (tmp32 != 0) + { + isSame = 0; + move16(); + } + p++; + } + } + IF (isSame) + { + IGF_write_bits(hBstr, pBitOffset, 1, 1); + } + ELSE + { + IF (!isIndepFlag) + { + IGF_write_bits(hBstr, pBitOffset, 0, 1); + } + IGF_WriteWhiteningTile(hBstr, pBitOffset, hPrivateData->igfCurrWhiteningLevel[0]); + p = 1; + move16(); + tmp32 = 0; + move32(); + if (LT_16(p, nTiles)) + { + isSame = 1; + move16(); + } + + WHILE ((LT_16(p, nTiles))&&(tmp32==0)) + { + test(); + tmp32 = L_sub(hPrivateData->igfCurrWhiteningLevel[p] , hPrivateData->igfCurrWhiteningLevel[p - 1]); + if (tmp32 != 0) + { + isSame = 0; + move16(); + } + p++; + } + + IF (!isSame) + { + IGF_write_bits(hBstr, pBitOffset, 1, 1); + FOR (p = 1; p < nTiles; p++) + { + IGF_WriteWhiteningTile(hBstr, pBitOffset, hPrivateData->igfCurrWhiteningLevel[p]); + } + } + ELSE + { + IGF_write_bits(hBstr, pBitOffset, 0, 1); + } + } + +} + +/**********************************************************************/ /* +write flattening trigger +**************************************************************************/ +static void IGF_WriteFlatteningTrigger( /**< out: | number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *pBitOffset /**< in: | ptr to bitOffset counter */ +) +{ + Word16 flatteningTrigger; + + + flatteningTrigger = hInstance->flatteningTrigger; + move16(); + + IGF_write_bits(hBstr, pBitOffset, flatteningTrigger, 1); + +} + +/**********************************************************************/ /* +updates the start/stop frequency of IGF according to igfGridIdx +**************************************************************************/ +static void IGF_UpdateInfo(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word16 igfGridIdx /**< in: Q0 | IGF grid index */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + + + hPrivateData = &hInstance->igfData; + hGrid = &hPrivateData->igfInfo.grid[igfGridIdx]; + hInstance->infoStartFrequency = hGrid->startFrequency; + move16(); + hInstance->infoStopFrequency = hGrid->stopFrequency; + move16(); + hInstance->infoStartLine = hGrid->startLine; + move16(); + hInstance->infoStopLine = hGrid->stopLine; + move16(); + + return; +} + +/**********************************************************************/ /* +IGF bitsream writer +**************************************************************************/ +Word16 IGFEncWriteBitstream_fx( /**< out: | number of bits written per frame */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 *pBitOffset, /**< in: | ptr to bitOffset counter */ + const Word16 igfGridIdx, /**< in: Q0 | igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 isIndepFlag /**< in: Q0 | if 1 frame is independent, 0 = frame is coded with data from previous frame */ +) +{ + Word16 igfAllZero; + Word16 startBitCount; + + + startBitCount = *pBitOffset; + move16(); + hInstance->infoTotalBitsPerFrameWritten = 0; + move16(); + + if (isIndepFlag) + { + hInstance->infoTotalBitsWritten = 0; + move16(); + } + + IGF_WriteEnvelope(hInstance, /* i: instance handle of IGF Encoder */ + hBstr, /* i: encoder state */ + pBitOffset, /* i: ptr to bitOffset counter */ + igfGridIdx, /* i: igf grid index see definition of IGF_GRID_IDX for details */ + isIndepFlag, /* i: if 1 frame is independent, 0 = frame is coded with data from previous frame */ + &igfAllZero); /* o: *igfAllZero */ + + IGF_WriteWhiteningLevels(hInstance, /* i: instance handle of IGF Encoder */ + hBstr, /* i: encoder state */ + pBitOffset, /* i: ptr to bitOffset counter */ + igfGridIdx, /* i: igf grid index see definition of IGF_GRID_IDX for details */ + isIndepFlag); /* i: if 1 frame is independent, 0 = frame is coded with data from previous frame */ + + IGF_WriteFlatteningTrigger(hInstance, /* i: instance handle of IGF Encoder */ + hBstr, /* i: encoder state */ + pBitOffset); /* i: ptr to bitOffset counter */ + + hInstance->infoTotalBitsPerFrameWritten = sub(*pBitOffset, startBitCount); + hInstance->infoTotalBitsWritten = add(hInstance->infoTotalBitsWritten, hInstance->infoTotalBitsPerFrameWritten); + + return hInstance->infoTotalBitsPerFrameWritten; +} + +/**********************************************************************/ /* +sets the IGF mode according to given bitrate +**************************************************************************/ +void IGFEncSetMode_fx( + const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word32 total_brate, /* i : encoder total bitrate */ + const Word16 bwidth, /* i : encoder audio bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + Word16 i; + + hPrivateData = &hIGFEnc->igfData; + hPrivateData->igfBitstreamBits = 0; + move16(); + set16_fx(hPrivateData->igfScfQuantized, 0, IGF_MAX_SFB); + set16_fx(hPrivateData->igfCurrWhiteningLevel, 0, IGF_MAX_TILES); + set16_fx(hPrivateData->igfPrevWhiteningLevel, 0, IGF_MAX_TILES); + FOR( i = 0; i < IGF_BITBUFSIZE /8; i++) + { + hPrivateData->igfBitstream[i] = 0; + move16(); + } + hPrivateData->wasTransient = 0; + move16(); + set32_fx(hPrivateData->prevSFM_FIR, 0, IGF_MAX_TILES); + set16_fx(hPrivateData->prevSFM_IIR, 0, IGF_MAX_TILES); + + IF (IGFCommonFuncsIGFConfiguration(total_brate, bwidth, element_mode, &hPrivateData->igfInfo, rf_mode) != 0) + { + IGFSCFEncoderOpen_fx(&hPrivateData->hIGFSCFArithEnc, &hPrivateData->igfInfo, total_brate, bwidth, element_mode, rf_mode); + + hIGFEnc->infoSamplingRate = hPrivateData->igfInfo.sampleRate; + move32(); + hIGFEnc->infoStartFrequency = hPrivateData->igfInfo.grid[0].startFrequency; + move16(); + hIGFEnc->infoStopFrequency = hPrivateData->igfInfo.grid[0].stopFrequency; + move16(); + hIGFEnc->infoStartLine = hPrivateData->igfInfo.grid[0].startLine; + move16(); + hIGFEnc->infoStopLine = hPrivateData->igfInfo.grid[0].stopLine; + move16(); + } + ELSE + { + /* IGF configuration failed -> error! */ + hIGFEnc->infoSamplingRate = 0; + move32(); + hIGFEnc->infoStartFrequency = -1; + move16(); + hIGFEnc->infoStopFrequency = -1; + move16(); + hIGFEnc->infoStartLine = -1; + move16(); + hIGFEnc->infoStopLine = -1; + move16(); + fprintf(stderr,"IGFEncSetMode_fx: initialization error!\n"); + } + + /* reset remaining variables */ + hIGFEnc->infoTotalBitsWritten = 0; + move16(); + hIGFEnc->infoTotalBitsPerFrameWritten = 0; + move16(); + hIGFEnc->flatteningTrigger = 0; + move16(); + hIGFEnc->spec_be_igf_e = 0; + move16(); + hIGFEnc->tns_predictionGain = 0; + move16(); + set32_fx(hIGFEnc->spec_be_igf, 0, N_MAX_TCX-IGF_START_MN); + return; +} +#ifdef IVAS_CODE_BITSTREAM + +/*-------------------------------------------------------------------* + * pack_bit() + * + * insert a bit into packed octet + *-------------------------------------------------------------------*/ + +static void pack_bit( + const int16_t bit, /* i : bit to be packed */ + uint8_t** pt, /* i/o: pointer to octet array into which bit will be placed */ + uint8_t* omask /* i/o: output mask to indicate where in the octet the bit is to be written */ +) +{ + if (*omask == 0x80) + { + **pt = 0; + } + + if (bit != 0) + { + **pt = **pt | *omask; + } + + *omask >>= 1; + if (*omask == 0) + { + *omask = 0x80; + (*pt)++; + } + + return; +} +/*-------------------------------------------------------------------* + * IGFEncConcatenateBitstream_fx() + * + * IGF bitstream concatenation for TCX10 modes + *-------------------------------------------------------------------*/ + +void IGFEncConcatenateBitstream_fx( + const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ + const int16_t bsBits, /* i : number of IGF bits written to list of indices */ + BSTR_ENC_HANDLE hBstr /* i/o: bitstream handle */ +) +{ + int16_t i; + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + Indice* ind_list; + uint8_t* pFrame; /* byte array with bit packet and byte aligned coded speech data */ + int16_t* pFrame_size; /* number of bits in the binary encoded access unit [bits] */ + int16_t k, nb_bits_written; + int32_t imask; + uint8_t omask; + + hPrivateData = &hIGFEnc->igfData; + + ind_list = &hBstr->ind_list[hBstr->nb_ind_tot - bsBits]; /* here, we assume that each bit has been written as a single indice */ + pFrame = hPrivateData->igfBitstream; + pFrame_size = &hPrivateData->igfBitstreamBits; + nb_bits_written = 0; + + omask = (0x80 >> (*pFrame_size & 0x7)); + pFrame += *pFrame_size >> 3; + + /* bitstream packing (conversion of individual indices into a serial stream) */ + for (i = 0; i < bsBits; i++) + { + if (ind_list[i].nb_bits > 0) + { + /* mask from MSB to LSB */ + imask = 1 << (ind_list[i].nb_bits - 1); + + /* write bit by bit */ + for (k = 0; k < ind_list[i].nb_bits; k++) + { + pack_bit(ind_list[i].value & imask, &pFrame, &omask); + imask >>= 1; + } + nb_bits_written += ind_list[i].nb_bits; + + /* delete the indice */ + ind_list[i].nb_bits = -1; + } + } + + *pFrame_size += nb_bits_written; + + /* update list of indices */ + hBstr->nb_ind_tot -= bsBits; + hBstr->nb_bits_tot -= nb_bits_written; + + return; +} +#else +/**********************************************************************/ /* +IGF bitsream concatenation for TCX10 modes +**************************************************************************/ +void IGFEncConcatenateBitstream_fx(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + Word16 bsBits, /**< in: Q0 | number of IGF bits written to list of indices */ + Word16 *next_ind, /**< in/out: | pointer to actual bit indice */ + Word16 *nb_bits, /**< in/out: | total number of bits already written */ + Indice *ind_list_fx /**< in: | pointer to list of indices */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + *next_ind = *next_ind - bsBits; + + indices_to_serial_generic( + &ind_list_fx[*next_ind], + bsBits, + hPrivateData->igfBitstream, + &hPrivateData->igfBitstreamBits + ); + + *nb_bits = sub(*nb_bits, bsBits); + + return; +} +#endif +/**********************************************************************/ /* +IGF reset bitsream bit counter for TCX10 modes +**************************************************************************/ +void IGFEncResetTCX10BitCounter_fx(const IGF_ENC_INSTANCE_HANDLE hInstance /**< in: | instance handle of IGF Encoder */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + + hPrivateData = &hInstance->igfData; + hPrivateData->igfBitstreamBits = 0; + move16(); + hInstance->infoTotalBitsWritten = 0; + move16(); + + return; +} + +/**********************************************************************/ /* +IGF write concatenated bitsream for TCX10 modes +**************************************************************************/ +Word16 IGFEncWriteConcatenatedBitstream_fx( /**< out: Q0 | total number of bits written */ + const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ + ) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + Word16 i; + Word16 tmp; + Word16 bitsLeft; + UWord8 *pBitstream; + + hPrivateData = &hInstance->igfData; + pBitstream = &hPrivateData->igfBitstream[0]; + + tmp = shr(hPrivateData->igfBitstreamBits, 3); + FOR (i = 0; i < tmp; i++) + { + push_next_indice_fx(hBstr, pBitstream[i], 8); + } + + bitsLeft = s_and(hPrivateData->igfBitstreamBits, 0x7); + IF(bitsLeft > 0) + { + push_next_indice_fx(hBstr, shr(pBitstream[i], sub(8, bitsLeft)), bitsLeft); + } + + return hInstance->infoTotalBitsWritten; +} + +/**********************************************************************/ /* +apply the IGF encoder, main encoder interface +**************************************************************************/ +void IGFEncApplyMono_fx(const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | instance handle of IGF Encoder */ + const Word16 igfGridIdx, /**< in: Q0 | IGF grid index */ + Encoder_State_fx *st, /**< in: | Encoder state */ + Word32 *pMDCTSpectrum, /**< in: Q31 | MDCT spectrum */ + Word16 MDCTSpectrum_e, /**< in: | exponent of MDCT spectrum */ + Word32 *pPowerSpectrum, /**< in: Q31 | MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 PowerSpectrum_e, /**< in: | exponent of pPowerSpectrum */ + Word16 isTCX20, /**< in: Q0 | flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + Word16 isTNSActive, /**< in: Q0 | flag indicating if the TNS is active */ + Word16 last_core_acelp /**< in: Q0 | indicator if last frame was acelp coded */ + ) +{ + Word32 *pPowerSpectrumParameter; /* If it is NULL it informs a function that specific handling is needed */ + Word32 *pPowerSpectrumParameterWhitening; /* If it is NULL it informs a function that specific handling is needed */ + Word16 highPassEner_exp; /*exponent of highpass energy - maybe not needed*/ + + + pPowerSpectrumParameter = NULL; + test(); + if ((isTNSActive == 0) && (isTCX20 != 0)) + { + pPowerSpectrumParameter = pPowerSpectrum; + } + pPowerSpectrumParameterWhitening = NULL; + if (isTCX20 != 0) + { + pPowerSpectrumParameterWhitening = pPowerSpectrum; + } + + IGF_UpdateInfo(hInstance, /* i: instance handle of IGF Encoder */ + igfGridIdx); /* i: IGF grid index */ + + IGF_CalculateEnvelope(hInstance, /* i: instance handle of IGF Encoder */ + pMDCTSpectrum, /* i: MDCT spectrum */ + MDCTSpectrum_e, /* i: exponent of MDCT spectrum */ + pPowerSpectrumParameter, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + PowerSpectrum_e, /* i: exponent of pPowerSpectrum */ + igfGridIdx /* i: IGF grid index */ + ); + + + IGF_Whitening(hInstance, /* i: instance handle of IGF Encoder */ + pPowerSpectrumParameterWhitening, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + PowerSpectrum_e, /* i: exponent of powerSpectrum */ + igfGridIdx, /* i: IGF grid index */ + (st->transientDetection.transientDetector.bIsAttackPresent == 1), + last_core_acelp); /* i: last frame was acelp indicator */ + + pPowerSpectrumParameter = NULL; + if (isTCX20 != 0) + { + pPowerSpectrumParameter = pPowerSpectrum; + } + + IGF_ErodeSpectrum( /* o: highpass energy */ + &highPassEner_exp, /* o: exponent of highPassEner */ + hInstance, /* i: instance handle of IGF Encoder */ + pMDCTSpectrum, /* i: MDCT spectrum */ + pPowerSpectrumParameter, /* i: MDCT^2 + MDST^2 spectrum, or estimate */ + PowerSpectrum_e, /* i: exponent of pPowerSpectrum */ + igfGridIdx); /* i: IGF grid index */ + +} + + diff --git a/lib_enc/igf_scf_enc_fx.c b/lib_enc/igf_scf_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..8621640fe12bf9bed51429355ff670523c89590a --- /dev/null +++ b/lib_enc/igf_scf_enc_fx.c @@ -0,0 +1,406 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "cnst.h" +//#include "prot_fx.h" +#include "stat_enc.h" +#include "stat_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 */ + + +/**********************************************************************/ /** +initialization of an instance of this module +**************************************************************************/ +void IGFSCFEncoderOpen_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + H_IGF_INFO hIgfInfo, /* i : IGF info handle */ + const int32_t total_brate, /* i : total bitrate */ + const int16_t bwidth, /* i : audio bandwidth */ + const int16_t element_mode, /* i : IVAS element mode */ + const int16_t rf_mode /* i : flag to signal the RF mode */ +) +{ + + + hPublicData->ptrBitIndex = 0; + move16(); + hPublicData->bitCount = 0; + move16(); + hPublicData->Tsave = 0; + move16(); + hPublicData->contex_saved = 0; + move16(); + hPublicData->acState.low = 0; + move32(); + hPublicData->acState.high = 0; + move32(); + hPublicData->acState.value = 0; + move16(); + set16_fx(hPublicData->prev, 0, 64); + set16_fx(hPublicData->prevSave, 0, 64); + + hPublicData->scfCountLongBlock[0] = hIgfInfo->grid[0].swb_offset_len - 1; + hPublicData->scfCountLongBlock[1] = hIgfInfo->grid[1].swb_offset_len - 1; + hPublicData->scfCountLongBlock[2] = hIgfInfo->grid[2].swb_offset_len - 1; + move16();move16();move16(); + + hPublicData->t = 0; + move16(); /* protect against the invalid request of starting encoding with a dependent block */ + + IGFCommonFuncsIGFGetCFTables(total_brate, bwidth, element_mode, rf_mode, &hPublicData->cf_se00, &hPublicData->cf_se01, &hPublicData->cf_off_se01, &hPublicData->cf_se02, &hPublicData->cf_off_se02, &hPublicData->cf_se10, &hPublicData->cf_off_se10, &hPublicData->cf_se11, &hPublicData->cf_off_se11); + +} + + +static Word16 quant_ctx( + Word16 ctx /* i: the context value to be quantized */ +) +{ + /* + ctx ... -5 -4 -3 -2 -1 0 1 2 3 4 5 ... + Q(ctx)... -3 -3 -3 -2 -1 0 1 2 3 3 3 ... + */ + Word16 result; + + + result = s_min(abs_s(ctx), IGF_CTX_OFFSET); /* limit the absolute value to IGF_CTX_OFFSET */ + if (ctx < 0) /* add the sign back, if needed */ + { + result = negate(result); + } + + return result; +} + + + +static void arith_encode_bits( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Word16 *ptr, /* i/o: pointer to expanded bit buffer, one bit in each Word16 */ + Word16 x, /* i: value to encode */ + Word16 nBits /* i: number of bits to encode */ +) +{ + Word16 i; + Word16 bit; + + + FOR (i = nBits - 1; i >= 0; --i) /* nBits > 0 */ + { + bit = s_and(shr(x, i), 1); + hPrivateData->ptrBitIndex = ari_encode_14bits_sign_fx(ptr, + hPrivateData->ptrBitIndex, + 32767, /* disable the bit count limitation */ + &hPrivateData->acState_fx, + bit + ); + } + +} + +static void arith_encode_residual( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Word16 *ptr, /* i/o: pointer to expanded bit buffer, one bit in each Word16 */ + Word16 x, /* i: residual value to encode */ + const Word16 *cumulativeFrequencyTable, /* i: cumulative frequency table to be used */ + Word16 tableOffset /* i: offset used to align the table */ +) +{ + Word16 extra; + Word16 extra_tmp; + Word16 extra_safety; + + + x = add(x, tableOffset); + + test(); + IF ((GE_16(x, IGF_MIN_ENC_SEPARATE))&&(LE_16(x,IGF_MAX_ENC_SEPARATE))) + { + x = sub(x, IGF_MIN_ENC_SEPARATE - 1); /* (x - IGF_MIN_ENC_SEPARATE) + 1 */ + /* encode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + hPrivateData->ptrBitIndex = ari_encode_14bits_ext_fx(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState_fx, + x, + (const UWord16*) cumulativeFrequencyTable + ); + + return; + } + + IF (LT_16(x, IGF_MIN_ENC_SEPARATE)) + { + /* send escape code 0 to indicate x <= IGF_MIN_ENC_SEPARATE - 1 */ + extra = sub(IGF_MIN_ENC_SEPARATE - 1, x); + hPrivateData->ptrBitIndex = ari_encode_14bits_ext_fx(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState_fx, + 0, + (const UWord16*) cumulativeFrequencyTable + ); + } + ELSE /* x > IGF_MAX_ENC_SEPARATE */ + { + /* send escape code (IGF_SYMBOLS_IN_TABLE - 1) to indicate x >= IGF_MAX_ENC_SEPARATE + 1 */ + extra = sub(x, IGF_MAX_ENC_SEPARATE + 1); + hPrivateData->ptrBitIndex = ari_encode_14bits_ext_fx(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState_fx, + IGF_SYMBOLS_IN_TABLE - 1, + (const UWord16*) cumulativeFrequencyTable + ); + } + + /* encode one of the tails of the distribution */ + extra_tmp = sub(extra, 15); + IF (extra_tmp < 0) + { + /* encode extra with 4 bits if extra < 15 */ + arith_encode_bits(hPrivateData, ptr, extra, 4); + } + ELSE /* extra >= 15 */ + { + /* send escape code 15 to indicate extra >= 15 */ + arith_encode_bits(hPrivateData, ptr, 15, 4); + + extra_safety = sub(extra_tmp, 63); + IF (extra_safety < 0) + { + /* encode additional extra with 6 bits */ + arith_encode_bits(hPrivateData, ptr, extra_tmp, 6); + } + ELSE { /* extra_tmp >= 63 */ + /* encode safety extra with 7 bits */ + arith_encode_bits(hPrivateData, ptr, extra_safety, 7); + } + } + +} + + +static void encode_sfe_vector( + IGFSCFENC_INSTANCE_HANDLE hPrivateData, /* i/o: instance handle */ + Word16 * ptr, /* i : pointer to expanded bit buffer, one bit in each short */ + const Word16 t, /* i : frame counter reset to 0 at each independent frame */ + Word16* prev_x, /* i : previous vector */ + Word16* x, /* i : current vector to encode */ + const Word16 length /* i : number of elements to encode */ +) +{ + /* + f + ^ + | d a x + | c b + | e --> t + */ + Word16 f; + Word16 pred; + Word16 res; + Word16 ctx; + Word16 ctx_f; + Word16 ctx_t; + Word16 prev_offset; + Word32 index1; + Word32 index2; + + + + FOR (f = 0; f < length; ++f) + { + IF (t == 0) + { + IF (f == 0) + { + /* (t == 0) && (f == 0) */ + /* encode one of the IGF_SYMBOLS_IN_TABLE == 27 alphabet symbols using the new raw AC function */ + hPrivateData->ptrBitIndex = ari_encode_14bits_ext_fx(ptr, + hPrivateData->ptrBitIndex, + &hPrivateData->acState_fx, + shr(x[f], 2), + (const UWord16*) hPrivateData->cf_se00 + ); + arith_encode_bits(hPrivateData, ptr, s_and(x[f], 3), 2); /* LSBs as 2 bit raw */ + } + ELSE IF (EQ_16(f, 1)) + { + /* (t == 0) && (f == 1) */ + res = sub(x[f], x[0]); /* pred = b */ + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se01, + hPrivateData->cf_off_se01); + } + ELSE + { + /* (t == 0) && (f >= 2) */ + prev_offset = sub(f, 1); + res = sub(x[f], x[prev_offset]); + move16(); /* pred = b */ + ctx = quant_ctx(sub(x[prev_offset], x[sub(prev_offset, 1)])); /* Q(b - e) */ + /* index1 is (IGF_SYMBOLS_IN_TABLE + 1) * (CTX_OFFSET + ctx) */ + index1 = L_mac0((IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_OFFSET, (IGF_SYMBOLS_IN_TABLE + 1), ctx); + /* index2 is IGF_CTX_OFFSET + ctx */ + index2 = L_mac0(IGF_CTX_OFFSET, 1, ctx); + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se02 + index1, + hPrivateData->cf_off_se02[index2]); + } + } + ELSE + { + /* t == 1 */ + IF (f == 0) + { + /* (t == 1) && (f == 0) */ + res = sub(x[f], prev_x[f]); + move16(); /* pred = a */ + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se10, + hPrivateData->cf_off_se10); + } + ELSE + { + /* (t == 1) && (f >= 1) */ + prev_offset = sub(f, 1); + pred = add(prev_x[f], x[prev_offset]); + pred = sub(pred, prev_x[prev_offset]); /* pred = a + b - c */ + res = sub(x[f], pred); + ctx_f = quant_ctx(sub(prev_x[f], prev_x[prev_offset])); /* Q(a - c) */ + ctx_t = quant_ctx(sub(x[prev_offset], prev_x[prev_offset])); /* Q(b - c) */ + /* index1 is (IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + + (IGF_SYMBOLS_IN_TABLE + 1) * (IGF_CTX_OFFSET + ctx_f) */ + index1 = L_mac0( + ((IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT + (IGF_SYMBOLS_IN_TABLE + 1)) * IGF_CTX_OFFSET, + (IGF_SYMBOLS_IN_TABLE + 1) * IGF_CTX_COUNT, ctx_t); + index1 = L_mac0(index1, (IGF_SYMBOLS_IN_TABLE + 1), ctx_f); + /* index2 is IGF_CTX_COUNT * (IGF_CTX_OFFSET + ctx_t) + (IGF_CTX_OFFSET + ctx_f) */ + index2 = L_mac0((IGF_CTX_COUNT + 1) * IGF_CTX_OFFSET, IGF_CTX_COUNT, ctx_t); + index2 = L_mac0(index2, 1, ctx_f); + arith_encode_residual(hPrivateData, + ptr, + res, + hPrivateData->cf_se11 + index1, + hPrivateData->cf_off_se11[index2]); + } + } + } + +} + + +/**********************************************************************/ /** +resets the internal encoder memory (context memory) +**************************************************************************/ +void IGFSCFEncoderReset_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +) +{ + + + /* reset of coder */ + hPublicData->t = 0; + move16(); /* indicate that an independent block follows */ + /* we do not need to fill hPublicData->prev with zeros, because when t = 0 no previous information is used */ + +} + +/**********************************************************************/ /** +main encoder function +**************************************************************************/ +Word16 IGFSCFEncoderEncode_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i : handle to public data or NULL in case there was no instance created */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 bitCount, /* i : offset to the first bit in bitbuffer which should be readed by iisArithDecoderDecode function */ + Word16* sfe, /* i : ptr to an array which contain quantized scalefactor energies */ + const Word16 igfGridIdx, /* i : igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 indepFlag /* i : if 1 frame is independent, 0 = frame is coded with data from previous frame */ +) +{ + Word16 ptr[IGF_BITBUFSIZE]; /* temporary expanded bit buffer, one bit in each Word16 */ + Word16 i; + + + + /* insert data: */ + hPublicData->ptrBitIndex = 0; + move16(); + hPublicData->bitCount = bitCount; + move16(); + ari_start_encoding_14bits_fx(&hPublicData->acState_fx); /* start AC encoding */ + + /* check if coder needs a reset and do it if necessary */ + IF (indepFlag != 0) + { + /* reset of coder */ + IGFSCFEncoderReset_fx(hPublicData); + } + + encode_sfe_vector(hPublicData, ptr, hPublicData->t, hPublicData->prev, sfe, hPublicData->scfCountLongBlock[igfGridIdx]); + + hPublicData->ptrBitIndex = ari_done_encoding_14bits_fx(ptr, + hPublicData->ptrBitIndex, + &hPublicData->acState_fx + ); /* finish AC encoding */ + hPublicData->bitCount = add(hPublicData->bitCount, hPublicData->ptrBitIndex); + + + /* advance history */ + Copy(sfe, hPublicData->prev, hPublicData->scfCountLongBlock[igfGridIdx]); + hPublicData->t = add(hPublicData->t, 1); + + + /* copy the bits from the temporary bit buffer, if doRealEncoding is enabled */ + IF (hBstr) + { + FOR (i = 0; i < hPublicData->ptrBitIndex; ++i) + { + push_next_indice_fx(hBstr, ptr[i], 1); + } + } + + /* return next bit offset in the stream */ + return hPublicData->bitCount; +} + +/**********************************************************************/ /** +for a closed loop encoder, the SCF encoder needs to memorize the context +**************************************************************************/ +void IGFSCFEncoderSaveContextState_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + const Word16 igfGridIdx /* i : igf grid index see declaration of IGF_GRID_IDX for details */ +) +{ + hPublicData->Tsave = hPublicData->t; + move16(); + Copy(hPublicData->prev, hPublicData->prevSave, hPublicData->scfCountLongBlock[igfGridIdx]); +} + +/**********************************************************************/ /** +for a closed loop encoder, the SCF encoder needs to memorize the context +**************************************************************************/ +void IGFSCFEncoderRestoreContextState_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + const Word16 igfGridIdx /* i : igf grid index see declaration of IGF_GRID_IDX for details */ +) +{ + + + hPublicData->t = hPublicData->Tsave; + move16(); + + Copy(hPublicData->prevSave, hPublicData->prev, hPublicData->scfCountLongBlock[igfGridIdx]); + + +} diff --git a/lib_enc/init_enc_fx.c b/lib_enc/init_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..e0d27edc047ae0bbfbd6df99168d176c4f4ce986 --- /dev/null +++ b/lib_enc/init_enc_fx.c @@ -0,0 +1,991 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#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 "stl.h" +#include "ivas_cnst.h" +#include "ivas_error.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + + +/*-----------------------------------------------------------------------* + * init_encoder_fx() + * + * Initialization of state variables + *-----------------------------------------------------------------------*/ +ivas_error init_encoder_fx( + Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */ +) +{ + Word16 i; + Word32 L_tmp; + + +Word16 idchan = 0; /* i : channel ID */ +Word16 vad_only_flag = 0; /* i : channel ID */ +ISM_MODE ism_mode = ISM_MODE_NONE; + ivas_error error; +//PMT("ism_mode, idchan, vad_only_flag to be move to function header") + error = IVAS_ERR_OK; + + + /*-----------------------------------------------------------------* + * General signal buffers + *-----------------------------------------------------------------*/ + if (!vad_only_flag) + { + if ((st_fx->hSignalBuf = (SIGNAL_BUFFERS_ENC_HANDLE)count_malloc(sizeof(SIGNAL_BUFFERS_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Signal buffers\n")); + } + + st_fx->Bin_E_old_fx = st_fx->hSignalBuf->Bin_E_old_fx; + st_fx->mem_decim_fx = st_fx->hSignalBuf->mem_decim_fx; + st_fx->mem_decim16k_fx = st_fx->hSignalBuf->mem_decim16k_fx; + st_fx->old_inp_12k8_fx = st_fx->hSignalBuf->old_inp_12k8_fx; + st_fx->old_inp_16k_fx = st_fx->hSignalBuf->old_inp_16k_fx; + st_fx->buf_speech_enc_pe = st_fx->hSignalBuf->buf_speech_enc_pe; + st_fx->buf_synth = st_fx->hSignalBuf->buf_synth; + st_fx->buf_speech_enc = st_fx->hSignalBuf->buf_speech_enc; + st_fx->buf_wspeech_enc = st_fx->hSignalBuf->buf_wspeech_enc; + + /* initializations */ + set16_fx(st_fx->old_inp_12k8_fx, 0, L_INP_MEM); /* memory of input signal at 12.8kHz */ + set16_fx(st_fx->old_inp_16k_fx, 0, L_INP_MEM); + set16_fx(st_fx->mem_decim16k_fx, 0, 2 * L_FILT_MAX); + set16_fx(st_fx->mem_decim_fx, 0, 2 * L_FILT_MAX); + set32_fx(st_fx->Bin_E_old_fx, 0, L_FFT/2); + + + st_fx->input_buff = st_fx->hSignalBuf->input_buff; + set16_fx(st_fx->input_buff, 0, L_FRAME48k + L_FRAME48k + NS2SA(48000, DELAY_FIR_RESAMPL_NS)); + st_fx->old_input_signal_fx = st_fx->input_buff; + IF (EQ_16(st_fx->element_mode, EVS_MONO)) + { + st_fx->input = st_fx->input_buff + st_fx->input_Fs_fx / FRAMES_PER_SEC + NS2SA(st_fx->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + } + ELSE + { + st_fx->input = st_fx->input_buff + st_fx->input_Fs_fx / FRAMES_PER_SEC; + } + } + else + { + st_fx->hSignalBuf = NULL; + st_fx->Bin_E_old_fx = NULL; + st_fx->mem_decim_fx = NULL; + st_fx->mem_decim16k_fx = NULL; + st_fx->old_inp_12k8_fx = NULL; + st_fx->old_inp_16k_fx = NULL; + st_fx->buf_speech_enc_pe = NULL; + st_fx->buf_synth = NULL; + st_fx->buf_speech_enc = NULL; + st_fx->buf_wspeech_enc = NULL; + st_fx->input_buff = NULL; + } + + /*-----------------------------------------------------------------* + * ACELP core parameters + *-----------------------------------------------------------------*/ + st_fx->last_core_fx = -1; + move16(); + if ( st_fx->Opt_AMR_WB_fx ) + { + st_fx->last_core_fx = AMR_WB_CORE; + move16(); + } + + st_fx->L_frame_fx = L_FRAME; + move16(); + st_fx->last_coder_type_fx = GENERIC; + move16(); + st_fx->last_total_brate_fx = st_fx->total_brate_fx; + move32(); + st_fx->last_total_brate_cng_fx = -1; + move32(); + st_fx->last_core_brate_fx = st_fx->total_brate_fx; + move32(); + st_fx->extl_fx = -1; + move16(); + st_fx->last_extl_fx = -1; + move16(); + st_fx->last_L_frame_fx = L_FRAME; + move16(); + st_fx->rate_switching_reset = 0; + move16(); + st_fx->rate_switching_reset_16kHz = 0; + move16(); + + /*-----------------------------------------------------------------* + * Bitstream + *-----------------------------------------------------------------*/ + + IF (!vad_only_flag) + { + IF ((st_fx->hBstr = (BSTR_ENC_HANDLE)count_malloc(sizeof(BSTR_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Bitstream structure\n")); + } +#ifdef IVAS_CODE_BITSTREAM + + /* set pointer to the buffer of indices */ + st->hBstr->ind_list = st_ivas->ind_list; + st->hBstr->ivas_ind_list_zero = &st_ivas->ind_list; + st->hBstr->ivas_max_num_indices = &st_ivas->ivas_max_num_indices; + st->hBstr->nb_ind_tot = 0; + st->hBstr->nb_bits_tot = 0; + st->hBstr->st_ivas = st_ivas; +#endif + } + ELSE + { + st_fx->hBstr = NULL; + } + st_fx->hBstr->nb_bits_tot_fx = 0; + move16(); + + + Copy( GEWB_Ave_fx, st_fx->mem_AR_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( GEWB_Ave_fx, st_fx->lsf_adaptive_mean_fx, M ); + init_lvq_fx( st_fx->offset_scale1_fx, st_fx->offset_scale2_fx, st_fx->offset_scale1_p_fx, st_fx->offset_scale2_p_fx, st_fx->no_scales_fx, st_fx->no_scales_p_fx ); + st_fx->next_force_safety_net_fx = 0; + + st_fx->pstreaklen_fx = 0; + move16(); + st_fx->streaklimit_fx = 32767; + move16(); /*1;//Q15 */ + set16_fx( st_fx->mem_MA_fx, 0, M ); + + init_gp_clip_fx( st_fx->clip_var_fx ); + pitch_ol_init_fx( &st_fx->old_thres_fx, &st_fx->old_pitch, &st_fx->delta_pit_fx, &st_fx->old_corr_fx ) ; + + /*-----------------------------------------------------------------* + * AMR-WB IO initialization + *-----------------------------------------------------------------*/ + test(); + IF (st_fx->Opt_AMR_WB_fx || EQ_16(st_fx->element_mode, EVS_MONO)) + { + IF ((st_fx->hAmrwb_IO = (AMRWB_IO_ENC_HANDLE)count_malloc(sizeof(AMRWB_IO_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for AMR-WB IO\n")); + } + + amr_wb_enc_init_fx(st_fx->hAmrwb_IO); + } + ELSE + { + st_fx->hAmrwb_IO = NULL; + } + st_fx->clas_fx = UNVOICED_CLAS; + move16(); + set16_fx( st_fx->old_wsp2_fx, 0, (L_WSP_MEM - L_INTERPOL)/OPL_DECIM ); + set16_fx( st_fx->old_wsp_fx, 0, L_WSP_MEM ); + st_fx->mem_deemph_fx = 0; + move16(); + st_fx->mem_preemph_fx = 0; + move16(); + st_fx->mem_preemph16k_fx = 0; + move16(); + st_fx->mem_preemph_enc = 0; + move16(); + + /* AVQ pre-quantizer memory */ + st_fx->mem_preemp_preQ_fx = 0; + move16(); + st_fx->mem_deemp_preQ_fx = 0; + move16(); + st_fx->last_nq_preQ_fx = 0; + move16(); + st_fx->use_acelp_preq = 0; + move16(); + + /* (Decimated) Weighted Speech Memory */ + st_fx->mem_wsp_enc = 0; + move16(); + + st_fx->mem_wsp_fx = 0; + move16(); + set32_fx( st_fx->Bin_E_fx, 0, L_FFT ); + set16_fx( st_fx->mem_decim2_fx, 0, 3 ); + set16_fx( st_fx->lgBin_E_fx, 0, L_FFT/2 ); + + st_fx->ini_frame_fx = 0; + move16(); + st_fx->ee_old_fx = 640; + move32();/*chk //10 in Q6 */ + st_fx->Nb_ACELP_frames_fx = 0; + move16(); + st_fx->audio_frame_cnt_fx = AUDIO_COUNTER_INI; + move16();/* Initializatin of the audio frame counter mildly into the audio mode */ + + /* adaptive lag window memory */ + st_fx->old_pitch_la = 0; + move16(); + st_fx->old_voicing_la = 0; + move16(); + set32_fx( st_fx->mem_hp20_in_fx, 0, 5 ); + + st_fx->old_hpfilt_in_fx = 0; + move16(); + st_fx->old_hpfilt_out_fx = 0; + move16(); + st_fx->EnergyLT_fx = 0; + move32(); + st_fx->prev_Q_new = 0; + move16(); + + + IF( EQ_32(st_fx->input_Fs_fx,8000)) + { + st_fx->min_band_fx = 1; + move16(); + st_fx->max_band_fx = 16; + move16(); + } + ELSE + { + st_fx->min_band_fx = 0; + move16(); + st_fx->max_band_fx = 19; + move16(); + } + IF ( st_fx->Opt_AMR_WB_fx ) + { + Copy( mean_isf_amr_wb_fx, st_fx->lsf_old_fx, M ); + E_LPC_isf_isp_conversion( st_fx->lsf_old_fx, st_fx->lsp_old1_fx, M); + } + ELSE + { + Copy( GEWB_Ave_fx, st_fx->lsf_old_fx, M ); + lsf2lsp_fx( st_fx->lsf_old_fx, st_fx->lsp_old1_fx, M, INT_FS_FX); + } + + Copy( st_fx->lsf_old_fx, st_fx->lsf_old1_fx, M ); + Copy( st_fx->lsp_old1_fx, st_fx->lsp_old_fx, M ); + Copy( st_fx->lsp_old_fx, st_fx->lsp_old16k_fx, M ); + Copy( st_fx->lsp_old_fx, st_fx->lspold_enc_fx, M ); + + st_fx->stab_fac_fx = 0; + move16(); + /* Bass post-filter memories - encoder side of MODE2 */ + st_fx->bpf_off_fx = 0; + move16(); + + /* TC mode */ + st_fx->tc_cnt_fx = 0; + move16(); + st_fx->mCb1_fx = 0; + move16(); + + /* AC mode */ + + /*-----------------------------------------------------------------* + * parameters for AC coder type (GSC) + *-----------------------------------------------------------------*/ + + //st_fx->GSC_noisy_speech = 0; + st_fx->GSC_IVAS_mode = 0; + + test();test(); + IF ((idchan == 0 && NE_16(st_fx->element_mode, IVAS_CPE_MDCT)) || EQ_16(st_fx->element_mode, IVAS_CPE_TD)) + { + IF ((st_fx->hGSCEnc = (GSC_ENC_HANDLE)count_malloc(sizeof(GSC_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for GSC\n")); + } + + GSC_enc_init_fx(st_fx->hGSCEnc); + } + ELSE + { + st_fx->hGSCEnc = NULL; + } + + st_fx->last_ener_fx = 0; + move16(); + + st_fx->old_dE1_fx = 0; + move16(); + st_fx->old_ind_deltaMax_fx = 0; + move32(); + set32_fx( st_fx->old_enr_ssf_fx, 0, 2*NB_SSF ); + st_fx->spike_hyst_fx = -1; + move16(); + st_fx->music_hysteresis_fx = 0; + move16(); /* Counter of frames after AUDIO frame to prevent UC */ + st_fx->last_harm_flag_acelp_fx = 0; + move16(); + st_fx->GSC_noisy_speech_fx = 0; + move16(); + + /* speech/music classifier */ + st_fx->Last_pulse_pos_fx = 0; + move16(); + + st_fx->last_vad_spa_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * VAD + *-----------------------------------------------------------------*/ + + st_fx->vad_flag = 1; + st_fx->localVAD = 0; + move16();move16(); + test();test();test();test(); + IF ((idchan == 0 || EQ_16(st_fx->element_mode, IVAS_CPE_TD) || EQ_16(st_fx->element_mode, IVAS_CPE_MDCT) || EQ_16(st_fx->element_mode, EVS_MONO)) && (!vad_only_flag)) + { + if ((st_fx->hVAD = (VAD_HANDLE)count_malloc(sizeof(VAD_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for VAD\n")); + } + + wb_vad_init_fx(st_fx->hVAD); + st_fx->hVAD->prim_act_quick_fx = 0; + move16(); + st_fx->hVAD->prim_act_slow_fx = 0; + move16(); + st_fx->hVAD->prim_act_fx = 0; + move16(); + st_fx->hVAD->prim_act_quick_he_fx = 0; + move16(); + st_fx->hVAD->prim_act_slow_he_fx = 0; + move16(); + st_fx->hVAD->prim_act_he_fx = 0; + move16(); + st_fx->hVAD->hangover_terminate_flag = 0; + move16(); + + st_fx->hVAD->consec_inactive = 0; + move16(); + st_fx->hVAD->spectral_tilt_reset = 1; + move16(); + st_fx->hVAD->running_avg_fx = 0; + move16(); + st_fx->hVAD->ra_deltasum_fx = 0; + move16(); + st_fx->hVAD->trigger_SID = 0; + move16(); + st_fx->hVAD->L_snr_sum_vad_fx = 0; + move32(); + } + else + { + st_fx->hVAD = NULL; + } + + st_fx->Pos_relE_cnt = 5120; move16(); /*20.0f*/ + st_fx->nb_active_frames_HE_SAD_fx = 0;move16(); + st_fx->lp_speech_fx = 11520;move16(); /*Q8 (45.0) */ /* Initialize the long-term active speech level in dB */ + + /* avoid uninitialized memory access */ + + /*-----------------------------------------------------------------* + * Noise estimator + *-----------------------------------------------------------------*/ + //PMT("deal with idchan ") + IF (/*idchan == 0 ||*/ EQ_16(st_fx->element_mode, IVAS_CPE_TD) || EQ_16(st_fx->element_mode, IVAS_CPE_MDCT) || EQ_16(st_fx->element_mode, EVS_MONO) ) + { + if ((st_fx->hNoiseEst = (NOISE_EST_HANDLE)count_malloc(sizeof(NOISE_EST_DATA))) == NULL) + { + return IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Noise estimation\n"); + } + noise_est_init_fx(st_fx->hNoiseEst); + } + ELSE + { + st_fx->hNoiseEst = NULL; + } + + /*-----------------------------------------------------------------* + * Speech/music classifier + *-----------------------------------------------------------------*/ + test();test(); + IF (idchan == 0 || EQ_16(st_fx->element_mode, IVAS_CPE_TD) || EQ_16(st_fx->element_mode, IVAS_CPE_MDCT) || EQ_16(st_fx->element_mode, EVS_MONO) ) + { + IF ((st_fx->hSpMusClas = (SP_MUS_CLAS_HANDLE)count_malloc(sizeof(SP_MUS_CLAS_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Speech/music classifier\n")); + } + + speech_music_clas_init_fx(st_fx->hSpMusClas); + + st_fx->sp_aud_decision0 = 0; + st_fx->sp_aud_decision1 = 0; + st_fx->sp_aud_decision2 = 0; + move16();move16();move16(); + } + ELSE + { + st_fx->hSpMusClas = NULL; + } + + st_fx->bckr_tilt_lt=0; + move32(); + + /* WB, SWB and FB bandwidth detector */ + st_fx->lt_mean_NB_fx = 0; + move16(); + st_fx->lt_mean_WB_fx = 0; + move16(); + st_fx->lt_mean_SWB_fx = 0; + move16(); + st_fx->count_WB_fx = BWD_COUNT_MAX; + move16(); + st_fx->count_SWB_fx = BWD_COUNT_MAX; + move16(); + st_fx->count_FB_fx = BWD_COUNT_MAX; + move16(); + st_fx->bwidth_fx = st_fx->max_bwidth_fx; + move16(); + st_fx->last_input_bwidth_fx = st_fx->bwidth_fx; + move16(); + st_fx->last_bwidth_fx = st_fx->bwidth_fx; + move16(); + st_fx->last_bwidth_cng_fx = st_fx->bwidth_fx; + move16(); + + + move16(); + st_fx->coder_type_raw_fx = VOICED; + st_fx->last_coder_type_raw_fx = st_fx->coder_type_raw_fx; + + st_fx->is_ism_format = 0; move16(); + if (NE_16(ism_mode, ISM_MODE_NONE) ) + { + st_fx->is_ism_format = 1; move16(); + } + /* Stationary noise UV modification */ + st_fx->ge_sm_fx = 640; + move32();/*Q(GE_SHIFT) */ + st_fx->uv_count_fx = 0; + move16(); + st_fx->act_count_fx = 3; + move16(); + Copy(st_fx->lsp_old_fx, st_fx->lspold_s_fx, M); + st_fx->noimix_seed_fx = RANDOM_INITSEED; + move16(); + st_fx->min_alpha_fx = 1; + move16(); + st_fx->exc_pe_fx = 0; + move16(); + + /* CNG and DTX */ + st_fx->lp_noise_fx = 0; + move16(); + + test();test(); + IF (((idchan == 0 && st_fx->Opt_DTX_ON_fx) || EQ_16(st_fx->element_mode, EVS_MONO)) || (EQ_16(st_fx->element_mode, IVAS_CPE_MDCT) && st_fx->Opt_DTX_ON_fx)) + { + if ((st_fx->hDtxEnc = (DTX_ENC_HANDLE)count_malloc(sizeof(DTX_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX variables\n")); + } + dtx_enc_init_fx(st_fx, st_fx->var_SID_rate_flag_fx, st_fx->interval_SID_fx); + + } + ELSE + { + st_fx->hDtxEnc = NULL; + } + + st_fx->fd_cng_reset_flag = 0; + move16(); + + IF( st_fx->Opt_DTX_ON_fx ) + { + move16(); + } + st_fx->active_fr_cnt_fx = 0; + move16(); + st_fx->cng_type_fx = -1; + move16(); + + + /*-----------------------------------------------------------------* + * LP-CNG + *-----------------------------------------------------------------*/ + + test();test();test(); + IF (((idchan == 0 && st_fx->Opt_DTX_ON_fx && NE_16(st_fx->element_mode, IVAS_CPE_MDCT)) || EQ_16(st_fx->element_mode, EVS_MONO)) && !(EQ_16(ism_mode, ISM_MODE_PARAM) || EQ_16(ism_mode, ISM_MODE_DISC))) + { + IF ((st_fx->hTdCngEnc = (TD_CNG_ENC_HANDLE)count_malloc(sizeof(TD_CNG_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n")); + } + + td_cng_enc_init_fx(st_fx->hTdCngEnc, st_fx->Opt_DTX_ON_fx, st_fx->max_bwidth_fx); + } + ELSE + { + st_fx->hTdCngEnc = NULL; + } + + + /*-----------------------------------------------------------------* + * ACELP LPDmem + *-----------------------------------------------------------------*/ + + test();test(); + IF ((idchan == 0 && NE_16(st_fx->element_mode, IVAS_CPE_MDCT)) || EQ_16(st_fx->element_mode, IVAS_CPE_TD)) + { + IF ((st_fx->hLPDmem = (LPD_state_HANDLE)count_malloc(sizeof(LPD_state))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LPDmem\n")); + } + + LPDmem_enc_init_fx(st_fx->hLPDmem); + } + ELSE + { + st_fx->hLPDmem = NULL; + } + + /* FEC */ + st_fx->last_clas_fx = UNVOICED_CLAS; + move16(); + + FOR (i=0; i<2*NB_SUBFR16k; i++) + { + st_fx->old_pitch_buf_fx[i] = L_SUBFR_Q6; + move16(); + } + st_fx->old_Es_pred_fx = 0; + move16(); + set16_fx(st_fx->old_Aq_12_8_fx + 1, 0, M ); + st_fx->old_Aq_12_8_fx[0] = 4096; + move16(); + + /*-----------------------------------------------------------------* + * CLDFB Analysis + *-----------------------------------------------------------------*/ + + /* open analysis for input SR */ + if ((error = openCldfb ( &st_fx->cldfbAna_Fx, CLDFB_ANALYSIS, CLDFB_getNumChannels(st_fx->input_Fs_fx), st_fx->input_frame_fx )) != IVAS_ERR_OK) + { + return error; + } + + if ((error = openCldfb ( &st_fx->cldfbSyn_Fx, CLDFB_SYNTHESIS, CLDFB_getNumChannels(16000), L_FRAME16k)) != IVAS_ERR_OK) + { + return error; + } + + st_fx->energyCoreLookahead_Fx = 0; + move32(); + st_fx->sf_energyCoreLookahead_Fx = 0; + move16(); + + /* stable short pitch detection */ + st_fx->voicing0_sm_fx = 0; + move16(); + st_fx->voicing_sm_fx = 0; + move16(); + st_fx->LF_EnergyRatio_sm_fx = 128; + move16(); + st_fx->predecision_flag_fx = 0; + move16(); + st_fx->diff_sm_fx = 0; + move32(); + st_fx->energy_sm_fx = 0; + move32(); + + /*-----------------------------------------------------------------* + * SC-VBR parameters + *-----------------------------------------------------------------*/ + test(); + IF (st_fx->Opt_SC_VBR_fx || EQ_16(st_fx->element_mode, EVS_MONO)) + { + IF ((st_fx->hSC_VBR = (SC_VBR_ENC_HANDLE)count_malloc(sizeof(SC_VBR_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SC-VBR\n")); + } + + sc_vbr_enc_init_fx(st_fx->hSC_VBR); + } + ELSE + { + st_fx->hSC_VBR = NULL; + } + /* PLC encoder */ + IF (EQ_16(st_fx->element_mode, EVS_MONO)) + { + IF ((st_fx->hPlcExt = (PLC_ENC_EVS_HANDLE)count_malloc(sizeof(PLC_ENC_EVS))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hPlcExt\n")); + } + } + ELSE + { + st_fx->hPlcExt = NULL; + } + /*-----------------------------------------------------------------* + * Temporal Envelope Coding + *-----------------------------------------------------------------*/ + + IF (st_fx->element_mode == EVS_MONO) + { + IF ((st_fx->hTECEnc = (TEC_ENC_HANDLE)count_malloc(sizeof(TEC_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TEC\n")); + } + } + ELSE + { + st_fx->hTECEnc = NULL; + } + + /*-----------------------------------------------------------------* + * Bitstream + *-----------------------------------------------------------------*/ + + IF (!vad_only_flag) + { + IF ((st_fx->hBstr = (BSTR_ENC_HANDLE)count_malloc(sizeof(BSTR_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Bitstream structure\n")); + } + } + ELSE + { + st_fx->hBstr = NULL; + } + + /*-----------------------------------------------------------------* + * SWB BWE parameters + *-----------------------------------------------------------------*/ + IF (idchan == 0 && NE_16(st_fx->element_mode, IVAS_CPE_MDCT)) + { + IF ((st_fx->hBWE_FD = (FD_BWE_ENC_HANDLE)count_malloc(sizeof(FD_BWE_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for FD BWE\n")); + } + + fd_bwe_enc_init_fx(st_fx->hBWE_FD); + } + ELSE + { + st_fx->hBWE_FD = NULL; + } + + st_fx->prev_Q_shb = 0; + move16(); + st_fx->last_Opt_SC_VBR_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * TBE parameters + *-----------------------------------------------------------------*/ + + IF (idchan == 0 && NE_16(st_fx->element_mode, IVAS_CPE_MDCT)) + { + IF ((st_fx->hBWE_TD = (TD_BWE_ENC_HANDLE)count_malloc(sizeof(TD_BWE_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD BWE\n")); + } + + //IF ((error = openCldfb(&st_fx->cldfbSynTd, CLDFB_SYNTHESIS, 16000, CLDFB_PROTOTYPE_1_25MS)) != IVAS_ERR_OK) + //{ + // return error; + //} + + InitSWBencBuffer_fx(st_fx/*st_fx->hBWE_TD*/); + ResetSHBbuffer_Enc_fx(st_fx/*st_fx->hBWE_TD*/); + } + ELSE + { + st_fx->hBWE_TD = NULL; + //st_fx->cldfbSynTd = NULL; + } + + + IF (st_fx->Opt_RF_ON || EQ_16(st_fx->element_mode, EVS_MONO)) + { + IF ((st_fx->hRF = (RF_ENC_HANDLE)count_malloc(sizeof(RF_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for RF\n")); + } + + /* initialize RF indice buffers */ + reset_rf_indices_fx(st_fx/*->hRF, st_fx->L_frame_fx, &st->rf_target_bits_write*/); + } + ELSE + { + st_fx->hRF = NULL; + } + + + /*-----------------------------------------------------------------* + * HQ core parameters + *-----------------------------------------------------------------*/ + + st_fx->input = st_fx->input_buff+L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS); + set16_fx( st_fx->input_buff+L_FRAME48k, 0, L_FRAME48k+NS2SA(48000, DELAY_FIR_RESAMPL_NS) ); + st_fx->old_input_signal_fx = st_fx->input - add(NS2SA_fx2(st_fx->input_Fs_fx, DELAY_FIR_RESAMPL_NS), st_fx->input_frame_fx); + + + st_fx->Energy_Old_fx = 0; + move16(); + st_fx->Q_old_wtda=15; + move16(); + st_fx->EnergyLT_fx = 1; + move32(); + st_fx->EnergyLT_fx_exp = 30; + move16(); /* Set to a High Exponent so it is 1^-30 */ + st_fx->TransientHangOver_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * TCX core + *-----------------------------------------------------------------*/ + + // VE: reduction possible for MCT_CHAN_MODE_LFE channel - see I1-172 + IF (idchan == 0 || EQ_16(st_fx->element_mode, IVAS_CPE_MDCT)) + { + IF ((st_fx->hTcxEnc = (TCX_ENC_HANDLE)count_malloc(sizeof(TCX_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxEnc\n")); + } + + /* Share the memories for 2xTCX10/4xTCX5 and for TCX20 */ + /*st_fx->hTcxEnc->spectrum[0] = st_fx->hTcxEnc->spectrum_long; + st_fx->hTcxEnc->spectrum[1] = st_fx->hTcxEnc->spectrum_long + N_TCX10_MAX;*/ + + set16_fx(st_fx->hTcxEnc->old_out_fx, 0, L_FRAME32k); + + /* MDCT selector */ + MDCT_selector_reset_fx(st_fx->hTcxEnc); + st_fx->hTcxEnc->Q_old_out = 0; + move16(); + + /* MDCT classifier */ + MDCT_classifier_reset_fx(st_fx->hTcxEnc); + + IF ((st_fx->hTcxCfg = (TCX_CONFIG_HANDLE)count_malloc(sizeof(TCX_config))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hTcxCfg\n")); + } + } + else + { + st_fx->hTcxEnc = NULL; + //st_fx->hTcxCfg = NULL; + } + /*-----------------------------------------------------------------* + * HQ core parameters + *-----------------------------------------------------------------*/ + + test();test(); + IF (NE_16(st_fx->element_mode, IVAS_CPE_TD) && NE_16(st_fx->element_mode, IVAS_CPE_MDCT) && idchan == 0) + { + IF ((st_fx->hHQ_core = (HQ_ENC_HANDLE)count_malloc(sizeof(HQ_ENC_DATA))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for HQ core\n")); + } + + HQ_core_enc_init_fx(st_fx->hHQ_core); + } + ELSE + { + st_fx->hHQ_core = NULL; + } + + st_fx->last_enerBuffer_exp = 0; + move16(); + + /*-----------------------------------------------------------------* + * Channel-aware mode + *-----------------------------------------------------------------*/ + + + test(); + test(); + test(); + IF( st_fx->Opt_RF_ON == 0 || (NE_16(st_fx->bwidth_fx,WB)&&NE_16(st_fx->bwidth_fx,SWB))||NE_32(st_fx->total_brate_fx,ACELP_13k20)) + { + IF (EQ_16(st_fx->Opt_RF_ON,1)) + { + printf("\nWarning: Channel-aware mode only available for 13.2 kbps WB/SWB\n"); + printf(" Switched to normal mode!\n"); + st_fx->Opt_RF_ON = 0; + move16(); + st_fx->rf_fec_offset = 0; + move16(); + } + st_fx->rf_mode = 0; + move16(); + } + ELSE + { + st_fx->rf_mode = st_fx->Opt_RF_ON; + move16(); + } + st_fx->rf_mode_last = st_fx->rf_mode; + + /* initialize RF indice buffers */ + reset_rf_indices_fx( st_fx ); + + /*-----------------------------------------------------------------* + * MODE2 initialization + *-----------------------------------------------------------------*/ + + st_fx->last_sr_core = i_mult2 (st_fx->last_L_frame_fx, 50); + + /*-----------------------------------------------------------------* + * IGF + *-----------------------------------------------------------------*/ + + test();test(); + IF (idchan == 0 || EQ_16(st_fx->element_mode, IVAS_CPE_MDCT)) + { + IF ((st_fx->hIGFEnc = (IGF_ENC_INSTANCE_HANDLE)count_malloc(sizeof(IGF_ENC_INSTANCE))) == NULL) + { + return (IVAS_ERROR(IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n")); + } + } + ELSE + { + st_fx->hIGFEnc = NULL; + move16(); + } + + IF( EQ_16(st_fx->codec_mode, MODE2)) + { + st_fx->igf = getIgfPresent_fx(st_fx->element_mode, st_fx->total_brate_fx, st_fx->bwidth_fx, st_fx->rf_mode); + } + ELSE + { + st_fx->igf = 0; + move16(); + } + + /* FD-CNG encoder */ + createFdCngEnc_fx(&st_fx->hFdCngEnc_fx); + initFdCngEnc_fx(st_fx->hFdCngEnc_fx, st_fx->input_Fs_fx, st_fx->cldfbAna_Fx->scale); + L_tmp = st_fx->total_brate_fx; + move32(); + test(); + if( st_fx->rf_mode && EQ_32(st_fx->total_brate_fx,ACELP_13k20)) + { + L_tmp = ACELP_9k60; + move32(); + } + configureFdCngEnc_fx( st_fx->hFdCngEnc_fx, st_fx->bwidth_fx, L_tmp ); + + st_fx->last_totalNoise_fx = 0; + move16(); + set16_fx( st_fx->totalNoise_increase_hist_fx, 0, TOTALNOISE_HIST_SIZE ); + st_fx->totalNoise_increase_len_fx = 0; + move16(); + init_coder_ace_plus_fx( st_fx, st_fx->last_total_brate_fx, 0, -10 /*hack*/); +//PMT("Transient detector init needs review, handle hTranDet is missing") + InitTransientDetection_fx( extract_l(Mult_32_16(st_fx->input_Fs_fx, 0x0290)), + NS2SA_fx2(st_fx->input_Fs_fx, DELAY_FIR_RESAMPL_NS), + &st_fx->transientDetection ); + + //reset_indices_enc_fx( st_fx->hBstr); + + + st_fx->Q_syn2 = 0; + move16(); + st_fx->Q_syn = 0; + move16(); + set16_fx(st_fx->Q_max, Q_MAX, L_Q_MEM); + set16_fx(st_fx->Q_max_16k, Q_MAX, L_Q_MEM); + st_fx->Q_old = 15; + move16(); + st_fx->old_wsp_max = 0; + move16(); + st_fx->old_wsp_shift = 0; + move16(); + st_fx->sharpFlag = 0; + move16(); + + st_fx->tdm_LRTD_flag = 0; /* LRTD stereo mode flag */ + st_fx->cna_dirac_flag = 0; /* CNA in DirAC flag */ + st_fx->cng_sba_flag = 0; /* CNG in SBA flag */ + st_fx->GSC_IVAS_mode = 0; /* CNG in SBA flag */ + st_fx->element_mode = EVS_MONO; /* element mode */ + st_fx->last_element_mode = st_fx->element_mode; /* element mode */ + st_fx->element_brate = -1; /* element bitrate */ + //PMT("element_mode and element_brate should be initialized at a proper place in ivas_dec_init eventually") + st_fx->low_rate_mode = 0; /* low-rate mode flag */ + //st_fx->coder_type_fx = GENERIC; /* low-rate mode flag */ + + set16_fx(st_fx->pitch_fx, L_SUBFR, 3); + set16_fx(st_fx->voicing_fx, 0, 3); + + +#ifdef DEBUGGING + st_fx->id_element = -1; /* element ID */ +#endif + st_fx->extl_orig = -1; /* extension layer */ + st_fx->extl_brate_orig = 0; /* extension layer bitrate */ + + return error; +} +/*-----------------------------------------------------------------------* + * LPDmem_enc_init_fx() + * + * Initialization of ACELP LPDmem state variables + *-----------------------------------------------------------------------*/ + +void LPDmem_enc_init_fx( + LPD_state_HANDLE hLPDmem /* i/o: LP memories */ +) +{ + Word16 i; + + set16_fx(hLPDmem->syn, 0, 1 + M); + set16_fx(hLPDmem->old_exc, 0, L_EXC_MEM); + set16_fx(hLPDmem->mem_syn, 0, M); + set16_fx(hLPDmem->mem_syn1_fx, 0, M); + set16_fx(hLPDmem->mem_syn2, 0, M); + set16_fx(hLPDmem->mem_syn_r, 0, L_SYN_MEM); + set16_fx(hLPDmem->mem_syn3, 0, M); + + hLPDmem->mem_w0 = 0; move16(); + hLPDmem->tilt_code = 0; move16(); + hLPDmem->gc_threshold = 0; move32(); +#if 0 + //set16_fx(hLPDmem->dispMem, 0, 8); +#else + hLPDmem->dm_fx.prev_state = 0; + move16(); /* This corresponds to st_fx->dispMem in FLP */ + hLPDmem->dm_fx.prev_gain_code = 0; + move32(); + + FOR(i = 2; i < 8; i++) + { + hLPDmem->dm_fx.prev_gain_pit[i - 2] = 0; + move16(); + } +#endif + return; +} +/*-----------------------------------------------------------------------* + * destroy_encoder_fx() + * + * Free memory which was allocated in init_encoder_fx() + *-----------------------------------------------------------------------*/ + +void destroy_encoder_fx( + Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */ +) +{ + deleteCldfb( &st_fx->cldfbAna_Fx ); + deleteCldfb( &st_fx->cldfbSyn_Fx ); + + deleteFdCngEnc_fx( &st_fx->hFdCngEnc_fx ); + + return; +} diff --git a/lib_enc/inov_enc_fx.c b/lib_enc/inov_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..9e7eafe83f642fd47c0c9ecef007602552dab4fe --- /dev/null +++ b/lib_enc/inov_enc_fx.c @@ -0,0 +1,416 @@ +/*==================================================================================== + 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 "basop_util.h" +#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 : inov_encode_fx() */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Encode the algebraic innovation */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) core_brate: core bitrate Q0 */ +/* _ (Word16) Opt_AMR_WB: flag indicating AMR-WB IO mode Q0 */ +/* _ (Word16) bwidth : input signal bandwidth Q0 */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16[]) h2 : weighted filter input response Q12 */ +/* _ (Word16[]) xn2 : target vector Q_new */ +/* _ (Word16) coder_type_fx : coding type Q0 */ +/* _ (Word16) i_subfr : current sub frame indicator Q0 */ +/* _ (Word16[]) exc_fx : pointer to excitation signal frame Q_new */ +/* _ (Word16) L_subfr : subframe length Q0 */ +/* _ (Word16) clip_gain : adaptive gain clipping flag Q0 */ +/* _ (Word16) gain_pit : adaptive excitation gain Q14 */ +/* _ (Word16) sharpFlag : formant sharpening flag Q0 */ +/* _ (Word16) tc_subfr : TC subframe index Q0 */ +/* _ (Word16) p_Aq : LP filter coefficients Q12 */ +/* _ (Word16) Jopt_flag :joint optimization flag Q0 */ +/* _ (Word16) y1 : Filtered adaptive excitation Q_new */ +/* _ (Word16) y2 :zero-memory filtered algebraic excitation Q_new */ +/* _ (Word16) cn : target vector in residual domain Q_new */ +/* _ (Word16) tilt_code : tilt of the excitation of previous subframe Q15 */ +/* _ (Word16) pt_pitch : pointer to current subframe fractional pitchQ6 */ +/* _ (Word16) index_buf_4T :5Sx4Track buffer for PI Q0 */ +/* _ (Word16) shift :shift */ +/* _ (Word16) Q_new : */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16) cn : target vector in residual domain Q_new */ +/* _ (Word16) code :algebraic excitation Q9 */ +/* _ (Word16) y2 :zero-memory filtered algebraic excitation Q_new */ +/* _ (Word16) unbits :number of unused bits for PI Q0 */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==============================================================================*/ + +Word16 inov_encode_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame, /* i : length of the last frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : input signal bandwidth */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16 *p_Aq, /* i : LP filter coefficients Q12*/ + const Word16 gain_pit, /* i : adaptive excitation gain Q14*/ + Word16 *cn, /* i/o: target vector in residual domain Q_new*/ + const Word16 *exc, /* i : pointer to excitation signal frame Q_new*/ + Word16 *h2, /* i/o: weighted filter input response Q12*/ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15*/ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + const Word16 *xn2, /* i : target vector for innovation search Q_new-1+shift*/ + Word16 *code, /* o : algebraic excitation Q9*/ + Word16 *y2, /* o : zero-memory filtered algebraic excitation Q9*/ + Word16 *unbits, /* o : number of unused bits for PI */ + const Word16 L_subfr, /* i : subframe length */ + Word16 shift +) +{ + Word16 dn[2*L_SUBFR]; + Word16 nBits, cmpl_flag; + Word16 stack_pulses; + Word16 g1, g2; + Word16 Rw[L_SUBFR]; + Word16 acelpautoc; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; +#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + (void)last_L_frame; +#endif + stack_pulses = 0; + move16(); + + IF( EQ_16(L_frame,L_FRAME)) + { + g1 = FORMANT_SHARPENING_G1; + move16(); + g2 = FORMANT_SHARPENING_G2; + move16(); + } + ELSE + { + g1 = FORMANT_SHARPENING_G1_16k; + move16(); + g2 = FORMANT_SHARPENING_G2_16k; + move16(); + } + + /*----------------------------------------------------------------* + * Update target vector for codebook search in residual domain + * Preemphasize the impulse response and include fixed-gain pitch contribution into impulse resp. h1[] (pitch sharpenning) + * Correlation between target xn2[] and impulse response h1[] + *----------------------------------------------------------------*/ + + test(); + test(); + IF (GT_32(core_brate, ACELP_13k20) && !Opt_AMR_WB && EQ_16(L_subfr, L_SUBFR)) + { + acelpautoc = 1; + move16(); + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, h2, tilt_code, shr(add(pt_pitch,26),6), 0 , L_SUBFR); + /* h2: Q11, Rw: (Rw_e)Q */ + /* Rw_e = */ E_ACELP_hh_corr(h2, Rw, L_SUBFR, 3); + + E_ACELP_conv(xn2, h2, cn); + + /* dn_e -> Rw_e*Q_xn */ + /*dn_e = */ E_ACELP_toeplitz_mul_fx( Rw, cn, dn, L_SUBFR, 1 ); + } + ELSE + { + acelpautoc = 0; + move16(); + updt_tar_fx( cn, cn, &exc[i_subfr], gain_pit, L_subfr ); + /* scaling of cn[] to limit dynamic at 12 bits */ + Scale_sig(cn, L_subfr, shift); + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, h2, tilt_code, shr(add(pt_pitch,26),6), 0 , L_subfr); + corr_xh_fx( xn2, dn, h2 ); + } + + /*-----------------------------------------------------------------* + * Set complexity reduction flag to limit the number of iterations + * in algebraic innovation search + *-----------------------------------------------------------------*/ + cmpl_flag = 0; + move16(); + test(); + IF (st_fx->acelp_cfg.fcb_mode) + { + /* set number of iterations in TD stereo, secondary channel */ + if (EQ_16(st_fx->element_mode, IVAS_CPE_TD) && EQ_16(st_fx->idchan, 1)) + { + cmpl_flag = 1; + move16(); + } + } + ELSE IF( EQ_16(L_frame,L_FRAME) && EQ_16(coder_type,TRANSITION)) + { + test();test(); + if( EQ_32(core_brate,ACELP_8k00) && i_subfr==0 && LT_16(tc_subfr,L_SUBFR)) + { + cmpl_flag = 3; + move16(); + } + test();test();test();test();test(); + if( EQ_32(core_brate,ACELP_11k60) && ((i_subfr==0 && LT_16(tc_subfr,L_SUBFR)) || EQ_16(tc_subfr,TC_0_0) || (EQ_16(i_subfr,3*L_SUBFR) && EQ_16(tc_subfr,TC_0_64)))) + { + cmpl_flag = 3; + move16(); + } + test();test();test();test(); + if( (EQ_32(core_brate,ACELP_13k20) || EQ_32(core_brate,ACELP_12k15)) && ((i_subfr==0 && LT_16(tc_subfr,L_SUBFR)) || LE_16(tc_subfr,TC_0_64))) + { + cmpl_flag = 3; + move16(); + } + } + + IF( EQ_16(L_frame,L_FRAME16k)) + { + IF( LE_32(core_brate,ACELP_32k)) + { + cmpl_flag = 4; + move16(); + + test(); + IF( EQ_16(coder_type,TRANSITION)&>_16(bwidth,WB)) + { + IF( LE_16(i_subfr,L_SUBFR)) + { + cmpl_flag = sub(cmpl_flag,1); + } + ELSE + { + cmpl_flag = sub(cmpl_flag,2); + } + } + } + ELSE IF( LE_32(core_brate,ACELP_48k)) + { + cmpl_flag = 3; + move16(); + + IF( EQ_16(coder_type,TRANSITION)) + { + IF( LE_16(i_subfr,L_SUBFR)) + { + cmpl_flag = sub(cmpl_flag,1); + } + ELSE + { + cmpl_flag = sub(cmpl_flag,2); + } + } + } + ELSE + { + cmpl_flag = 4; + move16(); + + IF( EQ_16(coder_type,TRANSITION)) + { + IF( LE_16(i_subfr,L_SUBFR)) + { + cmpl_flag = sub(cmpl_flag,1); + } + ELSE + { + cmpl_flag = sub(cmpl_flag,2); + } + } + + if( EQ_16(coder_type,INACTIVE)) + { + cmpl_flag = 4; + move16(); + } + } + } + + test(); + test(); + test(); + IF( NE_16(L_frame,st_fx->last_L_frame_fx)&>_32(core_brate,ACELP_13k20)&&(LT_32(core_brate,ACELP_32k)||EQ_16(bwidth,WB))) + { + if( GT_16(cmpl_flag,1)) + { + cmpl_flag = sub(cmpl_flag,1); + } + } + + /*-----------------------------------------------------------------* + * Find and encode the algebraic innovation + *-----------------------------------------------------------------*/ + + set16_fx( y2, 0, L_SUBFR ); + + IF ( !Opt_AMR_WB ) + { + IF (st_fx->acelp_cfg.fcb_mode) + { //PMTE() +#ifdef IVAS_CODE + if (st->acelp_cfg.fixed_cdk_index[i_subfr / L_subfr] < ACELP_FIXED_CDK_NB) + { + int16_t wordcnt, bitcnt; + int16_t prm[8]; + + if (st->acelp_cfg.fixed_cdk_index[i_subfr / L_subfr] >= 0) + { + if (L_subfr == 2 * L_SUBFR) + { + nBits = st->acelp_cfg.fixed_cdk_index[i_subfr / L_subfr]; + + if (nBits == 8) + { + acelp_1t64(hBstr, dn, h1, code, y2, L_subfr); + } + else + { + acelp_fast(hBstr, nBits, dn, cn, h1, code, y2, L_subfr); + } + } + else if ((st->idchan == 1 && st->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR] <= 7) || (st->idchan == 0 && st->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR] <= 3)) + { + if (st->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR] == 0) + { + acelp_1t64(hBstr, dn, h1, code, y2, L_subfr); + } + else + { + acelp_fast(hBstr, st->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR], dn, cn, h1, code, y2, L_SUBFR); + } + } + else + { + E_ACELP_4t(dn, cn, h1, Rw, acelpautoc, code, st->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR], prm, L_frame, last_L_frame, st->total_brate, i_subfr, cmpl_flag); + + wordcnt = ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR]) >> 4; + bitcnt = ACELP_FIXED_CDK_BITS(st->acelp_cfg.fixed_cdk_index[i_subfr / L_SUBFR]) & 15; + + for (i = 0; i < wordcnt; i++) + { + push_indice(hBstr, IND_ALG_CDBK_4T64, prm[i], 16); + } + if (bitcnt) + { + push_indice(hBstr, IND_ALG_CDBK_4T64, prm[i], bitcnt); + } + + /* Generate weighted code */ + set_f(y2, 0.0f, L_SUBFR); + for (i = 0; i < L_SUBFR; i++) + { + /* Code is sparse, so check which samples are non-zero */ + if (code[i] != 0) + { + for (k = 0; k < L_SUBFR - i; k++) + { + y2[i + k] += code[i] * h1[k]; + } + } + } + } + } + else + { + set_f(code, 0.0f, L_SUBFR); + set_f(y2, 0.0f, L_SUBFR); + } + } +#ifdef DEBUGGING + else + { + IVAS_ERROR(IVAS_ERR_INTERNAL_FATAL, "invalid mode for acelp frame!\n"); + } +#endif +#endif + } + ELSE + { + nBits = st_fx->acelp_cfg.fixed_cdk_index[shr(i_subfr, 6)]; + move16(); + + + IF(EQ_16(nBits, 7)) + { + acelp_1t64_fx(hBstr, dn, h2, code, y2, L_SUBFR); + } + ELSE IF(EQ_16(nBits, 12)) + { + acelp_2t32_fx(hBstr, dn, h2, code, y2); + } + ELSE + { + *unbits = add(*unbits, acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, nBits, cmpl_flag, Opt_AMR_WB)); + move16(); + } + } + } + ELSE + { + IF (EQ_32(core_brate,ACELP_6k60)) + { + acelp_2t32_fx(hBstr, dn, h2, code, y2 ); + } + ELSE IF( (EQ_32(core_brate,ACELP_8k85))) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 20, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_12k65)) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 36, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_14k25)) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 44, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_15k85)) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 52, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_18k25)) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 64, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_19k85)) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 72, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_23k05)) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 88, cmpl_flag, Opt_AMR_WB ); + } + ELSE IF( EQ_32(core_brate,ACELP_23k85)) + { + acelp_4t64_fx(hBstr, dn, cn, h2, Rw, acelpautoc, code, y2, 88, 1, Opt_AMR_WB); + } + } + + + /*----------------------------------------------------------------* + * Pitch sharpening + *----------------------------------------------------------------*/ + + cb_shape_fx( 1, 1, 0, sharpFlag, 0, g1, g2, p_Aq, code, tilt_code, shr(add(pt_pitch,26),6), 0 , L_subfr); + + return stack_pulses; + +} diff --git a/lib_enc/isf_enc_amr_wb_fx.c b/lib_enc/isf_enc_amr_wb_fx.c index de6a422f3da6ec5b8467fc31016e8dc82ee5aad0..405bcac3eb9f14e11b762c10857447030469235d 100644 --- a/lib_enc/isf_enc_amr_wb_fx.c +++ b/lib_enc/isf_enc_amr_wb_fx.c @@ -34,7 +34,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 */ /*-----------------------------------------------------------------* @@ -72,7 +74,7 @@ static Word16 sub_VQ_fx(Word16 *x, const Word16 *dico, const Word16 dim, const W *-------------------------------------------------------------------*/ 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 */ @@ -84,7 +86,7 @@ void isf_enc_amr_wb_fx( * ISF quantization of SID frames *---------------------------------*/ - IF(EQ_32(st->core_brate, SID_1k75)) + IF(EQ_32(st->core_brate_fx, SID_1k75)) { qisf_ns_28b_fx(hBstr, isf_new); @@ -97,17 +99,17 @@ void isf_enc_amr_wb_fx( } /* check resonance for pitch clipping algorithm */ - gp_clip_test_isf_fx(st->element_mode, st->core_brate, isf_new, st->clip_var_fx, 1); + gp_clip_test_isf_fx(st->element_mode, st->core_brate_fx, isf_new, st->clip_var_fx, 1); /*---------------------------------------* * ISF quantization of all other frames *---------------------------------------*/ - IF(EQ_32(st->core_brate, ACELP_6k60)) + IF(EQ_32(st->core_brate_fx, ACELP_6k60)) { qisf_2s_36b_fx(hBstr, isf_new, 4, st->mem_AR_fx, st->mem_MA_fx); } - ELSE IF(GE_32(st->core_brate, ACELP_8k85)) + ELSE IF(GE_32(st->core_brate_fx, ACELP_8k85)) { qisf_2s_46b_fx(hBstr, isf_new, 4, st->mem_AR_fx, st->mem_MA_fx); } @@ -132,7 +134,7 @@ void isf_enc_amr_wb_fx( /*------------------------------------------------------------------* * Calculate ISF stability (distance between old ISF and current ISF) *------------------------------------------------------------------*/ - IF(NE_32(st->last_core_brate, SID_1k75)) + IF(NE_32(st->last_core_brate_fx, SID_1k75)) { st->stab_fac_fx = lsf_stab_fx(isf_new, st->lsf_old_fx, 1, L_FRAME); } diff --git a/lib_enc/ivas_init_enc.c b/lib_enc/ivas_init_enc.c index ba4e0eaa1a6904be7ca1891195168396f66f28f2..8374b834d73ff8095feaa467032eb7ad8927bdb9 100644 --- a/lib_enc/ivas_init_enc.c +++ b/lib_enc/ivas_init_enc.c @@ -276,6 +276,38 @@ void copy_encoder_config( return; } +void copy_encoder_config_fx( + Encoder_Struct *st_ivas, /* i : IVAS encoder structure */ + Encoder_State_fx *st_fx, /* o : encoder state structure */ + const int16_t flag_all /* i : flag 1==update all, 0=partial update*/ +) +{ + if ( flag_all ) + { + st_fx->input_Fs_fx = st_ivas->hEncoderConfig->input_Fs; + + st_fx->last_codec_mode = st_ivas->last_codec_mode; + st_fx->last_total_brate_fx = st_ivas->hEncoderConfig->last_ivas_total_brate; + + st_fx->Opt_DTX_ON_fx = st_ivas->hEncoderConfig->Opt_DTX_ON; + + st_fx->last_Opt_SC_VBR_fx = st_ivas->hEncoderConfig->last_Opt_SC_VBR; + } + + st_fx->Opt_AMR_WB_fx = st_ivas->hEncoderConfig->Opt_AMR_WB; + st_fx->Opt_SC_VBR_fx = st_ivas->hEncoderConfig->Opt_SC_VBR; + + st_fx->codec_mode = st_ivas->codec_mode; + st_fx->max_bwidth_fx = st_ivas->hEncoderConfig->max_bwidth; + + st_fx->Opt_RF_ON = st_ivas->hEncoderConfig->Opt_RF_ON; + st_fx->rf_fec_offset = st_ivas->hEncoderConfig->rf_fec_offset; + st_fx->rf_fec_indicator = st_ivas->hEncoderConfig->rf_fec_indicator; + + st_fx->element_mode = st_ivas->hEncoderConfig->element_mode_init; + + return; +} /*------------------------------------------------------------------------- * ivas_initialize_handles_enc() @@ -476,11 +508,16 @@ ivas_error ivas_init_encoder( st_ivas->nCPE = 0; st_ivas->nchan_transport = 1; sce_id = 0; - if ( ( error = create_sce_enc( st_ivas, sce_id, ivas_total_brate ) ) != IVAS_ERR_OK ) { return error; } +#ifndef EVS_FLOAT_ENC + if ( ( error = create_evs_sce_enc( st_ivas, sce_id ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif /* prepare stereo downmix for EVS */ if ( hEncoderConfig->stereo_dmx_evs == 1 ) diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index db4960d4ac67f70ac50709d3b3ba8c6af90217cb..f22f115b12f770883e3e690fb47b654245474d21 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -31,11 +31,14 @@ *******************************************************************************************************/ #include +#include #include "options.h" #include "cnst.h" #include "ivas_cnst.h" #include "rom_com.h" #include "prot.h" +#include "prot_fx2.h" +#include "prot_fx_enc.h" #include "ivas_prot.h" #include "ivas_rom_com.h" #include "wmc_auto.h" @@ -46,6 +49,7 @@ * * Single Channel Element (SCE) encoding routine *-------------------------------------------------------------------*/ +Indice ind_list[MAX_NUM_INDICES]; ivas_error ivas_sce_enc( Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ @@ -289,6 +293,7 @@ ivas_error create_sce_enc( { SCE_ENC_HANDLE hSCE; Encoder_State *st; + ivas_error error; error = IVAS_ERR_OK; @@ -349,15 +354,84 @@ ivas_error create_sce_enc( { return error; } - hSCE->hCoreCoder[0] = st; st_ivas->hSCE[sce_id] = hSCE; return error; } +#ifndef EVS_FLOAT_ENC +/*------------------------------------------------------------------------- + * create_evs_sce_enc() + * + * Create, allocate and initialize EVS encoder SCE handle + *-------------------------------------------------------------------------*/ + +ivas_error create_evs_sce_enc( + Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + const int16_t sce_id /* i : SCE # identifier */ +) +{ + SCE_ENC_HANDLE hSCE = st_ivas->hSCE[sce_id]; + Encoder_State_fx *st_fx; + + ivas_error error; + error = IVAS_ERR_OK; + + /*-----------------------------------------------------------------* + * Core Coder, 1 instance: allocate and initialize + *-----------------------------------------------------------------*/ + if ( ( st_fx = (ENC_CORE_HANDLE_FX) malloc( sizeof( Encoder_State_fx ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); + } + memset( st_fx, 0, sizeof( Encoder_State_fx ) ); + st_fx->input_Fs_fx = 16000; + st_fx->total_brate_fx = ACELP_12k65; + + st_fx->Opt_AMR_WB_fx = 0; + st_fx->Opt_RF_ON = 0; + st_fx->rf_fec_offset = 0; + st_fx->rf_fec_indicator = 1; + + st_fx->max_bwidth_fx = SWB; + st_fx->interval_SID_fx = FIXED_SID_RATE; + st_fx->var_SID_rate_flag_fx = 1; + st_fx->Opt_HE_SAD_ON_fx = 0; + st_fx->Opt_SC_VBR_fx = 0; + st_fx->last_Opt_SC_VBR_fx = 0; + st_fx->bitstreamformat = G192; + + // copy_encoder_config_fx( st_ivas, st_fx, 1 ); + st_fx->max_bwidth_fx = st_ivas->hEncoderConfig->max_bwidth; + st_fx->Opt_DTX_ON_fx = st_ivas->hEncoderConfig->Opt_DTX_ON; + st_fx->var_SID_rate_flag_fx = st_ivas->hEncoderConfig->var_SID_rate_flag; + st_fx->interval_SID_fx = st_ivas->hEncoderConfig->interval_SID; + st_fx->Opt_RF_ON = st_ivas->hEncoderConfig->Opt_RF_ON; + st_fx->rf_fec_indicator = st_ivas->hEncoderConfig->rf_fec_indicator; + st_fx->rf_fec_offset = st_ivas->hEncoderConfig->rf_fec_offset; + // st_fx->bitstreamformat = st->bitstreamformat; + st_fx->total_brate_fx = st_ivas->hEncoderConfig->ivas_total_brate; + st_fx->Opt_SC_VBR_fx = st_ivas->hEncoderConfig->Opt_SC_VBR; + st_fx->last_Opt_SC_VBR_fx = st_ivas->hEncoderConfig->last_Opt_SC_VBR; + st_fx->Opt_AMR_WB_fx = st_ivas->hEncoderConfig->Opt_AMR_WB; + st_fx->input_Fs_fx = st_ivas->hEncoderConfig->input_Fs; + st_fx->codec_mode = st_ivas->codec_mode; + st_fx->last_codec_mode = st_ivas->last_codec_mode; + st_fx->input_frame_fx = extract_l( Mult_32_16( st_fx->input_Fs_fx, 0x0290 ) ); + if ( ( error = init_encoder_fx( st_fx ) ) != IVAS_ERR_OK ) + { + return error; + } + st_fx->hBstr->ind_list_fx = ind_list; + // st_fx->hBstr->ind_list_fx = st->hBstr->ind_list; + reset_indices_enc_fx( st_fx->hBstr ); + hSCE->hCoreCoder_fx[0] = st_fx; + return error; +} +#endif /*------------------------------------------------------------------------- * destroy_sce_enc() * @@ -377,6 +451,13 @@ void destroy_sce_enc( destroy_core_enc( st ); st = NULL; } +#ifndef EVS_FLOAT_ENC + if ( st != NULL ) + { + destroy_encoder_fx( hSCE->hCoreCoder_fx[0] ); + st = NULL; + } +#endif ivas_destroy_MD_bstr_enc( &( hSCE->hMetaData ) ); diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index eae9c41dd020fc758c4ca5c1b8182be8c9e9c663..969bc165db19f5a4904f5a122567fb16d032af7d 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -694,6 +694,9 @@ typedef struct ivas_spar_enc_lib_t int32_t core_nominal_brate; /* Nominal bitrate for core coding */ FRONT_VAD_ENC_HANDLE hFrontVad; /* front-VAD handle */ ENC_CORE_HANDLE hCoreCoderVAD; /* core-coder handle for front-VAD module */ +#ifndef EVS_FLOAT_ENC + ENC_CORE_HANDLE_FX hCoreCoderVAD_fx; /* core coder handle */ +#endif int16_t spar_reconfig_flag; int16_t front_vad_flag; @@ -962,6 +965,9 @@ typedef struct sce_enc_data_structure BSTR_ENC_HANDLE hMetaData; /* Metadata bitstream handle */ ENC_CORE_HANDLE hCoreCoder[1]; /* core coder handle */ +#ifndef EVS_FLOAT_ENC + ENC_CORE_HANDLE_FX hCoreCoder_fx[1]; /* core coder handle */ +#endif } SCE_ENC_DATA, *SCE_ENC_HANDLE; diff --git a/lib_enc/lead_indexing_fx.c b/lib_enc/lead_indexing_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..1a3b74ac7664c5dd093b86cf18fa29d3e5fc31ed --- /dev/null +++ b/lib_enc/lead_indexing_fx.c @@ -0,0 +1,198 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include "options.h" /* Compilation switches */ +#include "cnst.h" +//#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ +static Word16 fcb_encode_pos_fx(const Word16 pos_vector[], const Word16 pulse_num, + const Word16 pos_num); + +/*-------------------------------------------------------------------* + * re8_compute_base_index_fx: + * + * Compute base index for RE8 + *-------------------------------------------------------------------*/ +void re8_compute_base_index_fx( + const Word16 *x, /* i : Elemen of Q2, Q3 or Q4 */ + const Word16 ka, /* i : Identifier of the absolute leader related to x */ + UWord16 *I /* o : index */ +) +{ + Word16 i, j, k1 ,m; + Word16 setor_8p[8], setor_8p_temp[8]; + Word16 sign_8p; + Word16 code_level, code_area; + + const Word16 *a1,*a2; + Word16 code_index; + UWord16 offset; + + a1 = vals_a[ka]; + move16(); + a2 = vals_q[ka]; + move16(); + + /* the sign process */ + + sign_8p = 0; + move16(); + m = 0; + move16(); + code_index = 0; + move16(); + k1 = a2[0]; + move16(); + + test(); + test(); + IF (EQ_16(a2[1], 2)&&s_xor(a1[0],1)&&sub(ka,5)) + { + FOR (i=0; i<8; i++) + { + IF (x[i] != 0) + { + sign_8p = shl(sign_8p, 1); + setor_8p_temp[m] = i; + move16(); + m = add(m, 1); + } + + IF (x[i] < 0) + { + sign_8p = add(sign_8p, 1); + } + } + + code_index = fcb_encode_pos_fx(setor_8p_temp,8,m); + code_index = add(shl(code_index,k1),sign_8p); + + offset = Is[ka]; + move16(); + + *I = extract_l(L_add(offset, (Word32) code_index)); + } + ELSE + { + FOR (i=0; i<8; i++) + { + setor_8p[i] = abs_s(x[i]); + + IF (x[i] != 0) + { + sign_8p = shl(sign_8p, 1); + m = add(m, 1); + } + + IF (x[i] < 0) + { + sign_8p = add(sign_8p, 1); + } + } + + IF (NE_16(k1, m)) + { + sign_8p = shr(sign_8p, 1); + } + + /* code level by level */ + + code_level = sub(a2[1], 1); + code_area = 8; + move16(); + + IF (NE_16(a2[2], 1)) + { + FOR (j=0; j #include #include @@ -48,6 +50,7 @@ struct IVAS_ENC { Encoder_Struct *st_ivas; ENC_CORE_HANDLE hCoreCoder; + ENC_CORE_HANDLE_FX hCoreCoder_fx; bool isConfigured; bool switchingActive; /* flag for configuration changes during encoding - currently only used with mono */ int16_t Opt_RF_ON_loc; @@ -56,6 +59,7 @@ struct IVAS_ENC bool maxBandwidthUser; /* Was a specific max bandwith selected by the user? */ IVAS_ENC_BANDWIDTH newBandwidthApi; /* maximum encoded bandwidth, as set on API level */ bool extMetadataApi; /* External metadata requested, to be checked against current bit rate */ + bool isRawFile; }; /*---------------------------------------------------------------------* @@ -104,6 +108,7 @@ ivas_error IVAS_ENC_Open( } ( *phIvasEnc )->hCoreCoder = NULL; + ( *phIvasEnc )->hCoreCoder_fx = NULL; ( *phIvasEnc )->isConfigured = false; ( *phIvasEnc )->switchingActive = false; ( *phIvasEnc )->maxBandwidthUser = false; @@ -430,7 +435,7 @@ ivas_error IVAS_ENC_ConfigureForAmbisonics( const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ const IVAS_ENC_SBA_ORDER order, /* i : order of the Ambisonics input */ const bool isPlanar, /* i : if true, input is treated as planar Ambisonics */ - const bool Opt_PCA_ON /* i : PCA option flag */ + const bool Opt_PCA_ON /* i : PCA option flag */ ) { ENCODER_CONFIG_HANDLE hEncoderConfig; @@ -929,6 +934,9 @@ static ivas_error configureEncoder( if ( hEncoderConfig->ivas_format == MONO_FORMAT ) { hIvasEnc->hCoreCoder = st_ivas->hSCE[0]->hCoreCoder[0]; /* Note: this is needed for switching in EVS mono */ +#ifndef EVS_FLOAT_ENC + hIvasEnc->hCoreCoder_fx = st_ivas->hSCE[0]->hCoreCoder_fx[0]; +#endif } else { @@ -1059,7 +1067,6 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( { Encoder_Struct *st_ivas; ENCODER_CONFIG_HANDLE hEncoderConfig; - ENC_CORE_HANDLE hCoreCoder; int16_t i; int16_t n, ch; ivas_error error; @@ -1073,7 +1080,10 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( st_ivas = hIvasEnc->st_ivas; hEncoderConfig = st_ivas->hEncoderConfig; - hCoreCoder = hIvasEnc->hCoreCoder; + ENC_CORE_HANDLE hCoreCoder = hIvasEnc->hCoreCoder; +#ifndef EVS_FLOAT_ENC + ENC_CORE_HANDLE_FX hCoreCoder_fx = hIvasEnc->hCoreCoder_fx; +#endif if ( inputBufferSize != getInputBufferSize( st_ivas ) ) { @@ -1102,7 +1112,16 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( if ( hEncoderConfig->ivas_total_brate == ACELP_13k20 && hEncoderConfig->ivas_format == MONO_FORMAT ) { st_ivas->codec_mode = MODE1; - reset_rf_indices( hCoreCoder->hRF, hCoreCoder->L_frame, &( hCoreCoder->rf_target_bits_write ) ); +#ifndef EVS_FLOAT_ENC + if ( hIvasEnc->isRawFile ) + { + reset_rf_indices_fx( hCoreCoder_fx ); + } + else +#endif + { + reset_rf_indices( hCoreCoder->hRF, hCoreCoder->L_frame, &( hCoreCoder->rf_target_bits_write ) ); + } } hEncoderConfig->Opt_RF_ON = 0; hEncoderConfig->rf_fec_offset = 0; @@ -1114,7 +1133,16 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( st_ivas->codec_mode = MODE2; if ( hEncoderConfig->Opt_RF_ON == 0 && hEncoderConfig->ivas_format == MONO_FORMAT ) { - reset_rf_indices( hCoreCoder->hRF, hCoreCoder->L_frame, &( hCoreCoder->rf_target_bits_write ) ); +#ifndef EVS_FLOAT_ENC + if ( hIvasEnc->isRawFile ) + { + reset_rf_indices_fx( hCoreCoder_fx ); + } + else +#endif + { + reset_rf_indices( hCoreCoder->hRF, hCoreCoder->L_frame, &( hCoreCoder->rf_target_bits_write ) ); + } } hEncoderConfig->Opt_RF_ON = 1; hEncoderConfig->rf_fec_offset = hIvasEnc->rf_fec_offset_loc; @@ -1184,8 +1212,11 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( /* set pointers to the new buffers of indices in each element */ for ( n = 0; n < st_ivas->nSCE; n++ ) { - st_ivas->hSCE[n]->hCoreCoder[0]->hBstr->ind_list = st_ivas->ind_list; - st_ivas->hSCE[n]->hCoreCoder[0]->hBstr->ivas_ind_list_zero = &st_ivas->ind_list; + if ( !( hIvasEnc->hCoreCoder == NULL && hEncoderConfig->ivas_format == MONO_FORMAT ) ) + { + st_ivas->hSCE[n]->hCoreCoder[0]->hBstr->ind_list = st_ivas->ind_list; + st_ivas->hSCE[n]->hCoreCoder[0]->hBstr->ivas_ind_list_zero = &st_ivas->ind_list; + } if ( st_ivas->hSCE[n]->hMetaData != NULL ) { @@ -1212,14 +1243,32 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( if ( hIvasEnc->switchingActive && hEncoderConfig->ivas_format == MONO_FORMAT ) { - copy_encoder_config( st_ivas, hCoreCoder, 0 ); +#ifndef EVS_FLOAT_ENC + if ( hIvasEnc->isRawFile ) + { + copy_encoder_config_fx( st_ivas, hCoreCoder_fx, 0 ); + } + else +#endif + { + copy_encoder_config( st_ivas, hCoreCoder, 0 ); + } hEncoderConfig->last_ivas_total_brate = hEncoderConfig->ivas_total_brate; } /* run the main encoding routine */ if ( hEncoderConfig->ivas_format == MONO_FORMAT ) /* EVS mono */ { - hCoreCoder->total_brate = hEncoderConfig->ivas_total_brate; /* needed in case of bitrate switching */ +#ifndef EVS_FLOAT_ENC + if ( hIvasEnc->isRawFile ) + { + hCoreCoder_fx->total_brate_fx = hEncoderConfig->ivas_total_brate; /* needed in case of bitrate switching */ + } + else +#endif + { + hCoreCoder->total_brate = hEncoderConfig->ivas_total_brate; /* needed in case of bitrate switching */ + } if ( hEncoderConfig->stereo_dmx_evs == 1 ) { @@ -1229,13 +1278,35 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( if ( hEncoderConfig->Opt_AMR_WB ) { - amr_wb_enc( hCoreCoder, inputBuffer, st_ivas->mem_hp20_in[0], inputBufferSize ); +#ifndef EVS_FLOAT_ENC + if ( hIvasEnc->isRawFile ) + { + amr_wb_enc_fx( hCoreCoder_fx, inputBuffer, inputBufferSize ); + } + else +#endif + { + amr_wb_enc( hCoreCoder, inputBuffer, st_ivas->mem_hp20_in[0], inputBufferSize ); + } } else { - if ( ( error = evs_enc( hCoreCoder, inputBuffer, st_ivas->mem_hp20_in[0], inputBufferSize ) ) != IVAS_ERR_OK ) +#ifndef EVS_FLOAT_ENC + if ( hIvasEnc->isRawFile ) { - return error; + hCoreCoder_fx->input_frame_fx = inputBufferSize; + if ( ( error = evs_enc_fx( hCoreCoder_fx, inputBuffer, hCoreCoder_fx->mem_hp20_in_fx, inputBufferSize ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else +#endif + { + if ( ( error = evs_enc( hCoreCoder, inputBuffer, st_ivas->mem_hp20_in[0], inputBufferSize ) ) != IVAS_ERR_OK ) + { + return error; + } } } } @@ -1248,8 +1319,19 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( } /* write indices into bitstream buffer */ - write_indices_ivas( st_ivas, outputBitStream, numOutBits ); - +#ifndef EVS_FLOAT_ENC + if ( hEncoderConfig->ivas_format == MONO_FORMAT && hIvasEnc->isRawFile ) + { + /* write indices into bitstream file */ + UWord8 pFrame[( MAX_BITS_PER_FRAME + 7 ) >> 3]; + Word16 pFrame_size = 0; + write_indices_buf_fx( hCoreCoder_fx, hCoreCoder_fx->hBstr, outputBitStream, pFrame, pFrame_size, numOutBits ); + } + else +#endif + { + write_indices_ivas( st_ivas, outputBitStream, numOutBits ); + } /* Reset switching flag before next call - can be set to "true" by some setters */ hIvasEnc->switchingActive = false; @@ -2175,3 +2257,8 @@ static void init_encoder_config( return; } + +void set_raw_file_flag( const IVAS_ENC_HANDLE hIvasEnc, short isRaw ) +{ + hIvasEnc->isRawFile = isRaw; +} \ No newline at end of file diff --git a/lib_enc/lib_enc.h b/lib_enc/lib_enc.h index b57a1375a68e8ee92866b7a53eb8cd2993f3af07..5ecc95c20f4b7a1fe324836b5eae3112fdb3fc80 100644 --- a/lib_enc/lib_enc.h +++ b/lib_enc/lib_enc.h @@ -332,6 +332,8 @@ void IVAS_ENC_PrintDisclaimer( void ); +void set_raw_file_flag( const IVAS_ENC_HANDLE hIvasEnc, short isRaw ); + /* clang-format on */ #endif /* LIB_ENC_H */ diff --git a/lib_enc/long_enr_fx.c b/lib_enc/long_enr_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..1fad3dac49a3f984d034096cf137ab382233cb77 --- /dev/null +++ b/lib_enc/long_enr_fx.c @@ -0,0 +1,139 @@ +/*==================================================================================== + 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 "rom_com.h" +#include "stl.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + + +/*-------------------------------------------------------------------* + * long_enr_fx() + * + * Compute relative energy, long-term average total noise energy and total active speech energy + *-------------------------------------------------------------------*/ +void long_enr_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 Etot, /* i : total channel E (see lib_enc\analy_sp.c) */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + Word16 high_lpn_flag /* i : sp/mus LPN flag */ +#ifdef IVAS_CODE + ,FRONT_VAD_ENC_HANDLE hFrontVad[CPE_CHANNELS], /* i/o: front-VAD handles */ + const int16_t n_chan, /* i : number of channels */ + const int16_t localVAD_HE_SAD_LR[CPE_CHANNELS], /* i : HE-SAD flag without hangover LR channels */ + const float Etot_LR[CPE_CHANNELS] /* i : total channel energy LR channels */ +#endif +) +{ + Word16 tmp; + Word16 alpha; + NOISE_EST_HANDLE hNoiseEst = st_fx->hNoiseEst; + + /*-----------------------------------------------------------------* + * Compute long term estimate of total noise energy + * and total active speech energy + *-----------------------------------------------------------------*/ +#ifdef IVAS_CODE + Word16 n; + if (hFrontVad != NULL) + { + if (hFrontVad[0]->ini_frame < 4) + { + for (n = 0; n < n_chan; n++) + { + hFrontVad[n]->lp_noise = hFrontVad[n]->hNoiseEst->totalNoise; + tmp = hFrontVad[n]->lp_noise + 10.0f; + + if (hFrontVad[n]->lp_speech < tmp) + { + hFrontVad[n]->lp_speech = tmp; + } + } + } + else + { + float smooth_prev, smooth_curr; + + if (hFrontVad[0]->ini_frame < 150) + { + smooth_prev = 0.95f; + smooth_curr = 0.05f; + } + else + { + smooth_prev = 0.98f; + smooth_curr = 0.02f; + } + + for (n = 0; n < n_chan; n++) + { + hFrontVad[n]->lp_noise = smooth_prev * hFrontVad[n]->lp_noise + smooth_curr * hFrontVad[n]->hNoiseEst->totalNoise; + + if (localVAD_HE_SAD_LR[n] && !high_lpn_flag) + { + if ((hFrontVad[n]->lp_speech - Etot_LR[n]) < 10.0f) + { + hFrontVad[n]->lp_speech = 0.98f * hFrontVad[n]->lp_speech + 0.02f * Etot_LR[n]; + } + else + { + hFrontVad[n]->lp_speech = hFrontVad[n]->lp_speech - 0.05f; + } + } + } + } + } + else +#endif + { + IF(LT_16(st_fx->ini_frame_fx, 4)) + { + st_fx->lp_noise_fx = hNoiseEst->totalNoise_fx; + move16(); + tmp = add(st_fx->lp_noise_fx, 2560); /*10.0 in Q8*/ + st_fx->lp_speech_fx = s_max(st_fx->lp_speech_fx, tmp); + } + ELSE + { + /* if ( st->ini_frame < 150 ) { + st->lp_noise = 0.95f * st->lp_noise + 0.05f * st->totalNoise; + } else { + st->lp_noise = 0.98f * st->lp_noise + 0.02f * st->totalNoise; + } */ + alpha = 655; + move16();/* 0.02 Q15 */ + if (LT_16(st_fx->ini_frame_fx, 150)) /* should match HE_LT_CNT_INIT_FX */ + { + alpha = 1638; + move16(); /* 0.05 Q15 */ + } + st_fx->lp_noise_fx = noise_est_AR1_Qx(hNoiseEst->totalNoise_fx, st_fx->lp_noise_fx , alpha); /* Q8 state, alpha in Q15 */ + + test(); + IF((localVAD_HE_SAD != 0) + && (high_lpn_flag == 0)) + { + IF(LT_16(sub(st_fx->lp_speech_fx, Etot), 10 * 256)) /* 10.0 in Q8 */ + { + /* st->lp_speech = 0.98f * st->lp_speech + 0.02f * Etot; */ + st_fx->lp_speech_fx = noise_est_AR1_Qx(Etot, st_fx->lp_speech_fx, 655); /* Q8 state, 0.02 in Q15 */ + } + ELSE + { + st_fx->lp_speech_fx = sub(st_fx->lp_speech_fx, 13); /* st->lp_speech = st->lp_speech - 0.05f; linear decay*/ + } + } + + } + } + + /*-----------------------------------------------------------------* + * Initialize parameters for energy tracking and signal dynamics + *-----------------------------------------------------------------*/ + return; +} diff --git a/lib_enc/lp_exc_e_fx.c b/lib_enc/lp_exc_e_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..b118da9d705335728d1dd112389cdf4764b6b454 --- /dev/null +++ b/lib_enc/lp_exc_e_fx.c @@ -0,0 +1,429 @@ +/*==================================================================================== + 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 "basop_util.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define GAIN_PIT_MAX 19661 +#define HIGH_LTP_LIMIT 1.0f +#define LOW_LTP_LIMIT 0.55f + +/*-------------------------------------------------------------------* + * Local function prototypes + *-------------------------------------------------------------------*/ + +static Word16 adpt_enr_fx(const Word16 codec_mode, const Word16 *exc, const Word16 *h1, Word16 *y1, const Word16 L_subfr, + Word16 *gain, Word16 *g_corr, const Word16 clip_gain, const Word16 *xn, Word16 *xn2, Word16 *exp_ener + ,Word16 use_prev_sf_pit_gain); + +/*-------------------------------------------------------------------* + * function lp_filt_exc_enc_fx() + * + * Low-pass filtering of the adaptive excitation + * Innovation target construction + * Gain quantization limitation + *-------------------------------------------------------------------*/ + +Word16 lp_filt_exc_enc_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */ + const Word16 coder_type, /* i : coding type Q0 */ + const Word16 i_subfr, /* i : subframe index Q0 */ + Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */ + const Word16 *h1, /* i : weighted filter input response Q(14+shift) */ + const Word16 *xn, /* i : target vector Q_new-1+shift */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */ + Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */ + const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */ + const Word16 L_frame, /* i : frame size Q0 */ + Word16 *g_corr, /* o : ACELP correlation values mant/exp */ + const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + Word16 *lp_flag /* i/o: mode selection Q0 */ +) +{ + Word16 gain1, gain2, g_corr2[4], exc_tmp[5*L_SUBFR], xn2_tmp[5*L_SUBFR]; + Word16 y1_tmp[5*L_SUBFR]; + Word16 select, i, exp_ener, exp_ener1; + Word16 wtmp, wtmp1; + Word32 Ltmp; + + Word16 use_prev_sf_pit_gain = 0; + + gain1 = 0; + move16(); + gain2 = 0; + move16(); + + /*----------------------------------------------------------------* + * Find the target energy if the adaptive exc. is not filtered + *----------------------------------------------------------------*/ + test(); + IF( EQ_16(codec_mode,MODE2)&&EQ_16(coder_type,100)) + { + use_prev_sf_pit_gain = 1; + } + exp_ener = 0; + move16(); + wtmp = 0; + move16(); + test(); + IF( EQ_16(*lp_flag,FULL_BAND)||EQ_16(*lp_flag,NORMAL_OPERATION)) + { + wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain); + move16(); + + } + + /*----------------------------------------------------------------* + * Filter the adaptive excitation + * Find the target energy if the adapt. exc. is filtered + *----------------------------------------------------------------*/ + + exp_ener1 = 0; + move16(); + wtmp1 = 0; + move16(); + test(); + IF( (EQ_16(*lp_flag,LOW_PASS))||(EQ_16(*lp_flag,NORMAL_OPERATION))) + { + test(); + IF( EQ_16(codec_mode,MODE2)&&EQ_16(L_frame,L_FRAME16k)) + { + FOR ( i=0; i and -2 ) + *-------------------------------------------------------------------*/ + +Word16 corr_xy1_fx( /* o : pitch gain (0..GAIN_PIT_MAX) */ + const Word16 xn_1[], /* i : target signal */ + const Word16 y1_1[], /* i : filtered adaptive codebook excitation */ + Word16 g_corr[], /* o : correlations and -2 */ + const Word16 L_subfr, /* i : vector length */ + const Word16 norm_flag /* i : flag for constraining pitch contribution */ +#ifdef BASOP_NOGLOB + ,Flag *Overflow_out /* o : propagating the Overflow flag to upper level */ +#endif +) +{ + Word16 i; + Word16 tmp, xx, xy, yy, exp_xy, exp_xx, exp_yy, exp_div, gain, gain_p_snr; + Word32 Ltmp1, Ltmp2; + Word16 xn[L_FRAME16k], y1[L_FRAME16k]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*----------------------------------------------------------------* + * Find the ACELP correlations and the pitch gain + *----------------------------------------------------------------*/ + + /* Compute scalar product */ + Copy(xn_1, xn, L_subfr); + Copy(y1_1, y1, L_subfr); + Overflow = 0; + move16(); +#ifdef BASOP_NOGLOB /* Critical Overflow */ + Ltmp1 = Dot_product12_o(y1, y1, L_subfr, &exp_yy, &Overflow); + *Overflow_out |= Overflow; + move16(); +#else + Ltmp1 = Dot_product12(y1, y1, L_subfr, &exp_yy); +#endif + IF( Overflow ) + { + FOR(i = 0; i < L_subfr; i++) + { + xn[i] = mult_r(xn_1[i], 4096); + move16(); + y1[i] = mult_r(y1_1[i], 4096); + move16(); + } + + Ltmp1 = Dot_product12(y1, y1, L_subfr, &exp_yy); + exp_yy = add(exp_yy, 6); + yy = extract_h(Ltmp1); + + /* Compute scalar product */ + Ltmp2 = Dot_product12(xn, y1, L_subfr, &exp_xy); + xy = extract_h(Ltmp2); + exp_xy = add(exp_xy, 6); + + g_corr[0] = yy; + move16(); + g_corr[1] = exp_yy; + move16(); + /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function */ + g_corr[2] = xy; + move16(); + g_corr[3] = exp_xy; + move16(); + } + ELSE + { + yy = extract_h(Ltmp1); + /* Ltmp1 = L_shr(Ltmp1, sub(30, exp_yy));*/ + + /* Compute scalar product */ +#ifdef BASOP_NOGLOB + Ltmp2 = Dot_product12_o(xn, y1, L_subfr, &exp_xy, &Overflow); + *Overflow_out |= Overflow; + move16(); +#else + Ltmp2 = Dot_product12(xn, y1, L_subfr, &exp_xy); +#endif + xy = extract_h(Ltmp2); + /* Ltmp2 = L_shr(Ltmp2, sub(30, exp_xy));*/ + + g_corr[0] = yy; + move16(); + g_corr[1] = exp_yy; + move16(); + /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function*/ + g_corr[2] = xy; + move16(); + g_corr[3] = exp_xy; + move16(); + } + + /* find pitch gain and bound it by [0,GAIN_PIT_MAX] */ + test(); + IF ( xy >= 0 && NE_16(s_or(yy, xy), 16384)) + { + /* compute gain = xy/yy */ + xy = shr(xy, 1); /* be sure that xy < yy */ + gain = div_s(xy, yy); + i = sub(exp_xy, exp_yy); +#ifdef BASOP_NOGLOB + gain = shl_o(gain, i, &Overflow); /* saturation can occur here */ + *Overflow_out |= Overflow; + move16(); +#else /* BASOP_NOGLOB */ + gain = shl(gain, i); /* saturation can occur here */ +#endif + + gain = s_max(gain, 0); + gain = s_min(gain, GAIN_PIT_MAX); /* 1.2 in Q14 */ + } + ELSE + { + gain = 0; + move16(); + } + + /* Limit the energy of pitch contribution */ + IF (norm_flag) + { +#ifdef BASOP_NOGLOB + /*that part of code seems never used*/ +#endif + /* Compute scalar product */ + xx = round_fx(Dot_product12_offs(xn, xn, L_subfr, &exp_xx, 1)); + + /* gain_p_snr = sqrt(/) */ + tmp = BASOP_Util_Divide1616_Scale(xx, yy, &exp_div); + exp_xx = add(sub(exp_xx, exp_yy), exp_div); + tmp = Sqrt16(tmp, &exp_xx); + + /* Note: shl works as shl or shr. */ + exp_xx = sub(exp_xx,1); + BASOP_SATURATE_WARNING_OFF_EVS + gain_p_snr = round_fx(L_shl(Mpy_32_16_1( 1717986944l/*ACELP_GAINS_CONST Q31*/, tmp), exp_xx)); + BASOP_SATURATE_WARNING_ON_EVS + + gain = s_min(gain, gain_p_snr); + } + + return gain; +} diff --git a/lib_enc/lsf_enc_fx.c b/lib_enc/lsf_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..9d4eb808c5f732634240acf722db621e5087c15a --- /dev/null +++ b/lib_enc/lsf_enc_fx.c @@ -0,0 +1,2620 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "rom_enc.h" +#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 MIN_LOG_FX 0 +#define MIN_LOG_VAL_FX -15360 /* -60.0f in Q8 */ +#define MSVQ_MAXCNT 3000 +#define MAXINT32 MAX_32 + +/*---------------------------------------------------------------------* +* Local function prototypes +*---------------------------------------------------------------------*/ + +static void lsfq_CNG_fx(BSTR_ENC_HANDLE hBstr, const Word16 *lsf, const Word16 *wghts, Word16 *qlsf, Word32 *p_offset_scale1, Word32 * p_offset_scale2, + Word16 * p_no_scales ); + +static Word32 vq_lvq_lsf_enc( Word16 pred_flag, Word16 mode, Word16 u[], Word16 * levels, Word16 stages, Word16 w[], Word16 Idx[], const Word16 * lsf, + const Word16 * pred, Word32 p_offset_scale1[][MAX_NO_SCALES+1], Word32 p_offset_scale2[][MAX_NO_SCALES+1], + Word16 p_no_scales[][2], Word16 *resq, Word16 * lsfq ); + +static void lsf_mid_enc_fx(BSTR_ENC_HANDLE hBstr, int16_t nb_bits, const Word16 int_fs, const Word16 qlsp0[], const Word16 qlsp1[], Word16 lsp[], + const Word16 coder_type, const Word16 bwidth, Word32 Bin_Ener_old[], Word32 Bin_Ener[], Word16 Q_ener, Word16 ppp_mode, Word16 nelp_mode); + +/*===========================================================================*/ +/* FUNCTION : lsf_enc_fx() */ +/*---------------------------------------------------------------------------*/ +/* PURPOSE : Quantization of LSF vector */ +/*---------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) L_frame : length of the frame */ +/* _ (Word16) coder_type : coding type */ +/*---------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) Aq : LP filter coefficient Q12 */ +/* _ (Word16*) lsf_ne w : LP filter coefficient Q(x2.56) */ +/* _ (Word16) st_fx->stab_fac_fx : LSF stability factor Q15 */ +/*---------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Struct) st_fx : state structure */ +/* _ (Word16*) lsp_new : LP filter coefficient Q15 */ +/* _ (Word16*) lsp_mid : LP filter coefficient Q15 */ +/* _ (Word16[]) st_fx->mem_AR_fx : AR memory of LSF quantizer */ +/* (past quantized LSFs without mean) x2.56 */ +/* _ (Word16[]) st_fx->clip_var_fx : pitch gain clipping memory x2.56*/ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*===========================================================================*/ +void lsf_enc_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + Word16 *lsf_new, /* o : quantized LSF vector */ + Word16 *lsp_new, /* i/o: LSP vector to quantize/quantized */ + Word16 *lsp_mid, /* i/o : mid-frame LSP vector */ + Word16 *Aq, /* o : quantized A(z) for 4 subframes */ + const Word16 Nb_ACELP_frames, + const Word16 tdm_low_rate_mode, /* i : secondary channel low rate mode flag */ + const Word16 GSC_IVAS_mode, /* i : GSC IVAS mode */ +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + const float tdm_lsfQ_PCh[M], /* i : Q LSFs for primary channel */ +#endif + const Word16 Q_new +) +{ + Word16 nBits = 0; + Word16 int_fs; + Word16 force_sf = 0; + Word16 fec_lsf[M], stab, i; +#if 0 + Word16 no_param_lpc; +#endif +#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + (void)tdm_low_rate_mode; +#endif +#ifdef IVAS_CODE + Word16 param_lpc[NPRM_LPC_NEW]; +#endif + Word32 L_tmp; + Word16 coder_type, ppp_mode, nelp_mode; + + test(); + IF (EQ_32(st_fx->core_brate_fx, SID_2k40) || EQ_32(st_fx->core_brate_fx, SID_1k75)) + { + coder_type = INACTIVE; + move16(); + } + ELSE + { + coder_type = st_fx->coder_type; + move16(); + + } + + test(); + if (EQ_16(coder_type, AUDIO) && GSC_IVAS_mode > 0) + { + coder_type = GENERIC; + move16(); + } + +#if 0 + no_param_lpc = 0; +#endif + move16(); + + IF (st_fx->Opt_SC_VBR_fx) + { + ppp_mode = st_fx->hSC_VBR->ppp_mode; + nelp_mode = st_fx->hSC_VBR->nelp_mode; + move16();move16(); + } + ELSE + { + ppp_mode = 0; + nelp_mode = 0; + move16(); move16(); + } + + /* initialize */ +#if 0 + int_fs = INT_FS_16k_FX; + move16(); + if( EQ_16(L_frame, L_FRAME)) + { + int_fs = INT_FS_FX; + move16(); + } +#else + assert(st_fx->sr_core <= 32000); + int_fs = extract_l(st_fx->sr_core); + move32(); +#endif + /* convert LSPs to LSFs */ + lsp2lsf_fx( lsp_new, lsf_new, M, int_fs); + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf_fx(st_fx->element_mode, lsf_new, st_fx->clip_var_fx, 0 ); + + /* Find the number of bits for LSF quantization */ + nBits = 0; move16(); + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + nBits = LSF_BITS_CNG; + move16(); + } + ELSE + { + test(); + IF ( (nelp_mode == 0) && (ppp_mode == 0) ) + { + nBits = st_fx->acelp_cfg.lsf_bits; + move16(); + } + ELSE IF ( EQ_16(nelp_mode, 1)) + { + nBits = 30; + move16(); + + if ( EQ_16(st_fx->bwidth_fx,NB)) + { + nBits = 32; + move16(); + } + } + ELSE IF ( EQ_16(ppp_mode, 1)) + { + nBits = 26; + move16(); + } + } + force_sf = 0; move16(); + /* first three ACELP frames after an HQ frame shall be processed only with safety-net quantizer */ + test(); + if( LT_16(Nb_ACELP_frames, 3) && NE_32(st_fx->core_brate_fx, SID_2k40) ) + { + force_sf = 1; + move16(); + } + + /* in case of unstable filter in decoder FEC, choose safety-net to help FEC */ + IF ( EQ_16(st_fx->next_force_safety_net_fx ,1)) + { + force_sf = 1; + move16(); + st_fx->next_force_safety_net_fx = 0; + move16(); + } + + /*-------------------------------------------------------------------------------------* + * Frame end LSF quantization + *-------------------------------------------------------------------------------------*/ +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + lsf_end_enc_fx(st_fx, lsf_new, lsf_new, nBits, coder_type, Q_new + QSCALE - 2, + force_sf, NULL, NULL, NULL, st_fx->coder_type_raw_fxtdm_lsfQ_PCh); +#else + lsf_end_enc_fx( st_fx, lsf_new, lsf_new, nBits, coder_type, Q_new+QSCALE-2, + force_sf, NULL, NULL, NULL, st_fx->coder_type_raw_fx); +#endif + /* convert quantized LSFs back to LSPs */ + lsf2lsp_fx( lsf_new, lsp_new, M, int_fs); + + test(); + IF ( EQ_16(st_fx->last_core_fx, HQ_CORE)&&EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* don't use old LSF values if this is the first ACELP frame after HQ frames */ + Copy( lsf_new, st_fx->lsf_old_fx, M ); + } + /* set seed_acelp used in UC mode */ +#ifdef IVAS_CODE + test(); + IF (EQ_16(coder_type, UNVOICED) && GT_16(st_fx->element_mode, EVS_MONO)) + { + st_fx->seed_acelp = 0; move16(); + FOR (i = no_param_lpc - 1; i >= 0; i--) + { + /* rightshift before *seed_acelp+param_lpc[i] to avoid overflows*/ + st->seed_acelp = (int16_t)((((st->seed_acelp) >> 1) + param_lpc[i]) * 31821L + 13849L); + } + } +#endif + IF ( EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + /* return if SID frame (conversion to A(z) done in the calling function) */ + return; + } + + /*-------------------------------------------------------------------------------------* + * FEC - enforce safety-net in the next frame in case of unstable filter + *-------------------------------------------------------------------------------------*/ + + IF( NE_16(st_fx->last_L_frame_fx, st_fx->L_frame_fx)) + { + /* FEC - in case of core switching, use old LSFs */ + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsfoldbfi0_fx, M ); + Copy( st_fx->lsf_old_fx, st_fx->lsf_adaptive_mean_fx, M ); + } + + FEC_lsf_estim_enc_fx( st_fx, fec_lsf ); + + /* in case of FEC in decoder - calculate LSF stability */ + stab = lsf_stab_fx( lsf_new, fec_lsf, 0, st_fx->L_frame_fx ); + + test(); + test(); + test(); + /* If decoder FEC frame may be unstable force safety-net usage */ + IF ( (EQ_16(st_fx->L_frame_fx, L_FRAME16k))&&(LT_16(stab,STAB_FAC_LIMIT_FX))&&(EQ_16(coder_type,GENERIC))) + { + st_fx->next_force_safety_net_fx = 1; + move16(); + } + ELSE IF((LT_16(stab, STAB_FAC_LIMIT_FX))&&(EQ_16(st_fx->clas_fx,VOICED_CLAS)||(LT_16(st_fx->clas_fx,VOICED_CLAS)&&EQ_16(coder_type,AUDIO)))) + { + st_fx->next_force_safety_net_fx = 1; + move16(); + } + + + /* FEC - update adaptive LSF mean vector */ + FOR (i=0; ilsfoldbfi1_fx[i], 10922); /*Q(x2.56+16)*/ + L_tmp = L_mac(L_tmp, st_fx->lsfoldbfi0_fx[i], 10922); /*Q(x2.56+16)*/ + st_fx->lsf_adaptive_mean_fx[i] = round_fx(L_tmp); /*Q(x2.56)*/ + } + + /* FEC - update LSF memories */ + Copy( st_fx->lsfoldbfi0_fx, st_fx->lsfoldbfi1_fx, M ); + Copy( lsf_new, st_fx->lsfoldbfi0_fx, M ); + + + /*-------------------------------------------------------------------------------------* + * Mid-frame LSF encoding + * LSP interpolation and conversion of LSPs to A(z) + *-------------------------------------------------------------------------------------*/ + if(st_fx->rate_switching_reset) + { + /*extrapolation in case of unstable LSF convert*/ + Copy( lsp_new, st_fx->lsp_old_fx, M ); + Copy( lsf_new, st_fx->lsf_old_fx, M ); + } + /* Mid-frame LSF encoding */ + lsf_mid_enc_fx(st_fx->hBstr, st_fx->acelp_cfg.mid_lsf_bits, int_fs, st_fx->lsp_old_fx, lsp_new, lsp_mid, coder_type, st_fx->bwidth_fx, st_fx->Bin_E_old_fx, st_fx->Bin_E_fx, Q_new+QSCALE-2, ppp_mode, nelp_mode); + + test(); + IF ( EQ_16(st_fx->last_core_fx,HQ_CORE)&&EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* don't use old LSP/LSF values if this is the first ACELP frame after HQ frames */ + Copy( lsp_mid, st_fx->lsp_old_fx, M ); + lsp2lsf_fx( lsp_mid, st_fx->lsf_old_fx, M, int_fs ); + } + + /* LSP interpolation and conversion of LSPs to A(z) */ +#ifdef ADD_LRTD + test(); + IF (EQ_16(tdm_low_rate_mode, 1) && GT_16(coder_type, UNVOICED)) + { + IF (EQ_16(st_fx->active_cnt_fx, 1)) + { + Copy(lsp_mid, st_fx->lsp_old_fx, M); + lsp2lsf_fx(lsp_mid, st_fx->lsf_old_fx, M, int_fs); + Copy(lsp_new, lsp_mid, M); + } + + /* LSP interpolation and conversion of LSPs to A(z) - two-subframe mode */ + int_lsp4_fx(st_fx->L_frame_fx, st_fx->lsp_old_fx, lsp_mid, lsp_new, Aq, M, -2); + } + ELSE +#endif + { + int_lsp4_fx(st_fx->L_frame_fx, st_fx->lsp_old_fx, lsp_mid, lsp_new, Aq, M, 0); + } + /*------------------------------------------------------------------* + * Check LSF stability (distance between old LSFs and current LSFs) + *------------------------------------------------------------------*/ + IF (NE_32(st_fx->core_brate_fx, SID_2k40)) + { + st_fx->stab_fac_fx = lsf_stab_fx(lsf_new, st_fx->lsf_old_fx, 0, st_fx->L_frame_fx); + } + return; +} + + +/*-------------------------------------------------------------------* +* lsfq_CNG_fx() +* +* LSF quantizer for SID frames (uses 29 bits, 4 for VQ, 25 for LVQ) +* Note: +* The sampling frequency of the LP-CNG frame can be determined by checking the value of the highest order LSF +* coefficient (last coefficient of lsf). If the last LSF coefficient (lsf[M-1]) is larger than 6350 +* the decoded frame is WB2 with sampling rate of 16 kHz, otherwise it is sampled at 12.8kHz and contains +* either NB or WB LSF data. +*-------------------------------------------------------------------*/ + +static void lsfq_CNG_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *lsf, /*x2.56 unquantized LSF vector */ + const Word16 *wghts, /*Q10 LSF weights */ + Word16 *qlsf, /*x2.56 quantized LSF vecotor */ + Word32 *p_offset_scale1, + Word32 *p_offset_scale2, + Word16 *p_no_scales +) +{ + Word16 i, j, idx_cv, idx_lvq[3]; + Word32 min_dist, dist; + Word16 dd[M], ddq[M]; + const Word16 *p_cb; + Word16 first_cb, last_cb; + Word16 idx_lead_cng[2], idx_scale_cng[2]; + Word16 tmp; + + idx_cv = 0; + move16(); + + /* quantize first stage with 4 bits + The sampling frequency of the LP-CNG frame can be determined by checking the value of the highest order LSF + coefficient (last coefficient of lsf). If the last LSF coefficient (lsf[M-1]) is larger than 6350 + the decoded frame is WB2 with sampling rate of 16 kHz, otherwise it is sampled at 12.8kHz and contains + either NB or WB LSF data. */ + IF(GT_16(lsf[M - 1], WB_LIMIT_LSF_FX)) /* 16kHz sampled LSF vector*/ + { + p_cb = &CNG_SN1_fx[0]; + move16(); + first_cb = 0; + move16(); + last_cb = 6; + move16(); + } + ELSE /* 12.8kHz sampled LSF vector*/ + { + p_cb = &CNG_SN1_fx[6*M]; + move16(); + first_cb = 6; + move16(); + last_cb = M; + move16(); + } + + + min_dist = L_add(MAXINT32, 0); + FOR ( i = first_cb; i < last_cb; i++ ) + { + tmp = sub(*p_cb,shl(lsf[0],1)); /*x2.56 */ + dist = Mult_32_16(L_mult0(wghts[0], *p_cb),tmp); /*Q8 + x2.56 -Q15 + x2.56 = Q-7 + x2.56+x.256 */ + p_cb++; + FOR (j=1; jhBstr; +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + Word16 pred3[M]; + Word16 dummy, dummy_v[5]; +#endif + + flag_1bit_gran = (Word16)GT_16(st->element_mode, EVS_MONO); + + nBits = nBits_in; + move16(); + /* Update LSF coder_type for LSF quantizer for some special cases */ + test(); + test(); + test(); +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + IF(EQ_16(coder_type_org, GENERIC) && EQ_32(st->sr_core,INT_FS_16k) && EQ_16(st->codec_mode, MODE1) && (st->idchan == 0)) /* this bit is used only for primary channel or mono */ +#else + IF(EQ_16(coder_type_org, GENERIC) && EQ_32(st->sr_core, INT_FS_16k) && EQ_16(st->codec_mode, MODE1)) +#endif + { + IF (EQ_16(coder_type_raw, VOICED)) + { + coder_type = VOICED; + move16(); /* Reflect Inactive mode */ + if (EQ_16(flag_1bit_gran, 1)) + { + nBits = sub(nBits, 1); /* This is for real Generic*/ + } + } + ELSE + { + nBits = sub(nBits,1); /* This is for real Generic*/ + coder_type = coder_type_org; + move16(); + } + } + ELSE + { + coder_type = coder_type_org; + move16(); + } + + /*----------------------------------------------------------------------------------- -* + * Calculate the number of stages and levels for each stage based on allowed bit budget + * Set absolute threshold for codebook-type decision logic depending on signal bandwidth + *------------------------------------------------------------------------------------ -*/ + IF ( EQ_16(st->bwidth_fx, NB)) + { + abs_threshold = L_add(SFNETLOWLIMIT_NB, 0); + } + ELSE + { + abs_threshold = L_add(SFNETLOWLIMIT_WB, 0); + } + /* Calculate LSF weighting coefficients */ + Unified_weighting_fx(&st->Bin_E_fx[L_FFT/2], Q_ener, lsf, wghts, (Word16)EQ_16(st->bwidth_fx, NB), (Word16)EQ_16(coder_type,UNVOICED),st->sr_core,M); + + /*--------------------------------------------------------------------------------* + * LSF quantization of SID frames + *--------------------------------------------------------------------------------*/ + IF ( EQ_32(st->core_brate_fx, SID_2k40)) + { + lsfq_CNG_fx(hBstr, lsf, wghts, qlsf, &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->no_scales_fx[0][0] ); + sort_fx( qlsf, 0, M-1 ); + reorder_lsf_fx( qlsf, MODE1_LSF_GAP_FX, M, st->sr_core ); + + return; + } + /* Find allowed predictor mode for current coder_type. (SN only (0), SN/AR switched (2) or MA predictive (1) */ + find_pred_mode(&predmode, coder_type, st->bwidth_fx, st->sr_core, &mode_lvq, &mode_lvq_p,st->total_brate_fx); + + /*----------------------------------------------------------------* + * Calculate number of stages and levels for each stage based on the allowed bit allocation + * (subtract one bit for LSF predictor selection) + *----------------------------------------------------------------*/ + lsf_allocate_fx( sub(nBits, shr(predmode,1)), mode_lvq, mode_lvq_p, &stages0, &stages1, levels0, levels1, bits0, bits1); + + + /*--------------------------------------------------------------------------------* + * LSF quantization of all other frames but SID frames + * Select safety-net or predictive mode + *--------------------------------------------------------------------------------*/ + + Err[0] = MAXINT32; + move32(); + Err[1] = MAXINT32; + move32(); + /* for mem_MA update */ + FOR (i=0; imem_MA_fx[i])); + move16(); + } +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + /* TD stereo SCh: perform intra-frame prediction with pulling-to-mean */ + if (st->tdm_LRTD_flag == 0 && st->idchan == 1 && tdm_lsfQ_PCh != NULL) + { + /* if secondary channel predmode is set to be > 2 */ + predmode += 3; + + tdm_SCh_LSF_intra_pred(st->element_brate, tdm_lsfQ_PCh, pred3); + } +#endif + IF ( predmode == 0 ) + { + /* Subtract only mean */ + Copy(ModeMeans_fx[mode_lvq], pred0, M); + Vr_subt(lsf, pred0, Tmp, M); + + /* LVQ quantization (safety-net only) */ + Err[0] = vq_lvq_lsf_enc(0, mode_lvq, Tmp, levels0, stages0,wghts, Idx0, lsf, pred0, + st->offset_scale1_fx,st->offset_scale2_fx, st->no_scales_fx, resq, lsfq); + safety_net = 1; + move16(); + st->pstreaklen_fx = 0; + move16();/* predictive LSF quantizer streak is ended with safety-net */ + } + ELSE IF (EQ_16(predmode, 1)) /* only MA prediction */ + { + Vr_subt(lsf, pred1, Tmp1, M); + Err[1] = vq_lvq_lsf_enc(2, mode_lvq_p, Tmp1, levels1, stages1, wghts, Idx1, lsf, pred1, + st->offset_scale1_p_fx,st->offset_scale2_p_fx,st->no_scales_p_fx,resq, lsfq ); + + safety_net = 0; + move16(); + } + ELSE +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + PMT("LSF_RE_USE_SECONDARY_CHANNEL CODE IS MISSING ") + { + if (predmode == 2) +#endif + { + /* Adaptive scaling factor (multiplier) is updated in order to reduce the amount of consecutive predictive frames in + case of possible frame erasure. AR-predictive usage for VOICED mode is allowed to be higher than other modes. */ + test(); + test(); + test(); + IF ( ((GT_16(st->pstreaklen_fx, (STREAKLEN+3))) && (EQ_16(coder_type,VOICED))) || ((GT_16(st->pstreaklen_fx,(STREAKLEN))) && (NE_16(coder_type,VOICED)))) + { + /* update the adaptive scaling factor to become smaller with increasing number of concecutive predictive frames. */ + st->streaklimit_fx = mult(st->streaklimit_fx,STREAKMULT_FX); + move16(); + } + + IF (st->pstreaklen_fx == 0 ) + { + /* reset the consecutive AR-predictor multiplier */ + st->streaklimit_fx = 32767; /*1.0 in Q15 */ move16(); + } + + /* VOICED_WB@16kHz */ + test(); + IF ( EQ_32(st->sr_core, INT_FS_16k)&&EQ_16(coder_type,VOICED) && flag_1bit_gran == 0) + { + /* Subtract mean and AR prediction */ + Copy( ModeMeans_fx[mode_lvq], pred0, M ); + /* subtract only mean */ + Vr_subt(lsf, pred0, Tmp, M); + + FOR (i = 0; i < M; i++) + { + /* subtract mean and AR prediction */ + pred2[i] = mult(Predictors_fx[mode_lvq_p][i],sub(st->mem_AR_fx[i],pred0[i])); + Tmp2[i] = sub(Tmp[i], pred2[i]); + pred2[i] = add(pred2[i], pred0[i]); + } + + /* select safety_net or predictive */ + safety_net = qlsf_Mode_Select_fx( wghts, Tmp2, st->streaklimit_fx, OP_LOOP_THR_HVO ); + IF ( EQ_16(force_sf, 1)) + { + safety_net = 1; + move16(); + } + + IF ( safety_net ) + { + /* Safety-net - BC-TCQ quantization : SN */ + Err[0] = qlsf_ARSN_tcvq_Enc_16k_fx( Tmp, lsfq, TCQIdx0, wghts, sub(nBits,1), safety_net); + st->pstreaklen_fx = 0; + move16(); + } + ELSE + { + /* predictive - BC-TCQ quantization : AR */ + Err[1] = qlsf_ARSN_tcvq_Enc_16k_fx( Tmp2, lsfq, TCQIdx0, wghts, sub(nBits,1), safety_net); + st->pstreaklen_fx =add(st->pstreaklen_fx,1); + } + } + /* all other frames (not VOICED@16kHz) */ + ELSE + { + /* Subtract mean and AR prediction */ + Copy( ModeMeans_fx[mode_lvq], pred0, M ); + /* subtract only mean */ + Vr_subt(lsf, pred0, Tmp, M); + + FOR (i = 0; i < M; i++) + { + /* subtract mean and AR prediction */ + pred2[i] = add(pred0[i],mult(Predictors_fx[mode_lvq_p][i],sub(st->mem_AR_fx[i],pred0[i]))); + Tmp2[i] = sub(lsf[i], pred2[i]); + } + + /* safety-net */ + Err[0] = vq_lvq_lsf_enc(0, mode_lvq, Tmp, levels0, stages0, wghts, Idx0, lsf, pred0, st->offset_scale1_fx,st->offset_scale2_fx,st->no_scales_fx, resq, lsfq); + /* Predictive quantizer is calculated only if it can be selected */ + test(); + IF (!force_sf || GT_32(Err[0],abs_threshold)) + { + Err[1] = vq_lvq_lsf_enc(2, mode_lvq_p, Tmp2, levels1, stages1, wghts, Idx1, lsf, pred2, + st->offset_scale1_p_fx, st->offset_scale2_p_fx, st->no_scales_p_fx, &resq[M], &lsfq[M]); + + } + test(); + test(); + /* Select whether to use safety-net (non-predictive) or predictive LSF quantizer. The decision is based on following: + if the non-predictive (safety-net) quantization error (Err[0]) is low enough (spectral distortion is low) it is selected + or if the predictively quantized error (Err[1]) is by at least adaptive margin smaller than non-predictive quantizer. + or if the in case of frame erasure the resulting concealed predictive LSF would be unstable safety-net is selected */ + IF ( force_sf || LT_32(Mult_32_16(Err[0],(st->streaklimit_fx)),L_add(Err[1],Mult_32_16(Err[1],PREFERSFNET_FX))) || LT_32(Err[0],abs_threshold)) + { + safety_net = 1; + move16(); + st->pstreaklen_fx = 0; + move16(); /* Reset the consecutive predictive frame counter */ + } + ELSE + { + safety_net = 0; + move16(); /* Increase the consecutive predictive frame counter by one */ + st->pstreaklen_fx = add(st->pstreaklen_fx,1); + } + } + } +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + PMT("LSF_RE_USE_SECONDARY_CHANNEL CODE IS MISSING ") + else /* of "if (predmode==2)" */ + { + mvr2r(ModeMeans[mode_lvq], pred0, M); + + if (predmode == 4) + { + mode_lvq_p = 9; /* force to Generic WB with AR*/ + } + + for (i = 0; i < M; i++) + { + /* subtract mean and AR prediction */ + pred2[i] = pred0[i] + Predictors[mode_lvq_p][i] * (st->mem_AR[i] - pred0[i]); + Tmp[i] = lsf[i] - pred2[i]; + Tmp2[i] = lsf[i] - pred3[i]; + } + + /* Adaptive scaling factor (multiplier) is updated in order to reduce the amount of consecutive predictive frames in + case of possible frame erasure. AR-predictive usage for VOICED mode is allowed to be higher than other modes. */ + if (st->pstreaklen > (STREAKLEN)) + { + /* update the adaptive scaling factor to become smaller with increasing number of concecutive predictive frames. */ + st->streaklimit *= STREAKMULT; + } + + if (st->pstreaklen == 0) + { + /* reset the adaptive scaling factor */ + st->streaklimit = 1.0f; + } + + /* intra pred */ + /* use G AR pred for the intra mode (as a safety mode, this is why the indexes 0/1 are interchanged)*/ + + lsf_allocate(nBits - 1, mode_lvq, 9, &stages1, &stages0, levels1, levels0, bits1, bits0); + + Err[0] = vq_lvq_lsf_enc(2, 9, Tmp2, levels0, stages0, wghts, Idx0, lsf, pred3, &resq[M], &lsfq[M]); + + if (force_sf) + { + safety_net = 1; /* intra-frame prediction */ + st->pstreaklen = 0; /* Reset the consecutive predictive frame counter */ + } + else + { /* try also the inter frame prediction */ + + /* AR inter-frame prediction */ + lsf_allocate(nBits - 1, mode_lvq, mode_lvq_p, &dummy, &stages1, dummy_v, levels1, dummy_v, bits1); + + + Err[1] = vq_lvq_lsf_enc(2, mode_lvq_p, Tmp, levels1, stages1, wghts, Idx1, lsf, pred2, resq, lsfq); + + if (Err[0] * (st->streaklimit) < PREFERSFNET * Err[1]) + { + safety_net = 1; + st->pstreaklen = 0; /* Reset the consecutive predictive frame counter */ + } + else + { + safety_net = 0; + (st->pstreaklen)++; /* Increase the consecutive predictive frame counter by one */ + } + } + } + } +#endif /*--------------------------------------------------------------------------* + * Write indices to array + *--------------------------------------------------------------------------*/ + + IF (EQ_16(st->codec_mode, MODE1) && EQ_16(st->core_fx, ACELP_CORE)) + { + /* write coder_type bit for VOICED@16kHz or GENERIC@16kHz */ + test(); +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + IF(EQ_16(coder_type_org, GENERIC)&&EQ_32(st->sr_core,INT_FS_16k) && (st->idchan == 0)) +#else + IF(EQ_16(coder_type_org, GENERIC) && EQ_32(st->sr_core, INT_FS_16k) ) +#endif + { + /* VOICED =2 and GENERIC=3, so "coder_type-2" means VOICED =0 and GENERIC=1*/ + push_indice_fx( hBstr, IND_LSF_PREDICTOR_SELECT_BIT, sub(coder_type,2), 1 ); + } + + /* write predictor selection bit */ +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + IF(GE(predmode, 2)) +#else + IF ( EQ_16(predmode, 2)) +#endif + { + push_indice_fx( st->hBstr, IND_LSF_PREDICTOR_SELECT_BIT, safety_net, 1 ); + } + + test(); + IF ( EQ_16(coder_type, VOICED) && EQ_32(st->sr_core,INT_FS_16k) && flag_1bit_gran == 0) + { + /* BC-TCVQ (only for VOICED@16kHz) */ + TCQIdx = &TCQIdx0[1]; + Bit_alloc1 = &BC_TCVQ_BIT_ALLOC_40B[1]; + FOR( i=0; i<(M/2)+3; i++ ) + { + push_indice_fx( hBstr, IND_LSF, TCQIdx[i], Bit_alloc1[i]); + } + } + ELSE + { + cumleft = nBits; + move16(); +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + IF(GE(predmode, 2)) +#else + IF (EQ_16( predmode, 2 )) +#endif + { + /* subtract predictor selection bit */ + cumleft = sub(nBits, 1); + } + + IF ( safety_net ) + { + stages = stages0; + move16(); + Idx = Idx0; + move16(); + bits = bits0; + move16(); + } + ELSE + { + stages = stages1; + move16(); + Idx = Idx1; + move16(); + bits = bits1; + move16(); + } + + tmp = sub(stages,1); + FOR ( i=0; i 0 ) + { + indice[i] = Idx[i]; + move16(); + + IF ( GT_16(cumleft, LEN_INDICE)) + { + num_bits = LEN_INDICE; + move16(); + } + ELSE + { + num_bits = cumleft; + move16(); + } + + cumleft = sub(cumleft, num_bits); + push_indice_fx( hBstr, IND_LSF, indice[i], num_bits ); + i=add(i,1); + } + } + } + ELSE + { + test(); + IF ( EQ_16(coder_type, VOICED)&&EQ_32(st->sr_core,INT_FS_16k)) + { + /* BC-TCVQ (only for VOICED@16kHz) */ + /* Number of quantization indices */ + *no_indices = 10; + move16(); + FOR(i=0; i<*no_indices; i++) + { + lpc_param[i] = TCQIdx0[i]; + move16(); + bits_param_lpc[i] = BC_TCVQ_BIT_ALLOC_40B[i]; + move16(); + } + } + ELSE + { + /* Number of quantization indices */ + + /* there are 31 bits */ + IF (EQ_16(safety_net, 1)) + { + Idx = Idx0; + move16(); + *no_indices = add(stages0 ,1); + FOR( i=0; i0; i--) + { + tmp = sub(i,1); + lpc_param[i] = lpc_param[tmp]; + move16(); + bits_param_lpc[i] = bits_param_lpc[tmp]; + move16(); + } + lpc_param[0] = safety_net; + move16();/* put the safety net info on the last param */ + bits_param_lpc[0] = 1; + move16(); + *no_indices = add(*no_indices,1); + } + } + } + + + /*--------------------------------------------------------------------------* + * De-quantize encoded LSF vector + *--------------------------------------------------------------------------*/ + + IF ( safety_net ) + { + /* Safety-net */ + test(); + IF ( EQ_16(coder_type, VOICED) && EQ_32(st->sr_core,INT_FS_16k) && flag_1bit_gran == 0) + { + /* BC-TCQ */ + Copy( lsfq, st->mem_MA_fx, M ); + Vr_add( lsfq, pred0, qlsf, M ); + } + ELSE + { +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + if (st->tdm_LRTD_flag == 0 && st->idchan == 1 && tdm_lsfQ_PCh != NULL) + { + /* intra mode*/ + vq_dec_lvq(0, qlsf, &indice[0], stages0, M, 9, /*mode_lvq_p,*/ levels0[stages0 - 1]); + v_add(qlsf, pred3, qlsf, M); + v_sub(qlsf, pred1, st->mem_MA, M); + } + else +#endif + { + vq_dec_lvq_fx(1, qlsf, &indice[0], stages0, M, mode_lvq, levels0[stages0 - 1], + &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->offset_scale1_p_fx[0][0], &st->offset_scale2_p_fx[0][0], + &st->no_scales_fx[0][0], &st->no_scales_p_fx[0][0]); + Vr_add(qlsf, pred0, qlsf, M); + Vr_subt(qlsf, pred1, st->mem_MA_fx, M); + } + } + } + ELSE + { + test(); + IF ( EQ_16(coder_type, VOICED) && EQ_32(st->sr_core,INT_FS_16k) && flag_1bit_gran == 0) + { + /* BC-TCVQ */ + Copy( lsfq, st->mem_MA_fx, M ); + Vr_add( lsfq, pred2, qlsf, M ); + } + ELSE + { + /* LVQ */ + vq_dec_lvq_fx( 0, qlsf, &indice[0], stages1, M, mode_lvq_p, levels1[stages1-1], + &st->offset_scale1_fx[0][0], &st->offset_scale2_fx[0][0], &st->offset_scale1_p_fx[0][0], + &st->offset_scale2_p_fx[0][0], &st->no_scales_fx[0][0], &st->no_scales_p_fx[0][0] ); + IF (EQ_16(predmode,1)) + { + Copy(qlsf, st->mem_MA_fx, M); + Vr_add( qlsf, pred1, qlsf, M ); + } + ELSE + { + Vr_add( qlsf, pred2, qlsf, M ); + Vr_subt(qlsf, pred1, st->mem_MA_fx, M); + } + } + } + + /* Sort the quantized vector to ascending order */ + sort_fx( qlsf, 0, M-1 ); + + /* Verify stability by adding minimum separation */ + reorder_lsf_fx( qlsf, MODE1_LSF_GAP_FX, M, st->sr_core ); + + /* Update AR-predictor memories */ + Copy( qlsf, st->mem_AR_fx, M ); + return; +} + + + + +/*-------------------------------------------------------------------* +* first_VQstages() +* +* +*-------------------------------------------------------------------*/ + +static void first_VQstages( + const Word16 * const *cb, + Word16 u[], /* i : vector to be encoded (prediction and mean removed) */ + Word16 *levels, /* i : number of levels in each stage */ + Word16 stagesVQ, /* i : number of stages */ + Word16 w[], /* i : weights */ + Word16 N, /* i : vector dimension */ + Word16 max_inner, /* i : maximum number of swaps in inner loop */ + Word16 indices_VQstage[] +) +{ + Word16 resid_buf[2*LSFMBEST*M], *resid[2]; + Word32 dist_buf[2*LSFMBEST], *dist[2], en; + Word32 f_tmp, L_tmp, L_tmp1, *pTmp32; + Word16 Tmp[M], *pTmp, cs; + Word16 *pTmp_short, idx_buf[2*LSFMBEST*MAX_VQ_STAGES], parents[LSFMBEST], counter=0, j, + m, s,c, c2, p_max, *indices[2]; + Word16 maxC = LSFMBEST; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*float dd[16];*/ + const Word16 *cb_stage, *cbp; + + /* Set pointers to previous (parent) and current node (parent node is indexed [0], current node is indexed [1]) */ + indices[0] = idx_buf; + move16(); + indices[1] = idx_buf + maxC*stagesVQ; + move16(); + resid[0] = resid_buf; + move16(); + resid[1] = resid_buf + maxC*N; + move16(); + dist[0] = dist_buf; + move16(); + dist[1] = dist_buf + maxC; + move16(); + + set16_fx( idx_buf, 0, (const Word16)(2*stagesVQ*maxC) ); + set16_fx( parents, 0, maxC ) ; + + /* Set up inital distance vector */ + L_tmp = L_deposit_l(0); + FOR( j=0; j0) + { + /* first VQ stages */ + first_VQstages( cb, u, levels, stagesVQ, w, M, MSVQ_MAXCNT, indices_firstVQ ); + } + + + FOR ( i=0; i= 0; stage --) + { + bestCodeword[stage] = codeWord[stage][prev_state]; + move16(); + bestState[stage] = preState[stage][prev_state]; + move16(); + prev_state = bestState[stage]; + move16(); + } + + FOR (stage = 0; stage < 4; stage ++) + { + bestCodeword[stage + 4] = blockCodeword[fBlock][stage]; + move16(); + } + + return fBlock; +} + +static void quantEnc_fx( + Word16 *y_fx, + Word16 c[], + const Word16 CB_SUB1_fx[][128][2], + const Word16 CB_SUB2_fx[][64][2], + const Word16 CB_SUB3_fx[][32][2], + const Word16 itc_fx[][2][2] +) +{ + Word16 i,j; + Word16 stage; + Word16 pred_fx[N_DIM], Y_fx[8][2]; + + /* stage #1 */ + Y_fx[0][0] = CB_SUB1_fx[0][c[0]][0]; + move16(); + Y_fx[0][1] = CB_SUB1_fx[0][c[0]][1]; + move16(); + + /* stage #2 */ + pred_fx[0] = add(mult_r(itc_fx[0][0][0], Y_fx[0][0]), mult_r(itc_fx[0][0][1], Y_fx[0][1])); + move16(); + pred_fx[1] = add(mult_r(itc_fx[0][1][0], Y_fx[0][0]), mult_r(itc_fx[0][1][1], Y_fx[0][1])); + move16(); + Y_fx[1][0] = add(CB_SUB1_fx[1][c[1]][0], pred_fx[0]); + move16(); + Y_fx[1][1] = add(CB_SUB1_fx[1][c[1]][1], pred_fx[1]); + move16(); + + /* stage #3 - #4 */ + FOR (stage = 2; stage < N_STAGE_VQ-4; stage ++) + { + pred_fx[0] = add(mult_r(itc_fx[stage-1][0][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][0][1], Y_fx[stage-1][1])); + move16(); + pred_fx[1] = add(mult_r(itc_fx[stage-1][1][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][1][1], Y_fx[stage-1][1])); + move16(); + + Y_fx[stage][0] = add(CB_SUB2_fx[stage-2][c[stage]][0], pred_fx[0]); + move16(); + Y_fx[stage][1] = add(CB_SUB2_fx[stage-2][c[stage]][1], pred_fx[1]); + move16(); + } + + /* stage #5 - #8 */ + FOR (stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage ++) + { + pred_fx[0] = add(mult_r(itc_fx[stage-1][0][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][0][1], Y_fx[stage-1][1])); + move16(); + pred_fx[1] = add(mult_r(itc_fx[stage-1][1][0], Y_fx[stage-1][0]), mult_r(itc_fx[stage-1][1][1], Y_fx[stage-1][1])); + move16(); + + Y_fx[stage][0] = add(CB_SUB3_fx[stage-4][c[stage]][0], pred_fx[0]); + move16(); + Y_fx[stage][1] = add(CB_SUB3_fx[stage-4][c[stage]][1], pred_fx[1]); + move16(); + } + + /* Transform Vector to Scalar */ + FOR (i = 0; i < N_STAGE_VQ; i++) + { + FOR (j = 0; j < N_DIM; j++) + { + y_fx[i*N_DIM+j] = Y_fx[i][j]; + move16(); + } + } + + return; +} + +static void buildCode_fx( + Word16 *ind, + Word16 fins, + Word16 c[], + Word16 s[] +) +{ + Word16 stage; + Word16 BrIndex[4]; + + set16_fx(BrIndex, 0, (N_STAGE_VQ - 4)); + + + FOR (stage = N_STAGE_VQ - 4; stage >= 1; stage--) + { + if(GT_16(s[stage], 7)) + { + BrIndex[stage-1] =1; + move16(); + } + } + ind[0] = fins; + move16(); + + /* stage #1 - #2 */ + FOR (stage = 0; stage < 2; stage++) + { + ind[stage+1] = shl(BrIndex[stage], 4); + move16(); + ind[stage+1] = add(ind[stage+1], shr(c[stage], 3)); + move16(); + } + + /* stage #3 - #4 */ + FOR (stage = 2; stage < N_STAGE_VQ - 4; stage++) + { + ind[stage+1] = shl(BrIndex[stage], 3); + move16(); + ind[stage+1] = add(ind[stage+1], shr(c[stage], 3)); + move16(); + } + + /* Stage #5 - #8 */ + FOR (stage = N_STAGE_VQ-4; stage < N_STAGE_VQ; stage++) + { + ind[stage+1] = shr(c[stage], 3); + move16(); + } + + return; +} +static void BcTcvq_fx( + Word16 snFlag, + const Word16 *x_fx, + Word16 *y_fx, + const Word16 *weight_fx, + Word16 *ind +) +{ + Word16 X_fx[N_STAGE_VQ][N_DIM], W_fx[N_STAGE_VQ][N_DIM]; + + /* Count Variable */ + Word16 i,j; + + /* TCVQ Structure */ + Word16 stage, state, prev_state; + Word16 preState[N_STAGE_VQ][NUM_STATE]; + Word16 codeWord[N_STAGE_VQ][NUM_STATE]; + Word32 acumDist_fx[N_STAGE_VQ-4][NUM_STATE]; + Word16 inis, fins, ptr_fins; + Word16 fBlock; + Word16 fState[NUM_STATE]; + Word16 fCodeword[4][4]; + Word16 iniBlock[NUM_STATE]; + Word16 blockCodeword[NUM_STATE][4]; + + /* Prediction variable */ + Word16 quant_fx[N_STAGE_VQ][NUM_STATE][N_DIM]; + + /* Distortion variable */ + Word32 minDist_fx; + Word32 fDist_fx; + Word32 blockDist_fx[NUM_STATE]; + + /* Decoding variable */ + Word16 bestCodeword[N_STAGE_VQ]; + Word16 bestState[N_STAGE_VQ]; + + /* Code Share variable */ + const Word16 (*TCVQ_CB_SUB1_fx)[128][2], (*TCVQ_CB_SUB2_fx)[64][2], (*TCVQ_CB_SUB3_fx)[32][2]/**/; + const Word16 (*IntraCoeff_fx)[2][2]; + + /* Memoryless Module */ + IF (snFlag) + { + TCVQ_CB_SUB1_fx = SN_TCVQ_CB_SUB1_fx; + TCVQ_CB_SUB2_fx = SN_TCVQ_CB_SUB2_fx; + TCVQ_CB_SUB3_fx = SN_TCVQ_CB_SUB3_fx; + IntraCoeff_fx = SN_IntraCoeff_fx; + } + ELSE /* Memory Module */ + { + TCVQ_CB_SUB1_fx = AR_TCVQ_CB_SUB1_fx; + TCVQ_CB_SUB2_fx = AR_TCVQ_CB_SUB2_fx; + TCVQ_CB_SUB3_fx = AR_TCVQ_CB_SUB3_fx; + IntraCoeff_fx = AR_IntraCoeff_fx; + } + + /* Transform Scalar to Vector */ + FOR (i = 0; i < N_STAGE_VQ; i++) + { + FOR(j = 0; j < N_DIM; j++) + { + X_fx[i][j] = x_fx[(N_DIM*i) + j]; + move16(); + W_fx[i][j] = weight_fx[(N_DIM*i) + j]; + move16(); + } + } + + /* Initialzie */ + FOR (i=0; i= 0; stage--) + { + prev_state = preState[stage][prev_state]; + move16(); + } + iniBlock[state] = prev_state; + move16(); + } + + /* stage #5 - #8 */ + FOR (state = 0; state < NUM_STATE; state++) + { + inis = iniBlock[state]; + move16(); + ptr_fins = shr(inis, 2); + minDist_fx = L_add(MAX_32, 0); + + FOR (i = 0; i < 4; i++) + { + fins = add(shl(ptr_fins, 2), i); + prev_state = state; + move16(); + fDist_fx = BcTcvq_FixSearch_fx(X_fx, TCVQ_CB_SUB3_fx, fCodeword, quant_fx, FixBranch_tbl, N_STAGE_VQ-4, inis, i, &prev_state, W_fx, IntraCoeff_fx); + + FOR (stage = N_STAGE_VQ-3; stage < N_STAGE_VQ; stage++) + { + fDist_fx = L_add(fDist_fx, BcTcvq_FixSearch_fx(X_fx, TCVQ_CB_SUB3_fx, fCodeword, quant_fx, FixBranch_tbl, stage, inis, i, &prev_state, W_fx, IntraCoeff_fx)); + } + IF (LT_32(fDist_fx, minDist_fx)) + { + minDist_fx = L_add(fDist_fx, 0); + blockDist_fx[state] = minDist_fx; + move32(); + + fState[state] = fins; + move16(); + + blockCodeword[state][0] = fCodeword[i][0]; + move16(); + blockCodeword[state][1] = fCodeword[i][1]; + move16(); + blockCodeword[state][2] = fCodeword[i][2]; + move16(); + blockCodeword[state][3] = fCodeword[i][3]; + move16(); + } + } + } + + /* Select optimal path */ + fBlock = optimalPath_fx(acumDist_fx, blockDist_fx, blockCodeword, bestCodeword, codeWord, bestState, preState); + + /* Select Quantized Value */ + quantEnc_fx(y_fx, bestCodeword, TCVQ_CB_SUB1_fx, TCVQ_CB_SUB2_fx, TCVQ_CB_SUB3_fx, IntraCoeff_fx); + + /* Buid Code for Decoder */ + buildCode_fx(ind, fState[fBlock], bestCodeword, bestState); + + return; +} + +static Word16 SVQ_2d_fx( + Word16 *x_fx, + Word16 *y_fx, + const Word16 *W_fx, + const Word16 CB_fx[][8], + Word16 Size +) +{ + Word16 i, j; + Word16 index = 0; + Word32 distortion_fx; + Word32 temp_fx; + Word16 temp16_fx; + + temp_fx = L_add(MAX_32, 0); + + FOR (i = 0; i < Size; i++) + { + distortion_fx = L_deposit_l(0); + FOR (j = 0; j < 8; j++) + { + temp16_fx = sub(x_fx[j], CB_fx[i][j]); + distortion_fx = L_add(distortion_fx, + L_shr(Mult_32_16(L_mult(temp16_fx, temp16_fx), W_fx[j]), 1)); + } + + IF (LT_32(distortion_fx, temp_fx)) + { + temp_fx = L_add(distortion_fx, 0); + index = i; + move16(); + } + } + + FOR (i = 0; i < M/2; i++) + { + y_fx[i] = CB_fx[index][i]; + move16(); + } + + return index; +} + + +Word32 qlsf_ARSN_tcvq_Enc_16k_fx ( + const Word16 *x_fx, /* i : Vector to be encoded x2.65 */ + Word16 *y_fx, /* o : Quantized LSF vector x2.65 */ + Word16 *indice, /* o : Indices */ + const Word16 *w_fx, /* i : LSF Weights Q8 */ + const Word16 nBits, /* i : number of bits */ + Word16 safety_net /* i : safety_net flag */ +) +{ + Word16 i; + Word16 x_q_fx[M]; + Word16 yy_fx[M]; + Word16 error_svq_fx[M], error_svq_q_fx[M]; + Word16 cl, cs; + Word32 temp_l; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + IF (EQ_16(safety_net, 1)) + { + indice[0] = 1; + move16(); + BcTcvq_fx(1, /*x, x_q, w, */x_fx, x_q_fx, w_fx, &indice[1]); + + IF (GT_16(nBits, 30)) + { + /* SVQ */ + FOR (i = 0; i < M; i++) + { + error_svq_fx[i] = mult_r(sub(x_fx[i], x_q_fx[i]), scale_inv_ARSN_fx[i]); + move16(); + } + + /* 5bits 1st Split VQ for Residual*/ + indice[10] = SVQ_2d_fx(error_svq_fx, error_svq_q_fx, w_fx, AR_SVQ_CB1_fx, 32); + /* 4bits 2nd Split VQ for Residual*/ + indice[11] = SVQ_2d_fx(&error_svq_fx[8], &error_svq_q_fx[8], &w_fx[8], AR_SVQ_CB2_fx, 16 ); + + FOR (i = 0; i < M; i++) + { + x_q_fx[i] = add(x_q_fx[i], extract_h(L_shl(L_mult0(error_svq_q_fx[i], scale_ARSN_fx[i]), 2))); + move16(); + } + } + } + ELSE + { + indice[0] = 0; + move16(); + BcTcvq_fx(0, /*x, x_q, w, */x_fx, x_q_fx, w_fx, &indice[1]); + + IF (GT_16(nBits, 30)) + { + /* SVQ */ + FOR (i = 0; i < M; i++) + { + error_svq_fx[i] = sub(x_fx[i], x_q_fx[i]); + move16(); + } + + /* 5bits 1st Split VQ for Residual*/ + indice[10] = SVQ_2d_fx(error_svq_fx, error_svq_q_fx, w_fx, AR_SVQ_CB1_fx, 32); + /* 4bits 2nd Split VQ for Residual*/ + indice[11] = SVQ_2d_fx(&error_svq_fx[8], &error_svq_q_fx[8], &w_fx[8], AR_SVQ_CB2_fx, 16 ); + + FOR (i = 0; i < M; i++) + { + x_q_fx[i] = add(x_q_fx[i], error_svq_q_fx[i]); + move16(); + } + } + } + + cl = 0; + move16(); + FOR (i = 0; i < M; i ++) + { + yy_fx[i] = sub(x_fx[i], x_q_fx[i]); + move16(); + cl = s_max(cl, abs_s(yy_fx[i])); + } + cs = norm_s(cl); + temp_l = 0; + move16(); + + FOR (i = 0; i < M; i ++) + { + yy_fx[i] = shl(yy_fx[i], cs); + move16(); +#ifdef BASOP_NOGLOB + temp_l = L_mac_o(temp_l, mult(yy_fx[i], shl_o(w_fx[i],2, &Overflow) ), yy_fx[i], &Overflow); +#else /* BASOP_NOGLOB */ + temp_l = L_mac(temp_l, mult(yy_fx[i], shl(w_fx[i],2) ), yy_fx[i]); +#endif /* BASOP_NOGLOB */ + } + cs = shl(cs, 1); + temp_l = L_shr(temp_l, cs); + temp_l = Mult_32_16(temp_l, LSF_1_OVER_256SQ); /* Q-4 */ + + /* Recover the quantized LSF */ + Copy(x_q_fx, y_fx, M); + + return temp_l; +} + +static void FFT_Mid_Interpol_16k_fx( + Word32 Bin_Ener_old[], /* i/o: Old 2nd FFT Bin energy (128) */ + Word32 Bin_Ener[], /* i : Current 2nd FFT Bin energy (128) */ + Word32 Bin_Ener_mid[] /* o : LP weighting filter (numerator) */ +) +{ + Word16 i; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + FOR( i=0; i 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + + tmp = sub(lsf[j],qlsf[j]); + /* err += wghts[j] * ftemp * ftemp; */ + /* tmp is usually very small, we can have some extra precision with very rare saturation */ +#ifdef BASOP_NOGLOB + tmp = shl_o(tmp, 4, &Overflow); + tmp = mult_ro(tmp, tmp, &Overflow); + err = L_mac_o(err, tmp, shl_o(wghts[j],2, &Overflow), &Overflow); +#else /* BASOP_NOGLOB */ + tmp = shl(tmp, 4); + tmp = mult_r(tmp, tmp); + err = L_mac(err, tmp, shl(wghts[j],2) ); +#endif + } + /* err = L_shl(err,Wscale); */ + err = Mult_32_16(err,LSF_1_OVER_256SQ); + /* err = Mult_32_16(err,Wmult); */ + + IF ( LT_32(err,err_min)) + { + err_min = L_add(err, 0); + idx = k; + move16(); + } + k1+=M; + move16(); + } + + /* calculate the quantized LSF vector */ + FOR ( j = 0; j < M; j++ ) + { + /* qlsf[j] = (1.0f - ratio[idx*M+j]) * qlsf0[j] + ratio[idx*M+j] * qlsf1[j]; */ + L_tmp = L_mult(sub(0x2000, ratio[idx*M+j]), qlsf0[j]); + L_tmp = L_mac(L_tmp,ratio[idx*M+j],qlsf1[j]); + qlsf[j] = round_fx(L_shl(L_tmp,2)); + + test(); + test(); + IF ( j > 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + move16(); + } + } + + reorder_lsf_fx( qlsf, LSF_GAP_MID_FX, M, int_fs ); + + /* convert LSFs back to LSPs */ + lsf2lsp_fx( qlsf, lsp, M, int_fs); + push_indice_fx( hBstr, IND_MID_FRAME_LSF_INDEX, idx, nb_bits ); + + return; +} + diff --git a/lib_enc/lsf_msvq_ma_enc_fx.c b/lib_enc/lsf_msvq_ma_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..57106caa07e19a8ff3491fd1bc9785f09a40778b --- /dev/null +++ b/lib_enc/lsf_msvq_ma_enc_fx.c @@ -0,0 +1,776 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.h" +//#include "prot_fx.h" +#include "cnst.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 */ + + +/*-------------------------------------------------------------------* + * Local constants + *-------------------------------------------------------------------*/ + +#define MAXINT32 2147483647 +#ifndef swap + #define swap(x,y,type) {type u__p; u__p=x; x=y; y=u__p;} +#endif + +#define depack_4_values(cbp, val0, val1, val2, val3) \ + val0 = shr((cbp)[0], 4); \ + val1 = shr((cbp)[1], 4); \ + val2 = shr((cbp)[2], 4); \ + val3 = add(add(shr(lshl((cbp)[2],12),4),lshr(lshl((cbp)[1],12),8)),s_and((cbp)[0],0xF)); +/*--------------------------------------------------------------------------* + * depack_mul_values() + * + *--------------------------------------------------------------------------*/ + static Word32 depack_mul_values(Word16 *Tmp, const Word16 *w, const Word16 *cbp, const Word16 N) +{ + Word16 i, val0, val1, val2, val3; + Word32 en; + + en = 0; + move32(); + FOR (i = 0; i < N; i+=4) + { + depack_4_values(cbp+i_mult(shr(i,2),3), val0, val1, val2, val3) + Tmp[i+0] = mult_r(shl(w[i+0],2),val0); + move16(); + en = L_mac(en, val0, Tmp[i+0]); + Tmp[i+1] = mult_r(shl(w[i+1],2),val1); + move16(); + en = L_mac(en, val1, Tmp[i+1]); + Tmp[i+2] = mult_r(shl(w[i+2],2),val2); + move16(); + en = L_mac(en, val2, Tmp[i+2]); + Tmp[i+3] = mult_r(shl(w[i+3],2),val3); + move16(); + en = L_mac(en, val3, Tmp[i+3]); + } + + return en; +} +/*--------------------------------------------------------------------------* + * depack_sub_values() + * + *--------------------------------------------------------------------------*/ +static void depack_sub_values(Word16 *pTmp, const Word16 *p1, const Word16 *cbp, const Word16 N) +{ + Word16 j, val0, val1, val2, val3; + + FOR (j=0; j> 16 => Qwnorm-15/16 * Q0/16 << 1 => Qwnorm-14/32 * 6.5536 */ + ss2 = L_mult(mult(u[0], shl( w[0], 2 )), u[0]); + move16(); + FOR (j=1; j 0 && LT_16(j, M)&<_16(qlsf[j],add(qlsf[j-1],LSF_GAP_MID_FX))) + { + qlsf[j] = add(qlsf[j-1], LSF_GAP_MID_FX); + } + + tmp = sub(lsf[j],qlsf[j]); + /* err += wghts[j] * ftemp * ftemp; */ + /* tmp is usually very small, we can have some extra precision with very rare saturation */ +#ifdef BASOP_NOGLOB + tmp = shl_o(tmp, 4, &Overflow); + tmp = mult_ro(tmp, tmp, &Overflow); +#else /* BASOP_NOGLOB */ + tmp = shl(tmp, 4); + tmp = mult_r(tmp, tmp); +#endif /* BASOP_NOGLOB */ + err = L_mac(err, tmp, wghts[j]); + } +#ifdef BASOP_NOGLOB + err = L_shl_o( err, 2 , &Overflow); +#else /* BASOP_NOGLOB */ + err = L_shl( err, 2 ); +#endif + + /* err = L_shl(err,Wscale); */ + err = Mult_32_16(err,LSF_1_OVER_256SQ); + /* err = Mult_32_16(err,Wmult); */ + + IF ( LT_32(err,err_min)) + { + err_min = L_add(err, 0); + *idx = k; + move16(); + } + k1+=M; + move16(); + } + + return; +} + +/*--------------------------------------------------------------------------* + * Q_lsf_tcxlpc_fx() + * + * Returns: number of indices + *--------------------------------------------------------------------------*/ +Word16 Q_lsf_tcxlpc_fx( + /* const */ Word16 lsf[], /* i : original lsf */ + Word16 lsf_q[], /* o : quantized lsf */ + Word16 lsp_q_ind[], /* o : quantized lsp (w/o MA prediction) */ + Word16 indices[], /* o : VQ indices */ + const Word16 lpcorder, /* i : LPC order */ + const Word16 narrowband, /* i : narrowband flag */ + const Word16 cdk, /* i : codebook selector */ + const Word16 mem_MA[], /* i : MA memory */ + const Word16 coder_type, + const Word32 * Bin_Ener, + const Word16 Q_ener +) +{ + Word16 weights[M+1]; + Word16 pred[M16k]; + Word16 i; + Word16 NumIndices; + Word16 lsf_q_ind[M16k]; + const Word16 *means; + Word16 lsf_rem[M]; + Word16 lsf_rem_q_ind[M]; + + Unified_weighting_fx( Bin_Ener, Q_ener, lsf, weights, narrowband,(Word16)EQ_16(coder_type,UNVOICED),12800,M); + + move16(); + NumIndices = 0; + + /* Put disabled flag */ + indices[NumIndices] = 0; + move16(); + NumIndices = add(NumIndices, 1); + + /* Inter-frame prediction */ + + means = lsf_means[narrowband]; /* 14Q1 * 1.28 */ + + FOR (i=0; i +#include "options.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 */ +/*-------------------------------------------------------------------* + * ltd_stable_fx() + * + * + *-------------------------------------------------------------------*/ + +void ltd_stable_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + Word16 *ltd_stable_rate, /* o : time-domain stable rate*/ + const Word32 frame_energy, /* i : current frame energy*/ + const Word16 frameloop, /* i : amount of frames*/ + const Word16 Q_frames_power /* i : the Scaling of frames_power*/ +) +{ + + Word32 i; + Word32 zerop001,maxVal; + Word32 mid_frame_amp_mul,tmp_mul; + Word32 *frames_power_32; + Word32 frame_energy_Sqr32; + Word32 seg_amp32; + Word32 mid_frame_ampadd32[20]; + Word16 tmp16[20]; + Word32 mid_frame_amp32[20]; + Word32 dif32, apow32; + Word32 tmp32[20]; + + Word16 Q_frames_power_last_32; + Word16 Q_dif,Q_apow; + Word16 frame_energy_Sqr; + Word16 Q_frames_power32; + Word16 leadingzero_tmp32; + Word16 leadingzero_midamp; + Word16 Qsum_dif32,Qsum_apow32; + Word16 ltd_stable_rate_Qtmp; + Word16 scale1; + Word32 seg_amp32tmp; + Word16 tmp; + + zerop001 = 0; + move32(); + Q_dif = 0; + move16(); + Q_apow = 0; + move16(); + frames_power_32 = hVAD_CLDFB->frames_power_32; + Q_frames_power_last_32 = hVAD_CLDFB->Q_frames_power_32; + move16(); + leadingzero_midamp = 31; + move16(); + leadingzero_tmp32 = 31; + move16(); + Q_frames_power32 = Q_frames_power; + move16(); + + frame_energy_Sqr = FixSqrt(frame_energy, &Q_frames_power32); + frame_energy_Sqr32 = L_deposit_l(frame_energy_Sqr); + frame_energy_Sqr32 = L_shl(frame_energy_Sqr32,16); + Q_frames_power32 = add(Q_frames_power32, 16); + + /* +0.1 */ + IF (GE_16(Q_frames_power32, 40)) + { + zerop001 = L_shr(CNT0P001, 1); + frame_energy_Sqr32 = L_shr(frame_energy_Sqr32,sub(Q_frames_power32, 39)); + Q_frames_power32 = 39; + move16(); + } + ELSE + { + Q_frames_power32 = sub(Q_frames_power32, 1); + frame_energy_Sqr32 = L_shr(frame_energy_Sqr32,1); + zerop001 = L_shr(CNT0P001, sub(40, Q_frames_power32)); + } + frames_power_32[0] = L_add(frame_energy_Sqr32, zerop001); + move32(); + + IF(LT_16(frameloop, 3)) + { + FOR(i=1; i<40; i++) + { + frames_power_32[i] = frames_power_32[0]; + move32(); + } + } + ELSE + { + Word16 leadingzero; + maxVal = 0; + move32(); + FOR(i=1; i<40; i++) + { + maxVal = L_max(maxVal,frames_power_32[i]); + } + leadingzero = 31; + move16(); + if(maxVal) + leadingzero = norm_l(maxVal); + Q_frames_power_last_32 = add(Q_frames_power_last_32, leadingzero); + + + IF (GT_16(Q_frames_power_last_32,Q_frames_power32)) + { + scale1 = sub(Q_frames_power_last_32, Q_frames_power32); + scale1 = sub(scale1, leadingzero); + FOR(i=1; i<40; i++) + { + frames_power_32[i] = L_shr(frames_power_32[i],scale1); + move32(); + } + } + ELSE + { + scale1 = sub(Q_frames_power32, Q_frames_power_last_32); + frames_power_32[0] = L_shr(frames_power_32[0],scale1); + move32(); + Q_frames_power32 = Q_frames_power_last_32; + move16(); + FOR(i=1; i<40; i++) + { + frames_power_32[i] = L_shl(frames_power_32[i], leadingzero); + move32(); + } + } + } + + FOR(i=0; i<20; i++) + { + mid_frame_ampadd32[i] = L_add(L_shr(frames_power_32[2*i], 1), L_shr(frames_power_32[2*i+1], 1)); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<20; i++) + { + maxVal = L_max(maxVal,mid_frame_ampadd32[i]); + } + leadingzero_midamp = 31; + move16(); + if(maxVal) + leadingzero_midamp = norm_l(maxVal); + + FOR(i=0; i<20; i++) + { + mid_frame_amp32[i] = L_shl(mid_frame_ampadd32[i], leadingzero_midamp); + move32(); + } + + seg_amp32 = 0; move32(); + FOR(i=0; i<20; i++) + { + seg_amp32 = L_add(seg_amp32, L_shr(mid_frame_amp32[i], 5)); + } + seg_amp32 = MUL_F(seg_amp32, 0x0666); + + dif32 = 0; move32(); + apow32 = 0; move32(); + + seg_amp32tmp = L_shl(seg_amp32, 5); + FOR(i=0; i<20; i++) + { + tmp32[i] = L_sub(mid_frame_amp32[i],seg_amp32tmp); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<20; i++) + { + maxVal = L_max(maxVal,L_abs(tmp32[i])); + } + leadingzero_tmp32 = 31; + move16(); + if(maxVal) + leadingzero_tmp32 = norm_l(maxVal); + + FOR(i=0; i<20; i++) + { + tmp16[i] = extract_h(L_shl(tmp32[i], leadingzero_tmp32)); + } + + FOR(i=0; i<20; i++) + { + tmp_mul = L_mult(tmp16[i],tmp16[i]); + tmp_mul = L_shr(tmp_mul,5); + dif32 = L_add(dif32,tmp_mul); + + tmp = extract_h(mid_frame_amp32[i]); + mid_frame_amp_mul = L_mult(tmp,tmp); + mid_frame_amp_mul = L_shr(mid_frame_amp_mul,5); + apow32 = L_add(apow32,mid_frame_amp_mul); + } + + + IF (dif32==0) + { + ltd_stable_rate[0] = 0; + move16(); + } + ELSE + { + Q_dif = sub(norm_l(dif32), 1); + Q_apow = norm_l(apow32); + dif32 = L_shl(dif32,Q_dif); + apow32 = L_shl(apow32,Q_apow); + ltd_stable_rate[0] = div_l(dif32,extract_h(apow32)); + move16(); + } + + ltd_stable_rate_Qtmp = sub(Q_dif, Q_apow); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, leadingzero_tmp32); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, leadingzero_tmp32); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, 15); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, ITD_STABLE_RATE_Q); + + ltd_stable_rate_Qtmp = limitScale16(ltd_stable_rate_Qtmp); + ltd_stable_rate[0] = shr(ltd_stable_rate[0],ltd_stable_rate_Qtmp); + move16(); + + maxVal = 0; move32(); + FOR(i=0; i<14; i++) + { + maxVal = L_max(maxVal, L_abs(mid_frame_ampadd32[i])); + } + leadingzero_midamp = 31; + move16(); + if(maxVal) + leadingzero_midamp = norm_l(maxVal); + + FOR(i=0; i<14; i++) + { + mid_frame_amp32[i] = L_shl(mid_frame_ampadd32[i],leadingzero_midamp); + move32(); + } + + seg_amp32 = 0; move32(); + FOR(i=0; i<14; i++) + { + seg_amp32 = L_add(seg_amp32, L_shr(mid_frame_amp32[i],4)); + } + seg_amp32 = MUL_F(seg_amp32, 0x0924); + + dif32 = 0; move32(); + apow32 = 0; move32(); + seg_amp32tmp = L_shl(seg_amp32, 4); + FOR(i=0; i<14; i++) + { + tmp32[i] = L_sub(mid_frame_amp32[i], seg_amp32tmp); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<14; i++) + { + maxVal = L_max(maxVal,L_abs(tmp32[i])); + } + leadingzero_tmp32 = 31; + move16(); + if(maxVal) + leadingzero_tmp32 = norm_l(maxVal); + + FOR(i=0; i<14; i++) + { + tmp32[i] = L_shl(tmp32[i], leadingzero_tmp32); + move32(); + } + + FOR(i=0; i<14; i++) + { + tmp = extract_h(tmp32[i]); + tmp_mul = L_mult(tmp, tmp); + tmp_mul = L_shr(tmp_mul, 4); + dif32 = L_add(dif32, tmp_mul); + + tmp = extract_h(mid_frame_amp32[i]); + mid_frame_amp_mul = L_mult(tmp,tmp); + mid_frame_amp_mul = L_shr(mid_frame_amp_mul, 4); + apow32 = L_add(apow32, mid_frame_amp_mul); + } + + Qsum_apow32 = add(Q_frames_power32, Q_frames_power32); + Qsum_apow32 = add(Qsum_apow32, leadingzero_midamp); + Qsum_apow32 = add(Qsum_apow32, leadingzero_midamp); + Qsum_apow32 = sub(Qsum_apow32, 37); + + Qsum_dif32 = add(Qsum_apow32, leadingzero_tmp32); + Qsum_dif32 = add(Qsum_dif32, leadingzero_tmp32); + + /* +0.1 */ + IF (GE_16(Qsum_apow32,44)) + { + zerop001 = L_shr(CNT0P0001, 1); + apow32 = L_shr(apow32,limitScale32(sub(Qsum_apow32,43))); + Qsum_apow32 = 43; + move16(); + } + ELSE + { + Qsum_apow32 = sub(Qsum_apow32, 1); + apow32 = L_shr(apow32, 1); + zerop001 = L_shr(CNT0P0001, limitScale32(sub(44, Qsum_apow32))); + } + apow32 = L_add(apow32, zerop001); + IF (apow32 == 0) + { + apow32 = CNT0P0001; move32(); + Qsum_apow32 = 44; + move16(); + } + + IF (dif32 == 0) + { + ltd_stable_rate[1] = 0; + move16(); + } + ELSE + { + Q_dif=sub(norm_l(dif32), 1); + Q_apow=norm_l(apow32); + dif32 = L_shl(dif32,Q_dif); + apow32 = L_shl(apow32,Q_apow); + + ltd_stable_rate[1] = div_l(dif32,extract_h(apow32)); + move16(); + } + + ltd_stable_rate_Qtmp = add(Qsum_dif32, Q_dif); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Qsum_apow32); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Q_apow); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, 15); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, ITD_STABLE_RATE_Q); + + ltd_stable_rate_Qtmp = limitScale16(ltd_stable_rate_Qtmp); + + ltd_stable_rate[1] = shr(ltd_stable_rate[1],ltd_stable_rate_Qtmp); + move16(); + + maxVal = 0; move32(); + FOR(i=0; i<8; i++) + { + maxVal = L_max(maxVal,L_abs(mid_frame_ampadd32[i])); + } + leadingzero_midamp = 31; + move16(); + if(maxVal) + leadingzero_midamp = norm_l(maxVal); + + FOR(i=0; i<8; i++) + { + mid_frame_amp32[i] = L_shl(mid_frame_ampadd32[i], leadingzero_midamp); + move32(); + } + + seg_amp32 = 0; move32(); + FOR(i=0; i<8; i++) + { + seg_amp32 = L_add(seg_amp32, L_shr(mid_frame_amp32[i], 3)); + } + seg_amp32 = MUL_F(seg_amp32, 0x1000); + + dif32 = 0; move32(); + apow32 = 0; move32(); + seg_amp32tmp = L_shl(seg_amp32, 3); + FOR(i=0; i<8; i++) + { + tmp32[i] = L_sub(mid_frame_amp32[i], seg_amp32tmp); + move32(); + } + + maxVal = 0; move32(); + FOR(i=0; i<8; i++) + { + maxVal = L_max(maxVal,L_abs(tmp32[i])); + } + leadingzero_tmp32 = 31; + move16(); + if(maxVal) + leadingzero_tmp32 = norm_l(maxVal); + + FOR(i=0; i<8; i++) + { + tmp32[i] = L_shl(tmp32[i],leadingzero_tmp32); + move32(); + } + + FOR(i=0; i<8; i++) + { + tmp = extract_h(tmp32[i]); + tmp_mul = L_mult(tmp,tmp); + tmp_mul = L_shr(tmp_mul, 3); + dif32 = L_add(dif32, tmp_mul); + + tmp = extract_h(mid_frame_amp32[i]); + mid_frame_amp_mul = L_mult(tmp,tmp); + mid_frame_amp_mul = L_shr(mid_frame_amp_mul,3); + apow32 = L_add(apow32, mid_frame_amp_mul); + } + + Qsum_apow32 = add(Q_frames_power32,Q_frames_power32); + Qsum_apow32 = add(Qsum_apow32,leadingzero_midamp); + Qsum_apow32 = add(Qsum_apow32,leadingzero_midamp); + Qsum_apow32 = sub(Qsum_apow32,36); + + Qsum_dif32 = add(Qsum_apow32,leadingzero_tmp32); + Qsum_dif32 = add(Qsum_dif32,leadingzero_tmp32); + + /* +0.1 */ + IF (GE_16(Qsum_apow32,44)) + { + zerop001 = L_shr(CNT0P0001, 1); + apow32 = L_shr(apow32,limitScale32(sub(Qsum_apow32,43))); + Qsum_apow32 = 43; + move16(); + } + ELSE + { + Qsum_apow32 = sub(Qsum_apow32, 1); + apow32 = L_shr(apow32,1); + zerop001 = L_shr(CNT0P0001, limitScale32(sub(44, Qsum_apow32))); + } + apow32 = L_add(apow32, zerop001); + IF (apow32 == 0) + { + apow32 = CNT0P0001; move32(); + Qsum_apow32 = 44; + move16(); + } + + IF (dif32 == 0) + { + ltd_stable_rate[2] = 0; + move16(); + } + ELSE + { + Q_dif = sub(norm_l(dif32), 1); + Q_apow = norm_l(apow32); + dif32 = L_shl(dif32, Q_dif); + apow32 = L_shl(apow32, Q_apow); + + ltd_stable_rate[2] = div_l(dif32, extract_h(apow32)); + move16(); + } + + ltd_stable_rate_Qtmp = add(Qsum_dif32, Q_dif); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Qsum_apow32); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, Q_apow); + ltd_stable_rate_Qtmp = add(ltd_stable_rate_Qtmp, 15); + ltd_stable_rate_Qtmp = sub(ltd_stable_rate_Qtmp, ITD_STABLE_RATE_Q); + + ltd_stable_rate_Qtmp = limitScale16(ltd_stable_rate_Qtmp); + + ltd_stable_rate[2] = shr(ltd_stable_rate[2], ltd_stable_rate_Qtmp); + move16(); + ltd_stable_rate[3] = add(mult(ltd_stable_rate[3], 0x7333), mult(ltd_stable_rate[2], 0x0ccc)); + move16(); + + FOR(i=55; i>0; i--) + { + frames_power_32[i] = frames_power_32[i-1]; + move32(); + } + hVAD_CLDFB->Q_frames_power_32 = Q_frames_power32; + move16(); + +} diff --git a/lib_enc/mdct_classifier_fx.c b/lib_enc/mdct_classifier_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..627bee610392d4c9aa9b554b185fd7262d734593 --- /dev/null +++ b/lib_enc/mdct_classifier_fx.c @@ -0,0 +1,583 @@ +/*==================================================================================== + 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.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*--------------------------------------------------------------------------* + * Local constants + *--------------------------------------------------------------------------*/ + +#define MDCT_CLASSIFER_SMOOTH_FILT_COEFF 26214 /* 0.8 in Q15 */ +#define MDCT_CLASSIFER_THRESH_UP 13107 /* 1.6 in Q13 */ +#define MDCT_CLASSIFER_THRESH_DOWN 9011 /* 1.1 in Q13 */ +#define MDCT_CLASSIFER_HQ_LOCAL (3 << 13) /* Q13, Define those local to make the filtering operation robust in case classes numbers are changed */ +#define MDCT_CLASSIFER_TCX_LOCAL (1 << 13) /* Q13 */ +//IVAS_CODE +#define GAIN2_START_WB 6 +#define GAIN3_START_WB 12 +#define GAIN4_START_WB 9 +#define H1_START_WB 17 +#define H2_START_WB 14 +#define H_LENGTH_WB 3 + +#define GAIN2_START_SWB 8 +#define GAIN3_START_SWB 16 + +#define GAIN2_START_SWB_RS 3 +#define GAIN3_START_SWB_RS 4 + +#define GAIN4_START_SWB 12 +#define H1_START_SWB 25 +#define H2_START_SWB 20 +#define H_LENGTH_SWB 5 + +/*----------------------------------------------------------------------------- + * dft_mag_square_fx() + * + * Square magnitude of fft spectrum + *----------------------------------------------------------------------------*/ +static void dft_mag_square_fx( + const Word16 x[], /* i : Input vector: re[0], re[1], ..., re[n/2], im[n/2 - 1], im[n/2 - 2], ..., im[1] */ + Word32 magSq[], /* o : Magnitude square spectrum */ + const Word16 n /* i : Input vector length */ +) +{ + Word16 i, l; + const Word16 *pRe, *pIm; + Word32 *pMagSq, acc; + + /* Magnitude square at 0. */ + pMagSq = &magSq[0]; + pRe = &x[0]; + *pMagSq++ = L_mult0(*pRe, *pRe); + pRe++; + move32(); + + /* From 1 to (N/2 - 1). */ + l = sub(shr(n, 1), 1); /* N/2 - 1. */ + pIm = &x[n]; + pIm--; + FOR (i = 0; i < l; i++) + { + acc = L_mult0(*pRe, *pRe); + pRe++; + *pMagSq++ = L_mac0(acc, *pIm, *pIm); + pIm--; + move32(); + } + + /* The magnitude square at N/2 */ + *pMagSq = L_mult0(*pRe, *pRe); + move32(); + return; +} +/*-------------------------------------------------------------------* + * mdct_classifier() + * + * MDCT signal classifier for HQ_CORE/TCX_20_CORE + *-------------------------------------------------------------------*/ + +Word16 mdct_classifier_fx( /* o: MDCT A/B decision */ + const Word16 * fft_buff, /* i: re[0], re[1], ..., re[n/2], im[n/2 - 1], im[n/2 - 2], ..., im[1] */ + Encoder_State_fx *st_fx, /* i/o: Encoder state variable */ + Word32 *cldfbBuf_Ener, + Word16 enerBuffer_exp, + const Word32 brate /* i : current brate, IVAS: nominal bitrate, EVS: st->total_brate */ +) +{ + Word16 c; + Word32 magSq[129], *pMagSq, nf, pe; + Word16 k; + Word16 np; + Word32 max_cand; + Word16 max_i; + Word32 p_energy_man, n_energy_man, man; + Word16 p_energy_exp, n_energy_exp, expo; + Word16 d_acc; + Word16 pos_last; + Word16 clas_sec; + Word16 clas_final; + Word16 condition1, condition2; + Word16 factor; + Word32 acc; + UWord16 lsb16; + UWord32 lsb32; + Word32 gain1, gain2, gain3, gain11, gain4; + Word32 peak_l, peak_h, avrg_l, avrg_h, peak_H1, avrg_H1, peak_H2, avrg_H2; + Word16 condition3, condition4; + Word32 gain1_tmp = 0, gain2_tmp = 0; + Word16 exp, exp1, exp2, exp3; + Word32 L_tmp, L_tmp1; +#ifdef IVAS_CODE + Word16 gain2_start, gain3_start, gain4_start, H1_start, H2_start, H_length; + Word16 gain2_start_rs, gain3_start_rs; +#endif + TCX_ENC_HANDLE hTcxEnc = st_fx->hTcxEnc; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + test(); +#ifdef IVAS_CODE + IF (EQ_32(st_fx->input_Fs_fx, 32000) || EQ_32(st_fx->input_Fs_fx, 48000)) + { + gain2_start = GAIN2_START_SWB; + gain2_start_rs = GAIN2_START_SWB_RS; + gain3_start = GAIN3_START_SWB; + gain3_start_rs = GAIN3_START_SWB_RS; + gain4_start = GAIN4_START_SWB; + //gain4_start_rs = GAIN4_START_SWB_RS; + H1_start = H1_START_SWB; + H2_start = H2_START_SWB; + H_length = H_LENGTH_SWB; + move16();move16();move16();move16();move16();move16(); + } + ELSE IF (EQ_32(st_fx->input_Fs_fx, 16000)) + { + gain2_start = GAIN2_START_WB; + gain2_start_rs = GAIN2_START_SWB_RS; + gain3_start = GAIN3_START_WB; + gain2_start_rs = GAIN2_START_SWB_RS; + gain4_start = GAIN4_START_WB; + H1_start = H1_START_WB; + H2_start = H2_START_WB; + H_length = H_LENGTH_WB; + move16(); move16(); move16(); move16(); move16(); move16(); + + } + ELSE + { + assert(!"Unknown sampling frequency in MDCT_classifier"); + H1_start = -1; /* to avoid compilation warning */ + H2_start = -1; /* to avoid compilation warning */ + H_length = -1; /* to avoid compilation warning */ + gain2_start = -1; /* to avoid compilation warning */ + gain3_start = -1; /* to avoid compilation warning */ + gain4_start = -1; /* to avoid compilation warning */ + move16(); move16(); move16(); move16(); move16(); move16(); + } +#endif +#ifdef IVAS_CODE + if (NE_16(st_fx->element_mode, IVAS_CPE_DFT)) +#endif + { + + dft_mag_square_fx(fft_buff, magSq, 256); + } +#ifdef IVAS_CODE + ELSE + { + float norm_val; + + norm_val = (L_FFT * L_FFT) / 4.f; + for (k = 0; k < 128; k++) + { + X[k + 1] = st->Bin_E_old[k] * norm_val; + } + X[0] = X[1]; + } +#endif + nf = L_add(magSq[0], 0); + pe = L_add(magSq[0], 0); + np = 0; + move16(); + max_cand = L_negate(1); + max_i = 0; + move16(); + p_energy_man = L_deposit_l(0); + n_energy_man = L_deposit_l(0); + p_energy_exp = n_energy_exp = 32; + move16(); + move16(); + d_acc = 0; + move16(); + pos_last = -1; + move16(); + + pMagSq = magSq; + FOR (k = 0; k < 128; k++) + { + /* NB: a*f + b*(1 - f) needs two multiplies + * = (a - b)*f + b saves one multiply */ + IF (GT_32(*(++pMagSq), nf)) + { + factor = 31385; + move16();/* 0.9578 in Q15 */ + } + ELSE + { + factor = 21207; + move16();/* 0.6472 in Q15 */ + } + acc = L_sub(nf, *pMagSq); + Mpy_32_16_ss(acc, factor, &acc, &lsb16); + nf = L_add(acc, *pMagSq); + IF (GT_32(*pMagSq, pe)) + { + factor = 13840; + move16();/* 0.42237 in Q15 */ + } + ELSE + { + factor = 26308; + move16();/* 0.80285 in Q15 */ + } + acc = L_sub(pe, *pMagSq); + Mpy_32_16_ss(acc, factor, &acc, &lsb16); + pe = L_add(acc, *pMagSq); + Mpy_32_16_ss(pe, 20972, &acc, &lsb16); /* 0.64 in Q15 */ + IF (GT_32(*pMagSq, acc)) + { + IF (GT_32(*pMagSq, max_cand)) + { + max_cand = L_add(*pMagSq, 0); + max_i = add(2, k); + } + } + ELSE + { + IF (max_i > 0) + { + IF (GT_16(np, 0)) + { + d_acc = sub(add(d_acc, max_i), pos_last); + } + np = add(np, 1); + pos_last = max_i; + move16(); + } + + max_cand = L_negate(1); + max_i = 0; + move16(); + } + + IF (pe != 0) + { + expo = norm_l(pe); + man = L_shl(pe, expo); + Mpy_32_32_ss(man, man, &man, &lsb32); /* pe square */ + expo = shl(expo, 1); /* Multiply by 2 due to squaring. */ + floating_point_add(&p_energy_man, &p_energy_exp, man, expo); + } + IF (nf != 0) + { + expo = norm_l(nf); + man = L_shl(nf, expo); + Mpy_32_32_ss(man, man, &man, &lsb32); /* nf square */ + expo = shl(expo, 1); /* Multiply by 2 due to squaring. */ + floating_point_add(&n_energy_man, &n_energy_exp, man, expo); + } + } + + gain1 = L_deposit_l(0); + gain2 = L_deposit_l(0); + gain3 = L_deposit_l(0); +#ifdef IVAS_CODE + PMT("MDCT_classifier needs review for different sampling rate") +#endif +//IVAS_CODE to adapt + FOR (k = 0; k < 8; k++) + { + gain1 = L_add(gain1, L_shr(cldfbBuf_Ener[k], 3)); + gain2 = L_add(gain2, L_shr(cldfbBuf_Ener[k + 8], 3)); + gain3 = L_add(gain3, L_shr(cldfbBuf_Ener[k + 16], 3)); + } + + /* gain11 = 8*(gain1 - cldfbBuf_Ener[0]/8)/7; */ + acc = L_shr(cldfbBuf_Ener[0], 3); + acc = L_sub(gain1, acc); + acc = Mult_32_16(acc, 4681); + gain11 = L_shl(acc, 3); + gain4 = L_deposit_l(0); + FOR (k = 0; k < 12; k++) + { + gain4 = L_add(gain4, Mult_32_16(cldfbBuf_Ener[k + 12], 2731)); + } + + + peak_H1 = L_add(cldfbBuf_Ener[25], 0); + Mpy_32_16_ss(cldfbBuf_Ener[25], 6554, &avrg_H1, &lsb16); + FOR (k = 1; k < 5; k++) + { + IF(GT_32(cldfbBuf_Ener[k + 25], peak_H1)) + { + peak_H1 = L_add(cldfbBuf_Ener[k + 25], 0); + } + avrg_H1 = L_add(avrg_H1, Mult_32_16(cldfbBuf_Ener[k + 25], 6554)); + } + + peak_H2 = L_add(cldfbBuf_Ener[20], 0); + Mpy_32_16_ss(cldfbBuf_Ener[20], 6554, &avrg_H2, &lsb16); + FOR (k = 1; k < 5; k++) + { + IF (GT_32(cldfbBuf_Ener[k + 20], peak_H2)) + { + peak_H2 = L_add(cldfbBuf_Ener[k + 20], 0); + } + avrg_H2 = L_add(avrg_H2, Mult_32_16(cldfbBuf_Ener[k + 20], 6554)); + } +//End + peak_l = L_deposit_l(0); + avrg_l = L_deposit_l(0); + peak_h = L_deposit_l(0); + avrg_h = L_deposit_l(0); + FOR (k = 0; k < 32; k++) + { + avrg_l = L_add(avrg_l, L_shr(magSq[k + 20], 5)); + avrg_h = L_add(avrg_h, L_shr(magSq[k + 96], 5)); + IF (GT_32(magSq[k + 20], peak_l)) + { + peak_l = L_add(magSq[k + 20], 0); + } + IF (GT_32(magSq[k + 96], peak_h)) + { + peak_h = L_add(magSq[k + 96], 0); + } + } + + /* Compute: d_acc - 12*(np -1). */ + acc = L_deposit_l(d_acc); + IF (L_msu(acc, 12/2, sub(np, 1)) > 0) /* 12/2 is to compensate the fractional mode multiply */ + { + condition1 = 1; /* Signifies: d_acc/(np - 1) > 12 */ move16(); + } + ELSE + { + condition1 = 0; /* Signifies: d_acc/(np - 1) <= 12 */ move16(); + /* NB: For np = 0 or 1, it fits this condition. */ + } + + /* Compute: p_energy - 147.87276*n_energy. */ + IF (n_energy_man != 0) + { + Mpy_32_16_ss(n_energy_man, 18928, &acc, &lsb16); /* 147.87276 in Q7 */ + expo = sub(n_energy_exp, 15 - 7); /* Due to 18928 in Q7 */ + acc = L_negate(acc); /* To facilitate the following floating_point_add() to perform subtraction. */ + floating_point_add(&acc, &expo, p_energy_man, p_energy_exp); + } + ELSE + { + acc = L_deposit_l(0); + } + IF (acc > 0) + { + condition2 = 1; /* Signifies: p_energy / n_energy > 147.87276 */ move16(); + } + ELSE + { + condition2 = 0; /* Signifies: p_energy / n_energy <= 147.87276 */ move16(); + } + + condition3 = 0; + move16(); + condition4 = 0; + move16(); + + L_tmp = Mult_32_16(peak_h, 12603); + IF(GT_32(peak_l, L_tmp)) + { + exp = norm_l(peak_l); + } + ELSE + { + exp = norm_l(L_tmp); + } + IF(GT_32(avrg_h, avrg_l)) + { + exp1 = norm_l(avrg_h); + } + ELSE + { + exp1 = norm_l(avrg_l); + } + + L_tmp1 = Mult_32_16(peak_l, 12603); + IF(GT_32(peak_h, L_tmp1)) + { + exp2 = norm_l(peak_h); + } + ELSE + { + exp2 = norm_l(L_tmp1); + } + + test(); + test(); + test(); + test(); +#ifdef BASOP_NOGLOB + IF (GT_32(Mult_32_16(gain3, 27307), gain2)||(GE_32(gain3,Mult_32_16(gain2,26214))&>_32(peak_H1,L_shl_o(avrg_H1,1, &Overflow))) + || (LT_32(Mult_32_32(L_shl_o(peak_l, exp, &Overflow), L_shl_o(avrg_h, exp1, &Overflow)), Mult_32_32(L_shl_o(L_tmp, exp, &Overflow), L_shl_o(avrg_l, exp1, &Overflow))) + || GT_32(Mult_32_32(L_shl_o(L_tmp1, exp2, &Overflow), L_shl_o(avrg_h, exp1, &Overflow)), Mult_32_32(L_shl_o(peak_h, exp2, &Overflow), L_shl_o(avrg_l, exp1, &Overflow))))) +#else + IF (GT_32(Mult_32_16(gain3, 27307), gain2)||(GE_32(gain3,Mult_32_16(gain2,26214))&>_32(peak_H1,L_shl(avrg_H1,1))) + || (LT_32(Mult_32_32(L_shl(peak_l, exp), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(L_tmp, exp), L_shl(avrg_l, exp1))) + || GT_32(Mult_32_32(L_shl(L_tmp1, exp2), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(peak_h, exp2), L_shl(avrg_l, exp1))))) +#endif + { + condition3 = 1; + move16(); + } + + L_tmp = Mult_32_16(peak_h, 12800); + IF(GT_32(peak_l, L_tmp)) + { + exp = norm_l(peak_l); + } + ELSE + { + exp = norm_l(L_tmp); + } + + L_tmp1 = Mult_32_16(peak_l, 6400); + IF(GT_32(peak_h, L_tmp1)) + { + exp2 = norm_l(peak_h); + } + ELSE + { + exp2 = norm_l(L_tmp1); + } + + IF(GT_32(peak_h, L_shl(L_tmp1, 1))) + { + exp3 = norm_l(peak_h); + } + ELSE + { + exp3 = sub(norm_l(L_tmp1), 1); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF ((GT_32(gain4, Mult_32_16(gain11, 26214))&>_32(Mult_32_32(L_shl(peak_l,exp),L_shl(avrg_h,exp1)),Mult_32_32(L_shl(Mult_32_16(peak_h,12800),exp),L_shl(avrg_l,exp1))) + && LT_32(Mult_32_32(L_shl(Mult_32_16(peak_l, 6400), exp2), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(peak_h, exp2), L_shl(avrg_l, exp1)))) + || (GT_32(gain4, Mult_32_16(gain11, 9830))&& LT_32(Mult_32_16(peak_h, 21845), avrg_h)&& LT_32(Mult_32_16(peak_H2, 21845), avrg_H2)) + || (LT_32(Mult_32_32(L_shl(peak_l, exp), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(Mult_32_16(peak_h, 12800), exp), L_shl(avrg_l, exp1))) && GT_32(Mult_32_16(peak_h, 21845), avrg_h)) + || (GT_32(Mult_32_32(L_shl(Mult_32_16(peak_l, 12800), exp3), L_shl(avrg_h, exp1)), Mult_32_32(L_shl(peak_h, exp3), L_shl(avrg_l, exp1))) > 0 && LT_32(Mult_32_16(peak_h, 21845), avrg_h))) + { + condition4 = 1; + move16(); + } + + test(); + test(); + test(); + test(); + IF ((GE_32(brate, HQ_MDCTCLASS_CROSSOVER_BRATE) && GT_32(st_fx->input_Fs_fx, 16000) && (s_xor(condition1,condition2)!=0||condition3)) + || ((LT_32(brate, HQ_MDCTCLASS_CROSSOVER_BRATE) || EQ_32(st_fx->input_Fs_fx,16000) ) && condition4)) + { + c = MDCT_CLASSIFER_HQ_LOCAL; /* Q13 */ move16(); + } + ELSE + { + c = MDCT_CLASSIFER_TCX_LOCAL; /* Q13 */ move16(); + } + + /* Smooth decision from instantaneous decision*/ + acc = L_mult(hTcxEnc->clas_sec_old_fx, MDCT_CLASSIFER_SMOOTH_FILT_COEFF); /* st_fx->clas_sec_old_fx in Q13 */ + clas_sec = mac_r(acc, c, 0x7fff - MDCT_CLASSIFER_SMOOTH_FILT_COEFF); /* clas_sec and c are in Q13 */ + /* Do thresholding with hysteresis */ + IF(GT_16(st_fx->last_enerBuffer_exp, enerBuffer_exp)) + { + gain1_tmp = L_shr(gain1, sub(st_fx->last_enerBuffer_exp, enerBuffer_exp)); + move32(); + gain2_tmp = L_shr(gain2, sub(st_fx->last_enerBuffer_exp, enerBuffer_exp)); + move32(); + } + ELSE + { + hTcxEnc->last_gain1 = L_shr(hTcxEnc->last_gain1, sub(enerBuffer_exp, st_fx->last_enerBuffer_exp)); + move32(); + hTcxEnc->last_gain2 = L_shr(hTcxEnc->last_gain2, sub(enerBuffer_exp, st_fx->last_enerBuffer_exp)); + move32(); + gain1_tmp = gain1; + move32(); + gain2_tmp = gain2; + move32(); + } + + test(); + test(); + test(); + test(); + test(); + test(); +#ifdef BASOP_NOGLOB + IF ((EQ_16(hTcxEnc->clas_final_old, HQ_CORE) || EQ_16(hTcxEnc->clas_final_old,TCX_20_CORE)) + && ((GT_32(hTcxEnc->last_gain1, L_shr(gain1_tmp, 1)) && LT_32(hTcxEnc->last_gain1, L_shl_o(gain1_tmp, 1, &Overflow))) + && (GT_32(hTcxEnc->last_gain2, L_shr(gain2_tmp, 1)) && LT_32(hTcxEnc->last_gain2, L_shl_o(gain2_tmp, 1, &Overflow))))) +#else + IF ((EQ_16(hTcxEnc->clas_final_old, HQ_CORE) || EQ_16(hTcxEnc->clas_final_old,TCX_20_CORE)) + && ((GT_32(hTcxEnc->last_gain1, L_shr(gain1_tmp, 1)) && LT_32(hTcxEnc->last_gain1, L_shl(gain1_tmp, 1))) + && (GT_32(hTcxEnc->last_gain2, L_shr(gain2_tmp, 1)) && LT_32(hTcxEnc->last_gain2, L_shl(gain2_tmp, 1))))) +#endif + { + clas_final = hTcxEnc->clas_final_old; + move16(); + } + ELSE IF (GT_16(clas_sec, hTcxEnc->clas_sec_old_fx) && GT_16(clas_sec,MDCT_CLASSIFER_THRESH_UP)) /* Going up? */ + { + clas_final = HQ_CORE; /* Q0 */ move16(); + } + ELSE IF (LT_16(clas_sec, MDCT_CLASSIFER_THRESH_DOWN))/* Going down */ + { + clas_final = TCX_20_CORE; + move16(); + } + ELSE + { + clas_final = hTcxEnc->clas_final_old; + move16(); + } + + test(); + test(); + test(); + /* Prevent the usage of MDCTA on noisy-speech or inactive */ + if ( EQ_16(st_fx->mdct_sw_enable, MODE2) && (EQ_16(st_fx->flag_noisy_speech_snr,1) || st_fx->vad_flag==0) && EQ_16(clas_final,HQ_CORE)) + { + clas_final = TCX_20_CORE; + move16(); + } + /* Restrict usage of HQ_core to supported operating range */ + /* EVS: brate == st->total_brate */ + /* IVAS: brate is the nominal bitrate while st->total_brate may fluctuate. This sets a hard limit for HQ at HQ_16k40 */ + test();test();test(); + if (LE_32(st_fx->total_brate_fx, HQ_16k40) || LT_32(brate, HQ_16k40) || EQ_16(st_fx->bwidth_fx, NB) || GT_32(brate, IVAS_48k)) + { + clas_final = TCX_20_CORE; + move16(); + } + + /* Memory update */ + hTcxEnc->clas_sec_old_fx = clas_sec; + move16(); /* Q13 */ + hTcxEnc->clas_final_old = clas_final; + move16(); /* Q0 */ + hTcxEnc->last_gain1 = gain1; + move32(); + hTcxEnc->last_gain2 = gain2; + move32(); + st_fx->last_enerBuffer_exp = enerBuffer_exp; + move16(); + + return clas_final; /* Q0 */ +} + + diff --git a/lib_enc/mdct_selector_fx.c b/lib_enc/mdct_selector_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..9d86ec9418d37ac4a76f91686a9485d92c2a7002 --- /dev/null +++ b/lib_enc/mdct_selector_fx.c @@ -0,0 +1,397 @@ +/*==================================================================================== + 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.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +# define MDCT_SW_SIG_LINE_THR 840 /* 2.85f*LOG_10 in Q7 */ /* Significant spectral line threshold above Etot (dB) */ +# define MDCT_SW_SIG_PEAK_THR 9216 /* 36.0f in Q8 */ /* Significant peak threshold below Etot (dB) */ +# define MDCT_SW_HI_SPARSE_THR 8192 /* 0.25f in Q15*/ /* Max. ratio of significant spectral lines for the spectrum to be considered sparse */ +# define MDCT_SW_HI_ENER_LO_THR 1920 /* 7.5f in Q8 */ /* Hi band low energy threshold (dB) */ +# define MDCT_SW_SPARSE_THR 6554 /* 0.25f*0.8f in Q15*/ +# define MDCT_SW_1_VOICING_THR 29491 /* 0.9f in Q15*/ /* Voicing threshold */ +# define MDCT_SW_1_VOICING_THR2 23593 /* 0.9f*0.8f in Q15*/ +# define MDCT_SW_1_HI_ENER_LO_THR 3200 /* 12.5f in Q8 */ /* Hi band high energy threshold (dB) */ +# define MDCT_SW_1_SIG_HI_LEVEL_THR 7168 /* 28.0f in Q8 */ /* High signal level threshold above noise floor (dB) */ +# define MDCT_SW_1_SIG_LO_LEVEL_THR 5760 /* 22.5f in Q8 */ /* Low signal level threshold above noise floor (dB) */ +# define MDCT_SW_1_COR_THR 20480 /* 80.0f in Q8 */ /* Threshold on cor_map_sum to indicate strongly tonal signal */ +# define MDCT_SW_1_COR_THR2 16384 /* 80.0f*0.8f in Q8 */ +# define MDCT_SW_1_SPARSENESS_THR 21299 /* 0.65f in Q15*/ /* Threshold on spectrum sparseness */ +# define MDCT_SW_1_SPARSENESS_THR2 17039 /* 0.65f*0.8f in Q15*/ + +# define MDCT_SW_2_VOICING_THR 19661 /* 0.6f in Q15*/ /* Voicing threshold */ +# define MDCT_SW_2_VOICING_THR2 15729 /* 0.6f*0.8f in Q15*/ +# define MDCT_SW_2_HI_ENER_LO_THR 2432 /* 9.5f in Q8 */ /* Hi band low energy threshold (dB) */ +# define MDCT_SW_2_SIG_HI_LEVEL_THR 4864 /* 19.0f in Q8 */ /* High signal level threshold above noise floor (dB) */ +# define MDCT_SW_2_SIG_LO_LEVEL_THR 6016 /* 23.5f in Q8 */ /* Low signal level threshold above noise floor (dB) */ +# define MDCT_SW_2_COR_THR 16000 /* 62.5f in Q8 */ /* Threshold on cor_map_sum to indicate strongly tonal signal */ +# define MDCT_SW_2_COR_THR2 12800 /* 62.5f*0.8f in Q8 */ +# define MDCT_SW_2_SPARSENESS_THR 13107 /* 0.4f in Q15*/ /* Threshold on spectrum sparseness */ +# define MDCT_SW_2_SPARSENESS_THR2 10486 /* 0.4f*0.8f in Q15*/ + +/*--------------------------------------------------------------------------* + * get_sparseness() + * + * + *--------------------------------------------------------------------------*/ + +static Word16 get_sparseness( /* Returns sparseness measure (Q15) */ + const Word16 Bin_E[], /* i : per bin energy dB Q7 */ + Word16 n, /* i : number of bins Q0 */ + Word16 thr /* i : peak threshold Q8 */ +) +{ + Word16 num_max, i; + + thr = add(thr, mult(thr, 4958)); /* Convert to 10*log() domain from 10*log10() domain, and also to Q7 */ + + thr = s_max(thr, 384); /* 3.0 in Q7 */ /* Set an absolute minimum for close to silent signals */ + + num_max = 0; + move16(); + + FOR (i=1; ihTcxEnc; + test(); + IF (EQ_16(st->mdct_sw_enable, MODE1)||EQ_16(st->mdct_sw_enable,MODE2)) + { + Word16 hi_ener, frame_voicing, sparseness; + Word16 peak_count; + Word16 prefer_tcx, prefer_hq_core, switching_point, hi_sparse, sparse; + Word16 lob_cldfb, hib_cldfb, lob_fft, hib_fft; + Word16 i, tmp; + Word16 sig_lo_level_thr, sig_hi_level_thr, cor_thr, cor_thr2, voicing_thr, voicing_thr2, sparseness_thr, sparseness_thr2, hi_ener_lo_thr; + Word16 last_core; + + sp_floor = shl(sp_floor, 1); /* convert to Q8 */ + + IF (EQ_16(st->bwidth_fx, NB)) + { + lob_cldfb = 3200/400; + move16(); + hib_cldfb = 4000/400; + move16(); + lob_fft = (L_FFT/2)/2; /* 3.2 KHz */ move16(); + hib_fft = (40*(L_FFT/2))/64; /* 4.0 KHz */ move16(); + } + ELSE IF (EQ_16(st->bwidth_fx, WB)) + { + lob_cldfb = 4800/400; + move16(); + hib_cldfb = 8000/400; + move16(); + lob_fft = 3*L_FFT/2/4; /* 4.8 KHz */ move16(); + hib_fft = L_FFT/2; /* 6.4 KHz (should be 8 KHz) */ move16(); + } + ELSE + { + lob_cldfb = 6400/400; + move16(); + hib_cldfb = 16000/400; + move16(); + if (EQ_16(st->bwidth_fx, FB)) + { + hib_cldfb = 24000/400; + move16(); + } + lob_fft = L_FFT/2; /* 6.4 KHz */ move16(); + hib_fft = L_FFT/2; /* 6.4 KHz (should be 8 KHz) */ move16(); + } + + /* st->last_core_fx is reset to TCX_20_CORE in init_acelp() => fix it here */ + last_core = st->last_core_fx; + move16(); + test(); + if (EQ_16(st->last_codec_mode, MODE1)&&EQ_16(last_core,TCX_20_CORE)) + { + last_core = HQ_CORE; + move16(); + } + + /* Voicing */ + frame_voicing = add(shr(st->voicing_fx[0], 1), shr(st->voicing_fx[1], 1)); + + /* Spectral sparseness */ + sparseness = get_sparseness(st->lgBin_E_fx, lob_fft, sub(Etot, MDCT_SW_SIG_PEAK_THR)); + + /* Hi band energy */ + hi_ener = get_mean_ener(&enerBuffer[lob_cldfb], enerBuffer_exp, sub(hib_cldfb, lob_cldfb)); + + /* Hi band sparseness */ + IF (GE_16(st->bwidth_fx, SWB)) + { + /* For SWB, assume hi band sparseness based on 4.8 KHz-6.4 KHz band */ + lob_fft = 3*L_FFT/2/4; /* 4.8 KHz */ move16(); + } + peak_count = 0; + move16(); + tmp = add(MDCT_SW_SIG_LINE_THR, shr(Etot, 1)); /* Q7 */ + FOR (i=lob_fft; ilgBin_E_fx[i], tmp)) + { + peak_count = add(peak_count, 1); + } + } + + hi_sparse = 0; + move16(); + if (LE_16(peak_count, mult_r(sub(hib_fft, lob_fft), MDCT_SW_HI_SPARSE_THR))) + { + hi_sparse = 1; + move16(); + } + + sparse = 0; + move16(); + if (LE_16(peak_count, mult_r(sub(hib_fft, lob_fft), MDCT_SW_SPARSE_THR))) + { + sparse = 1; + move16(); + } + + /* Hysteresis */ + test(); + test(); + if (hTcxEnc->prev_hi_sparse > 0 && sparse > 0 && GE_16(s_min(s_min(st->voicing_fx[0], st->voicing_fx[1]), st->voicing_fx[2]), MDCT_SW_1_VOICING_THR)) + { + hi_sparse = 1; + move16(); + } + + /* Allowed switching point? */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + switching_point = (NE_16(last_core, HQ_CORE) && NE_16(last_core, TCX_20_CORE) ) || /* previous core was non-MDCT */ + (LE_16(hTcxEnc->prev_hi_ener, MDCT_SW_HI_ENER_LO_THR) || LE_16(hi_ener, MDCT_SW_HI_ENER_LO_THR) ) || /* hi band is close to silent */ + (EQ_16(last_core, HQ_CORE) && (EQ_16(st->mdct_sw_enable, MODE1) || (hi_sparse > 0 && hTcxEnc->prev_hi_sparse >= 0 && LE_16(hTcxEnc->prev_hi_sparse, 1) ))) || /* HQ_CORE and hi band became sparse */ + (EQ_16(last_core, TCX_20_CORE) && (hi_sparse == 0 && hTcxEnc->prev_hi_sparse > 0)); /* TCX and hi band became dense */ + + IF (EQ_16(st->mdct_sw_enable, MODE1)) + { + sig_lo_level_thr = MDCT_SW_1_SIG_LO_LEVEL_THR; + move16(); + sig_hi_level_thr = MDCT_SW_1_SIG_HI_LEVEL_THR; + move16(); + cor_thr = MDCT_SW_1_COR_THR; + move16(); + cor_thr2 = MDCT_SW_1_COR_THR2; + move16(); + voicing_thr = MDCT_SW_1_VOICING_THR; + move16(); + voicing_thr2 = MDCT_SW_1_VOICING_THR2; + move16(); + sparseness_thr = MDCT_SW_1_SPARSENESS_THR; + move16(); + sparseness_thr2 = MDCT_SW_1_SPARSENESS_THR2; + move16(); + hi_ener_lo_thr = MDCT_SW_1_HI_ENER_LO_THR; + move16(); + } + ELSE /* st->mdct_sw_enable == MODE2 */ + { + sig_lo_level_thr = MDCT_SW_2_SIG_LO_LEVEL_THR; + move16(); + sig_hi_level_thr = MDCT_SW_2_SIG_HI_LEVEL_THR; + move16(); + cor_thr = MDCT_SW_2_COR_THR; + move16(); + cor_thr2 = MDCT_SW_2_COR_THR2; + move16(); + voicing_thr = MDCT_SW_2_VOICING_THR; + move16(); + voicing_thr2 = MDCT_SW_2_VOICING_THR2; + move16(); + sparseness_thr = MDCT_SW_2_SPARSENESS_THR; + move16(); + sparseness_thr2 = MDCT_SW_2_SPARSENESS_THR2; + move16(); + hi_ener_lo_thr = MDCT_SW_2_HI_ENER_LO_THR; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + prefer_tcx = (GE_16(sub(Etot, sp_floor), sig_hi_level_thr)) && /* noise floor is low */ + (GE_16(cor_map_sum, cor_thr) || GE_16(frame_voicing, voicing_thr) || GE_16(sparseness, sparseness_thr) ) && /* strong tonal components */ + (LE_16(hi_ener, hi_ener_lo_thr) || hi_sparse > 0); /* high freqs have low energy or are sparse */ + + test(); + test(); + test(); + test(); + test(); + test(); + prefer_hq_core = (LT_16(sub(Etot, sp_floor), sig_lo_level_thr) ) || /* noise floor is very high */ + (LT_16(cor_map_sum, cor_thr2) && LT_16(frame_voicing, voicing_thr2) && LT_16(sparseness, sparseness_thr2) ) || /* too weak tonal components */ + (EQ_16(st->mdct_sw_enable, MODE1) && prefer_tcx == 0 && EQ_16(st->transientDetection.transientDetector.bIsAttackPresent, 1) ); + + /* Prefer HQ_CORE on transients */ + test(); + IF ( EQ_16(st->mdct_sw_enable, MODE2)&&EQ_16(st->transientDetection.transientDetector.bIsAttackPresent,1)) + { + prefer_tcx = 0; + move16(); + prefer_hq_core = 1; + move16(); + } + + test(); + test(); + test(); + IF (switching_point && (prefer_tcx || prefer_hq_core)) + { + IF (prefer_tcx) + { + st->core_fx = TCX_20_CORE; + move16(); + } + ELSE /* prefer_hq_core */ + { + st->core_fx = HQ_CORE; + move16(); + } + } + ELSE IF (EQ_16(last_core, HQ_CORE)||EQ_16(last_core,TCX_20_CORE)) + { + st->core_fx = last_core; + move16(); + } + + test(); + test(); + test(); + /* Prevent the usage of HQ_CORE on noisy-speech or inactive */ + IF (EQ_16(st->mdct_sw_enable, MODE2)&&EQ_16(st->core_fx,HQ_CORE)&&(EQ_16(st->flag_noisy_speech_snr,1)||st->vad_flag==0)) + { + st->core_fx = TCX_20_CORE; + move16(); + } + + /* Update memories */ + hTcxEnc->prev_hi_sparse = add(hTcxEnc->prev_hi_sparse, hi_sparse); + move16(); + if (hi_sparse <= 0) + { + hTcxEnc->prev_hi_sparse = hi_sparse; + move16(); + } + hTcxEnc->prev_hi_sparse = s_min(hTcxEnc->prev_hi_sparse, 2); + hTcxEnc->prev_hi_ener = hi_ener; + move16(); + } +} +/*--------------------------------------------------------------------------* + * MDCT_selector_reset_fx() + * + * reset MDCT selector memories + *--------------------------------------------------------------------------*/ +void MDCT_selector_reset_fx( + TCX_ENC_HANDLE hTcxEnc +) +{ + hTcxEnc->prev_hi_ener = 0; + move16(); + hTcxEnc->prev_hi_sparse = -1; + move16(); +} +/*--------------------------------------------------------------------------* + * MDCT_classifier_reset_fx() + * + * reset MDCT classifier memories + *--------------------------------------------------------------------------*/ +void MDCT_classifier_reset_fx( + TCX_ENC_HANDLE hTcxEnc /* i/o: TCX Encoder Handle */ +) +{ + hTcxEnc->clas_sec_old_fx = 8192; /* 1.0f in Q13 */; + hTcxEnc->clas_final_old = 1; /* Q0 */ + hTcxEnc->last_gain1 = 0; + move32(); + hTcxEnc->last_gain2 = 0; + move32(); + + return; +} diff --git a/lib_enc/mslvq_enc_fx.c b/lib_enc/mslvq_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..45fb0729ab4bbdcdbbc254ed4be9a56444426ec0 --- /dev/null +++ b/lib_enc/mslvq_enc_fx.c @@ -0,0 +1,902 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "cnst.h" +//#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "stl.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + + +/*-----------------------------------------------------------------* + * Local functions + *-----------------------------------------------------------------*/ + +static Word32 quantize_data_fx( Word16 *data, const Word16 *w_in, Word16 *qin, Word16 *cv_out, Word16 *idx_lead, Word16 *idx_scale, const Word16 *sigma, const Word16 *inv_sigma, + const Word16 *scales, Word16 no_scales, const Word16 *no_lead ); +static Word32 q_data_fx(Word16 *pTmp1, const Word16 *w1, Word16 *quant, Word16 *cv_out, Word16 *idx_lead, Word16 *idx_scale, + const Word16 *p_sigma, const Word16 *p_inv_sigma, const Word16 *p_scales, Word16 *p_no_scales, + const Word16 *p_no_lead); +static void prepare_data_fx( Word16 *xsort, Word16 *sign, Word16 *data, Word32 *w, const Word16 *w_in, + const Word16 *sigma, const Word16 * inv_sigma, Word16 *p_sig ); +static Word32 calculate_min_dist_fx(Word16 cv_pot[LATTICE_DIM],Word16 no_scales, const Word16 *scale, + const Word32 *w, Word16 *p_best_scale, Word16 *p_best_idx, const Word16 *no_leaders, Word16 sig,Word16 *indx); +static Word16 find_pos_fx( Word16 *c, Word16 len, Word16 arg, Word16 *p ); +static void take_out_val_fx( Word16 *v, Word16 *v_out, Word16 val, Word16 len ); +static Word16 index_leaders_fx( Word16 *cv, Word16 idx_lead, Word16 dim ); +static Word16 c2idx_fx( Word16 n, Word16 *p, Word16 k ); +static Word16 encode_sign_pc1_fx( Word16 parity, Word16 *cv); +static Word32 encode_comb_fx( Word16 *cv, Word16 idx_lead ); +static void sort_desc_ind_fx( Word16 *s, Word16 len, Word16 *ind ); + + +/*-----------------------------------------------------------------* + * mslvq_fx() + * + * Encodes the LSF residual + *-----------------------------------------------------------------*/ +Word32 mslvq_fx ( + Word16 *pTmp, /* i : M-dimensional input vector x2.56*/ + Word16 *quant, /* o : quantized vector x2.56*/ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) Q13*/ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + Word16 *w, /* i : weights for LSF quantization Q10*/ + Word16 mode, /* i : number indicating the coding type (V/UV/G...)*/ + Word16 mode_glb, /* i : LVQ coding mode */ + Word16 pred_flag, /* i : prediction flag (0: safety net, 1,2 - predictive )*/ + Word16 no_scales[][2] +) +{ + Word32 dist, L_tmp; + const Word16 * p_scales, *p_sigma, *p_inv_sigma; + const Word16 *p_no_lead; + Word16 * p_no_scales; + + + dist = L_deposit_l(0); + p_no_scales = no_scales[mode_glb]; + move16(); + + IF ( pred_flag == 0 ) + { + p_sigma = sigma_MSLVQ_fx[mode]; + /* inverse sigma is precomputed to save complexity */ + p_inv_sigma = inv_sigma_MSLVQ_fx[mode]; + p_scales = scales_fx[mode_glb]; + p_no_lead = no_lead_fx[mode_glb]; + } + ELSE + { + p_sigma = sigma_p_fx[mode]; + /* inverse sigma is precomputed to save complexity */ + p_inv_sigma = inv_sigma_p_fx[mode]; + p_scales = scales_p_fx[mode_glb]; + p_no_lead = no_lead_p_fx[mode_glb]; + } + + /* first subvector */ + dist = quantize_data_fx( pTmp, w, quant, cv_out, idx_lead, idx_scale, + p_sigma, p_inv_sigma, p_scales, p_no_scales[0], p_no_lead ); + /* second subvector */ + L_tmp = quantize_data_fx(pTmp + LATTICE_DIM, w + LATTICE_DIM, quant + LATTICE_DIM, + cv_out + LATTICE_DIM, &idx_lead[1], &idx_scale[1], + p_sigma + LATTICE_DIM, p_inv_sigma + LATTICE_DIM, p_scales + MAX_NO_SCALES, + p_no_scales[1], p_no_lead+MAX_NO_SCALES ); + + dist = L_add(dist, L_tmp); + + return dist; +} +/*-----------------------------------------------------------------* + * q_data() + * + * (used for LSF quantization in CNG) + *-----------------------------------------------------------------*/ + +static Word32 q_data_fx( + Word16 *pTmp1, /* i: M-dimensional input vector x2.56 */ + const Word16 *w1, /* i: M-dimensional weight vector Q8 */ + Word16 *quant, /* o: quantized vector x2.56 */ + Word16 *cv_out, /* o: non-scaled lattice codevector x2.56 */ + Word16 *idx_lead, /* o: leader indexes for each subvector */ + Word16 *idx_scale, /* o: scale indexes for each subvector */ + const Word16 *p_sigma, /* i: standard deviation x2.56 */ + const Word16 *p_inv_sigma, /* i: inverse standard deviation Q15 */ + const Word16 *p_scales, /* i: scale values Q11 */ + Word16 *p_no_scales, /* i: number of scales/truncations for each subvector */ + const Word16 *p_no_lead /* i: number of leaders for each truncation and each subvector */ +) +{ + Word32 dist, L_tmp; + /* first subvector */ + dist = quantize_data_fx( pTmp1, w1, quant, cv_out, idx_lead, idx_scale, + p_sigma, p_inv_sigma, p_scales, p_no_scales[0], p_no_lead ); + /* second subvector */ + L_tmp = quantize_data_fx( pTmp1+LATTICE_DIM, w1+LATTICE_DIM, + quant+LATTICE_DIM, cv_out+LATTICE_DIM, &idx_lead[1], &idx_scale[1], + p_sigma+LATTICE_DIM, p_inv_sigma+LATTICE_DIM, p_scales+MAX_NO_SCALES, + p_no_scales[1], p_no_lead+MAX_NO_SCALES ); + + dist = L_add(dist,L_tmp); + + return dist; +} + +/*-----------------------------------------------------------------* + * mslvq_cng() + * + * Encodes the LSF residual in SID frames with LVQ + * LVQ has separate codebook for each individual first stage index + *-----------------------------------------------------------------*/ + + +Word32 mslvq_cng_fx ( + Word16 idx_cv, /* i : index of cv from previous stage */ + Word16 *pTmp, /* i : 16 dimensional input vector x2.56*/ + Word16 *quant, /* o : quantized vector x2.56*/ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) Q13*/ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + const Word16 *w, /* i : weights for LSF quantization Q10*/ + Word16 * no_scales +) +{ + Word32 dist; + const Word16 *p_scales, *p_sigma, *p_inv_sigma; + const Word16 *p_no_lead; + Word16 *p_no_scales; + Word16 mode_glb, mode, i; + Word16 pTmp1[M], w1[M]; + + dist = L_deposit_l(0); + mode = add(LVQ_COD_MODES, idx_cv); + move16(); + + /* for CNG there is only one bitrate but several lattice quantizer structures, + depending on the previous VQ stage */ + mode_glb = add(START_CNG, idx_cv); + move16(); + + p_sigma = sigma_MSLVQ_fx[mode]; + move16(); + p_inv_sigma = inv_sigma_MSLVQ_fx[mode]; + move16(); + p_scales = scales_fx[mode_glb]; + move16(); + p_no_lead = no_lead_fx[mode_glb]; + move16(); + p_no_scales = &no_scales[shl(mode_glb,1)]; + move16(); + + /* check if LSF component permutation is needed or not */ + IF ( cng_sort[idx_cv] ) + { + FOR( i=0; i 0 ) + { + prepare_data_fx( cv_pot, sign, data, w, w_in, sigma, inv_sigma, &sig ); + move16(); + /* sorting of the input vector based on its absolute values; indx: permutation corresponding to the sorting */ + sort_desc_ind_fx( cv_pot, LATTICE_DIM, indx ); + smallest = indx[LATTICE_DIM-1]; + move16(); + + min_dist = calculate_min_dist_fx( cv_pot, no_scales, scale, w, &best_scale, &best_idx ,no_leaders, sig, indx); + + IF ( GT_16(best_scale,-1) ) + { + FOR(j=0; j 0 ; k-- ) + { + IF (sorted) + { + BREAK; + } + + sorted = 1; + move16(); + FOR ( i=0 ; i < k ; i++ ) + { + IF ( LT_16(s[i],s[i+1])) + { + sorted = 0; + move16(); + t = s[i]; + move16(); + s[i] = s[i+1]; + move16(); + s[i+1] = t; + move16(); + a = ind[i]; + move16(); + ind[i] = ind[i+1]; + move16(); + ind[i+1] = a; + move16(); + } + } + } + + return; +} + +/*-----------------------------------------------------------------* + * index_lvq() + * + * sorts in descending order and computes indices in the sorted vector + *-----------------------------------------------------------------*/ +void index_lvq_fx ( + Word16 *quant, /* i : codevector to be indexed (2 8-dim subvectors) Q13*/ + Word16 *idx_lead, /* i : leader class index for each subvector */ + Word16 *idx_scale, /* i :scale index for each subvector */ + Word16 mode, /* i : integer signalling the quantizer structure for the current bitrate */ + Word16 *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ + Word32 * p_offset_scale1, /* i : scales for first subvector */ + Word32 * p_offset_scale2, /* i : scales for second subvector */ + Word16 * p_no_scales /* i : number of scales for each subvector */ +) +{ + Word32 index1, index2 + ; + Word16 len_offset; + Word64 idx64; + Word64 index2_64; + + len_offset = add(MAX_NO_SCALES,1); + move16(); + + index1 = 0; + move16(); + + /* for first subvector */ + IF ( GT_16(idx_scale[0],-1) ) + { + index1 = L_add(encode_comb_fx(quant, idx_lead[0]), L_add(table_no_cv_fx[idx_lead[0]] , p_offset_scale1[i_mult2(mode,len_offset) +idx_scale[0]])); + } + + /* for second subvector */ + index2 = L_deposit_l(0); + + IF ( GT_16(idx_scale[1], -1) ) + { + index2 = L_add(encode_comb_fx(&quant[LATTICE_DIM], idx_lead[1]), L_add(table_no_cv_fx[idx_lead[1]], p_offset_scale2[i_mult2(mode,len_offset)+idx_scale[1]])); + } + idx64 = W_mult0_32_32(index1, p_offset_scale2[mode*len_offset+p_no_scales[mode*2+1]]); + index2_64 = W_deposit32_l (index2); + idx64 = W_add_nosat(idx64, index2_64); + + /* convert to 3 short */ + index[0] = ((idx64)&(0x7fff)); + move16(); + index[1] = (idx64>>15)&(0x7fff); + move16(); + index[2] = (idx64>>30)&(0x7fff); + move16(); + return; +} + + +/*-----------------------------------------------------------------* + * encode_comb() + * + * creates an index for the lattice codevector + *-----------------------------------------------------------------*/ + +static Word32 encode_comb_fx( /* o : index of the absolute valued codevector*/ + Word16 *cv, /* i : codevector to be indexed Q13*/ + Word16 idx_lead /* i : leader class index, to know the values */ +) +{ + Word16 idx_sign, idx_ld_class; + Word32 L_tmp; + + idx_sign = encode_sign_pc1_fx( pl_par[idx_lead], cv ); + move16(); + idx_ld_class = index_leaders_fx( cv, idx_lead, LATTICE_DIM ); + move16(); + + L_tmp = L_mac0(idx_ld_class, idx_sign,pi0[idx_lead]); + + return L_tmp; +} + +/*-----------------------------------------------------------------* + * index_leaders() + * + * gives the index in a class of leaders without considering the sign yet + *-----------------------------------------------------------------*/ + +static Word16 index_leaders_fx( /* o : index */ + Word16 *cv, /* i : codevector to be indexed Q13*/ + Word16 idx_lead, /* i : leader class index */ + Word16 dim /* i : vector dimension */ +) +{ + Word16 index; + Word16 i, no_vals_loc, nr, p[LATTICE_DIM], dim_loc; + Word16 cv_copy[LATTICE_DIM], val_crt; + + no_vals_loc = no_vals[idx_lead]; + move16(); + + IF ( EQ_16(no_vals_loc, 1)) + { + return 0; + } + + FOR( i=0; i 0 ) + { + cnt = add(cnt, 1); + } + } + + return idx_sign; +} + +/*-----------------------------------------------------------------* + * take_out_val() + * + * removes the value val from the vector v + *-----------------------------------------------------------------*/ + +static void take_out_val_fx( + Word16 *v, /* i : input vector x2.56*/ + Word16 *v_out, /* o : output vector without the value val */ + Word16 val, /* i : value to be removed x2.56*/ + Word16 len /* i : input vector length */ +) +{ + Word16 i, cnt; + + cnt = 0; + move16(); + + FOR( i=0; i +#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" + +#define THR_CORR_FX (56<<15) /* 56 in Q15 starting threshold of multi-harm. correlation */ +#define THR_CORR_MAX_FX 30720 /* 60 in Q9 upper threshold of multi-harm. correlation */ +#define THR_CORR_MIN_FX 25088 /* 49 in Q9 lower threshold of multi-harm. correlation */ +#define THR_CORR_STEP_FX 102 /* 0.2 in Q9 step for the threshold of multi-harm. correlation */ + +/*---------------------------------------------------------------------* + * multi_harm() + * + * Perform multi-harmonic analysis, information used for UV and VAD decision + *---------------------------------------------------------------------*/ + +Word16 multi_harm_fx( /* o : frame multi-harmonicity (1-harmonic, 0-not) */ + const Word16 Bin_E[], /* i : log-energy spectrum of the current frame Q7 */ + Word16 old_S[], /* i/o: prev. log-energy spectrum w. subtracted floor Q7 */ + Word16 cor_map_LT[], /* i/o: LT correlation map Q15 */ + Word16 *multi_harm_limit, /* i/o: multi harminic threshold Q9 */ + const Word32 total_brate, /* i : total bitrate Q0 */ + const Word16 bwidth, /* i : input signal bandwidth Q0 */ + Word16 *cor_strong_limit, /* i/o: HF correlation indicator Q0 */ + Word16 *st_mean_avr_dyn, /* i/o: long term average dynamic Q7 */ + Word16 *st_last_sw_dyn, /* i/o: last dynamic Q7 */ + Word16 *cor_map_sum, /* i : sum of correlation map Q8 */ + Word16 *sp_floor, /* o: noise floor estimate Q7 */ + Word16 S_map[] /* o : short-term correlation map Q7 */ +) +{ + Word16 i, j, k, L, stemp, N_mins, ind_mins[L_FFT/4], *pt_mins, harm; + Word16 S[L_FFT/2], flor, step, sign_fx, tmp16, tmp2, ExpInd, tmpdB, ExpdB, Expx2, Expy2; + Word16 corx2, cory2, corxy, cor, cor_map[L_FFT/2], *pt1, *pt2, cor_strong; + Word32 L_acc; + Word32 Lcorx2, Lcory2, Lcorxy, Lcor_map_LT_sum; + Word16 mean_dyn; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*------------------------------------------------------------------* + * initialization + *------------------------------------------------------------------*/ + + /* length of the useful part of the spectrum (up to 6.4kHz) */ + L = L_FFT/2; + move16(); + if ( EQ_16(bwidth,NB)) + { + /* length of the useful part of the spectrum (up to 3.6kHz) */ + L = 76; + move16(); + } + + Copy(Bin_E, S, L); + + /*------------------------------------------------------------------* + * searching of spectral maxima and minima + *------------------------------------------------------------------*/ + + pt_mins = ind_mins; + move16(); + + /* index of the first minimum */ + if (LT_16(Bin_E[0],Bin_E[1])) + { + *pt_mins++ = 0; + move16(); + } + + FOR (i=1; i 0) + { + L_acc = L_deposit_l(0); + FOR (i=0; i 0) + { + Lcorx2 = L_deposit_l(0); + Lcorxy = L_deposit_l(0); + stemp = ind_mins[0]; + move16(); + Lcory2 = L_mult(old_S[stemp],old_S[stemp]); + k = 1; + move16(); + + FOR (i = add(stemp,1); i <= ind_mins[N_mins]; i++) + { + IF (EQ_16(i,ind_mins[k])) + { + /* include the last peak point (new minimum) to the corr. sum */ +#ifdef BASOP_NOGLOB + Lcory2 = L_mac_o(Lcory2, old_S[i], old_S[i], &Overflow); +#else /* BASOP_NOGLOB */ + Lcory2 = L_mac(Lcory2, old_S[i], old_S[i]); +#endif /* BASOP_NOGLOB */ + + /* calculation of the norm. peak correlation */ + test(); + IF (Lcorx2 != 0 && Lcory2 != 0) + { + /* corxy * corxy*/ + tmp16 = sub(norm_l(Lcorxy),1); + corxy = extract_h(L_shl(Lcorxy, tmp16)); + corxy = mult_r(corxy, corxy); + /* (corx2 * cory2) */ + Expx2 = norm_l(Lcorx2); + Expy2 = norm_l(Lcory2); + corx2 = extract_h(L_shl(Lcorx2, Expx2)); + cory2 = extract_h(L_shl(Lcory2, Expy2)); + corx2 = mult_r(corx2, cory2); + Expx2 = add(Expy2, Expx2); + /* Validate num < den */ + cor = sub(corx2, corxy); + cor = shr(cor, 15); + /* Add 1 to tmp16 & shr by 2 if corxy > corx2 */ + tmp16 = sub(tmp16, cor); + corxy = shl(corxy, cor); + corxy = shl(corxy, cor); + /* cor = corxy * corxy / (corx2 * cory2) */ + corxy = div_s(corxy, corx2); +#ifdef BASOP_NOGLOB + cor = shr_o(corxy, sub(shl(tmp16, 1), Expx2), &Overflow); /* Q15 */ +#else /* BASOP_NOGLOB */ + cor = shr(corxy, sub(shl(tmp16, 1), Expx2)); /* Q15 */ +#endif /* BASOP_NOGLOB */ + } + ELSE + { + cor = 0; + move16(); + } + + /* save the norm. peak correlation in the correlation map */ + FOR (j=ind_mins[k-1]; j 0) || (cor_strong != 0) ) + { + harm = 1; + move16(); + } + + /*------------------------------------------------------------------* + * updating of the decision threshold + *------------------------------------------------------------------*/ + + stemp = add(*multi_harm_limit, THR_CORR_STEP_FX); + if (GT_32(Lcor_map_LT_sum, THR_CORR_FX)) /* Q15 */ + { + /* *multi_harm_limit -= THR_CORR_STEP_FX */ + stemp = sub(*multi_harm_limit, THR_CORR_STEP_FX); + } + + stemp = s_min(stemp, THR_CORR_MAX_FX); + *multi_harm_limit = s_max(stemp, THR_CORR_MIN_FX); + move16(); + + IF (N_mins <= 0) + { + set16_fx(old_S, 0, L); + } + IF (S_map != NULL) + { + Copy(S, S_map, L); + } + return harm; +} diff --git a/lib_enc/nelp_enc_fx.c b/lib_enc/nelp_enc_fx.c index c5042c48abf1f488477fa503ca8784010bdcc596..a1cf4b1886a0f80ffadb9b89fd8a8c2eaceac262 100644 --- a/lib_enc/nelp_enc_fx.c +++ b/lib_enc/nelp_enc_fx.c @@ -34,8 +34,9 @@ #include "control.h" #include "options.h" /* Compilation switches */ #include "cnst.h" /* Common constants */ -#include "prot_fx2.h" /* Function prototypes */ #include "prot_fx1.h" +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ #include "rom_com.h" /*===================================================================*/ @@ -294,7 +295,7 @@ static void normalize_arr(Word16 *arr, Word16 *qf, Word16 size, Word16 hdr) /*===================================================================*/ 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, @@ -335,7 +336,7 @@ void nelp_encoder_fx( rf_flag = st_fx->rf_mode; - if (EQ_16(hSC_VBR->last_nelp_mode, 1) && NE_16(st_fx->bwidth, st_fx->last_bwidth)) + if (EQ_16(hSC_VBR->last_nelp_mode, 1) && NE_16(st_fx->bwidth_fx, st_fx->last_bwidth_fx)) { hSC_VBR->last_nelp_mode = 0; } @@ -343,7 +344,7 @@ void nelp_encoder_fx( qIn = *qIn1; move16(); test(); - IF(EQ_16(st_fx->bwidth, NB)) + IF(EQ_16(st_fx->bwidth_fx, NB)) { IF(hSC_VBR->last_nelp_mode != 1) { @@ -354,7 +355,7 @@ void nelp_encoder_fx( move16(); } } - ELSE IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB)) + ELSE IF(EQ_16(st_fx->bwidth_fx, WB) || EQ_16(st_fx->bwidth_fx, SWB)) { IF(hSC_VBR->last_nelp_mode != 1) { @@ -367,7 +368,7 @@ void nelp_encoder_fx( IF(hSC_VBR->last_nelp_mode != 1) { test(); - IF(st_fx->bwidth == WB || EQ_16(st_fx->bwidth, SWB)) + IF(st_fx->bwidth_fx == WB || EQ_16(st_fx->bwidth_fx, SWB)) { set16_fx(hSC_VBR->shape1_filt_mem_fx, 0, 10); set16_fx(hSC_VBR->shape2_filt_mem_fx, 0, 10); @@ -385,7 +386,7 @@ void nelp_encoder_fx( /* Start Unvoiced/NELP Processing */ test(); - IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB)) + IF(EQ_16(st_fx->bwidth_fx, WB) || EQ_16(st_fx->bwidth_fx, SWB)) { qE1 = qIn; move16(); @@ -675,7 +676,7 @@ void nelp_encoder_fx( qGain = 0; move16(); - quantize_uvg_fx(Gains_fx, &iG1_fx, iG2_fx, Gains_fx, st_fx->bwidth); + quantize_uvg_fx(Gains_fx, &iG1_fx, iG2_fx, Gains_fx, st_fx->bwidth_fx); IF(EQ_16(rf_flag, 1)) { @@ -691,7 +692,7 @@ void nelp_encoder_fx( } test(); - IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB)) + IF(EQ_16(st_fx->bwidth_fx, WB) || EQ_16(st_fx->bwidth_fx, SWB)) { gain_fac_fx = 19005; move16();/* 1.16f in Q14 */ @@ -708,14 +709,14 @@ void nelp_encoder_fx( generate_nelp_excitation_fx(&(hSC_VBR->nelp_enc_seed), Gains_fx, ptr_fx, gain_fac_fx); test(); - IF(EQ_16(st_fx->bwidth, WB) || EQ_16(st_fx->bwidth, SWB)) + IF(EQ_16(st_fx->bwidth_fx, WB) || EQ_16(st_fx->bwidth_fx, SWB)) { BP1_ORDER = 4; Scale_sig(hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER * 2, qGain - hSC_VBR->qprevGain_fx);/*qf-qAdj */ pz_filter_sp_fx(bp1_num_coef_wb_fx, bp1_den_coef_wb_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, 2); Copy(ptr_tmp_fx, ptr_fx, L_FRAME); } - ELSE IF(EQ_16(st_fx->bwidth, NB)) + ELSE IF(EQ_16(st_fx->bwidth_fx, NB)) { BP1_ORDER = 7; move16(); @@ -735,7 +736,7 @@ void nelp_encoder_fx( qE3 = 2 * qGain + 1; move16(); test(); - IF(st_fx->bwidth == WB || EQ_16(st_fx->bwidth, SWB)) + IF(st_fx->bwidth_fx == WB || EQ_16(st_fx->bwidth_fx, SWB)) { Scale_sig(hSC_VBR->shape1_filt_mem_fx, 10, (qGain - hSC_VBR->qprevGain_fx)); pz_filter_sp_fx(shape1_num_coef_fx, shape1_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape1_filt_mem_fx, 10, 10, L_FRAME, 1);/*1 = (16-qformat of shape1 cofficient) */ diff --git a/lib_enc/nois_est_fx.c b/lib_enc/nois_est_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..724aef5956755e59d498d44a636726367121e24e --- /dev/null +++ b/lib_enc/nois_est_fx.c @@ -0,0 +1,1935 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include +#include "options.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 */ +#include "basop_util.h" + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define ALPHA_FX 3277 /*.1 Q15*/ +#define ALPHAM1_FX 29491 /*.9 Q15*/ + +#define TH_PC_FX 12 /* max sum of pitch differencies */ + +#define BCKR_SLOW_UPDATE_SCALE_FX 3277 /*Q15 Step size for slow bckr update */ +#define COR_MIN16_FX 17039 /*.52 Q15 */ +#define COR_MAX16_FX 27853 /*.85 Q15 */ + +/* 10.0e5f causes problems with music - as the noise estimate starts to track the music */ +#define TH_STA16_FX (350000<<10) /* MODE1: 3.5e5f */ + +#define TH_EPS16_FX 3277 /* Q11 (1.6) tuned for speech only, not for music */ +#define K_16_FX 25690 /* Q20 (0.0245f) */ +#define C_16_FX -1925 /* Q13 (-0.235f) */ +#define ALPHA_MAX16_FX 32440 /* Q15 (0.99) */ + +#define COR_MIN8_FX 21299 /*.65 Q15 */ +#define COR_MAX8_FX 22938 /*.70 Q15 */ +#define TH_EPS8_FX 21299 /* 10.4 in Q11 Thresholds for NB processing - ... */ +#define TH_STA8_FX (500000<<10) +#define K_8_FX 9452 /* Q20 (0.0091f) */ +#define C_8_FX 2609 /* Q13 (0.0091f) */ +#define ALPHA_MAX8_FX 32735 /* Q15 (0.999) */ + +#define HC_CNT_SLOW_FX 80 /* limit for harm corr count slow */ + +#define HE_LT_CNT_PRE_FX 50 +#define HE_LT_CNT_INIT_FX 150 +#define HE_LT_CNT_PRE_SHORT_FX 250 +#define HE_LT_CNT_FX 30 + +#define LN_E_MIN_PLUS_ONE_FX 1 /* max(1, ln(E_MIN+1.0)) = max(1,ln(0.0035f+1f)) in Q8 */ +#define COR_MAX_NNE_FX 27853 /* 0.85 Q15 */ + +#define HE_LT_THR1_FX 2560 /*10.0 Q8*/ +#define HE_LT_THR2_FX 7680 /*30.0 Q8*/ + +/*-----------------------------------------------------------------* + * noise_est_AR1_Qx() + * + * y(n)(Qx) = alpha(Q15) * x(Qx) + (1.0f-alpha)* y(n-1) (Qx) + *-----------------------------------------------------------------*/ + +Word16 noise_est_AR1_Qx( /* o : Qx y(n) */ + Word16 x, /* i : Qx x(n) */ + Word16 y, /* i : Qx y(n-1) */ + Word16 alpha /*i : Q15 scaling of driving x(n) */ +) +{ + Word16 alpham1; + /*alpham1 = negate(add((Word16)-32768, alpha)); */ + alpham1 = sub(32767, alpha); /* one cycle less */ + + return mac_r(L_mult(y, alpham1), x, alpha); +} + +/*-----------------------------------------------------------------* + * noise_est_ln_q8_fx() + * + * q8 = (float)log( L_enr[i] + add1po*1.0 ); + *-----------------------------------------------------------------*/ + +static Word16 noise_est_ln_q8_fx( + Word32 L_enr, + Word16 flag_add1p0, /* flag to add 1.0 */ + Word16 q_new_plus_q_scale ) +{ + Word16 e_ener, f_ener; + Word32 L_tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + +#ifdef BASOP_NOGLOB + L_tmp = L_add_o(L_enr, L_shl((Word32)1L, q_new_plus_q_scale), &Overflow); /* +1.0f */ +#else /* BASOP_NOGLOB */ + L_tmp = L_add(L_enr, L_shl((Word32)1L, q_new_plus_q_scale)); /* +1.0f */ +#endif /* BASOP_NOGLOB */ + if( flag_add1p0 == 0 ) + { + L_tmp = L_add(L_enr, 0); /* +0 , no offset */ + } + + L_tmp = L_max(L_tmp,(Word32)1L); /* make sure log2_norm_lc does not cause table reading out of bounds */ + + e_ener = norm_l(L_tmp); + f_ener = Log2_norm_lc(L_shl(L_tmp, e_ener)); + e_ener = sub(sub(30,e_ener),q_new_plus_q_scale); + L_tmp = Mpy_32_16(e_ener, f_ener, 22713); /* Q16 (22713 = Ln(2) in Q15)*/ + return round_fx(L_shl(L_tmp, 8)); /* Q8 */ +} + +/*-----------------------------------------------------------------* + * eps_quota_fx() + * + * + *-----------------------------------------------------------------*/ + +static Word32 eps_quota_fx( /* o: eps_num/eps_den in q_out */ + Word16 eps_num_h, /* num high ,*/ + Word16 eps_num_l, /* num low (signed) ,*/ + Word16 eps_den_h, /* den low */ + Word16 eps_den_l, /* den low (signed),*/ + Word16 q_out /* range 15...0 , tested with 11 and 12 */ +) +{ + Word32 L_tmp_num, L_tmp_den; + Word16 exp_num, exp_den; + Word16 m_num, m_den; + Word16 num_shift; + + + L_tmp_num = L_Comp(eps_num_h, eps_num_l); + L_tmp_den = L_Comp(eps_den_h, eps_den_l); + + exp_num = sub(norm_l(L_tmp_num), 1); /* make sure m_ num is lower than m_den */ + m_num = extract_h(L_shl(L_tmp_num, exp_num)); + exp_den = norm_l(L_tmp_den); + m_den = extract_h(L_shl(L_tmp_den, exp_den)); + + exp_num = sub(exp_num, exp_den); + if (m_den != 0) + { + assert(m_den >= m_num); + m_num = div_s(m_num, m_den); /* single basop */ + } + + num_shift = add(15-q_out, exp_num); + if (m_den == 0) + { + /* no division made due to zero denominator */ + m_num = 0; + move16(); + } + + return L_shr(m_num, num_shift); +} + +/*-----------------------------------------------------------------* + * noise_est_init_fx() + * + * Initialization of Noise estimator + *-----------------------------------------------------------------*/ +void noise_est_init_fx( + NOISE_EST_HANDLE hNoiseEst /* i/o: Noise estimation handle */ +) +{ + Word16 i; + + FOR(i = 0; i < NB_BANDS; i++) + { + hNoiseEst->fr_bands1_fx[i] = 1; + move32();/*1e-5f; */ + hNoiseEst->fr_bands2_fx[i] = 1; + move32();/*1e-5f; */ + hNoiseEst->ave_enr2_fx[i] = E_MIN_FX; + move32(); /*Q7//E_MIN; */ + hNoiseEst->enrO_fx[i] = E_MIN_FX; + move32(); + hNoiseEst->bckr_fx[i] = E_MIN_FX; + move32(); + hNoiseEst->ave_enr_fx[i] = E_MIN_FX; + move32(); + } + move16(); + hNoiseEst->totalNoise_fx = 0; + move16(); + hNoiseEst->first_noise_updt = 0; + //hNoiseEst->first_noise_updt_cnt_fx = 0; IVAS_CODE ?? + move16(); + + hNoiseEst->aEn = 6; + //hNoiseEst->aEn_inac_cnt = 0; IVAS_CODE + move16(); + + hNoiseEst->harm_cor_cnt = 0; + move16(); + hNoiseEst->bg_cnt = 0; + move16(); + + hNoiseEst->lt_tn_track_fx = 6554; /*.20 in Q15*/ move16(); + hNoiseEst->lt_tn_dist_fx = 0; + move16(); + hNoiseEst->lt_Ellp_dist_fx = 0; + move16(); + hNoiseEst->lt_haco_ev_fx = 13107; /*.40 in Q15*/ move16(); + hNoiseEst->low_tn_track_cnt = 0; + move16(); + + hNoiseEst->Etot_st_est_fx = 5120; /* 20.0f in Q8 */ + hNoiseEst->Etot_sq_st_est_fx = 1600; /* 400 in Q2 */ +//### + + hNoiseEst->epsP_0_2_lp_fx = 4096; /*1.0 Q12*/ move16(); + hNoiseEst->epsP_0_2_ad_lp_fx = 0; + move16(); + hNoiseEst->epsP_2_16_lp_fx = 4096; + move16(); + hNoiseEst->epsP_2_16_lp2_fx = 4096; + move16(); + hNoiseEst->epsP_2_16_dlp_lp2_fx = 0; + move16(); + hNoiseEst->lt_aEn_zero_fx = 0; + move16(); + + /* Tonal detector */ + FOR(i = 0; i < L_FFT / 2; i++) + { + hNoiseEst->old_S_fx[i] = 1; + move16(); + } + set16_fx(hNoiseEst->cor_map_fx, 0, L_FFT / 2); + hNoiseEst->act_pred_fx = 32767; + move16(); + hNoiseEst->noise_char_fx = 0; + move16(); + hNoiseEst->multi_harm_limit_fx = THR_CORR_INIT_FX; + + hNoiseEst->Etot_lp_fx = 0; + hNoiseEst->Etot_h_fx = 0; + hNoiseEst->Etot_l_fx = 0; + hNoiseEst->Etot_l_lp_fx = 0; + hNoiseEst->Etot_last_fx = 0; + hNoiseEst->Etot_v_h2_fx = 0; + hNoiseEst->sign_dyn_lp_fx = 0; + move16(); move16(); move16();move16(); + move16();move16();move16(); + + return; + +} +/*-----------------------------------------------------------------* + * noise_est_pre_fx() + * + * Track energy and signal dynamics + *-----------------------------------------------------------------*/ + +void noise_est_pre_fx( + const Word16 Etot, /* i : Energy of current frame */ + const Word16 ini_frame_fx, /* i : Frame number (init) */ + NOISE_EST_HANDLE hNoiseEst, /* i/o: Noise estimation handle */ + const int16_t idchan, /* i : channel ID */ + const int16_t element_mode, /* i : element mode */ + const int16_t last_element_mode /* i : last element mode */ +) +{ + Word16 tmp; + + IF(LE_16(ini_frame_fx, 1) || (EQ_16(idchan, 1) && EQ_16(element_mode, IVAS_CPE_TD) && EQ_16(last_element_mode, IVAS_CPE_DFT))) + { + hNoiseEst->Etot_h_fx = Etot; + move16(); + hNoiseEst->Etot_l_fx = Etot; + move16(); + hNoiseEst->Etot_l_lp_fx = Etot; + move16(); + hNoiseEst->Etot_last_fx = Etot; + move16(); + hNoiseEst->Etot_v_h2_fx = 0; + move16(); + hNoiseEst->Etot_lp_fx = Etot; + move16(); + hNoiseEst->sign_dyn_lp_fx = 0; + move16(); + } + ELSE + { + /* *Etot_lp = 0.20f*Etot + 0.80f* *Etot_lp; */ + hNoiseEst->Etot_lp_fx = mac_r(L_mult(6554, Etot), 26214, hNoiseEst->Etot_lp_fx); + move16(); + + hNoiseEst->Etot_h_fx = sub(hNoiseEst->Etot_h_fx, 10); + move16(); /* 10=0.04 in Q8 */ + hNoiseEst->Etot_h_fx = s_max(hNoiseEst->Etot_h_fx, Etot); + move16(); + hNoiseEst->Etot_l_fx = add(hNoiseEst->Etot_l_fx, 20); + move16(); /* 20 = .08 in Q8 */ + + + /* Could even be higher but it also delays first entry to DTX */ + IF(GT_16(hNoiseEst->harm_cor_cnt,HE_LT_CNT_PRE_FX)) + { + test(); + IF((LT_16(ini_frame_fx , s_min(HE_LT_CNT_INIT_FX ,MAX_FRAME_COUNTER - 1))) + && (LT_16(sub(hNoiseEst->Etot_h_fx, hNoiseEst->Etot_lp_fx),(Word16)3 * 256)) /* 3.0 Q8 */ + ) + { + /* *Etot_l += min(2,(*Etot_last-*Etot_l)*0.1f); */ + tmp = mult_r(sub(hNoiseEst->Etot_last_fx, hNoiseEst->Etot_l_fx), 3277); /* factor in Q15 3277 .1*32768 */ + tmp = s_min(512, tmp); /* 2.0 in Q8 is 512*/ + hNoiseEst->Etot_l_fx = add(hNoiseEst->Etot_l_fx, tmp); + move16();/* Q8 */ + } + + /* Avoids large steps in short active segments */ + test(); + IF((GT_16(sub(hNoiseEst->Etot_last_fx, hNoiseEst->Etot_l_fx), HE_LT_THR2_FX)) /* 30.0f*Q8 */ + && (GT_16(hNoiseEst->harm_cor_cnt,HE_LT_CNT_PRE_SHORT_FX)) + ) + { + /* *Etot_l += (*Etot_last-*Etot_l)*0.02f; */ + hNoiseEst->Etot_l_fx = add(hNoiseEst->Etot_l_fx, mult_r(sub(hNoiseEst->Etot_last_fx, hNoiseEst->Etot_l_fx), 655)); + move16();/* 0.02 = 655 Q8*/ + } + ELSE IF(GT_16(sub(hNoiseEst->Etot_last_fx, hNoiseEst->Etot_l_fx), HE_LT_THR1_FX)) /* 10.0 in Q8*/ + { + hNoiseEst->Etot_l_fx = add(hNoiseEst->Etot_l_fx, 20); + move16();/* 0.08 is 20 in Q8*/ + } + + } + + hNoiseEst->Etot_l_fx = s_min(hNoiseEst->Etot_l_fx, Etot); + + IF(LT_16(ini_frame_fx,100) && LT_16(hNoiseEst->Etot_l_fx,hNoiseEst->Etot_l_lp_fx)) + { + /**Etot_l_lp = 0.1f * *Etot_l + (1.0f - 0.1) * *Etot_l_lp; */ + hNoiseEst->Etot_l_lp_fx = mac_r(L_mult(3277, hNoiseEst->Etot_l_fx), 29491, hNoiseEst->Etot_l_lp_fx); + move16(); + } + ELSE + { + test(); + test(); + test(); + test(); + IF(((GT_16(hNoiseEst->harm_cor_cnt, HE_LT_CNT_FX)) + && (GT_16(sub(hNoiseEst->Etot_last_fx, hNoiseEst->Etot_l_fx), HE_LT_THR2_FX)) + ) + || ((sub(hNoiseEst->harm_cor_cnt, HE_LT_CNT_FX) > 0) && (LT_16(ini_frame_fx, HE_LT_CNT_INIT_FX))) + || (GT_16(sub(hNoiseEst->Etot_l_lp_fx, hNoiseEst->Etot_l_fx), HE_LT_THR2_FX)) + ) + { + /**Etot_l_lp = 0.03f * *Etot_l + (1.0f - 0.03f) * *Etot_l_lp; */ + hNoiseEst->Etot_l_lp_fx = mac_r(L_mult(983, hNoiseEst->Etot_l_fx), 31785, hNoiseEst->Etot_l_lp_fx); + move16(); + + } + ELSE + { + /* *Etot_l_lp = 0.02f * *Etot_l + (1.0f - 0.02f) * *Etot_l_lp; */ + hNoiseEst->Etot_l_lp_fx = round_fx(L_mac(L_mult(655 , hNoiseEst->Etot_l_fx), 32113 , hNoiseEst->Etot_l_lp_fx)); + } + } + /**sign_dyn_lp = 0.1f * (*Etot_h - *Etot_l) + (1.0f - 0.1f) * *sign_dyn_lp;*/ + hNoiseEst->sign_dyn_lp_fx = round_fx(L_mac(L_mult(3277, sub(hNoiseEst->Etot_h_fx, hNoiseEst->Etot_l_fx)), 29491, hNoiseEst->sign_dyn_lp_fx)); + } + + return; +} + + +/*==================================================================================*/ +/* FUNCTION : noise_est_down_fx() */ +/*----------------------------------------------------------------------------------*/ +/* PURPOSE : Down-ward noise udatation routine */ +/*----------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word32[]) fr_bands : per band input energy Q_new+QSCALE */ +/* _ (Word32[]) bckr : per band background noise energy estimate Q_new+QSCALE */ +/* _ (Word16 ) min_band : minimum critical band Q0 */ +/* _ (Word16 ) max_band : maximum critical band Q0 */ +/* _ (Word32[]) bckr_he : per band background noise energy estimate Q_new+QSCALE */ +/* _ (Word16 ) Etot : Energy of current frame Q8 */ +/* _ (Word16* ) Etot_last : Energy of last frame Q8 */ +/* _ (Word16* ) Etot_v_h2 : Energy variaions of noise frames Q8 */ +/* _ (Word16 ) Q_new : Qformat */ +/*----------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word32[]) bckr : per band background noise energy estimate Q_new+QSCALE */ +/* _ (Word32[]) tmpN : temporary noise update Q_new+QSCALE */ +/* _ (Word32[]) enr : averaged energy over both subframes Q_new+QSCALE */ +/* _ (Word16* ) totalNoise : noise estimate over all critical bands Q8 */ +/* _ (Word16 ) Etot : Energy of current frame Q8 */ +/* _ (Word16* ) Etot_last : Energy of last frame Q8 */ +/* _ (Word16* ) Etot_v_h2 : Energy variaions of noise frames Q8 */ +/* _ (Word32[]) tmpN_he1 : temporary noise update 1 Q_new+QSCALE */ +/*----------------------------------------------------------------------------------*/ + + +void noise_est_down_fx( + const Word32 fr_bands[], /* i : per band input energy (contains 2 vectors) */ + Word32 bckr[], /* i/o: per band background noise energy estimate */ + Word32 tmpN[], /* o : temporary noise update */ + Word32 enr[], /* o : averaged energy over both subframes */ + const Word16 min_band, /* i : minimum critical band */ + const Word16 max_band, /* i : maximum critical band */ + Word16 *totalNoise, /* o : noise estimate over all critical bands */ + Word16 Etot, /* i : Energy of current frame */ + Word16 *Etot_last, /* i/o: Energy of last frame Q8 */ + Word16 *Etot_v_h2, /* i/o: Energy variations of noise frames Q8 */ + Word16 Q_new, + const Word32 e_min /* i : minimum energy scaled Q_new + QSCALE */ +) + +{ + Word32 Ltmp, L_tmp; + const Word32 *pt1, *pt2; + Word16 i; + Word16 e_Noise, f_Noise; + Word16 scale; + Word32 totalNoise_temp; + Word32 L_Etot, L_Etot_last, L_Etot_v_h2, L_Etot_v; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + L_Etot = L_shl(Etot, 16); /*Q24 for later AR1 computations*/ + L_Etot_last = L_shl(*Etot_last, 16); + L_Etot_v_h2 = L_shl(*Etot_v_h2, 16); + scale = add(Q_new,QSCALE); + move16(); + + /*-----------------------------------------------------------------* + * Estimate total noise energy + *-----------------------------------------------------------------*/ + + totalNoise_temp = L_deposit_l(0); + FOR (i = min_band; i <= max_band; i++) + { +#ifdef BASOP_NOGLOB + totalNoise_temp = L_add_o(totalNoise_temp, bckr[i], &Overflow); /*Q_new+QSCALE*/ +#else + totalNoise_temp = L_add(totalNoise_temp, bckr[i]); /*Q_new+QSCALE*/ +#endif + } + totalNoise_temp = L_max(totalNoise_temp,L_shl(e_min,4)); + + + totalNoise_temp = L_max(totalNoise_temp,(Word32)1L); /* make sure log2_norm_lc does not cause table reading out of bounds */ + + /*totalNoise = 10.0f * (float)log10( *totalNoise );*/ + e_Noise = norm_l(totalNoise_temp); + f_Noise = Log2_norm_lc(L_shl(totalNoise_temp, e_Noise)); + e_Noise = sub(30, e_Noise); + e_Noise = sub(e_Noise, scale); + Ltmp = Mpy_32_16(e_Noise, f_Noise, LG10); + *totalNoise = round_fx(L_shl(Ltmp, 10)); /*Q8*/ + + /*-----------------------------------------------------------------* + * Average energy per frame for each frequency band + *-----------------------------------------------------------------*/ + + pt1 = fr_bands; /*Q_new+QSCALE*/ + pt2 = fr_bands + NB_BANDS; + + FOR( i=0 ; i < NB_BANDS; i++ ) + { +#ifdef BASOP_NOGLOB + Ltmp = L_add_o(L_shr_r(*pt1,1),L_shr_r(*pt2,1), &Overflow); +#else /* BASOP_NOGLOB */ + Ltmp = L_add(L_shr_r(*pt1,1),L_shr_r(*pt2,1)); +#endif /* BASOP_NOGLOB */ + /*Ltmp = L_shr_r(L_add(*pt1,*pt2),1);*/ + enr[i] = Ltmp; + move32();/*Q_new+QSCALE*/ + pt1++; + pt2++; + } + + /*-----------------------------------------------------------------* + * Background noise energy update + *-----------------------------------------------------------------*/ + + FOR( i=0; i< NB_BANDS; i++ ) + { + /* tmpN[i] = (1-ALPHA) * bckr[i] + ALPHA * enr[i]; */ + L_tmp = Mult_32_16(enr[i], ALPHA_FX); /*ALPHA * enr2*/ + tmpN[i] = Madd_32_16(L_tmp, bckr[i], ALPHAM1_FX); + move32();/*Q_new+QSCALE*/ + tmpN[i] =L_max( tmpN[i] , e_min); /* handle div by zero in find_tilt_fx */ + + /* if( tmpN[i] < bckr[i] ) { bckr[i] = tmpN[i]; }*/ + /* Defend to increase noise estimate: keep as it is or decrease */ + bckr[i] = L_max(L_min(bckr[i], tmpN[i]), e_min); + move32();/*Q_new+QSCALE*/ + } + + /*------------------------------------------------------------------* + * Energy variation update + *------------------------------------------------------------------*/ + /*Etot_v = (float) fabs(*Etot_last - Etot);*/ + L_Etot_v = L_abs(L_sub(L_Etot_last, L_Etot)); /* Q24 */ + + /* *Etot_v_h2 = (1.0f-0.02f) * *Etot_v_h2 + 0.02f * min(3.0f, Etot_v); */ + L_Etot_v_h2 = Mult_32_16(L_Etot_v_h2, 32113); /*.98 in Q15 , Q24+Q15+1 -16 => Q24 */ + L_Etot_v = L_min((Word32)(3*(1<<24)), L_Etot_v); + L_tmp = Mult_32_16(L_Etot_v, 655); /*.02 in Q15 , Q24+Q15+1 -16 ==> Q24 ) */ + + *Etot_v_h2 = round_fx(L_add(L_Etot_v_h2, L_tmp)); /*Q24->Q8*/ + + /* if (*Etot_v_h2 < 0.1f) { *Etot_v_h2 = 0.1f; } */ + *Etot_v_h2 = s_max(*Etot_v_h2, 26 ); /* 0.1 in Q8*/ + + return; +} + +/*-----------------------------------------------------------------* +* noise_est_fx() +* +* Noise energy estimation (noise energy is updated in case of noise-only frame) +*-----------------------------------------------------------------*/ +void noise_est_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 old_pitch1, /* i : previous frame OL pitch[1] */ + const Word32 tmpN[], /* i : temporary noise update Q_new + QSCALE */ + const Word16 epsP_h[], /* i : msb prediction error energies Q_r-1 */ + const Word16 epsP_l[], /* i : msb prediction error energies Q_r-1 */ + const Word16 Etot, /* i : total channel E (see find_enr_fx.c) Q8 */ + const Word16 relE, /* i : (VA_CHECK addition) relative frame energy Q8? */ + const Word16 corr_shift, /* i : normalized correlation correction Q15 */ + const Word32 enr[], /* i : averaged energy over both subframes Q_new + Q_SCALE */ + Word32 fr_bands[], /* i : spectrum per critical bands of the current frame Q_new + Q_SCALE */ + Word16 *cor_map_sum, /* o : Q8 */ + Word16* ncharX, /* o : IVAS_CODE -> size of ncharX needs validation noise character for sp/mus classifier Qx? */ + Word16 *sp_div, /* o : Q_sp_div */ + Word16 *Q_sp_div, /* o : Q factor for sp_div */ + Word16 *non_staX, /* o : non-stationarity for sp/mus classifier */ + Word16 *loc_harm , /* o : multi-harmonicity flag for UV classifier */ + const Word32 *lf_E, /* i : per bin energy for low frequencies Q_new + Q_SCALE -2 */ + Word16 *st_harm_cor_cnt, /* i/o : 1st harm correlation timer Q0 */ + const Word16 Etot_l_lp, /* i : Smoothed low energy Q8 */ + const Word16 Etot_v_h2, /* i : Energy variations Q8 */ + Word16 *bg_cnt, /* i : Background burst length timer Q0 */ + Word16 EspecdB[], /* i/o: log E spectrum (with f=0) of the current frame Q7 for multi harm */ + Word16 Q_new, /* i : SCaling of current frame */ + const Word32 Le_min_scaled, /*i : Minimum energy value in Q_new + Q_SCALE */ + Word16 *sp_floor, /* o : noise floor estimate Q7 */ + Word16 S_map[], /* o : short-term correlation map Q7 */ +#ifdef IVAS_CODE + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + FRONT_VAD_ENC_HANDLE hFrontVad, /* i/o: front-VAD handle */ +#endif + const Word16 ini_frame /* i : Frame number (init) */ +) +{ + Word16 alpha, alpha2, alpha2m1, alpham1; + Word16 cor_min, cor_max, num, den, ExpNum, ExpDen, noise_chartmp; + Word16 wtmp1,wtmp, ExpLmax, ExpLmax2, tmpExp, nchar_thr, cor_tmp; + Word16 i, tmp_pc, pc,th_eps; + Word32 th_sta, Lnum, Lden, non_sta, LepsP, Ltmpden; + Word16 e_ener, f_ener; + Word32 Ltmp, Ltmp1,Lsum_num, Lsum_den, *pt1, *pt2,Ltmp2, Lnon_sta2; + Word16 spec_div, noise_char; + Word16 log_enr16; + Word16 updt_step ; /* Q15 */ + Word16 aE_bgd,sd1_bgd,bg_bgd2; + Word16 tn_ini; + Word16 epsP_0_2,epsP_0_2_ad,epsP_0_2_ad_lp_max; + Word16 epsP_2_16,epsP_2_16_dlp,epsP_2_16_dlp_max; + Word16 PAU, BG_1, NEW_POS_BG; + + Word16 haco_ev_max; + Word16 Etot_l_lp_thr; + Word16 comb_ahc_epsP, comb_hcm_epsP; + + Word16 enr_bgd,cns_bgd,lp_bgd,ns_mask; + Word16 lt_haco_mask, bg_haco_mask; + Word16 SD_1,SD_1_inv, bg_bgd3,PD_1,PD_2,PD_3,PD_4,PD_5; + + Word16 non_staB; /* Q8 */ + Word32 L_tmp_enr, L_tmp_ave_enr, L_tmp_ave_enr2; + Word16 tmp_Q; + Word16 tmp, tmp2; /* general temp registers */ + Word16 tmp_enr, tmp_floor ; /* constants in Q8 */ + Word16 vad_bwidth_fx; /* vad ns control variabel for input bwidth from teh BWD */ + /* for DTX operation */ + Word16 vad_2nd_stage_fx; + + Word16 lim_Etot_fx; /* Q8 */ + Word16 lim_Etot_sq_fx; /* Q2 */ + Word16 st_E_var_est_fx; /* Q2 */ + NOISE_EST_HANDLE hNoiseEst; + SP_MUS_CLAS_HANDLE hSpMusClas; + hSpMusClas = st_fx->hSpMusClas; +#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + (void)(ncharX); +#endif + /* Check if LR-VAD */ +#ifdef IVAS_CODE + IF (hFrontVad != NULL) + { + hNoiseEst = hFrontVad->hNoiseEst; + } + ELSE +#endif + { + hNoiseEst = st_fx->hNoiseEst; + } + + GSC_ENC_HANDLE hGSCEnc = st_fx->hGSCEnc; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + vad_bwidth_fx = st_fx->input_bwidth_fx; + move16(); + + /*st_fx->ener_RAT = 10.0f * (float)log10( mean(lf_E, 8));*/ +#ifdef IVAS_CODE + IF(hFrontVad == NULL) +#endif + { + if (hSpMusClas != NULL) + { + Ltmp = L_shr(lf_E[0], 3); + FOR(i = 1; i < 8; i++) + { + Ltmp = L_add(Ltmp, L_shr(lf_E[i], 3)); + } + IF (LT_32(Ltmp, L_shl(1, add(Q_new, Q_SCALE - 2)))) + { + hSpMusClas->ener_RAT_fx = 0; + //PMT("hSpMusClas->ener_RAT_fx = 0, that should be validated") + } + ELSE + { + Ltmp = L_max(Ltmp, (Word32)1L); /* make sure log2_norm_lc does not cause table reading out of bounds */ + e_ener = norm_l(Ltmp); + f_ener = Log2_norm_lc(L_shl(Ltmp, e_ener)); + e_ener = sub(30, e_ener); + e_ener = sub(e_ener, sub(add(Q_new, QSCALE), 2)); + Ltmp = Mpy_32_16(e_ener, f_ener, LG10); + wtmp = round_fx(L_shl(Ltmp, 10));/*Q8*/ + + /* st_fx->ener_RAT /= (Etot + 0.01f); */ + wtmp1 = add(Etot, 3);/*3 is 0.01 in Q8 */ + /* st_fx->ener_RAT_fx = wtmp/wtmp1 */ + hSpMusClas->ener_RAT_fx = 0; + move16(); + IF(wtmp > 0) + { + hSpMusClas->ener_RAT_fx = 32767; + move16(); /*Q15*/ + if (GE_16(wtmp1, wtmp)) + { + hSpMusClas->ener_RAT_fx = div_s(wtmp, wtmp1); /*Q15*//* wtmp1 gte than wtmp */ + } + } + } + } + } + /*-----------------------------------------------------------------* + * Set the threshold for eps & non_sta based on input sampling rate + * The reason is that in case of 8kHz sampling input, there is nothing + * between 4kHz-6.4kHz. In noisy conditions, this makes a fast + * transition even in noise-only parts, hence producing a "higher + * order" spectral envelope => the epsP ratio is much less effective. + *-----------------------------------------------------------------*/ + + IF (NE_16(vad_bwidth_fx,NB)) /* WB input */ + { + th_eps = TH_EPS16_FX; + move16();/*Q11*/ + th_sta = TH_STA16_FX; + move16();/*Q10 */ + cor_min = COR_MIN16_FX; + move16();/*Q15*/ + cor_max = COR_MAX16_FX; + move16();/*Q15*/ + } + ELSE /* NB input */ + { + th_eps = TH_EPS8_FX; + move16();/* Q11 */ + th_sta = TH_STA8_FX; + move16(); /* Q10 */ + cor_min = COR_MIN8_FX; + move16(); + cor_max = COR_MAX8_FX; + move16(); + } + + + /*-----------------------------------------------------------------* + * Estimation of pitch stationarity + *-----------------------------------------------------------------*/ + + /* pc = abs(pit[0] - pitO) + abs(pit[1] - pit[0]) */ /* needed in signal_clas() */ + wtmp = abs_s(sub(st_fx->pitch_fx[0], old_pitch1)); + wtmp1 = abs_s(sub(st_fx->pitch_fx[1], st_fx->pitch_fx[0])); + pc = add(wtmp, wtmp1); + + + Ltmp = L_deposit_h(corr_shift); + Ltmp = L_mac(Ltmp, st_fx->voicing_fx[0], 10923); +#ifdef BASOP_NOGLOB + Ltmp = L_mac_o(Ltmp, st_fx->voicing_fx[1], 10923, &Overflow); + wtmp = mac_ro(Ltmp, st_fx->voicing_fx[2], 10923, &Overflow); +#else /* BASOP_NOGLOB */ + Ltmp = L_mac(Ltmp, st_fx->voicing_fx[1], 10923); + wtmp = mac_r(Ltmp, st_fx->voicing_fx[2], 10923); +#endif /* BASOP_NOGLOB */ + + tmp_pc = pc; + move16(); + if (LT_16(wtmp, cor_min)) + { + tmp_pc = TH_PC_FX; + move16(); /* low correlation -> probably inactive signal */ + } + + move16(); /* Update */ + + /*-----------------------------------------------------------------* + * Multi-harmonic analysis + *-----------------------------------------------------------------*/ +#ifdef IVAS_CODE + IF (hFrontVad == NULL) +#endif + { + IF (st_fx->hSpMusClas != NULL) + { + i = 0; move16(); + *loc_harm = multi_harm_fx(EspecdB, hNoiseEst->old_S_fx, hNoiseEst->cor_map_fx, &hNoiseEst->multi_harm_limit_fx, st_fx->total_brate_fx, + st_fx->bwidth_fx, (st_fx->hGSCEnc != NULL) ? &hGSCEnc->cor_strong_limit : &i, &hSpMusClas->mean_avr_dyn_fx, &hSpMusClas->last_sw_dyn_fx, cor_map_sum, sp_floor, S_map); + } + } + /*-----------------------------------------------------------------* + * Detection of frames with non-stationary spectral content + *-----------------------------------------------------------------*/ + + /* weighted sum of spectral changes per critical bands */ + Lsum_num = L_deposit_l(0); + Lsum_den = L_deposit_l(0); + + /* Find a proper scaling to prevent overflow, but acheiving good computation on low level signals */ + tmpExp = 0; + move16(); + ExpLmax = sub(30, norm_l(fr_bands[10])); + ExpLmax2 = sub(30, norm_l(hNoiseEst->fr_bands2_fx[10])); + tmpExp = s_max(tmpExp, sub(shl(s_max(ExpLmax,ExpLmax2), 1), s_min(ExpLmax, ExpLmax2))); + FOR (i = 11; i<= st_fx->max_band_fx; i++) + { + ExpLmax = sub(30, norm_l(fr_bands[i])); + ExpLmax2 = sub(30, norm_l(hNoiseEst->fr_bands2_fx[i])); + tmpExp = s_max(tmpExp, sub(shl(s_max(ExpLmax,ExpLmax2), 1), s_min(ExpLmax, ExpLmax2))); + } + tmpExp = sub(tmpExp, 30-4-4); /* 4bits for internal summation and 4 bits for comparaison */ + + pt1 = fr_bands + 10; + pt2 = hNoiseEst->fr_bands2_fx + 10; + FOR (i=10; i<=st_fx->max_band_fx; i++) + { + Lnum = L_max(*pt1, *pt2); /* Don't need if anymore */ +#ifdef BASOP_NOGLOB + Lsum_den = L_add_o(Lsum_den, Lnum, &Overflow); +#else /* BASOP_NOGLOB */ + Lsum_den = L_add(Lsum_den, Lnum); +#endif /* BASOP_NOGLOB */ + Ltmpden = L_min(*pt1, *pt2); + if( Ltmpden == 0 ) + { + Ltmpden = L_add(Ltmpden,1); + } + ExpNum = sub(norm_l(Lnum), 1); + num = extract_h(L_shl(Lnum, ExpNum)); + num = mult_r(num, num); + ExpDen = norm_l(Ltmpden); + den = extract_h(L_shl(Ltmpden, ExpDen)); + num = div_s(num, den); + Ltmp = L_shr(num, add(sub(sub(shl(ExpNum, 1), ExpDen), 15+1), tmpExp)); + Lsum_num = L_add(Lsum_num, Ltmp); + + pt1++; + pt2++; + } + Lsum_den = L_shr(Lsum_den, tmpExp); + + + /* calculation of spectral diversity */ + /* THR_SPDIV_FX = 5 , 1/5 Q15 = 6554 */ + spec_div = 0; + move16(); + if (GT_32(Mult_32_16(Lsum_num, 6554), Lsum_den)) /* Qx+Q15+1-16 ==> Qx */ + { + spec_div = 1; + move16(); + } + + /* *sp_div = Lsum_num / (Lsum_den + 1e-5f); */ + ExpNum = sub(norm_l(Lsum_num), 1); + num = extract_h(L_shl(Lsum_num, ExpNum)); + + Lsum_den = L_add(Lsum_den,1); + + ExpDen = norm_l(Lsum_den); + den = extract_h(L_shl(Lsum_den, ExpDen)); + + *sp_div = div_s(num, den); + move16(); + + *Q_sp_div = add(15,sub(ExpNum ,ExpDen)); + move16(); + + /*-----------------------------------------------------------------* + * Detection of frames with high energy content in high frequencies + *-----------------------------------------------------------------*/ + + /* calculation of energy in first 10 critical bands */ + Ltmp = sum32_fx( &fr_bands[st_fx->min_band_fx], sub(10, st_fx->min_band_fx) ); + + /* calculation of energy in the rest of bands */ + Ltmp2 = sum32_fx( &fr_bands[10], sub(st_fx->max_band_fx,9) ); + +#ifdef BASOP_NOGLOB + wtmp = shl_o(1, sub(add(Q_new, QSCALE), 1), &Overflow); +#else /* BASOP_NOGLOB */ + wtmp = shl(1, sub(add(Q_new, QSCALE), 1)); +#endif /* BASOP_NOGLOB */ +#ifdef IVAS_CODE + IF (ncharX != NULL) + { + *ncharX = ftemp2 / (ftemp + 1e-5f); + } +#endif + test(); + IF (L_msu(Ltmp, 100, wtmp) < 0 || L_msu(Ltmp2, 100, wtmp) < 0) + { + noise_chartmp = 0; + move16(); + } + ELSE + { + /* ftemp2 /= ftemp */ + ExpNum = sub(norm_l(Ltmp2), 1); + num = extract_h(L_shl(Ltmp2, ExpNum)); + + ExpDen = norm_l(Ltmp); + den = extract_h(L_shl(Ltmp, ExpDen)); + num = div_s(num, den); +#ifdef BASOP_NOGLOB + noise_chartmp = extract_h(L_shr_o(num, add(sub(ExpNum, ExpDen), 4-16), &Overflow)); /* Q11 */ +#else /* BASOP_NOGLOB */ + noise_chartmp = extract_h(L_shr(num, add(sub(ExpNum, ExpDen), 4-16))); /* Q11 */ +#endif /* BASOP_NOGLOB */ + } + + noise_chartmp = s_min(noise_chartmp, (Word16)10<<11); /* Q11 */ + + /* update LT value of the final parameter */ + /* *st_noise_char = M_ALPHA * *st_noise_char + (1-M_ALPHA) * noise_chartmp */ + hNoiseEst->noise_char_fx = mac_r(L_mult(M_ALPHA_FX, hNoiseEst->noise_char_fx), ONE_MINUS_M_ALPHA, noise_chartmp); + + + nchar_thr = THR_NCHAR_WB_FX; + move16(); /* 1.0 Q11 */ + if( EQ_16(vad_bwidth_fx,NB)) + { + nchar_thr = THR_NCHAR_NB_FX; + move16(); /* 1.0 Q11 */ + } + + noise_char = 0; + move16(); + if (GT_16(hNoiseEst->noise_char_fx, nchar_thr)) + { + noise_char = 1; + move16(); + } + + /* save the 2 last spectra per crit. bands for the future */ + Copy32(hNoiseEst->fr_bands1_fx, hNoiseEst->fr_bands2_fx, NB_BANDS); + Copy32(fr_bands+NB_BANDS, hNoiseEst->fr_bands1_fx, NB_BANDS); + + /*-----------------------------------------------------------------* + * Non-stationarity estimation for each band + * Handicap high E frames in average computing + *-----------------------------------------------------------------*/ + + /* set averaging factor */ + /* ftemp = relE; */ + /* if( ftemp < 0.0f ) { ftemp = 0.0f; } */ + tmp = s_max(relE,0); /* Q8 */ + + /* alpha = 0.064f * ftemp + 0.75f; */ + Ltmp = Mult_32_16((Word32)137438953L, tmp); /* Q31(.064)+Q8+1-16 --> Q24 */ + Ltmp = L_mac(Ltmp,256,24576) ; /* Q8+Q15(.75)+1 --> Q24 */ +#ifdef BASOP_NOGLOB + alpha = round_fx_o(L_shl_o(Ltmp,7, &Overflow), &Overflow); /*Q24 +7 --> Q31 Q15*/ +#else /* BASOP_NOGLOB */ + alpha = round_fx(L_shl(Ltmp,7)); /*Q24 +7 --> Q31 Q15*/ +#endif /* BASOP_NOGLOB */ + + /*if( alpha > 0.999f { alpha = 0.999f;} */ + alpha = s_min(alpha, 32735 ); /*.999 in Q15*/ + alpham1 = negate(add(-32768, alpha)); /* 1.0 - alpha */ + /*--------------------------------------------------------------* + * during significant attacks, replace the LT energy by the + * current energy this will cause non_sta2 failures to occur in + * different frames than non_sta failures + *--------------------------------------------------------------*/ + + alpha2 = alpha; + move16(); + alpha2m1 = alpham1; + move16(); + IF (spec_div > 0) + { + alpha2 = 0; + move16(); + alpha2m1 = 32767; + move16(); + } + Lnon_sta2 = L_deposit_l(1<<10); + + non_sta = L_deposit_l(1<<10); + *non_staX = 0; + move16(); + non_staB = 0; + move16(); + + FOR( i = st_fx->min_band_fx; i <= st_fx->max_band_fx; i++ ) + { + /* + 1.0f added to reduce sensitivity to non stationarity in low energies */ + /* tmp_enr = enr[i] + 1.0f; */ + tmp_Q = add(Q_new, Q_SCALE); + Ltmp = L_shl((Word32)1L, tmp_Q); /* 1.0 added in the right dynamic domain */ +#ifdef BASOP_NOGLOB + L_tmp_enr = L_add_o(enr[i] , Ltmp , &Overflow); /* enr scale dynamic */ + L_tmp_ave_enr = L_add_o(hNoiseEst->ave_enr_fx[i], Ltmp, &Overflow); /* ave__enr scale dynamic */ +#else /* BASOP_NOGLOB */ + L_tmp_enr = L_add(enr[i] , Ltmp ); /* enr scale dynamic */ + L_tmp_ave_enr = L_add(hNoiseEst->ave_enr_fx[i], Ltmp); /* ave__enr scale dynamic */ +#endif /* BASOP_NOGLOB */ + + IF (LE_32(non_sta, th_sta)) /* Just to limit the saturation */ + { + /* if( enr[i] > st_ave_enr2[i] ) */ + /* non_sta2 = non_sta2 * ((enr[i]+1) / (st_ave_enr2[i]+1)) */ + Lnum = L_max(L_tmp_enr, L_tmp_ave_enr); + + /* else */ + /* non_sta2 = non_sta2 * ((st_ave_enr2[i]+1) / (enr[i]+1)) */ + Lden = L_min(L_tmp_enr, L_tmp_ave_enr); + + ExpNum = sub(norm_l(Lnum), 1); + num = extract_h(L_shl(Lnum, ExpNum)); + Lnum = L_shl(Lnum, ExpNum); + ExpDen = norm_l(Lden); + den = extract_h(L_shl(Lden, ExpDen)); + num = div_s(num, den); + Ltmp = Mult_32_16(non_sta, num); +#ifdef BASOP_NOGLOB + non_sta = L_shr_o(Ltmp, sub(ExpNum, ExpDen), &Overflow); /* Q10 */ +#else /* BASOP_NOGLOB */ + non_sta = L_shr(Ltmp, sub(ExpNum, ExpDen)); /* Q10 */ +#endif /* BASOP_NOGLOB */ + } + + /* st->ave_enr[i] = alpha * st->ave_enr[i] + (1-alpha) * enr[i];*/ /* update long-term average */ + Ltmp = Mult_32_16(hNoiseEst->ave_enr_fx[i], alpha); + Ltmp = L_add(Ltmp, Mult_32_16(enr[i], alpham1)); + hNoiseEst->ave_enr_fx[i] = L_max(Le_min_scaled, Ltmp); + move32(); + + /* calculation of another non-stationarity measure (following attacks) */ + /*if( non_sta2 <= th_sta ){ + tmp_ave2 = st->ave_enr2[i] + 1.0f; + if( tmp_enr > tmp_ave2 ){ + non_sta2 = non_sta2 * ( tmp_enr / tmp_ave2 ); + } else { + non_sta2 = non_sta2 * (tmp_ave2 / tmp_enr ); + } + } */ + + /* ave_enr2:: calculation of another non-stationarity measure (following attacks) */ + Ltmp = L_shl((Word32)1L, tmp_Q ); /* 1.0 added in the right dynamic domain */ + /*L_tmp_enr = L_add(enr[i] , Ltmp );*/ /* enr scale dynamic , done above */ +#ifdef BASOP_NOGLOB + L_tmp_ave_enr2 = L_add_o(hNoiseEst->ave_enr2_fx[i], Ltmp, &Overflow); /* ave__enr scale dynamic */ +#else + L_tmp_ave_enr2 = L_add(hNoiseEst->ave_enr2_fx[i], Ltmp); /* ave__enr scale dynamic */ +#endif + IF (LE_32(Lnon_sta2, th_sta )) /* Just to limit the saturation */ + { + Lnum = L_max(L_tmp_enr, L_tmp_ave_enr2 ); + Lden = L_min(L_tmp_enr, L_tmp_ave_enr2 ); + + ExpNum = sub(norm_l(Lnum), 1); + num = extract_h(L_shl(Lnum, ExpNum)); + Lnum = L_shl(Lnum, ExpNum); + ExpDen = norm_l(Lden); + den = extract_h(L_shl(Lden, ExpDen)); + num = div_s(num, den); + Ltmp1 = Mult_32_16(Lnon_sta2, num); +#ifdef BASOP_NOGLOB + Lnon_sta2 = L_shr_o(Ltmp1, sub(ExpNum, ExpDen), &Overflow); /* Q10 */ +#else /* BASOP_NOGLOB */ + Lnon_sta2 = L_shr(Ltmp1, sub(ExpNum, ExpDen)); /* Q10 */ +#endif /* BASOP_NOGLOB */ + } + + /* st_ave_enr2[i] = (float)alpha2 * st_ave_enr2[i] + + (1.0f - alpha2) * (enr[i]) */ + Ltmp1 = Mult_32_16(hNoiseEst->ave_enr2_fx[i], alpha2); + Ltmp1 = L_add(Ltmp1, Mult_32_16(enr[i], alpha2m1)); + hNoiseEst->ave_enr2_fx[i] = L_max(Le_min_scaled, Ltmp1); + move32(); + + /* calculation of non-stationarity measure for speech/music classification */ +#ifdef IVAS_CODE + IF(hFrontVad == NULL) +#endif + { + test();test(); + IF(GE_16(i, START_BAND_SPMUS) && LT_16(i, NB_BANDS_SPMUS + START_BAND_SPMUS) && st_fx->hSpMusClas != NULL) + { + /* log_enr = (float)ln_fx(enr[i]); */ + log_enr16 = noise_est_ln_q8_fx(enr[i], 0, tmp_Q); + wtmp = abs_s(sub(log_enr16, hSpMusClas->past_log_enr_fx[i - START_BAND_SPMUS])); +#ifdef BASOP_NOGLOB + *non_staX = add_o(*non_staX, wtmp, &Overflow); +#else /* BASOP_NOGLOB */ + *non_staX = add(*non_staX, wtmp); +#endif /* BASOP_NOGLOB */ + move16(); /* Q8 */ + hSpMusClas->past_log_enr_fx[i - START_BAND_SPMUS] = log_enr16; + move16(); + } + } + IF(GE_16(i, 2) && LE_16(i, 16)) + { + IF(GE_16(ini_frame , 100)) + { + /* calculate non-stationarity feature relative background */ + tmp_enr = noise_est_ln_q8_fx(enr[i], 1, tmp_Q); /* 1.0f added */ + tmp_floor = LN_E_MIN_PLUS_ONE_FX; + move16(); /* non dynamic init constant in Q8 */ + tmp_floor = noise_est_ln_q8_fx(hNoiseEst->bckr_fx[i], 1, tmp_Q); +#ifdef BASOP_NOGLOB + non_staB = add_o(non_staB, abs_s(sub(tmp_enr, tmp_floor)), &Overflow); /* Q8 */ +#else /* BASOP_NOGLOB */ + non_staB = add(non_staB, abs_s(sub(tmp_enr, tmp_floor))); /* Q8 */ +#endif /* BASOP_NOGLOB */ + } + ELSE /*ini_frame < 100*/ + { + /* calculate non-stationarity feature relative background */ + tmp_enr = noise_est_ln_q8_fx(enr[i], 1, tmp_Q); /* 1.0f added */ + tmp_floor = LN_E_MIN_PLUS_ONE_FX; + move16(); /* non dynamic init constant in Q8 */ + tmp_floor = noise_est_ln_q8_fx(E_MIN_FX, 1, tmp_Q); +#ifdef BASOP_NOGLOB + non_staB = add_o(non_staB, abs_s(sub(tmp_enr, tmp_floor)), &Overflow); /* Q8 */ +#else /* BASOP_NOGLOB */ + non_staB = add(non_staB, abs_s(sub(tmp_enr, tmp_floor))); /* Q8 */ +#endif /* BASOP_NOGLOB */ + } + } + + } /* end of band loop FOR( i = st_fx->min_band_fx; i <= st_fx->max_band_fx; i++ ) */ + + IF (LT_16(Etot,-1280)) + { + non_sta = L_deposit_l(1024); /* 1.0 in Q10 */ + Lnon_sta2 = L_deposit_l(1024); /* 1.0 in Q10 */ + } + + lim_Etot_fx = s_max(5120,Etot); /* 20.0f Q8 */ + lim_Etot_sq_fx = extract_h(L_shl_r(L_mult(lim_Etot_fx,lim_Etot_fx),1)); /* Q2 */ + + if ( st_fx->ini_frame_fx < 150 ) + { + /* Allow use of quicker filter during init - if needed */ + /* st->Etot_st_est = 0.25f * lim_Etot + (1.0f-0.25F) * st->Etot_st_est; */ + hNoiseEst->Etot_st_est_fx = mac_r(L_mult(8192, lim_Etot_fx), 24576, hNoiseEst->Etot_st_est_fx); + move16(); + /* st->Etot_sq_st_est = 0.25f * lim_Etot * lim_Etot + (1.0f-0.25f) * st->Etot_sq_st_est; */ + hNoiseEst->Etot_sq_st_est_fx = mac_r(L_mult(8192, lim_Etot_sq_fx), 24576, hNoiseEst->Etot_sq_st_est_fx); + move16(); + } + else + { + /* st->Etot_st_est = 0.25f * lim_Etot + (1.0f-0.25F) * st->Etot_st_est; */ + hNoiseEst->Etot_st_est_fx = mac_r(L_mult(8192, lim_Etot_fx), 24576, hNoiseEst->Etot_st_est_fx); + move16(); + /* st->Etot_sq_st_est = 0.25f * lim_Etot * lim_Etot + (1.0f-0.25f) * st->Etot_sq_st_est; */ + hNoiseEst->Etot_sq_st_est_fx = mac_r(L_mult(8192, lim_Etot_sq_fx), 24576, hNoiseEst->Etot_sq_st_est_fx); + move16(); + } + + st_E_var_est_fx = sub(hNoiseEst->Etot_sq_st_est_fx,extract_h(L_shl_r(L_mult(hNoiseEst->Etot_st_est_fx,hNoiseEst->Etot_st_est_fx),1))); + + + + /*-----------------------------------------------------------------* + * Count frames since last correlation or harmonic event + *-----------------------------------------------------------------*/ + + Ltmp = L_mult(st_fx->voicing_fx[0], 16384); + Ltmp = L_mac(Ltmp, st_fx->voicing_fx[1], 16384); + + test(); + test(); + *st_harm_cor_cnt = add(*st_harm_cor_cnt , 1); + if( (Etot > 0) && ( (*loc_harm > 0 ) || (GT_16(round_fx(Ltmp), COR_MAX_NNE_FX )))) + { + *st_harm_cor_cnt = 0; + move16(); + } + + IF( (GT_16(*st_harm_cor_cnt,1))&&((LT_16(Etot,3840))||/* 15 in Q8 */ + ( GT_16(st_fx->ini_frame_fx,10) && + GT_16(sub(Etot, hNoiseEst->Etot_lp_fx),1792) )) /* 7 in Q8 */ + ) + { + *st_harm_cor_cnt = 1; + } + + if ( GT_16(*st_harm_cor_cnt,1)&& + GT_16(Etot,7680) && /* 30.0f in Q8 */ + GT_16(st_E_var_est_fx,32 ) /* 8.0f in Q2 */ + ) + { + + /* st->harm_cor_cnt = max(1, (short) round_f( (float) st->harm_cor_cnt / 4.0f )) ; */ + *st_harm_cor_cnt = s_max(1, shr(add(*st_harm_cor_cnt,2),1)); + } + + + /*-----------------------------------------------------------------* + * Energy based pause length counter + *-----------------------------------------------------------------*/ + test(); + IF( (*bg_cnt >= 0) && (GT_16(sub(Etot , Etot_l_lp),1280)/*5.0 in Q8*/)) + { + /* Possible speech burst */ + *bg_cnt = -1; + move16(); + } + ELSE + { + test(); + if( EQ_16(*bg_cnt,-1)&&(LT_16(sub(Etot,Etot_l_lp),1280))/*5 in Q8*/) + { + /* Possible start of speech pause */ + *bg_cnt = 0; + move16(); + } + } + if (*bg_cnt >= 0) + { + *bg_cnt = add(*bg_cnt,1); + move16(); + } + + /*-----------------------------------------------------------------* + * Linear predition efficiency 0 to 2 order + *-----------------------------------------------------------------*/ + + /*epsP_0_2 = max(0 , min(8, epsP[0] / epsP[2])); */ + Ltmp = eps_quota_fx(epsP_h[0], epsP_l[0], + epsP_h[2], epsP_l[2] , 12 ); /* Word32 Q12 */ + BASOP_SATURATE_WARNING_OFF_EVS /* may saturate*/ +#ifdef BASOP_NOGLOB + epsP_0_2 = round_fx_o(L_shl_o(Ltmp,16, &Overflow), &Overflow); /* Q12+16 -16 -> Q12 , NB saturation in Q12 sets max value to 7,999 */ +#else /* BASOP_NOGLOB */ + epsP_0_2 = round_fx(L_shl(Ltmp,16)); /* Q12+16 -16 -> Q12 , NB saturation in Q12 sets max value to 7,999 */ +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + + epsP_0_2 = s_max(0, epsP_0_2); /* min value is 0 , Q12 */ + + + /* st->epsP_0_2_lp = 0.15f * epsP_0_2 + (1.0f-0.15f) * st->epsP_0_2_lp; */ + alpha = 4915; + move16(); /*0.15 in Q15 */ + hNoiseEst->epsP_0_2_lp_fx = noise_est_AR1_Qx(epsP_0_2, hNoiseEst->epsP_0_2_lp_fx ,alpha); + + /* epsP_0_2_ad = (float) fabs(epsP_0_2 - st->epsP_0_2_lp ); */ + epsP_0_2_ad = abs_s(sub(epsP_0_2, hNoiseEst->epsP_0_2_lp_fx)); /* Q12 */ + + /*if (epsP_0_2_ad < st->epsP_0_2_ad_lp) { + st->epsP_0_2_ad_lp = 0.1f * epsP_0_2_ad + (1.0f - 0.1f) * st->epsP_0_2_ad_lp; + } else { + st->epsP_0_2_ad_lp = 0.2f * epsP_0_2_ad + (1.0f - 0.2f) * st->epsP_0_2_ad_lp; + } */ + alpha = 6554; + move16();/* 0.2 Q15 */ + if (LT_16(epsP_0_2_ad, hNoiseEst->epsP_0_2_ad_lp_fx)) + { + alpha = shr(alpha,1); /* 0.1 Q15 */ + } + hNoiseEst->epsP_0_2_ad_lp_fx = noise_est_AR1_Qx(epsP_0_2_ad, hNoiseEst->epsP_0_2_ad_lp_fx ,alpha); + + /* epsP_0_2_ad_lp_max = max(epsP_0_2_ad,st->epsP_0_2_ad_lp);*/ + epsP_0_2_ad_lp_max = s_max(epsP_0_2_ad, hNoiseEst->epsP_0_2_ad_lp_fx); /* Q12 */ + + + /*-----------------------------------------------------------------* + * Linear predition efficiency 2 to 16 order + *-----------------------------------------------------------------*/ + + /* epsP_2_16 = max(0 , min(8, epsP[2] / epsP[16])); */ + Ltmp = eps_quota_fx(epsP_h[2], epsP_l[2], + epsP_h[16], epsP_l[16] , 12 ); /* Word32 Q12 */ + BASOP_SATURATE_WARNING_OFF_EVS /* may saturate*/ +#ifdef BASOP_NOGLOB + epsP_2_16 = round_fx_o(L_shl_o(Ltmp,16, &Overflow), &Overflow); /* Q12+16 -16 -> Q12 , + NB saturation in Q12 sets max value to 7,999 */ +#else /* BASOP_NOGLOB */ + epsP_2_16 = round_fx(L_shl(Ltmp,16)); /* Q12+16 -16 -> Q12 , + NB saturation in Q12 sets max value to 7,999 */ +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + + epsP_2_16 = s_max(0, epsP_2_16); /* min value is 0 , Q12 */ + + + /* if (epsP_2_16 > st->epsP_2_16_lp){ + st->epsP_2_16_lp = 0.2f * epsP_2_16 + (1.0f-0.2f) * st->epsP_2_16_lp; + } else { + st->epsP_2_16_lp = 0.03f * epsP_2_16 + (1.0f-0.03f) * st->epsP_2_16_lp; + } + + st->epsP_2_16_lp2 = 0.02f * epsP_2_16 + (1.0f-0.02f) * st->epsP_2_16_lp2; */ + + alpha = 983 ; + move16();/* 0.03 Q15 */ + if (GT_16(epsP_2_16 , hNoiseEst->epsP_2_16_lp_fx)) + { + alpha = 6554; + move16();/* 0.2 Q15 */ + } + hNoiseEst->epsP_2_16_lp_fx = noise_est_AR1_Qx(epsP_2_16, hNoiseEst->epsP_2_16_lp_fx , alpha); + + hNoiseEst->epsP_2_16_lp2_fx = noise_est_AR1_Qx(epsP_2_16, hNoiseEst->epsP_2_16_lp2_fx , 655); /* 0.02 */ + + epsP_2_16_dlp = sub(hNoiseEst->epsP_2_16_lp_fx, hNoiseEst->epsP_2_16_lp2_fx); + + + /* if (epsP_2_16_dlp < st->epsP_2_16_dlp_lp2 ) { + st->epsP_2_16_dlp_lp2 = 0.02f * epsP_2_16_dlp + (1.0f-0.02f) * st->epsP_2_16_dlp_lp2; + } else { + st->epsP_2_16_dlp_lp2 = 0.05f * epsP_2_16_dlp + (1.0f-0.05f) * st->epsP_2_16_dlp_lp2; + }*/ + alpha = 1638; + move16();/* 0.05 Q15 */ + if (LT_16(epsP_2_16_dlp , hNoiseEst->epsP_2_16_dlp_lp2_fx)) + { + alpha = 655; + move16();/* 0.02 Q15 */ + } + hNoiseEst->epsP_2_16_dlp_lp2_fx = noise_est_AR1_Qx(epsP_2_16_dlp, hNoiseEst->epsP_2_16_dlp_lp2_fx , alpha); + + /* epsP_2_16_dlp_max = max(epsP_2_16_dlp,st->epsP_2_16_dlp_lp2); */ + epsP_2_16_dlp_max = s_max(epsP_2_16_dlp, hNoiseEst->epsP_2_16_dlp_lp2_fx); + + /*-----------------------------------------------------------------* + * long term extensions of frame features + *-----------------------------------------------------------------*/ + + tmp = sub(Etot, hNoiseEst->totalNoise_fx ); /* Q8 */ + /* st->lt_tn_track = 0.03f* (Etot - st->totalNoise < 10) + 0.97f*st->lt_tn_track; */ + tmp2 = 0; + move16(); + if( LT_16(tmp, 2560 )) /*10 in Q8 */ + { + tmp2=32767; + move16(); + } + hNoiseEst->lt_tn_track_fx = noise_est_AR1_Qx(tmp2, hNoiseEst->lt_tn_track_fx , 983); /*0.03 in Q15 ,Q15 state*/ + + /* st->lt_tn_dist = 0.03f* (Etot - st->totalNoise) + 0.97f*st->lt_tn_dist; */ + hNoiseEst->lt_tn_dist_fx = noise_est_AR1_Qx(tmp, hNoiseEst->lt_tn_dist_fx , 983); /*0.03 in Q15 ,Q8 state*/ + + /* st->lt_Ellp_dist = 0.03f* (Etot - st->Etot_l_lp) + 0.97f*st->lt_Ellp_dist;*/ + tmp = sub(Etot, hNoiseEst->Etot_l_lp_fx); /* Q8 */ + hNoiseEst->lt_Ellp_dist_fx = noise_est_AR1_Qx(tmp, hNoiseEst->lt_Ellp_dist_fx, 983); /*0.03 in Q15 ,Q8 state*/ + + + + /* if (st->harm_cor_cnt == 0) { + st->lt_haco_ev = 0.03f*1.0 + 0.97f*st->lt_haco_ev; + } else { + st->lt_haco_ev = 0.99f*st->lt_haco_ev; + } */ + IF ( *st_harm_cor_cnt == 0) + { + hNoiseEst->lt_haco_ev_fx = noise_est_AR1_Qx((Word16)32767, hNoiseEst->lt_haco_ev_fx, 983); /*.03 in Q15 , Q15 state */ + } + ELSE + { + hNoiseEst->lt_haco_ev_fx = mult_r(32440, hNoiseEst->lt_haco_ev_fx); /*.99 in Q15 , Q15 state */ + } + + + /* if (st->lt_tn_track < 0.05f) { + st->low_tn_track_cnt++; + } else { + st->low_tn_track_cnt=0; + }*/ + tmp = 0; + move16(); + move16(); + if( LT_16(hNoiseEst->lt_tn_track_fx , 1638 )) /* 0.05 in Q15*/ + { + tmp = add(hNoiseEst->low_tn_track_cnt, 1); + } + hNoiseEst->low_tn_track_cnt = tmp; + move16(); + + + /* update of the long-term non-stationarity measure (between 0 and 1) */ + /* if ( (non_sta > th_sta) || (*loc_harm > 0) ) { + st->act_pred = M_GAMMA * st->act_pred + (1-M_GAMMA) * 1; + } else { + st->act_pred = M_GAMMA * st->act_pred + (1-M_GAMMA) * 0; + }*/ + Ltmp = L_mult(M_GAMMA_FX, hNoiseEst->act_pred_fx); /*Q15*Q15+1 --> Q31 , 32440= .99 Q15 */ + tmp = round_fx(Ltmp); /* Q15 */ + test(); + if ( ( GT_32(non_sta, th_sta)) /* float th_sta NB 5e10 , WB 3.5e10*/ + || (*loc_harm > 0) + ) + { + tmp = mac_r(Ltmp, (-32768+M_GAMMA_FX), -32768); /* (-0.01)*(-1.0) */ + } + hNoiseEst->act_pred_fx = tmp ; + move16(); + + + + /*-----------------------------------------------------------------* + * Background noise adaptation enable flag + *-----------------------------------------------------------------*/ + Ltmp = L_mult(st_fx->voicing_fx[0], 16384); + Ltmp = L_mac(Ltmp, st_fx->voicing_fx[1], 16384); +#ifdef BASOP_NOGLOB + cor_tmp = mac_ro(Ltmp, corr_shift,MAX_16, &Overflow); +#else /* BASOP_NOGLOB */ + cor_tmp = mac_r(Ltmp, corr_shift,MAX_16); +#endif + + LepsP = eps_quota_fx(epsP_h[2] , epsP_l[2], + epsP_h[16], epsP_l[16] , 11 ); /* L_epsP in Q11 */ + /* note this epsP2/eps16 is not limited to 8 as, epsP_2_16 is !! */ + + vad_2nd_stage_fx = 0; + move16(); /* background noise present - decrement counter */ + /* + if( ( (*st_harm_cor_cnt < 3*HC_CNT_SLOW ) + && ( ( non_sta > th_sta ) || + ( tmp_pc < TH_PC ) || + ( noise_char > 0) ) + ) + || + ( (st->ini_frame > 150) && (Etot - Etot_l_lp) > 10 ) || + ( 0.5f * (voicing[0]+voicing[1]) > cor_max ) || + ( epsP[2] / epsP[16] > th_eps ) || + ( *loc_harm > 0) || + ((st->act_pred > 0.8f) && (non_sta2 > th_sta)) + ) */ + + Ltmp = L_mult(st_fx->voicing_fx[0], 16384); /* Q15 + Q15(.5)) + 1 -> Q31 */ + cor_tmp = mac_r(Ltmp, st_fx->voicing_fx[1], 16384 ); /* Q31 -16 -> Q15 */ + if ( Etot < 0 ) + { + cor_tmp = 0; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + + if( ( ( LT_16(*st_harm_cor_cnt, (3*HC_CNT_SLOW_FX) )) + && ( ( GT_32(non_sta, th_sta) ) || (LT_16(tmp_pc, TH_PC_FX) ) || ( GT_16(noise_char ,0)) ) ) + || + ( (GT_16(st_fx->ini_frame_fx, HE_LT_CNT_INIT_FX ) ) && ( GT_16(sub(Etot, Etot_l_lp), 2560) ) ) || + ( GT_16(cor_tmp, cor_max) ) || /* Q15 */ + ( GT_32(LepsP, th_eps) ) || /* Q11 */ + ( GT_16(*loc_harm,0)) || + ((GT_16(hNoiseEst->act_pred_fx, 26214) ) && (GT_32(Lnon_sta2, th_sta) ) ) /*act_pred in Q15 , th_sta in Q10 */ + ) + { + vad_2nd_stage_fx = 1; + move16(); /* active signal present - increment counter */ + } + + tmp = 2; + move16(); /* Signal present */ + if(vad_2nd_stage_fx == 0 ) + { + tmp = -1; + move16(); /* Background present */ + } + hNoiseEst->aEn = add(hNoiseEst->aEn, tmp); + + + hNoiseEst->aEn = s_min(hNoiseEst->aEn,6); + hNoiseEst->aEn = s_max(hNoiseEst->aEn,0); +#ifdef IVAS_CODE + /*-----------------------------------------------------------------* + * Stereo classifier - save raw aEn + *-----------------------------------------------------------------*/ + + if (hStereoClassif != NULL) + { + if ((non_sta > th_sta) || + (tmp_pc < TH_PC) || + (0.5f * (st->voicing[0] + st->voicing[1]) > cor_max) || + (epsP[2] / epsP[16] > th_eps) || + ((hNoiseEst->act_pred > 0.8f) && (non_sta2 > th_sta))) + { + /* active signal present - increment counter */ + hStereoClassif->aEn_raw[st->idchan] = hStereoClassif->aEn_raw[st->idchan] + 2; + } + else + { + /* background noise present - decrement counter */ + hStereoClassif->aEn_raw[st->idchan] = hStereoClassif->aEn_raw[st->idchan] - 1; + } + + if (hStereoClassif->aEn_raw[st->idchan] > 6) + { + hStereoClassif->aEn_raw[st->idchan] = 6; + } + else if (hStereoClassif->aEn_raw[st->idchan] < 0) + { + hStereoClassif->aEn_raw[st->idchan] = 0; + } + } +#endif + + + /* Additional NNE detectors */ + + /* comb_ahc_epsP = max(max(st->act_pred, st->lt_haco_ev), epsP_2_16_dlp); */ + /* Q15 Q15 Q12 */ + comb_ahc_epsP = s_max(s_max(shr(hNoiseEst->act_pred_fx,15-12), shr(hNoiseEst->lt_haco_ev_fx, 15-12)), epsP_2_16_dlp); /* Q12 */ + + + /* comb_hcm_epsP = max(max(st->lt_haco_ev,epsP_2_16_dlp_max),epsP_0_2_ad_lp_max); */ + /* Q15 Q12 Q12 */ + comb_hcm_epsP = s_max(s_max(shr(hNoiseEst->lt_haco_ev_fx,15-12), epsP_2_16_dlp_max), epsP_0_2_ad_lp_max); /* Q12 */ + + /*haco_ev_max = max(*st_harm_cor_cnt==0,st->lt_haco_ev); */ + tmp = 0; + move16(); + if ( *st_harm_cor_cnt == 0 ) + { + tmp = (Word16)32767; + move16(); + } + haco_ev_max = s_max(tmp, hNoiseEst->lt_haco_ev_fx); /* Q15 */ + + /* Etot_l_lp_thr = st->Etot_l_lp + (1.5f + 1.5f * (st->Etot_lp<50.0f))*st->Etot_v_h2; */ + tmp = 12288; + move16();/* 1.5 Q13 */ + if( LT_16(hNoiseEst->Etot_lp_fx, 12800 )) /* 50.0 in Q8 */ + { + tmp =shl(tmp,1); /*1.5 + 1.5 Q13 */ + } + Ltmp = L_deposit_h(hNoiseEst->Etot_l_lp_fx); + Etot_l_lp_thr = round_fx(L_add(Ltmp, L_shl(L_mult(tmp, Etot_v_h2),2))); /* Q13+Q8+1 +2 = Q24 -> Q8*/ + + /* enr_bgd = Etot < Etot_l_lp_thr; */ + enr_bgd = 0; + move16(); + if(LT_16(Etot, Etot_l_lp_thr )) /* Q8 */ + { + enr_bgd = 1; + move16();/* Q0 */ + } + + /* cns_bgd = (epsP_0_2 > 7.95f) && (non_sta< 1e3f); */ + cns_bgd = 0 ; + move16(); + test(); + if( (GT_16(epsP_0_2, 32563)) /* 7.95 in Q12 */ + && (LT_32(non_sta, 1024000L) ) ) /* 1e3f in Q10 ? */ + { + cns_bgd = 1; + move16(); /* Q0 */ + } + + /*lp_bgd = epsP_2_16_dlp_max < 0.10f; */ + lp_bgd = 0; + move16(); + if( LT_16(epsP_2_16_dlp_max, 410)) /*0.10 Q12 */ + { + lp_bgd = 1; + move16(); /* Q0 */ + } + + + /* ns_mask = non_sta < 1e5f; */ + ns_mask = 0; + move16(); + if( LT_32(non_sta, (Word32)102400000L )) /* (1e5f in Q10)*/ + { + ns_mask = 1; + move16(); /* Q0 */ + } + + + /* lt_haco_mask = st->lt_haco_ev < 0.5f; */ + lt_haco_mask = 0; + move16(); + if( LT_16(hNoiseEst->lt_haco_ev_fx, 16384 )) /* ( .5 in Q15)*/ + { + lt_haco_mask = 1; + move16(); /* Q0 */ + } + + /* bg_haco_mask = haco_ev_max < 0.4f; */ + bg_haco_mask = 0; + move16(); + if( LT_16(haco_ev_max, 13107)) /* ( 0.4 in Q15)*/ + { + bg_haco_mask = 1; + move16(); /* Q0 */ + } + + + /* SD_1 = ( (epsP_0_2_ad > 0.5f) && (epsP_0_2 > 7.95f) ); */ + SD_1 = 0; + move16(); + test(); + if( (GT_16(epsP_0_2_ad,2048)) /* 0.5 in Q12 */ + && (GT_16(epsP_0_2, 32563) )) /* 7.95 in Q12 */ + { + SD_1 = 1; + move16(); /* Q0 */ + } + SD_1_inv = sub(1, SD_1); /* Q0 */ + + /* NB "STL::test()"; has a cost of 2, using bitwise "s_and" , "s_or" at a cost of 1 */ + /* NB only lowest bit position is used, result is always 0 or 1 */ + + /* bg_bgd3 = enr_bgd || ( ( cns_bgd || lp_bgd ) && ns_mask && lt_haco_mask && SD_1==0 ); */ + tmp = s_and(s_and(s_and(s_or(cns_bgd, lp_bgd), ns_mask), lt_haco_mask ), SD_1_inv); + bg_bgd3 = s_or(enr_bgd, tmp); + + /*PD_1 = (epsP_2_16_dlp_max < 0.10f ) ; */ + PD_1 = 0; + move16(); + if( (LT_16( epsP_2_16_dlp_max, 410))) /* 0.10 in Q12 */ + { + PD_1 = 1; + move16(); /* Q0 */ + } + + /*PD_2 = (epsP_0_2_ad_lp_max < 0.10f ) ; */ + PD_2 = 0; + move16(); + if( (LT_16( epsP_0_2_ad_lp_max, 410))) /* 0.10 in Q12 */ + { + PD_2 = 1; + move16(); /* Q0 */ + } + + /*PD_3 = (comb_ahc_epsP < 0.85f ); */ + PD_3 = 0; + move16(); + if( (LT_16(comb_ahc_epsP, 3482 ))) /* 0.85 in Q12 */ + { + PD_3 = 1; + move16(); /* Q0 */ + } + + /* PD_4 = comb_ahc_epsP < 0.15f; */ + PD_4 = 0; + move16(); + if( (LT_16(comb_ahc_epsP, 614))) /* 0.15 in Q12 */ + { + PD_4 = 1; + move16(); /* Q0 */ + } + + /*PD_5 = comb_hcm_epsP < 0.30f; */ + PD_5 = 0; + move16(); + if( (LT_16(comb_hcm_epsP, 1229))) /* 0.30 in Q12 */ + { + PD_5 = 1; + move16(); /* Q0 */ + } + + /* BG_1 = ( (SD_1==0) || (Etot < Etot_l_lp_thr) ) + && bg_haco_mask && (st->act_pred < 0.85f) && (st->Etot_lp < 50.0f); */ + BG_1 = 0; + move16(); + test(); + test(); + test(); + test(); + if( ( (SD_1 == 0) || (LT_16(Etot, Etot_l_lp_thr))) + && (bg_haco_mask != 0) && ( LT_16(hNoiseEst->act_pred_fx, 27853 ) ) /* 0.85f in Q15 */ + && (LT_16(hNoiseEst->Etot_lp_fx, 50*256) )) /* 50.0 in Q8 */ + { + BG_1 = 1; + move16(); + } + + /* PAU = (st->aEn==0) + || ( (Etot < 55.0f) && (SD_1==0) + && ( ( PD_3 && (PD_1 || PD_2 ) ) || ( PD_4 || PD_5 ) ) ); */ + PAU=0; + move16();/*Q0*/ + if(hNoiseEst->aEn == 0) + { + PAU = 1; + move16();/*Q0*/ + } + tmp = 0; + move16();/*Q0*/ + if( LT_16(Etot, 55*256)) /*55.0 in Q8 */ + { + tmp = 1; + move16();/*Q0*/ + } + tmp = s_and(tmp, SD_1_inv); + PAU = s_or(PAU, s_and(tmp, s_or(s_and(PD_3, s_or(PD_1, PD_2 )) , s_or( PD_4, PD_5 )))) ; + + + /* NEW_POS_BG = (PAU | BG_1) & bg_bgd3; note bitwise logic in float */ + NEW_POS_BG = s_and(s_or(PAU, BG_1),bg_bgd3); + + /* Original silence detector works in most cases */ + /* aE_bgd = (st->aEn == 0);*/ + aE_bgd = 0; + move16(); + if(hNoiseEst->aEn == 0) + { + aE_bgd = 1; + move16(); + } + + + + /* When the signal dynamics is high and the energy is close to the background estimate */ + /* sd1_bgd = (st->sign_dyn_lp > 15) + && (Etot - st->Etot_l_lp ) < 2*st->Etot_v_h2 + && st->harm_cor_cnt > 20; */ + sd1_bgd = 0; + move16(); + test(); + test(); + if ( ( GT_16(hNoiseEst->sign_dyn_lp_fx, 15*256)) /* 15 in Q8 */ + && ( LT_16(sub(Etot, hNoiseEst->Etot_l_lp_fx ), shl(Etot_v_h2, 1) ) ) /* Q8 , Etot_v_h2 has limited dynmics can be upscaled*/ + && (GT_16(*st_harm_cor_cnt, 20) ) ) + { + sd1_bgd = 1; + move16(); + } + + /* tn_ini = st->ini_frame < 150 && st->harm_cor_cnt > 5 && + ( (st->act_pred < 0.59f && st->lt_haco_ev <0.23f ) || + st->act_pred < 0.38f || + st->lt_haco_ev < 0.15f || + non_staB < 50.0f || + aE_bgd );*/ + + tmp = 0; + move16(); + test(); + test(); + test(); + test(); + test(); + if ( ( (LT_16(hNoiseEst->act_pred_fx, 19333))&&(LT_16(hNoiseEst->lt_haco_ev_fx,7537))) /* .59 in Q15 .23 in Q15 */ + || (LT_16(hNoiseEst->act_pred_fx, 12452) ) /* .38 in Q15 */ + || ((EQ_16(st_fx->element_mode, EVS_MONO) && LT_16(hNoiseEst->lt_haco_ev_fx, 4915)) || (GT_16(st_fx->element_mode, EVS_MONO) && LT_16(hNoiseEst->lt_haco_ev_fx, 2621)) ) /* .15 in Q15 || 0.08 */ + || (LT_16(non_staB, 50*256 ) ) /* 50.0 in Q8 */ + || aE_bgd != 0 + || ( (LT_16(Etot,10752)) /* 42 in Q8 */ + && (GT_16(hNoiseEst->harm_cor_cnt, 10) ) + && ( LT_16(hNoiseEst->lt_haco_ev_fx, 11469) ) /* 0.35 in Q15 */ + && ( LT_16(hNoiseEst->act_pred_fx, 26214) ) /* 0.80 in Q15 */ + ) + ) + { + tmp = 1; + move16(); + } + + tn_ini = 0; + move16(); + test(); + test(); + if ( ( LT_16(st_fx->ini_frame_fx, HE_LT_CNT_INIT_FX )) + && ( GT_16(hNoiseEst->harm_cor_cnt,5)) /* > 5 Q0 */ + && ( LT_16(sub(Etot, hNoiseEst->Etot_lp_fx),1792 )) /* 7 in Q8 */ + && ( NE_16(tmp, 0)) ) + { + tn_ini = 1; + move16(); + } + + /* Energy close to the background estimate serves as a mask for other background detectors */ + /* bg_bgd2 = Etot < Etot_l_lp_thr || tn_ini ; */ + bg_bgd2 = 0; + move16(); + test(); + if ( ( LT_16(Etot, Etot_l_lp_thr)) + || (tn_ini != 0 ) ) + { + bg_bgd2 = 1; + move16(); /* Q0 */ + } + + updt_step = 0; + move16(); /* Q15 */ + /*if (( bg_bgd2 && ( aE_bgd || sd1_bgd || st->lt_tn_track >0.90f || NEW_POS_BG ) ) + || tn_ini ) */ + tmp = 0; + move16(); + if( GT_16(hNoiseEst->lt_tn_track_fx, 29491 )) /* .90 in Q15 */ + { + tmp = 1; + move16(); + } + + IF ( s_or(s_and(bg_bgd2 , s_or(aE_bgd, s_or(sd1_bgd, s_or(tmp, NEW_POS_BG)))), tn_ini) ) + { + /*if( ( ( st->act_pred < 0.85f ) + && (aE_bgd !=0) + && ( st->lt_Ellp_dist < 10 || sd1_bgd ) + && (st->lt_tn_dist<40) + && ( ( Etot - st->totalNoise ) < 10.0f ) + ) + || ( (st->first_noise_updt == 0) && (st->harm_cor_cnt > 80) && (aE_bgd!=0) && (st->lt_aEn_zero > 0.5f) ) + || ( (tn_ini!=0) && ( aE_bgd != 0) || (non_staB < 10.0) || (st->harm_cor_cnt > 80) ) + )*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); /* for the ELSE IF below*/ + test(); + test(); + test(); + test(); + test(); + test(); /* for the ELSE IF below*/ + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( LT_16(hNoiseEst->act_pred_fx, 27853)) /* 0.85 in Q15 */ + && ( NE_16(aE_bgd ,0) ) + && ( (LT_16(hNoiseEst->lt_Ellp_dist_fx, 10*256) ) || ( NE_16(sd1_bgd, 0) ) ) /* 10.0 in Q8*/ + && ( LT_16(hNoiseEst->lt_tn_dist_fx, 40*256 ) ) /* 40.0 in Q8*/ + && ( LT_16(sub(Etot, hNoiseEst->totalNoise_fx), 10*256) ) /* 10.0 in Q8*/ + ) + || ( (hNoiseEst->first_noise_updt == 0) && (GT_16(hNoiseEst->harm_cor_cnt,80) ) + && ( aE_bgd != 0 ) && (GT_16(hNoiseEst->lt_aEn_zero_fx, 16384) ) /*.5 in Q15*/ + ) + || ( (tn_ini != 0 ) && ( ( aE_bgd != 0 ) || ( LT_16(non_staB, 10*256) ) || (GT_16(hNoiseEst->harm_cor_cnt, 80) ) ) /* 10.0 in Q8*/ + ) + ) + + { + updt_step = 32767; + move16(); + hNoiseEst->first_noise_updt = 1; + FOR( i=0; i< NB_BANDS; i++ ) + { + hNoiseEst->bckr_fx[i] = tmpN[i]; + move32(); + } + } + /* else if ( ( ( st->act_pred < 0.80f ) && ( aE_bgd || PAU ) && st->lt_haco_ev < 0.10f ) + || ( ( st->act_pred < 0.70f ) && ( aE_bgd || non_staB < 17.0f ) && PAU && st->lt_haco_ev < 0.15f ) + || ( st->harm_cor_cnt > 80 && st->totalNoise > 5.0f && Etot < max(1.0f,Etot_l_lp + 1.5f* st->Etot_v_h2) ) + || + ( st->harm_cor_cnt > 50 && st->first_noise_updt > 30 && aE_bgd && st->lt_aEn_zero>0.5f ) + || tn_ini + ) */ + ELSE IF ( ( ( LT_16(hNoiseEst->act_pred_fx, 26214)) /* .8 in Q15*/ + && ( ( aE_bgd != 0 ) || ( PAU != 0 ) ) + && (LT_16(hNoiseEst->lt_haco_ev_fx, 3277) ) ) /* .10 in q15*/ + || ( ( LT_16(hNoiseEst->act_pred_fx, 22938 ) ) /* 0.70 in Q15 */ + && ( (aE_bgd!=0 ) || ( LT_16(non_staB, 17*256 ) ) )/* 17.0 in Q8 */ + && ( PAU != 0 ) + && ( LT_16(hNoiseEst->lt_haco_ev_fx,4915) ) /* 0.15 in Q15 */ + ) + || ( (GT_16(hNoiseEst->harm_cor_cnt, 80) ) && (GT_16(hNoiseEst->totalNoise_fx, 5*256) ) /* 5.0 in Q8 */ + && ( LT_16(Etot, s_max((Word16)1*256, add(Etot_l_lp, add(hNoiseEst->Etot_v_h2_fx,shr(hNoiseEst->Etot_v_h2_fx,1))))) ) /* 1.5= 1.0+.5 */ + ) + || ( (GT_16(hNoiseEst->harm_cor_cnt,50) ) && (GT_16(hNoiseEst->first_noise_updt, 30) ) + && (aE_bgd != 0) && (GT_16(hNoiseEst->lt_aEn_zero_fx, 16384) ) ) /*.5 in Q15*/ + || ( tn_ini != 0 ) + ) + + { + updt_step = 3277; + move16(); /* 0.1 in Q15 */ + /* if ( !aE_bgd && st->harm_cor_cnt < 50 + && ( (st->act_pred > 0.6f) + || ( (tn_ini==0) && (Etot_l_lp - st->totalNoise < 10.0f) && non_staB > 8.0f ) + ) + ) + */ + test(); + test(); + test(); + test(); + test(); + IF ( ( aE_bgd==0 ) + && ( LT_16(hNoiseEst->harm_cor_cnt, 50) ) + && ( ( GT_16(hNoiseEst->act_pred_fx, 19661) ) /* 0.6 in Q15*/ + || ( ( tn_ini==0 ) + && (LT_16(sub(Etot_l_lp, hNoiseEst->totalNoise_fx),10*256) ) /* 10.0 in Q8 */ + && (GT_16(non_staB, 8*256) ) /* 8.0 in in Q8*/ + ) + ) + ) + { + updt_step = 328; + move16(); /* 0.01 Q15 */ + } + /* + IF (updt_step > 0 ) + { + */ + hNoiseEst->first_noise_updt = 1; + move16(); + FOR( i=0; i< NB_BANDS; i++ ) + { + /* st->bckr[i] = st->bckr[i] + updt_step * (tmpN[i]-st->bckr[i]);*/ + /* 32 bit state update */ + Ltmp = L_sub(tmpN[i], hNoiseEst->bckr_fx[i]); /*Q_new+Q_SCALE*/ + Ltmp = Mult_32_16(Ltmp, updt_step ); /* Q_new+Q_SCALE+15+1 -16*/ + hNoiseEst->bckr_fx[i] = L_add(Ltmp, hNoiseEst->bckr_fx[i]); + move32(); + } + /* + } */ + } + /*else if (aE_bgd || st->harm_cor_cnt > 100 )*/ + ELSE IF ( (aE_bgd !=0) || (GT_16(hNoiseEst->harm_cor_cnt, 100))) + { + hNoiseEst->first_noise_updt = add(hNoiseEst->first_noise_updt,1); + } + } + ELSE + { + /* If in music lower bckr to drop further */ + test(); + test(); + IF ( (GT_16(hNoiseEst->low_tn_track_cnt, 300)) + && (GT_16(hNoiseEst->lt_haco_ev_fx, 29491 ) ) /*.9 in Q15 */ + && (hNoiseEst->totalNoise_fx > 0 ) ) + { + updt_step = -655; + move16(); /* for debug purposes */ + FOR( i=0; i< NB_BANDS; i++ ) + { + IF( GT_32(hNoiseEst->bckr_fx[i], L_shl(Le_min_scaled, 1L) )) /* 2*E_MIN(float) in float, here we use 2*Le_min_scaled Q_new+Q_SCALE */ + { + /* st->bckr[i] = 0.98f*st->bckr[i]; */ + hNoiseEst->bckr_fx[i] = Mult_32_16(hNoiseEst->bckr_fx[i], 32113); /* .98 in Q15 */ + move32(); /* move to array */ + } + } + } + /*st->lt_aEn_zero = 0.2f * (st->aEn==0) + (1-0.2f) *st->lt_aEn_zero;*/ + /* y(n+1)= alpha*tmp + (1-alpha)*y(n) */ + tmp=0; + move16(); + if(hNoiseEst->aEn == 0 ) + { + tmp=32767; + move16(); + } + hNoiseEst->lt_aEn_zero_fx = noise_est_AR1_Qx(tmp, hNoiseEst->lt_aEn_zero_fx, 6554); /* alpha=0.2 , Q15 */ + + } + +#ifdef IVAS_CODE + IF (GT_16(st_fx->element_mode, EVS_MONO)) + { + test(); + if (hNoiseEst->first_noise_updt_cnt_fx > 0 && LT_16(hNoiseEst->first_noise_updt_cnt_fx, 100)) + { + hNoiseEst->first_noise_updt_cnt_fx = add(hNoiseEst->first_noise_updt_cnt_fx, 1); + } + } +#endif + + return; +} + + diff --git a/lib_enc/noise_adjust_fx.c b/lib_enc/noise_adjust_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..e2d506c050c9edf06c3db344dd2beef4ec4926f5 --- /dev/null +++ b/lib_enc/noise_adjust_fx.c @@ -0,0 +1,70 @@ +/*==================================================================================== + 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 "prot_fx.h" /* Function prototypes */ +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*--------------------------------------------------------------------------* + * noise_adjust_fx() + * + * Calculate attenuation + *--------------------------------------------------------------------------*/ + +Word16 noise_adjust_fx( /* o : index of noise attenuation Q0 */ + const Word16 *coeffs_norm, /* i : normalized coefficients Qx */ + const Word16 qx, /* i : Q value of coeffs_norm */ + const Word16 *bitalloc, /* i : bit allocation Q0 */ + const Word16 *sfm_start, /* i : band start Q0 */ + const Word16 *sfm_end, /* i : band end Q0 */ + const Word16 core_sfm /* i : index of the end band for core Q0 */ +) +{ + Word16 nf_idx, sfm, bin, num_coeffs; + Word16 E, diff, inv_num_coeffs; + + E = 0; + move16(); + num_coeffs = 0; + move16(); + + FOR (sfm = 0; sfm <= core_sfm; sfm++) + { + IF (bitalloc[sfm] == 0) + { + FOR (bin = sfm_start[sfm]; bin < sfm_end[sfm]; bin++) + { + IF (coeffs_norm[bin] == 0) + { + E = sub(E, 1); + } + ELSE + { + E = add(E, sub(15+8,add(qx,norm_s(coeffs_norm[bin])))); + } + num_coeffs = add(num_coeffs, 1); + } + } + } + + IF (num_coeffs != 0) + { + inv_num_coeffs = div_s(1,num_coeffs); /* Q15 */ + E = mult(E,inv_num_coeffs); /* Q0 (0+15-15) */ + } + ELSE + { + E = 0; + move16(); + } + + diff = sub(7, E); + nf_idx = s_min(s_max(diff,0),3); + + return nf_idx; +} diff --git a/lib_enc/normalizecoefs_fx.c b/lib_enc/normalizecoefs_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..5797032ca6c6a408488cc6e69d7cf58165971588 --- /dev/null +++ b/lib_enc/normalizecoefs_fx.c @@ -0,0 +1,70 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include "options.h" /* Compilation switches */ +#include "cnst.h" /* Common constants */ +//#include "basop_mpy.h" +//#include "prot_fx.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + + +/*-------------------------------------------------------------------------- + * normalizecoefs_fx() + * + * Normalize MDCT coefficients with quantized norms + *--------------------------------------------------------------------------*/ + +void normalizecoefs_fx( + Word32 *coefs, /* i : Input vector (Q12) */ + const Word16 *ynrm, /* i : quantization indices for norms */ + const Word16 num_bands, /* i : Number of bands */ + const Word16 *band_start, /* i : Start of bands */ + const Word16 *band_end, /* i : End of bands */ + Word16 *coefs_norm /* o : Normalized output vector */ +) +{ + Word16 band, j, k, r, v; + Word16 *pcoefs16; + Word32 *pcoefs; + Word16 subvec_start, subvec_end, num_coefs; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + pcoefs = coefs; + pcoefs16 = coefs_norm; + + FOR (band = 0; band < num_bands; band++) + { + r = s_and(ynrm[band], 1); + v = shr(ynrm[band], 1); + k = sub(sub(17, r), v); + + subvec_start = band_start[band]; + move16(); + subvec_end = band_end[band]; + move16(); + num_coefs = sub(subvec_end, subvec_start); + + FOR (j = 0; j < num_coefs; j++) + { + IF (r!=0) + { + *pcoefs = Mpy_32_16_1(*pcoefs, INV2POWHALF); + move32(); + } +#ifdef BASOP_NOGLOB + * pcoefs16++ = round_fx_o(L_shl_o(*pcoefs++, 16 - k, &Overflow), &Overflow); /* Q12 */ +#else + BASOP_SATURATE_WARNING_OFF_EVS /* May saturate for strong peaks in a high band, in which case saturation is desirable */ + *pcoefs16++ = round_fx( L_shl(*pcoefs++, 16-k) ); /* Q12 */ + BASOP_SATURATE_WARNING_ON_EVS +#endif + } + } + + return; +} + diff --git a/lib_enc/peak_vq_enc_fx.c b/lib_enc/peak_vq_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..084609b994e1ab7079c0b26f68024c2a9aeb50fe --- /dev/null +++ b/lib_enc/peak_vq_enc_fx.c @@ -0,0 +1,785 @@ +/*==================================================================================== + 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" +#include "rom_enc.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-------------------------------------------------------------------------- + * Local function prototypes + *--------------------------------------------------------------------------*/ + +static void quant_peaks_fx(BSTR_ENC_HANDLE hBstr, const Word32*, Word32*, const Word32*, + Word16*, const Word16, const Word32, const Word16); +static Word16 hvq_code_pos_fx(BSTR_ENC_HANDLE hBstr, const Word16 *inp, const Word16 length, const Word16 num_peaks); +static Word16 sparse_code_pos_fx(const Word16 *inp, const Word16 length, Word16 *result); + +/*-------------------------------------------------------------------------- + * peak_vq_enc_fx() + * + * Vector Quantization of MDCT peaks + *--------------------------------------------------------------------------*/ + +Word16 peak_vq_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 bwidth, /* i : audio bandwidth */ + const Word32 *coefs, /* i : Input coefficient vector Q12 */ + Word32 *coefs_out, /* o : Quantized output vector Q12 */ + const Word32 core_brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 vq_peaks, /* i : Number of identified peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *vq_peak_idx, /* i : Peak index vector */ + Word32 *nf_gains /* i : Estimated noise floor gains Q12 */ +) +{ + Word16 pos_bits; + Word32 normq; + Word32 pgain_q[HVQ_MAX_PEAKS]; + Word32 peak_gains[HVQ_MAX_PEAKS]; + Word16 coefs_pvq[HVQ_PVQ_BUF_LEN], *pCoefsPvq; /* Q12 */ + Word32 pvq_vector[HVQ_PVQ_BUF_LEN], *pPvqVector; + Word32 *pPvqVectorBandStart; + Word16 pvq_vector_norm[HVQ_PVQ_BUF_LEN]; + Word16 fg_pred[NB_SFM_MAX]; + Word16 i, j, k, m, r, pvq_bands, num_overlap_bins; + Word16 hcode_l, FlagN, low_peak_bin, vq_cb_idx, max_peaks, bin_th, bin_th2; + Word16 bits; + Word16 nf_seed; + Word16 pgain_cb_idx[HVQ_MAX_PEAKS], pgain_difidx[HVQ_MAX_PEAKS]; /* Q0 */ + Word16 pvq_norm[MAX_PVQ_BANDS]; + Word16 pvq_bits, bit_budget; + Word16 pos_vec[HVQ_THRES_BIN_32k]; + Word16 npulses[MAX_PVQ_BANDS]; + Word16 pvq_inp_vector[HVQ_PVQ_BUF_LEN]; + Word16 k_sort[MAX_PVQ_BANDS]; + Word16 Rk[MAX_PVQ_BANDS]; + Word16 gopt[NB_SFM]; + Word16 tmp1, exp1; + Word16 Q_coefs; + + + Word16 indx, vqPeaksMinus1, tmp16, whiteNoise; + Word16 *pPgainDifIdx, *pPgainCbIdx, *pVqPeakIdx, *pPosVec; + Word32 *pPeakGains, *pCoefsOut; + const Word32 *pCoefs; + Word32 acc; + UWord16 dontCare16; + Word32 manE_peak, manPeakGains, manPkEnrg; /* Due to very wide dynamic range, use floating point format, i.e., (man, exp) */ + Word16 expE_peak, expPeakGains, expPkEnrg; + Word16 *pSelBnds; + Word16 sel_bnds[HVQ_NUM_SFM_24k]; + Word16 hvq_band_end[MAX_PVQ_BANDS]; + Word16 hvq_band_start[MAX_PVQ_BANDS]; + Word16 hvq_band_width[MAX_PVQ_BANDS]; + Word16 n_sel_bnds; + UWord32 lsb; + + assert((core_brate > HQ_16k40 && core_brate <= HQ_48k) && "HVQ rate not supported"); + + //PMT("max_peaks equation needs to be converted") + max_peaks = (Word16)((core_brate * HVQ_PEAKS_PER_DELTA + HVQ_PEAKS_PER_DELTA_OFFS) / HVQ_PEAKS_BPS_DELTA); + + + bits = 0; + move16(); + nf_seed = RANDOM_INITSEED; + move16(); + + + set16_fx(coefs_pvq, 0, HVQ_PVQ_BUF_LEN ); + set32_fx(pvq_vector, 0, HVQ_PVQ_BUF_LEN ); + set16_fx(pvq_vector_norm, 0, HVQ_PVQ_BUF_LEN ); + set16_fx(npulses, 0, MAX_PVQ_BANDS ); + + bin_th = HVQ_THRES_BIN_32k; + move16(); + bin_th2 = HVQ_THRES_BIN_32k/HVQ_NF_GROUPS; + move16(); + /* Set bit-rate dependent variables */ + IF (LT_32(core_brate, HQ_BWE_CROSSOVER_BRATE)) + { + bin_th = HVQ_THRES_BIN_24k; + move16(); + bin_th2 = HVQ_THRES_BIN_24k/HVQ_NF_GROUPS; + move16(); + } + + FOR (i = 0; i < bin_th; i++) + { + pos_vec[i] = 0; + move16(); + } + + /* Quantize noise floor gains */ + FOR (i = 0; i < HVQ_NF_GROUPS; i++) + { + logqnorm_fx(&nf_gains[i], 12, &indx, 32, 1, 0); + + /* De-quantization */ + acc = L_add(dicn_fx[indx], 0); /* Q14 */ + nf_gains[i] = L_shr(acc, 1 + 2); /* nf_gains in Q12. dicn_fx is in Q14. Need extra shift +2. */ + push_indice_fx( hBstr, IND_HVQ_NF_GAIN , (int)indx, 5); + bits = add(bits, 5); + } + + /* Signal number of peaks */ + i = sub(max_peaks, vq_peaks); + push_indice_fx( hBstr, IND_NUM_PEAKS, (int)i, 5); + bits = add(bits, 5); + + /* Identify position of first peak and arrange peak gains by position */ + pVqPeakIdx = &vq_peak_idx[0]; + low_peak_bin = bin_th; + FOR (i = 0; i < vq_peaks; i++) + { + indx = *pVqPeakIdx++; + move16(); + IF (LT_16(indx, low_peak_bin)) + { + low_peak_bin = indx; + move16(); + } + /* Store the sign information. */ + IF ( coefs[indx] < 0) + { + pos_vec[indx] = -1; /* Negative. */ move16(); + } + ELSE + { + pos_vec[indx] = 1; /* Positive */ move16(); + } + } + + pPeakGains = &peak_gains[0]; + pVqPeakIdx = &vq_peak_idx[0]; + pPosVec = &pos_vec[0]; + pCoefs = &coefs[0]; + FOR (i = 0; i < bin_th; i++) + { + acc = *pCoefs++; + IF(*pPosVec++ != 0) + { + *pPeakGains++ = L_abs(acc); /* in Q12 */ move32(); + *pVqPeakIdx++ = i; + move16(); + } + } + + /* Scale down peak gains */ + /* Divided by 4 is equivalent to consider peak_gains to be in Q14 from Q12. + * No physical bit shift is actually required. + */ + + /* Quantize peak gains */ + pPeakGains = &peak_gains[0]; + pPgainCbIdx = &pgain_cb_idx[0]; + logqnorm_fx(pPeakGains++, 14, pPgainCbIdx++, 32, 1, 1); + vqPeaksMinus1 = sub(vq_peaks, 1); + FOR (i = 0; i < vqPeaksMinus1; i++) + { + logqnorm_fx(pPeakGains++, 14, pPgainCbIdx++, 45, 1, 1); + } + + /* Code quantized peak gain indices + * and also scale up peak gains. */ + diffcod_fx(vq_peaks, pgain_cb_idx, &pgain_difidx[1]); + /* Accumulate peak energy. */ + manE_peak = L_deposit_l(0); + expE_peak = 32; + move16(); + FOR (i = 0; i < vq_peaks; i++) + { + indx = pgain_cb_idx[i]; + move16(); + /* Scale up peak gains */ + pgain_q[i] = L_shl(dicn_pg_fx[indx], 2); /* pgain_q in Q12 */ move32(); + /* Use floating point operation to deal with wide dynamic range.l + * 32-bit mantissa is used here. It should be even more accurate than + * the floating-point reference code with 24-bit mantissa! */ + expPeakGains = norm_l(pgain_q[i]); + manPeakGains = L_shl(pgain_q[i], expPeakGains); + Mpy_32_32_ss(manPeakGains, manPeakGains, &manPkEnrg, &lsb); /* peak_gains square */ + expPkEnrg = shl(expPeakGains, 1); /* Multiply by 2 due to squaring. */ + /* True floating value = manPkEng x 2^(32 - 1 - expPkEnrg - 2*12). + * In this context, the 32-bit manPkEng is in Q0. + * 32 is due to Mpy_32_32() only providing the 32 MSBs of the 64 bits product. + * -1 is due fractional mode Multiply. 2*12 is due to square of Q12. */ + floating_point_add(&manE_peak, &expE_peak, manPkEnrg, expPkEnrg); + } + pgain_difidx[0] = pgain_cb_idx[0]; + move16(); + + /* Huffman coding */ + hcode_l = 0; + pPgainDifIdx = &pgain_difidx[1]; + FOR (i = 0; i < vqPeaksMinus1; i++) + { + indx = *pPgainDifIdx++; + move16(); + hcode_l = add(hcode_l, pgain_huffsizn[indx]); + } + + FlagN = HUFCODE; + move16(); + + tmp16 = extract_l(L_mult0(GAINI_BITS, vqPeaksMinus1)); + IF ( GE_16(hcode_l, tmp16)) + { + hcode_l = tmp16; + move16(); + FlagN = NOHUFCODE; + move16(); + } + + push_indice_fx( hBstr, IND_FLAGN, (int)FlagN, 1); + push_indice_fx( hBstr, IND_PG_IDX, (int)pgain_difidx[0], GAIN0_BITS); + + IF (FlagN) + { + pPgainDifIdx = &pgain_difidx[1]; + FOR (i = 0; i < vqPeaksMinus1; i++) + { + j = *pPgainDifIdx++; + move16(); + m = pgain_huffnorm[j]; + move16(); + r = pgain_huffsizn[j]; + move16(); + + push_indice_fx( hBstr, IND_PG_IDX, (int)m, r ); + } + } + ELSE + { + pPgainDifIdx = &pgain_difidx[1]; + FOR (i = 0; i < vqPeaksMinus1; i++) + { + push_indice_fx( hBstr, IND_PG_IDX, (int)(*pPgainDifIdx++), GAINI_BITS ); + } + } + + /* Number of bits used for peak gain quantization */ + bits = add(bits, add(FLAGN_BITS + GAIN0_BITS, hcode_l)); + + /* Add sign for peak shape normalization */ + FOR (i = 0; i < vq_peaks; i++) + { + indx = vq_peak_idx[i]; + move16(); + peak_gains[i] = pgain_q[i]; /* Q12 */ move32(); + IF (pos_vec[indx] < 0) + { + peak_gains[i] = L_negate(peak_gains[i]); /* Q12 */ + } + } + + /* Quantize peak shapes */ + FOR (i = 0; i < vqPeaksMinus1; i++) + { + num_overlap_bins = sub(5, sub(vq_peak_idx[i+1], vq_peak_idx[i])); + indx = sub(vq_peak_idx[i], 2); + quant_peaks_fx(hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, num_overlap_bins, core_brate, vq_peaks); + push_indice_fx( hBstr, IND_HVQ_PEAKS, (UWord16)vq_cb_idx, 8 ); + bits = add(bits, 9); + } + + indx = sub(vq_peak_idx[i], 2); + quant_peaks_fx(hBstr, &coefs[indx], &coefs_out[indx], &peak_gains[i], &vq_cb_idx, 0, core_brate, vq_peaks); + push_indice_fx( hBstr, IND_HVQ_PEAKS, (UWord16)vq_cb_idx, 8 ); + bits = add(bits, 9); + + /* Quantize peak positions and sign with HVQ */ + pos_bits = hvq_code_pos_fx( hBstr, pos_vec, bin_th, vq_peaks ); + + bits = add(bits, pos_bits); + bit_budget = sub(num_bits, bits); + + /* Calculate number of PVQ bands to code and assign bits */ + pvq_bands = hvq_pvq_bitalloc_fx(bit_budget, core_brate, bwidth, ynrm, manE_peak, expE_peak, Rk, R, sel_bnds, &n_sel_bnds); + + /* Get band limits for concatenated PVQ target */ + hvq_concat_bands_fx(pvq_bands, sel_bnds, n_sel_bnds, hvq_band_start, hvq_band_width, hvq_band_end); + + /* Quantize PVQ bands */ + pCoefsOut = coefs_out; + pCoefs = coefs; + pPvqVector = pvq_vector; + pSelBnds = sel_bnds; + m = bin_th; + move16(); + FOR (k = 0; k < pvq_bands; k++) + { + IF (GE_16(k, sub(pvq_bands, n_sel_bnds))) + { + i = band_start_harm[*pSelBnds++]; + move16(); + pCoefs = coefs + i; + pCoefsOut = coefs_out + i; + } + k_sort[k] = k; + j = 0; + move16(); + pPvqVectorBandStart = pPvqVector; + WHILE (LT_16(j, hvq_band_width[k])) + { + IF (*pCoefsOut++ == 0) + { + *pPvqVector++ = *pCoefs; /* Q12 */ move32(); + j = add(j, 1); + } + pCoefs++; + } + logqnorm_fx( pPvqVectorBandStart, 12, &pvq_norm[k], 40, hvq_band_width[k], 0 ); + + } + + /* Normalize coefficients */ + normalizecoefs_fx( pvq_vector, pvq_norm, pvq_bands, hvq_band_start, hvq_band_end, pvq_vector_norm ); + Q_coefs = 12; + move16(); + + bit_budget = sub(bit_budget, i_mult2(HVQ_PVQ_GAIN_BITS, pvq_bands)); + + pvq_bits = bit_budget; + move16(); + set16_fx( npulses, 0, MAX_PVQ_BANDS ); + + pvq_encode_frame_fx(hBstr, pvq_vector_norm, Q_coefs, coefs_pvq, gopt, npulses, pvq_inp_vector, hvq_band_start, hvq_band_end, hvq_band_width, pvq_bands, + Rk, pvq_bits, HQ_CORE ); + + FOR (i = 0; i < pvq_bands; i++) + { + k_sort[i] = i; + move16(); + } + + + fine_gain_pred_fx( hvq_band_start, hvq_band_end, hvq_band_width, k_sort, npulses, NULL, NULL, pvq_bands, coefs_pvq, + pvq_inp_vector, fg_pred, HQ_CORE ); + + pCoefsOut = &coefs_out[0]; + pSelBnds = &sel_bnds[0]; + pCoefsPvq = &coefs_pvq[0]; + FOR (k = 0; k < pvq_bands; k++) + { + indx = pvq_norm[k]; + tmp1 = ratio(gopt[k], fg_pred[k], &exp1); + tmp1 = shr(tmp1, sub(1, exp1)); /* Q13 */ + Mpy_32_16_ss(dicn_fx[indx], tmp1, &normq, &dontCare16); /* dicn_fx in Q14, sorted_pvq_gain_pred_err_fx in Q13. */ + + logqnorm_fx(&normq, 12, &pvq_norm[k], 40, 1, 0); /* normq in Q(14+(16+13)+1-32)=Q12 */ + pvq_norm[k] = sub(pvq_norm[k], 8); + IF (pvq_norm[k] < 0) + { + pvq_norm[k] = 0; + move16(); + } + + push_indice_fx( hBstr, IND_HVQ_PVQ_GAIN, pvq_norm[k], HVQ_PVQ_GAIN_BITS); + pvq_bits = add(pvq_bits, HVQ_PVQ_GAIN_BITS); + + pvq_norm[k] = add(pvq_norm[k], 8); + + indx = pvq_norm[k]; + move16(); + normq = L_add(dicn_fx[indx], 0); /* in Q14 */ + j = 0; + move16(); + IF (GE_16(k, sub(pvq_bands, n_sel_bnds))) + { + i = band_start_harm[*pSelBnds++]; + move16(); + pCoefsOut = coefs_out + i; + } + WHILE (LT_16(j, hvq_band_width[k])) + { + IF (EQ_32(*pCoefsOut, 0)) + { + acc = L_mult(*pCoefsPvq++, fg_pred[k]); /* in Q(15 + 1 + 12 = 28) */ + tmp16 = extract_h(acc); /* in Q(28 - 16 = 12) */ + Mpy_32_16_ss(normq, tmp16, &acc, &dontCare16); /* acc(Q11), normq(Q14), tmp16(Q12) */ + *pCoefsOut = L_shl(acc, 12 - 11); /* Q12 */ + j = add(j, 1); + } + pCoefsOut++; + } + } + bits = add(bits, pvq_bits); + + /* Noise fill unqantized coeffs with one gain per group */ + pCoefsOut = &coefs_out[-1]; + FOR (i = 0; i < HVQ_NF_GROUPS; i++) + { + FOR (j = 0; j < bin_th2; j++) + { + IF (*(++pCoefsOut) == 0) + { + whiteNoise = Random(&nf_seed); /* Q15 */ + Mpy_32_16_ss(nf_gains[i], whiteNoise, pCoefsOut, &dontCare16); /* nf_gains in Q12. *pCoefsOut in Q12 */ + } + } + } + + return bits; +} + +/*-------------------------------------------------------------------------- + * quant_peaks_fx() + * + * Applies VQ on input vector + *--------------------------------------------------------------------------*/ + +static void quant_peaks_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word32 *vect_in, /* i : Target vector in Q12 */ + Word32 *vect_out, /* i/o: Quantized vector in Q12 */ + const Word32 *peak_gain,/* i : Peak gain vector in Q12 */ + Word16 *vq_idx, /* o : Codebook index */ + const Word16 overlap, /* i : Overlap indicator */ + const Word32 core_brate,/* i : Core bitrate */ + const Word16 Npeaks /* i : Number of peaks */ +) +{ + Word16 x[4]; /* Qx */ + Word16 xq[4]; /* Q15 */ + Word16 weights[4]; /* Q0 */ + Word16 *pWeights; + Word16 i, cb_class, search_overlap, indx, cbSize; + Word16 expPeakGain, manPeakGain, expIn, manIn; + Word32 vectIn, absPeakGain1, absPeakGain; + UWord16 dontCare; + Word16 Qx_vec[4]; + Word16 Qx = 15; + + set16_fx(weights,1,4); + + /* Divide vect_in[] by peak_gain to yield x[]. */ + expPeakGain = norm_l(*peak_gain); /* exponent */ + manPeakGain = extract_h(L_shl(*peak_gain, expPeakGain)); /* mantissa */ + manPeakGain = abs_s(manPeakGain); /* Prepare for div_s() only accepting +ve. */ + FOR (i = 0; i < 4; i++) + { + indx = hvq_index_mapping_fx[i]; + move16(); + vectIn = L_add(vect_in[indx], 0); + expIn = norm_l(vectIn); /* exponent */ + expIn = sub(expIn, 1); + expIn = s_min(expIn, expPeakGain); /* highest Q is Q15 */ + manIn = extract_h(L_shl(vectIn, expIn)); /* mantissa */ + manIn = abs_s(manIn); /* Prepare for div_s() only accepting +ve. */ + + x[i] = div_s(manIn, manPeakGain); /* in Q(15+expIn-expPeakGain) */ + + Qx_vec[i] = add(15, sub(expIn, expPeakGain)); + Qx = s_min(Qx, Qx_vec[i]); + + /* Restore the sign destroyed by abs operations. */ + if (L_xor(vectIn, *peak_gain) < 0) /* Check the sign bits (MSB). */ + { + x[i] = negate(x[i]); + } + } + FOR (i = 0; i < 4; i++) + { + IF (NE_16(Qx_vec[i], Qx)) + { + x[i] = shr(x[i], sub(Qx_vec[i], Qx)); /* Qx */ + } + } + absPeakGain = L_abs(peak_gain[0]); + IF (vect_out[0] != 0) + { + absPeakGain1 = L_abs(peak_gain[-1]); + IF (GT_32(absPeakGain1, absPeakGain)) + { + weights[0] = 0; + move16(); + if (vect_out[1] != 0) + { + weights[1] = 0; + move16(); + } + } + } + IF (overlap > 0) + { + absPeakGain1 = L_abs(peak_gain[1]); + IF (GT_32(absPeakGain1, absPeakGain)) + { + indx = sub(4, overlap); + pWeights = &weights[indx]; + FOR (i = 0; i < overlap; i++) + { + *pWeights++ = 0; + move16(); + } + } + } + + /* Classify */ +#if HVQ_VQ_DIM != 5 +#error w_vquant_fx() is hard-wired to dim = 4 = (HVQ_VQ_DIM - 1). +#endif + cb_class = w_vquant_fx(x, Qx, weights, 0, hvq_class_c_fx, HVQ_NUM_CLASS, 0); + IF (LT_32(core_brate, HQ_BWE_CROSSOVER_BRATE)) + { + indx = sub(HVQ_MAX_PEAKS_24k, Npeaks); + search_overlap = hvq_cb_search_overlap24k[indx]; + move16(); + } + ELSE + { + indx = sub(HVQ_MAX_PEAKS_32k, Npeaks); + search_overlap = hvq_cb_search_overlap32k[indx]; + move16(); + } + + /* Quantize */ + cbSize = add(HVQ_CB_SIZE/2, search_overlap); + IF ( cb_class == 0 ) + { + *vq_idx = w_vquant_fx(x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 0); + push_indice_fx( hBstr, IND_HVQ_PEAKS, 0, 1 ); + } + ELSE IF( EQ_16(cb_class, 1)) + { + indx = sub(HVQ_CB_SIZE*2, shl(search_overlap,2)); + *vq_idx = w_vquant_fx(x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 0); + *vq_idx = add(*vq_idx, sub(HVQ_CB_SIZE/2, search_overlap)); + push_indice_fx( hBstr, IND_HVQ_PEAKS, 0, 1 ); + } + ELSE IF( EQ_16(cb_class, 2)) + { + indx = sub(HVQ_CB_SIZE*2, shl(search_overlap,2)); + *vq_idx = w_vquant_fx(x, Qx, weights, xq, &hvq_peak_cb_fx[indx], cbSize, 1); + *vq_idx = add(*vq_idx, sub(HVQ_CB_SIZE/2, search_overlap)); + push_indice_fx( hBstr, IND_HVQ_PEAKS, 1, 1 ); + } + ELSE + { + *vq_idx = w_vquant_fx(x, Qx, weights, xq, hvq_peak_cb_fx, cbSize, 1); + push_indice_fx( hBstr, IND_HVQ_PEAKS, 1, 1 ); + } + + FOR (i = 0; i < 4; i++) + { + indx = hvq_index_mapping_fx[i]; + move16(); + IF (weights[i] != 0) + { + Mpy_32_16_ss(*peak_gain, xq[i], &vect_out[indx], &dontCare); /* peak_gains in Q12, xq in Q15 -> Q12. */ + move32(); + } + } + vect_out[2] = *peak_gain; + move32(); /* vect_out in Q12 */ + + return; +} + +/*-------------------------------------------------------------------------- + * code_pos() + * + * Code pulse positions + *--------------------------------------------------------------------------*/ + +static Word16 sparse_code_pos_fx( + const Word16 *inp, + const Word16 length, + Word16 *result +) +{ + Word16 layer2[HVQ_CP_L2_MAX]; + Word16 layer_length; + Word16 i,j,tmp; + Word16 val, idx; + Word16 bits = 0; + Word16 mask; + + set16_fx(layer2, 0, HVQ_CP_L2_MAX); + + /*layer_length = (short)((float)length/HVQ_CP_L1_LEN + 0.5); */ + layer_length = round_fx(L_mult0(length, 13107)); /* 0+16-16, 13107 is 1/5 in Q16 */ + + FOR (j = 0; j < layer_length; j++) + { + tmp = s_min(i_mult2(add(j,1),HVQ_CP_L1_LEN), length); + FOR (i = i_mult2(j, HVQ_CP_L1_LEN); i < tmp; i++) + { + IF (inp[i] != 0) + { + layer2[j] = 1; + move16(); + BREAK; + } + } + } + + FOR (i = 0; i < layer_length; i++) + { + result[i] = layer2[i]; + move16(); + } + bits = add(bits, layer_length); + + FOR (j = 0; j < layer_length; j++) + { + IF (layer2[j] != 0) + { + val = 0; + move16(); + tmp = s_min(i_mult2(add(j,1),HVQ_CP_L1_LEN), length); + FOR (i = i_mult2(j, HVQ_CP_L1_LEN); i < tmp; i++) + { + val = shl(val, 1); + val = s_or(val, inp[i]); + } + + FOR (idx = 0; idx < HVQ_CP_MAP_LEN; idx++) + { + IF (EQ_16(hvq_cp_layer1_map5[idx], val)) + { + BREAK; + } + } + + mask = shl(1, HVQ_CP_MAP_IDX_LEN - 1); + FOR (i = 0; i < HVQ_CP_MAP_IDX_LEN; i++) + { + result[bits++] = shr(s_and(idx, mask), sub(HVQ_CP_MAP_IDX_LEN - 1, i)); + mask >>= 1; + } + } + } + + return bits; +} + +/*-------------------------------------------------------------------------- + * hvq_code_pos() + * + * Code pulse positions + *--------------------------------------------------------------------------*/ + +static Word16 hvq_code_pos_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *inp, + const Word16 length, + const Word16 num_peaks +) +{ + Word16 sparse_result[4*HVQ_THRES_BIN_32k/HVQ_CP_L1_LEN]; + Word16 delta[HVQ_MAX_PEAKS]; + Word16 peak_idx[HVQ_MAX_PEAKS]; + Word16 inp_abs[HVQ_THRES_BIN_32k]; + Word16 inp_sign[HVQ_MAX_PEAKS]; + + Word16 i, j; + Word16 bits; + Word16 delta_max; + Word16 delta_bits, sparse_bits; + Word16 tmp; + + bits = 0; + move16(); + + /* Extract sorted peak index vector and sign vector */ + j = 0; + move16(); + FOR(i = 0; i < length; i++) + { + inp_abs[i] = abs_s(inp[i]); + IF (inp[i] != 0) + { + peak_idx[j] = i; + move16(); + inp_sign[j] = inp[i]; + move16(); + j = add(j, 1); + } + } + + /* Calculate delta */ + delta[0] = add(peak_idx[0], HVQ_CP_HUFF_OFFSET); + move16(); + delta_max = delta[0]; + move16(); + FOR (i = 1; i < num_peaks; i++) + { + delta[i] = sub(sub(peak_idx[i], peak_idx[i-1]), HVQ_CP_HUFF_OFFSET); + if (LT_16(delta_max, delta[i])) + { + delta_max = delta[i]; + move16(); + } + } + + /* Calculate bits needed for huffman coding of deltas */ + delta_bits = -1; + move16(); + IF (LE_16(delta_max, HVQ_CP_HUFF_MAX)) + { + delta_bits = 0; + move16(); + FOR (i = 0; i < num_peaks; i++) + { + delta_bits = add(delta_bits, hvq_cp_huff_len[delta[i]]); + } + } + + /* Calculate bits neeed for sparse coding */ + sparse_bits = sparse_code_pos_fx(inp_abs, length, sparse_result); + + /* Decide which coding mode to use */ + test(); + IF (GT_16(delta_bits, sparse_bits)||delta_bits<0) + { + push_indice_fx( hBstr, IND_POS_IDX, HVQ_CP_SPARSE, 1); + + FOR (i = 0; i < sparse_bits; i++) + { + push_indice_fx( hBstr, IND_POS_IDX, sparse_result[i], 1); + } + bits = add(add(bits, sparse_bits), 1); + } + ELSE + { + push_indice_fx( hBstr, IND_POS_IDX, HVQ_CP_DELTA, 1); + + FOR (i = 0; i < num_peaks; i++) + { + j = delta[i]; + move16(); + push_indice_fx( hBstr, IND_POS_IDX, hvq_cp_huff_val[j], hvq_cp_huff_len[j]); + } + bits = add(add(bits, delta_bits), 1); + } + + /* Send sign */ + FOR (i = 0; i < num_peaks; i++) + { + tmp = 1; + move16(); + if (inp_sign[i] < 0) + { + tmp = 0; + move16(); + } + push_indice_fx( hBstr, IND_POS_IDX, tmp, 1); + } + bits = add(bits, num_peaks); + + return bits; +} + diff --git a/lib_enc/pit_enc_fx.c b/lib_enc/pit_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..18224713ab7e280932943d16cabc24eab3018bae --- /dev/null +++ b/lib_enc/pit_enc_fx.c @@ -0,0 +1,1586 @@ +/*==================================================================================== + 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 "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 "rom_basop_util.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +#define inv_T0_res InvIntTable + +static void limit_T0_voiced2( Word16 res, const Word16 *T_op, Word16 *T0_min, Word16 *T0_min_frac, + Word16 *T0_max, Word16 *T0_max_frac, Word16 pit_min, Word16 pit_max, Word16 i_subfr ); + +/*==============================================================================*/ +/* FUNCTION : pit_encode_fx() */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Close-loop pitch lag search and pitch lag quantization */ +/* Adaptive excitation construction */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) core_brate: core bitrate Q0 */ +/* _ (Word16) Opt_AMR_WB: flag indicating AMR-WB IO mode Q0 */ +/* _ (Word16) bwidth : input signal bandwidth Q0 */ +/* _ (Word16[]) T_op : open loop pitch estimates in current frame Q0 */ +/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ +/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ +/* _ (Word16) T0 : close loop integer pitch Q0 */ +/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ +/* _ (Word16) L_frame_fx : length of the frame Q0 */ +/* _ (Word16[]) h1 : weighted filter input response Q15 */ +/* _ (Word16[]) xn : target vector Q_new */ +/* _ (Word16) coder_type_fx : coding type Q0 */ +/* _ (Word16) i_subfr : current sub frame indicator Q0 */ +/* _ (Word16[]) exc_fx : pointer to excitation signal frame Q_new */ +/* _ (Word16[]) L_subfr : subframe length Q0 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) exc_fx : adapt. excitation exc (Q0) */ +/* _ (Word16) T0_min : lower limit for close-loop search Q0 */ +/* _ (Word16) T0_max : higher limit for close-loop search Q0 */ +/* _ (Word16) T0 : close loop integer pitch Q0 */ +/* _ (Word16) T0_frac : close loop fractional part of the pitch Q0 */ +/*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==============================================================================*/ + +Word16 pit_encode_fx( /* o : Fractional pitch for each subframe */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 pitch_bits[], /* i : pitch bits */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 L_subfr, /* i : subframe length */ + const Word16 * pitch, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + const Word16 *h1, /* i : weighted filter input response */ + const Word16 *xn, /* i : target vector */ + const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const Word16 tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ +) +{ + Word16 pitch_cl; + Word16 pit_flag, delta, mult_Top, nBits; + Word16 L_sufr_sft; + Word16 T_op[2]; /* values for two half-frames */ +#ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + (void)tdm_Pitch_reuse_flag; +#endif + + L_sufr_sft = 6; + move16(); + if (EQ_16(L_subfr, 2*L_SUBFR)) + { + L_sufr_sft = 7; + } + + /*----------------------------------------------------------------* + * convert pitch values to 16kHz domain + *----------------------------------------------------------------*/ + IF (EQ_16(L_frame, L_FRAME) || (tdm_Pri_pitch_buf != NULL && tdm_Pri_pitch_buf[0] < 0)) + { + Copy(pitch, T_op, 2); + } + ELSE /* L_frame == L_FRAME16k */ + { + /*T_op[0] = (int16_t)(pitch[0] * 1.25f + 0.5f); + T_op[1] = (int16_t)(pitch[1] * 1.25f + 0.5f);*/ + T_op[0] = shr(add(round_fx(L_shl(L_mult(20480, pitch[0]), 2)), 1), 1); move16(); + T_op[1] = shr(add(round_fx(L_shl(L_mult(20480, pitch[1]), 2)), 1), 1); move16(); + } + + /*----------------------------------------------------------------* + * Set pit_flag to 0 for every subframe with absolute pitch search + *----------------------------------------------------------------*/ + pit_flag = i_subfr; + move16(); + if (EQ_16(i_subfr,2*L_SUBFR)) + { + pit_flag = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Limit range of pitch search + * Fractional pitch search + * Pitch quantization + *-----------------------------------------------------------------*/ + mult_Top = 1; + move16(); + + IF( !Opt_AMR_WB ) + { + /*----------------------------------------------------------------* + * pitch Q: Set limit_flag to 0 for restrained limits, and 1 for extended limits + *----------------------------------------------------------------*/ + test(); + test(); + IF( i_subfr == 0 ) + { + *limit_flag = 1; + move16(); + if( EQ_16(coder_type,VOICED)) + { + *limit_flag = 2; + move16(); /* double-extended limits */ + } + test(); + if( EQ_16(coder_type,GENERIC)&&EQ_32(core_brate,ACELP_7k20)) + { + *limit_flag = 0; + move16(); + } + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)&&EQ_16(coder_type,GENERIC)&&LE_32(core_brate,ACELP_13k20)) + { + /*if( *T0 > (PIT_FR1_EXTEND_8b + PIT_MIN)>>1 )*/ + if( GT_16(*T0,shr(add(PIT_FR1_EXTEND_8b , PIT_MIN), 1))) + { + *limit_flag = 0; + move16(); + } + } + + IF( *limit_flag == 0 ) + { + test(); + test(); + IF( i_subfr == 0 && LT_16(T_op[0],PIT_MIN)) + { + mult_Top = 2; + move16(); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)&<_16(T_op[1],PIT_MIN)) + { + mult_Top = 2; + move16(); + } + } + /*-------------------------------------------------------* + * Retrieve the number of Q bits + *-------------------------------------------------------*/ + nBits = 0; + move16(); + IF( NE_16(coder_type,AUDIO)) + { + nBits = pitch_bits[shr(i_subfr, L_sufr_sft)]; + } + IF( EQ_16(coder_type,AUDIO)) + { + /*-------------------------------------------------------* + * Pitch encoding in AUDIO coder type + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + delta = 4; + move16(); + test(); + test(); + if ( EQ_16(L_subfr,L_frame/2)&&i_subfr!=0&&EQ_16(L_frame,L_FRAME)) + { + pit_flag = L_SUBFR; + move16(); + } + IF ( pit_flag == 0 ) + { + nBits = 10; + move16(); + } + ELSE + { + nBits = 6; + move16(); + } + + /* pitch lag search limitation */ + test(); + IF( i_subfr == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)&& pit_flag == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_subfr ); + + pit_Q_enc_fx(hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE IF( EQ_16(coder_type,VOICED)) + { + /*-------------------------------------------------------* + * Pitch encoding in VOICED code type (ACELP@12k8 core only) + *-------------------------------------------------------*/ + + delta = 4; + move16(); + if ( EQ_16(i_subfr,2*L_SUBFR)) + { + pit_flag = i_subfr; + move16(); + } + + /* pitch lag search limitation */ + IF (i_subfr == 0) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + test(); + test(); + IF( EQ_16(nBits,9)||EQ_16(nBits,5)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_DOUBLEEXTEND_9b, PIT_FR1_DOUBLEEXTEND_9b, L_FRAME, L_SUBFR ); + move16(); + } + ELSE IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_SUBFR ); + move16(); + } + + pit_Q_enc_fx(hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } +#ifdef ADD_LRTD + else if (tdm_Pitch_reuse_flag == 1 || nBits == 4) + { + /*-------------------------------------------------------* + * Pitch encoding with reusing primary channel information + *-------------------------------------------------------*/ + int16_t loc_T0, loc_frac; + + delta = 4; + + pit_flag = L_SUBFR; + + if (L_subfr == 2 * L_SUBFR) + { + loc_T0 = (int16_t)(0.5f * tdm_Pri_pitch_buf[i_subfr / L_SUBFR] + 0.5f * tdm_Pri_pitch_buf[(i_subfr + L_SUBFR) / L_SUBFR]); + loc_frac = (int16_t)(((0.5f * tdm_Pri_pitch_buf[i_subfr / L_SUBFR] + 0.5f * tdm_Pri_pitch_buf[(i_subfr + L_SUBFR) / L_SUBFR]) - loc_T0) * 4.0f); + } + else + { + loc_T0 = (int16_t)tdm_Pri_pitch_buf[i_subfr / L_SUBFR]; + loc_frac = (int16_t)((tdm_Pri_pitch_buf[i_subfr / L_SUBFR] - loc_T0) * 4.0f); + } + + /* pitch lag search limitation */ + limit_T0(L_FRAME, delta, pit_flag, *limit_flag, loc_T0, loc_frac, T0_min, T0_max); + if (nBits > 0) + { + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4(&exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR); + if (delta == 8) + { + *T0_frac = 0; + } + pit_Q_enc(hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max); + } + else + { + *T0 = loc_T0; + *T0_frac = loc_frac; + } + } +#endif + ELSE + { + /*-------------------------------------------------------* + * Pitch encoding in GENERIC coder type + * (both ACELP@12k8 and ACELP@16k cores) + *-------------------------------------------------------*/ + + delta = 8; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + limit_T0_fx( L_frame, delta, pit_flag, *limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + } + + /* search and encode the closed loop pitch period */ + IF( EQ_16(L_frame,L_FRAME)) + { + test(); + test(); + IF( EQ_16(nBits,8)||EQ_16(nBits,5)) + { + IF( *limit_flag == 0 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN_EXTEND, PIT_FR1_EXTEND_8b, L_FRAME, L_SUBFR ); + } + } + ELSE IF( EQ_16(nBits,9)||EQ_16(nBits,6)) + { + IF( *limit_flag == 0 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_EXTEND_9b, PIT_FR1_EXTEND_9b, L_FRAME, L_SUBFR ); + } + } + ELSE IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MAX, PIT_MAX, L_FRAME, L_SUBFR ); + } + + pit_Q_enc_fx(hBstr, 0, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE /* L_frame == L_FRAME16k */ + { + test(); + IF( EQ_16(nBits,9)||EQ_16(nBits,6)) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT16k_FR2_EXTEND_9b, PIT16k_FR1_EXTEND_9b, L_FRAME16k, L_SUBFR ); + } + ELSE IF( nBits == 10 ) + { + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_FRAME16k, L_SUBFR ); + } + + pit16k_Q_enc_fx(hBstr, nBits, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + } + } + + /*-------------------------------------------------------* + * Pitch encoding in AMR-WB IO mode + *-------------------------------------------------------*/ + + ELSE + { + delta = 8; + move16(); + *limit_flag = 0; + move16(); + + IF( EQ_32(core_brate,ACELP_6k60)) + { + nBits = 5; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[0]), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + + if( EQ_16(i_subfr,2*L_SUBFR)) + { + /* rewrite pit_flag - it must not be zero */ + pit_flag = i_subfr; + move16(); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE IF( EQ_32(core_brate,ACELP_8k85)) + { + nBits = 5; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[0]), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[1]), 0, T0_min, T0_max ); + nBits = 8; + move16(); + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_MIN, PIT_FR1_8b, L_FRAME, L_SUBFR ); + } + ELSE + { + nBits = 6; + move16(); + + /* pitch lag search limitation */ + IF( i_subfr == 0 ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[0]), 0, T0_min, T0_max ); + nBits = 9; + move16(); + } + ELSE IF( EQ_16(i_subfr,2*L_SUBFR)) + { + limit_T0_fx( L_FRAME, delta, pit_flag, *limit_flag, i_mult2(mult_Top,T_op[1]), 0, T0_min, T0_max ); + nBits = 9; + move16(); + } + ELSE + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, *T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + + /* search and encode the closed loop pitch period */ + *T0 = pitch_fr4_fx( &exc[i_subfr], xn, h1, *T0_min, *T0_max, T0_frac, pit_flag, *limit_flag, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + + pit_Q_enc_fx(hBstr, 1, nBits, delta, pit_flag, *limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + + /*-------------------------------------------------------* + * Compute floating pitch output + *-------------------------------------------------------*/ + + /*pitch = (float)(*T0) + (float)(*T0_frac)/4.0f;*/ /* save subframe pitch values */ + pitch_cl = shl(add(shl(*T0,2),*T0_frac),4); /* save subframe pitch values Q6 */ + + return pitch_cl; + +} + +/*-------------------------------------------------------------------* + * abs_pit_enc() + * + * Encode pitch lag absolutely with resolution for shortest pitches + * depending on parameter 'fr_step': + * fr_step = 2: pitch range encoded with 8 bits + * fr_step = 4: pitch range encoded with 8 bits + *-------------------------------------------------------------------*/ + +Word16 abs_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4) for shortest pitches*/ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac /* i : pitch fraction */ +) +{ + Word16 pitch_index = 0; + + IF( limit_flag == 0 ) + { + IF( EQ_16(fr_steps,2)) + { + /*-----------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits + * and is divided as follows: + * PIT_MIN to PIT_FR1_8b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_8b to PIT_MAX resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + IF (LT_16(T0,PIT_FR1_8b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN*2);*/ + pitch_index = sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_MIN*2)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_8b + ((PIT_FR1_8b-PIT_MIN)*2);*/ + pitch_index = add(sub(T0,PIT_FR1_8b),((PIT_FR1_8b-PIT_MIN)*2)); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT_MIN to PIT_FR2_9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT_FR2_9b to PIT_FR1_9b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_9b to PIT_MAX resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF (LT_16(T0,PIT_FR2_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN*4);*/ + pitch_index = add(shl(T0,2),sub(T0_frac,(PIT_MIN*4))); + } + ELSE IF (LT_16(T0,PIT_FR1_9b)) + { + /* pitch_index = T0*2 + (T0_frac>>1) - (PIT_FR2_9b*2) + ((PIT_FR2_9b-PIT_MIN)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_FR2_9b*2)),((PIT_FR2_9b-PIT_MIN)*4)); + } + ELSE + { + /* pitch_index = T0 - PIT_FR1_9b + ((PIT_FR2_9b-PIT_MIN)*4) + ((PIT_FR1_9b-PIT_FR2_9b)*2);*/ + pitch_index = add(add(sub(T0,PIT_FR1_9b),((PIT_FR2_9b-PIT_MIN)*4)),((PIT_FR1_9b-PIT_FR2_9b)*2)); + } + } + ELSE /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + move16(); + } + } + ELSE IF( EQ_16(limit_flag,1)) /* extended Q range */ + { + IF( EQ_16(fr_steps,2)) + { + /*-----------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits + * and is divided as follows: + * PIT_MIN_EXTEND to PIT_FR1_EXTEND_8b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_EXTEND_8b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + IF( LT_16(T0,PIT_FR1_EXTEND_8b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN_EXTEND*2);*/ + pitch_index = sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_MIN_EXTEND*2)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_EXTEND_8b + ((PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2);*/ + pitch_index = add(sub(T0,PIT_FR1_EXTEND_8b),((PIT_FR1_EXTEND_8b-PIT_MIN_EXTEND)*2)); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT_MIN_EXTEND to PIT_FR2__EXTEND9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT_FR2_EXTEND_9b to PIT_FR1__EXTEND9b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_EXTEND_9b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF( LT_16(T0,PIT_FR2_EXTEND_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_EXTEND*4);*/ + pitch_index = add(shl(T0,2),sub(T0_frac,(PIT_MIN_EXTEND*4))); + } + ELSE IF( T0 < PIT_FR1_EXTEND_9b ) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_FR2_EXTEND_9b*2) + ((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_FR2_EXTEND_9b*2)),((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_EXTEND_9b + ((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4) + ((PIT_FR1_EXTEND_9b-PIT_FR2_EXTEND_9b)*2);*/ + pitch_index = add(add(sub(T0,PIT_FR1_EXTEND_9b),((PIT_FR2_EXTEND_9b-PIT_MIN_EXTEND)*4)),((PIT_FR1_EXTEND_9b-PIT_FR2_EXTEND_9b)*2)); + } + + } + ELSE /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + move16(); + } + } + ELSE /* double-extended Q range */ + { + IF( EQ_16(fr_steps,2)) + { + /*-----------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits + * and is divided as follows: + * PIT_MIN_DOUBLEEXTEND to PIT_FR1_DOUBLEEXTEND_8b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_DOUBLEEXTEND_8b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-----------------------------------------------------------------*/ + + IF( LT_16(T0,PIT_FR1_DOUBLEEXTEND_8b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_MIN_DOUBLEEXTEND*2);*/ + pitch_index = sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_MIN_DOUBLEEXTEND*2)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_DOUBLEEXTEND_8b + ((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2); */ + pitch_index = add(sub(T0,PIT_FR1_DOUBLEEXTEND_8b),((PIT_FR1_DOUBLEEXTEND_8b-PIT_MIN_DOUBLEEXTEND)*2)); + } + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT_MIN_DOUBLEEXTEND to PIT_FR2_DOUBLEEXTEND9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT_FR2_DOUBLEEXTEND_9b to PIT_FR1_DOOBLEEXTEND9b-1 resolution 1/2 (frac = 0 or 2) + * PIT_FR1_DOUBLEEXTEND_9b to PIT_MAX_EXTEND resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF(LT_16(T0,PIT_FR2_DOUBLEEXTEND_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_DOUBLEEXTEND*4);*/ + pitch_index = add(shl(T0,2),sub(T0_frac,(PIT_MIN_DOUBLEEXTEND*4))); + } + ELSE IF( LT_16(T0,PIT_FR1_DOUBLEEXTEND_9b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT_FR2_DOUBLEEXTEND_9b*2) + ((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT_FR2_DOUBLEEXTEND_9b*2)),((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4)); + } + ELSE + { + /*pitch_index = T0 - PIT_FR1_DOUBLEEXTEND_9b + ((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4) + ((PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2);*/ + pitch_index = add(add(sub(T0,PIT_FR1_DOUBLEEXTEND_9b),((PIT_FR2_DOUBLEEXTEND_9b-PIT_MIN_DOUBLEEXTEND)*4)),((PIT_FR1_DOUBLEEXTEND_9b-PIT_FR2_DOUBLEEXTEND_9b)*2)); + } + } + ELSE /* fr_step == 0 */ + { + /* not used in the codec */ + pitch_index = 0; + move16(); + } + } + + return pitch_index; +} + + +/*-------------------------------------------------------------------* + * delta_pit_enc: + * + * Encode pitch lag differentially from T0_min to T0_max + * with resolution depending on parameter 'fr_step': + * fr_step = 0: resolusion 1 (frac = 0), or + * fr_step = 2: resolusion 1/2 (frac = 0 or 2), or + * fr_step = 4: resolution 1/4 (frac = 0, 1, 2, or 3) + *-------------------------------------------------------------------*/ + +Word16 delta_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4)*/ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + const Word16 T0_min /* i : delta search min */ +) +{ + Word16 pitch_index = 0; + + IF( fr_steps == 0 ) + { + pitch_index = sub(T0,T0_min); + } + ELSE IF( EQ_16(fr_steps,2)) + { + /* pitch_index = (T0 - T0_min) * 2 + (T0_frac>>1);*/ + pitch_index = add(shl(sub(T0,T0_min),1),shr(T0_frac,1)); + } + ELSE IF( EQ_16(fr_steps,4)) + { + /*pitch_index = (T0 - T0_min) * 4 + T0_frac;*/ + pitch_index = add(shl(sub(T0,T0_min),2),T0_frac); + } + + return pitch_index; +} + +/*-------------------------------------------------------------------* + * pitch_fr4() + * + * Find the closed loop pitch period with 1/4 subsample resolution. + *-------------------------------------------------------------------*/ + +Word16 pitch_fr4_fx( /* o : chosen integer pitch lag */ + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t0_min, /* i : minimum value in the searched range. Q0*/ + const Word16 t0_max, /* i : maximum value in the searched range. Q0*/ + Word16 *pit_frac, /* o : chosen fraction (0, 1, 2 or 3) */ + const Word16 i_subfr, /* i : flag to first subframe */ + const Word16 limit_flag, /* i : flag for limits (0=restrained, 1=extended) */ + const Word16 t0_fr2, /* i : minimum value for resolution 1/2 */ + const Word16 t0_fr1, /* i : minimum value for resolution 1 */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 L_subfr /* i : size of subframe */ +) +{ + Word16 i; + Word16 t_min, t_max; + Word16 max_val, t0, t1, fraction, step, temp; + Word16 *corr; + Word16 corr_v[15+2*L_INTERPOL1+1]; /* Total length = t0_max-t0_min+1+2*L_inter */ + Word16 pit_min; + Word16 cor_max; + + /* initialization */ + IF( limit_flag == 0 ) + { + IF( EQ_16(L_frame,L_FRAME)) + { + pit_min = PIT_MIN; + move16(); + } + ELSE /* L_frame == L_FRAME16k */ + { + pit_min = PIT16k_MIN; + move16(); + } + } + ELSE + { + IF( EQ_16(L_frame,L_FRAME)) + { + pit_min = PIT_MIN_EXTEND; + move16(); + IF( EQ_16(limit_flag,2)) + { + pit_min = PIT_MIN_DOUBLEEXTEND; + move16(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + pit_min = PIT16k_MIN_EXTEND; + move16(); + } + } + + /*-----------------------------------------------------------------* + * - Find interval to compute normalized correlation + * - allocate memory to normalized correlation vector + * - Compute normalized correlation between target and filtered + * excitation + *-----------------------------------------------------------------*/ + + t_min = sub(t0_min, L_INTERPOL1); + t_max = add(t0_max, L_INTERPOL1); + corr = &corr_v[-t_min]; + move16(); + move16(); /* corr[t_min..t_max] */ + + norm_corr_fx( exc, xn, h, t_min, t_max, corr, L_subfr ); + + /*-----------------------------------------------------------------* + * Find integer pitch + *-----------------------------------------------------------------*/ + + max_val = corr[t0_min]; + move16(); + t0 = t0_min; + move16(); + + FOR (i = add(t0_min, 1); i <= t0_max; i++) + { + if (corr[i] >= max_val) + { + t0 = i; + move16(); + } + max_val = s_max(corr[i], max_val); + } + + IF( EQ_16(t0_fr1,pit_min)) + { + /* don't search fraction (for 7b/4b quant) */ + test(); + IF((i_subfr == 0) && (GE_16(t0,t0_fr2))) + { + i = shl(shr(t0,1),1); /* 2 samples resolution */ + if (GT_16(add(i,2),PIT_MAX)) + { + i = sub(i,2); + } + IF (GT_16(corr[i],corr[i+2])) + { + t0 = i; + move16(); + } + ELSE + { + t0 = add(i,2); + } + } + *pit_frac = 0; + move16(); + + return(t0); + } + + test(); + IF( (i_subfr == 0) && (GE_16(t0,t0_fr1))) + { + *pit_frac = 0; + move16(); + + return(t0); + } + + /*------------------------------------------------------------------* + * Search fractionnal pitch with 1/4 subsample resolution. + * search the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + *-----------------------------------------------------------------*/ + + t1 = t0; + move16(); + step = 1; + move16(); /* 1/4 subsample resolution */ + fraction = 1; + move16(); + test(); + test(); + IF (((i_subfr == 0) && (GE_16(t0,t0_fr2)))||(EQ_16(t0_fr2,pit_min))) + { + step = 2; + move16(); /* 1/2 subsample resolution */ + fraction = 2; + move16(); + } + + IF (EQ_16(t0,t0_min)) /* Limit case */ + { + fraction = 0; + move16(); + cor_max = Interpol_4( &corr[t0], fraction); + } + ELSE + { + t0 = sub(t0, 1); + cor_max = Interpol_4( &corr[t0], fraction); + FOR(i = add(fraction, step); i <= 3; i = (Word16) (i + step)) + { + temp = Interpol_4( &corr[t0], i); + IF (GT_16(temp,cor_max)) + { + cor_max = temp; + move16(); + fraction = i; + move16(); + } + } + } + + FOR (i = 0; i <= 3; i = (Word16) (i + step)) + { + temp = Interpol_4( &corr[t1], i); + IF (GT_16(temp,cor_max)) + { + cor_max = temp; + move16(); + fraction = i; + move16(); + t0 = t1; + move16(); + } + } + + *pit_frac = fraction; + move16(); + + return (t0); + +} + +/*-------------------------------------------------------------------* + * norm_corr() + * + * 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) + *---------------------------------------------------------------------*/ + +void norm_corr_fx( + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t_min, /* i : minimum value of searched range */ + const Word16 t_max, /* i : maximum value of searched range */ + Word16 ncorr[], /* o : normalized correlation Q15 */ + const Word16 L_subfr /* i : subframe size */ +) +{ + Word16 i, k, t; + Word16 corr, exp_corr, norm, exp_norm, exp, scale; + Word16 excf[L_FRAME16k]; + Word32 L_tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + k = negate(t_min); + + /*-----------------------------------------------------------------* + * compute the filtered excitation for the first delay t_min + *-----------------------------------------------------------------*/ + + conv_fx( &exc[k], h, excf, L_subfr ); + + /* Compute rounded down 1/sqrt(energy of xn[]) */ +#ifdef BASOP_NOGLOB + L_tmp = L_mac_o(1, xn[0], xn[0], &Overflow); +#else + L_tmp = L_mac(1, xn[0], xn[0]); +#endif + FOR (i = 1; i < L_subfr; i++) + { +#ifdef BASOP_NOGLOB + L_tmp = L_mac_o(L_tmp, xn[i], xn[i], &Overflow); +#else /* BASOP_NOGLOB */ + L_tmp = L_mac(L_tmp, xn[i], xn[i]); +#endif + } + exp = norm_l(L_tmp); + exp = sub(30, exp); + + exp = add(exp, 2); /* energy of xn[] x 2 + rounded up */ + scale = negate(shr(exp, 1)); /* (1< 0; i--) + { + /* saturation can occur in add() */ + /*excf[i] = add(mult(exc[k], h[i]), excf[i - 1]); move16(); */ + excf[i] = round_fx(L_mac(L_mult(excf[i - 1], 32767), exc[k], h[i])); + } + excf[0] = mult_r(exc[k], h[0]); + move16(); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * pit_Q_enc() + * + * Encode subframe pitch lag + *-------------------------------------------------------------------*/ + +void pit_Q_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max_val */ +) +{ + Word16 pitch_index; + + IF( EQ_16(nBits,10)) /* absolute encoding with 10 bits */ + { + IF( limit_flag == 0 ) + { + /* pitch_index = T0*4 + T0_frac - (PIT_MIN*4);*/ + pitch_index = sub(add(shl(T0 , 2), T0_frac), (PIT_MIN*4)); + } + ELSE IF( EQ_16(limit_flag,1)) + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_EXTEND*4);*/ + pitch_index = sub(add(shl(T0 , 2),T0_frac),(PIT_MIN_EXTEND*4)); + } + ELSE /* limit_flag == 2 */ + { + /*pitch_index = T0*4 + T0_frac - (PIT_MIN_DOUBLEEXTEND*4);*/ + pitch_index = sub(add(shl(T0 , 2) ,T0_frac) , (PIT_MIN_DOUBLEEXTEND*4)); + } + } + ELSE IF( EQ_16(nBits,9)) /* absolute encoding with 9 bits */ + { + pitch_index = abs_pit_enc_fx( 4, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16(nBits,8)) /* absolute encoding with 8 bits */ + { + pitch_index = abs_pit_enc_fx( 2, limit_flag, T0, T0_frac ); + + /* find T0_min and T0_max for delta search */ + IF( Opt_AMR_WB ) + { + limit_T0_fx( L_FRAME, delta, pit_flag, 0, T0, 0, T0_min, T0_max ); /* T0_frac==0 to keep IO with AMR-WB */ + } + } + ELSE IF( EQ_16(nBits,6)) /* relative encoding with 6 bits */ + { + pitch_index = delta_pit_enc_fx( 4, T0, T0_frac, *T0_min ); + } + ELSE IF( EQ_16(nBits,5)) /* relative encoding with 5 bits */ + { + IF( EQ_16(delta,8)) + { + pitch_index = delta_pit_enc_fx( 2, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + pitch_index = delta_pit_enc_fx( 4, T0, T0_frac, *T0_min ); + } + } + ELSE /* nBits == 4 ) */ /* relative encoding with 4 bits */ + { + IF( EQ_16(delta,8)) + { + pitch_index = delta_pit_enc_fx( 0, T0, T0_frac, *T0_min ); + } + ELSE /* delta == 4 */ + { + pitch_index = delta_pit_enc_fx( 2, T0, T0_frac, *T0_min ); + } + } + + IF( !Opt_AMR_WB ) + { + /* find T0_min and T0_max for delta search */ + limit_T0_fx( L_FRAME, delta, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + } + + { + push_indice_fx(hBstr, IND_PITCH, pitch_index, nBits ); + } + + return; +} + +/*-------------------------------------------------------------------* + * pit16k_Q_enc() + * + * Encode subframe pitch lag @16kHz core + *-------------------------------------------------------------------*/ + +void pit16k_Q_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max_val */ +) +{ + Word16 pitch_index; + + IF( EQ_16(nBits,10)) /* absolute encoding with 10 bits */ + { + { + IF( LT_16(T0,PIT16k_FR2_EXTEND_10b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT16k_MIN_EXTEND*4);*/ + pitch_index = add(shl(T0 , 2) , sub(T0_frac , (PIT16k_MIN_EXTEND*4))); + } + ELSE + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT16k_FR2_EXTEND_10b*2) + ((PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT16k_FR2_EXTEND_10b*2)),((PIT16k_FR2_EXTEND_10b-PIT16k_MIN_EXTEND)*4)); + } + } + + push_indice_fx(hBstr, IND_PITCH, pitch_index, nBits ); + } + ELSE IF( EQ_16(nBits,9)) /* absolute encoding with 9 bits */ + { + { + /*-------------------------------------------------------------------* + * The pitch range is encoded absolutely with 9 bits + * and is divided as follows: + * PIT16k_EXTEND_MIN to PIT16k_FR2_EXTEND_9b-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT16k_FR2_EXTEND_9b to PIT16k_FR1_EXTEND_9b-1 resolution 1/2 (frac = 0 or 2) + * PIT16k_FR1_EXTEND_9b to PIT16k_MAX_EXTEND resolution 1 (frac = 0) + *-------------------------------------------------------------------*/ + + IF( LT_16(T0,PIT16k_FR2_EXTEND_9b)) + { + /*pitch_index = T0*4 + T0_frac - (PIT16k_MIN_EXTEND*4);*/ + pitch_index = add(shl(T0 , 2) , sub(T0_frac , (PIT16k_MIN_EXTEND*4))); + } + ELSE IF( LT_16(T0,PIT16k_FR1_EXTEND_9b)) + { + /*pitch_index = T0*2 + (T0_frac>>1) - (PIT16k_FR2_EXTEND_9b*2) + ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4);*/ + pitch_index = add(sub(add(shl(T0,1),shr(T0_frac,1)),(PIT16k_FR2_EXTEND_9b*2)),((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4)); + } + ELSE + { + /*pitch_index = T0 - PIT16k_FR1_EXTEND_9b + ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4) + ((PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2);*/ + pitch_index = add(add(sub(T0, PIT16k_FR1_EXTEND_9b) , ((PIT16k_FR2_EXTEND_9b-PIT16k_MIN_EXTEND)*4)), ((PIT16k_FR1_EXTEND_9b-PIT16k_FR2_EXTEND_9b)*2)); + } + } + + push_indice_fx(hBstr, IND_PITCH, pitch_index, 9 ); + } + ELSE /* nBits == 6 */ /* relative encoding with 6 bits */ + { + /*pitch_index = (T0 - *T0_min) * 4 + T0_frac;*/ + pitch_index = add(shl(sub(T0,*T0_min),2),T0_frac); + + push_indice_fx(hBstr, IND_PITCH, pitch_index, nBits ); + } + + limit_T0_fx( L_FRAME16k, 8, L_SUBFR, limit_flag, T0, T0_frac, T0_min, T0_max ); + + return; +} + + +/*------------------------------------------------------------------* + * pit_encode: + * + * Close-loop pitch lag search and pitch lag quantization + * Adaptive excitation construction + *------------------------------------------------------------------*/ +void Mode2_pit_encode_fx( + const Word16 coder_type, /* i : coding model */ + const Word16 i_subfr, /* i : subframe index */ + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 *T_op, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_min_frac, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0_max_frac, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + Word16 *T0_res, /* i/o: close loop pitch resolution */ + Word16 *h1, /* i : weighted filter impulse response 1Q14+shift*/ + Word16 *xn, /* i : target vector */ + Word16 pit_min, + Word16 pit_fr1, + Word16 pit_fr1b, + Word16 pit_fr2, + Word16 pit_max, + Word16 pit_res_max +) +{ + Word16 pit_flag; + + BASOP_SATURATE_ERROR_ON_EVS; + + /* Pitch flag */ + pit_flag = i_subfr; + move16(); + if ( EQ_16(i_subfr,(2*L_SUBFR))) + { + pit_flag = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * - Limit range of pitch search + * - Fractional pitch search + * - Pitch quantization + *-----------------------------------------------------------------*/ + IF(coder_type == 0) /*Unvoiced Coding do nothing*/ + { + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + *T0_res = 1; + move16(); + + } + ELSE IF(EQ_16(coder_type,1)) /* 8/4/4/4 (EVS) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 4, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 4, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search_fx(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_min, pit_fr1b, L_SUBFR); + move16(); + + IF (i_subfr == 0) + { + Mode2_abs_pit_enc_fx( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc_fx( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + + } + ELSE IF(EQ_16(coder_type,2)) /* 8/5/8/5 (EVS) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 5, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE IF(i_subfr == 2*L_SUBFR) + { + limit_T0_voiced( 5, shr(pit_res_max,1), T_op[1], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 5, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search_fx(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + pit_flag, pit_min, pit_min, pit_fr1b, L_SUBFR); + move16(); + + IF (pit_flag == 0) + { + Mode2_abs_pit_enc_fx( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc_fx( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(EQ_16(coder_type,3)) /* 9/6/6/6 (HRs- VC) */ + { + Word16 pit_res_max2 = pit_res_max; + + if ( EQ_16(pit_min,PIT_MIN_16k)) + { + pit_res_max2 = shr(pit_res_max, 1); + } + + IF ( (i_subfr == 0) ) + { + limit_T0_voiced2( pit_res_max2, T_op, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max, i_subfr ); + } + ELSE + { + limit_T0_voiced( 6, pit_res_max2, *T0, 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max); + } + *T0 = E_GAIN_closed_loop_search_fx(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, pit_res_max2, T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_fr2, pit_fr1, L_SUBFR); + move16(); + + IF (i_subfr == 0) /* if 1st subframe */ + { + Mode2_abs_pit_enc_fx( *T0, *T0_frac, pt_indice, pit_min, pit_fr1, pit_fr2, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc_fx( *T0, *T0_frac, pit_res_max2, *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(coder_type == 4) /* 9/6/9/6 (AMRWB) */ + { + Word16 pit_res_max2 = pit_res_max; + if ( EQ_16(pit_min,PIT_MIN_16k)) + { + pit_res_max2 = shr(pit_res_max,1); + } + test(); + IF ( (i_subfr == 0) || EQ_16(i_subfr,shl(L_SUBFR,1))) + { + limit_T0_voiced2( pit_res_max2, T_op, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max, i_subfr ); + } + ELSE + { + limit_T0_voiced( 6, pit_res_max2, *T0, 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max); + } + *T0 = E_GAIN_closed_loop_search_fx(exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, pit_res_max2, T0_frac, T0_res, pit_res_max, + pit_flag, pit_min, pit_fr2, pit_fr1, L_SUBFR); + IF (pit_flag == 0) /* if 1st/3rd/5th subframe */ + { + Mode2_abs_pit_enc_fx( *T0, *T0_frac, pt_indice, pit_min, pit_fr1, pit_fr2, pit_res_max ); + } + ELSE /* if subframe 2 or 4 */ + { + Mode2_delta_pit_enc_fx( *T0, *T0_frac, pit_res_max2, *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(EQ_16(coder_type,8)) /* 8/5/5/5 (RF all pred mode) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 5, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 5, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search_fx( exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_min, pit_fr1b, L_SUBFR ); + + IF (i_subfr == 0) + { + Mode2_abs_pit_enc_fx( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc_fx( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + } + ELSE IF(EQ_16(coder_type,9)) /* 8/0/8/0 (RF mode Gen pred) */ + { + IF (i_subfr == 0) + { + limit_T0_voiced( 4, shr(pit_res_max,1), T_op[0], 0, 1, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + ELSE + { + limit_T0_voiced( 4, shr(pit_res_max,1), *T0, *T0_frac, *T0_res, T0_min, T0_min_frac, T0_max, T0_max_frac, pit_min, pit_max ); + } + *T0 = E_GAIN_closed_loop_search_fx( exc, xn, h1, *T0_min, *T0_min_frac, *T0_max, *T0_max_frac, shr(pit_res_max,1), T0_frac, T0_res, pit_res_max, + i_subfr, pit_min, pit_min, pit_fr1b, L_SUBFR ); + + IF (i_subfr == 0) + { + Mode2_abs_pit_enc_fx( *T0, *T0_frac, pt_indice, pit_min, pit_fr1b, pit_min, pit_res_max ); + } + ELSE + { + Mode2_delta_pit_enc_fx( *T0, *T0_frac, shr(pit_res_max,1), *T0_min, *T0_min_frac, pt_indice ); + } + } + + BASOP_SATURATE_ERROR_OFF_EVS; + + return; +} + +static void limit_T0_voiced2( + Word16 res, + const Word16 *T_op, + Word16 *T0_min, + Word16 *T0_min_frac, + Word16 *T0_max, + Word16 *T0_max_frac, + Word16 pit_min, + Word16 pit_max, + Word16 i_subfr +) +{ + Word16 t, temp1, temp2, res2; + + assert(res > 1 && res<=6); + + res2 = res; + move16(); + if(EQ_16(res,6)) + { + res2 =shr(res2,1); + } + + /* Lower-bound */ + IF (i_subfr == 0) + { + temp1 = sub(i_mult2(T_op[0],res),32); + } + ELSE + { + temp1 = sub(i_mult2(T_op[1],res),32); + } + + IF (LT_16(T_op[0],T_op[1])) + { + t = sub(i_mult2(T_op[0],res),16); + } + ELSE + { + t = sub(i_mult2(T_op[1],res),16); + } + + if (LT_16(temp1,t)) + { + temp1 = t; + } + + temp2 = mult(temp1,inv_T0_res[res2]); + if(EQ_16(res,6)) + { + temp2 = shr(temp2,1); + } + + *T0_min = temp2; + move16(); + + *T0_min_frac = sub(temp1,i_mult2(temp2,res)); + move16(); + + IF ( LT_16(*T0_min,pit_min)) + { + *T0_min = pit_min; + move16(); + *T0_min_frac = 0; + move16(); + } + + /* Higher-bound */ + temp1 = add(i_mult2(*T0_min,res),add(*T0_min_frac,63)); + + IF (T_op[0] +#include "options.h" /* Compilation switches */ +#include "cnst.h" /* Common constants */ +#include "rom_enc.h" /* Encoder static table prototypes */ +#include "rom_com_fx.h" /* Encoder static table prototypes */ +#include "rom_com.h" /* Encoder static table prototypes */ +#include "rom_dec.h" +//#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 MAX_DELTA 16 /* half-length of the delta search */ +#define COR_BUF_LEN (L_INTERPOL1*2 + MAX_DELTA*2 + 1) + +/*-------------------------------------------------------------------* + * pitch_ol2() + * + * Open-loop pitch precision improvement with 1/4 resolution + * The pitch is searched in the interval +#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 */ + +/*-----------------------------------------------------------------* + * Local Constants + *-----------------------------------------------------------------*/ +#define PIT_MIN2 20 /* pit_min for pitch tracking */ +#define PIT_MIN_1 44 /* for second pitch track */ +#define PIT_MIN2_1 24 + +#define THR_relE -2816 /* -11 (Q8) */ + +#define THRES0 4792 /* Threshold to favor smaller pitch lags; 1.17 (Q12) */ +#define DELTA0 2 /* multiples' search range initial */ +#define STEP 1 /* multiples' search range increment */ + +#define THRES1 13107 /* Threshold to favor pitch lags coherence for neighbours; 0.4 (Q15) */ +#define DELTA_COH 14 /* Maximum pitch lags difference for neighbours to be considered as coherent */ +#define THRES3 22938 /* Threshold to favor pitch lags coherence with previous frames; 0.7 (Q15) */ + +#define CORR_TH0 13107 /* Noise threshold for past frame correlations; 0.4 (Q15) */ +#define CORR_TH1 16384 /* Noise threshold for past frame correlations; 0.5 (Q15) */ + +#define LEN_X ((PIT_MAX/OPL_DECIM)-(PIT_MIN2/OPL_DECIM)+1) /* Correlation buffer length */ +#define COH_FAC 5734 /* Factor for measuring the pitch coherence; 1.4 (Q12) */ + +#define NSUBSECT 7 +#define NSECT 4 +#define NHFR 3 +#define L_FIR_PO 5 +#define L_MEM (L_FIR_PO-2) + + +/*-----------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------*/ +static void LP_Decim2_Copy(const Word16 x[], Word16 y[], Word16 l, Word16 mem[] ); + +static void pitch_neighbour_fx(Word16 sect0, Word16 pitch_tmp[],Word16 pitch[3][2*NSECT],Word16 corr_tmp[],Word16 corr[3][2*NSECT],Word16 thres1[2*NHFR],Word16 ind_tmp[2*NHFR]); + +static void find_mult_fx(Word16 *fac,Word16 pitch0,Word16 pitch1,Word16 pit_max0,Word16 *corr,Word16 *old_pitch,Word16 *old_corr,Word16 delta,Word16 step); + +static Word16 pitch_coherence_fx(Word16 pitch0,Word16 pitch1,Word16 fac_max,Word16 diff_max); + +static Word32 Dot_product12_OL(Word16 *sum1,const Word16 x[],const Word16 y[],const Word16 lg,const Word16 lg2,Word16 *exp,Word16 *exp2); + +static Word32 Dot_product12_OL_back(Word16 *sum1,const Word16 x[],const Word16 y[],const Word16 lg,const Word16 lg2,Word16 *exp,Word16 *exp2); + + +/*-----------------------------------------------------------------* + * pitch_ol_init() + * + * Open loop pitch variable initialization + *-----------------------------------------------------------------*/ +void pitch_ol_init_fx( + Word16 *old_thres, /* o : threshold for reinforcement of past pitch influence */ + Word16 *old_pitch, /* o : pitch of the 2nd half-frame of previous frame */ + Word16 *delta_pit, /* o : pitch evolution extrapolation */ + Word16 *old_corr /* o : correlation */ +) +{ + *old_thres = 0; + move16(); + *old_pitch = 0; + move16(); + *delta_pit = 0; + move16(); + *old_corr = 0; + move16(); +} + + +/*==================================================================================*/ +/* FUNCTION : pitch_ol_fx() */ +/*----------------------------------------------------------------------------------*/ +/* PURPOSE : + * Compute the open loop pitch lag. + * + * The pitch lag search is divided into two sets. + * Each set is divided into three sections. + * Each section cannot have a pitch multiple. + * We find a maximum for each section. + * We compare the maxima of each section. + * + * 1st set 2nd set + * 1st section: lag delay = 115 down to 62 and 115 down to 78 + * 2nd section: lag delay = 61 down to 32 and 77 down to 41 + * 3rd section: lag delay = 31 down to 17 and 40 down to 22 + * 4th section: lag delay = 16 down to 10 and 21 down to 12 + * + * As there is a margin between section overlaps, especially for + * longer delays, this section selection is more robust for not + * to find multiples in the same section when pitch evolves rapidly. + * + * For each section, the length of the vectors to correlate is + * greater/equal to the longest pitch delay. */ +/*----------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ +/* _ (Word16[]) old_corr_fx : correlation Q15 */ +/* _ (Word16[]) corr_shift_fx : normalized correlation correction Q15 */ +/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ +/* to past frame pitch Q15 */ +/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ +/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ +/* _ (Word16[]) wsp_fx : weighted speech for current frame & look-ahead qwsp */ +/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ +/* _ (Word16[]) relE_fx : relative frame energy Q8 */ +/* _ (Word16[]) L_look : look-ahead Q0 */ +/* _ (Word16[]) Opt_SC_VBR : SC-VBR flag Q0 */ +/* _ (Word16*) qwsp : wsp & filter memory Qformat */ +/*----------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16[]) pitch : open loop pitch lag for each half-frame Q0 */ +/* _ (Word16[]) T_op : open loop pitch lag for each half-frm for quant Q0 */ +/* _ (Word16[]) voicing_fx : max normalized correlation for each half-frame QIn */ +/* _ (Word16[]) old_pitch : OL pitch of the 2nd half-frame of the last frame Q0 */ +/* _ (Word16[]) old_corr_fx : correlation Q15 */ +/* _ (Word16[]) old_thres_fx : maximum correlation weighting with respect */ +/* to past frame pitch Q15 */ +/* _ (Word16[]) delta_pit : old pitch extrapolation correction Q0 */ +/* _ (Word16[]) st_old_wsp2_fx: weighted speech memory qwsp */ +/* _ (Word16[]) mem_decim2_fx : wsp decimation filter memory qwsp */ +/*----------------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*==================================================================================*/ + +void pitch_ol_fx( + Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ + Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ + Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ + Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ + Word16 corr_shift, /* i : normalized correlation correction Q15 */ + Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q15 */ + Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ + Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ + const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ + Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 last_class,/* i : frame classification of last frame */ + const Word16 bwidth, /* i : bandwidth */ + const Word16 Opt_SC_VBR /* i : SC-VBR flag */ +) +{ + Word16 ftmp, old_wsp2[(L_WSP-L_INTERPOL)/OPL_DECIM], *wsp2; + Word16 tmp_mem[3]; + + Word16 scale1[2*DELTA_COH-1]; + Word16 scaled_buf[2*LEN_X + 3*(DELTA_COH-1)]; + Word16 scaled_buf_exp[2*LEN_X + 3*(DELTA_COH-1)], exp_sect[8], exp_sect1[8], exp_sect0; + Word16 cor_buf[2*LEN_X]; + Word16 *pt_exp1, *pt_exp2, *pt_exp3, *pt_exp4; + Word16 *pt1, *pt2, *pt3, *pt4, *pt5, *pt6; + Word16 *pt_cor0, *pt_cor1, *pt_cor2, *pt_cor3, *pt_cor4, *pt_cor5, *pt_cor6; + Word16 thres1[6]; + Word16 diff, cnt, ind, ind1, offset, offset1, offset_la, offset_la1, coh_flag, coh_flag1; + Word16 ind_corX, ind1_corX; + + Word16 i, j, k, m, pit_min, pit_min1, sect0, subsect0, add_sect0, sub_sect0, old_tmp, old_tmp1, len_x, len_x1; + Word16 len_temp; + Word16 pitchX[NHFR][2*NSECT], pitch_tmp[2*NHFR], ind_tmp[2*NHFR], tmp_buf[NHFR+1]; + + Word16 enr0[NSECT], enr0_exp[NSECT], enr0_1[NSECT], enr0_1_exp[NSECT], enr1, enr1_exp, enr2_exp; + Word32 enr, enr2, Ltmp; + Word16 fac, tmp16, tmp16_2; + Word16 qCorX, qScaledX; + Word16 scaledX[NHFR][2*NSECT], corX[NHFR][2*NSECT], cor_tmp[2*NHFR], cor_mean; + const Word16 *len, *len1, *sublen, *sublen1, *pit_max, *sec_length, *sec_length1; + + Word16 pit_min_coding; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*--------------------------------------------------------------* + * Initialization + *--------------------------------------------------------------*/ + len = len_12k8; + len1 = len1_12k8; + sublen = sublen_12k8; + sublen1 = sublen1_12k8; + pit_max = pit_max_12k8; + sec_length = sec_length_12k8; + sec_length1 = sec_length1_12k8; + + test(); + if ((LT_16(last_class,VOICED_TRANSITION))&&(NE_16(bwidth,NB))) + { + /*reset last pitch reinforcement in case of unvoiced or transitions: it avoids some pitch doublings*/ + *old_thres = 0; + move16(); + } + + pit_min_coding = PIT_MIN_EXTEND; + move16(); + test(); + test(); + test(); + test(); + IF ( ( (NE_16(bwidth,NB))&&(GT_16(*old_pitch,PIT_MIN)))|| + ( (EQ_16(bwidth,NB) ) && ( (GT_16(*old_pitch,PIT_MIN2_1) ) || (LT_16(*old_thres,3277) ) ) ) ) /* 0.1 inQ15*/ + { + pit_min = PIT_MIN/OPL_DECIM; + move16(); + pit_min1= PIT_MIN_1/OPL_DECIM; + move16(); + subsect0 = 2; + move16(); + sect0 = 1; + move16(); + } + ELSE + { + pit_min = PIT_MIN2/OPL_DECIM; + move16(); + pit_min1= PIT_MIN2_1/OPL_DECIM; + move16(); + subsect0 = 0; + move16(); + sect0 = 0; + move16(); + } + + len_x = (PIT_MAX/OPL_DECIM - pit_min + 1); + move16(); + len_x1= (PIT_MAX/OPL_DECIM - pit_min1 + 1); + move16(); + + /*--------------------------------------------------------------* + * Find decimated weighted speech + * Update wsp buffer with the memory + * decimation of wsp[] to search pitch in LF and to reduce complexity + * Extend the decimation of wsp to the end of the speech buffer + * Update wsp memory + *--------------------------------------------------------------*/ + Copy(st_old_wsp2, old_wsp2, (L_WSP_MEM-L_INTERPOL)/OPL_DECIM); + wsp2 = old_wsp2 + ((L_WSP_MEM-L_INTERPOL)/OPL_DECIM); + + LP_Decim2_Copy(wsp, wsp2, L_FRAME, mem_decim2); + + /* Avoid uninitialized memory access */ + set16_fx(wsp2 + L_FRAME/2, 0, sizeof(old_wsp2)/sizeof(Word16)-((L_WSP_MEM-L_INTERPOL)/OPL_DECIM)-L_FRAME/2); + tmp_mem[0] = mem_decim2[0]; + move16(); + tmp_mem[1] = mem_decim2[1]; + move16(); + tmp_mem[2] = mem_decim2[2]; + move16(); + + LP_Decim2_Copy(&wsp[L_FRAME], &wsp2[shr(L_FRAME,1)], L_LOOK_12k8, tmp_mem); /* shr() used instead of division by OPL_DECIM*/ + + Copy(&old_wsp2[shr(L_FRAME,1)], st_old_wsp2, (L_WSP_MEM-L_INTERPOL)/OPL_DECIM); + + /*-----------------------------------------------------------------* + * Attenuate the correlation correction factor due to noise. + * Reset correlation buffer outside the useful range. + * Find the scaling functions for immediate neigbours and + * further ones. + *-----------------------------------------------------------------*/ + + corr_shift = shr(corr_shift, 1); + + set16_fx( scaled_buf, 0, DELTA_COH-1 ); + set16_fx( scaled_buf + (DELTA_COH-1) + len_x, 0, DELTA_COH-1 ); + set16_fx( scaled_buf + 2*(DELTA_COH-1) + len_x + len_x1, 0, DELTA_COH-1 ); + set16_fx( scaled_buf_exp, 0, len_x + len_x1 + 3*(DELTA_COH-1)); + + pt1 = scale1 + DELTA_COH-1; + pt2 = pt1; + tmp16 = mult(negate(*old_thres), MAX_16/DELTA_COH); + k = *old_thres; + move16(); + FOR (i=0; i < DELTA_COH; i++) + { + /* + * *pt1 = ( -(*old_thres)/DELTA_COH * i + *old_thres+1.0f ); + * To keep Q15 values, the following code does not add 1 to the result. + * A scaling factor must be applied accordingly (see next use of scale1) + */ + *pt1 = k; + move16(); + k = add(k, tmp16); + *pt2-- = *pt1++; + move16(); + } + + /*-----------------------------------------------------------------------------* + * Estimate the new pitch by extrapolating the old pitch value for 2 half-frames + *-----------------------------------------------------------------------------*/ + old_tmp = add(*old_pitch, *delta_pit); + old_tmp = s_min(old_tmp, PIT_MAX/OPL_DECIM); + old_tmp = s_max(old_tmp, pit_min); + old_tmp1 = add(old_tmp, *delta_pit); + old_tmp1 = s_min(old_tmp1, PIT_MAX/OPL_DECIM); + old_tmp1 = s_max(old_tmp1, pit_min); + + /*-----------------------------------------------------------------* + * Loop for all three half-frames (current frame + look-ahead) + *-----------------------------------------------------------------*/ + pt_cor0 = scaled_buf + DELTA_COH-1; + + pt_cor2 = pt_cor0 - pit_min + old_tmp; + pt_cor4 = pt_cor0 - pit_min1 + old_tmp + (DELTA_COH-1) + len_x; + + FOR( i=0; i Q12 */ + pt2 = pt1 - pit_min; /* *pt2 -> Q12 */ + pt4 = pt1 - pit_min1; /* *pt4 -> Q12 */ + + enr = L_deposit_l(1); + + pt_cor1 = pt_cor0; + pt_cor3 = pt_cor0 + (DELTA_COH-1) + len_x; + + pt_exp1 = scaled_buf_exp + DELTA_COH-1; + pt_exp2 = pt_exp1; + pt_exp3 = scaled_buf_exp + 2*(DELTA_COH-1) + len_x; + pt_exp4 = pt_exp3; + + IF( LT_16(i,NHFR-1)) /* First two half-frames (current frame) */ + { + pt3 = pt1; + pt5 = pt1; + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /*-----------------------------------------------------------------* + * Find fixed vector energy + *-----------------------------------------------------------------*/ + + /* 1st set */ + k = (Word16)(pt1 - pt3); + move16(); + + FOR (k = add(k, len[j]); k > 0; k--) + { + enr = L_mac0(enr, *pt3, *pt3); + pt3++; + } + /* keep Q15 normalized result */ + cnt = norm_l(enr); + enr0[j] = extract_h(L_shl(enr, cnt)); + enr0_exp[j] = sub(30, cnt); + move16(); + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + enr2 = enr; /* sets to 'enr' in 1 clock */ + move32(); + + /* 2nd set */ + k = (Word16)(pt1 - pt5); + move16(); + + FOR (k = add(k, len1[j]); k > 0; k--) + { + enr2 = L_mac0(enr2, *pt5, *pt5); + pt5++; + } + cnt = norm_l(enr2); + enr0_1[j] = extract_h(L_shl(enr2, cnt)); + enr0_1_exp[j] = sub(30, cnt); + move16(); + } + + /*----------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *----------------------------------------------------------*/ + exp_sect[subsect0] = 0; + move16(); + pt_cor5 = pt_cor1; + pt_cor6 = pt_cor3; + + tmp16 = exp_sect[subsect0]; + move16(); + + k = (Word16)(pt2 - pt1 + pit_max[subsect0]); + + IF (k >= 0) + { + len_temp = sublen[0]; + move16(); + + FOR (; k >= 0; k--) + { + /* Keep Q15 normalized result */ + /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ + /* Update exponent to reflect shr by 1 */ + *pt_cor1 = extract_h(L_shr(Dot_product12(pt1, pt2--, len_temp, pt_exp1), 1)); + + /* save the biggest exponent */ + tmp16 = s_max(tmp16, *pt_exp1); + + pt_cor1++; + pt_exp1++; + } + } + exp_sect[subsect0] = tmp16; + move16(); + + /*----------------------------------------------------------* + * For each subsection, find the correlation + *----------------------------------------------------------*/ + FOR (j = subsect0; j < NSUBSECT; j++) + { + len_temp = sublen[j]; + move16(); + + k = (Word16)(pt2 - pt1); + move16(); + k = add(k,pit_max[j+1]); + exp_sect[j+1] = 0; + move16(); + exp_sect1[j] = 0; + move16(); + + IF (k >= 0) + { + ind = exp_sect[j+1]; + move16(); + ind1 = exp_sect1[j]; + move16(); + + FOR (; k >= 0; k--) + { + /* Keep Q15 normalized result */ + /* shr by 1 to make room for scaling in the neighbourhood of the extrapolated pitch */ + /* Update exponent to reflect shr by 1 (done in Dot_product12_OL() for pt_cor3/pt_exp3) */ + *pt_cor1 = extract_h(L_shr(Dot_product12_OL(pt_cor3, pt1, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3), 1)); + /* The line above replaces: + * *pt_cor1 = shr(extract_h(Dot_product12(pt1, pt2, Sublen[j], pt_exp1)),1); move16(); + * *pt_cor3 = shr(extract_h(Dot_product12(pt1, pt2--, Sublen1[j+i*7], pt_exp3)),1); move16(); + */ + + /* save the biggest exponent */ + ind = s_max(ind, *pt_exp1); + ind1 = s_max(ind1, *pt_exp3); + + pt_cor1++; + pt_exp1++; + pt_cor3++; + pt_exp3++; + } + exp_sect[j+1] = ind; + move16(); + exp_sect1[j] = ind1; + move16(); + } /* IF (k >= 0) */ + } /* FOR (j = subsect0; ... */ + } + ELSE /* 3rd half-frame (look-ahead) */ + { + pt6 = pt1 + L_LOOK_12k8/OPL_DECIM - 1; + pt3 = pt6; + pt5 = pt6; + + /*-----------------------------------------------------------------* + * For each section in both sets, find fixed vector energy + *-----------------------------------------------------------------*/ + + FOR( j = sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + k = (Word16)(pt3 - pt6); + move16(); + + FOR (k = add(k, len[j]); k > 0; k--) + { + enr = L_mac0(enr, *pt3, *pt3); + pt3--; + } + + cnt = norm_l(enr); + enr0[j] = extract_h(L_shl(enr, cnt)); /*qwsp+cnt-16*/ + enr0_exp[j] = sub(30, cnt); + move16(); + + /* Reduce complexity (length of 'enr2' section is equal or larger than 'enr') */ + pt5 = pt3; + enr2 = enr; + move16(); + + /* 2nd set */ + k = (Word16)(pt5 - pt6); + move16(); + + FOR (k = add(k, len1[j]); k > 0; k--) + { + enr2 = L_mac0(enr2, *pt5, *pt5); + pt5--; + } + + cnt = norm_l(enr2); + enr0_1[j] = extract_h(L_shl(enr2, cnt)); /*qwsp+cnt-16*/ + enr0_1_exp[j] = sub(30, cnt); + move16(); + } + + /* Set pointers */ + IF( sect0 != 0 ) + { + pt2 = pt6 - add(pit_max[1],1); + k = sub(pit_max[2],pit_max[1]); + move16(); + } + ELSE + { + pt2 = pt6 - pit_min; + k = 2; + move16(); + } + + /*-----------------------------------------------------------------* + * Find correlation for the non-overlapping pitch lag values + *-----------------------------------------------------------------*/ + exp_sect[subsect0] = 0; + move16(); + pt_cor5 = pt_cor1; + pt_cor6 = pt_cor3; + + tmp16 = exp_sect[subsect0]; + move16(); + + IF (k > 0) + { + len_temp = sublen[0]; + move16(); + + FOR ( ; k > 0; k-- ) + { + /* Following lines are equivalent of Dot_product12() but with a backward incrementing */ + Ltmp = L_deposit_l(1); + FOR( m = 0; m < len_temp; m++ ) + { + Ltmp = L_mac(Ltmp, pt6[-m], pt2[-m]); + } + + /* Normalize acc in Q31 */ + tmp16_2 = norm_l(Ltmp); + Ltmp = L_shl(Ltmp, tmp16_2); + *pt_exp1 = sub(30, tmp16_2); + move16(); /* exponent = 0..30 */ + + /* Save result */ + *pt_cor1 = extract_h(L_shr(Ltmp,1)); + + /* Save the biggest exponent */ + tmp16 = s_max(tmp16, *pt_exp1); + + pt_cor1++; + pt_exp1++; + pt2--; + } + exp_sect[subsect0] = tmp16; + move16(); + } + + /*-----------------------------------------------------------------* + * For each subsection, find the correlation (overlapping pitch lag values) + *-----------------------------------------------------------------*/ + + FOR( j = subsect0; j < NSUBSECT; j++ ) + { + exp_sect[j+1] = 0; + move16(); + exp_sect1[j] = 0; + move16(); + + ind = exp_sect[j+1]; + move16(); + ind1 = exp_sect1[j]; + move16(); + + k = sub(pit_max[j+1], pit_max[j]); + + FOR( ; k > 0; k-- ) + { + *pt_cor1 = extract_h(L_shr(Dot_product12_OL_back(pt_cor3, pt6, pt2--, sublen[j], sublen1[j], pt_exp1, pt_exp3), 1)); + + /* Save the biggest exponent */ + ind = s_max(ind, *pt_exp1); + ind1 = s_max(ind1, *pt_exp3); + + pt_cor1++; + pt_exp1++; + pt_cor3++; + pt_exp3++; + } + exp_sect[j+1] = ind; + move16(); + exp_sect1[j] = ind1; + move16(); + } + } /* 3rd half-frame (look-ahead) */ + + /* Scale all values in each section to the same exponent for upcoming Find_max() */ + offset = 0; + move16(); + offset1 = 0; + move16(); + exp_sect1[7] = 0; /* padding */ move16(); + FOR (j = sect0; j < NSECT; j++) + { + exp_sect0 = s_max(exp_sect[j*2], exp_sect[j*2+1]); + + /* scaling of exp for track 1 */ + offset = add(offset, sec_length[j]); + k = (Word16)(pt_cor0 - pt_cor5); + move16(); + FOR (k = add(k, offset); k > 0; k--) + { + cnt = sub(exp_sect0, *pt_exp2); + tmp16 = s_min(15, cnt); + if (cnt > 0) + { + tmp16 = shr(*pt_cor5, tmp16); + } + if (cnt > 0) + { + *pt_cor5 = tmp16; + move16(); + } + *pt_exp2 = s_max(*pt_exp2, exp_sect0); + move16(); + pt_cor5++; + pt_exp2++; + } + + exp_sect0 = s_max(exp_sect1[j*2], exp_sect1[j*2+1]); + + /* scaling of exp for track 2 */ + offset1 = add(offset1, sec_length1[j]); + k = (Word16)(pt_cor0 - pt_cor6 + (DELTA_COH-1)); + move16(); + k = add(k, len_x); + FOR (k = add(k, offset1); k > 0; k--) + { + cnt = sub(exp_sect0, *pt_exp4); + tmp16 = s_min(15, cnt); + if (cnt > 0) + { + tmp16 = shr(*pt_cor6, tmp16); + } + if (cnt > 0) + { + *pt_cor6 = tmp16; + move16(); + } + *pt_exp4 = s_max(*pt_exp4, exp_sect0); + move16(); + pt_cor6++; + pt_exp4++; + } + } /* FOR (j = sect0; ... */ + + Copy( pt_cor0, cor_buf, len_x ); /* Save unscaled correlation vector */ + Copy( pt_cor0+(DELTA_COH-1)+len_x, cor_buf+len_x, len_x1 ) ; + + /*-----------------------------------------------------------------* + * Scale correlation function in the neighbourhood of + * the extrapolated pitch + *-----------------------------------------------------------------*/ + pt_cor1 = pt_cor2 - (DELTA_COH-1); + pt_cor3 = pt_cor4 - (DELTA_COH-1); + pt2 = scale1; + + FOR( k=0 ; k < 2*DELTA_COH-1 ; k++ ) + { + /* all Q15 here */ + *pt_cor1 = add(*pt_cor1, mult(*pt_cor1, *pt2)); + move16(); + *pt_cor3 = add(*pt_cor3, mult(*pt_cor3, *pt2++)); + move16(); + + pt_cor1++; + pt_cor3++; + } + + /* Update for next half-frame & look-ahead */ + pt_cor2 = pt_cor0 - pit_min + old_tmp1; + pt_cor4 = pt_cor0 - pit_min1 + old_tmp1 + (DELTA_COH-1) + len_x; + + /*-----------------------------------------------------------------* + * For each section, find maximum correlation and compute + * normalized correlation + *-----------------------------------------------------------------*/ + + pt_cor1 = pt_cor0; + pt_exp1 = scaled_buf_exp + DELTA_COH-1; + offset = 0; + move16(); + pt_cor3 = pt_cor0 + (DELTA_COH-1) + len_x; + pt_exp3 = scaled_buf_exp + 2*(DELTA_COH-1) + len_x; + offset1 = 0; + move16(); + + FOR( j=sect0; j < NSECT; j++ ) /* loop for each section */ + { + /* 1st set */ + offset_la = 0; + move16(); + if( EQ_16(i,2)) + { + offset_la = sub(L_LOOK_12k8/OPL_DECIM,len[j]); + } + + /* 2nd set */ + offset_la1 = 0; + move16(); + if( EQ_16(i,2)) + { + offset_la1 = sub(L_LOOK_12k8/OPL_DECIM,len1[j]); + } + + /* 1st set of candidates */ + ind = add(maximum_fx( pt_cor1, sec_length[j], &ftmp ), offset); + pitchX[i][j] = add(ind, pit_min); + move16(); + pt2 = pt1 - pitchX[i][j] +/*-*/ offset_la; /* selected moving vector */ + + enr1_exp = 0; + move16(); +#ifdef BASOP_NOGLOB + enr1 = add_o(extract_h(dotp_fx( pt2, pt2, len[j], &enr1_exp)), 1, &Overflow); +#else + enr1 = add(extract_h(dotp_fx( pt2, pt2, len[j], &enr1_exp)), 1); +#endif + + enr2 = L_mult(enr0[j], enr1); + enr2_exp = norm_l(enr2); + enr2 = L_shl(enr2, enr2_exp); + enr2_exp = sub(31,add(sub(28,add(enr0_exp[j],enr1_exp)),add(enr2_exp,1))); + + enr2 = Isqrt_lc(enr2, &enr2_exp); /* 1/sqrt(energy) */ /*31-enr2_exp*/ + enr1_exp = norm_l(enr2); + enr1 = extract_h(L_shl(enr2, enr1_exp)); /*31-enr2_exp+enr1_exp-16*/ + enr1_exp = sub(enr2_exp, enr1_exp); /*15-enr1_exp*/ + + Ltmp = L_mult0(cor_buf[ind], enr1); + qCorX = add(sub(15,enr1_exp), sub(14,pt_exp1[ind])); +#ifdef BASOP_NOGLOB + corX[i][j] = extract_h(L_shr_o(Ltmp, sub(qCorX,31), &Overflow)); +#else /* BASOP_NOGLOB */ + corX[i][j] = extract_h(L_shr(Ltmp, sub(qCorX,31))); +#endif /* BASOP_NOGLOB */ + qCorX = 31; + move16(); + + Ltmp = L_mult0(pt_cor0[ind], enr1); + qScaledX = add(sub(15,enr1_exp),sub(14,pt_exp1[ind])); + scaledX[i][j] = round_fx(L_shl(Ltmp, sub(16+12,qScaledX))); + qScaledX =12; + move16(); + + pt_cor1 += sec_length[j]; + move16(); + offset = add(offset,sec_length[j]); + + /* 2nd set of candidates */ + ind1 = add(maximum_fx( pt_cor3, sec_length1[j], &ftmp ), offset1); + pitchX[i][j+NSECT] = add(ind1, pit_min1); + move16(); + pt4 = pt1 - pitchX[i][j+NSECT] +/*-*/ offset_la1; + move16(); /* selected moving vector */ + enr1_exp = 0; + move16(); +#ifdef BASOP_NOGLOB + enr1 = add_o(extract_h(dotp_fx( pt4, pt4, len1[j], &enr1_exp)), 1, &Overflow); +#else + enr1 = add(extract_h(dotp_fx( pt4, pt4, len1[j], &enr1_exp)), 1); +#endif + + enr2 = L_mult(enr0_1[j], enr1); + enr2_exp = norm_l(enr2); + enr2 = L_shl(enr2, enr2_exp); + + enr2_exp = sub(31,add(sub(28,add(enr0_1_exp[j],enr1_exp)),add(enr2_exp,1))); + enr2 = Isqrt_lc(enr2, &enr2_exp); /* 1/sqrt(energy) */ /*31-enr2_exp*/ + enr1_exp = norm_l(enr2); + enr1 = extract_h(L_shl(enr2, enr1_exp)); /*31-enr2_exp+enr1_exp-16*/ + enr1_exp = sub(enr2_exp, enr1_exp); /*15-enr1_exp*/ + + Ltmp = L_mult0(cor_buf[ind1+len_x], enr1); + + qCorX = add(sub(15,enr1_exp),sub(14,pt_exp3[ind1])); +#ifdef BASOP_NOGLOB + corX[i][j+NSECT] = extract_h(L_shr_o(Ltmp, qCorX-31, &Overflow)); +#else /* BASOP_NOGLOB */ + corX[i][j+NSECT] = extract_h(L_shr(Ltmp, qCorX-31)); +#endif /* BASOP_NOGLOB */ + qCorX = 31; + move16(); + + Ltmp = L_mult0(pt_cor0[ind1+(DELTA_COH-1)+len_x], enr1); + qScaledX = add(sub(15,enr1_exp),sub(14,pt_exp3[ind1])); + scaledX[i][j+NSECT] = round_fx(L_shl(Ltmp, sub(16+12,qScaledX))); + /*scaledX[i][j+NSECT] = saturate(L_shr(Ltmp, qScaledX-12));*/ + qScaledX =12; + move16(); + + pt_cor3 += sec_length1[j]; + move16(); + offset1 = add(offset1, sec_length1[j]); + + } /* FOR j < NSECT */ + } /* FOR i < NHFR */ + + /*-----------------------------------------------------------------* + * Favor a smaller delay if it happens that it has its multiple + * in the longer-delay sections (harmonics check) + *-----------------------------------------------------------------*/ + + FOR( i=0; i < 2; i++ ) /* loop for the 2 half-frames */ + { + fac = THRES0; + move16(); + find_mult_fx(&fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx(&fac, pitchX[i][NSECT+2], pitchX[i][NSECT+3], pit_max[7], &scaledX[i][NSECT+2], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][NSECT+1], pitchX[i][NSECT+2], pit_max[6], &scaledX[i][NSECT+1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][NSECT+0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][NSECT+0], pitchX[i][NSECT+1], pit_max[4], &scaledX[i][NSECT+0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + } + + fac = THRES0; + move16(); /* the look-ahead */ + find_mult_fx(&fac, pitchX[i][2], pitchX[i][3], pit_max[7], &scaledX[i][2], old_pitch, old_corr, 2, 2); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][1], pitchX[i][2], pit_max[5], &scaledX[i][1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][0], pitchX[i][1], pit_max[3], &scaledX[i][0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ + } + fac = THRES0; + move16(); + find_mult_fx(&fac, pitchX[i][NSECT+2], pitchX[i][NSECT+3], pit_max[7], &scaledX[i][NSECT+2], old_pitch, old_corr, 2, 2); /* Multiples in 3rd section */ + find_mult_fx(&fac, pitchX[i][NSECT+1], pitchX[i][NSECT+2], pit_max[6], &scaledX[i][NSECT+1], old_pitch, old_corr, DELTA0, STEP); /* Multiples in 2nd section */ + test(); + IF((sect0==0) && GE_16(shl(pitchX[i][NSECT+0],1),pit_min_coding)) + { + find_mult_fx( &fac, pitchX[i][NSECT+0], pitchX[i][NSECT+1], pit_max[4], &scaledX[i][NSECT+0], old_pitch, old_corr, DELTA0, STEP ); /* Multiples in 2nd section */ /* Multiples in 2nd section */ + } + + /*-----------------------------------------------------------------* + * Do 1st estimate for pitch values + * Adjust the normalized correlation using estimated noise level + * Compute the maximum scaling for the neighbour correlation + * reinforcement + *-----------------------------------------------------------------*/ + add_sect0 = add(NSECT,sect0); + sub_sect0 = sub(NSECT,sect0); + FOR (i=0; i < NHFR; i++) + { + /* 1st set of pitch candidates */ + ind = add(maximum_fx(scaledX[i]+sect0, sub_sect0, &ftmp), sect0); + ind_tmp[i] = ind; + move16(); + pitch_tmp[i] = pitchX[i][ind]; + move16(); +#ifdef BASOP_NOGLOB + cor_tmp[i] = add_o(corX[i][ind], corr_shift, &Overflow); +#else /* BASOP_NOGLOB */ + cor_tmp[i] = add(corX[i][ind], corr_shift); +#endif /* BASOP_NOGLOB */ + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i] = mult(THRES1, cor_tmp[i]); + move16(); + + /* 2nd set of pitch candidates */ + ind1 = add(maximum_fx(scaledX[i]+add_sect0, sub_sect0, &ftmp), add_sect0); + ind_tmp[i+NHFR] = ind1; + move16(); + pitch_tmp[i+NHFR] = pitchX[i][ind1]; + move16(); +#ifdef BASOP_NOGLOB + cor_tmp[i+NHFR] = add_o(corX[i][ind1], corr_shift, &Overflow); +#else /* BASOP_NOGLOB */ + cor_tmp[i+NHFR] = add(corX[i][ind1], corr_shift); +#endif + move16(); + + /* Higher is the neighbour's correlation, higher is the weighting */ + /* operands are Q15, result is Q15 */ + thres1[i+NHFR] = mult(THRES1, cor_tmp[i+NHFR]); + move16(); + } + /*-----------------------------------------------------------------* + * Take into account previous and next pitch values of the present + * frame and look-ahead. Choose the pitch lags and normalize + * correlations for each half-frame & look-ahead + *-----------------------------------------------------------------*/ + + pitch_neighbour_fx(sect0, pitch_tmp, pitchX, cor_tmp, scaledX, thres1, ind_tmp); + FOR( i = 0; i < NHFR; i++ ) + { + ind = add(maximum_fx(scaledX[i]+sect0, sub_sect0, &ftmp), sect0); + ind_corX = add(maximum_fx(corX[i]+sect0, sub_sect0, &ftmp), sect0); + + ind1 = add(maximum_fx(scaledX[i]+add_sect0, sub_sect0, &ftmp), add_sect0); + ind1_corX = add(maximum_fx(corX[i]+add_sect0, sub_sect0, &ftmp), add_sect0); + + if ( GT_16(scaledX[i][ind1],scaledX[i][ind])) + { + ind = ind1; + move16(); + } + test(); + if ( Opt_SC_VBR && GT_16(corX[i][ind1_corX],corX[i][ind_corX])) + { + ind_corX = ind1_corX; + move16(); + } + test(); + test(); + test(); + IF (Opt_SC_VBR && (LT_16(mult(pitchX[i][ind], 13107 /*0.4 in Q15*/),pitchX[i][ind_corX]))&& + (GT_16(mult(pitchX[i][ind], 19661 /*0.6 in Q15*/),pitchX[i][ind_corX]) ) && + (GE_16(corX[i][ind_corX],29491/*0.9 in Q15*/))) + { + pitch[i] = pitchX[i][ind_corX]; + move16(); + voicing[i] = corX[i][ind_corX]; + move16(); + } + ELSE + { + pitch[i] = pitchX[i][ind]; + move16(); + voicing[i] = corX[i][ind]; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Increase the threshold for correlation reinforcement with + * the past if correlation high and pitch stable + *-----------------------------------------------------------------*/ + + /* all Q15 here */ + /* cor_mean = 0.5f * (voicing[0] + voicing[1]) + corr_shift; */ + Ltmp = L_mult(voicing[0], 16384); + Ltmp = L_mac(Ltmp, voicing[1], 16384); + cor_mean = round_fx(L_add(Ltmp, corr_shift)); + + /* pitch unstable in present frame or from previous frame or normalized correlation too low */ + coh_flag = pitch_coherence_fx(pitch[0], pitch[1], COH_FAC, DELTA_COH); + move16(); + coh_flag1 = pitch_coherence_fx(pitch[0], *old_pitch, COH_FAC, DELTA_COH); + move16(); + + test(); + test(); + test(); + IF ((coh_flag == 0) || (coh_flag1 == 0) || (LT_16(cor_mean, CORR_TH0))||(LT_16(relE,THR_relE))) + { + /* Reset the threshold */ + *old_thres = 0; + move16(); + } + ELSE + { + /* The threshold increase is directly dependent on normalized correlation */ + /* *old_thres += (0.16f * cor_mean); */ + *old_thres = round_fx(L_mac(L_deposit_h(*old_thres), 5243, cor_mean)); + } + + *old_thres = s_min(*old_thres, THRES3); + move16(); + + IF (GT_16(voicing[1], voicing[0])) + { + *old_corr = voicing[1]; + move16(); + } + ELSE + { + *old_corr = cor_mean; + move16(); + } + + /*-----------------------------------------------------------------* + * Extrapolate the pitch value for the next frame by estimating + * the pitch evolution. This value is added to the old_pitch + * in the next frame and is then used when the normalized + * correlation is reinforced by the past estimate + *-----------------------------------------------------------------*/ + tmp_buf[0] = *old_pitch; + move16(); + FOR( i = 0; i < NHFR; i++ ) + { + tmp_buf[i+1] = pitch[i]; + move16(); + } + + *delta_pit = 0; + move16(); + cnt = 0; + move16(); + + FOR ( i = 0; i < NHFR; i++ ) + { + diff = sub(tmp_buf[i+1], tmp_buf[i]); + move16(); + coh_flag = pitch_coherence_fx(tmp_buf[i], tmp_buf[i+1], COH_FAC, DELTA_COH); + + if (coh_flag != 0) + { + *delta_pit = add(*delta_pit, diff); + move16(); + } + cnt = add(cnt, coh_flag); + } + if (EQ_16(cnt, 2)) + { + /* *delta_pit /= 2; */ + *delta_pit = shr(*delta_pit, 1); + move16(); + } + IF (EQ_16(cnt, 3)) + { + k = *delta_pit; + move16(); + /* *delta_pit /= 3; */ + if (k < 0) + { + *delta_pit = mult(*delta_pit, -32768); + move16(); + } + tmp16 = mult(*delta_pit, 10923); + if (k < 0) + { + tmp16 = mult(tmp16, -32768); + } + *delta_pit = tmp16; + move16(); + } + + /*--------------------------------------------------------------* + * Update old pitch, upsample pitch, + *--------------------------------------------------------------*/ + + *old_pitch = pitch[1]; + move16(); + + FOR ( i = 0; i < NHFR; i++ ) + { + /* compensate decimation */ + pitch[i] = i_mult2(pitch[i], OPL_DECIM); + move16(); + } + + return; +} + + +/*-----------------------------------------------------------------* + * find_mult_fx + * + * Verifies whether max pitch delays in higher sections have multiples + * in lower sections + *-----------------------------------------------------------------*/ +static void find_mult_fx( + Word16 *fac, /* i/o: correlation scaling factor Q12 */ + Word16 pitch0, /* i : pitch of max correlation in the c section */ + Word16 pitch1, /* i : pitch of max correlation in the longer-delay section*/ + Word16 pit_max0, /* i : max pitch delay in the longer-delay section */ + Word16 *corr, /* i/o: max correlation in the shorter-delay section Q12 */ + Word16 *old_pitch, /* i : pitch from previous frame */ + Word16 *old_corr, /* i : max correlation from previous frame */ + Word16 delta, /* i : initial multiples search range */ + Word16 step /* i : increment in range of multiples search */ +) +{ + Word16 pit_min; + Word32 L_tmp; + + pit_min = shl(pitch0, 1); /* double the higher section pitch */ + + WHILE (LE_16(pit_min, add(pit_max0, delta))) /* check for section boundary */ + { + IF (LE_16(abs_s(sub(pit_min, pitch1)), delta)) /* if multiple in the allowed range */ + { + L_tmp = L_shl(L_mult(*corr, *fac), 3); + + /* if ( *old_corr < 0.6f || (float)pitch0 > (float)*old_pitch * 0.4f ) */ + IF (s_max(sub(19660, *old_corr), sub(pitch0, mult(*old_pitch, 13107))) > 0) + { + /* reinforce the normalized correlation */ + /* operands are Q12, result is Q12 */ + *corr = extract_h(L_tmp); + } + /* operands are Q12, result is Q12 */ + *fac = extract_h(L_shl(L_mult(*fac, THRES0), 3)); + } + pit_min = add(pit_min, pitch0); /* next multiple */ + delta = add(delta, step); /* the incertitude to the allowed range */ + } +} + +/*---------------------------------------------------------------------------* + * pitch_neighbour_fx + * + * Verifies if the maximum correlation pitch lag is coherent with neighbour + * values + *---------------------------------------------------------------------------*/ +static void pitch_neighbour_fx( + Word16 sect0, /* i : indicates whether section 0 (below PIT_MIN) is used */ + Word16 pitch_tmp[], /* i : estimated pitch values for each half-frame & look-ahead */ + Word16 pitch[3][2*NSECT], /* i : tested pitch values for each half-frame & look-ahead */ + Word16 corr_tmp[], /* i : raw normalized correlation (before different scalings) Q15*/ + Word16 corr[3][2*NSECT], /* i/o: normalized correlation for each half-frame & look-ahead Q12 */ + Word16 thres1[2*NHFR], /* i : maximum scaling for the immediate neighbours Q15 */ + Word16 ind_tmp[2*NHFR] /* i : best section index for each half-frame & look-ahead */ +) +{ + Word16 delta, i, j, k, K, coh_flag, fac; + + /*--------------------- + * 1st set of sections + ---------------------*/ + FOR ( k = sect0; k < NSECT; k++ ) /* loop for each section */ + { + K = 3; + move16(); + if (EQ_16(k, (NSECT-1))) /* the number of tests depends on the section */ + { + K = 2; + move16(); + } + /*pt = &pitch[i][k] and pt = &corr[i][k]*/ + FOR (i=0; i < K; i++) /* for the 2 half-frames and look-ahead */ + { + /* Compare pitch values of the present frame */ + FOR (j=0; j < K; j++) /* Verify pitch coherence with neighbours (including past pitch) */ + { + IF (NE_16(j, i)) /* Exclude itself, of course */ + { + IF (GE_16(corr_tmp[j], CORR_TH1)) /* reinforcement can happen only if the correlation is high enough */ + { + delta = abs_s(sub(pitch[i][k], pitch_tmp[j])); /* Find difference of pitch values */ + coh_flag = pitch_coherence_fx(pitch[i][k], pitch_tmp[j], COH_FAC, DELTA_COH); + + IF (coh_flag != 0) + { + /* Favour stability across sections, favour closer values */ + IF (EQ_16(ind_tmp[j], k)) + { + /* corr[i][k] *= ( -thres1[j]/DELTA1 * delta + thres1[j]+1 ); */ + /* operands are Q15, except corr[i][k] which is Q12 */ + fac = mult(negate(thres1[j]), MAX_16/DELTA_COH); + fac = add(i_mult2(fac, delta), thres1[j]); + } + ELSE + { + /* corr[i][k] *= ( -thres1[j]/DELTA1 * 0.625f * delta + 0.625f * thres1[j] +1.0f ); */ + fac = mult(negate(thres1[j]), 20479/DELTA_COH); + fac = add(i_mult2(fac,delta), mult(20479, thres1[j])); + } + corr[i][k] = add(corr[i][k], mult(fac, corr[i][k])); + move16(); + } + } + } + } + } + } + + /*--------------------- + * 2nd set of sections + ---------------------*/ + FOR ( k = sect0; k < NSECT; k++ ) /* loop for each section */ + { + K = 3; + move16(); + if (EQ_16(k, (NSECT-1))) /* the number of tests depends on the section */ + { + K = 2; + move16(); + } + /*pt = &pitch[i][k] and pt = &corr[i][k]*/ + FOR (i=0; i < K; i++)/* BRANCH(1); for the 2 half-frames and look-ahead */ + { + /* Compare pitch values of the present frame */ + FOR (j=0; j < K; j++)/* Verify pitch coherence with neighbours (including past pitch) */ + { + IF (NE_16(j, i))/* Exclude itself, of course */ + { + IF (GE_16(corr_tmp[j+NHFR], CORR_TH1))/* reinforcement can happen only if the correlation is high enough */ + { + delta = abs_s(sub(pitch[i][NSECT+k], pitch_tmp[j+NHFR])); /* Find difference of pitch values */ + coh_flag = pitch_coherence_fx(pitch[i][NSECT+k], pitch_tmp[j+NHFR], COH_FAC, DELTA_COH); + + IF (coh_flag != 0) + { + /* Favour stability across sections, favour closer values */ + IF (EQ_16(ind_tmp[j+NHFR], add(NSECT, k))) + { + /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * delta + thres1[j+NHFR]+1 ); */ + /* operands are Q15, except corr[i][NSECT+k] which is Q12 */ + fac = mult(negate(thres1[j+NHFR]), MAX_16/DELTA_COH); + fac = add(extract_l(L_shr(L_mult(fac, delta), 1)), thres1[j+NHFR]); + corr[i][NSECT+k] = add(corr[i][NSECT+k], mult(fac, corr[i][NSECT+k])); + move16(); + } + ELSE + { + /* corr[i][k] *= ( -thres1[j+NHFR]/DELTA1 * 0.625f * delta + 0.625f * thres1[j+NHFR] +1.0f ); */ + fac = mult(negate(thres1[j+NHFR]), 20479/DELTA_COH); + fac = add(extract_l(L_shr(L_mult(fac,delta), 1)), mult(20479, thres1[j+NHFR])); + corr[i][NSECT+k] = add(corr[i][NSECT+k], mult(fac, corr[i][NSECT+k])); + move16(); + } + } + } + } + } + } + } +} + +/*-----------------------------------------------------------------* + * pitch_coherence_fx + * + * Verify if pitch evolution is smooth + *-----------------------------------------------------------------*/ +static Word16 pitch_coherence_fx( + Word16 pitch0, /* i : first pitch to compare */ + Word16 pitch1, /* i : 2nd pitch to compare */ + Word16 fac_max, /* i : max ratio of both values Q12 */ + Word16 diff_max /* i : max difference of both values */ +) +{ + Word16 smaller, larger; + Word16 pc; + + smaller = s_min(pitch0, pitch1); + larger = s_max(pitch0, pitch1); + + pc = 0; + move16(); + test(); + if( (LE_16(larger, extract_h(L_shl(L_mult(fac_max, smaller), 3))))&& /* Changed to <= to keep BE */ + (LT_16(sub(larger, smaller), diff_max))) + { + pc = 1; + move16(); + } + + return pc; +} + +/*-----------------------------------------------------------------* + * LP_Decim2_Copy: + * + * Decimate a vector by 2 with 2nd order fir filter. + *-----------------------------------------------------------------*/ +static void LP_Decim2_Copy( + const Word16 x[], /* i: signal to process */ + Word16 y[], /* o: signal to process */ + Word16 l, /* i : size of filtering */ + Word16 mem[] /* i/o: memory (size=3) */ +) +{ + Word16 *p_x, x_buf[L_FRAME + L_MEM]; + Word16 i, j, k; + Word32 L_tmp; + + /* copy initial filter states into buffer */ + p_x = x_buf; + FOR (i = 0; i < L_MEM; i++) + { + *p_x++ = mem[i]; + move16(); + } + FOR (i = 0; i < l; i++) + { + *p_x++ = x[i]; + move16(); + } + if (l & 1) /* Fix for valgrind error in case l is odd. Anyway this function will be removed. */ + { + *p_x = *(p_x-1); + move16(); + } + + FOR (i = 0; i < L_MEM; i++) + { + mem[i] = x[l - L_MEM + i]; + move16(); + } + p_x = x_buf; + j = 0; + move16(); + FOR (i = 0; i < l; i += 2) + { + L_tmp = L_mult(*p_x, H_fir[0]); + FOR (k = 1; k < L_FIR_PO; k++) + { + L_tmp = L_mac(L_tmp, p_x[k], H_fir[k]); + } + p_x+=2; + + y[j++] = round_fx(L_tmp); + } +} +/*---------------------------------------------------------------------* + * Dot_product12_OL + * + * two different length dot products of x and y + *---------------------------------------------------------------------*/ +static Word32 Dot_product12_OL( /* o : Q31: normalized result (1 < val <= -1) */ + Word16 *sum1, /* o : Q31: normalized result 2 */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg, /* i : vector length */ + const Word16 lg2, /* i : vector length 2 */ + Word16 *exp, /* o : exponent of result (0..+30) */ + Word16 *exp2 /* o : exponent of result 2 (0..+30) */ +) +{ + Word16 i, sft; + Word32 L_sum, L_sum2; + + L_sum = L_mac(1, x[0], y[0]); + IF (LE_16(lg, lg2)) + { + FOR (i = 1; i < lg; i++) + { + L_sum = L_mac(L_sum, x[i], y[i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg2; i++) + { + L_sum2 = L_mac(L_sum2, x[i], y[i]); + } + } + ELSE + { + FOR (i = 1; i < lg2; i++) + { + L_sum = L_mac(L_sum, x[i], y[i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg; i++) + { + L_sum = L_mac(L_sum, x[i], y[i]); + } + } + + /* Q31 */ + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + *exp = sub(30, sft); + move16(); /* exponent = 0..30 */ + + sft = norm_l(L_sum2); + L_sum2 = L_shl(L_sum2, sft); + *exp2 = sub(30, sft); + move16(); /* exponent = 0..30 */ + + *sum1 = extract_h(L_shr(L_sum2, 1)); + + return L_sum; +} + +/*---------------------------------------------------------------------* + * Dot_product12_OL_back() + * + * two different length dot products of x and y, computed backward + *---------------------------------------------------------------------*/ +static Word32 Dot_product12_OL_back(/* o : Q31: normalized result (1 < val <= -1) */ + Word16 *sum1, /* o : Q31: normalized result 2 */ + const Word16 x[], /* i : 12bits: x vector */ + const Word16 y[], /* i : 12bits: y vector */ + const Word16 lg, /* i : vector length */ + const Word16 lg2, /* i : vector length 2 */ + Word16 *exp, /* o : exponent of result (0..+30) */ + Word16 *exp2 /* o : exponent of result 2 (0..+30) */ +) +{ + Word16 i, sft; + Word32 L_sum, L_sum2; + + L_sum = L_mac(1, x[0], y[0]); + IF (LE_16(lg, lg2)) + { + FOR (i = 1; i < lg; i++) + { + L_sum = L_mac(L_sum, x[-i], y[-i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg2; i++) + { + L_sum2 = L_mac(L_sum2, x[-i], y[-i]); + } + } + ELSE + { + FOR (i = 1; i < lg2; i++) + { + L_sum = L_mac(L_sum, x[-i], y[-i]); + } + /* sets to 'L_sum' in 1 clock */ + L_sum2 = L_sum; move32(); + FOR (; i < lg; i++) + { + L_sum = L_mac(L_sum, x[-i], y[-i]); + } + } + + /* Q31 */ + sft = norm_l(L_sum); + L_sum = L_shl(L_sum, sft); + *exp = sub(30, sft); + move16(); /* exponent = 0..30 */ + + sft = norm_l(L_sum2); + L_sum2 = L_shl(L_sum2, sft); + *exp2 = sub(30, sft); + move16(); /* exponent = 0..30 */ + + *sum1 = extract_h(L_shr(L_sum2, 1)); + + return L_sum; +} + + +void pitchDoubling_det_fx( + Word16 *wspeech, + Word16 *pitch_ol, + Word16 *T_op_fr, + Word16 *voicing_fr +) +{ + Word16 new_op_fr[2]; + Word16 new_voicing[2]; + Word16 new_Top[2]; + Word16 m, T; + + + /*save initial values*/ + + new_Top[0]=pitch_ol[0]; + move16(); + new_Top[1]=pitch_ol[1]; + move16(); + + FOR(m=2; m<5; m++) + { + + /* T= pitch_ol[0]/m; */ + T = mult(pitch_ol[0],One_div_fx[m-1]); + + IF(GE_16(T,PIT_MIN_12k8)) + { + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[0]), &new_voicing[0], 0, wspeech, 2 ); + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[1]), &new_voicing[1], L_SUBFR, wspeech, 2 ); + /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[0],voicing_fr[1]))>0 */ + IF( L_msu(L_msu(L_mac(L_mult(new_voicing[0], 8192),new_voicing[1], 8192), voicing_fr[0], 8192), voicing_fr[1], 8192) > 0 ) + { + new_Top[0]=T; + move16(); + T_op_fr[0]=new_op_fr[0]; + move16(); + T_op_fr[1]=new_op_fr[1]; + move16(); + voicing_fr[0]=new_voicing[0]; + move16(); + voicing_fr[1]=new_voicing[1]; + move16(); + } + } + + /* T= pitch_ol[1]/m; */ + T = mult(pitch_ol[1],One_div_fx[m-1]); + + IF(GE_16(T,PIT_MIN_12k8)) + { + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[0]), &new_voicing[0], 2*L_SUBFR, wspeech, 2 ); + pitch_ol2_fx( PIT_MIN_SHORTER, T, &(new_op_fr[1]), &new_voicing[1], 3*L_SUBFR, wspeech, 2 ); + /* IF(sub(add(new_voicing[0],new_voicing[1]),add(voicing_fr[2],voicing_fr[3]))>0) */ + IF( L_msu(L_msu(L_mac(L_mult(new_voicing[0], 8192),new_voicing[1], 8192), voicing_fr[2], 8192), voicing_fr[3], 8192) > 0 ) + { + new_Top[1]=T; + move16(); + T_op_fr[2]=new_op_fr[0]; + move16(); + T_op_fr[3]=new_op_fr[1]; + move16(); + voicing_fr[2]=new_voicing[0]; + move16(); + voicing_fr[3]=new_voicing[1]; + move16(); + } + } + } + + pitch_ol[0]=new_Top[0]; + move16(); + pitch_ol[1]=new_Top[1]; + move16(); + +}/*end of pitch doubling detection*/ diff --git a/lib_enc/plc_enc_ext_fx.c b/lib_enc/plc_enc_ext_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..da531a56e3dbaa8f7c258fc7bc20d2e95eb8a5b7 --- /dev/null +++ b/lib_enc/plc_enc_ext_fx.c @@ -0,0 +1,141 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "options.h" +#include "cnst.h" +#include "stat_enc.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 */ + +#define NBITS_GACELP 5 + +//extern const Word16 lsf_init_fx[16]; + +/*-------------------------------------------------------------------* + * init_PLC_enc_fx() + * + * + *-------------------------------------------------------------------*/ + +void init_PLC_enc_fx( + PLC_ENC_EVS_HANDLE hPlcExt, + Word32 sampleRate /* core coder SR */ +) +{ + Word16 itr; + + + hPlcExt->enableGplc = 0; + move16(); + hPlcExt->calcOnlylsf = 1; + move16(); + hPlcExt->nBits = NBITS_GACELP; + move16(); + + hPlcExt->Q_exp = 0; + move16(); + hPlcExt->Q_new = 0; + move16(); + + set16_fx(hPlcExt->mem_MA_14Q1,0,M); + set16_fx(hPlcExt->mem_AR,0,M); + set16_fx(hPlcExt->lsfold_14Q1,0,M); + set16_fx(hPlcExt->lspold_Q15,0,M); + + set16_fx(hPlcExt->old_exc_Qold,0,8); + + set16_fx(hPlcExt->lsfoldbfi0_14Q1,0,M); + set16_fx(hPlcExt->lsfoldbfi1_14Q1,0,M); + set16_fx(hPlcExt->lsf_adaptive_mean_14Q1,0,M); + hPlcExt->stab_fac_Q15 = 0; + move16(); + IF( EQ_32(sampleRate, INT_FS_12k8)) + { + hPlcExt->T0_4th = L_SUBFR; + move16(); + hPlcExt->T0 = L_SUBFR; + move16(); + FOR( itr=0; itrlsf_con[itr] = lsf_init_fx[itr]; + move16(); + hPlcExt->last_lsf_ref[itr] = lsf_init_fx[itr]; + move16(); + hPlcExt->last_lsf_con[itr] = lsf_init_fx[itr]; + move16(); + } + } + ELSE + { + hPlcExt->T0_4th = L_SUBFR; + move16(); + hPlcExt->T0 = L_SUBFR; + move16(); + FOR( itr=0; itrlsf_con[itr] = add(lsf_init_fx[itr],shr(lsf_init_fx[itr],2)); + hPlcExt->last_lsf_ref[itr] = add(lsf_init_fx[itr],shr(lsf_init_fx[itr],2)); + hPlcExt->last_lsf_con[itr] = add(lsf_init_fx[itr],shr(lsf_init_fx[itr],2)); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * gPLC_encInfo_fx() + * + * Function to extract and write guided information + *-------------------------------------------------------------------*/ +void gPLC_encInfo_fx( + PLC_ENC_EVS_HANDLE hPlcExt, + const Word32 total_brate, + const Word16 bwidth, + const Word16 last_clas, + const Word16 coder_type +) +{ + + + IF (hPlcExt) + { + hPlcExt->calcOnlylsf = 1; + move16(); + test(); + IF ( ( GE_16(bwidth, WB) && EQ_32(total_brate, ACELP_24k40))) + { + hPlcExt->enableGplc = 1; + move16(); + hPlcExt->nBits = 1; + move16(); + test(); + test(); + test(); + IF ( (EQ_16(last_clas, VOICED_CLAS)||EQ_16(last_clas,ONSET))&& + (EQ_16(coder_type, VOICED) || EQ_16(coder_type, GENERIC) ) ) + { + hPlcExt->nBits = NBITS_GACELP; + move16(); + hPlcExt->calcOnlylsf = 0; + move16(); + } + } + ELSE + { + hPlcExt->enableGplc = 0; + move16(); + hPlcExt->nBits = NBITS_GACELP; + move16(); + } + + } + +} + diff --git a/lib_enc/ppp_enc_fx.c b/lib_enc/ppp_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..b28fc526543909c554e7a2be312896a383c2dc6a --- /dev/null +++ b/lib_enc/ppp_enc_fx.c @@ -0,0 +1,1031 @@ +/*==================================================================================== + 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 "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 constants + *-------------------------------------------------------------------*/ +#define ERB_CBSIZE1 64 +#define ERB_CBSIZE2 64 +#define P_CBSIZE 64 + +/*-------------------------------------------------------------------* + * Local functions + *--------------------------------------------------------------------*/ +static Word16 DTFS_quant_cw_fx(DTFS_STRUCTURE* X_fx, Word16 pl, const Word16* curr_lpc_fx, Word16* POWER_IDX, + Word16* AMP_IDX, Word16* lastLgainE_fx, Word16* lastHgainE_fx, Word16* lasterbE_fx, Word16* sin_tab, Word16* cos_tab); +static Word16 DTFS_alignment_fine_new_fx(DTFS_STRUCTURE X1_fx, DTFS_STRUCTURE X2_fx, Word16* S_fx, Word16* C_fx); +static void erb_diff_fx(const Word16* prev_erb, Word16 pl, const Word16* curr_erb, Word16 l, const Word16* curr_lsp, Word16* index, Word16 num_erb); + + + +/*=======================================================================================*/ +/* FUNCTION : ppp_quarter_encoder_fx() */ +/*---------------------------------------------------------------------------------------*/ +/* PURPOSE : Quarter rate PPP encoder main routine */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) curr_lpc_fx: LPC coefficients, Q12 */ +/* _ (struct DTFS_STRUCTURE_FX) CURRCW_NQ_FX : prototype in Cartesian domain */ +/* (Word16) lag_fx: length of prototype */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (struct DTFS_STRUCTURE_FX) PREV_CW_E_FX : past dtfs in Cartesian domain */ +/* (Word16) lag: length of prototype */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (Word16) prevCW_lag_fx: Previous lag, Q0 */ +/* _ (Word16 *) exc : Global input (Q0) */ +/* _ (Word16 []) sinTab, Q15 : sin(2pi/4L*n), n=0,1,...,4L-1 */ +/* _ (Word16 []) cosTab, Q15 : cos(2pi/4L*n), n=0,1,...,4L-1 */ +/*---------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) pidx: Power index */ +/* _ (Word16[]) aidx: Amplitude indices, 2 words */ +/* _ (struct DTFS_fx *) CURRCW_Q_FX : quantized prototype in Cartesian domain */ +/* (Word16) lag_fx: length of prototype in time domain */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (struct DTFS_fx *) TARGETCW_FX : Target prototype in Cartesian domain */ +/* (Word16) lag_fx: length of prototype in time domain */ +/* (Word16 []) a/b: harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16[]) lasterbE_fx: ERB history for differential */ +/* quantization, Q13 */ +/* _ (Word16) lastLgainE_fx: low band power history, log domain, */ +/* Q11 */ +/* _ (Word16) lastHgainE_fx: high band power history, log domain, */ +/* Q11 */ +/*---------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) returnFlag: flag indicating success/failure */ +/* (TRUE/FALSE) */ +/*---------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*=======================================================================================*/ + +ivas_error ppp_quarter_encoder_fx( + Word16* returnFlag, /* o : return value */ + DTFS_STRUCTURE *CURRCW_Q_FX, /* o : Quantized (amp/phase) DTFS */ + DTFS_STRUCTURE *TARGETCW_FX, /* o : DTFS with quant phase but unquant Amp */ + Word16 prevCW_lag, /* i : previous lag */ + DTFS_STRUCTURE vCURRCW_NQ_FX, /* i : Unquantized DTFS */ + const Word16 *curr_lpc_fx, /* i : LPCS */ + Word16 *lastLgainE_fx, /* i/o: last low band gain */ + Word16 *lastHgainE_fx, /* i/o: last high band gain */ + Word16 *lasterbE_fx, /* i/o: last ERB vector */ + DTFS_STRUCTURE PREV_CW_E_FX, /* i : past DTFS */ + Word16 *S_fx, /* i : sin table, Q15 */ + Word16 *C_fx, /* i : cos table, Q15 */ + BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ +) +{ + DTFS_STRUCTURE *PREVDTFS_FX; + Word16 tmp_fx, temp_pl_fx, temp_l_fx; + Word16 temp; + Word16 l; + Word16 POWER_IDX_FX; /* Codebook index for the power quantization for PPP */ + Word16 AMP_IDX_fx[2]; /* Codebook index for the Amplitude quantization for PPP */ + Word16 Erot_fx = 0; + /* Word16 S_fx[PIT_MAX*4+1], C_fx[PIT_MAX*4+1];*/ + Word32 Ltempd,Ltempn; + Word32 L_tmp, L_tmp1; + Word16 tmp, exp; + ivas_error error; + + error = IVAS_ERR_OK; + *returnFlag = 1; + move16();move16(); + IF((error = DTFS_new_fx(&PREVDTFS_FX)) != IVAS_ERR_OK) + { + IVAS_ERROR(error, "Error creating DTFS structure"); + } + DTFS_copy_fx( CURRCW_Q_FX, vCURRCW_NQ_FX ); + DTFS_copy_fx( PREVDTFS_FX, PREV_CW_E_FX ); + + l = CURRCW_Q_FX->lag_fx; + move16(); + temp_l_fx = CURRCW_Q_FX->lag_fx; + move16(); + temp_pl_fx = prevCW_lag; + move16(); + + DTFS_adjustLag_fx( PREVDTFS_FX, l ); + + + /* z = ((L_FRAME-temp_l)*(temp_l+temp_pl))/(2*temp_l*temp_pl); */ + /* Erot = (float) (temp_l - rint_new(temp_l*(z - floor(z)))); */ + temp = sub(L_FRAME,temp_l_fx); /*Q0 */ + exp = norm_s(temp_pl_fx); + tmp = div_s(shl(1,sub(14,exp)),temp_pl_fx); /*Q(29-exp) */ + L_tmp = L_mult(temp,tmp); /*Q(31-exp); +1 due to /2 */ + L_tmp = L_shl(L_tmp,sub(exp,15)); /*Q16 */ + + exp = norm_s(temp_l_fx); + tmp = div_s(shl(1,sub(14,exp)),temp_l_fx); /*Q(29-exp) */ + L_tmp1 = L_mult(temp,tmp); /*Q(31-exp); +1 due to /2 */ + L_tmp1 = L_shl(L_tmp1,sub(exp,15)); /*Q16 */ + + L_tmp = L_add(L_tmp,L_tmp1); /*Q16 */ + + tmp = lshr(extract_l(L_tmp),1); /*Q15 */ + L_tmp = L_mult(temp_l_fx,tmp); /*Q16 */ + temp = rint_new_fx(L_tmp); + Erot_fx = sub(temp_l_fx,temp); /*Q0 */ + + GetSinCosTab_fx(CURRCW_Q_FX->lag_fx,S_fx,C_fx);/*get cos and sin tables for lag */ + Q2phaseShift_fx(PREVDTFS_FX,shl(Erot_fx,2),CURRCW_Q_FX->lag_fx,S_fx,C_fx); + + DTFS_copy_fx(TARGETCW_FX,*CURRCW_Q_FX); + /* Amplitude Quantization */ + DTFS_car2pol_fx(CURRCW_Q_FX); /* at this point currCW_q=curr_nq */ + + /*As the upper cut of freqencies are normalized to 12800, we have to multiply upper cut off freq by + 2.56(1/12800 in Q15) */ + Ltempn = L_mult(CURRCW_Q_FX->upper_cut_off_freq_fx,10486);/* Q0+Q27 = Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_fx = (Word16)L_shr(Ltempn,13);/*Q15 */ + Ltempn = L_mult(CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx,10486);/* Q0+Q27 = Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx = (Word16)L_shr(Ltempn,13);/*Q15 */ + + *returnFlag = DTFS_quant_cw_fx(CURRCW_Q_FX,prevCW_lag,curr_lpc_fx,&POWER_IDX_FX, + AMP_IDX_fx,lastLgainE_fx,lastHgainE_fx,lasterbE_fx,S_fx,C_fx); + move16(); + + /*De-normalize cut off frequencies */ + Ltempn = L_shl((Word32)CURRCW_Q_FX->upper_cut_off_freq_fx,13);/*Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_fx = (Word16)find_remd(Ltempn, 20971,&Ltempd); + move16(); + Ltempn = L_shl((Word32)CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx,13);/*Q28 */ + CURRCW_Q_FX->upper_cut_off_freq_of_interest_fx = (Word16)find_remd(Ltempn, 20971,&Ltempd); + + push_indice_fx(hBstr, IND_AMP0, AMP_IDX_fx[0], 6 ); + push_indice_fx( hBstr, IND_AMP1, AMP_IDX_fx[1], 6 ); + push_indice_fx( hBstr, IND_POWER, POWER_IDX_FX, 6); + + /*Phase copying is done through copy_phase instead of car2pol and pol2car */ + copy_phase_fx(TARGETCW_FX,*CURRCW_Q_FX,TARGETCW_FX); + /*Phase copying is done through copy_phase instead of car2pol and pol2car */ + copy_phase_fx(PREVDTFS_FX,*CURRCW_Q_FX,CURRCW_Q_FX); + /* Copying phase spectrum over */ + /*mvr2r(PREVDTFS->b, CURRCW_Q->b, (short)(CURRCW_Q->lag>>1)+1 ); */ + + /*DTFS_pol2car(CURRCW_Q); */ + /*DTFS_pol2car(TARGETCW); */ + + tmp_fx = DTFS_alignment_fine_new_fx(*TARGETCW_FX,*CURRCW_Q_FX,S_fx,C_fx); + move16(); + + test(); + IF (GT_16(add(tmp_fx,12),28)||LT_16(tmp_fx,-12)) + { + tmp_fx = 0; + move16(); + *returnFlag = 0; + move16(); + } + + /*DTFS_phaseShift( CURRCW_Q,(float)(PI2*tmp/CURRCW_Q->lag) ); */ + Q2phaseShift_fx(CURRCW_Q_FX,tmp_fx,CURRCW_Q_FX->lag_fx,S_fx,C_fx); + + push_indice_fx( hBstr, IND_GLOBAL_ALIGNMENT, shr(add(tmp_fx,12),2), 3 ); + + count_free(PREVDTFS_FX); + return error; +} + +/*-------------------------------------------------------------------* +* set_ppp_mode_fx() + * + * Determine if the current frame should be coded by PPP or not + * Impose PPP - CELP - CELP pattern + *-------------------------------------------------------------------*/ +void set_ppp_mode_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 noisy_speech_HO, /* i : SC-VBR noisy speech HO flag */ + const Word16 clean_speech_HO, /* i : SC-VBR clean speech HO flag */ + const Word16 NB_speech_HO, /* i : SC-VBR NB speech HO flag */ + const Word16 localVAD_he /* i : HE-SAD flag without hangover */ +) +{ + + SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR; + + test(); + test(); + test(); + test(); + test(); + + IF ( EQ_16( st_fx->vad_flag, 1)&& + ( EQ_16( noisy_speech_HO , 1 ) || EQ_16( clean_speech_HO, 1 ) || EQ_16( NB_speech_HO, 1) ) && + ( st_fx->localVAD == 0 || localVAD_he == 0 ) ) + + { + st_fx->coder_type = UNVOICED; + move16(); + } + + test(); + test(); + IF ( EQ_16( st_fx->coder_type , INACTIVE ) && (st_fx->vad_flag==0) && EQ_16(hSC_VBR->last_nelp_mode,1)) /* avoid HO frame go to GSC */ + { + st_fx->coder_type = UNVOICED; + move16(); + } + + + /* force the coder to NELP mode during the first five frames */ + /* this will indicate the decoder that the coder is operating in the VBR mode */ + IF ( LT_16( st_fx->ini_frame_fx, 5)) + { + st_fx->coder_type = UNVOICED; + move16(); + st_fx->vad_flag = 1; + move16(); + } + /* Pattern PPP-CELP-CELP (pppcountE holds number of consecutive PPP frames) */ + test(); + IF ( NE_16( st_fx->coder_type, VOICED )||EQ_16(st_fx->last_coder_type_fx,TRANSITION)) + { + /* ensure no transient to PPP transition */ + hSC_VBR->pppcountE = 0; + move16(); + } + ELSE + { + /* current mode is voiced */ + hSC_VBR->pppcountE = add( hSC_VBR->pppcountE, 1); + test(); + test(); + test(); + test(); + IF ( ( EQ_16( hSC_VBR->pppcountE, 1 )&&NE_16(hSC_VBR->last_last_ppp_mode,1)&& hSC_VBR->rate_control==0)|| + ( EQ_16( hSC_VBR->pppcountE, 1 ) && hSC_VBR->mode_QQF != 0) ) + { + hSC_VBR->ppp_mode = 1; + move16(); + st_fx->core_brate_fx = PPP_NELP_2k80; + move32(); + } + ELSE IF ( EQ_16(hSC_VBR->pppcountE, 2 )) + { + test(); + IF (hSC_VBR->last_ppp_mode != 0 && hSC_VBR->mode_QQF == 0 ) + { + /* QFF mode */ + hSC_VBR->ppp_mode = 0; + move16(); + } + ELSE + { + /* QQF Mode */ + hSC_VBR->ppp_mode = 1; + move16(); + st_fx->core_brate_fx = PPP_NELP_2k80; + move32(); + } + } + ELSE + { + hSC_VBR->ppp_mode = 0; + move16(); + hSC_VBR->pppcountE = 0; + move16(); + } + } + + + test(); + IF (hSC_VBR->ppp_mode == 0 && EQ_16(hSC_VBR->set_ppp_generic, 1)) + { + hSC_VBR->set_ppp_generic = 0; + move16(); + st_fx->coder_type = GENERIC; + move16(); + } + + IF ( st_fx->last_core_fx == HQ_CORE ) + { + hSC_VBR->ppp_mode = 0; + move16(); + hSC_VBR->set_ppp_generic = 0; + move16(); + st_fx->coder_type = TRANSITION; + move16(); + } + + test(); + test(); + test(); + test(); + IF ( (hSC_VBR->last_ppp_mode != 0 ) && (hSC_VBR->ppp_mode == 0 ) && ( st_fx->sp_aud_decision1 != 0) + && EQ_16(st_fx->bwidth_fx, NB)&&st_fx->Opt_SC_VBR_fx!=0) /*if it were about to go from ppp->HQ*/ + { + hSC_VBR->avoid_HQ_VBR_NB = 1; + move16(); + st_fx->coder_type = GENERIC; + move16(); + } + + test(); + test(); + test(); + IF ( (hSC_VBR->last_nelp_mode != 0) && ( st_fx->sp_aud_decision1 != 0) && EQ_16( st_fx->bwidth_fx, NB)&&(st_fx->Opt_SC_VBR_fx!=0)) /*if it were about to go from nelp->HQ*/ + { + hSC_VBR->avoid_HQ_VBR_NB = 1; + move16(); + st_fx->coder_type = GENERIC; + move16(); + } + + + test(); + test(); + test(); + if( ( GT_16(st_fx->old_pitch_buf_fx[(2*NB_SUBFR)-1], PPP_LAG_THRLD_Q6)|| + GT_16(st_fx->pitch_fx[1], PPP_LAG_THRLD) || !st_fx->last_Opt_SC_VBR_fx ) && + EQ_16(hSC_VBR->ppp_mode,1) ) + { + hSC_VBR->ppp_mode=0; + move16(); + st_fx->core_brate_fx = ACELP_7k20; + move32(); + } + + + return; +} + +/*===================================================================*/ +/* FUNCTION : Word16 DTFS_quant_cw_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Quantize QPPP prototype */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) pl: previous lag */ +/* _ (Word16 []) curr_lpc_fx: LPC coefficients, Q12 */ +/* _ (Word16 []) sin_tab: sine table based on lag, Q15 */ +/* _ (Word16 []) cos_tab: cosine table based on lag, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) POWER_IDX: Power index */ +/* _ (Word16[]) AMP_IDX: Amplitude indices */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X_fx : prototype in polar domain */ +/* (Word16) lag_fx: length of prototype in time domain*/ +/* (Word16 []) a: amplitude of harmonics, normalized */ +/* (Word16) Q: norm factor of a */ +/* _ (Word16[]) lasterb_fx: ERB history for differential */ +/* quantization, Q13 */ +/* _ (Word16) Lgain_fx: low band power history, log domain, Q11 */ +/* _ (Word16) Hgain_fx: high band power history, log domain, Q11 */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word16) flag: flag indicating success/failure (TRUE/FALSE) */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ +/* NOTE: Frequencies is normalized by 12800, i.e. 1=12800Hz */ +/*===================================================================*/ +static Word16 DTFS_quant_cw_fx( + DTFS_STRUCTURE* X_fx, /* i/o: DTFS unquant inp, quant out */ + Word16 pl, /* i : Previous lag */ + const Word16* curr_lpc_fx, /* i : LPC */ + Word16* POWER_IDX, /* o : Power index */ + Word16* AMP_IDX, /* o : Amplitude index */ + Word16* lastLgainE_fx, /* i/o: last frame lowband gain */ + Word16* lastHgainE_fx, /* i/o: last frame highband gain */ + Word16* lasterbE_fx, /* i/o: last frame ERB vector */ + Word16* sin_tab, + Word16* cos_tab +) + +{ + Word16 num_erb = 0; + const Word16* PowerCB_fx = NULL; + Word16 tmp, w[2], target[2], j, slot[NUM_ERB_WB], flag; + Word16 n, d1, d2, exp; + Word32 minerror, Ltemp, logLag_fx, L_tmp; + Word16 erb_uq[NUM_ERB_WB], Qh, Ql; + /* Word40 Lacc_40; */ + Word32 Lacc; + Word16 mfreq[NUM_ERB_WB]; + Word16 Q; + + Word16 curr_erb_fx[NUM_ERB_WB]; + + + /* upper_cute_off_freq are normalized to 12800 */ + + IF(EQ_16(X_fx->upper_cut_off_freq_fx, 0x2800))/* 4000 hz normalized to 12800 in Q15 */ + { + num_erb = NUM_ERB_NB; + move16(); + PowerCB_fx = PowerCB_NB_fx; + move16(); + } + ELSE IF(EQ_16(X_fx->upper_cut_off_freq_fx, 0x4000))/* 6400 hz normalized to 12800 in Q15 */ + { + num_erb = NUM_ERB_WB; + move16(); + PowerCB_fx = PowerCB_WB_fx; + move16(); + } + + /* Get weighting and target */ + quant_target_fx(X_fx, curr_lpc_fx, w, target, sin_tab, cos_tab); + + /* Power Quantization in log domain */ + target[0] = sub(target[0], *lastLgainE_fx); + move16(); + target[1] = sub(target[1], *lastHgainE_fx); + move16(); + + minerror = L_add(EVS_LW_MAX, 0); + *POWER_IDX = 0; + move16(); + + j = 0; + move16(); + FOR(n = 0; n < P_CBSIZE * 2; n += 2) + { + /* n=shl(j,1); n=offset to current codebook entry */ + d1 = sub(target[0], PowerCB_fx[n]); + d2 = sub(target[1], PowerCB_fx[n + 1]); + Ltemp = L_mult(w[0], abs_s(d1)); + Ltemp = L_mac(Ltemp, w[1], abs_s(d2)); /* Ltemp=error */ + + test(); + IF(d1 >= 0 && d2 >= 0) + { + Ltemp = Mult_32_16(Ltemp, 0x6666); /* *=0.8 */ + } + IF(LT_32(Ltemp, minerror)) + { + minerror = L_add(Ltemp, 0); + *POWER_IDX = j; + move16(); + } + j = add(j, 1); + } + DTFS_to_erb_fx(*X_fx, curr_erb_fx); + + FOR(j = 0; j < num_erb; j++) + { + erb_uq[j] = curr_erb_fx[j]; + move16(); + } + erb_slot_fx(X_fx->lag_fx, slot, mfreq, num_erb); + /* Amplitude Quantization */ + + + erb_diff_fx(lasterbE_fx, pl, curr_erb_fx, X_fx->lag_fx, curr_lpc_fx, AMP_IDX, num_erb); + + + /* Dequantization of prototype */ + /* PORTING: Removing the references */ + /* DTFS_dequant_cw_fx(pl, *POWER_IDX, AMP_IDX,lastLgainE_fx,lastHgainE_fx, lasterbE_fx,X_fx,num_erb,curr_erb_fx); */ + + /* Determine IF the amplitude quantization is good enough */ + erb_add_fx(curr_erb_fx, X_fx->lag_fx, lasterbE_fx, pl, AMP_IDX, num_erb); + + curr_erb_fx[0] = mult_r(curr_erb_fx[1], 9830); + move16(); /* 0.3 inQ15 leaves curr_erb in Q13 */ + curr_erb_fx[sub(num_erb, 2)] = mult_r(curr_erb_fx[sub(num_erb, 3)], 9830);/* Q13 */ + + curr_erb_fx[sub(num_erb, 1)] = 0; + move16(); + flag = 1; + move16(); + + Ltemp = L_deposit_l(0); + n = 0; + move16(); + FOR(j = 1; j < 10; j++) + { + IF(slot[j] != 0) + { + Ltemp = L_add(Ltemp, abs_s(sub(erb_uq[j], curr_erb_fx[j]))); /* Q13 */ + n = add(n, 1); /* n++ */ + } + } + + exp = norm_s(n); + tmp = div_s(shl(1, sub(14, exp)), n);/* 29 - exp */ + Lacc = L_shl(Mult_32_16(Ltemp, tmp), exp + 4); + + tmp = round_fx(Lacc); /* tmp in Q15 */ + + test(); + if (GT_16(tmp, 0x3C29) && GT_16(target[0], -819)) + { + flag = 0; /* Bumping up */ move16(); + } + + /* mfreq normalized (2.56) in Q15 */ + DTFS_erb_inv_fx(curr_erb_fx, slot, mfreq, X_fx, num_erb); + + + /* Back up the lasterbD memory after power normalization */ + DTFS_setEngyHarm_fx(236, 2828, 0, 2828, 1, 0, &Ql, X_fx); + DTFS_setEngyHarm_fx(2828, X_fx->upper_cut_off_freq_of_interest_fx, 2828, X_fx->upper_cut_off_freq_fx, 1, 0, &Qh, X_fx); + + /* Need to unify the Q factors of both bands */ + X_fx->Q = s_min(Ql, Qh); /* set Q factor to be the smaller one */ + n = sub(Ql, Qh); /* compare band Q factors */ + + + /* This logic adjusts difference between Q formats of both bands */ + + IF(n < 0) + rshiftHarmBand_fx(X_fx, 2828, X_fx->upper_cut_off_freq_fx, n); + ELSE IF(n > 0) + rshiftHarmBand_fx(X_fx, 0, 2828, sub(Qh, Ql)); + + tmp = shl(*POWER_IDX, 1); /* tmp=2*POWER_IDX */ + *lastLgainE_fx = add(*lastLgainE_fx, PowerCB_fx[tmp]); /* Q11 */ + *lastHgainE_fx = add(*lastHgainE_fx, PowerCB_fx[tmp + 1]); /* Q11 */ + + Ltemp = log10_fx(X_fx->lag_fx); /* Ltemp=10*log10(lag), Q23 */ + logLag_fx = Mult_32_16(Ltemp, 0x6666); /* logLag=log10(lag), Q26 */ + + Ltemp = L_sub(L_shr(L_deposit_h(*lastLgainE_fx), 1), logLag_fx); /* Ltemp=Lgain-log10(lag), Q26 */ + + L_tmp = pow_10(Ltemp, &Q); /* Lacc=10^Lgain/lag, Q15 */ + n = norm_l(L_tmp); + Ltemp = (Word32)L_shl(L_tmp, n); /* Ltemp in Q(15+n) */ + + + DTFS_setEngyHarm_fx(236, 2828, 0, 2828, Ltemp, add(Q, n), &Ql, X_fx); + + Ltemp = L_sub(L_shr(L_deposit_h(*lastHgainE_fx), 1), logLag_fx); /* Ltemp=Hgain-log10(lag), Q26 */ + + /* Ltemp = L_shr(Ltemp,1); */ + L_tmp = pow_10(Ltemp, &Q); /* Lacc=10^Lgain/lag, Q15 */ + n = norm_l(L_tmp); + Ltemp = (Word32)L_shl(L_tmp, n); /* Ltemp in Q(15+n) */ + + DTFS_setEngyHarm_fx(2828, X_fx->upper_cut_off_freq_of_interest_fx, 2828, X_fx->upper_cut_off_freq_fx, Ltemp, add(Q, n), &Qh, X_fx); + /* Need to unify the Q factors of both bands */ + X_fx->Q = s_min(Ql, Qh); /* set Q factor to be the smaller one */ + n = sub(Ql, Qh); /* compare band Q factors */ + + IF(n < 0) + { + rshiftHarmBand_fx(X_fx, 2828, X_fx->upper_cut_off_freq_fx, n); + } + ELSE IF(n > 0) + { + rshiftHarmBand_fx(X_fx, 0, 2828, sub(Qh, Ql)); + } + return flag; +} +/*===================================================================*/ +/* FUNCTION : DTFS_alignment_fine_new_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : search for alignment */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_fx) X1_fx : a/b in X1_fx.Q */ +/* _ (struct DTFS_fx) X2_fx : a/b in X2_fx.Q */ +/* _ (Word16 *) S_fx: sin(2pi*n/(4*lag)) table, Q15 */ +/* _ (Word16 *) C_fx: cos(2pi*n/(4*lag)) table, Q15 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) fshift_fx : Q2 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ + +static Word16 DTFS_alignment_fine_new_fx(DTFS_STRUCTURE X1_fx, DTFS_STRUCTURE X2_fx, Word16* S_fx, Word16* C_fx) +{ + Word16 temp, temp1, k, Qcorr, Qmaxcorr; + Word16 n, fshift_fx, HalfLag, ab1[MAXLAG_WI], ab2[MAXLAG_WI]; + Word32 corr_fx; + Word32 maxcorr_fx, wcorr_fx, diff_corr; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + IF(LT_16(X1_fx.lag_fx, X2_fx.lag_fx)) + { + DTFS_zeroPadd_fx(X2_fx.lag_fx, &X1_fx); + } + + maxcorr_fx = L_add(MIN_32, 0); + Qmaxcorr = 0; + move16(); + HalfLag = s_min(shr(X2_fx.lag_fx, 1), X2_fx.nH_fx); + + FOR(k = 0; k <= HalfLag; k++) + { + ab1[k] = round_fx(L_mac(L_mult(X1_fx.a_fx[k], X2_fx.a_fx[k]), X1_fx.b_fx[k], X2_fx.b_fx[k])); + ab2[k] = round_fx(L_msu(L_mult(X1_fx.b_fx[k], X2_fx.a_fx[k]), X1_fx.a_fx[k], X2_fx.b_fx[k])); + } + + + fshift_fx = 0; + move16(); + FOR(n = -76; n <= 80; n += 4) + { + /* n is Q2 */ + corr_fx = L_deposit_l(0); + temp = 0; + move16(); + temp1 = n; + move16(); + + IF(n < 0) + { + temp1 = add(temp1, shl(X2_fx.lag_fx, 2)); /* avoid negative */ + } + + FOR(k = 0; k <= HalfLag; k++) + { +#ifdef BASOP_NOGLOB + corr_fx = L_mac_o(corr_fx, ab1[k], C_fx[temp % (4 * X2_fx.lag_fx)], &Overflow); + corr_fx = L_mac_o(corr_fx, ab2[k], S_fx[temp % (4 * X2_fx.lag_fx)], &Overflow); + temp = add_o(temp, temp1, &Overflow); +#else + corr_fx = L_mac(corr_fx, ab1[k], C_fx[temp % (4 * X2_fx.lag_fx)]); + corr_fx = L_mac(corr_fx, ab2[k], S_fx[temp % (4 * X2_fx.lag_fx)]); + temp = add(temp, temp1); +#endif + } + temp = sub(32767, extract_l(L_shr(L_mult(82, abs_s(n)), 1))); /* Q15 */ + Qcorr = norm_l(corr_fx); + if (corr_fx == 0) + { + Qcorr = 31; + move16(); + } + +#ifdef BASOP_NOGLOB + temp1 = round_fx_o((Word32)L_shl_o(corr_fx, Qcorr, &Overflow), &Overflow); /* Q(Qcorr-16) */ + wcorr_fx = L_mult_o(temp1, temp, &Overflow); /* Q(Qcorr-16+15+1)=Q(Qcorr) */ +#else + temp1 = round_fx((Word32)L_shl(corr_fx, Qcorr)); /* Q(Qcorr-16) */ + wcorr_fx = L_mult(temp1, temp); /* Q(Qcorr-16+15+1)=Q(Qcorr) */ +#endif + + IF(GE_16(Qmaxcorr, Qcorr)) + { +#ifdef BASOP_NOGLOB + diff_corr = L_sub_o(wcorr_fx, L_shl_o(maxcorr_fx, sub(Qcorr, Qmaxcorr), &Overflow), &Overflow); /* Qcorr */ +#else + diff_corr = L_sub(wcorr_fx, L_shl(maxcorr_fx, sub(Qcorr, Qmaxcorr))); /* Qcorr */ +#endif + } + ELSE + { +#ifdef BASOP_NOGLOB + diff_corr = L_sub_o(L_shl_o(wcorr_fx, sub(Qmaxcorr, Qcorr), &Overflow), maxcorr_fx, &Overflow); /* Qmaxcorr */ +#else + diff_corr = L_sub(L_shl(wcorr_fx, sub(Qmaxcorr, Qcorr)), maxcorr_fx); /* Qmaxcorr */ +#endif + } + + if (diff_corr > 0) + { + fshift_fx = n; + move16(); +#ifdef BASOP_NOGLOB + maxcorr_fx = (Word32)L_shl_o(corr_fx, Qcorr, &Overflow); /* Qcorr */ +#else + maxcorr_fx = (Word32)L_shl(corr_fx, Qcorr); /* Qcorr */ +#endif + Qmaxcorr = Qcorr; + move16(); + } + } + + return fshift_fx; +} +/*===================================================================*/ +/* FUNCTION : LPCPowSpect_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Compute LPC power spectrum */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 []) freq : ERB frequency bounds, Q15 */ +/* _ (Word16 []) LPC : LPC coefficients, Q12 */ +/* _ (Word16) Nf: number of ERB bins, Q0 */ +/* _ (Word16) Np : order of LPC, Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) out : LPC power spectrum, Q7 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ +/* NOTE: Frequency is normalized by 12800, i.e. 1=12800Hz */ +/*===================================================================*/ +static void LPCPowSpect_fx( + const Word16* freq, /* i : ERB frequencies */ + const Word16 Nf, /* i : Number of ERBs */ + const Word16* LPC, /* i : LPC coefficients */ + const Word16 Np, /* i : Number of LPCs */ + Word16* out /* o : LPC power spectrum */ +) +{ + Word16 i, k; + Word16 w; /* Q9 */ + Word16 t1, dt; + /*Word16 t2; */ + Word16 dh, dl; + Word32 Re, Im; /* Q27 */ + Word32 Ltemp, Lw; + Word32 Lacc; + Word16 tmp, exp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + FOR(k = 0; k < Nf; k++) + { + + Re = L_add(0x8000000, 0); /* Re=1.0, Q27 */ + Im = L_deposit_l(0); + Lw = L_deposit_l(freq[k]);/* Q15 */ + FOR(i = 0; i < Np; i++) + { + Ltemp = L_shl(Lw, 10); /* Ltemp in Q25 */ + w = extract_h(Ltemp); /* w in Q9 */ + dl = extract_l(Ltemp); /* dl has 6 bits left-over */ + w = s_and(w, 511); + t1 = cos_table[w]; + /* t2=cos_table[s_and(add(w,1),511)]; */ + /*dt=sub(t2,t1); */ /* dt=t2-t1, Q15 */ + dt = cos_diff_table[w]; + + IF(dl < 0) + { + Ltemp = L_shl(L_add(65536, dl), 14);/* */ + Ltemp = Mult_32_16(Ltemp, dt); + Ltemp = L_shl(Ltemp, 1); + } + ELSE + { + Ltemp = (Word32)L_mult0(dt,dl); /* Ltemp in Q31 */ + } + + t1 = add(t1, (Word16)L_shr(Ltemp, 16)); /* t1 is interpolated cos(w) */ + Ltemp = L_shr(L_mult(LPC[i], t1), 1); /* Ltemp in Q27 */ +#ifdef BASOP_NOGLOB + Re = L_add_o(Re, Ltemp, &Overflow); /* Re=1-sum(LPC[i]*cos(Lw)); */ + Ltemp = L_add_o(Lw, 0x6000, &Overflow); /* add 0.75, which is 3pi/2 to convert sin to cos */ + Ltemp = L_shl_o(Ltemp, 10, &Overflow); /* Q25 */ +#else + Re = L_add(Re, Ltemp); /* Re=1-sum(LPC[i]*cos(Lw)); */ + Ltemp = L_add(Lw, 0x6000); /* add 0.75, which is 3pi/2 to convert sin to cos */ + Ltemp = L_shl(Ltemp, 10); /* Q25 */ +#endif + w = extract_h(Ltemp); /* w is equivalent cos index */ + dl = extract_l(Ltemp); /* dl is 6 bit left-over for interpolation */ + w = s_and(w, 511); + t1 = cos_table[w]; + /*t2=cos_table[s_and(add(w,1),511)]; */ + /*dt=sub(t2,t1); */ /* dt=t2-t1, Q15 */ + dt = cos_diff_table[w]; + + IF(dl < 0) + { + Ltemp = L_shl(L_add(65536, dl), 14);/* */ + Ltemp = Mult_32_16(Ltemp, dt); + Ltemp = L_shl(Ltemp, 1); + } + ELSE + { + Ltemp = (Word32)L_mult0(dt,dl); /* Ltemp in Q31 */ + } + + t1 = add(t1, (Word16)L_shr(Ltemp, 16)); /* t1 is interpolated cos(w) */ + Ltemp = L_shr(L_mult(LPC[i], t1), 1); /* Ltemp in Q27 */ +#ifdef BASOP_NOGLOB + Im = L_sub_o(Im, Ltemp, &Overflow); /* Im=sum(LPC[i]*sin(Lw)) */ + Lw = L_add_o(Lw, freq[k], &Overflow); /* Lw=(i+1)*freq[k] */ +#else + Im = L_sub(Im, Ltemp); /* Im=sum(LPC[i]*sin(Lw)) */ + Lw = L_add(Lw, freq[k]); /* Lw=(i+1)*freq[k] */ +#endif + } + /* If necessary, we can block-normalize Re and Im to improve precision */ + dh = extract_h(Re); + dl = extract_l(Re); + + IF(dl < 0) + { + Ltemp = L_shl(L_add(65536, dl), 14);/* */ + Ltemp = Mult_32_16(Ltemp, dh); + Lacc = L_shl(Ltemp, 1); + } + ELSE + Lacc = L_mult0(dh, dl); + +#ifdef BASOP_NOGLOB + Lacc = L_add_o(L_shr(Lacc, 15), L_shr(L_mult_o(dh, dh, &Overflow), 1), &Overflow); /* Lacc=Re*Re */ +#else + Lacc = L_add(L_shr(Lacc, 15), L_shr(L_mult(dh, dh), 1)); /* Lacc=Re*Re */ +#endif + dh = extract_h(Im); + dl = extract_l(Im); + + IF(dl < 0) + { + Ltemp = L_shl(L_add(65536, dl), 14);/* */ + Ltemp = Mult_32_16(Ltemp, dh); + Ltemp = L_shl(Ltemp, 1); + } + ELSE + Ltemp = (Word32)L_mult0(dh, dl); + + Lacc = L_add(Lacc, L_shr(Ltemp, 15)); + Lacc = L_add(Lacc, L_shr(L_mult(dh, dh), 1)); /* Lacc=Re^2+Im^2, Q22 */ + + exp = norm_l(Lacc); + tmp = round_fx(L_shl(Lacc, exp)); + exp = sub(sub(30, exp), 22); + + /* tmp may potentially become negative, when Lacc is a very large value */ + IF(tmp > 0) + { + tmp = div_s(16384, tmp); /* 15+exp1 */ + } + ELSE + { + tmp = 0; + move16(); + } + Ltemp = L_deposit_h(tmp); +#ifdef BASOP_NOGLOB + out[k] = round_fx_o(L_shl_o(Ltemp, negate(add(exp, 8)), &Overflow), &Overflow); +#else + out[k] = round_fx(L_shl(Ltemp, negate(add(exp, 8)))); +#endif + + /* out[k] = shl(tmp,-exp-8); in Q7 */ + + } + return; +} + +/*===================================================================*/ +/* FUNCTION : erb_diff_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : Quantize erb amplitude for QPPP */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) pl : previous pitch lag, Q0 */ +/* _ (Word16) l : current pitch lag, Q0 */ +/* _ (Word16 []) prev_erb : Previous erb amplitude, Q13 */ +/* _ (Word16 []) curr_erb : Current erb amplitude, Q13 */ +/* _ (Word16 []) curr_lsp : LSP coefficients, Q12 */ +/* _ (Word16 []) num_erb : Number of ERBs , Q0 */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16 []) index: quantized differential erb index */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ +static void erb_diff_fx( + const Word16* prev_erb, /* i : previous ERB */ + Word16 pl, /* i : previous lag */ + const Word16* curr_erb, /* i : current ERB */ + Word16 l, /* i : current lag */ + const Word16* curr_lsp, /* i : current LSP coefficients */ + Word16* index, /* 0 : ERB index */ + Word16 num_erb /* i : Number of ERBs */ +) +{ + Word16 i; + Word16 pslot[NUM_ERB_WB], cslot[NUM_ERB_WB]; + Word16 tmp, t_prev_erb[NUM_ERB_WB], LPC[M + 1], mfreq[NUM_ERB_WB], PowSpect[NUM_ERB_WB], dif_erb[NUM_ERB_WB]; + const Word16* AmpCB1_fx = NULL; + + IF(EQ_16(num_erb, NUM_ERB_NB)) + { + AmpCB1_fx = AmpCB1_NB_fx; + move16(); + } + ELSE IF(EQ_16(num_erb, NUM_ERB_WB)) + { + AmpCB1_fx = AmpCB1_WB_fx; + move16(); + + } + erb_slot_fx(l, cslot, mfreq, num_erb);/* cslot in Qo and mfreq in Q15 */ + erb_slot_fx(pl, pslot, t_prev_erb, num_erb); + + FOR(i = 0; i < M + 1; i++) + { + LPC[i] = mult_r(curr_lsp[i], pwf78_fx[i]); + move16(); + } + + LPCPowSpect_fx(mfreq, num_erb, LPC, M + 1, PowSpect);/* Powspect in Q7 */ + + FOR(i = 0; i < num_erb; i++) + { + if (cslot[i] == 0) + { + PowSpect[i] = 0; + move16(); + } + } + FOR(i = 0; i < num_erb; i++) + { + t_prev_erb[i] = prev_erb[i]; + move16(); + } + IF(GT_16(pl, l)) + { + tmp = t_prev_erb[0]; + move16(); + FOR(i = 0; i < num_erb; i++) + { + IF(pslot[i] != 0) + { + tmp = t_prev_erb[i]; + move16(); + } + ELSE + { + t_prev_erb[i] = tmp; + move16(); + } + } + } + ELSE IF(GT_16(l, pl)) + { + tmp = t_prev_erb[num_erb - 1]; + move16(); + + FOR(i = sub(num_erb, 1); i >= 0; i--) + { + IF(pslot[i] != 0) + { + tmp = t_prev_erb[i]; + move16(); + } + ELSE + { + t_prev_erb[i] = tmp; + move16(); + } + } + } + FOR(i = 0; i < num_erb; i++) + { + dif_erb[i] = sub(curr_erb[i], t_prev_erb[i]); + move16(); + } + + /* First Band Amplitude Search */ + index[0] = erb_diff_search_fx(t_prev_erb, curr_erb, dif_erb, + PowSpect, AmpCB1_fx, + ERB_CBSIZE1, 10, 1); + move16(); + IF(EQ_16(num_erb, NUM_ERB_NB)) + { + /* Second Band Amplitude Search */ + index[1] = erb_diff_search_fx(t_prev_erb, curr_erb, dif_erb, + PowSpect, AmpCB2_NB_fx, + ERB_CBSIZE2, 9, 11); + move16(); + } + ELSE IF(EQ_16(num_erb, NUM_ERB_WB)) + { + /* Second Band Amplitude Search */ + index[1] = erb_diff_search_fx(t_prev_erb, curr_erb, dif_erb, + PowSpect, AmpCB2_WB_fx, + ERB_CBSIZE2, 11, 11); + move16(); + } + +} diff --git a/lib_enc/pre_proc_fx.c b/lib_enc/pre_proc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..c4fef154b541de20d344d67cf497f3e0b102c495 --- /dev/null +++ b/lib_enc/pre_proc_fx.c @@ -0,0 +1,1310 @@ +/*==================================================================================== + 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 */ + +/*-------------------------------------------------------------------* + * pre_proc() + * + * Pre-processing (spectral analysis, LP analysis, VAD, + * OL pitch calculation, coder mode selection, ...) + *--------------------------------------------------------------------*/ + +void pre_proc_fx( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16 input_frame, /* i : frame length */ + Word16 old_inp_12k8[], /* i/o: buffer of old input signal */ + Word16 old_inp_16k[], /* i/o: buffer of old input signal @ 16kHz */ + Word16** inp, /* o : ptr. to inp. signal in the current frame */ + Word32 fr_bands[2 * NB_BANDS], /* o : energy in frequency bands */ + Word16* Etot, /* o : total energy */ + Word32* ener, /* o : residual energy from Levinson-Durbin */ +#ifndef FIX_I4_OL_PITCH + Word16 pitch_orig[3], /* o : open-loop pitch values for quantization */ +#endif + Word16 A[NB_SUBFR16k * (M + 1)], /* o : A(z) unquantized for the 4 subframes */ + Word16 Aw[NB_SUBFR16k * (M + 1)], /* o : weighted A(z) unquantized for subframes */ + Word16 epsP_h[M + 1], /* o : LP prediction errors */ + Word16 epsP_l[M + 1], /* o : LP prediction errors */ + Word32 epsP[M + 1], /* o : LP prediction errors */ + Word16 lsp_new[M], /* o : LSPs at the end of the frame */ + Word16 lsp_mid[M], /* o : LSPs in the middle of the frame */ + Word16* vad_hover_flag, + Word16* attack_flag, /* o : flag signalling attack encoded by AC mode (GSC) */ + Word16* new_inp_resamp16k, /* o : new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + Word16* Voicing_flag, /* o : voicing flag for HQ FEC */ + + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : cldfb real buffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : cldfb imag buffer */ + CLDFB_SCALE_FACTOR* cldfbScale, /* o : cldfb scale */ + Word16* old_exc, /* i/o: static excitation memory */ + Word16* hq_core_type, /* o : HQ core type */ + Word16* Q_new, + Word16* shift, + Word16* Q_r +) +{ + Word16 delay; + const Word16* signal_in; + + Word16 i; + Word16 *inp_12k8, *new_inp_12k8, *inp_16k, *new_inp_16k; /* pointers to current frame and new data */ + Word16 old_wsp[L_WSP], *wsp; /* weighted input signal buffer */ + Word16 pitch_fr[NB_SUBFR]; /* fractional pitch values */ + Word16 voicing_fr[NB_SUBFR]; /* fractional pitch gains */ + Word32 lf_E[2*VOIC_BINS]; /* per bin spectrum energy in lf */ + Word32 tmpN[NB_BANDS]; /* Temporary noise update */ + Word32 tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + Word32 ee[2]; /* Spectral tilt */ + Word16 corr_shift; /* correlation shift */ + Word16 relE; /* frame relative energy */ + Word16 loc_harm; /* harmonicity flag */ + Word16 cor_map_sum, sp_div; /* speech/music clasif. parameters */ + Word32 PS[128]; + Word16 L_look; /* length of look-ahead */ + + Word16 Q_sp_div, Q_esp; + Word16 localVAD_HE_SAD; /* HE SAD parameters */ + Word16 snr_sum_he; /* HE SAD parameters */ + + Word16 vad_flag_cldfb; + + Word16 vad_flag_dtx; + Word16 old_cor; + Word32 hp_E[2]; /* Energy in HF */ + Word16 noisy_speech_HO, clean_speech_HO, NB_speech_HO; /* SC-VBR HO flags */ + Word16 non_staX; /* unbound non-stationarity for sp/mus clas. */ + Word32 sr_core_tmp; + Word16 L_frame_tmp; + Word16 Q_exp, Q_wsp_exp, Q_new_16k; + Word16 shift_exp; + Word16 Scale_fac[2]; + Word32 Le_min_scaled; + Word16 excitation_max_test; + Word16 lsf_new[M], stab_fac; + Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX]; + Word16 enerBuffer_exp; /*[CLDFB_NO_CHANNELS_MAX];*/ + Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 tmp_e; + Word16 currFlatness; + Word16 high_lpn_flag; + Word16 alw_pitch_lag_12k8[2]; + Word16 alw_voicing[2]; + Word16 flag_spitch; + Word16 sf_energySum[CLDFB_NO_CHANNELS_MAX]; + Word32 L_tmp; + UWord16 lsb; + Word16 fft_buff[2*L_FFT]; + Word16 sp_floor; + Word16 freqTable_local[2] = { 20, 40 }; + Word16 last_core_orig; + Word16 headroom; + Word16 cldfb_addition = 0; move16(); + Word16 old_pitch1; + Word16 clas_mod; + SC_VBR_ENC_HANDLE hSC_VBR = st->hSC_VBR; + GSC_ENC_HANDLE hGSCEnc = st->hGSCEnc; + NOISE_EST_HANDLE hNoiseEst = st->hNoiseEst; + VAD_HANDLE hVAD = st->hVAD; + TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc; + + DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; + RF_ENC_HANDLE hRF = st->hRF; + LPD_state_HANDLE hLPDmem = st->hLPDmem; + FD_BWE_ENC_HANDLE hBWE_FD = st->hBWE_FD; + +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*------------------------------------------------------------------* + * Initializations + *------------------------------------------------------------------*/ + signal_in = st->input; + + vad_flag_dtx = 0; + move16(); + localVAD_HE_SAD = 0; + move16(); + NB_speech_HO = 0; + move16(); + clean_speech_HO = 0; + move16(); + noisy_speech_HO = 0; + move16(); + snr_sum_he = 0; + move16(); + currFlatness = 0; + move16(); + + Q_new_16k = 0; + move16(); + + *vad_hover_flag = 0; + move16(); + st->sp_aud_decision1 = 0; + move16(); + st->sp_aud_decision2 = 0; + move16(); + st->coder_type = GENERIC; + move16(); + hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); + *attack_flag = 0; + move16(); + + IF (hSC_VBR != NULL) + { + hSC_VBR->bump_up = 0; + move16(); + hSC_VBR->ppp_mode = 0; + move16(); + hSC_VBR->nelp_mode = 0; + move16(); + hSC_VBR->avoid_HQ_VBR_NB = 0; + move16(); + } + L_look = L_LOOK_12k8; + move16(); /* lookahead at 12.8kHz */ + + new_inp_12k8 = old_inp_12k8 + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ + inp_12k8 = new_inp_12k8 - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ + Copy( st->old_inp_12k8_fx, old_inp_12k8, L_INP_MEM ); + + Copy( st->old_wsp_fx, old_wsp, L_WSP_MEM ); + wsp = old_wsp + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ + + old_cor = st->old_corr_fx; + move16(); /* save old_cor for speech/music classifier */ + + st->rf_mode = st->Opt_RF_ON; + move16(); + + last_core_orig = st->last_core_fx; + move16(); + + /*--------------------------------------------------------------* + * Cldfb analysis + *---------------------------------------------------------------*/ + + move32(); + move16(); + st->prevEnergyHF_fx = st->currEnergyHF_fx; + tmp_e = st->currEnergyHF_e_fx; + + analysisCldfbEncoder_fx( st, signal_in, realBuffer, imagBuffer, realBuffer16, imagBuffer16, enerBuffer, &enerBuffer_exp, cldfbScale); + cldfbScale->hb_scale = cldfbScale->lb_scale; + + /*----------------------------------------------------------------* + * Change the sampling frequency to 12.8 kHz + *----------------------------------------------------------------*/ + + modify_Fs_fx( signal_in, input_frame, st->input_Fs_fx, new_inp_12k8, INT_FS_12k8, st->mem_decim_fx, (const Word16)(EQ_16(st->max_bwidth_fx,NB))); + Copy( new_inp_12k8, st->buf_speech_enc+L_FRAME32k, L_FRAME ); + Scale_sig( st->buf_speech_enc+L_FRAME32k, L_FRAME, 1 ); + /*------------------------------------------------------------------* + * Perform fixed preemphasis (12.8 kHz signal) through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + /* rf_mode: first time Q_new is computed here inside Preemph_scaled() for primary copy + these are the same memories used in partial frame assembly as well */ + + headroom = 1; + move16(); + test(); + test(); + /* reserve an extra bit of headroom in case of NB coding and if there is a chance of energy above 4 kHz */ + /* st->bwidth_fx refers to the coded bandwidth of the previous frame */ + if( ((EQ_16(st->bwidth_fx, NB))||(EQ_16(st->max_bwidth_fx,NB)))&&(GT_32(st->input_Fs_fx,8000))) + { + headroom = add(headroom, 1); + } + Preemph_scaled( new_inp_12k8, Q_new, &st->mem_preemph_fx, st->Q_max, + PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type_fx, 1 ); + + Q_exp = sub(*Q_new, st->Q_old); + st->prev_Q_old=st->Q_old; + move16(); + st->Q_old = *Q_new; + move16(); + + /*------------------------------------------------------------------* + * Scaling of memories + *-----------------------------------------------------------------*/ + + Le_min_scaled = Scale_mem_pre_proc( st->ini_frame_fx, Q_exp, Q_new, old_inp_12k8, &(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 ); + + /*-------------------------------------------------------------------------* + * Spectral analysis + *--------------------------------------------------------------------------*/ + + analy_sp_fx(-1, +#ifdef IVAS_CODE_CPE + NULL, +#endif + st->input_Fs_fx, inp_12k8, *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 ); + + st->band_energies_exp = sub(sub(WORD32_BITS-1,*Q_new),QSCALE); + move16(); + + /*----------------------------------------------------------------* + * SAD (1-signal, 0-noise) + *----------------------------------------------------------------*/ + + noise_est_pre_fx( *Etot, st->ini_frame_fx, hNoiseEst, 0, EVS_MONO, EVS_MONO); + + 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); + + vad_flag_cldfb = vad_proc_fx(&(st->vad_st), realBuffer, imagBuffer, cldfbScale->lb_scale, &cldfb_addition, + enerBuffer, enerBuffer_exp, st->cldfbAna_Fx->no_channels, st->vad_flag); + + IF ( LT_16( st->Pos_relE_cnt, 20) ) /* Ensure the level is high enough and cldfb decision is reliable */ + { + /* Combine decisions from SADS */ + test(); + IF (EQ_16(st->vad_flag, 1) && vad_flag_cldfb == 0) + { + st->localVAD = 0; + move16(); + } + + st->vad_flag = vad_flag_cldfb; + 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), cldfb_addition, vad_hover_flag, hVAD, hNoiseEst ); + + /*----------------------------------------------------------------* + * NB/WB/SWB/FB bandwidth detector + *----------------------------------------------------------------*/ + + FOR( i=0; i< CLDFB_NO_CHANNELS_MAX; i++ ) + { + sf_energySum[i] = enerBuffer_exp; + move16(); + } + + bw_detect_fx( st, signal_in, NULL, enerBuffer, sf_energySum, MONO_FORMAT, 0); + + /*----------------------------------------------------------------* + * 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 ); + + relE = sub(*Etot, st->lp_speech_fx); /* Q8 */ /* relE = *Etot - st->lp_speech;*/ + + test(); + IF ( GT_16(relE, 384) ) /*relE > 1.5 */ + { + st->Pos_relE_cnt = 0; + move16(); + } + ELSE IF (relE < 0 && EQ_16(st->vad_flag, 1)) + { + st->Pos_relE_cnt = add(st->Pos_relE_cnt, 1); + } + + corr_shift = correlation_shift_fx(hNoiseEst->totalNoise_fx ); + + /*----------------------------------------------------------------* + * FD-CNG Noise Estimator + *----------------------------------------------------------------*/ + + resetFdCngEnc_fx( st ); + perform_noise_estimation_enc_fx( st->band_energies, st->band_energies_exp, enerBuffer, enerBuffer_exp, st->hFdCngEnc_fx ); + + /*-----------------------------------------------------------------* + * Select SID or FRAME_NO_DATA frame if DTX enabled + *-----------------------------------------------------------------*/ + + dtx_fx(st, vad_flag_dtx, inp_12k8, *Q_new); + + /*----------------------------------------------------------------* + * Adjust FD-CNG Noise Estimator + *----------------------------------------------------------------*/ + test(); + IF( (NE_32(st->last_total_brate_fx,st->total_brate_fx))||(NE_16(st->last_bwidth_fx,st->bwidth_fx))) + { + L_tmp = st->total_brate_fx; + move32(); + test(); + if( st->rf_mode && EQ_32(st->total_brate_fx,ACELP_13k20)) + { + L_tmp = ACELP_9k60; + move32(); + } + configureFdCngEnc_fx( st->hFdCngEnc_fx, st->bwidth_fx, L_tmp ); + } + test(); + IF ( st->hFdCngEnc_fx!=NULL && st->Opt_DTX_ON_fx ) + { + AdjustFirstSID_fx( st->hFdCngEnc_fx->hFdCngCom->npart, st->hFdCngEnc_fx->msPeriodog, st->hFdCngEnc_fx->msPeriodog_exp, st->hFdCngEnc_fx->energy_ho, + &st->hFdCngEnc_fx->energy_ho_exp,st->hFdCngEnc_fx->msNoiseEst, &st->hFdCngEnc_fx->msNoiseEst_exp, st->hFdCngEnc_fx->msNoiseEst_old, + &st->hFdCngEnc_fx->msNoiseEst_old_exp, &(st->hFdCngEnc_fx->hFdCngCom->active_frame_counter), st ); + } + + /*----------------------------------------------------------------* + * Reconfigure MODE2 + *----------------------------------------------------------------*/ + + IF ( EQ_16(st->codec_mode,MODE2)) + { + SetModeIndex_fx( st, st->last_total_brate_fx, EVS_MONO, 0, *shift); + } + + calcLoEnvCheckCorrHiLo_Fix( st->cldfbAna_Fx->no_col, freqTable_local, st->hTECEnc->loBuffer, st->hTECEnc->loTempEnv, + st->hTECEnc->loTempEnv_ns, st->hTECEnc->hiTempEnv, &(st->hTECEnc->corrFlag) ); + + /*---------------------------------------------------------------* + * Time-domain transient detector + *---------------------------------------------------------------*/ + + /* Adjust prevEnergyHF and currEnergyHF to same exponent */ + i = sub(st->currEnergyHF_e_fx, tmp_e); + + /* If i > 0: currEnergyHF is higher => shr prevEnergyHF, exponent remains as is */ + st->prevEnergyHF_fx = L_shr(st->prevEnergyHF_fx, s_max(0, i)); + move32(); + + /* If i < 0: currEnergyHF is lower => shr currEnergyHF, exponent changes to previous */ + st->currEnergyHF_fx = L_shl(st->currEnergyHF_fx, s_min(0, i)); + move32(); + + if ( i < 0 ) + { + st->currEnergyHF_e_fx = tmp_e; + move16(); + } + + test(); + IF( st->tcx10Enabled || st->tcx20Enabled ) + { + RunTransientDetection_fx( signal_in, input_frame, &st->transientDetection); + currFlatness = GetTCXAvgTemporalFlatnessMeasure_fx( &st->transientDetection, NSUBBLOCKS, 0 ); + } + + /*----------------------------------------------------------------* + * LP analysis + *----------------------------------------------------------------*/ + + alw_pitch_lag_12k8[0] = st->old_pitch_la; + move16(); + alw_pitch_lag_12k8[1] = st->old_pitch_la; + move16(); + alw_voicing[0] = st->voicing_fx[2]; + move16(); + alw_voicing[1] = st->voicing_fx[2]; + move16(); + + analy_lp_fx( inp_12k8, L_FRAME, L_look, ener, A, epsP_h, epsP_l, lsp_new, lsp_mid, st->lsp_old1_fx, alw_pitch_lag_12k8, alw_voicing, INT_FS_12k8, -1/*IVAS_CODE !! LowRateFlag*/,*Q_new, Q_r ); + + lsp2lsf_fx( lsp_new, lsf_new, M, INT_FS_12k8); + stab_fac = lsf_stab_fx( lsf_new, st->lsf_old1_fx, 0, L_FRAME ); + Copy( lsf_new, st->lsf_old1_fx, M ); + + /*----------------------------------------------------------------* + * Compute weighted input (for OL pitch analysis) + * OL pitch analysis + * 1/4 pitch precision improvement + *----------------------------------------------------------------*/ + + find_wsp_fx( A, inp_12k8, wsp, &st->mem_wsp_fx, TILT_FAC_FX, L_FRAME, L_look, L_SUBFR, Aw, GAMMA1, NB_SUBFR ); + + Q_wsp_exp = Q_exp; + move16(); + Scale_wsp( wsp, &(st->old_wsp_max), shift, &Q_wsp_exp, &(st->old_wsp_shift), st->old_wsp2_fx, + st->mem_decim2_fx, old_wsp, add(L_FRAME, L_look) ); + shift_exp=sub(Q_wsp_exp, Q_exp); + + 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]; + + 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, st->clas_fx, st->bwidth_fx, st->Opt_SC_VBR_fx ); + + /* Updates for adaptive lag window memory */ + st->old_pitch_la = st->pitch_fx[2]; + move16(); + st->old_voicing_la = st->voicing_fx[2]; + move16(); + + /* Detection of very short stable st->pitch_fx period (MODE1 bit-rates) */ + StableHighPitchDetect_fx( &flag_spitch, st->pitch_fx, st->voicing_fx, wsp, st->localVAD, &st->voicing_sm_fx, &st->voicing0_sm_fx, + &st->LF_EnergyRatio_sm_fx, &st->predecision_flag_fx, &st->diff_sm_fx, &st->energy_sm_fx,*Q_new,st->lgBin_E_fx); + + /* 1/4 pitch precision improvement */ + IF( LE_32(st->total_brate_fx,ACELP_24k40)) + { + /* 1/4 pitch precision improvement */ + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch_fx[0], &pitch_fr[0], &voicing_fr[0], 0, wsp, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch_fx[0], &pitch_fr[1], &voicing_fr[1], L_SUBFR, wsp, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch_fx[1], &pitch_fr[2], &voicing_fr[2], 2*L_SUBFR, wsp, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch_fx[1], &pitch_fr[3], &voicing_fr[3], 3*L_SUBFR, wsp, 7 ); + } + ELSE + { + pitch_fr[0] = st->pitch_fx[0]; + move16(); + pitch_fr[1] = st->pitch_fx[0]; + move16(); + pitch_fr[2] = st->pitch_fx[1]; + move16(); + pitch_fr[3] = st->pitch_fx[1]; + move16(); + + voicing_fr[0] = st->voicing_fx[0]; + move16(); + voicing_fr[1] = st->voicing_fx[0]; + move16(); + voicing_fr[2] = st->voicing_fx[1]; + move16(); + voicing_fr[3] = st->voicing_fx[1]; + move16(); + } + + move16(); + + /*------------------------------------------------------------------* + * 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 , &loc_harm, 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); + + /*------------------------------------------------------------------* + * Update parameters used in the VAD and DTX + *-----------------------------------------------------------------*/ + vad_param_updt_fx( st, old_pitch1, corr_shift, corr_shift, A, NULL, 1); + + /*-----------------------------------------------------------------* + * Find spectral tilt + * UC and VC frame selection + *-----------------------------------------------------------------*/ + + find_tilt_fx( fr_bands, hNoiseEst->bckr_fx, ee, st->pitch_fx, st->voicing_fx, lf_E, corr_shift, st->input_bwidth_fx, + st->max_band_fx, hp_E, st->codec_mode, *Q_new, &(st->bckr_tilt_lt), st->Opt_SC_VBR_fx ); + + st->coder_type = find_uv_fx( st, pitch_fr, voicing_fr, inp_12k8, ee, +#ifdef IVAS_CODE + NULL, +#endif + corr_shift, relE, *Etot, hp_E, *Q_new, &flag_spitch, *shift, last_core_orig +#ifdef IVAS_CODE + , NULL +#endif + ); + + /*----------------------------------------------------------------* + * channel aware mode configuration * + *-----------------------------------------------------------------*/ + test(); + test(); + test(); + IF( !st->Opt_RF_ON) + { + st->rf_mode = 0; + st->rf_target_bits_write = 0; + } + ELSE IF( st->rf_mode && NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40)) + { + /* the RF config is for (n- fec_offset)th frame that will be packed along with the n-th frame bitstream */ + st->rf_mode = 1; + st->codec_mode = MODE2; + + st->rf_target_bits_write = hRF->rf_targetbits_buff[st->rf_fec_offset]; + } + ELSE + { + st->rf_mode = 0; + st->codec_mode = MODE1; + IF (st->Opt_RF_ON) + { + hRF->rf_indx_frametype[0] = RF_NO_DATA; + hRF->rf_targetbits_buff[0] = 6; /* rf_mode: 1, rf_frame_type: 3, and fec_offset: 2 */ + } + } + + /*-----------------------------------------------------------------* + * Signal classification for FEC + * TC frame selection + *-----------------------------------------------------------------*/ + + st->clas_fx = signal_clas_fx( st, inp_12k8, ee, relE, L_look, &clas_mod); + + select_TC_fx(st->codec_mode, st->tc_cnt_fx, &st->coder_type, st->localVAD); + + /* limit coder_type depending on the bitrate */ + coder_type_modif_fx(st, relE); + + + if (st->Opt_SC_VBR_fx) + { + hSC_VBR->Local_VAD = st->localVAD; + move16(); + } + /*----------------------------------------------------------------* + * Speech/music classification + * AC frame selection + *----------------------------------------------------------------*/ + + FOR( i=0; iOpt_DTX_ON_fx ) + { + st->vad_flag = vad_flag_dtx; + move16(); /* flag now with the DTX-HO for use in further high rate encoding below */ + } + + /*----------------------------------------------------------------* + * Selection of internal ACELP Fs (12.8 kHz or 16 kHz) + *----------------------------------------------------------------*/ + + IF( EQ_16(st->codec_mode,MODE1)) + { + test();test();test();test(); + test();test();test();test();test();test();test();test();test();test(); + IF( EQ_32(st->core_brate_fx,FRAME_NO_DATA)) + { + /* prevent "L_frame" changes in CNG segments */ + st->L_frame_fx = st->last_L_frame_fx; + move16(); + } + ELSE IF ( EQ_32(st->core_brate_fx,SID_2k40) && GE_16(st->bwidth_fx,WB) && hDtxEnc->first_CNG && (hTdCngEnc != NULL && LT_16(hTdCngEnc->act_cnt2,MIN_ACT_CNG_UPD))) + { + /* prevent "L_frame" changes in SID frame after short segment of active frames */ + st->L_frame_fx = hDtxEnc->last_CNG_L_frame; + move16(); + } + ELSE IF ( ( EQ_32(st->core_brate_fx,SID_2k40)&&GE_32(st->total_brate_fx,ACELP_9k60)&&((EQ_16(st->bwidth_fx,WB)&&!(EQ_32(st->total_brate_fx,ACELP_13k20)&&EQ_16(st->cng_type_fx,FD_CNG)))||(EQ_16(st->cng_type_fx,LP_CNG)&>_16(st->bwidth_fx,WB)&&GE_32(st->total_brate_fx,ACELP_16k40))))|| + ( GT_32(st->total_brate_fx,ACELP_24k40) && LT_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(); + } + ELSE + { + st->L_frame_fx = L_FRAME; + move16(); + } + + if( st->ini_frame_fx == 0 ) + { + /* avoid switching of internal ACELP Fs in the very first frame */ + st->last_L_frame_fx = st->L_frame_fx; + move16(); + } + + IF( EQ_16(st->L_frame_fx,L_FRAME)) + { + st->gamma = GAMMA1; + move16(); + st->preemph_fac = PREEMPH_FAC; + move16(); + } + ELSE + { + st->gamma = GAMMA16k; + move16(); + st->preemph_fac = PREEMPH_FAC_16k; + move16(); + } + + st->sr_core = L_mult0(FRAMES_PER_SEC,st->L_frame_fx); + st->encoderLookahead_enc = NS2SA_fx2(st->sr_core, ACELP_LOOK_NS); + move16(); + st->encoderPastSamples_enc = shr(imult1616(st->L_frame_fx, 9), 4); + } + + /*-----------------------------------------------------------------* + * coder_type rewriting in case of switching + * IC frames selection + * enforce TC frames in case of switching + *-----------------------------------------------------------------*/ + + IF( EQ_16(st->codec_mode,MODE1)) + { + /* enforce TRANSITION frames */ + test();test();test();test();test();test();test();test(); + test();test();test();test();test(); + IF( NE_16(st->last_L_frame_fx,st->L_frame_fx) && NE_32(st->core_brate_fx,FRAME_NO_DATA) && NE_32(st->core_brate_fx,SID_2k40) && (NE_16(st->coder_type_raw_fx,VOICED))) + { + /* enforce TC frame in case of ACELP@12k8 <-> ACELP@16k core switching */ + st->coder_type = TRANSITION; + move16(); + } + ELSE IF( EQ_16(st->last_core_fx,HQ_CORE) || EQ_16(st->last_core_fx,TCX_10_CORE) || EQ_16(st->last_core_fx,TCX_20_CORE)) + { + /* enforce TC frame in case of HQ/TCX -> ACELP core switching */ + st->coder_type = TRANSITION; + move16(); + } + ELSE IF( LE_32(st->last_core_brate_fx,SID_2k40) && EQ_16(st->cng_type_fx,FD_CNG)) + { + /* enforce TC frame in case of FD_CNG -> ACELP switching (past excitation not available) */ + st->coder_type = TRANSITION; + move16(); + } + + /* select INACTIVE frames */ + ELSE IF( LE_32(st->total_brate_fx,ACELP_24k40) && st->vad_flag==0) + { + /* inactive frames will be coded by GSC technology */ + /* except for the VBR mode. VBR mode uses NELP for that */ + test(); + IF ( !( EQ_16(st->Opt_SC_VBR_fx, 1) && EQ_16(vad_flag_dtx,1))) + { + st->coder_type = INACTIVE; + move16(); + hGSCEnc->noise_lev = NOISE_LEVEL_SP3; + move16(); + } + } + ELSE IF( GT_32(st->total_brate_fx,ACELP_24k40)&& + ( (st->vad_flag == 0 && GE_16(st->bwidth_fx,SWB) && GE_16(st->max_bwidth_fx,SWB) ) || (st->localVAD == 0 && (LE_16(st->bwidth_fx,WB) || LE_16(st->max_bwidth_fx,WB))) ) + ) + { + /* inactive frames will be coded by AVQ technology */ + st->coder_type = INACTIVE; + move16(); + } + } + ELSE + { + IF( !(st->vad_flag) ) + { + st->coder_type = INACTIVE; + move16(); + } + ELSE IF( GT_16(st->coder_type,GENERIC)) + { + st->coder_type = GENERIC; + move16(); + } + } + + /*---------------------------------------------------------------* + * SC-VBR - decision about PPP/NELP mode + *---------------------------------------------------------------*/ + + IF( st->Opt_SC_VBR_fx ) + { + set_ppp_mode_fx( st, noisy_speech_HO, clean_speech_HO, NB_speech_HO, localVAD_HE_SAD); + } + test(); + IF ( !st->Opt_AMR_WB_fx && !st->rf_mode ) + { + test(); + test(); + IF ( EQ_32(st->total_brate_fx,ACELP_13k20)||EQ_32(st->total_brate_fx,ACELP_32k)) + { + st->mdct_sw_enable = MODE1; + move16(); + } + ELSE IF ( LE_32(ACELP_16k40,st->total_brate_fx)&&LE_32(st->total_brate_fx,ACELP_24k40)) + { + st->mdct_sw_enable = MODE2; + move16(); + } + } + + /*---------------------------------------------------------------------* + * Decision matrix (selection of technologies) + *---------------------------------------------------------------------*/ + IF( EQ_16(st->codec_mode,MODE1)) + { + + decision_matrix_enc_fx( st, hq_core_type ); + + /* HQ_CORE/TCX_20_CORE decision */ + IF ( EQ_16(st->core_fx,HQ_CORE)) /* Decision matrix decided for MDCT coding */ + { + test(); + test(); + IF( (EQ_16(st->bwidth_fx,SWB) || EQ_16(st->bwidth_fx,FB)) && EQ_32(st->total_brate_fx, ACELP_32k)) + { + /* Select MDCT Core */ + st->core_fx = mdct_classifier_fx(fft_buff,st, enerBuffer,sub(enerBuffer_exp, 31), st->total_brate_fx); + } + test(); + IF( (EQ_32(st->total_brate_fx, ACELP_13k20)) && (NE_16(st->bwidth_fx,FB))) + { + MDCT_selector_fx( st, sp_floor, *Etot, cor_map_sum, enerBuffer, enerBuffer_exp); + } + } + ELSE + { + MDCT_selector_reset_fx(hTcxEnc); + } + + /* Switch to MODE2 if TCX_20_CORE */ + IF( EQ_16(st->core_fx,TCX_20_CORE)) + { + st->codec_mode = MODE2; + move16(); + IF( EQ_16(st->last_codec_mode,MODE1)) + { + Word32 last_total_brate = L_add(st->last_total_brate_fx, 0); + st->last_total_brate_fx = -1; + move32(); + SetModeIndex_fx( st, st->last_total_brate_fx, EVS_MONO, 0, *shift ); + st->last_total_brate_fx = last_total_brate; + move32(); + } + ELSE + { + SetModeIndex_fx( st, st->last_total_brate_fx, EVS_MONO, 0, *shift); + st->sr_core = getCoreSamplerateMode2(st->element_mode, st->total_brate_fx, st->bwidth_fx, st->flag_ACELP16k, st->rf_mode, 0 ); + + Mpy_32_16_ss(st->sr_core, 5243, &L_tmp, &lsb); /* 5243 is 1/50 in Q18. (0+18-15=3) */ + st->L_frame_fx = extract_l(L_shr(L_tmp, 3)); /* Q0 */ + st->encoderLookahead_enc = NS2SA_fx2(st->sr_core, ACELP_LOOK_NS); + move16(); + st->encoderPastSamples_enc = shr(imult1616(st->L_frame_fx, 9), 4); + assert(st->L_frame_fx == st->sr_core / 50); + + IF ( EQ_32(st->sr_core, INT_FS_12k8)) + { + st->preemph_fac = PREEMPH_FAC; + move16(); + st->gamma = GAMMA1; + move16(); + } + ELSE + { + st->preemph_fac = PREEMPH_FAC_16k; + move16(); + st->gamma = GAMMA16k; + move16(); + } + + st->igf = getIgfPresent_fx(st->element_mode, st->total_brate_fx, st->bwidth_fx, st->rf_mode); + } + + st->coder_type = st->coder_type_raw_fx; + move16(); + + IF( st->vad_flag == 0 ) + { + st->coder_type = INACTIVE; + move16(); + } + ELSE IF( GT_16((st->coder_type),GENERIC)) + { + st->coder_type = GENERIC; + move16(); + } + + st->mdct_sw = MODE1; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Update of ACELP harmonicity counter (used in ACELP transform codebook @32kbps) + *-----------------------------------------------------------------*/ + + test();test(); + test();test(); + IF( EQ_32(st->total_brate_fx, ACELP_32k)&&EQ_16(loc_harm,1)&>_16(cor_map_sum,50<<8) + && EQ_16(st->clas_fx, VOICED_CLAS) && EQ_16(st->coder_type,GENERIC) ) + { + st->last_harm_flag_acelp_fx = add(st->last_harm_flag_acelp_fx,1); + st->last_harm_flag_acelp_fx = s_min(st->last_harm_flag_acelp_fx,10); + } + ELSE + { + st->last_harm_flag_acelp_fx = 0; + move16(); + } + + /*-----------------------------------------------------------------* + * Update audio frames counter (used for UV decision) + *-----------------------------------------------------------------*/ + + IF( EQ_16(st->coder_type,AUDIO)) + { + st->audio_frame_cnt_fx = add(st->audio_frame_cnt_fx,AUDIO_COUNTER_STEP); + } + ELSE IF (NE_16(st->coder_type,INACTIVE)) + { + st->audio_frame_cnt_fx = sub(st->audio_frame_cnt_fx,1); + } + + st->audio_frame_cnt_fx = s_min(st->audio_frame_cnt_fx,AUDIO_COUNTER_MAX); + st->audio_frame_cnt_fx = s_max(st->audio_frame_cnt_fx,0); + + /*-----------------------------------------------------------------* + * Set formant sharpening flag + *-----------------------------------------------------------------*/ + + st->sharpFlag = 0; + move16(); + IF( EQ_16(st->coder_type,TRANSITION)) + { + test();test();test();test();test(); + IF( ( GT_32(st->total_brate_fx,ACELP_48k)&<_16(st->bwidth_fx,SWB))|| /* Deactivate for core bitrates higher than 48.0 kb/s */ + ( GE_32(st->total_brate_fx,ACELP_13k20) && LE_32(st->total_brate_fx,ACELP_16k40) ) || /* Deactivate for bitrates <13.2, 16.4> kb/s (this is basically due to lack of signaling configurations */ + ( GT_32(st->total_brate_fx,ACELP_16k40)&>_16(st->lp_noise_fx,FORMANT_SHARPENING_NOISE_THRESHOLD_FX))) /* Deactivate for bitrates >= 24.4 kb/s if the long-term noise level exceeds 34 dB */ + { + st->sharpFlag= 0; + move16(); + } + ELSE + { + st->sharpFlag= 1; + move16(); + } + } + + test(); + IF( EQ_16(st->coder_type,GENERIC)||EQ_16(st->coder_type,VOICED)) + { + test();test();test();test();test(); + IF( *vad_hover_flag || + ( GT_32(st->total_brate_fx,ACELP_48k) && LT_16(st->bwidth_fx,SWB) ) || /* Deactivate for core bitrates higher than 48.0 kb/s */ + ( GE_32(st->total_brate_fx,ACELP_13k20)&>_16(st->lp_noise_fx,FORMANT_SHARPENING_NOISE_THRESHOLD_FX) /* Deactivate for bitrates >= 13.2 kb/s if the long-term noise level exceeds 34 dB */ + && GT_32(st->total_brate_fx,CNA_MAX_BRATE) ) ) + { + st->sharpFlag = 0; + move16(); + } + ELSE + { + st->sharpFlag = 1; + move16(); + } + } + + /* channel-aware mode - due to lack of signalling bit, sharpFlag is 1 always in RF mode */ + test(); + test(); + IF( EQ_16(st->rf_mode,1)&&(EQ_16(st->coder_type,VOICED)||EQ_16(st->coder_type,GENERIC))) + { + st->sharpFlag = 1; + } + + /*-----------------------------------------------------------------* + * Set voicing flag for HQ FEC + *-----------------------------------------------------------------*/ + + *Voicing_flag = 0; + move16(); + test(); + test(); + if ( st->sp_aud_decision1 == 0 && ( EQ_16(st->coder_type,VOICED)||EQ_16(st->coder_type,GENERIC))) + { + *Voicing_flag = 1; + move16(); + } + + /*---------------------------------------------------------------* + * Preprocessing at other sampling frequency rate (16/25.6/32kHz) + *----------------------------------------------------------------*/ + + sr_core_tmp = L_max(INT_FS_16k_FX,st->sr_core); /* indicates the ACELP sampling rate for MODE2, 16 kHz for MODE1 */ + if( EQ_16(st->codec_mode,MODE1)) + { + sr_core_tmp = INT_FS_16k_FX; + move32(); + } + + L_frame_tmp = s_max(L_FRAME16k,st->L_frame_fx); + if( EQ_16(st->codec_mode,MODE1)) + { + L_frame_tmp = L_FRAME16k; + move16(); + } + L_look = NS2SA_fx2(sr_core_tmp, ACELP_LOOK_NS); + move16(); /* lookahead at other sampling rate (16kHz, 25.5kHz, 32kHz) */ + + 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; /* pointer to the current frame of input signal in 16kHz core */ + Copy( st->old_inp_16k_fx, old_inp_16k, L_INP_MEM ); /* Note: The merory has been rescaled at the begining of the function*/ + + /*---------------------------------------------------------------* + * Change the sampling frequency to 16/25.6/32 kHz + *----------------------------------------------------------------*/ + + test(); + IF( EQ_32(st->input_Fs_fx,sr_core_tmp)) + { + /* no resampling needed, only delay adjustement to account for the FIR resampling delay */ + delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + Copy_Scale_sig( st->mem_decim16k_fx + delay, new_inp_16k, delay, -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */ + Copy_Scale_sig( signal_in, new_inp_16k + delay, input_frame - delay, -1 ); /* Input in Q0 -> Output in Q-1 to mimic the resampling filter */ + Copy( signal_in + input_frame - shl(delay,1), st->mem_decim16k_fx, shl(delay,1) ); /* memory still in Q0 */ + } + ELSE IF( EQ_32(st->input_Fs_fx,32000)||EQ_32(st->input_Fs_fx,48000)) + { + modify_Fs_fx( signal_in, input_frame, st->input_Fs_fx, new_inp_16k, sr_core_tmp, st->mem_decim16k_fx, 0 ); + } + ELSE /* keep memories up-to-date in case of bitrate switching */ + { + /* no resampling needed, only delay adjustement to account for the FIR resampling delay */ + delay = NS2SA_fx2(st->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + Copy( st->mem_decim16k_fx + delay, new_inp_16k, delay ); + Copy( signal_in, new_inp_16k + delay, sub(input_frame, delay) ); + Copy( signal_in + sub(input_frame, shl(delay,1)), st->mem_decim16k_fx, shl(delay,1) ); + } + + IF( EQ_32(sr_core_tmp, INT_FS_16k)) + { + /* save input resampled at 16kHz, non-preemhasised */ + Copy( new_inp_16k, new_inp_resamp16k, L_FRAME16k ); + } + ELSE IF( GT_32(sr_core_tmp, INT_FS_16k)) + { + /* reset the buffer, the signal is needed for WB BWEs */ + set16_fx( new_inp_resamp16k, 0, L_FRAME16k ); + } + + /*------------------------------------------------------------------* + * Perform fixed preemphasis (16kHz signal) through 1 - g*z^-1 + *-----------------------------------------------------------------*/ + + test(); + test(); + IF( ((st->tcxonly == 0) || (EQ_16(st->codec_mode,MODE1)))&>_32(st->input_Fs_fx,8000)) + { +#ifdef BASOP_NOGLOB + st->mem_preemph_enc = shl_o(new_inp_16k[sub(L_frame_tmp,1)],1, &Overflow); +#else /* BASOP_NOGLOB */ + st->mem_preemph_enc = shl(new_inp_16k[sub(L_frame_tmp,1)],1); +#endif + } + + test(); + IF( GT_32(st->input_Fs_fx,8000)&&EQ_32(sr_core_tmp, INT_FS_16k)) + { + Preemph_scaled( new_inp_16k, &Q_new_16k, &(st->mem_preemph16k_fx), st->Q_max_16k, PREEMPH_FAC_16k, 0, 1, L_Q_MEM, L_FRAME16k, st->last_coder_type_fx, 1); + } + ELSE IF( GT_32(st->input_Fs_fx,8000)) /* keep memory up-to-date in case of bit-rate switching */ + { + st->mem_preemph16k_fx = new_inp_16k[sub(L_frame_tmp,1)]; + move16(); + } + + /*------------------------------------------------------------------* + * Core-encoder memories scaling + *-----------------------------------------------------------------*/ + + test();test();test();test();test();test(); + IF( ( ((st->tcxonly == 0) || !(NE_32(st->core_brate_fx,FRAME_NO_DATA) || NE_32(st->core_brate_fx,SID_2k40))) && EQ_16(st->L_frame_fx,L_FRAME16k) && EQ_16(st->codec_mode,MODE2)) || + ( EQ_16(st->L_frame_fx,L_FRAME16k) && EQ_16(st->codec_mode,MODE1) ) ) + { + *Q_new = Q_new_16k; + move16(); + } + ELSE + { + IF( GT_32(st->input_Fs_fx,8000)&&EQ_32(sr_core_tmp,16000)) + { + Scale_sig(new_inp_16k, L_FRAME16k, sub(*Q_new,Q_new_16k)); + } + } + + /* Above computed Q_new is used to scale primary copy exc and memory here by (Q_new, st->prev_Q_new) */ + + Q_exp = sub(*Q_new, st->prev_Q_new); + move16(); + Q_wsp_exp = add(Q_exp,shift_exp); + + 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 ); + + /*-----------------------------------------------------------------* + * Redo LP analysis at 16kHz if ACELP@16k core was selected + * update buffers + *-----------------------------------------------------------------*/ + + test(); + test(); + test(); + test(); + test(); + test(); +#ifndef CR_2109_to_2112_cd0_ce0 + IF((((st->tcxonly == 0) || !(NE_32(st->core_brate_fx, FRAME_NO_DATA) || NE_32(st->core_brate_fx, SID_2k40))) && EQ_16(st->L_frame_fx, L_FRAME16k) && EQ_16(st->codec_mode, MODE2)) || (EQ_16(st->L_frame_fx, L_FRAME16k) && EQ_16(st->codec_mode, MODE1)) ) +#else + IF((((st->tcxonly == 0) || !(NE_32(st->core_brate_fx,FRAME_NO_DATA) && NE_32(st->core_brate_fx,SID_2k40))) && EQ_16(st->L_frame_fx,L_FRAME16k) && EQ_16(st->codec_mode,MODE2)) || ( EQ_16(st->L_frame_fx,L_FRAME16k) && EQ_16(st->codec_mode,MODE1))) +#endif + { + /* update signal buffers */ + Copy( new_inp_resamp16k, st->buf_speech_enc+L_FRAME16k, L_FRAME16k ); + Scale_sig( st->buf_speech_enc+L_FRAME16k, L_FRAME16k, 1 ); + Copy( new_inp_16k, st->buf_speech_enc_pe+L_FRAME16k, L_FRAME16k ); + 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); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + test(); + IF( EQ_16(st->last_L_frame_fx,L_FRAME)&&EQ_16(st->codec_mode,MODE1)) + { + /* this is just an approximation, but it is sufficient */ + Copy( st->lsp_old1_fx, st->lspold_enc_fx, M ); + } + + analy_lp_fx( inp_16k, L_FRAME16k, L_look, ener, A, epsP_h, epsP_l, lsp_new, lsp_mid, st->lspold_enc_fx, st->pitch_fx, st->voicing_fx, 16000, -1/*IVAS_CODE !! LowRateFlag*/, *Q_new, Q_r ); + + /*--------------------------------------------------------------* + * Compute Weighted Input + *---------------------------------------------------------------*/ + + IF( EQ_16(st->codec_mode,MODE2)) + { + find_wsp_fx( A, st->speech_enc_pe, st->wspeech_enc, &st->mem_wsp_enc, PREEMPH_FAC_16k, L_FRAME16k, L_LOOK_16k, L_SUBFR, Aw, st->gamma, st->nb_subfr); + + /* This need to be harmonized with MODE2 */ + Scale_sig( st->wspeech_enc, L_FRAME16k+L_LOOK_16k, *shift ); + + } + ELSE + { + weight_a_subfr_fx( NB_SUBFR16k, A, Aw, GAMMA16k, M ); + } + } + ELSE + { + /* update signal buffers */ + Copy( new_inp_12k8, st->buf_speech_enc_pe+st->L_frame_fx, L_FRAME ); + Copy( st->buf_speech_enc+L_FRAME32k, st->buf_speech_enc+st->L_frame_fx, L_FRAME ); + + if ( st->tcxonly == 0 ) + { + Copy( wsp, st->buf_wspeech_enc+st->L_frame_fx+L_SUBFR, L_FRAME + L_LOOK_12k8 ); + } + test(); + test(); + IF( EQ_16(st->codec_mode,MODE2)&&st->tcxonly==0&&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 ); + } + } + + 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) + { + excitation_max_test = 1; + move16(); + *shift = -1; + move16(); + st->old_wsp_shift=-1; + move16(); + Scale_sig( old_wsp, L_WSP_MEM+L_FRAME+L_LOOK_12k8, -1 ); + } + ELSE + { + excitation_max_test = 0; + move16(); + } + + test(); + IF ( EQ_16(st->codec_mode,MODE2)&&st->tcxonly==0) + { + IF (Q_wsp_exp != 0) + { + Scale_sig(st->buf_wspeech_enc, st->L_frame_fx+L_SUBFR, Q_wsp_exp); + } + IF( EQ_16(excitation_max_test,1)) + { + Scale_sig( st->buf_wspeech_enc, st->L_frame_fx+L_SUBFR+st->L_frame_fx+st->encoderLookahead_enc, -1 ); + } + } + + /*-----------------------------------------------------------------* + * ACELP/TCX20/HQ Switching Decision + *-----------------------------------------------------------------*/ + +#ifndef FIX_I4_OL_PITCH + Copy(st->pitch_fx, pitch_orig, 3); +#endif + IF ( EQ_16(st->codec_mode,MODE2)) + { + test(); + test(); + IF((NE_32(st->core_brate_fx,FRAME_NO_DATA)&&NE_32(st->core_brate_fx,SID_2k40)&&st->tcxonly==0)) + { + core_acelp_tcx20_switching_fx( st, non_staX, pitch_fr, voicing_fr, currFlatness, lsp_mid, stab_fac, *Q_new, *shift ); + } + + test(); + IF (EQ_16(st->mdct_sw_enable,MODE2)&&!st->rf_mode) + { + IF (EQ_16(st->core_fx,TCX_20_CORE)) /* Switching only possible from TCX_20 frames, not from TCX_10 frames */ + { + /* Select MDCT Core */ + test(); + test(); + IF ((EQ_16(st->bwidth_fx,SWB) || EQ_16(st->bwidth_fx,FB)) && EQ_32(st->total_brate_fx, ACELP_24k40)) + { + st->core_fx = mdct_classifier_fx(fft_buff,st, enerBuffer, sub(enerBuffer_exp, 31), st->total_brate_fx); + } + test(); + IF ((EQ_32(st->total_brate_fx, ACELP_16k40)) && (NE_16(st->bwidth_fx,FB))) + { + MDCT_selector_fx( st, sp_floor, *Etot, cor_map_sum, enerBuffer, enerBuffer_exp ); + } + } + ELSE + { + MDCT_selector_reset_fx(hTcxEnc); + } + + /* Do the switching that was decided in the MDCT selector */ + test(); + IF( EQ_16(st->core_fx,HQ_CORE)) + { + st->codec_mode = MODE1; + move16(); + st->mdct_sw = MODE2; + move16(); + } + ELSE IF( EQ_16(st->last_codec_mode,MODE1)&&EQ_16(st->last_core_fx,HQ_CORE)) + { + Word16 L_frame_old = st->last_L_frame_fx; + move16(); + st->last_L_frame_fx = st->L_frame_fx; + move16(); + SetModeIndex_fx( st, st->last_total_brate_fx, EVS_MONO, 0, *shift); + st->last_L_frame_fx = L_frame_old; + move16(); + } + } + + /*--------------------------------------------------------------* + * TCX mode decision + *---------------------------------------------------------------*/ + + SetTCXModeInfo_fx( st, &st->transientDetection, &st->hTcxCfg->tcx_curr_overlap_mode ); + } + + /*-----------------------------------------------------------------* + * 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_12k8[L_FRAME], st->old_inp_12k8_fx, L_INP_MEM ); + + /* update old input signal @16kHz buffer */ + test(); + IF( GT_32(st->input_Fs_fx,8000)&&EQ_32(sr_core_tmp, INT_FS_16k)) + { + Copy( &old_inp_16k[L_frame_tmp], st->old_inp_16k_fx, L_INP_MEM ); + } + ELSE IF( GT_32(st->input_Fs_fx,8000)) + { + lerp( st->old_inp_12k8_fx+L_INP_MEM-L_INP_MEM*4/5, st->old_inp_16k_fx, L_INP_MEM, L_INP_MEM*4/5); + Scale_sig(st->old_inp_16k_fx, L_INP_MEM, sub(*Q_new,st->Q_old)); + } + + test(); + test(); + IF( (EQ_32(sr_core_tmp, INT_FS_16k))&&st->tcxonly&&EQ_16(st->codec_mode,MODE2)) + { + /* copy input resampled at 16kHz, non-preemhasised */ + Copy( new_inp_resamp16k, new_inp_16k, L_FRAME16k ); + } + + /* update of old per-band energy spectrum */ + Copy32( fr_bands + NB_BANDS, hNoiseEst->enrO_fx, NB_BANDS ); + + /* set the pointer of the current frame for the ACELP core */ + *inp = inp_16k; + if ( EQ_16(st->L_frame_fx,L_FRAME)) + { + *inp = inp_12k8; + } + + /* Update vAD hangover frame counter in active frames */ + if ((NE_16(st->core_fx, HQ_CORE) && st->tcxonly == 0) || EQ_16(st->core_fx, ACELP_CORE)) + { + + IF(!(EQ_32(st->core_brate_fx, SID_2k40) || EQ_32(st->core_brate_fx, FRAME_NO_DATA))) + { + test(); + IF(st->Opt_DTX_ON_fx != 0 && *vad_hover_flag != 0) + { + hTdCngEnc->burst_ho_cnt = add(hTdCngEnc->burst_ho_cnt, 1); + hTdCngEnc->burst_ho_cnt = s_min(hTdCngEnc->burst_ho_cnt, HO_HIST_SIZE); + } + ELSE + { + IF(hTdCngEnc != NULL && vad_flag_dtx != 0) + { + hTdCngEnc->burst_ho_cnt = 0; + move16(); + } + } + + } + } + + return; +} diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h new file mode 100644 index 0000000000000000000000000000000000000000..b0e62236a1ff41794f45a353d634c32a2ba8e667 --- /dev/null +++ b/lib_enc/prot_fx_enc.h @@ -0,0 +1,3286 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#ifndef PROT_FX_ENC_H +#define PROT_FX_ENC_H + +#include "ivas_cnst.h" +#include "stat_enc.h" +#include "stat_dec.h" +#include "ivas_stat_dec.h" +#include "ivas_error.h" +#include "ivas_error_utils.h" +#include "complex_basop.h" +#include "ivas_stat_enc.h" +/*----------------------------------------------------------------------------------* + * Prototypes of RAM counting tool macros + *----------------------------------------------------------------------------------*/ +ivas_error acelp_core_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 inp_fx[], /* i : i 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 +); + +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 +); + +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 i */ +); + +void AVQ_encmux_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + const Word16 extl, /* i : extension layer */ + Word16 xriq[], /* i/o: rounded subvectors [0..8*Nsv-1] followed + by rounded bit allocations [8*Nsv..8*Nsv+Nsv-1] */ + Word16* nb_bits, /* i/o: number of allocated bits */ + const Word16 Nsv, /* i: number of subvectors */ + Word16 nq_out[], /* o : AVQ nq index */ + Word16 avq_bit_sFlag, /* i : flag for AVQ bit saving solution */ + Word16 trgtSvPos /* i : target SV for AVQ bit savings */ +); + +void bw_detect_fx( + Encoder_State_fx* st, /* i/o: Encoder State */ + const Word16 signal_in[], /* i : i 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 */ +); + +void core_switching_post_enc_fx( /*done */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 inp12k8[], /* i : i signal @12.8 kHz */ + const Word16 inp16k[], /* i : i signal @16 kHz */ + 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 */ +); + +void core_switching_pre_enc_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word16* old_inp_12k8, /* i : old i signal @12.8kHz */ + const Word16* old_inp_16k, /* i : old i signal @16kHz */ + const Word16 active_cnt, /* i : active frame counter */ + const Word16 last_element_mode /* i : last_element_mode */ +); + +Word16 correlation_shift_fx( /* o : noise dependent voicing correction Q15 */ + const Word16 totalNoise_fx /* i/o: noise estimate over all critical bands Q8 */ +); + +void dtx_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 vad, /* i : vad flag */ + const Word16 speech[], /* i : Pointer to the speech frame */ + Word16 Q_speech /* i : Q factor for speech */ + +); + +Word16 dtx_hangover_addition_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word16 vad_flag, /* i Q0 */ + const Word16 lp_snr, /* i Q8 */ + const Word16 cldfb_subtraction, /* i Q0 number of DTX-HO frames CLDFB wants to reduce */ + Word16* vad_hover_flag_ptr, + VAD_HANDLE hVAD, /* i/o: VAD data handle */ + NOISE_EST_HANDLE hNoiseEst /* i : Noise estimation handle */ +); + +void fb_tbe_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : i speech at 48 kHz sample rate */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part */ + Word16 Q_fb_exc +); + +void fb_tbe_reset_enc_fx( + Word32 elliptic_bpf_2_48k_mem_fx[][4], + Word32 *prev_fb_energy_fx, + Word16 elliptic_bpf_2_48k_mem_fx_Q[], + Word16 *prev_fb_energy_fx_Q +); + +Word16 ffr_getSfWord32( + const Word32* vector, /*!< Pointer to i vector */ + const Word16 len /*!< Length of i vector */ +); + +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 : i 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 + , Word16 Opt_vbr_mode +); + +Word16 find_uv_fx( /* o : coding type */ + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word16* T_op_fr, /* i : pointer to adjusted fractional pitch (4 val.) Q6*/ + const Word16* voicing_fr, /* i : refined correlation for each subframes Q15*/ + const Word16* speech, /* i : pointer to speech signal for E computation Q_new*/ + const Word32* ee, /* i : lf/hf Energy ratio for present frame Q6*/ +#ifdef IVAS_CODE + Word32* dE1X, /* o : sudden energy increase for S/M classifier */ +#endif + const Word16 corr_shift, /* i : normalized correlation correction in noise Q15*/ + const Word16 relE, /* i : relative frame energy Q8*/ + const Word16 Etot, /* i : total energy Q8*/ + const Word32 hp_E[], /* i : energy in HF Q_new + Q_SCALE*/ + const Word16 Q_new, + Word16* flag_spitch, /* i/o: flag to indicate very short stable pitch and high correlation */ + const Word16 shift, + const Word16 last_core_orig /* i : original last core */ +#ifdef IVAS_CODE + , STEREO_CLASSIF_HANDLE hStereoClassif /* i/o: stereo classifier structure */ +#endif +); + +void fine_gain_quant_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *ord, /* i : Indices for energy order */ + const Word16 num_sfm, /* i : Number of bands */ + const Word16 *gain_bits, /* i : Gain adjustment bits per sub band */ + Word16 *fg_pred, /* i/o: Predicted gains / Corrected gains Q12 */ + const Word16 *gopt /* i : Optimal gains Q12 */ +); + +void hq_core_enc_fx( + Encoder_State_fx* st_fx, + const Word16* audio, /* i : i audio signal Q0 */ + const Word16 input_frame_orig, /* i : frame length */ + const Word16 hq_core_type, /* i : HQ core type */ + const Word16 Voicing_flag, /* i : Voicing flag for FER method selection */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +); + +void long_enr_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 Etot, /* i : total channel E (see lib_enc\analy_sp.c) */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + Word16 high_lpn_flag +); + +Word16 mdct_classifier_fx( /* o: MDCT A/B decision */ + const Word16 *Y, /* i: re[0], re[1], ..., re[n/2], im[n/2 - 1], im[n/2 - 2], ..., im[1] */ + Encoder_State_fx *st_fx, /* i/o: Encoder state variable */ + Word32 *cldfbBuf_Ener, + Word16 enerBuffer_exp, + const Word32 brate /* i : current brate, IVAS: nominal bitrate, EVS: st->total_brate */ +); + +void noise_est_down_fx( + const Word32 fr_bands[], /* i : per band i energy (contains 2 vectors) */ + Word32 bckr[], /* i/o: per band background noise energy estimate */ + Word32 tmpN[], /* o : temporary noise update */ + Word32 enr[], /* o : averaged energy over both subframes */ + const Word16 min_band, /* i : minimum critical band */ + const Word16 max_band, /* i : maximum critical band */ + Word16 *totalNoise, /* o : noise estimate over all critical bands */ + Word16 Etot, /* i : Energy of current frame */ + Word16 *Etot_last, /* i/o: Energy of last frame Q8 */ + Word16 *Etot_v_h2, /* i/o: Energy variations of noise frames Q8 */ + Word16 Q_new, + const Word32 e_min /* i : minimum energy scaled Q_new + QSCALE */ +); + +void noise_est_fx( + Encoder_State_fx* st_fx, /* i/o: state structure */ + const Word16 old_pitch1, /* i : previous frame OL pitch[1] */ + const Word32 tmpN[], /* i : temporary noise update Q_new + QSCALE */ + const Word16 epsP_h[], /* i : msb prediction error energies Q_r-1 */ + const Word16 epsP_l[], /* i : msb prediction error energies Q_r-1 */ + const Word16 Etot, /* i : total channel E (see find_enr_fx.c) Q8 */ + const Word16 relE, /* i : (VA_CHECK addition) relative frame energy Q8? */ + const Word16 corr_shift, /* i : normalized correlation correction Q15 */ + const Word32 enr[], /* i : averaged energy over both subframes Q_new + Q_SCALE */ + Word32 fr_bands[], /* i : spectrum per critical bands of the current frame Q_new + Q_SCALE */ + Word16* cor_map_sum, /* o : Q8 */ + Word16* ncharX, /* o : IVAS_CODE -> size of ncharX needs validation noise character for sp/mus classifier Qx? */ + Word16* sp_div, /* o : Q_sp_div */ + Word16* Q_sp_div, /* o : Q factor for sp_div */ + Word16* non_staX, /* o : non-stationarity for sp/mus classifier */ + Word16* loc_harm, /* o : multi-harmonicity flag for UV classifier */ + const Word32* lf_E, /* i : per bin energy for low frequencies Q_new + Q_SCALE -2 */ + Word16* st_harm_cor_cnt, /* i/o : 1st harm correlation timer Q0 */ + const Word16 Etot_l_lp, /* i : Smoothed low energy Q8 */ + const Word16 Etot_v_h2, /* i : Energy variations Q8 */ + Word16* bg_cnt, /* i : Background burst length timer Q0 */ + Word16 EspecdB[], /* i/o: log E spectrum (with f=0) of the current frame Q7 for multi harm */ + Word16 Q_new, /* i : SCaling of current frame */ + const Word32 Le_min_scaled, /*i : Minimum energy value in Q_new + Q_SCALE */ + Word16* sp_floor, /* o : noise floor estimate Q7 */ + Word16 S_map[], /* o : short-term correlation map Q7 */ +#ifdef IVAS_CODE + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + FRONT_VAD_ENC_HANDLE hFrontVad, /* i/o: front-VAD handle */ +#endif + const Word16 ini_frame /* i : Frame number (init) */ +); + +void noise_est_pre_fx( + const Word16 Etot, /* i : Energy of current frame */ + const Word16 ini_frame_fx, /* i : Frame number (init) */ + NOISE_EST_HANDLE hNoiseEst, /* i/o: Noise estimation handle */ + const Word16 idchan, /* i : channel ID */ + const Word16 element_mode, /* i : element mode */ + const Word16 last_element_mode /* i : last element mode */ + +); + +void pitch_ol2_fx( + const Word16 pit_min, /* i : minimum pitch value (20 or 29) */ + const Word16 pitch_ol, /* i : pitch to be improved */ + Word16 *pitch_fr_fx, /* o : adjusted 1/4 fractional pitch */ /*Q7 */ + Word16 *voicing_fr_fx, /* o : adjusted 1/4 fractional voicing */ /*Q15 */ + const Word16 pos, /* i : position in frame where to calculate the improv. */ + const Word16 *wsp_fx, /* i : weighted speech for current frame and look-ahead */ /*Q_new-1+shift*/ + const Word16 delta /* i : delta for pitch search (2 or 7) */ +); + +void pitch_ol_fx( + Word16 pitch[3], /* o : open loop pitch lag for each half-frame in range [29,231] Q0 */ + Word16 voicing[3], /* o : maximum normalized correlation for each half-frame in [0,1.0[ Q15 */ + Word16 *old_pitch, /* i/o: pitch of the 2nd half-frame of previous frame (i.e. pitch[1]) Q0 */ + Word16 *old_corr, /* i/o: correlation of old_pitch (i.e. voicing[1] or corr_mean) Q15 */ + Word16 corr_shift, /* i : normalized correlation correction Q15 */ + Word16 *old_thres, /* i/o: maximum correlation weighting with respect to past frame pitch Q15 */ + Word16 *delta_pit, /* i/o: old pitch extrapolation correction in range [-14,+14] Q0 */ + Word16 *st_old_wsp2, /* i/o: weighted speech memory qwsp */ + const Word16 *wsp, /* i : weighted speech for current frame and look-ahead qwsp */ + Word16 mem_decim2[3], /* i/o: wsp decimation filter memory qwsp */ + const Word16 relE, /* i : relative frame energy Q8 */ + const Word16 last_class, /* i : frame classification of last frame */ + const Word16 bwidth, /* i : bandwidth */ + const Word16 Opt_SC_VBR /* i : SC-VBR flag */ +); + +void pitch_ol_init_fx( + Word16 *old_thres, /* o : threshold for reinforcement of past pitch influence */ + Word16 *old_pitch, /* o : pitch of the 2nd half-frame of previous frame */ + Word16 *delta_pit, /* o : pitch evolution extrapolation */ + Word16 *old_corr /* o : correlation */ +); + +void Preemph_scaled( + Word16 new_speech[], /* i : Speech to scale already on 14 bits*/ + Word16 *Q_new, /* o : Scaling factor */ + Word16 *mem_preemph, /* i/o: Preemph memory */ + Word16 *Q_max, /* i/o: Q_new limitation */ + const Word16 Preemph_factor, /* i : Preemphasis factor Q15 */ + const Word16 bits, /* i : Bit to remove from the output to (15-bits)*/ + const Word16 bit1, /* i : Limit the output scaling to ((15-bits)-bit1) bits */ + const Word16 L_Q_mem, /* i : Number of old scaling to take into account */ + const Word16 Lframe, /* i : Frame length */ + const Word16 last_coder_type, /* i : coder_type */ + const Word16 Search_scaling /* i : enable the search of a proper scaling factor*/ +); + +void Scale_mem_enc( + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *old_speech16k, /* i/o: Speech memory */ + Word16 *old_exc, /* i/o: excitation memory */ + Word16 *old_bwe_exc, /* i/o: BWE excitation memory */ + Word16 *mem_w0, /* i/o: target vector memory */ + Word16 *mem_syn, /* i/o: synthesis memory */ + Word16 *mem_syn2, /* i/o: synthesis memory */ + Word16 *mem_deemp_preQ_fx, /*i/o: deemphasis memory for the high rate celp codec */ + Word16 *last_exc_dct_in, + Word16 *old_input_lp +); + +Word32 Scale_mem_pre_proc( /* o : Min energy scaled */ + Word16 ini_frame_fx, /* i : Frame number */ + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *Q_new, /* i/o: Absolute scaling factor */ + Word16 *old_speech, /* i/o: Speech memory */ + Word16 *mem_wsp, /* i/o: wsp vector memory */ + Word32 *enrO, /* i/o: Enr mem */ + Word32 *bckr, /* i/o: Back ground_fx ener mem */ + Word32 *ave_enr, /* i/o: Ave_enr mem */ + Word32 *ave_enr2, /* i/o: Ave_enr2 mem */ + Word32 *st_fr_bands1, /* i/o: spectrum per critical bands of the previous frame */ + Word32 *st_fr_bands2, /* i/o: spectrum per critical bands 2 frames ago */ + Word32 *st_Bin_E_old +); + +void Scale_wsp( + Word16 *wsp, /* i : Weigthed speech */ + Word16 *old_wsp_max, /* i : Last weigthed speech maximal valu */ + Word16 *shift, /* i/o: Scaling of current frame */ + Word16 *Q_exp, /* i/o: Differential scaling factor */ + Word16 *old_wsp_shift, /* i/o: Last wsp scaling */ + Word16 *old_wsp, /* i/o: Old weighted speech buffer */ + Word16 *mem_decim2, /* i/o: Decimation buffer */ + Word16 *old_wsp12k8, /* i/o: wsp memory @ 12.8 kHz used in pitol2 */ + const Word16 Len_p_look /* i : L_frame + look ahead */ +); + +Word16 signal_clas_fx( /* o : classification for current frames */ + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16* speech, /* i : pointer to speech signal for E computation */ + const Word32* ee, /* i : lf/hf E ration for 2 half-frames */ + const Word16 relE, /* i : frame relative E to the long term average */ + const Word16 L_look, /* i : look-ahead */ + Word16* uc_clas /* o : temporary classification used in music/speech class*/ +); + +void speech_music_classif_fx( + Encoder_State_fx* st, /* i/o: state structure */ + const Word16* new_inp, /* i : new input signal */ + const Word16* inp, /* i : input signal to locate attach position */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const Word16 lsp_new[M], /* i : LSPs in current frame Q15 */ + const Word16 cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.)Q8*/ + const Word32 epsP[M + 1], /* i : LP prediciton error Q_esp*/ + const Word32 PS[], /* i : energy spectrum Q_new+QSCALE*/ + const Word16 Etot, /* i : total frame energy Q8 */ + const Word16 old_cor, /* i : max correlation from previous frame Q15 */ + Word16* attack_flag, /* o : flag to indicate if attack is to be treated by TC or GSC */ + Word16 non_sta, /* i : unbound non-stationarity for sp/mus classifier */ + Word16 relE, /* i : relative frame energy */ + Word16 Q_esp, /* i : scaling of esP */ + Word16 Q_inp, /* i : scaling of input */ + Word16* high_lpn_flag_ptr, /* o : noise log prob flag for NOISE_EST */ + Word16 flag_spitch /* i : flag to indicate very short stable pitch */ +); + +void StableHighPitchDetect_fx( + Word16 *flag_spitch, /* o : flag to indicate very short stable pitch */ + Word16 pitch[], /* i/o: OL pitch buffer */ + const Word16 voicing[], /* i : OL pitch gains */ + const Word16 wsp[], /* i : weighted speech */ + const Word16 localVAD, + Word16 *voicing_sm, /* i/o: smoothed open-loop pitch gains */ + Word16 *voicing0_sm, /* i/o: smoothed high pitch gains */ + Word16 *LF_EnergyRatio_sm, /* i/o: smoothed [0, 300Hz] relative peak energy*/ + Word16 *predecision_flag, /* i/o: predecision flag */ + Word32 *diff_sm, /* i/o: smoothed pitch frequency difference */ + Word32 *energy_sm, /* i/o: smoothed energy around pitch frequency */ + Word16 Q_new, + Word16 EspecdB[] +); + +void swb_bwe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *old_input_12k8_fx, /* i : i signal @12.8kHz for SWB BWE */ + Word16 *old_input_16k_fx, /* i : i signal @16kHz for SWB BWE */ + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + const Word16 *new_swb_speech_fx, /* i : original i signal at 32kHz */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_shb_speech, + Word16 Q_slb_speech +); + +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 */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz */ +); + +void swb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *input_fx, /* i : original i signal */ + Word16 *new_swb_speech_fx, /* o : original i signal at 32kHz */ + Word16 *shb_speech_fx, /* o : SHB target signal (6-14kHz) at 16kHz */ + Word16 *Q_shb_spch /* o : shb target signal Q factor */ + , Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* i : real buffer */ + , Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] /* i : imag buffer */ + , const CLDFB_SCALE_FACTOR *cldfbScale /* i : scale data of real and imag CLDFB buffers */ +); + +void swb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type_fx, /* i : coding type */ + Word16 *new_speech_fx, /* i : original i signal */ + Word32 *bwe_exc_extended_fx, /* i : bandwidth extended excitation */ + const Word16 voice_factors_fx[], /* i : voicing factors */ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE */ + Word16 *Q_white_exc, /* o : generated white noise for FB Q factor */ + Word16 Q_bwe_exc, /* i : bandwidth extended excitation Q factor */ + Word16 Q_shb, /* i : SHB target Q factor */ + Word16 *voicing_fx, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : pitch for each subframe */ +); + +void tbe_write_bitstream_fx( + Encoder_State_fx *st_fx /* i/o: encoder state structure */ +); + +Word16 tfaEnc_TBE_fx( + const Word32* enr, + const Word16 last_core, + const Word16* voicing, /* Q15 */ + const Word16* pitch_buf, /* Q6 */ + const Word16 Q_enr +); + +Word32 VAD_Log2(Word32 i_s32Val, + Word16 i_s16Q +); + +Word32 VAD_L_ADD(Word32 s32Mantissa1, + Word16 i_tExp1, + Word32 s32Mantissa2, + Word16 i_tExp2, + Word16 *s16Exp +); + +Word32 VAD_L_div(Word32 L_var1, + Word32 L_var2, + Word16 Q_L_var1, + Word16 Q_L_var2, + Word16 *Q_OUT +); + +void vad_param_updt_fx( + Encoder_State_fx* st_fx, /* i/o: state structure */ + const Word16 old_pitch1, /* i : OL pitch value from last frame */ + const Word16 corr_shift, /* i : correlation shift Q15*/ + const Word16 corr_shiftR, /* i : correlation shift */ + const Word16 Az[], /* i: a coeffs Q12 */ + FRONT_VAD_ENC_HANDLE hFrontVad[], /* i/o: front-VAD handles */ + const Word16 n_channels /* i : number of channels */ +); +void wb_bwe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *new_wb_speech_fx, /* i : original i signal at 16kHz */ + Word16 coder_type /* i : coding type */ +); + +void wb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *new_inp_resamp16k, /* i : original i signal */ + Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz */ +); + +void wb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz */ + const Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const Word16 Q_new, /* i : i HB speech Q factor */ + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 pitch_buf[], /* i : pitch for each subframe */ + const Word16 voicing[] /* i : OL maximum normalized correlation */ +); + +Word16 wb_vad_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word32 fr_bands[], /* i : per band i energy (contains 2 vectors) Q_new+QSCALE*/ + Word16* noisy_speech_HO, /* o : SC-VBR noisy speech HO flag */ + Word16* clean_speech_HO, /* o : SC-VBR clean speech HO flag */ + Word16* NB_speech_HO, /* o : SC-VBR NB speech HO flag */ + Word16* snr_sum_he, /* o : Output snr_sum as weighted spectral measure*/ + Word16* localVAD_HE_SAD, + Word8* flag_noisy_speech_snr, /* o : */ + const Word16 Q_new, /* i : scaling factor Q0 */ + VAD_HANDLE hVAD, /* i/o: VAD data handle */ + NOISE_EST_HANDLE hNoiseEst, /* i : Noise estimation handle */ + Word16 lp_speech, /* i : long term active speech energy average */ + Word16 lp_noise /* i : long term noise energy */ +); + +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*/ + Word32 l_snr, /*(i) long time frequency domain snr*/ + Word32 continuous_speech_num, /*(i) amount of continuous speech frames*/ + Word16 continuous_noise_num, /*(i) amount of continuous noise frames*/ + Word32 fg_energy_est_start, /*(i) whether if estimated energy*/ + Word16 bw_index /*(i) band width index*/ +); + +void sc_vbr_enc_init_fx( + SC_VBR_ENC_HANDLE hSC_VBR /* i/o: SC-VBR encoder handle */ +); + +void updt_enc_common_fx( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16 Etot, /* i : total energy */ + const Word16 Q_new /* i : CUrrent frame scaling */ +); + +void attenuateNbSpectrum_fx(Word16 L_frame, Word32 *spectrum); + +Word16 corr_xy1_fx( /* o : pitch gain (0..GAIN_PIT_MAX) */ + const Word16 xn_1[], /* i : target signal */ + const Word16 y1_1[], /* i : filtered adaptive codebook excitation */ + Word16 g_corr[], /* o : correlations and -2 */ + const Word16 L_subfr, /* i : vector length */ + const Word16 norm_flag /* i : flag for constraining pitch contribution */ +#ifdef BASOP_NOGLOB + , Flag* Overflow_out /* o : propagating the Overflow flag to upper level */ +#endif +); + +Word16 E_ACELP_indexing_fx(const Word16 code[], const PulseConfig *config, Word16 num_tracks, Word16 prm[]); +void fcb_pulse_track_joint_fx(UWord16 *idxs, Word16 wordcnt, UWord32 *index_n, Word16 *pulse_num, Word16 track_num); + +Word16 gain_quant_fx( /* o: quantization index */ + Word32 *gain, /* i/o: quantized gain */ + Word16 *gain16, + 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 +); +void gsc_enc_fx( + Encoder_State_fx* st_fx, /* i/o: State structure */ + Word16 res_dct_in[], /* i : dct of residual signal */ + Word16 exc_dct_in[], /* i/o: dct of pitch-only excitation / total excitation */ + const Word16 Diff_len, + const Word16 bits_used, + const Word16 nb_subfr, + Word16* lsf_new, /* i : ISFs at the end of the frame */ + Word16* exc_wo_nf, /* o : excitation (in f domain) without noisefill */ + Word16* tmp_noise, /* o : noise energy */ + Word16 Q_exc +); + +void LPDmem_enc_init_fx( + LPD_state_HANDLE hLPDmem /* i/o: LP memories */ +); + +void lsf_end_enc_fx( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16* lsf, /* i : LSF in the frequency domain (0..6400) */ + Word16* qlsf, /* o : quantized LSF */ + const Word16 nBits_in, /* i : number of bits to spend on ISF quantization */ + const Word16 coder_type_org, /* i : coding type */ + Word16 Q_ener, /* i : Q valuen for Bin_Ener */ + Word16 force_sf, /* i : Force safety-net usage if coding type supports */ + Word16* lpc_param, + Word16* no_indices, + Word16* bits_param_lpc, + Word16 coder_type_raw /* i : Coder type (LSF coder_type have some special cases)*/ +#ifdef LSF_RE_USE_SECONDARY_CHANNEL + , const Word16 tdm_lsfQ_PCh[M] /* i : Q LSFs for primary channel */ +#endif +); + +void Mode2_abs_pit_enc_fx( + Word16 T0, /* i : integer pitch lag */ + Word16 T0_frac, /* i : pitch fraction */ + Word16 **pt_indice, /* i/o: pointer to Vector of Q indexes */ + Word16 pit_min, + Word16 pit_fr1, + Word16 pit_fr2, + Word16 pit_res_max +); + +void Mode2_delta_pit_enc_fx( + Word16 T0, /* i : integer pitch lag */ + Word16 T0_frac, /* i : pitch fraction */ + Word16 T0_res, /* i : pitch resolution */ + Word16 T0_min, /* i/o: delta search min */ + Word16 T0_min_frac, /* i/o: delta search min */ + Word16 **pt_indice /* i/o: pointer to Vector of Q indexes */ +); + +void norm_corr_fx( + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t_min, /* i : minimum value of searched range */ + const Word16 t_max, /* i : maximum value of searched range */ + Word16 ncorr[], /* o : normalized correlation Q15 */ + const Word16 L_subfr /* i : subframe size */ +); + +Word16 peak_avrg_ratio_fx( + const Word32 total_brate, + const Word32 *input_hi_fx, /* i : i signal */ + const Word16 length, /* i : number of coefficients */ + Word16 *mode_count, /* i/o: HQ_HARMONIC mode count */ + Word16 *mode_count1, /* i/o: HQ_NORMAL mode count */ + Word16 Q_coeff +); + +void pit16k_Q_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max */ +); + +Word16 pitch_fr4_fx( /* o : chosen integer pitch lag */ + const Word16 exc[], /* i : excitation buffer Q_new*/ + const Word16 xn[], /* i : target signal Q_new-1+shift*/ + const Word16 h[], /* i : weighted synthesis filter impulse response Q(14+shift)*/ + const Word16 t0_min, /* i : minimum value in the searched range. Q0*/ + const Word16 t0_max, /* i : maximum value in the searched range. Q0*/ + Word16 *pit_frac, /* o : chosen fraction (0, 1, 2 or 3) */ + const Word16 i_subfr, /* i : flag to first subframe */ + const Word16 limit_flag, /* i : flag for limits (0=restrained, 1=extended) */ + const Word16 t0_fr2, /* i : minimum value for resolution 1/2 */ + const Word16 t0_fr1, /* i : minimum value for resolution 1 */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 L_subfr /* i : size of subframe */ +); +void pit_Q_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 nBits, /* i : # of Q bits */ + const Word16 delta, /* i : Half the CL searched interval */ + const Word16 pit_flag, /* i : absolute(0) or delta(1) pitch Q */ + const Word16 limit_flag, /* i : restrained(0) or extended(1) Q limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + Word16 *T0_min, /* i/o: delta search min */ + Word16 *T0_max /* o : delta search max */ +); + +void PsychAdaptLowFreqEmph_fx(Word32 x[], + const Word16 lpcGains[], const Word16 lpcGains_e[] +); +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 */ +); + +Word16 WB_BWE_encoding_fx( /* o : classification of wb signal */ + const Word16 coder_type, /* i : coder type */ + const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ + Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ + Encoder_State_fx *st_fx, /* i/o: Encoder structure */ + Word16 Q_synth, + Word16 Q_synth_lf +); + +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 */ +); + +/*transient_detection.h*/ +/** Init transient detection. + * Fills TransientDetection structure with sensible content. + * @param nFrameLength Frame length. + * @param nTCXDelay Delay for the TCX Long/Short transient detector. + * Don't include the delay of the MDCT overlap. + * @param pTransientDetection Structure to be initialized. It contains all transient detectors to be used. + */ +void InitTransientDetection_fx(Word16 nFrameLength, + Word16 nTCXDelay, + struct TransientDetection * pTransientDetection); + + +/** Runs transient detection. + * Runs all transient detectors defined in pTransientDetection + * and calculates mean zero crossing. + * @param i New i samples. + * @param nSamplesAvailable Number of new i samples available. + * @param pTransientDetection Structure that contains transient detectors to be run. + */ +void RunTransientDetection_fx(Word16 const * i, Word16 nSamplesAvailable, struct TransientDetection * pTransientDetection); + +/** Get the average temporal flatness measure using subblock energies aligned with the TCX. + * @param pTransientDetection Structure that contains transient detectors to be run. + * @param nCurrentSubblocks Number of the subblocks from the current frame to use for the calculation. + A lookeahead can also be use if it exists. + * @param nPrevSubblocks Number of subblocks from the previous frames to use for the calculation. + * @return average temporal flatness measure with exponent AVG_FLAT_E + */ +Word16 GetTCXAvgTemporalFlatnessMeasure_fx(struct TransientDetection const * pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks); + +/** Get the maximum energy change using subblock energies aligned with the TCX. + * @param pTransientDetection Structure that contains transient detectors to be run. + * @param nCurrentSubblocks Number of the subblocks from the current frame to use for the calculation. + A lookeahead can also be use if it exists. + * @param nPrevSubblocks Number of subblocks from the previous frames to use for the calculation. + * @param maximum energy change with exponent NRG_CHANGE_E + */ +Word16 GetTCXMaxenergyChange_fx(struct TransientDetection const * pTransientDetection, + const Word8 isTCX10, + const Word16 nCurrentSubblocks, const Word16 nPrevSubblocks); + +/** Set TCX window length and overlap configuration + * @param prevEnergyHF previous HF energy. Exponent must be the same as for currEnergyHF. + * @param currEnergyHF current HF energy. Exponent must be the same as for prevEnergyHF. + */ +void SetTCXModeInfo_fx(Encoder_State_fx *st, + struct TransientDetection const * pTransientDetection, + Word16 * tcxModeOverlap); + +void GSC_enc_init_fx( + GSC_ENC_HANDLE hGSCEnc /* i/o: GSC data handle */ +); +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 */ +); + +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 */ +); +void select_TC_fx( + const Word16 codec_mode, /* i : codec mode */ + const Word16 tc_cnt, /* i : TC frame counter */ + Word16* coder_type, /* i/o: coder type */ + const Word16 localVAD /* i : VAD without hangover */ +); +void coder_type_modif_fx( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16 relE /* i : frame relative E to the long term average */ +); + +void speech_music_clas_init_fx( + SP_MUS_CLAS_HANDLE hSpMusClas /* i/o: speech/music classifier handle */ +); + +void pitchDoubling_det_fx( + Word16 *wspeech, + Word16 *pitch_ol, + Word16 *T_op_fr, + Word16 *voicing_fr +); +void fd_bwe_enc_init_fx( + FD_BWE_ENC_HANDLE hBWE_FD /* i/o: FD BWE data handle */ +); + +void HQ_core_enc_init_fx( + HQ_ENC_HANDLE hHQ_core /* i/o: HQ core data handle */ +); + +void AVQ_cod_lpc_fx( + Word16 *nvec, /* i : vector to quantize (normalized) */ + Word16 *nvecq, /* o : quantized vector */ + Word16 *indx, /* o : index[] (4 bits per words) */ + Word16 Nsv /* i : number of subvectors (lg=Nsv*8) */ +); +void ProcessIGF_fx( + IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ + Encoder_State_fx *st, /**< in: Encoder state */ + Word32 pMDCTSpectrum[], /**< in: MDCT spectrum */ + Word16 *pMDCTSpectrum_e, + Word32 pPowerSpectrum[], /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 *pPowerSpectrum_e, + Word16 isTCX20, /**< in: flag indicating if the i is TCX20 or TCX10/2xTCX5 */ + Word16 isTNSActive, /**< in: flag indicating if the TNS is active */ + Word16 isTransition, /**< in: flag indicating if the i is the transition from from ACELP to TCX20/TCX10 */ + Word16 frameno /**< in: flag indicating index of current subframe */ +); +void AnalyzePowerSpectrum_fx( + Encoder_State_fx *st, /* i/o: encoder states */ + Word16 L_frame, /* i : frame length */ + Word16 L_frameTCX, /* i : full band frame length */ + Word16 left_overlap, /* i : left overlap length */ + Word16 right_overlap, /* i : right overlap length */ + Word32 const mdctSpectrum[], /* i : MDCT spectrum */ + Word16 mdctSpectrum_e, + Word16 const signal[], /* i : windowed signal corresponding to mdctSpectrum */ + Word32 powerSpec[], /* o : Power spectrum. Can point to signal */ + Word16 *powerSpec_e +); +void AdaptLowFreqEmph_fx(Word32 x[], + Word16 x_e, + Word16 xq[], + Word16 invGain, + Word16 invGain_e, + Word16 tcx_lpc_shaped_ari, + Word16 lpcGains[], Word16 lpcGains_e[], + const Word16 lg +); +Word16 SQ_gain_fx( /* o : SQ gain */ + Word32 x[], /* i : vector to quantize */ + Word16 x_e, /* i : exponent */ + Word16 nbitsSQ, /* i : number of bits targeted */ + Word16 lg, /* i : vector size (2048 max) */ + Word16 *gain_e); /* o : SQ gain exponent */ + +void tcx_scalar_quantization_fx( + Word32 *x, /* i: i coefficients */ + Word16 x_e, /* i: exponent */ + Word16 *xq, /* o: quantized coefficients */ + Word16 L_frame, /* i: frame length */ + Word16 gain, /* i: quantization gain */ + Word16 gain_e, /* i: quantization gain exponent */ + Word16 offset, /* i: rounding offset (deadzone) */ + Word8 const *memQuantZeros, /* i: coefficients to be set to 0 */ + const Word16 alfe_flag +); + +Word16 tcx_scalar_quantization_rateloop_fx( + Word32 *x, /* i : i coefficients */ + Word16 x_e, /* i : exponent */ + Word16 *xq, /* o : quantized coefficients */ + Word16 L_frame, /* i : frame length */ + Word16 *gain, /* i/o: quantization gain */ + Word16 *gain_e, /* i/o: gain exponent */ + Word16 offset, /* i : rounding offset (deadzone) */ + Word8 const *memQuantZeros, /* i : coefficients to be set to 0 */ + Word16 *lastnz_out, /* i/o: last nonzero coeff index */ + Word16 target, /* i : target number of bits */ + Word16 *nEncoded, /* o : number of encoded coeff */ + Word16 *stop, /* i/o: stop param */ + Word16 sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) */ + Word16 sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) */ + Word16 tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ + const Word8 tcxonly, + CONTEXT_HM_CONFIG *hm_cfg /* i : configuration of the context-based harmonic model */ +); +void tcx_noise_factor_fx( + Word32 *x_orig, /* i: unquantized mdct coefficients */ + Word16 x_orig_e, /* i: exponent */ + Word32 *sqQ, /* i: quantized mdct coefficients */ + Word16 iFirstLine, /* i: first coefficient to be considered */ + Word16 lowpassLine, /* i: last nonzero coefficients after low-pass */ + Word16 nTransWidth, /* i: minimum size of hole to be checked */ + Word16 L_frame, /* i: frame length */ + Word16 gain_tcx, /* i: tcx gain */ + Word16 gain_tcx_e, /* i: gain exponent */ + Word16 tiltCompFactor, /* i: LPC tilt compensation factor */ + Word16 *fac_ns, /* o: noise factor */ + Word16 *quantized_fac_ns/* o: quantized noise factor */ +); + +void tcx_encoder_memory_update_fx( + Word16 *wsig, /* i: targert weighted signal */ + Word16 *xn_buf, /* i/o: mdct output buffer/TD weigthed synthesis */ + Word16 L_frame_glob, /* i: global frame length */ + const Word16 *Ai, /* i: Unquantized (interpolated) LPC coefficients */ + const Word16 *A, /* i: Quantized LPC coefficients */ + Word16 preemph, /* i: preemphasis factor*/ + LPD_state *LPDmem, /* i/o: coder memory state */ + Encoder_State_fx *st, + Word16 *synthout, /* o: synthesis signal */ + Word16 Q_new, + Word16 shift +); +Word16 tcx_ari_res_Q_spec_fx( + const Word32 x_orig[], /* i: original spectrum Q31-e */ + Word16 x_orig_e, /* i: original spectrum exponent Q0 */ + const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word16 gain, /* i: TCX gain Q15-e */ + Word16 gain_e, /* i: TCX gain exponent Q0 */ + Word16 prm[], /* o: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +); + +Word16 tcx_res_Q_gain_fx( + Word16 sqGain, + Word16 sqGain_e, + Word16 *gain_tcx, + Word16 *gain_tcx_e, + Word16 *prm, + Word16 sqTargetBits +); + +Word16 tcx_res_Q_spec_fx( + Word32 *x_orig, + Word16 x_orig_e, + Word32 *x_Q, + Word16 x_Q_e, + Word16 L_frame, + Word16 sqGain, + Word16 sqGain_e, + Word16 *prm, + Word16 sqTargetBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] +); + +/* compute noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ +void ComputeSpectrumNoiseMeasure_fx(const Word32 *powerSpec, + Word16 L_frame, + Word16 startLine, + Word8 resetMemory, + Word8 *noiseFlags, + Word16 lowpassLine); + +void lpc_quantization_fx( + Encoder_State_fx* st, + const Word16 lsp[], + const Word16 lspmid[], + Word16 lsp_q[], + Word16 lsf_q[], /* 14Q1*1.28 */ + Word16 lspmid_q[], + Word16 lspq_ind[], + Word16 clip_var[], + const Word16 coder_type, + const Word8 acelp_midLpc, + Word16 param_lpc[], + Word16 nbits_lpc[], + Word16* bits_param_lpc, + Word16* no_param_lpc, + const Word16 Q_ener +); + +void Mode2_pit_encode_fx( + const Word16 coder_type, /* i : coding model */ + const Word16 i_subfr, /* i : subframe index */ + Word16 **pt_indice, /* i/o: quantization indices pointer */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 *T_op, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_min_frac, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0_max_frac, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + Word16 *T0_res, /* i/o: close loop pitch resolution */ + Word16 *h1, /* i : weighted filter impulse response */ + Word16 *xn, /* i : target vector */ + Word16 pit_min, + Word16 pit_fr1, + Word16 pit_fr1b, + Word16 pit_fr2, + Word16 pit_max, + Word16 pit_res_max +); +void E_ACELP_4tsearch_fx(Word16 dn[], const Word16 cn[], const Word16 H[], Word16 code[], const PulseConfig *config, Word16 ind[], Word16 y[]); + +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 Word16 cmpl_flag +); + +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 */ +); + +/** Detect TNS parameters. + * Detects if TNS should be used and fills TNS data in pTnsData. + * @param pTnsConfig TNS configuration. + * @param pSpectrum Spectrum lines. + TNS is tested on the spectrum defined by pSpectrum. + * @param sbCnt Number of active subbands. + * @param pTnsData TNS data is filled with sensible information. + * @return Returns 1 if Tns should be used, otherwise 0. + */ +Word16 DetectTnsFilt_fx(STnsConfig const * pTnsConfig, + Word32 const pSpectrum[], + STnsData * pTnsData, + Word16 *predictionGain); + +/** Write TNS data into a stream of integers. + * Writes TNS data into a stream of integers. + * @param pTnsConfig TNS configuration. + * @param pTnsData TNS data to be written to a bitstream. + * @param stream Output stream of integers. + * @param pnSize Set to the number of elements written to the stream. + * @param pnBits Set to the number of required. + * @return 0 on success, otherwise 1. + */ +Word16 EncodeTnsData_fx(STnsConfig const * pTnsConfig, + STnsData const * pTnsData, + Word16 * stream, + Word16 * pnSize, + Word16 * pnBits); + +/** Write TNS data into a bitstream. + * Writes TNS data into a bitstream. + * @param pTnsConfig TNS configuration. + * @param stream Contains TNS data written with EncodeTnsData. + * @param pnSize Set to the number of used elements from stream. + * @param st Encoder state. + * @param pnBits Set to the number of bits written. + * @return 0 on success, otherwise 1. + */ +Word16 WriteTnsData_fx(STnsConfig const * pTnsConfig, + Word16 const * stream, + Word16 * pnSize, + Encoder_State_fx *st, + Word16 * pnBits); + +void subband_FFT_fx( + Word32 ** Sr, /*(i) real part of the CLDFB*/ + Word32 ** Si, /*(i) imag part of the CLDFB*/ + Word32 *spec_amp, /*(o) spectral amplitude*/ + Word32 Offset, /*(i) offset of the CLDFB*/ + Word16 *fftoQ /*(o) the Scaling */ +); +Word16 E_ACELP_toeplitz_mul_fx(const Word16 R[], const Word16 c[], Word16 d[], const Word16 L_subfr, const Word16 highrate); +Word16 E_ACELP_code43bit_fx(const Word16 code[], UWord32 *ps, Word16 *p, UWord16 idxs[]); +void tc_classif_enc_fx( + const Word16 Q_new, /* i : scaling factor */ + const Word16 L_frame, /* i : length of the frame */ + Word16* tc_subfr, /* o : TC subframe index */ + Word16* position, /* o : maximum of residual signal index */ + const Word16 attack_flag, /* i : attack flag */ + const Word16 pitch, /* i : open loop pitch estimates for first halfframe */ + const Word16* res /* i : pointer to the LP residual signal frame */ +); + +Word16 gain_enc_uv_fx( + const Word16 *code, /*, -2,, -2 and 2*/ + Word16 mean_ener, /*0=rel */ + const Word32 sr_core/* i : internal sampling rate */ +); + +Word16 update_decision_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + const Word32 frame_energy, /* i : current frame energy*/ + Word32 HB_Power, /* i : current frame high frequency energy*/ + const Word16 frameloop, /* i : amount of frames*/ + const Word16 bw, /* i : band width index*/ + const Word16 frame_energy_Q, /* i : the Scaling of current frame energy*/ + const Word16 HB_Power_Q, /* i : the Scaling of current frame high frequency energy*/ + const Word32 snr, /* i : frequency domain SNR */ + const Word32 tsnr, /* i : time domain SNR */ + const Word16 vad_flag, /* i : VAD flag */ + const Word16 music_backgound_f /* i : background music flag*/ +); + +void bg_music_decision_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + Word16 *music_backgound_f, /*(i) background music flag*/ + Word32 frame_energy, /*(i) current frame energy 1*/ + Word16 frame_energy_Q /*(i) the Scaling of current frame energy*/ +); + +void spec_center_fx( + Word32* sb_power, /* i : energy of sub-band divided uniformly*/ + Word16* sp_center, /* o : spectral center*/ + const Word32 bandwith, /* i : band width*/ + const Word16 Q_sb_p /* i : the Scaling of sb_power*/ +); + +void spec_flatness_fx(Word32 *spec_amp, /*(i) spectral amplitude*/ + Word32 smooth_spec_amp[], /*(i) smoothed spectral amplitude*/ + Word16 sSFM[5] /*(o) spectral flatness rate*/ +); + +void SetModeIndex_fx( + Encoder_State_fx* st, + Word32 last_total_brate, + const Word16 last_element_mode, + const Word16 is_mct, + const Word16 shift +); + +void MDCT_selector_fx( + Encoder_State_fx* st, /* i/o: Encoder State */ + Word16 sp_floor, /* i : Noise floor estimate Q7 */ + const Word16 Etot, /* i : Total energy Q8 */ + const Word16 cor_map_sum, /* i : harmonicity factor Q8 */ + const Word32 enerBuffer[], /* i : CLDFB buffers */ + const Word16 enerBuffer_exp /* i : exponent of enerBuffer */ +); + +void MDCT_selector_reset_fx( + TCX_ENC_HANDLE hTcxEnc +); +void MDCT_classifier_reset_fx( + TCX_ENC_HANDLE hTcxEnc /* i/o: TCX Encoder Handle */ +); + +void ltd_stable_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + Word16* ltd_stable_rate, /* o : time-domain stable rate*/ + const Word32 frame_energy, /* i : current frame energy*/ + const Word16 frameloop, /* i : amount of frames*/ + const Word16 Q_frames_power /* i : the Scaling of frames_power*/ +); +/* IGFSCFEncoder.c */ +void IGFSCFEncoderOpen_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + H_IGF_INFO hIgfInfo, /* i : IGF info handle */ + const Word32 total_brate, /* i : total bitrate */ + const Word16 bwidth, /* i : audio bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +); + +void IGFSCFEncoderReset_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData /* i/o: handle to public data */ +); + +Word16 IGFSCFEncoderEncode_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i : handle to public data or NULL in case there was no instance created */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 bitCount, /* i : offset to the first bit in bitbuffer which should be readed by iisArithDecoderDecode function */ + Word16* sfe, /* i : ptr to an array which contain quantized scalefactor energies */ + const Word16 igfGridIdx, /* i : igf grid index see declaration of IGF_GRID_IDX for details */ + const Word16 indepFlag /* i : if 1 frame is independent, 0 = frame is coded with data from previous frame */ +); + +void IGFSCFEncoderSaveContextState_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + const Word16 igfGridIdx /* i : igf grid index see declaration of IGF_GRID_IDX for details */ +); + +void IGFSCFEncoderRestoreContextState_fx( + IGFSCFENC_INSTANCE_HANDLE hPublicData, /* i/o: handle to public data */ + const Word16 igfGridIdx /* i : igf grid index see declaration of IGF_GRID_IDX for details */ +); + +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*/ +); + +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*/ +); + +void background_update_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + Word16 scale, /* i : the scaling of frame energy*/ + Word32 frame_energy, /* i : current frame energy*/ + Word32 update_flag, /* i : update flag*/ + Word16 music_backgound_f, /* i : background music flag*/ + Word32 snr +); +/* enc_gain.c */ + +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); + +void core_acelp_tcx20_switching_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + Word16 non_staX, + 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 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 +); +void amr_wb_enc_init_fx( + AMRWB_IO_ENC_HANDLE hAmrwb_IO /* i/o: AMR-WB IO encoder handle */ +); + +void snr_calc( + 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 */ + const Word32 frame_energy, /* i : current frame energy */ + const Word32 bwidth /* i : audio band width*/ +); +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 : i scaling */ + const Word16 shift /* i : scaling to get 12bits */ +); + +void updt_enc_fx( + Encoder_State_fx* st, /* i/o: state structure */ + const Word16* old_exc, /* i : buffer of excitation */ + const Word16* pitch_buf, /* i : floating pitch for each subframe */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + const Word16* Aq, /* i : A(z) quantized for all subframes */ + const Word16* lsf_new, /* i : current frame LSF vector */ + const Word16* lsp_new, /* i : current frame LSP vector */ + const Word16* old_bwe_exc /* i : buffer of excitation */ +); + +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 */ +); + +void update_average_rate_fx( + SC_VBR_ENC_HANDLE hSC_VBR, /* i/o: SC-VBR state structure */ + const Word32 core_brate_fx /* i : core bitrate */ +); +Word16 pit_encode_fx( /* o : Fractional pitch for each subframe */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 pitch_bits[], /* i : pitch bits */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 coder_type, /* i : coding type */ + Word16 *limit_flag, /* i/o: restrained(0) or extended(1) Q limits */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *exc, /* i/o: pointer to excitation signal frame */ + const Word16 L_subfr, /* i : subframe length */ + const Word16 *T_op, /* i : open loop pitch estimates in current frame */ + Word16 *T0_min, /* i/o: lower limit for close-loop search */ + Word16 *T0_max, /* i/o: higher limit for close-loop search */ + Word16 *T0, /* i/o: close loop integer pitch */ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch */ + const Word16 *h1, /* i : weighted filter i response */ + const Word16 *xn, /* i : target vector */ + const Word16 tdm_Pitch_reuse_flag, /* i : primary channel pitch reuse flag */ + const Word16 tdm_Pri_pitch_buf[] /* i : primary channel pitch buffer */ +); + +Word16 lp_filt_exc_enc_fx( + const Word16 codec_mode, /* i : MODE1 or MODE2 Q0 */ + const Word16 coder_type, /* i : coding type Q0 */ + const Word16 i_subfr, /* i : subframe index Q0 */ + Word16 *exc, /* i/o: pointer to excitation signal frame Q_new */ + const Word16 *h1, /* i : weighted filter i response Q(14+shift) */ + const Word16 *xn, /* i : target vector Q_new-1+shift */ + Word16 *y1, /* o : zero-memory filtered adaptive excitation Q_new-1+shift */ + Word16 *xn2, /* o : target vector for innovation search Q_new-1+shift */ + const Word16 L_subfr, /* i : length of vectors for gain quantization Q0 */ + const Word16 L_frame, /* i : frame size Q0 */ + Word16 *g_corr, /* o : ACELP correlation values mant/exp */ + const Word16 clip_gain, /* i : adaptive gain clipping flag Q0 */ + Word16 *gain_pit, /* o : adaptive excitation gain Q14 */ + Word16 *lp_flag /* i/o: mode selection Q0 */ +); + +Word16 inov_encode_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word32 core_brate, /* i : core bitrate */ + const Word16 Opt_AMR_WB, /* i : flag indicating AMR-WB IO mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 last_L_frame, /* i : length of the last frame */ + const Word16 coder_type, /* i : coding type */ + const Word16 bwidth, /* i : i signal bandwidth */ + const Word16 sharpFlag, /* i : formant sharpening flag */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16* p_Aq, /* i : LP filter coefficients Q12*/ + const Word16 gain_pit, /* i : adaptive excitation gain Q14*/ + Word16* cn, /* i/o: target vector in residual domain Q_new*/ + const Word16* exc, /* i : pointer to excitation signal frame Q_new*/ + Word16* h2, /* i/o: weighted filter i response Q12*/ + const Word16 tilt_code, /* i : tilt of the excitation of previous subframe Q15*/ + const Word16 pt_pitch, /* i : pointer to current subframe fractional pitch Q6*/ + const Word16* xn2, /* i : target vector for innovation search Q_new-1+shift*/ + Word16* code, /* o : algebraic excitation Q9*/ + Word16* y2, /* o : zero-memory filtered algebraic excitation Q9*/ + Word16* unbits, /* o : number of unused bits for PI */ + const Word16 L_subfr, /* i : subframe length */ + Word16 shift +); + +void gain_enc_mless_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 gains_mode[], /* i : gain bits */ + const Word16 element_mode, /* i : element mode */ + const Word16 L_frame, /* i : length of the frame */ + const Word16 i_subfr, /* i : subframe index */ + const Word16 tc_subfr, /* i : TC subframe index */ + const Word16* xn, /* i : target vector */ + const Word16* y1, /* i : zero-memory filtered adaptive excitation */ + const Word16 Q_xn, /* i : xn and y1 scaling */ + const Word16* y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16* code, /* i : algebraic excitation */ + const Word16 Es_pred, /* i : predicted scaled innovation energy */ + Word16* gain_pit, /* o : quantized pitch gain */ + Word32* gain_code, /* o : quantized codebook gain */ + Word16* gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32* norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16* g_corr, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain /* i : gain pitch clipping flag (1 = clipping) */ +); +void updt_IO_switch_enc_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 input_frame /* i : i frame length */ +); + +void hf_cod_init_fx( + Word16 *mem_hp400_enc, /* o: memory of hp 400 Hz filter */ + Word16 *mem_hf1_enc, /* o: HF band-pass filter memory */ + Word16 *mem_syn_hf_enc, /* o: HF synthesis memory */ + Word16 *mem_hf2_enc, /* o: HF band-pass filter memory */ + Word16 *gain_alpha_fx /* o: smoothing gain for transitions between active and inactive frames */ +); + +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 +); + +void encod_amr_wb_fx( + Encoder_State_fx* st, /* i/o: state structure */ + const Word16 speech[], /* i : i 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 : i speech @16kHz */ + Word16 shift, + Word16 Q_new +); + +void re8_cod_fx( + Word16 x[], /* i : point in RE8 (8-dimensional integer vector) */ + Word16 *n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + UWord16 *I, /* o : index of c (pointer to unsigned 16-bit word) */ + Word16 k[] /* o : index of v (8-dimensional vector of binary indices) = Voronoi index */ +); + +void TBEreset_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 bandwidth /* i : bandwidth mode */ +); + +void acelp_core_switch_enc_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word16 inp12k8[], /* i : i signal @12.8 kHz Q0 */ + const Word16 inp16k[], /* i : i 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 +); + +void gain_enc_amr_wb_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *xn, /* i : target vector */ + const Word16 Q_xn, /* i : xn and yy1 format Q0 */ + const Word16 *yy1, /* i : zero-memory filtered adaptive excitation */ + const Word16 *y2, /* i : zero-memory filtered algebraic codebook excitation */ + const Word16 *code, /* i : algebraic excitation */ + const Word32 core_brate, /* i : core bitrate */ + Word16 *gain_pit, /* i/o: pitch gain / Quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word16 *gain_inov, /* o : gain of the innovation (used for normalization) */ + Word32 *norm_gain_code, /* o : norm. gain of the codebook excitation */ + Word16 *g_coeff, /* i/o: correlations , -2,, -2 and 2 */ + const Word16 clip_gain, /* i : gain pitch clipping flag (1 = clipping) */ + Word16 *past_qua_en /* i/o: gain quantization memory (4 words) */ +); + + +void hf_cod_fx( + const Word32 core_brate_fx, /* i : core bitrate */ + const Word16 *speech16k_fx, /* i : original speech at 16 kHz */ + const Word16 Aq_fx[], /* i : quantized Aq */ + const Word16 exc_fx[], /* i : excitation at 12.8 kHz */ + Word16 synth_fx[], /* i : 12.8kHz synthesis signal */ + Word16 *seed2_enc_fx, /* i/o: random seed for HF noise gen */ + Word16 *mem_hp400_enc_fx, /* i/o: memory of hp 400 Hz filter */ + Word16 *mem_syn_hf_enc_fx, /* i/o: HF synthesis memory */ + Word16 *mem_hf1_enc_fx, /* i/o: HF band-pass filter memory */ + Word16 *mem_hf2_enc_fx, /* i/o: HF band-pass filter memory */ + const Word16 dtxHangoverCount_fx, + Word16 *gain_alpha_fx, /* i/o: smoothing gain for transitions between active and inactive frames */ + Word16 *hf_gain_fx, /* o : HF gain to be transmitted to decoder */ + Word16 Q_exc, + Word16 Q_syn +); + +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 i 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,... */ +); + +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 Word16 L_subfr /* i : subframe length */ +); + +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 */ +); + +void updt_tar_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain */ + const Word16 L /* i : subframe size */ +); +void updt_tar_HR_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain */ + const Word16 Qx, /* i : Scaling factor to adapt output to i */ + const Word16 L /* i : subframe size */ +); + +#ifdef BASOP_NOGLOB +Flag conv_fx( +#else +void conv_fx( +#endif + const Word16 x[], /* i : i vector Q_new*/ + const Word16 h[], /* i : impulse response (or second i vector) Q(15)*/ + Word16 y[], /* o : output vetor (result of convolution) 12 bits*/ + const Word16 L /* i : vector size */ +); + +ivas_error ppp_voiced_encoder_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + SC_VBR_ENC_HANDLE hSC_VBR, + const Word16 bwidth, /* i : audio bandwidth */ + const Word16 last_coder_type_raw, /* i : raw last_coder_type */ + const Word16 old_pitch_buf[], /* i : buffer of old subframe pitch values */ + Word16* in_fx, /* i : residual signal */ + Word16* out_fx, /* o : Quantized residual signal */ + Word16 delay_fx, /* i : open loop pitch */ + Word16* lpc1_fx, /* i : prev frame de-emphasized LPC */ + Word16* lpc2_fx, /* i : current frame de-emphasized LPC */ + Word16* exc_fx, /* i: previous frame quantized excitation */ + Word16* pitch_fx, /* o: floating pitch values for each subframe */ + Word16 Qres +); + +void signalling_enc_fx( + Encoder_State_fx *st_fx /* i : encoder state structure */ +); + +void transition_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *tc_subfr, /* i/o: TC subframe index */ + Word16 *Jopt_flag, /* i : joint optimization flag */ + Word16 *position, /* i/o: maximum of residual signal index */ + Word16 *T0, /* i/o: close loop integer pitch Q0*/ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch Q0*/ + Word16 *T0_min, /* i/o: lower limit for close-loop search Q0*/ + Word16 *T0_max, /* i/o: higher limit for close-loop search Q0*/ + Word16 *exc_fx, /* i/o: pointer to excitation signal frame Q_new*/ + Word16 *y1_fx, /* o : zero-memory filtered adaptive excitation Q_new-1+shift*/ + const Word16 *h1_fx, /* i : weighted filter i response Q(14+shift)*/ + const Word16 *xn_fx, /* i : target vector Q_new-1+shift*/ + Word16 *xn2_fx, /* o : target vector for innovation search Q_new-1+shift*/ + Word16 *gp_cl_fx, /* i/o: memory of gain of pitch clipping algorithm */ + Word16 *gain_pit_fx, /* o : adaptive excitation gain Q14*/ + Word16 *g_corr_fx, /* o : ACELP correlation values */ + Word16 *clip_gain, /* i/o: adaptive gain clipping flag */ + Word16 **pt_pitch_fx, /* o : floating pitch values */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE Q_new*/ + Word16* unbits_ACELP, /* i/o: unused bits */ + Word16 Q_new, /* i : Current scaling */ + Word16 shift /* i : downscaling needs for 12 bits convolutions */ + +); + +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 i 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,... */ +); +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 gaus_encode_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word16 i_subfr, /* i : subframe index */ + const Word16* h1, /* i : weighted filter i response */ + const Word16* xn, /* i : target vector */ + Word16* exc, /* o : pointer to excitation signal frame */ + Word16* mem_w0, /* o : weighting filter denominator memory */ + Word16* clip_gain, /* o : memory of gain of pitch clipping algorithm */ + Word16* tilt_code, /* o : synthesis excitation spectrum tilt */ + Word16* code, /* o : algebraic excitation Q9 */ + Word32* gain_code, /* o : Code gain. Q16 */ + Word16* y2, /* o : zero-memory filtered adaptive excitation Q9 */ + Word16* gain_inov, /* o : innovation gain Q12 */ + Word16* voice_fac, /* o : voicing factor Q15 */ + Word16* gain_pit, /* o : adaptive excitation gain Q14 */ + const Word16 Q_new, /* i : scaling factor */ + const Word16 shift, /* i : scaling factor */ + Word32* norm_gain_code /* o : normalized innovative cb. gain Q16 */ +); +void pre_proc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 input_frame, /* i : frame length */ + Word16 old_inp_12k8[], /* i/o: buffer of old i signal */ + Word16 old_inp_16k[], /* i/o: buffer of old i signal @ 16kHz */ + Word16 **inp, /* o : ptr. to inp. signal in the current frame */ + Word32 fr_bands[2 * NB_BANDS], /* o : energy in frequency bands */ + Word16 *Etot, /* o : total energy */ + Word32 *ener, /* o : residual energy from Levinson-Durbin */ +#ifndef FIX_I4_OL_PITCH + Word16 pitch_orig[3], /* o : open-loop pitch values for quantization */ +#endif + Word16 A[NB_SUBFR16k*(M + 1)], /* o : A(z) unquantized for the 4 subframes */ + Word16 Aw[NB_SUBFR16k*(M + 1)], /* o : weighted A(z) unquantized for subframes */ + Word16 epsP_h[M + 1], /* o : LP prediction errors */ + Word16 epsP_l[M + 1], /* o : LP prediction errors */ + Word32 epsP[M + 1], /* o : LP prediction errors */ + Word16 lsp_new[M], /* o : LSPs at the end of the frame */ + Word16 lsp_mid[M], /* o : LSPs in the middle of the frame */ + Word16 *vad_hover_flag, + Word16 *attack_flag, /* o : flag signalling attack encoded by AC mode (GSC) */ + Word16 *new_inp_resamp16k, /* o : new i signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + Word16 *Voicing_flag, /* o : voicing flag for HQ FEC */ + + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : cldfb real buffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o : cldfb imag buffer */ + CLDFB_SCALE_FACTOR *cldfbScale, /* o : cldfb scale */ + Word16 *old_exc, /* i/o: static excitation memory */ + Word16 *hq_core_type, /* o : HQ core type */ + Word16 *Q_new, + Word16 *shift, + Word16 *Q_r +); + +void swb_bwe_enc_hr_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + Word16* new_input_fx, /* i : i signal */ + Word16 new_input_fx_exp, /* i : Exponent of i signal */ + const Word16 input_frame, /* i : frame length */ + const Word16 unbits /* i : number of core unused bits */ +); + +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 */ +); +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 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 pvq_core_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 coefs_norm[], /* i/o: normalized coefficients to encode */ + Word16 coefs_quant[], /* o : quantized coefficients */ + Word16* Q_coefs, + const Word16 bits_tot, /* i : total number of bits */ + const Word16 nb_sfm, /* i : number of bands */ + const Word16* sfm_start, /* i : Subband start coefficient */ + const Word16* sfm_end, /* i : Subband end coefficient */ + const Word16* sfmsize, /* i : subband width */ + Word16* R, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */ + Word16* Rs, /* i/o: Integer bit allocation */ + Word16* npulses, /* o : number of pulses */ + Word16* maxpulse, /* i : maximum pulse per band */ + const Word16 core /* i : number of bands */ +); + +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 +); + +void hq_lr_enc_fx( + Encoder_State_fx *st_fx, /* i/o: : encoder state structure */ + Word32 L_t_audio[], /* i/o: Q12 : transform-domain coefs. */ + const Word16 inner_frame_fx, /* i : Q0 : inner frame length */ + Word16 *num_bits_fx, /* i/o: Q0 : number of available bits */ + const Word16 is_transient_fx /* i : Q0 : transient flag */ +); + +void hq_hr_enc_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure fx */ + Word32* t_audio, /* i/o: transform-domain coefficients Q12 */ + const Word16 length, /* i : length of spectrum Q0 */ + Word16* num_bits, /* i : number of available bits Q0 */ + const Word16 is_transient, /* i : transient flag Q0 */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +); + +void reordernorm_fx( + const Word16 *ynrm, /* i : quantization indices for norms Q0 */ + const Word16 *normqlg2, /* i : quantized norms Q0 */ + Word16 *idxbuf, /* o : reordered quantization indices Q0 */ + Word16 *normbuf, /* o : reordered quantized norms Q0 */ + const Word16 nb_sfm /* i : number of bands Q0 */ +); + +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 hq_classifier_enc_fx( /* o : Consumed bits Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 length, /* i : Frame length Q0 */ + const Word32 *coefs, /* i : Spectral coefficients Q12 */ + const Word16 is_transient, /* i : Transient flag Q0 */ + Word16 *Npeaks, /* o : Number of identified peaks Q0 */ + Word16 *peaks, /* o : Peak indices Q0 */ + Word32 *pe_gains, /* o : Peak gains Q12 */ + Word32 *nf_gains, /* o : Noise-fill gains Q12 */ + Word16 *hqswb_clas /* o : HQ class Q0 */ +); + +void diff_envelope_coding_fx( + const Word16 is_transient, /* i : transient indicator Q0 */ + const Word16 num_env_bands, /* i : number of envelope bands to code Q0 */ + const Word16 start_norm, /* i : start of envelope coding Q0 */ + Word16 *ynrm, /* i/o: quantization indices for norms Q0 */ + Word16 *normqlg2, /* i/o: quantized norms Q0 */ + Word16 *difidx /* o : differential code Q0 */ +); + +Word16 encode_envelope_indices_fx( /* o : Number of bits if flag_pack=0,0 if flag_pack=1 Q0 */ + BSTR_ENC_HANDLE hBstr, /* i : handle to the bitstream */ + const Word16 num_sfm, /* i : Number of subbands Q0 */ + const Word16 numnrmibits, /* i : Bitrate of fall-back coding mode Q0 */ + Word16 *difidx, /* i/o: Diff indices/encoded diff indices Q0 */ + Word16 *LCmode, /* o : Coding mode if flag_pack=0, i : if flag_pack=1 Q0 */ + const Word16 flag_pack, /* i : indicator of packing or estimating bits Q0 */ + const Word16 flag_HQ2 /* i : indicator of HQ2 core Q0 */ + , + const Word16 is_transient /* i : indicator of HQ_TRANSIENT Q0 */ +); + +void hq_generic_encoding_fx( + const Word32 *coefs_fx, /* i : MDCT coefficients of weighted original */ + Word16 *hq_generic_fenv_fx, /* i/o: energy of SWB envelope */ + const Word16 hq_generic_offset, /* i : frequency offset for extracting energy */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *hq_generic_exc_clas /* o : bwe excitation class */ +); + +void normalizecoefs_fx( + Word32 *coefs, /* i : Input vector (Q12) */ + const Word16 *ynrm, /* i : quantization indices for norms */ + const Word16 num_bands, /* i : Number of bands */ + const Word16 *band_start, /* i : Start of bands */ + const Word16 *band_end, /* i : End of bands */ + Word16 *coefs_norm /* o : Normalized output vector (Q12) */ +); + +Word16 hvq_enc_fx( /* o : Consumed bits */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 brate, /* i : Total bit rate */ + const Word16 hvq_bits, /* i : HVQ bit budget */ + const Word16 Npeaks, /* i : Number of peaks */ + const Word16 *ynrm, /* i : Envelope coefficients */ + Word16 *R, /* i/o: Bit allocation/updated bit allocation */ + Word16 *peaks, /* i : Peak pos. / Encoded peak pos. */ + Word32 *nf_gains, /* i/o: Noise fill gains / Quant. nf gains */ + Word16 *noise_level, /* o : Quantized noise level */ + const Word32 *pe_gains, /* i : Peak gains */ + const Word32 *coefs, /* i : spectrum coefficients in Q14 */ + Word32 *coefs_out /* o : encoded spectrum coefficients in Q14 */ +); + +Word16 pvq_core_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 coefs_norm[], /* i/o: normalized coefficients to encode */ + Word16 coefs_quant[], /* o : quantized coefficients */ + Word16* Q_coefs, + const Word16 bits_tot, /* i : total number of bits */ + const Word16 nb_sfm, /* i : number of bands */ + const Word16* sfm_start, /* i : Subband start coefficient */ + const Word16* sfm_end, /* i : Subband end coefficient */ + const Word16* sfmsize, /* i : subband width */ + Word16* R, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */ + Word16* Rs, /* i/o: Integer bit allocation */ + Word16* npulses, /* o : number of pulses */ + Word16* maxpulse, /* i : maximum pulse per band */ + const Word16 core /* i : number of bands */ +); + +Word16 noise_adjust_fx( /* o : index of noise attenuation Q0 */ + const Word16 *coeffs_norm, /* i : normalized coefficients Qx */ + const Word16 qx, /* i : Q value of coeffs_norm */ + const Word16 *bitalloc, /* i : bit allocation Q0 */ + const Word16 *sfm_start, /* i : band start Q0 */ + const Word16 *sfm_end, /* i : band end Q0 */ + const Word16 core_sfm /* i : index of the end band for core Q0 */ +); +ivas_error tcq_core_LR_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 inp_vector_fx[], /* x5 */ + const Word32 coefs_norm_fx[], /* Q12 */ + Word32 coefs_quant_fx[], /* Q12 */ + const Word16 bit_budget, /* number of bits */ + const Word16 BANDS, + const Word16* sfm_start, + const Word16* sfm_end, + const Word16* sfmsize, + Word32* R_fx, /* Q16 */ + Word16* npulses, + Word16* k_sort, + const Word16* p2a_flags, + const Word16 p2a_bands, + const Word16* last_bitalloc, + const Word16 input_frame, + const Word16 adjustFlag, + const Word16 is_transient +); + +Word16 encode_envelope_indices_fx( /* o : Number of bits if flag_pack=0,0 if flag_pack=1 Q0 */ + BSTR_ENC_HANDLE hBstr, /* i : handle to the bitstream */ + const Word16 num_sfm, /* i : Number of subbands Q0 */ + const Word16 numnrmibits, /* i : Bitrate of fall-back coding mode Q0 */ + Word16 *difidx, /* i/o: Diff indices/encoded diff indices Q0 */ + Word16 *LCmode, /* o : Coding mode if flag_pack=0, i : if flag_pack=1 Q0 */ + const Word16 flag_pack, /* i : indicator of packing or estimating bits Q0 */ + const Word16 flag_HQ2 /* i : indicator of HQ2 core Q0 */ + , + const Word16 is_transient /* i : indicator of HQ_TRANSIENT Q0 */ +); +void diffcod_lrmdct_fx( + const Word16 N, /* i : number of sub-vectors */ + const Word16 be_ref, /* i : band energy reference */ + Word16 *y, /* i/o: indices of quantized norms */ + Word16 *difidx, /* o : differential code */ + const Word16 is_transient /* i : transient flag */ +); + +Word16 peak_vq_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 bwidth, /* i : audio bandwidth */ + const Word32* coefs, /* i : Input coefficient vector Q12 */ + Word32* coefs_out, /* o : Quantized output vector Q12 */ + const Word32 brate, /* i : Core bitrate */ + const Word16 num_bits, /* i : Number of bits for HVQ */ + const Word16 vq_peaks, /* i : Number of identified peaks */ + const Word16* ynrm, /* i : Envelope coefficients */ + Word16* R, /* i/o: Bit allocation/updated bit allocation */ + Word16* vq_peak_idx, /* i : Peak index vector */ + Word32* nf_gains /* i : Estimated noise floor gains Q12 */ +); + +void wb_vad_init_fx( + VAD_HANDLE hVAD /* i/o: VAD data handle */ +); +void noise_est_init_fx( + NOISE_EST_HANDLE hNoiseEst /* i/o: Noise estimation handle */ +); + +void InitSWBencBuffer_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +); + +void ResetSHBbuffer_Enc_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +); +Word16 E_ACELP_hh_corr(Word16 *x, Word16 *y, Word16 L_subfr, Word16 bits); + +void acelp_1t64_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 */ + const Word16 L_subfr /* i : subframe length */ +); + +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 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 : coomplexity reduction flag */ + const Word16 Opt_AMR_WB /* i : flag indicating AMR-WB IO mode */ +); + +ivas_error evs_enc_fx( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16* data, /* i : i signal */ + Word32* mem_hp20_in_fx, /* i/o: hp20 filter memory */ + const Word16 n_samples /* i : number of i samples */ +); + +/* y(n)(Qx) = alpha(Q15) * x(Qx) + (1.0f-alpha)* y(n-1) (Qx) */ +Word16 noise_est_AR1_Qx( /* o: Qx y(n) */ + Word16 x, /* i : Qx x(n) */ + Word16 y, /* i : Qx y(n-1) */ + Word16 alpha /*i : Q15 scaling of driving x(n) */ +); +void FEC_lsf_estim_enc_fx( + Encoder_State_fx *st_fx, /* i : Encoder static memory */ + Word16 *lsf /* o : estimated LSF vector */ +); + +Word32 mslvq_cng_fx( + Word16 idx_cv, /* i : index of cv from previous stage */ + Word16 *pTmp, /* i : 16 dimensional i vector x2.56*/ + Word16 *quant, /* o : quantized vector x2.56*/ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) Q13*/ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + const Word16 *w, /* i : weights for LSF quantization Q10*/ + Word16 * no_scales +); + +void Unified_weighting_fx( + const Word32 Bin_Ener_128_fx[], /* i : FFT Bin energy 128 bins in two sets Q_ener */ + Word16 Q_ener, + const Word16 lsf_fx[], /* i : LSF vector x2.56 */ + Word16 w_fx[], /* o : LP weighting filter (numerator) Q8 */ + const Word16 narrowBand, /* i : flag for Narrowband */ + const Word16 unvoiced, /* i : flag for Unvoiced frame */ + const Word32 sr_core, /* i : sampling rate of core-coder */ + const Word16 order /* i : LP order */ +); + +Word32 qlsf_ARSN_tcvq_Enc_16k_fx( + const Word16 *x_fx, /* i : Vector to be encoded x2.65 */ + Word16 *y_fx, /* o : Quantized LSF vector x2.65 */ + Word16 *indice, /* o : Indices */ + const Word16 *w_fx, /* i : LSF Weights Q10 */ + const Word16 nBits, /* i : number of bits */ + Word16 safety_net /* i : safety_net flag */ +); + +Word32 mslvq_fx( + Word16 *pTmp, /* i : M-dimensional i vector */ + Word16 *quant, /* o : quantized vector */ + Word16 *cv_out, /* o : corresponding 8-dim lattice codevectors (without the scaling) */ + Word16 *idx_lead, /* o : leader index for each 8-dim subvector */ + Word16 *idx_scale, /* o : scale index for each subvector */ + Word16 *w, /* i : weights for LSF quantization */ + Word16 mode, /* i : number indicating the coding type (V/UV/G...)*/ + Word16 mode_glb, /* i : LVQ coding mode */ + Word16 pred_flag, /* i : prediction flag (0: safety net, 1 - predictive )*/ + Word16 no_scales[][2] +); + +Word16 multi_harm_fx( /* o : frame multi-harmonicity (1-harmonic, 0-not) */ + const Word16 Bin_E[], /* i : log-energy spectrum of the current frame Q7 */ + Word16 old_S[], /* i/o: prev. log-energy spectrum w. subtracted floor Q7 */ + Word16 cor_map_LT[], /* i/o: LT correlation map Q15 */ + Word16* multi_harm_limit, /* i/o: multi harminic threshold Q9 */ + const Word32 total_brate, /* i : total bitrate Q0 */ + const Word16 bwidth, /* i : i signal bandwidth Q0 */ + Word16* cor_strong_limit, /* i/o: HF correlation indicator Q0 */ + Word16* st_mean_avr_dyn, /* i/o: long term average dynamic Q7 */ + Word16* st_last_sw_dyn, /* i/o: last dynamic Q7 */ + Word16* cor_map_sum, /* i : sum of correlation map Q8 */ + Word16* sp_floor, /* o: noise floor estimate Q7 */ + Word16 S_map[] /* o : short-term correlation map Q7 */ +); + +void pvq_encode_frame_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16* coefs_norm, /* i : normalized coefficients to encode */ + Word16 Q_coefs, /* i : Q-point of coefs_norm[] */ + Word16* coefs_quant, /* o : quantized coefficients */ + Word16* gopt, /* o : optimal shape gains */ + Word16* npulses, /* o : number of pulses per band */ + Word16* pulse_vector, /* o : non-normalized pulse shapes */ + const Word16* sfm_start, /* i : indices of first coefficients in the bands */ + const Word16* sfm_end, /* i : indices of last coefficients in the bands */ + const Word16* sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16* R, /* i : bitallocation per band Q3 */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +); + +Word16 Interpol_4( /* o : interpolated value */ + Word16 * x, /* i : i vector */ + Word16 frac /* i : fraction (-4..+3) */ +); + +void set_ppp_mode_fx( + Encoder_State_fx* st_fx, /* i/o: state structure */ + const Word16 noisy_speech_HO, /* i : SC-VBR noisy speech HO flag */ + const Word16 clean_speech_HO, /* i : SC-VBR clean speech HO flag */ + const Word16 NB_speech_HO, /* i : SC-VBR NB speech HO flag */ + const Word16 localVAD_he /* i : HE-SAD flag without hangover */ +); + +void decision_matrix_enc_fx( + Encoder_State_fx *st_fx, /* i : encoder state structure */ + Word16 *hq_core_type /* o : HQ core_fx type */ +); + +void pvq_encode_fx( + BSTR_ENC_HANDLE hBstr, + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *x, /* i: vector to quantize Q15-3=>Q12 */ + Word16 *y, /* o: raw pulses (non-scaled short) Q0 */ + Word16 *xq, /* o: quantized vector Q15 */ + Word32 *L_xq, /* o: quantized vector Q31 */ + const Word16 pulses, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: - Gain use - negative gain in Q15 0 ..1 */ +); + +void rc_enc_init_fx( + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + Word16 tot_bits /* i : Total bit budget */ +); + +void rc_enc_finish_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: Encoder state */ + PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ +); + +void rc_encode_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq, /* i : Symbol probability */ + UWord32 tot /* i : Total cumulative frequency */ +); + +void rc_enc_uniform_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + UWord32 tot /* i : Maximum value */ +); + +void rc_enc_bits_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + Word16 bits /* i : Number of bits used */ +); + +void re8_compute_base_index_fx( + const Word16 *x, /* i : Elemen of Q2, Q3 or Q4 */ + const Word16 ka, /* i : Identifier of the absolute leader related to x */ + UWord16 *I /* o : index */ +); + +void tfaCalcEnv_fx( + const Word16* shb_speech, + Word32* enr +); + +Word16 delta_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4)*/ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac, /* i : pitch fraction */ + const Word16 T0_min /* i : delta search min */ +); + +void set_impulse_fx( + const Word16 xn_fx[], /* i : target signal */ + const Word16 h_orig_fx[], /* i : impulse response of weighted synthesis filter */ + Word16 exc_fx[], /* o : adaptive codebook excitation */ + Word16 yy1_fx[], /* o : filtered adaptive codebook excitation */ + Word16 *imp_shape, /* o : adaptive codebook index */ + Word16 *imp_pos, /* o : position of the glotal impulse center index */ + Word32 *gain_trans_fx, /* o : transition gain Q7 */ + Word16 Q_new /* i : Current scaling */ +); + +Word16 abs_pit_enc_fx( /* o : pitch index */ + const Word16 fr_steps, /* i : fractional resolution steps (2 or 4) for shortest pitches*/ + const Word16 limit_flag, /* i : restrained(0) or extended(1) limits */ + const Word16 T0, /* i : integer pitch lag */ + const Word16 T0_frac /* i : pitch fraction */ +); + +ivas_error ppp_quarter_encoder_fx( + Word16* returnFlag, /* o : return value */ + DTFS_STRUCTURE* CURRCW_Q_FX, /* o : Quantized (amp/phase) DTFS */ + DTFS_STRUCTURE* TARGETCW_FX, /* o : DTFS with quant phase but unquant Amp */ + Word16 prevCW_lag, /* i : previous lag */ + DTFS_STRUCTURE vCURRCW_NQ_FX, /* i : Unquantized DTFS */ + const Word16* curr_lpc_fx, /* i : LPCS */ + Word16* lastLgainE_fx, /* i/o: last low band gain */ + Word16* lastHgainE_fx, /* i/o: last high band gain */ + Word16* lasterbE_fx, /* i/o: last ERB vector */ + DTFS_STRUCTURE PREV_CW_E_FX, /* i : past DTFS */ + Word16* S_fx, /* i : sin table, Q15 */ + Word16* C_fx, /* i : cos table, Q15 */ + BSTR_ENC_HANDLE hBstr /* i/o: encoder bitstream handle */ +); + +void index_lvq_fx( + Word16 *quant, /* i : codevector to be indexed (2 8-dim subvectors) Q13*/ + Word16 *idx_lead, /* i : leader class index for each subvector */ + Word16 *idx_scale, /* i : scale index for each subvector */ + Word16 mode, /* i : integer signalling the quantizer structure for the current bitrate */ + Word16 *index, /* o : encoded index (represented on 3 short each with 15 bits ) */ + Word32 * p_offset_scale1, + Word32 * p_offset_scale2, + Word16 * p_no_scales +); + +ivas_error init_encoder_fx( + Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */ +); + +void copy_encoder_config_fx( + Encoder_Struct *st_ivas, /* i : IVAS encoder structure */ + Encoder_State_fx *st, /* o : encoder state structure */ + const int16_t flag_all /* i : flag 1==update all, 0=partial update*/ +); + +void destroy_encoder_fx( + Encoder_State_fx *st_fx /* i/o: Encoder static variables structure */ +); + +void amr_wb_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 input_sp[], /* i : i signal */ + const Word16 n_samples /* i : number of i samples */ +); +#endif \ No newline at end of file diff --git a/lib_enc/pvq_core_enc_fx.c b/lib_enc/pvq_core_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..6407888306906edd9052c672ab12185e7986d8d2 --- /dev/null +++ b/lib_enc/pvq_core_enc_fx.c @@ -0,0 +1,661 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* Compilation switches */ +#include "cnst.h" +#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 function prototypes + *--------------------------------------------------------------------*/ + +static Word16 calc_pvq_splits_fx(BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16 band_bits, const Word16 sfmsize, const Word16 *y, const Word16 Q_y, + Word16 *bits); + +static void densityIndexSymbolEncode_fx(BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16 density , const Word16 r_dim, const Word16 l_dim , const Word16 index_phi ); +static void encode_energies_fx(BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ, const Word16* coefs, const Word16 Q_coefs, Word16 Np, + Word16* dim_part, Word32* E_part, Word16* bits_part, Word16* g_part, Word16 qband, Word16* bits_left, Word32 enr, Word16 dim, const Word16 strict_bits); + +/* Encode band with PVQ */ + +static void pvq_encode_band_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: Encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16* coefs_norm, /* i : normalized vector to encode */ + const Word16 Q_coefs, + Word16 *pulse_vector, /* o : quantized vector, integer */ + Word16* npulses, /* o : number of pulses */ + Word16* coefs_quant, /* o : quantized vector */ + const Word16 sfmsize, /* i : length of vector */ + const Word16 band_bits, /* i : assigned bits */ + Word16* bits_left, /* o : bits remaining */ + const Word16 strict_bits /* i : conservative rounding flag */ +) +{ + + Word16 K_val; + Word16 j, Np; + Word32 enr, E_part[MAX_SPLITS+1]; + Word16 part_start[MAX_SPLITS+1], dim_part[MAX_SPLITS+1], bits_part[MAX_SPLITS+1]; + Word16 pool_tot, pool_part, dim_parts; + Word16 g_part[MAX_SPLITS]; + Word16 g_part_neg[MAX_SPLITS]; + Word16 sg_part[MAX_SPLITS+1]; + Word16 idx_sort[MAX_SPLITS+1]; + Word16 js, band_bits_tot, split_bit; + Word16 tmp; + Word32 L_coefs_quant_fx[PVQ_MAX_BAND_SIZE]; + + Np = calc_pvq_splits_fx(hBstr, hPVQ, band_bits, sfmsize, coefs_norm, Q_coefs, &split_bit); + band_bits_tot = sub(band_bits, split_bit); + + enr = L_deposit_l(0); + FOR (j = 0; j < sfmsize; j++) + { + /* This is of paramount importance that the number of bits down-shift here + * MUST BE IDENTICAL to that used to compute "l_enr" in encode_energies_fx(). + * If the number of bits down-shift is changed here, that in encode_energies_fx() + * must be changed to the same amount as well! + */ + tmp = shr(coefs_norm[j], 2); + enr = L_mac0(enr, tmp, tmp); + } + + dim_parts = extract_h(L_mult(negate(sfmsize),lim_neg_inv_tbl_fx[Np])); + set16_fx( dim_part, dim_parts, sub(Np, 1) ); + dim_part[Np-1] = sub(sfmsize, i_mult2(dim_parts, sub(Np, 1))); + move16(); + + part_start[0] = 0; + move16(); + FOR (j = 1; j < Np; j++) + { + part_start[j] = add(part_start[j-1], dim_part[j-1]); + move16(); + } + + /* Encode energies */ + set16_fx(g_part_neg, -32768, Np); /* -1.0 in Q15 */ + IF (GT_16(Np, 1)) + { + encode_energies_fx(hBstr, hPVQ, coefs_norm, Q_coefs, Np, dim_part, E_part, bits_part, g_part_neg, band_bits_tot, bits_left, enr, sfmsize, strict_bits ); + } + ELSE + { + bits_part[0] = band_bits_tot; + move16(); + } + + pool_tot = 0; /* Word16 */ + pool_part = 0; /* Word16 */ + + FOR (j = 0; j < Np; j++) + { + g_part[j] = negate(g_part_neg[j]); + } + srt_vec_ind16_fx(g_part, sg_part, idx_sort, Np); + FOR(j = 0; j < Np; j++) + { + js = idx_sort[Np-1-j]; + pool_part = shrtCDivSignedApprox( pool_tot, sub(Np, j) ); + bits_part[js] = s_max(0, s_min(add(bits_part[js], pool_part), 256)); + + conservativeL1Norm_fx(dim_part[js], bits_part[js], strict_bits, *bits_left, pool_tot, *npulses, /* inputs */ + &K_val, bits_left, &pool_tot, npulses); /* outputs */ + + IF( K_val > 0 ) + { + pvq_encode_fx(hBstr, hPVQ, coefs_norm + part_start[js], pulse_vector + part_start[js], + coefs_quant + part_start[js], L_coefs_quant_fx, K_val, dim_part[js], g_part_neg[js]); + } + ELSE + { + set16_fx(coefs_quant + part_start[js], 0, dim_part[js]); + set16_fx(pulse_vector + part_start[js], 0, dim_part[js]); + } + } + + return; +} + +void pvq_encode_frame_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 *coefs_norm, /* i : normalized coefficients to encode */ + Word16 Q_coefs, /* i : Q-point of coefs_norm[] */ + Word16 *coefs_quant, /* o : quantized coefficients */ + Word16 *gopt, /* o : optimal shape gains */ + Word16 *npulses, /* o : number of pulses per band */ + Word16 *pulse_vector, /* o : non-normalized pulse shapes */ + const Word16 *sfm_start, /* i : indices of first coefficients in the bands */ + const Word16 *sfm_end, /* i : indices of last coefficients in the bands */ + const Word16 *sfmsize, /* i : band sizes */ + const Word16 nb_sfm, /* i : total number of bands */ + const Word16 *R, /* i : bitallocation per band Q3 */ + const Word16 pvq_bits, /* i : number of bits avaiable */ + const Word16 core /* i : core */ +) +{ + Word16 i, j; + Word16 band_bits, bits_left; + + Word16 bit_pool = 0; + Word16 coded_bands, bands_to_code; + Word16 bits; + Word16 R_sort[NB_SFM]; + Word16 is, i_sort[NB_SFM]; + Word16 strict_bits; + Word16 exp, tmp, shift; + Word32 xy_corr, yy_corr; + PVQ_ENC_DATA pvq_enc; + PVQ_ENC_HANDLE hPVQ = &pvq_enc; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + rc_enc_init_fx(hPVQ, pvq_bits); + + bits = shl(sub(pvq_bits, RC_BITS_RESERVED), 3); + + bands_to_code = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + if (R[i] > 0) + { + bands_to_code = add(bands_to_code, 1); + } + } + + IF (core == ACELP_CORE) + { + strict_bits = 1; + move16(); + srt_vec_ind16_fx(R, R_sort, i_sort, nb_sfm); + } + ELSE + { + strict_bits = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + i_sort[i] = i; + move16(); + } + } + + coded_bands = 0; + move16(); + FOR (i = 0; i < nb_sfm; i++) + { + is = i_sort[i]; + move16(); + gopt[is] = 0; + move16(); + IF (R[is] > 0) + { + bandBitsAdjustment_fx(hPVQ->rc_num_bits, hPVQ->rc_range, bits, bands_to_code, bands_to_code-coded_bands, sfmsize[is] ,R[is], bit_pool, /* inputs */ + &band_bits, &bits_left, &bit_pool); /* outputs */ + pvq_encode_band_fx(hBstr, hPVQ, &coefs_norm[sfm_start[is]], Q_coefs, &pulse_vector[sfm_start[is]], + &npulses[is], &coefs_quant[sfm_start[is]], sfmsize[is], band_bits, + &bits_left, strict_bits); + + xy_corr = L_deposit_l(0); + yy_corr = L_deposit_l(1); + shift = band_len_ener_shift[ band_len_idx[ shr(sfmsize[is], 3)] ]; + move16(); + FOR (j = 0; j < sfmsize[i]; j++) + { + tmp = shr(coefs_quant[sfm_start[is]+j], shift); + xy_corr = L_mac0(xy_corr, shr(coefs_norm[sfm_start[is]+j], 1), tmp); /* Q_coefs-1+15-shift */ + yy_corr = L_mac0(yy_corr, tmp, tmp); /* 2*(15-shift) */ + } + + tmp = ratio(xy_corr, yy_corr, &exp); +#ifdef BASOP_NOGLOB + gopt[is] = shl_o(tmp, sub(sub(sub(14, Q_coefs), shift), exp), &Overflow); +#else /* BASOP_NOGLOB */ + gopt[is] = shl(tmp, sub(sub(sub(14, Q_coefs), shift), exp)); +#endif + + if (gopt[is] == 0) + { + gopt[is] = 1; + move16(); + } + + /* Updates */ + coded_bands = add(coded_bands, 1); + } + ELSE + { + FOR (j = sfm_start[is]; j < sfm_end[is]; j++) + { + coefs_quant[j] = 0; + move16(); + pulse_vector[j] = 0; + move16(); + } + } + } + + rc_enc_finish_fx(hBstr, hPVQ); + + return; +} + +/*---------------------------------------------------------------------* + * pvq_core_enc() + * + * Main Generic Audio Encoder Routine + *---------------------------------------------------------------------*/ + +Word16 pvq_core_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 coefs_norm[], /* i/o: normalized coefficients to encode */ + Word16 coefs_quant[], /* o : quantized coefficients */ + Word16 *Q_coefs, + const Word16 bits_tot, /* i : total number of bits */ + const Word16 nb_sfm, /* i : number of bands */ + const Word16* sfm_start, /* i : Subband start coefficient */ + const Word16* sfm_end, /* i : Subband end coefficient */ + const Word16* sfmsize, /* i : subband width */ + Word16* R, /* i/o: Bit allocation/Adjusted bit alloc. Q3 */ + Word16* Rs, /* i/o: Integer bit allocation */ + Word16* npulses, /* o : number of pulses */ + Word16* maxpulse, /* i : maximum pulse per band */ + const Word16 core /* i : number of bands */ +) +{ + Word16 i; + Word16 R_upd; /* Q3 */ + Word16 ord[NB_SFM_MAX]; + Word16 fg_pred[NB_SFM_MAX]; + Word16 pvq_bits; + + Word16 pulse_vector[L_SPEC48k_EXT]; + Word16 gopt[NB_SFM]; + Word16 gain_bits_array[NB_SFM]; + Word16 gain_bits_tot; + + + R_upd = shl(bits_tot, 3); + gain_bits_tot = assign_gain_bits_fx( core, nb_sfm, sfmsize, R, gain_bits_array, &R_upd ); + pvq_bits = shr(R_upd, 3); + + pvq_encode_frame_fx( hBstr, coefs_norm, *Q_coefs, coefs_quant, gopt, npulses, pulse_vector, sfm_start, sfm_end, sfmsize, nb_sfm, R, pvq_bits, core ); + + + IF( Rs != NULL ) + { + FOR (i=0; i < nb_sfm; i++) + { + if (npulses[i] <= 0) + { + Rs[i] = 0; + move16(); /* Update Rs in case no pulses were assigned */ + } + } + } + + FOR (i=0; i < nb_sfm; i++) + { + ord[i] = i; + move16(); + if (npulses[i] <= 0) + { + R[i] = 0; + move16(); /* Update in case no pulses were assigned */ + } + } + + get_max_pulses_fx( sfm_start, sfm_end, ord, npulses, nb_sfm, pulse_vector, maxpulse ); + + /* Fine gain prediction */ + fine_gain_pred_fx( sfm_start, sfm_end, sfmsize, ord, npulses, maxpulse, R, nb_sfm, + coefs_quant, pulse_vector, fg_pred, core); + + fine_gain_quant_fx(hBstr, ord, nb_sfm, gain_bits_array, fg_pred, gopt); + + apply_gain_fx(ord, sfm_start, sfm_end, nb_sfm, fg_pred, coefs_quant); + *Q_coefs = 12; + + return add(pvq_bits, gain_bits_tot);; +} + +static void encode_energies_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *coefs, /* In block-floating point format with a common block-exponent + not used in this function. Hence, the block-exponent is + not in the parameter list. */ + const Word16 Q_coefs, + Word16 Np, /* i : number of parts */ + Word16 *dim_part, /* o : sizes of parts */ + Word32 *E_part, /* o : energies of parts 32-bit Q15 */ + Word16 *bits_part, /* o : assigned bits per part */ + Word16 *g_part, /* o : gains Q15 */ + Word16 qband, /* i : assigned quanta per band */ + Word16 *bits_left, /* o : remaining bits */ + Word32 enr, /* i : energy of vector */ + Word16 dim, /* i : size of vector */ + const Word16 strict_bits /* i : conservative rounding flag */ +) +{ + Word16 i, j, l_Np, r_Np; + Word16 l_bits, r_bits, l_dim, r_dim; + Word32 l_enr, r_enr; + Word16 l_gain, r_gain; + Word16 il, ir; + Word16 density; + Word16 phi; + Word16 index_phi = -1; + Word16 oppRQ3, qzero ; + Word16 angle; + Word32 sqrt_r_enr, sqrt_l_enr; + Word16 exp1, exp2, tmp; + l_Np = shr(Np, 1); + r_Np = sub(Np, l_Np); + + l_enr = L_deposit_l(0); + l_bits = 0; + move16(); + l_dim = 0; + move16(); + FOR (i = 0; i < l_Np; i++) + { + l_dim = add(l_dim, dim_part[i]); + } + FOR (j = 0; j < l_dim; j++) + { + /* This is of paramount importance that the number of bits down-shift + * must be identical to that used to compute "enr" in pvq_encode_band_fx(). + * Otherwise, the subsequent "r_enr" will be computed incorrectly. + */ + tmp = shr(coefs[j], 2); + l_enr = L_mac0(l_enr, tmp, tmp); + } + r_enr = L_sub(enr, l_enr); + r_dim = sub(dim, l_dim); + + obtainEnergyQuantizerDensity_fx(dim, qband, &density); + sqrt_r_enr = Sqrt_l(r_enr, &exp1); + sqrt_l_enr = Sqrt_l(l_enr, &exp2); + + IF (LT_16(exp1, exp2)) + { + sqrt_l_enr = L_shr(sqrt_l_enr, shr(sub(exp2, exp1), 1)); + } + ELSE IF (LT_16(exp2, exp1)) + { + sqrt_r_enr = L_shr(sqrt_r_enr, shr(sub(exp1, exp2), 1)); + exp1 = exp2; + move16(); + } + + exp1 = add(shl(sub(Q_coefs, 2), 1), add(31, exp1)); /* 2x exponent */ + IF (EQ_16(s_and(exp1, 1), 1)) + { + sqrt_r_enr = Mult_32_16(sqrt_r_enr, 23170); /* Q(exp1/2) */ + sqrt_l_enr = Mult_32_16(sqrt_l_enr, 23170); /* Q(exp1/2) */ + } + + IF (sqrt_r_enr != 0) + { + angle = atan2_fx(sqrt_r_enr, sqrt_l_enr); /* Q14 */ + } + ELSE + { + angle = 0; + move16(); + } + + phi = mult_r(angle, 20861); + + rangeCoderFinalizationFBits_fx(hPVQ->rc_num_bits, (UWord32)hPVQ->rc_range, &qzero); + densityAngle2RmsProjEnc_fx(density, phi , &index_phi, &ir, &il, &oppRQ3); + densityIndexSymbolEncode_fx( hBstr, hPVQ, density , r_dim, l_dim , index_phi ); + + + + l_gain = il; /* Q15 */ move16(); + r_gain = ir; /* Q15 */ move16(); + + FOR (i = 0; i < l_Np; i++) + { + g_part[i] = mult_r(l_gain, g_part[i]); + } + + FOR (i = l_Np; i < Np; i++) + { + g_part[i] = mult_r(r_gain, g_part[i]); + } + + NearOppSplitAdjustment_fx( qband, qzero, hPVQ->rc_num_bits, hPVQ->rc_range, *bits_left, + strict_bits, Np, dim_part[0], dim_part[Np-1], + l_dim, r_dim, oppRQ3, + &l_bits, &r_bits, bits_left); + + IF (GT_16(l_Np, 1)) + { + encode_energies_fx(hBstr, hPVQ, coefs, Q_coefs, l_Np, dim_part, E_part, bits_part, g_part, l_bits, bits_left, l_enr, l_dim, strict_bits ); + } + ELSE + { + E_part[0] = l_enr; + move32(); + bits_part[0] = l_bits; + move16(); + } + IF (GT_16(r_Np, 1)) + { + encode_energies_fx(hBstr, hPVQ, &coefs[l_dim], Q_coefs, r_Np, &dim_part[l_Np], &E_part[l_Np], &bits_part[l_Np], &g_part[l_Np], r_bits, bits_left, r_enr, r_dim, strict_bits ); + } + ELSE + { + E_part[1] = r_enr; + move32(); + bits_part[1] = r_bits; + move16(); + } + + return; +} + + +static void densityIndexSymbolEncode_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 density, /* i : Current density */ + const Word16 r_dim, /* i : Opposite size */ + const Word16 l_dim, /* i : Near size */ + const Word16 index_phi /* i : Index */ +) +{ + Word16 angle, c, densitySubIndex, densitySubC; + Word32 sym_freq, cum_freq, tot; + Word32 acc; + UWord16 lsb; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + sym_freq = L_deposit_l(1); + + IF( s_and((Word16)0xFFFE, density) != 0 ) /* even */ + { + angle = atan2_fx(SQRT_DIM_fx[r_dim], SQRT_DIM_fx[l_dim]); +#ifdef BASOP_NOGLOB + angle = shl_o(angle, 1, &Overflow); +#else + angle = shl(angle, 1); +#endif + angle = mult_r(angle, 20861); + c = mult_r(density, angle); + + densitySubIndex = sub(density, index_phi); + densitySubC = sub(density, c); + + IF (c == 0) + { + tot = L_mac0(1L, density, add(density, 1)); + sym_freq = L_deposit_l(add(shl(sub(density, index_phi), 1), 1)); + cum_freq = L_mac0(L_mult(index_phi, density), index_phi, 1); + } + ELSE IF (EQ_16(c, density)) + { + tot = L_mac0(1L, density, add(density, 1)); + sym_freq = L_deposit_l(add(shl(index_phi, 1), 1)); + cum_freq = L_mult0(index_phi, index_phi); + } + ELSE + { + acc = L_mult0(density, c); /* density*c */ + Mpy_32_16_ss(acc, densitySubC, &acc, &lsb); /* density*c*(density - c) */ + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); /* Concatenate acc and lsb forming 48-bit; upshift 16 bits; keep 32 MSB. */ + acc = L_shr(acc, 1); /* Compensate fractional mode multiply (Mpy_32_16_ss) */ + tot = L_add(L_add(acc, (Word32)density), 1L); /* density*c*(density - c) + density + 1 */ + IF (LE_16(index_phi, c)) + { + sym_freq = L_mac(1L, index_phi, densitySubC); + acc = L_mult0(densitySubC, sub(index_phi, 1)); + acc = L_add(acc, 1); + Mpy_32_16_ss(acc, index_phi, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); + cum_freq = L_shr(acc, 1); + } + ELSE + { + sym_freq = L_mac(1L, densitySubIndex, c); + acc = L_mult0(densitySubIndex, add(densitySubIndex, 1)); + Mpy_32_16_ss(acc, c, &acc, &lsb); + acc = L_or(L_shl(acc, 16), L_and(lsb, 0xffffL)); + acc = L_shr(acc, 1); + acc = L_sub(acc, (Word32)index_phi); + acc = L_add(add(density, 1), acc); + cum_freq = L_sub(tot, acc); + } + } + + rc_encode_fx(hBstr, hPVQ, cum_freq, sym_freq, tot); + } + + return; +} + +/*--------------------------------------------------------------------------* + * calc_pvq_splits() + * + * Calculate the number of segments needed + *--------------------------------------------------------------------------*/ + +static Word16 calc_pvq_splits_fx( /* o : Number of segments */ + BSTR_ENC_HANDLE hBstr, /* i/o: Encoder state */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 band_bits, /* i : Band bit rate */ + const Word16 sfmsize, /* i : Band width */ + const Word16 *y, /* i : Target vector */ + const Word16 Q_y, /* i : Q point of y */ + Word16 *bits /* o : Consumed bits */ +) +{ + Word16 Np; + Word16 Npart; + Word16 i,j; + Word16 E[MAX_SPLITS]; + Word16 Emean, eTotal; + Word16 tmp, expo; + const Word16 *pY; + Word16 max_dev,qPoint; + Word32 acc, acc1; + + IF (band_bits == 0) + { + Np = 1; + move16(); + } + ELSE + { + acc = L_mult0(band_bits, 0x7a44); + Np = extract_l(L_shr(acc, 23)); /* Get integer part. */ + if (L_and(acc, 0x7fffffL) != 0) /* If fractional part != 0, add 1. */ + { + Np = add(Np, 1); /* ceiling operation */ + } + } + *bits = 0; + move16(); + + IF (LT_16(Np, MAX_SPLITS)) + { + acc = L_mult0(8*THR_ADD_SPLIT, sfmsize); + IF (GT_32(band_bits, acc)) + { + Npart = extract_l((Word32)intLimCDivPos_fx(UL_deposit_l((UWord16)sfmsize), Np)); + *bits = 8; + move16(); + eTotal = 0; + move16(); + pY = y; + qPoint = shl(Q_y, 1); /* acc in 2*Q_y */ + FOR (i = 0; i < Np; i++) + { + acc = L_deposit_l(0); + FOR (j = 0; j < Npart; j++) + { + acc= L_mac0(acc, *pY, *pY); + pY++; + } + acc = L_shr(acc, qPoint); + + E[i] = sub(30, norm_l(L_max(1L,acc))); /* L_max needed to handle low subvector levels */ + eTotal = add(eTotal, E[i]); + } + + Emean = ratio(eTotal, Np, &expo); + Emean = shr(Emean, add(14 - 8, expo)); /* Emean in Q8 */ + + max_dev = -1; + move16(); + FOR (i = 0; i < Np; i++) + { + tmp = abs_s(sub(shl(E[i], 8), Emean)); /* in Q8 */ + max_dev = s_max(tmp, max_dev); + } + + acc = L_sub(L_shl(Np, 5 + 3 + 8), L_shl(band_bits, 8)); /* NB: max_dev in Q8 */ + acc1 = L_shl(L_mult0(Np, max_dev), 3); + + tmp = 0; + move16() ; + if( GT_32(acc1, acc)) + { + tmp = 1; + move16(); + } + rc_enc_bits_fx(hBstr, hPVQ, tmp, 1); + Np = add(Np, tmp); + } + } + + /* Check constraints for number of splits */ + /* The following code assumes that PVQ_MAX_BAND_SIZE is 64 */ + i = shr(sfmsize, 6); /* 6 = log2(64) = log2(PVQ_MAX_BAND_SIZE) */ + if (s_and(sfmsize, 0x3f) != 0) + { + i = add(i, 1); /* ceiling operation */ + } + + Np = s_max(i, Np); + Np = s_min(MAX_SPLITS, Np); + Np = s_min(sfmsize, Np); /* The code line assumes that MIN_BAND_SIZE is 1 */ + return Np; +} + + diff --git a/lib_enc/pvq_encode_fx.c b/lib_enc/pvq_encode_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..d5300326336a4fc9422a2b9ff29edcbc5dde5d13 --- /dev/null +++ b/lib_enc/pvq_encode_fx.c @@ -0,0 +1,386 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include "options.h" /* Compilation switches */ +#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 */ +#include "rom_com_fx.h" +#include "rom_com.h" + +/* PVQ MIXED_SEARCH_LOOP: + low precision 16/32 + energy selective high precision 32/64, + mixed perf , 10 dB SEGSNR better than the low precision loop only, + active if k>=128 and accumulated energy is high enough, + comes at a controlled complexity cost, as dimensions decrease for high k's*/ + +static Word16 max_val_fx( /* o : maximum value in the input vector */ + const Word16 *vec, /* i : input vector */ + const Word16 lvec /* i : length of input vector */ +) +{ + Word16 j,tmp; + + tmp = vec[0]; + move16(); + FOR ( j=1 ; j 0 ); +} + + +/* The inner search loop for one single additional unit pulse, starting from pulse_tot , + with information about required energy precision/down scaling for the dim loop in en_dn_shift, + and the current max_xabs absolute value to be used for an near optimal correlation upscaling. + returns the index of the best positioned unit pulse in imax +*/ +static Word16 one_pulse_search( + const Word16 dim, /* vector dimension */ + const Word16* x_abs, /* absolute vector values */ + Word16* y, /* output vector */ + Word16 *pulse_tot_ptr, + Word32* L_xy_ptr, /* accumulated correlation */ + Word32* L_yy_ptr, /* accumulated energy */ + Word16 high_prec_active, + Word16 en_dn_shift, + Word16 max_xabs) /* current accumulated max amplitude for pulses */ +{ + Word16 i, corr_up_shift, corr_tmp, imax, corr_sq_tmp, en_max_den, cmax_num, en_tmp; + Word32 L_tmp_en_lc, L_tmp_corr ; + Word32 L_tmp_en, L_en_max_den, L_corr_sq_max, L_tmp_corr_sq; + Word32 L_left_h, L_right_h; + UWord32 UL_left_l, UL_right_l, UL_dummy; + Word32 L_tmp; + UWord16 u_sgn; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + en_tmp = en_dn_shift; /* dummy assignment to avoid compiler warning for unused parameter */ + + /* maximize correlation precision, prior to every unit pulse addition in the vector */ + corr_up_shift = norm_l(L_mac(*L_xy_ptr, 1, max_xabs)); /* pre analyze worst case L_xy update in the dim loop , 2 ops */ + imax = -1; /* not needed for search, only added to avoid compiler warning */ + + /* clean BE code, with split out low/high precision loops */ + /* activate low complexity en/corr search section conditionally if resulting vector energy is within limits */ + /* typical case for higher dimensions */ + + IF( high_prec_active == 0 ) + { + en_max_den = 0; /*move16()*/; /* OPT: move saved by using high_prec_active as en_max_den */ /* 1 op */ + cmax_num = -1; + move16(); /* req. to force a 1st update for n==0 */ /* 1 op */ + + FOR(i = 0; i < dim; i++) /* FOR 3 ops */ + { +#ifdef BASOP_NOGLOB + L_tmp_corr = L_shl_o(L_mac_o(*L_xy_ptr,1,x_abs[i], &Overflow), corr_up_shift, &Overflow); /* actual in-loop target value, 2 ops */ + corr_tmp = round_fx_o(L_tmp_corr, &Overflow); /* 1 op */ +#else + L_tmp_corr = L_shl(L_mac(*L_xy_ptr,1,x_abs[i]), corr_up_shift ); /* actual in-loop target value, 2 ops */ + corr_tmp = round_fx(L_tmp_corr); /* 1 op */ +#endif + corr_sq_tmp = mult(corr_tmp, corr_tmp); /* CorrSq, is a 16bit for low compelxity cross multiplication 1 op */ + + L_tmp_en_lc = L_mac(*L_yy_ptr, 1,y[i] ); /*Q1 result , energy may span up to ~14+1(Q1)+1(sign)=16 bits, 1 op */ + /* extract_l without shift can always be used for this section as energy is guaranteed to stay in the lower word, 1 op */ + en_tmp = extract_l(L_tmp_en_lc); /* L_shl + round_fx could also be used also but then adds an uphift cost (2-3 ops)*/ + + /* 16/32 bit comparison WC (4 +1+1 + (1+1+1) = 9 */ + IF( L_msu(L_mult(corr_sq_tmp, en_max_den),cmax_num , en_tmp) > 0) /* use L_mult and then a L_msu, 2 ops */ + { + cmax_num = corr_sq_tmp; + move16(); /* 1 op */ + en_max_den = en_tmp; + move16(); /* 1 op */ + imax = i; + move16(); /* 1 op */ + } + } /* dim */ + + } + ELSE + { + /* High resolution section activated when vector energy is becoming high (peaky or many pulses) */ + /* BASOP operator Mpy32_32_ss used to allow higher resolution for both the CorrSq term and the Energy term */ + + L_en_max_den = L_deposit_l(0); /* 1 op */ + L_corr_sq_max = L_deposit_l(-1); /* req. to force a 1st update */ /* 1 op */ + + FOR(i = 0; i < dim; i++) /* FOR 3 ops */ + { + L_tmp_corr = L_shl(L_mac(*L_xy_ptr,1,x_abs[i]), corr_up_shift ); /* actual in loop WC value 2 ops */ + Mpy_32_32_ss(L_tmp_corr,L_tmp_corr, &L_tmp_corr_sq, &UL_dummy); /* CorrSq 32 bits, 4 ops */ + + L_tmp_en = L_mac(*L_yy_ptr, 1, y[i]); /* Q1,energy may span up to sign+19 bits , 1 op */ + /* For highest accuracy use pairs of maximum upshifted 32x32 bit signed values */ + /* (L_tmp_corr_sq / L_tmp_en) > (L_corr_sq_max/L_en_max_den) */ + /* (L_tmp_corr_sq * L_en_max_den) > (L_corr_sq_max * L_tmp_en) */ + Mpy_32_32_ss( L_en_max_den, L_tmp_corr_sq, &L_left_h, &UL_left_l); /* 4 ops */ + Mpy_32_32_ss( L_tmp_en, L_corr_sq_max, &L_right_h, &UL_right_l); /* 4 ops */ + + /* STL optimized "Lazy evaluation" of: + IF( (L_left_h > L_right_h) || ( (L_left_h == L_right_h) && (UL_left_l > UL_right_l) ) + */ + /* 32/64 bit Lazy eval comparison WC cost is (1+ 1+1+1 + 4 +(2+2+1) = 13 , and average is ~12 */ + /* Unoptimized 32/64 bit comparison WC cost is (1+1+ 2x2 + 4 +(2+2+1) = 15 */ + L_tmp = L_sub(L_left_h, L_right_h); /* high signed word check 1 op */ + u_sgn = 0; + move16(); /* 1 op */ + if(L_tmp == 0) /* L_tmp high Word testing is always needed */ + { + /* The returned UL value from UL_subNs is not needed, only u_sgn is needed */ + UL_subNs(UL_right_l, UL_left_l, &u_sgn); /* low unsigned word check, note left/right order switch of ">" due to ">=" inside UL_subNs, 1 op */ + } + if( u_sgn != 0) + { + L_tmp = L_add(L_tmp, 1); /* 0+1 --> 1 use wrap/sign result of low Word u_sgn check */ /* 1 op */ + } + IF( L_tmp > 0 ) /* IF 4 ops */ + { + L_corr_sq_max = L_add(L_tmp_corr_sq, 0); /* 1-2 ops */ + L_en_max_den = L_add(L_tmp_en, 0); /* 1-2 ops */ + imax = i; + move16(); /* 1 op */ + } + } /* dim loop */ + + } + /* Complexity comparison per coeff for low precision vs. high precision + low precision: pulse_tot <= 127, 16 bit: WC 2+3 +(15)*dim ops, dim=5 --> 5+15*5 = 90 ops, 18 ops/coeff + high precision: pulse_tot > 127, 32 bit: WC 1+3+3 +(26-28)*dim ops, WC-band dim=5 --> 7+28*5 = 147 ops, 29 ops/coeff ~61% increase + */ + + /* finally add found unit pulse contribution to past L_xy, Lyy, for next pulse loop */ + *L_xy_ptr = L_mac(*L_xy_ptr, x_abs[imax], 1); /* Q12+1 */ + *L_yy_ptr = L_mac(*L_yy_ptr, 1, y[imax]); + + y[imax] = add(y[imax],1); + move16(); /* Q0 added pulse */ + (*pulse_tot_ptr) = add((*pulse_tot_ptr) ,1); /* increment total pulse sum */ + + return imax; +} +/*-----------------------------------------------------------------------* + * Function pvq_encode_fx() * + * * + *-----------------------------------------------------------------------*/ +void pvq_encode_fx( + BSTR_ENC_HANDLE hBstr, + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + const Word16 *x, /* i: vector to quantize Q15-3=>Q12 */ + Word16 *y, /* o: raw pulses (non-scaled short) Q0 */ + Word16 *xq, /* o: quantized vector Q15 */ + Word32 *L_xq, /* o: quantized vector Q31 fot eval */ + const Word16 pulses, /* i: number of allocated pulses */ + const Word16 dim, /* i: Length of vector */ + const Word16 neg_gain /* i: - Gain use - negative gain in Q15 0..1 */ +) +{ + Word16 i; + Word16 pulse_tot; + Word16 xabs[PVQ_MAX_BAND_SIZE]; + Word16 max_xabs; + Word32 L_xsum; + Word32 L_proj_fac; + Word32 L_yy, L_xy; + Word16 max_amp_y, imax; + Word16 k, en_margin, en_dn_shift, high_prec_active ; + + Word32 L_num, L_tmp; + Word16 proj_fac, tmp, shift_den,shift_num,shift_delta, num,den; + + UWord16 u16_tmp; + Word16 dim_m1; + Word32 L_isqrt; + Word16 neg_gain_norm, shift_tot; + Word16 high_pulse_density_flag; + PvqEntry entry; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + L_proj_fac = 4096; + L_xsum = L_deposit_h(0); + max_xabs = -1; + move16(); + + FOR( i = 0; i < dim; i++) + { + xabs[i] = abs_s(x[i]); + move16(); /* Q12 */ + max_xabs = s_max(max_xabs, xabs[i] ); /* for efficient search correlation scaling */ + L_xsum = L_mac0(L_xsum, 1, xabs[i] ); /* stay in Q12 */ + y[i] = 0; + move16(); /* init, later only non-zero values need to be normalized */ + } + + test(); + IF( L_xsum == 0 || neg_gain == 0 ) + { + pulse_tot = pulses; + move16(); + dim_m1 = sub(dim,1); + y[dim_m1] = 0; + move16(); + y[0] = shr(pulses,1); + move16(); + y[dim_m1] = add(y[dim_m1], sub(pulses, y[0])); + move16(); + L_yy = L_mult(y[0],y[0]); /* L_yy needed for normalization */ + if(dim_m1 != 0) + { + L_yy = L_mac(L_yy, y[dim_m1],y[dim_m1]); /* (single basop) */ + } + } + ELSE + { + + num = sub(pulses, PYR_OFFSET); + high_pulse_density_flag = pyramidSearchProjInit_fx(dim, pulses ); + + test(); + IF( (num > 0) && (high_pulse_density_flag != 0) ) + { + shift_den = norm_l(L_xsum); /* x_sum input Q12 */ + den = extract_h(L_shl(L_xsum, shift_den)); /* now in Q12+shift_den */ + + L_num = L_deposit_l(num); + shift_num = sub(norm_l(L_num) ,1); + L_num = L_shl(L_num, shift_num) ; /* now in Q0 +shift_num -1 */ + proj_fac = div_l(L_num, den ); /* L_num always has to be less than den<<16 */ + + shift_delta=sub(shift_num,shift_den); + L_proj_fac = L_shl(L_deposit_l(proj_fac), sub(9, shift_delta)); /* bring to a fixed Q12 */ + } + + pulse_tot = 0; + move16(); + L_yy = L_deposit_l(0); + L_xy = L_deposit_l(0); + test(); + IF( (num > 0 ) && (high_pulse_density_flag != 0 ) ) + { + FOR( i = 0; i < dim ; i++) /* max 64 */ + { + Mpy_32_16_ss(L_proj_fac,xabs[i],&L_tmp,&u16_tmp); /*Q12 *Q12 +1 */ + y[i] = extract_l(L_shr( L_tmp, 12+12-16+1 )); + move16();/* Q12 *Q12 -> Q0 */ + + pulse_tot = add(pulse_tot, y[i]); /* Q0 */ + L_yy = L_mac(L_yy, y[i], y[i]); /* Energy, result will scale up by 2 by L_mac */ + L_xy = L_mac(L_xy, xabs[i], y[i]); /* Corr, Q0*Q12 +1 --> Q13 */ + } + } + + + L_yy=L_shr(L_yy,1); + IF (LE_16(pulses,127)) + { + /* LC inner loop, enters here always for dimensions 6 and higher, and also sometimes for dimensions 1 .. 5 */ + /* ( if high energy precision is inactive, max_amp_y is not needed , no max_amp_y(k-1) update ) */ + FOR (k=pulse_tot; k +#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 */ + +static Word16 gain_enc( /* o : quantization pitch index */ + const Word16 *code, /* i : algebraic excitation */ + Word16 lcode, /* i : Subframe size in range: 40,64,80 */ + Word16 *gain_pit, /* o : quantized pitch gain */ + /* i/o : only func=1,coder_type=1 quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + ACELP_CbkCorr *g_coeff, /* i : correlations , -2,, -2 and 2 */ + Word16 mean_ener, /* i : only func=0: mean_ener defined in open-loop (3 bits) */ + const Word16 clip_gain, /* i : only func=0,1: gain pitch clipping flag (1 = clipping) */ + Word32 *past_gcode, /* o : past gain of code */ + Word16 *gain_inov, /* o : Q12 innovation gain */ + const Word16 coder_type, /* i : only func=0,1: coder type */ + const Word16 func_type /* i : algorithm: 0=gain_enc_mless, 1=gain_enc_2 */ +); + +/*-------------------------------------------------------------------------* + * procedure q_gain2_plus * + * ~~~~~~~~~~~~~~~~~~~~~~ * + * Quantization of pitch and codebook gains. * + * The following routines is Q_gains updated for AMR_WB_PLUS. * + * MA prediction is removed and MEAN_ENER is now quantized with 2 bits and * + * transmitted once every ACELP frame to the gains decoder. * + * The pitch gain and the code gain are vector quantized and the * + * mean-squared weighted error criterion is used in the quantizer search. * + *-------------------------------------------------------------------------*/ +void encode_acelp_gains_fx( + Word16 *code, + Word16 gains_mode, + Word16 mean_ener_code, + Word16 clip_gain, + ACELP_CbkCorr *g_corr, + Word16 *gain_pit, + Word32 *gain_code, + Word16 **pt_indice, + Word32 *past_gcode, + Word16 *gain_inov, + Word16 L_subfr, + Word16 *code2, + Word32 *gain_code2, + Word8 noisy_speech_flag /* i : noisy speech flag */ +) +{ + Word16 index = 0, func_type = 0; + + BASOP_SATURATE_ERROR_ON_EVS; + + SWITCH(gains_mode) + { + case 1: + case 2: + case 3: + /* Memory-less gain coding */ + gains_mode = sub(gains_mode, 1); + func_type = FUNC_GAIN_ENC_MLESS; + move16(); + BREAK; + case 4: + case 5: + assert(0); + BREAK; + case 6: + /* UV gains quantizer (6 bits/subfr) */ + gains_mode = sub(gains_mode, 6); + func_type = FUNC_GAIN_ENC_UV; + move16(); + BREAK; + case 7: + gains_mode = sub(gains_mode, 7); + func_type = FUNC_GAIN_ENC_GACELP_UV; + move16(); + BREAK; + default: + IVAS_ERROR(IVAS_ERR_INTERNAL, "invalid gains coding for acelp!"); + func_type = 0; + move16(); /*To avoid compiler warning*/ + BREAK; + } + + IF( func_type == FUNC_GAIN_ENC_MLESS ) + { + index = gain_enc(code, L_subfr, gain_pit, gain_code, g_corr, mean_ener_code, + clip_gain, past_gcode, gain_inov, gains_mode, func_type); + } + ELSE + { + index = gain_enc_uv_fx(code, code2, L_subfr, gain_pit, gain_code, gain_code2, + noisy_speech_flag, g_corr, mean_ener_code, past_gcode, gain_inov, func_type); + } + + move16(); + **pt_indice = index; + (*pt_indice)++; + + BASOP_SATURATE_ERROR_OFF_EVS; +} + +/*---------------------------------------------------------------------* + * procedure gain_enc_mless + * Quantization of pitch and codebook gains. + * - an initial predicted gain, gcode0, is first determined based on + * the predicted scaled innovation energy + * - the correction factor gamma = g_code / gcode0 is then vector quantized + * along with gain_pit + * - the mean-squared weighted error criterion is used for the quantizer search + *---------------------------------------------------------------------*/ + +static Word16 gain_enc( /* o : quantization pitch index */ + const Word16 *code, /* i : algebraic excitation */ + Word16 lcode, /* i : Subframe size in range: 40,64,80 */ + Word16 *gain_pit, /* o : quantized pitch gain */ + /* i/o : only func=1,coder_type=1 quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + ACELP_CbkCorr *g_coeff, /* i : correlations , -2,, -2 and 2 */ + Word16 mean_ener, /* i : only func=0: mean_ener defined in open-loop (3 bits) */ + const Word16 clip_gain, /* i : only func=0,1: gain pitch clipping flag (1 = clipping) */ + Word32 *past_gcode, /* o : past gain of code */ + Word16 *gain_inov, /* o : Q12 innovation gain */ + const Word16 coder_type, /* i : only func=0,1: coder type */ + const Word16 func_type /* i : algorithm: 0=gain_enc_mless, 1=gain_enc_2 */ +) +{ + Word16 i, j, index, size, min_index, exp_L_tmp1; + Word16 gcode0, gcode0_gi, exp_gcode0, exp_sum, exp_code, g_code_shl; + + Word16 g_code; + Word16 coeff0, coeff1, coeff2, coeff3, coeff4, exp_coeff0, exp_coeff1, exp_coeff2, exp_coeff3, exp_coeff4; + Word16 shr_coeff0, shr_coeff1, shr_coeff2, shr_coeff3, shr_coeff4; + const Word16 *p; + const Word16 *t_qua_gain; + Word32 L_tmp, dist_min, L_tmp1; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + + assert((func_type != FUNC_GAIN_ENC_UV) && (func_type != FUNC_GAIN_ENC_GACELP_UV)); + + /* Debug test value (not instrumented) */ + gcode0 = -3000; + move16(); + + /*----------------------------------------------------------------* + * - 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 = calc_gain_inov(code, lcode, &L_tmp1, &exp_L_tmp1); + move16(); +#ifdef BASOP_NOGLOB + *gain_inov = round_fx_o(L_shl_o(L_tmp, 15-3, &Overflow), &Overflow); /* gain_inov in Q12 */ +#else + *gain_inov = round_fx(L_shl(L_tmp, 15-3)); /* gain_inov in Q12 */ +#endif + /*----------------------------------------------------------------* + * calculate the predicted gain code + *----------------------------------------------------------------*/ + IF (func_type == FUNC_GAIN_ENC_MLESS) + { + /*j = 10 * log10((dot_product(code, code, lcode) + 0.01) / lcode) */ + j = BASOP_Util_lin2dB(L_tmp1, exp_L_tmp1, 1); /* Q8 */ + + /* predicted codebook gain */ + gcode0 = sub(mean_ener, j); /* Q8 */ + + } + + /*----------------------------------------------------------------* + * Compute coefficients needed for the quantization. + * + * coeff[0] = yy1 yy1 + * coeff[1] = -2 xn yy1 + * coeff[2] = y2 y2 + * coeff[3] = -2 xn y2 + * coeff[4] = 2 yy1 y2 + * + * Product and have been computed in Adpt_enr() and + * are in vector g_coeff[]. + *----------------------------------------------------------------*/ + + coeff0 = g_coeff->y1y1; + move16(); + exp_coeff0 = g_coeff->y1y1_e; + move16(); + coeff2 = g_coeff->y2y2; + move16(); + exp_coeff2 = g_coeff->y2y2_e; + move16(); + + coeff1 = g_coeff->xy1; + move16(); + exp_coeff1 = add(g_coeff->xy1_e, 1); + coeff3 = g_coeff->xy2; + move16(); + exp_coeff3 = add(g_coeff->xy2_e, 1); + coeff4 = g_coeff->y1y2; + move16(); + exp_coeff4 = add(g_coeff->y1y2_e, 1); + + /*---------------------------------------------------------------* + * Decode codebook gain and the adaptive excitation low-pass + * filtering factor (Finalize computation ) + *---------------------------------------------------------------*/ + + + /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */ + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) gcode in Q8 + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + + /* Check if gcode0 was uninitialized. */ + assert(gcode0 != -3000); + + L_tmp = L_mult(gcode0, 5443/*0.166096f Q15*/); + exp_gcode0 = add(1,extract_l(L_shr(L_tmp, 24))); + L_tmp = L_lshl(L_tmp, 7); + L_tmp = L_and(0x7FFFFFFF, L_tmp); + + L_tmp = Pow2(30,round_fx(L_tmp)); + gcode0 = round_fx(L_tmp); + /* exponent of gcode0 = exp_gcode0 */ + + /*-----------------------------------------------------------------* + * gain quantization initializations + * - find the initial quantization pitch index + * - set the gains searching range + *----------------------------------------------------------------*/ + + /*----------------------------------------------------------------* + * 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 Q11 and + * are multiplied by gcode0 which have been multiplied 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 + 4 + * if (func_type == gain_enc_2) + * gcode0 *= gain_inov (in Q12) => exp_code += 3 + * + * g_pitch*g_pitch = +1+1 + * g_pitch = +1 + * g_code*g_code = (2*exp_code) + * g_code = exp_code + * g_pitch*g_code = + 1 + exp_code + * + * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] + 2 + * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] + 1 + * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] + (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, 4); + + exp_coeff0 = add(exp_coeff0, 2); + exp_coeff1 = add(exp_coeff1, 1); + exp_coeff2 = add(exp_coeff2, shl(exp_code, 1)); + exp_coeff3 = add(exp_coeff3, exp_code); + exp_coeff4 = add(exp_coeff4, add(1, exp_code)); + + /* Find maximum exponent */ + exp_sum = s_max(exp_coeff1, exp_coeff0); + exp_sum = s_max(exp_coeff2, exp_sum); + exp_sum = s_max(exp_coeff3, exp_sum); + exp_sum = s_max(exp_coeff4, exp_sum); + exp_sum = add(exp_sum,2); + + /* Align exponents of summands in loop far below. */ + shr_coeff0 = sub(exp_sum, exp_coeff0); + shr_coeff1 = sub(exp_sum, exp_coeff1); + shr_coeff2 = sub(exp_sum, exp_coeff2); + shr_coeff3 = sub(exp_sum, exp_coeff3); + shr_coeff4 = sub(exp_sum, exp_coeff4); + /* Codebook search */ + + dist_min = L_deposit_h(MAX_16); + + min_index = 0; + move16(); + + { + Word16 size_clip; + + + IF( coder_type == 0) + { + + t_qua_gain = E_ROM_qua_gain5b_const; + size_clip=9; + size=NB_QUA_GAIN5B; + } + ELSE IF(coder_type == 1) + { + + t_qua_gain = E_ROM_qua_gain6b_const; + size_clip=6; + size = NB_QUA_GAIN6B; /* searching range of the gain quantizer */ + } + ELSE + { + + t_qua_gain = E_ROM_qua_gain7b_const; + size_clip=21; + size = NB_QUA_GAIN7B; + } + + if ( EQ_16(clip_gain,1)) + { + size = sub(size, size_clip); /* limit pitch gain to 1.0 */ + } + gcode0_gi = gcode0; + move16(); + + } + move16(); + p = t_qua_gain; + + index = 0; + move16(); + + /* divide all coeff1,2,3,4 by coeff0 */ + /* in order to skip multiplication with coeff0 in loop */ + assert(coeff0 >= 0x4000); + coeff0 = div_s(0x4000,coeff0); + coeff1 = mult_r(coeff1,coeff0); + coeff2 = mult_r(coeff2,coeff0); + coeff3 = mult_r(coeff3,coeff0); + coeff4 = mult_r(coeff4,coeff0); + + FOR (i = 0; i < size; i++) + { + /* + Note: gcode0_gi: either gcode0 or gcode0*gain_inov + g_pitch = *p++; + g_code = gcode0_gi * *p++; + + dist = g_pitch*g_pitch * coeff.y1y1 + + g_pitch * coeff.xy1 (negated) + + g_code*g_code * coeff.y2y2 + + g_code * coeff.xy2 (negated) + + g_pitch*g_code * coeff.y1y2; + */ + + /* Since g_code has a significant dynamic, we prefer to normalize this 16-bit value */ + g_code_shl = norm_s(p[2*i+1]); + g_code = shl(p[2*i+1],g_code_shl); + g_code = mult_r(g_code, gcode0_gi); + BASOP_SATURATE_WARNING_OFF_EVS /* needed to skip overflow warnings due to exceeding shift values */ + L_tmp = L_shr(Mpy_32_16_1(L_mult(g_code, g_code),coeff2),shr_coeff2); + if (g_code_shl != 0) + L_tmp = L_shr(L_tmp,g_code_shl); + L_tmp = L_sub(L_tmp,L_shr(L_mult(g_code, coeff3),shr_coeff3)); + L_tmp = L_add(L_tmp,L_shr(Mpy_32_16_1(L_mult(g_code, p[2*i+0]), coeff4),shr_coeff4)); + if (g_code_shl != 0) + L_tmp = L_shr(L_tmp,g_code_shl); + /* Here, we use L_mult0 to compensate the factor 0.5 applied to coeff[1..4] before */ + L_tmp = L_add(L_tmp,L_shr(L_mult0(p[2*i+0],p[2*i+0]), shr_coeff0)); + L_tmp = L_sub(L_tmp,L_shr(L_mult(p[2*i+0], coeff1),shr_coeff1)); +#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_SATURATE_WARNING_ON_EVS + if (L_tmp1 < 0) + { + index = i; + move16(); + } + if (L_tmp1 < 0) + { + dist_min = L_min(L_tmp, dist_min); + } + } + index = add(index, min_index); + *gain_pit = t_qua_gain[2*index+0]; + move16(); + g_code = t_qua_gain[2*index+1]; + move16(); + + L_tmp = L_mult(g_code, gcode0); /* Q11*Q15 -> Q27 */ + exp_gcode0 = add(exp_gcode0,-11); +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o(L_tmp, exp_gcode0, &Overflow); /* Q27 -> Q16 */ +#else + L_tmp = L_shl(L_tmp, exp_gcode0); /* Q27 -> Q16 */ +#endif + + *gain_code = L_tmp; + move32(); + /* Q16/Q12 => Q5 */ + L_tmp = L_deposit_h(BASOP_Util_Divide3216_Scale(L_tmp,*gain_inov,&i)); +#ifdef BASOP_NOGLOB + *past_gcode = L_shl_o(L_tmp,sub(i,15-12), &Overflow); +#else + *past_gcode = L_shl(L_tmp,sub(i,15-12)); +#endif + + return index; +} + +Word16 gain_enc_uv_fx( /* o : quantization pitch index */ + const Word16 *code, /* i : algebraic excitation */ + const Word16 *code2, /* i : gaussian excitation */ + Word16 lcode, /* i : Subframe size in range: 40,64,80 */ + Word16 *gain_pit, /* o : quantized pitch gain */ + Word32 *gain_code, /* o : quantized codebook gain */ + Word32 *gain_code2, /* o : quantized codebook gain */ + Word8 noisy_speech_flag, /* i : noisy speech flag */ + ACELP_CbkCorr *g_coeff, /* i : correlations , -2,, -2 and 2 */ + Word16 mean_ener, /* i : only func=0: mean_ener defined in open-loop (3 bits) */ + Word32 *past_gcode, /* o : past gain of code */ + Word16 *gain_inov, /* o : Q12 innovation gain */ + const Word16 func_type /* i : algorithm: 2=gain_enc_uv_fx, 3=gain_enc_gacelp_uv */ +) +{ + Word16 i, index, exp_L_tmp1, tmp; + Word16 exp_gcode; + Word16 g_code; + Word32 L_tmp, L_tmp1; + Word8 gacelp_uv; + Word32 pred_nrg_frame; + Word16 exp_gcode2, g_code2, norm_code2; + Word16 c, c_e, c_index2, c_index2_e, c_first, c_first_e; + Word16 s, tmp1, s1; + Word16 index2; + const Word16 log2_scale=16; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + pred_nrg_frame = 0; /* to suppress compilation warnings */ + g_code2 = 0; /* to suppress compilation warnings */ + exp_gcode2 = 0; /* to suppress compilation warnings */ + + + assert((func_type != FUNC_GAIN_ENC_MLESS) ); + + /* Debug check value (not instrumented) */ + index2 = -3000; + move16(); + + gacelp_uv = 0; + move16(); + if (EQ_16(func_type, FUNC_GAIN_ENC_GACELP_UV)) + { + gacelp_uv = 1; + move16(); + } + + /*----------------------------------------------------------------* + * - 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 = calc_gain_inov(code, lcode, NULL, NULL); + *gain_inov = round_fx(L_shl(L_tmp, 15-3)); /* gain_inov in Q12 */ + + /*----------------------------------------------------------------* + * calculate the predicted gain code + *----------------------------------------------------------------*/ + IF (gacelp_uv != 0) + { + /* pred_nrg_frame = (float)pow(10.0,mean_ener/20.0); */ + L_tmp = L_mult(mean_ener, 10885/*0.166096f * 2 Q15*/); /* 6Q25 */ + pred_nrg_frame = BASOP_Util_InvLog2(L_sub(L_tmp, 503316480l/*15.f Q25*/)); /* 15Q16 */ + + /* gcode = pred_nrg_frame * (*gain_inov); */ + L_tmp = Mpy_32_16_1(pred_nrg_frame, *gain_inov); /* 18Q13 */ + i = norm_l(L_tmp); + g_code = round_fx(L_shl(L_tmp, i)); + exp_gcode = sub(18, i); + + /* norm_code2 = 1.0f / sqrt((dot_product(code2, code2, lcode) + 0.01f) / lcode); */ + L_tmp = calc_gain_inov(code2, lcode, NULL, NULL); + norm_code2 = round_fx(L_shl(L_tmp, 15-3)); /* Q12 */ + + /* g_code2 = pred_nrg_frame * norm_code2; */ + L_tmp = Mpy_32_16_1(pred_nrg_frame, norm_code2); /* 18Q13 */ + i = norm_l(L_tmp); + g_code2 = round_fx(L_shl(L_tmp, i)); + exp_gcode2 = sub(18, i); + } + ELSE + { + g_code = *gain_inov; + move16(); + exp_gcode = 3; + move16(); + } + + tmp = BASOP_Util_Divide1616_Scale(g_coeff->xy2, mult_r(g_coeff->y2y2, g_code), &i); /*Correlation based*/ + L_tmp = L_shl( L_deposit_h(tmp), add(i, sub(g_coeff->xy2_e, add(g_coeff->y2y2_e, add(exp_gcode, log2_scale)))) ); + /* exponent of L_tmp is 16, accounted below by adding log2(2^16) */ + + index = 0; + move16(); + + IF (L_tmp > 0) + { + /*index = (int)(((20.f*log10(g_code)+30.f)/1.9f)+0.5f))); */ + /* Since ((20*log10(x)+30)/1.9)+0.5 = 63 (max index) implies x is between 2^15 and 2^16, + L_tmp might saturate at 65535 and above. That is why log2_scale is 16. */ + tmp = BASOP_Util_lin2dB(L_tmp, 16, 0); /* Q8 */ + + IF (gacelp_uv != 0) + { + L_tmp = L_mult(add(tmp, 5120/*20.0f Q8*/), 26214/*1.0f/1.25f Q15*/); + } + ELSE + { + L_tmp = L_mult(add(tmp, 7680/*30.0f Q8*/), 17246/*1.0f/1.9f Q15*/); + } + + index = round_fx(L_shr(L_tmp, 8)); + index = s_max(0, s_min(63, index)); + if (gacelp_uv != 0) index = s_min(31, index); + } + + /* *gain_code= (float) pow(10.f,(((index*1.9f)-30.f)/20.f)); */ + + /*----------------------------------------------------------------* + * gcode0 = pow(10.0, gcode0/20) + * = pow(2, 3.321928*gcode0/20) + * = pow(2, 0.166096*gcode0) + *----------------------------------------------------------------*/ + IF (gacelp_uv != 0) + { + L_tmp = L_mac(-111465139l/*-0.166096*20.0f Q25*/,shl(index, 16-7), 6803/*0.166096f*1.25f Q15*/); + } + ELSE + { + L_tmp = L_mac(-167197708l/*-0.166096*30.0f Q25*/,shl(index, 16-7), 10341/*0.166096f*1.9f Q15*/); + } + i = add(1,extract_l(L_shr(L_tmp, 25))); + L_tmp = L_lshl(L_tmp, 6); + L_tmp = L_and(0x7FFFFFFF, L_tmp); + + L_tmp = Pow2(30,round_fx(L_tmp)); + L_tmp = L_shl(L_tmp, i-(31-16)); /* Q16 */ + + IF (gacelp_uv != 0) + { + /* *past_gcode = L_tmp * pred_nrg_frame; */ + i = norm_l(L_tmp); + L_tmp1 = L_shl(L_tmp, i); + exp_L_tmp1 = sub(15, i); + + i = norm_l(pred_nrg_frame); + L_tmp1 = Mpy_32_32(L_tmp1, L_shl(pred_nrg_frame, i)); + exp_L_tmp1 = add(exp_L_tmp1, sub(15, i)); + + *past_gcode = L_shl(L_tmp1, sub(exp_L_tmp1, 15)); /* Q16 */ move32(); + } + ELSE + { + *past_gcode = L_tmp; /*unscaled gain*/ move32(); + } + + + *gain_code = L_shl(Mpy_32_16_1(*past_gcode, *gain_inov), 3); + move32(); + + *gain_pit = 0; + move16(); + + IF (gacelp_uv != 0) + { + /* c_first = 0.8f*g_coeff->xx - (*gain_code) * (*gain_code) * g_coeff->y2y2; */ + /* c_first = g_coeff->xx - (*gain_code) * (*gain_code) * g_coeff->y2y2; */ + tmp = g_coeff->xx; + move16(); + if (noisy_speech_flag != 0) + { + tmp = mult_r(26214/*0.8f Q15*/, tmp); + } + + s1 = norm_l(*gain_code); +#ifdef BASOP_NOGLOB + tmp1 = round_fx_o(L_shl_o(*gain_code, s1, &Overflow), &Overflow); +#else + tmp1 = round_fx(L_shl(*gain_code, s1)); +#endif + s1 = sub(15, s1); + tmp1 = mult_r(mult_r(tmp1, tmp1), g_coeff->y2y2); + + c_first_e = BASOP_Util_Add_MantExp(tmp, g_coeff->xx_e, + negate(tmp1), add(g_coeff->y2y2_e, shl(s1, 1)), + &c_first); + + L_tmp = Mpy_32_16_1(*gain_code, BASOP_Util_Divide1616_Scale(g_code2, g_code, &s)); + L_tmp = L_shl(L_tmp, sub(sub(add(s, exp_gcode2), exp_gcode), 2)); /* Q16 */ + L_tmp1 = L_add(L_tmp, 0); + + s1 = norm_l(*gain_code); +#ifdef BASOP_NOGLOB + tmp1 = round_fx_o(L_shl_o(*gain_code, s1, &Overflow), &Overflow); +#else + tmp1 = round_fx(L_shl(*gain_code, s1)); +#endif + s1 = sub(15, s1); + + c_index2 = 0x7FFF; + move16(); + c_index2_e = 127; + move16(); + FOR (i = 0; i < 4; i++) + { + /* c = c_first - L_tmp1 * (L_tmp1 * g_coeff->y1y1 + 2 * (*gain_code) * g_coeff->y1y2); */ + s = norm_l(L_tmp1); + tmp = round_fx(L_shl(L_tmp1, s)); + s = sub(15, s); + + c_e = BASOP_Util_Add_MantExp(mult_r(tmp, g_coeff->y1y1), add(s, g_coeff->y1y1_e), + mult_r(tmp1, g_coeff->y1y2), add(add(s1, g_coeff->y1y2_e), 1), + &c); + c = mult_r(c, tmp); + c_e = add(c_e, s); + c_e = BASOP_Util_Add_MantExp(c_first, c_first_e, negate(c), c_e, &c); + + tmp = 0; + move16(); + if (LT_16(c_e, c_index2_e)) + { + tmp = 1; + move16(); + } + test(); + if (EQ_16(c_e, c_index2_e)&<_16(abs_s(c),abs_s(c_index2))) + { + tmp = 1; + move16(); + } + + IF (tmp != 0) + { + index2 = i; + move16(); + c_index2 = c; + move16(); + c_index2_e = c_e; + move16(); + *gain_code2 = L_tmp1; + move32(); + } + + L_tmp1 = L_add(L_tmp1, L_tmp); + } + + /* check if value was uninitialized */ + assert(index2 != -3000); + index = add(index, shl(index2, 5)); + } + + + return index; +} + diff --git a/lib_enc/qlpc_avq_fx.c b/lib_enc/qlpc_avq_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..1f550708639f5228601605e1ebe43d9965e2af79 --- /dev/null +++ b/lib_enc/qlpc_avq_fx.c @@ -0,0 +1,396 @@ +/*==================================================================================== + 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 "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + + +/*-------------------------------------------------------------------* + * qlpc_avq_fx() + * + * + * --------------------------------------------------------------------*/ + void qlpc_avq_fx( + const Word16 *lsf, /* i : Input LSF vectors (14Q1*1.28) */ + const Word16 *lsfmid, /* i : Input LSF vectors (14Q1*1.28) */ + Word16 *lsf_q, /* o : Quantized LFS vectors (14Q1*1.28) */ + Word16 *lsfmid_q, /* o : Quantized LFS vectors (14Q1*1.28) */ + Word16 *index, /* o : Quantization indices */ + Word16 *nb_indices, /* o : Number of quantization indices */ + Word16 *nbbits, /* o : Number of quantization bits */ + const Word16 core, /* i : TCX10 or TCX20 */ + const Word32 sr_core /* i : internal sampling rate */ +) +{ + Word16 i; + Word16 lsfmid_q0[M]; + Word16 *tmp_index, indxt[256], nit, nbits, nbt; + Word16 dummy[M]; + + + /* Init */ + tmp_index = &index[0]; + *nb_indices = 0; + move16(); + + tmp_index[0] = vlpc_1st_cod_fx(lsf, lsf_q, dummy, 0); + + nbt = vlpc_2st_cod_fx(lsf, lsf_q, &tmp_index[1], 0, sr_core); + + /*nit = 1 + 2 + index[1] + index[2]; nit < NPRM_LPC_NEW(=50) */ + nit = add(add(3,index[1]),index[2]); + assert(nit < NPRM_LPC_NEW); + + /*tmp_index += nit;*/ + tmp_index = tmp_index + nit; + /**nb_indices += nit;*/ + *nb_indices = add(*nb_indices,nit); + move16(); + /*nbbits[0] = 8 + nbt;*/ + nbbits[0] = add(8,nbt); + move16(); + + *tmp_index = 0; + move16(); + + IF (EQ_16(core, TCX_20_CORE)) + { + + return; + } + + /* Quantize intermediate LPC (512 framing) */ + tmp_index++; + /**nb_indices +=1;*/ + *nb_indices = add(*nb_indices,1); + move16(); + + /* LPC2: Abs? */ + tmp_index[0] = vlpc_1st_cod_fx(lsfmid, lsfmid_q, dummy, 0); + + nbits = vlpc_2st_cod_fx(lsfmid, lsfmid_q, &tmp_index[1], 0, sr_core); + /*nbt = 8 + nbits;*/ + nbt = add(8,nbits); + /*nit = 1 + 2 + tmp_index[1] + tmp_index[2];*/ + nit = add(add(3,tmp_index[1]),tmp_index[2]); + + /* LPC2: RelR? */ + FOR (i=0; i 0; ind--) + { + push_next_indice_fx(hBstr, 1, 1); + nb_bits = add(nb_bits, 1); + } + + /* Stop bit */ + push_next_indice_fx(hBstr, 0, 1); + + return(nb_bits); +} +/*-------------------------------------------------------------------* + * unpack4bits() + * + * + *--------------------------------------------------------------------*/ +static Word16 unpack4bits(Word16 nbits, const Word16 *prm, BSTR_ENC_HANDLE hBstr) +{ + Word16 i; + + IF (nbits == 0) + { + push_next_indice_fx(hBstr, 0, 0); + i = 1; + move16(); + } + ELSE + { + move16(); + i=0; + + FOR ( ; nbits > 4; nbits -= 4) + { + push_next_indice_fx(hBstr, prm[i], 4); + i = add(i, 1); + } + push_next_indice_fx(hBstr, prm[i], nbits); + i = add(i, 1); + } + + return(i); +} +/*-------------------------------------------------------------------* + * encode_lpc_avq_fx() + * + * + *--------------------------------------------------------------------*/ + +Word16 encode_lpc_avq_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + const Word16 numlpc, /* i : Number of sets of lpc */ + const Word16* param_lpc, /* i : lpc parameters */ + const Word16 core, /* i : core */ + const Word16 element_mode /* i : element mode - decides between SNS and LPC coding */ +) +{ + Word16 k,j; + Word16 q_type, nb_ind; + Word16 i,qn1,qn2,nb,avqBits,st1; + Word16 nb_bits; + Word16 stereo_mode, bits_for_abs_quant; + + stereo_mode = 0; + move16(); + bits_for_abs_quant = LPC_ABS_QUANT_BITS; + move16(); + if (EQ_16(element_mode, IVAS_CPE_MDCT)) + { + bits_for_abs_quant = SNS_ABS_QUANT_BITS; + move16(); + } + + move16(); + move16(); + move16(); + st1=0; + j = 0; + nb_bits = 0; + + FOR (k=0; k 0) + { + unary_code(nb, hBstr); + } + nb_bits = add(nb_bits, nb); + + move16(); + nb = qn2; + + IF(GT_16(nb, 6)) + { + nb = sub(nb, 3); + } + ELSE IF(GT_16(nb, 4)) + { + nb = sub(nb, 4); + } + ELSE IF(nb == 0) + { + move16(); + nb = 3; + } + ELSE + { + move16(); + nb = 0; + } + + IF(nb > 0) + { + unary_code(nb, hBstr); + } + nb_bits = add(nb_bits, nb); + + avqBits = shl(qn1, 2); + unpack4bits(avqBits, ¶m_lpc[j], hBstr); + j = add(j, qn1); + nb_bits = add(nb_bits, avqBits); + + avqBits = shl(qn2, 2); + unpack4bits(avqBits, ¶m_lpc[j], hBstr); + j = add(j, qn2); + nb_bits = add(nb_bits, avqBits); + } + } + ELSE + { + j = add(j, nb_ind); + } + } + + return(nb_bits); +} + diff --git a/lib_enc/qlpc_stoch_fx.c b/lib_enc/qlpc_stoch_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..ea5bf12e767d4f068c8d44477b04d9ba1c79f7f7 --- /dev/null +++ b/lib_enc/qlpc_stoch_fx.c @@ -0,0 +1,454 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include "options.h" +#include "cnst.h" +#include "rom_enc.h" +#include "rom_com_fx.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 */ +#include "basop_util.h" +#include "rom_basop_util.h" + +/*-------------------------------------------------------------------* + * local constants + *--------------------------------------------------------------------*/ + +#define MIN_LOG_FX 0 +#define MIN_LOG_VAL_FX -15360 /* -60.0f in Q8 */ + +/*-------------------------------------------------------------------* + * lpc_quantization_fx() + * + * + *--------------------------------------------------------------------*/ +void lpc_quantization_fx( + Encoder_State_fx * st, + const Word16 lsp[], + const Word16 lspmid[], + Word16 lsp_q[], + Word16 lsf_q[], /* 14Q1*1.28 */ + Word16 lspmid_q[], + Word16 lspq_ind[], + Word16 clip_var[], + const Word16 coder_type, + const Word8 acelp_midLpc, + Word16 param_lpc[], + Word16 nbits_lpc[], + Word16 * bits_param_lpc, + Word16 *no_param_lpc, + const Word16 Q_ener +) +{ + Word16 nb_indices; + Word16 lsfmid_q[M]; /* 14Q1*1.28 */ + Word16 lsfmid_idx; + Word16 i, force_sf; + Word16 lsf[M], lsfmid[M]; + Word16 fec_lsf[M], stab; + + nb_indices = 0; + move16(); + + /****** High-rate LPC quantizer *******/ + + IF (st->lpcQuantization==0) + { + if (st->sr_core != 12800) + { + //PMT("from the comment in E_LPC_isp_isf_conversion, it seems built for 12.8kHz, current sampling rate is NOT 12800, is it ok?") + /*_DIFF_FLOAT_FIX_ E_LPC_lsp_lsf_conversion, does it work for 16kHz as well ?*/ + + } + E_LPC_lsp_lsf_conversion(lsp, lsf, M); + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf_fx(st->element_mode, lsf, clip_var, M ); + + IF ( (EQ_16(st->core_fx, TCX_10_CORE))) + { + E_LPC_lsp_lsf_conversion(lspmid, lsfmid, M); + } + + /* LPC quantizer */ + qlpc_avq_fx(lsf, lsfmid, lsf_q, lsfmid_q, param_lpc, &nb_indices, nbits_lpc, st->core_fx, st->sr_core); + + E_LPC_lsf_lsp_conversion(lsf_q, lsp_q, M); + + IF( EQ_16(st->core_fx, TCX_10_CORE)) + { + E_LPC_lsf_lsp_conversion( lsfmid_q, lspmid_q, M ); + } + + /* assert(nb_indices<=NPRM_LPC_NEW); */ + } + + /****** Low-rate LPC quantizer *******/ + + ELSE IF ( EQ_16(st->lpcQuantization, 1)) + { + assert(st->sr_core <= 32000); + + lsp2lsf_fx(lsp, lsf, M, extract_l(st->sr_core)); + + gp_clip_test_lsf_fx(st->element_mode, lsf, clip_var, M ); + + force_sf = 0; + move16(); + /*Force safety net when possible in case of transitions*/ + test(); + test(); + IF( st->tc_cnt_fx >= 1 || LE_32(st->last_core_brate_fx,SID_2k40) || (EQ_16(st->next_force_safety_net_fx,1))) + { + force_sf = 1; + move16(); + st->next_force_safety_net_fx = 0; + move16(); + } + + test(); + IF ( EQ_16(st->next_force_safety_net_fx,1) && EQ_16(st->Opt_RF_ON,1)) + { + force_sf = 1; + st->next_force_safety_net_fx = 0; + } + + test(); + IF ( EQ_32(st->sr_core, INT_FS_16k) && EQ_16(coder_type,UNVOICED)) + { + lsf_end_enc_fx( st, lsf, lsf_q, ENDLSF_NBITS, GENERIC, Q_ener, + force_sf, param_lpc, no_param_lpc, bits_param_lpc, GENERIC ); + + nb_indices = *no_param_lpc; + } + ELSE + { + lsf_end_enc_fx( st, lsf, lsf_q, ENDLSF_NBITS, coder_type, Q_ener, + force_sf, param_lpc, no_param_lpc, bits_param_lpc, coder_type ); + + nb_indices = *no_param_lpc; + } + + + FEC_lsf_estim_enc_fx( st, fec_lsf ); + + /* FEC - calculate LSF stability */ + stab = lsf_stab_fx( lsf_q, fec_lsf, 0, st->L_frame_fx); /*Q15*/ + + + test(); + test(); + test(); + IF ( LT_16(stab,add(STAB_FAC_LIMIT_FX, 6553/* =0.2 in Q15*/))&& + ( EQ_16(coder_type,VOICED) || EQ_16(coder_type,GENERIC) ) && EQ_16(st->Opt_RF_ON,1 )) + { + st->next_force_safety_net_fx = 1; + } + + lsf2lsp_fx(lsf_q, lsp_q, M, st->sr_core); + + *nbits_lpc = ENDLSF_NBITS; + move16(); + + } + ELSE + { + assert(0); + } + + IF (lspq_ind != NULL) + { + E_LPC_lsf_lsp_conversion( lsf_q, lspq_ind, M ); + } + + st->seed_acelp=0; + move16(); + FOR(i=nb_indices-1; i>=0; i--) + { + st->seed_acelp = extract_l(L_mac0(L_mac0(13849, shr(st->seed_acelp, 1), 31821), param_lpc[i], 31821)); + move16(); + } + + /* Mid-frame LPC quantization */ + + test(); + IF(st->lpcQuantization && acelp_midLpc) + { + + IF(st->rate_switching_reset==0) + { + lsp2lsf_fx(lspmid, lsfmid, M, extract_l(st->sr_core)); + + midlsf_enc_fx(st->lsf_old_fx, lsf_q, lsfmid, &lsfmid_idx, M, st->Bin_E_old_fx, Q_ener, st->narrowBand, st->sr_core, coder_type ); + param_lpc[nb_indices++] = lsfmid_idx; + move16(); + midlsf_dec (st->lsf_old_fx, lsf_q, lsfmid_idx, lsfmid_q, coder_type ,NULL,0,1 ); + + reorder_lsf_fx( lsfmid_q, LSF_GAP_MID_FX, M, st->sr_core ); + lsf2lsp_fx(lsfmid_q, lspmid_q, M, st->sr_core); + } + ELSE + { + param_lpc[nb_indices++] = 0; + move16(); + } + } + + + + return; +} + + + +/*-------------------------------------------------------------------* + * Unified_weighting() + * + * LSF weighting + *-------------------------------------------------------------------*/ + +void Unified_weighting_fx( + const Word32 Bin_Ener_128_fx[], /* i : FFT Bin energy 128 bins in two sets Q_ener */ + Word16 Q_ener, + const Word16 lsf_fx[], /* i : LSF vector x2.56 */ + Word16 w_fx[], /* o : LP weighting filter (numerator) Q8 */ + const Word16 narrowBand, /* i : flag for Narrowband */ + const Word16 unvoiced, /* i : flag for Unvoiced frame */ + const Word32 sr_core, /* i : sampling rate of core-coder */ + const Word16 order /* i : LP order */ +) +{ + Word16 i; + const Word16 (*ptr_lsf_fit_model)[M]; + Word16 last_bin; + /*float compen;*/ + + Word16 exp, frac; + Word16 w_fft_fx[M]/*, w_fx[M]*/; + Word16 norm_lsf_fx[M]; /* Q0 */ + Word16 tmp_fx, min_fx, tmp1_fx, tmp2_fx, s1, s2; + Word32 L_tmp; + Word16 nf_fx; + Word32 Bin_Ener_160_fx[160]; + const Word32 *Freq_w_Table_fx, *Bin_Ener_fx; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*Config. weighting*/ + IF ( narrowBand ) + { + ptr_lsf_fit_model = lsf_unified_fit_model_nb; + nf_fx = 16384; + move16(); /* x2.56 */ + + last_bin = 127; + move16(); + Bin_Ener_fx = Bin_Ener_128_fx; + } + ELSE IF( EQ_32(sr_core, INT_FS_12k8)) + { + ptr_lsf_fit_model = lsf_unified_fit_model_wb; + nf_fx = 16384; + move16(); /* x2.56 */ + + last_bin = 127; + move16(); + Bin_Ener_fx = Bin_Ener_128_fx; + } + ELSE + { + ptr_lsf_fit_model = lsf_unified_fit_model_wbhb; + nf_fx = 20480; + move16(); /* x2.56 */ + + /* Fill the missing part (128~159) of the bin energy */ + last_bin = 159; + move16(); + + Copy32(Bin_Ener_128_fx, Bin_Ener_160_fx, L_FFT/2); + + /* Find average bin energy (32 Energy) */ + L_tmp = L_deposit_l(0); + FOR ( i=95; i<127; i++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_add_o(L_tmp, Bin_Ener_160_fx[i], &Overflow); +#else + L_tmp = L_add(L_tmp, Bin_Ener_160_fx[i]); +#endif + } + + L_tmp = L_shr(L_tmp, 5); + FOR ( i=127; i<160; i++ ) + { + Bin_Ener_160_fx[i] = L_tmp; + move32(); + } + + Bin_Ener_fx = Bin_Ener_160_fx; + } + + /* 1) FFT weights*/ + Freq_w_Table_fx = Freq_Weight_Com_fx; + if ( unvoiced ) + { + Freq_w_Table_fx = Freq_Weight_UV_fx; + } + + /* Use Envelope */ + min_fx = MAX_16; + move16(); + FOR ( i=0; i 0) + { + tmp1_fx = sub(tmp1_fx, lsf_fx[i-1]); + } + + tmp2_fx = nf_fx; + move16(); + if (NE_16(i, order - 1)) + { + tmp2_fx = lsf_fx[i+1]; + move16(); + } + tmp2_fx = sub(tmp2_fx, lsf_fx[i]); + + s1 = 15; + move16(); + s2 = 15; + move16(); + if(tmp1_fx == 0) + { + tmp1_fx = 8; + } + tmp1_fx = Inv16(tmp1_fx, &s1); + if(tmp2_fx == 0) + { + tmp2_fx = 8; + } + tmp2_fx = Inv16(tmp2_fx, &s2); + s1 = BASOP_Util_Add_MantExp(tmp1_fx, s1, tmp2_fx, s2, &tmp1_fx); /* x * 2.56 / pow(2.0, 15 + |s1|) */ + tmp_fx = mult_r(nf_fx, 10430); + s2 = norm_s(tmp_fx); + tmp_fx = shl(tmp_fx, s2); + s1 = sub(s1, s2); + + tmp1_fx = mult_r(tmp1_fx, tmp_fx); /* |s1| */ + s1 = abs_s(s1); + + /* 3) Fitting model combining the two weights*/ + L_tmp = L_add(ptr_lsf_fit_model[0][i], 0); /* Q10 */ + L_tmp = L_add(L_tmp, L_shl(L_mult0(ptr_lsf_fit_model[1][i], tmp1_fx), sub(-5, s1))); /* Q10 */ + L_tmp = L_add(L_tmp, L_shl(L_mult0(mult_r(tmp1_fx, tmp1_fx), ptr_lsf_fit_model[2][i]), sub(7, shl(s1, 1)))); + L_tmp = L_add(L_tmp, L_shl(L_mult0(w_fft_fx[i], ptr_lsf_fit_model[3][i]), -12)); + move16(); /* Q10 */ + + IF ( LT_32( L_shl( L_tmp, 5), InvIntTable[i+1] )) + { + w_fx[i] = shr( InvIntTable[i+1], 7); + move16(); + } + ELSE + { + IF( norm_l( L_tmp ) < 14 ) + { + w_fx[i] = MAX_16; + move16(); + } + ELSE + { + w_fx[i] = extract_l( L_shr( L_tmp, 2 ) ); + } + } + } + + return; +} diff --git a/lib_enc/range_enc_fx.c b/lib_enc/range_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..6519b6c0f9b24cdc385acfd8f273a723d16b1f68 --- /dev/null +++ b/lib_enc/range_enc_fx.c @@ -0,0 +1,306 @@ +/*==================================================================================== + 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 "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 */ + + +static void rc_enc_shift_fx(BSTR_ENC_HANDLE hBstr, PVQ_ENC_HANDLE hPVQ); +static void rc_enc_write_fx(BSTR_ENC_HANDLE hBstr, Word16 byte, Word16 bits); + +/*-------------------------------------------------------------------* + * rc_enc_init() + * + * Initalize range coder + *-------------------------------------------------------------------*/ + +void rc_enc_init_fx( + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + Word16 tot_bits /* i : Total bit budget */ +) +{ + hPVQ->rc_low = L_deposit_l(0); + hPVQ->rc_range = 0xffffffff; + move32(); + hPVQ->rc_cache = -1; + move16(); + hPVQ->rc_carry = 0; + move16(); + hPVQ->rc_carry_count = 0; + move16(); + hPVQ->rc_num_bits = 0; + move16(); + hPVQ->rc_tot_bits = tot_bits; + move16(); + hPVQ->rc_offset = 0; + move16(); + + return; +} + +/*-------------------------------------------------------------------* + * rc_encode() + * + * Encode symbol with range coder + *-------------------------------------------------------------------*/ + +void rc_encode_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 cum_freq, /* i : Cumulative frequency up to symbol */ + UWord32 sym_freq, /* i : Symbol probability */ + UWord32 tot /* i : Total cumulative frequency */ +) +{ + UWord32 r, tmp, inv_tot, lsb; + Word16 exp; + UWord16 carry; + + inv_tot = UL_inverse(tot, &exp); + Mpy_32_32_uu(hPVQ->rc_range, inv_tot, &tmp, &lsb); /*0+exp-32 */ + r = UL_lshr(tmp, sub(exp, 32)); /* exp-32-exp3+32 = 0 */ + tmp = UL_Mpy_32_32(r, cum_freq); + + hPVQ->rc_low = UL_addNs(hPVQ->rc_low, tmp, &carry); + if (carry != 0) + { + hPVQ->rc_carry = carry; + move16(); + } + + hPVQ->rc_range = UL_Mpy_32_32(r, sym_freq); + + WHILE (hPVQ->rc_range < 1<<24) + { + L_sub(0, 0); /* Comparison in while */ + hPVQ->rc_range = UL_lshl(hPVQ->rc_range, 8); + hPVQ->rc_num_bits = add(hPVQ->rc_num_bits, 8); + rc_enc_shift_fx(hBstr, hPVQ); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_finish() + * + * Finalize range coder + *-------------------------------------------------------------------*/ + +void rc_enc_finish_fx( + BSTR_ENC_HANDLE hBstr, + PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ + +) +{ + UWord32 val, mask, high; + Word16 bits; + UWord16 over1, over2; + + bits = add(norm_ul(hPVQ->rc_range), 1); + mask = UL_lshr(0xffffffff, bits); + + val = UL_addNs(hPVQ->rc_low, mask, &over1); + high = UL_addNs(hPVQ->rc_low, hPVQ->rc_range, &over2); + + val = L_and(val, ~mask); + L_xor(0,0); /* For bit not */ + + IF ( (L_xor(over1, over2)) == 0 ) + { + L_sub(0, 0); /* For comparision in if */ + IF (UL_addNsD(val, mask) >= high) + { + bits = add(bits, 1); + mask = UL_lshr(mask, 1); + val = UL_and(UL_addNsD(hPVQ->rc_low, mask), ~mask); + L_xor(0,0); /* For bit not */ + } + + if (val < hPVQ->rc_low) + { + hPVQ->rc_carry = 1; + move16(); + } + } + + hPVQ->rc_low = val; + move32(); + + IF ( GT_16(bits, sub(hPVQ->rc_tot_bits, hPVQ->rc_num_bits))) + { + bits = sub(hPVQ->rc_tot_bits, hPVQ->rc_num_bits); + + } + + hPVQ->rc_num_bits = add(hPVQ->rc_num_bits, bits); + FOR ( ; bits > 0; bits -= 8) + { + rc_enc_shift_fx(hBstr, hPVQ); + } + bits = add(bits, 8); + + IF (hPVQ->rc_carry_count > 0 ) + { + rc_enc_write_fx(hBstr, add(hPVQ->rc_cache, hPVQ->rc_carry), 8); + + FOR ( ; hPVQ->rc_carry_count > 1; hPVQ->rc_carry_count--) + { + rc_enc_write_fx(hBstr, (hPVQ->rc_carry + 0xff), 8); + } + rc_enc_write_fx(hBstr, s_and(add(hPVQ->rc_carry, 0xff), sub(lshl(1, bits), 1)), bits); + } + ELSE + { + rc_enc_write_fx(hBstr, lshr(add(hPVQ->rc_cache, hPVQ->rc_carry), sub(8, bits)), bits); + } + + bits = hPVQ->rc_num_bits; + move16(); + WHILE (LT_16(bits, sub(hPVQ->rc_tot_bits, 16))) + { + rc_enc_write_fx(hBstr, 0, 16); + bits = add(bits, 16); + } + + bits = sub(hPVQ->rc_tot_bits, bits); + IF (bits > 0) + { + rc_enc_write_fx(hBstr, 0, bits); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_shift() + * + * Shift a byte out to bitstream + *-------------------------------------------------------------------*/ + +static void rc_enc_shift_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ /* i/o: PVQ encoder handle */ +) +{ + test(); + L_sub(0, 0); /* For comparision in if */ + IF (hPVQ->rc_low < (0xff000000UL) || EQ_16(hPVQ->rc_carry, 1)) + { + IF (hPVQ->rc_cache >= 0) + { + rc_enc_write_fx(hBstr, add(hPVQ->rc_cache, hPVQ->rc_carry), 8); + } + + WHILE (hPVQ->rc_carry_count > 0) + { + rc_enc_write_fx(hBstr, s_and(add(hPVQ->rc_carry, 0xff), 255), 8); + hPVQ->rc_carry_count = sub(hPVQ->rc_carry_count, 1); + } + + hPVQ->rc_cache = u_extract_l(UL_lshr(hPVQ->rc_low, 24)); + hPVQ->rc_carry = 0; + move16(); + } + ELSE + { + hPVQ->rc_carry_count = add(hPVQ->rc_carry_count, 1); + } + hPVQ->rc_low = UL_lshl(hPVQ->rc_low, 8); + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_bits() + * + * + *-------------------------------------------------------------------*/ + +void rc_enc_bits_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + Word16 bits /* i : Number of bits used */ +) +{ + IF ( LE_16(add(rc_get_bits2_fx(hPVQ->rc_num_bits, hPVQ->rc_range), bits), hPVQ->rc_tot_bits)) + { + hPVQ->rc_num_bits = add(hPVQ->rc_num_bits, bits); + + IF ( GT_16(bits, 16)) + { + push_indice_fx(hBstr, sub(IND_RC_END, hPVQ->rc_offset), u_extract_l(UL_lshr(value, 16)), sub(bits, 16)); + hPVQ->rc_offset = add(hPVQ->rc_offset, 1); + push_indice_fx(hBstr, sub(IND_RC_END, hPVQ->rc_offset), u_extract_l(UL_and(value, 0x0000ffff)), 16); + hPVQ->rc_offset = add(hPVQ->rc_offset, 1); + } + ELSE + { + push_indice_fx(hBstr, sub(IND_RC_END, hPVQ->rc_offset), u_extract_l(value), bits); + hPVQ->rc_offset = add(hPVQ->rc_offset, 1); + } + } + ELSE + { + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_uniform() + * + * Encode with uniform distribution + *-------------------------------------------------------------------*/ + +void rc_enc_uniform_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + PVQ_ENC_HANDLE hPVQ, /* i/o: PVQ encoder handle */ + UWord32 value, /* i : Value to encode */ + UWord32 tot /* i : Maximum value */ +) +{ + Word16 n; + + n = sub(32, norm_ul(UL_subNsD(tot, 1))); + + IF (LE_16(n, 8)) + { + rc_encode_fx(hBstr, hPVQ, value, 1, tot); + } + ELSE + { + n = sub(n, 8); + rc_encode_fx(hBstr, hPVQ, UL_lshr(value, n), 1, UL_addNsD(UL_lshr(tot, n), 1)); + rc_enc_bits_fx(hBstr, hPVQ, UL_and(value, UL_subNsD(UL_lshl(1, n), 1)), n); + } + + return; +} + +/*-------------------------------------------------------------------* + * rc_enc_write() + * + * Write a byte to bitstream + *-------------------------------------------------------------------*/ + +static void rc_enc_write_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 byte, /* i : Byte to write */ + Word16 bits /* i : Number of bits */ +) +{ + push_indice_fx(hBstr, IND_RC_START, byte, bits); + + return; +} diff --git a/lib_enc/re8_cod_fx.c b/lib_enc/re8_cod_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..49b88b8e96cb279bf94e4cf511be370c8d9a02a1 --- /dev/null +++ b/lib_enc/re8_cod_fx.c @@ -0,0 +1,56 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include "options.h" /* Compilation switches */ +#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 */ + +/*------------------------------------------------------------------------ + * RE8_cod: + * + * MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX COMPUTATION) + * note: the index I is defined as a 32-bit word, but only + * 16 bits are required (long can be replaced by unsigned integer) + *--------------------------------------------------------------------------*/ + +void re8_cod_fx( + Word16 x[], /* i : point in RE8 (8-dimensional integer vector) */ + Word16 *n, /* i : codebook number (*n is an integer defined in {0,2,3,4,..,n_max}) */ + UWord16 *I, /* o : index of c (pointer to unsigned 16-bit word) */ + Word16 k[] /* o : index of v (8-dimensional vector of binary indices) = Voronoi index */ +) +{ + Word16 ka_fx, c_fx[8]; + /*---------------------------------------------------------------------- + * decompose x as x = 2^r c + v, where r is an integer >=0, c is an element + * of Q0, Q2, Q3 or Q4, and v is an element of a Voronoi code in RE8 + * (if r=0, x=c) + * this decomposition produces as a side-product the index k[] of v + * and the identifier ka of the absolute leader related to c + * + * the index of y is split into 2 parts : + * - the index I of c + * - the index k[] of v + ----------------------------------------------------------------------*/ + re8_vor_fx(x, n, k, c_fx, &ka_fx); + + /* safeguard in case that the AVQ subquantizer is not found - might happen for extremely strong onsets at the end of the frame */ + IF( GE_16(ka_fx,NB_LEADER)) + { + *n = 0; + move16(); + set16_fx( x, 0, 8 ); + } + + /* compute the index I (only if c is in Q2, Q3 or Q4) */ + IF (*n > 0) + { + re8_compute_base_index_fx(c_fx, ka_fx, I); + } + + return; +} diff --git a/lib_enc/reordernorm_fx.c b/lib_enc/reordernorm_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..505cfd693997a91468010eb3b60f63f48f904faa --- /dev/null +++ b/lib_enc/reordernorm_fx.c @@ -0,0 +1,60 @@ +/*==================================================================================== + 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" +#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 */ + +/*--------------------------------------------------------------------------*/ +/* Function reordernorm_fx */ +/* ~~~~~~~~~~~~~~~~~~~~~ */ +/* */ +/* Reorder quantization indices and norms */ +/*--------------------------------------------------------------------------*/ + +void reordernorm_fx( + const Word16 *ynrm, /* i : quantization indices for norms Q0 */ + const Word16 *normqlg2, /* i : quantized norms Q0 */ + Word16 *idxbuf, /* o : reordered quantization indices Q0 */ + Word16 *normbuf, /* o : reordered quantized norms Q0 */ + const Word16 nb_sfm /* i : number of bands Q0 */ +) +{ + Word16 i; + const Word16 *order = NULL; + + SWITCH(nb_sfm) + { + case NB_SFM: + order = norm_order_48; + BREAK; + case SFM_N_SWB: + order = norm_order_32; + BREAK; + case SFM_N_WB: + order = norm_order_16; + BREAK; + default: + order = norm_order_48; + BREAK; + } + + FOR (i = 0; i < nb_sfm; i++) + { + idxbuf[i] = ynrm[order[i]]; + move16(); + move16(); + normbuf[i] = normqlg2[order[i]]; + move16(); + move16(); + } + + return; +} diff --git a/lib_enc/rom_enc.c b/lib_enc/rom_enc.c index ea1d5b46904c935ee3cf181c99ff3a9b69ff38d8..cfb1eac6c56a087e9c5e5a14ee037fb1aa03b08d 100644 --- a/lib_enc/rom_enc.c +++ b/lib_enc/rom_enc.c @@ -64,6 +64,20 @@ const float M_ini[16] = 1.00000000f, 0.98078531f, 0.92387956f, 0.83146966f, 0.70710677f, 0.55557019f, 0.38268328f, 0.19509009f }; +typedef struct +{ + Word16 r; + Word16 i; +} complex_16; + +const complex_16 M_in_fix16[16] = +{ + {32767, 0}, {32138, 6393}, {30274, 12540}, {27246, 18205}, + {23170, 23170}, {18205, 27246}, {12540, 30274}, {6393, 32138}, + {0, 32767}, {-6393, 32138}, {-12540, 30274}, {-18205, 27246}, + {-23170, 23170},{ -27246, 18205}, {-30274, 12540}, {-32138, 6393}, +}; + const float M_r[8] = { 1.00000000f, 0.92387950f, 0.70710677f, 0.38268343f, -0.00000004f, -0.38268352f, -0.70710677f, -0.92387950f @@ -79,12 +93,22 @@ const float M_Wr[16]= 9.9518473e-001f, 9.5694034e-001f, 8.8192126e-001f, 7.7301045e-001f, 6.3439328e-001f, 4.7139674e-001f, 2.9028468e-001f, 9.8017140e-002f, -9.8017140e-002f, -2.9028468e-001f, -4.7139674e-001f, -6.3439328e-001f, -7.7301045e-001f, -8.8192126e-001f, -9.5694034e-001f, -9.9518473e-001f }; +const Word16 M_Wr_fix16[16] = +{ + 32609/* 9.9518473e-001f Q15 */,31356/* 9.5694034e-001f Q15 */,28898/* 8.8192126e-001f Q15 */,25329/* 7.7301045e-001f Q15 */,20787/* 6.3439328e-001f Q15 */,15446/* 4.7139674e-001f Q15 */, 9512/* 2.9028468e-001f Q15 */, 3212/* 9.8017140e-002f Q15 */, + -3212/* -9.8017140e-002f Q15 */,-9512/* -2.9028468e-001f Q15 */,-15446/* -4.7139674e-001f Q15 */,-20787/* -6.3439328e-001f Q15 */,-25329/* -7.7301045e-001f Q15 */,-28898/* -8.8192126e-001f Q15 */,-31356/* -9.5694034e-001f Q15 */,-32609/* -9.9518473e-001f Q15 */ +}; const float M_Wi[16] = { 9.8017140e-002f, 2.9028468e-001f, 4.7139674e-001f, 6.3439328e-001f, 7.7301045e-001f, 8.8192126e-001f, 9.5694034e-001f, 9.9518473e-001f, 9.9518473e-001f, 9.5694034e-001f, 8.8192126e-001f, 7.7301045e-001f, 6.3439328e-001f, 4.7139674e-001f, 2.9028468e-001f, 9.8017140e-002f }; +const Word16 M_Wi_fix16[16] = +{ + 3212/* 9.8017140e-002f Q15 */, 9512/* 2.9028468e-001f Q15 */,15446/* 4.7139674e-001f Q15 */,20787/* 6.3439328e-001f Q15 */,25329/* 7.7301045e-001f Q15 */,28898/* 8.8192126e-001f Q15 */,31356/* 9.5694034e-001f Q15 */,32609/* 9.9518473e-001f Q15 */, + 32609/* 9.9518473e-001f Q15 */,31356/* 9.5694034e-001f Q15 */,28898/* 8.8192126e-001f Q15 */,25329/* 7.7301045e-001f Q15 */,20787/* 6.3439328e-001f Q15 */,15446/* 4.7139674e-001f Q15 */, 9512/* 2.9028468e-001f Q15 */, 3212/* 9.8017140e-002f Q15 */ +}; const int16_t SP_CENTER_BAND_NUM_TAB[5] = {10, 10, 20, 24, 24}; @@ -96,13 +120,17 @@ const int16_t NREGION_INDEX_NB[9] = {0,1,2,3,4,5,6,7, 9}; const int16_t NREGION_INDEX_WB[13] = {0,1,2,3,4,5,6,8,10,12,16}; const int16_t NREGION_INDEX_SWB[16] = {0,1,2,3,4,5,6,8,10,12,16,24,36}; const int16_t NREGION_INDEX_FB[16] = {0,1,2,3,4,5,6,8,10,12,16,24,36}; +const Word16 NREGION_PREOFF[12] = { 0,0,0,0,0,0,1,1,1,2,3,4 }; const int16_t ENERGY_BAND_NUM[4] = {8,10,12,MAX_SUBBAND_NUM}; const int16_t * const REGION_INDEX[4] = {NREGION_INDEX_NB, NREGION_INDEX_WB,NREGION_INDEX_SWB,NREGION_INDEX_FB}; const float MAX_LF_SNR_TAB[4] = {0.8f, 0.8f, 1.6f, 0.8f}; +const Word32 MAX_LF_SNR_TAB_FX[5] = { 26843545/* 0.8 Q25 */,26843545/* 0.8 Q25 */,53687090/* 1.6 Q25 */,26843545/* 0.8 Q25 */,26843545/* 0.8 Q25 */ }; const float COMVAD_INIT_SNR_DELTA[5] = {1.0f, 0.6f, 0.86f, 1.16f, 1.0f}; +const Word32 COMVAD_INIT_SNR_DELTA_FX[5] = { 33554431/* 1.0 Q25 */, 20132659/* 0.6 Q25 */, 28856811/* 0.86 Q25 */, 38923139/* 1.16 Q25 */, 33554431/* 1.0 Q25 */ }; const float LS_MIN_SELENCE_SNR[3] = {7.5f, 7.5f, 6.8f}; const float LT_MIN_SILENCE_SNR[3] = {4.5f, 4.5f, 4.5f}; +const Word32 LT_MIN_SILENCE_SNR_FX[4] = { 150994940/* 4.5 Q25 */, 150994940/* 4.5 Q25 */, 150994940/* 4.5 Q25 */,150994940/* 4.5 Q25 */ }; /* half of the square root hanning window for spectral analysis */ const float sqrt_han_window[L_FFT/2+1]= @@ -125,6 +153,24 @@ const float sqrt_han_window[L_FFT/2+1]= 0.995185f, 0.996313f, 0.997290f, 0.998118f, 0.998795f, 0.999322f, 0.999699f, 0.999925f, 1.000000f }; +const Word16 sqrt_han_window_fx[L_FFT / 2 + 1] = +{ + 0, 402, 804, 1206, 1608, 2009, 2410, 2811, 3212, + 3612, 4011, 4410, 4808, 5205, 5602, 5998, 6393, 6786, + 7179, 7571, 7962, 8351, 8739, 9126, 9512, 9896, 10278, + 10659, 11039, 11417, 11793, 12167, 12539, 12910, 13279, 13645, + 14010, 14372, 14732, 15090, 15446, 15800, 16151, 16499, 16846, + 17189, 17530, 17869, 18204, 18537, 18868, 19195, 19519, 19841, + 20159, 20475, 20787, 21096, 21403, 21705, 22005, 22301, 22594, + 22884, 23170, 23452, 23731, 24007, 24279, 24547, 24811, 25072, + 25329, 25582, 25832, 26077, 26319, 26556, 26790, 27019, 27245, + 27466, 27683, 27896, 28105, 28310, 28510, 28706, 28898, 29085, + 29268, 29447, 29621, 29791, 29956, 30117, 30273, 30424, 30571, + 30714, 30852, 30985, 31113, 31237, 31356, 31470, 31580, 31685, + 31785, 31880, 31971, 32057, 32137, 32213, 32285, 32351, 32412, + 32469, 32521, 32567, 32609, 32646, 32678, 32705, 32728, 32745, + 32757, 32765, 32767 +}; /*----------------------------------------------------------------------------------* * Starting points for pulse position search in Algebraic innovation codebook @@ -185,14 +231,21 @@ const int16_t sublen1_12k8[7] = { 40, 40, 50, 50, 80, 80, 115 }; const int16_t sec_length_12k8[4] = { 7, 15, 30, 54 }; const int16_t sec_length1_12k8[4] = { 10, 19, 37, 38 }; const float h_fir[5] = {0.13f, 0.23f, 0.28f, 0.23f, 0.13f}; +const Word16 H_fir[] = { 4260, 7536, 9175, 7536, 4260 }; const float W_HIST[DTX_HIST_SIZE] = { 0.2f, 0.16f, 0.128f, 0.1024f, 0.08192f, 0.065536f, 0.0524288f, 0.01048576f }; +const Word16 W_HIST_FX[DTX_HIST_SIZE] = { 13107, 10486, 8389, 6711, 5369, 4295, 3436, 687 }; /* Q16 */ + +const Word16 W_HIST_S_FX[DTX_HIST_SIZE] = { 20480, 11378, 8393, 6938, 6092, 5551, 5183, 5115 }; /* Q12 */ + const float preemphCompensation[NB_BANDS] = { 9.7461f, 9.5182f, 9.0262f, 8.3493f, 7.5764f, 6.7838f, 5.8377f, 4.8502f, 4.0346f, 3.2788f, 2.6283f, 2.0920f, 1.6304f, 1.2850f, 1.0108f, 0.7916f, 0.6268f, 0.5011f, 0.4119f, 0.3637f }; +const Word16 preemphCompensation_fx[NB_BANDS] = { 19960/*9.7461f Q11*/, 19493/*9.5182f Q11*/, 18486/*9.0262f Q11*/, 17099/*8.3493f Q11*/, 15516/*7.5764f Q11*/, 13893/*6.7838f Q11*/, 11956/*5.8377f Q11*/, 9933/*4.8502f Q11*/, 8263/*4.0346f Q11*/, 6715/*3.2788f Q11*/, 5383/*2.6283f Q11*/, 4284/*2.0920f Q11*/, 3339/*1.6304f Q11*/, 2632/*1.2850f Q11*/, 2070/*1.0108f Q11*/, 1621/*0.7916f Q11*/, 1284/*0.6268f Q11*/, 1026/*0.5011f Q11*/, 844/*0.4119f Q11*/, 745/*0.3637f Q11*/ }; + /*----------------------------------------------------------------------------------* * LSF quantizer *----------------------------------------------------------------------------------*/ @@ -256,6 +309,29 @@ const float Freq_Weight_Com[160] = 0.22338204f, 0.22199170f, 0.22061856f, 0.21926230f, 0.21792261f, 0.21659920f, 0.21529175f, 0.21400000f, 0.21272366f, 0.21146245f, 0.21021610f, 0.20898438f, 0.20776699f, 0.20656371f, 0.20537429f, 0.20419848f }; +const Word32 Freq_Weight_Com_fx[160] = /*Q31 */ +{ + 1073741824, 1351646720, 1610612736, 1832992000, 2003629568, 2110896768, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, + 2147483647, 2147483647, 2147483647, 2147483647, 2147483647, 2088915968, 2033457920, 1980868480, + 1930930688, 1883448832, 1838246016, 1795162112, 1754051584, 1714781696, 1677231744, 1641291136, + 1606858368, 1573840768, 1542152704, 1511715456, 1482456448, 1454308608, 1427209600, 1401102080, + 1375932672, 1351651456, 1328212480, 1305572480, 1283691392, 1262531584, 1242058112, 1222238080, + 1203040640, 1184436864, 1166399744, 1148903808, 1131924864, 1115440512, 1099429376, 1083871488, + 1068747648, 1054040128, 1039731904, 1025806912, 1012249984, 999046720, 986183488, 973647232, + 961425728, 949507264, 937880640, 926535296, 915461184, 904648640, 894088512, 883772096, + 873691072, 863837376, 854203520, 844782144, 835566336, 826549440, 817725120, 809087168, + 800629824, 792347392, 784234624, 776286336, 768497472, 760863424, 753379520, 746041408, + 738844864, 731785856, 724860416, 718064832, 711395520, 704848896, 698421760, 692110720, + 685912704, 679824704, 673843840, 667967296, 662192384, 656516416, 650936960, 645451520, + 640057792, 634753472, 629536320, 624404224, 619355136, 614387008, 609497984, 604686208, + 599949760, 595286912, 590696000, 586175360, 581723392, 577338560, 573019328, 568764224, + 564571840, 560440832, 556369856, 552357568, 548402752, 544504128, 540660608, 536870912, + 533133984, 529448736, 525814080, 522228992, 518692448, 515203488, 511761152, 508364480, + 505012640, 501704704, 498439808, 495217120, 492035872, 488895200, 485794400, 482732672, + 479709280, 476723552, 473774752, 470862208, 467985248, 465143232, 462335520, 459561504, + 456820576, 454112160, 451435648, 448790528, 446176224, 443592192, 441037920, 438512896 +}; const float Freq_Weight_UV[160] = { @@ -280,6 +356,29 @@ const float Freq_Weight_UV[160] = 0.46718147f, 0.46538460f, 0.46360153f, 0.46183205f, 0.46007603f, 0.45833334f, 0.45660377f, 0.45488721f, 0.45318353f, 0.45149255f, 0.44981414f, 0.44814816f, 0.44649446f, 0.44485295f, 0.44322345f, 0.44160584f }; +const Word32 Freq_Weight_UV_fx[160] = /*Q31 */ +{ + 1073741824, 1351646720, 1610612736, 1832992000, 2003629568, 2110896768, 2147483647, 2129881344, + 2112565248, 2095528448, 2078764160, 2062265984, 2046027776, 2030043136, 2014306304, 1998811648, + 1983553536, 1968526720, 1953725696, 1939145728, 1924781696, 1910628864, 1896682624, 1882938624, + 1869392256, 1856039424, 1842876032, 1829897984, 1817101568, 1804482816, 1792038016, 1779763840, + 1767656576, 1755713024, 1743929728, 1732303488, 1720831232, 1709510016, 1698336768, 1687308544, + 1676422656, 1665676416, 1655067008, 1644591872, 1634248576, 1624034560, 1613947392, 1603984640, + 1594144256, 1584423936, 1574821376, 1565334528, 1555961216, 1546699520, 1537547520, 1528503040, + 1519564416, 1510729728, 1501997184, 1493365120, 1484831488, 1476395008, 1468053760, 1459806336, + 1451650944, 1443586176, 1435610624, 1427722624, 1419920896, 1412203904, 1404570368, 1397018880, + 1389548288, 1382157056, 1374844032, 1367608064, 1360447744, 1353362048, 1346349824, 1339409920, + 1332541184, 1325742464, 1319012736, 1312351104, 1305756416, 1299227648, 1292763776, 1286363904, + 1280027136, 1273752576, 1267539072, 1261385984, 1255292416, 1249257344, 1243280000, 1237359616, + 1231495424, 1225686400, 1219932032, 1214231424, 1208583808, 1202988544, 1197444736, 1191951872, + 1186509184, 1181116032, 1175771648, 1170475264, 1165226496, 1160024704, 1154868992, 1149758976, + 1144693888, 1139673344, 1134696576, 1129763200, 1124872448, 1120023808, 1115216768, 1110450944, + 1105725568, 1101040384, 1096394624, 1091787904, 1087219712, 1082689664, 1078197248, 1073741824, + 1069323136, 1064940672, 1060593984, 1056282624, 1052006144, 1047764224, 1043556288, 1039382080, + 1035241152, 1031132992, 1027057408, 1023013888, 1019002048, 1015021568, 1011072064, 1007153152, + 1003264576, 999405824, 995576704, 991776768, 988005760, 984263360, 980549120, 976862848, + 973204224, 969572864, 965968512, 962390848, 958839552, 955314432, 951815104, 948341312, +}; /*----------------------------------------------------------------------------------* * Speech/music classification @@ -296,6 +395,18 @@ const float w_spmus[HANG_LEN][HANG_LEN] = {0.235f, 0.205f, 0.174f, 0.143f, 0.112f, 0.081f, 0.05f, 0}, {0.200f, 0.179f, 0.157f, 0.136f, 0.114f, 0.093f, 0.071f, 0.05f} }; +const Word16 w_spmus_fx[HANG_LEN][HANG_LEN] = +{ + /*Q15*/ + {32767, 0, 0, 0, 0, 0, 0, 0,}, + {19661, 13107, 0, 0, 0, 0, 0, 0,}, + {15401, 10813, 6554, 0, 0, 0, 0, 0,}, + {13107, 9830, 6554, 3277, 0, 0, 0, 0,}, + { 9830, 8192, 6554, 4915, 3277, 0, 0, 0,}, + { 7635, 6783, 5898, 5014, 4162, 3277, 0, 0,}, + { 7700, 6717, 5702, 4686, 3670, 2654, 1638, 0,}, + { 6554, 5865, 5145, 4456, 3736, 3047, 2327, 1638} +}; const float sm_means[N_SMC_FEATURES] = { @@ -449,6 +560,16 @@ const float m_speech[N_MIXTURES*N_FEATURES] = 0.380487f, 0.727792f, 0.209973f, 0.314364f, 0.421881f, 0.398734f, 0.446999f, 0.402498f, 0.105313f, 0.867979f, 0.877883f, 0.317694f, 0.344962f, 0.658148f, 0.240913f, 0.348251f, 0.433178f, 0.480324f, 0.498983f, 0.419444f, 0.187060f, 0.868077f, 0.855516f, 0.347290f }; +const Word16 m_speech_fx[N_MIXTURES*N_FEATURES] = +{ + /*Q15*/ + 9436, 29987, 4795, 7076, 11050, 13645, 15206, 15194, 1936, 27952, 25172, 10301, + 10057, 30685, 8381, 9965, 10762, 8680, 11589, 15788, 1641, 26751, 27163, 10992, + 7927, 31230, 7191, 8505, 14304, 16336, 14972, 16077, 2052, 27271, 27694, 10859, + 13914, 17323, 10682, 16458, 17807, 18403, 19368, 12665, 2205, 29598, 29213, 11285, + 12468, 23848, 6880, 10301, 13824, 13066, 14647, 13189, 3451, 28442, 28766, 10410, + 11304, 21566, 7894, 11411, 14194, 15739, 16351, 13744, 6130, 28445, 28034, 11380 +}; const float invV_speech[N_MIXTURES*N_FEATURES*N_FEATURES] = { @@ -525,11 +646,92 @@ const float invV_speech[N_MIXTURES*N_FEATURES*N_FEATURES] = 6.583566f, 3.620328f, 2.671665f, 8.763003f, -4.082685f, 12.865157f, -4.696593f, 9.548755f, 20.883675f, -2.460779f, -59.110310f, -3.725027f, 4.081524f, 11.092305f, 12.669825f, 1.241007f, 14.381269f, -12.793469f, 1.570194f, -6.625203f, -23.079216f, 12.595569f, -3.725027f, -62.429104f }; +const Word32 invV_speech_fx[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + /*Q10*/ + -40443, -14756, -39560, -18113, 8983, -11676, 450, -10588, -49908, 358, 17222, 32914, + -14756, -200610, -27679, -28092, -16846, -6393, 5954, 13058, -67051, -47861, -8575, 18740, + -39560, -27679, -772035, 118158, -48299, 27758, -37782, 74336, -305470, -23323, 181510, 91957, + -18113, -28092, 118158, -228070, 41104, -46248, 21977, 8161, -27789, 78357, 26088, 39736, + 8983, -16846, -48299, 41104, -96670, 41164, -18208, 3995, -14774, 23704, 13802, 17925, + -11676, -6393, 27758, -46248, 41164, -95654, 58562, 3668, 103, 5952, 9479, 11083, + 450, 5954, -37782, 21977, -18208, 58562, -91964, -5597, -47161, -15941, 14870, 11028, + -10588, 13058, 74336, 8161, 3995, 3668, -5597, -102767, 25363, -21490, -48411, 13509, + -49908, -67051, -305470, -27789, -14774, 103, -47161, 25363, -1410848, -57997, 238792, -117641, + 358, -47861, -23323, 78357, 23704, 5952, -15941, -21490, -57997, -221932, -936, 40579, + 17222, -8575, 181510, 26088, 13802, 9479, 14870, -48411, 238792, -936, -157118, -49202, + 32914, 18740, 91957, 39736, 17925, 11083, 11028, 13509, -117641, 40579, -49202, -321159, + -54755, -48603, -918, -25735, 31634, -27972, 23305, -18449, -68162, -3670, -7982, 35965, + -48603, -449238, -11496, -14811, 12790, -11453, 2686, -3752, -86924, -30083, -54695, 17457, + -918, -11496, -258042, 157642, 4617, 27546, -22677, 7281, -221085, -48457, 80126, 16406, + -25735, -14811, 157642, -334462, 64217, 7724, 24309, 20322, -99420, 2896, 76924, 35785, + 31634, 12790, 4617, 64217, -296101, 182629, -27282, 11581, -10495, 16901, 50011, 20823, + -27972, -11453, 27546, 7724, 182629, -274190, 15505, 4345, -7824, 79496, -2218, 12832, + 23305, 2686, -22677, 24309, -27282, 15505, -73195, 2055, -4690, 31413, 15447, 8774, + -18449, -3752, 7281, 20322, 11581, 4345, 2055, -77913, 57514, -8586, -106171, 6233, + -68162, -86924, -221085, -99420, -10495, -7824, -4690, 57514, -1966183, -9074, 512909, -17375, + -3670, -30083, -48457, 2896, 16901, 79496, 31413, -8586, -9074, -185355, -15990, 8445, + -7982, -54695, 80126, 76924, 50011, -2218, 15447, -106171, 512909, -15990, -444405, -71821, + 35965, 17457, 16406, 35785, 20823, 12832, 8774, 6233, -17375, 8445, -71821, -222292, + -96397, -65745, 316, -47258, 43061, -42973, 10442, -19582, -43973, -19682, -21732, 48029, + -65745, -838575, 30816, -43250, 6642, -4487, 11239, 338, -17329, -59741, -114530, -1706, + 316, 30816, -351192, 207585, -68100, 60838, -83672, 14796, -158998, 13313, 122647, 38113, + -47258, -43250, 207585, -322741, 76525, -99711, 59838, 20166, -63534, 7136, 76247, 22923, + 43061, 6642, -68100, 76525, -96244, 54110, -21689, 2401, -36455, -19725, 38782, 6802, + -42973, -4487, 60838, -99711, 54110, -284964, 220150, -642, -44874, -21815, 16040, 3963, + 10442, 11239, -83672, 59838, -21689, 220150, -239817, 2018, -17214, -1904, 16387, 4095, + -19582, 338, 14796, 20166, 2401, -642, 2018, -58537, 20742, -9245, -85094, 8867, + -43973, -17329, -158998, -63534, -36455, -44874, -17214, 20742, -1009892, 28181, 407531, -10963, + -19682, -59741, 13313, 7136, -19725, -21815, -1904, -9245, 28181, -186118, -32487, 5665, + -21732, -114530, 122647, 76248, 38782, 16040, 16387, -85094, 407531, -32487, -511009, -66277, + 48029, -1706, 38113, 22923, 6802, 3963, 4095, 8867, -10963, 5665, -66277, -251113, + -21146, 1393, -2365, 3756, -4538, -1528, 2298, -6668, -7599, -2720, -5226, 3049, + 1393, -46612, -28502, 11801, -5967, 8395, -4182, 13773, 18586, -9799, -6696, -3522, + -2365, -28502, -77446, 55688, -10615, 10476, -6282, 5520, -19365, 8818, -4576, 2603, + 3756, 11801, 55688, -152293, 104577, -8742, 15278, -2773, 16622, -12382, -2828, 5452, + -4538, -5967, -10615, 104577, -245151, 117173, -5020, 3412, -2855, -19929, 9729, 1888, + -1528, 8395, 10476, -8742, 117173, -258943, 136249, -2960, -8257, -20123, -6735, -6316, + 2298, -4182, -6282, 15278, -5020, 136249, -192889, 889, -6047, -74906, 15861, 4026, + -6668, 13773, 5520, -2773, 3412, -2960, 889, -298321, 8558, 5827, -66886, -3080, + -7599, 18586, -19365, 16622, -2855, -8257, -6047, 8558, -837495, -36576, 477123, -58582, + -2720, -9799, 8818, -12382, -19929, -20123, -74906, 5827, -36576, -279826, 29479, 36566, + -5226, -6696, -4576, -2828, 9729, -6735, 15861, -66886, 477123, 29479, -1017755, -75828, + 3049, -3522, 2603, 5452, 1888, -6316, 4026, -3080, -58582, 36566, -75828, -193453, + -30403, -6761, -6085, -8388, 12841, -17600, 8289, -11817, -4054, -3000, -13322, 14944, + -6761, -28452, -12326, -8945, 10515, -8369, -520, 2242, -3287, -20124, 179, 12354, + -6085, -12326, -180408, 89468, -19908, 3017, -41552, 4204, -31158, -23783, 87004, 44784, + -8388, -8945, 89468, -146434, 53166, -28645, 29987, -2506, -12242, 28411, 11874, 403, + 12841, 10515, -19908, 53166, -182342, 131104, -3630, 7016, -11031, -43497, 35570, 41136, + -17600, -8369, 3017, -28645, 131104, -169537, 52490, -4955, 3848, 41489, -7925, -19614, + 8289, -520, -41552, 29987, -3630, 52490, -111006, -916, 3418, 2295, 3395, 1491, + -11817, 2242, 4204, -2506, 7016, -4955, -916, -219477, -4965, -3871, -77054, -1199, + -4054, -3287, -31158, -12242, -11031, 3848, 3418, -4965, -272588, 2948, 184352, -45153, + -3000, -20124, -23783, 28411, -43497, 41489, 2295, -3871, 2948, -160538, -11875, 4491, + -13322, 179, 87004, 11874, 35570, -7925, 3395, -77054, 184352, -11875, -501251, -59166, + 14944, 12354, 44784, 403, 41136, -19614, 1491, -1199, -45153, 4491, -59166, -256669, + -24496, -5820, -2150, 131, 5291, -10279, 6605, -749, -2301, -4257, 6742, 4179, + -5820, -30866, -8866, -12879, -1341, 2042, -4488, 6991, -847, -21654, 3707, 11359, + -2150, -8866, -123923, 90609, -28405, 24864, -28222, 3814, 6439, -12821, 2736, 12974, + 131, -12879, 90609, -147490, 86712, -38319, 26159, 1048, -7654, 17099, 8973, 1271, + 5291, -1341, -28405, 86712, -147877, 74296, -14561, 2055, 18062, 1238, -4181, 14726, + -10279, 2042, 24864, -38319, 74296, -168459, 117891, -874, -17255, 675, 13174, -13101, + 6605, -4488, -28222, 26159, -14561, 117891, -147764, -13296, 2771, -4243, -4809, 1608, + -749, 6991, 3814, 1048, 2055, -874, -13296, -77582, -32335, -4868, 9778, -6784, + -2301, -847, 6439, -7654, 18062, -17255, 2771, -32335, -69840, 11490, 21385, -23633, + -4257, -21654, -12821, 17099, 1238, 675, -4243, -4868, 11490, -151841, -2520, 12898, + 6742, 3707, 2736, 8973, -4181, 13174, -4809, 9778, 21385, -2520, -60529, -3814, + 4179, 11359, 12974, 1271, 14726, -13101, 1608, -6784, -23633, 12898, -3814, -63927 +}; const float lvm_speech[N_MIXTURES] = { 31.996607f, 32.762783f, 32.964325f, 31.979258f, 30.885334f, 26.185850f }; +const Word32 lvm_speech_fx[N_MIXTURES] = +{ + /*Q10*/ + 32765, 33549, 33755, 32747, 31627, 26814 +}; const float m_music[N_MIXTURES*N_FEATURES] = { @@ -540,6 +742,16 @@ const float m_music[N_MIXTURES*N_FEATURES] = 0.305845f, 0.692470f, 0.378321f, 0.465361f, 0.486968f, 0.499951f, 0.520584f, 0.473288f, 0.125325f, 0.726521f, 0.692794f, 0.374433f, 0.513981f, 0.696380f, 0.246046f, 0.343276f, 0.374858f, 0.396051f, 0.418772f, 0.646286f, 0.026468f, 0.930184f, 0.778228f, 0.369588f }; +const Word16 m_music_fx[N_MIXTURES*N_FEATURES] = +{ + /*Q15*/ + 14804, 25446, 8882, 11624, 12963, 13563, 14794, 20567, 1033, 27373, 23772, 11713, + 15975, 20612, 7737, 12728, 14424, 15237, 16190, 15239, 2277, 30096, 28120, 11522, + 17631, 19827, 9280, 14111, 15555, 16289, 17009, 17271, 1132, 31186, 27733, 12469, + 15863, 24390, 7804, 11176, 11734, 11986, 12857, 23015, 713, 28823, 23782, 13779, + 10022, 22691, 12397, 15249, 15957, 16382, 17058, 15509, 4107, 23807, 22701, 12269, + 16842, 22819, 8062, 11248, 12283, 12978, 13722, 21178, 867, 30480, 25501, 12111 +}; const float invV_music[N_MIXTURES*N_FEATURES*N_FEATURES] = { @@ -616,11 +828,92 @@ const float invV_music[N_MIXTURES*N_FEATURES*N_FEATURES] = 3.172123f, -22.678297f, 15.459837f, 43.245403f, 10.640046f, 1.826011f, -0.166995f, -21.376526f, 791.254944f, -7.915982f, -312.138367f, -76.008308f, 5.710633f, -7.513731f, 34.635460f, 35.328983f, 17.738880f, 8.071489f, 3.456159f, 7.093094f, -708.115784f, 73.130432f, -76.008293f, -469.943726f }; +const Word32 invV_music_fx[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + /*Q10*/ + -7878, -673, -2037, -885, -236, -667, 749, -1726, -20424, -859, 2463, 4011, + -673, -31356, -1591, -3048, -1872, 1277, -3806, 8836, 5555, -2031, -11076, -7329, + -2037, -1591, -65556, 42935, -11408, 12166, 751, 8792, 24077, -15804, -2546, -2517, + -885, -3048, 42935, -88483, 42957, -13081, 4776, 14411, 23734, -5735, 15306, 15210, + -236, -1872, -11408, 42957, -90738, 37950, -1795, 4021, -35266, 12445, 13655, 17403, + -667, 1277, 12166, -13081, 37950, -86289, 37943, 3429, -5655, 5664, 8658, -11, + 749, -3806, 751, 4776, -1795, 37943, -77863, -8515, -74265, 22313, 3842, 645, + -1726, 8836, 8792, 14411, 4021, 3429, -8515, -59311, -121235, 1622, -8500, 4967, + -20424, 5555, 24077, 23734, -35266, -5655, -74265, -121235, -5534279, 175865, 247781, -296138, + -859, -2031, -15804, -5735, 12445, 5664, 22313, 1622, 175865, -104343, -1168, 32220, + 2463, -11076, -2546, 15306, 13655, 8658, 3842, -8500, 247781, -1168, -79522, -45571, + 4011, -7329, -2517, 15210, 17403, -11, 645, 4967, -296138, 32220, -45571, -249005, + -10115, 613, -4406, -403, 731, 898, 350, -1995, -8975, -169, -1296, 1233, + 613, -30663, -12425, -1115, -1862, 2906, -2485, 12887, -8842, -12067, 4833, 3070, + -4406, -12425, -86550, 49625, -11519, 15386, -20054, 20873, -13684, 28341, 23152, -807, + -403, -1115, 49625, -131210, 81002, 1045, 3085, 8149, -11887, -3094, 43855, 14533, + 731, -1862, -11519, 81002, -226160, 115669, 9052, -6427, -19605, -20406, 7481, 6064, + 898, 2906, 15386, 1045, 115669, -281745, 150559, -5530, 271, -5717, 1673, 7674, + 350, -2485, -20054, 3085, 9052, 150559, -200735, -21872, -9366, 10471, -2190, 3083, + -1995, 12887, 20873, 8149, -6427, -5530, -21872, -111299, -29613, -27611, -54741, -9432, + -8975, -8842, -13684, -11887, -19605, 271, -9366, -29613, -616730, 74872, 189453, -79618, + -169, -12067, 28341, -3094, -20406, -5717, 10471, -27611, 74872, -359342, -12919, 29609, + -1296, 4833, 23152, 43855, 7481, 1673, -2190, -54741, 189453, -12919, -407670, -16961, + 1233, 3070, -807, 14533, 6064, 7674, 3083, -9432, -79618, 29609, -16961, -180700, + -12411, 5539, -1902, 92, 2813, 339, -114, -1078, -24097, -2938, -1812, 399, + 5539, -36224, -7229, -766, -2442, 2066, -2896, 8507, 16429, -11423, -12067, -191, + -1902, -7230, -115426, 44336, 11635, 13946, -3573, 22728, -73099, 119214, 70165, 4686, + 92, -766, 44336, -187908, 81624, 24838, 12765, 1471, -43322, -24066, 44669, 3543, + 2813, -2442, 11635, 81624, -295220, 104190, 52986, -3246, -146322, -78690, 34365, -2814, + 339, 2066, 13946, 24838, 104190, -347659, 169287, -4458, -127093, -94499, 42989, 5700, + -114, -2896, -3573, 12765, 52986, 169287, -310084, -18605, -27182, -19113, -2714, 11, + -1078, 8507, 22728, 1471, -3246, -4458, -18605, -69283, 40578, -47905, -135760, -6645, + -24097, 16429, -73099, -43322, -146322, -127093, -27182, 40578, -8241631, -71531, 1853193, -175523, + -2938, -11423, 119214, -24066, -78690, -94499, -19113, -47905, -71531, -1361618, -36609, 26675, + -1812, -12067, 70165, 44669, 34365, 42989, -2714, -135760, 1853193, -36609, -1337597, -83909, + 399, -191, 4686, 3543, -2814, 5700, 11, -6645, -175523, 26675, -83909, -223653, + -8809, 3326, -1275, -1509, 1423, 1222, -767, -3923, -65513, -5992, 9965, 3853, + 3326, -31906, -1905, 4114, -4704, 1138, -584, 10709, 104184, 6118, -30358, -5240, + -1275, -1905, -184413, 67973, -17415, 32246, -7121, 16051, -2994, -52989, 23547, 27770, + -1509, 4114, 67973, -160389, 86351, -8947, 13772, 8224, 3480, 2626, 24337, 1870, + 1423, -4704, -17415, 86351, -198772, 68001, 7361, 14025, 11152, 23137, 12598, 9972, + 1222, 1138, 32246, -8947, 68001, -166130, 57911, 17629, 118765, 39472, 1806, 7267, + -767, -584, -7121, 13772, 7361, 57911, -123203, 2059, 47920, 59494, 10484, -5066, + -3923, 10709, 16051, 8224, 14025, 17629, 2059, -90332, -367027, -30259, -20438, -3054, + -65513, 104184, -2994, 3480, 11152, 118765, 47920, -367027, -16854832, -181537, 903929, -95027, + -5992, 6118, -52989, 2626, 23137, 39472, 59494, -30259, -181537, -320917, -11497, 56536, + 9965, -30358, 23547, 24337, 12598, 1806, 10484, -20438, 903929, -11497, -197437, -16106, + 3853, -5240, 27770, 1870, 9972, 7267, -5066, -3054, -95027, 56536, -16106, -107942, + -14599, -2426, -4488, 2252, 20, -696, -2636, 5531, 1097, 109, 1359, 2742, + -2426, -22977, 1326, -4413, -6555, 199, -2249, 16239, 6914, -6267, 1335, -319, + -4488, 1326, -38846, 40605, -16372, -138, 6341, 2358, -5859, 1498, -1344, -3917, + 2252, -4413, 40605, -94592, 69176, -3799, -16812, -5416, -11189, -3107, 2060, -3508, + 20, -6555, -16372, 69176, -121278, 55283, 86, 3716, 11782, -9657, 3416, 549, + -696, 199, -138, -3799, 55283, -105539, 62225, 5299, 3619, 1933, -2511, 609, + -2636, -2249, 6341, -16812, 86, 62225, -79693, -7236, -9729, -2907, 2795, 57, + 5531, 16239, 2358, -5416, 3716, 5299, -7236, -52597, -40766, -5195, 2995, 11158, + 1097, 6914, -5859, -11189, 11782, 3619, -9729, -40766, -95884, 18462, 2795, -18509, + 109, -6267, 1498, -3107, -9657, 1933, -2907, -5195, 18462, -29138, 3027, 17268, + 1359, 1335, -1344, 2060, 3416, -2511, 2795, 2995, 2795, 3027, -10878, -6828, + 2742, -319, -3917, -3508, 549, 609, 57, 11158, -18509, 17268, -6828, -48324, + -9462, 2969, -1087, -1924, 1418, -350, 396, -3124, -35326, 682, 3248, 5848, + 2969, -29148, -2662, 2400, -3059, 2772, 847, 8375, 60040, -6778, -23223, -7694, + -1087, -2662, -172602, 83798, 2597, 33012, 3851, 12397, 81998, -81017, 15831, 35467, + -1924, 2400, 83798, -204141, 66003, 2928, 18028, 14706, 8557, 16030, 44283, 36177, + 1418, -3059, 2597, 66003, -202589, 47215, 19493, 10544, -4664, 46480, 10895, 18165, + -350, 2772, 33012, 2928, 47215, -198011, 76335, 14223, 123301, 70945, 1870, 8265, + 396, 847, 3851, 18028, 19493, 76335, -177594, -5345, 78880, 114804, -171, 3539, + -3124, 8375, 12397, 14706, 10544, 14223, -5345, -67596, -251454, -55035, -21890, 7263, + -35326, 60040, 81998, 8557, -4664, 123301, 78880, -251454, -12784658, -217014, 810245, -725111, + 682, -6778, -81017, 16030, 46480, 70945, 114804, -55035, -217014, -793758, -8106, 74886, + 3248, -23223, 15831, 44283, 10895, 1870, -171, -21890, 810245, -8106, -319630, -77833, + 5848, -7694, 35467, 36177, 18165, 8265, 3539, 7263, -725111, 74886, -77832, -481222 +}; const float lvm_music[N_MIXTURES] = { 27.932661f, 30.347250f, 34.528702f, 31.239647f, 20.447638f, 33.589111f }; +const Word32 lvm_music_fx[N_MIXTURES] = +{ + /*Q10*/ + 28603, 31076, 35357, 31989, 20938, 34395 +}; const float m_noise[N_MIXTURES*N_FEATURES] = { @@ -631,6 +924,16 @@ const float m_noise[N_MIXTURES*N_FEATURES] = 0.421798f, 0.491610f, 0.266544f, 0.367277f, 0.407442f, 0.415130f, 0.458496f, 0.395402f, 0.035484f, 0.951506f, 0.861898f, 0.362091f, 0.422524f, 0.475384f, 0.321804f, 0.436169f, 0.468526f, 0.481682f, 0.505572f, 0.389095f, 0.048487f, 0.967269f, 0.878799f, 0.409561f }; +const Word16 m_noise_fx[N_MIXTURES*N_FEATURES] = +{ + /*Q15*/ + 14825, 18681, 7930, 11230, 13228, 13602, 14556, 14377, 1133, 29263, 26842, 13270, + 14312, 14992, 9378, 12891, 14075, 14581, 15548, 12386, 1050, 32143, 28322, 12379, + 18179, 16617, 8015, 13153, 13932, 14462, 15329, 11848, 1033, 31841, 28406, 12222, + 15822, 17883, 3231, 8086, 9983, 9933, 11537, 11904, 1018, 29549, 27473, 11111, + 13821, 16109, 8734, 12035, 13351, 13603, 15024, 12957, 1163, 31179, 28243, 11865, + 13845, 15577, 10545, 14292, 15353, 15784, 16567, 12750, 1589, 31695, 28796, 13420 +}; const float invV_noise[N_MIXTURES*N_FEATURES*N_FEATURES] = { @@ -707,11 +1010,92 @@ const float invV_noise[N_MIXTURES*N_FEATURES*N_FEATURES] = 3.117799f, 13.074540f, 36.098553f, -28.525242f, 20.279724f, -20.597570f, 34.979023f, -125.449432f, 739.213074f, -106.282112f, -1878.532593f, -113.480858f, 2.142687f, -2.708396f, -9.562349f, -5.235439f, -7.102309f, -14.877532f, -8.548790f, -11.139709f, -97.542229f, 1.036536f, -113.480865f, -101.406532f }; +const Word32 invV_noise_fx[N_MIXTURES*N_FEATURES*N_FEATURES] = +{ + /*Q10*/ + -11129, -775, -807, 4750, -4310, -1632, 1694, 530, -25134, -2399, 1632, 1938, + -775, -43700, -5296, -23144, -4086, -2008, 9445, 12956, 17119, 10623, -18169, -14373, + -807, -5296, -117924, 78859, -23526, 22681, -7637, 52382, 20661, -1131, 18004, -18669, + 4750, -23144, 78859, -165973, 70704, -954, 10160, 6713, 50481, 19307, -10190, 16924, + -4310, -4086, -23526, 70704, -186160, 114906, -28994, 9999, 17677, -18372, -20805, -12577, + -1632, -2008, 22681, -954, 114906, -235840, 123708, -3753, 21616, 9200, 15641, -10616, + 1694, 9445, -7637, 10160, -28994, 123708, -156081, -1564, -7627, 5159, 14184, -12573, + 530, 12956, 52382, 6713, 9999, -3753, -1564, -116541, -130257, -2892, -51260, -1433, + -25134, 17119, 20661, 50481, 17677, 21616, -7627, -130257, -6857531, -23164, 425725, -172307, + -2399, 10623, -1131, 19307, -18372, 9200, 5159, -2892, -23164, -157605, 9307, 20639, + 1632, -18169, 18004, -10190, -20805, 15641, 14184, -51260, 425725, 9307, -184817, -2232, + 1938, -14373, -18669, 16924, -12577, -10616, -12573, -1433, -172307, 20639, -2232, -94498, + -23585, -1283, 2220, 5814, -1063, -5524, 5040, -408, -7744, 65700, -4948, 1221, + -1283, -102238, 18435, -18156, -6216, 17104, -1870, 25097, 97427, 32242, -77595, -4567, + 2220, 18435, -305438, 139861, 24123, 32851, -45614, 45538, 124040, 301172, -22649, 3625, + 5814, -18156, 139861, -565373, 242575, 46852, 50718, -18774, -159188, 141029, 89911, 9768, + -1063, -6216, 24123, 242575, -798475, 256535, 104095, 9375, -84525, -408528, 98204, 4495, + -5524, 17104, 32851, 46852, 256535, -845586, 312678, -6990, 50242, -543393, -42629, 99, + 5040, -1870, -45614, 50718, 104095, 312678, -732093, 14409, 83177, -140864, -2169, -2321, + -408, 25097, 45538, -18774, 9375, -6990, 14409, -314037, 273543, -30059, -253352, -3462, + -7744, 97427, 124040, -159188, -84525, 50242, 83177, 273543, -19301626, -952154, 3668367, -93870, + 65700, 32242, 301172, 141029, -408528, -543393, -140864, -30059, -952154, -16033274, -164405, -24189, + -4948, -77595, -22649, 89911, 98204, -42629, -2169, -253352, 3668367, -164405, -2501887, -105127, + 1221, -4567, 3625, 9768, 4495, 99, -2321, -3462, -93870, -24189, -105127, -252171, + -11556, 5444, 1053, 1823, -1754, -6509, 3535, -483, 5751, 22898, -4369, 2503, + 5444, -61418, -46603, 523, -4221, 5377, -14703, 2336, 4414, 4601, 17795, 5358, + 1053, -46603, -197022, 61944, 30015, 11139, -14163, 4583, 14704, 174734, 105587, 3797, + 1823, 523, 61944, -579713, 310766, -24876, -8601, -1522, -38055, -308764, 10254, 11526, + -1754, -4221, 30015, 310766, -873205, 294102, 7806, 2338, -28081, -507955, -5526, -1671, + -6509, 5377, 11139, -24876, 294102, -740664, 309186, -19342, -50840, -143800, 27527, 4324, + 3535, -14703, -14163, -8601, 7806, 309186, -508227, 24986, 208442, -230010, -48336, -9651, + -483, 2336, 4583, -1522, 2338, -19342, 24986, -362502, 140055, -118693, -134546, 982, + 5751, 4414, 14704, -38055, -28081, -50840, 208442, 140055, -20820834, -328791, 3081671, -99923, + 22898, 4601, 174734, -308764, -507955, -143800, -230010, -118693, -328791, -7236926, -225976, -47887, + -4369, 17795, 105587, 10254, -5526, 27527, -48336, -134546, 3081671, -225976, -2500626, -124929, + 2503, 5358, 3797, 11526, -1671, 4324, -9651, 982, -99923, -47887, -124929, -277469, + -14533, 3263, -8141, 13301, 5586, 1808, -5289, 472, 7371, -21379, -2460, 596, + 3263, -46002, -56596, 9198, -765, 13994, 5247, 2629, -14758, -21574, 5644, 3817, + -8141, -56596, -895669, 406276, -247505, 72418, -246462, 32532, -190899, -74267, 59747, 10271, + 13301, 9198, 406276, -551172, 137309, 34772, -5367, 41269, 67372, 262339, 42457, 60892, + 5586, -765, -247505, 137309, -964866, 393695, 36960, 5148, 114354, 66434, -19640, 18501, + 1808, 13994, 72418, 34772, 393695, -906317, 366933, 14058, 76374, 284422, 16253, 32973, + -5289, 5247, -246462, -5367, 36960, 366933, -711303, 23465, 84856, 157990, 2319, 21580, + 472, 2629, 32532, 41269, 5148, 14058, 23465, -349612, -74011, -89655, -17686, 7616, + 7371, -14758, -190899, 67372, 114354, 76374, 84856, -74011, -17027780, -264311, 396822, -266476, + -21379, -21574, -74267, 262339, 66434, 284422, 157990, -89655, -264311, -871539, 3553, 2308, + -2460, 5644, 59747, 42457, -19640, 16253, 2319, -17686, 396822, 3553, -334956, -46272, + 596, 3817, 10271, 60892, 18501, 32973, 21580, 7616, -266476, 2308, -46272, -357254, + -21040, -1263, -6696, 8169, -1272, -4427, 4142, -8459, -63196, -17218, 710, 2270, + -1263, -83196, -34319, -27267, 2213, -240, -783, 22287, 136898, 9589, -27942, -6781, + -6696, -34319, -329281, 107754, 677, -33332, -46218, 43055, -204958, -43031, 204918, 20438, + 8169, -27267, 107754, -371373, 103141, 10674, 46337, -3299, -65216, -42038, -5280, 13005, + -1272, 2213, 677, 103141, -420124, 194457, 1575, 22157, -26994, 36729, 47504, 13852, + -4427, -240, -33332, 10674, 194457, -368592, 152851, 14172, 107043, 44274, -23917, -8922, + 4142, -783, -46218, 46337, 1575, 152851, -280668, -8210, 40158, 24389, 13385, 8410, + -8459, 22287, 43055, -3299, 22157, 14172, -8210, -256064, 79772, -1255, -101174, 759, + -63196, 136898, -204958, -65216, -26994, 107043, 40158, 79772, -13100212, 263557, 2000831, -242675, + -17218, 9589, -43031, -42038, 36729, 44274, 24389, -1255, 263557, -1223057, -216580, -23199, + 710, -27942, 204918, -5280, 47504, -23917, 13385, -101174, 2000831, -216580, -1303910, -90175, + 2270, -6781, 20438, 13005, 13852, -8922, 8410, 759, -242675, -23199, -90175, -372746, + -24335, -321, -1426, 1524, 1959, -4164, 7012, -3148, -7859, 9391, 3193, 2194, + -321, -90890, -9068, -27277, 5303, 10922, 2298, 22512, 17201, 4798, 13388, -2773, + -1426, -9068, -180137, 85478, 42242, 14714, -12908, 34197, 67246, 40663, 36965, -9792, + 1524, -27277, 85478, -392290, 221884, 12492, 33161, -14359, 7950, -103145, -29210, -5361, + 1959, 5303, 42242, 221884, -600963, 259592, 30301, 7895, -32577, -115360, 20766, -7273, + -4164, 10922, 14714, 12492, 259592, -611459, 304095, 6323, -42968, -37072, -21092, -15235, + 7012, 2298, -12908, 33161, 30301, 304095, -467758, 26953, -35709, 29107, 35819, -8754, + -3148, 22512, 34197, -14359, 7895, 6323, 26953, -271919, 2988, 852, -128460, -11407, + -7859, 17201, 67246, 7950, -32577, -42968, -35709, 2988, -1773460, -215853, 756954, -99883, + 9391, 4798, 40663, -103145, -115360, -37072, 29107, 852, -215853, -2382074, -108833, 1061, + 3193, 13388, 36965, -29210, 20766, -21092, 35819, -128460, 756954, -108833, -1923617, -116204, + 2194, -2773, -9792, -5361, -7273, -15235, -8754, -11407, -99883, 1061, -116204, -103840 +}; const float lvm_noise[N_MIXTURES] = { 28.723963f, 41.180500f, 39.296734f, 38.508724f, 37.029205f, 35.496319f }; +const Word32 lvm_noise_fx[N_MIXTURES] = +{ + /*Q10*/ + 29413, 42169, 40240, 39433, 37918, 36348 +}; /* Mel filterbank */ const int16_t mel_fb_start[NB_MEL_BANDS] = @@ -1011,6 +1395,30 @@ const float hann_window_320[BWD_TOTAL_WIDTH/2] = 0.998812366428647f, 0.999393946948934f, 0.999781792684653f, 0.999975753175008f }; +const Word16 hann_window_320_fx[BWD_TOTAL_WIDTH / 2] = +{ + 0, 1, 3, 7, 13, 20, 29, 39, + 51, 64, 79, 96, 114, 134, 155, 177, + 202, 227, 255, 283, 314, 345, 379, 413, + 449, 487, 525, 566, 607, 650, 695, 740, + 787, 835, 885, 935, 987, 1040, 1095, 1150, + 1207, 1265, 1323, 1383, 1444, 1506, 1569, 1633, + 1698, 1764, 1831, 1899, 1967, 2036, 2106, 2177, + 2249, 2321, 2394, 2468, 2543, 2617, 2693, 2769, + 2846, 2923, 3000, 3078, 3156, 3235, 3314, 3394, + 3473, 3553, 3633, 3713, 3794, 3874, 3955, 4035, + 4116, 4197, 4277, 4358, 4438, 4519, 4599, 4679, + 4759, 4838, 4917, 4996, 5075, 5153, 5231, 5308, + 5385, 5461, 5537, 5612, 5687, 5761, 5834, 5907, + 5979, 6050, 6121, 6190, 6259, 6327, 6395, 6461, + 6526, 6591, 6654, 6717, 6778, 6839, 6898, 6956, + 7014, 7070, 7125, 7178, 7231, 7282, 7332, 7381, + 7429, 7475, 7520, 7563, 7606, 7647, 7686, 7724, + 7761, 7796, 7830, 7863, 7894, 7923, 7951, 7978, + 8003, 8026, 8048, 8068, 8087, 8105, 8121, 8135, + 8147, 8158, 8168, 8176, 8182, 8187, 8190, 8192 +}; + /*----------------------------------------------------------------------------------* * Starting line for the noise measurement in TCX. *----------------------------------------------------------------------------------*/ @@ -1019,5 +1427,130 @@ const int16_t startLineWB[N_TCX_STARTLINE_NOISE_WB] = { 8, 23, 36, 45, 66, 128 const int16_t startLineSWB[N_TCX_STARTLINE_NOISE_SWB] = { 8, 44, 96 /* 13.2kbps */, 160, 320, 320, 256 /* 48kbps */, 341, 640 }; +const Word32 LS_MIN_SILENCE_SNR[4] = { 251658233/* 7.5 Q25 */, 251658233/* 7.5 Q25 */, 228170137/* 6.8 Q25 */,228170137/* 6.8 Q25 */ }; + +const Word16 SNR_SUB_BAND_NUM[4] = { 8,10,12,MAX_SUBBAND_NUM }; +const Word16 BAND_MUL[4] = { 4096/* 1/8.0 Q15 */,3277/* 1/10.0 Q15 */,2731/* 1/12.0 Q15 */,2731/* 1/12.0 Q15 */ }; +/* enc_acelp.c, enc_acelpx.c */ +const UWord8 E_ROM_tipos[40] = +{ + 0, 1, 2, 3, /* starting point &ipos[0], 1st iter */ + 1, 2, 3, 0, /* starting point &ipos[4], 2nd iter */ + 2, 3, 0, 1, /* starting point &ipos[8], 3rd iter */ + 3, 0, 1, 2, /* starting point &ipos[12], 4th iter */ + 0, 1, 2, 3, + 1, 2, 3, 0, + 2, 3, 0, 1, + 3, 0, 1, 2, + 0, 1, 2, 3, /* end point for 24 pulses &ipos[35], 4th iter */ + 1, 2, 3, 0 /* end point for 36 pulses &ipos[39], 2nd iter */ +}; + +/* pow(3 * i + 1, 0.3) / pow(256 - 1, 0.3) */ +const Word16 Weight[86] = +{ + 0x1848, 0x24CD, 0x2B87, 0x3072, 0x3469, 0x37C8, 0x3ABB, 0x3D5F, 0x3FC6, 0x41FA, 0x4406, 0x45EF, 0x47BB, 0x496E, 0x4B0A, + 0x4C93, 0x4E0A, 0x4F71, 0x50CA, 0x5216, 0x5357, 0x548C, 0x55B8, 0x56DA, 0x57F4, 0x5905, 0x5A10, 0x5B13, 0x5C10, 0x5D06, 0x5DF7, + 0x5EE2, 0x5FC8, 0x60A9, 0x6185, 0x625D, 0x6331, 0x6401, 0x64CD, 0x6595, 0x6659, 0x671B, 0x67D9, 0x6893, 0x694B, 0x6A00, 0x6AB2, + 0x6B62, 0x6C0F, 0x6CB9, 0x6D61, 0x6E07, 0x6EAB, 0x6F4C, 0x6FEB, 0x7088, 0x7124, 0x71BD, 0x7254, 0x72EA, 0x737E, 0x7410, 0x74A1, + 0x752F, 0x75BD, 0x7649, 0x76D3, 0x775C, 0x77E3, 0x7869, 0x78EE, 0x7971, 0x79F3, 0x7A74, 0x7AF4, 0x7B72, 0x7BF0, 0x7C6C, 0x7CE7, + 0x7D61, 0x7DDA, 0x7E51, 0x7EC8, 0x7F3E, 0x7FB3, 0x7FFF +}; + +const Word16 BAND_SCALE_AJ[5] = { 3,3,5,6,6 }; /* {OFFSET, NB, WB, SWB, FB} */ + +/* Inv possible delta used in gaus_enc (1.0/(1.0+delta*delta)) and delta = [1,7] */ +const Word16 inv_delta_tab[7] = /*Q15*/ +{ + 32640, + 32264, + 31655, + 30840, + 29855, + 28728, + 27504 +}; /* clang-format on */ + +const Word16 i_t_1[10] = { 2048,4096,6144,8192,10240,12288,14336,16384,18432,20480 }; +const Word16 i_t_2[23] = { 1024,2048,3072,4096,5120,6144,7168,8192,9216,10240,11264,12288,13312,14336,15360,16384,17408,18432,19456,20480,21504,22528,23552 }; + +const Word16 SF_mult_fx[N_FEATURES] = +{ + 20133, /*Q22*/ + 32767, /*Q15*/ + 20401, /*Q15*/ + 18013, /*Q15*/ + 16263, /*Q15*/ + 16545, /*Q15*/ + 16610, /*Q15*/ + 17197, /*Q22*/ + 18455, /*Q23*/ + 16515, /*Q18*/ + 17931, /*Q18*/ + 30382 /*Q18*/ +}; + +const Word16 SF_8k_mult_fx[N_FEATURES] = +{ + 17197, /*Q22*/ + 28088, /*Q15*/ + 22082, /*Q15*/ + 20503, /*Q15*/ + 18006, /*Q15*/ + 18983, /*Q15*/ + 8199 , /*Q15*/ + 17197, /*Q22*/ + 16777, /*Q23*/ + 16515, /*Q18*/ + 15676, /*Q18*/ + 16541 /*Q18*/ +}; + +const Word32 SF_add_fx[N_FEATURES] = +{ + -798595, /*Q23*/ + 0, /*Q31*/ + -37312528, /*Q29*/ + -67914170, /*Q29*/ + -119722213, /*Q29*/ + -220278135, /*Q29*/ + -306929100, /*Q29*/ + 0, /*Q30*/ + -6227703, /*Q31*/ + 537676218, /*Q29*/ + 488713591, /*Q29*/ + -314713729 /*Q30*/ +}; + +const Word32 SF_8k_add_fx[N_FEATURES] = +{ + 0, /*Q23*/ + 219043332, /*Q31*/ + -53687091, /*Q29*/ + -90086939, /*Q29*/ + -127775277, /*Q29*/ + -249430226, /*Q29*/ + 0, /*Q29*/ + 0, /*Q30*/ + 0, /*Q31*/ + 537676218, /*Q29*/ + 481412147, /*Q29*/ + 0 /*Q30*/ +}; + +/* subband_fft.c */ +const complex_16 wnk_table_16[16] = +{ + {32767, 0}, {30274, 12540}, {23170, 23170}, {12540, 30274}, + {32767, 0}, {23170, 23170}, {0, 32767}, {-23170, 23170}, + {32767, 0}, {12540, 30274}, {-23170, 23170}, {-30274, -12540}, + {32767, 0}, {32767, 0}, {32767, 0}, {0, -32768}, +}; + +/* integer square (i*i) */ +const Word16 int_sqr[17] = +{ + 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256 +}; \ No newline at end of file diff --git a/lib_enc/rom_enc.h b/lib_enc/rom_enc.h index 6e39642b4d32df757bb4cd9b1c015ed1e76e10a9..d001ac47189158018e609efc71c83baf82638c78 100644 --- a/lib_enc/rom_enc.h +++ b/lib_enc/rom_enc.h @@ -47,19 +47,24 @@ *----------------------------------------------------------------------------------*/ extern const float sqrt_han_window[]; /* Half of the square root hanning window */ +extern const Word16 sqrt_han_window_fx[]; /* Half of the square root hanning window */ extern const int16_t tipos[]; /* Starting points for pulse position search in Algebraic innovation codebook */ extern const float E_ROM_inter4_1[PIT_UP_SAMP * L_INTERPOL1 + 1]; extern const float E_ROM_inter6_1[PIT_UP_SAMP6 * L_INTERPOL1 + 1]; extern const float E_ROM_inter4_1[PIT_UP_SAMP * L_INTERPOL1 + 1]; extern const float E_ROM_inter6_1[PIT_UP_SAMP6 * L_INTERPOL1 + 1]; extern const float W_HIST[DTX_HIST_SIZE]; /* CNG & DTX - table for calculation of average excitation energy */ +extern const Word16 W_HIST_FX[DTX_HIST_SIZE]; /* CNG & DTX - table for calculation of average excitation energy */ +extern const Word16 W_HIST_S_FX[DTX_HIST_SIZE]; /* CNG & DTX - table for calculation of average excitation energy */ extern const int16_t bwd_start_bin[]; extern const int16_t bwd_end_bin[]; extern const float h_fir[]; /* 2nd order fir filter for wsp, decimation by 2 */ +extern const Word16 H_fir[]; /* 2nd order fir filter for wsp, decimation by 2 */ extern const float preemphCompensation[]; +extern const Word16 preemphCompensation_fx[]; /*----------------------------------------------------------------------------------* * VAD tables @@ -94,13 +99,16 @@ extern const int16_t lsf_unified_fit_model_wb[4][16]; extern const int16_t lsf_unified_fit_model_wbhb[4][16]; extern const float Freq_Weight_Com[160]; +extern const Word32 Freq_Weight_Com_fx[160]; extern const float Freq_Weight_UV[160]; +extern const Word32 Freq_Weight_UV_fx[160]; /*----------------------------------------------------------------------------------* * Speech/music classification *----------------------------------------------------------------------------------*/ extern const float w_spmus[HANG_LEN][HANG_LEN]; +extern const Word16 w_spmus_fx[HANG_LEN][HANG_LEN]; extern const float sm_means[]; extern const float sm_scale[]; @@ -123,16 +131,25 @@ extern const float prec_chol_noise[]; extern const float log_det_chol_noise[]; extern const float m_speech[]; +extern const Word16 m_speech_fx[]; extern const float invV_speech[]; +extern const Word32 invV_speech_fx[]; extern const float lvm_speech[]; +extern const Word32 lvm_speech_fx[]; extern const float m_music[]; +extern const Word16 m_music_fx[]; extern const float invV_music[]; +extern const Word32 invV_music_fx[]; extern const float lvm_music[]; +extern const Word32 lvm_music_fx[]; extern const float m_noise[]; +extern const Word16 m_noise_fx[]; extern const float invV_noise[]; +extern const Word32 invV_noise_fx[]; extern const float lvm_noise[]; +extern const Word32 lvm_noise_fx[]; extern const int16_t mel_fb_start[]; extern const int16_t mel_fb_len[]; @@ -153,6 +170,7 @@ extern const float lpc_weights[]; *----------------------------------------------------------------------------------*/ extern const float hann_window_320[]; +extern const Word16 hann_window_320_fx[]; /*----------------------------------------------------------------------------------* * Huffman coding @@ -174,10 +192,13 @@ extern const int16_t BAND_NUM_TAB[5]; extern const float M_inr[16]; extern const float M_ini[16]; +extern const complex_16 M_in_fix16[16]; extern const float M_r[8]; extern const float M_i[8]; extern const float M_Wr[16]; +extern const Word16 M_Wr_fix16[16]; extern const float M_Wi[16]; +extern const Word16 M_Wi_fix16[16]; extern const int16_t SP_CENTER_BAND_NUM_TAB[5]; extern const float VAD_DELTA1[5]; @@ -187,13 +208,17 @@ extern const int16_t NREGION_INDEX_NB[9]; extern const int16_t NREGION_INDEX_WB[13]; extern const int16_t NREGION_INDEX_SWB[16]; extern const int16_t NREGION_INDEX_FB[16]; +extern const Word16 NREGION_PREOFF[16]; extern const int16_t ENERGY_BAND_NUM[4]; extern const int16_t *REGION_INDEX[4]; extern const float MAX_LF_SNR_TAB[4]; +extern const Word32 MAX_LF_SNR_TAB_FX[4]; extern const float COMVAD_INIT_SNR_DELTA[5]; +extern const Word32 COMVAD_INIT_SNR_DELTA_FX[5]; extern const float LS_MIN_SELENCE_SNR[3]; extern const float LT_MIN_SILENCE_SNR[3]; +extern const Word32 LT_MIN_SILENCE_SNR_FX[4]; /*----------------------------------------------------------------------------------* * Starting line for the noise measurement in TCX. @@ -202,5 +227,22 @@ extern const float LT_MIN_SILENCE_SNR[3]; extern const int16_t startLineWB[N_TCX_STARTLINE_NOISE_WB]; extern const int16_t startLineSWB[N_TCX_STARTLINE_NOISE_SWB]; +//EVS basop +extern const Word32 LS_MIN_SILENCE_SNR[4]; +extern const Word16 SNR_SUB_BAND_NUM[4]; +extern const Word16 BAND_MUL[4]; + +extern const UWord8 E_ROM_tipos[]; /* ACELP indexing */ + +extern const Word16 Weight[86]; +extern const Word16 BAND_SCALE_AJ[5]; +extern const Word16 inv_delta_tab[7]; +extern const Word16 i_t_1[10]; +extern const Word16 i_t_2[23]; +extern const Word16 SF_mult_fx[N_FEATURES]; +extern const Word16 SF_8k_mult_fx[N_FEATURES]; +extern const Word32 SF_add_fx[N_FEATURES]; +extern const Word32 SF_8k_add_fx[N_FEATURES]; +extern const complex_16 wnk_table_16[16]; #endif diff --git a/lib_enc/rst_enc_fx.c b/lib_enc/rst_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..94703a0868c0fbbf508b6d58ac6fc4a0e46b1fd4 --- /dev/null +++ b/lib_enc/rst_enc_fx.c @@ -0,0 +1,78 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#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 */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * CNG_reset_enc() + * + * Reset encoder static variables after a CNG frame + *-------------------------------------------------------------------*/ + +void CNG_reset_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + LPD_state_HANDLE hLPDmem, /* i/o: acelp memories */ + Word16 *pitch_buf, /* o : floating pitch for each subframe */ + Word16 *voice_factors, /* o : voicing factors */ + Word16 VBR_cng_reset_flag +) +{ + TD_CNG_ENC_HANDLE hTdCngEnc = st_fx->hTdCngEnc; + + init_gp_clip_fx( st_fx->clip_var_fx ); + Copy( UVWB_Ave_fx, st_fx->mem_AR_fx, M ); + set16_fx( st_fx->mem_MA_fx, 0, M ); + hLPDmem->mem_w0 = 0; + move16(); + hLPDmem->tilt_code = 0; + move16(); + hLPDmem->gc_threshold = 0; + move16(); + IF( EQ_16(VBR_cng_reset_flag,1)) + { + set16_fx( hLPDmem->mem_syn, 0, M ); + } + set16_fx(hLPDmem->dm_fx.prev_gain_pit, 0, 6); + hLPDmem->dm_fx.prev_gain_code = L_deposit_l(0); + hLPDmem->dm_fx.prev_state = 0; + //PMTE() + move16(); + + /* last good received frame for FEC in ACELP */ + st_fx->clas_fx = UNVOICED_CLAS; + move16(); + + /* reset the pitch buffer in case of FRAME_NO_DATA or SID frames */ + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + set16_fx( pitch_buf, L_SUBFR, NB_SUBFR ); + } + ELSE /* st->L_frame == L_FRAME16k */ + { + set16_fx( pitch_buf, L_SUBFR16k, NB_SUBFR16k ); + } + + set16_fx( voice_factors, 1, NB_SUBFR16k ); + + /* deactivate bass post-filter */ + st_fx->bpf_off_fx = 1; + move16(); + + /* Reset active frame counter */ + if (hTdCngEnc != NULL) + { + hTdCngEnc->act_cnt2 = 0; + move16(); + } + + return; +} diff --git a/lib_enc/scale_enc_fx.c b/lib_enc/scale_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..31ef140c47ca1c228e7372d9bc96dbc8c5d465eb --- /dev/null +++ b/lib_enc/scale_enc_fx.c @@ -0,0 +1,304 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include "options.h" /* Compilation switches */ +#include "cnst.h" /* Common constants */ +#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 */ +#include "stl.h" + +/*-------------------------------------------------------------------* + * Scale_wsp + * + * Find scaling factor for weighted speech input + *-------------------------------------------------------------------*/ +void Scale_wsp( + Word16 *wsp, /* i : Weigthed speech */ + Word16 *old_wsp_max, /* i : Last weigthed speech maximal valu */ + Word16 *shift, /* i/o: Scaling of current frame */ + Word16 *Q_exp, /* i/o: Differential scaling factor */ + Word16 *old_wsp_shift, /* i/o: Last wsp scaling */ + Word16 *old_wsp, /* i/o: Old weighted speech buffer */ + Word16 *mem_decim2, /* i/o: Decimation buffer */ + Word16 *old_wsp12k8, /* i/o: wsp memory @ 12.8 kHz used in pitol2 */ + const Word16 Len_p_look /* i : L_frame + look ahead */ +) +{ + Word16 max, i, tmp; + + /* find maximum value on wsp[] for 12 bits scaling */ + max = 0; + move16(); + FOR (i = 0; i < Len_p_look; i++) + { + tmp = abs_s(wsp[i]); + max = s_max(max,tmp); + } + tmp = *old_wsp_max; + move16(); + tmp = s_max(max, tmp); + *old_wsp_max = max; + move16(); + + *shift = sub(norm_s(tmp), 3); + move16(); + + *shift = s_min(*shift, 0); + move16(); /* shift = 0..-3 */ + + + Scale_sig(wsp, Len_p_look, *shift); + /* scale old_wsp (warning: exp must be Q_new-Q_old) */ + *Q_exp= add(*Q_exp, sub(*shift, *old_wsp_shift)); + move16(); + *old_wsp_shift = *shift; + move16(); + Scale_sig(old_wsp12k8, L_WSP_MEM, *Q_exp); /* Already scaled with premphasis */ + Scale_sig(old_wsp, (L_WSP_MEM - L_INTERPOL)/OPL_DECIM, *Q_exp ); + Scale_sig(mem_decim2, 3, *Q_exp); + + Copy( old_wsp12k8, wsp - L_WSP_MEM, L_WSP_MEM ); /* Now memory and wsp vector have the same scaling */ +} + +/*-------------------------------------------------------------------* + * Preemph_scaled + * + * Find scaled preemphasis vector and its scaling factor + *-------------------------------------------------------------------*/ +void Preemph_scaled( + Word16 new_speech[], /* i : Speech to scale already on 14 bits*/ + Word16 *Q_new, /* o : Scaling factor */ + Word16 *mem_preemph, /* i/o: Preemph memory */ + Word16 *Q_max, /* i/o: Q_new limitation */ + const Word16 Preemph_factor, /* i : Preemphasis factor Q15 */ + const Word16 bits, /* i : Bit to remove from the output to (15-bits)*/ + const Word16 bit1, /* i : Limit the output scaling to ((15-bits)-bit1) bits */ + const Word16 L_Q_mem, /* i : Number of old scaling to take into account */ + const Word16 Lframe, /* i : Frame length */ + const Word16 last_coder_type, /* i : coder_type */ + const Word16 Search_scaling /* i : enable the search of a proper scaling factor*/ +) +{ + Word16 i, tmp_fixed; + Word16 mu, shift, QVal; + Word32 L_tmp, L_maxloc; + Word16 Q_min; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*---------------------------------------------------------------* + * Perform fixed preemphasis through 1 - g z^-1 * + * Scale signal to get maximum of precision in filtering * + *---------------------------------------------------------------*/ + + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + Overflow = 0; + QVal = shl_o(1, sub(15,bits), &Overflow); +#else /* BASOP_NOGLOB */ + QVal = shl(1, sub(15,bits)); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + mu = shr(Preemph_factor, bits); /* Q15 --> Q(15-bits) */ + + IF(EQ_16(Search_scaling,1)) + { + /* get max of new preemphased samples (L_FRAME+L_FILT) */ + + L_tmp = L_mult(new_speech[0], QVal); + L_tmp = L_msu(L_tmp, *mem_preemph, mu); + L_maxloc = L_abs(L_tmp); + + FOR (i = 1; i < Lframe; i++) + { + /* Equivalent to tmp = max((abs(x[i] - mu*x[i-1]),tmp) + * finds the max of preemphasized signal */ + L_tmp = L_mult(new_speech[i], QVal); +#ifdef BASOP_NOGLOB + L_tmp = L_msu_o(L_tmp, new_speech[i - 1], mu, &Overflow); +#else /* BASOP_NOGLOB */ + L_tmp = L_msu(L_tmp, new_speech[i - 1], mu); +#endif /* BASOP_NOGLOB */ + L_tmp = L_abs(L_tmp); + L_maxloc = L_max(L_tmp, L_maxloc); + } + + /* get scaling factor for new and previous samples */ + /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */ + /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */ + tmp_fixed = s_max(extract_h(L_maxloc),1); + + /* output on 14 bits: needed unless the resampling itself removes 1 bit*/ + shift = sub(norm_s(tmp_fixed), add(bits,bit1)); + shift = s_max(shift, 0); + shift = s_min(shift, Q_MAX); + + minimum_fx(Q_max, L_Q_mem, &Q_min); + *Q_new = s_min(shift, Q_min); + move16(); + + IF (tmp_fixed == 0) + { + IF ( NE_16(last_coder_type, UNVOICED)) + { + *Q_new = s_min(*Q_new, 1); + move16(); + } + } + + FOR(i = L_Q_mem-1; i > 0; i--) + { + Q_max[i] = Q_max[i-1]; + move16(); + } + Q_max[i] = shift; + move16(); + } + + /*---------------------------------------------------------------* + * preemphasis with scaling (L_FRAME+L_FILT) + * now do the actual preemphasis, since we have the + * proper scaling factor. + * Done backwards to save storage space + *---------------------------------------------------------------*/ + + tmp_fixed = new_speech[Lframe - 1]; + move16(); + + FOR (i = sub(Lframe,1); i > 0; i--) + { + L_tmp = L_mult(new_speech[i], QVal); +#ifdef BASOP_NOGLOB + L_tmp = L_msu_o(L_tmp, new_speech[i - 1], mu, &Overflow); +#else /* BASOP_NOGLOB */ + L_tmp = L_msu(L_tmp, new_speech[i - 1], mu); +#endif /* BASOP_NOGLOB */ + L_tmp = L_shl(L_tmp, *Q_new); + new_speech[i] = round_fx(L_tmp); + } + + L_tmp = L_mult(new_speech[0], QVal); + L_tmp = L_msu(L_tmp, *mem_preemph, mu); + L_tmp = L_shl(L_tmp, *Q_new); + new_speech[0] = round_fx(L_tmp); + + *mem_preemph = tmp_fixed; + move16(); +} +/*-------------------------------------------------------------------* + * Scale_mem + * + * Rescale memories + *-------------------------------------------------------------------*/ +Word32 Scale_mem_pre_proc( /* o : Min energy scaled */ + Word16 ini_frame_fx, /* i : Frame number */ + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *Q_new, /* i/o: Absolute scaling factor */ + Word16 *old_speech, /* i/o: Speech memory */ + Word16 *mem_wsp, /* i/o: wsp vector memory */ + Word32 *enrO, /* i/o: Enr mem */ + Word32 *bckr, /* i/o: Back ground_fx ener mem */ + Word32 *ave_enr, /* i/o: Ave_enr mem */ + Word32 *ave_enr2, /* i/o: Ave_enr2 mem */ + Word32 *st_fr_bands1, /* i/o: spectrum per critical bands of the previous frame */ + Word32 *st_fr_bands2, /* i/o: spectrum per critical bands 2 frames ago */ + Word32 *st_Bin_E_old +) +{ + Word16 i; + Word32 e_min_scaled; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + e_min_scaled = L_shr_r(L_add(L_shr(E_MIN_FXQ15,sub(14,add(*Q_new,QSCALE))),1),1); + + /* scale previous samples and memory (Q_exp - Q_new - Q_old) */ + /* Scale( x, y, z ) : shift left vector x of size y by z bits ) */ + IF (Q_exp != 0) + { + IF(old_speech != NULL) + { + Scale_sig(old_speech, L_INP_MEM, Q_exp); + } + Scale_sig(mem_wsp, 1, Q_exp); + IF( ini_frame_fx ==0 ) + { + /* Scaling noise vectors if frame ==1*/ + Scale_sig32(enrO, NB_BANDS,*Q_new); + Scale_sig32(bckr, NB_BANDS, *Q_new); + Scale_sig32(ave_enr, NB_BANDS, *Q_new); + Scale_sig32(ave_enr2, NB_BANDS, *Q_new); + Scale_sig32(st_fr_bands1, NB_BANDS, *Q_new); + Scale_sig32(st_fr_bands2, NB_BANDS, *Q_new); + Scale_sig32(st_Bin_E_old, L_FFT/2, *Q_new); + } + ELSE + { + /* Do scaling and valide minimum energy value */ + FOR (i = 0; i < NB_BANDS; i++) + { +#ifdef BASOP_NOGLOB + enrO[i] = L_max(L_shl_o(enrO[i], Q_exp, &Overflow),e_min_scaled); + bckr[i] = L_max(L_shl_o(bckr[i], Q_exp, &Overflow), e_min_scaled); + ave_enr[i] = L_max(L_shl_o(ave_enr[i], Q_exp, &Overflow), e_min_scaled); + ave_enr2[i] = L_max(L_shl_o(ave_enr2[i], Q_exp, &Overflow), e_min_scaled); + st_fr_bands1[i] = L_max(L_shl_o(st_fr_bands1[i], Q_exp, &Overflow), e_min_scaled); + st_fr_bands2[i] = L_max(L_shl_o(st_fr_bands2[i], Q_exp, &Overflow), e_min_scaled); +#else + enrO[i] = L_max(L_shl(enrO[i], Q_exp),e_min_scaled); + bckr[i] = L_max(L_shl(bckr[i], Q_exp), e_min_scaled); + ave_enr[i] = L_max(L_shl(ave_enr[i], Q_exp), e_min_scaled); + ave_enr2[i] = L_max(L_shl(ave_enr2[i], Q_exp), e_min_scaled); + st_fr_bands1[i] = L_max(L_shl(st_fr_bands1[i], Q_exp), e_min_scaled); + st_fr_bands2[i] = L_max(L_shl(st_fr_bands2[i], Q_exp), e_min_scaled); +#endif + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + } + } + } + return e_min_scaled; +} + +void Scale_mem_enc( + Word16 Q_exp, /* i : Diff scaling factor */ + Word16 *old_speech16k, /* i/o: Speech memory */ + Word16 *old_exc, /* i/o: excitation memory */ + Word16 *old_bwe_exc, /* i/o: BWE excitation memory */ + Word16 *mem_w0, /* i/o: target vector memory */ + Word16 *mem_syn, /* i/o: synthesis memory */ + Word16 *mem_syn2, /* i/o: synthesis memory */ + Word16 *mem_deemp_preQ_fx, /*i/o: deemphasis memory for the high rate celp codec */ + Word16 *last_exc_dct_in, + Word16 *old_input_lp +) +{ + /* scale previous samples and memory (Q_exp - Q_new - Q_old) */ + /* Scale( x, y, z ) : shift left vector x of size y by z bits ) */ + IF (Q_exp != 0) + { + Scale_sig(old_speech16k, L_INP_MEM, Q_exp); + Scale_sig(mem_w0, 1, Q_exp); + /* Scaling excitation */ + Scale_sig(old_exc,L_EXC_MEM, Q_exp); + Scale_sig(old_bwe_exc, PIT16k_MAX*2, Q_exp); + Scale_sig(mem_syn, M, Q_exp); + Scale_sig(mem_syn2, M, Q_exp); + Scale_sig(last_exc_dct_in,L_FRAME, Q_exp); + Scale_sig(mem_deemp_preQ_fx, 1, Q_exp); + Scale_sig(old_input_lp, NS2SA(16000, ACELP_LOOK_NS + DELAY_SWB_TBE_16k_NS + DELAY_FIR_RESAMPL_NS), Q_exp); + } + + return; +} + diff --git a/lib_enc/set_impulse_fx.c b/lib_enc/set_impulse_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..adbb356d5f9fb8eb62d0dbd22949eb9d08035a5e --- /dev/null +++ b/lib_enc/set_impulse_fx.c @@ -0,0 +1,383 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include "options.h" +#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 constant + *-----------------------------------------------------------------*/ +#define INPOL 4 /* +- range in samples for impulse position searching */ + +/*-----------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------*/ +static void convolve_tc_fx(const Word16 g[],const Word16 h[],Word16 y[],const Word16 L_1,const Word16 L_2); +static void correlate_tc_fx(const Word16 *x, Word16 *y, const Word16 *h, const Word16 start, const Word16 L_1,const Word16 L_2); +static void convolve_tc2_fx(const Word16 g[],const Word16 h[], Word16 y[], const Word16 pos_max); + +/*---------------------------------------------------------------------------------------* + * Function set_impulse() for TC * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * + * Builds glottal codebook contribution based on glotal impulses positions finding. * + * * + * Returns a position of the glotal impulse center and * + * a number of the glotal impulse shape. * + * * + * |----| |----| xn * + * imp_pos-> || | imp_shape-> | g1 | | * + * | | | | g2 | exc |---| y1 ---- | * + * | | |--------------| |---------| h |-------|gain|-------(-)---> xn2 * + * | || | gn | |---| ---- * + * |----| |----| * + * codebook excitation h_orig gain * + * * + * * + * nominator dd * * + * Searching criterion: maximize ------------- = ---- = ----------------- * + * denominator rr * + * * + * Notice: gain = gain_trans * gain_pit (computed in trans_enc() function) * + * * + *---------------------------------------------------------------------------------------*/ +void set_impulse_fx( + const Word16 xn_fx[], /* i : target signal */ + const Word16 h_orig_fx[], /* i : impulse response of weighted synthesis filter */ + Word16 exc_fx[], /* o : adaptive codebook excitation */ + Word16 yy1_fx[], /* o : filtered adaptive codebook excitation */ + Word16 *imp_shape, /* o : adaptive codebook index */ + Word16 *imp_pos, /* o : position of the glottal impulse center index */ + Word32 *gain_trans_fx, /* o : transition gain Q7 */ + Word16 Q_new /* i : Current scaling */ +) +{ + Word16 i, j, m; + Word16 start1, start2, end1; + Word32 rr_fx[L_SUBFR]; /* criterion: nominator coefficients */ + Word16 dd_fx[L_SUBFR],tmp16; /* criterion: denominator coefficients */ + Word16 gh_fx[L_SUBFR], num, den, exp_num, exp_den; /* convolution of 'g' and 'h' filters */ + Word16 krit_fx, krit_max_fx, gain16; + Word32 Lrr, Ldd, Ltmp,Ltmp1; + const Word16 *pt_Glt; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + krit_max_fx = -32768; + move16(); + + /* main loop */ + /* impulse */ + FOR (m = 0; m < NUM_IMPULSE; m++) + { + /* set searching ranges */ + IF (LT_16(*imp_pos, L_SUBFR-INPOL)) + { + end1 = add(*imp_pos, INPOL); + } + ELSE + { + end1 = L_SUBFR; + move16(); + } + IF (GT_16(*imp_pos, INPOL)) + { + start1 = sub(*imp_pos, INPOL); + } + ELSE + { + start1 = 0; + move16(); + } + IF (GT_16(start1, L_IMPULSE2)) + { + start2 = start1; + move16(); + } + ELSE + { + start2 = L_IMPULSE2; + move16(); + } + + /*-----------------------------------------------------------* + * nominator & DEnominator, gh=convolve(g,h) + *-----------------------------------------------------------*/ + IF (LT_16(start1, L_IMPULSE2)) + { + Lrr = L_deposit_l(0); + Ldd = L_deposit_l(0); + convolve_tc_fx(&Glottal_cdbk_fx[m*L_IMPULSE+L_IMPULSE2-start1], + &h_orig_fx[0], gh_fx, add(L_IMPULSE-L_IMPULSE2, start1), L_SUBFR); + + /* nominator & DEnominator row <0> */ + FOR (i=0; i < L_SUBFR; i++) + { +#ifdef BASOP_NOGLOB + Lrr = L_mac_o(Lrr, gh_fx[i], gh_fx[i], &Overflow); + Ldd = L_mac_o(Ldd, gh_fx[i], xn_fx[i], &Overflow); +#else + Lrr = L_mac(Lrr, gh_fx[i], gh_fx[i]); + Ldd = L_mac(Ldd, gh_fx[i], xn_fx[i]); +#endif + } + rr_fx[start1] = Lrr; + move32(); +#ifdef BASOP_NOGLOB + dd_fx[start1] = round_fx_o(Ldd, &Overflow); +#else + dd_fx[start1] = round_fx(Ldd); +#endif + rr_fx[start1] = L_max(rr_fx[start1], 1); + + FOR (i=add(start1, 1); i */ + FOR (j = L_SUBFR-1; j > 0; j--) + { + /* gh_fx[j] = gh_fx[j-1] + glottal_cdbk[m*L_IMPULSE+L_IMPULSE2-i]*h_orig_fx[j] */ + gh_fx[j] = mac_r(L_deposit_h(gh_fx[j-1]), + Glottal_cdbk_fx[m*L_IMPULSE+L_IMPULSE2-i], h_orig_fx[j]); + move16(); +#ifdef BASOP_NOGLOB + Lrr = L_mac_o(Lrr, gh_fx[j], gh_fx[j], &Overflow); + Ldd = L_mac_o(Ldd, gh_fx[j], xn_fx[j], &Overflow); +#else /* BASOP_NOGLOB */ + Lrr = L_mac(Lrr, gh_fx[j], gh_fx[j]); + Ldd = L_mac(Ldd, gh_fx[j], xn_fx[j]); +#endif /* BASOP_NOGLOB */ + } + + gh_fx[0] = mult_r(Glottal_cdbk_fx[m*L_IMPULSE+L_IMPULSE2-i],h_orig_fx[0]); + move16(); +#ifdef BASOP_NOGLOB + Lrr = L_mac_o(Lrr, gh_fx[0], gh_fx[0], &Overflow); + Ldd = L_mac_o(Ldd, gh_fx[0], xn_fx[0], &Overflow); +#else /* BASOP_NOGLOB */ + Lrr = L_mac(Lrr, gh_fx[0], gh_fx[0]); + Ldd = L_mac(Ldd, gh_fx[0], xn_fx[0]); +#endif + dd_fx[i] = round_fx(Ldd); + rr_fx[i] = L_max(Lrr, 1); + move32(); + /* move rr and dd into rr[i] and dd[i] */ + } + + /* complete convolution(excitation,h_orig) */ + FOR (j=L_SUBFR-1; j > 0; j--) + { + gh_fx[j] = mac_r(L_deposit_h(gh_fx[j-1]), + Glottal_cdbk_fx[m*L_IMPULSE], h_orig_fx[j]); + } + } + ELSE + { + convolve_tc_fx(&Glottal_cdbk_fx[m*L_IMPULSE], h_orig_fx, gh_fx, L_IMPULSE, L_SUBFR); + } + + IF (GE_16(end1, start2)) + { + /* DEnominator row */ + Lrr = L_mult(gh_fx[0], gh_fx[0]); + FOR (j=1; j <= L_IMPULSE2; j++) + { + /*rr[L_SUBFR-1] += gh[j]*gh[j];*/ + Lrr = L_mac(Lrr, gh_fx[j], gh_fx[j]); + } + rr_fx[L_SUBFR-1] = Lrr; + move32(); + /* DEnominator rows */ + FOR (i = L_SUBFR-2; i >= start2; i--) + { + /*rr[i] = rr[i+1] + gh[L_SUBFR+L_IMPULSE2-1-i]*gh[L_SUBFR+L_IMPULSE2-1-i];*/ +#ifdef BASOP_NOGLOB + rr_fx[i] = L_mac_o(rr_fx[i+1], gh_fx[L_SUBFR+L_IMPULSE2-1-i], + gh_fx[L_SUBFR+L_IMPULSE2-1-i], &Overflow); +#else + rr_fx[i] = L_mac(rr_fx[i+1], gh_fx[L_SUBFR+L_IMPULSE2-1-i], + gh_fx[L_SUBFR+L_IMPULSE2-1-i]); +#endif + move32(); + } + /* nominator rows */ + correlate_tc_fx(xn_fx, &dd_fx[L_IMPULSE2], gh_fx, sub(start2, L_IMPULSE2), + L_SUBFR, sub(end1, L_IMPULSE2)); + } + /*------------------------------------------------------------* + * maxim. criterion + *------------------------------------------------------------*/ + FOR (i = start1; i < end1; i++) + { + /* krit = (float)(dd[i]*dd[i])/rr[i] */ + exp_num = sub(norm_s(dd_fx[i]), 1); + num = shl(dd_fx[i], exp_num); + num = mult_r(num, num); + + exp_den = norm_l(rr_fx[i]); + den = extract_h(L_shl(rr_fx[i], exp_den)); + + num = div_s(num,den); +#ifdef BASOP_NOGLOB + krit_fx = shr_o(num, sub(sub(shl_o(exp_num, 1, &Overflow), exp_den), 2), &Overflow); /* Q18 */ +#else + krit_fx = shr(num, sub(sub(shl(exp_num, 1), exp_den), 2)); /* Q18 */ +#endif + + IF (GT_16(krit_fx, krit_max_fx)) + { + krit_max_fx = krit_fx; + move16(); + *imp_pos = i; + move16(); + *imp_shape = m; + move16(); + } + } + } + + /*---------------------------------------------------------------* + * Build the excitation using found codeword + *---------------------------------------------------------------*/ + + set16_fx(exc_fx, 0, L_SUBFR); + set16_fx(yy1_fx, 0, L_SUBFR); + tmp16 = sub(extract_l(L_mac0(L_IMPULSE2, *imp_shape, L_IMPULSE)), *imp_pos); + pt_Glt = &Glottal_cdbk_fx[tmp16]; + move16(); + j = add(*imp_pos, L_IMPULSE2); + FOR (i = sub(*imp_pos, L_IMPULSE2); i <= j; i++) + { + test(); + if (i >= 0 && LT_16(i, L_SUBFR)) + { + exc_fx[i] = pt_Glt[i]; + move16();/*Q13*/ + } + } + + /*---------------------------------------------------------------* + * Form filtered excitation, find gain_trans + *---------------------------------------------------------------*/ + convolve_tc2_fx(exc_fx, h_orig_fx, yy1_fx, *imp_pos); + + /* Find the ACELP correlations and the pitch gain (for current subframe) */ + /**gain_trans = dot_product( xn, yy1, L_SUBFR )/(dot_product( yy1, yy1, L_SUBFR ) + 0.01f);*/ + /* Compute scalar product */ + Ltmp = Dot_product(yy1_fx, yy1_fx, L_SUBFR); + exp_den = norm_l(Ltmp); + den = extract_h(L_shl(Ltmp, exp_den)); + + /* Compute scalar product */ + Ltmp1 = Dot_product(xn_fx, yy1_fx, L_SUBFR); + exp_num = sub(norm_l(Ltmp1), 1); + num = extract_h(L_shl(Ltmp1, exp_num)); + 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 */ + gain16= div_s(num, den); + + i = add(exp_num, sub(Q_new, 1+1+3)); + i = sub(i, exp_den); /* Gain_trans in Q7 */ + gain16 = i_mult2(gain16, tmp16);/* apply sign */ + *gain_trans_fx = L_shr(L_deposit_l(gain16), i); + move32(); + +} +/*-------------------------------------------------------------------* + * convolve_tc_fx: + * + * convolution for different vectors' lengths + *-------------------------------------------------------------------*/ +static void convolve_tc_fx( + const Word16 g[], /* i : input vector Qx */ + const Word16 h[], /* i : impulse response (or second input vector) Q15 */ + Word16 y[], /* o : output vector (result of convolution) 12 bits */ + const Word16 L_1, /* i : vector h size */ + const Word16 L_2 /* i : vector g size */ +) +{ + Word16 i, n, len; + Word32 L_sum; + + FOR (n = 0; n < L_2; n++) + { + len = s_min(add(n,1), L_1); + L_sum = L_mult(g[0], h[n]); + FOR (i = 1; i < len; i++) + { + L_sum = L_mac(L_sum, g[i], h[n - i]); + } + + y[n] = round_fx(L_sum); /* Q12*/ + } +} +/*-------------------------------------------------------------------* + * convolve_tc2_fx: + * + * convolution for one vector with only L_IMPULSE nonzero coefficients + *-------------------------------------------------------------------*/ +static void convolve_tc2_fx( + const Word16 g[], /* i : input vector Qx */ + const Word16 h[], /* i : impulse response (or second input vector) Q15 */ + Word16 y[], /* o : output vector (result of convolution) 12 bits */ + const Word16 pos_max /* o : artificial impulse position */ +) +{ + Word32 temp; + Word16 i, n; + Word16 i_start, i_end, i_end2; + + i_start = sub(pos_max,L_IMPULSE2); + i_start = s_max(i_start, 0); + + i_end = add(pos_max, L_IMPULSE); + i_end = s_min(i_end, L_SUBFR); + + FOR (n = i_start; n < L_SUBFR; n++) + { + temp = L_mult(g[0], h[n]); + i_end2 = s_min(add(n, 1), i_end); + + FOR (i = 1; i < i_end2; i++) + { + temp = L_mac(temp, g[i], h[n-i]); + } + y[n] = round_fx(temp); + } +} +/*-------------------------------------------------------------------* + * correlate_tc: + * + * correlation for different vectors' lengths + *-------------------------------------------------------------------*/ +static void correlate_tc_fx( + const Word16 *x, /* i: target signal */ + Word16 *y, /* o: correlation between x[] and h[] -Q3 */ + const Word16 *h, /* i: impulse response (of weighted synthesis filter) */ + const Word16 start, /* i: index of iterest */ + const Word16 L_1, /* i: vector size */ + const Word16 L_2 /* i: index of interest */ +) +{ + Word16 i, j; + Word32 s; + + FOR (i = start; i < L_2; i++) + { + s = L_deposit_l(0); + FOR (j = i; j < L_1; j++) + { + s = L_mac(s, x[j],h[j-i]); + } + y[i] = round_fx(s); + } +} diff --git a/lib_enc/setmodeindex_fx.c b/lib_enc/setmodeindex_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..b8b900bdc59f0bbd9673964d889136a8ae2ef8e2 --- /dev/null +++ b/lib_enc/setmodeindex_fx.c @@ -0,0 +1,59 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +//#include "prot_fx.h" +#include "cnst.h" +#include "rom_com_fx.h" +#include "rom_enc.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*--------------------------------------------------------------------------- + + function name: SetModeIndex_fx + description: function for configuring the codec between frames - currently bit rate and bandwidth only + must not be called while a frame is encoded - hence mutexes must be used in MT environments + + format: BANDWIDTH*16 + BITRATE (mode index) + + ---------------------------------------------------------------------------*/ + +void SetModeIndex_fx( + Encoder_State_fx *st, + Word32 last_total_brate, + const Word16 last_element_mode, + const Word16 is_mct, + const Word16 shift +) +{ + Word16 ini_frame_loc = st->ini_frame_fx; + + test();test(); + if (EQ_16(st->element_mode, IVAS_CPE_MDCT) && EQ_16(last_element_mode, IVAS_CPE_MDCT) && EQ_16(st->idchan, 1)) + { + st->ini_frame_fx = 0; + move16(); + } + + /* Reconfigure the core coder */ + test();test();test(); + IF( + (NE_32(last_total_brate,st->total_brate_fx) ) || + (NE_16(st->last_bwidth_fx,st->bwidth_fx) ) || + (EQ_16(st->last_codec_mode,MODE1) && EQ_16(st->element_mode, EVS_MONO) ) || + ( (NE_16(st->last_core_fx, TCX_20_CORE) && NE_16(st->last_core_fx, TCX_10_CORE)) && GT_16(st->element_mode, EVS_MONO)) || + (NE_16(st->rf_mode_last,st->rf_mode) ) || + (GT_16(st->element_mode, EVS_MONO) && st->ini_frame_fx == 0) + ) + { + core_coder_mode_switch_fx( st, last_total_brate, is_mct, shift); + } + st->ini_frame_fx = ini_frame_loc; + + return; +} + \ No newline at end of file diff --git a/lib_enc/sig_clas_fx.c b/lib_enc/sig_clas_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..fe9626b8daf3081ab7c750b35e6247d99164fd71 --- /dev/null +++ b/lib_enc/sig_clas_fx.c @@ -0,0 +1,474 @@ +/*==================================================================================== + 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" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ + +#define K_COR_FX 23405 /* Q13 2.857 */ +#define C_COR_FX -10535 /* Q13 -1.286 */ + +#define K_EE_FX 1365 /* Q15 0.04167 */ +#define C_EE_FX 0 + +#define K_ZC_FX -1311 /* Q15 -0.04 */ +#define C_ZC_FX 19661 /* Q13 2.4 */ + +#define K_RELE_FX 1638 /* Q15 0.05 */ +#define C_RELE_FX 14746 /* Q15 0.45 */ + +#define K_PC_FX -2341 /* Q15 -0.07143*/ +#define C_PC_FX 30425 /* Q1 1.857 */ + +#define K_SNR_FX 3541 /* Q15 .1111 */ +#define C_SNR_FX -10921 /* Q15 -0.3333f */ + + +#define THRES_EEN 514206 /* 251.077 => (10^(1/(K_EE*10))) Q11*/ + +/*-------------------------------------------------------------------* + * signal_clas_fx() + * + * classification state machine for FEC + * TC frames selection + *-------------------------------------------------------------------*/ + +Word16 signal_clas_fx( /* o : classification for current frames */ + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16* speech, /* i : pointer to speech signal for E computation */ + const Word32* ee, /* i : lf/hf E ration for 2 half-frames */ + const Word16 relE, /* i : frame relative E to the long term average */ + const Word16 L_look, /* i : look-ahead */ + Word16* clas_mod /* o : class flag for NOOP detection */ +) +{ + Word32 Ltmp; + Word16 mean_voi2, een, corn, zcn, relEn, pcn, fmerit1; + Word16 i, clas, pc, zc, lo, lo2, hi, hi2, exp_ee, frac_ee; + Word16 tmp16, tmpS; + const Word16* pt1; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*----------------------------------------------------------------* + * Calculate average voicing + * Calculate average spectral tilt + * Calculate zero-crossing rate + * Calculate pitch stability + *----------------------------------------------------------------*/ + + /* average voicing on second half-frame and look-ahead */ + Ltmp = L_mult(st->voicing_fx[1], 16384); + mean_voi2 = mac_r(Ltmp, st->voicing_fx[2], 16384); + + /* average spectral tilt in dB */ + lo = L_Extract_lc(ee[0], &hi); + lo2 = L_Extract_lc(ee[1], &hi2); + Ltmp = L_mult(lo, lo2); /* Q5*Q5->Q11 */ + + test(); + test(); + IF(LT_32(Ltmp, 2048)) + { + een = 0; + move16(); + } + ELSE IF(GT_32(Ltmp, THRES_EEN) || hi > 0 || hi2 > 0) + { + een = 512; + move16(); + } + ELSE + { + /* mean_ee2 = 0.5f * 20.0f * (float)log10( tmp ); */ + /* een = K_EE_ENC * mean_ee2 + C_EE_ENC; */ + exp_ee = norm_l(Ltmp); + frac_ee = Log2_norm_lc(L_shl(Ltmp, exp_ee)); + exp_ee = sub(30 - 11, exp_ee); + Ltmp = Mpy_32_16(exp_ee, frac_ee, LG10); /* Ltmp Q14 */ + een = round_fx(L_shl(Ltmp, 16 - 5)); /* Q14 -> Q9 */ + een = mac_r(C_EE_FX, een, K_EE_FX); + } + + /* compute zero crossing rate */ + pt1 = speech + L_look - 1; + tmpS = shr(*pt1, 15); /* sets 'tmpS to -1 if *pt1 < 0 */ + Ltmp = L_deposit_l(0); + FOR(i = 0; i < L_FRAME; i++) + { + tmp16 = add(1, tmpS); + pt1++; + tmpS = shr(*pt1, 15); /* pt1 >=0 ---> 0 OTHERWISE -1 */ + Ltmp = L_msu0(Ltmp, tmpS, tmp16); + } + zc = extract_l(Ltmp); + + /* compute pitch stability */ + pc = add(abs_s(sub(st->pitch_fx[1], st->pitch_fx[0])), abs_s(sub(st->pitch_fx[2], st->pitch_fx[1]))); + st->tdm_pc = pc; + + /*-----------------------------------------------------------------* + * Transform parameters to the range <0:1> + * Compute the merit function + *-----------------------------------------------------------------*/ + + /* corn = K_COR * mean_voi2 + C_COR */ + Ltmp = L_mult(C_COR_FX, 32767); + corn = round_fx(L_shl(L_mac(Ltmp, mean_voi2, K_COR_FX), -4)); /*Q13+Q13*Q15 =>Q13->Q9*/ + /* Limit [0, 1] */ + corn = s_max(corn, 0); + corn = s_min(corn, 512); + + Ltmp = L_mult(C_ZC_FX, 4); /*Q13*Q2 -> Q16*/ + zcn = round_fx(L_shl(L_mac(Ltmp, zc, K_ZC_FX), 16 - 7)); /*Q0*Q15 + Q16*/ + /* Limit [0, 1] */ + zcn = s_max(zcn, 0); + zcn = s_min(zcn, 512); + + Ltmp = L_mult(C_RELE_FX, 256); /*Q15 ->Q24*/ + relEn = round_fx(L_shl(L_mac(Ltmp, relE, K_RELE_FX), 1)); /*relE in Q8 but relEn in Q9*/ + /* Limit [0.5, 1] */ + relEn = s_max(relEn, 256); + relEn = s_min(relEn, 512); + + Ltmp = L_mult(C_PC_FX, 2); /*Q14*Q1 -> Q16*/ + pcn = round_fx(L_shl(L_mac(Ltmp, pc, K_PC_FX), 16 - 7)); /*Q16 + Q0*Q15*/ + /* Limit [0, 1] */ + pcn = s_max(pcn, 0); + pcn = s_min(pcn, 512); + + Ltmp = L_mult(een, 10923); + Ltmp = L_mac(Ltmp, corn, 21845); + Ltmp = L_mac(Ltmp, zcn, 10923); + Ltmp = L_mac(Ltmp, relEn, 10923); + Ltmp = L_mac(Ltmp, pcn, 10923); + +#ifdef BASOP_NOGLOB + fmerit1 = round_fx_o(L_shl_o(Ltmp, 16 - 10 - 1, &Overflow), &Overflow); /* fmerit1 ->Q15 */ +#else + fmerit1 = round_fx(L_shl(Ltmp, 16 - 10 - 1)); /* fmerit1 ->Q15 */ +#endif + + /*-----------------------------------------------------------------* + * FEC classification + *-----------------------------------------------------------------*/ + + st->fmerit_dt = sub(st->prev_fmerit, fmerit1); + st->prev_fmerit = fmerit1; + move16(); + + /* FEC classification */ + test(); + test(); + IF(st->localVAD == 0 || EQ_16(st->coder_type, UNVOICED) || LT_16(relE, -1536)) + { + clas = UNVOICED_CLAS; + *clas_mod = clas; + move16(); + move16(); + } + ELSE + { + SWITCH(st->last_clas_fx) + { + case VOICED_CLAS: + case ONSET: + case VOICED_TRANSITION: + + IF(LT_16(fmerit1, 16056)) /*0.49f*/ + { + clas = UNVOICED_CLAS; + move16(); + } + ELSE IF(LT_16(fmerit1, 21626)) /*0.66*/ + { + clas = VOICED_TRANSITION; + move16(); + } + ELSE + { + clas = VOICED_CLAS; + move16(); + } + IF(LT_16(fmerit1, 14745 /* 0.45f*/)) + { + *clas_mod = UNVOICED_CLAS; + move16(); + } + ELSE IF(LT_16(fmerit1, 21626 /* 0.66f*/)) + { + *clas_mod = VOICED_TRANSITION; + move16(); + } + ELSE + { + *clas_mod = VOICED_CLAS; + move16(); + } + BREAK; + + case UNVOICED_CLAS: + case UNVOICED_TRANSITION: + IF(GT_16(fmerit1, 20643)) /*0.63*/ + { + clas = ONSET; + move16(); + } + ELSE IF(GT_16(fmerit1, 19169)) /*0.585*/ + { + clas = UNVOICED_TRANSITION; + move16(); + } + ELSE + { + clas = UNVOICED_CLAS; + move16(); + } + *clas_mod = clas; + move16(); + + BREAK; + + default: + clas = UNVOICED_CLAS; + *clas_mod = clas; + move16(); + move16(); + BREAK; + } + } +#if 0 + /* set flag for unvoiced class, it will be used in sp/mus classifier */ + * uc_clas = clas; + move16(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if (((EQ_16(*coder_type, UNVOICED)) || + (NE_16(st->input_bwidth_fx, NB) && LT_16(fmerit1, 13435) && GT_16(st->mold_corr_fx, 21299)) || /* WB case */ + (EQ_16(st->input_bwidth_fx, NB) && LT_16(mult_r(fmerit1, 28836), 13435) && GT_16(st->mold_corr_fx, 18022))) && /* NB case */ + GT_16(relE, -3840) && LT_16(st->lt_dec_thres_fx, 768)) /* to compute unvoiced on frame that tends to speech */ + { + *uc_clas = UNVOICED_CLAS; + move16(); + } +#endif + /* Onset classification */ + + /* tc_cnt == -1: frame after TC frame in continuous block of GC/VC frames */ + /* tc_cnt == 0: UC frame */ + /* tc_cnt == 1: onset/transition frame, coded by GC coder type */ + /* tc_cnt == 2: frame after onset/transition frame, coded by TC coder type */ + + if (EQ_16(clas, UNVOICED_CLAS)) + { + st->tc_cnt_fx = 0; + move16(); + } + + test(); + if (GE_16(clas, VOICED_TRANSITION) && st->tc_cnt_fx >= 0) + { + st->tc_cnt_fx = add(st->tc_cnt_fx, 1); + move16(); + } + + if (GT_16(st->tc_cnt_fx, 2)) + { + st->tc_cnt_fx = -1; + move16(); + } + return clas; +} +/*-------------------------------------------------------------------* + * select_TC_fx() + * + * Select TC coder type for appropriate frames which is in general VOICED_TRANSITION, + * VOICED_CLAS or ONSET frames following UNVOICED_CLAS frames + *-------------------------------------------------------------------*/ + +void select_TC_fx( + const Word16 codec_mode, /* i : codec mode */ + const Word16 tc_cnt, /* i : TC frame counter */ + Word16* coder_type, /* i/o: coder type */ + const Word16 localVAD /* i : VAD without hangover */ +) +{ + IF (EQ_16(codec_mode, MODE1)) + { + /*---------------------------------------------------------------------* + * Select TC coder type for appropriate frames which is in general VOICED_TRANSITION, + * VOICED_CLAS or ONSET frames following UNVOICED_CLAS frames + *---------------------------------------------------------------------*/ + + IF (localVAD != 0 && GE_16(tc_cnt, 1)) + { + IF (EQ_16(tc_cnt, 1)) + { + /* onset/transition frame is always coded using GC coder type */ + *coder_type = GENERIC; + move16(); + } + ELSE + { + /* frame after onset/transition frame is coded by TC coder type */ + *coder_type = TRANSITION; + move16(); + } + } + } + + return; +} + +/*-------------------------------------------------------------------* + * coder_type_modif_fx() + * + * Coder type modification + *-------------------------------------------------------------------*/ + +void coder_type_modif_fx( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16 relE /* i : frame relative E to the long term average */ +) +{ + Word16 unmod_coder_type, vbr_generic_ho; + + SC_VBR_ENC_HANDLE hSC_VBR = st->hSC_VBR; + + + IF (st->Opt_SC_VBR_fx) + { + vbr_generic_ho = hSC_VBR->vbr_generic_ho; + move16(); + } + ELSE + { + vbr_generic_ho = -1; + move16(); + } + + IF(EQ_16(st->codec_mode, MODE1)) + { + /*---------------------------------------------------------------------* + * Coder type modification + * + * Prevent UC coder type in certain conditions + * Prevent VC coder type in certain conditions + * Select TC coder type in appropriate frames + *---------------------------------------------------------------------*/ + + /* At higher rates, use GC coding instead of UC coding to improve quality */ + test(); + if( (EQ_16(st->element_mode, EVS_MONO) && GT_32(st->total_brate_fx,ACELP_9k60) && EQ_16(st->coder_type,UNVOICED)) || + (GT_16(st->element_mode, EVS_MONO) && GT_32(st->total_brate_fx, MAX_UNVOICED_BRATE) && EQ_16(st->coder_type, UNVOICED)) ) + { + st->coder_type = GENERIC; + move16(); + } + + /* Prevent UC coding on mixed content at 9.6 kb/s */ + test(); + test(); + if( GE_32(st->total_brate_fx,ACELP_9k60) && EQ_16(st->coder_type,UNVOICED) && st->audio_frame_cnt_fx!=0) + { + st->coder_type = GENERIC; + move16(); + } + + unmod_coder_type = st->coder_type; + move16(); + + /* Enforce GC coder type on inactive signal (this can be later overwritten to INACTIVE) */ + test();test();test();test(); + test();test();test(); + if( st->localVAD == 0 && ( + ( + EQ_16(st->coder_type,UNVOICED) + && ( ( st->Opt_SC_VBR_fx == 0) || ( ( EQ_16(st->Opt_SC_VBR_fx, 1) ) && vbr_generic_ho == 0 && GT_16(st->last_coder_type_fx,UNVOICED) )) ) + || EQ_16(st->coder_type,TRANSITION) || EQ_16(st->coder_type,VOICED) ) + + ) + { + st->coder_type = GENERIC; + move16(); + } + + test(); + test(); + IF(EQ_16(st->Opt_SC_VBR_fx, 1)) + { + if (EQ_16(st->coder_type, GENERIC) && EQ_16(unmod_coder_type, UNVOICED) ) + { + hSC_VBR->vbr_generic_ho = 1; + move16(); + } + + test(); + if (GT_16(st->coder_type, UNVOICED) ) + { + hSC_VBR->vbr_generic_ho = 0; + move16(); + } + }//_DIFF_FLOAT_FIX_ see below +//PMT("Verify if EVS or IVAS is right about last_7k2_coder_type update") + hSC_VBR->last_7k2_coder_type = st->coder_type; + move16(); + test(); + if (st->localVAD == 0 && EQ_16(st->coder_type, UNVOICED)) + { + hSC_VBR->last_7k2_coder_type = GENERIC; + move16(); + } + //} closing bracket here in IVAS float, but not in EVS float. currently affects BE for switching bitrate on Linux 20220929 _DIFF_FLOAT_FIX_ !! + + IF (EQ_16(st->element_mode, EVS_MONO)) + { + /* At higher rates and with 16kHz core, allow only GC and TC coder type */ + test(); test(); test(); + if (GT_32(st->total_brate_fx, ACELP_16k40) && NE_16(st->coder_type, GENERIC) && NE_16(st->coder_type, TRANSITION)) + { + /* onset/transition frame is always coded using GC mode */ + st->coder_type = GENERIC; + move16(); + } + } + ELSE /*IVAS*/ + { + /* At higher bitrates, disable UC and VC coder type; note that IC coder type is classified later */ + if ((GT_32(st->total_brate_fx, MAX_VOICED_BRATE) && EQ_16(st->coder_type, VOICED)) || + (GT_32(st->total_brate_fx, MAX_UNVOICED_BRATE) && EQ_16(st->coder_type, UNVOICED))) + { + st->coder_type = GENERIC; + move16(); + } + + } + + /* Patch for certain low-level signals for which the gain quantizer sometimes goes out of its dynamic range */ + test();test();test(); + if( EQ_16(st->coder_type,VOICED) && EQ_16(st->input_bwidth_fx,NB) && LT_16(relE,-2560) && LE_32(st->total_brate_fx,ACELP_8k00)) + { + st->coder_type = GENERIC; + move16(); + } + } + + return ; +} diff --git a/lib_enc/spec_center_fx.c b/lib_enc/spec_center_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..6b41126b61ffe58e68fd42c86bd168f9e9620b68 --- /dev/null +++ b/lib_enc/spec_center_fx.c @@ -0,0 +1,320 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "basop_util.h" +#include "vad_basop.h" +//#include "prot_fx.h" +#include "rom_enc.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-------------------------------------------------------------------* + * spec_center_fx() + * + * + *-------------------------------------------------------------------*/ + +void spec_center_fx( + Word32* sb_power, /* i : energy of sub-band divided uniformly*/ + Word16* sp_center, /* o : spectral center*/ + const Word32 bw_index, /* i : band width*/ + const Word16 Q_sb_p /* i : the Scaling of sb_power*/ +) +{ + Word16 i; + + Word32 t_sp_center, frame_power; + Word32 t_sp_center_num, frame_power_den; + Word32 sb_power_mlt; + Word32 t_sp_center_nb, frame_power_nb; + Word32 zerop1; + Word32 sb_power_shr[24]; + + Word16 d_t_sp_center; + Word16 Q_t_sp_center, Q_frame_power; + Word16 Q_t_sc,Q_f_p; + Word16 d_t_sp_center_Qtmp; + + + zerop1 = 0; move32(); + t_sp_center = 0; move32(); + frame_power = 0; move32(); + + FOR (i=0; i<10; i++) + { + sb_power_shr[i] = L_shr(sb_power[i],5); + move32(); + } + + FOR(i=0; i<10; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_1[i]); + t_sp_center = L_add(L_shr(sb_power_mlt,6), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power);/*0-9 */ + } + + t_sp_center_nb = t_sp_center; move32(); + frame_power_nb = frame_power; move32(); + + /*+0.1 */ + Q_t_sc = sub(Q_sb_p, 10); + IF (GE_16(Q_t_sc,34)) + { + t_sp_center = L_shr(t_sp_center,sub(Q_t_sc, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_t_sc = 33; + move16(); + } + ELSE + { + Q_t_sc = sub(Q_t_sc, 1); + t_sp_center = L_shr(t_sp_center,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_t_sc)); + } + t_sp_center_num = L_add(t_sp_center, zerop1); + + Q_f_p = sub(Q_sb_p, 5); + IF (GE_16(Q_f_p,34)) + { + frame_power = L_shr(frame_power,sub(Q_f_p, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_f_p = 33; + move16(); + } + ELSE + { + Q_f_p = sub(Q_f_p, 1); + frame_power = L_shr(frame_power,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_f_p)); + } + + frame_power_den = L_add(frame_power, zerop1); + IF (frame_power == 0) + { + frame_power_den = CNT0P1; move32(); + Q_f_p = 34; + move16(); + } + /*div */ + Q_t_sp_center = sub(norm_l(t_sp_center_num), 1); + Q_frame_power = norm_l(frame_power_den); + t_sp_center_num = L_shl(t_sp_center_num,Q_t_sp_center); + frame_power_den = L_shl(frame_power_den,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + + d_t_sp_center_Qtmp = add(Q_t_sc,Q_t_sp_center); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_frame_power); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_f_p); + d_t_sp_center_Qtmp = add(d_t_sp_center_Qtmp,15); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,SP_CENTER_Q); + + d_t_sp_center = shr(d_t_sp_center,d_t_sp_center_Qtmp); + sp_center[0] = add(mult(sp_center[0],0x5999),mult(d_t_sp_center,0x2666)); + move16(); + sp_center[2] = d_t_sp_center; + move16(); + + t_sp_center = 0; move32(); + frame_power = 0; move32(); + IF(EQ_32(bw_index,CLDFBVAD_WB_ID)) + { + FOR (i=10; i<20; i++) + { + sb_power_shr[i] = L_shr(sb_power[i],5); + move32(); + } + + FOR(i=1; i<20; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_2[i-1]); + t_sp_center = L_add(L_shr(sb_power_mlt,8), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power);/*1-19 */ + } + /*+0.1 */ + Q_t_sc = sub(Q_sb_p, 13); + + IF (GE_16(Q_t_sc, 34)) + { + t_sp_center = L_shr(t_sp_center,sub(Q_t_sc, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_t_sc = 33; + move16(); + } + ELSE + { + Q_t_sc = sub(Q_t_sc, 1); + t_sp_center = L_shr(t_sp_center,1); + zerop1 = L_shr(CNT0P1, s_min(31, sub(34, Q_t_sc))); + } + t_sp_center_num = L_add(t_sp_center, zerop1); + + Q_f_p = sub(Q_sb_p, 5); + IF (GE_16(Q_f_p,34)) + { + frame_power = L_shr(frame_power, sub(Q_f_p, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_f_p = 33; + move16(); + } + ELSE + { + Q_f_p = sub(Q_f_p, 1); + frame_power = L_shr(frame_power,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_f_p)); + } + frame_power_den = L_add(frame_power, zerop1); + IF (frame_power == 0) + { + frame_power_den = CNT0P1; move32(); + Q_f_p = 34; + move16(); + } + + /*div */ + Q_t_sp_center = sub(norm_l(t_sp_center_num), 1); + Q_frame_power = norm_l(frame_power_den); + t_sp_center_num = L_shl(t_sp_center_num,Q_t_sp_center); + frame_power_den = L_shl(frame_power_den,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + + d_t_sp_center_Qtmp = add(Q_t_sc,Q_t_sp_center); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_frame_power); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_f_p); + d_t_sp_center_Qtmp = add(d_t_sp_center_Qtmp,15); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,SP_CENTER_Q); + + sp_center[3]= shr(d_t_sp_center,d_t_sp_center_Qtmp); + move16(); + } + ELSE IF(EQ_32(bw_index, CLDFBVAD_SWB_ID)) + { + FOR (i=10; i<24; i++) + { + sb_power_shr[i] = L_shr(sb_power[i],5); + move32(); + } + + FOR(i=1; i<24; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_2[i-1]); + t_sp_center = L_add(L_shr(sb_power_mlt,9), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power);/*1-23 */ + } + + /*+0.1 */ + Q_t_sc = sub(Q_sb_p, 14); + + IF (GE_16(Q_t_sc,34)) + { + t_sp_center = L_shr(t_sp_center, limitScale32(sub(Q_t_sc, 33))); + zerop1 = L_shr(CNT0P1,1); + Q_t_sc = 33; + move16(); + } + ELSE + { + Q_t_sc = sub(Q_t_sc, 1); + t_sp_center = L_shr(t_sp_center,1); + zerop1 = L_shr(CNT0P1, limitScale32(sub(34, Q_t_sc))); + } + t_sp_center_num = L_add(t_sp_center, zerop1); + + Q_f_p = sub(Q_sb_p, 5); + IF (GE_16(Q_f_p,34)) + { + frame_power = L_shr(frame_power,sub(Q_f_p, 33)); + zerop1 = L_shr(CNT0P1,1); + Q_f_p = 33; + move16(); + } + ELSE + { + Q_f_p = sub(Q_f_p, 1); + frame_power = L_shr(frame_power,1); + zerop1 = L_shr(CNT0P1, sub(34, Q_f_p)); + } + frame_power_den = L_add(frame_power, zerop1); + IF (frame_power == 0) + { + frame_power_den = CNT0P1; move32(); + Q_f_p = 34; + move16(); + } + + /*div*/ + Q_t_sp_center=sub(norm_l(t_sp_center_num), 1); + Q_frame_power=norm_l(frame_power_den); + t_sp_center_num = L_shl(t_sp_center_num,Q_t_sp_center); + frame_power_den = L_shl(frame_power_den,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + + d_t_sp_center_Qtmp = add(Q_t_sc,Q_t_sp_center); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_frame_power); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,Q_f_p); + d_t_sp_center_Qtmp = add(d_t_sp_center_Qtmp,15); + d_t_sp_center_Qtmp = sub(d_t_sp_center_Qtmp,SP_CENTER_Q); + sp_center[3]= shr(d_t_sp_center,d_t_sp_center_Qtmp); + move16(); + } + ELSE + { + t_sp_center = t_sp_center_nb; move32(); + frame_power = frame_power_nb; move32(); + + IF (frame_power==0) + { + d_t_sp_center = 0; + move16(); + } + ELSE + { + /*div*/ + Q_t_sp_center = sub(norm_l(t_sp_center), 1); + Q_frame_power = norm_l(frame_power); + t_sp_center_num = L_shl(t_sp_center,Q_t_sp_center); + frame_power_den = L_shl(frame_power,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + d_t_sp_center = shr(d_t_sp_center,sub(add(sub(Q_t_sp_center,Q_frame_power),10),SP_CENTER_Q)); + } + + sp_center[0] = add(mult(sp_center[0], 0x5999), mult(d_t_sp_center, 0x2666)); + sp_center[2] = d_t_sp_center; + move16(); + move16(); + + t_sp_center = 0; move32(); + frame_power = 0; move32(); + FOR(i=1; i<10; i++) + { + sb_power_mlt = Mpy_32_16_1(sb_power[i],i_t_1[i-1]); + t_sp_center = L_add(L_shr(sb_power_mlt,6), t_sp_center); + frame_power = L_add(sb_power_shr[i], frame_power); /*1-9 */ + } + IF (frame_power==0) + { + sp_center[3] = 0; + move16(); + } + ELSE + { + /*div */ + Q_t_sp_center = sub(norm_l(t_sp_center), 1); + Q_frame_power = norm_l(frame_power); + t_sp_center_num = L_shl(t_sp_center,Q_t_sp_center); + frame_power_den = L_shl(frame_power,Q_frame_power); + + d_t_sp_center = div_l(t_sp_center_num,extract_h(frame_power_den)); + sp_center[3] = shr(d_t_sp_center,sub(add(sub(Q_t_sp_center, Q_frame_power), 10),SP_CENTER_Q)); + move16(); + } + } + +} diff --git a/lib_enc/spec_flatness_fx.c b/lib_enc/spec_flatness_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..2d07bc15f2df98849a6aafe81bb5796b73be523d --- /dev/null +++ b/lib_enc/spec_flatness_fx.c @@ -0,0 +1,325 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include +#include "options.h" +#include "basop_util.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 */ + +/*-------------------------------------------------------------------* + * spec_flatness_fx() + * + * + *-------------------------------------------------------------------*/ + void spec_flatness_fx( + Word32 *spec_amp, /* i : spectral amplitude*/ + Word32 smooth_spec_amp[], /* i : smoothed spectral amplitude*/ + Word16 sSFM[ ] /* o : spectral flatness rate*/ +) +{ + Word32 i; + Word32 *smooth_spec_amp32; + Word32 prods,prods_Exp; + Word32 sums,prods_ExpM; + Word32 zerop1; + + Word16 smooth_spec_amp16; + Word16 Qnorm_prods,Qnorm_sums; + Word16 SFM; + Word16 prods_s,prods_Exps; + Word16 prods_leadingzero,prods_Expleadingzero; + + Word16 leadingzero_prod, leadingzero_spec_amp; + Word16 prods_Q_last,prods_ExpQ; + Word16 SFM_Qtmp; + Word16 prods_Q; + + + smooth_spec_amp32 = smooth_spec_amp; + zerop1 = 0; + move32(); + prods_Q = 0; + move16(); + FOR(i=MIN_AMP_ID; i<=MAX_AMP_ID; i++) + { + smooth_spec_amp32[i-MIN_AMP_ID] = L_add(MUL_F(smooth_spec_amp32[i-MIN_AMP_ID],0x5999),MUL_F(spec_amp[i],0x2666)); + move32(); + } + /*sSFM1*/ + sums = 0; + move32(); + prods = 1; + move32(); + prods_Q = 0; + move16(); + + + FOR(i=(5-MIN_AMP_ID); i<(20-MIN_AMP_ID); i++) + { + sums = L_add(sums, smooth_spec_amp32[i]); + leadingzero_spec_amp = norm_l(smooth_spec_amp32[i]); + smooth_spec_amp16 = extract_h(L_shl(smooth_spec_amp32[i],leadingzero_spec_amp)); + leadingzero_prod = norm_l(prods); + prods = L_shl(prods,leadingzero_prod); + prods_s = extract_h(prods); + prods = L_mult(prods_s, smooth_spec_amp16); + prods_Q = add(add(prods_Q, leadingzero_spec_amp),leadingzero_prod); + } + prods_Q = sub(prods_Q, 255); + + prods_Q_last = prods_Q; + move16(); + prods_ExpM = L_mult(prods_Q_last,-2184); + + prods = VAD_Pow(prods,0x08888888,0,31,&prods_Q); + prods_Exp = VAD_Pow2(prods_ExpM,16, &prods_ExpQ); + + prods_leadingzero = norm_l(prods); + prods_Expleadingzero = norm_l(prods_Exp); + prods_s = extract_h(L_shl(prods,prods_leadingzero)); + prods_Exps = extract_h(L_shl(prods_Exp,prods_Expleadingzero)); + + prods = L_mult(prods_s, prods_Exps); + prods_Q = add(prods_Q, prods_leadingzero); + prods_Q = add(prods_Q, prods_ExpQ); + prods_Q = add(prods_Q, prods_Expleadingzero); + prods_Q = sub(prods_Q, 31); + + prods = L_max(prods, 0); + + if(prods <= 0) + { + prods_Q = 34; + move16(); + } + sums = MUL_F(sums, 0x0888); + + /*+0.1 */ + IF (GE_16(prods_Q, 34)) + { + prods = L_shr(prods, sub(prods_Q, 33)); + zerop1 = L_shr(CNT0P1, 1); + prods_Q = 33; + move16(); + } + ELSE + { + prods_Q = sub(prods_Q, 1); + prods = L_shr(prods, 1); + zerop1 = L_shr(CNT0P1, sub(34, prods_Q)); + } + prods = L_add(prods, zerop1); + + zerop1 = L_shr(CNT0P1, 20); + sums = L_add(sums, zerop1); + + /*div*/ + Qnorm_prods = sub(norm_l(prods), 1); + Qnorm_sums = norm_l(sums); + prods = L_shl(prods,Qnorm_prods); + sums = L_shl(sums,Qnorm_sums); + + SFM = div_l(prods, extract_h(sums)); + + SFM_Qtmp = add(prods_Q, Qnorm_prods); + SFM_Qtmp = sub(SFM_Qtmp, Qnorm_sums); + SFM_Qtmp = add(SFM_Qtmp, 15); + SFM_Qtmp = sub(SFM_Qtmp, SPEC_AMP_Q); + SFM_Qtmp = sub(SFM_Qtmp, SFM_Q); + + sSFM[0] = add(mult(sSFM[0], 0x6ccc), shr(mult(SFM, 0x1333), SFM_Qtmp)); + move16(); + + /*sSFM2*/ + sums = 0; + move32(); + prods = 1; + move32(); + prods_Q = 0; + move16(); + + FOR(i=(20-MIN_AMP_ID); i<(40-MIN_AMP_ID); i++) + { + sums = L_add(sums, smooth_spec_amp32[i]); + leadingzero_spec_amp = norm_l(smooth_spec_amp32[i]); + smooth_spec_amp16 = extract_h(L_shl(smooth_spec_amp32[i],leadingzero_spec_amp)); + leadingzero_prod = norm_l(prods); + prods = L_shl(prods,leadingzero_prod); + prods_s = extract_h(prods); + prods = L_mult(prods_s, smooth_spec_amp16); + prods_Q = add(add(prods_Q, leadingzero_spec_amp),leadingzero_prod); + } + prods_Q = sub(prods_Q, 340); + + prods_Q_last = prods_Q; + move16(); + prods_ExpM = L_mult(prods_Q_last,-1638); + + prods = VAD_Pow(prods,0x06666666,0,31,&prods_Q); + prods_Exp = VAD_Pow2(prods_ExpM,16, &prods_ExpQ); + + prods_leadingzero = norm_l(prods); + prods_Expleadingzero = norm_l(prods_Exp); + prods_s = extract_h(L_shl(prods,prods_leadingzero)); + prods_Exps = extract_h(L_shl(prods_Exp,prods_Expleadingzero)); + + prods = L_mult(prods_s, prods_Exps); + prods_Q = add(prods_Q, prods_leadingzero); + prods_Q = add(prods_Q, prods_ExpQ); + prods_Q = add(prods_Q, prods_Expleadingzero); + prods_Q = sub(prods_Q, 31); + + prods = L_max(prods, 0); + + if(prods<=0) + { + prods_Q = 34; + move16(); + } + sums = MUL_F(sums, 0x0666); + + /*+0.1 */ + IF (GE_16(prods_Q, 34)) + { + prods = L_shr(prods,sub(prods_Q, 33)); + zerop1 = L_shr(CNT0P1,1); + prods_Q = 33; + move16(); + } + ELSE + { + prods_Q = sub(prods_Q,1); + prods = L_shr(prods,1); + zerop1 = L_shr(CNT0P1, sub(34, prods_Q)); + } + prods = L_add(prods, zerop1); + + zerop1 = L_shr(CNT0P1, 20); + sums = L_add(sums, zerop1); + + /*div*/ + Qnorm_prods=sub(norm_l(prods), 1); + Qnorm_sums=norm_l(sums); + prods = L_shl(prods, Qnorm_prods); + sums = L_shl(sums, Qnorm_sums); + + SFM = div_l(prods, extract_h(sums)); + + SFM_Qtmp = add(prods_Q, Qnorm_prods); + SFM_Qtmp = sub(SFM_Qtmp, Qnorm_sums); + SFM_Qtmp = add(SFM_Qtmp, 15); + SFM_Qtmp = sub(SFM_Qtmp, SPEC_AMP_Q); + SFM_Qtmp = sub(SFM_Qtmp, SFM_Q); + + sSFM[1] = add(mult(sSFM[1],0x6ccc),shr(mult(SFM,0x1333),SFM_Qtmp)); + move16(); + /*sSFM3*/ + sums = 0; + move32(); + prods =1; + move32(); + prods_Q = 0; + move16(); + + FOR(i=(40-MIN_AMP_ID); i<=(MAX_AMP_ID-MIN_AMP_ID); i++) + { + sums = L_add(sums, smooth_spec_amp32[i]); + leadingzero_spec_amp = norm_l(smooth_spec_amp32[i]); + smooth_spec_amp16 = extract_h(L_shl(smooth_spec_amp32[i],leadingzero_spec_amp)); + leadingzero_prod = norm_l(prods); + prods = L_shl(prods,leadingzero_prod); + prods_s = extract_h(prods); + prods = L_mult(prods_s, smooth_spec_amp16); + prods_Q = add(add(prods_Q, leadingzero_spec_amp),leadingzero_prod); + } + prods_Q = sub(prods_Q, 425); + + prods_Q_last = prods_Q; + move16(); + prods_ExpM = L_mult(prods_Q_last,-1310); + + prods = VAD_Pow(prods,0x051eb851,0,31,&prods_Q); + prods_Exp = VAD_Pow2(prods_ExpM,16, &prods_ExpQ); + + prods_leadingzero = norm_l(prods); + prods_Expleadingzero = norm_l(prods_Exp); + prods_s = extract_h(L_shl(prods,prods_leadingzero)); + prods_Exps = extract_h(L_shl(prods_Exp,prods_Expleadingzero)); + + prods = L_mult(prods_s, prods_Exps); + prods_Q = add(prods_Q, prods_leadingzero); + prods_Q = add(prods_Q, prods_ExpQ); + prods_Q = add(prods_Q, prods_Expleadingzero); + prods_Q = sub(prods_Q, 31); + + prods = L_max(prods, 0); + if(prods <= 0) + { + prods_Q = 34; + move16(); + } + + sums = MUL_F(sums, 0x051e); + + /*+0.1 */ + IF (GE_16(prods_Q, 34)) + { + prods = L_shr(prods,sub(prods_Q, 33)); + zerop1 = L_shr(CNT0P1,1); + prods_Q = 33; + move16(); + } + ELSE + { + prods_Q = sub(prods_Q, 1); + prods = L_shr(prods,1); + zerop1 = L_shr(CNT0P1, sub(34, prods_Q)); + } + prods = L_add(prods, zerop1); + + zerop1 = L_shr(CNT0P1, 20); + sums = L_add(sums, zerop1); + + /*div*/ + Qnorm_prods = sub(norm_l(prods), 1); + Qnorm_sums = norm_l(sums); + prods = L_shl(prods,Qnorm_prods); + sums = L_shl(sums,Qnorm_sums); + + SFM = div_l(prods,extract_h(sums)); + + SFM_Qtmp = add(prods_Q, Qnorm_prods); + SFM_Qtmp = sub(SFM_Qtmp, Qnorm_sums); + SFM_Qtmp = add(SFM_Qtmp, 15); + SFM_Qtmp = sub(SFM_Qtmp, SPEC_AMP_Q); + SFM_Qtmp = sub(SFM_Qtmp, SFM_Q); + + sSFM[2] = add(mult(sSFM[2],0x6ccc),shr(mult(SFM,0x1333),SFM_Qtmp)); + move16(); +} + + + + + + + + + + + + + + + + + + + diff --git a/lib_enc/speech_music_classif_fx.c b/lib_enc/speech_music_classif_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..57145de953399d68608b1dfa656d21249777ac8a --- /dev/null +++ b/lib_enc/speech_music_classif_fx.c @@ -0,0 +1,4063 @@ +/*==================================================================================== + 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_enc.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "stl.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*---------------------------------------------------------------------* + * Local constants + *---------------------------------------------------------------------*/ +#define ATT_NSEG 32 +#define ATT_SEG_LEN (L_FRAME/ATT_NSEG) +#define ATT_3LSUB_POS (3 * ATT_NSEG / NB_SUBFR) +#define ATT_3LSUB_POS_16k 26 /* (short)((4.0f * ATT_NSEG / (float)NB_SUBFR16k) + 0.5f) */ + +#define LOG_PROB_CONST 11292 /*0.5f * N_FEATURES * LOG_PI2 in Q10 */ + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static Word16 sp_mus_classif_gmm_fx( Encoder_State_fx *st_fx, const Word16 localVAD_HE_SAD, const Word16 lsp_new[M], const Word16 cor_map_sum, const Word32 epsP[M+1], const Word32 PS[], + Word16 non_sta, Word16 relE, Word16 *voi_fv, Word16 *cor_map_sum_fv, Word16 *LPCErr, Word16 Q_esp + , Word16 *high_lpn_flag_ptr); + + + +static void sp_mus_classif_2nd_fx(Encoder_State_fx* st, const Word16 Etot, Word16* attack_flag, const Word16* inp, const Word16 Qx); + +static void music_mixed_classif_improv_fx( Encoder_State_fx *st, const Word16 *new_inp, const Word32 *epsP, Word16 Q_epsP, Word16 etot, Word16 old_cor,Word16 cor_map_sum ); + +static void tonal_context_improv_fx( Encoder_State_fx *st_fx, const Word32 PS[], const Word16 voi_fv, const Word16 cor_map_sum_fv, const Word16 LPCErr, const Word16 Qx ); + +static void var_cor_calc_fx( const Word16 old_corr, Word16 *mold_corr, Word16 var_cor_t[], Word16 *high_stable_cor ); + +static Word16 attack_det_fx(const Word16* inp, const Word16 Qx, const Word16 last_clas, const Word16 localVAD, const Word16 coder_type, + const Word32 total_brate +#ifdef IVAS_CODE + , const Word16 element_mode, const Word16 clas, Word32 finc_prev[], Word32* lt_finc, Word16* last_strong_attack +#endif + ); + +static void order_spectrum_fx( Word16 *vec, Word16 len ); + +static void detect_sparseness_fx( Encoder_State_fx *st_fx, const Word16 localVAD_HE_SAD, const Word16 voi_fv ); +/*---------------------------------------------------------------------* + * speech_music_clas_init_fx() + * + * Initialization of speech/music classifier + *---------------------------------------------------------------------*/ + +void speech_music_clas_init_fx( + SP_MUS_CLAS_HANDLE hSpMusClas /* i/o: speech/music classifier handle */ +) +{ + int16_t i; + + + hSpMusClas->inact_cnt = 0; + move16(); + set16_fx(hSpMusClas->past_dec, 0, HANG_LEN - 1); + set16_fx(hSpMusClas->past_dlp_fx, 0, HANG_LEN - 1); + set16_fx(hSpMusClas->past_log_enr_fx, -1448, NB_BANDS_SPMUS); /* log(E_MIN) in Q8 */ + + hSpMusClas->sp_mus_state = -8; + move16(); + hSpMusClas->wdrop_fx = 0; + move16(); + hSpMusClas->wdlp_0_95_sp_fx = 0; + move16(); + set16_fx(hSpMusClas->last_lsp_fx, 0, M_LSP_SPMUS); + hSpMusClas->last_cor_map_sum_fx = 0; + move16(); + hSpMusClas->last_non_sta_fx = 0; + move16(); + set32_fx(hSpMusClas->past_PS_fx, 0, HIGHEST_FBIN - LOWEST_FBIN); + hSpMusClas->past_ps_diff_fx = 0; + move16(); + hSpMusClas->past_epsP2_fx = 1024; + move16(); + + + hSpMusClas->gsc_thres_fx[0] = TH_0_MIN_FX; + move16(); + hSpMusClas->gsc_thres_fx[1] = TH_1_MIN_FX; + move16(); + hSpMusClas->gsc_thres_fx[2] = TH_2_MIN_FX; + move16(); + hSpMusClas->gsc_thres_fx[3] = TH_3_MIN_FX; + move16(); + set16_fx(hSpMusClas->gsc_lt_diff_etot_fx, 0, 40); + hSpMusClas->gsc_mem_etot_fx = 0; + move16(); + hSpMusClas->gsc_last_music_flag = 0; + move16(); + hSpMusClas->gsc_nb_thr_1 = 0; + move16(); + hSpMusClas->gsc_nb_thr_3 = 0; + move16(); + hSpMusClas->mold_corr_fx = 29491; + move16(); + hSpMusClas->mean_avr_dyn_fx = 64; + move16();/*Q7 */ + hSpMusClas->last_sw_dyn_fx = 2560; + move16(); + /* speech/music classifier improvement */ + FOR(i = 0; i < BUF_LEN; i++) + { + hSpMusClas->buf_flux_fx[i] = -12800; + move16(); /*-100.0 in Q7 */ + hSpMusClas->buf_pkh_fx[i] = 0; + move16(); + hSpMusClas->buf_epsP_tilt_fx[i] = 0; + move16(); + hSpMusClas->buf_cor_map_sum_fx[i] = 0; + move16(); + hSpMusClas->buf_Ntonal_fx[i] = 0; + move16(); + hSpMusClas->buf_Ntonal2_fx[i] = 0; + move16(); + hSpMusClas->buf_Ntonal_lf_fx[i] = 0; + move16(); + } + + set16_fx(hSpMusClas->lpe_buf_fx, 0, HANG_LEN_INIT); + set16_fx(hSpMusClas->voicing_buf_fx, 0, HANG_LEN_INIT); + hSpMusClas->gsc_hangover = 0; + move16(); + set16_fx(hSpMusClas->sparse_buf_fx, 0, HANG_LEN_INIT); + set16_fx(hSpMusClas->hf_spar_buf_fx, 0, HANG_LEN_INIT); + hSpMusClas->LT_sparse_fx = 0; + move16(); + hSpMusClas->gsc_cnt = 0; + move16(); + set16_fx(hSpMusClas->old_Bin_E_fx, 0, 3 * N_OLD_BIN_E); + set16_fx(hSpMusClas->buf_etot_fx, 0, 4); + set16_fx(hSpMusClas->buf_dlp_fx, 0, 10); + + hSpMusClas->UV_cnt1 = 300; + move16(); + hSpMusClas->LT_UV_cnt1_fx = 16000; + move16(); /*250.0f in Q6 */ + hSpMusClas->onset_cnt = 0; + move16(); + hSpMusClas->attack_hangover = 0; + move16(); + hSpMusClas->dec_mov_fx = 0; + move16(); + hSpMusClas->dec_mov1_fx = 0; + move16(); + hSpMusClas->mov_log_max_spl_fx = 25600; + move16(); /*200.0 in Q7 */ + hSpMusClas->old_lt_diff_fx[0] = 0; + move16(); + hSpMusClas->old_lt_diff_fx[1] = 0; + move16(); + + /* GSC - pitch excitation parameters */ + hSpMusClas->high_stable_cor = 0; + move16(); + set16_fx(hSpMusClas->var_cor_t_fx, 0, VAR_COR_LEN); + + hSpMusClas->lps_fx = 0; + move16(); + hSpMusClas->lpm_fx = 0; + move16(); + hSpMusClas->lt_dec_thres_fx = 5120; + move16(); /*10 in Q9 */ + hSpMusClas->ener_RAT_fx = 0; + + /* speech/music classification */ + set16_fx(hSpMusClas->lt_old_mode, 1, 3); + hSpMusClas->lt_voicing = 16384/*0.5f Q15*/; + hSpMusClas->lt_corr = 16384/*0.5f Q15*/; + hSpMusClas->lt_tonality = 0; + move32(); + set16_fx(hSpMusClas->lt_corr_pitch, 0, 3); + hSpMusClas->lt_hangover = 0; + move16(); + hSpMusClas->lowrate_pitchGain = 0; + move16(); + + + hSpMusClas->lt_music_hangover = 0; + move16(); + set16_fx(hSpMusClas->tonality2_buf_fx, 0, HANG_LEN_INIT); + set16_fx(hSpMusClas->tonality3_buf_fx, 0, HANG_LEN_INIT); + set16_fx(hSpMusClas->LPCErr_buf_fx, 0, HANG_LEN_INIT); + hSpMusClas->lt_music_state = 0; + move16(); + hSpMusClas->lt_speech_state = 0; + move16(); + hSpMusClas->lt_speech_hangover = 0; + move16(); + + +#if 0 /*IVAS_CODE*/ + set_f(hSpMusClas->FV_st, 0.0f, N_SMC_FEATURES); //?? + for (i = 0; i < N_SMC_FEATURES; i++) + { + hSpMusClas->prev_FV[i] = 0.5f * hout_intervals[2 * i] + 0.5f * hout_intervals[2 * i + 1]; + } + hSpMusClas->past_epsP = 0; + hSpMusClas->wrise = 0.0f; + hSpMusClas->wdlp_xtalk = 0.0f; + //float past_dlp_mean_ST[HANG_LEN - 1]; /* Speech/music classifier - buffer of past non-binary decisions (with ST smoothing) */ + hSpMusClas->dlp_mean_ST = 0.0f; + hSpMusClas->flag_spitch_cnt = 0; + hSpMusClas->dlp_mean_LT = 0.0f; + hSpMusClas->dlp_var_LT = 0.0f; + hSpMusClas->relE_attack_cnt = 0; + hSpMusClas->prev_relE = 0.0f; + hSpMusClas->prev_Etot = 0.0f; + hSpMusClas->prev_vad = 0; + hSpMusClas->vad_0_1_cnt = 0; + hSpMusClas->relE_attack_sum = 0; + + set_f(hSpMusClas->finc_prev, 0.0f, ATT_NSEG); + hSpMusClas->lt_finc = 0.0f; + hSpMusClas->last_strong_attack = 0; + set_f(hSpMusClas->tod_lt_Bin_E, 0.0f, TOD_NSPEC); + set_f(hSpMusClas->tod_S_map_lt, 0.0f, TOD_NSPEC); + hSpMusClas->tod_thr_lt = TOD_THR_MASS; + hSpMusClas->tod_weight = 0.0f; + hSpMusClas->tod_S_mass_prev = 0.0f; + hSpMusClas->tod_S_mass_lt = 0.0f; + hSpMusClas->tdm_lt_Etot = 0.01f; + hSpMusClas->lpn = 0.0f; +#endif + + + return; +} + +/*---------------------------------------------------------------------* + * speech_music_classif() + * + * Speech/music classification + * + * The following technologies are used based on the outcome of the sp/mus classifier + * sp_aud_decision1 sp_aud_decision2 + * 0 0 use ACELP (+TD BWE) + * 1 0 use ACELP (+FD BWE) or HQ/LR-MDCT depending on bitrate + * 1 1 use GSC (+FD BWE) or HQ/LR-MDCT depending on bitrate + * + * 0 1 exceptionally use GSC (+FD BWE) instead of LR-MDCT at 13.2 kbps (WB/SWB) for sparse spectra + *---------------------------------------------------------------------*/ + +void speech_music_classif_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 *new_inp, /* i : new input signal */ + const Word16 *inp, /* i : input signal to locate attach position */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const Word16 lsp_new[M], /* i : LSPs in current frame Q15 */ + const Word16 cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.)Q8*/ + const Word32 epsP[M+1], /* i : LP prediciton error Q_esp*/ + const Word32 PS[], /* i : energy spectrum Q_new+QSCALE*/ + const Word16 Etot, /* i : total frame energy Q8 */ + const Word16 old_cor, /* i : max correlation from previous frame Q15 */ + Word16 *attack_flag, /* o : flag to indicate if attack is to be treated by TC or GSC */ + Word16 non_sta, /* i : unbound non-stationarity for sp/mus classifier */ + Word16 relE, /* i : relative frame energy */ + Word16 Q_esp, /* i : scaling of esP */ + Word16 Q_inp, /* i : scaling of input */ + Word16 *high_lpn_flag_ptr, /* o : noise log prob flag for NOISE_EST */ + Word16 flag_spitch /* i : flag to indicate very short stable pitch */ +) +{ + Word16 voi_fv, cor_map_sum_fv, LPCErr; + GSC_ENC_HANDLE hGSCEnc = st->hGSCEnc; + + /* 1st stage speech/music classifier based on the GMM model */ + st->sp_aud_decision1 = sp_mus_classif_gmm_fx( st, localVAD_HE_SAD, lsp_new, cor_map_sum, + epsP, PS, non_sta, relE, &voi_fv, &cor_map_sum_fv, &LPCErr, Q_esp, high_lpn_flag_ptr ); + + test(); + IF ( EQ_16( st->codec_mode, MODE1) || EQ_32(st->sr_core, INT_FS_12k8)) + { + + + /* Improvement of the 1st stage decision on mixed/music content */ + test(); + IF ( st->Opt_SC_VBR_fx == 0 && NE_32(st->total_brate_fx, ACELP_24k40)) + { + music_mixed_classif_improv_fx( st, new_inp, epsP, Q_esp, Etot, old_cor, cor_map_sum ); + } + + st->sp_aud_decision0 = st->sp_aud_decision1; + + + /* 2nd stage speech/music classifier (rewrite music to speech in onsets) */ + st->sp_aud_decision2 = st->sp_aud_decision1; + move16(); + + IF ( GT_16(st->bwidth_fx,NB)) + { + sp_mus_classif_2nd_fx( st, Etot, attack_flag, inp, Q_inp-1); + + /* avoid switch to AUDIO/MUSIC class for very short stable high st->pitch_fx + and/or stable pitch with high correlation at low bitrates*/ + test(); + test(); + IF ( flag_spitch && EQ_16(st->bwidth_fx,WB) && LT_32(st->total_brate_fx,ACELP_13k20)) + { + st->sp_aud_decision2 = 0; + move16(); + } + } + + + + /* Context-based improvement of 1st and 2nd stage decision on stable tonal signals */ + test(); + IF ( st->Opt_SC_VBR_fx == 0 && NE_32(st->total_brate_fx, ACELP_24k40)) + { + tonal_context_improv_fx( st, PS, voi_fv, cor_map_sum_fv, LPCErr, Q_inp + QSCALE -2 ); + } + + /* Avoid using LR-MDCT on sparse spectra, use GSC instead at 13.2 kbps (WB/SWB) */ + test(); + test(); + test(); + test(); + IF ( !st->Opt_SC_VBR_fx && EQ_32(st->total_brate_fx, ACELP_13k20) && EQ_16(st->vad_flag,1)&& + ( EQ_16(st->bwidth_fx, WB) || EQ_16(st->bwidth_fx, SWB)) ) + { + detect_sparseness_fx( st, localVAD_HE_SAD, voi_fv ); + } + + /* override speech/music classification to ACELP when background noise level reaches certain level */ + /* this is a patch against mis-classifications during active noisy speech segments */ + IF ( GT_16(st->lp_noise_fx, 3072)) + { + st->sp_aud_decision1 = 0; + move16(); + st->sp_aud_decision2 = 0; + move16(); + } + + + /* select GSC on SWB noisy speech (only on active unvoiced SWB noisy speech segments) */ + st->GSC_noisy_speech_fx = 0; + move16(); + + test();test();test();test();test();test(); + IF ( EQ_16(st->vad_flag,1)&&GE_32(st->total_brate_fx,ACELP_13k20)&<_32(st->total_brate_fx,ACELP_24k40)&& + GT_16(st->lp_noise_fx,3072) && st->sp_aud_decision1 == 0 && GE_16(st->bwidth_fx,SWB) && + EQ_16(st->coder_type_raw_fx,UNVOICED)) + { + st->GSC_noisy_speech_fx = 1; + move16(); + } + + /* Select AUDIO frames */ + test();test(); + test();test(); + IF ( EQ_16(st->codec_mode,MODE1) && (st->sp_aud_decision2 || st->GSC_noisy_speech_fx)) + { + st->coder_type = AUDIO; + move16(); + hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); + } + + } + ELSE + { + st->sp_aud_decision0 = st->sp_aud_decision1; + } + + + return; +} + +/*---------------------------------------------------------------------* + * sp_mus_classif_gmm_fx() + * + * Speech/music classification based on GMM model + *---------------------------------------------------------------------*/ + +static Word16 sp_mus_classif_gmm_fx( /* o : decision flag (1-music, 0-speech or noise) */ + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 localVAD_HE_SAD, /* i : local VAD HE flag */ + const Word16 lsp_new[M], /* i : LSPs in current frame Q15 */ + const Word16 cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.)Q8 */ + const Word32 epsP[M+1], /* i : LP prediciton error Q_esp */ + const Word32 PS[], /* i : energy spectrum Q_new+Qscale-2 */ + Word16 non_sta, /* i : unbound non-stationarity for sp/mus classifier */ + Word16 relE, /* i : relative frame energy */ + Word16 *voi_fv, /* o : scaled voicing feature */ + Word16 *cor_map_sum_fv, /* o : scaled correlation map feature */ + Word16 *LPCErr, /* o : scaled LP prediction error feature */ + Word16 Q_esp, /* i : scaling of epsP */ + Word16 *high_lpn_flag_ptr /* o : noise log prob flag for NOISE_EST */ +) +{ + Word16 i, k, p, dec, vad; + + Word16 lsp[M], FV[N_FEATURES], *pFV = FV; + const Word32 *pSF_a; + const Word16 *pSF_m; + Word16 lsf2acos_fact, wrelE, dlp, wdrop, wght; + + Word32 mx; + Word32 sum_PS; + Word16 ftmp, tmp16; + Word16 xm[N_FEATURES]; + Word16 lps, lpm; + Word16 lpn; + Word16 e_tmp, f_tmp; + Word32 L_tmp; + Word16 exp1; + Word32 ps_sta; + Word32 ps_diff; + Word16 ps_diff_16; + Word32 dPS[128], PS_norm[128]; + Word32 lepsP1; + Word32 max_s=0, max_m=0, py_s, py_m; + Word32 max_n, py_n; /* pyn */ + Word16 ishift[12] = {8,0,2,2,2,2,2,1,0,2,2,1}; + Word16 tmp; + Word16 tmp1,tmp2,exp2,scale,exp3; + SP_MUS_CLAS_HANDLE hSpMusClas = st_fx->hSpMusClas; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + vad = localVAD_HE_SAD; + move16(); + + /*------------------------------------------------------------------* + * Preparation of the feature vector + *------------------------------------------------------------------*/ + + /* [0] OL pitch Q0 */ + /*(float)(pitch[0] + pitch[1] + pitch[2]) / 3.0f;*/ + L_tmp = L_mult(st_fx->pitch_fx[0], 10923); + L_tmp = L_mac(L_tmp, st_fx->pitch_fx[1], 10923); + L_tmp = L_mac(L_tmp, st_fx->pitch_fx[2], 10923); + + test(); + IF ( EQ_16(st_fx->tc_cnt_fx,1)||EQ_16(st_fx->tc_cnt_fx,2)) + { + *pFV++ = st_fx->pitch_fx[2]; + move16(); + } + ELSE + { + *pFV++ = round_fx(L_tmp); + } + + /* [1] voicing Q15 */ + /*(float)(voicing[0] + voicing[1] + voicing[2]) / 3.0f*/ + test(); + IF ( EQ_16(st_fx->tc_cnt_fx,1)||EQ_16(st_fx->tc_cnt_fx,2)) + { + *pFV++ = st_fx->voicing_fx[2]; + move16(); + } + ELSE + { + L_tmp = L_mult(st_fx->voicing_fx[0], 10923); + L_tmp = L_mac(L_tmp, st_fx->voicing_fx[1], 10923); + L_tmp = L_mac(L_tmp, st_fx->voicing_fx[2], 10923); + *pFV++ = round_fx(L_tmp); + } + + /* [2,3,4,5,6] LSFs Q15*/ + Copy( lsp_new, lsp, M ); + lsf2acos_fact = 25735; + move16(); /* PI/6400 -> Q27 */ + + /*ftmp = (float)acos(lsp[1...5]);*/ + /**pFV++ = ftmp + st->last_lsp[1...5];*/ + /*st->last_lsp[1...5] = ftmp;*/ + FOR(i= 1; i < M_LSP_SPMUS; i++) + { + L_tmp = sub_lsp2lsf_fx(lsp[i]); + tmp16 = round_fx(L_shl(L_mult0(extract_l(L_tmp),lsf2acos_fact),2)); + *pFV++ = add(tmp16, hSpMusClas->last_lsp_fx[i]); + move16(); /*Q13*/ + hSpMusClas->last_lsp_fx[i] = tmp16; + move16(); + } + + /* [7] cor_map_sum Q8 */ + *pFV++ = round_fx(L_mac(L_mult(cor_map_sum, 16384), hSpMusClas->last_cor_map_sum_fx, 16384)); /* Q8 ->Q7*/ + hSpMusClas->last_cor_map_sum_fx = cor_map_sum; + move16(); + + /* [8] non_sta Q8*/ + *pFV++ = round_fx(L_mac(L_mult(non_sta,16384), hSpMusClas->last_non_sta_fx, 16384)); /* Q8 -> Q7 */ + hSpMusClas->last_non_sta_fx = non_sta; + move16(); + + /* [9] epsP Q10 */ + IF ( EQ_16(st_fx->bwidth_fx,NB)) + { + *pFV++ = -1687; + move16(); /*Q10*/ + } + ELSE + { + /*lepsP1 = (float)log(epsP[1] + 1e-5f);*/ + IF(epsP[1] != 0) + { + e_tmp = norm_l(epsP[1]); + f_tmp = Log2_norm_lc(L_shl(epsP[1],e_tmp)); + e_tmp = sub(30,add(e_tmp,Q_esp)); + lepsP1 = Mpy_32_16(e_tmp, f_tmp, 22713); /* Q16 */ /* 22713 = ln(2) in Q15 */ + } + ELSE + { + lepsP1 = L_deposit_l(0); + } + + /*ftmp = (float)log(epsP[13]);*/ + IF(epsP[13] != 0) + { + e_tmp = norm_l(epsP[13]); + f_tmp = Log2_norm_lc(L_shl(epsP[13],e_tmp)); + e_tmp = sub(30,add(e_tmp,Q_esp)); + L_tmp = Mpy_32_16(e_tmp, f_tmp, 22713); /* Q16 */ /* 22713 = ln(2) in Q15 */ + } + ELSE + { + L_tmp = L_deposit_l(0); + } + + /*ftmp = (float)log(epsP[13]) - lepsP1;*/ + L_tmp = L_sub(L_tmp, lepsP1); /*Q16 */ + ftmp = round_fx(L_shl(L_tmp,10)); /*Q10 */ + + /**pFV++ = ftmp + st->past_epsP2;*/ + *pFV++ = add(ftmp, hSpMusClas->past_epsP2_fx); + move16(); /*Q10 */ + + /*st->past_epsP2 = ftmp;*/ + hSpMusClas->past_epsP2_fx = ftmp; + move16(); /*Q10 */ + } + + /* calculation of differential normalized power spectrum */ + sum_PS = L_deposit_l(0); + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { +#ifdef BASOP_NOGLOB + sum_PS = L_add_o(sum_PS,PS[i], &Overflow); +#else /* BASOP_NOGLOB */ + sum_PS = L_add(sum_PS,PS[i]); +#endif /* BASOP_NOGLOB */ + } + exp1 = norm_l(sum_PS); +#ifdef BASOP_NOGLOB + tmp1 = round_fx_o(L_shl(sum_PS,exp1), &Overflow); +#else /* BASOP_NOGLOB */ + tmp1 = round_fx(L_shl(sum_PS,exp1)); +#endif /* BASOP_NOGLOB */ + exp1 = sub(30,exp1); + + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + /*PS_norm[i] = PS[i] / sum_PS;*/ + /*dPS[i] = (float)fabs(PS_norm[i] - st->past_PS[i]);*/ + exp2 = norm_l(PS[i]); +#ifdef BASOP_NOGLOB + tmp2 = round_fx_o(L_shl(PS[i],exp2), &Overflow); +#else /* BASOP_NOGLOB */ + tmp2 = round_fx(L_shl(PS[i],exp2)); +#endif /* BASOP_NOGLOB */ + exp2 = sub(30,exp2); + + scale = shr(sub(tmp1, tmp2), 15); + tmp2 = shl(tmp2, scale); + exp2 = sub(exp2, scale); + + exp3 = sub(exp1,exp2); + + tmp = div_s(tmp2, tmp1); /*Q(15+exp3) */ + PS_norm[i] = L_shl(tmp,sub(10,exp3)); + move32(); /*Q25 */ + dPS[i] = L_abs(L_sub(PS_norm[i], hSpMusClas->past_PS_fx[i-LOWEST_FBIN])); + move32(); /*Q25 */ + } + + /* [10] ps_diff (spectral difference) Q10*/ + ps_diff = 0; + move16(); + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + /*ps_diff += dPS[i];*/ + ps_diff = L_add(ps_diff,dPS[i]); /*Q25*/ + } + + /*ps_diff = (float)log(ps_diff + 1e-5f);*/ + IF( ps_diff != 0 ) + { + e_tmp = norm_l(ps_diff); + f_tmp = Log2_norm_lc(L_shl(ps_diff,e_tmp)); + e_tmp = sub(30-25,e_tmp); + ps_diff = Mpy_32_16(e_tmp, f_tmp, 22713);/* Q16 */ /* 22713 = ln(2) in Q15 */ + ps_diff_16 = round_fx(L_shl(ps_diff,10)); /*Q10 */ + } + ELSE + { + ps_diff_16 = -11789; + move16(); /*Q10 */ + } + + *pFV++ = add(ps_diff_16, hSpMusClas->past_ps_diff_fx); + move16();/*Q10 */ + hSpMusClas->past_ps_diff_fx = ps_diff_16; + move16(); /*Q10 */ + + /* [11] ps_sta (spectral stationarity) Q11 */ + ps_sta = 0; + move16(); + FOR ( i = LOWEST_FBIN; i < HIGHEST_FBIN; i++ ) + { + /*mx = PS_norm[i] > st->past_PS[i] ? PS_norm[i] : st->past_PS[i];*/ + IF (GT_32(PS_norm[i], hSpMusClas->past_PS_fx[i-LOWEST_FBIN])) + { + mx = PS_norm[i]; + move16(); /*Q25 */ + } + ELSE + { + mx = hSpMusClas->past_PS_fx[i-LOWEST_FBIN]; + move16(); /*Q25 */ + } + + /*ps_sta += mx / (dPS[i] + 1e-5f);*/ + IF( !dPS[i] ) + { + ps_sta = L_add(ps_sta,L_shr(mx,9)); /*Q16 */ + } + ELSE + { + exp1 = norm_l(L_add(dPS[i],336)); +#ifdef BASOP_NOGLOB + tmp1 = round_fx_o(L_shl_o(L_add(dPS[i],336),exp1, &Overflow), &Overflow); +#else + tmp1 = round_fx(L_shl(L_add(dPS[i],336),exp1)); +#endif + exp1 = sub(30,exp1); + + exp2 = norm_l(mx); + tmp2 = round_fx(L_shl(mx,exp2)); + exp2 = sub(30,exp2); + + scale = shr(sub(tmp1, tmp2), 15); + tmp2 = shl(tmp2, scale); + exp2 = sub(exp2, scale); + + exp3 = sub(exp1,exp2); + move16(); + + tmp = div_s(tmp2, tmp1); /*Q(15+exp3) */ + L_tmp = L_shl(tmp,sub(1,exp3)); /*Q16 */ + ps_sta = L_add(ps_sta,L_tmp); /*Q16 */ + } + } + + /**pFV++ = (float)log(ps_sta + 1e-5f);*/ + ps_sta = L_add(ps_sta, 336); + e_tmp = norm_l(ps_sta); + f_tmp = Log2_norm_lc(L_shl(ps_sta,e_tmp)); + e_tmp = sub(30-16,e_tmp); + L_tmp = Mpy_32_16(e_tmp, f_tmp, 22713); /* Q16 */ /* 22713 = ln(2) in Q15 */ + *pFV++ = round_fx(L_shl(L_tmp,11)); /*Q11 */ + + /* update PS vector */ + Copy32( &PS_norm[LOWEST_FBIN], hSpMusClas->past_PS_fx, HIGHEST_FBIN-LOWEST_FBIN ); + + /*------------------------------------------------------------------* + * Scaling of the feature vector + *------------------------------------------------------------------*/ + + /* FV[0] -> Q0 */ + /* FV[1...6] -> Q13*/ + /* FV[7,8] -> Q7 */ + /* FV[9,10] -> Q10 */ + /* FV[11] -> Q11 */ + + + pFV = FV; + move16(); + IF ( EQ_16(st_fx->bwidth_fx,NB)) + { + pSF_m = SF_8k_mult_fx; + pSF_a = SF_8k_add_fx; + } + ELSE + { + pSF_m = SF_mult_fx; + pSF_a = SF_add_fx; + } + + FOR ( i=0; ilpm_fx = lpm; + move16(); + hSpMusClas->lps_fx = lps; + move16(); + + /* determine HQ GENERIC speech class */ + IF (hHQ_core != NULL) + { + hHQ_core->hq_generic_speech_class = 0; + move16(); + if (GT_16(lps, add(lpm, 256))) + { + hHQ_core->hq_generic_speech_class = 1; + move16(); + } + } + + /*------------------------------------------------------------------* + * State machine (sp_mus_state < 0 .. inactive, > 0 .. entry, = 0 .. active ) + *------------------------------------------------------------------*/ + + IF ( vad ) + { + test(); + test(); + test(); + IF ( LT_16(relE,-20*256)||(LE_16(lps,-5*512)&&LE_16(lpm,-5*512))) + { + IF (hSpMusClas->sp_mus_state > 0 ) + { + if ( LT_16(hSpMusClas->sp_mus_state,HANG_LEN)) + { + /* energy is too low but we are in entry period -> reset the inactive counter to allow new entry later */ + hSpMusClas->inact_cnt = 0; + move16(); + } + + /* energy is too low -> we are going to instable state */ + hSpMusClas->sp_mus_state = 0; + move16(); + } + ELSE IF ( GT_16(hSpMusClas->sp_mus_state,-HANG_LEN)) + { + /* energy is still too low -> we are still in instable state */ + hSpMusClas->sp_mus_state = sub(hSpMusClas->sp_mus_state,1); + } + } + ELSE IF (hSpMusClas->sp_mus_state <= 0 ) + { + IF (hSpMusClas->inact_cnt == 0 ) + { + + hSpMusClas->sp_mus_state = 1; + move16(); + } + ELSE + { + + hSpMusClas->sp_mus_state = HANG_LEN; + move16(); + } + + hSpMusClas->inact_cnt = 12; + move16(); + } + ELSE IF (hSpMusClas->sp_mus_state > 0 && LT_16(hSpMusClas->sp_mus_state,HANG_LEN)) + { + /* we are inside an entry period -> increment the counter of entry frames */ + hSpMusClas->sp_mus_state = add(hSpMusClas->sp_mus_state,1); + } + + test(); + if (hSpMusClas->sp_mus_state < 0 && hSpMusClas->inact_cnt > 0 ) + { + hSpMusClas->inact_cnt = sub(hSpMusClas->inact_cnt,1); + } + } + ELSE + { + test(); + IF (hSpMusClas->sp_mus_state > 0 && LT_16(hSpMusClas->sp_mus_state,HANG_LEN)) + { + hSpMusClas->inact_cnt = 0; + move16(); + } + ELSE IF (hSpMusClas->inact_cnt > 0 ) + { + hSpMusClas->inact_cnt = sub(hSpMusClas->inact_cnt,1); + } + + test(); + IF (hSpMusClas->sp_mus_state > 0 && LT_16(hSpMusClas->sp_mus_state,HANG_LEN)) + { + + hSpMusClas->sp_mus_state = -HANG_LEN; + move16(); + } + ELSE IF (hSpMusClas->sp_mus_state > 0 ) + { + + hSpMusClas->sp_mus_state = -1; + move16(); + } + ELSE IF ( GT_16(hSpMusClas->sp_mus_state,-HANG_LEN)) + { + /* we are in inactive state */ + hSpMusClas->sp_mus_state = sub(hSpMusClas->sp_mus_state,1); + } + } + + /*------------------------------------------------------------------* + * Decision without hangover + * Weighted decision + *------------------------------------------------------------------*/ + + /* decision without hangover (0 - speech/noise, 1 - music) */ + logic16(); + dec = sub(lpm,lps) > 0; + move16(); + dlp = sub(lpm,lps); /*Q9*/ + + IF ( !vad ) + { + dec = 0; + move16(); + dlp = 0; + move16(); + } + + /* calculate weight based on relE (close to 0.01 in low-E regions, close to 1 in high-E regions) */ + /*wrelE = 1.0f + relE/15;*/ + wrelE = add(2048, mult_r(relE,17476)); /* 1/15 in Q18 -> 17476 result in Q11 */ + + + wrelE = s_min(wrelE, 2048); + wrelE = s_max(wrelE, 20); + + /* calculate weight based on drops of dlp (close to 1 during sudden drops of dlp, close to 0 otherwise) */ + test(); + IF ( dlp < 0 && LT_16(dlp, hSpMusClas->past_dlp_fx[0])) + { + IF (hSpMusClas->past_dlp_fx[0] > 0 ) + { + hSpMusClas->wdrop_fx = negate(dlp); /*Q9*/ + } + ELSE + { + hSpMusClas->wdrop_fx = add(hSpMusClas->wdrop_fx, sub(hSpMusClas->past_dlp_fx[0], dlp)); /*Q9*/ + } + } + ELSE + { + hSpMusClas->wdrop_fx = 0; + move16(); + } + + /*wdrop = st->wdrop/20;*/ + wdrop = mult_r(hSpMusClas->wdrop_fx, 26214); /*Q9*Q19->Q13*/ + wdrop = s_min(wdrop,8192); /* limitation [0.1,1] Q13 */ + wdrop = s_max(wdrop,819); + + /* combine weights into one */ + /*wght = wrelE * wdrop;*/ + wght = mult_r(wrelE, wdrop); /* Q11*Q13 -> Q9*/ + wght = s_max(wght,5); + + /* calculate weighted decision */ + /*st->wdlp_0_95_sp = wght * dlp + (1 - wght) * st->wdlp_0_95_sp;*/ + /* = Q9 * Q9 + (Q9-Q9)*Q9 */ + L_tmp = L_mac(L_mult(wght, dlp), sub(512, wght), hSpMusClas->wdlp_0_95_sp_fx); + hSpMusClas->wdlp_0_95_sp_fx = round_fx(L_shl(L_tmp, 6)); + + if ( EQ_16(hSpMusClas->sp_mus_state,-HANG_LEN)) + { + hSpMusClas->wdlp_0_95_sp_fx = 0; + move16(); + } + + /*------------------------------------------------------------------* + * Final speech/music decision + *------------------------------------------------------------------*/ + + test(); + test(); + IF ( !vad && EQ_16(hSpMusClas->sp_mus_state,-HANG_LEN)) + { + /* inactive state */ + dec = 0; + move16(); + } + ELSE IF (hSpMusClas->sp_mus_state <= 0 ) + { + /* transition from active to inactive state or instable state */ + dec = hSpMusClas->past_dec[0]; + move16(); + } + ELSE IF (hSpMusClas->sp_mus_state > 0 && LT_16(hSpMusClas->sp_mus_state,HANG_LEN)) + { + /* entry state -> final decision is calculated based on weighted average of past non-binary decisions */ + L_tmp = L_mult(w_spmus_fx[hSpMusClas->sp_mus_state-1][0], dlp); /*Q15*Q9 */ + + /*ftmp += dotp( &w[st_fx->sp_mus_state-1][1], st_fx->past_dlp_fx, HANG_LEN-1 );*/ + L_tmp = L_add(L_tmp, Dot_product( &w_spmus_fx[hSpMusClas->sp_mus_state-1][1], hSpMusClas->past_dlp_fx, HANG_LEN-1 )); + logic16(); + move16(); + + /*dec = ftmp > 2.0f;*/ + dec = L_sub(L_tmp, 2*(1<<25))>0; + } + ELSE + { + /* stable active state */ + test(); + test(); + test(); + test(); + IF (hSpMusClas->wdlp_0_95_sp_fx > 0 && hSpMusClas->past_dec[0] == 0 && hSpMusClas->past_dec[1] == 0 && hSpMusClas->past_dec[2] == 0 ) + { + /* switching from speech to music */ + dec = 1; + move16(); + } + ELSE IF (hSpMusClas->past_dec[0] == 1 && hSpMusClas->wdlp_0_95_sp_fx < 0 ) + { + /* switching from music to speech */ + dec = 0; + move16(); + } + ELSE + { + dec = hSpMusClas->past_dec[0]; + move16(); + } + } + + + /*------------------------------------------------------------------* + * Updates + *------------------------------------------------------------------*/ + + /* update the buffer of past non-binary decisions */ + Copy( &hSpMusClas->past_dlp_fx[0], &hSpMusClas->past_dlp_fx[1], HANG_LEN-2 ); + hSpMusClas->past_dlp_fx[0] = dlp; + move16(); + + /* update the buffer of past binary decisions */ + Copy( &hSpMusClas->past_dec[0], &hSpMusClas->past_dec[1], HANG_LEN-2 ); + hSpMusClas->past_dec[0] = dec; + move16(); + + return dec; +} + + +/*---------------------------------------------------------------------* + * sp_mus_classif_2nd_fx() + * + * 2nd stage speech/music classifier (convert music to speech for onsets) + *---------------------------------------------------------------------*/ + +static void sp_mus_classif_2nd_fx( + Encoder_State_fx *st, /* i/o: Encoder state structure */ + const Word16 Etot, /* i : total frame energy */ + Word16 *attack_flag, /* i/o: attack flag (GSC or TC) */ + const Word16 *inp, /* i : input signal */ + const Word16 Qx +) +{ + Word16 attack; + SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; + + /* initialization */ + *attack_flag = 0; + move16(); + + /* signal stability estimation */ + stab_est_fx( Etot, hSpMusClas->gsc_lt_diff_etot_fx, &hSpMusClas->gsc_mem_etot_fx + , &hSpMusClas->gsc_nb_thr_3, &hSpMusClas->gsc_nb_thr_1, hSpMusClas->gsc_thres_fx, &hSpMusClas->gsc_last_music_flag, st->vad_flag ); + + /* calculate variance of correlation */ + var_cor_calc_fx( st->old_corr_fx, &hSpMusClas->mold_corr_fx, hSpMusClas->var_cor_t_fx, &hSpMusClas->high_stable_cor ); + + /* attack detection */ + attack = attack_det_fx( inp, Qx, st->clas_fx, st->localVAD, st->coder_type, st->total_brate_fx +#ifdef IVAS_CODE + , EVS_MONO, st->clas_fx, hSpMusClas->finc_prev, &hSpMusClas->lt_finc, &hSpMusClas->last_strong_attack +#endif + ); + + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16(st->sp_aud_decision1,1)) + { + test(); + test(); + test(); + IF( LT_16(hSpMusClas->ener_RAT_fx,5898) && GT_16(hSpMusClas->lt_dec_thres_fx,7680)) + { + st->sp_aud_decision2 = 0; + move16(); + } + ELSE IF( EQ_16(hSpMusClas->high_stable_cor, 1)&&GE_16(st->pitch_fx[0],130)) + { + /* prevent GSC in highly correlated signal with low energy variation */ + /* this is basically a patch against bassoon-type of music */ + st->sp_aud_decision2 = 0; + move16(); + + test(); + IF( EQ_16(st->codec_mode,MODE1)&&EQ_16(st->coder_type,TRANSITION)) + { + st->coder_type = GENERIC; + move16(); + } + } + ELSE IF( GT_16(hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT-1],1152) && + GT_16(sub(hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT-1], hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT-2]),2560)) /* 10.0f in Q8 */ + { + IF ( EQ_16(st->tc_cnt_fx,1)) + { + st->sp_aud_decision2 = 0; + move16(); + + IF( EQ_16(st->codec_mode,MODE1)) + { + st->coder_type = TRANSITION; + move16(); + } + } + ELSE + { + IF( GE_16(attack, ATT_3LSUB_POS)) + { + /* do TC coding if attack is located in the last subframe */ + st->sp_aud_decision2 = 0; + move16(); + *attack_flag = add(attack, 1); + move16(); + IF( EQ_16(st->codec_mode,MODE1)) + { + st->coder_type = TRANSITION; + move16(); + } + } + ELSE IF( GE_16(attack,ATT_SEG_LEN/2)) + { + /* do GSC coding if attack is located after the first quarter of the first subframe */ + /* (pre-echo will be treated at the decoder side) */ + st->sp_aud_decision2 = 1; + *attack_flag = 31; + move16(); + move16(); + } + } + } + } + ELSE IF( EQ_16(st->localVAD,1)&&EQ_16(st->coder_type,GENERIC)&& + ( (GE_16(attack,ATT_3LSUB_POS) && LT_32(st->total_brate_fx,ACELP_24k40)) || + (GE_16(attack,ATT_3LSUB_POS_16k) && GE_32(st->total_brate_fx,ACELP_24k40) && LT_32(st->total_brate_fx,ACELP_48k)) ) + ) + { + /* do TC coding if attack is located in the last subframe */ + *attack_flag = add(attack, 1); + move16(); + IF( EQ_16(st->codec_mode,MODE1)) + { + st->coder_type = TRANSITION; + move16(); + } + } + + return; +} + + +/*---------------------------------------------------------------------* + * var_cor_calc_fx() + * + * Calculate variance of correlation + *---------------------------------------------------------------------*/ + +static void var_cor_calc_fx( + const Word16 old_corr, + Word16 *mold_corr, + Word16 var_cor_t[], + Word16 *high_stable_cor +) +{ + Word16 i, var_cor; + + /* update buffer of old correlation values */ + FOR( i = VAR_COR_LEN-1; i > 0; i-- ) + { + var_cor_t[i] = var_cor_t[i-1]; /*Q11*/ move16(); + } + var_cor_t[i] = old_corr; + move16(); + + /* calculate variance of correlation */ + var_cor = var_fx( var_cor_t, 11, VAR_COR_LEN ); + + *high_stable_cor = 0; + move16(); + test(); + IF( GT_16(*mold_corr,26214)&<_16(var_cor,2)) + { + *high_stable_cor = 1; + move16(); + } + + /* update average correlation */ + /*st->mold_corr = 0.1f * st->old_corr + 0.9f * st->mold_corr;*/ + *mold_corr = mac_r(L_mult(3277,old_corr),29491,*mold_corr); /*Q15 */ + + return; +} + +/*---------------------------------------------------------------------* + * attack_det_fx() + * + * Attack detection + *---------------------------------------------------------------------*/ + +static Word16 attack_det_fx( /* o : attack flag */ + const Word16 *inp, /* i : input signal */ + const Word16 Qx, + const Word16 last_clas, /* i : last signal clas */ + const Word16 localVAD, /* i : local VAD flag */ + const Word16 coder_type, /* i : coder type */ + const Word32 total_brate /* i : total bitrate */ +#ifdef IVAS_CODE + , + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 clas, /* i : signal class */ + Word32 finc_prev[], /* i/o: previous finc */ + Word32* lt_finc, /* i/o: long-term mean finc */ + Word16* last_strong_attack /* i/o: last strong attack flag */ +#endif +) +{ + Word16 i, j, tmp, tmp1, attack, exp1; + Word32 L_tmp, etmp, etmp2, finc[ATT_NSEG]; + Word16 att_3lsub_pos; +#ifdef IVAS_CODE + Word16 attack1; +#endif +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + att_3lsub_pos = ATT_3LSUB_POS; + move16(); + if( GE_32(total_brate,ACELP_24k40)) + { + att_3lsub_pos = ATT_3LSUB_POS_16k; + move16(); + } + + /* compute energy per section */ + FOR( i=0; i 0 ) + { + etmp2 = L_add(finc[attack], 0); + etmp = Mult_32_16(etmp2, 16384); /* etmp2 / 2.0 = (etmp2*0.5) */ + FOR( i=2; i 0 ) + { + etmp2 = L_add(finc[attack], 0); + etmp = Mult_32_16(etmp2, 25206); /* etmp2 / 1.3 = (etmp2*0.76923) */ + FOR( i=2; i etmp2 ) -> finc[i] > (etmp2*0.76923) */ + test(); + IF( NE_16(i,attack)&>_32(finc[i],etmp)) + { + attack = 0; + move16(); + BREAK; + } + } +#ifdef IVAS_CODE + *last_strong_attack = 0; +#endif + move16(); + } + + return attack; +} +#ifdef IVAS_CODE +/* -------------------------------------------------------------------- - * + *ivas_smc_gmm() + * + *1st stage of the speech / music classification(based on the GMM model) + * -------------------------------------------------------------------- - */ + /*! r: S/M decision (0=speech or noise,1=unclear,2=music) */ +int16_t ivas_smc_gmm( + Encoder_State * st, /* i/o: state structure */ + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + const int16_t localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const float Etot, /* i : total frame energy */ + const float lsp_new[M], /* i : LSPs in current frame */ + const float cor_map_sum, /* i : correlation map sum (from multi-harmonic anal.) */ + const float epsP[M + 1], /* i : LP prediciton error */ + const float PS[], /* i : energy spectrum */ + const float non_sta, /* i : unbound non-stationarity */ + const float relE, /* i : relative frame energy */ + int16_t * high_lpn_flag, /* i/o: sp/mus LPN flag */ + const int16_t flag_spitch /* i : flag to indicate very short stable pitch */ +) +{ + int16_t i, m, dec; + int16_t flag_odv; + float lps, lpm, lpn; + float ps[N_SMC_MIXTURES], pm[N_SMC_MIXTURES], pn[N_SMC_MIXTURES]; + float fvm[N_PCA_COEF], lprob; + float dlp, ftmp, sum_PS, ps_diff, ps_sta, wrelE, wdrop, wght; + float wrise; + float dlp_mean2var; + float FV[N_SMC_FEATURES], * pFV, PS_norm[128], dPS[128]; + const float* pODV; + float* pFV_st, smc_st_mean_fact; + int16_t relE_attack_flag; + int16_t j, len; + const float* pt_mel_fb; + float melS[NB_MEL_BANDS], mfcc[NB_MEL_BANDS]; + int16_t odv_cnt; + int16_t i_out[N_SMC_FEATURES], * p_out; + + /*------------------------------------------------------------------* + * Initialization + *------------------------------------------------------------------*/ + + SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; + + /*------------------------------------------------------------------* + * State machine (sp_mus_state: -8 = INACTIVE, -7:-1 = UNSTABLE, 0:7 = ENTRY, 8 = STABLE ) + *------------------------------------------------------------------*/ + + if (localVAD_HE_SAD) + { + if (relE < -20) + { + if (hSpMusClas->sp_mus_state > 0) + { + if (hSpMusClas->sp_mus_state < HANG_LEN) + { + /* energy is too low but we are in entry period -> reset the inactive counter to allow new entry later */ + hSpMusClas->inact_cnt = 0; + } + + /* energy is too low -> we are going to instable state */ + hSpMusClas->sp_mus_state = 0; + } + else if (hSpMusClas->sp_mus_state > -HANG_LEN) + { + /* energy is still too low -> we are still in instable state */ + hSpMusClas->sp_mus_state--; + } + } + else if (hSpMusClas->sp_mus_state <= 0) + { + if (hSpMusClas->inact_cnt == 0) + { + + hSpMusClas->sp_mus_state = 1; + } + else + { + + hSpMusClas->sp_mus_state = HANG_LEN; + } + + hSpMusClas->inact_cnt = 12; + } + else if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN) + { + /* we are inside an entry period -> increment the counter of entry frames */ + hSpMusClas->sp_mus_state++; + } + + if (hSpMusClas->sp_mus_state < 0 && hSpMusClas->inact_cnt > 0) + { + hSpMusClas->inact_cnt--; + } + } + else + { + if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN) + { + hSpMusClas->inact_cnt = 0; + } + else if (hSpMusClas->inact_cnt > 0) + { + hSpMusClas->inact_cnt--; + } + + if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN) + { + hSpMusClas->sp_mus_state = -HANG_LEN; + } + else if (hSpMusClas->sp_mus_state > 0) + { + hSpMusClas->sp_mus_state = -1; + } + else if (hSpMusClas->sp_mus_state > -HANG_LEN) + { + /* we are in inactive state */ + hSpMusClas->sp_mus_state--; + } + } + + /* detect attacks based on relE */ + if (relE > hSpMusClas->prev_relE) + { + hSpMusClas->relE_attack_sum += relE - hSpMusClas->prev_relE; + } + else + { + hSpMusClas->relE_attack_sum = 0; + } + hSpMusClas->prev_relE = relE; + + /* update counter from last VAD 0->1 change */ + if (hSpMusClas->prev_vad == 0 && localVAD_HE_SAD == 1) + { + hSpMusClas->vad_0_1_cnt = 1; + } + else if (localVAD_HE_SAD == 1 && hSpMusClas->vad_0_1_cnt > 0 && hSpMusClas->vad_0_1_cnt < 50) + { + hSpMusClas->vad_0_1_cnt++; + } + else + { + hSpMusClas->vad_0_1_cnt = 0; + } + hSpMusClas->prev_vad = localVAD_HE_SAD; + + if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN && hSpMusClas->relE_attack_sum > 5.0f) + { + hSpMusClas->relE_attack_cnt++; + + /* set flag only in the first X frames in a series */ + if (hSpMusClas->relE_attack_cnt > 0 && hSpMusClas->relE_attack_cnt < 3) + { + relE_attack_flag = 1; + } + else + { + relE_attack_flag = 0; + } + } + else + { + hSpMusClas->relE_attack_cnt = 0; + relE_attack_flag = 0; + } + + hSpMusClas->prev_Etot = Etot; + + /*------------------------------------------------------------------* + * Preparation of the feature vector + *------------------------------------------------------------------*/ + + pFV = FV; + + /* [0] OL pitch */ + if (relE_attack_flag || st->tc_cnt == 1 || st->tc_cnt == 2) + { + *pFV++ = (float)st->pitch[2]; + } + else + { + *pFV++ = (float)(st->pitch[0] + st->pitch[1] + st->pitch[2]) / 3.0f; + } + + /* [1] voicing */ + if (relE_attack_flag || st->tc_cnt == 1 || st->tc_cnt == 2) + { + *pFV++ = st->voicing[2]; + } + else + { + *pFV++ = (st->voicing[0] + st->voicing[1] + st->voicing[2]) / 3.0f; + } + + /* [2,3,4,5,6] LSFs */ + *pFV++ = acosf(lsp_new[2]); + *pFV++ = acosf(lsp_new[3]); + *pFV++ = acosf(lsp_new[4]); + *pFV++ = acosf(lsp_new[5]); + *pFV++ = acosf(lsp_new[6]); + + /* [7] cor_map_sum */ + *pFV++ = cor_map_sum; + + /* [8] non_sta */ + *pFV++ = non_sta; + + /* [9] epsP */ + *pFV++ = logf(epsP[14] + 1e-5f) - logf(epsP[0] + 1e-5f); + + /* [10,11,12] MFCCs */ + set_zero(melS, NB_MEL_BANDS); + pt_mel_fb = mel_fb; + for (i = 0; i < NB_MEL_BANDS; i++) + { + j = mel_fb_start[i]; + len = mel_fb_len[i]; + melS[i] = logf(dotp(&PS[j], pt_mel_fb, len) + 1e-5f); + pt_mel_fb += len; + } + + v_mult_mat(mfcc, melS, dct_mtx, NB_MEL_BANDS, NB_MEL_COEF); + + *pFV++ = mfcc[2]; + *pFV++ = mfcc[6]; + *pFV++ = mfcc[12]; + + /* calculation of differential normalized power spectrum */ + sum_PS = 1e-5f; + for (i = LOWEST_FBIN; i < HIGHEST_FBIN; i++) + { + sum_PS += PS[i]; + } + + for (i = LOWEST_FBIN; i < HIGHEST_FBIN; i++) + { + PS_norm[i] = PS[i] / sum_PS; + dPS[i] = fabsf(PS_norm[i] - hSpMusClas->past_PS[i - LOWEST_FBIN]); + } + + /* [13] ps_diff (spectral difference) */ + ps_diff = 0; + for (i = LOWEST_FBIN; i < HIGHEST_FBIN; i++) + { + ps_diff += dPS[i]; + } + + *pFV++ = ps_diff; + + /* [14] ps_sta (spectral stationarity) */ + ps_sta = 0; + for (i = LOWEST_FBIN; i < HIGHEST_FBIN; i++) + { + if (PS_norm[i] > hSpMusClas->past_PS[i - LOWEST_FBIN]) + { + ps_sta += PS_norm[i] / (dPS[i] + 1e-5f); + } + else + { + ps_sta += hSpMusClas->past_PS[i - LOWEST_FBIN] / (dPS[i] + 1e-5f); + } + } + + *pFV++ = logf(ps_sta + 1e-5f); + mvr2r(&PS_norm[LOWEST_FBIN], hSpMusClas->past_PS, HIGHEST_FBIN - LOWEST_FBIN); + + /* save ps_diff and ps_sta features for XTALK and UNCLR classifier */ + if (hStereoClassif != NULL) + { + if (st->idchan == 0) + { + hStereoClassif->ps_diff_ch1 = ps_diff; + hStereoClassif->ps_sta_ch1 = logf(ps_sta + 1e-5f); + } + else + { + hStereoClassif->ps_diff_ch2 = ps_diff; + hStereoClassif->ps_sta_ch2 = logf(ps_sta + 1e-5f); + } + } + + /*------------------------------------------------------------------* + * Outlier detection based on feature histograms + *------------------------------------------------------------------*/ + + flag_odv = 0; + if (localVAD_HE_SAD) + { + pFV = FV; + pODV = hout_intervals; + p_out = i_out; + odv_cnt = 0; + for (i = 0; i < N_SMC_FEATURES; i++) + { + if (*pFV < pODV[0] || *pFV > pODV[1]) + { + *p_out++ = i; + odv_cnt++; + } + + pFV++; + pODV += 2; + } + + /* set outlier flag */ + if (odv_cnt >= 2) + { + flag_odv = 1; + + /* replace outlying features with values from the previous frame */ + for (i = 0; i < odv_cnt; i++) + { + FV[i_out[i]] = hSpMusClas->prev_FV[i_out[i]]; + } + } + } + + /*------------------------------------------------------------------* + * Adaptive short-term mean filter on feature vector + *------------------------------------------------------------------*/ + + pFV = FV; + pFV_st = hSpMusClas->FV_st; + smc_st_mean_fact = SMC_ST_MEAN_FACT; + for (i = 0; i < N_SMC_FEATURES; i++) + { + *pFV_st = smc_st_mean_fact * (*pFV_st) + (1 - smc_st_mean_fact) * (*pFV); + + if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN && (relE_attack_flag || flag_odv)) + { + /* strong attack or outlier frame during entry state -> features cannot be trusted but there is also no useful past info -> */ + /* -> do whatever you want because dlp will be reset to 0 anyway */ + pFV++; + pFV_st++; + } + else if (hSpMusClas->sp_mus_state == HANG_LEN && (st->tc_cnt == 1 || st->tc_cnt == 2)) + { + /* energy attack in stable state -> use current features intead of the long-term average */ + pFV++; + pFV_st++; + } + else + { + *pFV++ = *pFV_st++; + } + } + + /* update */ + mvr2r(FV, hSpMusClas->prev_FV, N_SMC_FEATURES); + + /*------------------------------------------------------------------* + * Non-linear power transformation (boxcox) on certain features + *------------------------------------------------------------------*/ + + pFV = FV; + for (i = 0; i < N_SMC_FEATURES; i++) + { + if (bcox_lmbd[i] != 0) + { + *pFV -= bcox_add_cnst[i]; + if (*pFV < 1) + { + *pFV = 1; + } + *pFV = (powf(*pFV, bcox_lmbd[i]) - 1) / bcox_lmbd[i]; + } + + pFV++; + } + + /*------------------------------------------------------------------* + * Scaling of the feature vector + * PCA + *------------------------------------------------------------------*/ + + pFV = FV; + for (i = 0; i < N_SMC_FEATURES; i++) + { + /* Standard scaler - mean and variance normalization */ + *pFV = (*pFV - sm_means[i]) / sm_scale[i]; + pFV++; + + /* MinMax sclaer - mean and variance normalization */ + /**pFV = *pFV * sm_scale[i] + sm_min[i];*/ + /*pFV++;*/ + } + + /* PCA */ + v_sub(FV, pca_mean_, FV, N_SMC_FEATURES); + v_mult_mat(FV, FV, pca_components_, N_SMC_FEATURES, N_PCA_COEF); + + /*------------------------------------------------------------------* + * Calculation of posterior probability + * Log-probability + *------------------------------------------------------------------*/ + + /* run loop for all mixtures (for each mixture, calculate the probability of speech, music and noise) */ + lps = lpm = lpn = 0; + for (m = 0; m < N_SMC_MIXTURES; m++) + { + v_sub(FV, &means_speech[m * N_PCA_COEF], fvm, N_PCA_COEF); + lprob = dot_product_cholesky(fvm, &prec_chol_speech[m * (N_PCA_COEF * N_PCA_COEF + N_PCA_COEF) / 2], N_PCA_COEF); + ps[m] = logf(weights_speech[m]) + log_det_chol_speech[m] - 0.5f * N_PCA_COEF * logf(PI2) - 0.5f * lprob; + + v_sub(FV, &means_music[m * N_PCA_COEF], fvm, N_PCA_COEF); + lprob = dot_product_cholesky(fvm, &prec_chol_music[m * (N_PCA_COEF * N_PCA_COEF + N_PCA_COEF) / 2], N_PCA_COEF); + pm[m] = logf(weights_music[m]) + log_det_chol_music[m] - 0.5f * N_PCA_COEF * logf(PI2) - 0.5f * lprob; + + v_sub(FV, &means_noise[m * N_PCA_COEF], fvm, N_PCA_COEF); + lprob = dot_product_cholesky(fvm, &prec_chol_noise[m * (N_PCA_COEF * N_PCA_COEF + N_PCA_COEF) / 2], N_PCA_COEF); + pn[m] = logf(weights_noise[m]) + log_det_chol_noise[m] - 0.5f * N_PCA_COEF * logf(PI2) - 0.5f * lprob; + } + + lps = logsumexp(ps, N_SMC_MIXTURES); + lpm = logsumexp(pm, N_SMC_MIXTURES); + lpn = logsumexp(pn, N_SMC_MIXTURES); + + *high_lpn_flag = 0; + if (lpn > lps && lpn > lpm) + { + *high_lpn_flag = 1; + } + + hSpMusClas->lpm = lpm; + hSpMusClas->lps = lps; + hSpMusClas->lpn = lpn; + + /* determine HQ Generic speech class */ + if (st->hHQ_core != NULL) + { + if (lps > lpm + 0.5f) + { + st->hHQ_core->hq_generic_speech_class = 1; + } + else + { + st->hHQ_core->hq_generic_speech_class = 0; + } + } + + /*------------------------------------------------------------------* + * Decision without hangover + * Weighted decision + *------------------------------------------------------------------*/ + + /* decision without hangover (0 - speech/noise, 1 - music) */ + if (!localVAD_HE_SAD || Etot < 10 || (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN && (relE_attack_flag || flag_odv))) + { + dlp = 0; + } + else + { + dlp = lpm - lps + DLP_BIAS; + + if (dlp > 30.0f) + { + dlp = 30.0f; + } + else if (dlp < -30.0f) + { + dlp = -30.0f; + } + } + + dec = dlp > 0; + + /* calculate weight based on relE (higher relE -> lower weight, lower relE -> higher weight) */ + wrelE = lin_interp(relE, 15.0f, 0.9f, -15.0f, 0.99f, 1); + + /* calculate weight based on drops of dlp (close to 1 during sudden drops of dlp, close to 0 otherwise) */ + hSpMusClas->dlp_mean_ST = 0.8f * hSpMusClas->dlp_mean_ST + 0.2f * dlp; + hSpMusClas->lt_dec_thres = hSpMusClas->dlp_mean_ST; + + if (dlp < 0 && dlp < hSpMusClas->dlp_mean_ST) + { + if (hSpMusClas->dlp_mean_ST > 0) + { + hSpMusClas->wdrop = -dlp; + } + else if (hSpMusClas->wdrop > 0) + { + hSpMusClas->wdrop += hSpMusClas->dlp_mean_ST - dlp; + } + } + else + { + hSpMusClas->wdrop = 0; + } + + wdrop = lin_interp(hSpMusClas->wdrop, 15.0f, 0.7f, 0.0f, 1.0f, 1); + + /* calculate weight based on rises of dlp (close to 1 during sudden rise of dlp, close to 0 otherwise) */ + if (hSpMusClas->sp_mus_state == HANG_LEN && hSpMusClas->dlp_mean_ST > 0 && hSpMusClas->dlp_mean_ST > hSpMusClas->past_dlp_mean_ST[0]) + { + if (hSpMusClas->past_dlp_mean_ST[0] < 0) + { + hSpMusClas->wrise = hSpMusClas->dlp_mean_ST; + } + else if (hSpMusClas->wrise > 0) + { + hSpMusClas->wrise += hSpMusClas->dlp_mean_ST - hSpMusClas->past_dlp_mean_ST[0]; + } + } + else + { + hSpMusClas->wrise = 0; + } + + wrise = lin_interp(hSpMusClas->wrise, 5.0f, 0.95f, 0.0f, 1.0f, 1); + + /* combine weights into one */ + wght = wrelE * wdrop * wrise; + + /* ratio of delta means vs. delta variances */ + if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN) + { + hSpMusClas->dlp_mean_LT = dlp; + hSpMusClas->dlp_var_LT = 0; + } + + hSpMusClas->dlp_mean_LT = 0.9f * hSpMusClas->dlp_mean_LT + 0.1f * dlp; + ftmp = dlp - hSpMusClas->dlp_mean_LT; + hSpMusClas->dlp_var_LT = 0.9f * hSpMusClas->dlp_var_LT + 0.1f * (ftmp * ftmp); + + if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN) + { + dlp_mean2var = 0; + } + else + { + dlp_mean2var = fabsf(hSpMusClas->dlp_mean_LT) / (sqrtf(fabsf(hSpMusClas->dlp_var_LT)) + 1.0f); + } + + if (dlp_mean2var > 15.0f) + { + /* decrease the weight little bit when the classifier indicates "strong speech" or "strong music" */ + wght *= 0.9f; + } + + if (wght > 1.0f) + { + wght = 1.0f; + } + else if (wght < 0.01f) + { + wght = 0.01f; + } + + if (Etot < 10) + { + /* silence */ + wght = 0.92f; + } + + /* calculate weighted decision */ + hSpMusClas->wdlp_0_95_sp = wght * hSpMusClas->wdlp_0_95_sp + (1 - wght) * dlp; + + /* xtalk classifier: apply long hysteresis to prevent LRTD on music */ + hSpMusClas->wdlp_xtalk = 0.995f * hSpMusClas->wdlp_xtalk + 0.005f * dlp; + + /*------------------------------------------------------------------* + * Final speech/music decision + *------------------------------------------------------------------*/ + + if (flag_spitch) + { + hSpMusClas->flag_spitch_cnt = 5; + } + else if (hSpMusClas->flag_spitch_cnt > 0) + { + hSpMusClas->flag_spitch_cnt--; + } + + if (Etot < 10) + { + /* silence */ + dec = 0; + } + else if (hSpMusClas->sp_mus_state > 0 && hSpMusClas->sp_mus_state < HANG_LEN) + { + /* entry state -> final decision is calculated based on weighted average of past non-binary decisions */ + ftmp = w_spmus[hSpMusClas->sp_mus_state - 1][0] * dlp; + ftmp += dotp(&w_spmus[hSpMusClas->sp_mus_state - 1][1], hSpMusClas->past_dlp, HANG_LEN - 1); + if (ftmp > 2.0f) + { + if (dlp > 2.0f) + { + dec = 2; + } + else + { + dec = 1; + } + } + else + { + dec = 0; + } + } + else + { + /* stable active state */ + if (hSpMusClas->past_dec[0] == 0 && hSpMusClas->past_dec[1] == 0 && hSpMusClas->past_dec[2] == 0 && + ((hSpMusClas->flag_spitch_cnt > 0 && hSpMusClas->wdlp_0_95_sp > 3.4f) || (hSpMusClas->flag_spitch_cnt == 0 && hSpMusClas->wdlp_0_95_sp > 2.1f))) + { + /* switching from speech to unclear */ + dec = 1; + } + else if (hSpMusClas->past_dec[0] == 0 && hSpMusClas->vad_0_1_cnt < 50 && hSpMusClas->relE_attack_sum == 0.0f && hSpMusClas->wdlp_0_95_sp > 1.0f) + { + /* switch from speech to unclear also during slowly rising weak music onsets */ + dec = 1; + } + else if (hSpMusClas->past_dec[0] == 1 && hSpMusClas->wdlp_0_95_sp > 2.5f) + { + /* switching from unclear to music */ + dec = 2; + } + else if (hSpMusClas->past_dec[0] == 2 && hSpMusClas->past_dec[1] == 2 && hSpMusClas->past_dec[2] == 2 && hSpMusClas->wdlp_0_95_sp < -1.0f) + { + /* switching from music to unclear */ + dec = 1; + } + else if (hSpMusClas->past_dec[0] == 1 && hSpMusClas->wdlp_0_95_sp < -2.5f) + { + /* switching from unclear to speech */ + dec = 0; + } + else + { + dec = hSpMusClas->past_dec[0]; + } + } + + /*------------------------------------------------------------------* + * raw S/M decision based on smoothed GMM score + *------------------------------------------------------------------*/ + + if (dec == 0 || st->hSpMusClas->wdlp_0_95_sp <= 0) + { + st->sp_aud_decision0 = 0; + st->sp_aud_decision1 = 0; + } + else + { + st->sp_aud_decision0 = 1; + st->sp_aud_decision1 = 1; + } + + /*------------------------------------------------------------------* + * Updates + *------------------------------------------------------------------*/ + + /* update buffer of past non-binary decisions */ + mvr2r(&hSpMusClas->past_dlp[0], &hSpMusClas->past_dlp[1], HANG_LEN - 2); + hSpMusClas->past_dlp[0] = dlp; + + mvr2r(&hSpMusClas->past_dlp_mean_ST[0], &hSpMusClas->past_dlp_mean_ST[1], HANG_LEN - 2); + hSpMusClas->past_dlp_mean_ST[0] = hSpMusClas->dlp_mean_ST; + + /* update buffer of past binary decisions */ + mvs2s(&hSpMusClas->past_dec[0], &hSpMusClas->past_dec[1], HANG_LEN - 2); + hSpMusClas->past_dec[0] = dec; + +#ifdef DEBUG_MODE_INFO + dbgwrite(&st->hSpMusClas->wdlp_0_95_sp, sizeof(float), 1, 1, "res/wdlp_0_95_sp.x"); +#endif + + return dec; +} + +/*---------------------------------------------------------------------* + * ivas_smc_mode_selection() + * + * 2nd stage speech/music classifier (select coding mode (ACELP, GSC and TCX) based on S/M classification) + * output (sp_aud_decision1 - sp_aud_decision2 -> coding mode): + * 0 - 0 -> ACELP + * 1 - 0 -> GSC + * 1 - 1 -> TCX + *---------------------------------------------------------------------*/ + +void ivas_smc_mode_selection( + Encoder_State* st, /* i/o: encoder state structure */ + const int32_t element_brate, /* i : element bitrate */ + int16_t smc_dec, /* i : raw decision of the 1st stage classifier*/ + const float relE, /* i : relative frame energy */ + const float Etot, /* i : total frame energy */ + int16_t* attack_flag, /* i/o: attack flag (GSC or TC) */ + const float* inp, /* i : input signal */ + const float S_map[], /* i : short-term correlation map */ + const int16_t flag_spitch /* i : flag to indicate very short stable pitch*/ +) +{ + int16_t attack; + float ton; + int16_t i; + float S_p2a, S_max, S_ave; + float thr_sp2a; + + SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; + + /* initialization */ + *attack_flag = 0; + st->sp_aud_decision2 = 0; + + /* signal stability estimation */ + stab_est(Etot, hSpMusClas->gsc_lt_diff_etot, &hSpMusClas->gsc_mem_etot, &hSpMusClas->gsc_nb_thr_3, &hSpMusClas->gsc_nb_thr_1, hSpMusClas->gsc_thres, &hSpMusClas->gsc_last_music_flag, st->vad_flag); + + /* calculate variance of correlation */ + var_cor_calc(st->old_corr, &hSpMusClas->mold_corr, hSpMusClas->var_cor_t, &hSpMusClas->high_stable_cor); + + /* attack detection */ + attack = attack_det(inp, st->clas, st->localVAD, st->coder_type, 0, st->element_mode, st->clas, hSpMusClas->finc_prev, &hSpMusClas->lt_finc, &hSpMusClas->last_strong_attack); + + /* tonal detector */ + ton = tonal_det(S_map, st->vad_flag, hSpMusClas->tod_S_map_lt, &hSpMusClas->tod_thr_lt, &hSpMusClas->tod_weight, &hSpMusClas->tod_S_mass_prev, &hSpMusClas->tod_S_mass_lt); + + + /* calculate spectral peak-to-average ratio */ + for (i = 0; i < TOD_NSPEC; i++) + { + st->hSpMusClas->tod_lt_Bin_E[i] = P2A_FACT * st->hSpMusClas->tod_lt_Bin_E[i] + (1 - P2A_FACT) * st->Bin_E[i]; + } + + maximum(st->hSpMusClas->tod_lt_Bin_E, TOD_NSPEC, &S_max); + S_ave = sum_f(st->hSpMusClas->tod_lt_Bin_E, TOD_NSPEC) / TOD_NSPEC; + S_p2a = S_max - S_ave; + + + thr_sp2a = THR_P2A; + if (element_brate <= IVAS_16k4) + { + thr_sp2a = THR_P2A_HIGH; + } + + /* initial 3-way selection of coding modes (ACELP/GSC/TCX) */ + if (relE > -10.0f && (S_p2a > thr_sp2a || ton > hSpMusClas->tod_thr_lt)) + { + /* select TCX to encode extremely peaky signals or strongly tonal signals */ + st->sp_aud_decision1 = 1; + st->sp_aud_decision2 = 1; + } + else if (smc_dec == SPEECH) + { + /* select ACELP to encode speech */ + st->sp_aud_decision1 = 0; + st->sp_aud_decision2 = 0; + } + else if (smc_dec == SPEECH_OR_MUSIC) + { + /* select GSC to encode "unclear" segments (classifier's score on the borderline) */ + st->sp_aud_decision1 = 1; + st->sp_aud_decision2 = 0; + } + else + { + /* select TCX to encode music */ + st->sp_aud_decision1 = 1; + st->sp_aud_decision2 = 1; + } + + /* change decision from GSC to ACELP/TCX in some special cases */ + if (st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0) + { + if (hSpMusClas->ener_RAT < 0.18f && hSpMusClas->lt_dec_thres > 15.0f) + { + /* prevent GSC on strong music with almost no content below 1kHz */ + st->sp_aud_decision2 = 1; + } + else if (flag_spitch) + { + /* prevent GSC on signals with very short and stable high pitch period */ + if (hSpMusClas->wdlp_0_95_sp < 2.5f) + { + /* select ACELP instead */ + st->sp_aud_decision1 = 0; + } + else + { + /* select TCX instead */ + st->sp_aud_decision2 = 1; + } + } + else if (hSpMusClas->high_stable_cor && st->pitch[0] >= 130) + { + /* prevent GSC in highly correlated signal with low energy variation */ + /* this is basically a patch against bassoon-type of music */ + st->sp_aud_decision2 = 1; + } + } + + /* change decision from GSC to ACELP TC during attacks/onsets */ + if (st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0) + { + if ((hSpMusClas->gsc_lt_diff_etot[MAX_LT - 1] > 4.5f) && + (hSpMusClas->gsc_lt_diff_etot[MAX_LT - 1] - hSpMusClas->gsc_lt_diff_etot[MAX_LT - 2] > 10.0f)) + { + if (st->tc_cnt == 1) + { + /* do ACELP TC coding instead of GC/VC if onset has been already declared before */ + st->sp_aud_decision1 = 0; + st->coder_type = TRANSITION; + } + else + { + if (attack >= ATT_3LSUB_POS) + { + /* do ACELP TC coding also if attack is located in the last subframe */ + st->sp_aud_decision1 = 0; + *attack_flag = attack + 1; + st->coder_type = TRANSITION; + } + else if (attack >= ATT_SEG_LEN / 2) + { + /* do GSC coding if attack is located after the first quarter of the first subframe */ + /* (pre-echo will be treated at the decoder side) */ + *attack_flag = 31; + *attack_flag = attack + 1; + } + } + } + } + + if (st->localVAD == 1 && st->coder_type == GENERIC && attack > 0 /*&& *attack_flag < 32*/ /*&& st->tc_cnt != 2*/ && !(st->sp_aud_decision2 == 1 && ton > 0.65f)) + { + /* change ACELP coder_type to TC if attack has been detected */ + st->sp_aud_decision1 = 0; + st->sp_aud_decision2 = 0; + + st->coder_type = TRANSITION; + *attack_flag = attack + 1; + } + +#ifdef DEBUGGING + if (st->idchan == 0 && st->coder_type != INACTIVE) + { + if (st->force == FORCE_GSC && element_brate < IVAS_24k4) + { + /* enforce GSC */ + st->sp_aud_decision1 = 1; + st->sp_aud_decision2 = 0; + } + else if (st->force == FORCE_SPEECH && (st->sp_aud_decision1 == 1 || st->sp_aud_decision2 == 1)) + { + if (element_brate < IVAS_24k4) + { + /* convert TCX to GSC */ + st->sp_aud_decision1 = 1; + st->sp_aud_decision2 = 0; + } + else + { + /* convert TCX to ACELP */ + st->sp_aud_decision1 = 0; + st->sp_aud_decision2 = 0; + } + } + else if (st->force == FORCE_MUSIC) + { + /* enforce TCX */ + st->sp_aud_decision1 = 1; + st->sp_aud_decision2 = 1; + } + } +#endif + + /* set GSC noisy speech flag on unvoiced SWB segments */ + st->GSC_noisy_speech = 0; + if (st->vad_flag == 1 && element_brate <= IVAS_16k4 && st->lp_noise > 30.0f && st->sp_aud_decision1 == 0 && st->bwidth >= SWB && st->coder_type_raw == UNVOICED) + { + st->GSC_noisy_speech = 1; + } + + /* set GSC submode */ + if (st->element_mode > EVS_MONO && (st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0) && st->total_brate > STEREO_GSC_BIT_RATE_ALLOC) /* below STEREO_GSC_BIT_RATE_ALLOC, fall back on normal GSC */ + { + st->GSC_IVAS_mode = 1; + if (st->hSpMusClas->wdlp_0_95_sp > 0.0f) + { + /* music-like content */ + st->GSC_IVAS_mode = 3; + } + else if (st->tc_cnt > 0) + { + /* likely presence of an onset, GSC bit allocation will be more focused on LF */ + st->GSC_IVAS_mode = 2; + } + + if (st->coder_type_raw == UNVOICED && st->sp_aud_decision0 == 0 /*&& st->GSC_IVAS_mode < 3*/) + { + st->GSC_noisy_speech = 1; + } + else + { + st->GSC_noisy_speech = 0; + } + } + + /* set coder_type to AUDIO when GSC is selected (st->core will be set later in the decision matrix) */ + if ((st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0) || st->GSC_noisy_speech) + { + st->coder_type = AUDIO; + if (st->hGSCEnc != NULL && st->GSC_noisy_speech == 0) /* In case of GSC_noisy_speech, NOISE_LEVEL should remain at NOISE_LEVEL_SP3 */ + { + st->hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + } + } + + return; +} + +#endif + +/*---------------------------------------------------------------------* + * mode_decision_fx() + * + * + *---------------------------------------------------------------------*/ + +static Word16 mode_decision_fx( + Encoder_State_fx *st, /* i : endoer state structure */ + Word16 len, /* i : buffering status */ + Word16 *dec_mov, /* i/o: moving average of classifier decision Q15*/ + Word16 *buf_flux, /* i : buffer storing spectral energy fluctuation Q7*/ + Word16 *buf_epsP_tilt, /* i : buffer storing LP prediciton error tilt Q15*/ + Word16 *buf_pkh, /* i : buffer storing highband spectral peakiness Q1*/ + Word16 *buf_cor_map_sum, /* i : buffer storing correlation map sum Q8*/ + Word16 *buf_Ntonal, /* i : buffer storing No.of 1st spectral tone Q0*/ + Word16 *buf_Ntonal2, /* i : buffer storing No.of 2nd spectral tone Q0*/ + Word16 *buf_Ntonal_lf, /* i : buffer storing low band spectral tone ratio Q0*/ + Word16 *buf_dlp /* i : buffer storing log probability diff between speech and music Q9*/ +) +{ + Word16 mode; + Word16 i; + Word16 voiced_cnt; + Word16 M_pkh; + Word16 M_cor_map_sum; + Word16 M_Ntonal; + Word16 M_flux; + Word32 V_epsP_tilt; + Word16 lf_Ntonal_ratio; + Word16 tmp, tmp1; + Word32 L_tmp; + Word16 inv_len; + Word16 j; + Word16 M_flux10; + SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; + + + mode = *dec_mov > 16384; + logic16(); + move16(); + + IF ( LE_16(len,5)) + { + return (mode); + } + ELSE + { + IF ( LT_16(len,10)) + { + inv_len = div_s(1,len); /*Q15 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i3; i-- ) + { + if ( buf_dlp[i] > 0 ) + { + voiced_cnt = add(voiced_cnt,1); + } + } + + test(); + test(); + test(); + test(); + IF ( (GT_16(M_pkh,2200) || LT_32(V_epsP_tilt,171799) || GT_16(M_cor_map_sum,25600)) && LT_16(voiced_cnt, 4) ) + { + mode = 1; + move16(); + } + ELSE IF ( GT_16(M_Ntonal,108) && LT_16(voiced_cnt, 4)) /*27 in Q2 */ + { + mode = 1; + move16(); + } + } + ELSE + { + voiced_cnt = 0; + move16(); + FOR ( i=0; i<10; i++ ) + { + if ( buf_dlp[i] > 0 ) + { + voiced_cnt = add(voiced_cnt,1); + } + } + + inv_len = 3277; /*Q15 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<10; i++) + { + L_tmp = L_add(L_tmp,L_shl(buf_flux[BUF_LEN-10+i],2)); /*Q9 */ + } + L_tmp = Mult_32_16(L_tmp,inv_len); /*Q9 */ + M_flux10 = extract_l(L_tmp); /*Q9 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<10; i++) + { + L_tmp = L_add(L_tmp,buf_pkh[BUF_LEN-10+i]); /*Q1 */ + } + L_tmp = Mult_32_16(L_tmp,inv_len); /*Q1 */ + M_pkh = extract_l(L_tmp); /*Q1 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<10; i++) + { + L_tmp = L_add(L_tmp,buf_cor_map_sum[BUF_LEN-10+i]); /*Q8 */ + } + L_tmp = Mult_32_16(L_tmp,inv_len); /*Q8 */ + M_cor_map_sum = extract_l(L_tmp); /*Q8 */ + + V_epsP_tilt = var_fx_32( buf_epsP_tilt+BUF_LEN-10, 15, 10 ); /*Q31 */ + + L_tmp = L_deposit_l(0); + FOR(i=0; i<5; i++) + { + L_tmp = L_add(L_tmp,L_shl(buf_flux[BUF_LEN-5+i],2)); /*Q9 */ + } + L_tmp = Mult_32_16(L_tmp,6554); /*Q9 */ + tmp = extract_l(L_tmp); /*Q9 */ + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (LT_16(M_flux10,4352) || (LT_32(V_epsP_tilt,2147484) && LT_16(M_flux10,6144)) || GT_16(M_pkh,2100) || + GT_16(M_cor_map_sum,25600)) && LT_16(voiced_cnt,3) && LT_16(tmp,7680) ) + { + mode = 1; + move16(); + *dec_mov = 32767; + move16(); + return ( mode ); + } + + test(); + test(); + test(); + test(); + test(); + IF ( GT_16(M_flux10,8192) || (GT_16(M_flux10,7680) && GT_16(voiced_cnt, 2)) || GT_16(tmp,9728) || + (GE_16(buf_flux[59],2560) && GT_16(hSpMusClas->lps_fx, hSpMusClas->lpm_fx))) + { + mode = 0; + move16(); + *dec_mov = 0; + move16(); + return ( mode ); + } + + FOR ( i=10; i=0; i-- ) + { + IF (LE_16(Bin_E[i+1],Bin_E[i])) + { + BREAK; + } + k = i; + move16(); + } + + FOR ( i=1; ihSpMusClas; + + /* find sample with maximum absolute amplitude */ + max_spl = 0; + move16(); + FOR ( i=0; ivad_flag == 0 || LT_16(sub(st->lp_speech_fx,st->lp_noise_fx),6400)) /* 25 in Q8 */ + { + /* st->dec_mov = 0.5f; */ + /* st->dec_mov1 = 0.5f; */ + hSpMusClas->dec_mov_fx = 16384; + move16(); + hSpMusClas->dec_mov1_fx = 16384; + move16(); + + if (st->vad_flag == 0 ) + { + hSpMusClas->onset_cnt = 0; + move16(); + } + + return; + } + + hSpMusClas->onset_cnt = add(hSpMusClas->onset_cnt,1); + hSpMusClas->onset_cnt = s_min(hSpMusClas->onset_cnt, 9); + + IF ( EQ_16(hSpMusClas->onset_cnt,1)) + { + set16_fx(hSpMusClas->buf_flux_fx, -12800, BUF_LEN ); /*-100.0 in Q7 */ + } + + /* spectral analysis */ + spec_analysis_fx( st->lgBin_E_fx, p2v_map ); + + /* percussive music detection */ + log_max_spl = 0; + move16(); + IF ( max_spl ) + { + L_tmp = L_deposit_h(max_spl); /*Q16 */ + exp = norm_l(L_tmp); + frac = Log2_norm_lc(L_shl(L_tmp,exp)); + exp = sub(sub(30,exp),16); + L_tmp = Mpy_32_16(exp,frac,28391); /*Q12 */ + log_max_spl = round_fx(L_shl(L_tmp,11)); /*Q7 */ + } + + lt_diff = sub(log_max_spl, hSpMusClas->mov_log_max_spl_fx); /*Q7 */ + + FOR ( i=0; i<3; i++ ) + { + hSpMusClas->buf_etot_fx[i] = hSpMusClas->buf_etot_fx[i+1]; + move16(); /*Q8 */ + } + hSpMusClas->buf_etot_fx[i] = etot; + move16();/*Q8 */ + + percus_flag = 0; + move16(); + test(); + test(); + IF ( GT_16(sub(hSpMusClas->buf_etot_fx[1], hSpMusClas->buf_etot_fx[0]),1536)&& + LT_16(hSpMusClas->buf_etot_fx[2], hSpMusClas->buf_etot_fx[1]) && + GT_16(sub(hSpMusClas->buf_etot_fx[1], st->lp_speech_fx),768) ) /* 3 in Q8 */ + { + /*tmp = add(shr(voicing[0],2),shr(voicing[1],2)); //Q15 */ + /*tmp = add(tmp,shr(old_cor,1)); //Q15 */ + tmp = mac_r(L_mac(L_mult(st->voicing_fx[0],8192),st->voicing_fx[1],8192),old_cor, 16384); + test(); + test(); + IF ( GT_16(sub(hSpMusClas->buf_etot_fx[1], hSpMusClas->buf_etot_fx[3]),768)&& + LT_16(hSpMusClas->buf_etot_fx[3], hSpMusClas->buf_etot_fx[2]) && + LT_16(tmp,24576)) /* 0.75 in Q15 */ + { + IF ( GT_16(hSpMusClas->dec_mov_fx,26214)) /* 0.8 in Q15 */ + { + percus_flag = 1; + move16(); + } + ELSE + { + test(); + test(); + test(); + IF ( LT_16(old_cor,24576)&<_16(st->voicing_fx[0],24576)&<_16(st->voicing_fx[1],24576)&>_16(hSpMusClas->old_lt_diff_fx[0],1280)) + { + percus_flag = 1; + move16(); + } + } + } + } + + /* sound attack detection */ + test(); + test(); + test(); + IF ( GT_16(sub(hSpMusClas->buf_etot_fx[3], hSpMusClas->buf_etot_fx[2]),1536) + && GT_16(hSpMusClas->dec_mov_fx,29491) + && GT_16(sub(etot,st->lp_speech_fx),1280) + && GT_16(hSpMusClas->old_lt_diff_fx[0],640)) + { + hSpMusClas->attack_hangover = 3; + move16(); + } + + test(); + IF ( GT_16(st->voicing_fx[0],29491)&>_16(st->voicing_fx[1],29491)) + { + IF ( GT_16(log_max_spl, hSpMusClas->mov_log_max_spl_fx)) + { + /**mov_log_max_spl = add(mult_r(31130,(*mov_log_max_spl)),mult_r(1638,log_max_spl)); //Q7 */ + hSpMusClas->mov_log_max_spl_fx = round_fx(L_mac(L_mult(31130, hSpMusClas->mov_log_max_spl_fx),1638,log_max_spl)); /*Q7 */ + } + ELSE + { + /**mov_log_max_spl = add(mult_r(32604,(*mov_log_max_spl)),mult_r(164,log_max_spl)); //Q7 */ + hSpMusClas->mov_log_max_spl_fx = round_fx(L_mac(L_mult(32604,hSpMusClas->mov_log_max_spl_fx),164,log_max_spl)); /*Q7 */ + } + } + + hSpMusClas->old_lt_diff_fx[0] = hSpMusClas->old_lt_diff_fx[1]; + move16(); /*Q7 */ + hSpMusClas->old_lt_diff_fx[1] = lt_diff; + move16(); /*Q7 */ + + /* calculate and buffer spectral energy fluctuation */ + flux_fx( st->lgBin_E_fx, p2v_map, hSpMusClas->old_Bin_E_fx, hSpMusClas->buf_flux_fx, hSpMusClas->attack_hangover, hSpMusClas->dec_mov_fx ); + + hSpMusClas->attack_hangover = sub(hSpMusClas->attack_hangover,1); + hSpMusClas->attack_hangover = s_max(hSpMusClas->attack_hangover,0); + + /* identify flux buffer buffering status */ + len = 0; + move16(); + FOR ( i=BUF_LEN-1; i>=0; i-- ) + { + IF (hSpMusClas->buf_flux_fx[i] < 0) + { + BREAK; + } + + len = add(len,1); + } + + /* reset flux buffer if percussive music is detected */ + IF ( EQ_16(percus_flag,1)) + { + set16_fx( &hSpMusClas->buf_flux_fx[BUF_LEN-len], 640, len ); /* 5 in Q7 */ + } + + /* calculate and buffer the tilt of residual LP energies */ + ftmp = 0; + move16(); + ftmp1 = 0; + move16(); + FOR( i=1; i<=16; i++ ) + { + epsP_max = L_max(epsP_max , epsP[i]); + } + + FOR ( i=1; i<16; i++ ) + { + IF(EQ_32(epsP[i], epsP_max)) + { + tmp = -32768; + move16(); + L_tmp = Mult_32_16(epsP[i],tmp); /* Q_epsP */ + ftmp = L_sub(ftmp,L_shr(L_tmp,4)); /* Q(Q_epsP-4) */ + } + ELSE + { + expn = norm_l(epsP[i]); + fracn = extract_h(L_shl(epsP[i],expn)); + expn = sub(sub(30,expn),Q_epsP); + + expd = norm_l(epsP_max); + fracd = extract_h(L_shl(epsP_max,expd)); + expd = sub(sub(30,expd),Q_epsP); + + scale = shr(sub(fracd,fracn),15); + fracn = shl(fracn,scale); + expn = sub(expn,scale); + + tmp = div_s(fracn,fracd); /*Q(15+expd-expn) */ + tmp = shl(tmp,sub(expn,expd)); /*Q15 */ + + L_tmp = Mult_32_16(epsP[i],tmp); /*Q_epsP */ + ftmp = L_add(ftmp,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + } + + FOR ( i=1; i<16; i++ ) + { + IF(EQ_32(epsP[i], epsP_max)) + { + tmp = -32768; + move16(); + L_tmp = Mult_32_16(epsP[i+1],tmp); /*Q_epsP */ + ftmp1 = L_sub(ftmp1,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + ELSE IF(EQ_32(epsP[i+1],epsP_max)) + { + tmp = -32768; + move16(); + L_tmp = Mult_32_16(epsP[i],tmp); /*Q_epsP */ + ftmp1 = L_sub(ftmp1,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + ELSE + { + expn = norm_l(epsP[i]); + fracn = extract_h(L_shl(epsP[i],expn)); + expn = sub(sub(30,expn),Q_epsP); + + expd = norm_l(epsP_max); + fracd = extract_h(L_shl(epsP_max,expd)); + expd = sub(sub(30,expd),Q_epsP); + + scale = shr(sub(fracd,fracn),15); + fracn = shl(fracn,scale); + expn = sub(expn,scale); + + tmp = div_s(fracn,fracd); /*Q(15+expd-expn) */ + tmp = shl(tmp,sub(expn,expd)); /*Q15 */ + + L_tmp = Mult_32_16(epsP[i+1],tmp); /*Q_epsP */ + ftmp1 = L_add(ftmp1,L_shr(L_tmp,4)); /*Q(Q_epsP-4) */ + } + } + + /* epsP_tilt = ftmp1/ftmp; */ + expn = norm_l(ftmp1); + fracn = extract_h(L_shl(ftmp1,expn)); + expn = sub(sub(30,expn),Q_epsP-4); + + expd = norm_l(ftmp); + fracd = round_fx(L_shl(ftmp,expd)); + expd = sub(sub(30,expd),sub(Q_epsP,4)); + + scale = shr(sub(fracd,fracn),15); + fracn = shl(fracn,scale); + expn = sub(expn,scale); + + tmp = div_s(fracn,fracd); /*Q(15+expd-expn) */ + + epsP_tilt = shl(tmp,sub(expn,expd)); /*Q15 */ + + FOR ( i=0; ibuf_epsP_tilt_fx[i] = hSpMusClas->buf_epsP_tilt_fx[i+1]; + move16(); /*Q15 */ + } + hSpMusClas->buf_epsP_tilt_fx[i] = epsP_tilt; + move16(); /*Q15 */ + + /* calculate and buffer highband spectral peakness */ + tonal_dist_fx( p2v_map, hSpMusClas->buf_pkh_fx, hSpMusClas->buf_Ntonal_fx, hSpMusClas->buf_Ntonal2_fx, hSpMusClas->buf_Ntonal_lf_fx ); + + /* buffer sum of correlation map */ + FOR ( i=0; ibuf_cor_map_sum_fx[i] = hSpMusClas->buf_cor_map_sum_fx[i+1]; + move16(); /*Q8 */ + } + hSpMusClas->buf_cor_map_sum_fx[i] = cor_map_sum; + move16(); /*Q8 */ + + /* buffer voicing metric */ + FOR ( i=0; i<9; i++ ) + { + hSpMusClas->buf_dlp_fx[i] = hSpMusClas->buf_dlp_fx[i+1]; + move16(); + } + hSpMusClas->buf_dlp_fx[i] = sub(hSpMusClas->lps_fx, hSpMusClas->lpm_fx); + move16();/*Q9 */ + + /* classification */ + dec = mode_decision_fx( st, len, &hSpMusClas->dec_mov_fx, hSpMusClas->buf_flux_fx, hSpMusClas->buf_epsP_tilt_fx, hSpMusClas->buf_pkh_fx, + hSpMusClas->buf_cor_map_sum_fx, hSpMusClas->buf_Ntonal_fx, hSpMusClas->buf_Ntonal2_fx, hSpMusClas->buf_Ntonal_lf_fx, + hSpMusClas->buf_dlp_fx ); + move16(); + + /* update long term moving average of the classification decisions */ + IF ( GT_16(len,30)) + { + IF( dec == 0 ) + { + hSpMusClas->dec_mov_fx = mult_r(31785, hSpMusClas->dec_mov_fx); /*Q15 */ + hSpMusClas->dec_mov1_fx = mult_r(31785, hSpMusClas->dec_mov1_fx); /*Q15 */ + } + ELSE + { + hSpMusClas->dec_mov_fx = add(mult_r(31785,hSpMusClas->dec_mov_fx),983); /*Q15 */ + hSpMusClas->dec_mov1_fx = add(mult_r(31785, hSpMusClas->dec_mov1_fx),983); /*Q15 */ + } + } + + /* update long term unvoiced counter */ + test(); + test(); + test(); + IF ( (EQ_16(st->coder_type_raw_fx,UNVOICED)||EQ_16(st->coder_type_raw_fx,INACTIVE))&& + GT_16(etot,384) && LT_16(hSpMusClas->buf_Ntonal2_fx[59],2) ) + { + hSpMusClas->UV_cnt1 = sub(hSpMusClas->UV_cnt1,8); + } + ELSE + { + hSpMusClas->UV_cnt1 = add(hSpMusClas->UV_cnt1,1); + } + + hSpMusClas->UV_cnt1 = s_min(hSpMusClas->UV_cnt1,300); + hSpMusClas->UV_cnt1 = s_max(hSpMusClas->UV_cnt1,0); + + /**LT_UV_cnt1 = add(mult_r(29491,*LT_UV_cnt1),mult_r(3277,shl(*UV_cnt1,6)));*/ /* Q6 */ + hSpMusClas->LT_UV_cnt1_fx = round_fx(L_mac(L_mult(29491, hSpMusClas->LT_UV_cnt1_fx),3277,shl(hSpMusClas->UV_cnt1,6))); /*Q6 */ + + /* revert classification decision due to long-term unvoiced counter */ + test(); + test(); + IF ( EQ_16(dec,1)&<_16(hSpMusClas->dec_mov1_fx,6554)&<_16(hSpMusClas->LT_UV_cnt1_fx,12800)) + { + dec = 0; + move16(); + } + + /* overwrite 1st stage speech/music decision to music */ + IF (EQ_16(dec,1)) + { + st->sp_aud_decision1 = 1; + move16(); + } + + return; +} + + + +/*----------------------------------------------------------------------------------* + * tonal_context_improv_fx() + * + * Context-based improvement of 1st/2nd stage speech/music decision on stable tonal signals + *----------------------------------------------------------------------------------*/ + +static void tonal_context_improv_fx( + Encoder_State_fx *st_fx, /* i/o: Encoder state structure */ + const Word32 PS[], /* i : energy spectrum */ + const Word16 voi_fv, /* i : scaled voicing feature */ + const Word16 cor_map_sum_fv, /* i : scaled correlation map feature */ + const Word16 LPCErr, /* i : scaled LP prediction error feature */ + const Word16 Qx +) +{ + Word16 t2_fx, t3_fx, tL_fx, err_fx, cor_fx, dft_fx; + Word16 exp, expa, expb, fraca, fracb, scale, exp1, exp2, exp3, tmp; + Word16 voi_mean, lt_pitch_diff; + Word32 L_tmp, tonality, tonality1, tonality2, tonality3, sort_max, sort_avg, sort_val[80]; + VAD_HANDLE hVAD = st_fx->hVAD; + SP_MUS_CLAS_HANDLE hSpMusClas = st_fx->hSpMusClas; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + IF ( EQ_16(st_fx->last_codec_mode, MODE2)) + { + set16_fx(hSpMusClas->tonality2_buf_fx,0,HANG_LEN_INIT); + set16_fx(hSpMusClas->tonality3_buf_fx,0,HANG_LEN_INIT); + set16_fx(hSpMusClas->LPCErr_buf_fx,0,HANG_LEN_INIT); + hSpMusClas->lt_music_hangover = 0; + move16(); + hSpMusClas->lt_music_state = 0; + move16(); + hSpMusClas->lt_speech_state = 0; + move16(); + hSpMusClas->lt_speech_hangover= 0; + move16(); + } + + /* estimate maximum tonality in bands [0-1 kHz], [1-2kHz] and [2-4kHz] */ + Copy32( PS, sort_val, 80 ); + + /* tonality in band [0-1 kHz] */ + sort_32_fx(sort_val, 0, 19); + sort_max = L_add(sort_val[19], 0); + sort_avg = sum32_fx(&sort_val[0], 10); + + /* tonality1 = sort_max / sort_avg; */ + IF( sort_avg ) + { + expa = norm_l(sort_max); + fraca = extract_h(L_shl(sort_max,expa)); + expa = sub(30,add(expa, Qx)); + + expb = norm_l(sort_avg); + fracb = extract_h(L_shl(sort_avg,expb)); + expb = sub(30,add(expb, Qx)); + + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); + exp1 = sub(expa,expb); + +#ifdef BASOP_NOGLOB + tonality1 = L_shl_o(tmp , exp1, &Overflow); +#else /* BASOP_NOGLOB */ + tonality1 = L_shl(tmp , exp1); +#endif + } + ELSE + { + tonality1 = L_shl(sort_max,sub(15,Qx)); /*Q15 */ + } + + /* tonality in band [1-2 kHz] */ + sort_32_fx(sort_val, 20, 39); + sort_max = sort_val[39]; + sort_avg = sum32_fx(&sort_val[20], 10); + + IF( sort_avg ) + { + /* tonality2 = sort_max / sort_avg; */ + expa = norm_l(sort_max); + fraca = extract_h(L_shl(sort_max,expa)); + expa = sub(30,add(expa, Qx)); + + + expb = norm_l(sort_avg); + fracb = extract_h(L_shl(sort_avg,expb)); + expb = sub(30,add(expb, Qx)); + + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); + exp2 = sub(expa,expb); + +#ifdef BASOP_NOGLOB + tonality2 = L_shl_o(tmp , exp2, &Overflow); +#else + tonality2 = L_shl(tmp , exp2); +#endif + } + ELSE + { + tonality2 = L_shl(sort_max,sub(15,Qx)); /*Q15 */ + } + + /* tonality in band [2-4 kHz] */ + sort_32_fx(sort_val, 40, 79); + sort_max = sort_val[79]; + sort_avg = sum32_fx(&sort_val[40], 20); + + IF( sort_avg ) + { + /* tonality3 = sort_max / sort_avg; */ + expa = norm_l(sort_max); + fraca = extract_h(L_shl(sort_max,expa)); + expa = sub(30,add(expa, Qx)); + + expb = norm_l(sort_avg); + fracb = extract_h(L_shl(sort_avg,expb)); + expb = sub(30,add(expb, Qx)); + + scale = shr(sub(fracb,fraca),15); + fraca = shl(fraca,scale); + expa = sub(expa,scale); + + tmp = div_s(fraca,fracb); + exp3 = sub(expa,expb); + +#ifdef BASOP_NOGLOB + tonality3 = L_shl_o(tmp , exp3, &Overflow); +#else + tonality3 = L_shl(tmp , exp3); +#endif + } + ELSE + { + tonality3 = L_shl(sort_max,sub(15,Qx)); /*Q15 */ + } + + tonality = L_max(L_max(tonality1, tonality2), tonality3); + + /* voi_mean = 0.33f * (st->voicing_fx[0] + voicing[1] + voicing[2]); */ + L_tmp = L_mult(st_fx->voicing_fx[0], 10923); + L_tmp = L_mac(L_tmp, st_fx->voicing_fx[1], 10923); + voi_mean = mac_r(L_tmp, st_fx->voicing_fx[2], 10923); /* Q15 */ + + test(); + IF( EQ_16(hVAD->hangover_cnt,10) && EQ_16(st_fx->vad_flag,1)) + { + /* long-term voicing parameter */ + hSpMusClas->lt_voicing = round_fx(L_mac(L_mult(3277,hSpMusClas->lt_voicing),29491, voi_mean)); + + /* long-term correlation value */ + hSpMusClas->lt_corr = round_fx(L_mac(L_mult(3277,hSpMusClas->lt_corr),29491, st_fx->old_corr_fx)); + + /* long-term tonality measure */ + hSpMusClas->lt_tonality = L_add(Mult_32_16(hSpMusClas->lt_tonality,3277),Mult_32_16(tonality,29491)); + } + ELSE + { + /* long-term voicing parameter */ + hSpMusClas->lt_voicing = round_fx(L_mac(L_mult(22938,hSpMusClas->lt_voicing),9830, voi_mean)); + + /* long-term correlation value */ + hSpMusClas->lt_corr = round_fx(L_mac(L_mult(22938,hSpMusClas->lt_corr),9830, st_fx->old_corr_fx)); + + /* long-term tonality measure */ + hSpMusClas->lt_tonality = L_add(Mult_32_16(hSpMusClas->lt_tonality,16384),Mult_32_16(tonality,16384)); + } + + /* Pitch difference w.r.t to past 3 frames */ + lt_pitch_diff = abs_s(sub(hSpMusClas->lt_corr_pitch[0], st_fx->pitch_fx[0])); + lt_pitch_diff = add(lt_pitch_diff , abs_s(sub(hSpMusClas->lt_corr_pitch[1], st_fx->pitch_fx[0]))); + lt_pitch_diff = add(lt_pitch_diff,abs_s(sub(hSpMusClas->lt_corr_pitch[2], st_fx->pitch_fx[0]))); + + hSpMusClas->lt_corr_pitch[0] = hSpMusClas->lt_corr_pitch[1]; + move16(); + hSpMusClas->lt_corr_pitch[1] = hSpMusClas->lt_corr_pitch[2]; + move16(); + hSpMusClas->lt_corr_pitch[2] = st_fx->pitch_fx[0]; + move16(); + + hSpMusClas->lt_old_mode[0] = hSpMusClas->lt_old_mode[1]; + move16(); + hSpMusClas->lt_old_mode[1] = hSpMusClas->lt_old_mode[2]; + move16(); + + test();test();test();test();test();test();test();test();test();test();test();test();test(); + IF (st_fx->sp_aud_decision1 == 1 && + ( GT_32(L_min(L_min(tonality1, tonality2), tonality3),1638400) ) && + ( GT_32(L_add(tonality1, tonality2),6553600) && GT_32(L_add(tonality2, tonality3),6553600) && GT_32(L_add(tonality1, tonality3),6553600)) && + ( LT_32(hSpMusClas->lt_tonality,655360000) ) && + ( ( GT_32(hSpMusClas->lt_tonality,32768000) && GT_16(s_max(hSpMusClas->lt_voicing, voi_mean),32440) ) || + ( GT_32(hSpMusClas->lt_tonality,49152000) && GT_16(hSpMusClas->lt_corr,32440) ) || + ( GT_32(hSpMusClas->lt_tonality,98304000) && GT_16(hSpMusClas->lowrate_pitchGain,15729) ) || + ( lt_pitch_diff == 0 && GT_16(hSpMusClas->lowrate_pitchGain,14582)))) + { + IF( LT_16(sum16_fx(hSpMusClas->lt_old_mode, 2),2)) + { + /* probably speech - change the decision to speech */ + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 0; + move16(); + + if( hSpMusClas->lt_hangover == 0 ) + { + hSpMusClas->lt_hangover = 6; + move16(); + } + } + } + ELSE + { + /* not speech, but still in the hangover period - change the decision to speech */ + IF( hSpMusClas->lt_hangover > 0 ) + { + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 0; + move16(); + + hSpMusClas->lt_hangover = sub(hSpMusClas->lt_hangover,1); + } + } + + /* calculate standard deviation of log-tonality */ + Copy( hSpMusClas->tonality2_buf_fx + 1, hSpMusClas->tonality2_buf_fx, HANG_LEN_INIT - 1 ); + /* st->tonality2_buf[HANG_LEN_INIT - 1] = 0.2f*(float)log10(tonality2); */ + exp = norm_l(tonality2); + tmp = Log2_norm_lc(L_shl(tonality2, exp));/*15 */ + exp = sub(30, add(exp, 16)); + L_tmp = Mpy_32_16(exp, tmp, 15783);/*19 //3945, 0.2*log10(2), Q18 */ + hSpMusClas->tonality2_buf_fx[HANG_LEN_INIT - 1] = round_fx(L_shl(L_tmp, 11));/*14 */ + /* t2 = std( st->tonality2_buf, HANG_LEN_INIT ); */ + t2_fx = std_fx( hSpMusClas->tonality2_buf_fx, HANG_LEN_INIT ); /*14 */ + + Copy( hSpMusClas->tonality3_buf_fx + 1, hSpMusClas->tonality3_buf_fx, HANG_LEN_INIT - 1 ); + /* st->tonality3_buf[HANG_LEN_INIT - 1] = 0.2f*(float)log10(tonality3); */ + exp = norm_l(tonality3); + tmp = Log2_norm_lc(L_shl(tonality3, exp));/*15 */ + exp = sub(30, add(exp, 16)); + L_tmp = Mpy_32_16(exp, tmp, 15783);/*19 //3945, 0.2*log10(2), Q18 */ + hSpMusClas->tonality3_buf_fx[HANG_LEN_INIT - 1] = round_fx(L_shl(L_tmp, 11));/*14 */ + t3_fx = std_fx( hSpMusClas->tonality3_buf_fx, HANG_LEN_INIT ); /*14 */ + + /* tL = 0.2f*(float)log10(st->lt_tonality); */ + exp = norm_l(hSpMusClas->lt_tonality); + tmp = Log2_norm_lc(L_shl(hSpMusClas->lt_tonality, exp));/*15 */ + exp = sub(30, add(exp, 16)); + L_tmp = Mpy_32_16(exp, tmp, 15783);/*19 //3945, 0.2*log10(2), Q18 */ + tL_fx = round_fx(L_shl(L_tmp, 11));/*14 */ + + /* calculate standard deviation of residual LP energy */ + Copy( hSpMusClas->LPCErr_buf_fx + 1, hSpMusClas->LPCErr_buf_fx, HANG_LEN_INIT - 1 ); + hSpMusClas->LPCErr_buf_fx[HANG_LEN_INIT - 1] = LPCErr; + /* err = std( st->LPCErr_buf, HANG_LEN_INIT ); */ + err_fx = std_fx( hSpMusClas->LPCErr_buf_fx, HANG_LEN_INIT ); + + cor_fx = s_max(sub(voi_fv, cor_map_sum_fv), 0);/*15 */ + dft_fx = abs_s(sub(hSpMusClas->tonality2_buf_fx[HANG_LEN_INIT - 1], hSpMusClas->tonality3_buf_fx[HANG_LEN_INIT - 1]));/*14 */ + + + /* state machine for strong music */ + test();test();test();test();test();test();test();test();test();test();test();test(); + IF ( (EQ_16(st_fx->sp_aud_decision1, 1)) && hSpMusClas->lt_music_state==0 && hSpMusClas->lt_music_hangover==0 && + (LT_16(t2_fx, 8847)) && (GT_16(t2_fx, 4260)) && (GT_16(t3_fx, 3604)) && (LT_16(tL_fx, 8847)) && (GT_16(tL_fx, 4260)) && (GT_16(err_fx, 8192)) ) + { + hSpMusClas->lt_music_state = 1; + move16(); + hSpMusClas->lt_music_hangover = 6; + move16(); + } + ELSE IF( EQ_16(hSpMusClas->lt_music_state, 1) && hSpMusClas->lt_music_hangover==0 && + (LT_16(t2_fx, 5571) ) && (LT_16(t3_fx, 4260) ) && (LT_16(tL_fx, 7373) ) ) + { + hSpMusClas->lt_music_state = 0; + move16(); + hSpMusClas->lt_music_hangover = 6; + move16(); + } + + IF ( hSpMusClas->lt_music_hangover > 0 ) + { + hSpMusClas->lt_music_hangover = sub(hSpMusClas->lt_music_hangover,1); + } + + /* state machine for strong speech */ + test();test();test();test();test();test();test();test();test();test();test();test();test(); + IF ( (EQ_16(st_fx->sp_aud_decision1, 1)) && hSpMusClas->lt_speech_state==0 && hSpMusClas->lt_speech_hangover==0 && + (GT_16(cor_fx, 13107)) && (LT_16(dft_fx, 1638)) && GT_16(shr(voi_fv,1), add(cor_map_sum_fv, 1966)) && + (LT_16(t2_fx, shr(cor_fx, 1))) && (LT_16(t3_fx, shr(cor_fx, 1))) && (LT_16(tL_fx, shr(cor_fx, 1))) && + (LT_16(cor_map_sum_fv, cor_fx)) && (GT_16(voi_fv, cor_fx)) && (GT_16(voi_fv, 24903) ) ) + { + hSpMusClas->lt_speech_state = 1; + move16(); + hSpMusClas->lt_speech_hangover = 6; + move16(); + } + ELSE IF ( (EQ_16(hSpMusClas->lt_speech_state, 1)) && hSpMusClas->lt_speech_hangover==0 &&(LT_16(cor_fx,13107))) + { + hSpMusClas->lt_speech_state = 0; + move16(); + hSpMusClas->lt_speech_hangover = 6; + move16(); + } + + IF ( hSpMusClas->lt_speech_hangover > 0) + { + hSpMusClas->lt_speech_hangover = sub(hSpMusClas->lt_speech_hangover,1); + } + + /* final decision */ + test(); + test(); + IF ( EQ_16(st_fx->sp_aud_decision1,1) && EQ_16(hSpMusClas->lt_speech_state,1)) + { + /* strong speech - probably error in speech/music classification */ + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 0; + move16(); + } + ELSE IF (st_fx->sp_aud_decision1 == 0 && EQ_16(hSpMusClas->lt_speech_state,1)) + { + /* strong music - probably error in speech/music classification */ + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 0; + move16(); + } + + /* update the buffer of past decisions */ + hSpMusClas->lt_old_mode[2] = st_fx->sp_aud_decision1; + move16(); + + return; +} + +/*----------------------------------------------------------------------------------* + * detect_sparseness_fx() + * + * + *----------------------------------------------------------------------------------*/ +static void detect_sparseness_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 localVAD_HE_SAD, /* i : HE-SAD flag without hangover */ + const Word16 voi_fv /* i : scaled voicing feature */ +) +{ + Word16 sum, sumh; + Word32 L_tmp,L_tmp1; + Word16 tmp, tmp1; + Word16 S1[128]; + Word16 i,j; + Word16 hb_sp_high_flag = 0; + Word16 lb_sp_high_flag = 0; + Word16 sparse; + Word16 tmp_buf[4]; + Word16 Mlpe=0, Mv=0, Msp; + SP_MUS_CLAS_HANDLE hSpMusClas = st_fx->hSpMusClas; + + Copy(st_fx->lgBin_E_fx, S1, 128); + + L_tmp = L_deposit_l(0); + FOR (i = 0; i < 80; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); /* Q7 */ + } + L_tmp = L_add(L_tmp, L_deposit_l(S1[i])); + } + + L_tmp1 = L_deposit_l(0); + FOR (i = 80; i < 128; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + L_tmp1 = L_add(L_tmp1, L_deposit_l(S1[i])); + } + + sumh = extract_l(L_shr(L_tmp1, 7)); /* Q0 */ + sum = add(extract_l(L_shr(L_tmp, 7)), sumh); /* Q0 */ + + /* order spectral from max to min */ + order_spectrum_fx(S1, 128); + + /* calculate spectral sparseness in the range 0 - 6.4 kHz */ + j = 0; + move16(); + L_tmp = 0; + move16(); + L_tmp1 = L_deposit_l(mult(sum, 24576)); + FOR (i = 0; i < 128; i++) + { + L_tmp = L_add(L_tmp, L_deposit_l(S1[i])); + IF (GT_32(L_shr(L_tmp, 7), L_tmp1)) + { + j = i; + move16(); + BREAK; + } + } + + FOR (i = 0; i < HANG_LEN_INIT-1; i++) + { + hSpMusClas->sparse_buf_fx[i] = hSpMusClas->sparse_buf_fx[i+1]; + move16(); + } + + sparse = j; + move16(); + hSpMusClas->sparse_buf_fx[i] = sparse; + move16(); + + IF (EQ_16(st_fx->bwidth_fx, WB)) + { + Msp = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + Msp = add(Msp, hSpMusClas->sparse_buf_fx[i]); + } + Msp = shl(Msp, 5); /* Q8 */ + + /* find long-term smoothed sparseness */ + IF (st_fx->last_vad_spa_fx == 0 ) + { + set16_fx( &hSpMusClas->sparse_buf_fx[0], sparse, HANG_LEN_INIT-1 ); + hSpMusClas->LT_sparse_fx = sparse; + move16(); + } + ELSE + { + set16_fx(tmp_buf, 0, 4); + + FOR (i = 0; i < HANG_LEN_INIT; i++) + { + FOR (j = 0; j < 4; j++) + { + IF (GT_16(hSpMusClas->sparse_buf_fx[i], tmp_buf[j])) + { + Copy(&tmp_buf[j], &tmp_buf[j+1], sub(3, j)); + tmp_buf[j] = hSpMusClas->sparse_buf_fx[i]; + move16(); + BREAK; + } + } + } + + /* ftmp = 0.25f*(HANG_LEN_INIT*Msp - sum_f(tmp_buf, 4)) - st->LT_sparse; */ + tmp = shl(sum16_fx(tmp_buf, 4), 5); + tmp = shl(sub(Msp, tmp), 1); + tmp = sub(tmp, hSpMusClas->LT_sparse_fx); + + hSpMusClas->LT_sparse_fx = add(hSpMusClas->LT_sparse_fx, shr(tmp, 2)); /* Q8 */ + } + + /* find high-band sparseness */ + Copy(st_fx->lgBin_E_fx+80, S1, 48); + + order_spectrum_fx(S1, 48); + + FOR (i = 0; i < HANG_LEN_INIT-1; i++) + { + hSpMusClas->hf_spar_buf_fx[i] = hSpMusClas->hf_spar_buf_fx[i+1]; + move16(); + } + + /* st_fx->hf_spar_buf_fx[i] = sum_f(S1, 5)/sumh; */ + L_tmp = L_deposit_l(0); + FOR (i = 0; i < 5; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + + L_tmp = L_add(L_tmp, S1[i]); + } + + tmp = extract_l(L_shr(L_tmp, 7)); + IF (tmp == 0) + { + hSpMusClas->hf_spar_buf_fx[HANG_LEN_INIT-1] = 0; + move16(); + } + ELSE + { + hSpMusClas->hf_spar_buf_fx[HANG_LEN_INIT-1] = div_s(tmp, sumh); + } + + tmp = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + tmp = add(tmp, shr(hSpMusClas->hf_spar_buf_fx[i], 3)); + } + IF (GT_16(tmp, 6554)) + { + hb_sp_high_flag = 1; + move16(); + } + + /* find low-band sparseness */ + Copy(st_fx->lgBin_E_fx, S1, 60); + + order_spectrum_fx(S1, 60); + L_tmp = L_deposit_l(0); + L_tmp1 = L_deposit_l(0); + FOR (i = 0; i < 5; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + + L_tmp = L_add(L_tmp, S1[i]); + } + + FOR (; i < 60; i++) + { + if (S1[i] < 0) + { + S1[i] = 0; + move16(); + } + + L_tmp1 = L_add(L_tmp1, S1[i]); + } + + /* if ( sum_f(S1, 5)/sum_f(S1,60) > 0.18f ) */ + tmp = extract_l(L_shr(L_tmp, 7)); + IF (tmp != 0) + { + tmp = div_s(tmp, add(tmp, extract_l(L_shr(L_tmp1, 7)))); + if (GT_16(tmp, 5898)) + { + lb_sp_high_flag = 1; + move16(); + } + } + + /* find smoothed linear prediction efficiency */ + FOR (i = 0; i < 7; i++) + { + hSpMusClas->lpe_buf_fx[i] = hSpMusClas->lpe_buf_fx[i+1]; + move16(); + } + + hSpMusClas->lpe_buf_fx[i] = hSpMusClas->past_epsP2_fx; + move16(); + Mlpe = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + Mlpe = add(Mlpe, shr(hSpMusClas->lpe_buf_fx[i], 3)); + } + + /* find smoothed voicing */ + FOR (i = 0; i < HANG_LEN_INIT-1; i++) + { + hSpMusClas->voicing_buf_fx[i] = hSpMusClas->voicing_buf_fx[i+1]; + move16(); + } + + hSpMusClas->voicing_buf_fx[i] = voi_fv; + move16(); + Mv = 0; + move16(); + FOR (i = 0; i < 8; i++) + { + Mv = add(Mv, shr(hSpMusClas->voicing_buf_fx[i], 3)); + } + } + + /* avoid using LR-MDCT on sparse spectra */ + IF (EQ_16(st_fx->sp_aud_decision1, 1)) + { + tmp = 91; + move16(); + if (EQ_16(st_fx->bwidth_fx, WB)) + { + tmp = 90; + } + + IF (GT_16(sparse, tmp)) + { + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 1; + move16(); + hSpMusClas->gsc_hangover = 1; + move16(); + } + ELSE IF (EQ_16(hSpMusClas->gsc_hangover, 1)) + { + IF (GT_16(sparse, 85)) + { + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 1; + move16(); + } + ELSE + { + tmp = 0; + move16(); + FOR (i=0; igsc_cnt; i++) + { + tmp = add(tmp, hSpMusClas->sparse_buf_fx[HANG_LEN_INIT-1-hSpMusClas->gsc_cnt+i]); + } + tmp1 = div_s(1, hSpMusClas->gsc_cnt); + tmp = mult(tmp, tmp1); + + IF (LT_16(abs_s(sub(sparse, tmp)), 7)) + { + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 1; + move16(); + } + } + } + + IF (EQ_16(st_fx->bwidth_fx, WB)) + { + test();test();test();test();test();test();test();test();test(); + IF (GT_16(hSpMusClas->LT_sparse_fx, 15360) && GT_16(sparse,50) && LT_16(Mlpe,-1331) && GT_16(Mv,27853) && + lb_sp_high_flag == 0 && ((hb_sp_high_flag == 0 && GT_16(sumh, mult_r(4915, sum))) || LE_16(sumh, mult_r(4915, sum)))) + { + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 1; + move16(); + hSpMusClas->gsc_hangover = 1; + move16(); + } + ELSE IF (EQ_16(hSpMusClas->gsc_hangover, 1) && !(st_fx->sp_aud_decision1==0 && st_fx->sp_aud_decision2==1)) + { + IF (LT_16(abs_s(sub(sparse, mean_fx(&hSpMusClas->sparse_buf_fx[HANG_LEN_INIT-1-hSpMusClas->gsc_cnt], hSpMusClas->gsc_cnt))), 7)) + { + st_fx->sp_aud_decision1 = 0; + move16(); + st_fx->sp_aud_decision2 = 1; + move16(); + } + } + } + } + + /* update the counter of consecutive GSC frames with sparse spectrum */ + test(); + IF (st_fx->sp_aud_decision1 == 0 && EQ_16(st_fx->sp_aud_decision2, 1)) + { + hSpMusClas->gsc_cnt = add(hSpMusClas->gsc_cnt, 1); + IF (GT_16(hSpMusClas->gsc_cnt, 7)) + { + hSpMusClas->gsc_cnt = 7; + move16(); + } + } + ELSE + { + hSpMusClas->gsc_cnt = 0; + move16(); + hSpMusClas->gsc_hangover = 0; + move16(); + } + + st_fx->last_vad_spa_fx = localVAD_HE_SAD; + move16(); + + return; +} + +/*---------------------------------------------------------------------* + * order_spectrum() + * + * + *---------------------------------------------------------------------*/ +static void order_spectrum_fx( + Word16 *vec, + Word16 len +) +{ + Word16 i, j, end, end_1, len_2, tmp; + Word16 smax, smin; + Word16 imax, imin; + + len_2 = shr(len, 1); + FOR(i = 0; i < len_2; i++) + { + imax = i; + move16(); + imin = i; + move16(); + smax = vec[i]; + move16(); + smin = vec[i]; + move16(); + end = sub(len, i); + FOR(j = i; j < end; j++) + { + IF(GT_16(vec[j], smax)) + { + smax = vec[j]; + move16(); + imax = j; + move16(); + } + ELSE + { + IF(LT_16(vec[j], smin) ) + { + smin = vec[j]; + move16(); + imin = j; + move16(); + } + } + } + + tmp = vec[i]; + move16(); + vec[i] = smax; + move16(); + vec[imax] = tmp; + move16(); + + IF(EQ_16(imin, i)) + { + imin = imax; + move16(); + } + + end_1 = sub(end, 1); + tmp = vec[end_1]; + move16(); + vec[end_1] = smin; + move16(); + vec[imin] = tmp; + move16(); + } +} + diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 20cdde9c4ebf7a91d9b1fc847bf4dba8f90d2eb7..ee33099b9e671929f51e40e72e498f3e32f87a61 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -56,6 +56,17 @@ typedef struct int16_t nb_bits; /* number of bits used for the quantization of the indice */ } Indice, *INDICE_HANDLE; +typedef struct +{ + Word32 r; + Word32 i; +} complex_32; +typedef struct +{ + Word16 r; + Word16 i; +} complex_16; + typedef struct { Word16 s16Exp; @@ -167,6 +178,7 @@ typedef struct /* Attack detection function. */ typedef void ( *TCheckSubblocksForAttack )( const float *pSubblockNrg, const float *pAccSubblockNrg, int16_t nSubblocks, int16_t nPastSubblocks, float attackRatioThreshold, int16_t *pbIsAttackPresent, int16_t *pAttackIndex ); +typedef void(*TCheckSubblocksForAttack_fx)(Word32 const * pSubblockNrg, Word32 const * pAccSubblockNrg, Word16 nSubblocks, Word16 nPastSubblocks, Word16 attackRatioThreshold, Word16 * pbIsAttackPresent, Word16 * pAttackIndex); /* Transient detector. */ typedef struct TransientDetector @@ -175,6 +187,7 @@ typedef struct TransientDetector int16_t nDelay; /* Delay of the transient detector in number of subblocks, nDelay <= pSubblockEnergies->nDelay. */ int16_t nSubblocksToCheck; /* Number of subblocks to check for transients. */ TCheckSubblocksForAttack CheckSubblocksForAttack; /* Function for checking a presence of an attack. */ + TCheckSubblocksForAttack_fx CheckSubblocksForAttack_fx; /* Function for checking a presence of an attack. */ float attackRatioThreshold_flt; /* Attack ratio threshold. */ Word16 attackRatioThreshold; int16_t bIsAttackPresent; /* True when an attack was detected. */ @@ -248,7 +261,6 @@ typedef struct vad_structure } VAD_DATA, *VAD_HANDLE; - typedef struct cldfb_vad_structure { int16_t bw_index; /* index of band width */ @@ -301,6 +313,67 @@ typedef struct cldfb_vad_structure } T_CldfbVadState, *VAD_CLDFB_HANDLE; +typedef struct +{ + Word16 bw_index; /* index of band width */ + + /* feature */ + Word16 sp_center[SP_CENTER_NUM]; /* spectral center*/ + Word16 ltd_stable_rate[STABLE_NUM]; /* time-domain stable rate*/ + Word16 sfm[SFM_NUM]; /* spectral flatness*/ + Word16 f_tonality_rate[TONA_NUM]; /* tonality rate*/ + Word16 pre_spec_low_dif[PRE_SPEC_DIF_NUM]; /* low frequency spectral different*/ + Word32 frames_power_32[POWER_NUM]; /* energy of several frames*/ + Word32 frame_sb_energy[BG_ENG_NUM]; /* energy of sub-band divided non-uniformly*/ + Word32 t_bg_energy; /* time background energy of several frames*/ + T_VAD_EXP t_bg_energy_sum; /* number of time background energy*/ + Word16 tbg_energy_count; /* sum of time background energy of several frames*/ + Word16 bg_update_count; /* time of background update*/ + Word32 frame_energy_smooth; /* smoothed energy of several frames*/ + + /************************************************************************/ + /* history parameters */ + /************************************************************************/ + Word32 smooth_spec_amp[SPEC_AMP_NUM]; /* smoothed spectral amplitude*/ + Word32 pre_snr[PRE_SNR_NUM]; /* previous time SNR*/ + Word32 sb_bg_energy[BG_ENG_NUM]; /* sub-band background energy*/ + Word16 continuous_noise_num; /* time of continuous noise frames*/ + Word16 continuous_speech_num; /* time of continuous speech frames*/ + Word16 continuous_speech_num2; /* time 2 of continuous speech frames*/ + Word32 fg_energy_est_start; /* flag by that indicate whether if estimate energy*/ + Word16 speech_flag; /* residual number of hangover 1 */ + Word32 lt_noise_sp_center_diff_counter; /* number of the member lt_noise_sp_center_diff_sum*/ + Word32 fg_energy; /* foreground energy sum */ + Word32 bg_energy; /* background energy sum */ + Word32 lt_bg_highf_eng; /* average of long time high frequency energy*/ + Word32 lt_noise_sp_center_diff_sum; /* different sum of long time noise sp_center*/ + Word32 lt_snr_org; /* original long time SNR*/ + Word32 l_speech_snr; /* sum of snr's of active frames*/ + Word32 l_silence_snr; /* sum of snr's of non active frames*/ + Word32 l_speech_snr_count; /* number of active frames*/ + Word32 l_silence_snr_count; /* number of non active frames*/ + Word32 lf_snr_smooth; /* smoothed lf_snr*/ + Word16 frameloop; /* number of frame*/ + Word16 lt_noise_sp_center0; /* long time noise sp_center0*/ + Word16 lt_noise_sp_center3; /* long time noise sp_center3*/ + Word16 music_background_rate; /* music background rate*/ + Word16 tonality_rate3; /* tonality rate*/ + Word16 bg_energy_count; /* number of the background energy frame */ + Word16 fg_energy_count; /* number of the foreground energy frame */ + Word16 Q_frames_power_32; /* the Scaling of frames_power_fix32*/ + Word16 scale_spec_low_dif; /* the Scaling of spec_low_dif*/ + Word16 sb_bg_energy_scale; /* the Scaling of sb_bg_energy*/ + Word16 frame_sb_energy_scale; /* the Scaling of frame_sb_energy*/ + Word16 scale_t_bg_energy; /* the Scaling of t_bg_energy*/ + Word16 frame_energy_smooth_scale; /* the Scaling of frame_energy_smooth*/ + Word16 bg_energy_scale; /* the Scaling of bg_energy*/ + Word16 fg_energy_scale; /* the Scaling of fg_energy*/ + Word16 updateNumWithSnr; /* the number of the background update with SNR*/ + Word16 update_count; /* the number of the background update*/ + Word16 warm_hang_num; /* the number of hangover for warm up*/ + Word16 vad_flag_for_bk_update; +} T_CldfbVadState_fx, *VAD_CLDFB_HANDLE_FX; + /*------------------------------------------------------------------------------------------* * DTX and TD CNG structure @@ -329,6 +402,9 @@ typedef struct td_cng_enc_structure int16_t ho_hist_size; /* CNG and DTX - size of DTX hangover history buffer for averaging, <0,HO_HIST_SIZE> */ int16_t ho_hist_ptr; /* CNG and DTX - pointer for averaging buffers */ int32_t ho_sid_bw; /* CNG and DTX - SID bandwidth flags */ + Word16 ho_lsp_hist_fx[HO_HIST_SIZE * M]; /* CNG and DTX - old LSP buffer for averaging */ + Word32 ho_ener_hist_fx[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ + Word32 ho_env_hist_fx[HO_HIST_SIZE * NUM_ENV_CNG]; float ho_lsp_hist[HO_HIST_SIZE * M]; /* CNG and DTX - old LSP buffer for averaging */ float ho_ener_hist[HO_HIST_SIZE]; /* CNG and DTX - energy buffer for averaging */ float ho_env_hist[HO_HIST_SIZE * NUM_ENV_CNG]; @@ -383,7 +459,6 @@ typedef struct td_cng_enc_structure } TD_CNG_ENC_DATA, *TD_CNG_ENC_HANDLE; - /*------------------------------------------------------------------------------------------* * FD CNG arrays and variables *------------------------------------------------------------------------------------------*/ @@ -426,7 +501,50 @@ typedef struct fd_cng_enc_structure float mem_coherence[4]; } FD_CNG_ENC, *HANDLE_FD_CNG_ENC; - +typedef struct +{ + HANDLE_FD_CNG_COM hFdCngCom; + + Word32 msPeriodog[NPART]; /* Periodogram */ + Word16 msPeriodog_exp; /* Common exponent for fft and cldfb energies */ + Word16 msPeriodog_exp_fft; + Word16 msPeriodog_exp_cldfb; + Word32 msBminWin[NPART]; + Word32 msBminSubWin[NPART]; + Word16 msPsd[NPART]; /* Power Spectral Density estimate (i.e., smoothed periodogram) */ + Word32 msAlpha[NPART]; /* Optimal smoothing parameter */ + Word32 msMinBuf[MSNUMSUBFR*NPART]; /* Buffer of minima */ + Word32 msCurrentMinOut[NPART]; + Word32 msCurrentMin[NPART]; + Word32 msCurrentMinSubWindow[NPART]; + Word16 msLocalMinFlag[NPART]; + Word16 msNewMinFlag[NPART]; + Word16 msPsdFirstMoment[NPART]; + Word32 msPsdSecondMoment[NPART]; + Word16 msNoiseFloor[NPART]; /* Estimated noise floor */ + Word32 msNoiseEst[NPART]; /* Estimated noise level */ + Word16 msNoiseEst_exp; + Word32 energy_ho[NPART]; + Word16 energy_ho_exp; + Word32 msNoiseEst_old[NPART]; + Word16 msNoiseEst_old_exp; + + Word16 msPeriodogBuf[MSBUFLEN*NPART]; + Word16 msPeriodogBufPtr; + + Word16 stopFFTbinDec; + Word16 startBandDec; + Word16 stopBandDec; + Word16 npartDec; + Word16 midbandDec[NPART]; + Word16 nFFTpartDec; + Word16 partDec[NPART]; + + Word16 msLogPeriodog[NPART]; + Word16 msLogNoiseEst[NPART]; +} +FD_CNG_ENC_FX; +typedef FD_CNG_ENC_FX *HANDLE_FD_CNG_ENC_FX; /*------------------------------------------------------------------------------------------* * Structure for DTX-related variables used in both FD- and TD-CNG *------------------------------------------------------------------------------------------*/ @@ -458,7 +576,6 @@ typedef struct dtx_enc_structure } DTX_ENC_DATA, *DTX_ENC_HANDLE; - /*----------------------------------------------------------------------------------* * IGF structures *----------------------------------------------------------------------------------*/ @@ -483,6 +600,7 @@ typedef struct igfscfenc_public_data_struct const uint16_t *cf_se11; const int16_t *cf_off_se11; Tastat acState; + TastatEnc acState_fx; } IGFSCFENC_INSTANCE, *IGFSCFENC_INSTANCE_HANDLE; @@ -1041,10 +1159,10 @@ typedef struct sc_vbr_enc_structure int16_t vbr_generic_ho; int16_t Local_VAD; int16_t last_7k2_coder_type; + Word16 frame_cnt_ratewin_fx; /* keep count of how many ratewin (600) windows */ } SC_VBR_ENC_DATA, *SC_VBR_ENC_HANDLE; - /*----------------------------------------------------------------------------------* * AMR-WB IO mode structure *----------------------------------------------------------------------------------*/ @@ -1069,7 +1187,6 @@ typedef struct amrwb_io_enc_structure } AMRWB_IO_ENC_DATA, *AMRWB_IO_ENC_HANDLE; - /*----------------------------------------------------------------------------------* * TD BWE structure *----------------------------------------------------------------------------------*/ @@ -1225,6 +1342,7 @@ typedef struct fd_bwe_enc_structure int16_t prev_mode; float old_wtda_swb[L_FRAME48k]; Word16 L_old_wtda_swb_fx[L_FRAME48k]; + Word16 prev_Q_input_lp; int16_t prev_L_swb_norm1; float prev_global_gain; Word32 prev_global_gain_fx; @@ -1258,7 +1376,7 @@ typedef struct rf_enc_structure Word16 rf_clip_var[6]; Word16 rf_tilt_code; Word16 rf_mem_syn2[M]; - //struct dispMem_fx rf_dm_fx; + struct dispMem_fx rf_dm_fx; Word32 rf_gc_threshold; int16_t rf_target_bits; @@ -1290,7 +1408,6 @@ typedef struct rf_enc_structure } RF_ENC_DATA, *RF_ENC_HANDLE; - /*------------------------------------------------------------------------------------------* * PLC encoder *------------------------------------------------------------------------------------------*/ @@ -1383,9 +1500,11 @@ typedef struct tcx_enc_structure float ltpGainMemory[N_LTP_GAIN_MEMS]; /* for smoothing noiseTransWidth */ STnsData tnsData[2]; int16_t fUseTns[2]; + Word8 fUseTns_fx[2]; int16_t bTnsOnWhithenedSpectra[2]; int16_t memQuantZeros[L_FRAME_PLUS]; /* Quantization deadzone flags */ + Word8 memQuantZeros_fx[L_FRAME_PLUS]; float *speech_TCX_flt; float *new_speech_TCX_flt; @@ -1455,7 +1574,6 @@ typedef struct tcx_enc_structure } TCX_ENC_DATA, *TCX_ENC_HANDLE; - /*----------------------------------------------------------------------------------* * * Main Core encoder structure @@ -2078,6 +2196,542 @@ typedef struct enc_core_structure } Encoder_State, *ENC_CORE_HANDLE; +typedef struct TransientDetection +{ + /** Transient detector. */ + TransientDetector transientDetector; + /** Delay buffer used by the transient detectors. */ + DelayBuffer delayBuffer; + /** Subblock energies used by the transient detector. */ + SubblockEnergies subblockEnergies; +} TransientDetection; + +typedef struct Encoder_State_fx +{ + + /*----------------------------------------------------------------------------------* + * Common parameters + *----------------------------------------------------------------------------------*/ + /*----------------------------------------------------------------------------------* + * Stereo/IVAS parameters + *----------------------------------------------------------------------------------*/ + Word16 flag_ACELP16k; /* flag indicating use of ACELP core at 16kHz internal sampling rate */ + + Word16 tdm_LRTD_flag; /* LRTD stereo mode flag */ + Word16 cna_dirac_flag; /* CNA in DirAC flag */ + Word16 cng_sba_flag; /* CNG in SBA flag */ + Word16 idchan; /* channel ID (audio channel number) */ + Word16 element_mode; /* element mode */ + Word16 last_element_mode; /* element mode */ + Word16 low_rate_mode; /* low-rate mode flag */ + MCT_CHAN_MODE mct_chan_mode; + Word16 GSC_IVAS_mode; + Word16 is_ism_format; /* Indication whether the codec operates in ISM format */ + Word16 dtx_sce_sba; /* enable use of FD CNG with transform domain cores in SCE SBA */ + + + //#ifdef IVAS_CODE + +#ifdef DEBUGGING + Word16 id_element; /* element ID */ +#endif + Word32 element_brate; /* element bitrate */ + Word16 extl_orig; /* extension layer */ + Word32 extl_brate_orig; /* extension layer bitrate */ + /*----------------------- End of IVAS specific--------------------------------------*/ + + + Word16 codec_mode; /* MODE1 or MODE2 */ + Word16 last_codec_mode; /* Previous Codec Mode*/ + Word16 last_codec_mode_cng; /* Codec Mode of the last inactive frame*/ + Word16 mdct_sw_enable; /* MDCT switching enable flag */ + Word16 mdct_sw; /* MDCT switching indicator */ + Word16 last_enerBuffer_exp; + Word16 next_bit_pos_fx; /* position of the next bit to be written in the bitstream */ + Word16 bitstreamformat; /* Bitstream format flag (G.192/MIME) */ + + BSTR_ENC_HANDLE hBstr; /* encoder bitstream handle */ + + + LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */ + + + Word32 input_Fs_fx; /* input signal sampling frequency in Hz */ + Word32 total_brate_fx; /* total bitrate in kbps of the codec */ + Word32 last_total_brate_fx; /* total bitrate in kbps of the codec */ + Word32 last_total_brate_cng_fx; /* total bitrate in kbps of the last inactive frame */ + Word16 core_fx; /* core (ACELP_CORE, TCX_20_CORE, TCX_10_CORE, HQ_CORE, AMR_WB_CORE) */ + Word32 core_brate_fx; /* core bitrate */ + Word32 last_core_brate_fx; /* previous frame core bitrate */ + Word16 input_frame_fx; /* Frame lenght (function of input_Fs) */ + Word16 extl_fx; /* extension layer */ + Word16 last_extl_fx; /* previous extension layer */ + Word32 extl_brate_fx; /* extension layer bitrate */ + Word16 input_bwidth_fx; /* input signal bandwidth */ + Word16 last_input_bwidth_fx; /* input signal bandwidth in the previous frame */ + Word16 bwidth_fx; /* encoded bandwidth NB, WB, SWB or FB */ + Word16 max_bwidth_fx; /* maximum encoded bandwidth */ + Word16 last_bwidth_fx; /* input signal bandwidth in the previous frame */ + Word16 last_bwidth_cng_fx; /* input signal bandwidth in the previous inactive frame */ + Word16 L_frame_fx; /* ACELP core internal frame length */ + Word16 Opt_AMR_WB_fx; /* flag indicating AMR-WB IO mode */ + Word16 Opt_DTX_ON_fx; /* flag indicating DTX operation */ + Word16 cng_type_fx; /* flag indicating LP or CLDFB based SID/CNG */ + Word16 active_fr_cnt_fx; /* counter of active frames */ + Word16 Opt_SC_VBR_fx; /* flag indicating SC-VBR mode */ + Word16 last_Opt_SC_VBR_fx; /* flag indicating SC-VBR mode in the last frame */ + /*----------------------------------------------------------------------------------* + * ACELP core parameters + *----------------------------------------------------------------------------------*/ + + Word16 clas_fx; /* current frame clas */ + Word16 last_clas_fx; /* previous frame signal classification */ + Word32 Bin_E_fx[L_FFT]; /* Q_new + Q_SCALE -2 per bin energy of two frames */ + + /*----------------------------------------------------------------------------------* + * General signal buffers + *----------------------------------------------------------------------------------*/ + Word16* input_buff; + /*Word16* input; + Word16* old_input_signal;*/ + + SIGNAL_BUFFERS_ENC_HANDLE hSignalBuf; + + Word32* Bin_E_old_fx; /* per bin energy of old 2nd frames */ + Word16* mem_decim_fx; /* decimation filter memory */ + Word16* mem_decim16k_fx; /* ACELP@16kHz - decimation filter memory @16kHz */ + Word16* old_inp_12k8_fx; /* memory of input signal at 12.8kHz */ + Word16* old_inp_16k_fx; /* ACELP@16kHz - memory of input signal @16 kHz */ + + Word16* buf_speech_enc_pe; + Word16* buf_synth; /*can be reduced to PIT_MAX_MAX+L_FRAME_MAX if no rate switching*/ + Word16* buf_speech_enc; + Word16* buf_wspeech_enc; + + + Word16 lsp_old1_fx[M]; /* old unquantized LSP vector at the end of the frame */ + Word16 lsf_old1_fx[M]; /* old LSF vector at the end of the frame */ + Word16 lsp_old_fx[M]; /* old LSP vector at the end of the frame */ + Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame */ + Word16 lsp_old16k_fx[M]; /* old LSP vector at the end of the frame @16kHz */ + Word16 lspold_enc_fx[M]; /* old LSP vector at the end of the frame @16kHz */ + Word16 pstreaklen_fx; /* LSF quantizer */ + Word16 streaklimit_fx; /* LSF quantizer */ + Word32 offset_scale1_fx[MAX_NO_MODES + 1][MAX_NO_SCALES + 1]; /* offsets for LSF LVQ structure 1st 8-dim subvector*/ + Word32 offset_scale2_fx[MAX_NO_MODES + 1][MAX_NO_SCALES + 1]; /* offsets for LSF LVQ structure 2nd 8-dim subvector*/ + Word32 offset_scale1_p_fx[MAX_NO_MODES_p + 1][MAX_NO_SCALES + 1]; /* offsets for LSF LVQ structure, pred. case, 1st 8-dim subvector*/ + Word32 offset_scale2_p_fx[MAX_NO_MODES_p + 1][MAX_NO_SCALES + 1]; /* offsets for LSF LVQ structure, pred. case, 2nd 8-dim subvector*/ + Word16 no_scales_fx[MAX_NO_MODES][2]; /* LSF LVQ structure Q0*/ + Word16 no_scales_p_fx[MAX_NO_MODES_p][2]; /* LSF LVQ structure Q0*/ + Word16 stab_fac_fx; /* LSF stability factor */ + Word16 mem_deemph_fx; /* deemphasis filter memory */ + Word16 mem_preemph_fx; /* preemphasis filter memory */ + Word32 mem_hp20_in_fx[5]; /* HP filter memory for AMR-WB IO */ + Word16 old_wsp_fx[L_WSP_MEM]; /* old weighted signal vector */ + /*Word16 old_exc_fx[L_EXC_MEM];*/ /* old excitation vector */ + Word16 old_wsp2_fx[(L_WSP_MEM - L_INTERPOL) / OPL_DECIM]; /* old decimated weighted signal vector qwsp */ + + /*----------------------------------------------------------------------------------* + * Noise estimation + *----------------------------------------------------------------------------------*/ + + NOISE_EST_HANDLE hNoiseEst; + + Word16 mem_wsp_fx; /* weighted signal vector memory */ + Word16 mem_decim2_fx[3]; /* weighted signal decimation filter memory qwsp */ + Word16 clip_var_fx[6]; + Word16 mem_AR_fx[M]; /* AR memory of LSF quantizer (past quantized LSFs without mean) */ + Word16 mem_MA_fx[M]; /* MA memory of LSF quantizer (past quantized residual) (used also in AMR-WB IO mode) */ + Word16 mCb1_fx; /* LSF quantizer - counter of stationary frames after a transition frame */ + Word16 coder_type_raw_fx; + Word16 last_coder_type_raw_fx; /* raw last_coder_type (coming from the sigal classification) */ + Word16 last_coder_type_fx; /*Q0 previous coding type */ + Word16 ini_frame_fx; /* initialization frames counter */ + Word16 old_thres_fx; /* normalized correlation weighting in open-loop pitch Q15 */ + Word16 old_corr_fx; /* normalized correlation in previous frame (mean value) Q15 */ + Word16 old_pitch; /* previous pitch for open-loop pitch search Q0 */ + Word16 delta_pit_fx; /* open-loop pitch extrapolation correction Q0 */ + Word32 ee_old_fx; + Word16 min_band_fx; /* Q0 minimum critical band of useful bandwidth */ + Word16 max_band_fx; /* Q0 maximum critical band of useful bandwidth */ + Word16 tc_cnt_fx; /* TC frame counter */ + Word16 audio_frame_cnt_fx; /* Counter of relative presence of audio frames */ + Word32 old_dE1_fx; /* Maximum energy increase in previous frame */ + Word16 old_ind_deltaMax_fx; /* Index of the sub-subframe of maximum energy in previous frame */ + Word32 old_enr_ssf_fx[2 * NB_SSF]; /* Maxima of energies per sub-subframes of previous frame */ + Word16 spike_hyst_fx; /* Hysteresis to prevent UC after sharp energy spike */ + Word16 music_hysteresis_fx; /* Counter of frames after AUDIO coding mode to prevent UC */ + Word16 last_harm_flag_acelp_fx; /* harmonicity flag for ACELP @32kbps rate */ + Word16 old_Aq_12_8_fx[M + 1]; /* Q12 old Aq[] for core switching */ + Word16 old_Es_pred_fx; /* Q8 old Es_pred for core switching */ + + GSC_ENC_HANDLE hGSCEnc; + + + Word16 GSC_noisy_speech_fx; /* AC mode (GSC) - flag to indicate GSC on SWB noisy speech */ + + SP_MUS_CLAS_HANDLE hSpMusClas; + + Word16 lgBin_E_fx[L_FFT / 2]; /* Q8 per bin energy of two frames */ + + /* speech/music classifier improvement parameters */ + Word16 last_vad_spa_fx; + + + Word16 Last_pulse_pos_fx; /* FEC - last position of the first glotal pulse in the frame */ + Word16 lsfoldbfi0_fx[M]; /* FEC - LSF vector of the previous frame */ + Word16 lsfoldbfi1_fx[M]; /* FEC - LSF vector of the past previous frame */ + Word16 lsf_adaptive_mean_fx[M]; /* FEC - adaptive mean LSF vector for FEC */ + Word16 next_force_safety_net_fx; /* FEC - flag to force safety net in next frame */ + + + /*----------------------------------------------------------------------------------* + * VAD/DTX/CNG + *----------------------------------------------------------------------------------*/ + + VAD_HANDLE hVAD; + + VAD_CLDFB_HANDLE_FX hVAD_CLDFB; + Word16 lp_speech_fx; + Word16 Opt_HE_SAD_ON_fx; + Word16 nb_active_frames_HE_SAD_fx; + + + + + Word16 voicing_old_fx; + + + Word32 bckr_tilt_lt; + + + TD_CNG_ENC_HANDLE hTdCngEnc; + + DTX_ENC_HANDLE hDtxEnc; + Word16 var_SID_rate_flag_fx; /* CNG and DTX - flag for variable SID rate */ + Word16 interval_SID_fx; /* CNG and DTX - interval of SID update, default 8 */ + + Word16 lp_noise_fx; /* CNG and DTX - LP filtered total noise estimation */ + + Word16 uv_count_fx; /*Q0*/ /* Stationary noise UV modification - unvoiced counter */ + Word16 act_count_fx; /*Q0*/ /* Stationary noise UV modification - activation counter */ + Word32 ge_sm_fx; /* Stationary noise UV modification - smoothed excitation gain */ + Word16 lspold_s_fx[M]; /*Q15*/ /* Stationary noise UV modification - old LSP vector */ + Word16 noimix_seed_fx; /*Q0*/ /* Stationary noise UV modification - mixture seed */ + Word16 min_alpha_fx; /*Q15*/ /* Stationary noise UV modification - minimum alpha */ + Word16 exc_pe_fx; /* Stationary noise UV modification - memory of the preemphasis filter */ + + Word16 last_L_frame_fx; /* ACELP@16kHz - last L_frame value */ + Word16 mem_preemph16k_fx; /* ACELP@16kHz - preemphasis filter memory @16kHz */ + Word16 mem_deemp_preQ_fx; /* ACELP@16kHz - prequantizer deemhasis memory */ + Word16 mem_preemp_preQ_fx; /* ACELP@16kHz - prequantizer preemhasis memory */ + Word16 last_nq_preQ_fx; /* ACELP@16kHz - AVQ subquantizer number of the last sub-band of the last subframe */ + Word16 use_acelp_preq; /* ACELP@16kHz - flag of prequantizer usage */ + + Word16 bpf_off_fx; + Word16 old_pitch_buf_fx[2 * NB_SUBFR16k]; /*Q6 Bass post-filter - buffer of old subframe pitch values */ + + + /* stable short pitch detection */ + Word16 voicing0_sm_fx; + Word16 voicing_sm_fx; + Word16 LF_EnergyRatio_sm_fx; + Word16 predecision_flag_fx; + Word32 diff_sm_fx; + Word32 energy_sm_fx; + + Word16 last_ener_fx; /* AC mode (GSC) - previous energy */ + + /*----------------------------------------------------------------------------------* + * AMR-WB IO handle + *----------------------------------------------------------------------------------*/ + + AMRWB_IO_ENC_HANDLE hAmrwb_IO; /* AMR-WB IO encoder handle */ + + /*----------------------------------------------------------------------------------* + * CLDFB analysis + *----------------------------------------------------------------------------------*/ + HANDLE_CLDFB_FILTER_BANK cldfbAna_Fx; + + HANDLE_CLDFB_FILTER_BANK cldfbSyn_Fx; + + /*----------------------------------------------------------------------------------* + * FD CNG handle + *----------------------------------------------------------------------------------*/ + HANDLE_FD_CNG_ENC_FX hFdCngEnc_fx; + Word16 fd_cng_reset_flag; + Word16 last_totalNoise_fx; + Word16 totalNoise_increase_hist_fx[TOTALNOISE_HIST_SIZE]; + Word16 totalNoise_increase_len_fx; + /*----------------------------------------------------------------------------------* + * SC-VBR parameters + *----------------------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------------------* + * SC-VBR parameters + *----------------------------------------------------------------------------------*/ + + SC_VBR_ENC_HANDLE hSC_VBR; + + /*----------------------------------------------------------------------------------* + * HQ core parameters + *----------------------------------------------------------------------------------*/ + Word16 * input; + Word16 * old_input_signal_fx; + Word16 Q_old_wtda; + Word16 old_hpfilt_in_fx; + Word16 old_hpfilt_out_fx; + Word32 EnergyLT_fx; + Word32 Energy_Old_fx; + Word16 TransientHangOver_fx; + Word16 last_core_fx; + + HQ_ENC_HANDLE hHQ_core; /* HQ core encoder handle */ + + Word16 Nb_ACELP_frames_fx; + + PVQ_ENC_HANDLE hPVQ; + + /*----------------------------------------------------------------------------------* + * TD BWE parameters + *----------------------------------------------------------------------------------*/ + + TD_BWE_ENC_HANDLE hBWE_TD; + + /*----------------------------------------------------------------------------------* + * FD BWE parameters + *----------------------------------------------------------------------------------*/ + + FD_BWE_ENC_HANDLE hBWE_FD; + + /*----------------------------------------------------------------------------------* + * WB, SWB and FB bandwidth detector + *----------------------------------------------------------------------------------*/ + + Word16 lt_mean_NB_fx; + Word16 lt_mean_WB_fx; + Word16 lt_mean_SWB_fx; + Word16 count_WB_fx; + Word16 count_SWB_fx; + Word16 count_FB_fx; + + RF_ENC_HANDLE hRF; /* RF encoder handle */ + + Word16 rf_mode; + Word16 rf_target_bits_write; + Word16 rf_mode_last; + Word16 last_rf_mode_cng; + Word16 Opt_RF_ON; + Word16 rf_fec_offset; + Word16 rf_fec_indicator; + + /*----------------------------------------------------------------------------------* + * Fixed point only variables + *----------------------------------------------------------------------------------*/ + + Word16 prev_Q_bwe_exc; + Word16 prev_Q_bwe_syn; + Word16 Q_stat_noise_ge; + Word16 Q_stat_noise; + Word16 Q_syn2; + Word16 Q_syn; + Word16 Q_max[L_Q_MEM]; + Word16 Q_max_16k[L_Q_MEM]; + Word16 Q_old; + Word16 prev_Q_old; + Word16 old_wsp_max; /* Last weigthed speech maximal value */ + Word16 old_wsp_shift; /* Last wsp scaling */ + Word16 prev_Q_new; + Word16 prev_Q_shb; + + /*----------------------------------------------------------------------------------* + * + *----------------------------------------------------------------------------------*/ + + Word16 EnergyLT_fx_exp; + Word16 prev_lsp_wb_fx[LPC_SHB_ORDER_WB]; + Word16 prev_lpc_wb_fx[LPC_SHB_ORDER_WB]; + Word16 prev_lsp_wb_temp_fx[LPC_SHB_ORDER_WB]; + + Word16 frame_size_index; /* 0-FRAME_SIZE_NB-1: index determining the frame size */ + Word16 bits_frame_nominal; /* avg bits per frame on active frame */ + Word16 bits_frame; /* total bits per frame */ + Word16 bits_frame_core; /* bits per frame for the core */ + Word8 narrowBand; + + /*ACELP config*/ + ACELP_config acelp_cfg; /* configuration set for each frame */ + + ACELP_config acelp_cfg_rf; /* configuration for RF frame */ + + Word16 mode_index; /* Mode Index for LPD core */ + + /*TCX config*/ + TCX_CONFIG_HANDLE hTcxCfg; + /*----------------------------------------------------------------------------------* + * TCX core encoder handle + *----------------------------------------------------------------------------------*/ + + TCX_ENC_HANDLE hTcxEnc; + + /* cod_main.c */ + Word16 mem_preemph_enc; /* speech preemph filter memory (at encoder-sampling-rate) */ + + + Word16 *speech_enc; + Word16 *speech_enc_pe; + Word16 *new_speech_enc; + Word16 *new_speech_enc_pe; + Word16 *wspeech_enc; + Word16 *synth; + /* Core Signal Analysis Outputs */ + + Word8 enableTcxLpc; /* global toggle for the TCX LPC quantizer */ + Word16 envWeighted; /* are is{p,f}_old_q[] weighted or not? */ + + Word8 acelpEnabled; /* Flag indicating if ACELP can be used */ + Word8 tcx10Enabled; /* Flag indicating if TCX 10 can be used */ + Word8 tcx20Enabled; /* Flag indicating if TCX 20 can be used */ + + + Word16 mem_wsp_enc; /* wsp vector memory */ + + Word16 nb_bits_header_ace; /* number of bits for the header */ + Word16 nb_bits_header_tcx; /* number of bits for the header */ + + /*Added by fcs : restrict the possible in EVS: 0 base 10 = d.c.b.a base 2*/ + /* a = 0/1 : ACELP on/off*/ + /* b = 0/1 : TCX20 on/off*/ + /* c = 0/1 : TCX40 on/off*/ + /* d = 0/1 : TCX80 on/off*/ + Word8 restrictedMode; + + /* Framing */ + Word16 nb_subfr; + + Word16 preemph_fac; /*Preemphasis factor*/ + + Word16 gamma; + Word16 inv_gamma; + + TransientDetection transientDetection; + Word16 transient_info[3]; + + Word16 acelpFramesCount; /* Acelp frame counter. Counts upto 50 only !!! */ + + Word16 prevTempFlatness_fx; /* exponent is AVG_FLAT_E */ + + Word32 prevEnergyHF_fx; + Word32 currEnergyHF_fx; + Word16 currEnergyHF_e_fx; /* exponent of currEnergyHF and prevEnergyHF */ + Word32 energyCoreLookahead_Fx; + Word16 sf_energyCoreLookahead_Fx; + + /* lsf quantizer*/ + Word16 parcorr[2]; + Word16 parcorr_mid[2]; + + Word16 lpcQuantization; + Word16 numlpc; + Word16 encoderLookahead_enc; + Word16 encoderPastSamples_enc; + Word16 encoderLookahead_FB; + + /* pitch_ol for adaptive lag window */ + Word16 old_pitch_la; /* past open loop pitch lag from look-ahead */ + Word16 old_voicing_la; /* past open loop pitch gain from look-ahead */ + + Word32 band_energies[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 band_energies_exp; /* exponent for energy in critical bands without minimum noise floor MODE2_E_MIN */ + + Word8 tcxonly; + + Word16 Q_max_enc[2]; + + Word16 finalVAD; + Word8 flag_noisy_speech_snr; /*encoder detector for noisy speech*/ + Word16 Pos_relE_cnt; /* Number of frames between positive relE */ + + Word16 fscale; + Word32 sr_core; + Word32 last_sr_core; + Word8 acelp_autocorr; /* Optimize acelp in 0 covariance or 1 correlation domain */ + + Word16 pit_min; + Word16 pit_fr1; + Word16 pit_fr1b; + Word16 pit_fr2; + Word16 pit_max; + Word16 pit_res_max; /* goes from 1 upto 6 (see core_enc_init.c: init_acelp()) */ + + /* for FAC */ + Word16 L_frame_past; + + /*Adaptive BPF*/ + Word16 bpf_gain_param; + Word16 bpf_T[NB_SUBFR16k]; + Word16 bpf_gainT[NB_SUBFR16k]; + + struct MEM_BPF + { + Word16 noise_buf[2 * L_FILT16k]; + Word16 error_buf[L_FILT16k]; + Word32 lp_error; + Word32 lp_error_ener; + Word16 noise_shift_old; + } mem_bpf; + + + + Word8 glr; + Word16 glr_idx[2]; + Word32 gain_code[NB_SUBFR16k]; + Word32 mean_gc[2]; + Word16 prev_lsf4_mean; + Word16 last_stab_fac; + Word8 glr_reset; + + /*for rate switching*/ + Word16 rate_switching_reset; /*Rate switching flag requiring a reset of memories at least partially */ + Word16 rate_switching_reset_16kHz; + + Word16 enablePlcWaveadjust; + Word16 Tonal_SideInfo; + + IGF_ENC_INSTANCE_HANDLE hIGFEnc; /* IGF encoder handle */ + Word16 igf; + + Word16 seed_acelp; + + PLC_ENC_EVS_HANDLE hPlcExt; + + Word16 tec_tfa; + TEC_ENC_HANDLE hTECEnc; /* TEC encoder handle */ + Word16 tec_flag; + Word16 tfa_flag; + Word32 tfa_enr[N_TEC_TFA_SUBFR]; + + Word16 nTimeSlots; /* for CLDFB */ + + T_CldfbVadState_fx vad_st; + + + Word16 pitch_fx[3]; + Word16 voicing_fx[3]; + Word16 sp_aud_decision0; /* 1st stage speech/music classification */ + Word16 sp_aud_decision1; /* 1st stage speech/music classification */ + Word16 sp_aud_decision2; /* 2nd stage speech/music classification */ + Word16 coder_type; /* coder type */ + Word16 vad_flag; + Word16 sharpFlag; /* formant sharpening flag */ + Word16 localVAD; + + Word16 tdm_pc; + Word16 prev_fmerit; + Word16 fmerit_dt; + + +} Encoder_State_fx, * ENC_CORE_HANDLE_FX; typedef struct GainItemStr { diff --git a/lib_enc/stat_noise_uv_enc_fx.c b/lib_enc/stat_noise_uv_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..a7ab7164ac67af51f28ca2c5180a33418ed3ef82 --- /dev/null +++ b/lib_enc/stat_noise_uv_enc_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 "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 : stat_noise_uv_enc_fx */ +/*----------------------------------------------------------------------*/ +/* PURPOSE : Modifies excitation signal in UC mode */ +/* when the noise is stationary */ +/*----------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Encoder_State_fx) st_fx : Encoder state Structure */ +/* _ (Word16*) epsP : LP prediction errors */ +/* _ (Word16*) isp_new : immittance spectral pairs at 4th sfr Q15 */ +/* _ (Word16*) isp_mid : immittance spectral pairs at 2nd sfr Q15 */ +/* _ (Word16*) Aq : A(z) quantized for the 4 subframes Q12 */ +/* _ (Word16 ) uc_two_stage_flag flag undicating two-stage UC */ +/*-----------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ (Word16*) exc2 : excitation buffer Q_exc */ +/*-----------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*-----------------------------------------------------------------------*/ + +/* _ None */ +/*-----------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*=======================================================================*/ +void stat_noise_uv_enc_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word32 *LepsP, /* i : LP prediction errors */ + const Word16 *isp_new, /* i : immittance spectral pairs at 4th sfr */ + const Word16 *isp_mid, /* i : immittance spectral pairs at 2nd sfr */ + Word16 *Aq, /* i : A(z) quantized for the 4 subframes */ + Word16 *exc2, /* i/o: excitation buffer */ + const Word16 uc_two_stage_flag, /* o : flag undicating two-stage UC */ + Word16 Q_new +) +{ + Word16 noisiness = 0; + Word16 num,den,expn,expd; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + test(); + test(); + IF ( ( EQ_16(st_fx->coder_type,UNVOICED) && uc_two_stage_flag == 0) || (EQ_16(st_fx->coder_type,INACTIVE) && LE_32(st_fx->core_brate_fx,ACELP_9k60))) + { + + /*-----------------------------------------------------------------* + * Calculate and write the noisiness parameter + *-----------------------------------------------------------------*/ + /* epsP[2] is located in LepsP[0] and epsP[16] in LepsP[1] */ + expn = sub(norm_l(LepsP[0]),1); +#ifdef BASOP_NOGLOB + num = extract_h(L_shl_o(LepsP[0],expn, &Overflow));/*expn-16*/ +#else + num = extract_h(L_shl(LepsP[0],expn));/*expn-16*/ +#endif + expd = norm_l(LepsP[1]); +#ifdef BASOP_NOGLOB + den = extract_h(L_shl_o(LepsP[1],expd, &Overflow));/*expd-16*/ +#else + den = extract_h(L_shl(LepsP[1],expd));/*expd-16*/ +#endif + num = div_s(num,den);/*expn-expd+15*/ +#ifdef BASOP_NOGLOB + num = shr_o(num,add(sub(expn,expd),5), &Overflow);/*Q10*/ +#else + num = shr(num,add(sub(expn,expd),5));/*Q10*/ +#endif + num = sub(num,1024);/*num - 1*/ + + test(); + IF ( NE_16(st_fx->bwidth_fx,NB)) + { + /* WB case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*2 * 32);*/ + noisiness = shr(num,4);/*Q10 x64 -> Q0 */ + } + ELSE IF ( EQ_16(st_fx->coder_type,INACTIVE)&&EQ_16(st_fx->bwidth_fx,NB)) + { + /* NB GSC case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*.25f * 32);*/ + noisiness = shr(num,4+3);/*Q10 x8 -> Q0 */ + } + ELSE + { + /* NB case */ + noisiness = shr(num,4+2);/*Q16 x16 -> Q0 */ + } + + noisiness = s_max(noisiness, 0); + noisiness = s_min(noisiness, 31); + + push_indice_fx( st_fx->hBstr, IND_NOISINESS, noisiness, 5 ); + } + + /*-----------------------------------------------------------------* + * Modify the stationary noise excitation signal + *-----------------------------------------------------------------*/ + + stat_noise_uv_mod_fx( st_fx->coder_type, noisiness, st_fx->lsp_old_fx, isp_new, isp_mid, Aq + ,exc2, Q_new, 0, &st_fx->ge_sm_fx, &st_fx->uv_count_fx, &st_fx->act_count_fx, + st_fx->lspold_s_fx, &st_fx->noimix_seed_fx, &st_fx->min_alpha_fx, &st_fx->exc_pe_fx, + st_fx->core_brate_fx, st_fx->bwidth_fx, &st_fx->Q_stat_noise, &st_fx->Q_stat_noise_ge ); + + + return; +} diff --git a/lib_enc/subband_fft_fx.c b/lib_enc/subband_fft_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..74c8f84ac2104513e707bc00705730301eaf4c8d --- /dev/null +++ b/lib_enc/subband_fft_fx.c @@ -0,0 +1,379 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "options.h" +#include "basop_util.h" +#include "vad_basop.h" +//#include "prot_fx.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 + *---------------------------------------------------------------------*/ +#define RE(A) A.r +#define IM(A) A.i + +typedef struct +{ + complex_16 work[32]; + complex_16 const* tab; +} cfft_info_16; +/*-------------------------------------------------------------------* + * ComplexMult_16() + * + *-------------------------------------------------------------------*/ +static void ComplexMult_16( + Word16 *y1, + Word16 *y2, + const Word16 x1, + const Word16 x2, + const Word16 c1, + const Word16 c2 +) +{ + *y1 = add(mult(x1, c1) , mult(x2, c2)); + move16(); + *y2 = sub(mult(x2, c1) , mult(x1, c2)); + move16(); +} +/*-------------------------------------------------------------------* + * ffr_getSfWord32() + * + *-------------------------------------------------------------------*/ +Word16 ffr_getSfWord32( + const Word32 *vector, /*!< Pointer to input vector */ + const Word16 len /*!< Length of input vector */ +) +{ + Word32 maxVal; + Word16 i; + Word16 resu; + + + maxVal = 0; + move32(); + FOR(i=0; i +#include "options.h" + +//#include "prot_fx.h" +#include "cnst.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "stl.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*---------------------------------------------------------------------* + * Local functions + *---------------------------------------------------------------------*/ + +static Word16 SWB_BWE_encoding_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *insig_fx, /* i/o: delayed original input signal at 32kHz (might be rescaled)*/ + const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ + const Word16 *insig_hp_fx, /* i : delayed original highband input signal at 32kHz */ + const Word16 *synth_fx, /* i : delayed ACELP core synthesis at 12.8kHz */ + const Word16 *yos_fx, /* i : MDCT coefficients of the windowed original input signal at 32kHz */ + Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ + const Word16 tilt_nb_fx, /* i : SWB tilt */ + const Word16 st_offset, /* i : start frequency offset for BWE envelope */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_insig_lp, + Word16 Q_shb, + Word16 Q_synth, + Word16 Q_synth_lf +); + +static void delay_input_signal_fx( + Word16 *old_sig, + Word16 *cur_sig, + Word16 *new_sig, + Word16 m1, + Word16 m2, + Word16 *Q_old, + Word16 *Q_new +) +{ + Word16 i; + Word16 max; + Word16 max1_exp, max2_exp; + + max = abs_s(old_sig[0]); + FOR(i=1; ihBWE_FD; + Word16 WB_fenv_fx[SWB_FENV]; + + IF( EQ_32(st_fx->total_brate_fx, ACELP_13k20)) + { + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + set16_fx( old_input_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k ); + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS); + + new_input_fx = old_input_fx + Sample_Delay_WB_BWE; + Copy(hBWE_FD->old_input_wb_fx, old_input_fx, Sample_Delay_WB_BWE ); + Copy( new_wb_speech_fx, new_input_fx, L_FRAME16k ); + Copy( old_input_fx + L_FRAME16k, hBWE_FD->old_input_wb_fx, Sample_Delay_WB_BWE ); + + /*---------------------------------------------------------------------*/ + /* WB BWE encoding */ + + + /* MDCT of the core synthesis signal */ + /*---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + move16(); + + wtda_fx(old_input_fx, &new_input_fx_exp, L_wtda_synth_fx, hBWE_FD->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda,ALDO_WINDOW,ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + L_FRAME16k ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx(L_wtda_synth_fx, yorig_32, 0, L_FRAME16k, &new_input_fx_exp + , /*st_fx->element_mode*/EVS_MONO); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+8/*MAX_Q_NEW_INPUT*/, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32(yorig_32, L_FRAME16k); + + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(Q_synth, scl); + } + Copy_Scale_sig32_16(yorig_32, yorig_fx, L_FRAME16k, scl); + Q_synth = add(sub(new_input_fx_exp, 16), scl) - 1; + + mode = WB_BWE_encoding_fx( coder_type, yorig_fx, WB_fenv_fx, st_fx, Q_synth, Q_synth); + push_indice_fx(st_fx->hBstr, IND_WB_CLASS, mode - 2, 1 ); + } + + hBWE_FD->prev_mode = mode; + + return; +} + +/*-------------------------------------------------------------------* +* swb_bwe_enc() +* +* SWB BWE encoder (only for 32kHz signals) +*-------------------------------------------------------------------*/ +void swb_bwe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ + Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_shb_speech, + Word16 Q_slb_speech +) +{ + Word16 i; + Word16 *new_input_fx; + Word16 tmp, exp, exp1; + Word16 frac; + Word32 L_tmp; + Word16 inner_frame; + Word32 inner_Fs; + Word32 L_old_input_fx[2*L_FRAME48k]; + Word32 yorig_32[L_FRAME48k]; + Word16 old_input_fx[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k]; + Word16 old_input_lp_fx[L_FRAME16k]; + Word16 new_input_hp_fx[L_FRAME16k]; + Word16 yorig_fx[L_FRAME48k]; + Word16 scl, new_input_fx_exp; + Word16 max; + Word16 Sample_Delay_SWB_BWE; + Word16 Sample_Delay_HP; + Word16 Sample_Delay_LP; + Word16 idxGain = 0; + + Word16 Q_synth_hf, Q_synth, Q_shb; + Word16 tilt_nb_fx; + Word16 SWB_fenv_fx[SWB_FENV]; + Word32 ener_low_fx; + Word32 energy_fbe_fb_fx = 0; + Word16 fb_ener_adjust_fx; + Word16 ener_adjust_quan_fx = 0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + + + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + IF( EQ_16(st_fx->extl_fx, FB_BWE)) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + } + ELSE + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + } + + set16_fx( old_input_fx, 0, add(NS2SA(inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS), inner_frame) ); + + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + Sample_Delay_SWB_BWE = NS2SA(inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS); + 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); + + delay_input_signal_fx(hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_12k8_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + } + ELSE + { + Sample_Delay_SWB_BWE = NS2SA(inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS); + 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); + + delay_input_signal_fx(hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_16k_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME16k, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + } + + Copy(hBWE_FD->new_input_hp_fx, new_input_hp_fx, Sample_Delay_HP); + Copy( shb_speech_fx, &new_input_hp_fx[Sample_Delay_HP], L_FRAME16k-Sample_Delay_HP ); + Copy( shb_speech_fx + L_FRAME16k-Sample_Delay_HP, hBWE_FD->new_input_hp_fx, Sample_Delay_HP ); + new_input_fx = old_input_fx + Sample_Delay_SWB_BWE; + Copy(hBWE_FD->old_input_fx, old_input_fx, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech_fx, new_input_fx, inner_frame ); + Copy( old_input_fx + inner_frame, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + /*----------------------------------------------------------------------* + * Calculate tilt of the input signal and the ACELP core synthesis + *----------------------------------------------------------------------*/ + + /* tilt returned in Q24 goto to Q11 */ +#ifdef BASOP_NOGLOB + tilt_nb_fx = round_fx_o(L_shl_o(calc_tilt_bwe_fx(old_input_lp_fx, Q_slb_speech, st_fx->L_frame_fx), 3, &Overflow), &Overflow); +#else + tilt_nb_fx = round_fx(L_shl(calc_tilt_bwe_fx(old_input_lp_fx, Q_slb_speech, st_fx->L_frame_fx), 3)); +#endif + /*---------------------------------------------------------------------* + * SWB BWE encoding + * FB BWE encoding + *---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + /* MDCT of the core synthesis signal */ + wtda_fx(old_input_fx, &new_input_fx_exp, L_old_input_fx, hBWE_FD->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + inner_frame ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx(L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp + , /*st_fx->element_mode*/EVS_MONO); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+8, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32(yorig_32, inner_frame); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(Q_synth, scl); + } + Copy_Scale_sig32_16(yorig_32, yorig_fx, inner_frame, scl); + Q_synth = add(sub(new_input_fx_exp, 16), scl); + + max = 0; + move16(); + Q_synth_hf = 0; + move16(); + IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + scl = 300; + move16(); + } + ELSE + { + scl = 240; + move16(); + } + FOR(i=scl; ilast_extl_fx, SWB_BWE)||EQ_16(st_fx->last_extl_fx,FB_BWE)) + { + exp = norm_l(st_fx->EnergyLT_fx); + IF(add(st_fx->EnergyLT_fx_exp, exp) > shl(sub(Q_synth_hf, 4), 1)) + { + Q_shb = sub(Q_synth_hf, 4); + st_fx->EnergyLT_fx = L_shr(st_fx->EnergyLT_fx, sub(st_fx->EnergyLT_fx_exp, shl(Q_shb, 1))); + } + ELSE + { + Q_shb = shr(add(st_fx->EnergyLT_fx_exp, exp), 1); + IF(s_and(exp, 0x0001) == 1) + { + exp = sub(exp, 1); + } + st_fx->EnergyLT_fx = L_shl(st_fx->EnergyLT_fx, exp); + } + } + ELSE + { + Q_shb = sub(Q_synth_hf, 4); + } + Copy_Scale_sig(new_input_hp_fx, new_input_hp_fx, L_FRAME16k, sub(Q_shb, Q_shb_speech)); + /* SWB BWE encoding */ + IF (EQ_16(st_fx->L_frame_fx, L_FRAME16k)) + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 80, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + + } + ELSE + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 6, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + + /* FB BWE encoding */ + IF ( EQ_16(st_fx->extl_fx, FB_BWE)) + { + energy_fbe_fb_fx = L_deposit_l(0); + FOR( i=FB_BAND_BEGIN; i45-(exp+2*(Q_synth_hf-4)) */ + L_tmp = Mult_32_16(ener_low_fx, tmp); /*45-(exp+2*(Q_synth_hf-4)) + 2*(Q_synth_hf-4) - 15 = 30-exp */ + exp1 = norm_l(L_tmp); + L_tmp = L_shl(L_tmp, exp1); + exp = 31-exp1-(30-exp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*31-exp */ +#ifdef BASOP_NOGLOB + fb_ener_adjust_fx = round_fx_o(L_shl_o(L_tmp, exp, &Overflow), &Overflow); /*Q15 */ +#else + fb_ener_adjust_fx = round_fx(L_shl(L_tmp, exp)); /*Q15 */ +#endif + } + ELSE + { + fb_ener_adjust_fx = 0; + move16(); + } + + fb_ener_adjust_fx = s_min(fb_ener_adjust_fx, 16384); /*Q15 */ + idxGain = usquant_fx( fb_ener_adjust_fx, &ener_adjust_quan_fx, 0, 512, shl(1, NUM_BITS_FB_FRAMEGAIN) ); + } + + /* write FB BWE frame gain to the bitstream */ + IF( EQ_16(st_fx->extl_fx, FB_BWE)) + { + push_indice_fx(st_fx->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); + } + + return; +} +/*==========================================================================*/ +/* FUNCTION : static Word16 WB_BWE_fenv_q_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Scalar quantizer routine */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 *cb i: quantizer codebook Q10 */ +/* Word16 cb_length i: length of codebook */ +/* Word16 cb_dim i: dimension of codebook */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word16 *x i/o: energy of WB envelop Q10 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ +static Word16 WB_BWE_fenv_q_fx( /* o: quantized gain index */ + Word16 *x, /* i/o: energy of WB envelop Q10*/ + const Word16 *cb, /* i: quantizer codebook Q10 */ + const Word16 cb_length, /* i: length of codebook */ + const Word16 cb_dim /* i: dimension of codebook */ +) +{ + Word16 i, j, indx = 0; + Word32 dist, min_dist; + const Word16 *pit = cb;/*Q10 */ + Word16 tmp; + Word32 L_tmp; + + min_dist = L_add(MAX_32, 0); + FOR (i=0; iQ20 */ + dist = L_add(dist, L_tmp); + + pit++; + } + + IF( LT_32(dist,min_dist)) + { + min_dist = L_add(dist, 0); + indx = i; + move16(); + } + } + + FOR(j=0; jhBWE_FD; + + mode = NORMAL; + move16(); + k = 0; + move16(); + noise = 0; + move16(); + sharpPeak = 0; + move16(); + numsharp = 0; + move16(); + numharmonic = 4; + move16(); + sharplimit = 10; + move16(); + + L_mean_d = 0L; /* to avoid compilation warnings */ + + test(); + IF ( EQ_16(st_fx->extl_fx, SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + input_hi = &fSpectrum[256]; + move16(); + numsharp = NUM_SHARP; + move16(); + + test(); + test(); + test(); + IF ( ( EQ_16(st_fx->last_extl_fx, SWB_BWE)&&EQ_16(st_fx->extl_fx,SWB_BWE))||(EQ_16(st_fx->last_extl_fx,FB_BWE)&&EQ_16(st_fx->extl_fx,FB_BWE))) + { + IF(hBWE_FD->prev_global_gain_fx == 0) + { +#ifdef BASOP_NOGLOB + gain_tmp = round_fx_o(L_shl_o(fGain, 30, &Overflow), &Overflow); /*Q14 */ +#else + gain_tmp = round_fx(L_shl(fGain, 30)); /*Q14 */ +#endif + } + ELSE + { + expn = norm_l(fGain); +#ifdef BASOP_NOGLOB + num = extract_h(L_shl_o(fGain, expn, &Overflow)); +#else + num = extract_h(L_shl(fGain, expn)); +#endif + expn = sub(sub(30, expn), shl(Q_shb,1)); + + expd = norm_l(hBWE_FD->prev_global_gain_fx); +#ifdef BASOP_NOGLOB + den = extract_h(L_shl_o(hBWE_FD->prev_global_gain_fx, expd, &Overflow)); +#else + den = extract_h(L_shl(hBWE_FD->prev_global_gain_fx, expd)); +#endif + expd = sub(sub(30, expd), shl(st_fx->prev_Q_shb,1)); + + scale = shr(sub(den, num), 15); +#ifdef BASOP_NOGLOB + num = shl_o(num, scale, &Overflow); +#else + num = shl(num, scale); +#endif + expn = sub(expn, scale); + + tmp = div_s(num, den); + expn = sub(expn, expd); +#ifdef BASOP_NOGLOB + gain_tmp = shl_o(tmp, sub(expn,1), &Overflow);/*Q14 */ +#else + gain_tmp = shl(tmp, sub(expn,1));/*Q14 */ +#endif + } + test(); + IF (EQ_16(hBWE_FD->prev_mode,TRANSIENT)) + { + numharmonic = shl(numharmonic, 1); + } + ELSE IF (EQ_16(hBWE_FD->prev_mode, NORMAL)||EQ_16(hBWE_FD->prev_mode,NOISE)) + { + numharmonic = add(shr(numharmonic, 1), numharmonic); + } + } + ELSE + { + gain_tmp = 16384; + move16(); + IF (EQ_16(hBWE_FD->prev_mode, HARMONIC)) + { + numharmonic = shr(numharmonic, 1); + sharplimit = shr(sharplimit, 1); + } + ELSE + { + numharmonic = shl(numharmonic, 1); + sharplimit = shl(sharplimit, 1); + } + } + } + ELSE IF (EQ_16(st_fx->extl_fx, WB_BWE)) + { + input_hi = &fSpectrum[224]; + move16(); + numsharp = 3; + move16(); + + IF (EQ_16(hBWE_FD->prev_mode, HARMONIC)) + { + numharmonic = shr(numharmonic, 2); + } + ELSE + { + numharmonic = shr(numharmonic, 1); + } + IF (NE_16(st_fx->last_extl_fx, WB_BWE)) + { + IF (EQ_16(hBWE_FD->prev_mode, HARMONIC)) + { + sharplimit = shr(sharplimit, 1); + } + ELSE + { + sharplimit = shl(sharplimit, 1); + } + } + } + + L_meanH = L_deposit_l(0); + FOR(i = 0; i < numsharp; i ++) + { + peak = 0; + move16(); + mean[i] = L_deposit_l(0); + + FOR(j = 0; j < SHARP_WIDTH; j ++) + { + mag = abs_s(*input_hi); + IF (GT_16(mag, peak)) + { + peak = mag; + move16();/*Q_syn */ + } + mean[i] = L_add(mean[i], mag); + move32();/*Q_syn */ + input_hi ++; + } + + L_meanH = L_add(L_meanH, mean[i]);/*Q_syn */ + + IF(NE_32(mean[i], L_deposit_l(peak))) + { + L_tmp = L_sub(mean[i], peak);/*Q_syn */ + L_tmp = Mult_32_16(L_tmp, 16913); /* 1/31->Q19 -> Q_syn+19-15 */ + den = extract_l(L_shr(L_tmp, 4)); /*Q_syn */ + IF(den == 0) + { + den = 1; + move16(); + } + expd = norm_s(den); + tmp = div_s(shl(1,sub(14,expd)), den); /*Q(29-expd-Q_syn) */ + L_tmp = L_mult(tmp, peak); /*Q(30-expd) */ +#ifdef BASOP_NOGLOB + sharp = round_fx_o(L_shl_o(L_tmp, sub(expd, 4), &Overflow), &Overflow);/*Q10 */ +#else + sharp = round_fx(L_shl(L_tmp, sub(expd, 4)));/*Q10 */ +#endif + } + ELSE + { + sharp = 0; + move16(); + } + + test(); +#ifdef BASOP_NOGLOB + IF (GT_16(sharp, 4608)&>_16(peak,shl_o(1,add(Q_syn,3), &Overflow))) +#else + IF (GT_16(sharp, 4608)&>_16(peak,shl(1,add(Q_syn,3)))) +#endif + { + k = add(k, 1); + move16(); + } + ELSE IF (LT_16(sharp, 3072)) + { + noise = add(noise, 1); + move16(); + } + + IF (GT_16(sharp, sharpPeak)) + { + sharpPeak = sharp; + move16(); + } + } + test(); + IF ( EQ_16(st_fx->extl_fx, SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + test(); + test(); + test(); + IF(GE_16(k, numharmonic)&>_16(gain_tmp,8192)&<_16(gain_tmp,29491)&>_16(sharpPeak,shl(sharplimit,10))) + { + sharpMod = 1; + move16(); + } + ELSE + { + sharpMod = 0; + move16(); + } + + L_meanH = Mult_32_16(L_meanH, 29127); /*Q_syn+8 */ + L_mean_d = 0; + move16(); + FOR(i=0; iextl_fx, WB_BWE)) + { + test(); + IF (GE_16(k,numharmonic)&>_16(sharpPeak,shl(sharplimit,10))) + { + sharpMod = 1; + move16(); + } + ELSE + { + sharpMod = 0; + move16(); + } + } + + test(); + test(); + IF (sharpMod && LT_16(hBWE_FD->modeCount, 12)) + { + hBWE_FD->modeCount = add(hBWE_FD->modeCount, 1); + } + ELSE IF (sharpMod == 0 && hBWE_FD->modeCount > 0) + { + hBWE_FD->modeCount = sub(hBWE_FD->modeCount, 1); + } + + IF (GE_16(hBWE_FD->modeCount, 2)) + { + sharpMod = 1; + move16(); + } + + test(); + IF (sharpMod) + { + mode = HARMONIC; + move16(); + } + ELSE IF ( EQ_16(st_fx->extl_fx, SWB_BWE)||EQ_16(st_fx->extl_fx,FB_BWE)) + { + L_tmp = Mult_32_16(L_mean_d, 6827); /*Q_syn+8 ; 1/4.8 in Q15 */ + + test(); + test(); + test(); + IF (GT_16(noise, 4)&&(LT_32(L_tmp,L_meanH)||L_meanH==0)&<_16(tilt_nb,10240)) + { + mode = NOISE; + move16(); + } + } + + return (mode); +} +/*-------------------------------------------------------------------* +* freq_weights_fx() +* +*-------------------------------------------------------------------*/ +static void freq_weights_fx( + const Word16 Band_Ener[], /* i : Band energy Q8 */ + const Word16 f_weighting[], /* i : weigting coefs. Q15 */ + Word16 w_env[], /* o : Freq. weighting Q13 */ + const Word16 Nbands /* i : Number of bands */ +) +{ + Word16 i; + Word16 tmp, tmp1, w1[SWB_FENV], w2[SWB_FENV]; + Word16 min_b, max_b; + Word32 L_tmp; + Word16 exp; + + /* Find Max band energy */ + min_b = Band_Ener[0]; + move16(); + max_b = Band_Ener[0]; + move16(); + FOR( i=1; i k; l-- ) + { + dist_min[l] = dist_min[l - 1]; + move32(); + index[l] = index[l - 1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } + } + } + } + ELSE + { + set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ + + FOR (i = 0; i < surv; i++) + { + index[i] = i; + move16(); + } + + p_E_ROM_dico = E_ROM_dico; + move16(); + + FOR( i = 0; i < E_ROM_dico_size; i++ ) + { + dist = sub(x[0],*p_E_ROM_dico++);/*Q8 */ + L_dist = L_mult(dist,dist);/*Q17 */ + L_dist = L_shr(L_dist,12);/*Q5 */ + + FOR( j = 1; j < dim; j++ ) + { + temp1 = sub(x[j],*p_E_ROM_dico++);/*Q8 */ + L_tmp = L_mult(temp1,temp1);/*Q17 */ + L_dist = L_add(L_dist,L_shr(L_tmp,12));/*Q5 */ + } + + FOR( k = 0; k < surv; k++ ) + { + IF( LT_32(L_dist,dist_min[k])) + { + FOR( l = surv - 1; l > k; l-- ) + { + dist_min[l] = dist_min[l-1]; + move32(); + index[l] = index[l-1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } + } + } + } + + return; +} + +/*-------------------------------------------------------------------* +* vqSimple_w_fx() +* +*-------------------------------------------------------------------*/ + +static Word16 vqSimple_w_fx( + const Word16 *x, /* i : input for quantizer Q8 */ + Word16 *y, /* i : quantized value Q8 */ + const Word16 *cb, /* i : codebooks Q8 */ + const Word16 *w, /* i : weight Q13 */ + const Word16 dim, /* i : dimension */ + const Word16 l, /* i : number of candidates */ + const Word16 flag /* i : flag indicationg weighted distortion metric */ +) +{ + Word16 i, j, index; + const Word16 *cbP; + Word16 dist, temp; + Word32 L_dist,L_tmp,L_dist_min; + + index = 0; + move16(); + L_dist_min = L_add(MAX_32, 0); /* FLT_MAX */ + cbP = cb; + move16(); + IF( flag ) + { + FOR( i = 0; i < l; i++ ) + { + /*dist = x[0] - *cbP++; */ + /*dist *= (dist * w[0]); */ + dist = sub(x[0],*cbP++);/*Q8 */ + L_dist = L_mult(dist,w[0]);/*Q22 */ + L_dist = Mult_32_16(L_dist,dist);/*Q15 */ + L_dist = L_shr(L_dist,10);/*Q5 */ + + FOR( j = 1; j < dim; j++ ) + { + /*temp = x[j] - *cbP++; */ + /*dist += temp * temp * w[j]; */ + temp = sub(x[j],*cbP++); + L_tmp = L_mult(temp,w[j]);/*Q22 */ + L_tmp = Mult_32_16(L_tmp,temp);/*Q15 */ + L_dist = L_add(L_dist,L_shr(L_tmp,10));/*Q5 */ + } + IF (LT_32(L_dist, L_dist_min)) + { + L_dist_min = L_add(L_dist, 0);/*Q5 */ + index = i; + move16(); + } + } + } + ELSE + { + FOR( i = 0; i < l; i++ ) + { + /*dist = x[0] - *cbP++; */ + dist = sub(x[0],*cbP++); + /*dist *= dist; */ + L_dist = L_mult(dist,dist);/*Q17 */ + L_dist = L_shr(L_dist,12); + + FOR( j = 1; j < dim; j++ ) + { + /*temp = x[j] - *cbP++; */ + temp = sub(x[j] , *cbP++); + /*dist += temp * temp; */ + L_tmp = L_mult(temp,temp);/*Q17 */ + L_dist = L_add(L_dist,L_shr(L_tmp,12));/*Q5 */ + } + IF (LT_32(L_dist, L_dist_min)) + { + L_dist_min = L_add(L_dist, 0); + index = i; + move16(); + } + } + } + + + /* Reading the selected vector */ + Copy( &cb[index * dim], y, dim ); + + return(index); +} + + + +/*-------------------------------------------------------------------* +* MSVQ_Interpol_Tran_fx() +* +*-------------------------------------------------------------------*/ +static void MSVQ_Interpol_Tran_fx( + Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8 */ + Word16 *indice /* o : quantized index */ +) + +{ + Word16 k, n_band, candInd[N_CAND_TR], ind_tmp[2],tmp; + Word16 env_temp11[SWB_FENV_TRANS/2], env_temp12[SWB_FENV_TRANS/2]; + Word16 tmp_q; + Word16 quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; + Word16 quant_select[SWB_FENV_TRANS]; + Word32 L_tmp, L_dist, L_minDist,distCand[N_CAND_TR]; + + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) + { + env_temp11[n_band] = SWB_env_energy[2*n_band]; + move16();/*Q8 */ + env_temp12[n_band] = SWB_env_energy[2*n_band+1]; + move16();/*Q8 */ + } + + vqWithCand_w_fx( env_temp11, Env_TR_Cdbk1_fx, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); + + L_minDist = L_add(MAX_32, 0); /* FLT_MAX */ + + FOR( k=0; khBWE_FD; + + IF ( EQ_16(core,ACELP_CORE)) + { + gamma_fx = 11469; + move16();/*.35 in Q15 */ + test(); + IF ( NE_16(coder_type,AUDIO)&<_32(st_fx->total_brate_fx,ACELP_8k85)) + { + core_type = 0; + move16(); + } + ELSE + { + core_type = 1; + move16(); + } + get_normalize_spec_fx(core, st_fx->extl_fx, mode, core_type, org_fx, SWB_signal_fx, &(hBWE_FD->prev_L_swb_norm1), offset, Q_new_lf); + + IF ( EQ_16(st_fx->extl_fx,WB_BWE)) + { + max_band = 4; + move16(); + band_step = 2; + move16(); + } + ELSE + { + max_band = SWB_FENV; + move16(); + band_step = 1; + move16(); + } + } + ELSE /* HQ core */ + { + gamma_fx = 18022; + move16();/*.55 in Q15 */ + get_normalize_spec_fx(core, st_fx->extl_fx, mode, -1, org_fx, SWB_signal_fx, &(hBWE_FD->prev_L_swb_norm1), offset, Q_new_lf); + + band_step = 1; + move16(); + IF ( EQ_16(offset,HQ_GENERIC_FOFFSET_32K)) + { + max_band = 12; + move16(); + } + ELSE + { + max_band = SWB_FENV; + move16(); + } + } + + FOR( n_band=0; n_bandhBstr, IND_WB_FENV, index, 5 ); + + return (mode); +} + +/*-------------------------------------------------------------------* + * SWB_BWE_encoding() + * + * SWB BWE encoder + *-------------------------------------------------------------------*/ +static Word16 SWB_BWE_encoding_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *insig_fx, /* i : delayed original input signal at 32kHz */ + const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ + const Word16 *insig_hp_fx, /* i : delayed original highband input signal at 32kHz */ + const Word16 *synth_fx, /* i : delayed ACELP core synthesis at 12.8kHz */ + const Word16 *yos_fx, /* i : MDCT coefficients of the windowed original input signal at 32kHz */ + Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ + const Word16 tilt_nb_fx, /* i : SWB tilt */ + const Word16 st_offset, /* i : start frequency offset for BWE envelope */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_insig_lp, + Word16 Q_shb, + Word16 Q_synth, + Word16 Q_synth_lf +) +{ + Word16 IsTransient, mode; + Word16 index; + Word16 i, n_coeff, n_band, pos, indice[6]; + Word16 L; + Word16 IsTransient_LF; + + Word16 tmp; + Word32 energy_fx; + Word16 tilt_fx; + Word32 global_gain_fx; + Word32 L_tmp; + Word32 L_SWB_fenv_fx[SWB_FENV]; + Word16 SWB_tenv_fx[SWB_TENV]; + Word32 L_SWB_tenv, WB_tenv_syn_fx, WB_tenv_orig_fx; + Word16 exp, expn, expd; + Word16 num, den; + Word16 scale; + Word16 Rat_tenv_fx; + Word16 SWB_tenv_tmp_fx[SWB_TENV]; + Word16 max_fx; + Word16 energy_factor_fx[SWB_FENV], w_env_fx[SWB_FENV]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16(st_fx->L_frame_fx, L_FRAME )) + { + L = L_SUBFR; + move16(); + } + ELSE + { + L = L_SUBFR16k; + move16(); + } + + /* HF transient detect */ + IsTransient = detect_transient_fx( insig_hp_fx, L_FRAME16k, Q_shb, st_fx); + st_fx->EnergyLT_fx_exp = shl(Q_shb, 1); + + /* LF transient detect */ + IsTransient_LF = 0; + move16(); + FOR ( n_band = 0; n_band < 4; n_band++ ) + { + tmp = i_mult2(n_band, L); + energy_fx = L_deposit_l(0); + FOR(i=0; iEnergyLF_fx)) + { + IsTransient_LF = 1; + move16(); + } + + hBWE_FD->EnergyLF_fx = energy_fx; + move32(); + } + + /* tilt returned in Q24 go to Q11 */ +#ifdef BASOP_NOGLOB + tilt_fx = round_fx_o(L_shl_o(calc_tilt_bwe_fx(insig_fx, 0, L_FRAME32k), 3, &Overflow), &Overflow); +#else + tilt_fx = round_fx(L_shl(calc_tilt_bwe_fx(insig_fx, 0, L_FRAME32k), 3)); +#endif + test(); + test(); + IF( EQ_16(IsTransient,1)&&(GT_16(tilt_fx,16384)||GT_16(st_fx->clas_fx,1))) + { + IsTransient = 0; + move16(); + st_fx->TransientHangOver_fx = 0; + move16(); + } + + IF( EQ_16(IsTransient,1)) + { + mode = IsTransient; + move16(); + push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l(0); + FOR (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + energy_fx = L_deposit_l(0); + FOR (n_coeff = swb_bwe_trans_subband[n_band]+st_offset; n_coeff < swb_bwe_trans_subband[n_band+1]+st_offset; n_coeff++) + { + L_tmp = L_shr(L_mult0(yos_fx[n_coeff], yos_fx[n_coeff]), 7); /*2*Q_synth-7 */ + energy_fx = L_add(L_tmp, energy_fx); /*2*Q_synth-7 */ + } + global_gain_fx = L_add(global_gain_fx, L_shr(energy_fx, sub(sub(shl(Q_synth,1),7), shl(Q_shb,1)))); /*2*Q_shb */ + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + global_gain_fx = L_shr(global_gain_fx, 1); /*2*Q_shb */ + + FOR (n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + expd = norm_s(swb_bwe_trans_subband_width[n_band]); + tmp = div_s(shl(1,sub(14,expd)), swb_bwe_trans_subband_width[n_band]);/*Q(29-expd) */ + L_tmp = Mult_32_16(L_SWB_fenv_fx[n_band], tmp); /*2*Q_synth-7+29-expd - 15 */ + exp = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp)); + move16(); + exp = sub(sub(30, exp), sub(add(shl(Q_synth,1),7),expd)); + L_tmp = Mpy_32_16(exp, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + tmp = round_fx(L_shl(L_tmp, 10)); /* Q8 */ + + SWB_fenv_fx[n_band] = sub(tmp, Mean_env_tr_fx[n_band]); + move16();/*Q8 */ + } + + WB_tenv_orig_fx = L_deposit_l(0); + WB_tenv_syn_fx = L_deposit_l(1); + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + tmp = i_mult2(n_band, L_SUBFR16k); + L_SWB_tenv = L_deposit_l(0); + FOR(i = 0; i < L_SUBFR16k; i++) + { + L_SWB_tenv = L_add(L_SWB_tenv, L_mult0(insig_hp_fx[i + tmp], insig_hp_fx[i + tmp])); /*2*Q_shb */ + } + + tmp = i_mult2(n_band, L); + FOR(i=0; iQ_syn2 - 7 */ + WB_tenv_orig_fx = L_add(WB_tenv_orig_fx, L_shr(L_mult0(insig_lp_fx[i + tmp], insig_lp_fx[i + tmp]), 7)); /*2*Q_insig_lp - 7 */ + } + + L_tmp = Mult_32_16(L_SWB_tenv, INV_L_SUBFR16k_FX);/*2*Q_shb */ + SWB_tenv_fx[n_band] = 0; + move16(); + IF(L_tmp != 0) + { + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + exp = sub(exp, sub(30, 2*Q_shb)); + + tmp = div_s(16384, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp) */ + + SWB_tenv_fx[n_band] = round_fx(L_shl(L_tmp, sub(exp, 12))); /*Q3 */ + } + } + + IF(WB_tenv_orig_fx != 0) + { + expn = norm_l(WB_tenv_orig_fx); + num = extract_h(L_shl(WB_tenv_orig_fx, expn)); + expn = sub(sub(30, expn), sub(shl(Q_insig_lp,1),7)); + + expd = norm_l(WB_tenv_syn_fx); + den = round_fx(L_shl(WB_tenv_syn_fx, expd)); + expd = sub(sub(30, expd), sub(shl(st_fx->Q_syn2, 1), 7)); + + scale = shr(sub(den, num), 15); + num = shl(num, scale); + expn = sub(expn, scale); + + tmp = div_s(num, den); + expn = sub(expn, expd); + + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &expn); /*31-expn */ + +#ifdef BASOP_NOGLOB + Rat_tenv_fx = round_fx_o(L_shl_o(L_tmp, sub(expn, 1), &Overflow), &Overflow);/*Q14 */ +#else + Rat_tenv_fx = round_fx(L_shl(L_tmp, sub(expn, 1)));/*Q14 */ +#endif + } + ELSE + { + Rat_tenv_fx = 16384; + move16(); + } + + IF(LT_16(Rat_tenv_fx, 8192)) + { + L_tmp = L_mult(Rat_tenv_fx, 19661);/*Q29 */ +#ifdef BASOP_NOGLOB + Rat_tenv_fx = round_fx_o(L_shl_o(L_tmp, 2, &Overflow), &Overflow);/*Q15 */ +#else + Rat_tenv_fx = round_fx(L_shl(L_tmp, 2));/*Q15 */ +#endif + } + ELSE IF (GT_16(Rat_tenv_fx, 16384)) + { + Rat_tenv_fx = 32767; + move16(); + } + + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], Rat_tenv_fx); + move16();/*Q3 */ + } + + max_fx = SWB_tenv_fx[0]; + move16(); + pos = 0; + move16(); + FOR(n_band = 1; n_band < SWB_TENV; n_band++) + { + IF(GT_16(SWB_tenv_fx[n_band],max_fx)) + { + max_fx = SWB_tenv_fx[n_band]; + move16(); + pos = n_band; + move16(); + } + } + + max_fx = SWB_tenv_fx[0]; + move16(); + FOR(n_band = 1; n_band < SWB_TENV; n_band++) + { + tmp = sub(mult_r(SWB_tenv_fx[n_band], 6554), SWB_tenv_fx[n_band-1]); + IF(tmp > 0) + { + BREAK; + } + } + + IF(n_band < SWB_TENV) + { + energy_fx = L_deposit_l(0); + FOR(n_band = (pos+1); n_band < SWB_TENV; n_band++) + { + energy_fx = L_add(energy_fx, SWB_tenv_fx[n_band]);/*Q3 */ + } + + IF(pos == sub(SWB_TENV, 1)) + { + energy_fx = L_deposit_l(0); + } + ELSE + { + tmp = sub(SWB_TENV, pos+1); + tmp = div_s(1, tmp); /*Q15 */ + energy_fx = Mult_32_16(energy_fx, tmp);/*Q3 */ + } + + FOR(n_band = 0; n_band < pos; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 16384); + move16(); + } + + /*SWB_tenv_fx[pos] = add(SWB_tenv_fx[pos], mult_r(SWB_tenv_fx[pos], 164)); move16();//Q3 */ + SWB_tenv_fx[pos] = round_fx(L_mac(L_mult(SWB_tenv_fx[pos],32767), SWB_tenv_fx[pos], 164)); /*Q3 */ + + IF(LT_32(energy_fx, SWB_tenv_fx[pos])) + { + FOR(n_band = pos+1; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 29491); + move16();/*Q3 */ + } + } + } + ELSE + { + FOR(n_band = 1; n_band < SWB_TENV; n_band++) + { + IF(GT_16(SWB_tenv_fx[n_band-1], SWB_tenv_fx[n_band])) + { + /*SWB_tenv_fx[n_band-1] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ + SWB_tenv_fx[n_band-1] = round_fx(L_mac(L_mult(SWB_tenv_fx[n_band-1], 16384), SWB_tenv_fx[n_band], 16384)); /*Q3 */ + } + ELSE + { + /*SWB_tenv_fx[n_band] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ + SWB_tenv_fx[n_band] = round_fx(L_mac(L_mult(SWB_tenv_fx[n_band-1], 16384), SWB_tenv_fx[n_band], 16384)); /*Q3 */ + } + } + + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 29491); + move16();/*Q3 */ + } + } + + test(); + test(); + IF(IsTransient_LF == 0 && EQ_16(coder_type,INACTIVE)&&EQ_16(st_fx->TransientHangOver_fx,1)) + { + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + SWB_tenv_fx[n_band] = mult_r(SWB_tenv_fx[n_band], 16384); + move16(); + } + FOR(n_band = 0; n_band < SWB_FENV_TRANS; n_band++) + { + SWB_fenv_fx[n_band] = mult_r(SWB_fenv_fx[n_band], 1638); + move16(); + } + } + ELSE + { + SWB_fenv_fx[2] = mult_r(SWB_fenv_fx[2], 3277); + move16(); + SWB_fenv_fx[3] = mult_r(SWB_fenv_fx[3], 1638); + move16(); + } + + FOR(n_band = 0; n_band < SWB_TENV; n_band++) + { + IF(SWB_tenv_fx[n_band] == 0) + { + SWB_tenv_tmp_fx[n_band] = -32768; + move16(); /*-16 in Q11 */ + } + ELSE + { + L_tmp = L_deposit_h(SWB_tenv_fx[n_band]); /*Q19 */ + expn = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, expn)); + expn = sub(sub(30, expn), 19); + L_tmp = Mpy_32_16(expn, tmp, 32767); /* Q16 */ /*1 in Q15 */ + SWB_tenv_tmp_fx[n_band] = round_fx(L_shl(L_tmp, 11)); /* Q11 */ + } + + IF (GT_16(SWB_tenv_tmp_fx[n_band], 30720)) + { + index = 15; + move16(); + } + ELSE IF (SWB_tenv_tmp_fx[n_band] < 0) + { + index = 0; + move16(); + } + ELSE + { + index = shr(add(SWB_tenv_tmp_fx[n_band], 1024), 11); + } + + push_indice_fx( hBstr, IND_SWB_TENV, index, 4 ); + } + + MSVQ_Interpol_Tran_fx(SWB_fenv_fx, indice); + + push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 7 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 6 ); + } + ELSE + { + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l(0); + FOR (n_band = 0; n_band < SWB_FENV; n_band++) + { + energy_fx = L_deposit_l(0); + FOR (n_coeff = swb_bwe_subband[n_band]+st_offset; n_coeff < swb_bwe_subband[n_band+1]+st_offset; n_coeff++) + { + L_tmp = L_shr(L_mult0(yos_fx[n_coeff], yos_fx[n_coeff]), 5); /*2*Q_synth-5 */ + energy_fx = L_add(L_tmp, energy_fx); /*2*Q_synth-5 */ + } + + IF (LT_16(n_band, sub(SWB_FENV,2))) + { + global_gain_fx = L_add(global_gain_fx, L_shr(energy_fx, sub(2*Q_synth-5, 2*Q_shb))); /*2*Q_shb */ + } + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + + global_gain_fx = L_shr(global_gain_fx, 1); /*2*Q_shb */ + mode = FD_BWE_class_fx(yos_fx, global_gain_fx, tilt_nb_fx, Q_synth, Q_shb, st_fx); + push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + + energy_control_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); + + FOR (n_band = 0; n_band < SWB_FENV; n_band++) + { + L_tmp = Mult_32_16(L_SWB_fenv_fx[n_band],energy_factor_fx[n_band]);/*2*Q_synth-5 */ + L_tmp = Mult_32_16(L_tmp,swb_inv_bwe_subband_width_fx[n_band]);/*2*Q_synth-5 */ + + IF(L_tmp != 0) + { + expn = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp,expn)); + expn = sub(30,add(expn,sub(shl(Q_synth,1),5))); + L_tmp = Mpy_32_16(expn, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + SWB_fenv_fx[n_band] = round_fx(L_shl(L_tmp, 10)); /* Q8 */ + } + ELSE + { + SWB_fenv_fx[n_band] = -24576; + move16(); + } + } + freq_weights_fx(SWB_fenv_fx, w_NOR_fx, w_env_fx, SWB_FENV); + + FOR (n_band = 0; n_band < SWB_FENV; n_band++) + { + SWB_fenv_fx[n_band] = sub(SWB_fenv_fx[n_band] , Mean_env_fx[n_band]); + move16(); + } + + /* Energy VQ */ + msvq_interpol_fx(SWB_fenv_fx, w_env_fx, indice); + + push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 7 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[2], 6 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[3], 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[4], 6 ); + + } + hBWE_FD->prev_mode = mode; + move16(); + hBWE_FD->prev_global_gain_fx = global_gain_fx; + move32(); + st_fx->prev_Q_shb = Q_shb; + move16(); + + return mode; +} + +/*-------------------------------------------------------------------* + * get_normalize_spec_fx_32() + * + *-------------------------------------------------------------------*/ + +static void get_normalize_spec_fx_32( + const Word16 core, /* i : core selected : Q0 */ + const Word16 extl, /* i : extension layer selected: Q0 */ + const Word16 mode, /* i : SHB BWE class : Q0 */ + const Word16 core_type, /* i : coding type : Q0 */ + const Word32 *org_fx, /* i : input spectrum : Q12 */ + Word32 *SWB_signal_fx, /* o : output spectrum : Q20 */ + Word16 *prev_L_swb_norm, /* i : previous norm. len : Q0 */ + const Word16 offset /* i : frequency offset : Q0 */ +) +{ + Word16 n_freq, L_swb_norm; + Word16 frq_end; + Word16 exp1, exp2, tmp; + Word32 L_tmp; + Word32 envelope_fx[L_FRAME32k]; + + set32_fx(SWB_signal_fx, 0, HQ_GENERIC_HIGH0+offset); + calc_normal_length_fx_32(core, org_fx, mode, extl, &L_swb_norm, prev_L_swb_norm); + test(); + IF(EQ_16(extl , SWB_BWE)||EQ_16(extl,FB_BWE)) + { + IF ( EQ_16(mode ,HARMONIC)) + { + Copy32(org_fx, &SWB_signal_fx[add(240,offset)], 240); + Copy32(&org_fx[128], &SWB_signal_fx[add(480,offset)], 80); + } + ELSE + { + Copy32( &org_fx[112], &SWB_signal_fx[add(240,offset)], 128 ); + Copy32( &org_fx[112], &SWB_signal_fx[add(368,offset)], 128 ); + Copy32( &org_fx[176], &SWB_signal_fx[add(496,offset)], 64 ); + } + frq_end = 560+offset; + move16(); + } + ELSE IF (EQ_16(extl , WB_BWE)) + { + IF ( core_type == 0 ) + { + Copy32(&org_fx[160], &SWB_signal_fx[240], 80); + } + ELSE + { + Copy32(&org_fx[80], &SWB_signal_fx[240], 80); + } + frq_end = L_FRAME16k; + move16(); + } + ELSE + { + Copy32( org_fx+HQ_GENERIC_OFFSET, SWB_signal_fx+HQ_GENERIC_HIGH0+offset, HQ_GENERIC_LEN0 ); + Copy32( org_fx+HQ_GENERIC_OFFSET, SWB_signal_fx+HQ_GENERIC_HIGH1+offset, HQ_GENERIC_LEN0 ); + IF ( EQ_16(offset , HQ_GENERIC_FOFFSET_24K4)) + { + Copy32( org_fx+HQ_GENERIC_LOW0, SWB_signal_fx+HQ_GENERIC_HIGH2+offset, HQ_GENERIC_END_FREQ-HQ_GENERIC_HIGH2 ); + } + frq_end = L_FRAME32k; + move16(); + } + + /* calculate envelope */ + calc_norm_envelop_fx_32(SWB_signal_fx, envelope_fx, L_swb_norm, frq_end - offset, offset); + + /* Normalize with envelope */ + FOR ( n_freq = add(swb_bwe_subband[0],offset); n_freqhBWE_FD; + + IF ( core == ACELP_CORE ) + { + gamma_fx = 11468; + move16(); + test(); + IF ( NE_16(coder_type , AUDIO)&&LE_32(st_fx->total_brate_fx,ACELP_8k00)) + { + core_type = 0; + move16(); + } + ELSE + { + core_type = 1; + move16(); + } + + get_normalize_spec_fx_32(core, st_fx->extl_fx, mode, core_type, org_fx, SWB_signal_fx, &(hBWE_FD->prev_L_swb_norm1), offset ); + + IF ( EQ_16(st_fx->extl_fx , WB_BWE)) + { + max_band = 4; + move16(); + band_step = 2; + move16(); + } + } + ELSE /* HQ core */ + { + gamma_fx = 18021; + move16(); + get_normalize_spec_fx_32(core, -1, mode, -1, org_fx, SWB_signal_fx, &(hBWE_FD->prev_L_swb_norm1), offset ); + + IF ( EQ_16(offset , HQ_GENERIC_FOFFSET_32K)) + { + max_band = 12; + move16(); + } + } + + FOR ( n_band=0; n_band 0) + { + a_fx = Mult_32_16(a_fx, swb_inv_bwe_subband_width_fx[k]);/*6 */ + + exp = norm_l(p_fx); + tmp = Log2_norm_lc(L_shl(p_fx, exp));/*15 */ + exp = sub(30, add(exp, 6)); + L_tmp1 = L_add(L_deposit_h(exp), L_shr(L_deposit_h(tmp), 15));/*16 */ + + exp = norm_l(a_fx); + tmp = Log2_norm_lc(L_shl(a_fx, exp)); + exp = sub(30, add(exp, 6)); + L_tmp2 = L_add(L_deposit_h(exp), L_shr(L_deposit_h(tmp), 15));/*16 */ + + p2a_fx = L_sub(L_tmp1, L_tmp2);/*16 */ + avgp2a_fx = L_add(avgp2a_fx, p2a_fx);/*16 */ + } + } + avgp2a_fx = Mult_32_16(avgp2a_fx, inv_band_fx);/*16 + 15 - 15 */ + IF (GT_32(avgp2a_fx , 187227))/*8.6 / 10log10(2), Q16 */ + { + return HQ_GENERIC_EXC1; + } + ELSE + { + return HQ_GENERIC_EXC0; + } +} + +/*-------------------------------------------------------------------* + * hq_generic_encoding_fx() + * + *-------------------------------------------------------------------*/ +void hq_generic_encoding_fx( + const Word32 *coefs_fx, /* i : MDCT coefficients of weighted original : Q12 */ + Word16 *hq_generic_fenv_fx, /* i/o: energy of SWB envelope : Q3 */ + const Word16 hq_generic_offset, /* i : frequency offset for extracting energy : Q0 */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *hq_generic_exc_clas /* o : bwe excitation class : Q0 */ +) +{ + Word16 n_coeff, n_band; + Word16 indice[HQ_GENERIC_NVQIDX]; + Word16 nenv; + + Word16 energy_factor_fx[SWB_FENV] = {0}; + Word16 cs, exp, tmp, tmp2; + Word32 energy_fx; + Word32 L_tmp, max_coefs_fx; + Word16 w_env_fx[SWB_FENV]; + HQ_ENC_HANDLE hHQ_core = st_fx->hHQ_core; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + nenv = SWB_FENV; + move16(); + } + ELSE + { + nenv = SWB_FENV-2; + move16(); + } + + + energy_control_fx_32(st_fx, HQ_CORE, -1, -1, coefs_fx, hq_generic_offset, energy_factor_fx); + + IF ( EQ_16(hHQ_core->hq_generic_speech_class , 1)) + { + push_indice_fx( hBstr, IND_HQ_SWB_EXC_SP_CLAS, 1, 1 ); + *hq_generic_exc_clas = HQ_GENERIC_SP_EXC; + move16(); + } + ELSE + { + *hq_generic_exc_clas = decision_hq_generic_class_fx_32(coefs_fx, hq_generic_offset); + push_indice_fx( hBstr, IND_HQ_SWB_EXC_SP_CLAS, 0, 1 ); + push_indice_fx( hBstr, IND_HQ_SWB_EXC_CLAS, *hq_generic_exc_clas, 1 ); + } + + FOR ( n_band = 0; n_band < nenv; n_band++ ) + { + energy_fx = L_deposit_l(0); + max_coefs_fx = L_deposit_l(0); + tmp2 = add(swb_bwe_subband[n_band+1] , hq_generic_offset); + FOR ( n_coeff = add(swb_bwe_subband[n_band],hq_generic_offset); n_coeff < tmp2; n_coeff++ ) + { + IF (LT_32(max_coefs_fx , L_abs(coefs_fx[n_coeff]))) + { + max_coefs_fx = L_abs(coefs_fx[n_coeff]); + } + } + cs = norm_l(max_coefs_fx); + tmp2 = add(swb_bwe_subband[n_band+1] , hq_generic_offset); + FOR ( n_coeff = add(swb_bwe_subband[n_band],hq_generic_offset); n_coeff < tmp2; n_coeff++ ) + { + tmp = extract_h(L_shl(coefs_fx[n_coeff], cs));/*12 + cs - 16 */ + L_tmp = L_mult0(tmp, tmp);/*2*cs - 8 */ + energy_fx = L_add(energy_fx, L_shr(L_tmp, 5)); + } + + IF (energy_fx != 0) + { + L_tmp = Mult_32_16(energy_fx, energy_factor_fx[n_band]);/*2*cs - 13 */ + L_tmp = Mult_32_16(L_tmp, swb_inv_bwe_subband_width_fx[n_band]);/*2*cs - 13 + 15 - 15 */ + + exp = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(30, add(exp, 2*cs-13)); + + L_tmp = Mpy_32_16(exp, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + hq_generic_fenv_fx[n_band] = round_fx(L_shl(L_tmp, 10));/*Q8 */ + } + ELSE + { + hq_generic_fenv_fx[n_band] = -24576; + move16(); + } + } + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + FOR ( n_band = 0; n_band < DIM_FB; n_band++ ) + { + energy_fx = L_deposit_l(0); + max_coefs_fx = L_deposit_l(0); + tmp2 = fb_bwe_subband[add(n_band,1)]; + FOR ( n_coeff = fb_bwe_subband[n_band]; n_coeff < tmp2; n_coeff++ ) + { + IF (LT_32(max_coefs_fx, L_abs(coefs_fx[n_coeff]))) + { + max_coefs_fx = L_abs(coefs_fx[n_coeff]); + } + } + cs = norm_l(max_coefs_fx); + tmp2 = fb_bwe_subband[add(n_band,1)]; + FOR ( n_coeff = fb_bwe_subband[n_band]; n_coeff < tmp2; n_coeff++ ) + { + tmp = extract_h(L_shl(coefs_fx[n_coeff], cs));/*12 + cs - 16 */ + L_tmp = L_mult0(tmp, tmp);/*2*cs - 8 */ + energy_fx = L_add(energy_fx, L_shr(L_tmp, 5)); + } + + IF (energy_fx != 0) + { + L_tmp = Mult_32_16(energy_fx, fb_inv_bwe_subband_width_fx[n_band]);/*2*cs - 13 + 18 - 15 */ + + exp = norm_l(L_tmp); + tmp = Log2_norm_lc(L_shl(L_tmp, exp)); + exp = sub(30, add(exp, 2*cs-13)); + + L_tmp = Mpy_32_16(exp, tmp, 24660); /* Q14 */ /*10log10(2) in Q13 */ + hq_generic_fenv_fx[add(n_band,nenv)] = round_fx(L_shl(L_tmp, 10));/*Q8 */ + } + ELSE + { + hq_generic_fenv_fx[add(n_band,nenv)] = -24576; + move16(); + } + } + } + + freq_weights_fx(hq_generic_fenv_fx, w_NOR_fx, w_env_fx, nenv); + + FOR ( n_band = 0; n_band < nenv; n_band++ ) + { + hq_generic_fenv_fx[n_band] = sub(hq_generic_fenv_fx[n_band], Mean_env_fx[n_band]); + } + + IF ( st_fx->bwidth_fx == FB ) + { + FOR ( n_band = 0; n_band < DIM_FB; n_band++ ) + { + hq_generic_fenv_fx[add(n_band,nenv)] = sub(shr(hq_generic_fenv_fx[add(n_band,nenv)], 1), Mean_env_fb_fx[n_band]); + } + } + + + /* Energy VQ */ + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + msvq_interpol_fx( hq_generic_fenv_fx, w_env_fx, indice ); + } + ELSE + { + msvq_interpol_2_fx(hq_generic_fenv_fx, w_env_fx, indice, nenv); + } + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + indice[5] = vqSimple_w_fx(hq_generic_fenv_fx+nenv, hq_generic_fenv_fx+nenv, EnvCdbkFB_fx, NULL, DIM_FB, N_CB_FB, 0); + } + + push_indice_fx( hBstr, IND_SWB_FENV_HQ, indice[0], 5 ); + push_indice_fx( hBstr, IND_SWB_FENV_HQ, indice[1], 7 ); + push_indice_fx( hBstr, IND_SWB_FENV_HQ, indice[2], 6 ); + push_indice_fx( hBstr, IND_SWB_FENV_HQ, indice[3], 5 ); + + IF ( LE_16(hq_generic_offset , HQ_GENERIC_FOFFSET_24K4)) + { + push_indice_fx( hBstr, IND_SWB_FENV_HQ, indice[4], 6 ); + } + ELSE + { + push_indice_fx( hBstr, IND_SWB_FENV_HQ, indice[4], 5 ); + } + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + push_indice_fx( hBstr, IND_FB_FENV_HQ, indice[5], 5 ); + } + + FOR ( n_band = 0; n_band < nenv; n_band++ ) + { + tmp = add(hq_generic_fenv_fx[n_band], Mean_env_fx[n_band]);/*8 */ + L_tmp = L_mult(tmp, 21771);/*26 */ + L_tmp = L_shr(L_tmp, 10);/*16 */ + L_Extract(L_tmp, &exp, &tmp);/* */ + tmp = extract_l(Pow2(13, tmp)); + exp = sub(exp, 13); + hq_generic_fenv_fx[n_band] = shl(tmp, add(exp, 1));/*1 */ + } + + + IF ( EQ_16(st_fx->bwidth_fx , FB)) + { + FOR ( n_band = 0; n_band < DIM_FB; n_band++ ) + { + tmp = add(hq_generic_fenv_fx[add(n_band,nenv)], Mean_env_fb_fx[n_band]);/*7 */ + L_tmp = L_mult(tmp, 21771);/*25 */ + L_tmp = L_shr(L_tmp, 9);/*16 */ + L_Extract(L_tmp, &exp, &tmp); + tmp = extract_l(Pow2(13, tmp)); + exp = sub(exp, 13); + hq_generic_fenv_fx[add(n_band,nenv)] = shl(tmp, add(exp, 1));/*2 */ + } + } + + return; +} + +/*-------------------------------------------------------------------* + * fd_bwe_enc_init_fx() + * + * Initialize FD BWE state structure at the encoder + *-------------------------------------------------------------------*/ + +void fd_bwe_enc_init_fx( + FD_BWE_ENC_HANDLE hBWE_FD /* i/o: FD BWE data handle */ +) +{ + set16_fx(hBWE_FD->new_input_hp_fx, 0, NS2SA(16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS)); + set16_fx(hBWE_FD->old_input_fx, 0, NS2SA(48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS)); + set16_fx(hBWE_FD->old_input_wb_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_12k8_NS)); + set16_fx(hBWE_FD->old_input_lp_fx, 0, NS2SA(16000, ACELP_LOOK_NS + DELAY_SWB_TBE_16k_NS)); + set16_fx(hBWE_FD->old_syn_12k8_16k_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS)); + hBWE_FD->prev_mode = NORMAL; + move16(); + set16_fx(hBWE_FD->L_old_wtda_swb_fx, 0, L_FRAME48k); + hBWE_FD->prev_L_swb_norm1 = 8; + move16(); + hBWE_FD->prev_global_gain_fx = 0; + move32(); + hBWE_FD->modeCount = 0; + move16(); + hBWE_FD->EnergyLF_fx = 0; + move32(); + + hBWE_FD->prev_Q_input_lp = 0; + move16(); + set16_fx(hBWE_FD->old_fdbwe_speech_fx, 0, L_FRAME48k); + hBWE_FD->mem_deemph_old_syn_fx = 0; + move16(); + + //hBWE_FD->mem_old_wtda_swb = 0.0f; + + return; +} diff --git a/lib_enc/swb_bwe_enc_hr_fx.c b/lib_enc/swb_bwe_enc_hr_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..0e3bc89a5bd1b93b26c3085154048e1ec46576ce --- /dev/null +++ b/lib_enc/swb_bwe_enc_hr_fx.c @@ -0,0 +1,804 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include +#include "options.h" +#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 "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 constants + *-------------------------------------------------------------------*/ + +/* Values that Allow to Use Left/Right Shifting instead of Division & + 'and' (&) instead of 'modulo' (%) which is also a costly division. */ +#define NUM_TIME_SW_BLKS_SHIFT 2 +#define NUM_TIME_SW_BLKS_MASK (NUM_TIME_SWITCHING_BLOCKS-1) +#define WIDTH_BAND_SHIFT 3 + +/* Values for Max Scaling of Different Sub Function */ +#define DETECT_TRANSIENT_MAX_Q (11+2) +#define MAX_Q_NEW_INPUT 8 +#define NON_TRANSIENT_RESCALE_Q_GUARD 4 +#define TRANSIENT_RESCALE_Q_GUARD 0 +#define SPECTRUM_RESCALE_Q_GUARD 1 +#define MAX_Q_UPSCALING 6 +#define MAX_AVQ_COD_Q_IN 14 + +/*-------------------------------------------------------------------* + * en_band_quant_fx() + * + * Quantize the band envelop + *-------------------------------------------------------------------*/ + +static Word16 en_band_quant_fx(/* o : quantization index */ + Word16 *en_band, /* i/o: (un)quantized envelope value */ + const Word16 *env_code, /* i : envelope codebook */ + const Word16 N /* i : codebook dimension */ +) +{ + Word16 i, ind, tmp16; + Word32 L_err, L_maxerr; + + L_maxerr = 2147483647L; + move32(); + ind = 0; + move16(); + + FOR( i = 0; i < N; i++ ) + { + /* This is More Efficient */ + tmp16 = sub(en_band[0], env_code[i*2]); + L_err = L_mult0(tmp16, tmp16); + tmp16 = sub(en_band[1], env_code[i*2+1]); + L_err = L_mac0(L_err, tmp16, tmp16); + /* L_err = 0; move32(); + FOR (j = 0; j < 2; j++) + { + tmp16 = sub(en_band[j], env_code[i*2+j]); + L_err = L_mac0(L_err, tmp16, tmp16); + } */ + if (LT_32(L_err, L_maxerr)) + { + ind = i; + move16(); + } + L_maxerr = L_min(L_maxerr, L_err); + } + + en_band[0] = env_code[2*ind]; + move16(); + en_band[1] = env_code[2*ind+1]; + move16(); + + return( ind ); +} + +/*-------------------------------------------------------------------* + * swb_bwe_enc_hr_fx() + * + * HR SWB BWE encoder + *-------------------------------------------------------------------*/ +void swb_bwe_enc_hr_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 *new_input_fx, /* i : input signal */ + Word16 new_input_fx_exp, /* i : Exponent of input signal */ + const Word16 input_frame, /* i : frame length */ + const Word16 unbits /* i : number of core unused bits */ +) +{ + Word16 i, j, k, nBits, nBits_total, nBits_block, Nsv, Nsv2, width_noncoded; + Word16 is_transient, pos; + Word16 x_norm_fx[NSV_MAX*(WIDTH_BAND+1)], x_norm1_fx[NSV_MAX*(WIDTH_BAND+1)]; + Word32 t_audio32[L_FRAME48k]; + Word16 *t_audio_fx, t_audio_fx_exp; + Word16 *t_audio_tmp_fx; /* same exponent as 't_audio_fx' */ + Word16 en_band_fx[N_BANDS_BWE_HR]; /* in Q9 */ + Word16 gain1_fx, exp1, gain2_fx, exp2; + Word32 L_gain_fx; + Word16 ind1, ind2; + Word16 nq[NSV_MAX], nq2[NSV_MAX]; + Word32 L_tmp, L_temp; + Word16 temp, temp2; + Word16 *ptr16; + Word16 min_env_fx; + Word32 L_en_noncoded_fx; /* in Q16 */ + Word16 en_noncoded_fx_exp; + Word16 scl; +#if (N_BANDS_BWE_HR*WIDTH_NONTRANS_FREQ_COEF) > L_FRAME48k + Word32 L_t_audio_tmp_fx[N_BANDS_BWE_HR*WIDTH_NONTRANS_FREQ_COEF]; +#else + Word32 L_t_audio_tmp_fx[L_FRAME48k]; +#endif +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + Word32 *ptr32; + + /*---------------------------------------------------------------------* + * initializations + *---------------------------------------------------------------------*/ + + /* Use 32 Bits Buffer to Store Two 16 Bits Vectors in Order to Save Stack Space */ + t_audio_fx = (Word16 *)&t_audio32[0]; + move16(); + t_audio_tmp_fx = (Word16 *)&t_audio32[L_FRAME48k/2]; + move16(); + + ind2 = 0; + move16();/* only to suppress warnings */ + Nsv2 = 0; + move16();/* only to suppress warnings */ + L_en_noncoded_fx = 0; + move16();/* only to suppress warnings */ + en_noncoded_fx_exp = 0; + move16();/* only to suppress warnings */ + gain2_fx = 0; + move16(); + + /* reset memories in case that last frame was a different technology */ + test(); + IF( EQ_16(st_fx->last_core_fx, HQ_CORE)||NE_16(st_fx->last_extl_fx,st_fx->extl_fx)) + { + set16_fx(hBWE_FD->L_old_wtda_swb_fx, 0, L_FRAME48k ); + st_fx->Q_old_wtda = 0; + move16(); + } + + /* calculate SWB BWE bit-budget (extension layer bit-rate + AVQ unused bits from the core layer) */ + /* nBits = st->extl_brate/50 + unbits */ + assert(SWB_BWE_16k == st_fx->extl_brate_fx); + nBits = add(SWB_BWE_16k/50,unbits); /* st->extl_brate_fx is always 16kbps */ + nBits_total = nBits; + move16(); + + /*---------------------------------------------------------------------* + * detect transient frames + *---------------------------------------------------------------------*/ + /* Calc Room for Energy */ + temp = norm_l(st_fx->EnergyLT_fx); + /* Calc Max Exponent for 'new_input_fx' */ + temp = shr(temp, 1); + temp = add(temp, st_fx->EnergyLT_fx_exp); + temp = sub(temp, new_input_fx_exp); + /* Do not Upscale */ + temp = s_min(0, temp); + /* Limit Input to 'Q_DETECT_TRANSIENT_MAX_Q' (to avoid overflow in 'detect_transient_fx' for Energy Loop)*/ + exp1 = Find_Max_Norm16(new_input_fx, input_frame); + exp1 = sub(exp1, 15-DETECT_TRANSIENT_MAX_Q); + /* Downscale at Least by 'exp1' */ + temp = s_min(temp, exp1); + /* Set Exponent of Input */ + exp1 = add(new_input_fx_exp, temp); + + Copy_Scale_sig(new_input_fx, t_audio_fx, input_frame, temp); + /* Bring Energy in 2*Q'exp1' */ + st_fx->EnergyLT_fx = L_shl(st_fx->EnergyLT_fx, shl(sub(exp1, st_fx->EnergyLT_fx_exp), 1)); + + is_transient = detect_transient_fx( t_audio_fx, input_frame, exp1, st_fx ); + st_fx->EnergyLT_fx_exp = exp1; + move16(); + + push_indice_fx( hBstr, IND_HR_IS_TRANSIENT, is_transient, 1 ); + + /*---------------------------------------------------------------------* + * OLA and MDCT + *---------------------------------------------------------------------*/ + + /* To Bring Back to Q15 + 'new_input_fx_exp' */ + /* Save Exponent of Memory (relative to Q15) */ + st_fx->Q_old_wtda = new_input_fx_exp; + move16(); + new_input_fx_exp=0; + wtda_fx( new_input_fx, &new_input_fx_exp, L_t_audio_tmp_fx, hBWE_FD->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, input_frame ); + + direct_transform_fx(L_t_audio_tmp_fx, t_audio32, is_transient, input_frame, &new_input_fx_exp + , /*st_fx->element_mode*/EVS_MONO ); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub(16+MAX_Q_NEW_INPUT, new_input_fx_exp); + /* Possible to Upscale? */ + IF (scl > 0) + { + /* Yes */ + /* Calc Room to Upscale */ + t_audio_fx_exp = Find_Max_Norm32(t_audio32, input_frame); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min(t_audio_fx_exp, scl); + } + Copy_Scale_sig32_16(t_audio32, t_audio_fx, input_frame, scl); + t_audio_fx_exp = add(sub(new_input_fx_exp, 16), scl); + + IF( is_transient ) + { + nBits = -1; + move16(); /* is_transient flag */ + /* 'nBits_block = nBits_total / NUM_TIME_SWITCHING_BLOCKS' */ + nBits_block = shr(nBits_total, NUM_TIME_SW_BLKS_SHIFT); + /* 'nBits += nBits_total % NUM_TIME_SWITCHING_BLOCKS' */ + nBits = add(nBits, s_and(nBits_total, NUM_TIME_SW_BLKS_MASK)); + + /* set width of noncoded (blind estimated) spectrum */ + IF( EQ_16(st_fx->extl_fx, SWB_BWE_HIGHRATE)) + { + width_noncoded = L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + move16(); + } + ELSE /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = (2*END_FREQ_BWE_FULL_FB/50)/NUM_TIME_SWITCHING_BLOCKS - NUM_TRANS_END_FREQ_COEF; + move16(); + } + + /* Find Max Scaling on Remaining Frequencies (after frequencies of non interest are zeroed) */ + temp = shr(input_frame, NUM_TIME_SW_BLKS_SHIFT); + scl = 99; + move16(); + ptr16 = &t_audio_fx[NUM_TRANS_START_FREQ_COEF]; + move16(); + FOR( k = 0; k < input_frame; k+=temp ) + { + /* from t_audio_fx[k..NUM_TRANS_START_FREQ_COEF+k-1] will be zeroed out */ + /* AND */ + /* from t_audio_fx[k+L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS..k+switching_block_length-1] will be zeroed out */ + /* Find Max Scaling on Remaining Frequencies */ + scl = s_min(Find_Max_Norm16(ptr16+k, L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS-NUM_TRANS_START_FREQ_COEF), scl); + IF (scl == 0) + { + BREAK; + } + } + /* Need to Keep at Least some Guard Bits */ + scl = s_max(0, sub(scl, TRANSIENT_RESCALE_Q_GUARD)); + /* Reduce if 't_audio_fx_exp' is Q14 or more (AVQ Cod overflow with more than Q14 Input) */ + scl = sub(scl, s_max(0, sub(add(scl, t_audio_fx_exp), MAX_AVQ_COD_Q_IN))); + /* Update Exponent of 't_audio_fx' */ + /* Here tne Signal is not Upscaled yet and some adjustement to 't_audio_fx_exp' will be used + until the signal is indeed upscaled by 'scl'. That Occurs at the 'normalization with global gain'. */ + t_audio_fx_exp = add(t_audio_fx_exp, scl); + + /*---------------------------------------------------------------------* + * transient frames: processing in blocks (subframes) + *---------------------------------------------------------------------*/ + + FOR( k = 0; k < NUM_TIME_SWITCHING_BLOCKS; k++ ) + { + nBits = add(nBits, nBits_block); + + temp = i_mult2(k, shr(input_frame, NUM_TIME_SW_BLKS_SHIFT)); + + /* Calculate Original Exponent (because the part of the signal that is used + to Calculate the Energy is not yet Scaled) */ + j = sub(t_audio_fx_exp, scl); + + /* compute energy of noncoded (14.4-20kHz) spectrum */ + IF( EQ_16(st_fx->extl_fx, FB_BWE_HIGHRATE)) + { + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + add(temp, NUM_TRANS_END_FREQ_COEF), j, width_noncoded, &temp2); + L_en_noncoded_fx = Sqrt_Ratio32(L_tmp, temp2, L_deposit_l(width_noncoded), 0, &en_noncoded_fx_exp); + en_noncoded_fx_exp = sub(31, en_noncoded_fx_exp); + } + + /* keep only frequencies in interest */ + set16_fx( t_audio_fx + temp, 0, NUM_TRANS_START_FREQ_COEF ); + set16_fx( t_audio_fx + add(temp, L_FRAME32k/NUM_TIME_SWITCHING_BLOCKS), 0, shr(sub(input_frame, L_FRAME32k), NUM_TIME_SW_BLKS_SHIFT) ); + + /*---------------------------------------------------------------------* + * global gain coding + *---------------------------------------------------------------------*/ + + /* compute and quantize global energy */ + /* Original float Code: 'gain = (float)sqrt( gain ) / (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR)' */ + /* Put Divisor to Square to Move it Inside the Sqrt */ + /* So we can do 'sqrt( gain (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR)^2)' */ + L_temp = L_mult0(WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR, WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR); + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + add(temp, NUM_TRANS_START_FREQ_COEF), j, WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR, &temp2); + L_tmp = Sqrt_Ratio32(L_tmp, temp2, L_temp, /*L_temp is in Q0*/0, &exp2); + /* Put in Q16 */ + L_gain_fx = L_shr(L_tmp, sub(31-16, exp2)); /* 31: 'L_tmp' is already in Q31 */ + + ind1 = gain_quant_fx( &L_gain_fx, &gain1_fx, LG10_MIN_GLOB_GAIN_BWE_HR_Q14, LG10_MAX_GLOB_GAIN_BWE_HR_Q13, NBITS_GLOB_GAIN_BWE_HR, &exp1); + + push_indice_fx( hBstr, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_GLOB_GAIN_BWE_HR); + + /* normalization with global gain */ + ptr16 = &t_audio_fx[add(NUM_TRANS_START_FREQ_COEF, temp)]; + move16(); + temp2 = negate(exp1); + gain2_fx = Invert16(gain1_fx, &temp2); + + /* Also Upscale by 'scl' */ + temp2 = sub(temp2, scl); + FOR( i=0; iextl_fx, SWB_BWE_HIGHRATE)) + { + /* st->extl == FB_BWE_HIGHRATE */ + /* 'en_noncoded /= (gain * en_band[N_BANDS_TRANS_BWE_HR-1])' */ + /* Normalize 'L_en_noncoded_fx' */ + j = norm_l(L_en_noncoded_fx); + L_en_noncoded_fx = L_shl(L_en_noncoded_fx, j); + en_noncoded_fx_exp = add(en_noncoded_fx_exp, j); + /* Calc Divisor */ + L_temp = L_mult0(gain1_fx, en_band_fx[N_BANDS_TRANS_BWE_HR-1]); + /* Normalize Divisor */ + temp2 = norm_l(L_temp); + L_temp = L_shl(L_temp, temp2); + temp2 = sub(add(9, temp2), exp1); /* Q9 for 'en_band_fx' */ + j = Invert16(round_fx(L_temp), &temp2); + L_temp = Mult_32_16(L_en_noncoded_fx, j); + temp2 = add(temp2, en_noncoded_fx_exp); + /* Put in Q16 */ + L_temp = L_shr(L_temp, temp2); + + IF( L_msu0(L_temp, BWE_HR_TRANS_EN_LIMIT1_FX_Q16, 1) < 0) + { + ind1 = 1; + move16(); + L_en_noncoded_fx = L_mult0(en_band_fx[N_BANDS_TRANS_BWE_HR-1], BWE_HR_TRANS_EN_LIMIT1_FX_Q16); + } + ELSE IF( L_msu0(L_temp, BWE_HR_TRANS_EN_LIMIT2_FX_Q16, 1) < 0) + { + ind1 = 2; + move16(); + L_en_noncoded_fx = L_mult0(en_band_fx[N_BANDS_TRANS_BWE_HR-1], BWE_HR_TRANS_EN_LIMIT2_FX_Q16); + } + ELSE IF( L_msu0(L_temp, BWE_HR_TRANS_EN_LIMIT3_FX_Q16, 1) < 0) + { + ind1 = 3; + move16(); + L_en_noncoded_fx = L_mult0(en_band_fx[N_BANDS_TRANS_BWE_HR-1], BWE_HR_TRANS_EN_LIMIT3_FX_Q16); + } + ELSE + { + ind1 = 0; + move16(); + L_en_noncoded_fx = L_deposit_h(en_band_fx[N_BANDS_TRANS_BWE_HR-1]); /* to Put in Q16+9 */ + } + + push_indice_fx( hBstr, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_HF_GAIN_BWE_HR); + } + ELSE + { + L_en_noncoded_fx = L_deposit_h(en_band_fx[N_BANDS_TRANS_BWE_HR-1]); + } + en_noncoded_fx_exp = 9+16; + move16(); /* 9 for 'en_band_fx', 16 for 'BWE_HR_TRANS_EN_LIMIT...' */ + + /*---------------------------------------------------------------------* + * AVQ coding (quantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = (NUM_TRANS_END_FREQ_COEF - NUM_TRANS_START_FREQ_COEF) / WIDTH_BAND; + move16(); + AVQ_cod_fx(t_audio_fx + add(temp, NUM_TRANS_START_FREQ_COEF), x_norm_fx, nBits, Nsv, t_audio_fx_exp); + AVQ_encmux_fx(hBstr, st_fx->extl_fx, x_norm_fx, &nBits, Nsv, nq, 0, sub(Nsv, 1)); + + } + } + ELSE /* !is_transient */ + { + /* subtract one bit for is_transient flag */ + nBits = sub(nBits, 1); + + /*---------------------------------------------------------------------* + * processing of normal (non-transient) frames + *---------------------------------------------------------------------*/ + + /* set width of noncoded (blind estimated) spectrum */ + IF( EQ_16(st_fx->extl_fx, SWB_BWE_HIGHRATE)) + { + width_noncoded = L_FRAME32k - NUM_NONTRANS_END_FREQ_COEF; + move16(); + } + ELSE /* st->extl == FB_BWE_HIGHRATE */ + { + width_noncoded = 2*END_FREQ_BWE_FULL_FB/50 - NUM_NONTRANS_END_FREQ_COEF; + move16(); + } + + /* compute energy of noncoded (14.4-20kHz) spectrum */ + IF( EQ_16(st_fx->extl_fx, FB_BWE_HIGHRATE)) + { + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + NUM_NONTRANS_END_FREQ_COEF, t_audio_fx_exp, width_noncoded, &temp2); + L_en_noncoded_fx = Sqrt_Ratio32(L_tmp, temp2, L_deposit_l(width_noncoded), 0, &en_noncoded_fx_exp); + en_noncoded_fx_exp = sub(31, en_noncoded_fx_exp); + } + + /* keep only frequencies in interest */ + set16_fx( t_audio_fx, 0, NUM_NONTRANS_START_FREQ_COEF ); + set16_fx( t_audio_fx + NUM_NONTRANS_END_FREQ_COEF, 0, sub(input_frame, NUM_NONTRANS_END_FREQ_COEF) ); + + /*---------------------------------------------------------------------* + * global gain coding + *---------------------------------------------------------------------*/ + + /* compute and quantize global gain */ + L_tmp = Calc_Energy_Autoscaled(t_audio_fx + NUM_NONTRANS_START_FREQ_COEF, t_audio_fx_exp, WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR, &temp2); + /* Original float Code: 'gain = (float)sqrt( gain ) / (WIDTH_TRANS_FREQ_COEF*N_BANDS_TRANS_BWE_HR)' */ + /* Put Divisor to Square to Move it Inside the Sqrt */ + /* So we can do 'sqrt( gain (WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR)^2)' */ + L_temp = L_mult0(WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR, WIDTH_NONTRANS_FREQ_COEF*N_BANDS_BWE_HR); + L_tmp = Sqrt_Ratio32(L_tmp, temp2, L_temp, /*L_temp is in Q0*/0, &exp2); + /* Put in Q16 */ + L_gain_fx = L_shr(L_tmp, sub(31-16, exp2)); /* 31: 'L_tmp' is already in Q31 */ + ind1 = gain_quant_fx( &L_gain_fx, &gain1_fx, LG10_MIN_GLOB_GAIN_BWE_HR_Q14, LG10_MAX_GLOB_GAIN_BWE_HR_Q13, NBITS_GLOB_GAIN_BWE_HR, &exp1); + + push_indice_fx( hBstr, IND_HR_GAIN, ind1, NBITS_GLOB_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_GLOB_GAIN_BWE_HR); + + /* normalization with global gain */ + ptr16 = &t_audio_fx[NUM_NONTRANS_START_FREQ_COEF]; + move16(); + /* Find Max Scaling on Remaining Frequencies */ + temp2 = Find_Max_Norm16(ptr16, NUM_NONTRANS_END_FREQ_COEF-NUM_NONTRANS_START_FREQ_COEF); + temp2 = s_max(0, sub(temp2, NON_TRANSIENT_RESCALE_Q_GUARD)); + temp2 = s_min(temp2, MAX_Q_UPSCALING); + t_audio_fx_exp = add(t_audio_fx_exp, temp2); + temp2 = sub(temp2, exp1); + temp = Invert16(gain1_fx, &temp2); + + FOR( i=0; iextl_fx, SWB_BWE_HIGHRATE)) + { + /* st->extl == FB_BWE_HIGHRATE */ + /* 'en_noncoded /= (gain * min_env)' */ + /* Normalize 'L_en_noncoded_fx' */ + temp = norm_l(L_en_noncoded_fx); + L_en_noncoded_fx = L_shl(L_en_noncoded_fx, temp); + en_noncoded_fx_exp = add(en_noncoded_fx_exp, temp); + /* Calc Divisor */ + L_temp = L_mult0(gain1_fx, min_env_fx); + /* Normalize Divisor */ + temp2 = norm_l(L_temp); + L_temp = L_shl(L_temp, temp2); + temp2 = sub(add(9, temp2), exp1); /* Q9 for 'min_env_fx', 'exp1' for 'gain1' */ + j = Invert16(round_fx(L_temp), &temp2); + L_temp = Mult_32_16(L_en_noncoded_fx, j); + temp2 = add(temp2, en_noncoded_fx_exp); + /* Put in Q16 */ + L_temp = L_shr(L_temp, temp2); + IF( L_msu(L_temp, BWE_HR_NONTRANS_EN_LIMIT1_FX_Q15, 1) < 0) + { + ind1 = 1; + move16(); + /* 'en_noncoded = 0.5f * min_env * BWE_HR_NONTRANS_EN_LIMIT1' */ + L_en_noncoded_fx = L_mult0(min_env_fx, BWE_HR_NONTRANS_EN_LIMIT1_FX_Q15/2); + } + ELSE IF( L_msu(L_temp, BWE_HR_NONTRANS_EN_LIMIT2_FX_Q14, 2) > 0) + { + ind1 = 2; + move16(); + /* 'min_env * BWE_HR_NONTRANS_EN_LIMIT2' */ + L_en_noncoded_fx = L_mult(min_env_fx, BWE_HR_NONTRANS_EN_LIMIT2_FX_Q14); + } + ELSE IF( L_msu(L_temp, BWE_HR_NONTRANS_EN_LIMIT3_FX_Q15, 1) > 0) + { + ind1 = 3; + move16(); + L_en_noncoded_fx = L_mult0(min_env_fx, BWE_HR_NONTRANS_EN_LIMIT3_FX_Q15); + } + ELSE + { + ind1 = 0; + move16(); + L_en_noncoded_fx = L_mult0(min_env_fx, 16384); + } + + push_indice_fx( hBstr, IND_HR_HF_GAIN, ind1, NBITS_HF_GAIN_BWE_HR ); + nBits = sub(nBits, NBITS_HF_GAIN_BWE_HR); + } + ELSE + { + L_en_noncoded_fx = L_mult0(min_env_fx, 16384); + } + en_noncoded_fx_exp = 9+16-1; + move16(); /* 9 for 'en_band_fx', 16 for 'BWE_HR_TRANS_EN_LIMIT...' & -1 becaues of 'L_mult0' */ + + /*---------------------------------------------------------------------* + * AVQ coding (quantize normalized spectrum) + *---------------------------------------------------------------------*/ + + Nsv = shr(i, WIDTH_BAND_SHIFT); + AVQ_cod_fx(t_audio_tmp_fx/*same exponent as t_audio_fx*/, x_norm_fx, nBits, Nsv, t_audio_fx_exp); + AVQ_encmux_fx(hBstr, st_fx->extl_fx, x_norm_fx, &nBits, Nsv, nq, 0, sub(Nsv, 1)); + + /*---------------------------------------------------------------------* + * second stage coding + *---------------------------------------------------------------------*/ + + test(); + IF( GE_16(nBits, 9 + NBITS_GLOB_GAIN_BWE_HR)&&sum16_fx(nq,Nsv)>0) + { + /* select spectrum of the second stage coding */ + ptr16 = &t_audio_fx[0]; + move16(); + FOR( i=0; iextl_fx, x_norm1_fx, &nBits, Nsv2, nq2, 0, sub(Nsv2, 1)); + } + + } /* 'ELSE' of ' IF( is_transient )' */ + + /* write unused bits */ + WHILE( nBits > 0 ) + { + i = s_min( nBits, 16 ); + push_indice_fx( hBstr, IND_UNUSED, 0, i ); + nBits = sub(nBits, i); + } + return; +} + diff --git a/lib_enc/swb_bwe_enc_lr_fx.c b/lib_enc/swb_bwe_enc_lr_fx.c index 4088bb500a405d932d5e2b0a1faf5ed4afa37e79..bdd8bbd6358a3e975d6f9740da5b330b07a2e14a 100644 --- a/lib_enc/swb_bwe_enc_lr_fx.c +++ b/lib_enc/swb_bwe_enc_lr_fx.c @@ -32,7 +32,9 @@ #include #include "options.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_com.h" #include "enh32.h" @@ -845,7 +847,7 @@ static void gethar_noisegn_fx( * find lowband indices denoting the selected lowband subband. *--------------------------------------------------------------------------*/ static void EncodeSWBSubbands_fx( - Encoder_State *st_fx, /* i/o: encoder state structure */ + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ Word32 *L_spectra, /* i/o: MDCT domain spectrum */ Word16 QsL, /* i : Q value for L_spectra */ const Word16 fLenLow_fx, /* i : lowband length */ @@ -1044,7 +1046,7 @@ static void EncodeSWBSubbands_fx( * Main encoding routine of SWB BWE for the LR MDCT core *--------------------------------------------------------------------------*/ 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, /* i : Q value */ const Word32 L_m_orig[], /* i/o: scaled orig signal (MDCT) */ diff --git a/lib_enc/swb_pre_proc_fx.c b/lib_enc/swb_pre_proc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..76658d41b8fd62b6be6d9fc570f78d4110adf13f --- /dev/null +++ b/lib_enc/swb_pre_proc_fx.c @@ -0,0 +1,452 @@ +/*==================================================================================== + 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 "rom_com.h" +#include "stl.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 + +/*========================================================================*/ +/* FUNCTION : wb_pre_proc_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Resampling of input signal when input signal sample rate */ +/* is above 16kHz */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx : Encoder State Structure */ +/* _ (Word16*) input : original input signal */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) new_wb_speech : original input signal at 16kHz Q-1 */ +/*------------------------------------------------------------------------*/ + +/* st_fx->old_wtda_wb_fx */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + +void wb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *new_inp_resamp16k, /* i : original input signal in Q-1 */ + Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz in Q-1 */ +) +{ + Word16 Sample_Delay_WB_BWE; + Word16 ramp_flag; + Word16 old_input[NS2SA(16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k]; + Word16 *highband_new_speech; + Word16 highband_old_speech[(L_LOOK_12k8+L_SUBFR+L_FRAME)*5/16]; + Word16 temp_buf[320]; + Word16 Q_wb_sp, i, max_wb; + Word16 fSwitchFromIO = 0; + Word32 temp1 = 0; + Word32 temp2 = 0; + SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( (EQ_32(st_fx->last_total_brate_fx, ACELP_6k60))|| + (EQ_32(st_fx->last_total_brate_fx, ACELP_8k85)) || + (EQ_32(st_fx->last_total_brate_fx, ACELP_12k65)) || + (EQ_32(st_fx->last_total_brate_fx, ACELP_14k25)) || + (EQ_32(st_fx->last_total_brate_fx, ACELP_15k85)) || + (GE_32(st_fx->last_total_brate_fx, ACELP_18k25) && LE_32(st_fx->last_total_brate_fx, ACELP_23k85)) ) + { + fSwitchFromIO = 1; + move16(); + } + + set16_fx( old_input, 0, NS2SA_fx2(16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME16k ); + + max_wb = 1; + move16(); + FOR (i = 0; i < L_FRAME16k; i++ ) + { + max_wb = s_max(max_wb, abs_s(new_inp_resamp16k[i])); + } + Q_wb_sp = norm_s(max_wb); + + Copy_Scale_sig(new_inp_resamp16k, temp_buf, L_FRAME16k, -3); + temp1 = L_mac0(temp1, temp_buf[0], temp_buf[0]); + FOR (i = 1; i < L_FRAME16k; i++) + { + temp1 = L_mac0(temp1, temp_buf[i], temp_buf[i]); + temp2 = L_mac0(temp2, temp_buf[i-1], temp_buf[i]); + } + + if( temp2 < Mult_32_16(temp1, 31129 /*0.95f*/) ) + { + Q_wb_sp = sub(Q_wb_sp, 3); /* leave 3 bit headroom */ + } + Copy_Scale_sig(new_inp_resamp16k, temp_buf, L_FRAME16k, Q_wb_sp); + Scale_sig(hBWE_TD->decim_state1_fx, (2*ALLPASSSECTIONS_STEEP+1), Q_wb_sp); + Scale_sig(hBWE_TD->decim_state2_fx, (2*ALLPASSSECTIONS_STEEP+1), Q_wb_sp); + /* temp_buf, and the memory states are in Q_wb_sp */ + + test(); + test(); + IF ( EQ_16(st_fx->extl_fx, WB_BWE)||EQ_16(st_fx->extl_fx,WB_TBE)||st_fx->igf!=0) + { + ramp_flag = 0; + + test(); + test(); + test(); + test(); + IF( (NE_16(st_fx->last_extl_fx, WB_TBE)&&NE_16(st_fx->last_extl_fx,WB_BWE)&&st_fx->igf==0)|| + (st_fx->igf != 0 && fSwitchFromIO != 0) ) + { + ramp_flag = 1; + } + + IF ( !hSC_VBR->ppp_mode) + { + /* temp_buf is in Q_wb_sp + hb_speech and the two decimator memories are in Q_wb_sp */ + flip_spectrum_and_decimby4_fx( temp_buf, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + + /* rescale the hb_speech and memories back to Q-1 to keep the downstream BWE coding unaffected */ + Scale_sig(hb_speech, L_FRAME16k/4, -Q_wb_sp); + Scale_sig(hBWE_TD->decim_state1_fx, (2*ALLPASSSECTIONS_STEEP+1), -Q_wb_sp); + Scale_sig(hBWE_TD->decim_state2_fx, (2*ALLPASSSECTIONS_STEEP+1), -Q_wb_sp); + + IF( NE_16(st_fx->extl_fx, WB_TBE)) + { + /* Update the previous wideband speech buffer in case of a WB_BWE frame */ + Sample_Delay_WB_BWE = (L_LOOK_12k8 + L_SUBFR) * 5/16; + + highband_new_speech = highband_old_speech + Sample_Delay_WB_BWE; + Copy( hb_speech, highband_new_speech, L_FRAME16k / 4 ); + Copy( highband_old_speech + L_FRAME16k / 4, hBWE_TD->old_speech_wb_fx, Sample_Delay_WB_BWE ); + } + } + } + ELSE + { + 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->old_speech_wb_fx, 0, (L_LOOK_12k8 + L_SUBFR) * 5/16 ); + } + + /* st->old_input_wb and st->old_wtda_wb must be updated each frame, or there are often some clicks during WB TBE <-> WB BWE switching */ + test(); + test(); + test(); + IF ( (NE_16(st_fx->extl_fx, WB_BWE)||(EQ_16(st_fx->extl_fx,WB_BWE)&&LE_32(st_fx->total_brate_fx,ACELP_8k00)))&&!hSC_VBR->ppp_mode) + { + Sample_Delay_WB_BWE = NS2SA_fx2( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + Copy( new_inp_resamp16k, &old_input[Sample_Delay_WB_BWE], L_FRAME16k ); + Copy(hBWE_FD->old_input_wb_fx, old_input, Sample_Delay_WB_BWE ); + Copy( new_inp_resamp16k + L_FRAME16k - Sample_Delay_WB_BWE, hBWE_FD->old_input_wb_fx, Sample_Delay_WB_BWE ); + Copy( old_input, hBWE_FD->L_old_wtda_swb_fx, L_FRAME16k ); + } + return; +} + + +/*========================================================================*/ +/* FUNCTION : swb_pre_proc_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) */ +/* SHB target signal for SWB TBE or SWB BWE coding */ +/* Common SWB TBE and SWB BWE pre-processing */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx : Encoder State Structure Q0 */ +/* _ (Word16*) input_fx : original input signal Q0 */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) new_swb_speech_fx : original input signal at 16kHz Q0 */ +/* _ (Word16*) shb_speech_fx : original input signal at 16kHz Q0 */ +/*------------------------------------------------------------------------*/ + +/* st_fx->old_input_fx */ +/* st_fx->old_wtda_shb_fx */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + +void swb_pre_proc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 *input_fx, /* i : original input signal */ + Word16 *new_swb_speech_fx, /* o : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* o : SHB target signal (6-14kHz) at 16kHz */ + Word16 *Q_shb_spch, + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real CLDFB buffer for target synthesis */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag CLDFB buffer for target synthesis */ + const CLDFB_SCALE_FACTOR *cldfbScale /* i : scale data of real and imag CLDFB buffers */ +) +{ + Word16 Sample_Delay_SWB_BWE, delay; + Word16 inner_frame; + UWord16 inner_Fs; + Word16 old_input_fx[NS2SA(48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k]; + Word16 spchTmp_fx[L_FRAME32k]; + Word16 i; + Word16 startB, endB; + Word16 j; + Word32 *realBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 *imagBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][20]; + Word32 imagBufferTmp[CLDFB_NO_COL_MAX][20]; + Word32 cldfbWorkBuffer[256]; + Word16 ts, nB, uB; + /* Highband energy computation using CLDFB */ + Word32 CldfbHB_ener; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + Word16 realQ_neg1, imagQ_neg1, exp, Cldfbtemp1; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + + FOR( j=0; j < CLDFB_NO_COL_MAX; j++ ) + { + set32_fx(realBufferTmp[j], 0, 20); + set32_fx(imagBufferTmp[j], 0, 20); + realBufferFlipped[j] = realBufferTmp[j]; + imagBufferFlipped[j] = imagBufferTmp[j]; + } + + set16_fx( old_input_fx, 0, NS2SA_fx2(48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) + L_FRAME48k ); + + IF( EQ_32(st_fx->input_Fs_fx, 32000)) + { + Copy(input_fx, new_swb_speech_fx, L_FRAME32k); /*Q0 */ + test(); + test(); + IF( NE_16(st_fx->last_extl_fx, SWB_BWE)&&NE_16(st_fx->last_extl_fx,FB_BWE)&&NE_16(st_fx->extl_fx,SWB_BWE_HIGHRATE)) + { + Sample_Delay_SWB_BWE = NS2SA_fx2( 32000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + Copy(hBWE_FD->old_fdbwe_speech_fx, &old_input_fx[Sample_Delay_SWB_BWE], L_FRAME32k ); + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy(hBWE_FD->old_fdbwe_speech_fx + L_FRAME32k - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + + IF( sub(st_fx->extl_fx, WB_BWE) != 0 ) + { + Copy( old_input_fx, hBWE_FD->L_old_wtda_swb_fx, L_FRAME32k ); + } + } + + test(); + IF( NE_16(st_fx->extl_fx, SWB_BWE)&&NE_16(st_fx->extl_fx,FB_BWE)) + { + Copy( input_fx, hBWE_FD->old_fdbwe_speech_fx, L_FRAME32k ); + } + } + ELSE /* 48 kHz */ + { + /* 48kHz sampled processing needs review of FD2 memory handling/Q-factors */ + IF( EQ_16(st_fx->codec_mode,MODE1)) + { + test(); + test(); + IF( NE_16(st_fx->extl_fx,SWB_BWE)&&NE_16(st_fx->extl_fx,FB_BWE)&&EQ_16(st_fx->core_fx,ACELP_CORE)) + { + /* move the resampling out of the TDBWE path as new_swb_speech is not needed for TDBWE. */ + Copy( input_fx, hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k ); + } + ELSE + { + test(); + IF( NE_16(st_fx->last_extl_fx,SWB_BWE)&&NE_16(st_fx->last_extl_fx,FB_BWE)) + { + /* resample 48 kHz to 32kHz */ + IF( EQ_16(st_fx->last_bwidth_fx,FB)) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + Copy(hBWE_FD->old_fdbwe_speech_fx, new_swb_speech_fx, L_FRAME48k ); + } + ELSE + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + decimate_2_over_3_allpass_fx(hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k, new_swb_speech_fx, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); + } + + Sample_Delay_SWB_BWE = NS2SA_fx2( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + Copy( new_swb_speech_fx, &old_input_fx[Sample_Delay_SWB_BWE], inner_frame ); + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech_fx + inner_frame - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + Copy( old_input_fx, hBWE_FD->L_old_wtda_swb_fx, inner_frame ); + st_fx->Q_old_wtda = 0; + move16(); + } + /* resample 48 kHz to 32kHz */ + IF( EQ_16(st_fx->bwidth_fx,FB)) + { + Copy( input_fx, new_swb_speech_fx, L_FRAME48k ); + } + ELSE + { + decimate_2_over_3_allpass_fx( input_fx, L_FRAME48k, new_swb_speech_fx, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); + } + } + } + ELSE + { + /* resample 48 kHz to 32kHz */ + IF( EQ_16(st_fx->bwidth_fx,FB)) + { + Copy( input_fx, new_swb_speech_fx, L_FRAME48k ); + } + ELSE + { + decimate_2_over_3_allpass_fx( input_fx, L_FRAME48k, new_swb_speech_fx, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, + decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); + } + } + } + + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16(st_fx->core_fx, ACELP_CORE)&&NE_16(st_fx->extl_fx,SWB_BWE_HIGHRATE)&&NE_16(st_fx->extl_fx,FB_BWE_HIGHRATE)) + || ( ( EQ_32(st_fx->total_brate_fx, 9600) || st_fx->rf_mode != 0 ) && EQ_16(st_fx->bwidth_fx, SWB) ) ) + { + IF( EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + startB= 34; + endB= 14; + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + { + uB = 0; + FOR( nB = startB; nB > endB; nB-- ) + { + move16(); + realBufferFlipped[ts][uB] = realBuffer[ts][nB]; + if (s_and(ts, 1) != 0) + { + realBufferFlipped[ts][uB] = L_negate(realBufferFlipped[ts][uB]); + } + imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + if (s_and(ts, 1) == 0) + { + imagBufferFlipped[ts][uB] = L_negate(imagBufferFlipped[ts][uB]); + } + uB = add(uB, 1); /* uB ++ */ + } + } + } + ELSE + { + startB = 39; + endB = 19; + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + { + uB = 0; + FOR( nB = startB; nB > endB; nB-- ) + { + realBufferFlipped[ts][uB] = L_negate(realBuffer[ts][nB]); + imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + uB = add(uB, 1); /* uB ++ */ + } + } + } + + /* Highband energy computation for gain shape control in case of bandwidth switching fix*/ + { + CldfbHB_ener = 0; + FOR (nB = 0; nB < 10; nB++) + { + FOR (ts = 0; ts < CLDFB_NO_COL_MAX; ts++) + { + realQ_neg1 = extract_l(L_shr(realBufferFlipped[ts][nB], 31-(15+cldfbScale->hb_scale)+1)); + imagQ_neg1 = extract_l(L_shr(imagBufferFlipped[ts][nB], 31-(15+cldfbScale->hb_scale)+1)); /* Q(-1), headroom needed */ + +#ifdef BASOP_NOGLOB + CldfbHB_ener = L_mac0_o(CldfbHB_ener, realQ_neg1, realQ_neg1, &Overflow); + CldfbHB_ener = L_mac0_o(CldfbHB_ener, imagQ_neg1, imagQ_neg1, &Overflow); /* Q(-2) */ +#else + CldfbHB_ener = L_mac0(CldfbHB_ener, realQ_neg1, realQ_neg1); + CldfbHB_ener = L_mac0(CldfbHB_ener, imagQ_neg1, imagQ_neg1); /* Q(-2) */ +#endif + } + } + + exp = norm_l(CldfbHB_ener); + CldfbHB_ener = L_shl(CldfbHB_ener, exp); /* CldfbHB_ener = CldfbHB_fl*2^(exp) */ + Cldfbtemp1 = (Log2_norm_lc(CldfbHB_ener)); + Cldfbtemp1 = add(shr(Cldfbtemp1, 6), shl(sub(30, sub(exp, 2)), 9));/* Log2_norm_lc(CldfbHB_ener) = 2^15*(log2(CldfbHB_ener/2^30)) = 2^15*(log2(CldfbHB_fl*(2^-2)*2^exp/2^30)) = 2^15*(log2(CldfbHB_fl) + exp-2-30) => 2^(-6)*l2nc + 2^9(20-(exp-2)) = 2^9*log2(CldfbHB_fl), Q9 */ + CldfbHB_ener = L_mult(sub(Cldfbtemp1, 1741/*3.401 Q9*/), 3495); /* 3495 = Q19 log10(2)*0.1/log10(32768), Q = 19+9+1 = 29 */ + hBWE_TD->cldfbHBLT = mac_r(CldfbHB_ener, 29491/*0.9 Q15*/, hBWE_TD->cldfbHBLT); /* cldfbHBLT is in Q13 */ + } + cldfbSynthesisFiltering( st_fx->cldfbSyn_Fx, realBufferFlipped, imagBufferFlipped, + cldfbScale, shb_speech_fx, 0, CLDFB_NO_COL_MAX, cldfbWorkBuffer ); + *Q_shb_spch = 0; /*shb_speech_fx : Q0*/ + + test(); + test(); + IF( NE_16(st_fx->extl_fx, WB_TBE)&&NE_16(st_fx->extl_fx,SWB_TBE)&&NE_16(st_fx->extl_fx,FB_TBE)) + { + /* Update the previous superwideband speech buffer in case of a SWB_BWE frame - this code is in swb_tbe_enc */ + delay = L_LOOK_16k + L_SUBFR16k; + Copy( shb_speech_fx + L_FRAME16k - delay, hBWE_TD->old_speech_shb_fx, delay ); + } + } + ELSE + { + IF( EQ_16(st_fx->bwidth_fx, FB)||EQ_16(st_fx->core_fx,ACELP_CORE)) + { + set16_fx(hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( shb_speech_fx, 0, L_FRAME16k ); /* shb_speech for FB/SWB BWE_HIGHRATE is not used at 64kbps */ + } + ELSE + { + /* flip the spectrm */ + Copy( new_swb_speech_fx, spchTmp_fx, L_FRAME32k ); + + FOR( i = 0; i < L_FRAME32k; i = i+2 ) + { + spchTmp_fx[i] = negate(spchTmp_fx[i]); + } + + Decimate_allpass_steep_fx( spchTmp_fx, hBWE_TD->state_ana_filt_shb_fx, L_FRAME32k, shb_speech_fx ); + Copy( shb_speech_fx + L_FRAME16k - (L_LOOK_16k + L_SUBFR16k), hBWE_TD->old_speech_shb_fx, L_LOOK_16k + L_SUBFR16k ); + } + + /* Reset CLDFB synthesis buffer */ + set16_fx( st_fx->cldfbSyn_Fx->FilterStates, 0, st_fx->cldfbSyn_Fx->p_filter_length + st_fx->cldfbSyn_Fx->no_channels*st_fx->cldfbSyn_Fx->no_col ); + } + IF( st_fx->last_extl_fx == -1 ) + { + delay = NS2SA(st_fx->input_Fs_fx, DELAY_FIR_RESAMPL_NS); + FOR( i = 0; i < delay; i++ ) + { + shb_speech_fx[i] = mult_r( mult_r(i, 983/*0.03f Q15*/), shb_speech_fx[2*delay-1-i] ); + } + } + + return; +} + diff --git a/lib_enc/swb_tbe_enc_fx.c b/lib_enc/swb_tbe_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..e18647af7ab19c3c4671a70d3e8b47617d9d8aa0 --- /dev/null +++ b/lib_enc/swb_tbe_enc_fx.c @@ -0,0 +1,3895 @@ +/*==================================================================================== + 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 "rom_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ +#include "stl.h" + +/*-----------------------------------------------------------------* +* Local functions +*-----------------------------------------------------------------*/ +static void return_M_Least_fx_GainFrame( const Word32* inp, + const Word32* codebook, const Word16 num_grp, + const Word16 interNum, Word16* least ); + + +static void singlevectortest_gain_fx( const Word32* inp, const Word16 dimen, + const Word16 cb_size, Word16* index, + Word32* recon, const Word32* codebook ); + + +static void determine_gain_weights_fx( const Word32* gain, Word16* weights, + const Word16 dims ); + +static void QuantizeSHBsubgains_fx( Encoder_State_fx* st_fx, Word16* subgains, const Word16 extl ); + + +static void QuantizeSHBframegain_fx( Encoder_State_fx* st_fx, Word32* GainFrame, const Word16 extl, Word32 extl_brate + ,Word16 *rf_gainFrame_ind); + +static Word16 closest_centroid_fx( const Word16* data, const Word16* weights, + const Word16* quantizer, const Word16 centroids, const Word16 length ); + +static Word16 closest_centroid_lc_fx( const Word16* data, const Word16* quantizer, const Word16 centroids ); + +static void EstimateSHBFrameGain_fx( const Word16 length, + const Word16* oriSHB, const Word16 Q_oriSHB, + const Word16* synSHB, const Word16 Q_synSHB, Word16* subgain, + Word32* GainFrame, const Word16* win_shb, const Word16* subwin_shb, const Word16 n_subfr_saturation ); + + +static void EstimateSHBGainShape_fx( const Word16 length, + const Word16* oriSHB, const Word16 Q_oriSHB, + const Word16* synSHB, const Word16 Q_synSHB, + Word16* subgain, const Word16* subwin, Word16* n_subfr_saturation ); + + +static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ); + +static void find_max_mem_enc( Encoder_State_fx *st_fx, Word16 *n_mem, Word16 *n_mem2 ); +static void rescale_genSHB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ); +static void find_max_mem_wb_enc( Encoder_State_fx* st_fx, Word16* n_mem ); +static void rescale_genWB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ); + +static void Quant_lower_LSF_fx( const Word16 lsf[], + Word16 lsf_q[], + Word16 lsf_idx[]); + +static Word16 Quant_mirror_point_fx( const Word16 lsf[], const Word16 lsf_q[], + Word16* m ); +static Word16 Find_LSF_grid_fx( const Word16 lsf[], Word16 lsf_q[], + const Word16 m ); +static void Quant_BWE_LSF_fx( Encoder_State_fx* st_fx, const Word16 lsp_shb[], Word16 Q_lsfs[]); +static void Quant_shb_ener_sf_fx(Encoder_State_fx *st_fx, Word32 *shb_ener_sf_fx_32, Word16 Q_shb); +static void Quant_shb_res_gshape_fx(Encoder_State_fx *st_fx, Word16 *shb_res_gshape_fx); + +static void gainFrSmooth_En_fx(Encoder_State_fx *st_fx, + Word16 *shb_frame_fx, + const Word16 *lpc_shb_fx, + const Word16 *lsp_shb_fx, + Word16 *MA_lsp_shb_spacing, + Word16 *frGainAttenuate, + Word16 *frGainSmoothEn + ); + + +/*-------------------------------------------------------------------* + * find_max_mem_enc() + * + * Find norm and max in TBE memories and past buffers + *-------------------------------------------------------------------*/ +void find_max_mem_enc( + Encoder_State_fx *st_fx, + Word16 *n_mem, + Word16 *n_mem2 +) +{ + Word16 i; + Word16 n_mem_32; + Word16 max = 0; + Word32 Lmax = 0; + Word16 tempQ15, max2 = 0; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + /* old BWE exc max */ + FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) + { + tempQ15 = abs_s( hBWE_TD->old_bwe_exc_extended_fx[i] ); + max = s_max( max, tempQ15 ); + } + + /* decimate all-pass steep memory */ + FOR ( i = 0; i < (2*ALLPASSSECTIONS_STEEP+1); i++ ) + { + tempQ15 = abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ); + max = s_max(max, tempQ15); + } + + /* -- keep norm of state_lpc_syn_fx, state_syn_shbexc_fx, + and mem_stp_swb_fx separately for 24.4 and 32kbps ----*/ + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( hBWE_TD->state_lpc_syn_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < L_SHB_LAHEAD; i++ ) + { + tempQ15 = abs_s( hBWE_TD->state_syn_shbexc_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* findMaxMem2() inside tbe com */ + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( hBWE_TD->mem_stp_swb_fx[i] ); + max2 = s_max(max2, tempQ15); + } + + /* for total_brate > 16.4kbps, use n_mem2; else account for the max2 for n_mem calculation */ + *n_mem2 = norm_s(max2); + if(max2 == 0) *n_mem2 = 15; + if(LT_32(st_fx->total_brate_fx, ACELP_24k40)) + { + max = s_max(max, max2); + } + + /* de-emph and pre-emph memory */ + tempQ15 = abs_s( hBWE_TD->tbe_demph_fx ); + max = s_max(max, tempQ15); + + tempQ15 = abs_s( hBWE_TD->tbe_premph_fx ); + max = s_max(max, tempQ15); + + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tempQ15 = abs_s( hBWE_TD->fb_state_lpc_syn_fx[i] ); + max = s_max(max, tempQ15); + } + /* FB de-emph memory */ + tempQ15 = abs_s( hBWE_TD->fb_tbe_demph_fx); + max = s_max(max, tempQ15); + } + /* estimate the norm for 16-bit memories */ + *n_mem = norm_s( max ); + if( max == 0 ) + { + *n_mem = 15; + } + + /* estimate the norm for 32-bit memories */ + Lmax = L_abs( hBWE_TD->mem_csfilt_fx[0] ); /* only element [0] is used in env. shaping */ + + n_mem_32 = norm_l( Lmax ); + if( Lmax == 0 ) + { + n_mem_32 = 31; + } + + tempQ15 = sub( s_min( *n_mem, n_mem_32 ), 1 ); + *n_mem = s_max( tempQ15, 0 ); +} + + +/*-------------------------------------------------------------------* + * rescale_genSHB_mem_enc() + * + * Rescale genSHB memories + *-------------------------------------------------------------------*/ +void rescale_genSHB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ) +{ + Word16 i; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + FOR( i = 0; i old_bwe_exc_extended_fx[i] = shl( hBWE_TD->old_bwe_exc_extended_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] = shl( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i], sf ); + move16(); + } + + /* -- Apply memory scaling for 13.2 and 16.4k bps using sf ----*/ + IF(LT_32(st_fx->total_brate_fx, ACELP_24k40)) + { + FOR ( i = 0; i < LPC_SHB_ORDER; i++ ) + { + hBWE_TD->state_lpc_syn_fx[i] = shl( hBWE_TD->state_lpc_syn_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < L_SHB_LAHEAD; i++ ) + { + hBWE_TD->state_syn_shbexc_fx[i] = shl( hBWE_TD->state_syn_shbexc_fx[i], sf ); + move16(); + } + } + + hBWE_TD->mem_csfilt_fx[0] = L_shl( hBWE_TD->mem_csfilt_fx[0], sf ); + move32(); + + hBWE_TD->tbe_demph_fx = shl_r( hBWE_TD->tbe_demph_fx, sf ); + move16(); + hBWE_TD->tbe_premph_fx = shl_r( hBWE_TD->tbe_premph_fx, sf ); + move16(); + +} + +void find_max_mem_wb_enc( Encoder_State_fx* st_fx, Word16* n_mem ) +{ + Word16 i; + Word16 n_mem_32; + Word16 max =0; + Word32 Lmax =0; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + FOR ( i = 0; i < NL_BUFF_OFFSET; i++ ) + max = s_max( max, abs_s( hBWE_TD->old_bwe_exc_extended_fx[i] ) ); + + FOR ( i = 0; i < 7; i++ ) + { + IF ( abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ) > max ) + max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ); + } + + FOR ( i = 0; i < 7; i++ ) + { + IF ( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ) > max ) + max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ); + } + + FOR ( i = 0; i < 7; i++ ) + { + IF ( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ) > max ) + max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ); + } + + FOR ( i = 0; i < 10; i++ ) + { + IF ( abs_s( hBWE_TD->state_lpc_syn_fx[i] ) > max ) + max = abs_s( hBWE_TD->state_lpc_syn_fx[i] ); + } + + FOR ( i = 0; i < 5; i++ ) + { + IF ( abs_s( hBWE_TD->state_syn_shbexc_fx[i] ) > max ) + max = abs_s( hBWE_TD->state_syn_shbexc_fx[i] ); + } + + IF ( max == 0 ) + { + *n_mem = 15; + move16(); + } + ELSE + { + *n_mem = norm_s( max ); + move16(); + } + + FOR ( i = 0; i < 2; i++ ) + { + IF ( L_abs( hBWE_TD->mem_csfilt_fx[i] ) > Lmax ) + Lmax = L_abs( hBWE_TD->mem_csfilt_fx[i] ); + } + + + IF ( Lmax == 0 ) + { + n_mem_32 = 31; + move16(); + } + ELSE + { + n_mem_32 = norm_l( Lmax ); + } + + *n_mem = sub( s_min( *n_mem, n_mem_32 ), 1 ); + move16(); + *n_mem = s_max( *n_mem, 0 ); +} + +void rescale_genWB_mem_enc( Encoder_State_fx* st_fx, Word16 sf ) +{ + Word16 i; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + FOR ( i = 0; i < NL_BUFF_OFFSET; i++ ) + { + hBWE_TD->old_bwe_exc_extended_fx[i] = shl( hBWE_TD->old_bwe_exc_extended_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 10; i++ ) + { + hBWE_TD->state_lpc_syn_fx[i] = shl( hBWE_TD->state_lpc_syn_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 5; i++ ) + { + hBWE_TD->state_syn_shbexc_fx[i] = shl( hBWE_TD->state_syn_shbexc_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] = shl( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] = shl( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 7; i++ ) + { + hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] = shl( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i], sf ); + move16(); + } + + FOR ( i = 0; i < 2; i++ ) + { + hBWE_TD->mem_csfilt_fx[i] = L_shl( hBWE_TD->mem_csfilt_fx[i], sf ); + move32(); + } +} + + +/*-------------------------------------------------------------------* + * InitSWBencBuffer() + * + * Initialize SWB buffers + *-------------------------------------------------------------------*/ +void InitSWBencBuffer_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +) +{ + Word16 i; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + set16_fx( hBWE_TD->old_bwe_exc_fx, 0, ( PIT16k_MAX * 2 ) ); + hBWE_TD->bwe_seed[0] = 23; + move16(); + hBWE_TD->bwe_seed[1] = 59; + move16(); + set16_fx( hBWE_TD->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); + hBWE_TD->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + + set16_fx(hBWE_TD->state_ana_filt_shb_fx, 0, (2*ALLPASSSECTIONS_STEEP+1)); + set32_fx( hBWE_TD->elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); + set32_fx( hBWE_TD->elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); + set32_fx( hBWE_TD->elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); + set32_fx( hBWE_TD->elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); + hBWE_TD->prev_fb_energy_fx = 0; + move16(); + + set16_fx( hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx(hBWE_TD->old_speech_wb_fx, 0, (L_LOOK_12k8 + L_SUBFR) * 5 / 16); + set16_fx(hBWE_TD->old_input_fhb_fx, 0, NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k / 2); + + //IVAS_CODE + //set_f(hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER); + //set_f(hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k); + //hBWE_TD->old_mean_EnvSHBres = 0.0f; + //hBWE_TD->prev_enr_EnvSHBres = 1.0f; + //hBWE_TD->prev_shb_env_tilt = 0.0f; + //hBWE_TD->prev_pow_exc16kWhtnd = 1.0f; + //hBWE_TD->prev_mix_factor = 1.0f; + //hBWE_TD->prev_Env_error = 0.0f; + set16_fx(hBWE_TD->prev_lsp_shb_fx, 0, 10 ); + + hBWE_TD->cldfbHBLT = 8192/*1.0f Q13*/; + move16(); + hBWE_TD->prev_gainFr_SHB_fx = 0; + set16_fx(hBWE_TD->lsp_shb_slow_interpl_fx, 0, LPC_SHB_ORDER); + set16_fx(hBWE_TD->lsp_shb_fast_interpl_fx, 0, LPC_SHB_ORDER); + set16_fx(hBWE_TD->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER); + set16_fx(hBWE_TD->lsp_shb_spacing_fx, 3277, 3); + set16_fx( hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q, 0, 4 ); + + hBWE_TD->prev_swb_GainShape_fx = 0; + move16(); + hBWE_TD->prev_frGainAtten = 0; + move16(); + hBWE_TD->prev_wb_GainShape = 0; + move16(); + hBWE_TD->prev_Q_bwe_exc_fb = 51; + move16(); + set16_fx(hBWE_TD->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER); + hBWE_TD->fb_tbe_demph_fx = 0; + move16(); + hBWE_TD->tilt_mem_fx = 0; + move16(); + + 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); + + /* TD BWE post-processing */ + hBWE_TD->ptr_mem_stp_swb_fx = hBWE_TD->mem_stp_swb_fx + LPC_SHB_ORDER - 1; + set16_fx(hBWE_TD->mem_zero_swb_fx, 0, LPC_SHB_ORDER); + + FOR(i = 0; i < LPC_SHB_ORDER; i++) + { + hBWE_TD->swb_lsp_prev_interp_fx[i] = swb_lsp_prev_interp_init[i]; + } + + 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); + + + + hBWE_TD->prev_fb_energy_fx_Q = 0; + move16(); + + + // TV2TV IVAS_CODE -> To be verify if it has to be moved to hBWE_TD + st_fx->prev_Q_bwe_exc = 31; + move16(); + st_fx->prev_Q_bwe_syn = 31; + move16(); + set16_fx(st_fx->prev_lsp_wb_fx, 0, 6 ); + set16_fx(st_fx->prev_lsp_wb_temp_fx, 0, 6 ); + set16_fx(st_fx->prev_lpc_wb_fx, 0, LPC_SHB_ORDER_WB); + + return; +} + +/*-------------------------------------------------------------------* + * ResetSHBbuffer_Enc() + * + *-------------------------------------------------------------------*/ +void ResetSHBbuffer_Enc_fx( + Encoder_State_fx* st_fx /* i/o: SHB encoder structure */ +) +{ + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + /* states for the filters used in generating SHB excitation from WB excitation*/ + set16_fx( hBWE_TD->mem_genSHBexc_filt_down_shb_fx, 0, 2*ALLPASSSECTIONS_STEEP+1); + set32_fx( hBWE_TD->mem_csfilt_fx, 0, 2 ); + + /* states for the filters used in generating SHB signal from SHB excitation*/ + set16_fx( hBWE_TD->state_syn_shbexc_fx, 0, L_SHB_LAHEAD ); + set16_fx( hBWE_TD->state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + + //IF( EQ_16(st_fx->extl_fx, FB_TBE)) _DIFF_FLOAT_FIX_ + { + set16_fx( hBWE_TD->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + hBWE_TD->fb_tbe_demph_fx = 0; + move16(); + } + /* states for the filters used in generating WB signal from WB excitation*/ + 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->mem_genSHBexc_filt_down_wb2_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + set16_fx( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, 0, 2*ALLPASSSECTIONS_STEEP+1 ); + + /* overlap buffer used to Adjust SHB Frame Gain */ + set16_fx(hBWE_TD->mem_stp_swb_fx, 0, LPC_SHB_ORDER); + hBWE_TD->gain_prec_swb_fx = 16384;/*Q14=1 */ + set16_fx( hBWE_TD->syn_overlap_fx, 0, L_SHB_LAHEAD ); + hBWE_TD->tbe_demph_fx = 0; + hBWE_TD->tbe_premph_fx = 0; + + + return; +} + + +/*==========================================================================*/ +/* FUNCTION : void wb_tbe_enc_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : WB TBE encoder, 6 - 8 kHz band encoding module */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 coder_type i : coding type */ +/* Word16 *new_speech i : original input signal Q0 */ +/* Word32 *bwe_exc_extended i : bandwidth extended exciatation 2*Q_new*/ +/* Word16 voice_factors[] i : voicing factors Q15 */ +/* Word16 pitch_buf[] i : pitch for each subframe Q6 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* Word16 *synth o : WB SHB final synthesis */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Encoder_State_fx *st_fx i/o: encoder state structure */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ + +#define WBTBE_LOOK_LSUFBR_5_OVER_16 (L_LOOK_12k8 + L_SUBFR)*5/16 +#define WBTBE_LSUBFR_5_OVER_16 L_SUBFR*5/16 +#define WBTBE_ANA_ALIGNDELAY -(L_SHB_LAHEAD/4 + 5) +#define LFRAME16K_OVER_4 L_FRAME16k/4 +#define WBTBE_LPCWIN_LENGTH (L_LOOK_12k8 + L_SUBFR + L_FRAME) * 5/16 - 1 + +void wb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + const Word16 *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz at Q-1 */ + const Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation */ + const Word16 Q_new, /* i : input HB speech Q factor */ + const Word16 voice_factors[], /* i : voicing factors */ + const Word16 pitch_buf[], /* i : pitch for each subframe */ + const Word16 voicing_fx[] /* i : OL maximum normalized correlation */ +) +{ + Word16 i, j, k; + Word16 hb_old_speech [(L_LOOK_12k8 + L_SUBFR + L_FRAME)*5/16]; + Word16 bwe_exc_extended_16[ L_FRAME32k+NL_BUFF_OFFSET ]; + + Word16 shaped_wb_excitation[(L_FRAME16k + L_SHB_LAHEAD)/4]; + Word16 exc4kWhtnd[L_FRAME16k/4]; + /*Word16 ana_align_delay = WBTBE_ANA_ALIGNDELAY; */ /* -L_SHB_LAHEAD/4 - 5 */ + Word32 GainFrame; + Word16 GainShape[NUM_SHB_SUBFR]; + Word16 lpc_wb[LPC_SHB_ORDER_WB+1]; + Word32 lpc_wb_32_fx[LPC_SHB_ORDER_WB + 1]; + Word16 lsp_wb[LPC_SHB_ORDER_WB], weights_lsp[LPC_SHB_ORDER_WB] = {32767, 32767}; + Word16 *hb_new_speech, *hb_frame/*, hb_speech[ L_FRAME16k ]*/; + Word16 R_h[ LPC_SHB_ORDER_WB + 2 ], R_l[ LPC_SHB_ORDER_WB + 2 ]; + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER_WB+1]; + + Word32 prev_pow, curr_pow, Lscale; + /* Word16 scale; */ + /*Word16 ramp_flag;*/ + Word32 p2m_in, p2m_out; + /*Word16 cnt, max =0;*/ + Word16 n_mem, Q_bwe_exc, Q_bwe_exc_ext, exp_out; /* Q_hb_frame; */ + Word32 L_tmp, Lmax; + Word16 tmp, exp, Q_out, sc; + Word16 Q_ns = -1; + + Word16 pitBufAvg_fx, voicingBufAvg_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 temp_wb_fac_fx, feedback_fx; + Word16 lsp_spacing_fx; + Word16 lsp_wb_temp_fx[ LPC_SHB_ORDER_WB ], lpc_wb_temp_fx[ LPC_SHB_ORDER_WB + 1 ]; + Word32 L_feedback; + Word16 frac, exp1; + Word16 uv_flag; + Word16 dummy=0; + Word16 avg_voice_fac; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /*Word16 att = 32767;*/ + + hb_new_speech = hb_old_speech + WBTBE_LOOK_LSUFBR_5_OVER_16; + hb_frame = hb_old_speech + WBTBE_LSUBFR_5_OVER_16 + WBTBE_ANA_ALIGNDELAY; + + Copy( hBWE_TD->old_speech_wb_fx, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + Copy( hb_speech, hb_new_speech, LFRAME16K_OVER_4 ); + Copy( hb_old_speech + LFRAME16K_OVER_4, hBWE_TD->old_speech_wb_fx, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + + test(); + test(); + test(); + test(); + test(); + test(); + IF ( ( NE_16 (st_fx->last_extl_fx, WB_TBE) && NE_16( st_fx->last_extl_fx, WB_BWE)) + && ( EQ_16( st_fx->clas_fx, UNVOICED_CLAS) || ( LT_16( voicing_fx[0], 16384 ) && LT_16( voicing_fx[1], 16384 ) && LT_16( voicing_fx[2], 16384 ) ) ) + && st_fx->igf == 0 ) + { + /* In case of unvoiced signals after switching cores, back-propagate the target signal */ + Copy( hb_speech, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + + i = WBTBE_LOOK_LSUFBR_5_OVER_16; + move16(); + k = 0; + move16(); + + FOR ( j = 0; j < L_SUBFR16k; j = j + 4 ) + { + L_tmp = L_mult( hb_old_speech[i], ola_win_shb_switch_fold_fx[j] ); + hb_old_speech[i] = mac_r( L_tmp, hb_speech[j], ola_win_shb_switch_fold_fx[ L_SUBFR16k - 4 - j ] ); + move16(); + i--; + k++; + } + } + + autocorr_fx( hb_old_speech, LPC_SHB_ORDER_WB + 1, R_h, R_l, &Q_R, WBTBE_LPCWIN_LENGTH, win_lpc_hb_wb_fx, 0, 1 ); + + E_LPC_lev_dur(R_h, R_l, lpc_wb_temp_fx, LepsP, LPC_SHB_ORDER_WB, NULL); + + Copy_Scale_sig( lpc_wb_temp_fx, lpc_wb_temp_fx, LPC_SHB_ORDER_WB+1, sub(norm_s(lpc_wb_temp_fx[0]),2) ); + + /* convert into lsps and calculate weights */ + FOR ( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb_temp_fx[i] ), 1 ) ); + move32(); + } + + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb_temp_fx, st_fx->prev_lsp_wb_temp_fx, LPC_SHB_ORDER_WB ); + + FOR ( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lsp_wb_temp_fx[i] = lsp_wb_temp_fx[i]; + move16(); + } + + /* lsp_spacing_fx = 16384; move16(); */ + lsp_spacing_fx = lsp_wb_temp_fx[0]; + move16(); + FOR ( i = 1; i < LPC_SHB_ORDER_WB; i++ ) + { + /*if ( i == 0 ) + { + tmp = lsp_wb_temp_fx[0]; move16(); + } + else + {*/ + tmp = sub( lsp_wb_temp_fx[i], lsp_wb_temp_fx[i - 1] ); + /*} */ + + lsp_spacing_fx = s_min( lsp_spacing_fx, tmp ); + } + + /* Spectral smoothing of autocorrelation coefficients */ + FOR ( i = 1; i <= LPC_SHB_ORDER_WB; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_h[i - 1], wac_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + test(); + IF ( EQ_16(st_fx->rf_mode, 1)||EQ_32(st_fx->extl_brate_fx,WB_TBE_0k35)) + { + E_LPC_lev_dur(R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_LBR_WB, NULL); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_LBR_WB+1, sub(norm_s(lpc_wb[0]),2) ); + + /* Expand bandwidth of the LP coeffs */ + FOR ( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR ( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ),1 ) ); + move32();/*Q27 */ + } + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx,LPC_SHB_ORDER_LBR_WB ); + + FOR ( i = 0; i < LPC_SHB_ORDER_LBR_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_LBR_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, lbr_wb_bwe_lsfvq_cbook_2bit_fx, 4, LPC_SHB_ORDER_LBR_WB ); + IF( EQ_16(st_fx->codec_mode, MODE2)) + { + hBWE_TD->lsf_WB = i; + move16(); + } + ELSE + { + push_indice_fx( st_fx->hBstr, IND_SHB_LSF, i, NUM_BITS_LBR_WB_LSF ); + } + + Copy( lbr_wb_bwe_lsfvq_cbook_2bit_fx + i * LPC_SHB_ORDER_LBR_WB, lsp_wb, LPC_SHB_ORDER_LBR_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_LBR_WB ); + + set16_fx( lpc_wb + LPC_SHB_ORDER_LBR_WB + 1, 0, ( LPC_SHB_ORDER_WB - LPC_SHB_ORDER_LBR_WB ) ); + FOR ( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + + FOR ( i = 1; i < LPC_SHB_ORDER_LBR_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + ELSE /* 13.2kbps */ + { + E_LPC_lev_dur(R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_WB, NULL); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_WB+1, sub(norm_s(lpc_wb[0]),2) ); + + /* Expand bandwidth of the LP coeffs */ + FOR ( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR ( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ), 1 ) ); + move32();/*Q27 */ + } + + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx, LPC_SHB_ORDER_WB ); + + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, wb_bwe_lsfvq_cbook_8bit_fx, 256, LPC_SHB_ORDER_WB );/*move16(); */ + + IF( EQ_16(st_fx->codec_mode, MODE2)) + { + hBWE_TD->lsf_WB = i; + move16(); + } + ELSE + { + push_indice_fx( st_fx->hBstr, IND_SHB_LSF, i, NUM_BITS_WB_LSF ); + } + Copy( wb_bwe_lsfvq_cbook_8bit_fx + i * LPC_SHB_ORDER_WB, lsp_wb, LPC_SHB_ORDER_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_WB ); + + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + FOR( i = 1; i < LPC_SHB_ORDER_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + + uv_flag = 0; + move16(); + test(); + if( EQ_32(st_fx->extl_brate_fx, WB_TBE_1k05)&&EQ_16(st_fx->coder_type_raw_fx,UNVOICED)) + { + uv_flag = 1; + move16(); + } + + Copy( voice_factors, vf_modified_fx, NB_SUBFR16k ); + IF( EQ_16(coder_type,VOICED)) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + /*vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1];*/ + vf_modified_fx[i] = add( mult_r( 26214, voice_factors[i] ), mult_r( 6553, voice_factors[i - 1] ) ); + } + IF( NE_16(st_fx->L_frame_fx, L_FRAME)) + { + vf_modified_fx[4] = add( mult_r( 26214, voice_factors[4] ), mult_r( 6553, voice_factors[3] ) ); + } + } + + /* From low band excitation, generate highband excitation */ + Lmax = L_deposit_l(0); + FOR( i = 0; i < L_FRAME32k; i++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[i] ) ); + } + + Q_bwe_exc = 31; + if( Lmax != 0 ) + { + Q_bwe_exc = norm_l( Lmax ); + } + Q_bwe_exc = sub( Q_bwe_exc, 3 ); + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + find_max_mem_wb_enc( st_fx, &n_mem ); + + if( GT_16(sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ),n_mem)) + { + Q_bwe_exc = add( st_fx->prev_Q_bwe_exc, n_mem ); + } + + IF( uv_flag ) + { + if( GT_16( Q_bwe_exc, 20 )) + { + Q_bwe_exc = 20; + move16();/* restrict this to 20 due to the Q factor requireemnt of the random number generator (keep 1 bit headroom) */ + } + } + + prev_pow = 0; + move16(); + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + prev_pow = L_mac0( prev_pow, hBWE_TD->state_syn_shbexc_fx[i], hBWE_TD->state_syn_shbexc_fx[i] ); /* Q(2*st_fx->prev_Q_bwe_exc) */ + } + + rescale_genWB_mem_enc( st_fx, sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ) ); + + Copy( hBWE_TD->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + FOR ( i = 0; i < L_FRAME32k; i++ ) + { + bwe_exc_extended_16[i + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[i], sc ) ); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, hBWE_TD->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + + Copy( hBWE_TD->state_syn_shbexc_fx, shaped_wb_excitation, L_SHB_LAHEAD / 4 ); + Q_bwe_exc_ext = sub( Q_bwe_exc, 16 ); + + + GenShapedWBExcitation_fx( shaped_wb_excitation + L_SHB_LAHEAD / 4, lpc_wb, exc4kWhtnd, hBWE_TD->mem_csfilt_fx, + hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, + hBWE_TD->state_lpc_syn_fx, coder_type, bwe_exc_extended_16, Q_bwe_exc_ext, hBWE_TD->bwe_seed, + vf_modified_fx, uv_flag + , st_fx->igf + ); + + curr_pow = 0; + move16(); + FOR ( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + curr_pow = L_mac0( curr_pow, shaped_wb_excitation[i + L_SHB_LAHEAD/4], shaped_wb_excitation[i + L_SHB_LAHEAD / 4] ); /* Q(2*Q_bwe_exc_ext) */ + } + + IF ( GT_16( voice_factors[0], 24576 )) + { + curr_pow = L_shr( curr_pow, 2 ); /* Q(2*Q_bwe_exc_ext) */ + } + + Lscale = root_a_over_b_fx( curr_pow, shl_r( Q_bwe_exc_ext, 1 ), prev_pow, shl_r( sub(st_fx->prev_Q_bwe_exc, 16 ), 1 ), &exp ); + + + FOR ( i = 0; i < L_SHB_LAHEAD / 4 - 1; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[i] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + } + + Lscale = root_a_fx( Lscale, 31 - exp, &exp ); + L_tmp = Mult_32_16( Lscale, shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + + /* Update WB excitation */ + Copy( shaped_wb_excitation + L_FRAME16k / 4, hBWE_TD->state_syn_shbexc_fx, L_SHB_LAHEAD / 4 ); + + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, + shaped_wb_excitation, Q_bwe_exc_ext, GainShape,subwin_wb_fx, NULL ); + + /* Gain frame adjustment factor */ + test(); + IF( GainShape[0] && hBWE_TD->prev_wb_GainShape ) + { + exp = norm_s( hBWE_TD->prev_wb_GainShape ); + tmp = div_s( shl(1,sub( 14,exp )), hBWE_TD->prev_wb_GainShape ); + L_tmp = L_mult( GainShape[0], tmp ); /* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + L_feedback = L_mult0( temp_wb_fac_fx, temp_wb_fac_fx ); + FOR( i = 1; i < NUM_SHB_SUBFR / 4; i++ ) + { + /* temp_swb_fac = (float)log( (GainShape[i]+0.00001f) / (GainShape[i-1]+0.0001f) ); */ + test(); + IF( GainShape[i] && GainShape[i - 1] ) + { + exp = norm_s( GainShape[i - 1] ); + tmp = div_s( shl(1,sub( 14,exp )), GainShape[i - 1] ); + L_tmp = L_mult( GainShape[i], tmp );/*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + move16(); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_wb_fac_fx, temp_wb_fac_fx ); + + } + L_tmp = L_add( L_shr( L_feedback, 1 ), 1 << 21 ); /* Q30 */ + + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /* Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /* Q31 */ + feedback_fx = round_fx( L_tmp ); /* Q15 */ + } + ELSE + { + feedback_fx = 8738; + move16();/* Q15 */ + } + + + temp_wb_fac_fx = hBWE_TD->prev_wb_GainShape; + move16(); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + GainShape[i] = add( mult_r( sub( 32767, feedback_fx ), GainShape[i] ), mult_r( feedback_fx, temp_wb_fac_fx ) ); + move16(); + temp_wb_fac_fx = GainShape[i]; + move16(); + } + + hBWE_TD->prev_wb_GainShape = GainShape[sub(shr(NUM_SHB_SUBFR,2),1)]; + move16(); + p2m_in = pow_off_pk_fx( GainShape, shr(NUM_SHB_SUBFR,2), 1 ); + move16(); + + IF( EQ_32(st_fx->extl_brate_fx,WB_TBE_0k35)) + { + FOR( i = 0; i < 8; i++ ) + { + GainShape[i] = RECIP_ROOT_EIGHT_FX; + move16(); + } + + } + ELSE + { + push_indice_fx( st_fx->hBstr, IND_UV_FLAG, uv_flag, 1 ); + + /* Quantization of the subframe gain parameter */ + QuantizeSHBsubgains_fx( st_fx, GainShape, st_fx->extl_fx ); + } + + /* Compute the power of gains away from the peak gain after quantization */ + p2m_out = pow_off_pk_fx( GainShape, NUM_SHB_SUBFR / 2, 2 ); + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, shaped_wb_excitation, Q_bwe_exc_ext, GainShape, + &GainFrame, window_wb_fx, subwin_wb_fx, 0 ); + + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + + IF( GT_32( p2m_out, L_shl( p2m_in, 1 ) )) + { + L_tmp = root_a_over_b_fx( L_shl( p2m_in, 1 ), 29, p2m_out, 29, &exp_out ); + GainFrame = L_shl( Mult_32_32( GainFrame, L_tmp ), exp_out ); /* Q18 */ + } + + pitBufAvg_fx = 0; + move16(); + + FOR( i = 0; i < NB_SUBFR; i++ ) + { + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[i], 82 ) ); /*Q6 */ + } + voicingBufAvg_fx = 0; + move16(); + FOR( i = 0; i < 3; i++ ) + { + voicingBufAvg_fx = add( voicingBufAvg_fx, mult_r( voicing_fx[i], 10912 ) ); /*Q15 */ + } + /* GainFrame *= max(min((float)(pitBufAvg/voicingBufAvg), 1.0f), 0.7f); */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl(1,sub( 14,exp )), voicingBufAvg_fx );/* (14-exp) */ + L_tmp = L_mult( pitBufAvg_fx, tmp ); /* (21-exp) */ +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o( L_tmp, add(exp, 10) , &Overflow); + tmp = round_fx_o( L_tmp , &Overflow); /* Q15 */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shl( L_tmp, add(exp, 10) ); + tmp = round_fx( L_tmp ); /* Q15 */ +#endif + } + + tmp = s_max( s_min( tmp, 32767 ), 22938 ); /* Q15 */ + GainFrame = Mult_32_16( GainFrame, tmp ); /* Q18 */ + + IF( LT_16( lsp_spacing_fx, 328 )&&lsp_spacing_fx) + { + GainFrame = Mult_32_16( GainFrame, 21299 ); /* Q18 */ + } + + IF( EQ_16(st_fx->codec_mode, MODE1)) + { + /*wbbwe_em_factor = add( mult_r( 29491, st_fx->prev_wbbwe_em_factor_fx ), mult_r( 3277, wbbwe_em_factor ) ); */ /* Q15 */ + } + + + /*0.25f*sum_f(voice_factors, NB_SUBFR)*/ + L_tmp = L_mult(voice_factors[0], 8192); + FOR (i=1; iigf != 0 && EQ_16(coder_type, VOICED)) + { + /*GainFrame *= 0.5f;*/ + + GainFrame = Mult_32_16( GainFrame, 16384 ); + } + ELSE IF( st_fx->igf != 0 && GT_16( avg_voice_fac, 11469 )) /*Q15 -> 0.35f*/ + { + /*GainFrame *= 0.75f;*/ + GainFrame = Mult_32_16( GainFrame, 24576 ); + } + + /* Quantization of the frame gain parameter */ + QuantizeSHBframegain_fx( st_fx, &GainFrame, st_fx->extl_fx, st_fx->extl_brate_fx, &hRF->RF_bwe_gainFr_ind); + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation*/ + ScaleShapedSHB_fx( SHB_OVERLAP_LEN / 2, shaped_wb_excitation, hBWE_TD->syn_overlap_fx, GainShape, GainFrame, window_wb_fx, subwin_wb_fx, + &Q_bwe_exc_ext, &dummy, dummy, dummy ); + + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + return; +} + + +void fb_tbe_reset_enc_fx( + Word32 elliptic_bpf_2_48k_mem_fx[][4], + Word32 *prev_fb_energy_fx + ,Word16 elliptic_bpf_2_48k_mem_fx_Q[], + Word16 *prev_fb_energy_fx_Q +) +{ + set32_fx( elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); + *prev_fb_energy_fx = 0; + move16(); + set16_fx(elliptic_bpf_2_48k_mem_fx_Q, 0, 4); + *prev_fb_energy_fx_Q = 0; + move16(); + + return; +} +/*======================================================================================*/ +/* FUNCTION : void swb_tbe_enc_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) coder_type_fx : coding type */ +/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ +/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ +/* _(Word16[]) voice_factors :voicing factors Q15 */ +/* _(Word16*) Q_white_exc :Q Format of White Exc */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ +/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State_fx *st_fx: : Encoder state structure */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*======================================================================================*/ + +void swb_tbe_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type_fx, /* i : coding type */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb*/ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_new*/ + const Word16 voice_factors_fx[], /* i : voicing factors Q15*/ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc*/ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6*/ +) +{ + Word16 i, j; + + Word16 shb_old_speech_fx[ L_LOOK_16k + L_SUBFR16k + L_FRAME16k ]; + Word16 bwe_exc_extended_16[ L_FRAME32k+NL_BUFF_OFFSET ]; + + Word16 shaped_shb_excitation_fx [ L_FRAME16k + L_SHB_LAHEAD ]; + Word32 GainFrame_fx; + Word16 GainShape_fx[ NUM_SHB_SUBFR ]; + Word16 lpc_shb_fx[ LPC_SHB_ORDER + 1 ], lsp_shb_fx[ LPC_SHB_ORDER ], lsf_shb_fx[ LPC_SHB_ORDER ]; + Word16 weights_lsp[LPC_SHB_ORDER]; + Word16 Q_out; + Word16* shb_frame_fx, *shb_new_speech_fx; + Word16 R_h[ LPC_SHB_ORDER+ 2 ]; /* Autocorrelations of windowed speech MSB */ + Word16 R_l[ LPC_SHB_ORDER+ 2 ]; /* Autocorrelations of windowed speech LSB */ + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER+1]; + + Word16 ana_align_delay[2] = {-L_SHB_LAHEAD - (NL_BUFF_OFFSET/2), -L_SHB_LAHEAD - (NL_BUFF_OFFSET/2)}; + Word32 prev_pow_fx, curr_pow_fx, Lscale; + Word32 p2m_in_fx, p2m_out_fx; + + Word16 exp_out, exp, exp1, frac; + Word16 cnt, n_mem, n_mem2; + Word32 L_tmp, L_tmp1; + Word16 Q_bwe_exc; + + Word16 frGainAttenuate, frGainSmoothEn; + Word16 MA_lsp_shb_spacing; + Word16 temp_swb_fac, feedback; + Word32 L_feedback; + Word16 tmp, tmp1, tmp2; + Word32 Lmax; + Word16 sc; + Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; + Word16 sd_uq_q_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 pitBufAvg_fx; + Word16 voicingBufAvg_fx; + Word16 sum1, sum2; + Word16 recip,Q_recip; + const Word16 *ptr_lsp_interp_coef_fx; + + Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; + Word16 lpc_shb_sf_fx[4*(LPC_SHB_ORDER+1)]; + + /*Word32 shb_ener_sf_fx_32[4];*/ + Word32 shb_ener_sf_Q31; + Word16 shb_res_fx[L_FRAME16k]; + Word16 shb_res_gshape_fx[NB_SUBFR16k]; + Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; + Word16 vf_ind_fx; + + Word16 formant_fac_fx; + Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; + + Word16 mean_vf; + Word16 lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; + Word16 refl[M]; + Word16 tilt_para; + Word16 Q_bwe_exc_fb; + Word16 n_subfr_saturation; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + + /* init and buffers set up */ + exp1 = 0; /* to avoid compilation warnings */ + set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); + + /* compensate for the delay in target generation and subframe LA */ + shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay[0]; + move16(); + + /* set up the speech buffers for TBE processing*/ + shb_new_speech_fx = shb_old_speech_fx + (L_LOOK_16k + L_SUBFR16k); + move16(); + Copy(hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, (L_LOOK_16k + L_SUBFR16k) ); + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); + Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, (L_LOOK_16k + L_SUBFR16k) ); + + /* autocorrelation of SHB speech for 10-th order LP analysis */ + autocorr_fx( shb_old_speech_fx, + LPC_SHB_ORDER + 1, + R_h, /* autocorr (msb) Q15 */ + R_l, /* autocorr (lsb) */ + &Q_R, + NS2SA(INT_FS_16k, ACELP_LOOK_NS) + L_SUBFR16k + L_FRAME16k, + win_lpc_shb_fx, + 0, + 1 ); + + + /* Spectral smoothing of autocorrelation coefficients */ + test(); + IF( (st_fx->rf_mode != 0) || EQ_32( st_fx->total_brate_fx, ACELP_9k60 )) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + } + + /* Set the autocorr[0] element to a non-negative value */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + E_LPC_lev_dur(R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL); /* LPC in Q14 */ + { + Word16 enerG, lpc_shb1[M+1]; + + /* extend the lpc_shb to a 16th order gain calc */ + set16_fx(lpc_shb1, 0, M+1); + Copy(lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1); + + /* estimate the LP gain */ + enerG = Enr_1_Az_fx(lpc_shb1, 2*L_SUBFR); /* Q3 */ + + /* if the LP gain is greater than a threshold, avoid saturation */ + IF(GT_16(enerG, 256/*32 Q3*/)) + { + set16_fx(lpc_shb_fx, 0, LPC_SHB_ORDER+1); + E_LPC_lev_dur(R_h, R_l, lpc_shb_fx, LepsP, 2, NULL); /* LPC in Q14 */ + } + } + + /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb_fx[0]),2) ); + + /* Expand bandwidth of the LP coeffs */ + test(); + IF( (st_fx->rf_mode != 0) || EQ_32( st_fx->total_brate_fx, ACELP_9k60 )) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + lpc_shb_fx[i] = mult_r(lpc_shb_fx[i], lpc_weights_fx[i]); + } + } + + /* LPC to LSP conversion */ + /* LPC: Q12, LSP: Q15 */ + E_LPC_a_lsp_conversion(lpc_shb_fx, lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); + + /* LSP to LSF conversion */ + /* LSP: Q15, LSF: Q15 */ + E_LPC_lsp_lsf_conversion( lsp_shb_fx, lsf_shb_fx, LPC_SHB_ORDER ); + + /* Input signal filtering in case of tonal sounds in the high band + gain Frame smoothing and attenuation control */ + gainFrSmooth_En_fx(st_fx, shb_frame_fx, lpc_shb_fx, lsf_shb_fx, &MA_lsp_shb_spacing, &frGainAttenuate, &frGainSmoothEn); + + Copy( lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); + Copy( lsf_shb_fx, lsf_shb_orig_fx, LPC_SHB_ORDER ); + + test(); + IF( (EQ_16(st_fx->rf_mode,1))||EQ_32(st_fx->total_brate_fx,ACELP_9k60)) + { + lsp_weights_fx( lsf_shb_fx, weights_lsp, LPC_SHB_ORDER, &Q_out ); + + /* to compensate for the 1.1* weighting done inside the function lsp_weights */ + /*weights_lsp[3]*=0.909091f; weights_lsp[4]*=0.909091f; */ + weights_lsp[3] = mult_r( weights_lsp[3], 29789/*0.909091f Q15*/ ); + weights_lsp[4] = mult_r( weights_lsp[4], 29789/*0.909091f Q15*/ ); + + /* 8-bit VQ, 10 dimension */ + i = closest_centroid_fx( lsf_shb_fx, weights_lsp, swb_tbe_lsfvq_cbook_8b, 256, LPC_SHB_ORDER ); + Copy(swb_tbe_lsfvq_cbook_8b + i*LPC_SHB_ORDER, lsf_shb_fx, LPC_SHB_ORDER); + + set16_fx(hBWE_TD->lsf_idx, 0, NUM_Q_LSF); + hBWE_TD->lsf_idx[0] = i; + } + ELSE + { + /* LSF quantization (21 bits) */ + Quant_BWE_LSF_fx( st_fx, lsf_shb_fx, lsf_shb_fx ); + } + + /* space the lsfs to assert a minimum distance */ + space_lsfs_fx( lsf_shb_fx, LPC_SHB_ORDER ); + + /* voice factor adjustment and gainframe attenuation factor */ + tmp = sub( lsf_shb_fx[0], lsf_shb_orig_fx[0] ); + L_tmp = L_mult(tmp, tmp); + FOR( i = 1; i < LPC_SHB_ORDER; i++ ) + { + /* Estimate the QD in lsfs between UQ and Q */ + tmp = sub( lsf_shb_fx[i], lsf_shb_orig_fx[i] ); + L_tmp = L_mac( L_tmp, tmp, tmp ); + } + sd_uq_q_fx = round_fx(L_tmp); /* sd_uq_q_fx in Q15 */ + /* voice factor modification to limit any spurious jumps in the middle of voiced subframes*/ + /* mean(voice_factors_fx[i], 4); */ + + L_tmp = L_mult(voice_factors_fx[0], 8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[1], 8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[2], 8192); + mean_vf = mac_r(L_tmp, voice_factors_fx[3], 8192); + + Copy( voice_factors_fx, vf_modified_fx, NB_SUBFR16k ); + + test(); + IF( EQ_16(coder_type_fx, VOICED)||GT_16(mean_vf,13107/*0.4f Q15*/)) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + L_tmp = L_mult(voice_factors_fx[i], 26214); + vf_modified_fx[i] = mac_r(L_tmp, voice_factors_fx[i-1], 6554); + move16(); + } + IF( NE_16(st_fx->L_frame_fx, L_FRAME)) + { + L_tmp = L_mult(voice_factors_fx[4], 26214); + vf_modified_fx[4] = mac_r(L_tmp, voice_factors_fx[3], 6554); + move16(); + } + } + + /* convert quantized LSFs to LSPs for interpolation */ + E_LPC_lsf_lsp_conversion(lsf_shb_fx, lsp_shb_2_fx, LPC_SHB_ORDER); + + test(); + IF( EQ_16(st_fx->last_extl_fx, SWB_TBE)||EQ_16(st_fx->last_extl_fx,FB_TBE)) + { + /* SHB LSP values from prev. frame for interpolation */ + Copy(hBWE_TD->swb_lsp_prev_interp_fx, lsp_shb_1_fx, LPC_SHB_ORDER); + } + ELSE + { + /* Use current frame's LSPs; in effect no interpolation */ + Copy(lsp_shb_2_fx, lsp_shb_1_fx, LPC_SHB_ORDER); + } + + lsf_diff[0] = lsf_diff[sub(LPC_SHB_ORDER,1)] = 16384;/*Q15*/ + FOR(i=1; i < LPC_SHB_ORDER-1; i++) + { + lsf_diff[i] = sub(lsf_shb_fx[i],lsf_shb_fx[sub(i,1)]); + } + a2rc_fx (hBWE_TD->cur_sub_Aq_fx+1, refl, M); + + /* LSP interpolation for 13.2 kbps and 16.4 kbps */ + /* tilt_para = 6.6956f * (1.0f + refl[0]) * (1.0f + refl[0]) + - 3.8714f * (1.0f + refl[0]) + + 1.3041f; */ + tmp = add(16384,shr(refl[0],1));/*Q14*/ + tmp1 = mult(27425 /*Q12*/,tmp);/*Q11*/ + tmp1 = mult(tmp1,tmp); + tmp2 = shr(mult(31715,tmp),2); /* Q11 */ + tilt_para = add(sub(tmp1,tmp2),1335);/*Q10*/ + + IF(NE_16(st_fx->last_extl_fx,SWB_TBE)) + { + FOR( i=1; iprev_lsf_diff_fx[i-1] = mult(lsf_diff[i],16384);/*Q15*/ + } + } + + IF( LE_32(st_fx->total_brate_fx,ACELP_16k40)) + { + test(); + test(); + test(); + test(); + test(); + IF(!(GT_16(hBWE_TD->prev_tilt_para_fx,5120)&&(EQ_16(coder_type_fx,TRANSITION)||LT_16(tilt_para,1024)))&& + !(((LT_16(hBWE_TD->prev_tilt_para_fx,3072) && GE_16(hBWE_TD->prev_coder_type,VOICED) )) && GT_16(tilt_para,5120) )) + { + FOR( i = 1; i < LPC_SHB_ORDER-1; i++ ) + { + IF(LT_16(lsf_diff[i], hBWE_TD->prev_lsf_diff_fx[i-1])) + { + tmp = mult(26214,lsf_diff[i]); + tmp = div_s(tmp, hBWE_TD->prev_lsf_diff_fx[i-1]); + tmp = s_max(tmp,16384); + w[i] = s_min(tmp,32767); + } + ELSE + { + tmp = mult(26214,hBWE_TD->prev_lsf_diff_fx[i-1]); + tmp = div_s(tmp,lsf_diff[i]); + tmp = s_max(tmp,16384); + w[i] = s_min(tmp,32767); + } + } + w[0] = w[1]; + w[sub(LPC_SHB_ORDER,1)] = w[sub(LPC_SHB_ORDER,2)]; + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tmp1 = mult(lsp_shb_1_fx[i],sub(32767,w[i])); + tmp2 = mult(lsp_shb_2_fx[i],w[i]); + lsp_temp_fx[i] =add(tmp1,tmp2); + } + } + ELSE + { + Copy(lsp_shb_2_fx, lsp_temp_fx, LPC_SHB_ORDER); + } + } + + Copy( lsf_diff + 1, hBWE_TD->prev_lsf_diff_fx, LPC_SHB_ORDER-2 ); + hBWE_TD->prev_tilt_para_fx = tilt_para; + + shb_ener_sf_Q31 = 0; + move16(); + test(); + IF ( EQ_32(st_fx->total_brate_fx, ACELP_24k40 )||EQ_32(st_fx->total_brate_fx,ACELP_32k)) + { + /* ---------- SHB LSP interpolation ---------- */ + ptr_lsp_interp_coef_fx = interpol_frac_shb; /* Q15 */ + FOR( j = 0; j < 4; j++ ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + /*lsp_temp_fx[i] = lsp_shb_1_fx[i]*(*ptr_lsp_interp_coef_fx) */ + /* + lsp_shb_2_fx[i]*(*(ptr_lsp_interp_coef_fx+1)); */ + L_tmp = L_mult(lsp_shb_1_fx[i], (*ptr_lsp_interp_coef_fx)); + lsp_temp_fx[i] = mac_r(L_tmp, lsp_shb_2_fx[i], (*(ptr_lsp_interp_coef_fx+1))); + move16(); + } + ptr_lsp_interp_coef_fx += 2; + + tmp = i_mult2(j, (LPC_SHB_ORDER+1)); + /* convert LSPs to LPC coefficients for SHB synthesis*/ + E_LPC_f_lsp_a_conversion(lsp_temp_fx, lpc_shb_sf_fx+tmp, LPC_SHB_ORDER); + /* Bring the LPCs to Q12 */ + Copy_Scale_sig( lpc_shb_sf_fx+tmp, lpc_shb_sf_fx+tmp, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb_sf_fx[tmp]),2) ); + } + + /* -------- Calculate the SHB Energy -------- */ + /*shb_ener_sf[0] = 0.003125f * sum2_f( shb_frame + L_SHB_LAHEAD, 320 );*/ + FOR( i = L_SHB_LAHEAD; i < L_FRAME16k + L_SHB_LAHEAD; i++) + { + /* shbEner = shbEner + in[i] * in[i] */ + shb_ener_sf_Q31 = L_mac0(shb_ener_sf_Q31, shb_frame_fx[i], shb_frame_fx[i]); + /* o: shb_ener_sf_Q31 in (2*Q_shb) */ + } + shb_ener_sf_Q31= Mult_32_16(shb_ener_sf_Q31, 102/*0.003125f Q15*/); + shb_ener_sf_Q31= L_add(1l/*1 Q0*/, shb_ener_sf_Q31); + Quant_shb_ener_sf_fx(st_fx, &shb_ener_sf_Q31, (2*Q_shb)); + + /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ + set16_fx(shb_res_fx, 0, L_FRAME16k); + Residu3_10_fx(lpc_shb_sf_fx, shb_frame_fx + L_SHB_LAHEAD, shb_res_fx, 80, 0); + Residu3_10_fx(lpc_shb_sf_fx + (LPC_SHB_ORDER+1), shb_frame_fx + L_SHB_LAHEAD + 80, shb_res_fx + 80, 80, 0); + Residu3_10_fx(lpc_shb_sf_fx + 2*(LPC_SHB_ORDER+1), shb_frame_fx + L_SHB_LAHEAD + 160, shb_res_fx + 160, 80, 0); + Residu3_10_fx(lpc_shb_sf_fx + 3*(LPC_SHB_ORDER+1), shb_frame_fx + L_SHB_LAHEAD + 240, shb_res_fx + 240, 80, 0); + /* i: shb_frame_fx in Q_shb */ + /* o: shb_res_fx in Q_shb */ + + set32_fx(shb_res_gshape_fx_32, 0, NB_SUBFR16k); + FOR(i = 0; i < NB_SUBFR16k; i++) + { + shb_res_gshape_fx_32[i] = sum2_fx(shb_res_fx+i*64, 64); + } + /* o: shb_res_gshape_fx_32 in (2*Q_shb+1) */ + + maximum_32_fx(shb_res_gshape_fx_32, NB_SUBFR16k, &L_tmp); + + /* root_a_over_b_fx(shb_res_gshape_fx_32[i], (2*Q_shb+1), L_tmp, (2*Q_shb+1), &exp);*/ + /* First, find 1/L_tmp, L_tmp in QA = (2*Q_shb+1) */ + + /* case when den = 0 */ + recip = 0; /*instead of 32767 to be compatible with previous root_a_over_b_fx() output */ + Q_recip = 0; + + IF(L_tmp) + { + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp,exp)); + recip = div_s(16384,tmp); + Q_recip = 31-(exp-14); /* = 31-(exp+2*Q_shb+1-14), but adjusted by (2*Q_shb+1) for use at Mult_32_16 below */ + } + + FOR(i = 0; i < NB_SUBFR16k; i++) + { + L_tmp1 = Mult_32_16(shb_res_gshape_fx_32[i], recip); /*Q = Q_recip+1-16*/ + L_tmp = root_a_fx( L_tmp1, Q_recip+1-16, &exp ); + shb_res_gshape_fx[i] = round_fx(L_shl(L_tmp, exp-1)); /* Q14 */ + } + + Quant_shb_res_gshape_fx(st_fx, shb_res_gshape_fx); + } + + /* for 13.2 and 16.4kbps */ + E_LPC_f_lsp_a_conversion(lsp_temp_fx, lpc_shb_fx, LPC_SHB_ORDER); + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER+1, sub(norm_s(lpc_shb_fx[0]),2) ); /* Q12 */ + + /* Save the SWB LSP values from current frame for interpolation */ + Copy(lsp_shb_2_fx, hBWE_TD->swb_lsp_prev_interp_fx, LPC_SHB_ORDER); /* lsp_shb_2_fx in Q15 */ + + /* -------- start of memory rescaling -------- */ + /* ----- calculate optimum Q_bwe_exc and rescale memories accordingly ----- */ + Lmax = L_deposit_l(0); + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[cnt] ) ); + } + Q_bwe_exc = norm_l( Lmax ); + if(Lmax == 0) + { + Q_bwe_exc = 31; + } + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + /* Account for any outliers in the memories from previous frame for rescaling to avoid saturation */ + find_max_mem_enc( st_fx, &n_mem, &n_mem2); + + tmp2 = add( st_fx->prev_Q_bwe_exc, n_mem ); + if( GT_16( Q_bwe_exc, tmp2)) + { + Q_bwe_exc = tmp2; + } + + /* rescale the memories if Q_bwe_exc is different from previous frame */ + sc = sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ); + IF( sc != 0 ) + { + rescale_genSHB_mem_enc( st_fx, sc ); + } + + /* rescale the bwe_exc_extended and bring it to 16-bit single precision with dynamic norm */ + Copy(hBWE_TD->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + bwe_exc_extended_16[cnt + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, hBWE_TD->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + /* state_syn_shbexc_fx is kept at (st_fx->prev_Q_bwe_syn) for 24.4/32kbps or is kept at Q_bwe_exc for 13.2/16.4kbps */ + Copy(hBWE_TD->state_syn_shbexc_fx, shaped_shb_excitation_fx, L_SHB_LAHEAD ); + + /* save the previous Q factor of the buffer */ + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + Q_bwe_exc = sub( Q_bwe_exc, 16 ); /* Q_bwe_exc reflecting the single precision dynamic norm-ed buffers from here */ + + /* -------- end of rescaling memories -------- */ + Q_bwe_exc_fb = hBWE_TD->prev_Q_bwe_exc_fb; + move16(); + /* Determine formant PF strength */ + formant_fac_fx = swb_formant_fac_fx( lpc_shb_fx[1], &hBWE_TD->tilt_mem_fx ); + /* i:lpc_shb_fx Q12, o:formant_fac_fx Q15 */ + + /* Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) SHB excitation signal from the ACELP core excitation */ + vf_ind_fx = 20; + move16(); + + GenShapedSHBExcitation_fx( shaped_shb_excitation_fx + L_SHB_LAHEAD, lpc_shb_fx, White_exc16k_fx, + hBWE_TD->mem_csfilt_fx, hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->state_lpc_syn_fx, + coder_type_fx, bwe_exc_extended_16, hBWE_TD->bwe_seed, vf_modified_fx, st_fx->extl_fx, + &(hBWE_TD->tbe_demph_fx ), &(hBWE_TD->tbe_premph_fx ), lpc_shb_sf_fx, shb_ener_sf_Q31, + shb_res_gshape_fx, shb_res_fx, &vf_ind_fx, formant_fac_fx, hBWE_TD->fb_state_lpc_syn_fx, + &(hBWE_TD->fb_tbe_demph_fx), &Q_bwe_exc,&Q_bwe_exc_fb, Q_shb, n_mem2, st_fx->prev_Q_bwe_syn, st_fx->total_brate_fx, 0 ); + + *Q_white_exc = Q_bwe_exc_fb; + IF( EQ_16(st_fx->extl_fx, FB_TBE)) + { + hBWE_TD->prev_Q_bwe_exc_fb = Q_bwe_exc_fb; + } + ELSE + { + /*Indirectly a memory reset of FB memories for next frame such that rescaling of memories would lead to 0 due to such high prev. Q value. + 51 because of 31 + 20(shift of Q_bwe_exc_fb before de-emphasis)*/ + hBWE_TD->prev_Q_bwe_exc_fb = 51; + move16(); + } + + test(); + IF( EQ_32(st_fx->total_brate_fx, ACELP_24k40)||EQ_32(st_fx->total_brate_fx,ACELP_32k)) + { + IF( EQ_16( st_fx->codec_mode, MODE2 )) + { + hBWE_TD->idx_mixFac = vf_ind_fx; + move16(); + } + ELSE + { + push_indice_fx( st_fx->hBstr, IND_SHB_VF, vf_ind_fx, NUM_BITS_SHB_VF); + } + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + hBWE_TD->mem_stp_swb_fx[i] = shl(hBWE_TD->mem_stp_swb_fx[i], sub(Q_bwe_exc, st_fx->prev_Q_bwe_syn) ); + } + + FOR( i = 0; i < L_FRAME16k; i += L_SUBFR16k ) + { + PostShortTerm_fx( &shaped_shb_excitation_fx[L_SHB_LAHEAD+i], lpc_shb_fx, &shaped_shb_excitationTemp_fx[i], hBWE_TD->mem_stp_swb_fx, + hBWE_TD->ptr_mem_stp_swb_fx, &(hBWE_TD->gain_prec_swb_fx), hBWE_TD->mem_zero_swb_fx, formant_fac_fx ); + /* i: shaped_shb_excitation_fx in Q_bwe_exc */ + /* i: lpc_shb_fx in Q12 */ + } + Copy( shaped_shb_excitationTemp_fx, &shaped_shb_excitation_fx[L_SHB_LAHEAD], L_FRAME16k ); + + + + tmp = sub(shl(Q_bwe_exc, 1), 31); + prev_pow_fx = L_shl(21475l/*0.00001f Q31*/, tmp); /* 2*(Q_bwe_exc) */ + curr_pow_fx = L_shl(21475l/*0.00001f Q31*/, tmp); /* 2*(Q_bwe_exc) */ + FOR( i = 0; i < L_SHB_LAHEAD + 10; i++ ) + { +#ifdef BASOP_NOGLOB + prev_pow_fx = L_mac0_o( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i], &Overflow ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0_o( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], &Overflow); /* 2*Q_bwe_exc */ +#else + prev_pow_fx = L_mac0( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i] ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10] ); /* 2*Q_bwe_exc */ +#endif + } + + if( GT_16( voice_factors_fx[0], 24576/*0.75f Q15*/ )) + { + /*curr_pow_fx = Mult_32_16( curr_pow_fx, 8192);*/ /* Q(2*Q_bwe_exc) */ + curr_pow_fx = L_shr(curr_pow_fx, 2); /* scale by 0.25 */ + } + + Lscale = root_a_over_b_fx( curr_pow_fx, + shl(Q_bwe_exc, 1), + prev_pow_fx, + shl(Q_bwe_exc, 1), + &exp ); + FOR( i = 0; i < L_SHB_LAHEAD; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q(16-exp+Q_bwe_exc) */ + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + } + IF( exp < 0 ) + { + Lscale = L_shl(Lscale, exp); + exp = 0; + } + FOR( ; i < L_SHB_LAHEAD + 10; i++ ) + { +#ifdef BASOP_NOGLOB + tmp = i_mult_o(sub(i, 19), 3277/*0.1f Q15*/, &Overflow); /* Q15 */ + L_tmp1 = Mult_32_16(L_shl_o(1, sub(31,exp), &Overflow), tmp); /* Q31-exp */ +#else + tmp = i_mult(sub(i, 19), 3277/*0.1f Q15*/); /* Q15 */ + L_tmp1 = Mult_32_16(L_shl(1, sub(31,exp)), tmp); /* Q31-exp */ +#endif + tmp = sub(32767/*1.0f Q15*/, tmp); + Lscale = L_add(Mult_32_16(Lscale, tmp), L_tmp1); + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q_bwe_exc + (31-exp) - 15 */ +#ifdef BASOP_NOGLOB + shaped_shb_excitation_fx[i] = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow); /* Q_bwe_exc */ +#else + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ +#endif + } + + /* Update SHB excitation */ + Copy( shaped_shb_excitation_fx + L_FRAME16k, hBWE_TD->state_syn_shbexc_fx, L_SHB_LAHEAD ); /* Q_bwe_exc */ + + /* Estimate the gain-shape parameter */ + n_subfr_saturation = 0; + move16(); + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, + Q_bwe_exc, GainShape_fx, subwin_shb_fx, &n_subfr_saturation ); + + /* Gain shape BWS/high band low energy fix */ + IF( LT_16(hBWE_TD->cldfbHBLT, 8192/*1.0f Q13*/)) /* cldfbHBLT in Q13 */ + { + /* There is not much HB past 10kHz; the temporal resolution is quite coarse, so reduce the dynamic range */ + FOR(i = 0; i < NUM_SHB_SUBGAINS; i++) + { + /* 0.35f +/- delta variation; delta = 0.1*(GS-0.35)*/ + /* GainShape[i] = 0.315f + 0.1f * GainShape[i]; */ + GainShape_fx[i] = mac_r(676457349l/*0.315 Q31*/, 3277/*0.1 Q15*/, GainShape_fx[i]); + } + } + + /* Gain frame adjustment factor */ + /* log( (GainShape[0]) / (st->prev_wb_GainShape) )*/ + test(); + IF( GainShape_fx[0] && hBWE_TD->prev_swb_GainShape_fx ) + { + exp = norm_s(hBWE_TD->prev_swb_GainShape_fx ); + tmp = div_s( shl(1, sub( 14, exp )), hBWE_TD->prev_swb_GainShape_fx ); + L_tmp = L_mult( GainShape_fx[0], tmp );/*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) );/*move16(); */ + exp1 = sub(exp, exp1 ); /*move16(); */ + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + L_feedback = L_mult0( temp_swb_fac, temp_swb_fac ); + + + FOR( i = 1; i < NUM_SHB_SUBGAINS; i++ ) + { + test(); + IF( GainShape_fx[i] && GainShape_fx[i - 1] ) + { + exp = norm_s( GainShape_fx[i - 1] ); + tmp = div_s( shl(1, sub( 14, exp )), GainShape_fx[i - 1] ); + L_tmp = L_mult( GainShape_fx[i], tmp );/* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp , exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_swb_fac, temp_swb_fac ); + } + + /* feedback = 0.4f / (1 + 0.5f * feedback) */ + L_tmp = L_add( L_shr( L_feedback, 1 ), L_shl(1,21) ); /* Q21 */ + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /*Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /*Q31 */ + feedback = round_fx( L_tmp ); /*Q15 */ + } + ELSE + { + feedback = 8738; + move16(); /*Q15 */ + } + + /* voicing in Q15 */ + L_tmp = L_mult(voicing[0],8192); + L_tmp = L_mac(L_tmp, voicing[1],8192); + L_tmp = L_mac(L_tmp, voicing[2],8192); + tmp = sum1 = round_fx(L_tmp); /* sum1 used again below - Q13 */ + tmp = add(tmp,1); /* To ensure change is BE */ + + /* voice_factors_fx in Q15 */ + L_tmp = L_mult(voice_factors_fx[0],8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[1],8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[2],8192); + L_tmp = L_mac(L_tmp, voice_factors_fx[3],8192); + tmp1 = sum2 = round_fx(L_tmp); /* sum2 used again below - Q13 */ + + + test(); + test(); + IF( EQ_16(frGainAttenuate,1)||(GT_16(tmp,19661)&>_16(tmp1,6554))) + + { + temp_swb_fac = hBWE_TD->prev_swb_GainShape_fx; + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /*GainShape_fx[i] = (1 - feedback) * GainShape[i] + feedback * temp_swb_fac; */ + GainShape_fx[i] = round_fx(L_mac(L_mult(sub( 32767, feedback ), GainShape_fx[i] ),feedback, temp_swb_fac ) ); + temp_swb_fac = GainShape_fx[i]; + move16(); + } + } + hBWE_TD->prev_swb_GainShape_fx = GainShape_fx[3]; + move16(); + + /* Compute the power of gains away from the peak gain prior to quantization */ + p2m_in_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + + /* Quantization of the gain shape parameter */ + + QuantizeSHBsubgains_fx( st_fx, GainShape_fx, st_fx->extl_fx ); + /* o: GainShape_fx in Q15 */ + /* Compute the power of gains away from the peak gain after quantization */ + p2m_out_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, Q_bwe_exc, + GainShape_fx, &GainFrame_fx, window_shb_fx, subwin_shb_fx, n_subfr_saturation ); + + IF( EQ_16(st_fx->tec_tfa, 1)) + { + tfaCalcEnv_fx( shb_frame_fx, st_fx->tfa_enr ); + } + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + IF( GT_32( p2m_out_fx, L_shl( p2m_in_fx, 1 ) )) + { + L_tmp = root_a_over_b_fx( p2m_in_fx, 28, p2m_out_fx, 29, &exp_out ); + GainFrame_fx = L_shl( Mult_32_32( GainFrame_fx, L_tmp ), exp_out ); /* Q18 */ + } + test(); + IF( EQ_16(frGainSmoothEn,1)&<_32(hBWE_TD->prev_gainFr_SHB_fx,GainFrame_fx)) + { + GainFrame_fx = L_add( L_shr(hBWE_TD->prev_gainFr_SHB_fx, 1), L_shr(GainFrame_fx, 1) ); /* Q18 */ + } + + test(); + IF( EQ_16(frGainAttenuate, 1)&&LE_16(MA_lsp_shb_spacing,79/*0.0024f Q15*/)) + { + exp1 = norm_l( GainFrame_fx ); + frac = Log2_norm_lc( L_shl( GainFrame_fx, exp1 ) ); + exp = sub(30, add( exp1, 21 ) ); + L_tmp = Mpy_32_16( exp, frac, 26214 ); /* Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + GainFrame_fx = Pow2( 30, frac ); + exp = sub( exp, 30); + GainFrame_fx = L_shl( GainFrame_fx, exp + 18 ); /* Q18 */ + } + ELSE IF( EQ_16(hBWE_TD->prev_frGainAtten, 1)&>_32(Mult_32_16(GainFrame_fx,10923), hBWE_TD->prev_gainFr_SHB_fx)) + { + /*GainFrame *= (0.8f + 0.5f*feedback); */ + tmp = add( 26214, mult_r( feedback, 16384 ) ); + GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 */ + } + hBWE_TD->prev_frGainAtten = frGainAttenuate; + move16(); + hBWE_TD->prev_gainFr_SHB_fx = GainFrame_fx; + move16(); /* Q18 */ + + + /* Gain attenuation when the SWB LSF quantization error is larger than a threshold */ + tmp = mult_r(25600/*400 Q6*/, sd_uq_q_fx); /* Q6 * Q15 => Q6 */ + IF(EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + tmp1 = mult_r(6554/*0.2f Q15*/, tmp); /* Q15, Q6 => Q6 */ + L_tmp = L_msu(8192l/*1.0f Q13*/, tmp1, tmp); /* Q13 */ + } + ELSE + { + tmp1 = mult_r(3277/*0.1f Q15*/, tmp); /* Q15, Q6 => Q6 */ + L_tmp = L_msu(8192l/*1.0f Q13*/, tmp1, tmp); /* Q13 */ + } + /* sd_uq_q = max(min(sd_uq_q, 1.0f), 0.5f); */ + L_tmp = L_min(L_tmp, 8192l/*1.0f Q13*/); + L_tmp = L_max(L_tmp, 4096l/*0.5f Q13*/); /* Q13 */ + /* keep the L_tmp; dont overwrite */ + + /* pitBufAvg = 0.0025f * sum_f(pitch_buf, 4); */ + /* pitch_buf: Q6 */ + pitBufAvg_fx = mult_r(pitch_buf[0],1311) ; + pitBufAvg_fx = add( pitBufAvg_fx, mult_r(pitch_buf[1],1311) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r(pitch_buf[2],1311) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r(pitch_buf[3],1311) ); /* Q10 */ + + /* voicingBufAvg = (sum_f(voice_factors, 4)=sum2 > 0.6f) ? 0.333f : 0.1667f; */ + tmp2 = 5462/*0.1667f Q15*/; + if(GT_16(sum2, 4915/*0.6f Q13*/)) + { + tmp2 = 10912/*0.333f Q15*/; /* Q15 */ + } + voicingBufAvg_fx = shl(mult(tmp2, sum1),2); /* Q15 */ + + + + /* max(min((float)(sd_uq_q*pitBufAvg/voicingBufAvg), 1.0f), 0.6f) */ + /* sd_uq_q: Q13, pitBufAvg_fx: Q6, voicingBufAvg_fx: Q15 */ + + /* 1/voicingBufAvg_fx */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl(1, sub( 14, exp )), voicingBufAvg_fx ); /* (14-exp) */ + + /* sd_uq_q*pitBufAvg */ + L_tmp = Mult_32_16(L_tmp, pitBufAvg_fx); /* Q13 * Q10 + 1 -16 => Q8 */ + L_tmp = Mult_32_16(L_tmp, tmp ); /* Q8 + (14 - exp) - 15 => Q7 - exp */ +#ifdef BASOP_NOGLOB + tmp = round_fx_o(L_shl_o(L_tmp, 31-(7-exp), &Overflow), &Overflow); /* Q15 */ +#else + tmp = round_fx(L_shl(L_tmp, 31-(7-exp))); /* Q15 */ +#endif + } + + tmp = s_min(tmp, 32767/*1.0f Q15*/); + tmp = s_max(tmp, 19661/*0.6f Q15*/); + GainFrame_fx = Mult_32_16(GainFrame_fx, tmp); /* Q18 + Q15 + 1 - 16 : Q18 */ + + test(); + IF(EQ_16(st_fx->L_frame_fx, L_FRAME16k)||EQ_16(st_fx->rf_mode,1)) + { + /* Compensate for energy increase mismatch due to memory-less synthesis*/ + GainFrame_fx = Mult_32_16(GainFrame_fx, 27853/*0.85f Q15*/ ); /* Q18 */ + } + + /* Quantization of the frame gain parameter */ + QuantizeSHBframegain_fx( st_fx, &GainFrame_fx, st_fx->extl_fx, 0, &hRF->RF_bwe_gainFr_ind ); + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation */ + IF( EQ_32(st_fx->extl_fx,FB_TBE)) + { + tmp = norm_l( GainFrame_fx ); + if(GainFrame_fx == 0) + { + tmp = 31; + } + L_tmp = L_shl(GainFrame_fx,tmp);/* 18 + tmp */ + + tmp1 =0; + FOR( i = 0; i < L_FRAME16k; i++ ) + { + L_tmp1 = Mult_32_16( L_tmp, GainShape_fx[NUM_SHB_SUBFR * i / L_FRAME16k] ); /* Q : 18 + tmp +15 -15*/ + /*White_exc16k_fx[i] = round_fx( L_shl(Mult_32_16( L_tmp1, White_exc16k_fx[i]),(23 - tmp -*Q_white_exc)) );*/ + /*18 + tmp +*Q_white_exc -15 + 23 - tmp -*Q_white_exc -16 = 10*/ + White_exc16k_fx[i] = round_fx( Mult_32_16( L_tmp1, White_exc16k_fx[i] ) );/* 18 + tmp +*Q_white_exc -15 -16 */ + /*Lmax = L_max(Lmax,White_exc16k_fx[i]);*/ + tmp1 = s_max(tmp1,abs_s(White_exc16k_fx[i])); + /*White_exc16k_fx[i] =32767;*/ + /*White_exc16k_fx[i] = shr(White_exc16k_fx[i],5);*/ + } + *Q_white_exc = sub(add(*Q_white_exc, tmp),13); /* *Q_white_exc + 18 + tmp -15 -16 */ + tmp = norm_s( tmp1 ); + if(tmp1 == 0) + { + tmp = 15; + } + + FOR(i=0; iprev_Q_bwe_syn = Q_bwe_exc; + move16(); + + return; +} + + +/*==========================================================================*/ +/* FUNCTION : static void EstimateSHBFrameGain_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Estimate the overall gain factor needed to scale */ +/* synthesized highband to original highband signal level. */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) length : SHB overlap length Q0 */ +/* _(Word16*) oriSHB : target original SHB frame Q_oriSHB */ +/* _(Word16*) synSHB : shaped SHB excitation Q_synSHB */ +/* _(Word16*) win_shb : SHB window Q15 */ +/* _(Word16*) subwin_shb_local : SHB subframe window Q15 */ +/* _(Word16) Q_oriSHB : Q format of oriSHB */ +/* _(Word16) Q_synSHB : Q format of synSHB */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word32*)GainFrame :estimat of gain frame Q18 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ + +static void EstimateSHBFrameGain_fx( + const Word16 length, /* i : SHB overlap length */ + const Word16* oriSHB, /* i : target original SHB frame Q_oriSHB */ + const Word16 Q_oriSHB, + const Word16* synSHB, /* i : shaped SHB excitation Q_synSHB */ + const Word16 Q_synSHB, + Word16* subgain, /* i : estimate of gain shape Q15 */ + Word32* GainFrame, /* o : estimat of gain frame Q18 */ + const Word16* win_shb, /* i : SHB window Q15 */ + const Word16* subwin_shb_local /* i : SHB subframe window Q15 */ + ,const Word16 n_subfr_saturation /* i : Number of subframes which saturated in GainShape oriNrg calculation */ +) +{ + const Word16* skip; + Word16 i, j, k, l_shb_lahead, l_frame; + Word16 join_length, num_join, sig; + Word32 mod_syn[L_FRAME16k+L_SHB_LAHEAD]; + Word32 oriNrg = 0, synNrg = 0; + Word16 sum_gain; + Word32 frame_gain; + Word32 L_tmp; + Word16 exp_out; + Word16 tmp; + Word16 scaling = 0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + /* initilaization */ + l_frame = L_FRAME16k; + move16(); + l_shb_lahead = L_SHB_LAHEAD; + move16(); + skip = skip_bands_SWB_TBE; + + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2)) + { + skip = skip_bands_WB_TBE; + l_frame = L_FRAME16k / 4; + move16(); + l_shb_lahead = L_SHB_LAHEAD / 4; + move16(); + } + + /* apply gain for each subframe, and store noise output signal using overlap-add*/ + set32_fx( mod_syn, 0, l_frame + l_shb_lahead ); + + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2 )) + { + sum_gain = 0; + move16(); + j = skip[0]; + move16(); + FOR( k = 0; k < length / 2; k++ ) + { + sum_gain = mult_r( subwin_shb_local[2 * k + 2], subgain[0] ); /* Q15 */ + mod_syn[j + k] = L_mult( synSHB[j + k], sum_gain ); + move32();/* Q(16+Q_synSHB) */ + mod_syn[j + k + length / 2] = L_mult( synSHB[j + k + length / 2], subgain[0] ); + move32();/* Q(16+Q_synSHB) */ + } + + FOR( i = 1; i < NUM_SHB_SUBFR / 2; i++ ) + { + j = skip[i]; + move16(); + FOR( k = 0; k < length; k++ ) + { + + L_tmp = L_mult0( subwin_shb_local[k + 1], subgain[i] ); /* Q30 */ + sum_gain = round_fx( L_mac0( L_tmp, subwin_shb_local[length - k - 1], subgain[i - 1] ) ); /* Q14 */ + mod_syn[j + k] = L_shl( L_mult( sum_gain, synSHB[j + k] ), 1 ); + move32();/* Q(16+Q_synSHB) */ + } + } + FOR( k = 0; k < length / 2; k++ ) + { + j = skip[i]; + move16(); + sum_gain = mult_r( subwin_shb_fx[length - 2 * k - 2], subgain[i - 1] ); /* Q15 */ + mod_syn[ j + k ] = L_mult( synSHB[j + k], sum_gain ); + move32();/* Q(16+Q_synSHB) */ + } + } + ELSE + { + num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; + move16(); + join_length = i_mult2( num_join, length ); + j = 0; + move16(); + FOR( k = 0; k < length; k++ ) + { + sum_gain = mult_r( subwin_shb_local[k + 1], subgain[0] ); /* Q15 */ + mod_syn[j] = L_mult( synSHB[j], sum_gain ); + move32(); /* Q(16+Q_synSHB) */ + j++; + } + FOR( i = 0; i < NUM_SHB_SUBGAINS - 1; i++ ) + { + FOR( k = 0; k < join_length - length; k++ ) + { + mod_syn[j] = L_mult( synSHB[j], subgain[i * num_join] ); + move32(); /* Q(16+Q_synSHB) */ + j++; + } + + FOR( k = 0; k < length; k++ ) + { + L_tmp = L_mult0( subwin_shb_local[length - k - 1], subgain[i * num_join] ); + tmp = round_fx( L_mac0( L_tmp, subwin_shb_local[k + 1], subgain[( i + 1 ) * num_join] ) ); /* Q14 */ + mod_syn[j] = L_shl( L_mult( tmp, synSHB[j] ), 1 ); + move32(); /* Q(16+Q_synSHB) */ + j++; + } + } + FOR( k = 0; k < join_length - length; k++ ) + { + mod_syn[j] = L_mult( synSHB[j], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); + move32();/* Q(16+Q_synSHB)*/ + j++; + } + FOR( k = 0; k < length; k++ ) + { + tmp = mult_r( subwin_shb_local[length - k - 1], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); /* Q15 */ + mod_syn[j] = L_mult( tmp, synSHB[j] ); + move32();/* Q(16+Q_synSHB ) */ + j++; + } + + } + /* adjust frame energy */ + oriNrg = L_deposit_l(0); + synNrg = L_deposit_l(0); + + FOR( i = 0; i < l_shb_lahead; i++ ) + { +#ifdef BASOP_NOGLOB + sig = mult_ro( oriSHB[i], win_shb[i], &Overflow); /* Q_oriSHB */ + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow); /* 2*Q_orisHB*/ + sig = round_fx_o( Mult_32_16( mod_syn[i], win_shb[i] ), &Overflow); /*Q_synSHB */ + synNrg = L_mac0_o( synNrg, sig, sig, &Overflow); /* 2*Q_synSHB */ +#else + sig = mult_r( oriSHB[i], win_shb[i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_orisHB*/ + sig = round_fx( Mult_32_16( mod_syn[i], win_shb[i] ) ); /*Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_synSHB */ +#endif + } + + FOR( ; i < l_frame; i++) + { +#ifdef BASOP_NOGLOB + oriNrg = L_mac0_o( oriNrg, oriSHB[i], oriSHB[i], &Overflow); /* 2*Q_oriSHB */ + sig = round_fx_o( mod_syn[i], &Overflow); /* Q_oriSHB */ + synNrg = L_mac0_o( synNrg, sig, sig, &Overflow); /* 2*Q_oriSHB */ +#else + oriNrg = L_mac0( oriNrg, oriSHB[i], oriSHB[i] ); /* 2*Q_oriSHB */ + sig = round_fx( mod_syn[i] ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ +#endif + } + + tmp = add(l_frame, l_shb_lahead); + FOR( ; i < tmp; i++) + { +#ifdef BASOP_NOGLOB + sig = mult_ro( oriSHB[i], win_shb[l_frame + l_shb_lahead - 1 - i], &Overflow); /* Q_oriSHB */ + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow); /* 2*Q_oriSHB */ + + sig = round_fx_o( Mult_32_16( mod_syn[i], win_shb[l_frame + l_shb_lahead - 1 - i] ), &Overflow); /* Q_oriSHB */ + synNrg = L_mac0_o( synNrg, sig, sig, &Overflow); /* 2*Q_oriSHB */ +#else + sig = mult_r( oriSHB[i], win_shb[l_frame + l_shb_lahead - 1 - i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB */ + + sig = round_fx( Mult_32_16( mod_syn[i], win_shb[l_frame + l_shb_lahead - 1 - i] ) ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ +#endif + } + IF(EQ_32(oriNrg, MAX_32)) + { + scaling = negate(shr(n_subfr_saturation, 1) + 1); + move16(); + oriNrg = 0; + move32(); + FOR( i = 0; i < l_shb_lahead; i++ ) + { +#ifdef BASOP_NOGLOB + sig = mult_r( shl_o(oriSHB[i], scaling, &Overflow), win_shb[i]); + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow); /* 2*Q_oriSHB + 2*scaling */ +#else + sig = mult_r( shl(oriSHB[i], scaling), win_shb[i] ); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB + 2*scaling */ +#endif + } + FOR( ; i < l_frame; i++) + { +#ifdef BASOP_NOGLOB + sig = shl_o(oriSHB[i], scaling, &Overflow); + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow); /* 2*Q_oriSHB + 2*scaling */ +#else + sig = shl(oriSHB[i], scaling); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB + 2*scaling */ +#endif + } + FOR( ; i < tmp; i++) + { +#ifdef BASOP_NOGLOB + sig = mult_r( shl_o(oriSHB[i], scaling, &Overflow), win_shb[l_frame + l_shb_lahead - 1 - i] ); + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow); /* 2*Q_oriSHB + 2*scaling */ +#else + sig = mult_r( shl(oriSHB[i], scaling), win_shb[l_frame + l_shb_lahead - 1 - i] ); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB + 2*scaling */ +#endif + } + } + L_tmp = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &exp_out ); + exp_out = sub(exp_out, scaling); + frame_gain = L_shl( L_tmp, sub( exp_out, 13 ) ); /* Q18 */ + *GainFrame = frame_gain; + move32(); + + return; +} + + +static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) +{ + Word16 i, j = 0; + Word32 sum, L_tmp; + + sum = L_shr( L_mult0( a[0], a[0] ), 1 ); /* Q29 */ + + j = 0; + move16(); + FOR( i=1; i < len; i += step) + { + L_tmp = L_shr( L_mult0( a[i], a[i] ), 1 ); /* Q29 */ + sum = L_add( sum, L_tmp ); /* Q29 */ + if( GT_16( a[i], a[j] )) + { + j = i; + move16(); + } + } + L_tmp = L_shr( L_mult0( a[j], a[j] ), 1 ); /* Q29 */ + sum = L_sub( sum, L_tmp ); /* Q29 */ + + return ( sum ); +} + + +/*==========================================================================*/ +/* FUNCTION : static void EstimateSHBGainShape_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Estimate temporal gain parameters */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) length : SHB overlap length Q0 */ +/* _(Word16*) oriSHB : target original SHB frame Q_oriSHB */ +/* _(Word16*) synSHB : shaped SHB excitation Q_synSHB */ +/* _(Word16*) subwin : SHB subframe window Q15 */ +/* _(Word16) Q_oriSHB : Q format of oriSHB */ +/* _(Word16) Q_synSHB : Q format of synSHB */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)subgain :estimate of gain shape Q15 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +static void EstimateSHBGainShape_fx( + const Word16 length, /* i : SHB overlap length */ + const Word16* oriSHB, /* i : target original SHB frame Q_oriSHB*/ + const Word16 Q_oriSHB, + const Word16* synSHB, /* i : shaped SHB excitation Q_synSHB*/ + const Word16 Q_synSHB, + Word16* subgain, /* o : estimate of gain shape Q15*/ + const Word16* subwin /* i : SHB subframe window Q15*/ + ,Word16* n_subfr_saturation /* o : Number of subframes which saturated while calculating oriNrg */ +) +{ + const Word16* skip; + Word16 i, j, k; + Word16 sig; + Word32 L_subgain[NUM_SHB_SUBFR]; + Word32 L_sum_gain = 0; + Word32 oriNrg, synNrg; + Word16 num_join, num_gains, join_length; + Word16 norm[NUM_SHB_SUBFR]; + Word16 n_max = -32768; + Word16 n; + Word16 length2 = shl(length, 1); + Word16 length_tmp; + Word32 L_tmp, normFact; + Word16 scaling = 0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + move16(); + num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; + move16(); + num_gains = NUM_SHB_SUBGAINS; + move16(); + skip = skip_bands_SWB_TBE; + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2)) + { + num_gains = NUM_SHB_SUBFR / 4; + move16(); + skip = skip_bands_WB_TBE; + move16(); + } + /* calculate and normalize the subgain */ + oriNrg = 0; + move16(); + synNrg = 0; + move16(); + + IF( EQ_16(length,SHB_OVERLAP_LEN / 2)) + { + FOR( i = 0; i < NUM_SHB_SUBFR / 2; i++ ) + { + logic16(); + IF( ( i & 0x1 ) == 0 ) + { + oriNrg = 0; + move16(); + synNrg = 0; + move16(); + } + j = skip[i]; + IF( i == 0 ) + { + FOR( k = 0; k < length / 2; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[2 * k + 2] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + sig = mult_r( synSHB[j + k], subwin[2 * k + 2] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + FOR( k = length / 2; k < length; k++ ) + { + sig = oriSHB[j + k]; + move16(); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + sig = synSHB[j + k]; + move16(); + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + } + ELSE + { + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + k], subwin[k + 1] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + + } + } + IF( i == NUM_SHB_SUBFR / 2 - 1 ) + { + length_tmp = sub(length2, shr(length, 1)); + FOR( ; k < length_tmp; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[3 * length - 2 * k - 2] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + k], subwin[3 * length - 2 * k - 2] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + } + ELSE + { + FOR(; k < length2; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[2 * length - k - 1] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ + + sig = mult_r( synSHB[j + k], subwin[2 * length - k - 1] ); /* Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_synSHB */ + } + } + + logic16(); + IF( EQ_16(( i & 0x1 ),1)) + { + L_subgain[i / 2] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + move16(); /* Q(31-n) */ + norm[i / 2] = n; + move16(); + IF( GT_16(norm[i / 2],n_max)) + { + n_max = norm[i / 2]; + move16(); + } + } + } + } + ELSE + { + join_length = i_mult2( num_join, length ); + FOR( i = 0; i < num_gains; i++ ) + { + oriNrg = 0; + move16(); + synNrg = 0; + move16(); + + j = join_length * i; + move16(); + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ +#ifdef BASOP_NOGLOB + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow ); /* 2* Q_oriSHB */ +#else + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ +#endif + sig = mult_r( synSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ +#ifdef BASOP_NOGLOB + synNrg = L_mac0_o( synNrg, sig, sig, &Overflow); /* 2* Q_oriSHB */ +#else + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_oriSHB */ +#endif + } + + FOR( k = 0; k < ( join_length - length ); k++ ) + { + sig = mult_r( oriSHB[length + j + k], 32767 ); /* Q_oriSHB */ +#ifdef BASOP_NOGLOB + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow); /* 2* Q_oriSHB */ +#else + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ +#endif + sig = mult_r( synSHB[length + j + k], 32767 ); /* Q_oriSHB */ +#ifdef BASOP_NOGLOB + synNrg = L_mac0_o( synNrg, sig, sig, &Overflow); /* 2* Q_oriSHB */ +#else + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_oriSHB */ +#endif + } + + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + join_length + k], subwin[length - k - 1] ); /* Q_oriSHB */ +#ifdef BASOP_NOGLOB + oriNrg = L_mac0_o( oriNrg, sig, sig, &Overflow); /* 2* Q_oriSHB */ +#else + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2* Q_oriSHB */ +#endif + sig = mult_r( synSHB[j + join_length + k], subwin[length - k - 1] ); /* Q_oriSHB */ +#ifdef BASOP_NOGLOB + synNrg = L_mac0_o( synNrg, sig, sig, &Overflow); /* 2* Q_oriSHB */ +#else + synNrg = L_mac0( synNrg, sig, sig ); /* 2* Q_oriSHB */ +#endif + } + /* Only implemented in SWB because the length of samples in SWB frame is longer, more likely to saturate */ + scaling = 0; + move16(); + IF(EQ_32(oriNrg, MAX_32)) + { + if(n_subfr_saturation != NULL) + { + *n_subfr_saturation = add(*n_subfr_saturation, 1); + } + scaling = -1; + move16(); + oriNrg = 0; + move32(); + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( oriSHB[j + k], subwin[k + 1] ); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB - 2*/ + } + FOR( k = 0; k < ( join_length - length ); k++ ) + { + sig = shr(oriSHB[length + j + k], 1); + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB - 2*/ + } + FOR( k = 0; k < length; k++ ) + { + sig = mult_r( shr(oriSHB[j + join_length + k], 1), subwin[length - k - 1] ); /* Q_oriSHB - 1(scaling) */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB - 2 */ + } + } + L_subgain[i] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + move32(); /* Q(31-n) */ + n = sub(n, scaling); + norm[i] = n; + move16(); + IF( GT_16(norm[i],n_max)) + { + n_max = norm[i]; + move16(); + } + } + } + + FOR( i = 0; i < num_gains; i++ ) + { +#ifdef BASOP_NOGLOB + subgain[i] = round_fx_o( L_shl_o( L_subgain[i], sub( norm[i], n_max + 1 ), &Overflow), &Overflow); /* Q(14-n_max) */ + L_sum_gain = L_mac0_o( L_sum_gain, subgain[i], subgain[i], &Overflow); /* Q(28-2*n_max) */ +#else + subgain[i] = round_fx( L_shl( L_subgain[i], sub( norm[i], n_max + 1 ) ) ); /* Q(14-n_max) */ + L_sum_gain = L_mac0( L_sum_gain, subgain[i], subgain[i] ); /* Q(28-2*n_max) */ +#endif + } + + /* normalize the subgain */ + n = norm_l( L_sum_gain ); + L_sum_gain = L_shl( L_sum_gain, n ); + n = sub(31, add (n, (sub( 28 , n_max*2 ) ))); + normFact = Isqrt_lc( L_sum_gain, &n ); + + FOR( i = 0; i < num_gains; i++ ) + { + L_tmp = Mult_32_16( normFact, subgain[i] ); /*Q(31-n) * Q(31-norm[i]) */ /* Q(30-n-n_max) */ +#ifdef BASOP_NOGLOB + subgain[i] = s_max( round_fx_o( L_shl_o( L_tmp, add( n, n_max + 1 ), &Overflow), &Overflow), 3277/*0.1f Q15*/); /* Q15 */ +#else + subgain[i] = s_max( round_fx( L_shl( L_tmp, add( n, n_max + 1 ) ) ), 3277/*0.1f Q15*/); /* Q15 */ +#endif + } + + return; +} + + + +/*==========================================================================*/ +/* FUNCTION :static short closest_centroid_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Determine a set of closest VQ centroids for a given input*/ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16*) data : input data Q15 */ +/* _(Word16*) weights : weights Q0 */ +/* _(Word16*) quantizer : quantizer table Q15 */ +/* _(Word16) centroids : number of centroids Q0 */ +/* _(Word16) length : dimension of quantiser Q0 */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ Word16 : index Q0 */ +/*--------------------------------------------------------------------------*/ +static Word16 closest_centroid_fx( + 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 i, j, index; + Word16 tmp, tmpL; + Word64 werr_64; + Word32 L_tmp, werr, best_werr; + + index = 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++ ) + { + tmp = sub( data[j], quantizer[tmpL + j] ); + L_tmp = L_mult( tmp, tmp ); + werr_64 = W_mac_32_16( werr_64, L_tmp, weights[j] ); + } + werr = W_sat_m( werr_64); + if( LT_32( werr, best_werr) ) + { + index = i; + move16(); + } + best_werr = L_min( best_werr, werr ); + } + return index; +} + +/*==========================================================================*/ +/* FUNCTION :static short closest_centroid_lc_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Determine a set of closest VQ centroids for a given input */ +/* Gain shape is 4 dimensional */ +/*--------------------------------------------------------------------------*/ +static Word16 closest_centroid_lc_fx( + const Word16 *data, /* i : input data Qx*/ + const Word16 *quantizer, /* i : quantizer table Qx*/ + const Word16 centroids) /* i : number of centroids */ +{ + Word16 i, index, tmp, tmpL; + Word32 werr, best_werr; + + index = 0; + move16(); + best_werr = MAX_32; + move32(); + + FOR( i = 0; i < centroids; i++ ) + { + /* Gain shape dimension 4 */ + tmpL = shl(i, 2); + + /* index 0 */ + tmp = sub( data[0], quantizer[tmpL] ); + werr = L_mult(tmp, tmp); + + /* index 1 */ + tmp = sub( data[1], quantizer[tmpL + 1] ); + werr = L_mac(werr, tmp, tmp); + + /* index 2 */ + tmp = sub( data[2], quantizer[tmpL + 2] ); + werr = L_mac(werr, tmp, tmp); + + /* index 3 */ + tmp = sub( data[3], quantizer[tmpL + 3] ); + werr = L_mac(werr, tmp, tmp); + + if( LT_32( werr, best_werr )) + { + index = i; + move16(); + } + best_werr = L_min(best_werr, werr); + } + + return index; +} + +/*============================================================*/ +/* FUNCTION : static void QuantizeSHBsubgains_fx() */ +/*------------------------------------------------------------*/ +/* PURPOSE : Quantize super highband temporal gains */ +/*------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) extl : extension layer Q0 */ +/*------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _(Word16[])subgains :super highband temporal gains Q15 */ +/*------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ + +static void QuantizeSHBsubgains_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 subgains[], /* i/o: super highband temporal gains Q15*/ + const Word16 extl /* i : extension layer */ +) +{ + Word16 i, idxSubGain; + Word16 Unit_weights10[NUM_SHB_SUBFR]; + Word16 exp, frac; + Word32 L_tmp; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16(extl, WB_TBE)) + { + set16_fx( Unit_weights10, 32767, ( Word16 )NUM_SHB_SUBFR / 4 ); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + IF( EQ_16(subgains[i] ,0) ) + { + subgains[i + NUM_SHB_SUBFR / 4] = -18432; + move16(); /* (-72) in Q8 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); /* move16(); */ + /*exp = -1 - exp; */ + exp = sub(-1, exp); + L_tmp = Mpy_32_16( exp, frac, 24660 );/* Q13 ; 20.0 * log10(2) in Q12*/ + subgains[i + NUM_SHB_SUBFR / 4] = round_fx( L_shl( L_tmp, 11 ) ); /* Q8 */ + } + } + idxSubGain = closest_centroid_lc_fx( subgains + NUM_SHB_SUBFR / 4, HBCB_SubGain5bit_fx, 1 << NUM_BITS_SHB_SUBGAINS ); + Copy( HBCB_SubGain5bit_fx + idxSubGain * NUM_SHB_SUBFR / 4, subgains, NUM_SHB_SUBFR / 4 ); + + push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + L_tmp = L_mult( subgains[i], 21771 ); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16();/*Q15 */ + } + + FOR( i = NUM_SHB_SUBFR / 2 - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i / 2]; + move16(); + } + } + ELSE + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + IF( EQ_16(subgains[i] ,0) ) + { + subgains[i] = -12288; + move16(); /* (-3) in Q12 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = -1 - exp; */ + exp = sub(-1, exp); + + L_tmp = Mpy_32_16( exp, frac, 9864 ); /*move32(); // Q16 ; log10(2) in Q15 */ + subgains[i] = round_fx( L_shl( L_tmp, 12 ) ); /*Q12 */ + } + } + + idxSubGain = ( Word16 )vquant_fx( subgains, 0, subgains, SHBCB_SubGain5bit_12_fx, NUM_SHB_SUBGAINS, 1 << NUM_BITS_SHB_SUBGAINS ); + + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + L_tmp = L_mult( subgains[i], 27213 ); /* *3.321928 in Q13 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16();/*Q15 */ + } + + FOR( i = NUM_SHB_SUBFR - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; + move16(); + } + + hBWE_TD->idxSubGains = idxSubGain; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + } + } + + return; +} + + + +/*-------------------------------------------------------------------* + * Quant_shb_ener_sf_fx_fx() + * + * Quantize SHB subframe energies + *-------------------------------------------------------------------*/ + +static void Quant_shb_ener_sf_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word32 *shb_ener_sf_Q31, /* i/o: super highband subframe energies */ + Word16 Q_ener +) +{ + Word16 idxSubEner_fx; + Word16 temp_shb_ener_sf_fx; + Word16 exp/*, exp2*/,frac; + Word32 L_tmp1, L_tmp; + Word32 sum; + Word16 tmp; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + /* shb_ener_sf_fx[0] = log10(0.003125*shb_ener_sf[0:319]); */ + sum = *shb_ener_sf_Q31; /* L_tmp in Q_ener = (2*Q_shb+1) */ + + exp = norm_l(sum); + frac = Log2_norm_lc(L_shl(sum, exp)); + exp = sub(30, add(exp, Q_ener)); /* 30-(exp+Q_ener ) */ + L_tmp1 = Mpy_32_16(exp, frac, 617); /* 2466=LOG10(2) in Q11, so answer Ltmp in Q12 */ + + tmp = round_fx(L_shl(L_tmp1, 30-14)); /* tmp in Q12 */ + + temp_shb_ener_sf_fx = 0; + move16(); + idxSubEner_fx = usquant_fx(tmp, &temp_shb_ener_sf_fx, 0, 86, shl(1,NUM_BITS_SHB_ENER_SF)); /* 86 = 0.042f in Q11 = Qin-1 */ + /* o: temp_shb_ener_sf_fx in Q12 */ + + /* shb_ener_sf_fx[0] = pow(10.0, temp_shb_ener_sf_fx ); */ + /* = pow(2, 3.321928*temp_shb_ener_sf_fx) */ + L_tmp = L_mult(temp_shb_ener_sf_fx, 27213 ); /* 3.321928 in Q13 -> L_tmp in Q12+Q13+1 = Q26 */ + L_tmp = L_shl( L_tmp, -10 ); /* bring L_tmp from Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent */ + L_tmp = Pow2(14, frac ); + *shb_ener_sf_Q31 = L_shl(L_tmp, exp-14+Q_ener ); /* In Q_ener */ + + hBWE_TD->idx_shb_fr_gain = idxSubEner_fx; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx->hBstr, IND_SHB_ENER_SF, idxSubEner_fx, NUM_BITS_SHB_ENER_SF); + } + return; +} + + +/*-------------------------------------------------------------------* +* Quant_shb_res_gshape_fx() +* +* Quantize SHB gain shapes in residual domain +*-------------------------------------------------------------------*/ + +static void Quant_shb_res_gshape_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 shb_res_gshape_fx[] /* i/o: super highband gain shapes Q14 */ +) +{ + Word16 i, idxSubGain_fx[NB_SUBFR16k]; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + FOR(i = 0; i < NB_SUBFR16k; i++) + { + idxSubGain_fx[i] = usquant_fx(shb_res_gshape_fx[i], + &shb_res_gshape_fx[i], + 2048/*0.125f Q14*/, /*2048 = 0.125 in Q14 */ + 1024/*0.125f Q13*/, /*1024 = 0.125 in Q13 */ + shl(1,NUM_BITS_SHB_RES_GS)); + + hBWE_TD->idx_res_gs[i] = idxSubGain_fx[i]; + IF ( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx->hBstr, IND_SHB_RES_GS1+i, idxSubGain_fx[i], NUM_BITS_SHB_RES_GS); + } + } +} + +/*==========================================================================*/ +/* FUNCTION : static void QuantizeSHBframegain_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : QQuantize super highband frame gain */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 extl i : extension layer */ +/* Word32 extl_brate i : extension layer bitrate */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word32 *GainFrame i/o: Gain Q18 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ +static void QuantizeSHBframegain_fx( + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + Word32* GainFrame, /* i/o: Gain Q18 */ + const Word16 extl, /* i : extension layer */ + Word32 extl_brate /* i : extension layer bitrate */ + ,Word16 *rf_gainFrame_ind +) +{ + Word16 idxFrameGain; + Word32 Q_GainFrame; + Word16 Unit_weights1 = 1; + Word16 exp, frac, tmp; + Word32 L_tmp; + Word32 GainFrameLog; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + + IF( EQ_16(extl, WB_TBE)) + { + determine_gain_weights_fx( GainFrame, &( Unit_weights1 ), 1 ); + IF( EQ_32(extl_brate,WB_TBE_0k35)) + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain_LBR_WB, &idxFrameGain, + &Q_GainFrame, SHBCB_FrameGain16_fx ); + test(); + IF( GT_32( Q_GainFrame, L_shl( Mult_32_16( *GainFrame, 17367 ), 1 ) )&&idxFrameGain>0) /* 1.06 = +0.5 dB */ + { + idxFrameGain--; + Q_GainFrame = L_add(SHBCB_FrameGain16_fx[idxFrameGain], 0); /* Q18 */ + } + hBWE_TD->gFrame_WB = idxFrameGain; + move16(); + *rf_gainFrame_ind = idxFrameGain; + } + ELSE + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain, &idxFrameGain, &Q_GainFrame, + SHBCB_FrameGain64_fx ); + + push_indice_fx( st_fx->hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FrameGain ); + *rf_gainFrame_ind = idxFrameGain; + move16(); /* Q18 */ + } + } + ELSE + { + IF( *GainFrame == 0 ) + { + GainFrameLog = -196608; + move32(); + } + ELSE + { + exp = norm_l( *GainFrame ); + frac = Log2_norm_lc( L_shl( *GainFrame, exp ) ); + exp = ( 30 - exp - 18 ); + GainFrameLog = Mpy_32_16( exp, frac, 9864 ); + /*GainFrameLog= round_fx(L_shl(L_tmp,12)); //Q12 */ + } + + exp = norm_s( SHB_GAIN_QDELTA_FX_15 ); + tmp = div_s( shl(1, sub(14, exp)), SHB_GAIN_QDELTA_FX_15 ); + L_tmp = Mult_32_16( L_sub( GainFrameLog, SHB_GAIN_QLOW_FX_16 ), tmp ); + idxFrameGain = extract_l( L_shr( L_add( L_tmp, shl(1, sub(14, exp)) ), sub(15, exp) ) ); /*Q0*/ + IF( GT_16( idxFrameGain, ( 1 << NUM_BITS_SHB_FRAMEGAIN ) - 1 )) + { + idxFrameGain = sub( ( 1 << NUM_BITS_SHB_FRAMEGAIN ), 1 ); + } + ELSE + { + if( idxFrameGain < 0 ) + { + idxFrameGain = 0; + move16(); + } + } + + L_tmp = SHB_GAIN_QLOW_FX_16; + Q_GainFrame = L_mac( L_tmp, idxFrameGain, SHB_GAIN_QDELTA_FX_15 ); + + WHILE( GT_32( Q_GainFrame, L_add( GainFrameLog, 4866 ) )&& + idxFrameGain != 0 ) + { + idxFrameGain = sub(idxFrameGain, 1); + Q_GainFrame = L_mac0( SHB_GAIN_QLOW_FX_16, idxFrameGain, SHB_GAIN_QDELTA_FX_16 ); + } + + /* Q_GainFrame = (float) pow(10.0, Q_GainFrame ); */ + /* i: Q_GainFrame in Q16 */ + L_tmp = Mult_32_16( Q_GainFrame, 27213 ); /* *3.321928 in Q13 -> Q25 */ + L_tmp = L_shr( L_tmp, -2 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + Q_GainFrame = Pow2( 30, frac ); + exp = sub ( exp, 30) ; + Q_GainFrame = L_shl( Q_GainFrame, exp + 18 ); /* Q18 */ + + hBWE_TD->idxFrameGain = idxFrameGain; + move16(); + IF ( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx( st_fx->hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + } + *rf_gainFrame_ind = idxFrameGain; + } + + IF( EQ_16(st_fx->rf_mode,1)) + { + /*Currently intended for SWB only. Modify for WB is needed later!*/ + IF( EQ_16(hRF->rf_frame_type,RF_NELP)) + { + *rf_gainFrame_ind = idxFrameGain; /* NELP Frame uses full 5 bits */ + } + ELSE /*RF_ALLPRED, RF_GENPRED, RF_NOPRED modes*/ + { + IF(*GainFrame <= 327680 /*1.25 in Q18*/) /* [0 to 1.25] range --> 0.5*/ + { + *rf_gainFrame_ind = 0; + } + ELSE IF(*GainFrame <= 786432 /*3 in Q18*/) /* (1.25 to 3] --> 2 */ + { + *rf_gainFrame_ind = 1; + } + ELSE IF(*GainFrame <= 1572864 /*6 in Q18*/) /* (3 to 6] --> 4 */ + { + *rf_gainFrame_ind = 2; + } + ELSE /* (6 to Inf) --> 8 */ + { + *rf_gainFrame_ind = 3; + } + } + } + + *GainFrame = Q_GainFrame; + move32(); /* Q18 */ + + return; +} + + +/*============================================================*/ +/* FUNCTION : static void determine_gain_weights_fx() */ +/*------------------------------------------------------------*/ +/* PURPOSE : Determine weights for gain quantization */ +/*------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word32*)gain :Gain parameter Q18 */ +/* _(Word16) dims : number of gains */ +/*------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)weights : gain weights Q12/Q6 */ +/*------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +static void determine_gain_weights_fx ( + const Word32* gain, /* i : Gain parameter Q18 */ + Word16* weights, /* o : gain weights Q12/Q6*/ + const Word16 dims /* i : number of gains */ ) +{ + Word16 j; + Word16 exp, exp1, frac, tmp, exp2; + Word32 L_tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + FOR( j = 0; j < dims; j++ ) + { + IF( GT_32(gain[j],8))/* 8 = 0.001 in Q13 */ + { + /*weights[j] = (float)(pow (fabs (gain[j]), -0.9f)); = pow(2,(-0.9)*log2(gain[j])) */ + exp1 = norm_l( gain[j] ); + frac = Log2_norm_lc( L_shl( gain[j], exp1 ) ); + move16(); + exp = 30 - exp1 - 18; + move16(); + L_tmp = Mpy_32_16( exp, frac, -29491 ); /* Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + tmp = extract_l( Pow2( 14, frac ) ); /* Q14 */ + + exp2 = sub(exp,8); + if( LE_16(exp1,21)) + { + exp2 = sub(exp,2); + } +#ifdef BASOP_NOGLOB + weights[j] = shl_o( tmp, exp2, &Overflow); +#else + weights[j] = shl( tmp, exp2); +#endif + move16(); /* Q12 */ + } + ELSE + { + weights[j] = 32076; + move16();/* (501.187233628f) in Q6*/ + } + } + + return; +} + + + + +/*==============================================================================*/ +/* FUNCTION : static singlevectortest_gain_fx () */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : Single stage VQ for coding */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word32*) inp : input gain vector Q18 */ +/* _(Word16) dimen : dimension of the input vector */ +/* _(Word16) cb_size : codebook size */ +/* _(Word16*) weight : Weights for the quanitzation */ +/* _(Word32*) codebook : Codebook 19Q13 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)index :quanitzation index */ +/* _(Word32*)recon :Reconstruction 19Q13 */ +/*------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------------------------*/ +static void singlevectortest_gain_fx ( + const Word32* inp, /* i : input gain vector Q18*/ + const Word16 dimen, /* i : dimension of the input vector */ + const Word16 cb_size, /* i : codebook size */ + Word16* index, /* o : quanitzation index */ + Word32* recon, /* o : Reconstruction Q18 */ + const Word32* codebook + /* i : Codebook Q18*/ ) +{ + Word16 k, interNum, flag; + Word32 meanU, meanQ; + Word16 least[4]; + Word32 L_tmp; + + interNum = 4; + move16(); + + return_M_Least_fx_GainFrame( inp, codebook, cb_size, interNum, least ); + + meanU = sum32_fx( inp, dimen ); /* Q18 */ + Copy32( codebook + dimen * least[0], recon, dimen ); + + L_tmp = L_shl( Mult_32_16( meanU, 18022 ), 1 ); /* Q18 */ + index[0] = least[0]; + move16(); + flag = 0; + move16(); + FOR( k = 0; k < interNum; k++ ) + { + IF( flag == 0 ) + { + meanQ = sum32_fx( codebook + dimen * least[k], dimen ); /* Q18 */ + IF( LE_32( meanQ, L_tmp )) + { + flag = 1; + move16(); + Copy32( codebook + dimen * least[k], recon, dimen ); + index[0] = least[k]; + move16(); + } + } + } + + return; +} + + + + +/*==============================================================================*/ +/* FUNCTION : return_M_Least_fx_GainFrame () */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word32*) inp : input Q18 */ +/* _(Word16*) weight : input gain weights */ +/* _(Word16) n_cols : vector size */ +/* _(Word16) num_grp : number of centroids for 1st stage */ +/* _(Word16) interNum : number on short list prior to 2nd stage search */ +/* _(Word32*) codebook : first stage codebook Q18 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16*)least :return value */ +/*------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------------------------*/ +static void return_M_Least_fx_GainFrame( + const Word32* inp, /* i: input Q18*/ + const Word32* codebook, /* i: codebook Q18*/ + const Word16 num_grp, /* i: number of centroids */ + const Word16 interNum, /* i: number on short list prior to 2nd stage search*/ + Word16* least /* o: return value */ ) +{ + Word16 i, k; + Word32 distance[1024], mindist; + + Word16 n; + Word32 diff[1024]; + Word32 max_diff; + mindist = L_add(MAX_32, 0); + + diff[0] = L_sub( *inp, codebook[0] ); + move32(); + max_diff = L_abs( diff[0] ); + FOR( i = 1; i < num_grp; i++ ) + { + diff[i] = L_sub( *inp, codebook[i] ); + move32(); + max_diff = L_max(max_diff , L_abs( diff[i] )); + } + n = 31; + if( max_diff != 0 ) + { + n = norm_l(max_diff); + } + + FOR( i = 0; i < num_grp; i++ ) + { + diff[i] = L_shl( diff[i], n ); + move32(); + } + + FOR( i = 0; i < num_grp; i++ ) + { + distance[i] = L_deposit_l(0); + distance[i] = Mult_32_32( diff[i], diff[i] ); + move32(); + + if( LT_32( distance[i], mindist )) + { + least[0] = i; + move16(); + } + mindist = L_min(mindist,distance[i]); + } + + distance[least[0]] = MAX_32; + move32(); + + FOR( k = 1; k < interNum; k++ ) + { + mindist = L_add(MAX_32, 0); + FOR( i = 0; i < num_grp; i++ ) + { + if( LT_32( distance[i], mindist )) + { + least[k] = i; + move16(); + } + mindist = L_min(mindist,distance[i]); + } + + distance[least[k]] = MAX_32; + move32(); + } + + return; +} + + +/*-------------------------------------------------------------------* +* Quant_lower_LSF_fx() +*-------------------------------------------------------------------*/ +static void Quant_lower_LSF_fx( + const Word16 lsf[], /* i : Input LSFs Q15 */ + Word16 lsf_q[], /* o : Quantized LSFs Q15 */ + Word16 lsf_idx[] /* o : Quantized LSFs indices */ +) +{ + Word16 i; + + lsf_idx[0] = ( Word16 )squant_fx( lsf[0], &lsf_q[0], lsf_q_cb_fx[0], lsf_q_cb_size[0] ); + FOR( i = 1; i < NUM_Q_LSF; i++ ) + { + lsf_idx[i] = ( Word16 )squant_fx( sub( lsf[i], lsf_q[i - 1] ), &lsf_q[i], lsf_q_cb_fx[i], lsf_q_cb_size[i] ); + move16(); + lsf_q[i] = add( lsf_q[i - 1], lsf_q[i] ); + move16(); + } + + return; +} + + +/*-------------------------------------------------------------------* +* Quant_mirror_point_fx() +*-------------------------------------------------------------------*/ +static Word16 Quant_mirror_point_fx( + const Word16 lsf[], /* i : Input LSFs */ + const Word16 lsf_q[], + Word16* m /* o : Mirror point */ +) +{ + Word16 m_diff; + Word16 m_idx; + + m_diff = mult_r( sub( lsf[NUM_Q_LSF], lsf_q[NUM_Q_LSF - 1] ), 16384 ); + + m_idx = ( Word16 )squant_fx( m_diff, m, mirror_point_q_cb_fx, + MIRROR_POINT_Q_CB_SIZE ); /*move16(); */ + + *m = add( lsf_q[NUM_Q_LSF - 1], *m ); + move16(); + + return m_idx; +} + +/*-------------------------------------------------------------------* +* Find_LSF_grid() +* +* Find the best grid for the LSFs +*-------------------------------------------------------------------*/ + +static Word16 Find_LSF_grid_fx( + const Word16 lsf[], /* i : Input LSFs */ + Word16 lsf_q[], /* o : Quantized LSFs */ + const Word16 m /* i : Mirror point */ +) +{ + Word16 lsf_map[NUM_MAP_LSF]; + Word16 grid[NUM_LSF_GRIDS][NUM_MAP_LSF]; + Word16 offset; + Word16 last_q_lsf; + Word16 lsf_t[NUM_MAP_LSF]; + Word16 lsf_smooth[NUM_MAP_LSF]; + Word32 D, D_best; + Word16 I_best = 0; + Word16 i, j; + Word16 scale; + + Word16 tmp, exp, tmp1; + Word32 L_tmp; + + + tmp = shl(m, 1); + lsf_map[0] = sub( tmp, lsf_q[NUM_MAP_LSF-1-0] ); + move16(); + lsf_map[1] = sub( tmp, lsf_q[NUM_MAP_LSF-1-1] ); + move16(); + lsf_map[2] = sub( tmp, lsf_q[NUM_MAP_LSF-1-2] ); + move16(); + lsf_map[3] = sub( tmp, lsf_q[NUM_MAP_LSF-1-3] ); + move16(); + lsf_map[4] = sub( tmp, lsf_q[NUM_MAP_LSF-1-4] ); + move16(); + + + IF( GT_16( m, MAX_LSF_FX_2 )) + { + offset = lsf_map[0]; + move16(); + exp = norm_s( m ); + tmp = div_s( shl(1, sub(14, exp)), m ); + L_tmp = L_mult( sub( MAX_LSF_FX, m ), tmp ); + scale = round_fx( L_shl( L_tmp, exp + 1 ) ); + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + tmp = mult_r( sub( lsf_map[i], offset ), scale ); + lsf_map[i] = add( tmp, offset ); + move16(); + } + } + + last_q_lsf = lsf_q[NUM_Q_LSF - 1]; + move16(); + scale = sub( MAX_LSF_FX, last_q_lsf ); + + FOR( i = 0; i < NUM_LSF_GRIDS; i++ ) + { + FOR( j = 0; j < NUM_MAP_LSF; j++ ) + { + grid[i][j] = add( mult_r( lsf_grid_fx[i][j], scale ), last_q_lsf ); + move16(); + } + } + + D_best = L_add(MAX_32, 0); + FOR( i = 0; i < NUM_LSF_GRIDS; i++ ) + { + D = L_deposit_l(0); + FOR( j = 0; j < NUM_MAP_LSF; j++ ) + { + /*lsf_t[j] = (1 - grid_smoothing[j])*lsf_map[j] + grid_smoothing[j]*grid[i][j]; */ + tmp = sub( 32767, grid_smoothing_fx[j] ); + tmp = mult_r( tmp, lsf_map[j] ); + tmp1 = mult_r( grid_smoothing_fx[j], grid[i][j] ); + lsf_t[j] = add( tmp, tmp1 ); + move16(); + + tmp = sub( lsf_t[j], lsf[NUM_Q_LSF + j] ); + D = L_mac0( D, tmp, tmp ); + + /* D += (lsf_t[j] - lsf[NUM_Q_LSF + j])*(lsf_t[j] - lsf[NUM_Q_LSF + j]); */ + } + IF( LT_32( D, D_best )) + { + Copy( lsf_t, lsf_smooth, NUM_MAP_LSF ); + D_best = L_add(D, 0); + I_best = i; + move16(); + } + } + + FOR( i = 0; i < NUM_MAP_LSF; i++ ) + { + lsf_q[NUM_Q_LSF + i] = lsf_smooth[i]; + move16(); + } + + return I_best; +} + +/*-------------------------------------------------------------------* +* gainFrSmooth_En_fx() +* +* Gain frame smoothing and attenuation control +*-------------------------------------------------------------------*/ +static void gainFrSmooth_En_fx(Encoder_State_fx *st_fx, + Word16 *shb_frame_fx, + const Word16 *lpc_shb_fx, + const Word16 *lsp_shb_fx, + Word16 *MA_lsp_shb_spacing, + Word16 *frGainAttenuate, + Word16 *frGainSmoothEn + ) +{ + Word16 temp_shb_frame[L_FRAME16k+L_SHB_LAHEAD]; + Word32 lsp_slow_evol_rate, lsp_fast_evol_rate; + Word16 lsp_spacing; + + Word32 tempQ31; + Word16 tempQ15_1, tempQ15_2; + Word16 i; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + /* inits */ + *frGainAttenuate = 0; + move16(); + *frGainSmoothEn = 0; + move16(); + *MA_lsp_shb_spacing = 16384; + move16(); + lsp_spacing = lsp_shb_fx[0]; + move16(); + + /* estimate the mean square error in lsps from current frame to past frames */ + tempQ15_1 = sub( lsp_shb_fx[0], hBWE_TD->lsp_shb_slow_interpl_fx[0] ); + tempQ15_2 = sub( lsp_shb_fx[0], hBWE_TD->lsp_shb_fast_interpl_fx[0] ); + lsp_slow_evol_rate = L_mult(tempQ15_1, tempQ15_1 ); + lsp_fast_evol_rate = L_mult(tempQ15_2, tempQ15_2 ); + + /* update the slow and fast lsp interp for next frame */ + tempQ31 = L_mult(hBWE_TD->lsp_shb_slow_interpl_fx[0], 22937 ); + hBWE_TD->lsp_shb_slow_interpl_fx[0] = mac_r(tempQ31, lsp_shb_fx[0], 9830 ); + move16(); + tempQ31 = L_mult(hBWE_TD->lsp_shb_fast_interpl_fx[0], 9830 ); + hBWE_TD->lsp_shb_fast_interpl_fx[0] = mac_r(tempQ31, lsp_shb_fx[0], 22937 ); + move16(); + + FOR( i = 1; i < LPC_SHB_ORDER; i++ ) + { + tempQ15_1 = sub(lsp_shb_fx[i], lsp_shb_fx[i-1]); + lsp_spacing = s_min( lsp_spacing, tempQ15_1); + + /* estimate the mean square error in lsps from current frame to past frames */ + tempQ15_1 = sub( lsp_shb_fx[i], hBWE_TD->lsp_shb_slow_interpl_fx[i] ); + tempQ15_2 = sub( lsp_shb_fx[i], hBWE_TD->lsp_shb_fast_interpl_fx[i] ); + lsp_slow_evol_rate = L_mac(lsp_slow_evol_rate, tempQ15_1, tempQ15_1 ); + lsp_fast_evol_rate = L_mac(lsp_fast_evol_rate , tempQ15_2, tempQ15_2 ); + + /* update the slow and fast interpolation lsps for next frame */ + tempQ31 = L_mult(hBWE_TD->lsp_shb_slow_interpl_fx[i], 22937 ); + hBWE_TD->lsp_shb_slow_interpl_fx[i] = mac_r(tempQ31, lsp_shb_fx[i], 9830 ); + move16(); + tempQ31 = L_mult(hBWE_TD->lsp_shb_fast_interpl_fx[i], 9830 ); + hBWE_TD->lsp_shb_fast_interpl_fx[i] = mac_r(tempQ31, lsp_shb_fx[i], 22937 ); + move16(); + } + + test(); + test(); + IF( NE_16( st_fx->last_extl_fx, SWB_TBE ) + && NE_16(st_fx->last_extl_fx, FB_TBE) + && LT_16( lsp_spacing, 262 ) ) + { + hBWE_TD->lsp_shb_spacing_fx[0] = lsp_spacing; + move16(); + hBWE_TD->lsp_shb_spacing_fx[1] = lsp_spacing; + move16(); + hBWE_TD->lsp_shb_spacing_fx[2] = lsp_spacing; + move16(); + hBWE_TD->prev_frGainAtten = 1; + move16(); + set16_fx(hBWE_TD->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER); + } + + /* Estimate the moving average LSP spacing */ + tempQ31 = L_mult(hBWE_TD->lsp_shb_spacing_fx[0], 3277); /* 0.1f */ + tempQ31 = L_mac(tempQ31, hBWE_TD->lsp_shb_spacing_fx[1], 6553); /* 0.2f */ + tempQ31 = L_mac(tempQ31, hBWE_TD->lsp_shb_spacing_fx[2], 9830); /* 0.3f */ + *MA_lsp_shb_spacing = mac_r(tempQ31, lsp_spacing, 13107); /* 0.4f */ + + hBWE_TD->lsp_shb_spacing_fx[0] = hBWE_TD->lsp_shb_spacing_fx[1]; + move16(); + hBWE_TD->lsp_shb_spacing_fx[1] = hBWE_TD->lsp_shb_spacing_fx[2]; + move16(); + hBWE_TD->lsp_shb_spacing_fx[2] = lsp_spacing; + move16(); + + test(); + test(); + test(); + IF( ( LT_16( lsp_spacing, 262 )&&(LT_16(*MA_lsp_shb_spacing,164)||EQ_16(hBWE_TD->prev_frGainAtten,1))) + || LE_16( lsp_spacing, 105 ) ) + { + *frGainAttenuate = 1; + move16(); + + IF( NE_32(st_fx->total_brate_fx , ACELP_24k40)) + { + Copy( shb_frame_fx, temp_shb_frame, L_FRAME16k + L_SHB_LAHEAD ); + fir_fx( temp_shb_frame, lpc_shb_fx, shb_frame_fx, hBWE_TD->shb_inv_filt_mem_fx, L_FRAME16k + L_SHB_LAHEAD, LPC_SHB_ORDER, 1,3); + } + ELSE + { + set16_fx(hBWE_TD->shb_inv_filt_mem_fx, 0, LPC_SHB_ORDER); + } + + test(); + IF ( LT_32( lsp_slow_evol_rate, 2147484l/*0.001f Q31*/ )&<_32(lsp_fast_evol_rate,2147484l/*0.001f Q31*/)) + { + *frGainSmoothEn = 1; + move16(); + } + } + +} + +/*-------------------------------------------------------------------* +* Quant_BWE_LSF() +* +* Quantize super highband spectral envolope +*-------------------------------------------------------------------*/ + +static void Quant_BWE_LSF_fx( + + Encoder_State_fx* st_fx, /* i/o: encoder state structure */ + const Word16 lsf_shb[], /* i : unquanitzed LSFs */ + Word16 Q_lsfs[] /* o : quanitzed LSFs */ +) +{ + Word16 lsf[LPC_SHB_ORDER]; + Word16 lsf_q[LPC_SHB_ORDER]; + Word16 lsf_idx[NUM_Q_LSF]; + Word16 i; + Word16 m_idx; + Word16 m; + Word16 grid_idx; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsf[i] = sub( 16384, lsf_shb[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + + Quant_lower_LSF_fx( lsf, lsf_q, lsf_idx); + /* i: lsf in Q15 */ + /* o: lsf_q in Q15 */ + + FOR( i = 0; i < NUM_Q_LSF; i++ ) + { + hBWE_TD->lsf_idx[i] = lsf_idx[i]; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx(hBstr, IND_SHB_LSF, lsf_idx[i], lsf_q_num_bits[i] ); + } + } + + m_idx = Quant_mirror_point_fx( lsf, lsf_q, &m ); + + hBWE_TD->m_idx = m_idx; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx(hBstr, IND_SHB_MIRROR, m_idx, MIRROR_POINT_BITS ); + } + + grid_idx = Find_LSF_grid_fx( lsf, lsf_q, m ); + + hBWE_TD->grid_idx = grid_idx; + IF( NE_16( st_fx->codec_mode, MODE2 )) + { + push_indice_fx(hBstr, IND_SHB_GRID, grid_idx, NUM_LSF_GRID_BITS ); + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + Q_lsfs[i] = sub( 16384, lsf_q[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + + return; +} + +/*-------------------------------------------------------------------* + * fb_tbe_enc() + * + * FB TBE encoder, 14(resp. 15.5) - 20 kHz band encoding module + *-------------------------------------------------------------------*/ + +void fb_tbe_enc_fx( + Encoder_State_fx *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : input speech at 48 kHz sample rate */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part */ + Word16 Q_fb_exc +) +{ + Word16 ratio; + Word16 tmp_vec[L_FRAME48k]; + Word16 idxGain; + Word16 input_fhb[L_FRAME48k]; + Word16 Sample_Delay_HP; + Word32 fb_exc_energy, temp2; + Word32 L_tmp; + Word16 tmp,tmp1,tmp2,exp,exp2,exp_norm; + Word16 s_max_value,exp_temp,i; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + s_max_value = 0; + FOR( i = 0; i < L_FRAME48k; i++ ) + { + s_max_value = s_max(s_max_value,abs_s(new_input[i])); + } + exp_temp = norm_s( s_max_value ); + if( s_max_value == 0 ) + { + exp_temp = 15; + } + exp_temp = sub(exp_temp,1); + + Copy_Scale_sig( new_input, input_fhb, L_FRAME48k, exp_temp ); + + elliptic_bpf_48k_generic_fx( input_fhb, &exp_temp , tmp_vec, hBWE_TD->elliptic_bpf_2_48k_mem_fx, hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q,full_band_bpf_2_fx ); + Sample_Delay_HP = NS2SA(48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS) - L_FRAME48k/2 ; + + IF( NE_16(st->last_extl_fx,FB_TBE)) + { + set16_fx( hBWE_TD->old_input_fhb_fx, 0, Sample_Delay_HP ); + hBWE_TD->old_input_fhb_fx_Q = 0; + move16(); + set16_fx( tmp_vec, 0, L_FRAME16k ); + } + Copy_Scale_sig( hBWE_TD->old_input_fhb_fx, hBWE_TD->old_input_fhb_fx, Sample_Delay_HP, sub(exp_temp,hBWE_TD->old_input_fhb_fx_Q) ); + hBWE_TD->old_input_fhb_fx_Q = exp_temp; + Copy( hBWE_TD->old_input_fhb_fx, input_fhb, Sample_Delay_HP ); + Copy( tmp_vec, input_fhb + Sample_Delay_HP, L_FRAME48k-Sample_Delay_HP ); + Copy( tmp_vec + L_FRAME48k - Sample_Delay_HP, hBWE_TD->old_input_fhb_fx, Sample_Delay_HP ); + temp2 = sum2_fx_mod( input_fhb, L_FRAME48k/2 );/* Q11 */ +#ifdef BASOP_NOGLOB + temp2 = L_add_o(temp2,L_shl_o(hBWE_TD->prev_fb_energy_fx,sub(sub(add(exp_temp,exp_temp),6),hBWE_TD->prev_fb_energy_fx_Q), &Overflow), &Overflow);/* Q11 */ +#else + temp2 = L_add(temp2,L_shl(hBWE_TD->prev_fb_energy_fx,sub(sub(add(exp_temp,exp_temp),6),hBWE_TD->prev_fb_energy_fx_Q)));/* Q11 */ +#endif + hBWE_TD->prev_fb_energy_fx = sum2_fx_mod( input_fhb + L_FRAME48k/2, L_FRAME48k/2 );/*Q11*/ + hBWE_TD->prev_fb_energy_fx_Q = sub(add(exp_temp,exp_temp),6); + fb_exc_energy = sum2_fx_mod( fb_exc, L_FRAME16k );/* Q(2*Q_fb_exc+1 -7) */ + + /*ratio = (float) sqrt( temp2 / fb_exc_energy );*/ + L_tmp = L_max(1, temp2); /*Q6*/ + exp = norm_l(L_tmp); + tmp = extract_h(L_shl(L_tmp, exp)); + exp = sub(sub(31,sub(add(exp_temp,exp_temp),8)), exp); /* in Q15 (L_tmp in Q6)*/ + + exp2 = norm_l(fb_exc_energy); + tmp2 = extract_h(L_shl(fb_exc_energy, exp2)); + tmp1 = sub(add(Q_fb_exc,Q_fb_exc), 8);/*1 - 9*/ + exp2 = sub(sub(31,tmp1), exp2); /* in Q15 (L_tmp in Q6)*/ + + exp = sub(exp2, exp); /* Denormalize and substract */ + IF (GT_16(tmp2, tmp)) + { + tmp2 = shr(tmp2, 1); + exp = add(exp, 1); + } + IF( 0 != tmp ) + { + tmp = div_s(tmp2, tmp); + L_tmp = L_deposit_h(tmp); + L_tmp = Isqrt_lc(L_tmp, &exp); /*Q(31-exp)*/ +#ifdef BASOP_NOGLOB + L_tmp = L_max(L_shr_o(L_tmp,sub(31,exp), &Overflow),0x1);/* Q0 */ +#else + L_tmp = L_max(L_shr(L_tmp,sub(31,exp)),0x1);/* Q0 */ +#endif + } + ELSE + { + L_tmp =0; + } + + /* idxGain = (short)( log2_f ((float)ratio) + 0.5f ); + idxGain = max( 0, min(15,idxGain) ); */ + ratio = 0; + IF(GE_32(L_tmp,32768)) + { + idxGain = 15; + } + ELSE + { + ratio = extract_l(L_tmp); + exp_norm = norm_s(ratio); + idxGain = sub(14, exp_norm); + idxGain = s_max(0,idxGain); + } + IF(GT_16(idxGain,2)&<_16(idxGain,15)&>_16(ratio,add(shl(2,sub(idxGain,1)),shl(2,sub(idxGain,2))))) + { + idxGain = add(idxGain,1); + } + + /* ratio = (float)(1 << idxGain);*/ + IF( st->codec_mode == MODE2 ) + { + hBWE_TD->idxGain = idxGain; + } + ELSE + { + push_indice_fx( st->hBstr, IND_FB_SLOPE, idxGain, 4 ); + } + + return; +} +void tbe_write_bitstream_fx( + Encoder_State_fx *st_fx /* i/o: encoder state structure */ +) +{ + Word16 i; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + + test(); + test(); + test(); + test(); + test(); + IF ( ( st_fx->rf_mode || EQ_32( st_fx->total_brate_fx, ACELP_9k60 ))&&(EQ_16(st_fx->bwidth_fx,WB))) + { + /* WB LSF */ + push_next_indice_fx(hBstr, hBWE_TD->lsf_WB, NUM_BITS_LBR_WB_LSF ); + + /* WB frame */ + push_next_indice_fx(hBstr, hBWE_TD->gFrame_WB, NUM_BITS_SHB_FrameGain_LBR_WB ); + } + ELSE IF ( ( GE_32( st_fx->total_brate_fx, ACELP_9k60 ))&&(LE_32(st_fx->total_brate_fx,ACELP_32k))&& + ( ( EQ_16( st_fx->bwidth_fx, SWB ) ) || ( EQ_16( st_fx->bwidth_fx, FB ) ) ) ) + { + /* LSF coefficients */ + + test(); + IF( (EQ_16(st_fx->rf_mode,1))||EQ_32(st_fx->total_brate_fx,ACELP_9k60)) + { + push_next_indice_fx(hBstr, hBWE_TD->lsf_idx[0], 8 ); + } + ELSE + { + FOR (i = 0; i < NUM_Q_LSF; i++) + { + push_next_indice_fx(hBstr, hBWE_TD->lsf_idx[i], lsf_q_num_bits[i] ); + } + + /* LSF mirror points */ + push_next_indice_fx(hBstr, hBWE_TD->m_idx, MIRROR_POINT_BITS ); + + /* LSF grid points */ + push_next_indice_fx(hBstr, hBWE_TD->grid_idx, NUM_LSF_GRID_BITS ); + } + + /* Gain shape */ + push_next_indice_fx(hBstr, hBWE_TD->idxSubGains, NUM_BITS_SHB_SUBGAINS ); + + /* frame gain */ + push_next_indice_fx(hBstr, hBWE_TD->idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + + IF ( GE_32( st_fx->total_brate_fx, ACELP_24k40 )) + { + /* sub frame energy*/ + push_next_indice_fx(hBstr, hBWE_TD->idx_shb_fr_gain, NUM_BITS_SHB_ENER_SF ); + + /* gain shapes residual */ + FOR (i = 0; i < NB_SUBFR16k; i++) + { + push_next_indice_fx(hBstr, hBWE_TD->idx_res_gs[i], NUM_BITS_SHB_RES_GS ); + } + + /* voicing factor */ + push_next_indice_fx(hBstr, hBWE_TD->idx_mixFac, NUM_BITS_SHB_VF ); + } + + IF( EQ_16(st_fx->tec_tfa, 1)) + { + push_next_indice_fx(hBstr, st_fx->tec_flag, BITS_TEC ); + push_next_indice_fx(hBstr, st_fx->tfa_flag, BITS_TFA ); + } + } + + IF ( EQ_16( st_fx->bwidth_fx, FB )) + { + push_next_indice_fx(hBstr, hBWE_TD->idxGain, 4 ); + } +} + + +void TBEreset_enc_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + Word16 bandwidth /* i : bandwidth mode */ +) +{ + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + IF( NE_16(st_fx->last_core_fx,ACELP_CORE)) + { + set16_fx( hBWE_TD->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + hBWE_TD->bwe_non_lin_prev_scale_fx = L_deposit_l(0); + st_fx->prev_Q_bwe_exc = 31; + move16(); + } + + test(); + IF( EQ_16( bandwidth, WB )) + { + wb_tbe_extras_reset_fx(hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, hBWE_TD->mem_genSHBexc_filt_down_wb3_fx ); + set16_fx( hBWE_TD->mem_genSHBexc_filt_down_shb_fx, 0, 7 ); + set16_fx( hBWE_TD->state_lpc_syn_fx, 0, 10 ); + 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 ); + } + ELSE IF( ( EQ_16( bandwidth, SWB ))||(EQ_16(bandwidth,FB))) + { + set16_fx( hBWE_TD->state_ana_filt_shb_fx, 0, (2*ALLPASSSECTIONS_STEEP+1) ); + + 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) ); + + IF( EQ_16( bandwidth, FB )) + { + set16_fx( hBWE_TD->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER ); + hBWE_TD->fb_tbe_demph_fx = 0; + move16(); + 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); + } + } +} + + diff --git a/lib_enc/tcq_core_enc_fx.c b/lib_enc/tcq_core_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..8b4add95230dce466c42029bd5fea8d44f5094b3 --- /dev/null +++ b/lib_enc/tcq_core_enc_fx.c @@ -0,0 +1,482 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include +#include "options.h" /* Compilation switches */ +#include "cnst.h" +//#include "prot_fx.h" +#include "rom_com.h" +#include "ivas_error.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +ivas_error tcq_core_LR_enc_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + Word16 inp_vector_fx[], /* x5 */ + const Word32 coefs_norm_fx[], /* Q12 */ + Word32 coefs_quant_fx[], /* Q12 */ + const Word16 bit_budget, /* number of bits */ + const Word16 BANDS, + const Word16 *sfm_start, + const Word16 *sfm_end, + const Word16 *sfmsize, + Word32 *R_fx, /* Q16 */ + Word16 *npulses, + Word16 *k_sort, + const Word16 *p2a_flags, + const Word16 p2a_bands, + const Word16 *last_bitalloc, + const Word16 input_frame, + const Word16 adjustFlag, + const Word16 is_transient +) +{ + Word16 i, j, k, size, nb_bytes; + + Word16 USQ_TCQ[NB_SFM]; /* TCQ is selected by default*/ + Word16 coefs_norm_dec_fx[L_FRAME32k]; /* New output buffer (TCQ+USQ)*/ + Word32 savedstates[TCQ_MAX_BAND_SIZE]; + ARCODEC arenc_fx, *parenc_fx; + TCQ_BITSTREAM bs_fx, *pbs_fx; + Word16 k_num[2]; + Word32 bit_surplus_fx[2]; + + Word16 flag_wbnb = 0; + Word16 lsbtcq_bits = TCQ_AMP; + Word16 tcq_arbits = 2; + Word16 nzb = 0; + Word16 nzbands = 0; + Word16 bcount = 0; + Word32 bsub_fx = 0; + Word32 abuffer_fx[MAX_PULSES]; + Word16 mbuffer_fx[MAX_PULSES]; + Word32 sbuffer_fx[MAX_PULSES]; + Word16 dpath[280]; + Word32 Rk_sort_fx[NB_SFM]; + Word32 step_scale_fx[NB_SFM]; + Word16 pulses_fx, nzp_fx; + + Word32 gain_fx, crosscorr_fx, selfcorr_fx; + Word16 hi, lo, exp; + Word32 surplus_fx, delta_fx, est_frame_bits_fx; + + Word32 leftbits = 0; + Word32 sepbits = 0; + Word32 divider = 0; + ivas_error error; + + error = IVAS_ERR_OK; + move16(); + set16_fx(dpath, 0, 280); + set32_fx(abuffer_fx, 0, MAX_PULSES); + set32_fx(sbuffer_fx, 0, MAX_PULSES); + set16_fx(mbuffer_fx, 0, MAX_PULSES); + /* initialization */ + set32_fx(Rk_sort_fx, 0, NB_SFM); + set16_fx(USQ_TCQ, 0, NB_SFM); + set16_fx(coefs_norm_dec_fx, 0, L_FRAME32k); + + InitLSBTCQ_fx(&bcount); + + test(); + test(); + IF( input_frame <= L_FRAME16k && adjustFlag == 0 && is_transient == 0 ) + { + flag_wbnb = 1; + move16(); + lsbtcq_bits = 0; + move16(); + tcq_arbits = 0; + move16(); + } + + /* TCQ Index initialize */ + parenc_fx = &arenc_fx; + pbs_fx = &bs_fx; + + pbs_fx->curPos = 7; + move16(); + pbs_fx->numbits = L_deposit_l(0); + pbs_fx->numByte = L_deposit_l(0); + FOR (i = 0; i < MAX_SIZEBUF_PBITSTREAM; i++) + { + pbs_fx->buf[i] = 0; + move16(); + } + ar_encoder_start_fx(parenc_fx, pbs_fx, L_deposit_l(bit_budget)); + + /* Bits distribution analysis */ + FOR ( i = 0; i < BANDS; i++ ) + { + IF ( GE_32(ar_div(R_fx[i], sfmsize[i]), 49152)) + { + /* USQ used for high importance bands*/ + USQ_TCQ[i] = 1; + move16(); + } + ELSE + { + /* TCQ used for usual bands */ + USQ_TCQ[i] = 0; + move16(); + } + + IF( R_fx[i] > 0 ) + { + /* nzbands++; */ + nzbands = add(nzbands, 1); + } + } + + FOR ( j = 0; j < BANDS; j++ ) + { + IF ( R_fx[j] > 0 ) + { + nzb++; + } + } + + bsub_fx = L_shl(add(tcq_arbits, lsbtcq_bits), 16); /* Q16 */ + IF( bsub_fx > 0) + { + bsub_fx = L_add( bsub_fx, 2048); + } + FOR ( j = BANDS - 1; j >= 0; j-- ) + { + IF( R_fx[j] > 0 ) + { + R_fx[j] = L_sub(R_fx[j], ar_div(bsub_fx, nzb)); + + IF( R_fx[j] < 0) + { + bsub_fx = L_sub(bsub_fx, L_add(ar_div(bsub_fx, nzb), R_fx[j])); + R_fx[j] = L_deposit_l(0); + } + ELSE + { + bsub_fx = L_sub(bsub_fx, ar_div(bsub_fx, nzb)); + } + /* nzb--; */ + nzb = sub(nzb, 1); + } + } + + /* Sort the bit allocation table (R) in ascending order, figure out number of pulses per band */ + srt_vec_ind_fx(R_fx, Rk_sort_fx, k_sort, BANDS); + + /* Quantize spectral band shapes using TCQ */ + /* Select ISC */ + set32_fx(coefs_quant_fx, 0, sfm_end[BANDS - 1]+1); + Copy32( coefs_norm_fx, coefs_quant_fx,sfm_end[BANDS-1]+1); + + delta_fx = L_deposit_l(0); + est_frame_bits_fx = L_deposit_l(0); + + test(); + test(); + IF ( LE_16(input_frame, L_FRAME16k)&&adjustFlag==0&&is_transient==0) + { + surplus_fx = -131072; + move32(); + bit_allocation_second_fx( R_fx, Rk_sort_fx, BANDS, sfmsize, k_sort, k_num, p2a_flags, p2a_bands, last_bitalloc, input_frame ); + + nzbands = 0; + move16(); + FOR ( j = 0; j < BANDS; j++ ) + { + IF( NE_16(j, k_num[0])&&NE_16(j,k_num[1])) + { + leftbits = L_add( leftbits, R_fx[k_sort[j]]); + if( R_fx[k_sort[j]] > 0 ) + { + nzbands = add(nzbands, 1); + } + } + ELSE + { + sepbits = L_add( sepbits, R_fx[k_sort[j]]); + } + } + /* Separate the position information from the input signal(coefs_norm) */ + /* Gather the NZ coefficients*/ + FOR ( k = 0; k < BANDS; k++) /* Loop through non-zero blocks */ + { + test(); + IF ( NE_16(k, k_num[0])&&NE_16(k,k_num[1])) + { + test(); + test(); + IF ( R_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) /* Then have non-zero block AND WILL BE ENCODED BY TCQ */ + { + /* Encode Position Info, NZ Info, Signs */ + size = sfmsize[k_sort[k]]; + move16(); + + /* Determine scale step, ISC and TCQ quantizer */ + GetISCScale_fx( &coefs_quant_fx[sfm_start[k_sort[k]]], size, + L_add( R_fx[k_sort[k]], delta_fx), + /* R_fx[k_sort[k]], */ + &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 0, &nzp_fx + , 0, 0, 0, 0 + ); + leftbits = L_sub( leftbits, L_add( R_fx[k_sort[k]], delta_fx) ); + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_tcq_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, savedstates, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx ); + nzbands--; + } + /* Have USQ coded band */ + ELSE IF( R_fx[k_sort[k]] > 0 && EQ_16(USQ_TCQ[k_sort[k]], 1)) + { + size = sfmsize[k_sort[k]]; + move16(); + + GetISCScale_fx( &coefs_quant_fx[ sfm_start[ k_sort[k]]], size, + L_add( R_fx[k_sort[k]], delta_fx), + /* R_fx[k_sort[k]], */ + &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 1, &nzp_fx + , 0, 0, 0, 0 + ); + leftbits = L_sub( leftbits, L_add( R_fx[k_sort[k]], delta_fx) ); + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_usq_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[ k]]], size, nzp_fx, &est_frame_bits_fx ); + nzbands--; + } + ELSE /* Then have zero block */ + { + npulses[ k_sort[ k]] = 0; + move16(); + size = sfmsize[k_sort[k]]; + move16(); + } + + delta_fx = L_deposit_l(0); + test(); + IF( R_fx[k_sort[k]] > 0 && surplus_fx < 0 ) + { + /* delta_fx = L_deposit_h( div_l( surplus_fx, nzbands ) ); */ + IF( nzbands <= 1 ) + { + divider = 0; + } + ELSE + { + divider = 2; + } + + IF( L_add( L_add( surplus_fx, sepbits), ar_div( leftbits, divider) ) < 0 ) + { + /* Overflow possible => start to distribute negative surplus */ + delta_fx = ar_div( surplus_fx + sepbits, nzbands); + } + else + { + delta_fx = 0; + } + surplus_fx = L_sub(surplus_fx, delta_fx); + } + } + } + + test(); + test(); + test(); + IF (( GT_32(surplus_fx,524288)&&EQ_16(input_frame,L_FRAME8k))||(GT_32(surplus_fx,786432)&&EQ_16(input_frame,L_FRAME16k))) + { + bit_surplus_fx[0] = Mult_32_16(surplus_fx,24576); /* Q16 */ + bit_surplus_fx[1] = Mult_32_16(surplus_fx,8192); /* Q16 */ + } + ELSE + { + bit_surplus_fx[0] = surplus_fx; + move32(); + bit_surplus_fx[1] = L_deposit_l(0); + } + + FOR ( k = 0; k < BANDS; k++ ) + { + FOR ( j = 0; j < 2; j++ ) + { + IF ( EQ_16(k, k_num[j])) + { + R_fx[k_sort[k]] = L_add(R_fx[k_sort[k]],bit_surplus_fx[j]); + + test(); + test(); + IF ( R_fx[k_sort[k]] > 0 && USQ_TCQ[k_sort[k]] == 0 ) /* Then have non-zero block AND WILL BE ENCODED BY TCQ */ + { + /* Encode Position Info, NZ Info, Signs */ + size = sfmsize[k_sort[k]]; + move16(); + + /* Determine scale step, ISC and TCQ quantizer */ + GetISCScale_fx( &coefs_quant_fx[sfm_start[k_sort[k]]], size, R_fx[k_sort[k]], &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 0, &nzp_fx + , 0, 0, 0, 0 + ); + + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_tcq_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, savedstates, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx ); + } + /* Have USQ coded band */ + ELSE IF( R_fx[k_sort[k]] > 0 && EQ_16(USQ_TCQ[k_sort[k]], 1)) + { + size = sfmsize[k_sort[k]]; + move16(); + + GetISCScale_fx( &coefs_quant_fx[ sfm_start[ k_sort[k]]], size, R_fx[k_sort[k]], &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 1, &nzp_fx + , 0, 0, 0, 0 + ); + + npulses[ k_sort[k]] = pulses_fx; + move16(); + + encode_position_ari_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, &est_frame_bits_fx ); + encode_magnitude_usq_fx( parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, &est_frame_bits_fx ); + encode_signs_fx( parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx ); + } + ELSE /* Then have zero block */ + { + npulses[ k_sort[k]] = 0; + move16(); + size = sfmsize[k_sort[k]]; + move16(); + } + } + } + } + } + ELSE + { + surplus_fx = L_deposit_l(0); + + /* Separate the position information from the input signal(coefs_norm) */ + /* Gather the NZ coefficients*/ + FOR( k = 0; k < BANDS; k++) /* Loop through non-zero blocks */ + { + IF( R_fx[k_sort[k]] > 0 ) + { + size = sfmsize[k_sort[k]]; + move16(); + GetISCScale_fx( &coefs_quant_fx[ sfm_start[ k_sort[k]]], size, R_fx[k_sort[k]] + delta_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], &step_scale_fx[k_sort[k]], &surplus_fx, &pulses_fx, savedstates, 1, &nzp_fx, &bcount, abuffer_fx, mbuffer_fx, sbuffer_fx); + + npulses[ k_sort[k]] = pulses_fx; + move16(); + encode_position_ari_fx(parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, &est_frame_bits_fx); + encode_magnitude_usq_fx(parenc_fx, &coefs_norm_dec_fx[sfm_start[k_sort[k]]], size, npulses[k_sort[k]], nzp_fx, &est_frame_bits_fx); + encode_signs_fx(parenc_fx, &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, nzp_fx, &est_frame_bits_fx); + + /* nzbands--; */ + nzbands = sub(nzbands, 1); + } + ELSE /* Then have zero block */ + { + npulses[ k_sort[k]] = 0; + move16(); + size = sfmsize[k_sort[k]]; + move16(); + } + + /* Surplus distribution */ + /* if( surplus > 0.0f && nzbands > 0 ) */ + test(); + IF( surplus_fx > 0 && nzbands > 0 ) + { + /* delta = surplus / nzbands; + surplus -= delta; */ + + delta_fx = ar_div(surplus_fx, nzbands); + surplus_fx = L_sub(surplus_fx, delta_fx); + } + } + } + + TCQLSB_fx(bcount, /*abuffer, */abuffer_fx, /*mbuffer, */mbuffer_fx, /*sbuffer, */sbuffer_fx, dpath); + + /* Save TCQ path to bitstream */ + SaveTCQdata_fx(parenc_fx, dpath, lsbtcq_bits); + + /* Add tcq sequence to decoding buffer */ + InitLSBTCQ_fx(&bcount); + + ar_encoder_done_fx(parenc_fx); + + /* Loop through non-zero blocks */ + FOR (i = 0; i < L_FRAME32k; i++) + { + coefs_norm_dec_fx[i] = extract_l(L_mult0(coefs_norm_dec_fx[i], 5)); + } + IF( !flag_wbnb ) + { + FOR ( k = 0; k < BANDS; k++) + { + IF( R_fx[k_sort[k]] > 0 ) + { + size = sfmsize[k_sort[k]]; + move16(); + RestoreTCQ_fx( &coefs_norm_dec_fx[ sfm_start[ k_sort[k]]], size, &bcount, mbuffer_fx ); + } + } + } + + nb_bytes = shr(bit_budget, 3); + j = sub(bit_budget, shl(nb_bytes, 3)); + FOR( i = 0; i < nb_bytes; i++ ) + { + push_indice_fx(hBstr, IND_HQ2_SUBBAND_TCQ, pbs_fx->buf[i], 8); + } + IF( j > 0 ) + { + push_indice_fx(hBstr, IND_HQ2_SUBBAND_TCQ, shr(pbs_fx->buf[nb_bytes],(8 - j)), j); + } + /* Clear decoding buffer */ + set32_fx(coefs_quant_fx, 0, sfm_end[BANDS-1]+1); + + /* New analysis of decoded frame */ + FOR ( i = 0; i < BANDS; i++ ) + { + IF ( R_fx[ k_sort[i]] > 0 ) + { + gain_fx = L_deposit_l(0); + + crosscorr_fx = L_deposit_l(0); + selfcorr_fx = L_deposit_l(0); + + FOR ( j = 0; j < sfmsize[k_sort[i]]; j++ ) + { + crosscorr_fx = L_add( crosscorr_fx, Mult_32_16( coefs_norm_fx[sfm_start[k_sort[ i]]+j], shl(coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j], 2) ) );/*1 */ + selfcorr_fx = L_mac0(selfcorr_fx, coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j], coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j]); + } + + exp =sub(norm_l(crosscorr_fx), 1); + gain_fx = ar_div( L_shl(crosscorr_fx, exp), selfcorr_fx); /* 1 + exp */ + gain_fx = L_shl( gain_fx, sub( 16, 1 + exp) + 2);/* 0.2 * Q16 */ + lo = L_Extract_lc(gain_fx, &hi); + /* Use optimal gain */ + FOR ( j = 0; j < sfmsize[k_sort[i]]; j++ ) + { + inp_vector_fx[sfm_start[k_sort[i]]+j] = coefs_norm_dec_fx[sfm_start[k_sort[i]]+j]; + move16(); + coefs_quant_fx[sfm_start[k_sort[ i]]+j] = L_add(L_shl(L_mult0(hi, coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j]), 12), + L_shr(L_mult0(lo, coefs_norm_dec_fx[sfm_start[k_sort[ i]]+j]), 3)); /* Q12 */ + } + } + } + + + + return error; + +} diff --git a/lib_enc/tcx_ltp_enc_fx.c b/lib_enc/tcx_ltp_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..e214f9f6fa9825dfc6b9aa101aed1c79ecc9a3d3 --- /dev/null +++ b/lib_enc/tcx_ltp_enc_fx.c @@ -0,0 +1,655 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +//#include "prot_fx.h" +#include "stl.h" +#include "cnst.h" +#include "basop_util.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +static Word32 dot(const Word16 *X, const Word16 *Y, Word16 n) +{ + Word32 acc; + Word16 i; + + Word64 acc_64; + acc_64 = 0; + move64(); + FOR (i = 0; i < n; i++) + { + acc_64 = W_mac0_16_16(acc_64, X[i], Y[i]); + } + acc = W_sat_l( acc_64 ); + + return acc; +} + +static Word32 interpolate_corr( /* o : interpolated value */ + const Word32 *x, /* i : input vector */ + const Word16 frac, /* i : fraction of lag */ + const Word16 frac_max /* i : max fraction */ +) +{ + Word32 s; + const Word16 *c, *win; + + + win = E_ROM_inter4_1_fx; + if (EQ_16(frac_max, 6))win=E_ROM_inter6_1_fx; + + + s = L_deposit_l(0); + + c = &win[frac]; + s = L_add(s, Mpy_32_16_1(x[0], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[-1], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[-2], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[-3], *c)); + + c = &win[frac_max-frac]; + s = L_add(s, Mpy_32_16_1(x[1], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[2], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[3], *c)); + c += frac_max; + s = L_add(s, Mpy_32_16_1(x[4], *c)); + + + return s; +} + +void tcx_ltp_pitch_search( + Word16 pitch_ol, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *index, + Word16 *norm_corr, + const Word16 len, + Word16 *wsp, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres +) +{ + Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp; + Word32 cor_max, cor[256], *pt_cor, temp; + Word16 wsp2[L_FRAME_PLUS+PIT_MAX_MAX+L_INTERPOL1]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + + delta = 16; + move16(); + if ( EQ_16(pitres, 6)) + { + delta = 8; + move16(); + } + + t0_min = sub(pitch_ol, shr(delta, 1)); + t0_max = sub(add(t0_min, delta), 1); + + IF ( LT_16(t0_min, pitmin)) + { + t0_min = pitmin; + move16(); + t0_max = sub(add(t0_min, delta), 1); + } + + IF ( GT_16(t0_max, pitmax)) + { + t0_max = pitmax; + move16(); + t0_min = add(sub(t0_max, delta), 1); + } + + t_min = sub(t0_min, L_INTERPOL1); + t_max = add(t0_max, L_INTERPOL1); + + /* normalize wsp */ + assert(len+t_max <= L_FRAME_PLUS+PIT_MAX_MAX+L_INTERPOL1); + s_wsp = getScaleFactor16(wsp - t_max, add(len, t_max)); + s_wsp = sub(s_wsp, 4); + FOR (t = negate(t_max); t < len; t++) + { + wsp2[t+t_max] = shl(wsp[t], s_wsp); + move16(); + } + wsp = wsp2 + t_max; + + pt_cor = cor; + + FOR ( t=t_min; t<=t_max; t++ ) + { + *pt_cor = dot(wsp, wsp-t, len); + pt_cor++; + } + + pt_cor = cor + L_INTERPOL1; + cor_max = L_add(*pt_cor++, 0); + t1 = t0_min; + move16(); + + FOR ( t = add(t0_min, 1); t <= t0_max; t++ ) + { + IF ( *pt_cor > cor_max ) + { + cor_max = *pt_cor; + t1 = t; + } + pt_cor++; + } + + temp = dot(wsp, wsp, len); + s = norm_l(temp); + temp_m = extract_h(L_shl(temp, s)); + temp_e = negate(s); + + temp = dot(wsp-t1, wsp-t1, len); + s = norm_l(temp); + temp_m = mult(temp_m, extract_h(L_shl(temp, s))); + temp_e = sub(temp_e, s); + + temp_m = Sqrt16(temp_m, &temp_e); + + if (temp_m == 0) + { + temp_m = 1; + move16(); + } + s = sub(norm_l(cor_max), 1); + temp_m = divide1616(extract_h(L_shl(cor_max, s)), temp_m); + temp_e = sub(negate(s), temp_e); + +#ifdef BASOP_NOGLOB + *norm_corr = shl_o(temp_m, temp_e, &Overflow); +#else + BASOP_SATURATE_WARNING_OFF_EVS + *norm_corr = shl(temp_m, temp_e); + BASOP_SATURATE_WARNING_ON_EVS +#endif + + IF ( GE_16(t1, pitfr1)) + { + *pitch_int = t1; + move16(); + *pitch_fr = 0; + move16(); + + *index = add(sub(t1, pitfr1), extract_l(L_mac0(L_mult0(sub(pitfr2, pitmin), pitres), + sub(pitfr1, pitfr2), shr(pitres,1)))); + move16(); + + return; + } + + /*------------------------------------------------------------------* + * Search fractional pitch with 1/4 subsample resolution. + * search the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + *-----------------------------------------------------------------*/ + + pt_cor = cor + sub(L_INTERPOL1, t0_min); + t0 = t1; + move16(); + + step = 1; + move16(); + if (GE_16(t0, pitfr2)) + { + step = 2; + move16(); + } + fraction = step; + move16(); + + IF (EQ_16(t0, t0_min)) /* Limit case */ + { + fraction = 0; + move16(); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + } + ELSE /* Process negative fractions */ + { + t0 = sub(t0, 1); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + + FOR ( i = add(fraction, step); i < pitres; i += step ) + { + temp = interpolate_corr( &pt_cor[t0], i, pitres ); + + IF (GT_32(temp, cor_max)) + { + cor_max = L_add(temp, 0); + fraction = i; + move16(); + } + } + } + + i = 0; + FOR ( i = 0; i < pitres; i += step ) /* Process positive fractions */ + { + temp = interpolate_corr( &pt_cor[t1], i, pitres ); + + IF (GT_32(temp, cor_max)) + { + cor_max = L_add(temp, 0); + fraction = i; + move16(); + t0 = t1; + move16(); + } + } + + *pitch_int = t0; + move16(); + *pitch_fr = fraction; + move16(); + + IF ( GE_16(t0, pitfr2)) + { + *index = add( extract_l(L_mac0(L_mult0(sub(t0, pitfr2), shr(pitres,1)), + sub(pitfr2, pitmin), pitres)), shr(fraction,1) ); + move16(); + } + ELSE + { + *index = add(imult1616(sub(t0, pitmin), pitres), fraction); + move16(); + } + +} + + +static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_frame, Word16 *gain, Word16 *gain_index ) +{ + Word32 corr, ener; + Word16 i, g, s1, s2, tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + + s1 = sub(getScaleFactor16(speech, L_frame), 4); + s2 = sub(getScaleFactor16(pred_speech, L_frame), 4); + + /* Find gain */ + corr = L_deposit_l(0); + ener = L_deposit_l(1); + + FOR (i = 0; i < L_frame; i++) + { + tmp = shl(pred_speech[i], s2); + corr = L_mac0(corr, shl(speech[i], s1), tmp); + ener = L_mac0(ener, tmp, tmp); + } + + s1 = sub(1, add(s1, s2)); + s2 = sub(1, shl(s2, 1)); + + tmp = sub(norm_l(corr), 1); + corr = L_shl(corr, tmp); + s1 = sub(s1, tmp); + + tmp = norm_l(ener); + ener = L_shl(ener, tmp); + s2 = sub(s2, tmp); + +#ifdef BASOP_NOGLOB + g = divide1616(round_fx_o(corr, &Overflow), round_fx_o(ener, &Overflow)); +#else + g = divide1616(round_fx(corr), round_fx(ener)); +#endif + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + g = shl_o(g, sub(s1, s2), &Overflow); +#else /* BASOP_NOGLOB */ + g = shl(g, sub(s1, s2)); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + + /* Quantize gain */ + g = shr(sub(g, 0x1000), 13); + g = s_max(g, -1); + + *gain_index = g; + move16(); + + /* Dequantize gain */ + *gain = imult1616(add(g, 1), 0x1400); + move16(); + + +} + +void tcx_ltp_encode_fx( Word8 tcxltp_on, + Word8 tcxOnly, + Word16 tcxMode, + Word16 L_frame, + Word16 L_subfr, + Word16 *speech, + Word16 *speech_ltp, + Word16 *wsp, + Word16 Top, + Word16 *ltp_param, + Word16 *ltp_bits, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *gain, + Word16 *pitch_int_past, + Word16 *pitch_fr_past, + Word16 *gain_past, + Word16 *norm_corr_past, + Word16 last_core, + Word16 pitmin, + Word16 pitfr1, + Word16 pitfr2, + Word16 pitmax, + Word16 pitres, + struct TransientDetection const * pTransientDetection, + Word8 SideInfoOnly, + Word16 *A, + Word16 lpcorder + ) +{ + Word16 n; + Word16 norm_corr; + Word16 pred_speech[L_FRAME32k]; + Word16 tempFlatness; + Word16 maxEnergyChange; + Word16 buf_zir[M+L_SUBFR], *zir; + Word16 Aest[M+1]; + Word16 alpha, step; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + + norm_corr = 0; + move16(); + + /* Reset memory if past frame is acelp */ + IF (last_core == ACELP_CORE) + { + *pitch_int_past = L_frame; + move16(); + *pitch_fr_past = 0; + move16(); + *gain_past = 0; + move16(); + } + + /* By default, LTP is off */ + ltp_param[0] = 0; + move16(); + + test(); + IF (tcxltp_on != 0 || SideInfoOnly != 0) + { + Word16 nPrevSubblocks; + Word8 isTCX10 = 0; + + if (EQ_16(tcxMode, TCX_10)) + { + isTCX10 = 1; + move16(); + } + + /* Find pitch lag */ + tcx_ltp_pitch_search( Top, pitch_int, pitch_fr, <p_param[1], &norm_corr, L_frame, wsp, pitmin, pitfr1, pitfr2, pitmax, pitres ); + + nPrevSubblocks = extract_h(L_mac(0x17fff, NSUBBLOCKS, div_s(*pitch_int, L_frame))); + nPrevSubblocks = add(s_min(nPrevSubblocks, NSUBBLOCKS), 1); + + tempFlatness = GetTCXAvgTemporalFlatnessMeasure_fx(pTransientDetection, NSUBBLOCKS, nPrevSubblocks); + + maxEnergyChange = GetTCXMaxenergyChange_fx(pTransientDetection, + (const Word8) isTCX10, + NSUBBLOCKS, nPrevSubblocks); + + /* Switch LTP on */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + BASOP_SATURATE_WARNING_OFF_EVS; + if ( ( + tcxOnly == 0 && + EQ_16(tcxMode, TCX_20) && + GT_16(mult(norm_corr, *norm_corr_past), 0x2000) && + LT_16(tempFlatness, 448/*3.5f Q7*/) + ) || + ( + tcxOnly != 0 && + EQ_16(tcxMode, TCX_10) && + GT_16(s_max(norm_corr, *norm_corr_past), 0x4000) && + LT_16(maxEnergyChange, 448/*3.5f Q7*/) + ) || + ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */ + tcxOnly != 0 && + GT_16(norm_corr, 14418/*0.44f Q15*/) && + L_msu(L_mult(L_frame, sub(19661/*1.2f Q14*/, shr(norm_corr, 1))), *pitch_int, 1<<14) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */ + ) || + ( + tcxOnly != 0 && + EQ_16(tcxMode, TCX_20) && + GT_16(norm_corr, 14418/*0.44f Q15*/) && + ( + LT_16(tempFlatness, 768/*6.0f Q7*/) || + ( + LT_16(tempFlatness, 896/*7.0f Q7*/) && + LT_16(maxEnergyChange, 2816/*22.0f Q7*/) + ) + ) + ) + ) + { + ltp_param[0] = 1; + move16(); + } + BASOP_SATURATE_WARNING_ON_EVS; + } + + IF (ltp_param[0] != 0) + { + /* Find predicted signal */ + predict_signal( speech, pred_speech, *pitch_int, *pitch_fr, pitres, L_frame ); + + /* Find gain */ + tcx_ltp_find_gain( speech, pred_speech, L_frame, gain, <p_param[2] ); + + /* Total number of bits for LTP */ + IF (NE_16(ltp_param[2], -1) ) /* gain > 0 */ + { + *ltp_bits = 12; + move16(); + } + ELSE /* gain <= 0 -> turn off LTP */ + { + ltp_param[0] = 0; + move16(); + } + } + + IF (ltp_param[0] == 0) + { + /* No LTP -> set everything to zero */ + *pitch_int = L_frame; + move16(); + *pitch_fr = 0; + move16(); + ltp_param[1] = 0; + move16(); + set16_fx( pred_speech, 0, L_frame ); + *gain = 0; + move16(); + ltp_param[2] = 0; + move16(); + + *ltp_bits = 0; + move16(); + test(); + if (tcxltp_on != 0 || SideInfoOnly != 0) + { + *ltp_bits = 1; + move16(); + } + } + + if (SideInfoOnly != 0) + { + *gain = 0; + move16(); + } + + test(); + IF (*gain_past == 0 && *gain == 0) + { + Copy(speech, speech_ltp, L_subfr); + } + ELSE IF (*gain_past == 0) + { + alpha = 0; + move16(); + + /* step = 1.f/(float)(L_subfr); */ + step = shl(2, norm_s(L_subfr)); + if (s_and(L_subfr, sub(L_subfr, 1)) != 0) + { + step = mult_r(step, 26214/*64.f/80.f Q15*/); + } + + FOR (n = 0; n < L_subfr; n++) + { +#ifdef BASOP_NOGLOB + speech_ltp[n] = sub_o(speech[n], mult_ro(*gain, mult_ro(alpha, pred_speech[n], &Overflow), &Overflow), &Overflow); +#else + speech_ltp[n] = sub(speech[n], mult_r(*gain, mult_r(alpha, pred_speech[n]))); +#endif + move16(); + BASOP_SATURATE_WARNING_OFF_EVS; +#ifdef BASOP_NOGLOB + alpha = add_o(alpha, step, &Overflow); +#else /* BASOP_NOGLOB */ + alpha = add(alpha, step); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + } + } + ELSE + { + IF (A == NULL) + { + tcx_ltp_get_lpc(speech-L_frame, L_frame, Aest, lpcorder); + A = Aest; + } + + IF (*gain > 0) + { + predict_signal(speech-lpcorder, buf_zir, *pitch_int, *pitch_fr, pitres, lpcorder); + } + ELSE { + set16_fx(buf_zir, 0, lpcorder); + } + + FOR (n = 0; n < lpcorder; n++) + { + buf_zir[n] = add(sub(speech_ltp[n-lpcorder], speech[n-lpcorder]), mult_r(*gain, buf_zir[n])); + move16(); + } + + zir = buf_zir + lpcorder; + + set16_fx(zir, 0, L_subfr); + + E_UTIL_synthesis(0, A, zir, zir, L_subfr, buf_zir, 0, lpcorder); + + alpha = 0x7FFF; + /* step = 1.f/(float)(L_subfr/2); */ + step = shl(4, norm_s(L_subfr)); + if (s_and(L_subfr, sub(L_subfr, 1)) != 0) + { + step = mult_r(step, 26214/*64.f/80.f Q15*/); + } + + FOR (n = shr(L_subfr, 1); n < L_subfr; n++) + { + zir[n] = mult_r(zir[n], alpha); + move16(); + alpha = sub(alpha, step); + } + + FOR (n = 0; n < L_subfr; n++) + { +#ifdef BASOP_NOGLOB + speech_ltp[n] = add_o(sub_o(speech[n], mult_ro(*gain, pred_speech[n], &Overflow), &Overflow), zir[n], &Overflow); +#else + speech_ltp[n] = add(sub(speech[n], mult_r(*gain, pred_speech[n])), zir[n]); +#endif + move16(); + } + } + + test(); + IF ( SideInfoOnly || *gain == 0) + { + FOR ( n=L_subfr; n +#include +#include +#include "stl.h" +#include "options.h" +#include "cnst.h" +//#include "prot_fx.h" +#include "rom_basop_util.h" +#include "basop_util.h" +#include "rom_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +#define inv_int InvIntTable +extern const Word16 int_sqr[17]; + +static Word16 quantize(Word32 x, Word16 invGain, Word16 shift, Word32 offset) +{ + Word16 tmp16; + Word32 tmp32; + + tmp32 = Mpy_32_16_1(L_abs(x), invGain); /* multiply */ + tmp32 = L_shl(tmp32, shift); /* convert to 15Q16 */ + tmp32 = L_add(tmp32, offset); /* add offset */ + tmp16 = extract_h(tmp32); /* truncate */ + if (x < 0) tmp16 = negate(tmp16); /* restore sign */ + + return tmp16; +} + +/* compute noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ +void ComputeSpectrumNoiseMeasure_fx(const Word32 *powerSpec, + Word16 L_frame, + Word16 startLine, + Word8 resetMemory, + Word8 *noiseFlags, + Word16 lowpassLine) +{ + Word16 i, lastTone; + Word32 s, c; + Word16 tmp16; + Word32 tmp1, tmp2 = 0; /* initialization only to avoid compiler warning, not counted */ + + int j; + + IF (resetMemory != 0) + { + FOR (i = 0; i < lowpassLine; i++) + { + noiseFlags[i] = 0; + move16(); + } + } + + FOR (i = lowpassLine; i < L_frame; i++) + { + noiseFlags[i] = 1; + move16(); + } + + test(); + IF (powerSpec != NULL && LT_16(add(startLine, 6), L_frame)) + { + lastTone = 0; + move16(); + + /* noise-measure flags for spectrum filling and quantization (0: tonal, 1: noise-like) */ + i = sub(startLine, 1); + s = 0; + move32(); + for (j=-7; j<8; j++) + { + s = L_add(s, L_shr(powerSpec[i+j], 4)); + } + tmp16 = sub(lowpassLine, 7); + FOR (i = add(i, 1); i < tmp16; i++) + { + c = L_shr(powerSpec[i-1], 4); + c = L_add(c, L_shr(powerSpec[i], 4)); + c = L_add(c, L_shr(powerSpec[i+1], 4)); + + s = L_sub(s, L_shr(powerSpec[i-8], 4)); + s = L_add(s, L_shr(powerSpec[i+7], 4)); + + tmp1 = L_shr(c, 2); + if (noiseFlags[i] == 0) c = L_shl(c, 1); + if (noiseFlags[i] == 0) tmp2 = L_sub(c, tmp1); /* 1.75 * c */ + if (noiseFlags[i] != 0) tmp2 = L_add(c, tmp1); /* 1.25 * c */ + + tmp2 = L_sub(s, tmp2); + if (tmp2 >= 0) + { + noiseFlags[i] = 1; + move16(); + } + if (tmp2 < 0) + { + noiseFlags[i] = 0; + move16(); + } + if (tmp2 < 0) + { + lastTone = i; + move16(); + } + } + + /* lower L_frame*startRatio lines are tonal (0), upper 7 lines are processed separately */ + tmp16 = sub(lowpassLine, 1); + FOR (; i < tmp16; i++) + { + c = L_shr(powerSpec[i-1], 4); + c = L_add(c, L_shr(powerSpec[i], 4)); + c = L_add(c, L_shr(powerSpec[i+1], 4)); + + tmp1 = L_shr(c, 2); + if (noiseFlags[i] == 0) c = L_shl(c, 1); + if (noiseFlags[i] == 0) tmp2 = L_sub(c, tmp1); /* 1.75 * c */ + if (noiseFlags[i] != 0) tmp2 = L_add(c, tmp1); /* 1.25 * c */ + + /* running sum can't be updated any more, just use the latest one */ + tmp2 = L_sub(s, tmp2); + if (tmp2 >= 0) + { + noiseFlags[i] = 1; + move16(); + } + if (tmp2 < 0) + { + noiseFlags[i] = 0; + move16(); + /* lastTone = i; */ + } + } + noiseFlags[i] = 1; /* uppermost line is defined as noise-like (1) */ move16(); + + if (lastTone > 0) /* spread uppermost tonal line one line upward */ + { + noiseFlags[lastTone+1] = 0; + move16(); + } + } + +} + +void detectLowpassFac(const Word32 *powerSpec, Word16 powerSpec_e, Word16 L_frame, Word8 rectWin, Word16 *pLpFac, Word16 lowpassLine) +{ + Word16 i, tmp; + Word32 threshold; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + threshold = 256l/*0.1f * 2*NORM_MDCT_FACTOR Q3*/; /* Q3 */ + BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturation, because threshold is being compared to powerSpec[i] below. */ +#ifdef BASOP_NOGLOB + threshold = L_shl_o(threshold, sub(28, powerSpec_e), &Overflow); +#else /* BASOP_NOGLOB */ + threshold = L_shl(threshold, sub(28, powerSpec_e)); +#endif /* BASOP_NOGLOB */ + + if (rectWin != 0) + { + /* compensate for bad side-lobe attenuation with asymmetric windows */ +#ifdef BASOP_NOGLOB + threshold = L_shl_o(threshold, 1, &Overflow); +#else + threshold = L_shl(threshold, 1); +#endif + } + BASOP_SATURATE_WARNING_ON_EVS + + tmp = shr(lowpassLine, 1); + FOR (i = sub(lowpassLine, 1); i >= tmp; i--) + { + IF (GT_32(powerSpec[i], threshold)) + { + BREAK; + } + } + + tmp = getInvFrameLen(L_frame); + + tmp = mult_r(22938/*0.7f Q15*/, round_fx(L_shl(L_mult0(add(i, 1), tmp), 9))); + *pLpFac = add(tmp, mult_r(9830/*0.3f Q15*/, *pLpFac)); + move16(); + +} + +/*-----------------------------------------------------------* + * Compute noise-measure flags for spectrum filling * + * and quantization (0: tonal, 1: noise-like). * + * Detect low pass if present. * + *-----------------------------------------------------------*/ +void AnalyzePowerSpectrum_fx( + Encoder_State_fx *st, /* i/o: encoder states */ + Word16 L_frame, /* input: frame length */ + Word16 L_frameTCX, /* input: full band frame length */ + Word16 left_overlap, /* input: left overlap length */ + Word16 right_overlap, /* input: right overlap length */ + Word32 const mdctSpectrum[], /* input: MDCT spectrum */ + Word16 mdctSpectrum_e, + Word16 const signal[], /* input: windowed signal corresponding to mdctSpectrum */ + Word32 powerSpec[], /* output: Power spectrum. Can point to signal */ + Word16 *powerSpec_e +) +{ + Word16 i, iStart, iEnd, lowpassLine; + Word16 tmp, s1, s2; + Word32 tmp32; + Word8 tmp8; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + lowpassLine = L_frameTCX; + move16(); + + *powerSpec_e = 16; + move16(); + TCX_MDST(signal, powerSpec, powerSpec_e, left_overlap, sub(L_frameTCX, shr(add(left_overlap, right_overlap), 1)), right_overlap, st->element_mode); + + iStart = 0; + move16(); + iEnd = L_frameTCX; + move16(); + + IF (st->narrowBand != 0) + { + attenuateNbSpectrum_fx(L_frameTCX, powerSpec); + } + + /* get shift to common exponent */ + s1 = 0; + move16(); + s2 = 0; + move16(); + tmp = sub(mdctSpectrum_e, *powerSpec_e); + if (tmp > 0) + { + s2 = negate(tmp); + } + if (tmp < 0) + { + s1 = tmp; + move16(); + } + + /* get headroom */ + tmp = sub(getScaleFactor32(mdctSpectrum, L_frameTCX), s1); + tmp = s_min(tmp, sub(getScaleFactor32(powerSpec, L_frameTCX), s2)); + s1 = add(s1, tmp); + s2 = add(s2, tmp); + + /* power spectrum: MDCT^2 + MDST^2 */ + FOR (i = iStart; i < iEnd; i++) + { + tmp = round_fx(L_shl(mdctSpectrum[i], s1)); + tmp32 = L_mult0(tmp, tmp); + + tmp = round_fx(L_shl(powerSpec[i], s2)); + tmp32 = L_mac0(tmp32, tmp, tmp); + + powerSpec[i] = tmp32; + move32(); + } + + *powerSpec_e = add(shl(sub(mdctSpectrum_e, s1), 1), 1); + move16(); + + tmp8 = 0; + move16(); + test(); + if ( L_msu0(L_mult0(st->L_frame_fx, extract_l(st->last_sr_core)), st->L_frame_past, extract_l(st->sr_core)) != 0 + || NE_16(st->last_core_fx, TCX_20_CORE ) ) + { + tmp8 = 1; + move16(); + } + + ComputeSpectrumNoiseMeasure_fx(powerSpec, + L_frameTCX, + divide3216(L_mult(hTcxEnc->nmStartLine, L_frame), st->L_frame_fx), + tmp8, + hTcxEnc->memQuantZeros_fx, + lowpassLine); + + IF( LE_32(st->total_brate_fx, ACELP_24k40)) + { + lowpassLine = shl(mult(st->hTcxCfg->bandwidth, L_frame), 1); + + test(); + detectLowpassFac(powerSpec, *powerSpec_e, + L_frame, + sub(st->last_core_fx, ACELP_CORE) == 0, + &hTcxEnc->measuredBwRatio, + lowpassLine); + } + ELSE + { + hTcxEnc->measuredBwRatio = 0x4000; + move16(); + } +} + +void AdaptLowFreqEmph_fx(Word32 x[], + Word16 x_e, + Word16 xq[], + Word16 invGain, + Word16 invGain_e, + Word16 tcx_lpc_shaped_ari, + Word16 lpcGains[], Word16 lpcGains_e[], + const Word16 lg + ) +{ + Word16 i, i_max, i_max_old, lg_4, tmp16, s; + Word32 tmp32; + + + IF (tcx_lpc_shaped_ari == 0) + { + lg_4 = shr(lg, 2); + + /* 1. find first magnitude maximum in lower quarter of spectrum */ + invGain_e = add(invGain_e, 1); + i_max = -1; + move16(); + + FOR (i = 0; i < lg_4; i++) + { + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + + test(); + IF ((GE_16(abs_s(xq[i]), 2))&&(tmp32>=0x3A000)) /* 0x3A000 -> 3.625 (15Q16) */ + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + + i_max = i; + move16(); + BREAK; + } + } + + s = sub(add(x_e, invGain_e), 15); + + /* 2. compress value range of all xq up to i_max: add two steps */ + FOR (i = 0; i < i_max; i++) + { + xq[i] = quantize(x[i], invGain, s, 0x6000); + move16(); + } + + /* 3. find first mag. maximum below i_max which is half as high */ + i_max_old = i_max; + move16(); + + IF (i_max_old >= 0) + { + invGain_e = add(invGain_e, 1); + i_max = -1; /* reset first maximum, update inverse gain */ move16(); + + FOR (i = 0; i < lg_4; i++) + { + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + + test(); + IF ((GE_16(abs_s(xq[i]), 2))&&(tmp32>=0x3A000)) /* 0x3A000 -> 3.625 (15Q16) */ + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + + i_max = i; + move16(); + BREAK; + } + } + } + + s = sub(add(x_e, invGain_e), 15); + + /* 4. re-compress and quantize all xq up to half-height i_max+1 */ + FOR (i = 0; i < i_max; i++) + { + xq[i] = quantize(x[i], invGain, s, 0x6000); + move16(); + } + + /* 5. always compress 2 lines; lines could be at index 0 and 1! */ + IF (i_max_old >= 0) + { + invGain_e = sub(invGain_e, 1); /* reset inverse gain */ + if (LT_16(i_max, i_max_old)) + { + i_max = i_max_old; + move16(); + } + } + + i = add(i_max, 1); + + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + IF (GE_32(tmp32, 0x3A000)) + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + } + ELSE + { + xq[i] = quantize(x[i], invGain, sub(add(x_e, invGain_e), 15), 0x6000); + move16(); + } + + i = add(i, 1); + + tmp32 = Mpy_32_16_1(L_abs(x[i]), invGain); /* multiply */ + tmp32 = L_shl(tmp32, sub(add(x_e, invGain_e), 15)); /* convert to 15Q16 */ + IF (GE_32(tmp32, 0x3A000)) + { + + /* Debug initialization to catch illegal cases of xq[i] */ + tmp16 = 0; + + if (xq[i] > 0) + { + tmp16 = 2; + move16(); + } + if (xq[i] < 0) + { + tmp16 = -2; + move16(); + } + + assert(tmp16 != 0); + + xq[i] = add(xq[i], tmp16); + move16(); + } + ELSE + { + xq[i] = quantize(x[i], invGain, sub(add(x_e, invGain_e), 15), 0x6000); + move16(); + } + + + } + ELSE /*if(!tcx_lpc_shaped_ari)*/ + { + PsychAdaptLowFreqEmph_fx(x, lpcGains, lpcGains_e); + }/*if(!tcx_lpc_shaped_ari)*/ + +} + +void PsychAdaptLowFreqEmph_fx(Word32 x[], + const Word16 lpcGains[], const Word16 lpcGains_e[] + ) +{ + Word16 i; + Word16 max, max_e, fac, min, min_e, tmp, tmp_e; + Word32 L_tmp; + + + + assert(lpcGains[0] >= 0x4000); + + max = lpcGains[0]; + move16(); + max_e = lpcGains_e[0]; + move16(); + min = lpcGains[0]; + move16(); + min_e = lpcGains_e[0]; + move16(); + + /* find minimum (min) and maximum (max) of LPC gains in low frequencies */ + FOR (i = 1; i < 9; i++) + { + IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], min, min_e) < 0) + { + min = lpcGains[i]; + move16(); + min_e = lpcGains_e[i]; + move16(); + } + + IF (compMantExp16Unorm(lpcGains[i], lpcGains_e[i], max, max_e) > 0) + { + max = lpcGains[i]; + move16(); + max_e = lpcGains_e[i]; + move16(); + } + } + + min_e = add(min_e, 5); /* min *= 32.0f; */ + + test(); + IF ((compMantExp16Unorm(max, max_e, min, min_e) < 0) && (max > 0)) + { + /* fac = tmp = (float)pow(min / max, 0.0078125f); */ + tmp_e = max_e; + move16(); + tmp = Inv16(max, &tmp_e); + L_tmp = L_shl(L_mult(tmp, min), sub(add(tmp_e, min_e), 6)); /* Q25 */ + L_tmp = L_add(BASOP_Util_Log2(L_tmp), 6<<25); /* Q25 */ + L_tmp = L_shr(L_tmp, 7); /* 0.0078125f = 1.f/(1<<7) */ + L_tmp = BASOP_Util_InvLog2(L_sub(L_tmp, 1<<25)); /* Q30 */ + tmp = round_fx(L_tmp); /* Q14 */ + fac = shr(tmp, 1); /* Q13 */ + + /* gradual boosting of lowest 32 bins; DC is boosted by (min/max)^1/4 */ + FOR (i = 31; i >= 0; i--) + { + x[i] = L_shl(Mpy_32_16_1(x[i], fac), 2); + move32(); + fac = shl(mult_r(fac, tmp), 1); + } + } + +} + +Word16 SQ_gain_fx( /* output: SQ gain */ + Word32 x[], /* input: vector to quantize */ + Word16 x_e, /* input: exponent */ + Word16 nbitsSQ, /* input: number of bits targeted */ + Word16 lg, /* input: vector size (2048 max) */ + Word16 *gain_e) /* output: SQ gain exponent */ +{ + Word16 i, iter, lg_4, s, tmp16; + Word32 ener, tmp32; + Word32 target, fac, offset; + Word32 en[N_MAX/4]; + + + lg_4 = shr(lg, 2); + + /* energy of quadruples with 9dB offset */ + FOR (i=0; i 0.15*log2(10) */ + fac = L_add(0x2A854B, 0); /* -> 12.8f*log2(10); */ + offset = L_add(fac, 0); + + /* find offset (0 to 128 dB with step of 0.125dB) */ + FOR (iter=0; iter<10; iter++) + { + fac = L_shr(fac, 1); + offset = L_sub(offset, fac); + ener = L_deposit_l(0); + + FOR (i=0; i 0.3*log2(10); */ + { + ener = L_add(ener, tmp32); + } + + /* if ener is above target -> break and increase offset */ + IF (GT_32(ener, target)) + { + offset = L_add(offset, fac); + BREAK; + } + } + } + + offset = L_add(L_shr(offset, 1), 0x17EB0); /* 0x17EB0 -> 0.45*log2(10) */ + + *gain_e = add(extract_h(offset), 1); + move16(); + offset = L_sub(L_and(offset, 0xFFFF), 0x10000); + tmp16 = extract_h(BASOP_Util_InvLog2(L_shl(offset, 9))); + + /* return gain */ + + return tmp16; +} + +void tcx_scalar_quantization_fx( + Word32 *x, /* i: input coefficients */ + Word16 x_e, /* i: exponent */ + Word16 *xq, /* o: quantized coefficients */ + Word16 L_frame, /* i: frame length */ + Word16 gain, /* i: quantization gain */ + Word16 gain_e, /* i: quantization gain exponent */ + Word16 offset, /* i: rounding offset (deadzone) */ + Word8 const *memQuantZeros_fx, /* i: coefficients to be set to 0 */ + const Word16 alfe_flag +) +{ + Word16 i, tmp16, s; + Word32 tmp32, offs32; + + + /* common exponent for x and gain for comparison */ + tmp16 = sub(gain_e, x_e); + tmp32 = L_shl(L_deposit_h(gain), s_max(-31, s_min(tmp16, 0))); + tmp16 = negate(s_max(tmp16, 0)); + + i = sub(L_frame, 1); + WHILE ((memQuantZeros_fx[i] != 0) && (LT_32(L_abs(L_shl(x[i], tmp16)), tmp32))) + { + test(); + xq[i] = 0; + move16(); + i = sub(i, 1); + } + + /* invert gain */ + gain = Inv16(gain, &gain_e); + + s = sub(add(x_e, gain_e), 15); + + /*It should almost never happen and if so the quantization will be discarded later on (saturation of gain Quantizer).*/ + IF( GT_16(s,31)) + { + /* Limit the inverse gain to maximal possible value=sqrtL_spec/NORM_MDCT_FACTOR)*/ + gain = 22435; /*sqrt(1200/NORM_MDCT_FACTOR) in 2Q13*/ + gain_e = 2; + + s = sub(add(x_e, gain_e), 15); + } + + /* substract 0x8000 to affect the mac_r in the following loop + so it acts like extract_h. the 0x4000 will be multiplied by 2 + by the mac_r to get to 0x8000 and disable the round. */ + offset = sub(offset, 0x4000); + + FOR (; i >= 0; i--) + { + offs32 = Mpy_32_16_1(L_abs(x[i]), gain); /* multiply */ + offs32 = L_shl(offs32, s); /* convert to 15Q16 */ + tmp16 = mac_r(offs32, offset, 1); /* add offset and truncate */ + if (x[i] < 0) tmp16 = negate(tmp16); /* restore sign */ + + xq[i] = tmp16; + move16(); + } + + IF (alfe_flag == 0) + { + AdaptLowFreqEmph_fx(x, x_e, xq, gain, gain_e, + 0, NULL, NULL, + L_frame + ); + } + +} + +Word16 tcx_scalar_quantization_rateloop_fx( + Word32 *x, /* i : input coefficients */ + Word16 x_e, /* i : exponent */ + Word16 *xq, /* o : quantized coefficients */ + Word16 L_frame, /* i : frame length */ + Word16 *gain, /* i/o: quantization gain */ + Word16 *gain_e, /* i/o: gain exponent */ + Word16 offset, /* i : rounding offset (deadzone) */ + Word8 const*memQuantZeros_fx, /* i : coefficients to be set to 0 */ + Word16 *lastnz_out, /* i/o: last nonzero coeff index */ + Word16 target, /* i : target number of bits */ + Word16 *nEncoded, /* o : number of encoded coeff */ + Word16 *stop, /* i/o: stop param */ + Word16 sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) */ + Word16 sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) */ + Word16 tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ + const Word8 tcxonly, + CONTEXT_HM_CONFIG *hm_cfg /* i : configuration of the context-based harmonic model */ +) +{ + const Word16 iter_max = 4; + Word16 sqBits; + Word16 stopFlag; + Word8 ubfound,lbfound; + Word16 ub, ub_e, lb, lb_e; + Word16 shift, shiftInv; + Word16 iter; + Word16 sqGain, sqGain_e; + Word16 w_lb, w_ub; + const Word16 kDampen = 10; + Word16 old_stopFlag; + Word16 old_nEncoded; + Word16 old_sqBits; + Word16 mod_adjust0, mod_adjust1; + Word16 inv_target, inv_target_e; + const Word16 kMargin = 0x7AE1; /* 0.96 */ + const Word16 kMarginInv = 0x42AB; /* 1/0.96 (1Q14) */ + Word16 tmp, fac1, fac2; + Word32 tmp32; + Word16 lastnz; + + + + /* Init */ + sqGain = *gain; + move16(); + sqGain_e = *gain_e; + move16(); + stopFlag = *stop; + move16(); + ubfound = 0; + move16(); + lbfound = 0; + move16(); + shift = 0x41DE; /* 10^(1/80), 1Q14 */ move16(); + shiftInv = 0x78D7; /* 10^(-1/40) */ move16(); + lb = lb_e = 0; + move16(); + ub = ub_e = 0; + move16(); + w_lb = 0; + move16(); + w_ub = 0; + move16(); + lastnz = *lastnz_out; + move16(); + old_stopFlag = stopFlag; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_sqBits = sqBits_in_noStop; + move16(); + + sqBits = sqBits_in; + move16(); + + mod_adjust0 = extract_l(L_shr(L_max(0x10000, L_sub(0x24CCD, L_mult(0x0052, target))), 3)); /* 2Q13 */ + mod_adjust1 = div_s(0x2000, mod_adjust0); /* 0Q15 */ + + inv_target_e = 15; + move16(); + inv_target = Inv16(target, &inv_target_e); + + fac1 = shl(mult(mult(kMarginInv, mod_adjust0), inv_target), 1); /* 2Q13 */ + fac2 = mult(mult(kMargin, mod_adjust1), inv_target); + + /* Loop */ + FOR ( iter=0 ; iter 0) + { + stopFlag = 0; + move16(); + } + + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( xq, L_frame, + &lastnz, + nEncoded, target, &stopFlag, + hm_cfg + ); + + IF ( tcxRateLoopOpt > 0 ) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF ( ((GE_16(*nEncoded, old_nEncoded))&&(GE_16(stopFlag,old_stopFlag)))|| + ((GT_16(*nEncoded, old_nEncoded) ) && ((stopFlag == 0) && (old_stopFlag > 0))) || + ((stopFlag == 0) && (old_stopFlag == 0)) ) + { + *gain = sqGain; + move16(); + *gain_e = sqGain_e; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_stopFlag = stopFlag; + move16(); + old_sqBits = sqBits; + move16(); + *lastnz_out = lastnz; + move16(); + } + } + } /* for ( iter=0 ; iter 0 ) + { + /* Quantize spectrum */ + tcx_scalar_quantization_fx( x, x_e, xq, L_frame, *gain, *gain_e, offset, memQuantZeros_fx, tcxonly ); + + /* Output */ + *nEncoded = old_nEncoded; + move16(); + sqBits = old_sqBits; + move16(); + *stop = old_stopFlag; + move16(); + } + ELSE + { + /* Output */ + *gain = sqGain; + move16(); + *gain_e = sqGain_e; + move16(); + *stop = stopFlag; + move16(); + *lastnz_out = lastnz; + move16(); + } + + + return sqBits; +} + +void QuantizeGain(Word16 n, Word16 *pGain, Word16 *pGain_e, Word16 *pQuantizedGain) +{ + Word16 ener, ener_e, enerInv, enerInv_e, gain, gain_e; + Word16 quantizedGain; + Word32 tmp32; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + +#ifdef BASOP_NOGLOB + ener = mult_r(shl_o(n, 5, &Overflow), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); +#else + ener = mult_r(shl(n, 5), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); +#endif + ener_e = 15-5-7; + move16(); + IF( n >= 1024 ) + { + /*reduce precision for avoiding overflow*/ + ener = mult_r(shl(n, 4), 26214/*128.f/NORM_MDCT_FACTOR Q15*/); + ener_e = 15-4-7; + } + BASOP_Util_Sqrt_InvSqrt_MantExp(ener, ener_e, &ener, &ener_e, &enerInv, &enerInv_e); + + gain = mult(*pGain, ener); + gain_e = *pGain_e + ener_e; + + assert(gain > 0); + + /* quantize gain with step of 0.714 dB */ + quantizedGain = add(round_fx(BASOP_Util_Log2(L_deposit_h(gain))), shl(gain_e, 9)); /* 6Q9 */ + quantizedGain = mult(quantizedGain, 0x436E); /* 10Q5; 0x436E -> 28/log2(10) (4Q11) */ + quantizedGain = shr(add(quantizedGain, 0x10), 5); /* round */ + + if (quantizedGain < 0) + { + quantizedGain = 0; + move16(); + } + + if (quantizedGain > 127) + { + quantizedGain = 127; + move16(); + } + + *pQuantizedGain = quantizedGain; + move16(); + + tmp32 = L_shl(L_mult0(quantizedGain, 0x797D), 7); /* 6Q25; 0x797D -> log2(10)/28 (Q18) */ + gain_e = add(extract_l(L_shr(tmp32, 25)), 1); /* get exponent */ + gain = round_fx(BASOP_Util_InvLog2(L_or(tmp32, 0xFE000000))); + + *pGain = mult(gain, enerInv); + move16(); + *pGain_e = add(gain_e, enerInv_e); + move16(); + +} + +void tcx_noise_factor_fx( + Word32 *x_orig, /* i: unquantized mdct coefficients */ + Word16 x_orig_e, /* i: exponent */ + Word32 *sqQ, /* i: quantized mdct coefficients */ + Word16 iFirstLine, /* i: first coefficient to be considered */ + Word16 lowpassLine, /* i: last nonzero coefficients after low-pass */ + Word16 nTransWidth, /* i: minimum size of hole to be checked */ + Word16 L_frame, /* i: frame length */ + Word16 gain_tcx, /* i: tcx gain */ + Word16 gain_tcx_e, /* i: gain exponent */ + Word16 tiltCompFactor, /* i: LPC tilt compensation factor */ + Word16 *fac_ns, /* o: noise factor */ + Word16 *quantized_fac_ns/* o: quantized noise factor */ +) +{ + Word16 i, k, maxK, segmentOffset; + Word32 sqErrorNrg, n; + Word16 inv_gain2, inv_gain2_e, tilt_factor, nTransWidth_1; + Word32 accu1, accu2, tmp32; + Word16 tmp1, tmp2, s; + Word16 c1, c2; + Word16 att; /* noise level attenuation factor for transient windows */ + Word32 xMax; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + assert(nTransWidth <= 16); + + c1 = sub(shl(nTransWidth, 1), 4); + c2 = mult(9216/*0.28125f Q15*/, inv_int[nTransWidth]); + nTransWidth_1 = sub(nTransWidth, 1); + + /*Adjust noise filling level*/ + sqErrorNrg = L_deposit_l(0); + n = L_deposit_l(0); + + /* get inverse frame length */ + tmp1 = getInvFrameLen(L_frame); + + /* tilt_factor = 1.0f /(float)pow(max(0.375f, tiltCompFactor), 1.0f/(float)L_frame); */ + tmp32 = BASOP_Util_Log2(L_deposit_h(s_max(0x3000, tiltCompFactor))); /* 6Q25 */ + tmp32 = L_shr(Mpy_32_16_1(tmp32, negate(tmp1)), 6); + tilt_factor = round_fx(BASOP_Util_InvLog2(L_sub(tmp32, 0x2000000))); /* 1Q14 */ + + /* inv_gain2 = 1.0f / ((float)(nTransWidth * nTransWidth) * gain_tcx); */ + tmp32 = L_mult(imult1616(nTransWidth, nTransWidth), gain_tcx); /* 15Q16 */ + tmp1 = norm_l(tmp32); + inv_gain2 = round_fx(L_shl(tmp32, tmp1)); + inv_gain2_e = add(sub(15, tmp1), gain_tcx_e); + inv_gain2 = Inv16(inv_gain2, &inv_gain2_e); + inv_gain2 = shr(inv_gain2, 2); /* 2 bits headroom */ + inv_gain2_e = add(inv_gain2_e, 2); + + /* find last nonzero line below iFirstLine, use it as start offset */ + tmp1 = shr(iFirstLine, 1); + FOR (i = iFirstLine; i > tmp1; i--) + { + IF (sqQ[i] != 0) + { + BREAK; + } + } + /* inv_gain2 *= (float)pow(tilt_factor, (float)i); */ + FOR (k = 0; k < i; k++) + { + inv_gain2 = shl(mult(inv_gain2, tilt_factor), 1); + } + + /* initialize left (k) and right (maxK) non-zero neighbor pointers */ + k = 0; + move16(); + FOR (maxK = 1; maxK < nTransWidth; maxK++) + { + IF (sqQ[i+maxK] != 0) + { + BREAK; + } + } + i = add(i, 1); + segmentOffset = i; + move16(); + + IF (LE_16(nTransWidth, 3)) + { + accu1 = L_deposit_l(0); + accu2 = L_deposit_l(0); + xMax = L_deposit_l(0); + + FOR (k = s_and(i, (Word16)0xFFFE); k < lowpassLine; k++) + { + xMax = L_max(xMax, L_abs(x_orig[k])); + } + s = sub(norm_l(xMax), 4); + + FOR (k = s_and(i, (Word16)0xFFFE); k < lowpassLine; k += 2) + { + /* even-index bins, left sub-win */ + tmp1 = round_fx(L_shl(x_orig[k], s)); + accu1 = L_mac0(accu1, tmp1, tmp1); + + /* odd-index bins, right sub-win */ + tmp1 = round_fx(L_shl(x_orig[k+1], s)); + accu2 = L_mac0(accu2, tmp1, tmp1); + } + k = 0; + move16(); + + if (accu1 == 0) accu1 = L_deposit_l(1); + if (accu2 == 0) accu2 = L_deposit_l(1); + + att = BASOP_Util_Divide3232_Scale( L_shl(L_min(accu1, accu2), 1), L_add(accu1, accu2), &s ); + att = Sqrt16(att, &s); + BASOP_SATURATE_WARNING_OFF_EVS; /* att is always <= 1.0 */ +#ifdef BASOP_NOGLOB + att = shl_o(att, s, &Overflow); +#else + att = shl(att, s); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + } + ELSE + { + att = 0x7FFF; + move16(); + } + + accu1 = L_deposit_l(0); + + tmp1 = sub(lowpassLine, nTransWidth); + FOR (; i <= tmp1; i++) + { + inv_gain2 = shl(mult(inv_gain2, tilt_factor), 1); + + IF (EQ_16(maxK, 1)) /* current line is not zero, so reset pointers */ + { + k = sub(i, segmentOffset); + + IF (k > 0) /* add segment sum to sum of segment magnitudes */ + { + IF (LE_16(nTransWidth, 3)) + { + tmp2 = sub(k, c1); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_mac(n, nTransWidth_1, (Word16)0x8000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], c2); + } + ELSE + { + tmp2 = sub(k, 12); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_sub(n, 0x70000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], 1152/*0.03515625f Q15*/); + } + sqErrorNrg = L_add(sqErrorNrg, accu1); + accu1 = L_deposit_l(0); /* segment ended here, so reset segment sum */ + k = 0; + move16(); + } + + FOR (; maxK < nTransWidth; maxK++) + { + IF (sqQ[i+maxK] != 0) + { + BREAK; + } + } + segmentOffset = add(i, 1); /* new segment might start at next line */ + } + ELSE /* current line is zero, so update pointers & segment sum */ + { + if (LT_16(k, nTransWidth)) + { + k = add(k, 1); + } + + tmp2 = sub(maxK, nTransWidth); + if (tmp2 < 0) + { + maxK = sub(maxK, 1); + } + + test(); + if ((tmp2 >= 0) && (sqQ[i+sub(nTransWidth, 1)] != 0)) + { + maxK = sub(nTransWidth, 1); + } + + /* update segment sum: magnitudes scaled by smoothing function */ + /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ + tmp2 = mult(inv_gain2, shl(imult1616(k, maxK), 8)); + accu1 = L_add(accu1, L_abs(Mpy_32_16_1(x_orig[i], tmp2))); + } + } + + FOR (; i < lowpassLine; i++) + { + inv_gain2 = shl(mult(inv_gain2, tilt_factor), 1); + + IF (EQ_16(maxK, 1)) /* current line is not zero, so reset pointers */ + { + k = sub(i, segmentOffset); + + IF (k > 0) /* add segment sum to sum of segment magnitudes */ + { + IF (LE_16(nTransWidth, 3)) + { + tmp2 = sub(k, c1); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_mac(n, nTransWidth_1, (Word16)0x8000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], c2); + } + ELSE + { + tmp2 = sub(k, 12); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_sub(n, 0x70000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], 1152/*0.03515625f Q15*/); + } + sqErrorNrg = L_add(sqErrorNrg, accu1); + } + segmentOffset = add(i, 1); /* no new segments since maxK remains 1 */ + } + ELSE /* current line is zero, so update pointers & energy sum */ + { + if (LT_16(k, nTransWidth)) + { + k = add(k, 1); + } + if (LT_16(maxK, nTransWidth)) + { + maxK = sub(maxK, 1); + } + + /* update segment sum: magnitudes scaled by smoothing function */ + /*accu1 += (float)fabs(x_orig[i]) * inv_gain2 * (float)(k * maxK);*/ + tmp2 = mult(inv_gain2, shl(imult1616(k, maxK), 8)); + accu1 = L_add(accu1, L_abs(Mpy_32_16_1(x_orig[i], tmp2))); + } + } + + k = sub(i, segmentOffset); + IF (k > 0) /* add last segment sum to sum of segment magnitudes */ + { + IF (LE_16(nTransWidth, 3)) + { + tmp2 = sub(k, c1); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_mac(n, nTransWidth_1, (Word16)0x8000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], c2); + } + ELSE + { + tmp2 = sub(k, 12); + if (tmp2 > 0) n = L_msu(n, k, (Word16)0x8000); + if (tmp2 > 0) n = L_sub(n, 0x70000); + if (tmp2 <= 0) n = L_mac(n, int_sqr[k], 1152/*0.03515625f Q15*/); + } + sqErrorNrg = L_add(sqErrorNrg, accu1); + } + + /* noise level factor: average of segment magnitudes of noise bins */ + IF (n > 0) + { + tmp1 = BASOP_Util_Divide3232_Scale(Mpy_32_16_1(sqErrorNrg, att), n, &s); + s = add(add(add(s, x_orig_e), inv_gain2_e), 7 - 15); + BASOP_SATURATE_WARNING_OFF_EVS; +#ifdef BASOP_NOGLOB + tmp1 = shl_o(tmp1, s, &Overflow); +#else /* BASOP_NOGLOB */ + tmp1 = shl(tmp1, s); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + } + ELSE + { + tmp1 = 0; + move16(); + } + + /* quantize, dequantize noise level factor (range 0.09375 - 0.65625) */ + tmp2 = round_fx(L_shr(L_mult(tmp1, 22016/*1.34375f Q14*/), 14-NBITS_NOISE_FILL_LEVEL)); + + if (GT_16(tmp2, (1<syn, buf, M+1); + + Copy(xn_buf, synth, L_frame_glob); + Copy(synth + sub(L_frame_glob, M+1), LPDmem->syn, M+1); + + IF (st->tcxonly == 0) + { + /* Update weighted synthesis */ + Residu3_fx(Ai+(st->nb_subfr-1)*(M+1), synth + sub(L_frame_glob, 1), &tmp, 1, Q_new+shift-1); + LPDmem->mem_w0 =sub(wsig[sub(L_frame_glob, 1)], tmp); + move16(); + LPDmem->mem_w0 =shr(LPDmem->mem_w0, shift); /*Qnew-1*/ + } + + + /* Emphasis of synth -> synth_pe */ + tmp = synth[-(M+1)]; + move16(); + E_UTIL_f_preemph2(Q_new-1, synth - M, preemph, add(M, L_frame_glob), &tmp); + + Copy(synth + sub(L_frame_glob, M), LPDmem->mem_syn, M); + Copy(synth + sub(L_frame_glob, M), LPDmem->mem_syn2, M); + Copy(synth + sub(L_frame_glob, L_SYN_MEM), LPDmem->mem_syn_r, L_SYN_MEM); + + test(); + IF (st->tcxonly == 0 || LE_16(L_frame_glob,L_FRAME16k)) + { + /* Update excitation */ + IF (LT_16(L_frame_glob, L_EXC_MEM)) + { + Copy( LPDmem->old_exc + L_frame_glob, LPDmem->old_exc, sub(L_EXC_MEM, L_frame_glob) ); + Residu3_fx(A, synth, LPDmem->old_exc + sub(L_EXC_MEM, L_frame_glob), L_frame_glob, 1); + } + ELSE + { + Residu3_fx(A, synth + sub(L_frame_glob, L_EXC_MEM), LPDmem->old_exc, L_EXC_MEM, 1); + } + + } + +} + + +/*--------------------------------------------------------------- + * Residual Quantization + *--------------------------------------------------------------*/ + +/* Returns: number of bits used (including "bits") Q0 */ +Word16 tcx_ari_res_Q_spec_fx( + const Word32 x_orig[], /* i: original spectrum Q31-e */ + Word16 x_orig_e, /* i: original spectrum exponent Q0 */ + const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word16 gain, /* i: TCX gain Q15-e */ + Word16 gain_e, /* i: TCX gain exponent Q0 */ + Word16 prm[], /* o: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +) +{ + Word16 i, j, num_zeros; + Word16 zeros[L_FRAME_PLUS]; + Word16 fac_p, sign; + Word32 thres, x_Q_m, x_Q_p; + Word32 L_tmp, L_tmp2; + Word16 s, s2; + + + /* Limit the number of residual bits */ + target_bits = s_min(target_bits, NPRM_RESQ); + + + /* Requantize the spectrum line-by-line */ + /* fac_m = deadzone * 0.5f; + fac_p = 0.5f - fac_m; */ + num_zeros = 0; + move16(); + + s = sub(add(gain_e, x_Q_e), x_orig_e); + FOR (i=0; i < L_frame; i++) + { + IF (GE_16(bits, target_bits)) /* no bits left */ + { + BREAK; + } + + IF (x_Q[i] != 0) + { + sign = x_fac[i]; + move16(); + if (signs[i] != 0) sign = negate(sign); + + /* x_Q_m = x_Q[i] - sign*fac_m; + x_Q_p = x_Q[i] + sign*fac_p; */ + + L_tmp = L_mult(sign, deadzone); /* sign*deadzone/2 in Q31 */ + x_Q_m = L_sub(x_Q[i], L_shr(L_tmp, x_Q_e)); + + L_tmp = L_mac(L_tmp, sign, (Word16)0x8000); /* sign*(deadzone-1)/2 in Q31 */ + x_Q_p = L_sub(x_Q[i], L_shr(L_tmp, x_Q_e)); + + /* if (fabs(x_orig[i] - gain * x_Q_m) < fabs(x_orig[i] - gain * x_Q_p)) */ + L_tmp = L_abs(L_sub(x_orig[i], L_shl(Mpy_32_16_1(x_Q_m, gain), s))); + L_tmp2 = L_abs(L_sub(x_orig[i], L_shl(Mpy_32_16_1(x_Q_p, gain), s))); + + IF (LT_32(L_tmp, L_tmp2)) /* Decrease magnitude */ + { + x_Q[i] = x_Q_m; + move32(); + prm[bits] = 0; + move16(); + } + ELSE /* Increase magnitude */ + { + x_Q[i] = x_Q_p; + move32(); + prm[bits] = 1; + move16(); + } + bits = add(bits, 1); + } + ELSE + { + zeros[num_zeros] = i; + move16(); + num_zeros = add(num_zeros, 1); + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = msu_r(1417339264l/*2*0.33f Q31*/, deadzone, 21627/*2*0.33f Q15*/); /* Q16 */ + target_bits = sub(target_bits, 1); /* reserve 1 bit for the check below */ + + s = sub(gain_e, x_orig_e); + s2 = sub(x_Q_e, 1); + FOR (j = 0; j < num_zeros; j++) + { + IF (GE_16(bits, target_bits)) /* 1 or 0 bits left */ + { + BREAK; + } + + i = zeros[j]; + move16(); + + thres = L_mult(fac_p, x_fac[i]); /* Q31 */ + + IF (GT_32(L_abs(x_orig[i]), L_shl(Mpy_32_16_1(thres, gain), s))) + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + prm[bits] = sub(1, signs[i]); + move16(); + bits = add(bits, 1); + + L_tmp = L_shr(thres, s2); + if (signs[i]) L_tmp = L_negate(L_tmp); + x_Q[i] = L_tmp; + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add(bits, 1); + } + } + + + return bits; +} + +#define kMaxEstimatorOvershoot 5 +#define kMaxEstimatorUndershoot 0 + +Word16 tcx_res_Q_gain_fx( + Word16 sqGain, + Word16 sqGain_e, + Word16 *gain_tcx, + Word16 *gain_tcx_e, + Word16 *prm, + Word16 sqTargetBits +) +{ + Word16 bits; + Word16 gain_reQ, gain_reQ_e; + + /*Refine the gain quantization : Normal greedy gain coding */ + + gain_reQ = *gain_tcx; + move16(); + gain_reQ_e = *gain_tcx_e; + move16(); + + /* make sure we have a bit of headroom */ + IF (GT_16(gain_reQ, 0x7000)) + { + gain_reQ = shr(gain_reQ, 1); + gain_reQ_e = add(gain_reQ_e, 1); + } + + /* bring sqGain to same exponent */ + sqGain = shr(sqGain, sub(gain_reQ_e, sqGain_e)); + + FOR (bits=0; bits < TCX_RES_Q_BITS_GAIN; bits++) + { + IF (LT_16(sqGain, gain_reQ)) + { + prm[bits] = 0; + move16(); + gain_reQ = mult_r(gain_reQ, gain_corr_inv_fac[bits]); + } + ELSE + { + prm[bits] = 1; + move16(); + gain_reQ = shl(mult_r(gain_reQ, gain_corr_fac[bits]), 1); + } + + IF (LT_16(bits, sqTargetBits)) + { + *gain_tcx = gain_reQ; + move16(); + *gain_tcx_e = gain_reQ_e; + move16(); + } + } + + + return bits; +} + +Word16 tcx_res_Q_spec_fx( + Word32 *x_orig, + Word16 x_orig_e, + Word32 *x_Q, + Word16 x_Q_e, + Word16 L_frame, + Word16 sqGain, + Word16 sqGain_e, + Word16 *prm, + Word16 sqTargetBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] /* 1Q14 */ +) +{ + Word16 i; + Word16 fac_m, fac_p; + Word32 tmp1, tmp2; + Word16 s, s2, lf_deemph_factor; + Word16 c; + Word32 thres; + + + /* Limit the number of residual bits */ + sqTargetBits = s_min(sqTargetBits, NPRM_RESQ); + + /* Requantize the spectrum line-by-line */ + fac_m = shr(sq_round, 1); + fac_p = sub(0x4000, fac_m); + + /* exponent difference of x_orig and x_Q * sqGain */ + s = sub(x_orig_e, add(x_Q_e, sqGain_e)); + + lf_deemph_factor = 0x4000; + move16(); + s2 = sub(x_Q_e, 1); + + FOR (i = 0; i < L_frame; i++) + { + IF (GE_16(bits, sub(sqTargetBits, kMaxEstimatorUndershoot))) + { + fac_m = 0; + move16(); + fac_p = 0; + move16(); + + IF (GE_16(bits, s_min(NPRM_RESQ, add(sqTargetBits, kMaxEstimatorOvershoot)))) + { + BREAK; + } + } + + test(); + test(); + IF ((x_Q[i] != 0) && ((lf_deemph_factors == NULL) || (GT_16(lf_deemph_factors[i], 0x2000)))) + { + tmp1 = L_add(x_orig[i], 0); + tmp2 = Mpy_32_16_1(x_Q[i], sqGain); + if (s > 0) tmp2 = L_shr(tmp2, s); + if (s < 0) tmp1 = L_shl(tmp1, s); + + if (lf_deemph_factors != NULL) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + IF (LT_32(tmp1, tmp2)) + { + prm[bits] = 0; + move16(); + bits = add(bits, 1); + + if (x_Q[i] > 0) tmp1 = L_mult(fac_m, lf_deemph_factor); + if (x_Q[i] < 0) tmp1 = L_mult(fac_p, lf_deemph_factor); + x_Q[i] = L_sub(x_Q[i], L_shr(tmp1, s2)); + move32(); + } + ELSE + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + if (x_Q[i] > 0) tmp1 = L_mult(fac_p, lf_deemph_factor); + if (x_Q[i] < 0) tmp1 = L_mult(fac_m, lf_deemph_factor); + x_Q[i] = L_add(x_Q[i], L_shr(tmp1, s2)); + move32(); + } + } + } + + /*Quantize zeroed-line of the spectrum*/ + c = sub(21627/*0.66f Q15*/, mult_r(sq_round, 21627/*0.66f Q15*/)); + + FOR (i = 0; i < L_frame; i++) + { + IF (GE_16(bits, sub(sqTargetBits, 2))) + { + BREAK; + } + + test(); + test(); + IF ((x_Q[i] == 0) && ((lf_deemph_factors == NULL) || (GT_16(lf_deemph_factors[i], 0x2000)))) + { + if (lf_deemph_factors != NULL) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + thres = L_mult(c, lf_deemph_factor); + tmp1 = L_shl(Mpy_32_16_1(thres, sqGain), sub(sqGain_e, x_orig_e)); + + IF (GT_32(x_orig[i], tmp1)) + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + x_Q[i] = L_shl(thres, sub(1, x_Q_e)); + move32(); + } + ELSE IF (L_add(x_orig[i], tmp1) < 0) + { + prm[bits] = 1; + move16(); + bits = add(bits, 1); + + prm[bits] = 0; + move16(); + bits = add(bits, 1); + + x_Q[i] = L_shl(L_negate(thres), sub(1, x_Q_e)); + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add(bits, 1); + } + } + } + + /*Be sure that every possible bits are initialized*/ + FOR (i = bits; i < NPRM_RESQ; i++) + { + prm[i] = 0; + move16(); + } + + + return bits; +} +void ProcessIGF_fx( + IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ + Encoder_State_fx *st, /**< in: Encoder state */ + Word32 pMDCTSpectrum[], /**< in: MDCT spectrum */ + Word16 *pMDCTSpectrum_e, + Word32 pPowerSpectrum[], /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 *pPowerSpectrum_e, + Word16 isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + Word16 isTNSActive, /**< in: flag indicating if the TNS is active */ + Word16 isTransition, /**< in: flag indicating if the input is the transition from from ACELP to TCX20/TCX10 */ + Word16 frameno /**< in: flag indicating index of current subframe */ +) +{ + Word16 igfGridIdx; + Word16 isIndepFlag; + Word16 bsBits; + Word16 bsStart; + BSTR_ENC_HANDLE hBstr = st->hBstr; + + + isIndepFlag = 1; + move16(); + test(); + IF (isTransition && isTCX20) + { + igfGridIdx = IGF_GRID_LB_TRAN; + move16(); + } + ELSE + { + IF (isTCX20) + { + igfGridIdx = IGF_GRID_LB_NORM; + move16(); + } + ELSE + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + move16(); + if (EQ_16(frameno, 1)) + { + isIndepFlag = 0; + move16(); + } + } + } + + + IGFEncApplyMono_fx(hInstance, /**< in: instance handle of IGF Encoder */ + igfGridIdx, /**< in: IGF grid index */ + st, /**< in: Encoder state */ + pMDCTSpectrum, /**< in: MDCT spectrum */ + *pMDCTSpectrum_e, + pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ + *pPowerSpectrum_e, + isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + isTNSActive, /**< in: flag indicating if the TNS is active */ + (st->last_core_fx == ACELP_CORE) + ); + { + const Word32 tns_predictionGain = st->hIGFEnc->tns_predictionGain; + const Word16 startLine = st->hIGFEnc->infoStartLine; + const Word16 endLine = st->hIGFEnc->infoStopLine; + const Word16 maxOrder = 8; + const Word32 *spec_before = st->hIGFEnc->spec_be_igf; + Word16 curr_order = 0; + Word16 A[ITF_MAX_FILTER_ORDER+1]; + Word16 Q_A; + Word16 predictionGain = 0; + Word16 *flatteningTrigger = &(st->hIGFEnc->flatteningTrigger); + + ITF_Detect_fx( spec_before, startLine, endLine, maxOrder, A, &Q_A, &predictionGain, &curr_order, shl(st->hIGFEnc->spec_be_igf_e, 1) ); + *flatteningTrigger = 0; + test(); + IF (LT_32(tns_predictionGain, 9646899l/*1.15 Q23*/)&& + LT_16(predictionGain, 147/*1.15 Q7*/)) + { + *flatteningTrigger = 1; + } + } + +//IVAS_CODE_BITSTREAM + bsStart = hBstr->next_ind_fx; + + move16(); + hInstance->infoTotalBitsPerFrameWritten = 0; + move16(); + IF (isTCX20) + { + IGFEncWriteBitstream_fx(hInstance, NULL, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag); + } + ELSE + { + IGFEncWriteBitstream_fx(hInstance, st->hBstr, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag); + } + +#ifndef IVAS_CODE_BITSTREAM + bsBits = sub(hBstr->next_ind_fx, bsStart); + IF (!isTCX20) + { + IGFEncConcatenateBitstream_fx(hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot_fx, hBstr->ind_list_fx); + } +#else +PMT("New bit stream implementation to be checked") + bsBits = sub(hBstr->next_ind_fx, bsStart); + IF(!isTCX20) + { + IGFEncConcatenateBitstream_fx(hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot_fx, hBstr->ind_list_fx); + } + +#endif + +} + +void attenuateNbSpectrum_fx(Word16 L_frame, Word32 *spectrum) +{ + Word16 i, length, att; + + length = idiv1616U(L_frame, 20); + + att = 21627/*0.66f Q15*/; + move16(); + if (EQ_16(length, 8)) + { + att = 19661/*0.6f Q15*/; + move16(); + } + + spectrum += sub(L_frame, length); + FOR (i=0; i < length; i++) + { + spectrum[i] = Mpy_32_16_1(spectrum[i], att); + move32(); + att = mult_r(att, att); + } +} diff --git a/lib_enc/tfa_enc_fx.c b/lib_enc/tfa_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..66ee96687bed9da86de3d610f05d3c48422ae776 --- /dev/null +++ b/lib_enc/tfa_enc_fx.c @@ -0,0 +1,112 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "basop_util.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 */ + +/*-------------------------------------------------------------------* + * tfaCalcEnv() + * + * + *-------------------------------------------------------------------*/ + +void tfaCalcEnv_fx( + const Word16* shb_speech, + Word32* enr +) +{ + Word16 i, j, k; + + k = 0; + move16(); + FOR (i=0; i +#include +#include "rom_com_fx.h" +#include "rom_com.h" +#include "prot.h" /* Function prototypes */ +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +#define HLM_MIN_NRG (32768.0f * 2*NORM_MDCT_FACTOR / (640*640)) + +/** Get TNS filter parameters from autocorrelation. + * + * @param rxx Autocorrelation function/coefficients. + * @param maxOrder Maximum filter order/number of coefficients. + * @param pTnsFilter Pointer to the output filter. + */ +static void GetFilterParameters(Word32 rxx[], Word16 maxOrder, STnsFilter * pTnsFilter); + +/** Quantization for reflection coefficients. + * + * @param parCoeff input reflection coefficients. + * @param index output quantized values. + * @param order number of coefficients/values. + */ +static void Parcor2Index(Word16 const parCoeff[], Word16 index[], Word16 order); + +/** Linear prediction analysis/synthesis filter definition. + * @param order filter order. + * @param parCoeff filter (PARCOR) coefficients. + * @param state state of the filter. Must be at least of 'order' size. + * @param x the current input value. + * @return the output of the filter. + */ +typedef Word32 (* TLinearPredictionFilter)(Word16 order, Word16 const parCoeff[], Word32 * state, Word32 x); + + +/********************************/ +/* Interface functions */ +/********************************/ + +#define MAX_SUBDIVISIONS 3 + +Word16 DetectTnsFilt_fx(STnsConfig const * pTnsConfig, + Word32 const pSpectrum[], + STnsData * pTnsData, + Word16 *predictionGain) +{ + Word16 facs[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; + Word16 facs_e[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; /* exponents of facs[][] */ + Word16 shifts[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; + Word16 iFilter = 0; + + ResetTnsData(pTnsData); + + IF (pTnsConfig->maxOrder <= 0) + { + return 0; + } + + /* Calculate norms for each spectrum part */ + FOR (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++) + { + Word16 idx0; + Word16 idx1; + Word16 nSubdivisions; + Word16 iSubdivisions; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + move16(); + move16(); + move16(); + idx0 = pTnsConfig->iFilterBorders[iFilter+1]; + idx1 = pTnsConfig->iFilterBorders[iFilter]; + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + + assert(pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS); + + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + Word16 iStartLine; + Word16 iEndLine; + Word16 tmp, headroom, shift; + Word32 L_tmp, tmp32; + + /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions; + iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */ + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + tmp = sub(idx1, idx0); + iStartLine = imult1616(tmp, iSubdivisions); + iEndLine = add(iStartLine, tmp); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, idx0); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, idx0); + + /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/ + headroom = getScaleFactor32(&pSpectrum[iStartLine], sub(iEndLine, iStartLine)); + + /* Calculate norm of spectrum band */ + L_tmp = Norm32Norm(pSpectrum+iStartLine, headroom, sub(iEndLine, iStartLine), &shift); + + /* Check threshold HLM_MIN_NRG */ + BASOP_SATURATE_WARNING_OFF_EVS; +#ifdef BASOP_NOGLOB + tmp32 = L_sub(L_shl_o(L_tmp, s_min(31, sub(shift, 24-31*2)), &Overflow), 3277l/*HLM_MIN_NRG Q7*/); +#else /* BASOP_NOGLOB */ + tmp32 = L_sub(L_shl(L_tmp, s_min(31, sub(shift, 24-31*2))), 3277l/*HLM_MIN_NRG Q7*/); +#endif + BASOP_SATURATE_WARNING_ON_EVS; + + /* get pre-shift for autocorrelation */ + tmp = sub(shift, norm_l(L_tmp)); /* exponent for normalized L_tmp */ + tmp = shr(sub(1, tmp), 1); /* pre-shift to apply before autocorrelation */ + shifts[iFilter][iSubdivisions] = s_min(tmp, headroom); + move16(); + + /* calc normalization factor */ + facs[iFilter][iSubdivisions] = 0; + move16(); + facs_e[iFilter][iSubdivisions] = 0; + move16(); + + if (tmp32 > 0) + { + facs[iFilter][iSubdivisions] = 0x7FFF; + move16(); /* normalization not needed for one subdivision */ + } + + test(); + IF ((tmp32 > 0) && (GT_16(nSubdivisions, 1))) + { + move16(); + facs_e[iFilter][iSubdivisions] = shl(sub(tmp, shifts[iFilter][iSubdivisions]), 1); + + tmp = sub(1, shl(tmp, 1)); /* exponent of autocorrelation */ + L_tmp = L_shl(L_tmp, sub(shift, tmp)); /* shift L_tmp to that exponent */ + + /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */ + move16(); + facs[iFilter][iSubdivisions] = div_s(0x2000, round_fx(L_tmp)); /* L_tmp is >= 0x2000000 */ + } + + } + + } + /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */ + FOR (iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++) + { +#define RXX_E (3) + Word32 rxx[TNS_MAX_FILTER_ORDER+1]; + Word16 idx0; + Word16 idx1; + Word16 spectrumLength; + STnsFilter * pFilter; + Word16 nSubdivisions; + Word16 iSubdivisions; + Word16 tmpbuf[325]; + + set32_fx(rxx, 0, TNS_MAX_FILTER_ORDER+1); + + move16(); + move16(); + move16(); + idx0 = pTnsConfig->iFilterBorders[iFilter+1]; + idx1 = pTnsConfig->iFilterBorders[iFilter]; + spectrumLength = sub(idx1, idx0); + pFilter = pTnsData->filter + iFilter; + nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions; + + FOR (iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++) + { + Word16 iStartLine, n, i; + Word16 iEndLine; + const Word16 * pWindow; + Word16 lag, shift; + Word32 L_tmp; + + IF ( facs[iFilter][iSubdivisions] == 0 ) + { + BREAK; + } + + + /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions; + iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */ + assert((nSubdivisions == 1) || (nSubdivisions == 3)); + + iStartLine = imult1616(spectrumLength, iSubdivisions); + iEndLine = add(iStartLine, spectrumLength); + + if (EQ_16(nSubdivisions, 3))iStartLine=mult(iStartLine,0x2AAB); + iStartLine = add(iStartLine, idx0); + + if (EQ_16(nSubdivisions, 3))iEndLine=mult(iEndLine,0x2AAB); + iEndLine = add(iEndLine, idx0); + + + move16(); + shift = shifts[iFilter][iSubdivisions]; + + move16(); + pWindow = tnsAcfWindow_fx; + + n = sub(iEndLine, iStartLine); + assert(n < (Word16)(sizeof(tmpbuf)/sizeof(Word16))); + FOR (i = 0; i < n; i++) + { + tmpbuf[i] = round_fx(L_shl(pSpectrum[iStartLine+i], shift)); + } + + FOR (lag = 0; lag <= pTnsConfig->maxOrder; lag++) + { + n = sub(sub(iEndLine,lag), iStartLine); + + L_tmp = L_deposit_l(0); + FOR (i = 0; i < n; i++) + { + L_tmp = L_mac0(L_tmp, tmpbuf[i], tmpbuf[i+lag]); + } + + if (lag != 0) L_tmp = Mpy_32_16_1(L_tmp, *pWindow++); + + L_tmp = Mpy_32_16_1(L_tmp, facs[iFilter][iSubdivisions]); + L_tmp = L_shl(L_tmp, facs_e[iFilter][iSubdivisions]); + + rxx[lag] = L_add(rxx[lag], L_tmp); + move32(); + } + + } + + IF ( EQ_16(iSubdivisions,nSubdivisions)) /* meaning there is no subdivision with low energy */ + { + pFilter->spectrumLength = spectrumLength; + move16(); + /* Limit the maximum order to spectrum length/4 */ + GetFilterParameters(rxx, s_min (pTnsConfig->maxOrder, shr(pFilter->spectrumLength,2)), pFilter); + } + } + + if (predictionGain) + { + assert(pTnsConfig->nMaxFilters == 1); + move16(); + *predictionGain = pTnsData->filter->predictionGain; + } + + /* We check the filter's decisions in the opposite direction */ + FOR (iFilter = sub(pTnsConfig->nMaxFilters,1); iFilter >= 0; iFilter--) + { + STnsFilter * pFilter; + struct TnsParameters const * pTnsParameters; + + move16(); + move16(); + pFilter = pTnsData->filter + iFilter; + pTnsParameters = pTnsConfig->pTnsParameters + iFilter; + + IF ( s_or((Word16)GT_16(pFilter->predictionGain,pTnsParameters->minPredictionGain), + sub(pFilter->avgSqrCoef,pTnsParameters->minAvgSqrCoef) > 0 ) ) + { + move16(); + pTnsData->nFilters = add(pTnsData->nFilters,1); + } + ELSE IF (pTnsData->nFilters > 0) /* If a previous filter is turned on */ + { + /* Since TNS filter of order 0 is not allowed we haved to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */ + ClearTnsFilterCoefficients(pFilter); + move16(); + move16(); + pFilter->order = 1; + pTnsData->nFilters = add(pTnsData->nFilters,1); + } + ELSE + { + ClearTnsFilterCoefficients(pFilter); + } + } + + + test(); + return (pTnsData->nFilters > 0); +} + +Word16 EncodeTnsData_fx(STnsConfig const * pTnsConfig, STnsData const * pTnsData, Word16 * stream, Word16 * pnSize, Word16 * pnBits) +{ + + move16(); + move16(); + *pnSize = 0; + *pnBits = 0; + + IF ( GT_16(pTnsConfig->nMaxFilters, 1)) + { + + IF ( LT_16(pTnsConfig->iFilterBorders[0],512)) + { + GetParameters(&tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits); + } + ELSE + { + GetParameters(&tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits); + } + } + ELSE + { + GetParameters(&tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits); + } + + return TNS_NO_ERROR; +} + +Word16 WriteTnsData_fx(STnsConfig const * pTnsConfig, Word16 const * stream, Word16 * pnSize, Encoder_State_fx *st, Word16 * pnBits) +{ + + IF ( GT_16(pTnsConfig->nMaxFilters,1)) + { + + IF ( LT_16(pTnsConfig->iFilterBorders[0],512)) + { + WriteToBitstream_fx(&tnsEnabledSWBTCX10BitMap, 1, &stream, pnSize, st->hBstr, pnBits); + } + ELSE + { + WriteToBitstream_fx( &tnsEnabledSWBTCX20BitMap, 1, &stream, pnSize, st->hBstr, pnBits ); + } + } + ELSE + { + WriteToBitstream_fx( &tnsEnabledWBTCX20BitMap, 1, &stream, pnSize, st->hBstr, pnBits ); + } + + + return TNS_NO_ERROR; +} + +/*********************************************************************************************/ +/* Definitions of functions used in the mapping between TNS parameters and a bitstream. */ +/*********************************************************************************************/ + +/* Helper functions for Hufmann table coding */ + +/********************************/ +/* Private functions */ +/********************************/ + +static void GetFilterParameters(Word32 rxx[], Word16 maxOrder, STnsFilter * pTnsFilter) +{ + Word16 i; + Word16 parCoeff[TNS_MAX_FILTER_ORDER]; + Word32 epsP[TNS_MAX_FILTER_ORDER+1], L_tmp; +#if TNS_COEF_RES == 5 + Word16 const * values = tnsCoeff5; +#elif TNS_COEF_RES == 4 + Word16 const * values = tnsCoeff4; +#elif TNS_COEF_RES == 3 + Word16 const * values = tnsCoeff3; +#endif + Word16 * indexes = pTnsFilter->coefIndex; + + + /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */ + L_tmp = E_LPC_schur(rxx, parCoeff, epsP, maxOrder); + BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturation, this value is compared against a threshold. */ + pTnsFilter->predictionGain = divide3232(L_shr(epsP[0], PRED_GAIN_E), L_tmp); + BASOP_SATURATE_WARNING_ON_EVS + /* non-linear quantization of TNS lattice coefficients with given resolution */ + Parcor2Index(parCoeff, indexes, maxOrder); + + /* reduce filter order by truncating trailing zeros */ + i = sub(maxOrder,1); + + WHILE ((i >= 0) && (indexes[i] == 0)) + { + i = sub(i, 1); + } + + move16(); + pTnsFilter->order = add(i, 1); + + /* compute avg(coef*coef) */ + L_tmp = L_deposit_l(0); + + FOR (i = pTnsFilter->order-1; i >= 0; i--) + { + Word16 value ; + + move16(); + value = shr(values[indexes[i]+INDEX_SHIFT], 1); + + move16(); + L_tmp = L_mac0(L_tmp, value, value); + + } + move16(); + pTnsFilter->avgSqrCoef = round_fx(L_tmp); + + /* assert(maxOrder == 8); + pTnsFilter->avgSqrCoef = shr(pTnsFilter->avgSqrCoef, 3); */ + +} + +static void Parcor2Index(const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order) +{ + Word16 nValues; + Word16 const * values; + Word16 i; + Word16 iIndex; + Word16 x; + + + move16(); + move16(); + nValues = 1 << TNS_COEF_RES; +#if TNS_COEF_RES == 5 + values = tnsCoeff5; +#elif TNS_COEF_RES == 4 + values = tnsCoeff4; +#elif TNS_COEF_RES == 3 + values = tnsCoeff3; +#endif + + FOR (i = 0; i < order; i++) + { + move16(); + move16(); + iIndex = 1; + x = parCoeff[i]; + + /* parCoeff is in the range of -1.0 ... 1.0 by definition */ + /* assert((x >= FL2WORD16(-1.0f)) && (x <= FL2WORD16(1.0f))); */ + + WHILE ((iIndex < nValues) && (x > add(shr(values[iIndex-1], 1), shr(values[iIndex], 1))) ) + { + iIndex = add(iIndex,1); + + } + index[i] = sub(iIndex, 1 + INDEX_SHIFT); + } + +} + diff --git a/lib_enc/transient_detection_fx.c b/lib_enc/transient_detection_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..b3a11d1160362dc6b6a1ffe2714e6ce18d2d7a41 --- /dev/null +++ b/lib_enc/transient_detection_fx.c @@ -0,0 +1,908 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include "options.h" +#include "stl.h" +#include "basop_util.h" +//#include "prot_fx.h" +#include "rom_com.h" +#include +#include +#include +#include +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/* Exponent of attack threshold. Picked according to current threshold values. */ +#define ATTACKTHRESHOLD_E 4 +/* Exponent of subblock energies and accumulated subblock energies. + The current value of 2 does not prevent saturations to happen in all cases. */ +#define SUBBLOCK_NRG_E 4 +/* Exponent of the subblock energy change. + This value is coupled to the transient detector API. */ +#define SUBBLOCK_NRG_CHANGE_E NRG_CHANGE_E + +#define MIN_BLOCK_ENERGY ((Word32)1) + + +/************************************************/ +/* */ +/* Internal functions prototypes */ +/* */ +/************************************************/ + +static void InitDelayBuffer(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer); +static void InitSubblockEnergies(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer, SubblockEnergies * pSubblockEnergies); +static void InitTransientDetector_fx(SubblockEnergies * pSubblockEnergies, Word16 nDelay, Word16 nSubblocksToCheck, + TCheckSubblocksForAttack_fx pCheckSubblocksForAttack, + Word16 attackRatioThreshold, TransientDetector * pTransientDetector); +static void UpdateDelayBuffer(Word16 const * input, Word16 nSamplesAvailable, DelayBuffer * pDelayBuffer); +static void HighPassFilter(Word16 const * input, Word16 length, Word16 * pFirState1, Word16 * pFirState2, Word16 * output); +static void UpdateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies); +static void CalculateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies); +static void RunTransientDetector(TransientDetector * pTransientDetector); + +/************************************************/ +/* */ +/* Functions that define transient detectors */ +/* */ +/************************************************/ + +/** TCX decision. + * Check IF there is an attack in a subblock. Version FOR TCX Long/Short decision. + * See TCheckSubblocksForAttack_fx FOR definition of parameters. + * It is assumed that the delay of MDCT overlap was not taken into account, so that the last subblock corresponds to the newest input subblock. + */ +static void GetAttackForTCXDecision(Word32 const * pSubblockNrg, Word32 const * pAccSubblockNrg, Word16 nSubblocks, Word16 nPastSubblocks, Word16 attackRatioThreshold, Word16 * pbIsAttackPresent, Word16 * pAttackIndex) +{ + Word16 i; + Word16 bIsAttackPresent, attackIndex; + Word16 attackRatioThreshold_1_5; + + (void)nPastSubblocks; + (void)nSubblocks; + assert(nSubblocks >= NSUBBLOCKS); + assert(nPastSubblocks >= 2); + + /* attackRatioThreshold_1_5 = attackRatioThreshold * 1.5, exponent is ATTACKTHRESHOLD_E+1 */ + attackRatioThreshold_1_5 = add(shr(attackRatioThreshold,2),shr(attackRatioThreshold,1)); + + move16(); + move16(); + bIsAttackPresent = FALSE; + attackIndex = 0; + /* Search for the last attack in the subblocks */ + if ( s_or((Word16)GT_32(L_shr(pSubblockNrg[-1],ATTACKTHRESHOLD_E), Mpy_32_16_1(pAccSubblockNrg[-1], attackRatioThreshold)), + L_sub(L_shr(pSubblockNrg[-2],ATTACKTHRESHOLD_E), Mpy_32_16_1(pAccSubblockNrg[-2], attackRatioThreshold)) > 0) ) + { + move16(); + bIsAttackPresent = TRUE; + } + + FOR (i = 0; i < NSUBBLOCKS; i++) + { + IF ( GT_32(L_shr(pSubblockNrg[i],ATTACKTHRESHOLD_E), Mpy_32_16_1(pAccSubblockNrg[i], attackRatioThreshold))) + { + if (i < 6) + { + move16(); + bIsAttackPresent = TRUE; + } + + if ( s_and((Word16)NE_16(attackIndex,2),(Word16)NE_16(attackIndex,6))) + { + move16(); + attackIndex = i; + } + } + ELSE /* no attack, but set index anyway in case of strong energy increase */ + { + IF ( s_and(( (Word16)GT_32(L_shr(pSubblockNrg[i],1+ATTACKTHRESHOLD_E), Mpy_32_16_1(pSubblockNrg[sub(i,1)], attackRatioThreshold_1_5))), + ( L_sub(L_shr(pSubblockNrg[i],1+ATTACKTHRESHOLD_E), Mpy_32_16_1(pSubblockNrg[sub(i,2)], attackRatioThreshold_1_5)) > 0 )) ) + { + + if ( s_and((Word16)NE_16(attackIndex,2),(Word16)NE_16(attackIndex,6))) + { + move16(); + attackIndex = i; + } + } + } + } + /* avoid post-echos on click sounds (very short transients) due to TNS aliasing */ + if ( EQ_16(attackIndex,4)) + { + move16(); + attackIndex = 7; + } + if ( EQ_16(attackIndex,5)) + { + move16(); + attackIndex = 6; + } + + move16(); + move16(); + *pAttackIndex = attackIndex; + *pbIsAttackPresent = bIsAttackPresent; + +} + + +/** Initialize TCX transient detector. + * See InitTransientDetector_fx for definition of parameters. + */ +static void InitTCXTransientDetector(Word16 nDelay, SubblockEnergies * pSubblockEnergies, TransientDetector * pTransientDetector) +{ + InitTransientDetector_fx(pSubblockEnergies, nDelay, NSUBBLOCKS, GetAttackForTCXDecision, 17408/*8.5f/(1<delayBuffer); + /* Init a subblock energies buffer used for the TCX Short/Long decision. */ + InitSubblockEnergies(nFrameLength, nTCXDelay, &pTransientDetection->delayBuffer, &pTransientDetection->subblockEnergies); + /* Init the TCX Short/Long transient detector. */ + InitTCXTransientDetector(nTCXDelay, &pTransientDetection->subblockEnergies, &pTransientDetection->transientDetector); + /* We need two past subblocks for the TCX TD and NSUBBLOCKS+1 for the temporal flatness measure FOR the TCX LTP. */ + pTransientDetection->transientDetector.pSubblockEnergies->nDelay = + add(pTransientDetection->transientDetector.pSubblockEnergies->nDelay, NSUBBLOCKS+1); +} + +/** + * \brief Calculate average of temporal energy change. + * \return average temporal energy change with exponent = 8 + */ +Word16 GetTCXAvgTemporalFlatnessMeasure_fx(struct TransientDetection const * pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks) +{ + Word16 i; + TransientDetector const * pTransientDetector; + SubblockEnergies const * pSubblockEnergies; + Word16 nDelay; + Word16 nRelativeDelay; + Word16 const * pSubblockNrgChange; + Word32 sumTempFlatness; + Word16 nTotBlocks; + + + /* Initialization */ + pTransientDetector = &pTransientDetection->transientDetector; + pSubblockEnergies = pTransientDetector->pSubblockEnergies; + move16(); + nDelay = pTransientDetector->nDelay; + nRelativeDelay = sub(pSubblockEnergies->nDelay, nDelay); + pSubblockNrgChange = NULL; + nTotBlocks = add(nCurrentSubblocks,nPrevSubblocks); + + assert(nTotBlocks > 0); + + sumTempFlatness = L_deposit_l(0); + + assert((nPrevSubblocks <= nRelativeDelay) && (nCurrentSubblocks <= NSUBBLOCKS+nDelay)); + + move16(); + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[sub(nRelativeDelay,nPrevSubblocks)]; + + FOR (i = 0; i < nTotBlocks; i++) + { + sumTempFlatness = L_add(sumTempFlatness, L_deposit_l(pSubblockNrgChange[i])); + } + + /* exponent = AVG_FLAT_E */ + i = div_l(L_shl(sumTempFlatness,16-15+SUBBLOCK_NRG_CHANGE_E-AVG_FLAT_E), nTotBlocks); + + return i; +} + +Word16 GetTCXMaxenergyChange_fx(struct TransientDetection const * pTransientDetection, + const Word8 isTCX10, + const Word16 nCurrentSubblocks, const Word16 nPrevSubblocks) +{ + Word16 i; + TransientDetector const * pTransientDetector; + SubblockEnergies const * pSubblockEnergies; + Word16 nDelay; + Word16 nRelativeDelay; + Word16 const * pSubblockNrgChange; + Word16 maxEnergyChange; + Word16 nTotBlocks; + + + pTransientDetector = &pTransientDetection->transientDetector; + pSubblockEnergies = pTransientDetector->pSubblockEnergies; + move16(); + nDelay = pTransientDetector->nDelay; + nRelativeDelay = sub(pSubblockEnergies->nDelay, nDelay); + pSubblockNrgChange = NULL; + nTotBlocks = nCurrentSubblocks+nPrevSubblocks; + + assert(nTotBlocks > 0); + maxEnergyChange = 0/*0.0f Q7*/; + + assert((nPrevSubblocks <= nRelativeDelay) && (nCurrentSubblocks <= NSUBBLOCKS+nDelay)); + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nRelativeDelay-nPrevSubblocks]; + + IF ( s_or(pTransientDetector->bIsAttackPresent, isTCX10) ) /* frame is TCX-10 */ + { + Word32 const * pSubblockNrg = &pSubblockEnergies->subblockNrg[sub(nRelativeDelay,nPrevSubblocks)]; + Word32 nrgMin, nrgMax; + Word16 idxMax = 0; + + move16(); + + nrgMax = L_add(pSubblockNrg[0], 0); + + /* find subblock with maximum energy */ + FOR (i = 1; i < nTotBlocks; i++) + { + if ( LT_32(nrgMax, pSubblockNrg[i])) + { + idxMax = i; + move16(); + } + nrgMax = L_max(nrgMax, pSubblockNrg[i]); + } + + nrgMin = L_add(nrgMax, 0); + + /* find minimum energy after maximum */ + FOR (i = idxMax + 1; i < nTotBlocks; i++) + { + nrgMin = L_min(nrgMin, pSubblockNrg[i]); + } + /* lower maxEnergyChange if energy doesn't decrease much after energy peak */ + /* if (nrgMin > 0.375f * nrgMax) */ + if ( LT_32(Mpy_32_16_1(nrgMax, 12288/*0.375f Q15*/), nrgMin) ) + { + nTotBlocks = sub(idxMax, 3); + } + } + + FOR (i = 0; i < nTotBlocks; i++) + { + maxEnergyChange = s_max(maxEnergyChange, pSubblockNrgChange[i]); + } + + move16(); + i = maxEnergyChange; + + return i; +} + +void RunTransientDetection_fx(Word16 const * input, Word16 nSamplesAvailable, TransientDetection * pTransientDetection) +{ + Word16 filteredInput[L_FRAME48k]; + SubblockEnergies * pSubblockEnergies = &pTransientDetection->subblockEnergies; + TransientDetector * pTransientDetector = &pTransientDetection->transientDetector; + + assert((input != NULL) && (pTransientDetection != NULL) && (pSubblockEnergies != NULL) && (pTransientDetector != NULL)); + + HighPassFilter(input, nSamplesAvailable, &pSubblockEnergies->firState1, &pSubblockEnergies->firState2, filteredInput); + + /* Update subblock energies. */ + UpdateSubblockEnergies(filteredInput, nSamplesAvailable, pSubblockEnergies); + + /* Run transient detectors. */ + RunTransientDetector(pTransientDetector); + + /* Update the delay buffer. */ + UpdateDelayBuffer(filteredInput, nSamplesAvailable, &pTransientDetection->delayBuffer); +#ifdef IVAS_CODE + /* compute ramp up flag */ + pSubblockEnergies->ramp_up_flag = ((pSubblockEnergies->ramp_up_flag << 1) & 0x0003); + e0 = dotp(filteredInput + length / 2, filteredInput + length / 2, pSubblockEnergies->pDelayBuffer->nSubblockSize / 2) + 0.5f * MIN_BLOCK_ENERGY; + e1 = pSubblockEnergies->subblockNrg[pSubblockEnergies->nDelay + 4] - e0; + if (e1 > e0) + { + pSubblockEnergies->ramp_up_flag |= 0x0001; + } +#endif +} + +void SetTCXModeInfo_fx(Encoder_State_fx *st, + TransientDetection const * pTransientDetection, + Word16 * tcxModeOverlap) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + assert(pTransientDetection != NULL); + + IF( EQ_16(st->codec_mode,MODE2)) + { + + /* determine window sequence (1 long or 2 short windows) */ + + test(); + IF ( st->tcx10Enabled != 0 && st->tcx20Enabled != 0 ) + { + /* window switching based on transient detector output */ + test(); + test(); + test(); + IF ( ((pTransientDetection->transientDetector.bIsAttackPresent != 0) + || (GT_32(Mpy_32_16_1(st->currEnergyHF_fx, 840/*1.0f/39.0f Q15*/), st->prevEnergyHF_fx) )) + && ((NE_16(st->last_core_fx, ACELP_CORE) ) && (NE_16(st->last_core_fx, AMR_WB_CORE) )) ) + { + move16(); + hTcxEnc->tcxMode = TCX_10; + } + ELSE + { + move16(); + hTcxEnc->tcxMode = TCX_20; + } + } + ELSE + { + /* window selection (non-adaptive) based on flags only */ + IF (st->tcx10Enabled) + { + move16(); + hTcxEnc->tcxMode = TCX_10; + } + ELSE IF (st->tcx20Enabled) + { + move16(); + hTcxEnc->tcxMode = TCX_20; + } + ELSE { + move16(); + hTcxEnc->tcxMode = NO_TCX; + } + } + test(); + test(); + IF (st->last_core_fx == ACELP_CORE || st->last_core_fx == AMR_WB_CORE) + { + move16(); + st->hTcxCfg->tcx_last_overlap_mode = TRANSITION_OVERLAP; + } + ELSE IF ( (EQ_16(hTcxEnc->tcxMode, TCX_10))&&(EQ_16(st->hTcxCfg->tcx_curr_overlap_mode,ALDO_WINDOW))) + { + move16(); + st->hTcxCfg->tcx_last_overlap_mode = FULL_OVERLAP; + } + ELSE + { + move16(); + st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; + } + + /* determine window overlaps (0 full, 2 none, or 3 half) */ + + IF ( EQ_16(hTcxEnc->tcxMode, TCX_10)) + { + IF( pTransientDetection->transientDetector.attackIndex < 0) + { + move16(); + *tcxModeOverlap = HALF_OVERLAP; + } + ELSE + { + move16(); + *tcxModeOverlap = s_and(pTransientDetection->transientDetector.attackIndex, 3); + if ( EQ_16(*tcxModeOverlap,1)) + { + move16(); + *tcxModeOverlap = FULL_OVERLAP; + } + } + } + ELSE IF ( EQ_16(hTcxEnc->tcxMode, TCX_20)) + { + IF (EQ_16(pTransientDetection->transientDetector.attackIndex, 7)) + { + move16(); + *tcxModeOverlap = HALF_OVERLAP; + } + ELSE IF (EQ_16(pTransientDetection->transientDetector.attackIndex, 6)) + { + move16(); + *tcxModeOverlap = MIN_OVERLAP; + } + ELSE + { + move16(); + *tcxModeOverlap = ALDO_WINDOW; + } + } + ELSE /* NO_TCX */ + { + move16(); + *tcxModeOverlap = TRANSITION_OVERLAP; + } + test(); + if ((EQ_16(st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP))&&(EQ_16(*tcxModeOverlap,ALDO_WINDOW))) + { + move16(); + *tcxModeOverlap = FULL_OVERLAP; + } + + /* Sanity check */ + assert(*tcxModeOverlap !=1); + + } + +} + +/************************************************/ +/* */ +/* Internal functions */ +/* */ +/************************************************/ + +static void InitDelayBuffer(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer) +{ + Word16 const nMaxBuffSize = sizeof(pDelayBuffer->buffer)/sizeof(pDelayBuffer->buffer[0]); + + + move16(); + move16(); + assert((nFrameLength > NSUBBLOCKS) && (nFrameLength % NSUBBLOCKS == 0) && (nDelay >= 0) && (pDelayBuffer != NULL)); + pDelayBuffer->nSubblockSize = nFrameLength/NSUBBLOCKS; + assert(pDelayBuffer->nSubblockSize <= nMaxBuffSize); + set16_fx(pDelayBuffer->buffer, 0, nMaxBuffSize); + pDelayBuffer->nDelay = nDelay % pDelayBuffer->nSubblockSize; + assert(pDelayBuffer->nDelay <= nMaxBuffSize); + +} + +static void InitSubblockEnergies(Word16 nFrameLength, Word16 nDelay, DelayBuffer * pDelayBuffer, SubblockEnergies * pSubblockEnergies) +{ + Word16 const nMaxBuffSize = sizeof(pSubblockEnergies->subblockNrg)/sizeof(pSubblockEnergies->subblockNrg[0]); + (void)nFrameLength; + + + assert((pDelayBuffer != NULL) && (pSubblockEnergies != NULL) && (pDelayBuffer->nSubblockSize * NSUBBLOCKS == nFrameLength) && (pDelayBuffer->nSubblockSize > 0)); + + set32_fx(pSubblockEnergies->subblockNrg, MIN_BLOCK_ENERGY, nMaxBuffSize); + set32_fx(pSubblockEnergies->accSubblockNrg, MIN_BLOCK_ENERGY, nMaxBuffSize+1); + set16_fx(pSubblockEnergies->subblockNrgChange, 0x7fff, nMaxBuffSize); + pSubblockEnergies->nDelay = nDelay / pDelayBuffer->nSubblockSize; + assert(pSubblockEnergies->nDelay < nMaxBuffSize); + pSubblockEnergies->nPartialDelay = nDelay % pDelayBuffer->nSubblockSize; + pSubblockEnergies->facAccSubblockNrg = 26624/*0.8125f Q15*/; /* Energy accumulation factor */ + pSubblockEnergies->firState1 = 0; + pSubblockEnergies->firState2 = 0; + + pSubblockEnergies->pDelayBuffer = pDelayBuffer; + pDelayBuffer->nDelay = s_max(pDelayBuffer->nDelay, pSubblockEnergies->nPartialDelay); + +} + +/** Init transient detector. + * Fills TransientDetector structure with sensible content and enable it. + * @param pSubblockEnergies Subblock energies used in this transient detector. + * @param nDelay Delay FOR this transient detector. + * @param nSubblocksToCheck Number of subblocks to check in this transient detector. + * @param pCheckSubblockForAttack Attack detection function FOR this transient detector. + * @param pSetAttackPosition Function FOR finalizing this transient detector. + * @param attackRatioThreshold Attack ratio threshold with exponent ATTACKTHRESHOLD_E. + * @param pTransientDetector Structure to be initialized. + */ +static void InitTransientDetector_fx(SubblockEnergies * pSubblockEnergies, Word16 nDelay, Word16 nSubblocksToCheck, + TCheckSubblocksForAttack_fx pCheckSubblocksForAttack, + Word16 attackRatioThreshold, TransientDetector * pTransientDetector) +{ + Word16 nMaxBuffSize; + + move16(); + nMaxBuffSize = sizeof(pSubblockEnergies->subblockNrg)/sizeof(pSubblockEnergies->subblockNrg[0]); + + assert((pSubblockEnergies != NULL) && (pSubblockEnergies->pDelayBuffer != NULL) && (pTransientDetector != NULL) && (pSubblockEnergies->pDelayBuffer->nSubblockSize != 0)); + pTransientDetector->pSubblockEnergies = pSubblockEnergies; + pTransientDetector->nDelay = (nDelay - pSubblockEnergies->nPartialDelay) / pSubblockEnergies->pDelayBuffer->nSubblockSize; + assert(nDelay == pTransientDetector->nDelay * pSubblockEnergies->pDelayBuffer->nSubblockSize + pSubblockEnergies->nPartialDelay); + assert(pTransientDetector->nDelay < nMaxBuffSize); + pSubblockEnergies->nDelay = s_max(pSubblockEnergies->nDelay, pTransientDetector->nDelay); + assert(nSubblocksToCheck <= NSUBBLOCKS + pTransientDetector->nDelay); + pTransientDetector->nSubblocksToCheck = nSubblocksToCheck; + pTransientDetector->CheckSubblocksForAttack_fx = pCheckSubblocksForAttack; + pTransientDetector->attackRatioThreshold = attackRatioThreshold; + pTransientDetector->prev_bIsAttackPresent = FALSE; + pTransientDetector->bIsAttackPresent = FALSE; + pTransientDetector->attackIndex = -1; +} + +/* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ +static Word32 InlineFilter(Word16 inValue, Word16 firState1, Word16 firState2) +{ + /* 0.375f * inValue - 0.5f * firState1 + 0.125f * firState2 */ + + return L_msu(L_mac(L_mult(firState2, 4096/*0.125f Q15*/), inValue, 12288/*0.375f Q15*/), firState1, 16384/*0.5f Q15*/); +} + +static void HighPassFilter(Word16 const * input, Word16 length, Word16 * pFirState1, Word16 * pFirState2, Word16 * output) +{ + Word16 i; + + output[0] = round_fx(InlineFilter(input[0], *pFirState1, *pFirState2)); + output[1] = round_fx(InlineFilter(input[1], input[0], *pFirState1)); + + FOR (i = 2; i < length; i++) + { + output[i] = round_fx(InlineFilter(input[i], input[i-1], input[i-2])); + } + + /* update filter states: shift time samples through delay line */ + move16(); + move16(); + *pFirState2 = input[length-2]; + *pFirState1 = input[length-1]; + +} + +static void RunTransientDetector(TransientDetector * pTransientDetector) +{ + Word16 const attackRatioThreshold = pTransientDetector->attackRatioThreshold; + SubblockEnergies const * pSubblockEnergies = pTransientDetector->pSubblockEnergies; + Word16 const nDelay = pTransientDetector->nDelay; + Word16 const nRelativeDelay = pSubblockEnergies->nDelay - nDelay; + Word32 const * pSubblockNrg = &pSubblockEnergies->subblockNrg[nRelativeDelay]; + Word32 const * pAccSubblockNrg = &pSubblockEnergies->accSubblockNrg[nRelativeDelay]; + + assert((pTransientDetector->CheckSubblocksForAttack_fx != NULL)); + + pTransientDetector->CheckSubblocksForAttack_fx(pSubblockNrg, pAccSubblockNrg, + NSUBBLOCKS+nDelay, nRelativeDelay, + attackRatioThreshold, + &pTransientDetector->bIsAttackPresent, &pTransientDetector->attackIndex); + +} + +static void UpdateDelayBuffer(Word16 const * input, Word16 nSamplesAvailable, DelayBuffer * pDelayBuffer) +{ + Word16 i; + Word16 nDelay; + + + move16(); + nDelay = pDelayBuffer->nDelay; + + assert((nDelay >= 0) && (nDelay <= (int)sizeof(pDelayBuffer->buffer)/(int)sizeof(pDelayBuffer->buffer[0]))); + assert(nSamplesAvailable <= NSUBBLOCKS*pDelayBuffer->nSubblockSize); + /* If this is not the last frame */ + IF (nSamplesAvailable == NSUBBLOCKS*pDelayBuffer->nSubblockSize) + { + /* Store the newest samples into the delay buffer */ + FOR (i = 0; i < nDelay; i++) + { + move16(); + pDelayBuffer->buffer[i] = input[i+nSamplesAvailable-nDelay]; + } + } + +} + +static void UpdateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies) +{ + Word16 i; + + + assert((pSubblockEnergies->nDelay >= 0) && (pSubblockEnergies->nDelay+NSUBBLOCKS <= (int)sizeof(pSubblockEnergies->subblockNrg)/(int)sizeof(pSubblockEnergies->subblockNrg[0]))); + assert(pSubblockEnergies->nPartialDelay <= pSubblockEnergies->pDelayBuffer->nDelay); + /* At least one block delay is required when subblock energy change is required */ + assert(pSubblockEnergies->nDelay >= 1); + + /* Shift old subblock energies */ + FOR (i = 0; i < pSubblockEnergies->nDelay; i++) + { + move32(); + move32(); + move16(); + pSubblockEnergies->subblockNrg[i] = pSubblockEnergies->subblockNrg[i+NSUBBLOCKS]; + pSubblockEnergies->accSubblockNrg[i] = pSubblockEnergies->accSubblockNrg[i+NSUBBLOCKS]; + pSubblockEnergies->subblockNrgChange[i] = pSubblockEnergies->subblockNrgChange[i+NSUBBLOCKS]; + } + + /* Compute filtered subblock energies for the new samples */ + CalculateSubblockEnergies(input, nSamplesAvailable, pSubblockEnergies); + +} + +/* This function should be inlined and WMOPS instrumentation takes that into account, meaning that all references are considered as local variables */ +static void UpdatedAndStoreAccWindowNrg(Word32 newWindowNrgF, Word32 * pAccSubblockNrg, Word16 facAccSubblockNrg, Word32 * pOutAccWindowNrgF) +{ + /* Store the accumulated energy */ + move32(); + *pOutAccWindowNrgF = *pAccSubblockNrg; + /* Update the accumulated energy: maximum of the current and the accumulated energy */ + *pAccSubblockNrg = Mpy_32_16_1(*pAccSubblockNrg, facAccSubblockNrg); + + if ( GT_32(newWindowNrgF, *pAccSubblockNrg)) + { + move32(); + *pAccSubblockNrg = newWindowNrgF; + } +} + +static void CalculateSubblockEnergies(Word16 const * input, Word16 nSamplesAvailable, SubblockEnergies * pSubblockEnergies) +{ + DelayBuffer * pDelayBuffer; + Word16 nSubblockSize; + Word16 nDelay; + Word16 nPartialDelay; + Word16 * delayBuffer; + Word16 facAccSubblockNrg; + Word32 * pSubblockNrg; + Word32 * pAccSubblockNrg; + Word16 * pSubblockNrgChange; + Word32 * pAccSubblockTmp; + Word16 nWindows; + Word16 w, k, k2, tmp; + Word16 firState1, firState2; + Word32 w0, w1; + Word32 accu; + + move16(); + pDelayBuffer = pSubblockEnergies->pDelayBuffer; + facAccSubblockNrg = pSubblockEnergies->facAccSubblockNrg; + + move16(); + move16(); + move16(); + nSubblockSize = pDelayBuffer->nSubblockSize; + nDelay = pSubblockEnergies->nDelay; + nPartialDelay = pSubblockEnergies->nPartialDelay; + + delayBuffer = &pDelayBuffer->buffer[sub(pDelayBuffer->nDelay, nPartialDelay)]; + pSubblockNrg = &pSubblockEnergies->subblockNrg[nDelay]; + pAccSubblockNrg = &pSubblockEnergies->accSubblockNrg[nDelay]; + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[nDelay]; + + move16(); + move16(); + /* nWindows = (nSamplesAvailable + nPartialDelay) / nSubblockSize */ + nWindows = shr(div_s( add(nSamplesAvailable,nPartialDelay), shl(nSubblockSize, 7)),8); + firState1 = pSubblockEnergies->firState1; + firState2 = pSubblockEnergies->firState2; + pAccSubblockTmp = &pAccSubblockNrg[nWindows]; + + IF (nWindows > 0) + { + /* Process left over samples from the previous frame. */ + accu = L_add(MIN_BLOCK_ENERGY, 0); + assert((SUBBLOCK_NRG_E & 1) == 0); + FOR (k = 0; k < nPartialDelay; k++) + { + tmp = shr(delayBuffer[k], SUBBLOCK_NRG_E/2); + accu = L_mac0(accu, tmp, tmp); + } + + /* Process new samples in the 0. subblock. */ + w = sub(nSubblockSize,nPartialDelay); + assert((SUBBLOCK_NRG_E & 1) == 0); + FOR (k = 0; k < w; k++) + { + tmp = shr(input[k], SUBBLOCK_NRG_E/2); + accu = L_mac0(accu, tmp, tmp); + } + + move32(); + pSubblockNrg[0] = accu; + /* Set accumulated subblock energy at this point. */ + UpdatedAndStoreAccWindowNrg(pSubblockNrg[0], pAccSubblockTmp, facAccSubblockNrg, &pAccSubblockNrg[0]); + + FOR (w = 1; w < nWindows; w++) + { + accu = L_add(MIN_BLOCK_ENERGY, 0); + /* Process new samples in the w. subblock. */ + k2 = add(k, nSubblockSize); + assert((SUBBLOCK_NRG_E & 1) == 0); + FOR (; k < k2; k++) + { + tmp = shr(input[k], SUBBLOCK_NRG_E/2); + accu = L_mac0(accu, tmp, tmp); + } + move32(); + pSubblockNrg[w] = accu; + /* Set accumulated subblock energy at this point. */ + UpdatedAndStoreAccWindowNrg(pSubblockNrg[w], pAccSubblockTmp, facAccSubblockNrg, &pAccSubblockNrg[w]); + } + + /* Calculate energy change for each block. */ + FOR (w = 0; w < nWindows; w++) + { + w0 = L_add(pSubblockNrg[w], 0); + w1 = L_add(pSubblockNrg[sub(w,1)], 0); + + IF ( GT_32(w0, w1)) + { + k2 = BASOP_Util_Divide3232_uu_1616_Scale(w0, w1, &k); + } + ELSE + { + k2 = BASOP_Util_Divide3232_uu_1616_Scale(w1, w0, &k); + } + move16(); + pSubblockNrgChange[w] = MAX_16; + IF ( LT_16(k,SUBBLOCK_NRG_CHANGE_E)) + { + move16(); + pSubblockNrgChange[w] = shr(k2, sub(SUBBLOCK_NRG_CHANGE_E,k)); + } + } + } + + move16(); + move16(); + pSubblockEnergies->firState1 = firState1; + pSubblockEnergies->firState2 = firState2; +} +#ifdef IVAS_CODE +/*-------------------------------------------------------------------* + * set_transient_stereo() + * + * + *-------------------------------------------------------------------*/ + +void set_transient_stereo( + CPE_ENC_HANDLE hCPE, /* i : CPE structure */ + float currFlatness[] /* i/o: current flatness */ +) +{ + int16_t n, attackIsPresent; + float currFlatnessMax; + Encoder_State** sts; + + sts = hCPE->hCoreCoder; + + /* for DFT/TD based stereo ,map avg. flatness to individual stereo channels (M/S or X/Y) */ + maximum(currFlatness, CPE_CHANNELS, &currFlatnessMax); + attackIsPresent = 0; + + for (n = 0; n < CPE_CHANNELS; n++) + { + attackIsPresent = max(attackIsPresent, sts[n]->hTranDet->transientDetector.bIsAttackPresent); + } + + set_f(currFlatness, currFlatnessMax, CPE_CHANNELS); + + for (n = 0; n < CPE_CHANNELS; n++) + { + sts[n]->hTranDet->transientDetector.bIsAttackPresent = attackIsPresent; + } + + if (hCPE->hStereoDft != NULL) + { + if (hCPE->hStereoDft->attackPresent) + { + hCPE->hStereoDft->wasTransient = 1; + } + else if (hCPE->hStereoDft->wasTransient) + { + hCPE->hStereoDft->wasTransient = 0; + } + + hCPE->hStereoDft->attackPresent = attackIsPresent; + + hCPE->hStereoDft->hItd->currFlatness = 0; + for (n = 0; n < CPE_CHANNELS; n++) + { + hCPE->hStereoDft->hItd->currFlatness = max(hCPE->hStereoDft->hItd->currFlatness, currFlatness[n]); + } + } + + if (hCPE->hStereoMdct != NULL) + { + hCPE->hStereoMdct->hItd->currFlatness = 0; + for (n = 0; n < CPE_CHANNELS; n++) + { + hCPE->hStereoMdct->hItd->currFlatness = max(hCPE->hStereoMdct->hItd->currFlatness, currFlatness[n]); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * transient_analysis() + * + * + *-------------------------------------------------------------------*/ + + /*! r: preliminary flag to force ACELP */ +int16_t transient_analysis( + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + const float cor_map_LT[], /* i : LT correlation map */ + const float multi_harm_limit /* i : multi harminic threshold */ +) +{ + const float* pSubblockNrg; + float accSubblockNrgRev[NSUBBLOCKS]; /* store acc Nrg in reversed signal */ + float* pTmp; /* point to acc Nrg */ + int16_t offset; + int16_t i; + float thr_fwd; + float thr_rev; + const int16_t nRelativeDelay = hTranDet->subblockEnergies.nDelay - hTranDet->transientDetector.nDelay; + int16_t prel_force_td; + float cor_map_LT_sum; + + pTmp = &accSubblockNrgRev[NSUBBLOCKS - 1]; + offset = nRelativeDelay - 4; + prel_force_td = FALSE; + + /* summation of the LT correlation map */ + cor_map_LT_sum = sum_f(cor_map_LT, L_FFT / 2); /* Note maybe BE optimized by computing inside noise_est */ + + thr_fwd = THR_NORM_HIGH; + if (cor_map_LT_sum > multi_harm_limit * 0.8f) + { + thr_fwd = THR_HIGH; + } + thr_rev = THR_LOW; + if (cor_map_LT_sum > multi_harm_limit * 0.6f) + { + thr_rev = THR_NORM_LOW; + } + + /* forward attack analysis */ + for (i = -2; i < 7; i++) + { + if (hTranDet->subblockEnergies.subblockNrg[nRelativeDelay + i] > hTranDet->subblockEnergies.accSubblockNrg[nRelativeDelay + i] * thr_fwd) + { + prel_force_td |= 0x0001; + } + } + if (prel_force_td == 0 && hTranDet->transientDetector.prev_bIsAttackPresent == 1) + { + /* release analysis */ + pSubblockNrg = hTranDet->transientDetector.pSubblockEnergies->subblockNrg; + set_zero(accSubblockNrgRev, NSUBBLOCKS); + + for (i = NSUBBLOCKS - 1; i > -1; i--) + { + if (i == NSUBBLOCKS - 1) + { + accSubblockNrgRev[i] = pSubblockNrg[i + offset]; + } + else + { + accSubblockNrgRev[i] = *pTmp; + *pTmp *= hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg; + if (pSubblockNrg[i + offset] > *pTmp) + { + *pTmp = pSubblockNrg[i + offset]; + } + } + } + + /* -3 check */ + if (pSubblockNrg[1 + offset] > accSubblockNrgRev[1] * thr_rev) + { + prel_force_td |= 0x0002; + } + + /* -4 check */ + if (prel_force_td == 0 && pSubblockNrg[offset] > accSubblockNrgRev[0] * thr_rev) + { + if (pSubblockNrg[offset] > accSubblockNrgRev[0] * (thr_rev + THR_LOW_STEP)) + { + prel_force_td |= 0x0004; + } + else if ((hTranDet->subblockEnergies.ramp_up_flag & 0x0002) != 0) + { + prel_force_td |= 0x0008; + } + } + } + + return prel_force_td != 0; +} + +#endif + diff --git a/lib_enc/transition_enc_fx.c b/lib_enc/transition_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..baf2a2db74d11bf480d0d20366ce41c614300ee0 --- /dev/null +++ b/lib_enc/transition_enc_fx.c @@ -0,0 +1,1304 @@ +/*==================================================================================== + 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 function prototypes + *-----------------------------------------------------------------*/ + +static void gain_trans_enc_fx(Word32 gain_trans32, Word16 exc[], Word16 *quant_index, Word16 *quant_sign, Word16 Q_new); + +static void tc_enc_fx(Encoder_State_fx *st_fx, const Word16 i_subfr, Word16 *tc_subfr, Word16 *position, + const Word16 *h1_fx, const Word16 *xn_fx, Word16 *exc_fx, Word16 *yy1_fx, Word16 *T0_min, Word16 *T0_max, + Word16 *T0, Word16 *T0_frac, Word16 *gain_pit_fx, Word16 g_corr_fx[], Word16 *bwe_exc_fx, Word16 Q_new); + + +/*==========================================================================*/ +/* FUNCTION : void transition_enc_fx () */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE :Principal function for adaptive excitation construction in TC*/ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* (Word32) core_brate : core bitrate Q0 */ +/* (Word16) bwidth : input signal bandwidth Q0 */ +/* (Word16) i_subfr : subrame index Q0 */ +/* (Word16*) Jopt_flag : joint optimization flag Q0 */ +/* (Word16*) h1_fx : weighted filter input response Q14 */ +/* (Word16*) xn_fx : target signal Q_new*/ +/* (Word16) Q_new : input scaling */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* (Word16*) y1_fx : zero-memory filtered adaptive excitation Q12*/ +/* (Word16*) xn2_fx : target vector for innovation search Qnew */ +/* (Word16*) gain_pit_fx : pitch gain (0..GAIN_PIT_MAX) Q14*/ +/* (Word16[])g_corr_fx : correlations and -2 */ +/* (Word16**)pt_pitch_fx : floating pitch values Q6 */ +/* (Word16*) bwe_exc_fx : excitation for SWB TBE Q0 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* (Word16*) tc_subfr : TC subframe index Q0 */ +/* (Word16*) position : index of the residual signal maximum Q0 */ +/* (Word16*) T0_min : lower pitch limit Q0 */ +/* (Word16*) T0_max : higher pitch limit Q0 */ +/* (Word16*) T0 : close loop integer pitch Q0 */ +/* (Word16*) T0_frac : close loop fractional part of the pitch Q0*/ +/* (Word16*) exc_fx : pointer to excitation signal frame */ +/* (Word16*) gp_cl_fx : memory of gain of pitch clipping algorithm*/ +/* (Word16*) clip_gain : adaptive gain clipping flag Q0 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ + +void transition_enc_fx( + Encoder_State_fx *st_fx,/* i/o: encoder state structure */ + const Word16 i_subfr, /* i : subframe index */ + Word16 *tc_subfr, /* i/o: TC subframe index */ + Word16 *Jopt_flag, /* i : joint optimization flag */ + Word16 *position, /* i/o: maximum of residual signal index */ + Word16 *T0, /* i/o: close loop integer pitch Q0*/ + Word16 *T0_frac, /* i/o: close loop fractional part of the pitch Q0*/ + Word16 *T0_min, /* i/o: lower limit for close-loop search Q0*/ + Word16 *T0_max, /* i/o: higher limit for close-loop search Q0*/ + Word16 *exc_fx, /* i/o: pointer to excitation signal frame Q_new*/ + Word16 *y1_fx, /* o : zero-memory filtered adaptive excitation Q_new-1+shift*/ + const Word16 *h1_fx, /* i : weighted filter input response Q(14+shift)*/ + const Word16 *xn_fx, /* i : target vector Q_new-1+shift*/ + Word16 *xn2_fx, /* o : target vector for innovation search Q_new-1+shift*/ + Word16 *gp_cl_fx, /* i/o: memory of gain of pitch clipping algorithm */ + Word16 *gain_pit_fx, /* o : adaptive excitation gain Q14*/ + Word16 *g_corr_fx, /* o : ACELP correlation values */ + Word16 *clip_gain, /* i/o: adaptive gain clipping flag */ + Word16 **pt_pitch_fx, /* o : floating pitch values */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE Q_new*/ + Word16* unbits_ACELP, /* i/o: unused bits */ + Word16 Q_new, /* i : Current scaling */ + Word16 shift /* i : downscaling needs for 12 bits convolutions */ + +) +{ + Word16 pit_flag, pit_start, pit_limit, index, nBits; + Word16 tmp, tmp1, i; + Word32 offset; + Word16 shift_wsp; + Word16 limit_flag, mult_Top, lp_select, lp_flag; + Word16 T_op[2]; /* values for two half-frames */ + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + /* set limit_flag to 0 for restrained limits, and 1 for extended limits */ + limit_flag = 0; + move16(); + + pit_start = PIT_MIN; + move16(); + + /*----------------------------------------------------------------* + * convert pitch values to 16kHz domain + *----------------------------------------------------------------*/ + + IF(EQ_16(st_fx->L_frame_fx, L_FRAME) /*|| (tdm_Pri_pitch_buf != NULL && tdm_Pri_pitch_buf[0] < 0)*/) + { + Copy(st_fx->pitch_fx, T_op, 2); + } + ELSE /* L_frame == L_FRAME16k */ + { + /*T_op[0] = (int16_t)(pitch[0] * 1.25f + 0.5f); + T_op[1] = (int16_t)(pitch[1] * 1.25f + 0.5f);*/ + T_op[0] = add(st_fx->pitch_fx[0], mult_r(st_fx->pitch_fx[0], 8192/*0.25f Q15*/)); + T_op[1] = add(st_fx->pitch_fx[1], mult_r(st_fx->pitch_fx[1], 8192/*0.25f Q15*/)); + } + shift_wsp = add(Q_new,shift); + + lp_flag = st_fx->acelp_cfg.ltf_mode; + move16(); + /*-----------------------------------------------------------------* + * TC: subrame determination for glottal shape search + * ------------------------------------------------------- + * tc_subfr == 0 - TC in 1st subframe + * tc_subfr == TC_0_0 - TC in 1st subframe + information about T0 + * tc_subfr == L_SUBFR - TC in 2nd subframe + * tc_subfr == 2*L_SUBFR - TC in 3rd subframe + * tc_subfr == 3*L_SUBFR - TC in 4th subframe + *-----------------------------------------------------------------*/ + + IF( i_subfr == 0 ) + { + mult_Top = 1; + IF( limit_flag == 0 ) + { + test(); + IF( EQ_16(st_fx->L_frame_fx,L_FRAME) && LT_16(T_op[1],PIT_MIN) ) + { + mult_Top = 2; + move16(); + } + test(); + if( EQ_16(st_fx->L_frame_fx,L_FRAME16k) && LT_16(T_op[1],PIT16k_MIN)) + { + mult_Top = 2; + move16(); + } + } + + limit_T0_fx( st_fx->L_frame_fx, 8, 0, limit_flag, mult_Top*T_op[1], 0, T0_min, T0_max ); + + } + /*-----------------------------------------------------------------* + * zero adaptive excitation signal construction + *-----------------------------------------------------------------*/ + IF ( GT_16(*tc_subfr,i_subfr)) + { + *gain_pit_fx = 0; + move16(); + *clip_gain = 0; + move16(); + g_corr_fx[0] = 16384; + move16(); + g_corr_fx[1] = add(shl(sub(shift_wsp,1),1),1); + move16(); + g_corr_fx[2] = -16384; + move16(); + g_corr_fx[3] = shl(sub(shift_wsp,1),1); + + set16_fx(&exc_fx[i_subfr], 0, L_SUBFR); /* set excitation for current subrame to 0 */ + + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + set16_fx(&bwe_exc_fx[i_subfr*HIBND_ACB_L_FAC], 0, (Word16)(L_SUBFR*HIBND_ACB_L_FAC)); /* set past excitation buffer to 0 */ + } + ELSE + { + set16_fx(&bwe_exc_fx[i_subfr*2], 0, L_SUBFR*2); /* set past excitation buffer to 0 */ + } + + set16_fx(y1_fx, 0, L_SUBFR); /* set filtered adaptive excitation to 0 */ + Copy(xn_fx, xn2_fx, L_SUBFR); /* target vector for codebook search */ + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + + **pt_pitch_fx = shl(add(shl(*T0,2),*T0_frac),4); + move16(); /* save subframe pitch values Q6 */ + + } + + /*-----------------------------------------------------------------* + * glottal codebook contribution construction + *-----------------------------------------------------------------*/ + ELSE IF ( EQ_16(*tc_subfr,i_subfr)) + { + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + set16_fx( bwe_exc_fx-PIT_MAX*HIBND_ACB_L_FAC, 0, PIT_MAX*HIBND_ACB_L_FAC); /* set past excitation buffer to 0 */ + } + ELSE + { + set16_fx( bwe_exc_fx-PIT16k_MAX*2, 0, PIT16k_MAX*2); /* set past excitation buffer to 0 */ + } + + tc_enc_fx( st_fx, i_subfr, tc_subfr, position, h1_fx, xn_fx, exc_fx, + y1_fx, T0_min, T0_max, T0, T0_frac, gain_pit_fx, g_corr_fx, bwe_exc_fx,Q_new); + + IF (EQ_16(*tc_subfr, TC_0_0) ) + { + /* this is called only to compute unused bits */ + 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, + L_FRAME, -1, &(st_fx->acelp_cfg), hBstr->nb_bits_tot_fx, TRANSITION, TC_0_0, 3, NULL, unbits_ACELP, + 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*/, st_fx->tdm_LRTD_flag, 0 /*GSC_IVAS_mode*/ + ); + } + *clip_gain = gp_clip_fx(st_fx->element_mode, st_fx->core_brate_fx, st_fx->voicing_fx, i_subfr, TRANSITION, xn_fx, gp_cl_fx, sub(shift_wsp,1) ); + updt_tar_fx( xn_fx, xn2_fx, y1_fx, *gain_pit_fx, L_SUBFR ); + + **pt_pitch_fx = shl(add(shl(*T0,2),*T0_frac),4); + move16(); + *Jopt_flag = 1; + move16(); + } + + /*--------------------------------------------------------------* + * other subframes -> GENERIC encoding type, + * standard adaptive excitation contribution + * - exemption only in case when first glottal impulse is + * in the 1st subframe and the second one in 2nd subframe + * and later + *--------------------------------------------------------------*/ + ELSE IF ( LT_16(*tc_subfr,i_subfr)) + { + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + *Jopt_flag = 1; + move16(); + /* pit_flag for T0 bits number coding determination */ + test(); + IF( (EQ_16(sub(i_subfr,*tc_subfr),L_SUBFR))||(EQ_16(sub(i_subfr,*tc_subfr),L_SUBFR-TC_0_0))) + { + pit_flag = 0; + move16(); + } + ELSE + { + pit_flag = L_SUBFR; + move16(); + } + + IF( EQ_16(*tc_subfr,TC_0_0)) + { + IF( EQ_16(i_subfr,L_SUBFR)) + { + limit_T0_fx( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); + } + pit_flag = 1; + move16(); + } + + /*----------------------------------------------------------* + * if tc_subfr==0, change tc_subfr corresponding to the + * second glot. impulse position + *----------------------------------------------------------*/ + test(); + IF( (*tc_subfr == 0) && (EQ_16(i_subfr,L_SUBFR))) + { + IF( GT_16(PIT_MIN,(*position))) + { + pit_start = sub(L_SUBFR, (*position)); + } + ELSE + { + pit_start = PIT_MIN; + move16(); + } + pit_start = s_max(pit_start, PIT_MIN); + + pit_limit = add(shl(pit_start,1), *position); + + /* Find the closed loop pitch period */ + + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, pit_flag, limit_flag, pit_start, pit_limit, L_FRAME, L_SUBFR ); + + offset = tbe_celp_exc_offset(*T0, *T0_frac, st_fx->L_frame_fx); + + + FOR (i=0; itotal_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, TRANSITION, *tc_subfr, 2, NULL, + unbits_ACELP, 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*/, st_fx->tdm_LRTD_flag, 0 /*GSC_IVAS_mode*/); + } + /*-----------------------------------------------------------------* + * get number of bits for pitch encoding + *-----------------------------------------------------------------*/ + + nBits = st_fx->acelp_cfg.pitch_bits[shr(i_subfr, 6)]; + move16(); + + /*-----------------------------------------------------------------* + * Find adaptive part of excitation, encode pitch period + *-----------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + test(); + test(); + /* first glottal impulse is in the 1st subrame */ + IF( (EQ_16(i_subfr,L_SUBFR))&&(GE_16(*tc_subfr,TC_0_128))) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 3rd or 4th subframe + * - build exc[] in 2nd subframe + *--------------------------------------------------------*/ + *T0 = 2*L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + *Jopt_flag = 0; + move16(); + set16_fx( &exc_fx[i_subfr], 0, (Word16)(L_SUBFR+1) ); + set16_fx( &bwe_exc_fx[i_subfr*HIBND_ACB_L_FAC], 0, (Word16)(L_SUBFR*HIBND_ACB_L_FAC) ); + + } + ELSE IF( (EQ_16(i_subfr,L_SUBFR))&&(EQ_16(*tc_subfr,TC_0_64))) + { + /*--------------------------------------------------------* + * second glottal impulse is in the 2nd subframe, + * - build exc[] in 2nd subframe + + *--------------------------------------------------------*/ + IF( LT_16(add(*T0,*position), L_SUBFR )) + { + /* impulse must be in the 2nd subframe (not in 1st) */ + *T0 = sub(L_SUBFR, (*position)); + move16(); + *T0_frac = 0; + move16(); + } + IF( GE_16(add(*T0,*position),2*L_SUBFR)) + { + /* impulse must be in the 2nd subframe (not in 3rd) */ + *T0 = sub(2*L_SUBFR-1,(*position)); + move16(); + *T0_frac = 2; + move16(); + } + + limit_T0_fx( L_FRAME, 8, pit_flag, limit_flag, *T0, 0, T0_min, T0_max ); /* find T0_min and T0_max for delta search */ + + /* 7bit ENCODER */ + /* index = (*T0-pit_start)*2 + *T0_frac/2;*/ + index = add(shl(sub(*T0,pit_start),1), shr(*T0_frac,1)); + push_indice_fx( hBstr, IND_PITCH, index, nBits ); + + /* Find the adaptive codebook vector - ACELP long-term prediction */ + pred_lt4(&exc_fx[i_subfr], &exc_fx[i_subfr], *T0, *T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + + + offset = tbe_celp_exc_offset(*T0, *T0_frac, st_fx->L_frame_fx); + + FOR (i=0; iL_frame_fx); + + + FOR (i=0; iL_frame_fx); + + FOR (i=0; iL_frame_fx); + + + FOR (i=0; iL_frame_fx); + + FOR (i=0; ielement_mode, st_fx->core_brate_fx, st_fx->voicing_fx, i_subfr, TRANSITION, xn_fx, gp_cl_fx, (Q_new+shift-1) ); + + lp_select = lp_filt_exc_enc_fx( MODE1, TRANSITION, i_subfr, exc_fx, h1_fx, + xn_fx, y1_fx, xn2_fx, L_SUBFR, st_fx->L_frame_fx, g_corr_fx, *clip_gain, gain_pit_fx, &lp_flag ); + + IF( EQ_16(lp_flag,NORMAL_OPERATION)) + { + push_indice_fx( hBstr, IND_LP_FILT_SELECT, lp_select, 1 ); + } + } + + **pt_pitch_fx = shl(add(shl(*T0,2),*T0_frac),4); + move16(); + /*---------------------------------------------------------------------* + * fill the pitch buffer - needed for post-processing + *---------------------------------------------------------------------*/ + test(); + test(); + test(); + test(); + test(); + IF( (*tc_subfr >= 2*L_SUBFR) && (i_subfr == 3*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 3; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + } + ELSE IF( (*tc_subfr == L_SUBFR) && (i_subfr == 2*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 2; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + ELSE IF( (*tc_subfr == TC_0_64) && (i_subfr == L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 1; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + ELSE IF( (*tc_subfr == TC_0_128) && (i_subfr == 2*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 2; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + ELSE IF( (*tc_subfr == TC_0_192) && (i_subfr == 3*L_SUBFR) ) + { + tmp = shl(add(shl(*T0,2),*T0_frac),4); + (*pt_pitch_fx) -= 3; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + **pt_pitch_fx = tmp; + move16(); + (*pt_pitch_fx)++; + move16(); + } + } + ELSE /* L_frame == L_FRAME16k */ + { + if( GE_16(i_subfr,2*L_SUBFR)) + { + limit_flag = 1; + move16(); + } + IF( LE_16(i_subfr,2*L_SUBFR)) + { + IF( LT_16(i_subfr,2*L_SUBFR)) + { + mult_Top = 1; + move16(); + if( LT_16(T_op[0],PIT16k_MIN)) + { + mult_Top = 2; + move16(); + } + + limit_T0_fx( L_FRAME16k, 8, 0, limit_flag, mult_Top*T_op[0], 0, T0_min, T0_max ); /* TC0 second subfr. */ + + } + ELSE + { + limit_T0_fx( L_FRAME16k, 8, 0, limit_flag, T_op[1], 0, T0_min, T0_max ); /* TC0 third subfr., or TC64 third subfr. */ + } + } + + /*-----------------------------------------------------------------* + * get number of bits for pitch encoding + *-----------------------------------------------------------------*/ + + nBits = st_fx->acelp_cfg.pitch_bits[shr(i_subfr, 6)]; + move16(); + + /*-----------------------------------------------------------------* + * Find adaptive part of excitation, encode pitch period + *-----------------------------------------------------------------*/ + + IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, limit_flag, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, st_fx->L_frame_fx, L_SUBFR ); + pit16k_Q_enc_fx( hBstr, nBits, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE IF( EQ_16(nBits,8)) /* tc_subfr==0 && i_subfr==L_SUBFR */ + { + /*-----------------------------------------------------------------------------* + * The pitch range is encoded absolutely with 8 bits and is divided as follows: + * PIT16k_MIN to PIT16k_FR2_TC0_2SUBFR-1 resolution 1/4 (frac = 0,1,2 or 3) + * PIT16k_FR2_TC0_2SUBFR to 2*L_SUBFR resolution 1/2 (frac = 0 or 2) + *-----------------------------------------------------------------------------*/ + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, limit_flag, PIT16k_FR2_TC0_2SUBFR, 2*L_SUBFR, st_fx->L_frame_fx, L_SUBFR ); + + IF( GT_16(*T0_max,2*L_SUBFR)) + { + *T0 = 2*L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + } + + IF( LT_16(*T0,PIT16k_FR2_TC0_2SUBFR )) + { + /*index = (*T0)*4 + (*T0_frac) - (PIT16k_MIN*4);*/ + index = add(shl(*T0,2), sub(*T0_frac, PIT16k_MIN*4)); + } + ELSE + { + /*index = (*T0)*2 + ((*T0_frac)>>1) - (PIT16k_FR2_TC0_2SUBFR*2) + ((PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4);*/ + index = add(sub(add(shl(*T0,1), shr(*T0_frac,1)), (PIT16k_FR2_TC0_2SUBFR*2)), (PIT16k_FR2_TC0_2SUBFR-PIT16k_MIN)*4); + } + push_indice_fx( hBstr, IND_PITCH, index, nBits ); + } + ELSE IF( EQ_16(nBits,6)) + { + /* delta search */ + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, L_SUBFR, limit_flag, PIT16k_FR2_EXTEND_9b, PIT16k_FR1_EXTEND_9b, st_fx->L_frame_fx, L_SUBFR ); + + index = delta_pit_enc_fx( 4, *T0, *T0_frac, *T0_min ); + push_indice_fx( hBstr, IND_PITCH, index, nBits ); + } + IF( EQ_16(nBits,6)) + { + limit_T0_fx( L_FRAME16k, 8, L_SUBFR, limit_flag, *T0, *T0_frac, T0_min, T0_max ); + } + + /*-----------------------------------------------------------------* + * - gain clipping test to avoid unstable synthesis + * - LP filtering of the adaptive excitation + * - codebook target computation + *-----------------------------------------------------------------*/ + test(); + IF( (EQ_16(i_subfr,L_SUBFR))&&(EQ_16(*T0,2*L_SUBFR))) + { + *gain_pit_fx = 0; + move16(); + *clip_gain = 0; + move16(); + g_corr_fx[0] = 0; + move16(); + g_corr_fx[1] = 0; + move16(); + *Jopt_flag = 0; + move16(); + + set16_fx( &exc_fx[i_subfr], 0, L_SUBFR+1 ); /* set excitation for current subrame to 0 */ + push_indice_fx( hBstr, IND_LP_FILT_SELECT, 0, 1 ); /* this bit is actually not needed */ + + Copy( xn_fx, xn2_fx, L_SUBFR ); /* target vector for codebook search */ + set16_fx( y1_fx, 0, L_SUBFR ); /* set filtered adaptive excitation to 0 */ + set16_fx( &bwe_exc_fx[i_subfr * 2], 0, L_SUBFR * 2 ); + } + ELSE + { + /* Find the adaptive codebook vector - ACELP long-term prediction */ + pred_lt4(&exc_fx[i_subfr], &exc_fx[i_subfr], *T0, *T0_frac, L_SUBFR+1, pitch_inter4_2, L_INTERPOL2, PIT_UP_SAMP); + offset = L_deposit_l(0); + + tmp = extract_l(L_mult(*T0_frac,32));/*Q8, 0.25 in Q7*/ + tmp = add(512,tmp);/*Q8; 2 in Q8*/ + tmp = mult_r(tmp,256);/*Q16->Q0; 2 in Q7*/ + + tmp1 = sub(*T0,2);/*Q0*/ + tmp1 = shl(tmp1,1);/*Q0 */ + + offset = add(tmp,tmp1);/*Q0*/ + FOR (i=0; ielement_mode, st_fx->core_brate_fx, st_fx->voicing_fx, i_subfr, TRANSITION, xn_fx, gp_cl_fx,Q_new ); + + lp_select = lp_filt_exc_enc_fx( MODE1, TRANSITION, i_subfr, exc_fx, h1_fx, + xn_fx, y1_fx, xn2_fx, L_SUBFR, st_fx->L_frame_fx, g_corr_fx, *clip_gain, gain_pit_fx, &lp_flag ); + + IF( EQ_16(lp_flag,NORMAL_OPERATION)) + { + push_indice_fx( hBstr, IND_LP_FILT_SELECT, lp_select, 1 ); + } + + *Jopt_flag = 1; + move16(); + } + + /***pt_pitch = (float)(*T0) + (float)(*T0_frac)/4.0f;*/ /* save subframe pitch value */ + /***pt_pitch_fx = shl(add(*T0,shr(*T0_frac,2)),4); move16();*/ + tmp = shl(add(shl(*T0,2),*T0_frac),4); + **pt_pitch_fx = tmp; + move16(); + + /*---------------------------------------------------------------------* + * fill the pitch buffer - needed for post-processing + *---------------------------------------------------------------------*/ + test(); + test(); + IF( (EQ_16(sub(i_subfr, *tc_subfr),L_SUBFR))||(*tc_subfr==0&&EQ_16(i_subfr,2*L_SUBFR))) + { + index = shr(i_subfr,6); + (*pt_pitch_fx) -= index; + move16(); + + FOR( i=0; i|| | imp_shape->| g1 | | + * | | | | g2 | ---- exc |---| y1 ---- | + * | | |-------------| |----|gain|-------| h |------|gain|----(-)---> xn2 + * | || | gn | ---- |---| ---- + * |----| |----| + * codebook excitation gain_trans h_orig gain_pit + * + *-------------------------------------------------------------------------------------------*/ + +static void tc_enc_fx( + Encoder_State_fx *st_fx,/* i/o: encoder state structure */ + const Word16 i_subfr, /* i : subrame index */ + Word16 *tc_subfr, /* i/o: TC subframe index */ + Word16 *position, /* i/o: index of the residual signal maximum */ + const Word16 *h1_fx, /* i : weighted filter input response Q(14+shift)*/ + const Word16 *xn_fx, /* i : target signal Q_new-1+shift*/ + Word16 *exc_fx, /* o : glottal codebook contribution Q_new*/ + Word16 *yy1_fx, /* o : filtered glottal codebook contribution */ + Word16 *T0_min, /* o : lower pitch limit Q0*/ + Word16 *T0_max, /* o : higher pitch limit Q0*/ + Word16 *T0, /* o : close loop integer pitch Q0*/ + Word16 *T0_frac, /* o : close loop fractional part of the pitch Q0*/ + Word16 *gain_pit_fx, /* o : pitch gain (0..GAIN_PIT_MAX) Q14*/ + Word16 g_corr_fx[], /* o : correlations and -2 */ + Word16 *bwe_exc_fx, /* i/o: excitation for SWB TBE Q_new*/ + Word16 Q_new /* i : input scaling */ +) +{ + Word16 i,imp_shape, imp_pos, index, nBits, h1_tmp_fx[L_SUBFR]; + Word16 pitch_index,pitch_sign_fx; + Word32 gain_trans32; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + imp_pos = sub(*position, i_subfr); + FOR (i = 0; i < L_SUBFR; i++) + { + h1_tmp_fx[i] = h1_fx[i]; + move16(); + } + /*-----------------------------------------------------------------* + * get number of bits for pitch encoding + *-----------------------------------------------------------------*/ + + nBits = st_fx->acelp_cfg.pitch_bits[shr(i_subfr, 6)]; + + /*--------------------------------------------------------------* + * Closed loop pitch search + *--------------------------------------------------------------*/ + + *T0_frac = 0; + move16(); + + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + test(); + IF( (LE_16(*T0_min,L_SUBFR))||(EQ_16(*tc_subfr,3*L_SUBFR))) + { + IF( EQ_16(nBits,9)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT_FR2_9b, PIT_FR1_9b, L_FRAME, L_SUBFR ); + } + ELSE IF( EQ_16(nBits,6)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT_MIN, L_SUBFR, L_FRAME, L_SUBFR ); + } + ELSE + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT_MAX, PIT_MIN, L_FRAME, L_SUBFR ); + } + } + ELSE + { + *T0 = L_SUBFR; + move16(); + } + test(); + if( EQ_16(*tc_subfr,L_SUBFR)&<_16(*T0,L_SUBFR)) + { + *T0 = L_SUBFR; + move16(); + } + } + ELSE /* st_fx->L_frame_fx == L_FRAME16k */ + { + IF( EQ_16(nBits,10)) + { + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 1, PIT16k_FR2_EXTEND_10b, PIT16k_MAX, L_FRAME16k, L_SUBFR ); + } + ELSE IF( EQ_16(nBits,6)) + { + /* T0_frac with 1/2 sample resolution */ + *T0 = pitch_fr4_fx( &exc_fx[i_subfr], xn_fx, h1_fx, *T0_min, *T0_max, T0_frac, 0, 0, PIT16k_MIN, L_SUBFR, L_FRAME16k, L_SUBFR ); + IF( *T0 > L_SUBFR ) + { + *T0 = L_SUBFR; + move16(); + *T0_frac = 0; + move16(); + } + } + } + + + /* set tc_subfr to TC_0_0 */ + test(); + test(); + test(); + if( i_subfr == 0 && EQ_16(st_fx->L_frame_fx,L_FRAME)&&(LT_16(*T0,L_SUBFR)||EQ_16(*tc_subfr,3*L_SUBFR))) + { + *tc_subfr = TC_0_0; + move16(); + } + + /*--------------------------------------------------------------* + * Builds glottal codebook contribution + *--------------------------------------------------------------*/ + + set_impulse_fx(xn_fx, h1_tmp_fx, &exc_fx[i_subfr], yy1_fx, &imp_shape, &imp_pos, &gain_trans32, Q_new);/*chk h1_tmp_fx*/ + + /*--------------------------------------------------------------* + * quantize gain_trans and scale glottal codebook contribution + *--------------------------------------------------------------*/ + + gain_trans_enc_fx( gain_trans32, &exc_fx[i_subfr], &pitch_index, &pitch_sign_fx, Q_new ); + + /* set past excitation buffer to zeros */ + set16_fx( exc_fx-L_EXC_MEM, 0, L_EXC_MEM ); + /*--------------------------------------------------------------* + * adapt. search of the second impulse in the same subframe + * (when appears) + *--------------------------------------------------------------*/ + + pred_lt4_tc_fx( exc_fx, *T0, *T0_frac, inter4_2_fx, imp_pos, i_subfr ); + IF (st_fx->hBWE_TD != NULL) + { + IF(EQ_16(st_fx->L_frame_fx, L_FRAME)) + { + interp_code_5over2_fx(&exc_fx[i_subfr], &bwe_exc_fx[i_subfr * HIBND_ACB_L_FAC], L_SUBFR); + } + ELSE + { + interp_code_4over2_fx(&exc_fx[i_subfr], &bwe_exc_fx[i_subfr * 2], L_SUBFR); + } + } + /*--------------------------------------------------------------* + * compute glottal-shape codebook excitation + *--------------------------------------------------------------*/ + + /* create filtered glottal codebook contribution */ + conv_fx( &exc_fx[i_subfr], h1_fx, yy1_fx, L_SUBFR ); + + /* gain_pit computation */ +#ifdef BASOP_NOGLOB + *gain_pit_fx = corr_xy1_fx( xn_fx, yy1_fx, g_corr_fx, L_SUBFR, 0, &Overflow ); +#else + *gain_pit_fx = corr_xy1_fx( xn_fx, yy1_fx, g_corr_fx, L_SUBFR, 0 ); +#endif + /*--------------------------------------------------------------* + * Encode parameters and write indices + *--------------------------------------------------------------*/ + IF( EQ_16(st_fx->L_frame_fx,L_FRAME)) + { + test(); + test(); + IF( ( (i_subfr != 0) || (EQ_16(*tc_subfr,TC_0_0))) + && (NE_16(*tc_subfr,L_SUBFR) )) + { + test(); + /* write pitch index */ + IF( (GE_16(*T0,L_SUBFR))&&(NE_16(*tc_subfr,3*L_SUBFR))) + { + push_indice_fx( hBstr, IND_PITCH, 0, nBits ); + } + ELSE IF( EQ_16(*tc_subfr,3*L_SUBFR)) + { + IF( EQ_16(nBits,9)) + { + index = abs_pit_enc_fx( 4, 0, *T0, *T0_frac ); + } + ELSE + { + index = abs_pit_enc_fx( 2, 0, *T0, *T0_frac ); + } + push_indice_fx( hBstr, IND_PITCH, index, nBits ); + + limit_T0_fx( L_FRAME, 8, 0, 0, *T0, 0, T0_min, T0_max ); + } + ELSE + { + IF( EQ_16(nBits,6)) + { + index = delta_pit_enc_fx( 2, *T0, *T0_frac, PIT_MIN-1 ); + push_indice_fx( hBstr, IND_PITCH, index, nBits ); + } + ELSE + { + index = delta_pit_enc_fx( 0, *T0, *T0_frac, PIT_MIN-1 ); + push_indice_fx( hBstr, IND_PITCH, index, nBits ); + } + } + } + } + ELSE /* st_fx->L_frame_fx == L_FRAME16k */ + { + IF( EQ_16(nBits,10)) + { + pit16k_Q_enc_fx( hBstr, nBits, 1, *T0, *T0_frac, T0_min, T0_max ); + } + ELSE IF( EQ_16(nBits,6)) + { + index = add(shl(sub(*T0,PIT16k_MIN),1) , shr(*T0_frac,1)); + push_indice_fx( hBstr, IND_PITCH, index, nBits ); + } + } + push_indice_fx( hBstr, IND_TC_IMP_SHAPE, imp_shape, 3 ); + push_indice_fx( hBstr, IND_TC_IMP_POS, imp_pos, 6 ); + push_indice_fx( hBstr, IND_TC_IMP_SIGN, pitch_sign_fx, 1 ); + push_indice_fx( hBstr, IND_TC_IMP_GAIN, pitch_index, 3 ); + + *position = add(imp_pos, i_subfr); + move16(); + return; +} + + +/*-----------------------------------------------------------------* + * gain_trans_enc() + * + * Quantize gain_trans of TC (gains of glottal impulses). + * - Uses scalar quantization prototypes tbl_gain_trans_tc[N_GAIN_TC]. + * - Gains the glottal codebook contibution signal. + *-----------------------------------------------------------------*/ +static void gain_trans_enc_fx( + Word32 gain_trans32, /* i : gain for mode Tc Q7 */ + Word16 exc[], /* i/o: glottal codebook contribution i:Q13 o:Q_new*gain_trans */ + Word16 *quant_index, /* o : index of quantized gain_trans */ + Word16 *quant_sign, /* o : sign of quantized gain_trans */ + Word16 Q_new /* i : curent scaling */ +) +{ + Word16 i, imax, istart, tmp16, gain_trans, gscale; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + istart = 0; + move16(); + imax = 4; + move16(); + gscale = 7; + move16(); +#ifdef BASOP_NOGLOB + gain_trans = extract_h(L_shl_o(gain_trans32,16, &Overflow)); /* Q7 */ +#else /* BASOP_NOGLOB */ + gain_trans = extract_h(L_shl(gain_trans32,16)); /* Q7 */ +#endif /* BASOP_NOGLOB */ + + IF (GT_32(L_abs(gain_trans32), 29862L)) + { +#ifdef BASOP_NOGLOB + gain_trans = extract_h(L_shl_o(gain_trans32,16-3, &Overflow)); /* Q4 */ +#else /* BASOP_NOGLOB */ + gain_trans = extract_h(L_shl(gain_trans32,16-3)); /* Q4 */ +#endif /* BASOP_NOGLOB */ + istart = 4; + move16(); + imax = N_GAIN_TC-1; + move16(); + gscale = 4; + move16(); + } + + /* qsign = 0 if *gain_trans < 0 else qsign = 1*/ + tmp16 = shr(gain_trans,16); + *quant_sign = add(1, tmp16); + move16();/* quantize sign */ + tmp16 = s_or(tmp16, 1); /* Keep sign */ + gain_trans = abs_s(gain_trans); + + *quant_index = N_GAIN_TC-1; + move16(); + FOR (i = istart; i < imax; i++) + { + IF (LE_16(gain_trans,tbl_gain_trans_tc_fx[i])) + { + *quant_index = i; + move16(); + BREAK; + } + } + + gain_trans = i_mult2(tbl_gain_trans_tc_fx[i], tmp16); /* Retreive quantized gain with sign */ + tmp16 = sub(Q_new,add(gscale,13-16+1)); /*remove 16 from rounding */ + FOR (i = 0; i < L_SUBFR; i++) + { + /*exc[i] *= (*gain_trans);*/ +#ifdef BASOP_NOGLOB + exc[i] = round_fx_o(L_shl_o(L_mult(exc[i], gain_trans),tmp16, &Overflow), &Overflow); +#else + exc[i] = round_fx(L_shl(L_mult(exc[i], gain_trans),tmp16)); +#endif + } +} + + +/*-----------------------------------------------------------------* + * tc_classif_enc_fx() + * + * TC subframe determination + *-----------------------------------------------------------------*/ +void tc_classif_enc_fx( + const Word16 Q_new, /* i : scaling factor */ + const Word16 L_frame, /* i : length of the frame */ + Word16* tc_subfr, /* o : TC subframe index */ + Word16* position, /* o : maximum of residual signal index */ + const Word16 attack_flag, /* i : attack flag */ + const Word16 pitch, /* i : open loop pitch estimates for first halfframe */ + const Word16* res /* i : pointer to the LP residual signal frame */ +) +{ + Word32 temp; + Word16 T_op, i; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + T_op = pitch; + move16(); + + IF ( EQ_16(L_frame, L_FRAME16k) ) + { + /*T_op = (int16_t)(pitch * 1.25f + 0.5f);*/ + T_op = add(pitch, mult_r(pitch, 8192)); + } + + *tc_subfr = -1; + move16(); + IF (attack_flag) + { + *tc_subfr = 3 * L_SUBFR; + move16(); + IF (attack_flag > 0) + { + IF (EQ_16(L_frame, L_FRAME)) + { + /* *tc_subfr = NB_SUBFR * (attack_flag - 1) / 32 ; ATT_NSEG == 32*/ + *tc_subfr = mult(i_mult(NB_SUBFR, sub(attack_flag, 1)), 1024) ; /* divide by 32 Q15*/ + move16(); + } + ELSE + { + /* *tc_subfr = NB_SUBFR16k * (attack_flag - 1) / 32 ; */ + *tc_subfr = mult(i_mult(NB_SUBFR16k, sub(attack_flag, 1)), 1024); /* divide by 32 Q15*/ + move16(); + } + /* *tc_subfr *= L_SUBFR; */ + *tc_subfr = i_mult(*tc_subfr, L_SUBFR); + move16(); + } + } + + IF (attack_flag) + { + /*-----------------------------------------------------------------* + * TC: subrame determination for glottal shape search + * ------------------------------------------------------- + * tc_subfr == 0 - TC in 1st subframe + * tc_subfr == TC_0_0 - TC in 1st subframe + information about T0 + * tc_subfr == L_SUBFR - TC in 2nd subframe + * tc_subfr == 2*L_SUBFR - TC in 3rd subframe + * tc_subfr == 3*L_SUBFR - TC in 4th subframe + *-----------------------------------------------------------------*/ + + /** position = emaximum(res + *tc_subfr, min(T_op + 2, L_SUBFR), &temp) + *tc_subfr;*/ + *position = add(emaximum_fx(Q_new, res + *tc_subfr, s_min(add(T_op, 2), L_SUBFR), &temp), *tc_subfr); + move16(); + } + ELSE + { + *position = emaximum_fx(Q_new, res, add(T_op,2), &temp); + + /* correction in case of possibly wrong T_op (double-pitch values) */ + test(); + test(); + test(); + IF((EQ_16(L_frame,L_FRAME) && GT_16(T_op,2 * PIT_MIN)) || (EQ_16(L_frame,L_FRAME16k) && GT_16(T_op,2 * PIT16k_MIN)) ) + { + Word16 position_tmp, len, exp_aver = 0, exp = 0, exp2 = 0; + Word32 aver, temp2, L_sum, L_temp1, L_temp2; + + len = add(shr(T_op,1), 2); + position_tmp = emaximum_fx(Q_new, res, len, &temp2); + + L_sum = L_mac(1L, res[0], res[0]); + FOR(i = 1; i < len; i++) + { +#ifdef BASOP_NOGLOB + L_sum = L_mac0_o(L_sum, res[i], res[i], &Overflow); +#else /* BASOP_NOGLOB */ + L_sum = L_mac0(L_sum, res[i], res[i]); +#endif /* BASOP_NOGLOB */ + } + aver = L_sum; /*Q = 2*Q_new */ + aver = root_a_over_b_fx(aver, 2 * Q_new, L_shl(len,15), 15, &exp_aver); /*Q = 31-exp_aver*/ + + temp = root_a_fx(temp, 0, &exp); /* Q=31-exp */ + temp2 = root_a_fx(temp2, 0, &exp2); /* Q=31-exp2 */ + + L_temp2 = Mult_32_16(temp, 26214); /* Q=31-exp */ + L_temp1 = Mult_32_16(temp, 8192); /* Q=31-exp */ + + test(); +#ifdef BASOP_NOGLOB + IF(GT_32(temp2, L_shl_o(L_temp2,(31 - exp2) - (31 - exp), &Overflow)) && + LT_32(aver, L_shl_o(L_temp1,(31 - exp_aver) - (31 - exp), &Overflow))) +#else /* BASOP_NOGLOB */ + IF(GT_32(temp2, L_shl(L_temp2,(31 - exp2) - (31 - exp))) && + LT_32(aver, L_shl(L_temp1,(31 - exp_aver) - (31 - exp)))) +#endif + { + *position = position_tmp; + } + } + *tc_subfr = s_and(*position, 0x7FC0); + move16(); + } + + return; +} diff --git a/lib_enc/update_decision_fx.c b/lib_enc/update_decision_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..77f4619c145b54775ef3e57c8be79e0aa84fbb8e --- /dev/null +++ b/lib_enc/update_decision_fx.c @@ -0,0 +1,480 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + + +#include +#include "options.h" +#include "basop_util.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 */ +/*-------------------------------------------------------------------* + * bg_music_decision_fx() + * + * + * -------------------------------------------------------------------*/ + void bg_music_decision_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + Word16 *music_backgound_f, /* i : background music flag*/ + Word32 frame_energy, /* i : current frame energy 1*/ + Word16 frame_energy_Q /* i : the Scaling of current frame energy*/ +) +{ + + Word16 *f_tonality_rate = hVAD_CLDFB->f_tonality_rate; + Word16 *ltd_stable_rate = hVAD_CLDFB->ltd_stable_rate; + Word16 *sp_center = hVAD_CLDFB->sp_center; + Word16 *sSFM = hVAD_CLDFB->sfm; + Word16 cmp_result; + Word32 music_background_frame; + Word32 tmp1; + Word16 tmp1_Q; + Word16 tmp_norm; + Word32 frame_energy_Mcount; + Word16 fg_energy_Qtmp; + + + music_background_frame = 0; + move32(); + tmp1 = L_mult(hVAD_CLDFB->fg_energy_count,18842); + tmp1_Q = norm_l(tmp1); + tmp1 = L_shl(tmp1,tmp1_Q); + tmp_norm = extract_h(tmp1); + frame_energy_Mcount = MUL_F(frame_energy,tmp_norm); + + fg_energy_Qtmp = sub(frame_energy_Q, 18); + fg_energy_Qtmp = add(fg_energy_Qtmp, tmp1_Q); + + cmp_result = VAD_L_CMP(frame_energy_Mcount,fg_energy_Qtmp,hVAD_CLDFB->fg_energy,hVAD_CLDFB->fg_energy_scale); + + test(); + IF((GT_16(f_tonality_rate[1],9830/* 0.6 Q14 */)) + ||(GT_16(f_tonality_rate[0],14089/* 0.86 Q14 */))) + { + + test(); + test(); + test(); + test(); + if((LT_16(ltd_stable_rate[0], 2359/* 0.072 Q15 */)) + &&(GT_16(sp_center[0],1228/* 1.2 Q10 */)) + &&((LT_16(sSFM[0],24903/* 0.76 Q15 */)) + ||(LT_16(sSFM[1],28835/* 0.88 Q15 */)) + ||(LT_16(sSFM[2],31456/* 0.96 Q15 */)))) + { + music_background_frame = 1; + move32(); + } + } + + test(); + test(); + IF(music_background_frame + &&(cmp_result > 0) + &&(EQ_32(hVAD_CLDFB->fg_energy_est_start,1))) + { + hVAD_CLDFB->music_background_rate = add(mult(hVAD_CLDFB->music_background_rate,31949), 819); + move16(); + } + ELSE IF(music_background_frame) + { + hVAD_CLDFB->music_background_rate = add(mult(hVAD_CLDFB->music_background_rate,32702), 66); + move16(); + } + ELSE + { + hVAD_CLDFB->music_background_rate = mult(hVAD_CLDFB->music_background_rate,32670); + move16(); + } + + *music_backgound_f = 0; + move16(); + if(GT_16(hVAD_CLDFB->music_background_rate, 16384)) + { + *music_backgound_f = 1; + move16(); + } + +} + /*-------------------------------------------------------------------* + * update_decision_fx() + * + * + *-------------------------------------------------------------------*/ + +Word16 update_decision_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB ,/* i/o: CLDFB VAD state */ + const Word32 frame_energy, /* i : current frame energy*/ + Word32 HB_Power, /* i : current frame high frequency energy*/ + const Word16 frameloop, /* i : amount of frames*/ + const Word16 bw, /* i : band width index*/ + const Word16 frame_energy_Q, /* i : the Scaling of current frame energy*/ + const Word16 HB_Power_Q, /* i : the Scaling of current frame high frequency energy*/ + const Word32 snr, /* i : frequency domain SNR */ + const Word32 tsnr, /* i : time domain SNR */ + const Word16 vad_flag, /* i : VAD flag */ + const Word16 music_backgound_f /* i : background music flag*/ +) +{ + Word16 *sp_center = hVAD_CLDFB->sp_center; + Word16 *ltd_stable_rate = hVAD_CLDFB->ltd_stable_rate; + Word16 *sSFM = hVAD_CLDFB->sfm; + Word16 *f_tonality_rate = hVAD_CLDFB->f_tonality_rate; + + Word16 update_flag; + Word16 tonality_flag; + Word32 tmp1; + Word16 tmp1_Q; + Word16 tmp_norm; + Word32 frame_energy_Mcount; + Word32 lt_bg_highf_eng_trbl; + Word16 flag_high_eng; + Word16 fg_energy_Qtmp; + Word16 cmp_result; + Word16 tmpout; + Word16 sp_center3_diff; + + Word16 Q_counter; + Word16 Q_sum; + Word32 sum_num,counter_den; + Word16 div_r; + + Word16 div_r_Q; + Word32 div_r_32; + + + update_flag = 1; + move16(); + tonality_flag = 0; + move16(); + + lt_bg_highf_eng_trbl = MUL_F(hVAD_CLDFB->lt_bg_highf_eng,24576); + IF (GT_16(14,HB_Power_Q)) + { + lt_bg_highf_eng_trbl = L_shr(lt_bg_highf_eng_trbl,sub(14,HB_Power_Q)); + } + ELSE + { + HB_Power = L_shr(HB_Power, s_min(31, sub(HB_Power_Q, 14))); + } + + flag_high_eng = 0; + move16(); + if (GT_32(HB_Power,lt_bg_highf_eng_trbl)) + { + flag_high_eng = 1; + move16(); + } + + sp_center3_diff = sub(sp_center[3], hVAD_CLDFB->lt_noise_sp_center3); + + IF(sub(frameloop, 50) > 0) + { + if(GT_16(ltd_stable_rate[0],3932/* 0.12 Q15 */)) + + { + update_flag = 0; + move16(); + } + + tmpout= VAD_L_CMP(frame_energy, sub(frame_energy_Q,2), hVAD_CLDFB->frame_energy_smooth,hVAD_CLDFB->frame_energy_smooth_scale); + test(); + IF((NE_16(bw, CLDFBVAD_NB_ID))&&tmpout>0) + { + test(); + if((flag_high_eng) && (GT_16(sp_center3_diff, 409))) + { + update_flag = 0; + move16(); + } + test(); + if((GT_16(sp_center[3],2864/* 2.8 Q10 */))&&(GT_16(ltd_stable_rate[0],655/* 0.02 Q15 */))) + { + update_flag = 0; + move16(); + } + } + } + + test(); + if((GT_16(f_tonality_rate[1], 8192/* 0.5 Q14 */)) + && (GT_16(ltd_stable_rate[0],3277/* 0.1 Q15 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((LT_16(sSFM[1], 30146/* 0.92 Q15 */)) + && (LT_16(sSFM[0], 30146/* 0.92 Q15 */)) + && (LT_16(sSFM[2], 30146/* 0.92 Q15 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((LT_16(sSFM[0], 26214/* 0.8 Q15 */)) + || (LT_16(sSFM[1],25558/* 0.78 Q15 */) ) + || (LT_16(sSFM[2],26214/* 0.8 Q15 */) )) + { + update_flag = 0; + move16(); + } + + /*if(frame_energy > 32*hVAD_CLDFB->frame_energy_smooth)*/ + tmpout= VAD_L_CMP(frame_energy, frame_energy_Q, hVAD_CLDFB->frame_energy_smooth,sub(hVAD_CLDFB->frame_energy_smooth_scale,5)); + + if(tmpout>0) + { + update_flag = 0; + move16(); + } + tmp1 = L_mult(hVAD_CLDFB->fg_energy_count,18842); + tmp1_Q = norm_l(tmp1); + tmp1 = L_shl(tmp1,tmp1_Q); + tmp_norm = extract_h(tmp1); + frame_energy_Mcount = MUL_F(frame_energy,tmp_norm); + + fg_energy_Qtmp = sub(frame_energy_Q, 18); + fg_energy_Qtmp = add(fg_energy_Qtmp, tmp1_Q); + + cmp_result = VAD_L_CMP(frame_energy_Mcount,fg_energy_Qtmp,hVAD_CLDFB->fg_energy,hVAD_CLDFB->fg_energy_scale); + + tmpout = VAD_L_CMP(frame_energy, frame_energy_Q, 3, 0); + + test(); + test(); + if((cmp_result>0) + &&(EQ_32(hVAD_CLDFB->fg_energy_est_start,1)) + &&(tmpout>0)) + { + update_flag = 0; + move16(); + } + + test(); + IF((GT_16(f_tonality_rate[1],9830/* 0.6 Q14 */)) + ||(GT_16(f_tonality_rate[0],14089/* 0.86 Q14 */))) + { + update_flag = 0; + move16(); + tonality_flag = 1; + move16(); + } + + hVAD_CLDFB->tonality_rate3 = mult(hVAD_CLDFB->tonality_rate3, 32211); + move16(); + if(tonality_flag) + { + hVAD_CLDFB->tonality_rate3 = add(mult(hVAD_CLDFB->tonality_rate3,32211), 557); + move16(); + } + + if(GT_16(hVAD_CLDFB->tonality_rate3, 16384)) + { + update_flag = 0; + move16(); + } + + test(); + if((GT_16(sp_center[0], 4092/* 4.0 Q10 */)) + && (GT_16(ltd_stable_rate[0], 1311/* 0.04 Q15 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((GT_16(f_tonality_rate[1], 7536/* 0.46 Q14 */)) + && ((GT_16(sSFM[1],30473/* 0.93 Q15 */) ) + ||(GT_16(ltd_stable_rate[0], 2949/* 0.09 Q15 */)))) + + { + update_flag = 0; + move16(); + } + + test(); + test(); + test(); + IF( (LT_16(sSFM[1],30473/* 0.93 Q15 */) + && LT_16(sSFM[0], 30146/* 0.92 Q15 */) + && LT_16(sSFM[2], 31784/* 0.97 Q15 */)) + && (GT_16(f_tonality_rate[1], 8192/* 0.5 Q14 */))) + { + update_flag = 0; + move16(); + } + + test(); + test(); + IF((f_tonality_rate[1] > 7045/* 0.43 Q14 */) + &&(sSFM[0] < 31129/* 0.95 Q15 */) + &&(sp_center[1] > 1985/* 1.94 Q10 */)) + { + update_flag = 0; + move16(); + } + + IF(EQ_16(update_flag, 1)) + { + if(LT_16(hVAD_CLDFB->update_count, 1000)) + { + hVAD_CLDFB->update_count = add(hVAD_CLDFB->update_count,1); + } + } + + + IF(update_flag) + { + hVAD_CLDFB->lt_noise_sp_center3 = add(mult(hVAD_CLDFB->lt_noise_sp_center3,29491),mult(sp_center[3],3277)); + move16(); + } + + + + tmpout= VAD_L_CMP(frame_energy, frame_energy_Q, hVAD_CLDFB->frame_energy_smooth,sub(hVAD_CLDFB->frame_energy_smooth_scale,2)); + + + test(); + test(); + test(); + test(); + if((tmpout>0) + &&(LT_16(frameloop, 100) ) + &&(LT_16(f_tonality_rate[1],9174/* 0.56 Q14 */)) + &&((LT_16(sp_center[0], 1391/* 1.36 Q10 */))||LT_16(ltd_stable_rate[0],983/* 0.03 Q15 */))) + { + update_flag = 1; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + if((LT_32(snr,10066329/* 0.3 Q25 */))&&tmpout<0 + &&(LT_32(L_shr(tsnr,1), 20132659/* 1.2/2.0 Q25 */)) + &&(vad_flag==0) + &&(LT_16(hVAD_CLDFB->f_tonality_rate[1],8192/* 0.5 Q14 */)) + &&(music_backgound_f==0) + &&(LT_16(hVAD_CLDFB->ltd_stable_rate[3],3277/* 0.1 Q15 */))) + { + update_flag = 1; + move16(); + } + + test(); + test(); + test(); + IF(vad_flag && GT_32(snr, 33554431/* 1.0 Q25 */)&&EQ_16(bw,CLDFBVAD_SWB_ID)&&tmpout>0) + { + update_flag = 0; + } + + test(); + test(); + test(); + IF(vad_flag && GT_32(snr, 50331647/* 1.5 Q25 */)&&NE_16(bw,CLDFBVAD_SWB_ID)&&tmpout>0) + { + update_flag = 0; + } + + + IF(update_flag == 0) + { + hVAD_CLDFB->updateNumWithSnr = 0; + } + ELSE + { + test(); + test(); + IF(vad_flag && GT_32(snr, 100663293/* 3.0 Q25 */)&<_16(hVAD_CLDFB->updateNumWithSnr,10)) + { + update_flag = 0; move16(); + hVAD_CLDFB->updateNumWithSnr = add(hVAD_CLDFB->updateNumWithSnr, 1); + } + } + + + test(); + IF(vad_flag==0||EQ_16(update_flag,1)) + { + Word16 tmp_fix; + tmp_fix = sub(hVAD_CLDFB->sp_center[2],hVAD_CLDFB->lt_noise_sp_center0); + tmp_fix = abs_s(tmp_fix); + if (GT_16(tmp_fix, 2558/* 2.5 Q10 */)) + { + tmp_fix = 2558/* 2.5 Q10 */; + move16(); + } + hVAD_CLDFB->lt_noise_sp_center_diff_sum = L_add(hVAD_CLDFB->lt_noise_sp_center_diff_sum ,tmp_fix); + move32(); + + hVAD_CLDFB->lt_noise_sp_center_diff_counter = L_add(hVAD_CLDFB->lt_noise_sp_center_diff_counter,1); + move32(); + IF(EQ_32(hVAD_CLDFB->lt_noise_sp_center_diff_counter, 128)) + { + hVAD_CLDFB->lt_noise_sp_center_diff_sum = MUL_F(hVAD_CLDFB->lt_noise_sp_center_diff_sum,24576); + move32(); + hVAD_CLDFB->lt_noise_sp_center_diff_counter = 96; + move32(); + } + + move16(); + move16(); + IF(GT_16((Word16)abs_s(sub(hVAD_CLDFB->sp_center[0],hVAD_CLDFB->lt_noise_sp_center0)), 2455/* 2.4 Q10 */)) + { + hVAD_CLDFB->lt_noise_sp_center0 = add(mult(hVAD_CLDFB->lt_noise_sp_center0,32637),mult(hVAD_CLDFB->sp_center[0],131)); + move16(); + } + ELSE IF(GT_16((Word16)abs_s(sub(hVAD_CLDFB->sp_center[0],hVAD_CLDFB->lt_noise_sp_center0)), 1023/* 1.0 Q10 */)) + { + hVAD_CLDFB->lt_noise_sp_center0 = add(mult(hVAD_CLDFB->lt_noise_sp_center0,32440),mult(hVAD_CLDFB->sp_center[0],328)); + move16(); + } + ELSE + { + hVAD_CLDFB->lt_noise_sp_center0 = add(mult(hVAD_CLDFB->lt_noise_sp_center0,31457),mult(hVAD_CLDFB->sp_center[0],1311)); + move16(); + } + } + + Q_sum = sub(norm_l(hVAD_CLDFB->lt_noise_sp_center_diff_sum), 1); + Q_counter = norm_l(hVAD_CLDFB->lt_noise_sp_center_diff_counter); + sum_num = L_shl(hVAD_CLDFB->lt_noise_sp_center_diff_sum,Q_sum); + counter_den = L_shl(hVAD_CLDFB->lt_noise_sp_center_diff_counter,Q_counter); + + IF(extract_h(counter_den)==0) + { + div_r = EVS_SW_MAX; + move16(); + } + ELSE + { + div_r = div_l(sum_num,extract_h(counter_den)); + } + + div_r = mult(div_r,24576); + div_r_32 = VAD_L_ADD(L_deposit_l(div_r),add(sub(Q_sum,Q_counter),22), 9830, 15,&div_r_Q); + div_r =extract_l(L_shr(div_r_32, sub(div_r_Q, SP_CENTER_Q))); + + test(); + if((GT_16(abs_s(sub(hVAD_CLDFB->sp_center[2],hVAD_CLDFB->lt_noise_sp_center0)), div_r))&&(GT_16(frameloop,200))) + { + update_flag = 0; + move16(); + } + + + return update_flag; +} diff --git a/lib_enc/updt_enc_fx.c b/lib_enc/updt_enc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..5c93894a9ee3b4e9c6fabfab39c5c4c1c2bee6ca --- /dev/null +++ b/lib_enc/updt_enc_fx.c @@ -0,0 +1,529 @@ +/*==================================================================================== + 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 "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 */ + +/*-------------------------------------------------------------------* + * updt_enc() + * + * Common updates (all frame types) + *-------------------------------------------------------------------*/ + +void updt_enc_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 *old_exc, /* i : buffer of excitation */ + const Word16 *pitch_buf, /* i : floating pitch for each subframe */ + const Word16 Es_pred, /* i : predicited scaled innovation energy */ + const Word16 *Aq, /* i : A(z) quantized for all subframes */ + const Word16 *lsf_new, /* i : current frame LSF vector */ + const Word16 *lsp_new, /* i : current frame LSP vector */ + const Word16 *old_bwe_exc /* i : buffer of excitation */ +) +{ + Word16 i, tmp; + SC_VBR_ENC_HANDLE hSC_VBR = st->hSC_VBR; + LPD_state_HANDLE hLPDmem = st->hLPDmem; + GSC_ENC_HANDLE hGSCEnc = st->hGSCEnc; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; + + /* update old excitation buffer */ + Copy( &old_exc[st->L_frame_fx], hLPDmem->old_exc, L_EXC_MEM ); + test(); + IF( !st->Opt_AMR_WB_fx && st->hBWE_TD != NULL) + { + Copy( &old_bwe_exc[L_FRAME32k], hBWE_TD->old_bwe_exc_fx, PIT16k_MAX * 2 ); + } + + /* update old LSP and LSF vector */ + Copy( lsp_new, st->lsp_old_fx, M ); + Copy( lsf_new, st->lsf_old_fx, M ); + + /* update last coder type */ + st->last_coder_type_fx = st->coder_type; + move16(); + test(); + test(); + test(); + if( EQ_16(st->coder_type,INACTIVE) || (EQ_16(st->bpf_off_fx,1) && NE_16(st->coder_type,AUDIO) && NE_16(st->coder_type,TRANSITION))) + { + st->last_coder_type_fx = UNVOICED; + move16(); + } + + /* this ensures that st->last_coder_type_fx is never set to INACTIVE in case of AVQ inactive because the FEC does not distinguish between GSC inactive and AVQ inactive */ + test(); + if ( EQ_16(st->coder_type,INACTIVE) && GT_32(st->total_brate_fx,ACELP_24k40)) + { + st->last_coder_type_fx = GENERIC; + move16(); + } + + test(); + test(); + test(); + IF( st->Opt_AMR_WB_fx && EQ_16(st->coder_type,INACTIVE) && st->core_brate_fx!=SID_1k75 && st->core_brate_fx!=FRAME_NO_DATA) + { + /* overwrite previous coding type to help FEC */ + st->last_coder_type_fx = UNVOICED; + move16(); + } + + /* AC mode (GSC) - in speech we can consider that the last pitch band reached the max */ + test();test(); + IF (st->hGSCEnc != NULL && NE_16(st->coder_type,AUDIO) && NE_16(st->coder_type,INACTIVE)) + { + hGSCEnc->mem_last_pit_band = 10 + BAND1k2; + move16(); + hGSCEnc->past_dyn_dec = NOISE_LEVEL_SP0-1; + move16(); /* tends to speech */ + hGSCEnc->noise_lev = NOISE_LEVEL_SP0-1; + move16(); /* tends to speech */ + /*st->mid_dyn_fx = 40.0f * 0.5f + st->mid_dyn * 0.5f;*/ + hGSCEnc->mid_dyn_fx = add(20*128, mult_r(hGSCEnc->mid_dyn_fx, 16384)); /*Q7*/ + } + + /* convert old LSP vector from 12kHz domain to 16kHz domain (needed in case of ACELP@12k8 <-> ACELP@16kHz switching) */ + IF( EQ_16(st->L_frame_fx,L_FRAME)) + { + Copy( st->lsp_old_fx, st->lsp_old16k_fx, M ); + st->rate_switching_reset_16kHz=lsp_convert_poly_fx( st->lsp_old16k_fx, L_FRAME16k, st->Opt_AMR_WB_fx ); + } + + /* update buffer of old subframe pitch values */ + IF( NE_16(st->last_L_frame_fx,st->L_frame_fx)) + { + IF( EQ_16(st->L_frame_fx,L_FRAME)) + { + FOR( i=0; iold_pitch_buf_fx[NB_SUBFR+i] = mult_r(26214, st->old_pitch_buf_fx[NB_SUBFR+i+1]); + move16(); + } + } + ELSE + { + FOR( i=NB_SUBFR; i>0; i-- ) + { + st->old_pitch_buf_fx[NB_SUBFR+i] = add(mult_r(8192, st->old_pitch_buf_fx[NB_SUBFR+i-1]),st->old_pitch_buf_fx[NB_SUBFR+i-1]); + move16(); + } + st->old_pitch_buf_fx[2*NB_SUBFR16k-1] = st->old_pitch_buf_fx[2*NB_SUBFR16k-2]; + move16(); + } + } + tmp = shr(st->L_frame_fx,6); + Copy( &st->old_pitch_buf_fx[tmp], st->old_pitch_buf_fx, tmp); + Copy( pitch_buf, &st->old_pitch_buf_fx[tmp], tmp); + + /* SC-VBR */ + st->last_Opt_SC_VBR_fx = st->Opt_SC_VBR_fx; + move16(); + IF(st->hSC_VBR != NULL) + { + hSC_VBR->last_last_ppp_mode = hSC_VBR->last_ppp_mode; + move16(); + hSC_VBR->last_ppp_mode = hSC_VBR->ppp_mode; + move16(); + hSC_VBR->last_nelp_mode = hSC_VBR->nelp_mode; + move16(); + } + /* core switching updates */ + Copy( &Aq[(st->L_frame_fx/L_SUBFR-1)*(M+1)], st->old_Aq_12_8_fx, M+1 ); + st->old_Es_pred_fx = Es_pred; + + return; +} + +/*-------------------------------------------------------------------* + * updt_IO_switch() + * + * Common updates for AMR-WB IO mode and EVS primary mode switching + *-------------------------------------------------------------------*/ + +void updt_IO_switch_enc_fx( + Encoder_State_fx *st, /* i/o: state structure */ + const Word16 input_frame /* i : input frame length */ +) +{ + Word16 xsp_tmp[M]; + SC_VBR_ENC_HANDLE hSC_VBR = st->hSC_VBR; + DTX_ENC_HANDLE hDtxEnc = st->hDtxEnc; + TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc; + 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; + + IF( EQ_16(st->last_core_fx,AMR_WB_CORE)) /* switching to EVS primary mode */ + { + /* reset onset detection counter */ + st->tc_cnt_fx = -1; + + /* force safety-net LSFQ in the first frames after the switching */ + st->Nb_ACELP_frames_fx = 0; + move16(); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + Copy( stable_LSP_fx, xsp_tmp, M ); + isf2lsf_fx( st->lsf_old_fx, st->lsf_old_fx, xsp_tmp); + Copy( stable_LSP_fx, xsp_tmp, M ); + isp2lsp_fx( st->lsp_old_fx, st->lsp_old_fx, xsp_tmp, M); + isp2lsp_fx( st->lsp_old1_fx, st->lsp_old1_fx, xsp_tmp, M); + + Copy( stable_LSP_fx, xsp_tmp, M ); + isp2lsp_fx(hDtxEnc->lspCNG_fx, hDtxEnc->lspCNG_fx, xsp_tmp, M); + /*st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_AMR_WB_SID * STEP_SID), 127 );*/ + IF(hTdCngEnc->old_enr_index >=0 ) + { + /* old index is initialized to -1, and may only be updated after it has been calculated properly at least once once */ + hTdCngEnc->old_enr_index = s_min(mult(shl(hTdCngEnc->old_enr_index,1), 32459), 127 ); /*32459 = 2/(STEP_SID/STEP_AMR_WB_SID)*/ + } + /* Perform preemphasis of the old input signal @16kHz */ + st->mem_preemph16k_fx = 0; + move16(); + preemph_fx( st->old_inp_16k_fx, PREEMPH_FAC_16k, L_INP_MEM, &(st->mem_preemph16k_fx) ); + Scale_sig(st->old_inp_16k_fx, L_INP_MEM, st->prev_Q_new); + /* reset TD BWE buffers */ + set16_fx( hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + set16_fx( hBWE_TD->old_speech_wb_fx, 0, (L_LOOK_12k8 + L_SUBFR) * 5/16 ); + set16_fx( hBWE_TD->old_bwe_exc_fx, 0, PIT16k_MAX * 2 ); + set16_fx( hBWE_TD->old_bwe_exc_extended_fx, 0, NL_BUFF_OFFSET ); +#ifdef IVAS_CODE + 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 = 32767; + st->hBWE_TD->prev_pow_exc16kWhtnd = 32767; + st->hBWE_TD->prev_mix_factor = 32767; + st->hBWE_TD->prev_Env_error = 0; + move16();move16();move16();move16();move16(); +#endif + hBWE_TD->bwe_non_lin_prev_scale_fx = 0; + move16(); + 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_FD->L_old_wtda_swb_fx, 0, L_FRAME16k ); + set16_fx(hBWE_FD->old_input_wb_fx, 0, NS2SA(16000, DELAY_FD_BWE_ENC_NS) ); + + wb_tbe_extras_reset_fx( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, hBWE_TD->mem_genSHBexc_filt_down_wb3_fx ); + + IF( GE_16(input_frame,L_FRAME32k)) + { + 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) ); + + } + + IF( EQ_16(input_frame,L_FRAME48k)) + { + set16_fx(hBWE_TD->fb_state_lpc_syn_fx, 0, LPC_SHB_ORDER); + hBWE_TD->fb_tbe_demph_fx = 0; + move16(); + 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); + } + + /* reset FD BWE buffers */ + hBWE_FD->prev_mode = NORMAL; + move16(); + + /* reset the unvoiced/audio signal improvement memories */ + hGSCEnc->seed_tcx = 15687; + move16(); + + st->use_acelp_preq = 0; + move16(); +#ifdef IVAS_CODE + set16_fx(st->hSpMusClas->finc_prev, 0, ATT_NSEG); + set16_fx(st->hSpMusClas->tod_lt_Bin_E, 0, TOD_NSPEC); + set16_fx(st->hSpMusClas->tod_S_map_lt, 0, TOD_NSPEC); + st->hSpMusClas->lt_finc = 0; + st->hSpMusClas->last_strong_attack = 0; + st->hSpMusClas->tod_thr_lt = TOD_THR_MASS; + st->hSpMusClas->tod_weight = 0; + st->hSpMusClas->tod_S_mass_prev = TOD_THR_MASS; + st->hSpMusClas->tod_S_mass_lt = TOD_THR_MASS; + move16();move16();move16();move16();move16();move16(); +#endif + + } + ELSE /* switching to AMR-WB IO mode */ + { + set16_fx(st->mem_MA_fx, 0, M ); + + /* AMR-WB IO mode uses ISF(ISP), but EVS primary mode LSF(LSP) */ + Copy( stable_ISP_fx, xsp_tmp, M ); + lsf2isf_fx( st->lsf_old_fx, st->lsf_old_fx, xsp_tmp, M); + Copy( stable_ISP_fx, xsp_tmp, M ); + lsp2isp_fx( st->lsp_old_fx, st->lsp_old_fx, xsp_tmp, M); + lsp2isp_fx( st->lsp_old1_fx, st->lsp_old1_fx, xsp_tmp, M); + Copy( stable_ISP_fx, xsp_tmp, M ); + lsp2isp_fx(hDtxEnc->lspCNG_fx, hDtxEnc->lspCNG_fx, xsp_tmp, M); + + IF(hTdCngEnc->old_enr_index >= 0 ) + { + /* old_enr__index is initialized to -1, and may only be updated this way after it has been calculated properly at least once once */ + /*st->old_enr_index = min( (short)((float)st->old_enr_index / STEP_SID * STEP_AMR_WB_SID), 63 );*/ + hTdCngEnc->old_enr_index = s_max(s_min(mult(hTdCngEnc->old_enr_index, 16384), 63 ),0); /*32459 = 2/(STEP_SID/STEP_AMR_WB_SID)*/ + } + /* gain quantization memory */ + set16_fx(hAmrwb_IO->past_qua_en_fx, (-14*1024), GAIN_PRED_ORDER ); + /* reset VBR signalling */ + IF (st->Opt_SC_VBR_fx) + { + hSC_VBR->ppp_mode = 0; + move16(); + hSC_VBR->nelp_mode = 0; + move16(); + } + st->hGSCEnc->seed_tcx = 15687; /* the re-init here was present only in float _DIFF_FLOAT_FIX_*/ + move16(); + } + + /* Force SID in case of AMR-WB IO/EVS primary mode switching */ + IF (hTdCngEnc != NULL) + { + hDtxEnc->cnt_SID = 0; + move16(); + + /* CNG - reset */ + hDtxEnc->cng_cnt = 0; + move16(); + hTdCngEnc->ho_hist_size = 0; + move16(); + hTdCngEnc->burst_ho_cnt = 0; + move16(); + } + /* LP memories */ + Copy( UVWB_Ave_fx, st->mem_AR_fx, M ); + + /* FEC - update adaptive LSF mean vector */ + Copy( st->lsf_old_fx, st->lsfoldbfi0_fx, M ); + Copy( st->lsf_old_fx, st->lsfoldbfi1_fx, M ); + Copy( st->lsf_old_fx, st->lsf_adaptive_mean_fx, M ); + + return; +} + +/*-------------------------------------------------------------------* + * updt_enc_common_fx() + * + * Common updates for MODE1 and MODE2 + *-------------------------------------------------------------------*/ +#if 1 +void updt_enc_common_fx( + Encoder_State_fx* st, /* i/o: encoder state structure */ + const Word16 Etot, /* i : total energy */ + const Word16 Q_new /* i : CUrrent frame scaling */ +) +{ + /*---------------------------------------------------------------------* + * Updates - main main codec parameters + *---------------------------------------------------------------------*/ + + st->last_sr_core = st->sr_core; //## + move32(); + st->last_codec_mode = st->codec_mode; + move16(); + st->last_L_frame_fx = st->L_frame_fx; // + move16(); + st->last_core_fx = st->core_fx; + move16(); + + st->last_core_brate_fx = st->core_brate_fx; + move32(); +#ifdef IVAS_CODE + st->last_bits_frame_nominal_fx = st->bits_frame_nominal; +#endif + st->last_total_brate_fx = st->total_brate_fx; + move32(); + st->last_extl_fx = st->extl_fx; // + move16(); + st->last_input_bwidth_fx = st->input_bwidth_fx; //## + move16(); + st->last_bwidth_fx = st->bwidth_fx; //## + move16(); + st->hNoiseEst->Etot_last_fx = Etot; + move16(); + st->last_coder_type_raw_fx = st->coder_type_raw_fx; + move16(); + + st->prev_Q_new = Q_new; + move16(); + + test(); + if (GT_32(st->core_brate_fx, SID_2k40) && st->hDtxEnc != NULL) + { + st->hDtxEnc->last_active_brate = st->total_brate_fx; + move32(); + } + + IF(st->hBWE_TD != NULL) + { + st->hBWE_TD->prev_coder_type = st->coder_type; + move16(); + if (EQ_16(st->core_fx, HQ_CORE)) + { + /* in the HQ core, coder_type is not used so it could have been set to anything */ + st->hBWE_TD->prev_coder_type = GENERIC; + move16(); + + } + } + + test(); + IF(st->Opt_DTX_ON_fx && st->hTdCngEnc != NULL) + { + IF(GT_32(st->core_brate_fx, SID_2k40) ) + { + IF(EQ_16(st->hDtxEnc->first_CNG, 1)) + { + if (GE_16(st->hTdCngEnc->act_cnt, BUF_DEC_RATE)) + { + st->hTdCngEnc->act_cnt = 0; + move16(); + } + st->hTdCngEnc->act_cnt = add(st->hTdCngEnc->act_cnt, 1); + + test(); + if (EQ_16(st->hTdCngEnc->act_cnt, BUF_DEC_RATE) && st->hTdCngEnc->ho_hist_size > 0) + { + st->hTdCngEnc->ho_hist_size = sub(st->hTdCngEnc->ho_hist_size, 1); + } + } + + test(); test(); test(); + IF(EQ_16(st->element_mode, IVAS_SCE) || EQ_16(st->element_mode, IVAS_CPE_DFT) || EQ_16(st->element_mode, IVAS_CPE_TD) || EQ_16(st->hDtxEnc->first_CNG, 1)) + { + st->hTdCngEnc->act_cnt2 = add(st->hTdCngEnc->act_cnt2, 1); + st->hTdCngEnc->act_cnt2 = s_min(st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD); + +#ifdef IVAS_CODE + test(); test(); test(); + IF((EQ_16(st->element_mode, IVAS_SCE) || EQ_16(st->element_mode, IVAS_CPE_DFT) || EQ_16(st->element_mode, IVAS_CPE_TD)) && GE_16(st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD)) + { + st->hTdCngEnc->CNG_att_fx = 0; move16(); + + apply_scale(&st->hTdCngEnc->CNG_att, st->hFdCngEnc->hFdCngCom->CngBandwidth, st->hFdCngEnc->hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO); + } +#endif + } + } + + test(); test(); test(); + if( (EQ_32(st->core_brate_fx, SID_2k40) || EQ_32(st->core_brate_fx, FRAME_NO_DATA)) && st->hDtxEnc->first_CNG == 0 && EQ_16(st->cng_type_fx, LP_CNG)) + { + st->hDtxEnc->first_CNG = 1; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Increase the counter of initialization frames + * Limit the max number of init. frames + *-----------------------------------------------------------------*/ + + if (LT_16(st->ini_frame_fx, MAX_FRAME_COUNTER)) + { + st->ini_frame_fx = add(st->ini_frame_fx, 1); + } + + /* synchronisation of CNG seeds */ + test();test();test(); + IF (st->hTdCngEnc != NULL && NE_32(st->core_brate_fx, FRAME_NO_DATA) && NE_32(st->core_brate_fx, SID_2k40) && NE_16(st->core_fx, AMR_WB_CORE)) + { + Random(&(st->hTdCngEnc->cng_seed)); + Random(&(st->hTdCngEnc->cng_ener_seed)); + } + + /*---------------------------------------------------------------------* + * Updates - MODE2 + *---------------------------------------------------------------------*/ + + IF (EQ_16(st->element_mode, EVS_MONO) && EQ_16(st->mdct_sw, MODE2)) + { + st->codec_mode = MODE2; + move16(); + + st->sr_core = getCoreSamplerateMode2(EVS_MONO, st->total_brate_fx, st->bwidth_fx, st->flag_ACELP16k, st->rf_mode, 0); + + //st->L_frame_fx = extract_l(Mult_32_16(st->sr_core, 0x0290)); /*(int16_t)(st->sr_core / FRAMES_PER_SEC);*/ + + IF (EQ_32(st->sr_core, INT_FS_12k8)) + { + st->preemph_fac = PREEMPH_FAC; + st->gamma = GAMMA1; + st->L_frame_fx = L_FRAME; + move16(); move16(); move16(); + } + ELSE + { + st->preemph_fac = PREEMPH_FAC_16k; + st->gamma = GAMMA16k; + st->L_frame_fx = L_FRAME16k; + move16();move16();move16(); + } + + st->igf = getIgfPresent_fx(EVS_MONO, st->total_brate_fx, st->bwidth_fx, st->rf_mode); + } + + /* update FER clas */ + if (NE_16(st->core_fx, AMR_WB_CORE)) + { + st->last_clas_fx = st->clas_fx; + move16(); + } + + /* Update Core */ + core_encode_update_fx(st); + + /*---------------------------------------------------------------------* + * RF mode updates + *---------------------------------------------------------------------*/ + + IF (st->rf_mode) + { + IF (st->hSC_VBR != NULL) + { + st->hSC_VBR->last_nelp_mode = 0; + move16(); + if (EQ_16(st->hRF->rf_frame_type, RF_NELP)) + { + st->hSC_VBR->last_nelp_mode = 1; + move16(); + } + + } + } + + st->rf_mode_last = st->rf_mode; move16(); + + IF (st->Opt_RF_ON) + { + st->L_frame_fx = L_FRAME; + st->rf_mode = 1; + move16();move16(); + } + + /*---------------------------------------------------------------------* + * Other updates + *---------------------------------------------------------------------*/ +#ifdef IVAS_CODE + test(); + if (GT_16(st->element_mode, EVS_MONO) && st->hTcxEnc != NULL) + { + st->hTcxEnc->tcxltp_norm_corr_mem= st->hTcxEnc->tcxltp_norm_corr_past; + move16(); + } +#endif + return; +} +#endif \ No newline at end of file diff --git a/lib_enc/updt_tar_fx.c b/lib_enc/updt_tar_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..3183b65217c95591a3fbd06492000d82c2acc0d9 --- /dev/null +++ b/lib_enc/updt_tar_fx.c @@ -0,0 +1,79 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include "options.h" /* Compilation switches */ +#include "cnst.h" +//#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 */ + +/*----------------------------------------------------------------------------------* + * procedure updt_tar: + * + * Update the target vector for codebook search. + *----------------------------------------------------------------------------------*/ +void updt_tar_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain */ + const Word16 L /* i : subframe size */ +) +{ + Word16 i; + Word32 L_tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + FOR (i = 0; i < L; i++) + { + /*x2[i] = x[i] - gain*y[i];*/ + L_tmp = L_mult(x[i], 16384); + L_tmp = L_msu(L_tmp, y[i], gain); +#ifdef BASOP_NOGLOB + x2[i] = extract_h(L_shl_o(L_tmp, 1, &Overflow)); +#else /* BASOP_NOGLOB */ + x2[i] = extract_h(L_shl(L_tmp, 1)); +#endif + } + return; +} +/*----------------------------------------------------------------------------------* + * procedure updt_tar: + * + * Update the target vector for codebook search. + *----------------------------------------------------------------------------------*/ +void updt_tar_HR_fx( + const Word16 *x, /* i : old target (for pitch search) */ + Word16 *x2, /* o : new target (for codebook search) */ + const Word16 *y, /* i : filtered adaptive codebook vector */ + const Word16 gain, /* i : adaptive codebook gain Q2 */ + const Word16 Qx, /* i : Scaling factor to adapt output to input */ + const Word16 L /* i : subframe size */ +) +{ + Word16 i; + Word32 L_tmp, L_tmp1; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + FOR (i = 0; i < L; i++) + { + /*x2[i] = x[i] - gain*y[i];*/ + L_tmp = L_mult(x[i], 32767); +#ifdef BASOP_NOGLOB + L_tmp1 = L_shl_o(L_mult_o(y[i], gain, &Overflow), Qx, &Overflow); + L_tmp = L_sub_o(L_tmp, L_tmp1, &Overflow); +#else + L_tmp1 = L_shl(L_mult(y[i], gain), Qx); + L_tmp = L_sub(L_tmp, L_tmp1); +#endif + x2[i] = extract_h(L_tmp); + } + return; +} diff --git a/lib_enc/vad_basop.h b/lib_enc/vad_basop.h new file mode 100644 index 0000000000000000000000000000000000000000..9ffeaf3ad171d4f99251b10cad91421c42a3d0bf --- /dev/null +++ b/lib_enc/vad_basop.h @@ -0,0 +1,81 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#ifndef __VAD_BASOP_H__ +#define __VAD_BASOP_H__ + +#include "typedef.h" +#include "basop32.h" +#include "stat_enc.h" + +Word16 vadmin( Word16 a, + Word16 b + ); + +Word32 vad_Sqrt_l( Word32 i_s32Val, + Word16 *io_s16Q + ); + +Word32 fft_vad_Sqrt_l( Word32 i_s32Val, + Word16 i_s16Q, + Word16 *o_s16Q + ); + +T_VAD_EXP VAD_AddExp( T_VAD_EXP i_tExp1, + T_VAD_EXP i_tExp2 + ); + +Word16 VAD_L_CMP( Word32 s32Mantissa1, + Word16 i_tExp1, + Word32 s32Mantissa2, + Word16 i_tExp2 + ); + +Word32 VAD_L_ADD( Word32 s32Mantissa1, + Word16 i_tExp1, + Word32 s32Mantissa2, + Word16 i_tExp2, + Word16 *s16Exp + ); + +Word32 VAD_L_div( Word32 L_var1, + Word32 L_var2, + Word16 Q_L_var1, + Word16 Q_L_var2, + Word16 *Q_OUT + ); + +Word32 VAD_Log2( Word32 i_s32Val, + Word16 i_s16Q + ); +/*already defined in prot_fx_enc.h +Word16 ffr_getSfWord32( + Word32 *vector, + Word16 len + );*/ + +Word32 VAD_Pow( Word32 i_s32Base, + Word32 i_s32Exp, + Word16 i_s16BaseQ, + Word16 i_s16ExpQ, + Word16 *o_pOuQ + ); + +Word32 VAD_Pow2( Word32 i_s32X, + Word16 i_s16Q, + Word16 *o_pOuQ + ); + +Word16 FixSqrt( Word32 i_s32Val, + Word16 *io_s16Q + ); + +void cfftf( Word16* scale, + complex_32 *c, + complex_32 *ch, + const complex_16 *wa + ); + + +#endif diff --git a/lib_enc/vad_basop_fx.c b/lib_enc/vad_basop_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..9cab551c32b3ac24280146a4d48aad16f88dd9c3 --- /dev/null +++ b/lib_enc/vad_basop_fx.c @@ -0,0 +1,146 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.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 "vad_basop.h" +#include "basop_util.h" + +Word32 vad_Sqrt_l( /* o : output value, Q31 */ + Word32 i_s32Val, + Word16 *io_s16Q +) +{ + Word16 exp; + Word32 result; + + exp = sub(31,*io_s16Q); + result = Sqrt32(i_s32Val, &exp); + *io_s16Q = sub(31,exp); + move16(); + + return (result); +} + +Word32 fft_vad_Sqrt_l( /* o : output value, Q31 */ + Word32 i_s32Val, + Word16 i_s16Q, + Word16 *o_s16Q +) +{ + Word16 exp; + Word32 result; + + exp = sub(31, i_s16Q); + result = Sqrt32(i_s32Val, &exp); + *o_s16Q = sub(31, exp); + move16(); + + return (result); +} + +Word32 VAD_L_div(Word32 L_var1, Word32 L_var2,Word16 Q_L_var1,Word16 Q_L_var2,Word16 *Q_OUT ) +{ + Word32 result; + + result = L_deposit_h(BASOP_Util_Divide3232_Scale(L_var1, L_var2, Q_OUT)); + move16(); + *Q_OUT = add(sub(sub(31, *Q_OUT), Q_L_var2), Q_L_var1); + return result; +} + +Word32 VAD_Log2(Word32 i_s32Val, Word16 i_s16Q) +{ + Word32 result; + + /* log10(x) = log2(x) * 1.0/log2(10), exponent LD_DATA_SCALE - 1 */ + result = BASOP_Util_Log2(i_s32Val); + + result = L_add(result, L_shl(L_deposit_l(sub(31, i_s16Q)), 31-LD_DATA_SCALE)); + + return result; +} + +T_VAD_EXP VAD_AddExp(T_VAD_EXP i_tExp1, T_VAD_EXP i_tExp2) +{ + Word16 s16Shift; + T_VAD_EXP tRtnVal; + + if(i_tExp1.s32Mantissa == 0) + { + return i_tExp2; + } + + if(i_tExp2.s32Mantissa == 0) + { + return i_tExp1; + } + s16Shift = sub(s_min(i_tExp1.s16Exp,i_tExp2.s16Exp),1); + tRtnVal.s32Mantissa = L_add(L_shr(i_tExp2.s32Mantissa, sub(i_tExp2.s16Exp,s16Shift)), L_shr(i_tExp1.s32Mantissa, sub(i_tExp1.s16Exp,s16Shift))); + tRtnVal.s16Exp = s16Shift; + move16(); + + s16Shift = norm_l(tRtnVal.s32Mantissa); + tRtnVal.s32Mantissa = L_shl(tRtnVal.s32Mantissa, s16Shift); + tRtnVal.s16Exp = add(tRtnVal.s16Exp,s16Shift); + + return tRtnVal; + +} +Word32 VAD_L_ADD(Word32 s32Mantissa1,Word16 i_tExp1, Word32 s32Mantissa2, Word16 i_tExp2,Word16 *s16Exp) +{ + Word32 result; + + result = BASOP_Util_Add_Mant32Exp(s32Mantissa1, sub(31, i_tExp1), s32Mantissa2, sub(31, i_tExp2), s16Exp); + + move16(); + *s16Exp = sub(31, *s16Exp); + + return result; +} + +Word16 VAD_L_CMP(Word32 s32Mantissa1,Word16 i_tExp1, Word32 s32Mantissa2, Word16 i_tExp2) +{ + Word16 ret; + + ret = BASOP_Util_Cmp_Mant32Exp(s32Mantissa1, sub(31, i_tExp1), s32Mantissa2, sub(31, i_tExp2)); + + return ret; +} + +Word16 FixSqrt(Word32 i_s32Val, Word16 *io_s16Q) +{ + Word16 result, exp; + + exp = sub(31, *io_s16Q); + result = round_fx(Sqrt32(i_s32Val, &exp)); + move16(); + *io_s16Q = sub(15, exp); + + return result; +} + +Word32 VAD_Pow(Word32 i_s32Base, Word32 i_s32Exp, + Word16 i_s16BaseQ, Word16 i_s16ExpQ, Word16 *o_pOuQ) +{ + Word32 result; + result = BASOP_Util_fPow(i_s32Base, sub(31, i_s16BaseQ), i_s32Exp, sub(31, i_s16ExpQ), o_pOuQ); + move16(); + *o_pOuQ = sub(31, *o_pOuQ); + return result; +} + +Word32 VAD_Pow2(Word32 i_s32X, Word16 i_s16Q, Word16 *o_pOuQ) +{ + Word32 result; + result = BASOP_util_Pow2(i_s32X, sub(31, i_s16Q), o_pOuQ); + move16(); + *o_pOuQ = sub(31, *o_pOuQ); + + return result; +} diff --git a/lib_enc/vad_fx.c b/lib_enc/vad_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..5e1b13569db95da40e1026ea6ca2ae2d4b10afff --- /dev/null +++ b/lib_enc/vad_fx.c @@ -0,0 +1,1673 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ +#include +#include "options.h" +#include "cnst.h" /* Common constants */ +//#include "prot_fx.h" /* Function prototypes */ +#include "rom_enc.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ +/* old fx constants */ +#define HANGOVER_LONG 10 /* Hangover for CNG */ +#define HANGOVER_LONG_HE 20 /* Hangover of CNG */ +#define HANGOVER_LONG_NB 8 /* Hangover for CNG */ +#define ACTIVE_FRAMES 3 /* Number of consecutive active SPEECH frames necessary to trigger HO */ + +/* SNR threshold curve constants for WB input */ +#define SK16_2_FX 16930 /* Q14 (1.0333f)-> Linear function for clean speech */ +#define SC16_2_FX -4608 /* Q8 (-18)*/ +#define NK16_2_FX 13529 /* Q15 (.41287)-> Linear function for noisy speech */ +#define NC16_2_FX 3394 /* Q8 (13.259625)*/ +/* SNR threshold curve constants for NB input */ +#define NK8_1_FX 3509 /*Q15 (0.1071f) Linear function for noisy speech */ +#define NC8_1_FX 4224 /*Q8 (16.5f) */ +#define SK8_1_FX 12406 /*Q15 (0.3786f) Linear function for clean speech */ +#define SC8_1_FX 2834 /*Q8 (11.07f) */ +#define SIGN_THR_FX 40 /*Q4 (2.5f) Significanse threshold for per band snr calculation */ +#define MIN_SNR_FX 2 /*Q4 Minimum snr used for per band snr calculation */ + + +#define THR_M0_FX 3379 /* Q8 (13.2) Zero ofset for threshod */ +#define THR_K_BG_FX -8192 /* Q15(-0.25) Coefficient for dependence on background level */ +#define THR_K_BG_OFS_FX 5120 /* Q8 (20.0f) Zero offset for background level */ +#define THR_K_SNR_FX 3277 /* Q15 (0.1f) Coefficient for dependence on SNR */ +#define THR_K_EV_FX 18022 /* Q15 (0.55) Coefficient for dependence on noise variations */ + + +#define HO_DTX_CLEAN 1 /* Hangover for dtx in clean conditions */ +#define HO_DTX_NOISY 10 /* Hangover for dtx in noisy conditions */ +#define HO_DTX_NOISY2 4 /* Hangover for dtx in very noisy conditions */ +#define VAD_THR_MIN_FX 2688 + +#define ONE_LG10 2466 /* 1.0*log10(2) in Q13 */ + + +#define HANGOVER_LONG_FX 10 /* Hangover for CNG */ +#define HANGOVER_LONG_MUSIC_FX 20 /* Hangover of CNG */ +#define HANGOVER_LONG_HE_FX 20 /* Hangover of CNG */ +#define HANGOVER_LONG_NB_FX 8 /* Hangover for CNG */ +#define ACTIVE_FRAMES_FX 3 /* Number of consecutive active SPEECH frames necessary to trigger HO */ + +/* SNR threshold curve constants for WB input */ +#define TH16_2_FX 8960 /* Q8 (35) -> lp SNR that separates the curves for clean speech and noisy speech */ +#define TH8_1_FX 5120 /*Q8 (20.0f) long-term SNR that separates the curves for clean speech and noisy speech */ + +#define TH16_2_NFLAG_FX 8960 /* Q8 (35) */ +#define TH8_1_NFLAG_FX 8960 /* Q8 (35) */ + + +#define SNR_OUTLIER_WGHT_1_FX 16384 /* Q14 (1.00)*/ +#define SNR_OUTLIER_WGHT_2_FX 16548 /* Q14 (1.01)*/ +#define SNR_OUTLIER_WGHT_3_FX 16712 /* Q14 (1.02)*/ +#define INV_OUTLIER_THR_1_FX 3277 /* (1/10.0f) in Q15*/ +#define INV_OUTLIER_THR_2_FX 5461 /* (1/6.0f) in Q15 */ + +#define MAX_SNR_OUTLIER_IND_FX 17 /*Q0 */ +#define MAX_SNR_OUTLIER_1_FX 160 /*Q4 (10.0f)*/ +#define MAX_SNR_OUTLIER_2_FX 400 /*Q4 (25.0f)*/ +#define MAX_SNR_OUTLIER_3_FX 800 /*Q4 (50.0f)*/ + + +/* snr_sum = "scale" * (float)log10( L_snr_sum ) ;*/ +static Word16 vad_snr_log_fx( /* o: Q8 */ + Word32 L_snr, /* i: Q4 */ + Word16 scale/* i: scale Q13 , 10.0*log10(2) or 1.0*log10(2) */ +) +{ + Word16 e_snr,f_snr; + Word32 L_tmp; + + e_snr = norm_l(L_snr); + f_snr = Log2_norm_lc(L_shl(L_snr, e_snr)); + e_snr = sub(30-4, e_snr); + L_tmp=Mpy_32_16(e_snr, f_snr, scale); + return round_fx(L_shl(L_tmp, 10)); /* Q8 */ +} + + +void wb_vad_init_fx( + VAD_HANDLE hVAD /* i/o: VAD data handle */ +) +{ + hVAD->hangover_cnt = 0; + move16(); /* Hangover counter initialized to 0 */ + hVAD->nb_active_frames = ACTIVE_FRAMES_FX; + move16(); /* The counter of SPEECH frames necessary to trigger HO */ + /* is set to max (-> start with hangover) */ + + hVAD->vad_flag_reg_H = L_deposit_l(0); + hVAD->vad_flag_reg_L = L_deposit_l(0); + hVAD->vad_prim_reg = L_deposit_l(0); + hVAD->vad_flag_cnt_50 = 0; + move16(); + hVAD->vad_prim_cnt_16 = 0; + move16(); + + hVAD->hangover_cnt_dtx = HANGOVER_LONG_FX; + move16(); /* hangover for DTX */ + hVAD->hangover_cnt_music = HANGOVER_LONG_MUSIC_FX; + move16(); /* hangover for MUSIC DTX */ + + hVAD->hangover_cnt_he = 0; + move16(); /* Hangover counter initialized to 0 */ + hVAD->nb_active_frames_he = ACTIVE_FRAMES_FX; + move16(); /* The counter of SPEECH frames necessary to trigger HO */ + hVAD->bcg_flux_fx = 1120; + move16(); /*70 in Q4 */ + hVAD->soft_hangover = 0; + move16(); + hVAD->voiced_burst = 0; + move16(); + hVAD->bcg_flux_init = 50; + move16(); + hVAD->nb_active_frames_he1 = ACTIVE_FRAMES_FX; + move16(); + hVAD->hangover_cnt_he1 = 0; + move16(); + return; +} + + +/*-----------------------------------------------------------------* + * sign_thr_snr_acc_fx() + * + * accumulate snr_sum with significance thresholds + *-----------------------------------------------------------------*/ +static void sign_thr_snr_acc_fx( + Word32 *L_snr_sum, /* o: Q4 */ + Word32 L_snr, /* i: Q4 */ + Word16 sign_thr, /* i: Q4 */ + Word16 min_snr /* i: Q4 */ +) +{ + /*if( snr >= sign_thr ) */ + Word32 L_tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + L_tmp = L_deposit_l(min_snr); + if( GE_32(L_snr, L_deposit_l(sign_thr))) + { + L_tmp = L_add(L_snr, 0); + } + BASOP_SATURATE_WARNING_OFF_EVS /* may saturate in BASOP */ +#ifdef BASOP_NOGLOB + *L_snr_sum = L_add_o(*L_snr_sum, L_tmp, &Overflow); /* Q4 */ +#else /* BASOP_NOGLOB */ + *L_snr_sum = L_add(*L_snr_sum, L_tmp); /* Q4 */ +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS +} + +/*-----------------------------------------------------------------* + * dtx_hangover_addition_fx() + * + *-----------------------------------------------------------------*/ + +Word16 dtx_hangover_addition_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word16 vad_flag, /* i Q0 */ + const Word16 lp_snr, /* i Q8 */ + const Word16 cldfb_subtraction, /* i Q0 number of DTX-HO frames CLDFB wants to reduce */ + Word16 *vad_hover_flag_ptr, + VAD_HANDLE hVAD, /* i/o: VAD data handle */ + NOISE_EST_HANDLE hNoiseEst /* i : Noise estimation handle */ +) +{ + Word16 hangover_short_dtx ; + Word16 flag_dtx ; + Word16 tmp; + if (hNoiseEst == NULL) + { + hNoiseEst = st_fx->hNoiseEst; + move16(); + } + + if (hVAD == NULL) + { + move16(); + hVAD = st_fx->hVAD; + } + + + flag_dtx = 0; + move16(); + + /* Determine initial hangover length */ + hangover_short_dtx = 2; + move16(); + + test(); + test(); + if ( ( ( LT_16(lp_snr,(16*256))) + && ( NE_16(st_fx->input_bwidth_fx, NB) )) + || ( GT_16(hVAD->prim_act_he_fx, 31130) ) ) /*.95*Q15*/ + { + hangover_short_dtx = 3; + move16(); + } + + /* Adjust hangover according to activity history */ + if (GT_16(hVAD->vad_prim_cnt_16, 12)) /* 12 requires roughly > 80% primary activity */ + { + hangover_short_dtx = add(hangover_short_dtx,2); + } + + if (GT_16(hVAD->vad_flag_cnt_50, 40)) /* 40 requires roughtly > 80% flag activity */ + { + hangover_short_dtx = add(hangover_short_dtx,5); + } + + /* Keep hangover_short lower than maximum hangover count */ + if (GT_16(hangover_short_dtx, HANGOVER_LONG_FX-1)) + { + hangover_short_dtx = (HANGOVER_LONG_FX-1); + move16(); + } + + /* Only allow short HO if not sufficient active frames in clean speech*/ + + tmp = 3; + move16(); /* default for EVS*/ + if (EQ_16(st_fx->core_fx,AMR_WB_CORE)) + { + tmp = 2; + move16(); /* default for AMRWBIO*/ + } + + /* need to be a bit stricter with the DTXHO in very clean WB, SWB cond for EVS12k8VAD section */ + test(); + test(); + if ( ( NE_16(st_fx->input_bwidth_fx, NB)) /* WB or SWB or FB */ + && ( NE_16(st_fx->core_fx, AMR_WB_CORE) ) + && ( GT_16(lp_snr, 25*256) ) + ) + { + tmp = 2; + move16(); + } + + /* limit dtx hangover addition up to "tmp" frames in clean cond */ + IF ( tmp != 0 ) + { + test(); + test(); + test(); + if ( (GT_16(hangover_short_dtx, tmp)) + && ( (LT_16(hVAD->vad_prim_cnt_16, 7) ) + || ( (GT_16(lp_snr, (16*256)) ) + && (LT_16(hVAD->prim_act_he_fx, 27853) ) /*0.85f*2^15 */ + ) + ) + ) + { + hangover_short_dtx = tmp; + move16(); + } + } + + + /* hangover adjustment from combined FFT+CLDFBVAD */ + IF (NE_16(st_fx->core_fx,AMR_WB_CORE)) + { + hangover_short_dtx = sub(hangover_short_dtx, cldfb_subtraction); + hangover_short_dtx = s_max(hangover_short_dtx, 0); + } + + IF ( vad_flag != 0 ) /* Speech present */ + { + flag_dtx = 1; + move16(); + + /* Add hangover after sufficient # of active frames or sufficient activity during last second */ + test(); + if ( ( GE_16(hVAD->nb_active_frames, ACTIVE_FRAMES_FX)) + || (GT_16(hVAD->vad_flag_cnt_50,45)) ) /* 45 requires roughly > 90% flag activity */ + { + hVAD->hangover_cnt_dtx = 0; + move16(); + } + + /* inside HO period */ + test(); + if( ( LT_16(hVAD->hangover_cnt_dtx, HANGOVER_LONG_FX)) + && (hVAD->hangover_cnt_dtx != 0) ) + { + hVAD->hangover_cnt_dtx = add(hVAD->hangover_cnt_dtx, 1); + } + hVAD->hangover_terminate_flag = 0; + move16();/* float fix FIX_HO_TERMINATE */ + + /* Music hangover when music detected */ + test(); + test(); + test(); + if ( (GT_16(hVAD->prim_act_he_fx,31129)) + && (GT_16(hNoiseEst->Etot_lp_fx,40*256) ) + && (GT_16(hVAD->vad_prim_cnt_16,14) ) + && (GT_16(hVAD->vad_flag_cnt_50,48) ) ) /* 45 requires roughly > 95% flag activity */ + { + hVAD->hangover_cnt_music = 0; + move16(); + } + + /* inside Music HO period */ + test(); + if( ( LT_16(hVAD->hangover_cnt_music, HANGOVER_LONG_MUSIC_FX)) + && (hVAD->hangover_cnt_music != 0) ) + { + hVAD->hangover_cnt_music = add(hVAD->hangover_cnt_music, 1); + } + } + ELSE + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + if(LT_16(hVAD->hangover_cnt_dtx,HANGOVER_LONG_FX)) /* inside HO period */ + { + hVAD->hangover_cnt_dtx = add(hVAD->hangover_cnt_dtx,1); + } + if(LT_16(hVAD->hangover_cnt_music,HANGOVER_LONG_MUSIC_FX)) /* inside HO period */ + { + hVAD->hangover_cnt_music = add(hVAD->hangover_cnt_music,1); + } + + /* fast terminate DTX hangover if st->hangover_terminate_flag is set */ + IF ( hVAD->hangover_terminate_flag != 0 ) + { + hVAD->hangover_cnt = HANGOVER_LONG_FX; + move16(); + hVAD->hangover_cnt_dtx = HANGOVER_LONG_FX; + move16(); + hVAD->hangover_terminate_flag = 0; + move16(); + /* Only shorten music hangover when low energy frames */ + if (LT_16(hNoiseEst->Etot_lp_fx,20*256)) + { + hVAD->hangover_cnt_music = HANGOVER_LONG_MUSIC_FX; + move16(); + } + } + + if( LE_16(hVAD->hangover_cnt_dtx, hangover_short_dtx)) /* "hard" hangover */ + { + flag_dtx = 1; + move16(); + } + + if( LE_16(hVAD->hangover_cnt_music, 15)) /* "hard" hangover music */ + { + flag_dtx = 1; + move16(); + } + } + + + + test(); + if ( flag_dtx != 0 && st_fx->localVAD == 0 ) + { + *vad_hover_flag_ptr = 1; + move16(); + } + + return flag_dtx ; +} + +/*-----------------------------------------------------------------* + * wb_vad() + * + * Voice Activity Detector + *-----------------------------------------------------------------*/ +/* new simplified and harmonized code */ +Word16 wb_vad_fx( + Encoder_State_fx *st_fx, /* i/o: encoder state structure */ + const Word32 fr_bands[], /* i : per band input energy (contains 2 vectors) Q_new+QSCALE*/ + Word16 *noisy_speech_HO, /* o : SC-VBR noisy speech HO flag */ + Word16 *clean_speech_HO, /* o : SC-VBR clean speech HO flag */ + Word16 *NB_speech_HO, /* o : SC-VBR NB speech HO flag */ + Word16 *snr_sum_he, /* o : Output snr_sum as weighted spectral measure*/ + Word16 *localVAD_HE_SAD, + Word8 *flag_noisy_speech_snr , /* o : */ + const Word16 Q_new, /* i : scaling factor Q0 */ + VAD_HANDLE hVAD, /* i/o: VAD data handle */ + NOISE_EST_HANDLE hNoiseEst, /* i : Noise estimation handle */ + Word16 lp_speech_fx, /* i : long term active speech energy average */ + Word16 lp_noise_fx /* i : long term noise energy */ +) +{ + Word16 i, flag=0, hangover_short; + + Word16 snr_sum, thr1=0, thr1_nb_mod, thr2=0, nk=0, nc=0, th_clean=0; + Word16 lp_snr; /* Q8 */ + const Word32 *pt1; + const Word32 *pt2; + const Word32 *pt3; + + Word16 min_snr, sign_thr; + + Word32 L_snr, L_snr_sum ; + Word32 ftmp, ftmp1, ftmp2; + Word16 m_noise_local, e_noise, e_num, m_num, snr, snr_tmp, shift_snr; + + Word16 snr_sumt; + Word32 L_vad_thr; + Word16 hangover_hd; + Word16 snr_idx; + Word16 delta1, delta2, delta3,delta4; + + Word16 flag_he1; + Word16 stmp; + Word32 L_msnr, L_mssnr=0, L_mssnr_hov; + Word16 j, tmp, tmp1, tmp2 ; + Word32 L_tmp, L_tmp1, L_tmp2; + + Word32 L_snr18, L_snr19; /* Q4 */ + Word32 L_msnr18, L_msnr19; /* Q13 */ + Word16 nb_sig_snr; /* Q0 */ + + Word16 nv; + Word16 nv_ofs; /* Q8 */ + Word32 L_snr_sum_HE_SAD; /* Q4 */ + Word16 snr_sum_HE_SAD; /*Q8 log */ + Word16 sign_thr_HE_SAD, min_snr_HE_SAD; + + + Word16 thr1_ol; + Word32 L_snr_sum_ol; + Word16 snr_sum_ol; /* Q8 log */ + + Word32 L_snr_outlier; + Word16 snr_outlier_index; + Word32 L_accum_ener_L; + Word32 L_accum_ener_H; + Word16 vad_bwidth_fx; + Word16 last_7k2_coder_type; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + if (hNoiseEst == NULL) + { + hNoiseEst = st_fx->hNoiseEst; + move16(); + } + + if (hVAD == NULL) + { + move16(); + hVAD = st_fx->hVAD; + } + if ( LT_16(lp_speech_fx , -100*256)) + { + lp_speech_fx = st_fx->lp_speech_fx; + move16(); + } + + if (LT_16(lp_noise_fx, -100*256)) + { + lp_noise_fx = st_fx->lp_noise_fx; + move16(); + } + + vad_bwidth_fx = st_fx->input_bwidth_fx; + move16(); + + L_snr_outlier = L_deposit_l(0); + snr_outlier_index = 0; + move16(); + L_accum_ener_L = L_deposit_l(0); + L_accum_ener_H = L_deposit_l(0); + + L_snr18 = L_deposit_l(0); /* Q4*/ + L_snr19 = L_deposit_l(0); /* Q4 */ + L_msnr18 = L_deposit_l(8192); /* 1.0 Q13*/ + L_msnr19 = L_deposit_l(8192); /* 1.0 Q13 */ + + + IF( EQ_16(vad_bwidth_fx, NB)) + { + st_fx->min_band_fx = 1; + move16(); + st_fx->max_band_fx = 16; + move16(); + } + ELSE + { + st_fx->min_band_fx = 0; + move16(); + st_fx->max_band_fx = 19; + move16(); + } + /*_DIFF_FLOAT_FIX_ -> see around Ln1570, inversion in if conditions compared to float*/ + //PMT("Error in EVS fixed point ?") + /*FIXED EVS */ + /* ELSE IF(((LE_16(st_fx->last_coder_type_fx, UNVOICED)) && (LT_32(L_snr_outlier, MAX_SNR_OUTLIER_2_FX)) && (st_fx->Opt_SC_VBR_fx != 0)) || + ((LE_16(last_7k2_coder_type, UNVOICED)) && (LT_32(L_snr_outlier, MAX_SNR_OUTLIER_2_FX)) && (st_fx->Opt_SC_VBR_fx == 0)))*/ + + /*FLOAT both IVAS and EVS */ + /*if ((snr_outlier_index <= 4 && (st->last_coder_type > UNVOICED) && !st->Opt_SC_VBR) || + (snr_outlier_index <= 4 && (last_7k2_coder_type > UNVOICED) && st->Opt_SC_VBR))*/ + IF ( 1)//st_fx->Opt_SC_VBR_fx) + { + last_7k2_coder_type = st_fx->hSC_VBR->last_7k2_coder_type; + move16(); + } + ELSE + { + last_7k2_coder_type = -1; + move16(); + } + /*---------------------------------------------------------------------* + * set SNR thresholds depending on the input bandwitdh + *---------------------------------------------------------------------*/ + IF( EQ_16(st_fx->max_band_fx,19)) /* WB input */ /* or SWB input */ + { + nk = 3277; + move16(); /*0.1 Q15 */ + nc = 4122 ; + move16(); /*16.1 Q8 */ + nv = 525; + move16();/* 2.05 Q8*/ + nv_ofs = 422; + move16();/* 1.65 Q8*/ + th_clean = TH16_2_FX; + move16();/* 35 Q8 */ + sign_thr = 21; + move16(); /*1.3 Q4 */ + tmp = sub(vad_bwidth_fx, WB); + if ( tmp != 0 ) + { + sign_thr = 28; + move16();/*1.75f; Q4 SWB */ + } + min_snr = 13; + move16(); /*0.8 Q4 WB */ + if ( tmp != 0 ) + { + min_snr = 4; + move16(); /*0.25f; Q4 SWB */ + } + + sign_thr_HE_SAD = 40; + move16();/* 2.5f Q4 */; + min_snr_HE_SAD = 3; + move16(); /* 0.2f Q4 */; + } + ELSE /* NB input */ + { + move16(); + nk = 3277; + move16(); /* 0.1 Q15 */ + nc = 4096; + move16(); /* 16.0 Q8 */ + nv = 1024; + move16(); /* 4.0 Q8 */ + nv_ofs = 294 ; + move16(); /*1.15 Q8*/ + th_clean = TH8_1_FX; + move16(); /*20 Q8 */ + sign_thr = 28; + move16(); /* 1.75 * Q4 SIGN_THR */ + min_snr = 4; + move16(); /* .25 *Q4 MIN_SNR */ + sign_thr_HE_SAD = 42; + move16(); /* 2.65f Q4 */; + min_snr_HE_SAD = 1; + move16(); /* 0.05f Q4 */; + } + + hangover_short = 0; + move16(); + + /* IF( st_fx->Opt_SC_VBR_fx != 0 ) */ + *noisy_speech_HO = 0; + move16(); + *clean_speech_HO = 0; + move16(); + *NB_speech_HO = 0; + move16(); + /* } */ + + /*---------------------------------------------------------------------* + * compute SNR for each band & total + *---------------------------------------------------------------------*/ + + lp_snr = sub(lp_speech_fx, lp_noise_fx); /*Q8 */ + + snr_idx = 2; + move16(); + if( GT_16(lp_snr,4608)) /*18.0 Q8*/ + { + snr_idx = 1; + move16(); + } + if ( GT_16(lp_snr,6144)) /*24.0 Q8*/ + { + snr_idx = 0; + move16(); + } + + + IF ( snr_idx == 0 ) + { + stmp = 6; + move16(); + delta1 = 0; + move16(); /*0.0f in Q13 */ + delta2 = 0; + move16(); /*0.0f in Q13 */ + delta3 = 0; + move16(); /*0.0f in Q13 */ + delta4 = 0; + move16(); + + + /*vad_thr = 2.4f*lp_snr - 42.2f; + vad_thr = min(vad_thr, 80 ); */ + + L_vad_thr = -345702; + move32() ; /* -42.2 Q13*/ + L_vad_thr = L_mac0(L_vad_thr,77,lp_snr) ; /* (2.4)Q5*(lp_snr)Q8 */ + L_vad_thr = L_min(L_vad_thr, 80*(1<<13) ); + } + ELSE IF ( EQ_16(snr_idx,1)) + { + stmp = 6; + move16(); + delta1 = 819; + move16(); /*0.1f in Q13 */ + delta2 = 1638; + move16(); /*0.2f in Q13 */ + delta3 = 1638; + move16(); /*0.2f in Q13 */ + delta4 = 1638; + move16(); /*0.2f in Q13 */ + + /* vad_thr = 2.4f*lp_snr - 40.2f; + vad_thr = min(vad_thr, 80); + */ + L_vad_thr = -329318; + move32() ; /* -40.2 Q13*/ + L_vad_thr = L_mac0(L_vad_thr,77,lp_snr) ; /* (2.4)Q5*(lp_snr)Q8 */ + L_vad_thr = L_min(L_vad_thr, 80*(1<<13) ); + } + ELSE + { + stmp = 9; + move16(); + delta1 = 1638; + move16(); /*0.2f in Q13 */ + delta2 = 3277; + move16(); /*0.4f in Q13 */ + delta3 = 2458; + move16(); /*0.3f in Q13 */ + delta4 = 3277; + move16(); /*0.4f in Q13 */ + /* vad_thr = 2.5f*lp_snr - 10.0f; + vad_thr = max(vad_thr, 1); + */ + L_vad_thr = -81920; + move32() ; /* -10 Q13*/ + L_vad_thr = L_mac0(L_vad_thr,80,lp_snr) ; /* (2.5)Q5*(lp_snr)Q8 */ + L_vad_thr = L_max(L_vad_thr, 1*(1<<13) ); + } + + nb_sig_snr = 20; + move16(); + + pt1 = fr_bands; + pt2 = fr_bands + NB_BANDS; + pt3 = hNoiseEst->bckr_fx; + + L_snr_sum = L_deposit_l(0); + L_snr_sum_HE_SAD = L_deposit_l(0); + snr_sumt = 0; + move16(); + L_mssnr_hov = L_deposit_l(0); + *snr_sum_he = 0; + move16(); + snr_sum_HE_SAD = 0; + move16(); + + + FOR( i=st_fx->min_band_fx; i<=st_fx->max_band_fx; i++ ) + { + ftmp = L_add(*pt1++, 0); + ftmp1 = L_add(*pt2++, 0); + ftmp2 = L_add(*pt3++, 0); + + /*fr_enr = ( 0.2f * st->enrO[i] + 0.4f * ftmp + 0.4f * ftmp1 );*/ + L_tmp = Mult_32_16(hNoiseEst->enrO_fx[i], 13107); /* L_tmp(high word) = Qenr0fx*Q16+1 -16 -> Qener0+1 */ + L_tmp1 = Madd_32_16(L_tmp, ftmp, 26214); /* 26214 = .4 in Q16 */ + L_tmp1 = Madd_32_16(L_tmp1, ftmp1, 26214); /* L_tmp1 re_used a bit later for final snr[i]*/ + + L_tmp2 = Madd_32_16(L_tmp, ftmp, 19661); /* 19661 = 0.3 in Q16 */ + L_tmp2 = Msub_32_16(L_tmp2, ftmp1, -32768); /* -32768= -0.5 in Q16 */ + + IF (GT_32(ftmp,ftmp1)) + { + /*snr[i] = ( 0.2f * st->enrO[i] + 0.4f * ftmp + 0.4f * ftmp1 ) / ftmp2 ;*/ + /*snr[i] = L_tmp1/(ftmp2) */ + IF (ftmp2 != 0) + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + e_noise = norm_l(ftmp2); + m_noise_local = extract_h( L_shl( ftmp2, e_noise ) ); + + m_num = shr(m_num,1); + shift_snr = add(sub(e_num, e_noise),15-4); + + snr_tmp = div_s( m_num, m_noise_local ); +#ifdef BASOP_NOGLOB + L_snr = L_shr_o(snr_tmp, shift_snr, &Overflow); /* L_snr in Q4 */ +#else /* BASOP_NOGLOB */ + L_snr = L_shr(snr_tmp, shift_snr); /* L_snr in Q4 */ +#endif /* BASOP_NOGLOB */ + } + ELSE + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + /* if bckr[i] == 0; approx. L_snr */ + e_noise = add(30+1, abs_s(Q_new)); + + m_num = shr(m_num, 1); + shift_snr = add(sub(e_num, e_noise), 15-4); + + snr_tmp = div_s(m_num, 32767); + L_snr = L_shr(snr_tmp, shift_snr); /*L_snr in Q4*/ + } + } + ELSE + { + /*snr[i] = ( 0.2f * st->enrO[i] + 0.3f * ftmp + 0.5f * ftmp1 ) / ftmp2 ;*/ + /*snr[i] =L_tmp2/( ftmp2 ) */ + IF (ftmp2 != 0) + { + e_num = norm_l(L_tmp2); + m_num = extract_h(L_shl(L_tmp2,e_num)); + + e_noise = norm_l(ftmp2); + m_noise_local = extract_h( L_shl( ftmp2, e_noise ) ); + + m_num = shr(m_num,1); + shift_snr = add(sub(e_num, e_noise),15-4); + + snr_tmp = div_s( m_num, m_noise_local ); +#ifdef BASOP_NOGLOB + L_snr = L_shr_o(snr_tmp, shift_snr, &Overflow); /* L_snr in Q4 */ +#else /* BASOP_NOGLOB */ + L_snr = L_shr(snr_tmp, shift_snr); /* L_snr in Q4 */ +#endif /* BASOP_NOGLOB */ + } + ELSE + { + e_num = norm_l(L_tmp2); + m_num = extract_h(L_shl(L_tmp2,e_num)); + + /* if bckr[i] == 0; approx. L_snr */ + e_noise = add(30+1, abs_s(Q_new)); + + m_num = shr(m_num, 1); + shift_snr = add(sub(e_num, e_noise), 15-4); + + snr_tmp = div_s(m_num, 32767); + L_snr = L_shr(snr_tmp, shift_snr); /*L_snr in Q4*/ + } + } + + if(LT_32(L_snr,2*(1<<4))) + { + nb_sig_snr=sub(nb_sig_snr,1); /* nb_sig_snr--; */ + } + L_snr = L_max(L_snr, 1*(1<<4)); /* if ( snr[i] < 1 ){snr[i] = 1;}*/ + + + /* snr[i] = (float)log10(snr[i]); */ + snr = vad_snr_log_fx(L_snr, ONE_LG10); + + /* snr_sumt += snr[i];*/ + snr_sumt = add(snr_sumt,shr(snr,4)); /*Q4 */ + + +#ifdef BASOP_NOGLOB + tmp = shl_o(snr,5, &Overflow); /* Q8 -> Q13 */ +#else /* BASOP_NOGLOB */ + tmp = shl(snr,5); /* Q8 -> Q13 */ +#endif /* BASOP_NOGLOB */ + IF (LT_16(i,2)) + { +#ifdef BASOP_NOGLOB + tmp = add_o(tmp,delta1, &Overflow); /*Q13 */ +#else /* BASOP_NOGLOB */ + tmp = add(tmp,delta1); /*Q13 */ +#endif /* BASOP_NOGLOB */ + } + ELSE IF (LT_16(i,7)) + { +#ifdef BASOP_NOGLOB + tmp = add_o(tmp,delta2, &Overflow); /*Q13 */ +#else /* BASOP_NOGLOB */ + tmp = add(tmp,delta2); /*Q13 */ +#endif /* BASOP_NOGLOB */ + } + ELSE IF (LT_16(i,18)) + { +#ifdef BASOP_NOGLOB + tmp = add_o(tmp,delta3, &Overflow); /*Q13 */ +#else /* BASOP_NOGLOB */ + tmp = add(tmp,delta3); /*Q13 */ +#endif /* BASOP_NOGLOB */ + } + ELSE + { +#ifdef BASOP_NOGLOB + tmp = add_o(tmp,delta4, &Overflow); /*Q13 */ +#else /* BASOP_NOGLOB */ + tmp = add(tmp,delta4); /*Q13 */ +#endif /* BASOP_NOGLOB */ + } + + tmp1=tmp; + move16(); /* ftmp1 = ftmp; */ + sub(0,0); + if ( i < 7 ) + { +#ifdef BASOP_NOGLOB + tmp1=add_o(tmp,3277, &Overflow); /*.4 in Q13 ftmp1 = ftmp + 0.4f; */ +#else /* BASOP_NOGLOB */ + tmp1=add(tmp,3277); /*.4 in Q13 ftmp1 = ftmp + 0.4f; */ +#endif /* BASOP_NOGLOB */ + } + + tmp=s_min(tmp,16384); /* Q13, ftmp = min(ftmp, 2.0f); */ + tmp1=s_min(tmp1,16384); /* Q13, ftmp1 = min(ftmp1, 2.0f); */ + + L_msnr = L_deposit_l(tmp); /*msnr = 1*tmp;*/ + FOR (j=1; jbckr[i] = L_tmp1/st->bckr[i];*/ + IF (hNoiseEst->bckr_fx[i] != 0) + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + e_noise = norm_l(hNoiseEst->bckr_fx[i]); + m_noise_local = extract_h( L_shl( hNoiseEst->bckr_fx[i], e_noise ) ); + + m_num = shr(m_num,1); + shift_snr = add(sub(e_num, e_noise),15-4); + + snr_tmp = div_s( m_num, m_noise_local ); +#ifdef BASOP_NOGLOB + L_snr = L_shr_o(snr_tmp, shift_snr, &Overflow); /* L_snr in Q4 */ +#else /* BASOP_NOGLOB */ + L_snr = L_shr(snr_tmp, shift_snr); /* L_snr in Q4 */ +#endif /* BASOP_NOGLOB */ + } + ELSE + { + e_num = norm_l(L_tmp1); + m_num = extract_h(L_shl(L_tmp1,e_num)); + + /* if bckr[i] == 0; approx. L_snr */ + e_noise = add(30+1, abs_s(Q_new)); + + m_num = shr(m_num, 1); + shift_snr = add(sub(e_num, e_noise), 15-4); + + snr_tmp = div_s(m_num, 32767); + L_snr = L_shr(snr_tmp, shift_snr); /*L_snr in Q4*/ + } + + + /* conditional snrsum, snr_sum = snr_sum + snr[i];*/ + sign_thr_snr_acc_fx(&L_snr_sum_HE_SAD,L_snr, sign_thr_HE_SAD, min_snr_HE_SAD); + sign_thr_snr_acc_fx(&L_snr_sum, L_snr, sign_thr, min_snr); + + L_snr = L_max(L_snr, 16); /*Q4, if( snr[i] < 1.0f ) { snr[i] = 1.0f;} */ + + /* float saves all snrs in an snr[] vector , + in fix we only save two bands */ + if ( EQ_16(i,18)) + { + L_snr18 = L_add(L_snr, 0); /*Q4 */ + } + if ( EQ_16(i,19)) + { + L_snr19 = L_add(L_snr, 0); /* Q4 */ + } + + /* accumulate background noise energy in bands [0-2] and in bands [3-19]*/ + IF(LT_16(i,3)) + { +#ifdef BASOP_NOGLOB + L_accum_ener_L = L_add_o(L_accum_ener_L , hNoiseEst->bckr_fx[i], &Overflow);/*Q_new+QSCALE */ +#else + L_accum_ener_L = L_add(L_accum_ener_L , hNoiseEst->bckr_fx[i]);/*Q_new+QSCALE */ +#endif + } + ELSE + { +#ifdef BASOP_NOGLOB + L_accum_ener_H = L_add_o(L_accum_ener_H , hNoiseEst->bckr_fx[i], &Overflow);/*Q_new+QSCALE */ +#else + L_accum_ener_H = L_add(L_accum_ener_H , hNoiseEst->bckr_fx[i]);/*Q_new+QSCALE */ +#endif + } + + /* Identify the outlier band */ + IF( GT_32(L_snr, L_snr_outlier)) + { + L_snr_outlier = L_add(L_snr, 0); /*Q4*/ + snr_outlier_index = i; + move16(); + } + } /* end of band loop */ + + test(); + test(); + test(); /* one additional test for ELSE IF */ + IF ( (EQ_16(st_fx->max_band_fx, 19)) + && ( GT_32(L_snr18, 5*(1<<4)) ) + && ( GT_32(L_snr19, 5*(1<<4)) ) ) + { + /* mssnr = (mssnr + 3*(msnr18 + msnr19)) * 0.77f; */ + /* mssnr = (mssnr*.77f + 2.31f*(msnr18 + msnr19)); */ + L_tmp1 = Mult_32_16(L_mssnr, 25231 ); /* Q13+Q15+1-16 --> Q13 */ + L_tmp = Mult_32_16(L_shl(L_add(L_msnr18, L_msnr19),2),18924 ); /* Q(13+2)+Q(15-2)+1-16 --> Q13 */ + L_tmp = L_add( L_tmp1, L_tmp); + if ( GT_32(L_tmp, L_mssnr)) + { + L_mssnr = L_tmp; + } + } + ELSE IF ( (snr_idx != 0) + && GT_16(nb_sig_snr, 13) ) + { + L_tmp = -126976; + move32() ; /* -15.5 Q13 */ + L_tmp = L_mac0(L_tmp,80,lp_snr) ; /* 2.5f(Q5)*lp_snr(Q8) - 15.5f */ + if ( L_tmp > 0 ) /* 2.5f*lp_snr - 15.5f > 0 */ + { + L_mssnr = L_add(L_mssnr, L_tmp); /* mssnr += 2.5f*lp_snr - 15.5f; */ + } + } + + + /* Separated SNR_SUM outlier modification */ + L_snr_sum_ol = L_snr_sum; /* snr_sum_ol = snr_sum; */ + + test(); + test(); + test(); + IF( ( EQ_16(st_fx->max_band_fx, 19)) + && LT_32(L_snr_outlier , MAX_SNR_OUTLIER_3_FX) + && GT_16(snr_outlier_index, 3) + && LT_16(snr_outlier_index, MAX_SNR_OUTLIER_IND_FX) ) + { + /* Update the total SNR only for WB signals */ + + + /* corresponding float section + if( (accum_ener_L > OUTLIER_THR_1 * accum_ener_H ) || (snr_outlier < MAX_SNR_OUTLIER_1) ) + { + snr_sum_ol = SNR_OUTLIER_WGHT_1 * (snr_sum_ol - snr_outlier); + } + else if( (accum_ener_L > OUTLIER_THR_2 * accum_ener_H ) || (snr_outlier < MAX_SNR_OUTLIER_2) ) + { + snr_sum_ol = SNR_OUTLIER_WGHT_2 * (snr_sum_ol - snr_outlier); + } + else + { + snr_sum_ol = SNR_OUTLIER_WGHT_3 * (snr_sum_ol - snr_outlier); + } + } */ + + test(); + test(); + IF( LT_32(L_accum_ener_H, Mult_32_16(L_accum_ener_L,INV_OUTLIER_THR_1_FX))/* float:: (accum_ener_L*INV_OUTLIER_THR_1 > accum_ener_H ) !!! */ + || LT_32(L_snr_outlier,MAX_SNR_OUTLIER_1_FX) ) + + { + /* as weight1 is 1.0 we do not need to multiply here , i.e. no need to loose any precisison */ + L_snr_sum_ol = L_sub(L_snr_sum_ol,L_snr_outlier); /*Q4 */ + + } + ELSE IF( LT_32(L_accum_ener_H, Mult_32_16(L_accum_ener_L,INV_OUTLIER_THR_2_FX))/* float:: (accum_ener_L *INV_OUTLIER_THR_2 > accum_ener_H ) !!! */ + || LT_32(L_snr_outlier,MAX_SNR_OUTLIER_2_FX) ) + { + /* L_snr_sum = SNR_OUTLIER_WGHT_2 * (snr_sum - snr_outlier); */ + + /* 1.01*x -> (1*x + 0.01*x) to not drop down to Q3 */ + L_tmp = L_sub(L_snr_sum_ol,L_snr_outlier); + L_tmp2 = Mult_32_16(L_tmp, 20972); /* 0.01(in Q21)= 20972 Q4*Q21+1-16 -> Q10 */ + L_snr_sum_ol = L_add(L_tmp, L_shr(L_tmp2,6)); /* Q4 */ + } + ELSE + { + /* L_snr_sum = SNR_OUTLIER_WGHT_3 * (snr_sum - snr_outlier);*/ + /* 1.02*x -> (1*x + 0.02*x) to not drop down to Q3 */ + L_tmp = L_sub(L_snr_sum_ol,L_snr_outlier); + L_tmp2 = Mult_32_16(L_tmp, 20972); /* 0.02(in Q20)= 20972 Q4*Q20+1-16 -> Q9 */ + L_snr_sum_ol = L_add(L_tmp, L_shr(L_tmp2, 5)); /* Q4 */ + + } + } + /*st_fx->snr_sum_vad_fx = 0.5f * st->snr_sum_vad + 0.5f * snr_sum_ol;*/ +#ifdef BASOP_NOGLOB + hVAD->L_snr_sum_vad_fx = L_shr(L_add_o(hVAD->L_snr_sum_vad_fx ,L_snr_sum_ol, &Overflow),1); /*Q4*/ +#else /* BASOP_NOGLOB */ + hVAD->L_snr_sum_vad_fx = L_shr(L_add(hVAD->L_snr_sum_vad_fx ,L_snr_sum_ol ),1); /*Q4*/ +#endif /* BASOP_NOGLOB */ + + /* snr_sum_ol = 10.0f * (float)log10( snr_sum_ol ); */ + snr_sum_ol = vad_snr_log_fx(L_snr_sum_ol, LG10); + snr_sum = snr_sum_ol; + move16(); /* note for NB no outlier modification */ + + /* snr_sum_HE_SAD = 10.0f * (float)log10( snr_sum_HE_SAD ); */ + snr_sum_HE_SAD = vad_snr_log_fx( L_snr_sum_HE_SAD, LG10); + + *snr_sum_he=snr_sum_HE_SAD; + move16(); /* *snr_sum_he=snr_sum_HE_SAD; */ + + + /*---------------------------------------------------------------------* + * compute thr1 for SAD decision + *---------------------------------------------------------------------*/ + lp_snr = sub(lp_speech_fx, lp_noise_fx); /*Q8*/ + + sub(0,0); + IF ( LT_16(lp_snr, hNoiseEst->sign_dyn_lp_fx)) + { + lp_snr = add(lp_snr,1<<8); /* lp_snr += 1; */ + + if (GT_16(lp_snr, hNoiseEst->sign_dyn_lp_fx)) + { + lp_snr = hNoiseEst->sign_dyn_lp_fx; + move16(); + } + } + + /*thr1 = nk * lp_snr + nc*1.0 + nv * ( st->Etot_v_h2 - nv_ofs); */ /* Linear function for noisy speech */ + + L_tmp = L_shl(L_mult(sub(hNoiseEst->Etot_v_h2_fx, nv_ofs), nv ),7); /* Q8+Q8+1 +7 --> Q24 */ + L_tmp = L_mac(L_tmp, nc, (Word16)32767); /* Q8+Q15+1 = Q24 */ + thr1 = mac_r(L_tmp, lp_snr, nk ); /* Q8+Q15+1 - 16 --> Q8 */ +#ifdef IVAS_CODE + if (st->element_mode > EVS_MONO && hNoiseEst->first_noise_updt_cnt < 100) + { + /* lower threshold during warmup time */ + thr1 -= 10.0f; + vad_thr = 0.f; + } +#endif + IF (GT_16(lp_snr, (Word16)20*(1<<8))) /* if (lp_snr > 20.0f )*/ + { +#ifdef IVAS_CODE + if (st->element_mode == EVS_MONO || hNoiseEst->first_noise_updt_cnt >= 100) +#endif + { + /* thr1 = thr1 + 0.3f * (lp_snr - 20.0f); */ + thr1 = add(thr1, mult(9830, sub(lp_snr, (Word16)20 * (1 << 8)))); /* Q15*Q8+1 -16 --> Q8 */ + + test(); + test(); + test(); + if (EQ_16(st_fx->max_band_fx, 16) + && GT_16(lp_snr, 40 * 256) + && GT_16(thr1, 6600) + && LT_16(lp_speech_fx, 11520)) + { + thr1 = 6600; + } + } + } + + + + + /*---------------------------------------------------------------------* + * WB input + * SNR threshold computing + * Hangover control & final VAD decision + *---------------------------------------------------------------------*/ + + IF( NE_16(vad_bwidth_fx, NB)) + { + + /* Outlier Detection first calculates thr1_ol and snr_sum_ol instead of + modyfying thr1 and snr_sum */ + + thr1_ol = thr1; + move16(); + hangover_short = 3; + move16(); + + IF( LT_16(lp_snr,th_clean)) + { + hangover_short = 4; + move16(); + + /* In this section the modified nk, and nc are used */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); /*_DIFF_FLOAT_FIX_ -> the conditions around Opt_SC_VBR_fx are invertered compared to float + ### st_fx->Opt_SC_VBR_fx!=0 vs !st_fx->Opt_SC_VBR #####*/ + test(); + IF( LE_16(snr_outlier_index, 4) && ( ( GT_16(st_fx->last_coder_type_fx,UNVOICED) && (st_fx->Opt_SC_VBR_fx!=0)) || + ( GT_16(last_7k2_coder_type, UNVOICED) && ( st_fx->Opt_SC_VBR_fx == 0 ) ) ) ) + + + { + thr1_ol = sub(thr1_ol,(Word16)(1<<8)); /*thr1_ol = thr1 - 1.0f ; */ + /*snr_sum_ol = 10.0f * (float)log10( hVAD->L_snr_sum_vad_fx );*/ + snr_sum_ol = vad_snr_log_fx(hVAD->L_snr_sum_vad_fx, LG10); /* snr in Q8 */ + + } + ELSE IF ( ((LE_16(st_fx->last_coder_type_fx, UNVOICED)) && (LT_32(L_snr_outlier,MAX_SNR_OUTLIER_2_FX)) && ( st_fx->Opt_SC_VBR_fx != 0)) || + ((LE_16(last_7k2_coder_type, UNVOICED) ) && (LT_32(L_snr_outlier,MAX_SNR_OUTLIER_2_FX)) && ( st_fx->Opt_SC_VBR_fx == 0 ) ) ) + + { + /* thr1_ol = thr1 + (float)(1.0f - 0.04f * snr_outlier); */ + L_tmp2 = Msub_32_16( (Word32)(1<<(24-16)), L_snr_outlier, 20972 ); /* (1.0)Q24(Q8 in high 32bit word) - Q4*Q19+1 */ + tmp2 = round_fx( L_shl(L_tmp2,16)); /* high word is in Q8 */ + thr1_ol = add(thr1_ol, tmp2 ); /* (Q8 , Q8) */ + } + ELSE + { + /*thr1_ol = thr1 + max(0, (float)(0.6f - 0.01f * L_snr_outlier)); */ + thr1_ol = thr1; + move16(); + L_tmp2 = Msub_32_16( (Word32)614 , L_snr_outlier, 20972); /* .6*1024= */ /* 0.6 Q26(Q10 in high word) - Q4*Q21+1 */ +#ifdef BASOP_NOGLOB + tmp2 = round_fx(L_shl_o(L_tmp2,14, &Overflow)); /* Q10(high word)+ 14 -16 --> Q8*/ +#else /* BASOP_NOGLOB */ + tmp2 = round_fx(L_shl(L_tmp2,14)); /* Q10(high word)+ 14 -16 --> Q8*/ +#endif + if(L_tmp2 > 0) + { + thr1_ol = add(thr1_ol, tmp2 ); /* Q24 >>16 + Q8 */ + } + } + } + + /* apply outlier modification */ + snr_sum = snr_sum_ol; + move16(); /*NB s*/ + thr1 = thr1_ol; + move16(); + + /* DTX HANGOVER is in pre_proc_fx() */ + flag_he1 = 0; + move16(); + + IF ( GT_32(L_mssnr, L_vad_thr)) + { + flag_he1 = 1; + move16(); /* he1 primary decision */ + hVAD->nb_active_frames_he1 = add(hVAD->nb_active_frames_he1,1); /* Counter of consecutive active speech frames */ + + IF ( GE_16(hVAD->nb_active_frames_he1,ACTIVE_FRAMES_FX)) + { + hVAD->nb_active_frames_he1 = ACTIVE_FRAMES_FX; + move16(); + hVAD->hangover_cnt_he1 = 0; + move16(); /* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + /* inside HO period */ + test(); + if ( sub(hVAD->hangover_cnt_he1, HANGOVER_LONG_HE_FX) < 0 &&hVAD->hangover_cnt_he1 != 0 ) + { + hVAD->hangover_cnt_he1 = add(hVAD->hangover_cnt_he1 ,1); + } + + if ( hVAD->soft_hangover > 0 ) + { + hVAD->soft_hangover = sub(hVAD->soft_hangover ,1); + } + } + ELSE + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + hVAD->nb_active_frames_he1 = 0; + move16(); + } + + + + + IF ( GT_16(hVAD->voiced_burst, 3)) + { + IF ( LT_16(hVAD->bcg_flux_fx, 640)) /* Q4 */ + { + hVAD->soft_hangover = hangover_sf_tbl[add(snr_idx,3)]; + move16(); + } + ELSE + { + hVAD->soft_hangover = hangover_sf_tbl[snr_idx]; + move16(); + } + } + + + hangover_hd = hangover_hd_tbl[snr_idx]; + move16(); + + IF ( LT_16(hVAD->bcg_flux_fx, 640)) + { + hangover_hd = add(shr(hangover_hd,1), 1); + move16(); + } + + /* VAD hangover for he1 */ + test(); + IF ( flag_he1 == 0 && hVAD->soft_hangover > 0 ) + { + IF ( GT_32(L_mssnr_hov, L_vad_thr)) + { + flag_he1 = 1; + move16(); + hVAD->soft_hangover=sub(hVAD->soft_hangover,1); + } + ELSE + { + hVAD->soft_hangover=0; + move16(); + } + + if( hVAD->soft_hangover < 0) + { + hVAD->soft_hangover=0; + move16(); + } + } + + test(); + test(); + IF ( (flag_he1 == 0) + && (LT_16(hVAD->hangover_cnt_he1, hangover_hd) ) + && (hVAD->soft_hangover == 0 ) ) + { + flag_he1 = 1; + move16(); + hVAD->hangover_cnt_he1 = add(hVAD->hangover_cnt_he1,1); + } + + + + /* Calculate background stationarity */ + test(); + IF ( flag_he1 == 0 && hNoiseEst->first_noise_updt > 0 ) + { + IF ( GT_16(snr_sumt, hVAD->bcg_flux_fx)) + { + IF (hVAD->bcg_flux_init-- > 0 ) + { + IF ( GT_16(snr_sumt,add(hVAD->bcg_flux_fx,800))) + { + /*st->bcg_flux = 0.9f * st->bcg_flux + (1-0.9f)*(st->bcg_flux+50);*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,29491),add(hVAD->bcg_flux_fx,800),3277); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.9f * st->bcg_flux + (1-0.9f)*snr_sumt*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,29491),snr_sumt,3277); /*Q4 */ + } + } + ELSE + { + IF ( GT_16(snr_sumt,add(hVAD->bcg_flux_fx,160))) + { + /*st->bcg_flux = 0.99f * st->bcg_flux + (1-0.99f)*(st->bcg_flux+10);*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,32440),add(hVAD->bcg_flux_fx,160),328); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.99f * st->bcg_flux + (1-0.99f)*snr_sumt;*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,32440),snr_sumt,328); /*Q4 */ + } + } + } + ELSE + { + IF (hVAD->bcg_flux_init-- > 0 ) + { + IF ( LT_16(snr_sumt,sub(hVAD->bcg_flux_fx,480))) + { + /*st->bcg_flux = 0.95f * st->bcg_flux + (1-0.95f)*(st->bcg_flux-30);*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,31130),sub(hVAD->bcg_flux_fx,480),1638); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.95f * st->bcg_flux + (1-0.95f)*snr_sumt;*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,31130),snr_sumt,1638); /*Q4 */ + } + } + ELSE + { + IF ( LT_16(snr_sumt,sub(hVAD->bcg_flux_fx,160))) + { + /*st->bcg_flux = 0.9992f * st->bcg_flux + (1-0.9992f)*(st->bcg_flux-10);*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,32742),sub(hVAD->bcg_flux_fx,160),26); /*Q4 */ + } + ELSE + { + /*st->bcg_flux = 0.9992f * st->bcg_flux + (1-0.9992f)*snr_sumt;*/ + hVAD->bcg_flux_fx = mac_r(L_mult(hVAD->bcg_flux_fx,32742),snr_sumt,26); /*Q4 */ + } + } + } + + hVAD->bcg_flux_init = s_max(hVAD->bcg_flux_init,0); + } + + flag = 0; + move16(); + st_fx->localVAD = 0; + move16(); + /* if ( snr_sum > thr1 && flag_he1 == 1 ) *//* Speech present */ + test(); + + IF ( (GT_16(snr_sum, thr1))&&(EQ_16(flag_he1,1))) /* Speech present */ + { + flag = 1; + move16(); + st_fx->localVAD = 1; + move16(); + + hVAD->nb_active_frames = add(hVAD->nb_active_frames,1); /* Counter of consecutive active speech frames */ + + IF ( GE_16(hVAD->nb_active_frames,ACTIVE_FRAMES_FX)) + { + hVAD->nb_active_frames = ACTIVE_FRAMES_FX; + move16(); + hVAD->hangover_cnt = 0; + move16(); /* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + /* inside HO period */ + test(); + if( LT_16(hVAD->hangover_cnt,HANGOVER_LONG_FX) + &&hVAD->hangover_cnt != 0 ) + { + hVAD->hangover_cnt = add(hVAD->hangover_cnt,1); + } + } + ELSE + { + /* Reset the counter of speech frames necessary to start hangover algorithm */ + hVAD->nb_active_frames = 0; + move16(); + + if( LT_16(hVAD->hangover_cnt,HANGOVER_LONG_FX)) /* inside HO period */ + { + hVAD->hangover_cnt = add(hVAD->hangover_cnt,1); + } + + + IF( LE_16(hVAD->hangover_cnt, hangover_short)) /* "hard" hangover */ + { + test(); + test(); + if (EQ_16(st_fx->element_mode, EVS_MONO) && (LT_16(lp_snr,th_clean)) && (st_fx->Opt_SC_VBR_fx != 0 ) && (GE_16(hVAD->hangover_cnt, 2)) ) + { + *noisy_speech_HO = 1; + move16(); + } + test(); + test(); + if (EQ_16(st_fx->element_mode, EVS_MONO) && (GE_16(lp_snr,th_clean)) && (st_fx->Opt_SC_VBR_fx != 0 ) && (GE_16(hVAD->hangover_cnt, 2) ) ) + { + *clean_speech_HO = 1; + move16(); + } + flag = 1; + move16(); /*HO*/ + } + } + + + /* localVAD and vad_flag for HE-SAD - in parallel with normal localVAD and vad_flag */ + + *localVAD_HE_SAD = 0; + move16(); + + test(); + IF ( (GT_16(snr_sum_HE_SAD, thr1)) + && (EQ_16(flag_he1, 1) ) ) /* Speech present */ + { + + *localVAD_HE_SAD = 1; + move16(); + } + } /* end of WB SWB */ + + /*---------------------------------------------------------------------* + * NB input + * SNR threshold computing + * Hangover control & final VAD decision + *---------------------------------------------------------------------*/ + + ELSE /* NB input */ + { + /* Add localVAD_HE_SAD also for NB operation for use with speech music classifier */ + *localVAD_HE_SAD = 0; + move16(); + if (GT_16(snr_sum_HE_SAD, thr1)) + { + *localVAD_HE_SAD = 1; + move16(); + } + + st_fx->localVAD = 0; + move16(); /* safety inits for fx */ + IF ( GT_16(snr_sum,thr1)) /* Speech present, possibly in hangover */ + { + hVAD->nb_active_frames = add(hVAD->nb_active_frames,1); /* Counter of consecutive active speech frames */ + IF ( GE_16(hVAD->nb_active_frames,ACTIVE_FRAMES_FX)) + { + hVAD->nb_active_frames = ACTIVE_FRAMES_FX; + move16(); + hVAD->hangover_cnt = 0; + move16();/* Reset the counter of hangover frames after at least "active_frames" speech frames */ + } + + st_fx->localVAD = 1; + move16(); + } + ELSE + { + hVAD->nb_active_frames = 0; + move16(); /* Reset the counter of speech frames necessary to start hangover algorithm */ + /* st_fx->localVAD = 0; move16(); */ /* set above */ + } + + thr1_nb_mod = thr1; + move16(); /* thr1 may be adjusted after this point */ + IF( LT_16(hVAD->hangover_cnt,HANGOVER_LONG_NB_FX)) + { + hVAD->hangover_cnt = add(hVAD->hangover_cnt,1); + + IF( LT_16(lp_snr, 4864 )) /*19.0f Q8*/ /* very low SNR */ + { + thr1_nb_mod = sub(thr1_nb_mod , 1331); /*thr1 -= 5.2f;*/ + } + ELSE IF( LT_16(lp_snr, 8960)) /*35 in Q8 */ /* low SNR */ + { + thr1_nb_mod = sub(thr1_nb_mod , 512); /*thr1 -= 2.0f;*/ + } + } + + + thr2 = sub(thr1_nb_mod, 384); /*thr2 = thr1 - 1.5f; , clean speech */ + + /* -dtx condition dependency in noisy speech */ + tmp = 333; + move16(); /* 1.3f; */ + if ( st_fx->Opt_DTX_ON_fx == 0 ) + { + tmp = 282; + move16(); /* 1.10f; */ + } + if (LT_16(lp_snr,th_clean)) + { + thr2 = sub(thr1_nb_mod, tmp); /*thr2 = thr1 - [ 1.10 || 1.3 ];*/ + } + + + flag = 0; + move16(); + IF ( GT_16(snr_sum, thr1_nb_mod)) /* Speech assumed present, even though lowered thr1 */ + { + flag = 1; + move16(); + } + + + + test(); + IF ( (LT_16(snr_sum, thr1_nb_mod)) + && (GT_16(snr_sum, thr2)) ) /* Speech present */ + { + flag = 1; + move16(); + st_fx->localVAD = 0; + move16(); + + if (EQ_16(st_fx->element_mode, EVS_MONO)) + { + *NB_speech_HO = 1; + } + move16(); + } + thr1 = thr1_nb_mod ; + move16(); /* needed for st_fx->vadnoise_fx update below */ + } /* end of NB */ + + + + /* *flag_noisy_speech_snr is a Word8 parameter */ + *flag_noisy_speech_snr = 0; /*_DIFF_FLOAT_FIX_ -> this initialisation is not done here in float */ + move16(); + IF( vad_bwidth_fx != NB ) + { + if(LT_16(lp_snr, TH16_2_NFLAG_FX )) /*now 27, original threshold: 35dB*/ + { + *flag_noisy_speech_snr = 1; + move16(); + } + } + ELSE + { + if(LT_16(lp_snr, TH8_1_NFLAG_FX )) /* now 20.0 */ + { + *flag_noisy_speech_snr = 1; + move16(); + } + } + + if (st_fx->hSC_VBR != NULL) + { + /* SC-VBR */ + st_fx->hSC_VBR->vadsnr_fx = snr_sum; + move16(); /* for ppp, voiced_enc */ + st_fx->hSC_VBR->vadnoise_fx = thr1; + move16(); /* used in nb for find_uv */ + } + + /* Updates */ + hVAD->prim_act_quick_fx = mult_r(26214,hVAD->prim_act_quick_fx); /*Q15 */ + + if(st_fx->localVAD != 0) + { + hVAD->prim_act_quick_fx = add(6554,hVAD->prim_act_quick_fx ); /*Q15 */ + } + + hVAD->prim_act_slow_fx = mult_r(32440,hVAD->prim_act_slow_fx); /*Q15 */ + + if(st_fx->localVAD != 0) + { + hVAD->prim_act_slow_fx = add(328, hVAD->prim_act_slow_fx ); /*Q15 */ + } + + tmp = hVAD->prim_act_slow_fx; + move16(); + if (LE_16(hVAD->prim_act_quick_fx,hVAD->prim_act_slow_fx)) + { + tmp=hVAD->prim_act_quick_fx; + move16(); + } + /*st->prim_act = 0.1f * tmp + (1.0f-0.1f)* st->prim_act;*/ + hVAD->prim_act_fx = mac_r(L_mult(3277,tmp),29491,hVAD->prim_act_fx); + + + + hVAD->prim_act_quick_he_fx = mult_r(26214,hVAD->prim_act_quick_he_fx); /*Q15 */ + if(*localVAD_HE_SAD != 0) + { + hVAD->prim_act_quick_he_fx = add(6554,hVAD->prim_act_quick_he_fx ); /*Q15 */ + } + + hVAD->prim_act_slow_he_fx = mult_r(32440,hVAD->prim_act_slow_he_fx); /*Q15 */ + if(*localVAD_HE_SAD != 0) + { + hVAD->prim_act_slow_he_fx = add(328, hVAD->prim_act_slow_he_fx ); /*Q15 */ + } + + tmp = hVAD->prim_act_slow_he_fx; + move16(); + if (LE_16(hVAD->prim_act_quick_he_fx,hVAD->prim_act_slow_he_fx)) + { + tmp = hVAD->prim_act_quick_he_fx; + move16(); + } + hVAD->prim_act_he_fx = mac_r(L_mult(3277,tmp),29491, hVAD->prim_act_he_fx); + + + if (L_and(hVAD->vad_flag_reg_H, (Word32) 0x40000L) != 0) /* 0x4000L = 0x01L << 18 */ + { + hVAD->vad_flag_cnt_50 = sub(hVAD->vad_flag_cnt_50,1); + } + + hVAD->vad_flag_reg_H = L_shl(L_and(hVAD->vad_flag_reg_H, (Word32) 0x3fffffffL ), 1); + + + if (L_and(hVAD->vad_flag_reg_L, (Word32) 0x40000000L) != 0) + { + hVAD->vad_flag_reg_H = L_or(hVAD->vad_flag_reg_H, 0x01L); + } + + hVAD->vad_flag_reg_L = L_shl(L_and(hVAD->vad_flag_reg_L, (Word32) 0x3fffffffL ), 1); + + + IF ( flag != 0 ) /* should not include the extra DTX hangover */ + { + hVAD->vad_flag_reg_L = L_or(hVAD->vad_flag_reg_L, 0x01L); + hVAD->vad_flag_cnt_50 = add(hVAD->vad_flag_cnt_50, 1); + } + + + if (L_and(hVAD->vad_prim_reg, (Word32) 0x8000L) != 0) /* 0x8000L = 1L << 15 */ + { + hVAD->vad_prim_cnt_16 = sub(hVAD->vad_prim_cnt_16,1); + } + + hVAD->vad_prim_reg = L_shl(L_and(hVAD->vad_prim_reg, (Word32) 0x3fffffffL ), 1); + + IF ( st_fx->localVAD != 0 ) + { + hVAD->vad_prim_reg = L_or(hVAD->vad_prim_reg, 0x01L); + hVAD->vad_prim_cnt_16 = add(hVAD->vad_prim_cnt_16,1); + } + + return flag; +} + + + + diff --git a/lib_enc/vad_param_updt_fx.c b/lib_enc/vad_param_updt_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..c1313b3d738747ac51ae1741e6b6b9e032c8d317 --- /dev/null +++ b/lib_enc/vad_param_updt_fx.c @@ -0,0 +1,204 @@ +/*==================================================================================== + 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 "ivas_stat_enc.h" /* Function prototypes */ +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-------------------------------------------------------------------* + * vad_param_updt() + * + * Update parameters used by VAD + *--------------------------------------------------------------------*/ + +void vad_param_updt_fx( + Encoder_State_fx *st_fx, /* i/o: state structure */ + const Word16 old_pitch1, /* i : OL pitch value from last frame */ + const Word16 corr_shift, /* i : correlation shift Q15*/ + const Word16 corr_shiftR, /* i : correlation shift */ + const Word16 Az[], /* i: a coeffs Q12 */ + FRONT_VAD_ENC_HANDLE hFrontVad[], /* i/o: front-VAD handles */ + const Word16 n_channels /* i : number of channels */ +) +{ + Word16 voice_tmp, pitch_tmp; + Word32 L_tmp; + Word16 refl[M+1]; + Word16 tmp1,tmp2; + Word16 tmp_active_flag; + Word16 i, ini_frame, corr_shift_temp[2]; + VAD_HANDLE hVAD; + DTX_ENC_HANDLE hDtxEnc = st_fx->hDtxEnc; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + corr_shift_temp[0] = corr_shift; + corr_shift_temp[1] = corr_shiftR; + move16(); move16(); + + hVAD = st_fx->hVAD; + ini_frame = st_fx->ini_frame_fx; + move16();move16(); + + IF (hFrontVad != NULL) + { + hVAD = hFrontVad[0]->hVAD; + ini_frame = hFrontVad[0]->ini_frame; + move16(); move16(); + } + FOR(i = 0; i < n_channels; i++) + { + if (EQ_16(i, 1)) + { + hVAD = hFrontVad[1]->hVAD; + move16(); + } + IF(!st_fx->Opt_AMR_WB_fx) + { + /* fix explanation + , after function dtx_fx, the "vad_flag" parameter can not be used for SID scheduling purposes any longer + as dtx_fx can schedules active frames even if the initial analyzed vad_flag is 0 ) + in the worst case without the fix an active frame could be classified as SID frame, quite/very unlikley though + */ + tmp_active_flag = 0; + move16(); + test(); + if ((NE_32(st_fx->core_brate_fx, (Word32)SID_2k40)) && (st_fx->core_brate_fx != 0)) /* Note, core_brate_fx can be -1 */ + { + tmp_active_flag = 1; + move16(); /* reqires active coding according to dtx_fx logic */ + } + test(); + test(); + IF((st_fx->Opt_DTX_ON_fx != 0) && (tmp_active_flag == 0) && (GT_16(ini_frame, 3))) + + + { + /* update the counter of consecutive inactive frames in DTX */ + hVAD->consec_inactive = add(hVAD->consec_inactive, 1); + IF(GT_16(hVAD->consec_inactive, 5)) + { + hVAD->consec_inactive = 5; + move16(); + } + + IF(EQ_16(hVAD->consec_inactive, 5)) + { + /* compute spectral tilt parameter */ + a2rc_fx(&Az[1], refl, M); /* cast to kill MSVC warning */ + /* i: Az in Q12 */ + /* o: refl in Q15 */ + + IF(EQ_16(hVAD->spectral_tilt_reset, 1)) + { + hVAD->spectral_tilt_reset = 0; + move16(); + hVAD->running_avg_fx = refl[0]; + move16(); /*Q15*/ + hVAD->ra_deltasum_fx = 0; + move16(); /*Q15*/ + } + + /* st_fx->ra_deltasum_fx += (0.80f * st_fx->running_avg_fx + 0.20f * refl[0]) - st_fx->running_avg_fx; + st_fx->running_avg_fx = 0.80f * st_fx->running_avg_fx + 0.20f * refl[0]; */ + tmp1 = mult(6553, hVAD->running_avg_fx); /* = -0.80f * st_fx->running_avg_fx + st_fx->running_avg_fx*/ + tmp2 = mult(6553, refl[0]); + hVAD->ra_deltasum_fx = add(hVAD->ra_deltasum_fx, sub(tmp2, tmp1)); + move16(); + + tmp1 = mult(26214, hVAD->running_avg_fx); + hVAD->running_avg_fx = add(tmp1, tmp2); + move16(); + + IF(GT_16(abs_s(hVAD->ra_deltasum_fx), 6553)) /*0.2 in Q15*/ + { + hVAD->spectral_tilt_reset = 1; + move16(); + hVAD->running_avg_fx = 0; + move16(); + hVAD->ra_deltasum_fx = 0; + move16(); + hVAD->trigger_SID = 1; + move16(); + } + } + } + ELSE + { + hVAD->trigger_SID = 0; + move16(); + hVAD->consec_inactive = 0; + move16(); + } + + IF( EQ_16(hVAD->trigger_SID, 1)) + { + IF(GE_16(hDtxEnc->cng_cnt, 8)) + { + /* Declare SID frame due to spectral tilt changes */ + hDtxEnc->cnt_SID = 1; + move16(); + st_fx->core_brate_fx = SID_2k40; + move16(); + hVAD->trigger_SID = 0; + move16(); + } + ELSE IF(EQ_32(st_fx->core_brate_fx, SID_2k40)) + { + /* SID fame has already been declared before */ + hVAD->trigger_SID = 0; + move16(); + } + } + } + + + + /* (voicing[0] + voicing[1] + voicing[2]) / 3 + corr_shift */ + L_tmp = L_mult(st_fx->voicing_fx[0], 10923); + L_tmp = L_mac(L_tmp, st_fx->voicing_fx[1], 10923); + L_tmp = L_mac(L_tmp, st_fx->voicing_fx[2], 10923); /*Q15 */ +#ifdef BASOP_NOGLOB + L_tmp = L_mac_o(L_tmp, corr_shift_temp[i], 32767, &Overflow); /*Q15 */ + voice_tmp = round_fx_o(L_tmp, &Overflow); /*Q15 */ +#else /* BASOP_NOGLOB */ + L_tmp = L_mac(L_tmp, corr_shift_temp[i], 32767); /*Q15 */ + voice_tmp = round_fx(L_tmp); /*Q15 */ +#endif + + /* abs(pitch[0] - *pitO) + abs(pitch[1] - pitch[0]) + abs(pitch[2] - pitch[1]) */ + pitch_tmp = abs_s(sub(st_fx->pitch_fx[0], old_pitch1)); /*Q0 */ + pitch_tmp = add(pitch_tmp, abs_s(sub(st_fx->pitch_fx[1], st_fx->pitch_fx[0]))); /*Q0 */ + pitch_tmp = add(pitch_tmp, abs_s(sub(st_fx->pitch_fx[2], st_fx->pitch_fx[1]))); /*Q0 */ + + + /* if( (voicing[0] + voicing[1] + voicing[2]) / 3 + corr_shift > 0.65 && + (short)(abs(pitch[0] - st->pitO) + abs(pitch[1] - pitch[0]) + abs(pitch[2] - pitch[1])) / 3 < 14 ) + { + (st->voiced_burst)++; + } else { + st->voiced_burst = 0; + } */ + + hVAD->voiced_burst = add(hVAD->voiced_burst, 1); + move16(); + test(); + if ((LE_16(voice_tmp, 21299)) /* 0.65 in Q15 */ + || (GE_16(pitch_tmp, 42))) /*3*14 = 42 Q0 */ + { + hVAD->voiced_burst = 0; + move16(); + } + + } + + + return; +} diff --git a/lib_enc/vad_proc_fx.c b/lib_enc/vad_proc_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..14bf4de21df72debea513f67839f6292f743f360 --- /dev/null +++ b/lib_enc/vad_proc_fx.c @@ -0,0 +1,369 @@ +/*==================================================================================== + 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 "stat_enc.h" +#include "rom_enc.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 */ +/*-------------------------------------------------------------------* + * vad_init_fx() + * + * + *-------------------------------------------------------------------*/ +Word16 vad_init_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB /* i/o: CLDFB VAD state */ +) +{ + Word16 i = 0; + + IF(hVAD_CLDFB == NULL) + { + return -1; + } + + hVAD_CLDFB->frameloop=0; + move16(); + hVAD_CLDFB->continuous_noise_num = 0; + move16(); + hVAD_CLDFB->continuous_speech_num = 0; + move16(); + hVAD_CLDFB->continuous_speech_num2 = 0; + move16(); + hVAD_CLDFB->fg_energy_est_start = L_deposit_l(0); + hVAD_CLDFB->speech_flag = 0; + move16(); + hVAD_CLDFB->frame_sb_energy_scale = 0; + move16(); + hVAD_CLDFB->updateNumWithSnr=0; + move16(); + hVAD_CLDFB->update_count = 0; + move16(); + hVAD_CLDFB->warm_hang_num = 0; + move16(); + + FOR(i = 0; i < SPEC_AMP_NUM; i++) + { + hVAD_CLDFB->smooth_spec_amp[i] = L_deposit_l(0); + } + + FOR(i = 0; i < PRE_SNR_NUM; i++) + { + hVAD_CLDFB->pre_snr[i] = L_deposit_l(0); + } + + FOR(i = 0; i < BG_ENG_NUM; i++) + { + hVAD_CLDFB->frame_sb_energy[i] = L_deposit_l(0); + } + + hVAD_CLDFB->sfm[0] = 28835/* 0.88 Q15 */; + move16(); + hVAD_CLDFB->sfm[1] = 30146/* 0.92 Q15 */; + move16(); + hVAD_CLDFB->sfm[2] = 30146/* 0.92 Q15 */; + move16(); + hVAD_CLDFB->l_silence_snr_count = L_deposit_l(1); + hVAD_CLDFB->l_speech_snr_count = L_deposit_l(1); + hVAD_CLDFB->lt_snr_org = 33554432; + move32(); + hVAD_CLDFB->lf_snr_smooth = 167772155/* 5.0 Q25 */; + move32(); + hVAD_CLDFB->fg_energy = 1073741824; + move32(); + hVAD_CLDFB->fg_energy_scale = 41; + move16(); + + hVAD_CLDFB->bg_energy = 1073741824; + move32(); + hVAD_CLDFB->bg_energy_scale = 57; + move16(); + hVAD_CLDFB->lt_noise_sp_center_diff_counter = L_deposit_l(4); + + hVAD_CLDFB->t_bg_energy = 1374389535; + move32(); + hVAD_CLDFB->scale_t_bg_energy = 37; + move16(); + + hVAD_CLDFB->t_bg_energy_sum.s16Exp = 37; + move16(); + hVAD_CLDFB->t_bg_energy_sum.s32Mantissa = 1374389535; + move32(); + hVAD_CLDFB->tbg_energy_count = 1; + move16(); + hVAD_CLDFB->fg_energy_count = 16; + move16(); + hVAD_CLDFB->bg_energy_count = 16; + move16(); + + hVAD_CLDFB->bg_update_count = 0; + move16(); + hVAD_CLDFB->frame_energy_smooth = 1073741824; + move32(); + hVAD_CLDFB->frame_energy_smooth_scale = 30; + move16(); + hVAD_CLDFB->Q_frames_power_32 = 31; + move16(); + hVAD_CLDFB->lt_bg_highf_eng = 131070/* 2.0 Q16 */; + move16(); + hVAD_CLDFB->lt_noise_sp_center0 = 1841/* 0.4 Q10 */; + move16(); + hVAD_CLDFB->lt_noise_sp_center3 = 2046/* 0.4 Q10 */; + move16(); + hVAD_CLDFB->music_background_rate = 15073/* 0.46 Q15 */; + move16(); + hVAD_CLDFB->tonality_rate3 = 15073/* 0.46 Q15 */; + move16(); + hVAD_CLDFB->lt_noise_sp_center_diff_sum = 409/* 0.4 Q10 */; + move32(); + hVAD_CLDFB->l_silence_snr = 32768/* 0.5 Q16 */; + move32(); + hVAD_CLDFB->l_speech_snr = 327675/* 5.0 Q16 */; + move32(); + + FOR(i = 0; i < SP_CENTER_NUM; i++) + { + hVAD_CLDFB->sp_center[i] = 1228/* 1.2 Q10 */; + move16(); + } + + FOR(i = 0; i < STABLE_NUM; i++) + { + hVAD_CLDFB->ltd_stable_rate[i] = 2294/* 0.07 Q15 */; + move16(); + } + + FOR(i = 0; i < BG_ENG_NUM; i++) + { + hVAD_CLDFB->sb_bg_energy[i] =1374389535; + move32(); + } + hVAD_CLDFB->sb_bg_energy_scale = 37; + move16(); + + hVAD_CLDFB->f_tonality_rate[0] = 7864/* 0.48 Q14 */; + move16(); + hVAD_CLDFB->f_tonality_rate[1] = 7864/* 0.48 Q14 */; + move16(); + hVAD_CLDFB->f_tonality_rate[2] = 7864/* 0.48 Q14 */; + move16(); + + + FOR(i = 0; i < PRE_SPEC_DIF_NUM; i++) + { + hVAD_CLDFB->pre_spec_low_dif[i] = 4095; + move16(); + } + hVAD_CLDFB->scale_spec_low_dif = 12; + move16(); + + FOR (i = 0; i < 56; i++) + { + hVAD_CLDFB->frames_power_32[i] = L_deposit_l(0); + } + + + return 0; +} + + +void UpdateState( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + Word16 vad_flag, /* i : VAD flag */ + Word32 frame_energy, /* i : current frame energy */ + Word16 sacle_sbpower, /* i : the Scaling of current frame energy */ + Word32 update_flag, /* i : current frame update flag */ + Word16 music_backgound_f, /* i : background music flag */ + Word32 HB_Power, /* i : current frame high frequency energy */ + Word16 HB_Power_Q, /* i : the Scaling of current frame high frequency energy*/ + Word32 snr +) +{ + Word16 lt_bg_energy_scal; + Word32 tmp,tmp2; + + + tmp = MUL_F(hVAD_CLDFB->frame_energy_smooth, 31129/* 0.95 Q15 */); + tmp2 = MUL_F(frame_energy, 26214); + hVAD_CLDFB->frame_energy_smooth = VAD_L_ADD(tmp, hVAD_CLDFB->frame_energy_smooth_scale, tmp2, add(4, sacle_sbpower), <_bg_energy_scal); + move32(); + hVAD_CLDFB->frame_energy_smooth_scale = lt_bg_energy_scal; + move16(); + + + IF( vad_flag == 0 ) + { + hVAD_CLDFB->lt_bg_highf_eng = L_add(MUL_F(hVAD_CLDFB->lt_bg_highf_eng, 31130), L_shr(MUL_F(HB_Power, 1638), sub(HB_Power_Q, lt_bg_highf_eng_Q))); + } + + if(LT_16(hVAD_CLDFB->frameloop, 1000)) + { + hVAD_CLDFB->frameloop = add(hVAD_CLDFB->frameloop, 1); + move16(); + } + + background_update_fx(hVAD_CLDFB, sacle_sbpower, frame_energy, update_flag, music_backgound_f, snr); + + IF( vad_flag== 0) + { + hVAD_CLDFB->continuous_speech_num2 = 0; + move16(); + IF(GT_16(hVAD_CLDFB->continuous_noise_num, 10)) + { + hVAD_CLDFB->continuous_speech_num = 0; + move16(); + } + ELSE IF(GT_32(hVAD_CLDFB->continuous_speech_num, 9)) + { + hVAD_CLDFB->continuous_speech_num = 9; + move16(); + } + hVAD_CLDFB->continuous_noise_num = add(hVAD_CLDFB->continuous_noise_num, 1); + move16(); + + if(GT_16(hVAD_CLDFB->continuous_noise_num, 2048)) + { + hVAD_CLDFB->continuous_noise_num = 2048; + move16(); + } + } + ELSE + { + hVAD_CLDFB->continuous_noise_num = 0; + move16(); + + hVAD_CLDFB->continuous_speech_num2 = add(hVAD_CLDFB->continuous_speech_num2, 1); + hVAD_CLDFB->continuous_speech_num = add(hVAD_CLDFB->continuous_speech_num, 1); + if(GT_16(hVAD_CLDFB->continuous_speech_num, 2048)) + { + hVAD_CLDFB->continuous_speech_num = 2048; + move16(); + } + + if(GT_16(hVAD_CLDFB->continuous_speech_num2, 2048)) + { + hVAD_CLDFB->continuous_speech_num2 = 2048; + move16(); + } + } + +} + + +Word16 vad_proc_fx( + VAD_CLDFB_HANDLE_FX hVAD_CLDFB, /* i/o: CLDFB VAD state */ + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real values */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag values */ + Word16 riBuffer_exp, /* i : exponent of real & imag Buffer */ + Word16 *cldfb_addition, /* o : adjust the harmonized hangover */ + Word32 enerBuffer[CLDFB_NO_CHANNELS_MAX], /* i : energy vector per band */ + Word16 enerBuffer_exp, /* i : exponent of energy vector */ + Word16 numBands, /* i : band width 1: NB; 2:WB;3:SWB;4:FB*/ + Word16 vada_flag /* i : VAD flag */ +) +{ + Word16 i; + Word16 bw_index; + Word16 music_backgound_f; + Word16 Q_cldfb; + Word16 frame_energy2_Q, HB_Power_Q; + Word16 sb_power_Q,frame_energy_Q; + Word32 frame_energy, frame_energy2, HB_Power; + Word32 spec_amp[120]; + Word32 update_flag,snr_flux,lt_snr_org,lt_snr,lf_snr; + Word32 snr,tsnr; + Word16 vad_flag; + Word32 *cldfbBufferReal[CLDFB_NO_COL_MAX]; /* dynamic scaling; cldfbBufferReal_float[x][y] = cldfbBufferReal[x][y] * 2^(-Q_cldfb) */ + Word32 *cldfbBufferImag[CLDFB_NO_COL_MAX]; /* dynamic scaling; cldfbBufferImag_float[x][y] = cldfbBufferReal[x][y] * 2^(-Q_cldfb) */ + + + music_backgound_f = 0; + move16(); + frame_energy = 0; + move32(); + + + IF(LT_16(numBands, 20)) + { + bw_index = 1; + move16(); + } + ELSE IF(LT_16(numBands, 40)) + { + bw_index = 2; + move16(); + } + ELSE + { + bw_index = 3; + move16(); + } + + hVAD_CLDFB->bw_index = bw_index; + move16(); + FOR (i=0; iframe_sb_energy, &frame_energy2, &HB_Power,&frame_energy, &sb_power_Q, &frame_energy2_Q, &HB_Power_Q, &frame_energy_Q, + &hVAD_CLDFB->frame_sb_energy_scale,bw_index ); + + subband_FFT_fx(cldfbBufferReal, cldfbBufferImag, spec_amp, 0, &Q_cldfb ); + + frame_spec_dif_cor_rate_fx(hVAD_CLDFB, spec_amp, add(Q_cldfb, 8), hVAD_CLDFB->f_tonality_rate ); + + spec_center_fx(enerBuffer, hVAD_CLDFB->sp_center, bw_index, sb_power_Q ); + + ltd_stable_fx(hVAD_CLDFB, hVAD_CLDFB->ltd_stable_rate, frame_energy, hVAD_CLDFB->frameloop, frame_energy_Q ); + + spec_flatness_fx(spec_amp, hVAD_CLDFB->smooth_spec_amp, hVAD_CLDFB->sfm ); + + bg_music_decision_fx(hVAD_CLDFB, &music_backgound_f, frame_energy, frame_energy_Q); + + snr_calc(hVAD_CLDFB, frame_energy2_Q, &snr, &tsnr, frame_energy2, bw_index ); + + calc_snr_flux_fx(tsnr, hVAD_CLDFB->pre_snr, &snr_flux); + + calc_lt_snr_fx(hVAD_CLDFB, <_snr_org, <_snr, hVAD_CLDFB->fg_energy, hVAD_CLDFB->fg_energy_count, hVAD_CLDFB->bg_energy, + hVAD_CLDFB->bg_energy_count, bw_index, hVAD_CLDFB->lt_noise_sp_center0); + + calc_lf_snr_fx(&hVAD_CLDFB->lf_snr_smooth, &lf_snr, hVAD_CLDFB->l_speech_snr, hVAD_CLDFB->l_speech_snr_count, hVAD_CLDFB->l_silence_snr, + hVAD_CLDFB->l_silence_snr_count, hVAD_CLDFB->fg_energy_count, hVAD_CLDFB->bg_energy_count, bw_index ); + + + vad_flag = comvad_decision_fx(hVAD_CLDFB, lf_snr, lt_snr_org, lt_snr,snr_flux, snr, tsnr, frame_energy2, music_backgound_f, frame_energy2_Q, + cldfb_addition, vada_flag); + + + update_flag = update_decision_fx(hVAD_CLDFB, frame_energy, HB_Power, hVAD_CLDFB->frameloop, bw_index,frame_energy_Q, + HB_Power_Q, snr, tsnr, hVAD_CLDFB->vad_flag_for_bk_update, music_backgound_f); + + + UpdateState(hVAD_CLDFB, hVAD_CLDFB->vad_flag_for_bk_update, frame_energy2, frame_energy2_Q, update_flag, music_backgound_f, HB_Power, HB_Power_Q, snr); + + + return vad_flag; +} + + + diff --git a/lib_enc/vbr_average_rate_fx.c b/lib_enc/vbr_average_rate_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..d893c4b8e9b3e8add8e1b708b4e1f5b6a296eccf --- /dev/null +++ b/lib_enc/vbr_average_rate_fx.c @@ -0,0 +1,256 @@ +/*==================================================================================== + 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 "stat_enc.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 */ + + +#define RATEWIN 600 /* length of the rate control window. This is 600 active speech frames. This equals roughly 12s of active speech */ + +/*=================================================================================*/ +/* FUNCTION : update_average_rate_fx */ +/*---------------------------------------------------------------------------------*/ +/* PURPOSE : SC-VBR update average data rate */ +/*---------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) */ +/*---------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* hSC_VBR->global_avr_rate_fx Q13 */ +/* hSC_VBR->sum_of_rates_fx Q13 */ +/* hSC_VBR->SNR_THLD_fx Q8 */ +/* hSC_VBR->Q_to_F_fx Q0 */ +/* hSC_VBR->pattern_m_fx Q0 */ +/* hSC_VBR->rate_control_fx Q0 */ +/*---------------------------------------------------------------------------------*/ +/*/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*---------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*---------------------------------------------------------------------------------*/ +/* CALLED FROM : */ +/*=================================================================================*/ +void update_average_rate_fx( + SC_VBR_ENC_HANDLE hSC_VBR, /* i/o: SC-VBR state structure */ + const Word32 core_brate_fx /* i : core bitrate */ +) +{ + Word32 avratetarg_fx; /* target rate for next RATEWIN active frames */ + Word32 target_fx; /* target set by VBR_ADR_MAX_TARGET*RATEWIN*10 */ + Word16 tmp; + Word32 L_tmp; + Word32 L_tmp1,L_tmp2; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + Word16 exp, recip, Qrecip; + + IF ( EQ_16(hSC_VBR->numactive,RATEWIN)) /* goes into rate control only the numactive ==RATEWIN. So rate control is triggered after each RATEWIN avtive frames */ + { + /* after 1000 blocks of RATEWIN frames, we change the way we control the average rate by using + st->global_avr_rate=0.99*st->global_avr_rate+0.01*st->sum_of_rates. This will avoid + veriables growing indefinitely while providing a good long term average rate */ + + IF ( LT_32(hSC_VBR->frame_cnt_ratewin_fx,1000)) + { + hSC_VBR->frame_cnt_ratewin_fx = add(hSC_VBR->frame_cnt_ratewin_fx,1); + + /*st->global_avr_rate = (st->global_avr_rate * (st->global_frame_cnt-1) + st->sum_of_rates) / st->global_frame_cnt; */ + exp = norm_s(hSC_VBR->frame_cnt_ratewin_fx); + tmp = shl(hSC_VBR->frame_cnt_ratewin_fx,exp); + recip = div_s(16384,tmp); + Qrecip = 15-(exp-14); + + IF(GT_32(hSC_VBR->frame_cnt_ratewin_fx,1)) + { + tmp = div_s(sub(hSC_VBR->frame_cnt_ratewin_fx,1),hSC_VBR->frame_cnt_ratewin_fx); /*Q15*/ + L_tmp1 = Mult_32_16(hSC_VBR->global_avr_rate_fx, tmp); /* Q13*Q15 = Q13 */ + + L_tmp2 = Mult_32_16(hSC_VBR->sum_of_rates_fx, recip); /*Q13*Qrecip = 13+Qrecip+1-16 = Qrecip-2 */ + + hSC_VBR->global_avr_rate_fx = L_add(L_tmp1, L_shl(L_tmp2,13-(Qrecip-2))); /*Q13 */ + } + ELSE + { + hSC_VBR->global_avr_rate_fx = hSC_VBR->sum_of_rates_fx; /*handle the first frame*/ + } + /* Q13 */ + } + ELSE + { + /* st->global_avr_rate = 0.01f * st->sum_of_rates + 0.99f * st->global_avr_rate; */ + hSC_VBR->global_avr_rate_fx = L_add(Mult_32_16(hSC_VBR->sum_of_rates_fx,328),Mult_32_16(hSC_VBR->global_avr_rate_fx,32441) ); /*Q13 */ + } + + + IF ( hSC_VBR->sum_of_rates_fx == 0 ) + { + /* st->sum_of_rates = (float) (RATEWIN * VBR_ADR_MAX_TARGET * 10); */ + hSC_VBR->sum_of_rates_fx = L_shl(L_mult0(RATEWIN ,VBR_ADR_MAX_TARGET_x10_Q1 ),12); /*Q13 */ + } + + /* target = VBR_ADR_MAX_TARGET * 10 * RATEWIN; */ + target_fx = L_shl(L_mult0(VBR_ADR_MAX_TARGET_x10_Q1,RATEWIN ),12); /*Q13 */ + + IF ( LT_32(target_fx,hSC_VBR->global_avr_rate_fx)) /* Action is taken to reduce the averge rate. Only initiated if the global rate > target rate */ + { + /* Check the vad snr values to table the noisey/not noisey decision */ + + test(); + IF ( LT_16(hSC_VBR->SNR_THLD_fx , 17152)) /*Q8 */ /* Currently in QFF mode. The bumpup thresholds are slightly relaxed for noisy speech. */ + { + /* Increase the threshold so the the bumpup procedure is done using the noisy thresholds. + Use 3.5 steps to quickly ramp up the rate control to reduce the settling time */ + + /* st->SNR_THLD += 3.5f; */ + hSC_VBR->SNR_THLD_fx = add(hSC_VBR->SNR_THLD_fx , 896 ); /*Q8 */ + } + ELSE IF ( hSC_VBR->mode_QQF == 0 && GT_32(hSC_VBR->sum_of_rates_fx, target_fx)) /* Now SNR_THLD is in the max allowed. Sill the global average is higher and + last RATEWIN frames have a higher agerage than the target rate. Now slightly + more aggresive rate control is used by changing the mode to QQF. Still the + same strict bumpups (more bumpups,higher rate) are used. */ + { + /* Kick in QQF mode */ + hSC_VBR->mode_QQF = 1; + move16(); + } + ELSE IF ( GT_32(hSC_VBR->sum_of_rates_fx , target_fx)) /* Actions (1) and (2) are not sufficient to control the rate. Still the last RATEWIN active + frames have a higher average rate than the target rate. More aggresive rate control is + needed. At this point the rate_control flag is set. This will enable the more relaxed + bump up thresholds (less bump ups->reduced rate)*/ + { + /* Relaxed bump ups are used */ + hSC_VBR->rate_control = 1; + move16(); + /* This will be triggered only if the gloabl average rate is considerablly higher than the target rate. + Keep a higher threshold to avoid short term rate increases over the target rate. */ + IF ( GT_32(hSC_VBR->global_avr_rate_fx ,L_add(target_fx,3440640))) /* Last resort rate control. This is a safer rate control mechanism by increasing NELPS */ + { + hSC_VBR->Last_Resort = 1; + move16(); /* compute based on a larger window as the last resort */ + } + ELSE + { + hSC_VBR->Last_Resort = 0; + move16(); + } + } + ELSE IF ( LT_32(hSC_VBR->sum_of_rates_fx, target_fx )) /* If the average rate of last RATEWIN frames is controlled by above actions, disable the most + aggresive rate control mechanisms. Still keep QQF mode as the global rate is not under + the target rate*/ + { + hSC_VBR->Last_Resort = 0; + move16(); + hSC_VBR->mode_QQF = 1; + move16(); + hSC_VBR->rate_control = 0; + move16(); + } + } + ELSE + { + /* floding back to lesser and leser aggresive rate control mechanisms gradually if global rate is under control */ + hSC_VBR->Last_Resort = 0; + move16(); + + IF ( EQ_16(hSC_VBR->rate_control,1)) + { + hSC_VBR->rate_control = 0; + move16(); + } + ELSE IF ( EQ_16(hSC_VBR->mode_QQF,1)) /* now rate control is not active and still the global rate is below the target. so go to QFF mode */ + { + hSC_VBR->mode_QQF = 0; + move16(); + } + ELSE + { + IF ( GE_16(hSC_VBR->SNR_THLD_fx, 15360)) + { + hSC_VBR->SNR_THLD_fx =sub(hSC_VBR->SNR_THLD_fx ,384 ); /*Q8 */ + } + ELSE + { + hSC_VBR->SNR_THLD_fx = 15360; + move16(); + } + } + } + + IF ( LT_32(hSC_VBR->global_avr_rate_fx , L_sub(target_fx,983040))) /* In QFF mode and global rate is less than target rate-0.2kbps. We can send some Q frames + to F frames to improve the quality */ + { + /* kick in bouncing back from Q to F */ + hSC_VBR->Q_to_F = 1; + move16(); + + /* average rate for next 600ms = global_rate * 2 - rate of the past RATEWIN active frames */ + /* avratetarg = (float)((RATEWIN * 10) * 2 * VBR_ADR_MAX_TARGET - st->global_avr_rate); */ + avratetarg_fx = L_sub(L_shl(L_mult0(RATEWIN ,VBR_ADR_MAX_TARGET_x10_Q1 ),13), hSC_VBR->global_avr_rate_fx ); + /* Q13 */ + + + /* compute the percentage of frames that needed to be sent to F. st->pattern_m is computed as % val * 1000. eg. if % is 10%, then + st->pattern_m=100 . Later this value is used in voiced.enc to bump up 10% of PPP frames to F frames. */ + /* st->pattern_m = (short)(1000 * (avratetarg - 6.15f * RATEWIN * 10)/(10 * RATEWIN * 0.1f) ); */ + + L_tmp = L_mult0(RATEWIN ,VBR_ADR_MAX_TARGET_x10_Q1 ); + L_tmp = L_shl(L_tmp , 12); + L_tmp = L_sub(avratetarg_fx , L_tmp); + tmp = extract_h(L_shl(Mult_32_16(L_tmp,27307),4)); + hSC_VBR->pattern_m =tmp; + move16(); + + if ( hSC_VBR->pattern_m < 0 ) + { + hSC_VBR->pattern_m = 0; + move16(); /* no bump up will ever happen */ + } + + if ( GT_16(hSC_VBR->pattern_m,1000)) + { + hSC_VBR->pattern_m = 1000; + move16();/* 10% of bump ups */ + } + + hSC_VBR->patterncount = 0; + move16(); + } + ELSE + { + hSC_VBR->Q_to_F = 0; + move16(); + } + + hSC_VBR->sum_of_rates_fx = 0; + move16(); + hSC_VBR->numactive = 0; + move16(); + + } + + hSC_VBR->numactive = add(hSC_VBR->numactive,1); + + /* sum the total number of bits (in kbytes) * 10 here */ + /*st->sum_of_rates += (hSC_VBR->core_brate_fx / 1000.0f) * 10; */ + L_tmp = L_shl(Mult_32_16(core_brate_fx ,20972),7); +#ifdef BASOP_NOGLOB + hSC_VBR->sum_of_rates_fx = L_add_o(hSC_VBR->sum_of_rates_fx ,L_tmp, &Overflow); +#else + hSC_VBR->sum_of_rates_fx = L_add(hSC_VBR->sum_of_rates_fx ,L_tmp); +#endif + + return; +} + diff --git a/lib_enc/vlpc_1st_cod_fx.c b/lib_enc/vlpc_1st_cod_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..cc54d3182c9dfd0a150ea01a93baf43076768478 --- /dev/null +++ b/lib_enc/vlpc_1st_cod_fx.c @@ -0,0 +1,149 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "control.h" +#include "cnst.h" +//#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +#define ISF_ONE 3/*1.0f*1.28f Q1*/ /*=1.0f in 14Q1*1.28*/ + +/*------------------------------------------------------------------* + * lsf_weight() + * + * outputs only the weightings, doesn't do anything with the lsfq + *------------------------------------------------------------------*/ +/*outputs only the weightings, doesn't do anything with the lsfq*/ +static void lsf_weight( + const Word16 *lsfq, /* i : quantized lsf coefficients (14Q1*1.28)*/ + Word16 *w /* o : lsf weighting vector (0Q15) */ +) +{ + Word16 i; + Word16 inv_di0, inv_di1; + + + + /* weighting function */ + /*use the second element as the base to avoid the following division by 0*/ + /*this happens when the ac function is nearly flat*/ + i = lsfq[0]; + move16(); + if (lsfq[0] == 0) + { + i = lsfq[1]; + move16(); + } + inv_di0 = 0x7fff; + move16(); + if (GT_16(i, ISF_ONE)) + { + inv_di0 = div_s(ISF_ONE,i); /*0Q15*/ /*inv_di0 = 1.0f / lsfq[0];*/ + } + + /* Allow saturation during weight calculation, because the values that are + weighted later are used for a minimum search and experimental saturation + avoidance also showed no improvement. */ + BASOP_SATURATE_WARNING_OFF_EVS + FOR (i=1; i<(M-2); i+=2) /*for (i=1; i<(M-2); i+=2)*/ + { + inv_di1 = div_s(ISF_ONE,s_max(ISF_ONE, sub(lsfq[i],lsfq[i-1]))); /*0Q15*/ /*inv_di1 = 1.0f / (lsfq[i] - lsfq[i-1]);*/ + w[i-1] = add(inv_di0,inv_di1); + move16(); /*0Q15*/ /*w[i-1] = inv_di0 + inv_di1;*/ + inv_di0 = div_s(ISF_ONE,s_max(ISF_ONE, sub(lsfq[i+1],lsfq[i]))); /*0Q15*/ /*inv_di0 = 1.0f / (lsfq[i+1] - lsfq[i]);*/ + w[i] = add(inv_di1,inv_di0); + move16(); /*0Q15*/ /*w[i] = inv_di1 + inv_di0;*/ + } + inv_di1 = div_s(ISF_ONE, s_max(ISF_ONE, sub(lsfq[i],lsfq[i-1]))); /*inv_di1 = 1.0f / (lsfq[i] - lsfq[i-1]);*/ + w[i-1] = add(inv_di0,inv_di1); + move16(); /*w[i-1] = inv_di0 + inv_di1;*/ + inv_di0 = div_s(ISF_ONE, s_max(ISF_ONE, sub(FREQ_MAX,lsfq[i]))); /*inv_di0 = 1.0f / (FREQ_MAX - lsfq[i]);*/ + w[i] = add(inv_di1,inv_di0); + move16(); /*w[i] = inv_di1 + inv_di0;*/ + + BASOP_SATURATE_WARNING_ON_EVS + + + return; +} +/*------------------------------------------------------------------* +* vlpc_1st_cod_fx() +* +* +*------------------------------------------------------------------*/ +Word16 vlpc_1st_cod_fx( /* o : codebook index */ + const Word16 *lsf, /* i : vector to quantize (14Q1*1.28) */ + Word16 *lsfq, /* o : quantized lsf (14Q1*1.28) */ + Word16 *wout, /* o : lsf weights */ + Word16 rf_mode +) +{ + Word16 i, j, index, diff, wdiff; + Word16 w[M]; + Word32 dist_min, dist; + const Word16 *p_dico; + + + + /* weighting */ + lsf_weight(lsf, w);/*lsf:14Q1*1.28=>w:0Q15*/ + IF(EQ_16(rf_mode, 1)) + { + Word16 s; + s = Find_Max_Norm16(w, M); + Scale_sig(w, M, s); + } + Copy(w, wout, M); + /* remove lsf prediction/means */ + + /*dist_min = 1.0e30f;*/ + dist_min = L_add(MAX_32, 0); + p_dico = dico_lsf_abs_8b; /*14Q1*1.28*/ + index = 0; + move16(); + + FOR (i = 0; i < 256; i++) + { + dist = 0; + move32(); + FOR (j = 0; j < M; j++) + { + diff = sub(lsf[j], p_dico[j]); + wdiff = shr(mult_r(w[j],diff),4); + dist = L_mac(dist,wdiff,diff); + } + p_dico += M; + + if (LT_32(dist,dist_min)) + { + index = i; /* store index of new minimum */ + move16(); + } + dist_min = L_min(dist,dist_min); + } + + /* quantized vector */ + p_dico = &dico_lsf_abs_8b[index * M]; + + FOR (j = 0; j < M; j++) + { + /*lsfq[j] += *p_dico++;*/ /* += cause it's differential# + -> since isfq[i] is 0, only data move is sufficient*/ + /*lsfq[j] = add(lsfq[j],*p_dico++);*/ + lsfq[j] = *p_dico++; + move16(); + } + + + return index; +} + + + diff --git a/lib_enc/vlpc_2st_cod_fx.c b/lib_enc/vlpc_2st_cod_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..70cfa036fa14c6c8fd12588dacac03309442c7d8 --- /dev/null +++ b/lib_enc/vlpc_2st_cod_fx.c @@ -0,0 +1,161 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" +#include "cnst.h" +#include "options.h" +//#include "prot_fx.h" +#include "control.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ +#include "basop_util.h" + +/*------------------------------------------------------------------* + * vlpc_2st_cod_fx() + * + * + *------------------------------------------------------------------*/ + +Word16 vlpc_2st_cod_fx( /* output: number of allocated bits */ + const Word16 *lsf, /* i : normalized vector to quantize */ + Word16* lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + Word16* indx, /* o : index[] (4 bits per words) */ + const Word16 mode, /* i : 0=abs, >0=rel */ + const Word32 sr_core/* i : internal sampling rate */ +) +{ + Word16 i, nbits; + Word16 w[M], x[M]; + Word16 nq, xq[M]; + Word32 L_tmp; + Word16 gap; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + + + + /* 0 bit with true weighting: save 0.5 bit */ + lsf_weight_2st(lsf, w, 1); /*w:0Q15*1.28*/ + + FOR (i=1; i wops) */ + nbits = 6; /* 2*(2+1) */ move16(); + test(); + IF ( (mode == 0) || (EQ_16(mode,3))) + { + nbits = 10; /* 2*(2+3) */ move16(); + } + ELSE IF (EQ_16(mode,1)) + { + nbits = 2; /* 2*1 */ move16(); + } + + return nbits; + } + + /* weighting from the 1st stage */ + lsf_weight_2st(lsfq, w, mode); + + /* find lsf and scale the residual */ + FOR (i=0; i +#include "options.h" +#include "cnst.h" +//#include "prot_fx.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 functions + *--------------------------------------------------------------------*/ +static void synthesis_filter_fx (Word16 b[], Word16 x[], Word16 y[], Word16 buf[], Word16 P, Word16 N ); +static Word32 DTFS_freq_corr_fx(DTFS_STRUCTURE X1_DTFS_fx, DTFS_STRUCTURE X2_DTFS_fx, Word16 lband, Word16 hband, Word16* Qout); +static Word16 DTFS_alignment_extract_td_fx(Word16* x1, Word16* x2, Word16 lag); +static Word32 DTFS_getEngy_band_fx(DTFS_STRUCTURE X_fx,const Word16 lband,const Word16 hband); + +/*=======================================================================================*/ +/* FUNCTION : ppp_voiced_encoder_fx() */ +/*---------------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16) delay_fx: open loop pitch, Q6 - WRONG, it is Q0 */ +/* _ (Word16) hSC_VBR->vadsnr_fx: SNR for current frame Q7 */ +/* _ (Word16) prevCW_lag_fx: Previous lag, Q0 */ +/* _ (Word16 *) in_fx : residual signal (Q_res) */ +/* _ (Word16 *) lpc1_fx : prev frame de-emphasized LPC Q12 */ +/* _ (Word16 *) lpc2_fx : current frame de-emphasized LPC Q12 */ +/* _ (Word16 *) exc_fx : prrevious frame quantized excitation (Q_exc) */ +/* _ (Word16) Q_res: Q factor for res */ +/* _ (Word16) Q_exc: Q factor for exc */ +/*---------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) pitch_fx: floating pitch values for each subframe(Q6) */ +/* _ (Word16*) out_fx: Quantized residual signal (Q0) */ +/* _ Encoder_State_fx *st_fx: */ +/* _ lastLgainE_fx - Q11 */ +/* _ lastHgainE_fx - Q11 */ +/* _ lasterbE_fx - Q13 */ +/*---------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State_fx *st_fx: */ +/* _ hSC_VBR->dtfs_enc_xxxx */ +/* _ a nd b in hSC_VBR->dtfs_enc_Q */ +/* rest all in Q0 */ +/* - bump_up_fx - Q0 */ +/*---------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None. */ +/*---------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*=======================================================================================*/ + +ivas_error ppp_voiced_encoder_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + SC_VBR_ENC_HANDLE hSC_VBR, + const Word16 bwidth_fx, /* i : audio bandwidth */ + const Word16 last_coder_type_raw, /* i : raw last_coder_type */ + const Word16 old_pitch_buf[], /* i : buffer of old subframe pitch values */ + Word16 *in_fx, /* i : residual signal */ + Word16 *out_fx, /* o : Quantized residual signal */ + Word16 delay_fx, /* i : open loop pitch */ + Word16 *lpc1_fx, /* i : prev frame de-emphasized LPC */ + Word16* lpc2_fx, /* i : current frame de-emphasized LPC */ + Word16 *exc_fx, /* i: previous frame quantized excitation */ + Word16 *pitch_fx, /* o: floating pitch values for each subframe */ + Word16 Qres +) +{ + Word16 i; + Word16 spike_near_edge = 0; + Word16 flag; + Word16 delta_lag_E = 0, PPP_MODE_E, Q_delta_lag = 0; + Word16 out_of_bound = 0; + Word16 tmp, tmptmp, tmptmp1; + Word16 pl, l; + Word16 interp_delay[3], temp_pl, temp_l; + Word16 upper_cut_off_freq_of_interest_fx = 0; + Word16 upper_cut_off_freq_of_interest_norm_fx = 0, upper_cut_off_freq_norm_fx = 0; + + Word16 S_fx[PIT_MAX*4+1], C_fx[PIT_MAX*4+1]; + Word16 Qtmpres; + Word32 Ltemp, logLag, Ltemp_q; + Word32 Lacc,Lacc1; + Word16 Ql, Qh,n,sft,flag1; + + Word16 pf_temp1[MAXLAG_WI]; /*maynot need more than MAXLAG_WI/2+1 */ + Word16 pf_temp2[MAXLAG_WI]; + Word16 pf_temp[MAXLAG_WI]; + Word16 pf_n2[MAXLAG_WI]; + Word16 exp,expa,expb,fraca,fracb,scale,frac; + Word32 L_tmp; + + Word16 x_fx; + Word16 impzi_fx[160],impzo_fx[160]; + Word16 exp_ee, frac_ee; + Word16 Qtmp; + Word32 res_enratio_fx =0 ; + Word16 mem_fx[10]; + Word32 energy_impz_fx = 0,tmpres_fx; + Word32 pos_nq0_fx,neg_nq0_fx,Ltmp; + Word32 Ltmp_32, Ltmp1_32, Ltemp1, Ltemp2, Ltemp_fx; + Word16 Qadj; + + Word32 tmp_fx = 0,sp_hb_enratio_fx = 0,sp_enratio_fx = 0; + Word32 low_band_en_fx; + Word32 curr_Engy,prev_Engy; + Word16 temp_Fs; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + DTFS_STRUCTURE* CURRP_NQ_FX; + DTFS_STRUCTURE* TMPDTFS_FX; + DTFS_STRUCTURE* TMPDTFS2_FX; + DTFS_STRUCTURE* TMPDTFS3_FX; + DTFS_STRUCTURE* CURRP_Q_E_FX; + DTFS_STRUCTURE* dtfs_temp_fx; + + ivas_error error; + + error = IVAS_ERR_OK; + + + IF ((error = DTFS_new_fx(&CURRP_NQ_FX)) != IVAS_ERR_OK) + { + IVAS_ERROR(error, "Error creating DTFS structure"); + } + IF ((error = DTFS_new_fx(&TMPDTFS_FX)) != IVAS_ERR_OK) + { + IVAS_ERROR(error, "Error creating DTFS structure"); + } + IF ((error = DTFS_new_fx(&TMPDTFS2_FX)) != IVAS_ERR_OK) + { + IVAS_ERROR(error, "Error creating DTFS structure"); + } + IF ((error = DTFS_new_fx(&TMPDTFS3_FX)) != IVAS_ERR_OK) + { + IVAS_ERROR(error, "Error creating DTFS structure"); + } + IF ((error = DTFS_new_fx(&CURRP_Q_E_FX)) != IVAS_ERR_OK) + { + IVAS_ERROR(error, "Error creating DTFS structure"); + } + IF ((error = DTFS_new_fx(&dtfs_temp_fx)) != IVAS_ERR_OK) + { + IVAS_ERROR(error, "Error creating DTFS structure"); + } + + + temp_Fs = 8000; + move16(); + + if ( EQ_16( bwidth_fx, WB)) + { + temp_Fs = 16000; + move16(); + } + + test(); + IF (EQ_16(bwidth_fx,WB)||EQ_16(bwidth_fx,SWB)) + { + upper_cut_off_freq_of_interest_fx = 4000; + move16(); + upper_cut_off_freq_of_interest_norm_fx = 10240; + move16();/*value normalized by 12800 */ + upper_cut_off_freq_norm_fx = 16384; + move16();/*value normalized by 12800 */ + } + ELSE IF (EQ_16(bwidth_fx,NB)) + { + upper_cut_off_freq_of_interest_fx = 3300; + move16(); + upper_cut_off_freq_of_interest_norm_fx = 8448; + move16();/*value normalized by 12800 */ + upper_cut_off_freq_norm_fx = 10240; + move16();/*value normalized by 12800 */ + } + + /* Initialization */ + IF (hSC_VBR->firstTime_voicedenc) + { + hSC_VBR->firstTime_voicedenc = 0; + move16(); + hSC_VBR->dtfs_enc_lag = 0; + move16(); + hSC_VBR->dtfs_enc_nH = 0; + move16(); + hSC_VBR->dtfs_enc_nH_4kHz = 0; + move16(); + hSC_VBR->dtfs_enc_upper_cut_off_freq_of_interest_fx = 3300; + move16(); + hSC_VBR->dtfs_enc_upper_cut_off_freq_fx = 4000; + move16(); + set16_fx(hSC_VBR->dtfs_enc_a_fx, 0, MAXLAG_WI); + set16_fx(hSC_VBR->dtfs_enc_b_fx, 0, MAXLAG_WI); + } + test(); + /* Figure out the PPP_MODE */ + IF ( EQ_16(hSC_VBR->last_ppp_mode,1)&&!hSC_VBR->mode_QQF) + { + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + + /* Use the aggresive bumpups if there are two consecutive Q frames */ + /* Aggresive bump upsare only used in the second Q frame */ + if (hSC_VBR->last_ppp_mode == 1 ) + { + hSC_VBR->rate_control = 0; + } + + PPP_MODE_E = 'Q'; + move16(); + + pl = s_min(MAX_LAG_PIT, rint_new_fx(L_shl(old_pitch_buf[(2*NB_SUBFR)-1],10))); + move16(); + l = s_min(MAX_LAG_PIT, rint_new_fx(L_deposit_h(delay_fx))); + move16(); + /* old_pitch_buf in Q6*/ + + /* Bump up if the lag is out_fx of range */ + test(); + IF (GT_16(sub(l,pl),13)||LT_16(sub(l,pl),-11)||LT_16(l,19)||LT_16(pl,19)) + { + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + + IF (NE_16(hSC_VBR->last_ppp_mode,1)) + { + /* Obtain DTFS of last pl values of past excitation */ + GetSinCosTab_fx(pl,S_fx,C_fx); + DTFS_to_fs_fx(exc_fx-pl, pl, dtfs_temp_fx, temp_Fs, 0,S_fx,C_fx); + } + + if (EQ_16(last_coder_type_raw,UNVOICED)) + { + pl = l; + move16(); /* if prev frame was sil/uv */ + } + + /* Use the out_fx array as a temp storage for currp */ + spike_near_edge = ppp_extract_pitch_period_fx(in_fx, out_fx, l, &out_of_bound,Qres) ; + move16(); + /* out_fx in Qres */ + + IF (out_of_bound == 1) + { + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + + /* Get DTFS of current prototype */ + GetSinCosTab_fx(l,S_fx,C_fx); + + DTFS_to_fs_fx(out_fx, l, CURRP_NQ_FX, temp_Fs, 0,S_fx,C_fx); + /* This requires input out_fx in Q0, but currently in Qres */ + + /* Ensure the extracted prototype is time-synchronous to the + * last l samples of the frame. This proves to eliminate + * some of the PPP-CELP transition problems. + * Convert last samples into DTFS */ + IF (spike_near_edge != 0) + { + /* These two function calls are combined in one call DTFS_alignment_extract_td_fx() */ + /* DTFS_to_fs(in+L_FRAME-l, l, TMPDTFS,(short) st->input_Fs,0); */ + /* tmp = DTFS_alignment_extract(*TMPDTFS, *CURRP_NQ, 0.0, lpc2) ; */ + tmp = DTFS_alignment_extract_td_fx(out_fx, in_fx+L_FRAME-l, l) ; + move16(); /*Q0 */ + tmp = negate(shl(tmp,2));/*Q2 */ + Q2phaseShift_fx(CURRP_NQ_FX, tmp, l, S_fx,C_fx) ; + /* output CURRP_NQ is correct */ + } + temp_pl = pl; + move16(); + temp_l = l; + move16(); + + FOR(i = 0; i < NB_SUBFR; i++) + { + /* do the linear pitch_fx interp to drive the nb_post_filt */ + Interpol_delay_fx(interp_delay, temp_pl, temp_l, i, frac_4sf_fx); /* interp_delay in Q4 */ + pitch_fx[i] = shl(interp_delay[0],2); + move16();/* pitch_fx in Q6 */ + } + curr_Engy=DTFS_getEngy_P2A_fx(CURRP_NQ_FX); /*2Q where Q=CURRP_NQ_FX->Q */ + + /* Restoring PPP memories when the last frame is non-PPP */ + IF (NE_16(hSC_VBR->last_ppp_mode,1)) + { + + hSC_VBR->ph_offset_E_fx = 0 ; + move16(); + + /* st->prev_cw_en = DTFS_getEngy(*dtfs_temp); */ + Lacc=DTFS_getEngy_P2A_fx(dtfs_temp_fx); /*2Q where Q = dtfs_temp_fx->Q */ + + + prev_Engy = L_add(Lacc, 0); + + hSC_VBR->Q_prev_cw_en_fx=norm_l(Lacc); /* = K = headroom */ + + /*hSC_VBR->Q_prev_cw_en_fx = (Lacc==0)?31: hSC_VBR->Q_prev_cw_en_fx; */ + if (Lacc==0) + { + hSC_VBR->Q_prev_cw_en_fx = 31; + move16(); + } + + hSC_VBR->prev_cw_en_fx=(Word32) L_shl(Lacc, hSC_VBR->Q_prev_cw_en_fx); /*2Q+K */ + hSC_VBR->Q_prev_cw_en_fx = add(hSC_VBR->Q_prev_cw_en_fx,shl(dtfs_temp_fx->Q,1)); + /* hSC_VBR->Q_prev_cw_en_fx = 2*(dtfs_temp_fx->Q) + K */ + + DTFS_copy_fx(TMPDTFS_FX,*dtfs_temp_fx); /* output = TMPDTFS_FX */ + + DTFS_car2pol_fx(TMPDTFS_FX); + + logLag=log10_fx(TMPDTFS_FX->lag_fx); /* logLag=10*log10(pl), Q23 */ + Ltemp_q=L_shl(L_mult(shl(TMPDTFS_FX->Q,1),24660),9); /* Ltemp_q=2Q*10log10(2), Q23 */ + + /* Process low band */ + Ltemp=DTFS_setEngyHarm_fx(236,2828,0,2828, 1, 0, &Ql,TMPDTFS_FX);/* Q of Ltemp = 2*(TMPDTFS_FX->Q) = Ql ? */ + /* Compensate for Q factor of energy to get log10(lag*eng) */ + Ltemp=log10_fx(Ltemp); /* Ltemp=10log10(eng), Q23 */ + Ltemp=L_add(L_sub(Ltemp,Ltemp_q),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + /*hSC_VBR->lastLgainE_fx=round_fx(L_shl((Word32)Mpy_32_16(extract_h(Ltemp),extract_l(Ltemp),0x6666),1)); // Q11, 0x6666 = 0.1 in Q18 */ + hSC_VBR->lastLgainE_fx=round_fx(L_shl(Mult_32_16(Ltemp,0x6666),1)); /* Q11, 0x6666 = 0.1 in Q18 */ + + + /* Process high band */ + Ltemp=DTFS_setEngyHarm_fx(2828,upper_cut_off_freq_of_interest_norm_fx,2828,upper_cut_off_freq_norm_fx, 1, 0, &Qh,TMPDTFS_FX); + Ltemp=log10_fx(Ltemp); + Ltemp=L_add(L_sub(Ltemp,Ltemp_q),logLag); /* Ltemp=10*log10(lag*eng), Q23 */ + hSC_VBR->lastHgainE_fx=round_fx(L_shl(Mult_32_16(Ltemp,0x6666),1)); /* Q11 */ + + /* Need to unify the Q factors of both bands */ + TMPDTFS_FX->Q=s_min(Ql,Qh); + move16();/* set Q factor to be the smaller one of Ql and Qh */ + n=sub(Ql,Qh); /* compare band Q factors */ + + IF (n<0) + { + rshiftHarmBand_fx(TMPDTFS_FX,2828, upper_cut_off_freq_norm_fx,n); + } + ELSE IF (n>0) + { + rshiftHarmBand_fx(TMPDTFS_FX,0, 2828, sub(Qh,Ql)); + } + + DTFS_to_erb_fx(*TMPDTFS_FX, hSC_VBR->lasterbE_fx); /* output lasterbE_fx in Q13 */ + Lacc1 = L_max(prev_Engy, 1); + } + ELSE + { + /* Copy DTFS related parameters from 'st_fx' to 'dtfs_temp' structure */ + dtfs_temp_fx->lag_fx = hSC_VBR->dtfs_enc_lag; + move16(); + dtfs_temp_fx->nH_fx = hSC_VBR->dtfs_enc_nH; + move16(); + dtfs_temp_fx->nH_4kHz_fx = hSC_VBR->dtfs_enc_nH_4kHz; + move16(); + dtfs_temp_fx->upper_cut_off_freq_of_interest_fx = hSC_VBR->dtfs_enc_upper_cut_off_freq_of_interest_fx; + move16(); + dtfs_temp_fx->upper_cut_off_freq_fx = hSC_VBR->dtfs_enc_upper_cut_off_freq_fx; + move16(); + + Copy(hSC_VBR->dtfs_enc_a_fx, dtfs_temp_fx->a_fx, MAXLAG_WI); + Copy(hSC_VBR->dtfs_enc_b_fx, dtfs_temp_fx->b_fx, MAXLAG_WI); + + dtfs_temp_fx->Q = hSC_VBR->dtfs_enc_Q; + move16(); + Lacc1=DTFS_getEngy_P2A_fx(dtfs_temp_fx); + prev_Engy = L_add(Lacc1, 0); + } + + /*-----Open-loop Bump-Up-------- */ + + /* Energy ratio calculation in_fx residual and speech domain */ + /* Also, compute correlation between the previous and the */ + /* current prototype */ + + /* res_enratio = DTFS_getEngy(*CURRP_NQ) / DTFS_getEngy(*dtfs_temp); */ + Lacc = L_add(curr_Engy, 0); + /* Lacc1 has been handled above */ + + sft=add(shl(sub(CURRP_NQ_FX->Q,dtfs_temp_fx->Q),1),4); + IF (sft>0) + { + if (LT_32(Lacc1,L_shr(Lacc,sft))) + { + res_enratio_fx=0x7FFF; + move16(); + } + } + ELSE + { + if (LT_32(L_shr(Lacc1,negate(sft)),Lacc)) + { + res_enratio_fx=0x7FFF; + move16(); + } + } + /* max value res_enratio compared against is 0x7400 (14.5 in Q11) */ + + IF (NE_32(res_enratio_fx,0x7FFF)) + { + + expb = norm_l(Lacc); + fracb = extract_h(L_shl(Lacc,expb)); + expb = sub(30,add(expb, shl(CURRP_NQ_FX->Q, 1))); + + + expa = norm_l(Lacc1); + fraca = extract_h(L_shl(Lacc1,expa)); + expa = sub(30, add(expa, shl(dtfs_temp_fx->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + res_enratio_fx = shl(tmp,sub(exp,4)); + } + /* res_enratio_fx is Q11 */ + + /* Copy over CURRP_NQ into TMPDTFS */ + DTFS_copy_fx(TMPDTFS_FX, *CURRP_NQ_FX); /* output = TMPDTFS_FX with Q = CURRP_NQ_FX->Q */ + + /* Copy over dtfs_temp into TMPDTFS2 */ + DTFS_copy_fx(TMPDTFS2_FX, *dtfs_temp_fx); /* output = TMPDTFS2_FX with Q = dtfs_temp_fx->Q */ + + tmptmp = DTFS_alignment_full_fx(*TMPDTFS2_FX,*TMPDTFS_FX, hSC_VBR->ph_offset_E_fx,S_fx,C_fx, 0); + + tmptmp1 = sub(shl(TMPDTFS_FX->lag_fx,1), tmptmp);/* (C_l-tmptmp) , Q1 */ + + Q2phaseShift_fx(TMPDTFS_FX, negate(shl(tmptmp1,1)), TMPDTFS_FX->lag_fx,S_fx,C_fx); /* fixed bug , phase shift by tmp computed in_fx TMP.lag domain (above) */ + + /*tmpres = (float)(DTFS_freq_corr(*TMPDTFS, *TMPDTFS2, 100.0f, 3700.0f));*/ + tmpres_fx = DTFS_freq_corr_fx(*TMPDTFS_FX, *TMPDTFS2_FX, 100, 3700, &Qtmpres); /* tmpres_fx has Q factor tmpres */ + + + + poleFilter_setup_fx(lpc2_fx, M+1, *TMPDTFS_FX, S_fx, C_fx, pf_temp1, pf_temp2, pf_temp, pf_n2); + DTFS_poleFilter_fx_9(TMPDTFS_FX, pf_temp1, pf_temp2, pf_temp, pf_n2); + /* lpc2_fx in Q12 */ + + DTFS_adjustLag_fx(TMPDTFS2_FX, TMPDTFS_FX->lag_fx); /* operate in_fx CL domain */ + + DTFS_poleFilter_fx(TMPDTFS2_FX,lpc1_fx,M+1, S_fx, C_fx); /* lpc1_fx in Q12 */ + + tmp_fx = DTFS_freq_corr_fx(*TMPDTFS_FX, *TMPDTFS2_FX, 100, 3700, &Qtmp); + /* tmp_fx Q = Qtmp */ + + + /******************************************************************************* + if ( DTFS_getEngy(*TMPDTFS2) > 0 ) + { + sp_enratio = DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS2); + } + else + { + sp_enratio = 0.0f; + } + *******************************************************************************/ + Ltmp_32 = (DTFS_getEngy_fx(TMPDTFS2_FX)); /* Output Q=2*(TMPDTFS2_FX->Q) */ + IF ( Ltmp_32 > 0 ) + { + /*sp_enratio = DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS2); in Q15 */ + Lacc=DTFS_getEngy_P2A_fx(TMPDTFS_FX); + Lacc1=Ltmp_32; + /* IF (L_sub(sp_enratio_fx,0x7FFF)!=0) */ + { + expb = norm_l(Lacc); + fracb = extract_h(L_shl(Lacc,expb)); + + expb = sub(30, add(expb, shl(TMPDTFS_FX->Q, 1))); + + expa = norm_l(Lacc1); + fraca = extract_h(L_shl(Lacc1,expa)); + + expa = sub(30, add(expa, shl(TMPDTFS2_FX->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + sp_enratio_fx = L_shl(tmp, exp); /* Q15 */ + } + } + ELSE + { + sp_enratio_fx = L_deposit_l(0);/* Q15 */ + } + + /*******************************************************************************/ + IF (EQ_16(PPP_MODE_E,'Q')) + { + /* Bump up if the lag is out_fx of range */ + test(); + IF (GT_16(sub(l,pl),13)||LT_16(sub(l,pl),-11)) + { + PPP_MODE_E = 'B' ; + move16(); + } + ELSE + { + delta_lag_E= sub(l,pl); + } + + /* Bump up if big change between the previous and the current CWs */ +#ifdef BASOP_NOGLOB + IF ( LT_16(shl_o(hSC_VBR->vadsnr_fx,1, &Overflow) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#else + IF ( LT_16(shl(hSC_VBR->vadsnr_fx,1) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#endif + { + /*if ( res_enratio > 5.0 && tmp < 0.65 ) */ + /* 5 in Q11, 0.65 in Q15 // L_shl(tmp_fx,sub(31,Qtmp)) makes tmp_fx FIXED Q31 */ + test(); +#ifdef BASOP_NOGLOB + IF ((GT_32(res_enratio_fx,10240))&&(LT_16(extract_h(L_shl_o(tmp_fx,sub(31,Qtmp), &Overflow)),21299))) +#else + IF ((GT_32(res_enratio_fx,10240))&&(LT_16(extract_h(L_shl(tmp_fx,sub(31,Qtmp))),21299))) +#endif + { + PPP_MODE_E = 'B'; + move16(); + } + } + ELSE + { + /* if ( res_enratio > 3.0 && tmp < 1.2 ) */ + /*3 in Q11, 1.2 in Q14 // L_shl(tmp_fx,sub(31,Qtmp)) makes tmp_fx FIXED Q14 */ + test(); +#ifdef BASOP_NOGLOB + IF ( (GT_32(res_enratio_fx,6144))&&(LT_16(extract_h(L_shl_o(tmp_fx,sub(30,Qtmp), &Overflow)),19661))) +#else + IF ( (GT_32(res_enratio_fx,6144))&&(LT_16(extract_h(L_shl(tmp_fx,sub(30,Qtmp))),19661))) +#endif + { + PPP_MODE_E = 'B'; + move16(); + } + } + } + + /* Rapid rampdown frame where time resolution is important */ + /* Not a suitable PPP frame -> Bump to CELP */ + +#ifdef BASOP_NOGLOB + IF ( LT_16(shl_o(hSC_VBR->vadsnr_fx,1, &Overflow) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#else + IF ( LT_16(shl(hSC_VBR->vadsnr_fx,1) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#endif + { + /* if (res_enratio < 0.025) */ +#ifdef BASOP_NOGLOB + IF (LT_32(L_shl_o(res_enratio_fx,4, &Overflow),819)) /*0x0333 = 0.025 in Q15, res_enratio_fx in Q15 after shl 4 */ +#else + IF (LT_32(L_shl(res_enratio_fx,4),819)) /*0x0333 = 0.025 in Q15, res_enratio_fx in Q15 after shl 4 */ +#endif + { + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + } + ELSE + { + /* if ( res_enratio < 0.092f) */ +#ifdef BASOP_NOGLOB + if ( LT_32(L_shl_o(res_enratio_fx,4, &Overflow), 3015))/*3015 = 0.092 in Q15, res_enratio_fx in Q15 after shl 4 */ +#else + if ( LT_32(L_shl(res_enratio_fx,4), 3015))/*3015 = 0.092 in Q15, res_enratio_fx in Q15 after shl 4 */ +#endif + { + hSC_VBR->bump_up = 1; + move16(); + } + } + + /* if (min(res_enratio, sp_enratio) < 0.075 && tmp < -0.5f)) : 2458 = 0.075 in Q15 */ + test(); +#ifdef BASOP_NOGLOB + if ( LT_32(L_min(L_shl_o(res_enratio_fx,4, &Overflow), sp_enratio_fx), 2458)&<_32(tmp_fx,shl_o(-1,sub(Qtmp,1), &Overflow))) +#else + if ( LT_32(L_min(L_shl(res_enratio_fx,4), sp_enratio_fx), 2458)&<_32(tmp_fx,shl(-1,sub(Qtmp,1)))) +#endif + { + hSC_VBR->bump_up = 1; + move16(); + } + + /* Rapid rampup frame where time resolution is important */ + /* Not a suitable PPP frame -> Bump to CELP */ +#ifdef BASOP_NOGLOB + IF ( LT_16(shl_o(hSC_VBR->vadsnr_fx,1, &Overflow) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#else + IF ( LT_16(shl(hSC_VBR->vadsnr_fx,1) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#endif + { + IF (GT_32(res_enratio_fx,29696)) /*14.5 in Q11 */ + { + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + } + ELSE + { + if (GT_32(res_enratio_fx,14336)) /* 7.0 in Q11 */ + { + hSC_VBR->bump_up = 1; + move16(); + } + } + + IF ( hSC_VBR->bump_up == 1 ) + { + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + + /* Bump up when the previous frame is an unvoiced or a silent frame */ + IF (EQ_16(last_coder_type_raw,UNVOICED)) + { + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + /* -----End Open-loop Bump-Up */ + + /* PPP-WI Quantization */ + IF (EQ_16(PPP_MODE_E,'Q')) + { + flag = 1; + move16(); + IF (EQ_16(PPP_MODE_E,'Q')) + { + if ((error = ppp_quarter_encoder_fx(&flag, CURRP_Q_E_FX, TMPDTFS_FX, dtfs_temp_fx->lag_fx, *CURRP_NQ_FX, lpc2_fx, &hSC_VBR->lastLgainE_fx, &hSC_VBR->lastHgainE_fx, hSC_VBR->lasterbE_fx, *dtfs_temp_fx, S_fx, C_fx, hBstr)) != IVAS_ERR_OK) + { + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + } + + IF (flag) + { + /* TMPDTFS : Target prototype: Amp Quantized + Phase Unquantized */ + /* TMPDTFS2: Quantized prototype: Amp Quantized + Phase Quantized */ + /* TMPDTFS3: Delta prototype: Diff betw. target and quant. in_fx speech dom */ + + /* ----- Closed-loop Bump-Up ---------- */ + Word32 pos_nq_fx, neg_nq_fx,pos_q_fx,neg_q_fx; + Word16 Qposnq, Qnegnq, Qposq,Qnegq; + + DTFS_peaktoaverage_fx(*TMPDTFS_FX,&pos_nq_fx,&Qposnq,&neg_nq_fx,&Qnegnq); + DTFS_peaktoaverage_fx(*CURRP_Q_E_FX, &pos_q_fx, &Qposq,&neg_q_fx,&Qnegq); + + + /* Before we perform the peak-to-average ratio comparison, we have to */ + /* ensure that the energy is not decaying and also the pitch_fx pulse */ + /* is clearly defined */ + + /* Usually triggers in the slow ramp down frames. Does not fall under the test condition (res_enratio < 0.025) as + both frames have little energy and the ratio is not very small. Not suitable for PPP */ + + IF ( GT_16(CURRP_Q_E_FX->upper_cut_off_freq_fx , 4000)) + { + Ltemp2 = DTFS_getEngy_band_wb_fx(*CURRP_Q_E_FX, 0, 2000); + /* Use this bump-up only for WB signals */ + IF ( Ltemp2 > 0 ) + { + /* sp_hb_enratio = DTFS_getEngy_band_wb(*CURRP_Q_E, 2000.0, 6400.0)/DTFS_getEngy_band_wb(*CURRP_Q_E, 0.0, 2000.0); */ + Ltemp1 = DTFS_getEngy_band_wb_fx(*CURRP_Q_E_FX, 2000, 6400);/*Q13 */ + /*sp_hb_enratio_fx = divide_dp(Ltemp1,Ltemp2,0, 1);//Q29 */ + Qadj = 0; + move16(); + /*----------------------------------------------------------*/ + /* Ltemp_fx = (Word32)divide_dp(Ltemp1, Ltemp2, Qadj,1); Q29*/ + /*----------------------------------------------------------*/ + if(Ltemp1<0) + { + Ltemp1 = L_negate(Ltemp1); + } + expa = norm_l(Ltemp2); +#ifdef BASOP_NOGLOB + fraca = extract_h(L_shl_o(Ltemp2,expa, &Overflow)); +#else + fraca = extract_h(L_shl(Ltemp2,expa)); +#endif + expa = sub(30,expa); + + expb = norm_l(Ltemp1); + fracb = round_fx(L_shl(Ltemp1,expb)); + expb = sub(30, add(expb, Qadj)); + + scale = shr(sub(fraca,fracb),15); +#ifdef BASOP_NOGLOB + fracb = shl_o(fracb,scale, &Overflow); +#else + fracb = shl(fracb,scale); +#endif + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); +#ifdef BASOP_NOGLOB + Ltemp_fx = L_shl_o(tmp, add(exp,14), &Overflow); +#else + Ltemp_fx = L_shl(tmp, add(exp,14)); +#endif + /*-------------------------------------------*/ + sp_hb_enratio_fx = L_add(Ltemp_fx, 0); /* Q29 */ + } + ELSE + { + sp_hb_enratio_fx = L_deposit_l(0); + } + low_band_en_fx = Ltemp2; /*Q13 */ + + /* if ( low_band_en < 25.0f && sp_hb_enratio < 1.6f ) */ + /* 25.0 in Q13 = 204800, 1.6 in Q29 = 858993459 */ + test(); + IF ( LT_32(low_band_en_fx , 204800 )&<_32(sp_hb_enratio_fx,858993459)) + { + PPP_MODE_E = 'B'; + move16(); + } + } + + Ltmp_32=DTFS_getEngy_fx(CURRP_NQ_FX); /*Q = 2*(CURRP_NQ_FX->Q) */ + Qadj = sub(hSC_VBR->Q_prev_cw_en_fx, shl(CURRP_NQ_FX->Q, 1)); + +#ifdef BASOP_NOGLOB + Ltmp_32 = L_shl_o(Ltmp_32,Qadj, &Overflow); /* shift left required to adjust Q of CURRP_NQ_FX = Q_prev_cw_en_fx */ +#else + Ltmp_32 = L_shl(Ltmp_32,Qadj); /* shift left required to adjust Q of CURRP_NQ_FX = Q_prev_cw_en_fx */ +#endif + /* Ltmp1_32 = 0.8f * st->prev_cw_en */ + Ltmp1_32 = Mult_32_16(hSC_VBR->prev_cw_en_fx,26214); /* Q = (Q_prev_cw_en_fx + Q15+1)-Q16 = Q_prev_cw_en_fx */ + +#ifdef BASOP_NOGLOB + IF ( LT_16(shl_o(hSC_VBR->vadsnr_fx,1, &Overflow) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#else + IF ( LT_16(shl(hSC_VBR->vadsnr_fx,1) ,hSC_VBR->SNR_THLD_fx)) /*Q8 */ +#endif + { + /* if ( DTFS_getEngy(*CURRP_NQ) > 0.8f * st->prev_cw_en && max(pos_nq, neg_nq) > 3.0f && st->rate_control ) */ + /* pos_nq_fx and neg_nq_fx in Q28 ???? */ + test(); + test(); + IF ( GT_32( Ltmp_32, Ltmp1_32)&>_32(L_max(pos_nq_fx,neg_nq_fx),805306368)&&hSC_VBR->rate_control) + { + /*if ( pos_nq > neg_nq && pos_nq > 2.0f * pos_q ) */ + test(); + IF ( GT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(pos_nq_fx,16384),pos_q_fx)) + { + PPP_MODE_E = 'B'; + move16(); + } + + test(); + /*if ( pos_nq < neg_nq && neg_nq > 2.0f * neg_q ) */ + IF ( LT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(neg_nq_fx,16384),neg_q_fx)) + { + PPP_MODE_E = 'B'; + move16(); + } + } + } + + ELSE + { + /* if ((((DTFS_getEngy(*CURRP_NQ) >(st->prev_cw_en))&&(max(pos_nq,neg_nq)>3.5))&&(st->rate_control))|| */ + /* (((DTFS_getEngy(*CURRP_NQ) >0.8*(st->prev_cw_en))&&(max(pos_nq,neg_nq)>3.0))&&(!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + IF ((((L_sub(Ltmp_32 ,(hSC_VBR->prev_cw_en_fx)>0))&&(GT_32(L_max(pos_nq_fx,neg_nq_fx),939524096)))&&(hSC_VBR->rate_control))|| + (((GT_32( Ltmp_32, Ltmp1_32) ) && (GT_32(L_max(pos_nq_fx,neg_nq_fx),805306368)))&&(!hSC_VBR->rate_control))) + { + /* if (((pos_nq > neg_nq) && (pos_nq > 2.5*pos_q)&&(st->rate_control))|| + ((pos_nq > neg_nq) && (pos_nq > 2.0*pos_q)&&(!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + IF ((GT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(pos_nq_fx,13107),pos_q_fx)&&(hSC_VBR->rate_control))|| + (GT_32(pos_nq_fx , neg_nq_fx) && GT_32(Mult_32_16(pos_nq_fx,16384),pos_q_fx) && (!hSC_VBR->rate_control))) + { + PPP_MODE_E='B'; + move16(); + } + + /* if ((((pos_nq < neg_nq) && (neg_nq > 2.5*neg_q))&&(st->rate_control))|| + ((pos_nq < neg_nq) && (neg_nq > 2.0*neg_q)&&(!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + IF ((LT_32(pos_nq_fx , neg_nq_fx)&>_32(Mult_32_16(neg_nq_fx,13107),neg_q_fx)&&(hSC_VBR->rate_control))|| + (LT_32(pos_nq_fx , neg_nq_fx) && GT_32(Mult_32_16(neg_nq_fx,16384),neg_q_fx) && (!hSC_VBR->rate_control))) + { + PPP_MODE_E='B'; + move16(); + } + } + + + IF ( hSC_VBR->rate_control ) + { + + DTFS_peaktoaverage_fx(*CURRP_NQ_FX,&pos_nq0_fx,&Qposnq,&neg_nq0_fx,&Qnegnq); + + impzi_fx[0]=1; + move16(); + FOR (x_fx=1; x_fx<160; x_fx++) + { + impzi_fx[x_fx]=0; + move16(); + } + + FOR (x_fx=0; x_fx<160; x_fx++) + { + impzo_fx[x_fx]=0; + move16(); + } + + FOR (x_fx=0; x_fx<10; x_fx++) + { + mem_fx[x_fx]=0; + move16(); + } + + /* lpc2_fx in Q12, so Qadj is set to 3 toi bring it to Q15 */ + Qadj = 15-12; + move16(); + synthesis_filter_fx(lpc2_fx,&impzi_fx[0],&impzo_fx[0],&mem_fx[0],10,160 ); + + /* compute energy of impz */ + FOR (x_fx=0; x_fx<160; x_fx++) + { +#ifdef BASOP_NOGLOB + energy_impz_fx = L_add_o(energy_impz_fx , L_mult0(impzo_fx[x_fx],impzo_fx[x_fx]), &Overflow); +#else + energy_impz_fx = L_add(energy_impz_fx , L_mult0(impzo_fx[x_fx],impzo_fx[x_fx])); +#endif + } + + /*energy_impz = (float)(10*log10((float)energy_impz)); */ + exp_ee = norm_l(energy_impz_fx); + frac_ee = Log2_norm_lc(L_shl(energy_impz_fx, exp_ee)); + exp_ee = sub(30, exp_ee); /*30-exp-Q0 */ + Ltmp = Mpy_32_16(exp_ee, frac_ee, LG10); /* Ltmp Q14 */ + energy_impz_fx =L_shr(Ltmp, 3); /* 16+11(4bits for 15 no) = 14+x => x= 11 */ + /* energy_impz_fx is Q11 */ + + Ltmp_32 = DTFS_getEngy_fx(CURRP_Q_E_FX); /*Q = 2*(CURRP_Q_E_FX->Q) */ + Qadj = sub(hSC_VBR->Q_prev_cw_en_fx, shl(CURRP_Q_E_FX->Q, 1)); +#ifdef BASOP_NOGLOB + Ltmp_32 = L_shl_o(Ltmp_32,Qadj, &Overflow); /* shift left required to adjust Q of CURRP_Q_E_FX = Q_prev_cw_en_fx */ +#else + Ltmp_32 = L_shl(Ltmp_32,Qadj); /* shift left required to adjust Q of CURRP_Q_E_FX = Q_prev_cw_en_fx */ +#endif + /* if ((DTFS_getEngy(*CURRP_Q_E) > st->prev_cw_en)&&(max(pos_q,neg_q)>3.5) && energy_impz>15.0 && tmpres>0.7) */ + test(); + test(); + test(); +#ifdef BASOP_NOGLOB + IF ((GT_32(Ltmp_32, hSC_VBR->prev_cw_en_fx ))&&(GT_32(L_max(pos_q_fx,neg_q_fx),939524096))&&(GT_32(energy_impz_fx,30720)) + && (GT_32(Mult_32_16(tmpres_fx,23265),shl_o(1,sub(Qtmpres,1), &Overflow))) ) +#else + IF ((GT_32(Ltmp_32, hSC_VBR->prev_cw_en_fx ))&&(GT_32(L_max(pos_q_fx,neg_q_fx),939524096))&&(GT_32(energy_impz_fx,30720)) + && (GT_32(Mult_32_16(tmpres_fx,23265),shl(1,sub(Qtmpres,1)))) ) +#endif + { + /* if ((pos_q > neg_q) && ((pos_q>3.0*pos_nq0) || ((pos_q > 1.5*pos_nq0) && (neg_q < 1.5*neg_nq0)))) */ + test(); + test(); + test(); + IF ( (GT_32(pos_q_fx , neg_q_fx)) + && ((GT_32(Mult_32_16(pos_q_fx,10923), L_shr(pos_nq0_fx,sub(Qposnq,28)) )) + || ((GT_32( Mult_32_16(pos_q_fx,21845),L_shr(pos_nq0_fx,sub(Qposnq,28)) )) + && (LT_32(Mult_32_16(neg_q_fx,21846), L_shr(neg_nq0_fx,sub(Qnegnq,28)) )) )) + ) + /* 10923 = (1/3) oin Q15, pos_q_fx is Q28, so result of Mult_32_16(pos_q_fx,10923) = Q28 */ + /* L_shr(pos_nq0_fx,sub(Qposnq,28)) brings pos_nq0_fx with variable Q to fixed Q28 */ + { + PPP_MODE_E='B'; + move16(); + } + test(); + test(); + test(); + /* if ((pos_q <= neg_q) && ((neg_q>3.0*neg_nq0)|| ((neg_q > 1.5*neg_nq0) && (pos_q < 1.5*pos_nq0)))) */ + IF ( (LE_32(pos_q_fx ,neg_q_fx)) + && ((GT_32(Mult_32_16(neg_q_fx,10923), L_shr(neg_nq0_fx,sub(Qnegnq,28)))) + || ((GT_32(Mult_32_16(neg_q_fx,21846), L_shr(neg_nq0_fx,sub(Qnegnq,28)))) + && (LT_32( Mult_32_16( pos_q_fx,21846),L_shr(pos_nq0_fx,sub(Qposnq,28)))))) + ) + { + PPP_MODE_E='B'; + move16(); + } + } + } + } + + DTFS_copy_fx(TMPDTFS2_FX,*CURRP_Q_E_FX); + DTFS_poleFilter_fx_9(TMPDTFS_FX, pf_temp1, pf_temp2, pf_temp, pf_n2); + DTFS_poleFilter_fx_9(TMPDTFS2_FX, pf_temp1, pf_temp2, pf_temp, pf_n2); + + DTFS_sub_fx(TMPDTFS3_FX, *TMPDTFS_FX,*TMPDTFS2_FX); + + + /* operate in ADR mode only the rate control is active. This adds some bumpups to improve the speech quality */ + /* if ((DTFS_getEngy_band(*TMPDTFS, 1500.0, upper_cut_off_freq_of_interest)/DTFS_getEngy(*TMPDTFS) > 0.05)&&(!st->rate_control)) */ + Ltemp1 = DTFS_getEngy_band_fx(*TMPDTFS_FX, 1500, upper_cut_off_freq_of_interest_fx); /* Q = 2*TMPDTFS_FX->Q*/ + Ltemp2 = DTFS_getEngy_fx(TMPDTFS_FX); /* Q = 2*TMPDTFS_FX->Q */ + + IF (Ltemp2==0) + { + Ltemp_fx=0; + } + ELSE + { + expb = norm_l(Ltemp1); + fracb = extract_h(L_shl(Ltemp1,expb)); + expb = sub(30, add(expb,shl(TMPDTFS_FX->Q, 1))); + expa = norm_l(Ltemp2); + fraca = extract_h(L_shl(Ltemp2,expa)); + expa = sub(30, add(expa,shl(TMPDTFS_FX->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); /* tmp in Q15 */ + exp = sub(expb,expa); /* ans = tmp*2^(exp) */ +#ifdef BASOP_NOGLOB + Ltemp_fx = L_shl_o(tmp, add(exp,12), &Overflow); /* make tmp Q27 */ +#else + Ltemp_fx = L_shl(tmp, add(exp,12)); /* make tmp Q27 */ +#endif + + } + test(); + IF (GT_32(Ltemp_fx , 6710886)&&(!hSC_VBR->rate_control)) /* 0.05 in Q27 = 6710886 */ + { + /*if (10.0*log10(DTFS_getEngy_band(*TMPDTFS,1500.0,upper_cut_off_freq_of_interest)/ */ + /*DTFS_getEngy_band(*TMPDTFS3,1500.0,upper_cut_off_freq_of_interest)) < 0.1) */ + + Ltemp1 = DTFS_getEngy_band_fx(*TMPDTFS_FX,1500,upper_cut_off_freq_of_interest_fx); + Ltemp2 = DTFS_getEngy_band_fx(*TMPDTFS3_FX,1500,upper_cut_off_freq_of_interest_fx); + + /*--------------------------------------------------------------*/ + /* Ltemp_fx = (Word32)divide_dp(Ltemp1, Ltemp2, Qadj,1);//Q29+1 */ + /*--------------------------------------------------------------*/ + IF (Ltemp2==0) + { + Ltemp_fx=0; + } + ELSE + { + expa = norm_l(Ltemp2); + fraca = extract_h(L_shl(Ltemp2,expa)); + expa = sub(30, expa); + + expb = norm_l(Ltemp1); + fracb = round_fx(L_shl(Ltemp1,expb)); + expb = sub(30,expb); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); +#ifdef BASOP_NOGLOB + Ltemp_fx = L_shl_o(tmp,add(exp,14), &Overflow); /* answer in Q29 */ +#else + Ltemp_fx = L_shl(tmp,add(exp,14)); /* answer in Q29 */ +#endif + + } + /*-------------------------------------------*/ + + /* 10.0*log10(Ltemp_fx) */ + exp_ee = norm_l(Ltemp_fx); + frac_ee = Log2_norm_lc(L_shl(Ltemp_fx, exp_ee)); + exp_ee = sub(30,add(exp_ee,29)); /* 30 fixed here, 29 is the Q of Ltemp_fx */ + Ltmp = Mpy_32_16(exp_ee, frac_ee, LG10); /* LG10 in Q13, so answer Ltmp in Q14 */ + + IF(LT_32(Ltmp,1638)) /* 1638 = 0.1 in Q14 */ + { + /* if (res_enratio > 0.8) */ + if (GT_32(res_enratio_fx , 1638)) /* 1638 = 0.8 in Q11, res_enratio_fx in Q11 */ + { + PPP_MODE_E = 'B'; + move16(); + } + } + } + + /* To increase bump up, raise first threshold, lower second */ + /*tmp = (float)(10.0*log10(DTFS_getEngy(*TMPDTFS)/DTFS_getEngy(*TMPDTFS3)));*/ + Lacc = DTFS_getEngy_P2A_fx(TMPDTFS_FX); /* Q = 2*(TMPDTFS_FX->Q) */ + Lacc1= DTFS_getEngy_P2A_fx(TMPDTFS3_FX); /* Q = 2*(TMPDTFS3_FX->Q) */ + + + sft=shl(sub(TMPDTFS_FX->Q,TMPDTFS3_FX->Q),1);/* to check if Lacc<=2*Lacc1 */ + flag1=0; + move16(); + IF (sft>0) + { + /*if (L_sub40_40(L_shr40(Lacc,sft),Lacc1)<=0) */ + Lacc = L_shr(Lacc,sft); + flag1=1; + move16(); /* do the divide */ + } + ELSE + { + /*if (L_sub40_40(Lacc,L_shr40(Lacc1,negate(sft)))<=0) */ + Lacc1 = L_shr(Lacc1,negate(sft)); + flag1=1; + move16();/* do the divide */ + } + IF (EQ_16(flag1,1)) + { + expb = norm_l(Lacc); + fracb = extract_h(L_shl(Lacc,expb)); + expb = sub(30,add(expb,shl(TMPDTFS_FX->Q, 1))); + + expa = norm_l(Lacc1); + fraca = extract_h(L_shl(Lacc1,expa)); + expa = sub(30,add(expa,shl(TMPDTFS3_FX->Q, 1))); + + scale = shr(sub(fraca,fracb),15); + fracb = shl(fracb,scale); + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); /* tmp is always Q15 */ + exp = sub(expb,expa); /* Answer after division Lacc/Lacc1 = (2^exp)*(tmp/2^15) */ + + L_tmp = L_deposit_h(tmp); /* tmp is always Q15, L_tmp is always Q31 */ + expa = norm_l(L_tmp); + L_tmp = L_shl(L_tmp,expa); + exp = sub(30,add(expa,sub(31,exp))); + frac = Log2_norm_lc(L_tmp); + L_tmp = Mpy_32_16(exp,frac,12330); /* L_tmp is always Q13 */ +#ifdef BASOP_NOGLOB + Ltemp = L_shl_o(L_tmp,10, &Overflow); /* Ltemp is always Q23 */ +#else + Ltemp = L_shl(L_tmp,10); /* Ltemp is always Q23 */ +#endif + } + ELSE + { + Ltemp = L_add(MAX_32, 0); + } + + test(); + if ((Ltemp <= 0)&&(!hSC_VBR->rate_control)) + { + PPP_MODE_E = 'B'; + move16(); + } + +#ifdef BASOP_NOGLOB + IF ( LT_16(shl_o(hSC_VBR->vadsnr_fx,1, &Overflow) ,hSC_VBR->SNR_THLD_fx)) /* Q8 */ +#else + IF ( LT_16(shl(hSC_VBR->vadsnr_fx,1) ,hSC_VBR->SNR_THLD_fx)) /* Q8 */ +#endif + { + /* if ((( tmp < 3.05 && max(res_enratio,sp_enratio) > 0.8 ) && (st->rate_control))|| + (( tmp < 2.8 && max(res_enratio,sp_enratio) > 0.65 ) && (!st->rate_control))) */ + /* First comparison in Q23, Second comparison in Q15 */ + test(); + test(); + test(); + test(); + test(); + if ((( LT_32(Ltemp, 25585254 )&>_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx),6554))&&(hSC_VBR->rate_control))|| + (( LT_32(Ltemp, 23488102 ) && GT_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx) , 5325) )&&(!hSC_VBR->rate_control))) + { + PPP_MODE_E = 'B'; + move16(); + } + } + ELSE + { + /* if ((( tmp < 2.4 && max(res_enratio,sp_enratio) > 0.94) && (st->rate_control))|| + (( tmp < 4.5 && max(res_enratio,sp_enratio) > 0.5 ) && (!st->rate_control))) */ + test(); + test(); + test(); + test(); + test(); + if ((( LT_32(Ltemp ,20132659 )&>_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx),7700))&&(hSC_VBR->rate_control))|| + (( LT_32(Ltemp, 37748736 ) && GT_32(L_max(L_shl(res_enratio_fx,4),sp_enratio_fx) , 4096) )&&(!hSC_VBR->rate_control))) + { + PPP_MODE_E = 'B'; + move16(); + } + } + + /* -----End closed-loop Bump-Up */ + } + ELSE + { + PPP_MODE_E = 'B' ; + move16();/*Amplitude quantization is failing*/ + } + } + ELSE + { + } + if (PPP_MODE_E == 'B') + { + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + + IF ( hSC_VBR->Q_to_F ) + { + hSC_VBR->patterncount = add(hSC_VBR->patterncount ,hSC_VBR->pattern_m); + + IF (GE_16(hSC_VBR->patterncount , 1000)) + { + hSC_VBR->patterncount = sub (hSC_VBR->patterncount , 1000); + PPP_MODE_E = 'B'; + move16(); + hSC_VBR->bump_up = 1; + move16(); + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + return error; + } + + } + + /* packetization of the delta lag in_fx PPP */ + IF (EQ_16(PPP_MODE_E,'Q')) + { + Q_delta_lag = add(delta_lag_E,11); /* to make it positive always */ + + push_indice_fx(hBstr, IND_DELTALAG, Q_delta_lag, 5 ); + } + + WIsyn_fx(*dtfs_temp_fx, CURRP_Q_E_FX, lpc2_fx, &(hSC_VBR->ph_offset_E_fx), out_fx, L_FRAME,0,S_fx,C_fx, + pf_temp1,pf_temp2,pf_temp,pf_n2); + /* i/o ph_offset_fx in Q15, out_fx in Q0 */ + + DTFS_copy_fx(dtfs_temp_fx, *CURRP_Q_E_FX); + Lacc = DTFS_getEngy_P2A_fx(CURRP_NQ_FX); + hSC_VBR->Q_prev_cw_en_fx=norm_l(Lacc); + + /* hSC_VBR->Q_prev_cw_en_fx = (Lacc==0)?31: hSC_VBR->Q_prev_cw_en_fx;move16(); */ + if (Lacc==0) + { + hSC_VBR->Q_prev_cw_en_fx = 31; + move16(); + } + + hSC_VBR->prev_cw_en_fx=(Word32) L_shl(Lacc,hSC_VBR->Q_prev_cw_en_fx); /*2Q+Q_prev_cw_en_fx */ + hSC_VBR->Q_prev_cw_en_fx=add(hSC_VBR->Q_prev_cw_en_fx,shl(CURRP_NQ_FX->Q,1)); + /* Copy DTFS related parameters from 'dtfs_temp' to 'st_fx' structure */ + hSC_VBR->dtfs_enc_lag = dtfs_temp_fx->lag_fx; + move16(); + hSC_VBR->dtfs_enc_nH = dtfs_temp_fx->nH_fx; + move16(); + hSC_VBR->dtfs_enc_nH_4kHz = dtfs_temp_fx->nH_4kHz_fx; + move16(); + hSC_VBR->dtfs_enc_upper_cut_off_freq_of_interest_fx = dtfs_temp_fx->upper_cut_off_freq_of_interest_fx; + move16(); + hSC_VBR->dtfs_enc_upper_cut_off_freq_fx = dtfs_temp_fx->upper_cut_off_freq_fx; + move16(); + Copy(dtfs_temp_fx->a_fx, hSC_VBR->dtfs_enc_a_fx, MAXLAG_WI); + Copy(dtfs_temp_fx->b_fx, hSC_VBR->dtfs_enc_b_fx, MAXLAG_WI); + + hSC_VBR->dtfs_enc_Q = dtfs_temp_fx->Q; + move16(); + + count_free(CURRP_NQ_FX); + count_free(TMPDTFS_FX); + count_free(TMPDTFS2_FX); + count_free(TMPDTFS3_FX); + count_free(CURRP_Q_E_FX); + count_free(dtfs_temp_fx); + + return error; +} + + +/*===================================================================*/ +/* FUNCTION : synthesis_filter_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : IIR-filter residual by the LPC sysnthesis filter */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) b : filter coefficients (Qc). */ +/* _ (Word16 []) x : residual input (Qn). */ +/* _ (Word16) P : filter order. */ +/* _ (Word16) N : number of input samples. */ +/* _ (Word16) Qa : Q factor compensation (Qa=15-Qc) */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word16 []) y : output speech (Qn) */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* */ +/* _ (Word32 []) buf : filter memory (Q16+Qn) */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*===================================================================*/ +/* y(n)=sum(i=1 to 10){ */ +/* rxLpcCoeff(i)*rxFormSynthMem(n-i) */ +/* } */ +/* +fres(n) */ +/*===================================================================*/ +static void synthesis_filter_fx (Word16 b[], Word16 x[], Word16 y[], Word16 buf[], Word16 P, Word16 N ) +{ + Word32 acc; + Word16 i, j; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + FOR (i = 0; i < N; i++) + { + acc = L_deposit_h(*x++);/*Q16 */ + acc = L_shr(acc, 3);/*Q13 */ + + FOR (j = P - 1; j > 0; j--) + { + /* acc = L_sub(acc, L_mult(memory[j], coef[j])); */ +#ifdef BASOP_NOGLOB + acc = L_msu_o(acc, buf[j], b[j], &Overflow);/*Q13 */ +#else + acc = L_msu(acc, buf[j], b[j]);/*Q13 */ +#endif + buf[j] = buf[j - 1]; + move16(); + } + /* acc = L_sub(acc, L_mult(memory[0], coef[0])); */ +#ifdef BASOP_NOGLOB + acc = L_msu_o(acc, buf[0], b[0], &Overflow); + acc = L_shl_o(acc, 3, &Overflow); + + *y++ = round_fx_o(acc, &Overflow); + buf[0] = round_fx_o(acc, &Overflow); +#else + acc = L_msu(acc, buf[0], b[0]); + acc = L_shl(acc, 3); + + *y++ = round_fx(acc); + buf[0] = round_fx(acc); +#endif + } +} +/*==============================================================================*/ +/* FUNCTION : DTFS_freq_corr_fx () */ +/*------------------------------------------------------------------------------*/ +/* PURPOSE : */ +/*------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X1_DTFS_fx : a_fx/b_fx in X1_DTFS_fx.Q */ +/* _ (struct DTFS_STRUCTURE_FX) X2_DTFS_fx : a_fx/b_fx in X2_DTFS_fx.Q */ +/* _ (Word16) lband: Q0 */ +/* _ (Word16) hband: Q0 */ +/*------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) *Qout : Q of output result */ +/*------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ (Word32) Result : Qout */ +/*------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*==============================================================================*/ + +static Word32 DTFS_freq_corr_fx( + DTFS_STRUCTURE X1_DTFS_fx, + DTFS_STRUCTURE X2_DTFS_fx, + Word16 lband, + Word16 hband, + Word16* Qout +) +{ + Word16 k, HalfLag, lk, hk; + Word32 corr_fx; + Word32 freq_fx, L_lband, L_hband; + Word32 E_fx; + Word32 Num, Den, Result; + Word16 E1_fx, E2_fx, q1, q2, Qr; + Word16 expa, expb, fraca, fracb, scale; + Word16 exp, tmp; + Word32 L_tmp; + Word16 Q_num, Q_den; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + IF(LT_16(X1_DTFS_fx.lag_fx, X2_DTFS_fx.lag_fx)) + { + DTFS_zeroPadd_fx(X2_DTFS_fx.lag_fx, &X1_DTFS_fx); + } + + corr_fx = L_deposit_l(0); + + L_lband = L_mult(lband, X2_DTFS_fx.lag_fx); + L_hband = L_mult(hband, X2_DTFS_fx.lag_fx); + HalfLag = s_min(shr(X2_DTFS_fx.lag_fx, 1), X2_DTFS_fx.nH_4kHz_fx); + + /* get lband and hband */ + FOR(k = 0; k <= HalfLag; k++) + { + freq_fx = L_mult(k, 12800); + IF(GE_32(freq_fx, L_lband)) + { + BREAK; + } + } + lk = k; + FOR(k = 0; k <= HalfLag; k++) + { + freq_fx = L_mult(k, 12800); + IF(GE_32(freq_fx, L_hband)) + { + BREAK; + } + } + hk = k; + move16(); + + FOR(k = lk; k < hk; k++) + { +#ifdef BASOP_NOGLOB + corr_fx = L_mac0_o(corr_fx, X1_DTFS_fx.a_fx[k], X2_DTFS_fx.a_fx[k], &Overflow); /* Q(1) */ + corr_fx = L_mac0_o(corr_fx, X1_DTFS_fx.b_fx[k], X2_DTFS_fx.b_fx[k], &Overflow); /* Q(1) */ +#else + corr_fx = L_mac0(corr_fx, X1_DTFS_fx.a_fx[k], X2_DTFS_fx.a_fx[k]); /* Q(1) */ + corr_fx = L_mac0(corr_fx, X1_DTFS_fx.b_fx[k], X2_DTFS_fx.b_fx[k]); /* Q(1) */ +#endif + } + + Qr = norm_l(corr_fx); + if (corr_fx == 0) + { + Qr = 31; + move16(); + } + +#ifdef BASOP_NOGLOB + E1_fx = round_fx_o(L_shl_o(corr_fx, Qr, &Overflow), &Overflow); /* Q(Qr-16) */ +#else + E1_fx = round_fx(L_shl(corr_fx, Qr)); /* Q(Qr-16) */ +#endif + Num = L_mult0(E1_fx, E1_fx); /* Q(2+2*Qr-32+1) */ + Q_num = sub(shl(add(add(X1_DTFS_fx.Q, X2_DTFS_fx.Q), Qr), 1), 32); + + /* PORTING: Handling the functions with variable no. of arguments */ + E_fx = DTFS_getEngy_band_fx(X1_DTFS_fx, lband, hband); /* Q(1) */ + q1 = norm_l(E_fx); + if (E_fx == 0) + { + q1 = 31; + move16(); + } + +#ifdef BASOP_NOGLOB + E1_fx = round_fx_o( L_shl_o( E_fx, q1, &Overflow ), &Overflow ); /* Q(1+q1-16) */ +#else + E1_fx = round_fx( L_shl( E_fx, q1 ) ); /* Q(1+q1-16) */ +#endif + /* PORTING: Handling the functions with variable no. of arguments */ + E_fx = DTFS_getEngy_band_fx(X2_DTFS_fx, lband, hband); /* Q(1) */ + q2 = norm_l(E_fx); + if (E_fx == 0) + { + q2 = 31; + move16(); + } + +#ifdef BASOP_NOGLOB + E2_fx = round_fx_o(L_shl_o(E_fx, q2, &Overflow), &Overflow); /* Q(1+q2-16) */ +#else + E2_fx = round_fx( L_shl( E_fx, q2 ) ); /* Q(1+q2-16) */ +#endif + Den = L_mult0(E1_fx, E2_fx); /* Q(2+q1+q2-32+1) */ + Q_den = sub( add( shl( add( X2_DTFS_fx.Q, X1_DTFS_fx.Q ), 1 ), add( q1, q2 ) ), 32 ); + + Num = L_max(Num, 1); + + IF(Num == 0) + { + Result = 0; + *Qout = 31; + } + ELSE + { + + expa = norm_l(Num); +#ifdef BASOP_NOGLOB + fraca = extract_h(L_shl_o(Num,expa, &Overflow)); +#else + fraca = extract_h(L_shl(Num,expa)); +#endif + expa = sub(30, add(expa,Q_num)); + + + expb = norm_l(Den); +#ifdef BASOP_NOGLOB + fracb = round_fx_o(L_shl_o(Den,expb, &Overflow), &Overflow); +#else + fracb = round_fx(L_shl(Den,expb)); +#endif + expb = sub(30, add(expb,Q_den)); + + + scale = shr(sub(fraca,fracb),15); +#ifdef BASOP_NOGLOB + fracb = shl_o(fracb,scale, &Overflow); +#else + fracb = shl(fracb,scale); +#endif + expb = sub(expb,scale); + + tmp = div_s(fracb,fraca); + exp = sub(expb,expa); + + L_tmp = Isqrt_lc(L_deposit_h(tmp),&exp); /* Q(31-exp) */ + IF(corr_fx > 0) + { + Result = L_add(L_tmp, 0); + } + ELSE + { + Result = L_negate(L_tmp); + } + *Qout = sub(30,exp); + + } + return Result; +} +/*===================================================================*/ +/* FUNCTION : DTFS_alignment_extract_td_fx () */ +/*-------------------------------------------------------------------*/ +/* PURPOSE : search for alignment in time domain */ +/*-------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (Word16 *) x1: Q? */ +/* _ (Word16 *) x2: Q? */ +/*-------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16) lag : Q0 */ +/*-------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*-------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ (Word16 *) idx: Q0 */ +/*-------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*===================================================================*/ + +static Word16 DTFS_alignment_extract_td_fx(Word16* x1, Word16* x2, Word16 lag) +{ + Word16 j, k, idx, Adiff_fx; + Word32 maxcorr, corr; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + maxcorr = L_add(MIN_32, 0); + Adiff_fx = (Word16)(s_max(4, shr(lag, 3))); + + idx = 0; + move16(); + FOR(j = negate(Adiff_fx); j <= Adiff_fx; j++) + { + corr = L_deposit_l(0); + FOR(k = 0; k < lag; k++) + { +#ifdef BASOP_NOGLOB + corr = L_mac_o(corr, x1[k], x2[(k - j + lag) % lag], &Overflow); +#else + corr = L_mac(corr, x1[k], x2[(k - j + lag) % lag]); +#endif + } + if (GT_32(corr, maxcorr)) + { + idx = j; + move16(); + maxcorr = L_add(corr, 0); + } + } + return idx; +} +/*=================================================================================*/ +/* FUNCTION : DTFS_getEngy_band_fx (Word16 lband, Word16 hband) */ +/*---------------------------------------------------------------------------------*/ +/* PURPOSE : compute the energy of X1.a[k] and X2.b[k] */ +/*---------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _ (struct DTFS_STRUCTURE_FX) X_fx : a_fx/b_fx in X_fx.Q, lag in Q0 */ +/* _ (Word16) lband: Q0 */ +/* _ (Word16) hband: Q0 */ +/*---------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word40) en_fx : 2*X1.Q */ +/*---------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ None */ +/*---------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : _ None. */ +/*---------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*=================================================================================*/ + +/* PORTING: Handling the functions with variable no. of arguments */ + +static Word32 DTFS_getEngy_band_fx( + DTFS_STRUCTURE X_fx, + const Word16 lband, + const Word16 hband +) +{ + Word16 k, lk, hk, HalfLag; + Word32 freq_fx, L_lband, L_hband; + Word32 en_fx = 0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + L_lband = L_mult(lband, X_fx.lag_fx); + L_hband = L_mult(hband, X_fx.lag_fx); + HalfLag = s_min(shr(sub(X_fx.lag_fx, 1), 1), X_fx.nH_4kHz_fx); + /* get lband and hband */ + FOR(k = 1; k <= HalfLag; k++) + { + freq_fx = L_mult(k, 12800); + IF(GE_32(freq_fx, L_lband)) + { + BREAK; + } + } + lk = k; + move16(); + FOR(k = 1; k <= HalfLag; k++) + { + freq_fx = L_mult(k, 12800); + IF(GE_32(freq_fx, L_hband)) + { + BREAK; + } + } + hk = k; + move16(); + + FOR(k = lk; k < hk; k++) + { +#ifdef BASOP_NOGLOB + en_fx = L_mac0_o(en_fx, X_fx.a_fx[k], X_fx.a_fx[k], &Overflow); /* 2*X1.Q+1 */ + en_fx = L_mac0_o(en_fx, X_fx.b_fx[k], X_fx.b_fx[k], &Overflow); +#else + en_fx = L_mac0(en_fx, X_fx.a_fx[k], X_fx.a_fx[k]); /* 2*X1.Q+1 */ + en_fx = L_mac0(en_fx, X_fx.b_fx[k], X_fx.b_fx[k]); +#endif + } + + if (lband == 0) + { + en_fx = L_mac0(en_fx, X_fx.a_fx[0], X_fx.a_fx[0]); /* 2*X1.Q+1 */ + } + + /* IF ((X_fx.lag_fx%2 == 0) && (hband == X_fx.upper_cut_off_freq_fx)) */ + test(); + IF((s_and(X_fx.lag_fx, 1) == 0) && (hband == X_fx.upper_cut_off_freq_fx)) + { +#ifdef BASOP_NOGLOB + en_fx = L_mac0_o(en_fx, X_fx.a_fx[k], X_fx.a_fx[k], &Overflow); + en_fx = L_mac0_o(en_fx, X_fx.b_fx[k], X_fx.b_fx[k], &Overflow); +#else + en_fx = L_mac0(en_fx, X_fx.a_fx[k], X_fx.a_fx[k]); + en_fx = L_mac0(en_fx, X_fx.b_fx[k], X_fx.b_fx[k]); +#endif + } + + return en_fx; /* 2*X1.Q */ +} +/*---------------------------------------------------------------------* + * sc_vbr_enc_init_fx() + * + * Initialize SC-VBR encoder + *---------------------------------------------------------------------*/ + +void sc_vbr_enc_init_fx( + SC_VBR_ENC_HANDLE hSC_VBR /* i/o: SC-VBR encoder handle */ +) +{ + hSC_VBR->nelp_enc_seed = 0; + move16(); + hSC_VBR->last_nelp_mode = 0; + move16(); + hSC_VBR->pppcountE = 0; + move16(); + hSC_VBR->last_ppp_mode = 0; + move16(); + hSC_VBR->last_last_ppp_mode = 0; + move16(); + hSC_VBR->firstTime_voicedenc = 1; + move16(); + hSC_VBR->prev_ppp_gain_pit_fx = 0; + move16(); + hSC_VBR->prev_tilt_code_fx = 0; + move16(); + + hSC_VBR->ppp_mode = 0; + move16(); + hSC_VBR->nelp_mode = 0; + move16(); + + + hSC_VBR->pattern_m = 0; + move16(); + hSC_VBR->Last_Resort = 0; + move16(); + hSC_VBR->Q_to_F = 0; + move16(); + + hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ + hSC_VBR->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ + hSC_VBR->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + hSC_VBR->frame_cnt_ratewin_fx = 0; /* 600 active frame block count. Used to update the global rate*/ + hSC_VBR->rate_control = 0; + move16(); + hSC_VBR->SNR_THLD_fx = SNR_THLD_FX_Q8; + move16(); + hSC_VBR->mode_QQF = 1; + move16(); + + hSC_VBR->vbr_generic_ho = 0; + move16(); + hSC_VBR->Local_VAD = 0; + + hSC_VBR->Last_Resort = 0; + hSC_VBR->set_ppp_generic = 0; + + hSC_VBR->last_7k2_coder_type = GENERIC; + move16(); + + set16_fx(hSC_VBR->shape1_filt_mem_fx, 0, 10); + set16_fx(hSC_VBR->shape2_filt_mem_fx, 0, 10); + set16_fx(hSC_VBR->shape3_filt_mem_fx, 0, 10); + set16_fx(hSC_VBR->txlpf1_filt1_mem_fx, 0, 10); + set16_fx(hSC_VBR->txlpf1_filt2_mem_fx, 0, 10); + set16_fx(hSC_VBR->txhpf1_filt1_mem_fx, 0, 10); + set16_fx(hSC_VBR->txhpf1_filt2_mem_fx, 0, 10); + hSC_VBR->qprevIn_fx = 0; + move16(); + hSC_VBR->qprevGain_fx = 0; + move16(); + + return; +} + diff --git a/lib_enc/waveadjust_fec_cod_fx.c b/lib_enc/waveadjust_fec_cod_fx.c new file mode 100644 index 0000000000000000000000000000000000000000..988d7564c2c8e2fa883587eeba5c35a247ac9ddd --- /dev/null +++ b/lib_enc/waveadjust_fec_cod_fx.c @@ -0,0 +1,85 @@ +/*==================================================================================== + EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0 + ====================================================================================*/ + +#include +#include "options.h" /* for wmc_tool */ +#include "cnst.h" +//#include "prot_fx.h" +#include "rom_com_fx.h" +#include "rom_com.h" +#include "stat_com.h" +#include "prot_fx1.h" /* Function prototypes */ +#include "prot_fx2.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ + +/*-------------------------------------------------------------------* + * SFM_Cal_fx() + * + * + *--------------------------------------------------------------------*/ + +Word32 SFM_Cal_fx(Word32 magn[], Word16 n) +{ + /* Counted Dymamic RAM: 16 words */ + Word32 logCurFlatness; + Word32 magn_abs, frac, logMagn, sumLogMagn, sumMagn; + Word16 i, norm_value, logSumMagn, logn; + sumLogMagn = L_deposit_l(0); + sumMagn = L_deposit_l(0); + FOR(i = 0; i < n; i++) + { + /* log2(magn(i)) */ + magn_abs = L_abs(magn[i]); + norm_value = norm_l(L_max(magn_abs, 1)); + /* next two codes lost precision. */ + frac = L_and(L_shr(L_shl(magn_abs, norm_value), 22), 0xFF); + logMagn = L_deposit_l(add(shl(sub(30, norm_value), 8), kLog2TableFrac_x[frac]));; /* Q8 */ + /* sum(log2(magn(i))) */ + sumLogMagn =L_add(sumLogMagn, logMagn); /* Q8 */ + + sumMagn =L_add(sumMagn, magn_abs); + } + + IF(EQ_32(sumMagn,MAX_32)) + { + sumMagn = L_deposit_l(0); + FOR(i = 0; i < n; i++) + { + magn_abs = L_shr(L_abs(magn[i]), 8); + sumMagn = L_add(sumMagn, magn_abs); + } + /* log2(sumMagn) */ + norm_value = norm_l(sumMagn); + frac = L_and(L_shr(L_shl(sumMagn, norm_value), 22), 0xFF); + logSumMagn = add(shl(sub(38,norm_value), 8), kLog2TableFrac_x[frac]); /* Q8 */ + } + ELSE + { + /* log2(sumMagn) */ + norm_value = norm_l(sumMagn); + frac = L_and(L_shr(L_shl(sumMagn, norm_value), 22), 0xFF); + logSumMagn = add(shl(sub(30, norm_value), 8), kLog2TableFrac_x[frac]); /* Q8 */ + } + + /* log2(n) */ + norm_value = norm_l(n); + frac = L_and(L_shr(L_shl(n, norm_value), 22), 0xFF); + logn = add(shl(sub(30, norm_value), 8), kLog2TableFrac_x[frac]); /* Q8 */ + + + logMagn=L_sub(L_mult0(n, sub(logSumMagn, logn)), sumLogMagn); + logMagn = (Word32)L_max(0, logMagn); + + logCurFlatness = L_deposit_l(div_l(L_shl(logMagn, 1), n)); + frac = L_and(logCurFlatness, 0xFF); + norm_value = (Word16)L_shr(logCurFlatness, 8); + move16(); + + logCurFlatness = L_sub(kExp2TableFrac_x[frac], 33); + logCurFlatness = L_shl(logCurFlatness, sub(16, norm_value)); /* Q31 */ + + + return logCurFlatness; +} + diff --git a/lib_rend/ivas_output_init_fx.c b/lib_rend/ivas_output_init_fx.c index d3dfaad7bb19346b23e55d407ce139b959bb54f6..477b430025cf207349e7415b6d31fc2d690a5a10 100644 --- a/lib_rend/ivas_output_init_fx.c +++ b/lib_rend/ivas_output_init_fx.c @@ -155,4 +155,4 @@ Word16 ivas_get_nchan_buffers_dec_ivas_fx( return nchan_out_buff; } -#endif // IVAS_FLOAT_FIXED \ No newline at end of file +#endif // IVAS_FLOAT_FIXED diff --git a/lib_util/audio_file_reader.c b/lib_util/audio_file_reader.c index 4f6bd0c34d13fd62439775d31933f9d67a4197f4..47ac4b13881a48d9e1af3a9e2e6c87422ffdc7c1 100644 --- a/lib_util/audio_file_reader.c +++ b/lib_util/audio_file_reader.c @@ -75,7 +75,8 @@ static int8_t AudioFileReader_open_wav( /*! r: AudioFileReader handle */ ivas_error AudioFileReader_open( AudioFileReader **audioReader, /* o : AudioFileReader handle */ - const char *fileName /* i : path to wav/raw pcm file */ + const char *fileName, /* i : path to wav/raw pcm file */ + short *isInputRawFile ) { AudioFileReader *self; @@ -104,10 +105,12 @@ ivas_error AudioFileReader_open( if ( fileNameLen > wavSuffixLen && strncmp( fileName + fileNameLen - wavSuffixLen, wavSuffix, wavSuffixLen ) == 0 ) { retCode = AudioFileReader_open_wav( self, fileName ); + *isInputRawFile = 0; } else { retCode = AudioFileReader_open_raw( self, fileName ); + *isInputRawFile = 1; } if ( retCode != 0 ) diff --git a/lib_util/audio_file_reader.h b/lib_util/audio_file_reader.h index 0fd4da5ac76c25285d3b49d67166ce651a96eeb8..2756d87b1e1de951bbb660b7756621e44f50e6d6 100644 --- a/lib_util/audio_file_reader.h +++ b/lib_util/audio_file_reader.h @@ -42,7 +42,8 @@ typedef struct AudioFileReader AudioFileReader; ivas_error AudioFileReader_open( AudioFileReader **audioReader, /* o : AudioFileReader handle */ - const char *fileName /* i : path to wav/raw pcm file */ + const char *fileName, /* i : path to wav/raw pcm file */ + short *isInputRawFile ); ivas_error AudioFileReader_read(