From 30ca7c5c4cc9e883da0fc571b1db30d39feb05ad Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Sat, 23 Mar 2024 23:27:13 +0530 Subject: [PATCH] Integration of fixed point sub-functions - 5 [x] Integration of fixed point version of ivas_sba_dirac_stereo_dec [x] Integrated bandwidth_switching_detect and redundant code removal in ivas_core_dec [x] Integration and Cleanup of MASA ISM metadata dec (OMASA path) [x] Refactor lsf buffers for core_switching_pre_dec() [x] Integration of few functions for MASA path. Few BASOP and instrumentation changes included. [x] Functions converted: ivas_qmetadata_azimuth_elevation_to_direction_vector_fx, sort_desc_ind_16_fx, only_reduce_bits_direction_fx. [x] Added saturation to getCosWord16R2 based on the recommendation from the PC group. [x] Limitations of only_reduce_bits_direction_fx: - Precision loss was occuring after using BASOP_Util_Divide3232_Scale which was leading to penalty getting calculated wrongly and hence ind_order being sorted incorrectly which might cause infinite loop. - Causing issues for Test OMASA 2Dir2TC 4ISM at 384 kbps, 48kHz in, 48kHz out, EXT out - Workaround is checking if the denominator is same for bits_sph_idx_orig[j] for no_subframes. If yes then adding all the numerator first and then doing division later with bits_sph_idx_orig[j][0] instead of dividing each numerator with bits_sph_idx_orig[j][k]. --- lib_com/basop_util.c | 5 + lib_com/cnst.h | 12 +- lib_com/float_to_fix_ops.c | 20 +- lib_com/ivas_masa_com.c | 43 +- lib_com/ivas_prot.h | 19 +- lib_com/ivas_prot_fx.h | 111 ++++ lib_com/ivas_qmetadata_com.c | 446 +++++++++++++- lib_com/ivas_qspherical_com.c | 97 +++ lib_com/ivas_rom_com.h | 1 + lib_com/ivas_rom_com_fx.c | 86 +++ lib_com/ivas_stat_com.h | 8 + lib_com/mslvq_com.c | 91 +++ lib_dec/amr_wb_dec.c | 26 +- lib_dec/core_dec_switch.c | 4 + lib_dec/core_dec_switch_fx.c | 8 + lib_dec/core_switching_dec.c | 7 +- lib_dec/evs_dec.c | 24 +- lib_dec/init_dec.c | 1 + lib_dec/init_dec_fx.c | 1 + lib_dec/ivas_core_dec.c | 24 +- lib_dec/ivas_corecoder_dec_reconfig.c | 1 + lib_dec/ivas_cpe_dec_fx.c | 76 ++- lib_dec/ivas_jbm_dec.c | 800 +++++++++++++++++++++---- lib_dec/ivas_omasa_dec.c | 217 ++++++- lib_dec/ivas_post_proc.c | 10 +- lib_dec/ivas_qmetadata_dec.c | 4 +- lib_dec/ivas_sba_dirac_stereo_dec.c | 3 +- lib_dec/ivas_sba_dirac_stereo_dec_fx.c | 177 ++++-- lib_dec/ivas_stat_dec.h | 8 +- lib_dec/ivas_stereo_dft_dec.c | 10 + lib_dec/ivas_stereo_dft_dec_fx.c | 121 +++- lib_dec/ivas_stereo_esf_dec.c | 12 +- lib_dec/ivas_stereo_switching_dec.c | 5 +- lib_dec/stat_dec.h | 12 +- lib_dec/updt_dec_fx.c | 36 ++ lib_enc/ivas_init_enc.c | 3 + lib_enc/ivas_masa_enc.c | 3 + lib_enc/ivas_mct_enc.c | 3 + lib_enc/ivas_qmetadata_enc.c | 4 + lib_enc/ivas_qspherical_enc.c | 3 + lib_rend/ivas_dirac_ana.c | 5 +- 41 files changed, 2223 insertions(+), 324 deletions(-) diff --git a/lib_com/basop_util.c b/lib_com/basop_util.c index bf25f1b0c..df9361b8b 100644 --- a/lib_com/basop_util.c +++ b/lib_com/basop_util.c @@ -1276,7 +1276,12 @@ Word16 getCosWord16R2( /* The negation cannot overflow, sine is in range [0x0..0x7FFF] */ BASOP_SATURATE_WARNING_OFF sine = negate( sine ); + /* Saturation has been included based on the recommendation from the PC group */ +#ifdef BASOP_NOGLOB + result = msu_r_sat( L_mult( sine, residual ), cosine, -32768 ); +#else result = msu_r( L_mult( sine, residual ), cosine, -32768 ); +#endif BASOP_SATURATE_WARNING_ON return result; diff --git a/lib_com/cnst.h b/lib_com/cnst.h index c51c73ba0..e2e19ab3d 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -2068,6 +2068,7 @@ typedef enum _DCTTYPE #define ENV_ADJ_INCL 5 /* Inclination for mapping between attenuation region width and attenuation limit */ #define ENV_SMOOTH_FAC 0.1f /* Smoothing factor for envelope stability measure */ +#define ENV_SMOOTH_FAC_FX ((Word16)0x0CCD) #define L_STAB_TBL 10 /* Number of elements in stability transition table */ #define LUMPED_ENV_SMOOTH_FAC_FX ((Word16)10089) /* Q19 (no typo error), 0.1/sqrt(27) */ #define CMPLMNT_ENV_SMOOTH_FAC_FX ((Word16)29491) /* Q15 0.9 */ @@ -2086,9 +2087,14 @@ typedef enum _DCTTYPE #define ENV_STAB_EST2_FX (-9011) /* env_stab estimation coefficient 2 *//*Q-12*/ #define ENV_STAB_EST3_FX 3035 /* env_stab estimation coefficient 3 *//*Q-12*/ #endif // IVAS_FLOAT_FIXED -#define STAB_FAC_EST1 1.093f /* stab_fac HQ estimation coefficient 1 */ -#define STAB_FAC_EST2 (-5.84e-05f) /* stab_fac HQ estimation coefficient 2, including Q12 scaling */ -#define STAB_FAC_EST3 0.125f /* stab_fac HQ estimation coefficient 3 */ +#define STAB_FAC_EST1 1.093f /* stab_fac HQ estimation coefficient 1 */ +#define STAB_FAC_EST2 (-5.84e-05f) /* stab_fac HQ estimation coefficient 2, including Q12 scaling */ +#define STAB_FAC_EST3 0.125f /* stab_fac HQ estimation coefficient 3 */ +#ifdef IVAS_FLOAT_FIXED +#define STAB_FAC_EST1_FX ((Word32)0x45F3B646) /* stab_fac HQ estimation coefficient 1 */ +#define STAB_FAC_EST2_FX ((Word32)0xFFFF0B0D) /* stab_fac HQ estimation coefficient 2, including Q12 scaling */ +#define STAB_FAC_EST3_FX ((Word32)0x10000000) /* stab_fac HQ estimation coefficient 3 */ +#endif // IVAS_FLOAT_FIXED #define ATT_LIM_HANGOVER 150 /* Number of hangover frames for disabling stability dependent attenuation */ #define DELTA_TH 5.0f /* Delta energy threshold for transient detection for envelope stability */ diff --git a/lib_com/float_to_fix_ops.c b/lib_com/float_to_fix_ops.c index 3c9ec9474..edbcce09a 100644 --- a/lib_com/float_to_fix_ops.c +++ b/lib_com/float_to_fix_ops.c @@ -1047,9 +1047,9 @@ void stereo_tcx_dec_mode_switch_reconf_To_fixed_2( FOR( i = 0; i < M; i++ ) { st->lsf_cng[i] = (Word16) floatToFixed( st->lsf_cng_float[i] * 2.56f / st->scale, 0 ); - st->lsf_adaptive_mean_fx[i] = (Word16) floatToFixed( st->lsf_adaptive_mean[i] * 2.56f / st->scale, 0 ); - st->lsfoldbfi0_fx[i] = (Word16) floatToFixed( st->lsfoldbfi0[i] * 2.56f / st->scale, 0 ); - st->lsfoldbfi1_fx[i] = (Word16) floatToFixed( st->lsfoldbfi1[i] * 2.56f / st->scale, 0 ); + st->lsf_adaptive_mean_fx[i] = (Word16) floatToFixed( st->lsf_adaptive_mean[i] * 2.56f / st->scale_lsfbfi, 0 ); + st->lsfoldbfi0_fx[i] = (Word16) floatToFixed( st->lsfoldbfi0[i] * 2.56f / st->scale_lsfbfi, 0); + st->lsfoldbfi1_fx[i] = (Word16)floatToFixed(st->lsfoldbfi1[i] * 2.56f / st->scale_lsfbfi, 0 ); } IF( st->hTcxLtpDec ) { @@ -1178,7 +1178,7 @@ void stereo_tcx_dec_mode_switch_reconf_To_fixed_2( } for ( i = 0; i < M; i++ ) { - st->lsf_adaptive_mean_fx[i] = (Word16) ( st->lsf_adaptive_mean[i] * ( 2.56f / st->scale ) ); + st->lsf_adaptive_mean_fx[i] = (Word16) ( st->lsf_adaptive_mean[i] * ( 2.56f / st->scale_lsfbfi) ); } st->stab_fac_fx = (Word16) floatToFixed( st->stab_fac, Q15 ); @@ -1660,9 +1660,9 @@ void stereo_tcx_dec_mode_switch_reconf_To_fixed_2( // st->lsf_adaptive_mean[i] = fixedToFloat( L_mult( st->lsf_adaptive_mean_fx[i], 100 ), 9 ); // st->lsfoldbfi0[i] = fixedToFloat( L_mult( st->lsfoldbfi0_fx[i], 100 ), 9 ); // st->lsfoldbfi1[i] = fixedToFloat( L_mult( st->lsfoldbfi1_fx[i], 100 ), 9 ); - st->lsf_adaptive_mean[i] = (float) st->lsf_adaptive_mean_fx[i] / ( 2.56f / st->scale ); - st->lsfoldbfi1[i] = (float) st->lsfoldbfi1_fx[i] / ( 2.56f / st->scale ); - st->lsfoldbfi0[i] = (float) st->lsfoldbfi0_fx[i] / ( 2.56f / st->scale ); + st->lsf_adaptive_mean[i] = (float) st->lsf_adaptive_mean_fx[i] / ( 2.56f / st->scale_lsfbfi); + st->lsfoldbfi1[i] = (float)st->lsfoldbfi1_fx[i] / (2.56f / st->scale_lsfbfi); + st->lsfoldbfi0[i] = (float)st->lsfoldbfi0_fx[i] / (2.56f / st->scale_lsfbfi); } st->old_enr_LP_float = fixedToFloat( st->old_enr_LP, Q_old_enr_LP ); st->enr_old = fixedToFloat( st->enr_old_fx, 0 ); @@ -1823,9 +1823,9 @@ void fixed_to_float_stereo_tcx_core_dec( { st->mem_MA[p] = (float) st->mem_MA_fx[p] / 2.56f; st->mem_AR[p] = (float) st->mem_AR_fx[p] / 2.56f; - st->lsf_adaptive_mean[p] = (float) st->lsf_adaptive_mean_fx[p] / ( 2.56f / st->scale ); - st->lsfoldbfi1[p] = (float) st->lsfoldbfi1_fx[p] / ( 2.56f / st->scale ); - st->lsfoldbfi0[p] = (float) st->lsfoldbfi0_fx[p] / ( 2.56f / st->scale ); + st->lsf_adaptive_mean[p] = (float) st->lsf_adaptive_mean_fx[p] / ( 2.56f / st->scale_lsfbfi); + st->lsfoldbfi1[p] = (float) st->lsfoldbfi1_fx[p] / ( 2.56f / st->scale_lsfbfi); + st->lsfoldbfi0[p] = (float) st->lsfoldbfi0_fx[p] / ( 2.56f / st->scale_lsfbfi); st->lsf_q_cng_float[p] = (float) st->lsf_q_cng[p] / ( 2.56f / st->scale ); st->old_lsf_q_cng_float[p] = (float) st->old_lsf_q_cng[p] / ( 2.56f / st->scale ); } diff --git a/lib_com/ivas_masa_com.c b/lib_com/ivas_masa_com.c index 650c326d9..4fa9f5701 100644 --- a/lib_com/ivas_masa_com.c +++ b/lib_com/ivas_masa_com.c @@ -777,10 +777,10 @@ void masa_sample_rate_band_correction( #ifdef IVAS_FLOAT_FIXED void masa_sample_rate_band_correction_fx( MASA_CODEC_CONFIG *config, /* i/o: MASA codec config */ - Word16 *band_mapping, /* i/o: Band mapping used and modified */ + Word16 *band_mapping, /* i/o: Band mapping used and modified */ IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: QMetadata structure for modification */ - const UWord8 maxBand, /* i : max band */ - UWord8 is_encoder, /* i : signals if called at encoder */ + const UWord8 maxBand, /* i : max band */ + UWord8 is_encoder, /* i : signals if called at encoder */ MASA_DECODER_EXT_OUT_META_HANDLE hExtOutMeta /* i/o: MASA decoder metadata ext out buffer */ ) { @@ -790,40 +790,42 @@ void masa_sample_rate_band_correction_fx( numBands48k = config->numCodingBands; - FOR ( band = 1; band < config->numCodingBands + 1; band++ ) + FOR( band = 1; band < config->numCodingBands + 1; band++ ) { highBand = band_mapping[band]; + move16(); - IF ( GE_16( highBand, (Word16)maxBand ) ) + IF( GE_16( highBand, (Word16) maxBand ) ) { config->numCodingBands = band; hQMetaData->numCodingBands = band; - IF ( is_encoder ) + IF( is_encoder ) { test(); - IF ( GT_16( hQMetaData->q_direction->cfg.nbands, (Word16)band ) ) + IF( GT_16( hQMetaData->q_direction->cfg.nbands, (Word16) band ) ) { hQMetaData->q_direction->cfg.nbands = band; } - IF ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) && GT_16( hQMetaData->q_direction[1].cfg.nbands, (Word16)band ) ) + IF( EQ_16( (Word16) hQMetaData->no_directions, 2 ) && GT_16( hQMetaData->q_direction[1].cfg.nbands, (Word16) band ) ) { hQMetaData->q_direction[1].cfg.nbands = band; } } band_mapping[band] = maxBand; + move16(); BREAK; } } /* Set rest of the bands to zero in qmetadata. */ - FOR ( ; band < numBands48k; band++ ) + FOR( ; band < numBands48k; band++ ) { - FOR ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) { -#if 1 /* TODO: remove float code */ +#if 1 /* TODO: remove float code */ hQMetaData->q_direction[0].band_data[band].azimuth[sf] = 0.0f; hQMetaData->q_direction[0].band_data[band].elevation[sf] = 0.0f; hQMetaData->q_direction[0].band_data[band].energy_ratio[sf] = 0.0f; @@ -835,14 +837,14 @@ void masa_sample_rate_band_correction_fx( hQMetaData->q_direction[0].band_data[band].energy_ratio_fx[sf] = 0; move32(); - IF ( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL ) + IF( hQMetaData->coherence_flag && hQMetaData->q_direction[0].coherence_band_data != NULL ) { hQMetaData->q_direction[0].coherence_band_data[band].spread_coherence[sf] = 0u; } - IF ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) ) + IF( EQ_16( (Word16) hQMetaData->no_directions, 2 ) ) { -#if 1 /* TODO: remove float code */ +#if 1 /* TODO: remove float code */ hQMetaData->q_direction[1].band_data[band].azimuth[sf] = 0.0f; hQMetaData->q_direction[1].band_data[band].elevation[sf] = 0.0f; hQMetaData->q_direction[1].band_data[band].energy_ratio[sf] = 0.0f; @@ -854,32 +856,33 @@ void masa_sample_rate_band_correction_fx( hQMetaData->q_direction[1].band_data[band].energy_ratio_fx[sf] = 0; move32(); - IF ( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL ) + IF( hQMetaData->coherence_flag && hQMetaData->q_direction[1].coherence_band_data != NULL ) { hQMetaData->q_direction[1].coherence_band_data[band].spread_coherence[sf] = 0u; } } - IF ( hQMetaData->coherence_flag && hQMetaData->surcoh_band_data != NULL ) + IF( hQMetaData->coherence_flag && hQMetaData->surcoh_band_data != NULL ) { hQMetaData->surcoh_band_data[band].surround_coherence[sf] = 0u; } } - IF ( EQ_16( (Word16) hQMetaData->no_directions, 2 ) ) + IF( EQ_16( (Word16) hQMetaData->no_directions, 2 ) ) { hQMetaData->twoDirBands[band] = 0; } } - IF ( hExtOutMeta != NULL ) + IF( hExtOutMeta != NULL ) { /* in decoder, zero the EXT out MASA meta buffer */ - FOR ( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) + FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ ) { - FOR ( band = hQMetaData->numCodingBands; band < MASA_FREQUENCY_BANDS; band++ ) + FOR( band = hQMetaData->numCodingBands; band < MASA_FREQUENCY_BANDS; band++ ) { hExtOutMeta->directionIndex[0][sf][band] = SPH_IDX_FRONT; + move16(); hExtOutMeta->directToTotalRatio[0][sf][band] = 0u; hExtOutMeta->spreadCoherence[0][sf][band] = 0u; diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index ac997fe6d..88bcea929 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -3702,6 +3702,7 @@ void ivas_qmetadata_to_dirac( int16_t *dirac_to_spar_md_bands /* o : DirAC->SPAR MD bands */ ); #endif +#ifndef IVAS_FLOAT_FIXED ivas_error ivas_qmetadata_open( IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ ); @@ -3716,6 +3717,8 @@ ivas_error ivas_qmetadata_allocate_memory( void ivas_qmetadata_close( IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ ); +#endif + void restore_metadata_buffer( BSTR_ENC_HANDLE hMetaData, @@ -3735,11 +3738,6 @@ void ivas_qmetadata_azimuth_elevation_to_direction_vector( const float el, /* i : elevation */ float *dv /* o : direction vector */ ); -void ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( - const Word32 az, /* i : azimuth */ - const Word32 el, /* i : elevation */ - Word32 *dv /* o : direction vector */ -); void ivas_qmetadata_direction_vector_to_azimuth_elevation( const float *dv, /* i : direction vector */ @@ -3747,12 +3745,6 @@ void ivas_qmetadata_direction_vector_to_azimuth_elevation( float *el /* o : elevation */ ); -void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( - const Word32 *dv, /* i : direction vector */ - const Word32 div_q, - Word32 *az, /* o : azimuth */ - Word32 *el /* o : elevation */ -); ivas_error only_reduce_bits_direction( int16_t *reduce_bits_out, IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ @@ -3904,12 +3896,14 @@ void deindex_spherical_component( const MC_LS_SETUP mc_format /* i : channel format if in MC-mode */ ); +#ifndef IVAS_FLOAT_FIXED void small_reduction_direction( IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ uint16_t bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], /* i : bit allocation in tF tiles */ const int16_t raw_flag[MASA_MAXIMUM_CODING_SUBBANDS], /* i : raw/EC coding indicator for each subband*/ int16_t *diff /* i/o: number of bits that need to be reduced */ ); +#endif uint16_t ivas_qmetadata_reorder_generic( const int16_t signed_value @@ -3921,6 +3915,8 @@ int16_t ivas_qmetadata_dereorder_generic( ); #endif + +#ifndef IVAS_FLOAT_FIXED /*! r: projected azimuth index */ int16_t ivas_dirac_project_azimuth_index( const int16_t az_idx, /* i : azimuth index */ @@ -3941,6 +3937,7 @@ int16_t ivas_chan_project_elevation_index( const int16_t el_alph, /* i : number of elevation symbols */ const int16_t el_alph_proj /* i : size of projected alphabet */ ); +#endif void ivas_dirac_param_est_enc( DIRAC_ENC_HANDLE hDirAC, diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 28ad8b9f0..a5482a57e 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -132,6 +132,23 @@ ivas_error ivas_masa_decode_fx( Word16 *nb_bits_read /* o : number of bits read */ ); +void ivas_omasa_rearrange_channels_fx( + Word32 *output[], /* o : output synthesis signal */ + const Word16 nchan_transport_ism, /* o : number of ISM TCs */ + const Word16 output_frame /* i : output frame length per channel */ +); + +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_omasa_ism_metadata_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word32 ism_total_brate, /* i : ISM total bitrate */ + Word16 *nchan_ism, /* o : number of ISM separated channels */ + Word16 *nchan_transport_ism, /* o : number of ISM TCs */ + const Word16 dirac_bs_md_write_idx, /* i : DirAC bitstream write index */ + Word16 nb_bits_metadata[] /* o : number of ISM metadata bits */ +); +#endif + void ivas_omasa_modify_masa_energy_ratios_fx( IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ const Word32 masa_to_total_energy_ratio_fx[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_MAXIMUM_CODING_SUBBANDS] // Q30 @@ -994,6 +1011,14 @@ void stereo_dft_dec_synthesize_fx( const Word16 output_frame /* i : output frame length */ ); +void stereo_dft_dec_res_fx( + CPE_DEC_HANDLE hCPE, /* i/o: decoder CPE handle */ + Word32 res_buf[STEREO_DFT_N_8k], /* i : residual buffer */ + Word16 q_res, /* i : q fact of residural buffer */ + Word16 q_output, /* i : q factor of output buffer */ + Word32 *output /* o : output */ +); + void stereo_dft_dec_fx( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder DFT stereo handle */ Decoder_State *st0, /* i/o: decoder state structure */ @@ -1751,4 +1776,90 @@ void stereo_tcx_core_dec_fx( ); #endif // IVAS_FLOAT_FIXED +void masa_compensate_two_dir_energy_ratio_index_fx( + const Word16 ratio_index_1, /* i : Input ratio for direction 1 */ + const Word16 ratio_index_2, /* i : Input ratio for direction 2 */ + Word16 *ratio_index_mod1, /* o : Output modified ratio for direction 1 */ + Word16 *ratio_index_mod2, /* o : Output modified ratio for direction 2 */ + const Word16 hodirac_flag /* i : flag to indicate HO-DirAC mode */ +); + +#ifdef IVAS_FLOAT_FIXED +/*! r: projected azimuth index */ +Word16 ivas_dirac_project_azimuth_index( + const Word16 az_idx, /* i : azimuth index */ + const Word16 az_alph, /* i : number of azimuth symbols */ + const Word16 az_alph_proj /* i : size of projected alphabet */ +); + +/*! r: projected elevation index */ +Word16 ivas_dirac_project_elevation_index( + const Word16 el_idx, /* i : elevation index */ + const Word16 el_alph, /* i : number of elevation symbols */ + const Word16 el_alph_proj /* i : size of projected alphabet */ +); + +/*! r: projected index in channel mode */ +Word16 ivas_chan_project_elevation_index( + const Word16 el_idx, /* i : elevation index */ + const Word16 el_alph, /* i : number of elevation symbols */ + const Word16 el_alph_proj /* i : size of projected alphabet */ +); + +void small_reduction_direction( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + UWord16 bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], + const Word16 raw_flag[MASA_MAXIMUM_CODING_SUBBANDS], + Word16 *diff ); +#endif + +void sort_desc_ind_16_fx( + Word16 *s, /* i/o: vector to be sorted Qx*/ + const Word16 len, /* i : vector length */ + Word16 *ind /* o : array of indices */ +); + +void sort_desc_ind_32_fx( + Word32 *s, /* i/o: vector to be sorted Qx*/ + const Word16 len, /* i : vector length */ + Word16 *ind /* o : array of indices */ +); + +ivas_error only_reduce_bits_direction_fx( + Word16 *reduce_bits_out, + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + Word16 reduce_bits, + const Word16 coding_subbands, + const Word16 no_subframes, + Word16 *ind_order ); + +void ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( + const Word32 az, /* i : azimuth */ + const Word32 el, /* i : elevation */ + Word32 *dv /* o : direction vector */ +); + +void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( + const Word32 *dv, /* i : direction vector */ + const Word16 div_q, + Word32 *az, /* o : azimuth */ + Word32 *el /* o : elevation */ +); + +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_qmetadata_open( + IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ +); + +ivas_error ivas_qmetadata_allocate_memory( + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ + const Word16 nbands, /* i : new number of frequency bands */ + const Word16 ndirs, /* i : new number of directions */ + const Word16 coherence_flag /* i : new coherence coding status */ +); + +void ivas_qmetadata_close( + IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ +); +#endif #endif diff --git a/lib_com/ivas_qmetadata_com.c b/lib_com/ivas_qmetadata_com.c index ad2bf714f..b7fcd9f66 100644 --- a/lib_com/ivas_qmetadata_com.c +++ b/lib_com/ivas_qmetadata_com.c @@ -41,6 +41,12 @@ #include "prot_fx1.h" #include "cnst.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx2.h" +#include "ivas_prot_fx.h" +#endif + +//#include "debug.h" /*-----------------------------------------------------------------------* * Local constants @@ -61,6 +67,24 @@ static void ivas_qmetadata_free_memory( IVAS_QMETADATA_HANDLE hQMetaData ); * Allocate Q Metadata handle *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_qmetadata_open( + IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ +) +{ + /* allocate MetaData handle */ + IF( ( *hQMetaData = (IVAS_QMETADATA_HANDLE) malloc( sizeof( IVAS_QMETADATA ) ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); + } + + ( *hQMetaData )->q_direction = NULL; + ( *hQMetaData )->surcoh_band_data = NULL; + ( *hQMetaData )->bandMap = NULL; + + return IVAS_ERR_OK; +} +#else ivas_error ivas_qmetadata_open( IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ ) @@ -77,6 +101,7 @@ ivas_error ivas_qmetadata_open( return IVAS_ERR_OK; } +#endif /*-----------------------------------------------------------------------* @@ -92,6 +117,114 @@ ivas_error ivas_qmetadata_open( * set here to their default values out of practicality. *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_qmetadata_allocate_memory( + IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ + const Word16 nbands, /* i : new number of frequency bands */ + const Word16 ndirs, /* i : new number of directions */ + const Word16 coherence_flag /* i : new coherence coding status */ +) +{ + Word16 j, dir; + UWord8 do_realloc; + + + /* Check if we need to reallocate memory or do we need to do the first time allocation. */ + IF( hQMetaData->q_direction != NULL ) + { + do_realloc = (UWord8) NE_16( nbands, hQMetaData->q_direction->cfg.nbands ); + do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( ndirs, hQMetaData->no_directions ) ); + do_realloc = (UWord8) s_or( do_realloc, (Word16) NE_32( coherence_flag, hQMetaData->coherence_flag ) ); + } + ELSE + { + do_realloc = TRUE; + } + + IF( do_realloc ) + { + ivas_qmetadata_free_memory( hQMetaData ); + + hQMetaData->numCodingBands = (UWord8) nbands; + hQMetaData->no_directions = ndirs; + move16(); + hQMetaData->coherence_flag = coherence_flag; + move16(); + + IF( ( hQMetaData->q_direction = (IVAS_QDIRECTION *) malloc( sizeof( IVAS_QDIRECTION ) * ndirs ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); + } + + FOR( dir = 0; dir < hQMetaData->no_directions; dir++ ) + { + hQMetaData->q_direction[dir].cfg.nbands = nbands; + move16(); + IF( EQ_16( nbands, 0 ) ) + { + hQMetaData->q_direction[dir].band_data = NULL; + } + ELSE + { + IF( ( hQMetaData->q_direction[dir].band_data = (IVAS_QDIRECTION_BAND_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); + } + + FOR( j = 0; j < nbands; j++ ) + { + set_zero( hQMetaData->q_direction[dir].band_data[j].elevation, MAX_PARAM_SPATIAL_SUBFRAMES ); +#ifdef IVAS_FLOAT_FIXED + set32_fx( hQMetaData->q_direction[dir].band_data[j].elevation_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif + set_zero( hQMetaData->q_direction[dir].band_data[j].azimuth, MAX_PARAM_SPATIAL_SUBFRAMES ); +#ifdef IVAS_FLOAT_FIXED + set32_fx( hQMetaData->q_direction[dir].band_data[j].azimuth_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif + set_zero( hQMetaData->q_direction[dir].band_data[j].energy_ratio, MAX_PARAM_SPATIAL_SUBFRAMES ); +#ifdef IVAS_FLOAT_FIXED + set32_fx( hQMetaData->q_direction[dir].band_data[j].energy_ratio_fx, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); +#endif + } + } + + IF( coherence_flag ) + { + hQMetaData->q_direction[dir].coherence_band_data = (IVAS_QDIRECTION_BAND_COHERENCE_DATA *) malloc( sizeof( IVAS_QDIRECTION_BAND_COHERENCE_DATA ) * hQMetaData->q_direction[dir].cfg.nbands ); + } + ELSE + { + hQMetaData->q_direction[dir].coherence_band_data = NULL; + } + + /* These default values are set here to get them conveniently in one place */ + hQMetaData->q_direction[dir].cfg.nblocks = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + hQMetaData->q_direction[dir].cfg.search_effort = 3; + move16(); + hQMetaData->q_direction[dir].cfg.start_band = 0; + move16(); + hQMetaData->q_direction[dir].cfg.mc_ls_setup = MC_LS_SETUP_INVALID; + move32(); + } + + IF( coherence_flag ) + { + IF( ( hQMetaData->surcoh_band_data = (IVAS_SURROUND_COHERENCE_BAND_DATA *) malloc( sizeof( IVAS_SURROUND_COHERENCE_BAND_DATA ) * hQMetaData->q_direction[0].cfg.nbands ) ) == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for Q MetaData" ); + } + } + ELSE + { + hQMetaData->surcoh_band_data = NULL; + } + } + + + return IVAS_ERR_OK; +} +#else ivas_error ivas_qmetadata_allocate_memory( IVAS_QMETADATA_HANDLE hQMetaData, /* i/o: q_metadata handle */ const int16_t nbands, /* i : new number of frequency bands */ @@ -191,6 +324,7 @@ ivas_error ivas_qmetadata_allocate_memory( return IVAS_ERR_OK; } +#endif /*-----------------------------------------------------------------------* @@ -199,6 +333,47 @@ ivas_error ivas_qmetadata_allocate_memory( * free dynamic part of Q Metadata memory *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void ivas_qmetadata_free_memory( + IVAS_QMETADATA_HANDLE hQMetaData /* i/o: q_metadata handle */ +) +{ + Word16 dir; + + IF( hQMetaData == NULL ) + { + return; + } + + IF( hQMetaData->q_direction != NULL ) + { + FOR( dir = 0; dir < hQMetaData->no_directions; dir++ ) + { + IF( hQMetaData->q_direction[dir].band_data != NULL ) + { + free( hQMetaData->q_direction[dir].band_data ); + hQMetaData->q_direction[dir].band_data = NULL; + } + IF( hQMetaData->q_direction[dir].coherence_band_data != NULL ) + { + free( hQMetaData->q_direction[dir].coherence_band_data ); + hQMetaData->q_direction[dir].coherence_band_data = NULL; + } + } + + free( hQMetaData->q_direction ); + hQMetaData->q_direction = NULL; + } + + IF( hQMetaData->surcoh_band_data != NULL ) + { + free( hQMetaData->surcoh_band_data ); + hQMetaData->surcoh_band_data = NULL; + } + + return; +} +#else static void ivas_qmetadata_free_memory( IVAS_QMETADATA_HANDLE hQMetaData /* i/o: q_metadata handle */ ) @@ -238,6 +413,7 @@ static void ivas_qmetadata_free_memory( return; } +#endif /*-----------------------------------------------------------------------* @@ -246,6 +422,24 @@ static void ivas_qmetadata_free_memory( * close Q Metadata *-----------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ivas_qmetadata_close( + IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ +) +{ + IF( hQMetaData == NULL || *hQMetaData == NULL ) + { + return; + } + + ivas_qmetadata_free_memory( *hQMetaData ); + + free( *hQMetaData ); + *hQMetaData = NULL; + + return; +} +#else void ivas_qmetadata_close( IVAS_QMETADATA_HANDLE *hQMetaData /* i/o: q_metadata handle */ ) @@ -262,6 +456,7 @@ void ivas_qmetadata_close( return; } +#endif /*------------------------------------------------------------------------- @@ -317,6 +512,170 @@ Word16 masa_sq_fx( * *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error only_reduce_bits_direction_fx( + Word16 *reduce_bits_out, + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + Word16 reduce_bits, + const Word16 coding_subbands, + const Word16 no_subframes, + Word16 *ind_order ) +{ + Word16 j, k, red_times, rem, n; + Word16 max_nb, delta; + Word16 *bits_dir0; + + Word16 bits_sph_idx_orig[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES]; + Word16 penalty[MASA_MAXIMUM_CODING_SUBBANDS]; + Word16 shift, tmp, tmp_e, flag; + Word32 tmp_32; + FOR( j = 0; j < coding_subbands; j++ ) + { + FOR( k = 0; k < no_subframes; k++ ) + { + bits_sph_idx_orig[j][k] = q_direction->band_data[j].bits_sph_idx[k]; + move16(); + } + } + n = 0; + move16(); + delta = 1; + move16(); + + IF( GT_16( reduce_bits, 0 ) ) + { + red_times = reduce_bits / ( coding_subbands * no_subframes ); /* number of complete reductions by 1 bit */ + IF( GT_16( red_times, 0 ) ) + { + FOR( j = 0; j < coding_subbands; j++ ) + { + bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx; + FOR( k = 0; k < no_subframes; k++ ) + { + bits_dir0[k] = sub( bits_dir0[k], red_times ); + move16(); + reduce_bits = sub( reduce_bits, red_times ); + + IF( LT_16( bits_dir0[k], MASA_MIN_BITS_TF ) ) + { + reduce_bits = add( reduce_bits, sub( MASA_MIN_BITS_TF, bits_dir0[k] ) ); + bits_dir0[k] = MASA_MIN_BITS_TF; + move16(); + } + } + } + } + + rem = reduce_bits; /* -coding_subbands*no_subframes*red_times; */ + move16(); + WHILE( LT_16( n, rem ) ) + { + max_nb = 0; + move16(); + FOR( j = 0; j < coding_subbands; j++ ) + { + bits_dir0 = (Word16 *) q_direction->band_data[j].bits_sph_idx; + FOR( k = 0; k < no_subframes; k++ ) + { + IF( LT_16( n, rem ) && GT_16( bits_dir0[k], sub( MASA_MIN_BITS_TF, delta ) ) ) + { + bits_dir0[k] = sub( bits_dir0[k], 1 ); + move16(); + n++; + } + + IF( LT_16( max_nb, bits_dir0[k] ) ) + { + max_nb = bits_dir0[k]; + move16(); + } + } + } + + IF( LE_16( max_nb, MASA_MIN_BITS_TF ) ) + { + delta = add( delta, 1 ); + } + } + + reduce_bits = 0; + move16(); + } + + IF( EQ_16( ind_order[0], -1 ) ) + { + FOR( j = 0; j < coding_subbands; j++ ) + { + ind_order[j] = j; + move16(); + } + } + ELSE + { + FOR( j = 0; j < coding_subbands; j++ ) + { + penalty[j] = 0; + move16(); + tmp_32 = 0; + move32(); + shift = find_guarded_bits_fx( no_subframes ); + + flag = 1; + move16(); + // This change was done due to loss of precision from BASOP_Util_Divide3232_Scale which was leading to penalty getting calculated wrongly + // and hence ind_order being sorted incorrectly which might cause infinite loop. + FOR( k = 0; k < no_subframes - 1; k++ ) + { + IF( NE_16( bits_sph_idx_orig[j][k], bits_sph_idx_orig[j][k + 1] ) ) + { + flag = 0; + move16(); + } + } + + IF( flag ) + { + tmp = 0; + move16(); + FOR( k = 0; k < no_subframes; k++ ) + { + IF( GT_16( bits_sph_idx_orig[j][k], 0 ) ) + { + tmp = add( tmp, sub( bits_sph_idx_orig[j][k], q_direction->band_data[j].bits_sph_idx[k] ) ); + } + } + + tmp = BASOP_Util_Divide1616_Scale( tmp, bits_sph_idx_orig[j][0], &tmp_e ); + + tmp_32 = L_shl( tmp, tmp_e ); /* Q15 */ + + penalty[j] = extract_l( L_shr( tmp_32, shift ) ); /* Q15 - shift */ + move16(); + // Division by no_subframes for penalty[j] not required + } + ELSE + { + FOR( k = 0; k < no_subframes; k++ ) + { + IF( GT_16( bits_sph_idx_orig[j][k], 0 ) ) + { + tmp = BASOP_Util_Divide3232_Scale( extract_l( L_sub( bits_sph_idx_orig[j][k], q_direction->band_data[j].bits_sph_idx[k] ) ), bits_sph_idx_orig[j][k], &tmp_e ); + tmp_32 = L_add( tmp_32, L_shl( tmp, tmp_e ) ); + } + } + penalty[j] = extract_l( L_shr( tmp_32, shift ) ); /* Q15 - shift */ + move16(); + // Division by no_subframes for penalty[j] not required + } + } + sort_desc_ind_16_fx( penalty, coding_subbands, ind_order ); + } + + *reduce_bits_out = negate( reduce_bits ); + + return IVAS_ERR_OK; +} +#endif ivas_error only_reduce_bits_direction( int16_t *reduce_bits_out, IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ @@ -618,6 +977,29 @@ void invdct4_transform_fx( * separately for both directions. *--------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void masa_compensate_two_dir_energy_ratio_index_fx( + const Word16 ratio_index_1, /* i : Input ratio for direction 1 */ + const Word16 ratio_index_2, /* i : Input ratio for direction 2 */ + Word16 *ratio_index_mod1, /* o : Output modified ratio for direction 1 */ + Word16 *ratio_index_mod2, /* o : Output modified ratio for direction 2 */ + const Word16 hodirac_flag /* i : flag to indicate HO-DirAC mode */ +) +{ + IF( hodirac_flag ) + { + *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hordiac_ratio1; + *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].hoardia_ratio2; + } + ELSE + { + *ratio_index_mod1 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio1; + *ratio_index_mod2 = masa_diffuse_ratios[ratio_index_1][ratio_index_2].ratio2; + } + + return; +} +#endif void masa_compensate_two_dir_energy_ratio_index( const int16_t ratio_index_1, /* i : Input ratio for direction 1 */ const int16_t ratio_index_2, /* i : Input ratio for direction 2 */ @@ -726,29 +1108,30 @@ void ivas_qmetadata_azimuth_elevation_to_direction_vector( return; } +#ifdef IVAS_FLOAT_FIXED void ivas_qmetadata_azimuth_elevation_to_direction_vector_fx( - const Word32 az, /* i : azimuth */ - const Word32 el, /* i : elevation */ - Word32 *dv /* o : direction vector */ + const Word32 az, /* i : azimuth */ + const Word32 el, /* i : elevation */ + Word32 *dv /* o : direction vector */ ) { - float radius_length; + Word16 radius_length; + Word16 elevation_fx, azimuth_fx; - float temp_az, temp_el; - float temp_dv[3]; - temp_az = (float)az / (1 << 22); - temp_el = (float)el / (1 << 22); - temp_dv[2] = sinf(temp_el * PI_OVER_180); - radius_length = cosf(temp_el * PI_OVER_180); - temp_dv[0] = radius_length * cosf(temp_az * PI_OVER_180); - temp_dv[1] = radius_length * sinf(temp_az * PI_OVER_180); + elevation_fx = extract_l( L_shr( Mpy_32_16_1( el, 91 ), 7 ) ); + azimuth_fx = extract_l( L_shr( Mpy_32_16_1( az, 91 ), 7 ) ); - dv[0] = (Word32)(temp_dv[0] * (1 << 30)); - dv[1] = (Word32)(temp_dv[1] * (1 << 30)); - dv[2] = (Word32)(temp_dv[2] * (1 << 30)); + dv[2] = L_shl( getSineWord16R2( elevation_fx ), Q15 ); /* Q30 */ + move32(); + radius_length = getCosWord16R2( elevation_fx ); + dv[0] = L_mult0( radius_length, getCosWord16R2( azimuth_fx ) ); /* Q30 */ + move32(); + dv[1] = L_mult0( radius_length, getSineWord16R2( azimuth_fx ) ); /* Q30 */ + move32(); - return; + return; } +#endif /*------------------------------------------------------------------------- * ivas_qmetadata_direction_vector_to_azimuth_elevation() @@ -771,28 +1154,25 @@ void ivas_qmetadata_direction_vector_to_azimuth_elevation( return; } +#ifdef IVAS_FLOAT_FIXED void ivas_qmetadata_direction_vector_to_azimuth_elevation_fx( - const Word32 *dv, /* i : direction vector */ - const Word32 dv_q, - Word32 *az, /* o : azimuth */ - Word32 *el /* o : elevation */ + const Word32 *dv, /* i : direction vector */ + const Word16 dv_q, + Word32 *az, /* o : azimuth */ + Word32 *el /* o : elevation */ ) { - /* note: dv does not need to have unit L_2 norm, because the conversion is scale invariant */ - - - float temp_dv[3]; - temp_dv[0] = (float)dv[0] / (1 << dv_q); - temp_dv[1] = (float)dv[1] / (1 << dv_q); - temp_dv[2] = (float)dv[2] / (1 << dv_q); - float temp_az, temp_el; - temp_el = atan2f(temp_dv[2], sqrtf(temp_dv[0] * temp_dv[0] + temp_dv[1] * temp_dv[1])) * _180_OVER_PI; - temp_az = atan2f(temp_dv[1], temp_dv[0]) * _180_OVER_PI; - - *az = (Word32)(temp_az * (1 << 22)); - *el = (Word32)(temp_el * (1 << 22)); + /* note: dv does not need to have unit L_2 norm, because the conversion is scale invariant */ + Word32 L_tmp; + Word16 e_tmp; + L_tmp = L_add( Mpy_32_32( dv[0], dv[0] ), Mpy_32_32( dv[1], dv[1] ) ); /* 2 * dv_q - 31 */ + e_tmp = shl( sub( 31, dv_q ), 2 ); + L_tmp = Sqrt32( L_tmp, &e_tmp ); + *el = L_mult0( BASOP_util_atan2( dv[2], L_tmp, 31 - dv_q - e_tmp ), 29335 ); /* Q22 */ + *az = L_mult0( BASOP_util_atan2( dv[1], dv[0], 0 ), 29335 ); /* Q22 */ return; } +#endif /*------------------------------------------------------------------------- diff --git a/lib_com/ivas_qspherical_com.c b/lib_com/ivas_qspherical_com.c index 17ad66752..3d6ad98b1 100644 --- a/lib_com/ivas_qspherical_com.c +++ b/lib_com/ivas_qspherical_com.c @@ -110,6 +110,21 @@ int16_t ivas_qmetadata_dereorder_generic( *------------------------------------------------------------------------*/ /*! r: projected elevation index */ +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_dirac_project_elevation_index( + const Word16 el_idx, /* i : elevation index */ + const Word16 el_alph, /* i : number of elevation symbols */ + const Word16 el_alph_proj /* i : size of projected alphabet */ +) +{ + Word16 el_idx_proj; + + /* evaluate floor((el_idx / (el_alph - 1)) * (el_alph_proj - 1) + 0.5) using only integer */ + el_idx_proj = ( 2 * el_idx * ( el_alph_proj - 1 ) + ( el_alph - 1 ) ) / ( 2 * ( el_alph - 1 ) ); + + return el_idx_proj; +} +#else int16_t ivas_dirac_project_elevation_index( const int16_t el_idx, /* i : elevation index */ const int16_t el_alph, /* i : number of elevation symbols */ @@ -123,6 +138,7 @@ int16_t ivas_dirac_project_elevation_index( return el_idx_proj; } +#endif /*------------------------------------------------------------------------- @@ -132,6 +148,28 @@ int16_t ivas_dirac_project_elevation_index( *------------------------------------------------------------------------*/ /*! r: projected index in channel mode */ +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_chan_project_elevation_index( + const Word16 el_idx, /* i : elevation index */ + const Word16 el_alph, /* i : number of elevation symbols */ + const Word16 el_alph_proj /* i : size of projected alphabet */ +) +{ + Word16 el_idx_proj; + + /* evaluate floor((el_idx / (el_alph - 1)) * (el_alph_proj - 1) + 0.5) using only integer */ + IF( EQ_16( el_idx, sub( el_alph, 1 ) ) ) + { + el_idx_proj = el_alph_proj - 1; + } + ELSE + { + el_idx_proj = ( 2 * el_idx * el_alph_proj + el_alph ) / ( 2 * el_alph ); + } + + return el_idx_proj; +} +#else int16_t ivas_chan_project_elevation_index( const int16_t el_idx, /* i : elevation index */ const int16_t el_alph, /* i : number of elevation symbols */ @@ -152,6 +190,7 @@ int16_t ivas_chan_project_elevation_index( return el_idx_proj; } +#endif /*------------------------------------------------------------------------- @@ -161,6 +200,32 @@ int16_t ivas_chan_project_elevation_index( *------------------------------------------------------------------------*/ /*! r: projected azimuth index */ +#ifdef IVAS_FLOAT_FIXED +Word16 ivas_dirac_project_azimuth_index( + const Word16 az_idx, /* i : azimuth index */ + const Word16 az_alph, /* i : number of azimuth symbols */ + const Word16 az_alph_proj /* i : size of projected alphabet */ +) +{ + Word16 az_idx_proj; + + IF ( EQ_16(az_alph_proj, 1) ) + { + return 0; + } + + /* evaluate floor((az_idx / az_alph) * az_alph_proj + 0.5) using only integer */ + az_idx_proj = ( 2 * az_idx * az_alph_proj + az_alph ) / ( 2 * az_alph ); + + IF(EQ_16(az_idx_proj, az_alph_proj) ) + { + az_idx_proj = 0; + move16(); + } + + return az_idx_proj; +} +#else int16_t ivas_dirac_project_azimuth_index( const int16_t az_idx, /* i : azimuth index */ const int16_t az_alph, /* i : number of azimuth symbols */ @@ -184,6 +249,7 @@ int16_t ivas_dirac_project_azimuth_index( return az_idx_proj; } +#endif /*------------------------------------------------------------------------- @@ -193,6 +259,36 @@ int16_t ivas_dirac_project_azimuth_index( * is exceeded by diff. bits *------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void small_reduction_direction( + IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ + UWord16 bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], + const Word16 raw_flag[MASA_MAXIMUM_CODING_SUBBANDS], + Word16 *diff ) +{ + Word16 i, j, k; + + FOR( k = 0; ( k < 2 ) && ( *diff > 0 ); k++ ) + { + FOR( i = q_direction->cfg.start_band; ( i < q_direction->cfg.nbands ) && ( *diff > 0 ); i++ ) + { + IF( EQ_16( raw_flag[i], 1 ) ) + { + FOR( j = 0; ( j < q_direction->cfg.nblocks ) && ( *diff > 0 ); j++ ) + { + IF( GT_32( bits_dir[i][j], MASA_MIN_BITS_TF ) ) + { + bits_dir[i][j] = (UWord16) L_sub( bits_dir[i][j], 1 ); + ( *diff )--; + } + } + } + } + } + + return; +} +#else void small_reduction_direction( IVAS_QDIRECTION *q_direction, /* i/o: quantized direction structure */ uint16_t bits_dir[MASA_MAXIMUM_CODING_SUBBANDS][MAX_PARAM_SPATIAL_SUBFRAMES], @@ -221,6 +317,7 @@ void small_reduction_direction( return; } +#endif /*-----------------------------------------------------------------------* diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 01cebf304..48073c7d8 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -179,6 +179,7 @@ extern const int16_t dft_cng_coh_alpha_start[STEREO_DFT_N_COH_ALPHA_STEPS - 1]; #ifdef IVAS_FLOAT_FIXED extern const Word32 diffuseness_reconstructions_fx[DIRAC_DIFFUSE_LEVELS]; extern const Word32 diffuseness_thresholds_fx[DIRAC_DIFFUSE_LEVELS + 1]; +extern const Masa_Diffuseness_Ratios masa_diffuse_ratios[DIRAC_DIFFUSE_LEVELS][DIRAC_DIFFUSE_LEVELS]; #endif extern const float diffuseness_reconstructions[DIRAC_DIFFUSE_LEVELS]; diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index ec6735a07..605dd3a75 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -634,4 +634,90 @@ const Word16 ivas_tan_panning_gain_dirac_tbl_fx[601] = { SHC( 0x7fff ), }; +#ifdef IVAS_FLOAT_FIXED +const Masa_Diffuseness_Ratios masa_diffuse_ratios[DIRAC_DIFFUSE_LEVELS][DIRAC_DIFFUSE_LEVELS] = +{ +{ + { 0, 0, 0, 0 }, + { 0, 0, 0, 1 }, + { 0, 0, 0, 2 }, + { 0, 1, 0, 3 }, + { 0, 2, 0, 4 }, + { 0, 3, 0, 5 }, + { 0, 5, 0, 6 }, + { 0, 7, 0, 7 }, +}, +{ + { 0, 0, 1, 0 }, + { 0, 0, 1, 1 }, + { 0, 0, 1, 2 }, + { 0, 1, 1, 3 }, + { 0, 2, 1, 4 }, + { 0, 3, 1, 5 }, + { 0, 5, 1, 6 }, + { 0, 7, 1, 7 }, +}, +{ + { 0, 0, 2, 0 }, + { 0, 0, 2, 1 }, + { 0, 0, 2, 2 }, + { 0, 1, 2, 3 }, + { 0, 2, 2, 4 }, + { 0, 3, 2, 5 }, + { 0, 5, 2, 6 }, + { 0, 7, 2, 7 }, +}, +{ + { 1, 0, 3, 0 }, + { 1, 0, 3, 1 }, + { 1, 0, 3, 2 }, + { 1, 1, 3, 3 }, + { 1, 2, 3, 4 }, + { 1, 3, 3, 5 }, + { 1, 5, 3, 6 }, + { 1, 7, 3, 7 }, +}, +{ + { 2, 0, 4, 0 }, + { 2, 0, 4, 1 }, + { 2, 0, 4, 2 }, + { 2, 1, 4, 3 }, + { 2, 2, 4, 4 }, + { 2, 3, 4, 5 }, + { 2, 5, 4, 6 }, + { 3, 7, 4, 7 }, +}, +{ + { 3, 0, 5, 0 }, + { 3, 0, 5, 1 }, + { 3, 0, 5, 2 }, + { 3, 1, 5, 3 }, + { 3, 2, 5, 4 }, + { 3, 3, 5, 5 }, + { 3, 4, 5, 6 }, + { 4, 7, 5, 7 }, +}, +{ + { 5, 0, 6, 0 }, + { 5, 0, 6, 1 }, + { 5, 0, 6, 2 }, + { 5, 1, 6, 3 }, + { 5, 2, 6, 4 }, + { 4, 3, 6, 5 }, + { 4, 4, 6, 6 }, + { 5, 7, 6, 7 }, +}, +{ + { 7, 0, 7, 0 }, + { 7, 0, 7, 1 }, + { 7, 0, 7, 2 }, + { 7, 1, 7, 3 }, + { 7, 3, 7, 4 }, + { 7, 4, 7, 5 }, + { 7, 5, 7, 6 }, + { 6, 6, 7, 7 }, +} +}; +#endif + /* clang-format on */ diff --git a/lib_com/ivas_stat_com.h b/lib_com/ivas_stat_com.h index 6dfb0b6ed..e6dcccddb 100644 --- a/lib_com/ivas_stat_com.h +++ b/lib_com/ivas_stat_com.h @@ -854,5 +854,13 @@ typedef struct ivas_param_ism_data_structure Word16 last_cardioid_left_fx[MAX_NUM_OBJECTS]; } PARAM_ISM_CONFIG_DATA, *PARAM_ISM_CONFIG_HANDLE; +#ifdef IVAS_FLOAT_FIXED +typedef struct { + Word16 ratio1; /* Modified ratio index1 (hordiac_flag is 0) */ + Word16 ratio2; /* Modified ratio index2 (hordiac_flag is 0) */ + Word16 hordiac_ratio1; /* Modified ratio index1 (hordiac_flag is 1) */ + Word16 hoardia_ratio2; /* Modified ratio index2 (hordiac_flag is 1) */ +} Masa_Diffuseness_Ratios; +#endif #endif /* IVAS_STAT_COM */ diff --git a/lib_com/mslvq_com.c b/lib_com/mslvq_com.c index 0916c901a..39a1c4c69 100644 --- a/lib_com/mslvq_com.c +++ b/lib_com/mslvq_com.c @@ -738,6 +738,97 @@ void create_offset( * * sorts in descending order and computes indices in the sorted vector *-----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void sort_desc_ind_16_fx( + Word16 *s, /* i/o: vector to be sorted Qx*/ + const Word16 len, /* i : vector length */ + Word16 *ind /* o : array of indices */ +) +{ + Word16 i, k, sorted, a; + Word16 t; + + FOR( i = 0; i < len; i++ ) + { + ind[i] = i; + move16(); + } + sorted = 0; + move16(); + FOR( k = len - 1; k && !sorted; k-- ) + { + 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; +} + +void sort_desc_ind_32_fx( + Word32 *s, /* i/o: vector to be sorted Qx*/ + const Word16 len, /* i : vector length */ + Word16 *ind /* o : array of indices */ +) +{ + Word16 i, k, sorted, a; + Word32 t; + + FOR(i = 0; i < len; i++) + { + ind[i] = i; + move16(); + } + sorted = 0; + move16(); + FOR(k = len - 1; k && !sorted; k--) + { + sorted = 1; + move16(); + FOR(i = 0; i < k; i++) + { + IF(LT_32(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; +} +#endif void sort_desc_ind( float *s, /* i/o: vector to be sorted */ const int16_t len, /* i : vector length */ diff --git a/lib_dec/amr_wb_dec.c b/lib_dec/amr_wb_dec.c index bd448a036..80febf6f5 100644 --- a/lib_dec/amr_wb_dec.c +++ b/lib_dec/amr_wb_dec.c @@ -271,13 +271,13 @@ ivas_error amr_wb_dec_flt( floatToFixed_arr16( st->mem_syn_clas_estim, st->mem_syn_clas_estim_fx, Q_mem_syn_clas_estim, 258 ); FOR( i = 0; i < M; i++ ) { - st->lsf_old32[i] = float_to_fix( ( st->lsf_old[i] * 2.56f ), 0 ); - st->lsfoldbfi132[i] = float_to_fix( ( st->lsfoldbfi1[i] * 2.56f ), 0 ); - st->lsfoldbfi032[i] = float_to_fix( ( st->lsfoldbfi0[i] * 2.56f ), 0 ); - st->lsf_adaptive_mean32[i] = float_to_fix( ( st->lsf_adaptive_mean[i] * 2.56f ), 0 ); - st->lsp_old_fx[i] = float_to_fix16( st->lsp_old[i], 15 ); - st->mem_AR32[i] = float_to_fix( ( st->mem_AR[i] * 2.56f ), 0 ); - st->mem_MA32[i] = (Word32) ( ( st->mem_MA[i] * 5.12f ) ); + st->lsf_old_fx[i] = (Word16)float_to_fix16( ( st->lsf_old[i] * (2.56f / st->scale)), 0); + st->lsfoldbfi1_fx[i] = (Word16)float_to_fix16((st->lsfoldbfi1[i] * (2.56f / st->scale_lsfbfi)), 0); + st->lsfoldbfi0_fx[i] = (Word16)float_to_fix16((st->lsfoldbfi0[i] * (2.56f / st->scale_lsfbfi)), 0); + st->lsf_adaptive_mean_fx[i] = (Word16)float_to_fix16((st->lsf_adaptive_mean[i] * (2.56f / st->scale_lsfbfi)), 0); + st->lsp_old_fx[i] = float_to_fix16(st->lsp_old[i], 15); + st->mem_AR_fx[i] = (Word16)float_to_fix16( ( st->mem_AR[i] * 2.56f ), 0 ); + st->mem_MA_fx[i] = (Word16) ( ( st->mem_MA[i] * 2.56f ) ); } IF( st->hFdCngDec ) { @@ -324,12 +324,12 @@ ivas_error amr_wb_dec_flt( st->lp_gainc = fixedToFloat( st->lp_gainc_fx, 3 ); /*Q3*/ FOR( i = 0; i < M; i++ ) { - st->mem_MA[i] = (float) ( st->mem_MA32[i] / 5.12f ); - st->mem_AR[i] = (float) ( st->mem_AR32[i] / 2.56f ); - st->lsf_old[i] = (float) ( st->lsf_old32[i] / 2.56f ); - st->lsfoldbfi1[i] = (float) ( st->lsfoldbfi132[i] / 2.56f ); - st->lsfoldbfi0[i] = (float) ( st->lsfoldbfi032[i] / 2.56f ); - st->lsf_adaptive_mean[i] = (float) ( st->lsf_adaptive_mean32[i] / 2.56f ); + st->mem_MA[i] = (float) ( st->mem_MA_fx[i] / 2.56f ); + st->mem_AR[i] = (float) ( st->mem_AR_fx[i] / 2.56f ); + st->lsf_old[i] = (float) ( st->lsf_old_fx[i] / (2.56f / st->scale)); + st->lsfoldbfi1[i] = (float)(st->lsfoldbfi1_fx[i] / (2.56f / st->scale_lsfbfi)); + st->lsfoldbfi0[i] = (float)(st->lsfoldbfi0_fx[i] / (2.56f / st->scale_lsfbfi)); + st->lsf_adaptive_mean[i] = (float)(st->lsf_adaptive_mean_fx[i] / (2.56f / st->scale_lsfbfi)); st->lsp_old[i] = fixedToFloat( st->lsp_old_fx[i], 15 ); } fixedToFloat_arr( st->mem_syn_r, st->mem_syn_r_float, Q_mem_syn, L_SYN_MEM ); diff --git a/lib_dec/core_dec_switch.c b/lib_dec/core_dec_switch.c index ee8ae2088..8c74d7fa5 100644 --- a/lib_dec/core_dec_switch.c +++ b/lib_dec/core_dec_switch.c @@ -162,6 +162,10 @@ void mode_switch_decoder_LPD_flt( lsp2lsf( st->lsp_old, st->lsfoldbfi1, M, st->sr_core ); mvr2r( st->lsfoldbfi1, st->lsfoldbfi0, M ); mvr2r( st->lsfoldbfi1, st->lsf_adaptive_mean, M ); +#ifdef IVAS_FLOAT_FIXED + // To be removed + st->scale_lsfbfi = (float) st->sr_core / INT_FS_12k8; +#endif // IVAS_FLOAT_FIXED; if ( st->igf && st->hBWE_TD != NULL ) { diff --git a/lib_dec/core_dec_switch_fx.c b/lib_dec/core_dec_switch_fx.c index a8923e07d..2a3a0afba 100644 --- a/lib_dec/core_dec_switch_fx.c +++ b/lib_dec/core_dec_switch_fx.c @@ -410,10 +410,18 @@ void mode_switch_decoder_LPD_ivas_fx( IF( EQ_16( st->tcxonly, 0 ) ) { lsp2lsf_fx( st->lsp_old_fx, st->lsfoldbfi1_fx, M, extract_l( st->sr_core ) ); +#ifdef IVAS_FLOAT_FIXED + // To be removed + st->scale_lsfbfi = (float) st->sr_core / INT_FS_12k8; +#endif // IVAS_FLOAT_FIXED } ELSE { E_LPC_lsp_lsf_conversion( st->lsp_old_fx, st->lsfoldbfi1_fx, M ); +#ifdef IVAS_FLOAT_FIXED + // To be removed + st->scale_lsfbfi = (float) st->sr_core / INT_FS_12k8; +#endif // IVAS_FLOAT_FIXED } Copy( st->lsfoldbfi1_fx, st->lsfoldbfi0_fx, M ); Copy( st->lsfoldbfi1_fx, st->lsf_adaptive_mean_fx, M ); diff --git a/lib_dec/core_switching_dec.c b/lib_dec/core_switching_dec.c index 6706f3589..44897c93f 100644 --- a/lib_dec/core_switching_dec.c +++ b/lib_dec/core_switching_dec.c @@ -367,10 +367,6 @@ ivas_error core_switching_pre_dec_ivas_fx( Copy( TRWB_Ave_fx, st->lsf_adaptive_mean_fx, M ); lsf2lsp_fx( st->lsf_old_fx, st->lsp_old_fx, M, INT_FS_12k8 ); } - Copy_Scale_sig_16_32( st->lsf_old_fx, st->lsf_old32, 0, M ); - Copy_Scale_sig_16_32( st->lsfoldbfi1_fx, st->lsfoldbfi132, 0, M ); - Copy_Scale_sig_16_32( st->lsfoldbfi0_fx, st->lsfoldbfi032, 0, M ); - Copy_Scale_sig_16_32( st->lsf_adaptive_mean_fx, st->lsf_adaptive_mean32, 0, M ); IF( ( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && EQ_16( nchan_out, 2 ) && GT_32( st->core_brate, SID_2k40 ) && ( EQ_32( last_core_brate_st0, FRAME_NO_DATA ) || EQ_32( last_core_brate_st0, SID_2k40 ) ) && st->hTcxDec != NULL ) { @@ -393,7 +389,7 @@ ivas_error core_switching_pre_dec_ivas_fx( } /* Reset ACELP parameters */ - set32_fx( st->mem_MA32, 0, M ); + set16_fx( st->mem_MA_fx, 0, M ); IF( EQ_32(st->sr_core , INT_FS_16k) ) { @@ -403,7 +399,6 @@ ivas_error core_switching_pre_dec_ivas_fx( { Copy( GEWB_Ave_fx, st->mem_AR_fx, M ); } - Copy_Scale_sig_16_32( st->mem_AR_fx, st->mem_AR32, M, 0 ); #if 1 /*To be removed later: floating point initializations*/ st->tilt_code = 0.0f; st->gc_threshold = 0.0f; diff --git a/lib_dec/evs_dec.c b/lib_dec/evs_dec.c index 2499d03c1..0c57c5b36 100644 --- a/lib_dec/evs_dec.c +++ b/lib_dec/evs_dec.c @@ -387,13 +387,13 @@ ivas_error evs_dec_flt( floatToFixed_arr16( st->mem_syn_clas_estim, st->mem_syn_clas_estim_fx, Q_mem_syn_clas_estim, 258 ); FOR( i = 0; i < M; i++ ) { - st->lsf_old32[i] = float_to_fix( ( st->lsf_old[i] * 2.56f ), 0 ); - st->lsfoldbfi132[i] = float_to_fix( ( st->lsfoldbfi1[i] * 2.56f ), 0 ); - st->lsfoldbfi032[i] = float_to_fix( ( st->lsfoldbfi0[i] * 2.56f ), 0 ); - st->lsf_adaptive_mean32[i] = float_to_fix( ( st->lsf_adaptive_mean[i] * 2.56f ), 0 ); + st->lsf_old_fx[i] = float_to_fix16( ( st->lsf_old[i] * (2.56f / st->scale)), 0); + st->lsfoldbfi1_fx[i] = float_to_fix16((st->lsfoldbfi1[i] * (2.56f / st->scale_lsfbfi)), 0); + st->lsfoldbfi0_fx[i] = float_to_fix16((st->lsfoldbfi0[i] * (2.56f / st->scale_lsfbfi)), 0); + st->lsf_adaptive_mean_fx[i] = float_to_fix16((st->lsf_adaptive_mean[i] * (2.56f / st->scale_lsfbfi)), 0 ); st->lsp_old_fx[i] = float_to_fix16( st->lsp_old[i], 15 ); - st->mem_AR32[i] = float_to_fix( ( st->mem_AR[i] * 2.56f ), 0 ); - st->mem_MA32[i] = (Word32) ( ( st->mem_MA[i] * 5.12f ) ); + st->mem_AR_fx[i] = float_to_fix16( ( st->mem_AR[i] * 2.56f ), 0 ); + st->mem_MA_fx[i] = (Word16) ( ( st->mem_MA[i] * 2.56f ) ); } IF( st->hFdCngDec ) { @@ -440,12 +440,12 @@ ivas_error evs_dec_flt( st->lp_gainc = fixedToFloat( st->lp_gainc_fx, 3 ); /*Q3*/ FOR( i = 0; i < M; i++ ) { - st->mem_MA[i] = (float) ( st->mem_MA32[i] / 5.12f ); - st->mem_AR[i] = (float) ( st->mem_AR32[i] / 2.56f ); - st->lsf_old[i] = (float) ( st->lsf_old32[i] / 2.56f ); - st->lsfoldbfi1[i] = (float) ( st->lsfoldbfi132[i] / 2.56f ); - st->lsfoldbfi0[i] = (float) ( st->lsfoldbfi032[i] / 2.56f ); - st->lsf_adaptive_mean[i] = (float) ( st->lsf_adaptive_mean32[i] / 2.56f ); + st->mem_MA[i] = (float) ( st->mem_MA_fx[i] / 2.56f ); + st->mem_AR[i] = (float)(st->mem_AR_fx[i] / 2.56f ); + st->lsf_old[i] = (float)(st->lsf_old_fx[i] / (2.56f / st->scale)); + st->lsfoldbfi1[i] = (float)(st->lsfoldbfi1_fx[i] / (2.56f / st->scale_lsfbfi)); + st->lsfoldbfi0[i] = (float)(st->lsfoldbfi0_fx[i] / (2.56f / st->scale_lsfbfi)); + st->lsf_adaptive_mean[i] = (float)(st->lsf_adaptive_mean_fx[i] / (2.56f / st->scale_lsfbfi)); st->lsp_old[i] = fixedToFloat( st->lsp_old_fx[i], 15 ); } fixedToFloat_arr( st->mem_syn_r, st->mem_syn_r_float, Q_mem_syn, L_SYN_MEM ); diff --git a/lib_dec/init_dec.c b/lib_dec/init_dec.c index 953380aaa..fb8dff651 100644 --- a/lib_dec/init_dec.c +++ b/lib_dec/init_dec.c @@ -131,6 +131,7 @@ ivas_error init_decoder( #ifdef IVAS_FLOAT_FIXED st->scale = 1.f; + st->scale_lsfbfi = 1.f; #endif // IVAS_FLOAT_FIXED set_f( st->mem_syn1, 0, M ); diff --git a/lib_dec/init_dec_fx.c b/lib_dec/init_dec_fx.c index 241327fa2..6a490087a 100644 --- a/lib_dec/init_dec_fx.c +++ b/lib_dec/init_dec_fx.c @@ -967,6 +967,7 @@ ivas_error init_decoder_ivas_fx( #ifdef IVAS_FLOAT_FIXED st_fx->scale = 1.f; + st_fx->scale_lsfbfi = 1.f; #endif // IVAS_FLOAT_FIXED set_f(st_fx->mem_syn1, 0, M); diff --git a/lib_dec/ivas_core_dec.c b/lib_dec/ivas_core_dec.c index 45b8e339f..3d00a5556 100644 --- a/lib_dec/ivas_core_dec.c +++ b/lib_dec/ivas_core_dec.c @@ -625,13 +625,13 @@ ivas_error ivas_core_dec( floatToFixed_arr16( st->mem_syn_clas_estim, st->mem_syn_clas_estim_fx, Q_mem_syn_clas_estim, 258 ); FOR( i = 0; i < M; i++ ) { - st->lsf_old32[i] = float_to_fix( ( st->lsf_old[i] * 2.56f ), 0 ); - st->lsfoldbfi132[i] = float_to_fix( ( st->lsfoldbfi1[i] * 2.56f ), 0 ); - st->lsfoldbfi032[i] = float_to_fix( ( st->lsfoldbfi0[i] * 2.56f ), 0 ); - st->lsf_adaptive_mean32[i] = float_to_fix( ( st->lsf_adaptive_mean[i] * 2.56f ), 0 ); + st->lsf_old_fx[i] = float_to_fix16( ( st->lsf_old[i] * (2.56f / st->scale)), 0); + st->lsfoldbfi1_fx[i] = float_to_fix16((st->lsfoldbfi1[i] * (2.56f / st->scale_lsfbfi)), 0); + st->lsfoldbfi0_fx[i] = float_to_fix16((st->lsfoldbfi0[i] * (2.56f / st->scale_lsfbfi)), 0); + st->lsf_adaptive_mean_fx[i] = float_to_fix16((st->lsf_adaptive_mean[i] * (2.56f / st->scale_lsfbfi)), 0 ); st->lsp_old_fx[i] = float_to_fix16( st->lsp_old[i], 15 ); - st->mem_AR32[i] = float_to_fix( ( st->mem_AR[i] * 2.56f ), 0 ); - st->mem_MA32[i] = (Word32) ( ( st->mem_MA[i] * 5.12f ) ); + st->mem_AR_fx[i] = float_to_fix16( ( st->mem_AR[i] * 2.56f ), 0 ); + st->mem_MA_fx[i] = (Word16) ( ( st->mem_MA[i] * 2.56f ) ); } IF( st->hFdCngDec ) { @@ -678,12 +678,12 @@ ivas_error ivas_core_dec( st->lp_gainc = fixedToFloat( st->lp_gainc_fx, 3 ); /*Q3*/ FOR( i = 0; i < M; i++ ) { - st->mem_MA[i] = (float) ( st->mem_MA32[i] / 5.12f ); - st->mem_AR[i] = (float) ( st->mem_AR32[i] / 2.56f ); - st->lsf_old[i] = (float) ( st->lsf_old32[i] / 2.56f ); - st->lsfoldbfi1[i] = (float) ( st->lsfoldbfi132[i] / 2.56f ); - st->lsfoldbfi0[i] = (float) ( st->lsfoldbfi032[i] / 2.56f ); - st->lsf_adaptive_mean[i] = (float) ( st->lsf_adaptive_mean32[i] / 2.56f ); + st->mem_MA[i] = (float) ( st->mem_MA_fx[i] / 2.56f ); + st->mem_AR[i] = (float) ( st->mem_AR_fx[i] / 2.56f ); + st->lsf_old[i] = (float) ( st->lsf_old_fx[i] / (2.56f / st->scale)); + st->lsfoldbfi1[i] = (float)(st->lsfoldbfi1_fx[i] / (2.56f / st->scale_lsfbfi)); + st->lsfoldbfi0[i] = (float)(st->lsfoldbfi0_fx[i] / (2.56f / st->scale_lsfbfi)); + st->lsf_adaptive_mean[i] = (float)(st->lsf_adaptive_mean_fx[i] / (2.56f / st->scale_lsfbfi)); st->lsp_old[i] = fixedToFloat( st->lsp_old_fx[i], 15 ); } fixedToFloat_arr( st->mem_syn_r, st->mem_syn_r_float, Q_mem_syn, L_SYN_MEM ); diff --git a/lib_dec/ivas_corecoder_dec_reconfig.c b/lib_dec/ivas_corecoder_dec_reconfig.c index b64288fb8..c1a7d0d36 100644 --- a/lib_dec/ivas_corecoder_dec_reconfig.c +++ b/lib_dec/ivas_corecoder_dec_reconfig.c @@ -352,6 +352,7 @@ ivas_error ivas_corecoder_dec_reconfig( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) ); } set_l( st_ivas->hSCE[0]->save_synth_fx, 0, output_frame ); + st_ivas->hSCE[0]->q_save_synth_fx = 0; #endif } diff --git a/lib_dec/ivas_cpe_dec_fx.c b/lib_dec/ivas_cpe_dec_fx.c index 11ee97058..e56c6b714 100644 --- a/lib_dec/ivas_cpe_dec_fx.c +++ b/lib_dec/ivas_cpe_dec_fx.c @@ -185,8 +185,11 @@ ivas_error ivas_cpe_dec_fx( q_old_out_LB -= 1; FOR(Word16 ind1 = 0; ind1 < 1; ind1++) { IF(hCPE->hCoreCoder[ind1]->hHQ_core) - FOR(Word16 ind2 = 0; ind2 < L_FRAME32k; ind2++) { - hCPE->hCoreCoder[ind1]->hHQ_core->old_outLB_fx[ind2] = (Word32)(hCPE->hCoreCoder[ind1]->hHQ_core->old_outLB[ind2] * (1<hCoreCoder[ind1]->hHQ_core->old_outLB_fx[ind2] = (Word32)(hCPE->hCoreCoder[ind1]->hHQ_core->old_outLB[ind2] * (1<hCoreCoder[ind1]->hHQ_core->q_old_outLB_fx = q_old_out_LB; } } q_tcxltp_mem_in_float = 11; @@ -665,7 +668,74 @@ ivas_error ivas_cpe_dec_fx( /* DFT Stereo residual decoding */ IF( GT_16( hCPE->hStereoDft->res_cod_band_max, 0 ) && !st_ivas->bfi ) { +#ifndef IVAS_FLOAT_FIXED_ stereo_dft_dec_res( hCPE, res_buf, output_flt[1] ); +#else + { + Word32 output_fix[L_FRAME8k], i_max_val; + Word16 q_output_fix, q_pst_old_syn, s_max_val; + float max_val = 0.0f; + Word16 ii; + for (ii = 0; ii < NBPSF_PIT_MAX; ii++) + { + if (max_val < fabs(hCPE->hStereoDft->hBpf->pst_old_syn[ii])) + { + max_val = (float)fabs(hCPE->hStereoDft->hBpf->pst_old_syn[ii]); + } + } + s_max_val = (Word16)max_val; + if (max_val > 32767.0 || max_val < -32768.0) + { + assert(0); + } + IF (s_max_val != 0) + { + q_pst_old_syn = norm_s(s_max_val) - Q3; + } + ELSE + { + q_pst_old_syn = 0; + } + hCPE->hStereoDft->hBpf->q_pst_old_syn = q_pst_old_syn; + + for (ii = 0; ii < L_FRAME8k; ii++) + { + if (max_val < fabs(output_flt[1][ii])) + { + max_val = (float)fabs(output_flt[1][ii]); + } + } + i_max_val = (Word32)max_val; + IF (i_max_val != 0) + { + q_output_fix = norm_l(i_max_val) - Q8; + } + ELSE + { + q_output_fix = 0; + } + hCPE->hStereoDft->q_res_cod_mem_fx = q_output_fix; + floatToFixed_arrL(output_flt[1], &output_fix[0], q_output_fix, L_FRAME8k); + floatToFixed_arrL(hCPE->hStereoDft->res_cod_mem, hCPE->hStereoDft->res_cod_mem_fx, q_output_fix, sizeof(hCPE->hStereoDft->res_cod_mem_fx) / sizeof(hCPE->hStereoDft->res_cod_mem_fx[0])); + floatToFixed_arr(hCPE->hStereoDft->hBpf->pst_old_syn, hCPE->hStereoDft->hBpf->pst_old_syn_fx, q_pst_old_syn, sizeof(hCPE->hStereoDft->hBpf->pst_old_syn_fx) / sizeof(hCPE->hStereoDft->hBpf->pst_old_syn_fx[0])); + floatToFixed_arr(hCPE->hStereoDft->hBpf->mem_mean_pit, hCPE->hStereoDft->hBpf->mem_mean_pit_fx, Q4, sizeof(hCPE->hStereoDft->hBpf->mem_mean_pit) / sizeof(hCPE->hStereoDft->hBpf->mem_mean_pit[0])); + floatToFixed_arr(hCPE->hCoreCoder[0]->old_pitch_buf, hCPE->hCoreCoder[0]->old_pitch_buf_16_fx, Q6, sizeof(hCPE->hCoreCoder[0]->old_pitch_buf_16_fx) / sizeof(hCPE->hCoreCoder[0]->old_pitch_buf_16_fx[0])); + hCPE->hStereoDft->hBpf->psf_att_fx = floatToFixed(hCPE->hStereoDft->hBpf->psf_att, Q15); + Copy(hCPE->hStereoDft->hBpf->Track_on_hist, hCPE->hStereoDft->hBpf->Track_on_hist_fx, sizeof(hCPE->hStereoDft->hBpf->Track_on_hist_fx) / sizeof(hCPE->hStereoDft->hBpf->Track_on_hist_fx[0])); + Copy(hCPE->hStereoDft->hBpf->vibrato_hist, hCPE->hStereoDft->hBpf->vibrato_hist_fx, sizeof(hCPE->hStereoDft->hBpf->vibrato_hist_fx) / sizeof(hCPE->hStereoDft->hBpf->vibrato_hist_fx[0])); + + stereo_dft_dec_res_fx(hCPE, res_buf_fx, Q8, q_output_fix, output_fix); + + Copy(hCPE->hStereoDft->hBpf->vibrato_hist_fx, hCPE->hStereoDft->hBpf->vibrato_hist, sizeof(hCPE->hStereoDft->hBpf->vibrato_hist_fx) / sizeof(hCPE->hStereoDft->hBpf->vibrato_hist_fx[0])); + Copy(hCPE->hStereoDft->hBpf->Track_on_hist_fx, hCPE->hStereoDft->hBpf->Track_on_hist, sizeof(hCPE->hStereoDft->hBpf->Track_on_hist_fx) / sizeof(hCPE->hStereoDft->hBpf->Track_on_hist_fx[0])); + hCPE->hStereoDft->hBpf->psf_att = fixedToFloat(hCPE->hStereoDft->hBpf->psf_att_fx, Q15); + fixedToFloat_arr(hCPE->hCoreCoder[0]->old_pitch_buf_16_fx, hCPE->hCoreCoder[0]->old_pitch_buf, Q6, sizeof(hCPE->hCoreCoder[0]->old_pitch_buf_16_fx) / sizeof(hCPE->hCoreCoder[0]->old_pitch_buf_16_fx[0])); + fixedToFloat_arr(hCPE->hStereoDft->hBpf->mem_mean_pit_fx, hCPE->hStereoDft->hBpf->mem_mean_pit, Q4, sizeof(hCPE->hStereoDft->hBpf->mem_mean_pit) / sizeof(hCPE->hStereoDft->hBpf->mem_mean_pit[0])); + fixedToFloat_arr(hCPE->hStereoDft->hBpf->pst_old_syn_fx, hCPE->hStereoDft->hBpf->pst_old_syn, q_pst_old_syn, sizeof(hCPE->hStereoDft->hBpf->pst_old_syn_fx) / sizeof(hCPE->hStereoDft->hBpf->pst_old_syn_fx[0])); + fixedToFloat_arrL(hCPE->hStereoDft->res_cod_mem_fx, hCPE->hStereoDft->res_cod_mem, q_output_fix, sizeof(hCPE->hStereoDft->res_cod_mem_fx) / sizeof(hCPE->hStereoDft->res_cod_mem_fx[0])); + fixedToFloat_arrL(&output_fix[0], output_flt[1], q_output_fix, L_FRAME8k); + } +#endif stereo_dft_dec_analyze( hCPE, output_flt[1], DFT, 1, L_FRAME8k, output_frame, DFT_STEREO_DEC_ANA_LB, 0, 0 ); } @@ -1230,7 +1300,7 @@ ivas_error create_cpe_dec( set32_fx( hCPE->prev_hb_synth_fx[n], 0, NS2SA_fx2( output_Fs, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ) ); set32_fx( hCPE->prev_synth_fx[n], 0, NS2SA_fx2( output_Fs, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ) ); } - + hCPE->q_prev_synth_fx = 0; hCPE->brate_surplus = 0; /*-----------------------------------------------------------------* diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 0e8448923..c2f56d36c 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -891,7 +891,7 @@ ivas_error ivas_jbm_dec_tc( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd = norm_l(i_max_val_psd) - Q9; IF (EQ_16(hCPE->hStereoDft->first_frame, 1)) { - hCPE->q_prev_synth_fx = hCPE->hStereoDft->q_dft; + //hCPE->q_prev_synth_fx = hCPE->hStereoDft->q_dft; hCPE->hStereoDft->q_smoothed_nrg = Q6;//hCPE->hStereoDft->q_dft; hCPE->hStereoDft->q_ap_delay_mem_fx = hCPE->hStereoDft->q_dft; } @@ -961,18 +961,23 @@ ivas_error ivas_jbm_dec_tc( if (hSCE != NULL) { floatToFixed_arrL(&hSCE->prev_hb_synth[0], &hSCE->prev_hb_synth_fx[0], hCPE->hStereoDft->q_dft, sizeof(hSCE->prev_hb_synth_fx) / sizeof(hSCE->prev_hb_synth_fx[0])); + hSCE->q_prev_hb_synth_fx = hCPE->hStereoDft->q_dft; floatToFixed_arrL(&hSCE->save_hb_synth[0], &hSCE->save_hb_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + hSCE->q_save_hb_synth_fx = q; floatToFixed_arrL(&hSCE->save_synth[0], &hSCE->save_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + hSCE->q_save_synth_fx = q; } IF( hCPE->hCoreCoder[0] != NULL ) { floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_outLB[0], &hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[0], q, L_FRAME32k); + hCPE->hCoreCoder[0]->hHQ_core->q_old_outLB_fx = q; floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_out[0], &hCPE->hCoreCoder[0]->hHQ_core->oldOut_fx[0], q, L_FRAME48k); IF( (hCPE->hCoreCoder[0] != NULL) && (hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL) ) floatToFixed_arrL(&hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[0], &hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[0], q, L_FRAME16k); } IF( hCPE->hStereoDft != NULL ) { + floatToFixed_arrL(&hCPE->hStereoDft->td_gain[0], &hCPE->hStereoDft->td_gain_fx[0], Q31, sizeof( hCPE->hStereoDft->td_gain_fx ) / sizeof( hCPE->hStereoDft->td_gain_fx[0] ) ); floatToFixed_arrL(&hCPE->hStereoDft->ap_delay_mem[0], &hCPE->hStereoDft->ap_delay_mem_fx[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS )); floatToFixed_arrL(&hCPE->hStereoDft->buff_LBTCX_mem[0], &hCPE->hStereoDft->buff_LBTCX_mem_fx[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS )); floatToFixed_arr(&hCPE->hStereoDft->smooth_fac[0][0], &hCPE->hStereoDft->smooth_fac_fx[0][0], Q15, sizeof(hCPE->hStereoDft->smooth_fac_fx) / sizeof(hCPE->hStereoDft->smooth_fac_fx[0][0])); @@ -997,9 +1002,16 @@ ivas_error ivas_jbm_dec_tc( hCPE->q_output_mem_fx[ii] = hCPE->hStereoDft->q_dft; floatToFixed_arrL(&hCPE->output_mem[ii][0], &hCPE->output_mem_fx[ii][0], hCPE->hStereoDft->q_dft, NS2SA_fx2( st_ivas->hDecoderConfig->output_Fs, STEREO_DFT32MS_OVL_NS )); } + floatToFixed_arrL(&hCPE->prev_synth[0][0], &hCPE->prev_synth_fx[0][0], hCPE->q_prev_synth_fx, sizeof(hCPE->prev_synth) / sizeof(hCPE->prev_synth[0][0])); ivas_sba_dirac_stereo_dec_fx( st_ivas, p_output_fix, output_frame, st_ivas->ivas_format == MC_FORMAT ); + IF (hSCE != NULL) + { + hSCE->hCoreCoder[0]->log_energy_diff_lt = fixedToFloat(hSCE->hCoreCoder[0]->log_energy_diff_lt_fx, Q15); + hSCE->hCoreCoder[0]->stab_fac_smooth_lt = fixedToFloat(hSCE->hCoreCoder[0]->stab_fac_smooth_lt_fx, Q31); + } + fixedToFloat_arrL(&hCPE->prev_synth_fx[0][0], &hCPE->prev_synth[0][0], hCPE->q_prev_synth_fx, sizeof(hCPE->prev_synth) / sizeof(hCPE->prev_synth[0][0])); st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact = fixedToFloat( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact_fx, 15 ); st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact = fixedToFloat( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact_fx, 15 ); fixedToFloat_arrL( &hCPE->hStereoDft->res_gains_ind_fx[0][0], &hCPE->hStereoDft->res_gains_ind[0][0], Q26, sizeof( hCPE->hStereoDft->res_gains_ind_fx ) / sizeof( hCPE->hStereoDft->res_gains_ind_fx[0][0] ) ); @@ -1008,7 +1020,7 @@ ivas_error ivas_jbm_dec_tc( fixedToFloat_arrL( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0], st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0] ) ); for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_subr_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_subr_fx[0] ); ii++ ) { - hCPE->hStereoDft->hb_nrg_subr[0] = ((float)hCPE->hStereoDft->hb_nrg_subr_fx[0] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr))); + hCPE->hStereoDft->hb_nrg_subr[ii] = ((float)hCPE->hStereoDft->hb_nrg_subr_fx[ii] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr))); } for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_fx[0] ); ii++ ) { @@ -1024,7 +1036,6 @@ ivas_error ivas_jbm_dec_tc( fixedToFloat_arr( &hCPE->hStereoCng->cm_fx[0], &hCPE->hStereoCng->cm[0], Q15, sizeof( hCPE->hStereoCng->cm_fx ) / sizeof( hCPE->hStereoCng->cm_fx[0] ) ); } fixedToFloat_arr( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state[0], Q15, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0] ) ); - fixedToFloat_arrL( &hCPE->hStereoDft->td_gain_fx[0], &hCPE->hStereoDft->td_gain[0], Q15, sizeof( hCPE->hStereoDft->td_gain_fx ) / sizeof( hCPE->hStereoDft->td_gain_fx[0] ) ); for ( int ii = 0; ii < 2; ii++ ) { fixedToFloat_arrL( &p_output_fix[ii][0], &p_output[ii][0], hCPE->hStereoDft->q_dft, ( 48000 / FRAMES_PER_SEC ) ); @@ -1049,6 +1060,7 @@ ivas_error ivas_jbm_dec_tc( } IF( hCPE->hStereoDft != NULL ) { + fixedToFloat_arrL(&hCPE->hStereoDft->td_gain_fx[0], &hCPE->hStereoDft->td_gain[0], Q31, sizeof( hCPE->hStereoDft->td_gain_fx ) / sizeof( hCPE->hStereoDft->td_gain_fx[0] ) ); fixedToFloat_arrL(&hCPE->hStereoDft->ap_delay_mem_fx[0], &hCPE->hStereoDft->ap_delay_mem[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS )); fixedToFloat_arrL(&hCPE->hStereoDft->buff_LBTCX_mem_fx[0], &hCPE->hStereoDft->buff_LBTCX_mem[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS )); fixedToFloat_arrL(&hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0], &hCPE->hStereoDft->mixer_mat_smooth[0][0][0], Q31, sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx) / sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0])); @@ -1198,9 +1210,24 @@ ivas_error ivas_jbm_dec_tc( dirac_bs_md_write_idx = st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx; /* Store the write-index for this frame */ } - /* MASA metadata decoding */ + + /* set ISM parameters and decode ISM metadata in OMASA format */ #ifdef IVAS_FLOAT_FIXED - // Float to fix conversion starts here. + Word32 *output_fx[MAX_TRANSPORT_CHANNELS]; + Word16 q_output = 11; + for ( int i = 0; i < MAX_TRANSPORT_CHANNELS; i++ ) + { + output_fx[i] = malloc( sizeof( Word32 ) * L_FRAME48k ); + } + // NOTE: the following is done to calculate the number of hIsmMetaData indices + Word16 tmp_nchan_ism; + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + tmp_nchan_ism = 1; + else if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + tmp_nchan_ism = 0; + else + tmp_nchan_ism = st_ivas->nchan_ism; + ///////////////////////////////////// Float to fix conversion starts here. /////////////////////////////////// FOR( Word32 l = 0; l < st_ivas->nchan_ism; l++ ) { st_ivas->hMasaIsmData->q_azimuth_old_fx[l] = float_to_fix( st_ivas->hMasaIsmData->q_azimuth_old[l], Q22 ); @@ -1230,14 +1257,102 @@ ivas_error ivas_jbm_dec_tc( } } } - // Float to fix conversion ends here. + FOR( Word16 ind = 0; ind < tmp_nchan_ism; ind++ ) + { + st_ivas->hIsmMetaData[ind]->azimuth_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->azimuth * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->elevation_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->elevation * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_azimuth_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_azimuth * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_elevation_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_elevation * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_true_azimuth_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_true_azimuth * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->last_true_elevation_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->last_true_elevation * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->radius_fx = (Word16) ( st_ivas->hIsmMetaData[ind]->radius * ( 1 << 9 ) ); + st_ivas->hIsmMetaData[ind]->yaw_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->yaw * ( 1 << 22 ) ); + st_ivas->hIsmMetaData[ind]->pitch_fx = (Word32) ( st_ivas->hIsmMetaData[ind]->pitch * ( 1 << 22 ) ); + } + FOR( n = 0; n < tmp_nchan_ism; n++ ) + { + set32_fx( output_fx[n], 0, L_FRAME48k ); + FOR( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[n]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[n]->prev_hb_synth[k] * ONE_IN_Q11 ); + } + } + ///////////////////////////////////// Float to fix conversion ends here. /////////////////////////////////// + /* MASA metadata decoding */ IF( ( error = ivas_masa_decode_fx( st_ivas, st_ivas->hCPE[0]->hCoreCoder[0], &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) { return error; } - // Fix to float conversion starts here. + /* Configuration of combined-format bit-budget distribution */ + ivas_set_surplus_brate_dec( st_ivas, &ism_total_brate ); + + st_ivas->hCPE[0]->hCoreCoder[0]->bit_stream = &( st_ivas->bit_stream[( ism_total_brate / FRAMES_PER_SEC )] ); + + IF( ( error = ivas_omasa_ism_metadata_dec_fx( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + + FOR( n = 0; n < nchan_transport_ism; n++ ) + { + IF( ( error = ivas_sce_dec_fx( st_ivas, n, &output_fx[st_ivas->nchan_transport + n], output_frame, nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* decode MASA channels */ + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, output_fx, output_frame, nb_bits_metadata[0], &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* shifting both the channels from variable q_output to constant Q-factor (Q11) */ + FOR( int k = 0; k < output_frame; k++ ) + { + output_fx[0][k] = L_shr( output_fx[0][k], 11 - q_output ); + move32(); + output_fx[1][k] = L_shr( output_fx[1][k], 11 - q_output ); + move32(); + } + + IF( EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) + { + Copy32( output_fx[0], output_fx[1], output_frame ); /* Copy mono signal to stereo output channels */ + } + + FOR( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20_fix32( output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + + Word16 output_q = 11; + move16(); + IF( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + ivas_mono_downmix_render_passive_fx( st_ivas, output_fx, output_frame ); + + output_q = 8; + move16(); + } + ELSE IF( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) + { + /* sanity check in case of bitrate switching */ + IF( st_ivas->ism_mode != ISM_MASA_MODE_DISC ) + { + return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified for combined MASA and ISM format" ); + } + + ivas_omasa_rearrange_channels_fx( output_fx, nchan_transport_ism, output_frame ); + + output_q = 11; + move16(); + + ivas_jbm_dec_copy_masa_meta_to_buffer( st_ivas ); + } + //////////////////////////// Fix to float conversion starts here. /////////////////////////////////// IF( st_ivas->hSpatParamRendCom != NULL ) { FOR( Word16 i = 0; i < st_ivas->hSpatParamRendCom->dirac_md_buffer_length; i++ ) @@ -1285,7 +1400,7 @@ ivas_error ivas_jbm_dec_tc( st_ivas->hMasa->data.dir_decode_quality = fix16_to_float( st_ivas->hMasa->data.dir_decode_quality_fx, Q14 ); IF( st_ivas->hMasa->hMasaLfeSynth != NULL ) { - FOR ( Word16 j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) + FOR( Word16 j = 0; j < MAX_PARAM_SPATIAL_SUBFRAMES; j++ ) { st_ivas->hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio[j] = fix16_to_float( st_ivas->hMasa->hMasaLfeSynth->lfeToTotalEnergyRatio_fx[j], Q14 ); } @@ -1303,71 +1418,57 @@ ivas_error ivas_jbm_dec_tc( } } } - // Fixed to float conversion ends here. -#else - if ( ( error = ivas_masa_decode( st_ivas, st_ivas->hCPE[0]->hCoreCoder[0], &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) - { - return error; - } -#endif - - /* Configuration of combined-format bit-budget distribution */ - ivas_set_surplus_brate_dec( st_ivas, &ism_total_brate ); - - st_ivas->hCPE[0]->hCoreCoder[0]->bit_stream = &( st_ivas->bit_stream[( ism_total_brate / FRAMES_PER_SEC )] ); - - /* set ISM parameters and decode ISM metadata in OMASA format */ - if ( ( error = ivas_omasa_ism_metadata_dec( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + FOR( Word16 ind = 0; ind < tmp_nchan_ism; ind++ ) { - return error; + st_ivas->hIsmMetaData[ind]->azimuth = (float) ( st_ivas->hIsmMetaData[ind]->azimuth_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->elevation = (float) ( st_ivas->hIsmMetaData[ind]->elevation_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_azimuth = (float) ( st_ivas->hIsmMetaData[ind]->last_azimuth_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_elevation = (float) ( st_ivas->hIsmMetaData[ind]->last_elevation_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_true_azimuth = (float) ( st_ivas->hIsmMetaData[ind]->last_true_azimuth_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->last_true_elevation = (float) ( st_ivas->hIsmMetaData[ind]->last_true_elevation_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->radius = (float) ( st_ivas->hIsmMetaData[ind]->radius_fx ) / (float) ( 1 << 9 ); + st_ivas->hIsmMetaData[ind]->yaw = (float) ( st_ivas->hIsmMetaData[ind]->yaw_fx ) / (float) ( 1 << 22 ); + st_ivas->hIsmMetaData[ind]->pitch = (float) ( st_ivas->hIsmMetaData[ind]->pitch_fx ) / (float) ( 1 << 22 ); } - -#ifdef IVAS_FLOAT_FIXED - Word32 *output_fx[2]; - Word16 q_output = 11; - output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); - output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); - FOR( n = 0; n < nchan_transport_ism; n++ ) { - set32_fx( output_fx[0], 0, L_FRAME48k ); - for ( int k = 0; k < 45; k++ ) - { - st_ivas->hSCE[n]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[n]->prev_hb_synth[k] * ONE_IN_Q11 ); - } - - IF( ( error = ivas_sce_dec_fx( st_ivas, n, &output_fx[0], output_frame, nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) - { - return error; - } - - for ( int k = 0; k < output_frame; k++ ) - { - p_output[st_ivas->nchan_transport + n][k] = (float) output_fx[0][k] / ONE_IN_Q11; - } - for ( int k = 0; k < 96; k++ ) + FOR( int k = 0; k < 96; k++ ) { st_ivas->hSCE[n]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[n]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ONE_IN_Q11; - if ( k < 45 ) + IF( k < 45 ) st_ivas->hSCE[n]->prev_hb_synth[k] = (float) st_ivas->hSCE[n]->prev_hb_synth_fx[k] / ONE_IN_Q11; } } - - /* decode MASA channels */ - IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0], &q_output ) ) != IVAS_ERR_OK ) + FOR( n = 0; n < s_max( getNumChanSynthesis( st_ivas ), nchan_transport_ism + st_ivas->nchan_transport ); n++ ) + { + FOR( int i = 0; i < output_frame; i++ ) + { + p_output[n][i] = (float) output_fx[n][i] / ( 1 << output_q ); + } + } + ///// FREE ///// + FOR( int i = 0; i < MAX_TRANSPORT_CHANNELS; i++ ) + { + free( output_fx[i] ); + } + /////////////////////////////////// Fixed to float conversion ends here. /////////////////////////////////// +#else + /* MASA metadata decoding */ + if ( ( error = ivas_masa_decode( st_ivas, st_ivas->hCPE[0]->hCoreCoder[0], &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) { return error; } - for ( int k = 0; k < output_frame; k++ ) + /* Configuration of combined-format bit-budget distribution */ + ivas_set_surplus_brate_dec( st_ivas, &ism_total_brate ); + + st_ivas->hCPE[0]->hCoreCoder[0]->bit_stream = &( st_ivas->bit_stream[( ism_total_brate / FRAMES_PER_SEC )] ); + + if ( ( error = ivas_omasa_ism_metadata_dec( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) { - p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); - p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + return error; } - free( output_fx[0] ); - free( output_fx[1] ); -#else /* decode ISM channels */ for ( n = 0; n < nchan_transport_ism; n++ ) { @@ -1382,7 +1483,6 @@ ivas_error ivas_jbm_dec_tc( { return error; } -#endif // IVAS_FLOAT_FIXED if ( st_ivas->hCPE[0]->nchan_out == 1 ) { @@ -1392,58 +1492,12 @@ ivas_error ivas_jbm_dec_tc( /* HP filtering */ for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) { -#ifdef IVAS_FLOAT_FIXED - Word32 p_output_fix[L_FRAME48k]; - for ( int i = 0; i < output_frame; i++ ) - { - p_output_fix[i] = (Word32) ( p_output[n][i] * ( 1 << 11 ) ); - } - hp20_fix32( p_output_fix, output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - for ( int i = 0; i < output_frame; i++ ) - { - p_output[n][i] = (float) p_output_fix[i] / ( 1 << 11 ); - } -#else hp20_flt( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); -#endif // IVAS_FLOAT_FIXED } if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) { -#ifdef IVAS_FLOAT_FIXED - for ( int lp = 0; lp < 12; lp++ ) - { - if ( p_output[lp] != NULL ) - { - p_output_fx[lp] = (Word32 *) malloc( sizeof( Word32 ) * L_FRAME48k ); - } - } - for ( int lp = 0; lp < 12; lp++ ) - { - if ( p_output[lp] != NULL ) - { - for ( int lp2 = 0; lp2 < output_frame; lp2++ ) - { - p_output_fx[lp][lp2] = (Word32) ( p_output[lp][lp2] * ( 1u << 11 ) ); - } - } - } - ivas_mono_downmix_render_passive_fx( st_ivas, p_output_fx, output_frame ); - - for ( int lp = 0; lp < 960; lp++ ) - { - p_output[0][lp] = (float) p_output_fx[0][lp] / ( 1u << 8 ); - } - for ( int lp = 0; lp < 12; lp++ ) - { - if ( p_output[lp] != NULL ) - { - free( p_output_fx[lp] ); - } - } -#else ivas_mono_downmix_render_passive( st_ivas, p_output, output_frame ); -#endif } else if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) { @@ -1452,11 +1506,11 @@ ivas_error ivas_jbm_dec_tc( { return IVAS_ERROR( IVAS_ERR_INVALID_OUTPUT_FORMAT, "Incorrect output configuration specified for combined MASA and ISM format" ); } - ivas_omasa_rearrange_channels( p_output, nchan_transport_ism, output_frame ); ivas_jbm_dec_copy_masa_meta_to_buffer( st_ivas ); } +#endif } else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) { @@ -1576,38 +1630,275 @@ ivas_error ivas_jbm_dec_tc( output_fx[i] = malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( Word32 ) ); FOR( Word16 j = 0; j < output_frame; j++ ) { - output_fx[i][j] = (Word32) ( p_output[i + sba_ch_idx][j] * ONE_IN_Q14 ); + output_fx[i][j] = (Word32) ( p_output[i + sba_ch_idx][j] * ONE_IN_Q14 ); + } + } + + ivas_agc_dec_process_fx( st_ivas->hSpar->hAgcDec, ( output_fx ), ( output_fx ), st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); + + FOR( Word16 i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) + { + FOR( Word16 j = 0; j < output_frame; j++ ) + { + p_output[i + sba_ch_idx][j] = (float) output_fx[i][j] / ONE_IN_Q11; + } + } + +#ifdef DUMPS_ENABLED + dbgwrite_txt( &p_output[sba_ch_idx][0], output_frame, "fix_ivas_agc_dec_process_output.txt", NULL ); +#endif // DUMPS_ENABLED + + FOR( Word16 i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) + { + free( output_fx[i] ); + } +#endif // !IVAS_FLOAT_FIXED + + if ( st_ivas->hSpar->hPCA != NULL ) + { + ivas_pca_dec( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, &p_output[sba_ch_idx] ); + } + + ivas_spar_dec_gen_umx_mat( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ) ); + +#ifndef IVAS_FLOAT_FIXED + ivas_sba_dirac_stereo_dec( st_ivas, &p_output[sba_ch_idx], output_frame, 0 ); +#else + { + Word16 q; + float l_hb_nrg = 0.0, l_hb_nrg_subr = 0.0; + static int frame_counter = 0; + if ( frame_counter >= 200 ) + frame_counter = frame_counter; + float max_val = 0.0; + int i_max_val_psd, i_max_val_op; + CPE_DEC_HANDLE hCPE = st_ivas->hCPE[0]; + SCE_DEC_HANDLE hSCE = st_ivas->hSCE[0]; + for ( int ii = 0; ii < sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0] ); ii++ ) + { + if ( max_val < fabs( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[ii] ) ) + { + max_val = (float) fabs( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[ii] ); + } + } + i_max_val_psd = (int) max_val; + for ( int ii = sba_ch_idx; ii < sba_ch_idx + 2; ii++ ) + { + for ( int jj = 0; jj < ( 48000 / FRAMES_PER_SEC ); jj++ ) + { + if ( max_val < fabs( p_output[ii][jj] ) ) + { + max_val = (float) fabs( p_output[ii][jj] ); + } + } + } + i_max_val_op = (int)max_val; + hCPE->hStereoDft->q_dft = norm_l(i_max_val_op) - Q11; + IF(hCPE->hStereoDft->q_dft < 0) + { + hCPE->hStereoDft->q_dft = 0; + } + ELSE IF (hCPE->hStereoDft->q_dft > Q11) + { + hCPE->hStereoDft->q_dft = Q11; + } + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd = norm_l(i_max_val_psd) - Q9; + IF (EQ_16(hCPE->hStereoDft->first_frame, 1)) + { + //hCPE->q_prev_synth_fx = hCPE->hStereoDft->q_dft; + hCPE->hStereoDft->q_smoothed_nrg = Q6;//hCPE->hStereoDft->q_dft; + hCPE->hStereoDft->q_ap_delay_mem_fx = hCPE->hStereoDft->q_dft; + } + + st_ivas->hCPE[0]->hCoreCoder[0]->stab_fac_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->stab_fac, 15); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact, 15); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact, 15); + floatToFixed_arrL(&hCPE->hStereoDft->res_gains_ind[0][0], &hCPE->hStereoDft->res_gains_ind_fx[0][0], Q26, sizeof(hCPE->hStereoDft->res_gains_ind_fx) / sizeof(hCPE->hStereoDft->res_gains_ind_fx[0][0])); + floatToFixed_arrL(&hCPE->hStereoDft->res_pred_gain[0], &hCPE->hStereoDft->res_pred_gain_fx[0], Q31, sizeof(hCPE->hStereoDft->res_pred_gain_fx)/ sizeof(hCPE->hStereoDft->res_pred_gain_fx[0])); + floatToFixed_arrL(&hCPE->hStereoDft->itd[0], &hCPE->hStereoDft->itd_fx[0], Q1, sizeof(hCPE->hStereoDft->itd_fx) / sizeof(hCPE->hStereoDft->itd_fx[0])); + floatToFixed_arrL(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0], st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0])); + floatToFixed_arrL(&hCPE->prev_hb_synth[0][0], &hCPE->prev_hb_synth_fx[0][0], hCPE->hStereoDft->q_dft, sizeof(hCPE->prev_hb_synth_fx) / sizeof(hCPE->prev_hb_synth_fx[0][0])); + for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++) + { + if ( l_hb_nrg_subr < hCPE->hStereoDft->hb_nrg_subr[ii] ) + { + l_hb_nrg_subr = hCPE->hStereoDft->hb_nrg_subr[ii]; + } + } + hCPE->hStereoDft->q_hb_nrg_subr = 0; + if ( l_hb_nrg_subr > (float) MAX_32 ) + { + int quotient = (int) ceil( l_hb_nrg_subr / (float) MAX_32 ); + hCPE->hStereoDft->q_hb_nrg_subr = Q31 - norm_l( quotient ); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_subr_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_subr_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg_subr_fx[ii] = (Word32) ( hCPE->hStereoDft->hb_nrg_subr[ii] / ( (float) ( 1 << hCPE->hStereoDft->q_hb_nrg_subr ) ) ); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_fx[0] ); ii++ ) + { + if ( l_hb_nrg < hCPE->hStereoDft->hb_nrg[ii] ) + { + l_hb_nrg = hCPE->hStereoDft->hb_nrg[ii]; + } + } + hCPE->hStereoDft->q_hb_nrg = 0; + if ( l_hb_nrg > (float) MAX_32 ) + { + int quotient = (int) ceil( l_hb_nrg / (float) MAX_32 ); + hCPE->hStereoDft->q_hb_nrg = Q31 - norm_l( quotient ); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg_fx[ii] = (Word32)(hCPE->hStereoDft->hb_nrg[ii] * ((float)(1 << hCPE->hStereoDft->q_hb_nrg))); + } + + floatToFixed_arrL( &hCPE->hStereoDft->side_gain[0], &hCPE->hStereoDft->side_gain_fx[0], Q31, sizeof( hCPE->hStereoDft->side_gain_fx ) / sizeof( hCPE->hStereoDft->side_gain_fx[0] ) ); + floatToFixed_arrL( &hCPE->hStereoDft->gipd[0], &hCPE->hStereoDft->gipd_fx[0], Q13, sizeof( hCPE->hStereoDft->gipd_fx ) / sizeof( hCPE->hStereoDft->gipd_fx[0] ) ); + floatToFixed_arr( &hCPE->hStereoDft->g_state[0], &hCPE->hStereoDft->g_state_fx[0], Q15, sizeof( hCPE->hStereoDft->g_state_fx ) / sizeof( hCPE->hStereoDft->g_state_fx[0] ) ); + floatToFixed_arr( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0], Q15, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0] ) ); + IF( hCPE->hStereoCng != NULL ) + { + floatToFixed_arr( &hCPE->hStereoCng->cm[0], &hCPE->hStereoCng->cm_fx[0], Q15, sizeof( hCPE->hStereoCng->cm_fx ) / sizeof( hCPE->hStereoCng->cm_fx[0] ) ); + } + floatToFixed_arr( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0], Q15, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0] ) ); + for ( int ii = sba_ch_idx; ii < sba_ch_idx + 2; ii++ ) + { + floatToFixed_arrL( &p_output[ii][0], &p_output_fix[ii][0], hCPE->hStereoDft->q_dft, ( 48000 / FRAMES_PER_SEC ) ); + } + q = hCPE->hStereoDft->q_dft; + floatToFixed_arrL(&hCPE->input_mem_BPF[0][0], &hCPE->input_mem_BPF_fx[0][0], q, STEREO_DFT32MS_OVL_16k); + floatToFixed_arrL(&hCPE->input_mem[0][0], &hCPE->input_mem_fx[0][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + floatToFixed_arrL(&hCPE->input_mem_LB[0][0], &hCPE->input_mem_LB_fx[0][0], q, STEREO_DFT32MS_OVL_16k); + floatToFixed_arrL(&hCPE->input_mem[1][0], &hCPE->input_mem_fx[1][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + floatToFixed_arrL(&hCPE->input_mem_LB[1][0], &hCPE->input_mem_LB_fx[1][0], q, STEREO_DFT32MS_OVL_16k); + if (hSCE != NULL) + { + floatToFixed_arrL(&hSCE->prev_hb_synth[0], &hSCE->prev_hb_synth_fx[0], hCPE->hStereoDft->q_dft, sizeof(hSCE->prev_hb_synth_fx) / sizeof(hSCE->prev_hb_synth_fx[0])); + hSCE->q_prev_hb_synth_fx = hCPE->hStereoDft->q_dft; + floatToFixed_arrL(&hSCE->save_hb_synth[0], &hSCE->save_hb_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + hSCE->q_save_hb_synth_fx = q; + floatToFixed_arrL(&hSCE->save_synth[0], &hSCE->save_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + hSCE->q_save_synth_fx = q; + } + IF( hCPE->hCoreCoder[0] != NULL ) + { + floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_outLB[0], &hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[0], q, L_FRAME32k); + hCPE->hCoreCoder[0]->hHQ_core->q_old_outLB_fx = q; + floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_out[0], &hCPE->hCoreCoder[0]->hHQ_core->oldOut_fx[0], q, L_FRAME48k); + IF( (hCPE->hCoreCoder[0] != NULL) && (hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL) ) + floatToFixed_arrL(&hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[0], &hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[0], q, L_FRAME16k); + } + IF( hCPE->hStereoDft != NULL ) + { + floatToFixed_arrL(&hCPE->hStereoDft->td_gain[0], &hCPE->hStereoDft->td_gain_fx[0], Q31, sizeof( hCPE->hStereoDft->td_gain_fx ) / sizeof( hCPE->hStereoDft->td_gain_fx[0] ) ); + floatToFixed_arrL(&hCPE->hStereoDft->ap_delay_mem[0], &hCPE->hStereoDft->ap_delay_mem_fx[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS )); + floatToFixed_arrL(&hCPE->hStereoDft->buff_LBTCX_mem[0], &hCPE->hStereoDft->buff_LBTCX_mem_fx[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS )); + floatToFixed_arr(&hCPE->hStereoDft->smooth_fac[0][0], &hCPE->hStereoDft->smooth_fac_fx[0][0], Q15, sizeof(hCPE->hStereoDft->smooth_fac_fx) / sizeof(hCPE->hStereoDft->smooth_fac_fx[0][0])); + hCPE->hStereoDft->q_smooth_buf_fx = Q7; + floatToFixed_arrL(&hCPE->hStereoDft->smooth_buf[0][0], &hCPE->hStereoDft->smooth_buf_fx[0][0], hCPE->hStereoDft->q_smooth_buf_fx, sizeof(hCPE->hStereoDft->smooth_buf_fx) / sizeof(hCPE->hStereoDft->smooth_buf_fx[0][0])); + floatToFixed_arrL(&hCPE->hStereoDft->mixer_mat_smooth[0][0][0], &hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0], Q31, sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx) / sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0])); + floatToFixed_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_prev[0][0][0][0], &st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0], Q31, sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx) / sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0])); + } + for (int ii = 0; ii < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; ii++) + { + for (int jj = 0; jj < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; jj++) + { + floatToFixed_arrL(&st_ivas->hSpar->hMdDec->mixer_mat[ii][jj][0], + &st_ivas->hSpar->hMdDec->mixer_mat_fx[ii][jj][0], + Q31, + st_ivas->hSpar->hMdDec->mix_mat_dim_2); + } + } + hCPE->lt_es_em_fx = floatToFixed(hCPE->lt_es_em, Q15); + for (int ii = 0; ii < CPE_CHANNELS; ii++) + { + hCPE->q_output_mem_fx[ii] = hCPE->hStereoDft->q_dft; + floatToFixed_arrL(&hCPE->output_mem[ii][0], &hCPE->output_mem_fx[ii][0], hCPE->hStereoDft->q_dft, NS2SA_fx2( st_ivas->hDecoderConfig->output_Fs, STEREO_DFT32MS_OVL_NS )); + } + floatToFixed_arrL(&hCPE->prev_synth[0][0], &hCPE->prev_synth_fx[0][0], hCPE->q_prev_synth_fx, sizeof(hCPE->prev_synth) / sizeof(hCPE->prev_synth[0][0])); + + ivas_sba_dirac_stereo_dec_fx( st_ivas, &p_output_fix[sba_ch_idx], output_frame, 0 ); + + IF (hSCE != NULL) + { + hSCE->hCoreCoder[0]->log_energy_diff_lt = fixedToFloat(hSCE->hCoreCoder[0]->log_energy_diff_lt_fx, Q15); + hSCE->hCoreCoder[0]->stab_fac_smooth_lt = fixedToFloat(hSCE->hCoreCoder[0]->stab_fac_smooth_lt_fx, Q31); + } + fixedToFloat_arrL(&hCPE->prev_synth_fx[0][0], &hCPE->prev_synth[0][0], hCPE->q_prev_synth_fx, sizeof(hCPE->prev_synth) / sizeof(hCPE->prev_synth[0][0])); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact = fixedToFloat( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact_fx, 15 ); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact = fixedToFloat( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact_fx, 15 ); + fixedToFloat_arrL( &hCPE->hStereoDft->res_gains_ind_fx[0][0], &hCPE->hStereoDft->res_gains_ind[0][0], Q26, sizeof( hCPE->hStereoDft->res_gains_ind_fx ) / sizeof( hCPE->hStereoDft->res_gains_ind_fx[0][0] ) ); + fixedToFloat_arrL( &hCPE->hStereoDft->res_pred_gain_fx[0], &hCPE->hStereoDft->res_pred_gain[0], Q31, sizeof( hCPE->hStereoDft->res_pred_gain_fx ) / sizeof( hCPE->hStereoDft->res_pred_gain_fx[0] ) ); + fixedToFloat_arrL( &hCPE->hStereoDft->itd_fx[0], &hCPE->hStereoDft->itd[0], Q1, sizeof( hCPE->hStereoDft->itd_fx ) / sizeof( hCPE->hStereoDft->itd_fx[0] ) ); + fixedToFloat_arrL( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0], st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0] ) ); + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_subr_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_subr_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg_subr[ii] = ((float)hCPE->hStereoDft->hb_nrg_subr_fx[ii] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr))); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg[ii] = ( (float) hCPE->hStereoDft->hb_nrg_fx[ii] * ( (float) ( 1 << hCPE->hStereoDft->q_hb_nrg ) ) ); + } + fixedToFloat_arrL(&hCPE->hStereoDft->side_gain_fx[0], &hCPE->hStereoDft->side_gain[0], Q31,sizeof(hCPE->hStereoDft->side_gain_fx) / sizeof(hCPE->hStereoDft->side_gain_fx[0])); + fixedToFloat_arrL(&hCPE->hStereoDft->gipd_fx[0], &hCPE->hStereoDft->gipd[0], Q13, sizeof(hCPE->hStereoDft->gipd_fx) / sizeof(hCPE->hStereoDft->gipd_fx[0])); + fixedToFloat_arr(&hCPE->hStereoDft->g_state_fx[0], &hCPE->hStereoDft->g_state[0], Q15, sizeof(hCPE->hStereoDft->g_state_fx) / sizeof(hCPE->hStereoDft->g_state_fx[0])); + fixedToFloat_arr(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm[0], Q15, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0])); + fixedToFloat_arrL(&hCPE->prev_hb_synth_fx[0][0], &hCPE->prev_hb_synth[0][0], hCPE->hStereoDft->q_dft, sizeof(hCPE->prev_hb_synth_fx) / sizeof(hCPE->prev_hb_synth_fx[0][0])); + IF (hCPE->hStereoCng != NULL) + { + fixedToFloat_arr( &hCPE->hStereoCng->cm_fx[0], &hCPE->hStereoCng->cm[0], Q15, sizeof( hCPE->hStereoCng->cm_fx ) / sizeof( hCPE->hStereoCng->cm_fx[0] ) ); + } + fixedToFloat_arr( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state[0], Q15, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0] ) ); + for ( int ii = sba_ch_idx; ii < sba_ch_idx + 2; ii++ ) + { + fixedToFloat_arrL( &p_output_fix[ii][0], &p_output[ii][0], hCPE->hStereoDft->q_dft, ( 48000 / FRAMES_PER_SEC ) ); + } + fixedToFloat_arrL(&hCPE->input_mem_BPF_fx[0][0], &hCPE->input_mem_BPF[0][0], q, STEREO_DFT32MS_OVL_16k); + fixedToFloat_arrL(&hCPE->input_mem_fx[0][0], &hCPE->input_mem[0][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + fixedToFloat_arrL(&hCPE->input_mem_LB_fx[0][0], &hCPE->input_mem_LB[0][0], q, STEREO_DFT32MS_OVL_16k); + fixedToFloat_arrL(&hCPE->input_mem_fx[1][0], &hCPE->input_mem[1][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + fixedToFloat_arrL(&hCPE->input_mem_LB_fx[1][0], &hCPE->input_mem_LB[1][0], q, STEREO_DFT32MS_OVL_16k); + if (hSCE != NULL) + { + fixedToFloat_arrL(&hSCE->prev_hb_synth_fx[0], &hSCE->prev_hb_synth[0], hCPE->hStereoDft->q_dft, sizeof(hSCE->prev_hb_synth_fx) / sizeof(hSCE->prev_hb_synth_fx[0])); + fixedToFloat_arrL(&hSCE->save_synth_fx[0], &hSCE->save_synth[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + fixedToFloat_arrL(&hSCE->save_hb_synth_fx[0], &hSCE->save_hb_synth[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + } + IF( hCPE->hCoreCoder[0] != NULL ) + { + fixedToFloat_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[0], &hCPE->hCoreCoder[0]->hHQ_core->old_outLB[0], q, L_FRAME32k); + fixedToFloat_arrL(&hCPE->hCoreCoder[0]->hHQ_core->oldOut_fx[0], &hCPE->hCoreCoder[0]->hHQ_core->old_out[0], q, L_FRAME48k); + IF( hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL ) + fixedToFloat_arrL(&hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[0], &hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[0], q, L_FRAME16k); + } + IF( hCPE->hStereoDft != NULL ) + { + fixedToFloat_arrL( &hCPE->hStereoDft->td_gain_fx[0], &hCPE->hStereoDft->td_gain[0], Q31, sizeof( hCPE->hStereoDft->td_gain_fx ) / sizeof( hCPE->hStereoDft->td_gain_fx[0] ) ); + fixedToFloat_arrL(&hCPE->hStereoDft->ap_delay_mem_fx[0], &hCPE->hStereoDft->ap_delay_mem[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS )); + fixedToFloat_arrL(&hCPE->hStereoDft->buff_LBTCX_mem_fx[0], &hCPE->hStereoDft->buff_LBTCX_mem[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS )); + fixedToFloat_arrL(&hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0], &hCPE->hStereoDft->mixer_mat_smooth[0][0][0], Q31, sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx) / sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0])); + fixedToFloat_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0], &st_ivas->hSpar->hMdDec->mixer_mat_prev[0][0][0][0], Q31, sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx) / sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0])); + fixedToFloat_arrL(&hCPE->hStereoDft->smooth_buf_fx[0][0], &hCPE->hStereoDft->smooth_buf[0][0], hCPE->hStereoDft->q_smooth_buf_fx, sizeof(hCPE->hStereoDft->smooth_buf_fx) / sizeof(hCPE->hStereoDft->smooth_buf_fx[0][0])); + fixedToFloat_arr(&hCPE->hStereoDft->smooth_fac_fx[0][0], &hCPE->hStereoDft->smooth_fac[0][0], Q15, sizeof(hCPE->hStereoDft->smooth_fac_fx) / sizeof(hCPE->hStereoDft->smooth_fac_fx[0][0])); } - } - - ivas_agc_dec_process_fx( st_ivas->hSpar->hAgcDec, ( output_fx ), ( output_fx ), st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); - - FOR( Word16 i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) - { - FOR( Word16 j = 0; j < output_frame; j++ ) + for (int ii = 0; ii < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; ii++) { - p_output[i + sba_ch_idx][j] = (float) output_fx[i][j] / ONE_IN_Q11; + for (int jj = 0; jj < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; jj++) + { + fixedToFloat_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_fx[ii][jj][0], + &st_ivas->hSpar->hMdDec->mixer_mat[ii][jj][0], + Q31, + st_ivas->hSpar->hMdDec->mix_mat_dim_2); + } } + for (int ii = 0; ii < CPE_CHANNELS; ii++) + { + fixedToFloat_arrL(&hCPE->output_mem_fx[ii][0], &hCPE->output_mem[ii][0], hCPE->hStereoDft->q_dft, NS2SA_fx2( st_ivas->hDecoderConfig->output_Fs, STEREO_DFT32MS_OVL_NS )); + } + hCPE->lt_es_em = fixedToFloat(hCPE->lt_es_em_fx, Q15); } - -#ifdef DUMPS_ENABLED - dbgwrite_txt( &p_output[sba_ch_idx][0], output_frame, "fix_ivas_agc_dec_process_output.txt", NULL ); -#endif // DUMPS_ENABLED - - FOR( Word16 i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) - { - free( output_fx[i] ); - } -#endif // !IVAS_FLOAT_FIXED - - if ( st_ivas->hSpar->hPCA != NULL ) - { - ivas_pca_dec( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, &p_output[sba_ch_idx] ); - } - - ivas_spar_dec_gen_umx_mat( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ) ); - - ivas_sba_dirac_stereo_dec( st_ivas, &p_output[sba_ch_idx], output_frame, 0 ); +#endif } /* HP filtering */ @@ -2427,7 +2718,250 @@ ivas_error ivas_jbm_dec_tc( if ( st_ivas->sba_dirac_stereo_flag ) /* use the flag to trigger the DFT upmix */ { +#ifndef IVAS_FLOAT_FIXED ivas_sba_dirac_stereo_dec( st_ivas, p_output, output_frame, 1 ); +#else + { + Word16 q; + float l_hb_nrg = 0.0, l_hb_nrg_subr = 0.0; + static int frame_counter = 0; + if ( frame_counter >= 200 ) + frame_counter = frame_counter; + float max_val = 0.0; + int i_max_val_psd, i_max_val_op; + CPE_DEC_HANDLE hCPE = st_ivas->hCPE[0]; + SCE_DEC_HANDLE hSCE = st_ivas->hSCE[0]; + for ( int ii = 0; ii < sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0] ); ii++ ) + { + if ( max_val < fabs( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[ii] ) ) + { + max_val = (float) fabs( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[ii] ); + } + } + i_max_val_psd = (int) max_val; + for ( int ii = 0; ii < 2; ii++ ) + { + for ( int jj = 0; jj < ( 48000 / FRAMES_PER_SEC ); jj++ ) + { + if ( max_val < fabs( p_output[ii][jj] ) ) + { + max_val = (float) fabs( p_output[ii][jj] ); + } + } + } + i_max_val_op = (int)max_val; + hCPE->hStereoDft->q_dft = norm_l(i_max_val_op) - Q11; + IF(hCPE->hStereoDft->q_dft < 0) + { + hCPE->hStereoDft->q_dft = 0; + } + ELSE IF (hCPE->hStereoDft->q_dft > Q11) + { + hCPE->hStereoDft->q_dft = Q11; + } + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd = norm_l(i_max_val_psd) - Q9; + IF (EQ_16(hCPE->hStereoDft->first_frame, 1)) + { + //hCPE->q_prev_synth_fx = hCPE->hStereoDft->q_dft; + hCPE->hStereoDft->q_smoothed_nrg = Q6;//hCPE->hStereoDft->q_dft; + hCPE->hStereoDft->q_ap_delay_mem_fx = hCPE->hStereoDft->q_dft; + } + + st_ivas->hCPE[0]->hCoreCoder[0]->stab_fac_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->stab_fac, 15); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact, 15); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact_fx = (Word16)floatToFixed(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact, 15); + floatToFixed_arrL(&hCPE->hStereoDft->res_gains_ind[0][0], &hCPE->hStereoDft->res_gains_ind_fx[0][0], Q26, sizeof(hCPE->hStereoDft->res_gains_ind_fx) / sizeof(hCPE->hStereoDft->res_gains_ind_fx[0][0])); + floatToFixed_arrL(&hCPE->hStereoDft->res_pred_gain[0], &hCPE->hStereoDft->res_pred_gain_fx[0], Q31, sizeof(hCPE->hStereoDft->res_pred_gain_fx)/ sizeof(hCPE->hStereoDft->res_pred_gain_fx[0])); + floatToFixed_arrL(&hCPE->hStereoDft->itd[0], &hCPE->hStereoDft->itd_fx[0], Q1, sizeof(hCPE->hStereoDft->itd_fx) / sizeof(hCPE->hStereoDft->itd_fx[0])); + floatToFixed_arrL(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0], st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0])); + floatToFixed_arrL(&hCPE->prev_hb_synth[0][0], &hCPE->prev_hb_synth_fx[0][0], hCPE->hStereoDft->q_dft, sizeof(hCPE->prev_hb_synth_fx) / sizeof(hCPE->prev_hb_synth_fx[0][0])); + for (int ii = 0; ii < sizeof(hCPE->hStereoDft->hb_nrg_subr_fx) / sizeof(hCPE->hStereoDft->hb_nrg_subr_fx[0]); ii++) + { + if ( l_hb_nrg_subr < hCPE->hStereoDft->hb_nrg_subr[ii] ) + { + l_hb_nrg_subr = hCPE->hStereoDft->hb_nrg_subr[ii]; + } + } + hCPE->hStereoDft->q_hb_nrg_subr = 0; + if ( l_hb_nrg_subr > (float) MAX_32 ) + { + int quotient = (int) ceil( l_hb_nrg_subr / (float) MAX_32 ); + hCPE->hStereoDft->q_hb_nrg_subr = Q31 - norm_l( quotient ); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_subr_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_subr_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg_subr_fx[ii] = (Word32) ( hCPE->hStereoDft->hb_nrg_subr[ii] / ( (float) ( 1 << hCPE->hStereoDft->q_hb_nrg_subr ) ) ); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_fx[0] ); ii++ ) + { + if ( l_hb_nrg < hCPE->hStereoDft->hb_nrg[ii] ) + { + l_hb_nrg = hCPE->hStereoDft->hb_nrg[ii]; + } + } + hCPE->hStereoDft->q_hb_nrg = 0; + if ( l_hb_nrg > (float) MAX_32 ) + { + int quotient = (int) ceil( l_hb_nrg / (float) MAX_32 ); + hCPE->hStereoDft->q_hb_nrg = Q31 - norm_l( quotient ); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg_fx[ii] = (Word32)(hCPE->hStereoDft->hb_nrg[ii] * ((float)(1 << hCPE->hStereoDft->q_hb_nrg))); + } + + floatToFixed_arrL( &hCPE->hStereoDft->side_gain[0], &hCPE->hStereoDft->side_gain_fx[0], Q31, sizeof( hCPE->hStereoDft->side_gain_fx ) / sizeof( hCPE->hStereoDft->side_gain_fx[0] ) ); + floatToFixed_arrL( &hCPE->hStereoDft->gipd[0], &hCPE->hStereoDft->gipd_fx[0], Q13, sizeof( hCPE->hStereoDft->gipd_fx ) / sizeof( hCPE->hStereoDft->gipd_fx[0] ) ); + floatToFixed_arr( &hCPE->hStereoDft->g_state[0], &hCPE->hStereoDft->g_state_fx[0], Q15, sizeof( hCPE->hStereoDft->g_state_fx ) / sizeof( hCPE->hStereoDft->g_state_fx[0] ) ); + floatToFixed_arr( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0], Q15, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0] ) ); + IF( hCPE->hStereoCng != NULL ) + { + floatToFixed_arr( &hCPE->hStereoCng->cm[0], &hCPE->hStereoCng->cm_fx[0], Q15, sizeof( hCPE->hStereoCng->cm_fx ) / sizeof( hCPE->hStereoCng->cm_fx[0] ) ); + } + floatToFixed_arr( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0], Q15, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0] ) ); + for ( int ii = 0; ii < 2; ii++ ) + { + floatToFixed_arrL( &p_output[ii][0], &p_output_fix[ii][0], hCPE->hStereoDft->q_dft, ( 48000 / FRAMES_PER_SEC ) ); + } + q = hCPE->hStereoDft->q_dft; + floatToFixed_arrL(&hCPE->input_mem_BPF[0][0], &hCPE->input_mem_BPF_fx[0][0], q, STEREO_DFT32MS_OVL_16k); + floatToFixed_arrL(&hCPE->input_mem[0][0], &hCPE->input_mem_fx[0][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + floatToFixed_arrL(&hCPE->input_mem_LB[0][0], &hCPE->input_mem_LB_fx[0][0], q, STEREO_DFT32MS_OVL_16k); + floatToFixed_arrL(&hCPE->input_mem[1][0], &hCPE->input_mem_fx[1][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + floatToFixed_arrL(&hCPE->input_mem_LB[1][0], &hCPE->input_mem_LB_fx[1][0], q, STEREO_DFT32MS_OVL_16k); + if (hSCE != NULL) + { + floatToFixed_arrL(&hSCE->prev_hb_synth[0], &hSCE->prev_hb_synth_fx[0], hCPE->hStereoDft->q_dft, sizeof(hSCE->prev_hb_synth_fx) / sizeof(hSCE->prev_hb_synth_fx[0])); + hSCE->q_prev_hb_synth_fx = hCPE->hStereoDft->q_dft; + floatToFixed_arrL(&hSCE->save_hb_synth[0], &hSCE->save_hb_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + hSCE->q_save_hb_synth_fx = q; + floatToFixed_arrL(&hSCE->save_synth[0], &hSCE->save_synth_fx[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + hSCE->q_save_synth_fx = q; + } + IF( hCPE->hCoreCoder[0] != NULL ) + { + floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_outLB[0], &hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[0], q, L_FRAME32k); + hCPE->hCoreCoder[0]->hHQ_core->q_old_outLB_fx = q; + floatToFixed_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_out[0], &hCPE->hCoreCoder[0]->hHQ_core->oldOut_fx[0], q, L_FRAME48k); + IF( (hCPE->hCoreCoder[0] != NULL) && (hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL) ) + floatToFixed_arrL(&hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[0], &hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[0], q, L_FRAME16k); + } + IF( hCPE->hStereoDft != NULL ) + { + floatToFixed_arrL(&hCPE->hStereoDft->td_gain[0], &hCPE->hStereoDft->td_gain_fx[0], Q31, sizeof( hCPE->hStereoDft->td_gain_fx ) / sizeof( hCPE->hStereoDft->td_gain_fx[0] ) ); + floatToFixed_arrL(&hCPE->hStereoDft->ap_delay_mem[0], &hCPE->hStereoDft->ap_delay_mem_fx[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS )); + floatToFixed_arrL(&hCPE->hStereoDft->buff_LBTCX_mem[0], &hCPE->hStereoDft->buff_LBTCX_mem_fx[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS )); + floatToFixed_arr(&hCPE->hStereoDft->smooth_fac[0][0], &hCPE->hStereoDft->smooth_fac_fx[0][0], Q15, sizeof(hCPE->hStereoDft->smooth_fac_fx) / sizeof(hCPE->hStereoDft->smooth_fac_fx[0][0])); + hCPE->hStereoDft->q_smooth_buf_fx = Q7; + floatToFixed_arrL(&hCPE->hStereoDft->smooth_buf[0][0], &hCPE->hStereoDft->smooth_buf_fx[0][0], hCPE->hStereoDft->q_smooth_buf_fx, sizeof(hCPE->hStereoDft->smooth_buf_fx) / sizeof(hCPE->hStereoDft->smooth_buf_fx[0][0])); + floatToFixed_arrL(&hCPE->hStereoDft->mixer_mat_smooth[0][0][0], &hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0], Q31, sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx) / sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0])); + } + IF (st_ivas->hSpar != NULL) + { + floatToFixed_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_prev[0][0][0][0], &st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0], Q31, sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx) / sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0])); + for (int ii = 0; ii < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; ii++) + { + for (int jj = 0; jj < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; jj++) + { + floatToFixed_arrL(&st_ivas->hSpar->hMdDec->mixer_mat[ii][jj][0], + &st_ivas->hSpar->hMdDec->mixer_mat_fx[ii][jj][0], + Q31, + st_ivas->hSpar->hMdDec->mix_mat_dim_2); + } + } + } + hCPE->lt_es_em_fx = floatToFixed(hCPE->lt_es_em, Q15); + for (int ii = 0; ii < CPE_CHANNELS; ii++) + { + hCPE->q_output_mem_fx[ii] = hCPE->hStereoDft->q_dft; + floatToFixed_arrL(&hCPE->output_mem[ii][0], &hCPE->output_mem_fx[ii][0], hCPE->hStereoDft->q_dft, NS2SA_fx2( st_ivas->hDecoderConfig->output_Fs, STEREO_DFT32MS_OVL_NS )); + } + floatToFixed_arrL(&hCPE->prev_synth[0][0], &hCPE->prev_synth_fx[0][0], hCPE->q_prev_synth_fx, sizeof(hCPE->prev_synth) / sizeof(hCPE->prev_synth[0][0])); + + ivas_sba_dirac_stereo_dec_fx( st_ivas, p_output_fix, output_frame, 1 ); + + IF (hSCE != NULL) + { + hSCE->hCoreCoder[0]->log_energy_diff_lt = fixedToFloat(hSCE->hCoreCoder[0]->log_energy_diff_lt_fx, Q15); + hSCE->hCoreCoder[0]->stab_fac_smooth_lt = fixedToFloat(hSCE->hCoreCoder[0]->stab_fac_smooth_lt_fx, Q31); + } + fixedToFloat_arrL(&hCPE->prev_synth_fx[0][0], &hCPE->prev_synth[0][0], hCPE->q_prev_synth_fx, sizeof(hCPE->prev_synth) / sizeof(hCPE->prev_synth[0][0])); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact = fixedToFloat( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_rescale_fact_fx, 15 ); + st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact = fixedToFloat( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_act_fact_fx, 15 ); + fixedToFloat_arrL( &hCPE->hStereoDft->res_gains_ind_fx[0][0], &hCPE->hStereoDft->res_gains_ind[0][0], Q26, sizeof( hCPE->hStereoDft->res_gains_ind_fx ) / sizeof( hCPE->hStereoDft->res_gains_ind_fx[0][0] ) ); + fixedToFloat_arrL( &hCPE->hStereoDft->res_pred_gain_fx[0], &hCPE->hStereoDft->res_pred_gain[0], Q31, sizeof( hCPE->hStereoDft->res_pred_gain_fx ) / sizeof( hCPE->hStereoDft->res_pred_gain_fx[0] ) ); + fixedToFloat_arrL( &hCPE->hStereoDft->itd_fx[0], &hCPE->hStereoDft->itd[0], Q1, sizeof( hCPE->hStereoDft->itd_fx ) / sizeof( hCPE->hStereoDft->itd_fx[0] ) ); + fixedToFloat_arrL( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd[0], st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->q_smoothed_psd, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->smoothed_psd_fx[0] ) ); + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_subr_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_subr_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg_subr[ii] = ((float)hCPE->hStereoDft->hb_nrg_subr_fx[ii] / ((float)(1 << hCPE->hStereoDft->q_hb_nrg_subr))); + } + for ( int ii = 0; ii < sizeof( hCPE->hStereoDft->hb_nrg_fx ) / sizeof( hCPE->hStereoDft->hb_nrg_fx[0] ); ii++ ) + { + hCPE->hStereoDft->hb_nrg[ii] = ( (float) hCPE->hStereoDft->hb_nrg_fx[ii] * ( (float) ( 1 << hCPE->hStereoDft->q_hb_nrg ) ) ); + } + fixedToFloat_arrL(&hCPE->hStereoDft->side_gain_fx[0], &hCPE->hStereoDft->side_gain[0], Q31,sizeof(hCPE->hStereoDft->side_gain_fx) / sizeof(hCPE->hStereoDft->side_gain_fx[0])); + fixedToFloat_arrL(&hCPE->hStereoDft->gipd_fx[0], &hCPE->hStereoDft->gipd[0], Q13, sizeof(hCPE->hStereoDft->gipd_fx) / sizeof(hCPE->hStereoDft->gipd_fx[0])); + fixedToFloat_arr(&hCPE->hStereoDft->g_state_fx[0], &hCPE->hStereoDft->g_state[0], Q15, sizeof(hCPE->hStereoDft->g_state_fx) / sizeof(hCPE->hStereoDft->g_state_fx[0])); + fixedToFloat_arr(&st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm[0], Q15, sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx) / sizeof(st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_cm_fx[0])); + fixedToFloat_arrL(&hCPE->prev_hb_synth_fx[0][0], &hCPE->prev_hb_synth[0][0], hCPE->hStereoDft->q_dft, sizeof(hCPE->prev_hb_synth_fx) / sizeof(hCPE->prev_hb_synth_fx[0][0])); + IF (hCPE->hStereoCng != NULL) + { + fixedToFloat_arr( &hCPE->hStereoCng->cm_fx[0], &hCPE->hStereoCng->cm[0], Q15, sizeof( hCPE->hStereoCng->cm_fx ) / sizeof( hCPE->hStereoCng->cm_fx[0] ) ); + } + fixedToFloat_arr( &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0], &st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state[0], Q15, sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx ) / sizeof( st_ivas->hCPE[0]->hCoreCoder[0]->hFdCngDec->cna_g_state_fx[0] ) ); + for ( int ii = 0; ii < 2; ii++ ) + { + fixedToFloat_arrL( &p_output_fix[ii][0], &p_output[ii][0], hCPE->hStereoDft->q_dft, ( 48000 / FRAMES_PER_SEC ) ); + } + fixedToFloat_arrL(&hCPE->input_mem_BPF_fx[0][0], &hCPE->input_mem_BPF[0][0], q, STEREO_DFT32MS_OVL_16k); + fixedToFloat_arrL(&hCPE->input_mem_fx[0][0], &hCPE->input_mem[0][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + fixedToFloat_arrL(&hCPE->input_mem_LB_fx[0][0], &hCPE->input_mem_LB[0][0], q, STEREO_DFT32MS_OVL_16k); + fixedToFloat_arrL(&hCPE->input_mem_fx[1][0], &hCPE->input_mem[1][0], q, NS2SA( hCPE->hCoreCoder[0]->output_Fs, STEREO_DFT32MS_OVL_NS )); + fixedToFloat_arrL(&hCPE->input_mem_LB_fx[1][0], &hCPE->input_mem_LB[1][0], q, STEREO_DFT32MS_OVL_16k); + if (hSCE != NULL) + { + fixedToFloat_arrL(&hSCE->prev_hb_synth_fx[0], &hSCE->prev_hb_synth[0], hCPE->hStereoDft->q_dft, sizeof(hSCE->prev_hb_synth_fx) / sizeof(hSCE->prev_hb_synth_fx[0])); + fixedToFloat_arrL(&hSCE->save_synth_fx[0], &hSCE->save_synth[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + fixedToFloat_arrL(&hSCE->save_hb_synth_fx[0], &hSCE->save_hb_synth[0], q, (Word16)(hCPE->hCoreCoder[0]->output_Fs / FRAMES_PER_SEC)); + } + IF( hCPE->hCoreCoder[0] != NULL ) + { + fixedToFloat_arrL(&hCPE->hCoreCoder[0]->hHQ_core->old_outLB_fx[0], &hCPE->hCoreCoder[0]->hHQ_core->old_outLB[0], q, L_FRAME32k); + fixedToFloat_arrL(&hCPE->hCoreCoder[0]->hHQ_core->oldOut_fx[0], &hCPE->hCoreCoder[0]->hHQ_core->old_out[0], q, L_FRAME48k); + IF( hCPE->hCoreCoder[0]->p_bpf_noise_buf_32 != NULL ) + fixedToFloat_arrL(&hCPE->hCoreCoder[0]->p_bpf_noise_buf_32[0], &hCPE->hCoreCoder[0]->p_bpf_noise_buf_float[0], q, L_FRAME16k); + } + IF( hCPE->hStereoDft != NULL ) + { + fixedToFloat_arrL( &hCPE->hStereoDft->td_gain_fx[0], &hCPE->hStereoDft->td_gain[0], Q31, sizeof( hCPE->hStereoDft->td_gain_fx ) / sizeof( hCPE->hStereoDft->td_gain_fx[0] ) ); + fixedToFloat_arrL(&hCPE->hStereoDft->ap_delay_mem_fx[0], &hCPE->hStereoDft->ap_delay_mem[0], q, NS2SA( 16000, DELAY_BWE_TOTAL_NS )); + fixedToFloat_arrL(&hCPE->hStereoDft->buff_LBTCX_mem_fx[0], &hCPE->hStereoDft->buff_LBTCX_mem[0], q, NS2SA( 16000, STEREO_DFT32MS_OVL_NS )); + fixedToFloat_arrL(&hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0], &hCPE->hStereoDft->mixer_mat_smooth[0][0][0], Q31, sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx) / sizeof(hCPE->hStereoDft->mixer_mat_smooth_fx[0][0][0])); + fixedToFloat_arrL(&hCPE->hStereoDft->smooth_buf_fx[0][0], &hCPE->hStereoDft->smooth_buf[0][0], hCPE->hStereoDft->q_smooth_buf_fx, sizeof(hCPE->hStereoDft->smooth_buf_fx) / sizeof(hCPE->hStereoDft->smooth_buf_fx[0][0])); + fixedToFloat_arr(&hCPE->hStereoDft->smooth_fac_fx[0][0], &hCPE->hStereoDft->smooth_fac[0][0], Q15, sizeof(hCPE->hStereoDft->smooth_fac_fx) / sizeof(hCPE->hStereoDft->smooth_fac_fx[0][0])); + } + IF (st_ivas->hSpar != NULL) + { + fixedToFloat_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0], &st_ivas->hSpar->hMdDec->mixer_mat_prev[0][0][0][0], Q31, sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx) / sizeof(st_ivas->hSpar->hMdDec->mixer_mat_prev_fx[0][0][0][0])); + for (int ii = 0; ii < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; ii++) + { + for (int jj = 0; jj < st_ivas->hSpar->hMdDec->mix_mat_dim_0_1; jj++) + { + fixedToFloat_arrL(&st_ivas->hSpar->hMdDec->mixer_mat_fx[ii][jj][0], + &st_ivas->hSpar->hMdDec->mixer_mat[ii][jj][0], + Q31, + st_ivas->hSpar->hMdDec->mix_mat_dim_2); + } + } + } + for (int ii = 0; ii < CPE_CHANNELS; ii++) + { + fixedToFloat_arrL(&hCPE->output_mem_fx[ii][0], &hCPE->output_mem[ii][0], hCPE->hStereoDft->q_dft, NS2SA_fx2( st_ivas->hDecoderConfig->output_Fs, STEREO_DFT32MS_OVL_NS )); + } + hCPE->lt_es_em = fixedToFloat(hCPE->lt_es_em_fx, Q15); + } +#endif } /* HP filtering */ diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index 9dc355a7d..9ffdfdd7e 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -554,7 +554,7 @@ ivas_error ivas_omasa_dec_config( * * set bit-rate surplus in combined format coding *--------------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void ivas_set_surplus_brate_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ int32_t *ism_total_brate /* i/o: ISM total bitrate */ @@ -630,6 +630,105 @@ void ivas_set_surplus_brate_dec( return; } +#else +void ivas_set_surplus_brate_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + Word32 *ism_total_brate /* i/o: ISM total bitrate */ +) +{ + Word16 n, bits_ism, bits_element[MAX_NUM_OBJECTS]; + Word32 ism_total_brate_ref, element_brate[MAX_NUM_OBJECTS]; + + *ism_total_brate = 0; + move32(); + + test(); + IF ( EQ_32(st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ) || EQ_32(st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ) ) + { + *ism_total_brate = ivas_interformat_brate( st_ivas->ism_mode, 1, st_ivas->hSCE[0]->element_brate, st_ivas->hIsmMetaData[0]->ism_imp, 0 ); + + st_ivas->hCPE[0]->brate_surplus = L_sub(st_ivas->hSCE[0]->element_brate, *ism_total_brate); + + /* set 'st->total_brate'; there are no meta-data in ISM_MASA_MODE_PARAM_ONE_OBJ mode */ + st_ivas->hSCE[0]->hCoreCoder[0]->total_brate = *ism_total_brate; + move32(); + + st_ivas->hSCE[0]->hCoreCoder[0]->low_rate_mode = 0; + move16(); + IF ( EQ_16( st_ivas->hIsmMetaData[0]->ism_imp, ISM_NO_META ) ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->low_rate_mode = 1; + move16(); + } + } + ELSE IF ( EQ_32(st_ivas->ism_mode, ISM_MASA_MODE_DISC) ) + { + Word16 brate_limit_flag, ism_imp[MAX_NUM_OBJECTS], tmp; + + FOR ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + ism_imp[n] = st_ivas->hIsmMetaData[n]->ism_imp; + move16(); + } + + brate_limit_flag = calculate_brate_limit_flag( ism_imp, st_ivas->nchan_ism ); + move16(); + + ism_total_brate_ref = 0; + move32(); + FOR ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + ism_total_brate_ref = L_add(ism_total_brate_ref, st_ivas->hSCE[n]->element_brate); + } + + bits_ism = BASOP_Util_Divide3216_Scale( ism_total_brate_ref, FRAMES_PER_SEC, &tmp ); + bits_ism = shr(bits_ism, negate(add(tmp,1))); // bring down to Q0. + + tmp = 0; + move16(); + IF(bits_ism != 0) + { + tmp = idiv1616(bits_ism, st_ivas->nchan_ism); + } + set16_fx( bits_element, tmp, st_ivas->nchan_ism ); + bits_element[st_ivas->nchan_ism - 1] = add(bits_element[st_ivas->nchan_ism - 1], bits_ism % st_ivas->nchan_ism); + move16(); + bitbudget_to_brate( bits_element, element_brate, st_ivas->nchan_ism ); + + *ism_total_brate = 0; + move32(); + FOR ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + st_ivas->hSCE[n]->element_brate = element_brate[n]; + move32(); + + *ism_total_brate = L_add(*ism_total_brate, ivas_interformat_brate( ISM_MASA_MODE_DISC, st_ivas->nchan_ism, st_ivas->hSCE[n]->element_brate, st_ivas->hIsmMetaData[n]->ism_imp, brate_limit_flag ) ); + + test(); test(); + IF ( GT_16( ism_imp[n], 1 ) && EQ_16( st_ivas->flag_omasa_brate, 1 ) && brate_limit_flag >= 0 ) + { + *ism_total_brate = L_sub(*ism_total_brate, ADJUST_ISM_BRATE_NEG); + } + + test(); test(); + IF ( EQ_16( brate_limit_flag, -1 ) && GE_16( ism_imp[n], 1 ) && GE_16( st_ivas->nchan_ism, 3 ) && GT_32( L_sub( ism_total_brate_ref, *ism_total_brate ), IVAS_48k ) ) + { + *ism_total_brate = L_add(*ism_total_brate, ADJUST_ISM_BRATE_POS); + } + } + st_ivas->hCPE[0]->brate_surplus = L_sub( ism_total_brate_ref, *ism_total_brate ); + + /* 'st->total_brate' is set in ivas_ism_config */ + } + ELSE + { + st_ivas->hCPE[0]->brate_surplus = 0; + move32(); + } + + return; +} +#endif /*--------------------------------------------------------------------------* @@ -709,6 +808,98 @@ ivas_error ivas_omasa_ism_metadata_dec( return IVAS_ERR_OK; } +/*--------------------------------------------------------------------------* + * ivas_omasa_ism_metadata_dec_fx() + * + * decode ISM metadata in OMASA format + *--------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +ivas_error ivas_omasa_ism_metadata_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word32 ism_total_brate, /* i : ISM total bitrate */ + Word16 *nchan_ism, /* o : number of ISM separated channels */ + Word16 *nchan_transport_ism, /* o : number of ISM TCs */ + const Word16 dirac_bs_md_write_idx, /* i : DirAC bitstream write index */ + Word16 nb_bits_metadata[] /* o : number of ISM metadata bits */ +) +{ + Word16 n, block; + Word16 azimuth_ism, elevation_ism, meta_write_index; + ivas_error error; + + /* set ISM parameters */ + *nchan_ism = st_ivas->nchan_ism; + move16(); + *nchan_transport_ism = st_ivas->nchan_ism; + move16(); + IF ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + *nchan_ism = 1; + move16(); + *nchan_transport_ism = 1; + move16(); + } + ELSE IF ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { + *nchan_ism = 0; + move16(); + *nchan_transport_ism = 1; + move16(); + } + + test(); + IF ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + /* decode ISM metadata */ + IF( ( error = ivas_ism_metadata_dec_fx( ism_total_brate, *nchan_ism, nchan_transport_ism, st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, + nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt, st_ivas->hSCE[0]->hCoreCoder[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + IF ( st_ivas->hDirAC != NULL ) + { + IF ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + FOR ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + //azimuth_ism = (int16_t) ( st_ivas->hIsmMetaData[n]->azimuth + 0.5f ); + //elevation_ism = (int16_t) ( st_ivas->hIsmMetaData[n]->elevation + 0.5f ); + azimuth_ism = extract_l(L_shr(L_add(st_ivas->hIsmMetaData[n]->azimuth_fx, ONE_IN_Q21), 21) / 2); // using "/ 2" here because it rounds towards 0, whereas L_shr rounds towards -inf + elevation_ism = extract_l(L_shr(L_add(st_ivas->hIsmMetaData[n]->elevation_fx, ONE_IN_Q21), 21)/ 2); + + FOR ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + meta_write_index = ( add( dirac_bs_md_write_idx, block ) ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length; + move16(); + st_ivas->hMasaIsmData->azimuth_ism[n][meta_write_index] = azimuth_ism; + move16(); + st_ivas->hMasaIsmData->elevation_ism[n][meta_write_index] = elevation_ism; + move16(); + } + } + } + ELSE /* ISM_MASA_MODE_MASA_ONE_OBJ */ + { + azimuth_ism = extract_l(L_shr(L_add(st_ivas->hIsmMetaData[0]->azimuth_fx, ONE_IN_Q21), 21) / 2); // using "/ 2" here because it rounds towards 0, whereas L_shr rounds towards -inf + elevation_ism = extract_l(L_shr(L_add(st_ivas->hIsmMetaData[0]->elevation_fx, ONE_IN_Q21), 21) / 2); + + FOR ( block = 0; block < MAX_PARAM_SPATIAL_SUBFRAMES; block++ ) + { + meta_write_index = ( add( dirac_bs_md_write_idx, block ) ) % st_ivas->hSpatParamRendCom->dirac_md_buffer_length; + move16(); + st_ivas->hMasaIsmData->azimuth_separated_ism[meta_write_index] = azimuth_ism; + move16(); + st_ivas->hMasaIsmData->elevation_separated_ism[meta_write_index] = elevation_ism; + move16(); + } + } + } + } + + return IVAS_ERR_OK; +} +#endif /*--------------------------------------------------------------------------* * ivas_omasa_dirac_rend_jbm() @@ -1012,3 +1203,27 @@ void ivas_omasa_rearrange_channels( return; } + +#ifdef IVAS_FLOAT_FIXED +void ivas_omasa_rearrange_channels_fx( + Word32 *output[], /* o : output synthesis signal */ + const Word16 nchan_transport_ism, /* o : number of ISM TCs */ + const Word16 output_frame /* i : output frame length per channel */ +) +{ + Word16 n; + Word32 tmp_buff[CPE_CHANNELS][L_FRAME48k]; + + Copy32( output[0], tmp_buff[0], output_frame ); + Copy32( output[1], tmp_buff[1], output_frame ); + + FOR ( n = 0; n < nchan_transport_ism; n++ ) + { + Copy32( output[CPE_CHANNELS + n], output[n], output_frame ); + } + Copy32( tmp_buff[0], output[n], output_frame ); + Copy32( tmp_buff[1], output[n + 1], output_frame ); + + return; +} +#endif \ No newline at end of file diff --git a/lib_dec/ivas_post_proc.c b/lib_dec/ivas_post_proc.c index 177f86ceb..5e61a16e7 100644 --- a/lib_dec/ivas_post_proc.c +++ b/lib_dec/ivas_post_proc.c @@ -598,6 +598,7 @@ void stereo_dft_dec_core_switching_fx( Word32 tmp_fade_fx[max( STEREO_DFT_ALLPASS_FADELEN_12k8, STEREO_DFT_ALLPASS_FADELEN_16k )]; Copy32( st->hHQ_core->old_outLB_fx + numZeros, hCPE->hStereoDft->ap_fade_mem_fx, ap_fade_len ); + hCPE->hStereoDft->q_ap_fade_mem_fx = st->hHQ_core->q_old_outLB_fx; IF( st->last_core == ACELP_CORE && !( st->prev_bfi == 1 && st->last_core == ACELP_CORE && st->last_con_tcx == 1 ) && !st->tcxonly ) { @@ -625,11 +626,12 @@ void stereo_dft_dec_core_switching_fx( Copy32( output_fx, pAp_input_fx, st->L_frame ); IF( st->last_core != ACELP_CORE ) /* TCX/HQ-Core -> ACELP */ { + Word16 shift = sub(hCPE->hStereoDft->q_ap_fade_mem_fx, q_DFT[0]); FOR( i = 0; i < ap_fade_len; i++ ) { pAp_input_fx[i] = L_add( Mpy_32_32( pAp_input_fx[i], i * ( 1 << qap_fade_len ) ), - Mpy_32_32( hCPE->hStereoDft->ap_fade_mem_fx[i], ap_fade_len_fx - i * ( 1 << qap_fade_len ) ) ); + Mpy_32_32( L_shr(hCPE->hStereoDft->ap_fade_mem_fx[i], shift), ap_fade_len_fx - i * ( 1 << qap_fade_len ) ) ); pAp_input_fx[i] = L_shl( Mpy_32_32( pAp_input_fx[i], ap_fade_len_inv ), 31 - qap_fade_len ); } } @@ -669,9 +671,9 @@ void stereo_dft_dec_core_switching_fx( } /* apply 5-stage allpass, each stage consisting of a nested allpass pair */ - filter_with_allpass_fx( pAp_input_fx, pAp_input_fx, st->L_frame, &hCPE->hStereoDft->ap1, sub(hCPE->hStereoDft->q_ap_delay_mem_fx , *q) ); - filter_with_allpass_fx( pAp_input_fx, pAp_input_fx, st->L_frame, &hCPE->hStereoDft->ap2, sub(hCPE->hStereoDft->q_ap_delay_mem_fx , *q) ); - filter_with_allpass_fx( pAp_input_fx, pAp_input_fx, st->L_frame, &hCPE->hStereoDft->ap3, sub(hCPE->hStereoDft->q_ap_delay_mem_fx , *q) ); + filter_with_allpass_fx( pAp_input_fx, pAp_input_fx, st->L_frame, &hCPE->hStereoDft->ap1, *q ); + filter_with_allpass_fx( pAp_input_fx, pAp_input_fx, st->L_frame, &hCPE->hStereoDft->ap2, *q ); + filter_with_allpass_fx( pAp_input_fx, pAp_input_fx, st->L_frame, &hCPE->hStereoDft->ap3, *q ); /* apply DFT to allpass-filtered signal */ stereo_dft_dec_analyze_fx( hCPE, pAp_input_fx, DFT_fx, 1, st->L_frame, output_frame, DFT_STEREO_DEC_ANA_FB, 0, 0, q, q_DFT ); diff --git a/lib_dec/ivas_qmetadata_dec.c b/lib_dec/ivas_qmetadata_dec.c index d751de8c2..c0a73c12d 100644 --- a/lib_dec/ivas_qmetadata_dec.c +++ b/lib_dec/ivas_qmetadata_dec.c @@ -325,7 +325,7 @@ Word16 ivas_qmetadata_dec_decode( index_dirRatio1Inv = hQMetaData->q_direction[0].band_data[b].energy_ratio_index[0]; index_dirRatio2Inv = hQMetaData->q_direction[1].band_data[dir2band].energy_ratio_index[0]; - masa_compensate_two_dir_energy_ratio_index( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); + masa_compensate_two_dir_energy_ratio_index_fx( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); FOR( m = 0; m < hQMetaData->q_direction[0].cfg.nblocks; m++ ) { @@ -562,7 +562,7 @@ Word16 ivas_qmetadata_dec_decode( reduce_bits = bits_dir_raw - nbands * nblocks; } } - only_reduce_bits_direction( &dummy, q_direction, reduce_bits, nbands, nblocks, ind_order ); + only_reduce_bits_direction_fx( &dummy, q_direction, reduce_bits, nbands, nblocks, ind_order ); /* Read directions */ bits_dir = read_directions_fx( q_direction, (UWord8) nbands, (UWord8) nblocks, bitstream, index, ind_order ); diff --git a/lib_dec/ivas_sba_dirac_stereo_dec.c b/lib_dec/ivas_sba_dirac_stereo_dec.c index 4781d50bf..1ddff43a4 100644 --- a/lib_dec/ivas_sba_dirac_stereo_dec.c +++ b/lib_dec/ivas_sba_dirac_stereo_dec.c @@ -115,7 +115,6 @@ void ivas_sba_dirac_stereo_config( return; } -#endif /*-------------------------------------------------------------------* @@ -1058,3 +1057,5 @@ void ivas_sba_dirac_stereo_dec( return; } + +#endif \ No newline at end of file diff --git a/lib_dec/ivas_sba_dirac_stereo_dec_fx.c b/lib_dec/ivas_sba_dirac_stereo_dec_fx.c index c8dc50699..aefa51ac7 100644 --- a/lib_dec/ivas_sba_dirac_stereo_dec_fx.c +++ b/lib_dec/ivas_sba_dirac_stereo_dec_fx.c @@ -336,7 +336,8 @@ static void map_params_dirac_to_stereo( Word32 DFT[STEREO_DFT_BUF_MAX], /* i/o: DFT buffer */ const UWord8 b_wide_panning, /* i : flag indicating wider panning */ const Word16 L_frame, /* i : core signal length */ - const Word16 mcmasa /* i : McMASA flag */ + const Word16 mcmasa, /* i : McMASA flag */ + const Word16 q_synth ) { Word16 i, b, k; @@ -350,7 +351,7 @@ static void map_params_dirac_to_stereo( Word32 block_nrg[MAX_PARAM_SPATIAL_SUBFRAMES]; Word32 nrg_norm1, nrg_norm2; Word32 *pSynth; - Word32 surrCoh[SBA_DIRAC_STEREO_NUM_BANDS]; + Word16 surrCoh[SBA_DIRAC_STEREO_NUM_BANDS]; Word32 *pDFT; Word32 subframe_band_nrg[NB_DIV][SBA_DIRAC_STEREO_NUM_BANDS]; Word16 q_nrg; @@ -394,9 +395,9 @@ static void map_params_dirac_to_stereo( q_nrg = sub(Q31, sub(shl(hStereoDft->q_dft, 1) , Q31)); subframe_band_nrg[k][b] = Sqrt32( subframe_band_nrg[k][b], &q_nrg ); move32(); - IF (NE_16(q_nrg , sub(Q31, hStereoDft->q_smooth_buf_fx))) + IF (NE_16(sub(Q31, q_nrg) , hStereoDft->q_smooth_buf_fx)) { - subframe_band_nrg[k][b] = L_shl(subframe_band_nrg[k][b], sub(q_nrg, sub(Q31, hStereoDft->q_smooth_buf_fx))); + subframe_band_nrg[k][b] = L_shl(subframe_band_nrg[k][b], sub(hStereoDft->q_smooth_buf_fx, sub(Q31, q_nrg))); } hStereoDft->smooth_buf_fx[b][NB_DIV - 1 - k] = subframe_band_nrg[k][b]; move32(); @@ -477,6 +478,7 @@ static void map_params_dirac_to_stereo( IF ( mcmasa ) { + Word16 q_div1; /* calculate block energies for side gain weighting (combine angles of 2 DirAC blocks to side gain for 1 DFT Stereo subframe; 4 blocks and 2 subframes overall) */ pSynth = synth; block_len = idiv1616(L_frame , nBlocks); @@ -489,35 +491,55 @@ static void map_params_dirac_to_stereo( block_nrg[block] = Madd_32_32(block_nrg[block], pSynth[i] , pSynth[i]); move32(); } - q_nrg = sub(Q31, sub(shl(hStereoDft->q_dft, 1) , Q31)); + q_nrg = sub(Q31, sub(shl(q_synth, 1) , Q31)); block_nrg[block] = Sqrt32( block_nrg[block], &q_nrg); move32(); - IF (NE_16(q_nrg , sub(Q31, hStereoDft->q_dft))) + IF (NE_16(sub(Q31, q_nrg) , q_synth)) { - block_nrg[block] = L_shl(block_nrg[block], sub(q_nrg, sub(Q31, hStereoDft->q_dft))); + block_nrg[block] = L_shl(block_nrg[block], sub(q_synth, sub(Q31, q_nrg))); move32(); } pSynth += block_len; } - nrg_norm1 = L_deposit_l(BASOP_Util_Divide3232_Scale(MAX_32, L_add(block_nrg[0] , L_add(block_nrg[1] , EPSILON_FIX) ), &q_div)); - IF (NE_16(q_div, 0)) +#if 0 + /* + * block_nrg array's q-format will be q_synth at this point in the control flow. + * So unity used for division numerator should also be in the same Q - q_synth. + */ + nrg_norm1 = L_deposit_l(BASOP_Util_Divide3232_Scale(L_shl(1, q_synth), L_add(block_nrg[0] , L_add(block_nrg[1] , EPSILON_FIX) ), &q_div1)); + IF (NE_16(q_div1, 0) && NE_32(block_nrg[0], 0) && NE_32(block_nrg[1], 0)) { - assert(0); + /* + nrg_norm1 obtained in the previous step will be in Q15 - q_div1 format. + Below step converts and stores nrg_norm1 in Q31 format. + */ + nrg_norm1 = L_shl(nrg_norm1, add(Q16, q_div1)); + q_div1 = 0; } - nrg_norm2 = L_deposit_l(BASOP_Util_Divide3232_Scale(MAX_32, L_add(block_nrg[2] , L_add(block_nrg[3] , EPSILON_FIX) ), &q_div)); - IF (NE_16(q_div, 0)) + + nrg_norm2 = L_deposit_l(BASOP_Util_Divide3232_Scale(L_shl(1, q_synth), L_add(block_nrg[2] , L_add(block_nrg[3] , EPSILON_FIX) ), &q_div2)); + IF (NE_16(q_div2, 0) && NE_32(block_nrg[2], 0) && NE_32(block_nrg[3], 0)) { - assert(0); + /* + nrg_norm2 obtained in the previous step will be in Q15 - q_div2 format. + Below step converts and stores nrg_norm2 in Q31 format. + */ + nrg_norm2 = L_shl(nrg_norm2, add(Q16, q_div2)); + q_div2 = 0; } +#else + nrg_norm1 = L_add(block_nrg[0] , L_add(block_nrg[1] , EPSILON_FIX)); + nrg_norm2 = L_add(block_nrg[2] , L_add(block_nrg[3] , EPSILON_FIX)); +#endif /* extract DirAC parameters from metadata */ FOR ( b = 0; b < nbands; b++ ) { - diffuseness[b] = L_sub(MAX_32 , q_direction->band_data[b].energy_ratio_fx[0]); + diffuseness[b] = L_shl(L_sub(ONE_IN_Q30 , q_direction->band_data[b].energy_ratio_fx[0]), 1); move32(); IF ( hQMetaData->surcoh_band_data != NULL ) { - surrCoh[b] = L_shr(Mpy_32_16_1(hQMetaData->surcoh_band_data[b].surround_coherence[0], (Word16)0x0101), 1); + surrCoh[b] = extract_h(imult3216((Word32)0x00808080, hQMetaData->surcoh_band_data[b].surround_coherence[0])); move32(); } ELSE @@ -542,12 +564,17 @@ static void map_params_dirac_to_stereo( } IF ( LT_32(q_direction->band_data[b].azimuth_fx[block_metadata], 0) ) { - q_direction->band_data[b].azimuth_fx[block_metadata] = L_add(360, q_direction->band_data[b].azimuth_fx[block_metadata]); + q_direction->band_data[b].azimuth_fx[block_metadata] = L_add((Word32)0x5A000000, q_direction->band_data[b].azimuth_fx[block_metadata]); move16(); } - azimuth[block][b] = (Word16)q_direction->band_data[b].azimuth_fx[block_metadata]; + /* + * Converting Azimuth and elevation to Q0 as the ensuing blocks expect them in Q0. + * Before converting rounding is done. + */ + + azimuth[block][b] = extract_l(L_shr(L_add(q_direction->band_data[b].azimuth_fx[block_metadata], ONE_IN_Q21), Q22)); move16(); - elevation[block][b] = (Word16)q_direction->band_data[b].elevation_fx[block_metadata]; + elevation[block][b] = extract_l(L_shr(L_add(q_direction->band_data[b].elevation_fx[block_metadata], ONE_IN_Q21), Q22)); move16(); } } @@ -560,6 +587,7 @@ static void map_params_dirac_to_stereo( move32(); FOR ( block = 0; block < shr(nBlocks , 1); block++ ) { +#if 0 IF ( EQ_16(b_wide_panning, 1) ) { /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ @@ -571,6 +599,34 @@ static void map_params_dirac_to_stereo( side_gain[b] = Madd_32_32(side_gain[b], nrg_norm1, Mpy_32_16_1(block_nrg[block] , mult(ptr_sin_az[azimuth[block][b]] , ptr_cos_el[elevation[block][b]]))); move32(); } +#else + /* + * The floating point version of the code computes + * nrg_norm1 = 1 / (block_nrg[0] + block_nrg[1]); and then computes + * block_nrg[0] * nrg_norm1; which effectively is block_nrg[0] / (block_nrg[0] + block_nrg[1]); + */ + IF ( EQ_16(b_wide_panning, 1) ) + { + Word32 temp = L_mult(BASOP_Util_Divide3232_Scale(block_nrg[block], nrg_norm1, &q_div1) , get_panning( azimuth[block][b], elevation[block][b])); + IF (NE_16(q_div1, 0)) + { + temp = L_shl_sat(temp, q_div1); + } + /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ + side_gain[b] = L_add_sat(side_gain[b], temp); + move32(); + } + ELSE + { + Word32 temp = L_mult(BASOP_Util_Divide3232_Scale(block_nrg[block], nrg_norm1, &q_div1) , mult(ptr_sin_az[azimuth[block][b]] , ptr_cos_el[elevation[block][b]])); + IF (NE_16(q_div1, 0)) + { + temp = L_shl_sat(temp, q_div1); + } + side_gain[b] = L_add_sat(side_gain[b], temp); + move32(); + } +#endif } /* combine angles of last 2 blocks to side gain of second subframe */ @@ -578,6 +634,7 @@ static void map_params_dirac_to_stereo( move32(); FOR ( block = shr(nBlocks , 1); block < nBlocks; block++ ) { +#if 0 IF ( EQ_16(b_wide_panning, 1) ) { /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ @@ -589,23 +646,48 @@ static void map_params_dirac_to_stereo( side_gain[b + STEREO_DFT_BAND_MAX] = Madd_32_32(side_gain[b + STEREO_DFT_BAND_MAX], nrg_norm2 , Mpy_32_16_1(block_nrg[block] , mult( ptr_sin_az[azimuth[block][b]] , ptr_cos_el[elevation[block][b]]))); move32(); } +#else + IF ( EQ_16(b_wide_panning, 1) ) + { + Word32 temp = L_mult(BASOP_Util_Divide3232_Scale(block_nrg[block], nrg_norm2, &q_div1) , get_panning( azimuth[block][b], elevation[block][b])); + IF (NE_16(q_div1, 0)) + { + temp = L_shl_sat(temp, q_div1); + } + /* panning between left and ride, saturate at the stereo ls positions (+/- 30deg azi) */ + side_gain[b + STEREO_DFT_BAND_MAX] = L_add_sat(side_gain[b + STEREO_DFT_BAND_MAX], temp); + move32(); + } + ELSE + { + Word32 temp = L_mult(BASOP_Util_Divide3232_Scale(block_nrg[block], nrg_norm2, &q_div1) , mult(ptr_sin_az[azimuth[block][b]] , ptr_cos_el[elevation[block][b]])); + IF (NE_16(q_div1, 0)) + { + temp = L_shl_sat(temp, q_div1); + } + side_gain[b + STEREO_DFT_BAND_MAX] = L_add_sat(side_gain[b + STEREO_DFT_BAND_MAX], temp); + move32(); + } +#endif } - + q_sqrt = 0; side_gain[b] = Mpy_32_32(side_gain[b], Sqrt32(L_sub(MAX_32, diffuseness[b]), &q_sqrt)); move32(); IF (NE_16(q_sqrt, 0)) { side_gain[b] = L_shl(side_gain[b], q_sqrt); + q_sqrt = 0; } - side_gain[b + STEREO_DFT_BAND_MAX] = Mpy_32_32(side_gain[b + STEREO_DFT_BAND_MAX], Sqrt32(L_sub((Word32)0x7FFFFFFF, diffuseness[b]), &q_sqrt)); + side_gain[b + STEREO_DFT_BAND_MAX] = Mpy_32_32(side_gain[b + STEREO_DFT_BAND_MAX], Sqrt32(L_sub(MAX_32, diffuseness[b]), &q_sqrt)); move32(); IF (NE_16(q_sqrt, 0)) { side_gain[b + STEREO_DFT_BAND_MAX] = L_shl(side_gain[b], q_sqrt); + q_sqrt = 0; } - res_pred_gain[b] = Mpy_32_32(diffuseness[b], L_sub((Word32)0x7FFFFFFF, surrCoh[b] )); + res_pred_gain[b] = Mpy_32_16_1(diffuseness[b], sub(MAX_16, surrCoh[b] )); move32(); - res_pred_gain[b + STEREO_DFT_BAND_MAX] = Mpy_32_32(diffuseness[b], L_sub((Word32)0x7FFFFFFF, surrCoh[b]) ); + res_pred_gain[b + STEREO_DFT_BAND_MAX] = Mpy_32_16_1(diffuseness[b], sub(MAX_16, surrCoh[b]) ); move32(); } } @@ -632,7 +714,8 @@ static void ivas_sba_dirac_stereo_compute_td_stefi_nrgs( const Word32 hb_synth[L_FRAME48k], /* i : HB signal */ const Word16 core, /* i : core decision */ const Word16 output_frame, /* i : output frame length per channel */ - const Word16 fd_cng_flag /* i : FD-CNG indicator */ + const Word16 fd_cng_flag, /* i : FD-CNG indicator */ + const Word16 q_hb_synth ) { Word16 i; @@ -661,15 +744,32 @@ static void ivas_sba_dirac_stereo_compute_td_stefi_nrgs( move32(); hb_nrg = L_add(hb_nrg, hb_nrg2); - Copy32( hb_synth, hStereoDft->hb_stefi_sig_fx + hStereoDft->hb_stefi_delay, output_frame ); + IF (EQ_16(hStereoDft->q_hb_stefi_sig_fx, q_hb_synth)) + { + Copy32( hb_synth, hStereoDft->hb_stefi_sig_fx + hStereoDft->hb_stefi_delay, output_frame ); + } + ELSE + { + IF (GT_16(hStereoDft->q_hb_stefi_sig_fx, q_hb_synth)) + { + v_shr(hStereoDft->hb_stefi_sig_fx, sub(hStereoDft->q_hb_stefi_sig_fx, q_hb_synth), hStereoDft->hb_stefi_sig_fx, sizeof(hStereoDft->hb_stefi_sig_fx) / sizeof(hStereoDft->hb_stefi_sig_fx[0])); + hStereoDft->q_hb_stefi_sig_fx = q_hb_synth; + Copy32( hb_synth, hStereoDft->hb_stefi_sig_fx + hStereoDft->hb_stefi_delay, output_frame ); + } + ELSE + { + v_shr(hb_synth, sub(q_hb_synth, hStereoDft->q_hb_stefi_sig_fx), hStereoDft->hb_stefi_sig_fx + hStereoDft->hb_stefi_delay, output_frame); + } + + } } ELSE { set_val_Word32( hStereoDft->hb_stefi_sig_fx + hStereoDft->hb_stefi_delay, 0, output_frame); } - hStereoDft->hb_nrg_subr_fx[0] = (hStereoDft->hb_nrg_subr_fx[0] * shr(hStereoDft->NFFT, 1)); + hStereoDft->hb_nrg_subr_fx[0] = hStereoDft->hb_nrg_subr_fx[0]; //imult3216(hStereoDft->hb_nrg_subr_fx[0] , shr(hStereoDft->NFFT, 1)); move32(); - hStereoDft->hb_nrg_subr_fx[1] = (hStereoDft->hb_nrg_subr_fx[1] * shr(hStereoDft->NFFT, 1)); + hStereoDft->hb_nrg_subr_fx[1] = hStereoDft->hb_nrg_subr_fx[1]; //imult3216(hStereoDft->hb_nrg_subr_fx[1] , shr(hStereoDft->NFFT, 1)); move32(); hStereoDft->hb_nrg_fx[0] = hb_nrg; move32(); @@ -921,7 +1021,6 @@ static void ivas_sba_dirac_stereo_apply_td_stefi( g_L = L_sub( L_add(g_W_1 , g_W_2) , L_add(g_Y_1 , g_Y_2) ); /* 0x147B = 0.16 in Q15 */ g_R = L_add( L_add(g_W_1 , g_W_2) , L_add(g_Y_1 , g_Y_2) ); /* 0x147B = 0.16 in Q15 */ - FOR ( i = 0; i < dftOvlLen; i++ ) { win_in = mult_r(win_dft[STEREO_DFT32MS_STEP * i], win_dft[STEREO_DFT32MS_STEP * i]); @@ -930,9 +1029,9 @@ static void ivas_sba_dirac_stereo_apply_td_stefi( stefi_L = L_shr(Mpy_32_32( Madd_32_16(Mpy_32_32(win_out , hStereoDft->g_L_prev_fx) , g_L , win_in ) , hStereoDft->hb_stefi_sig_fx[i]), 1); stefi_R = L_shr(Mpy_32_32( Madd_32_16(Mpy_32_32(win_out , hStereoDft->g_R_prev_fx) , g_R , win_in ) , hStereoDft->hb_stefi_sig_fx[i]), 1); - output[0][i] = L_add(output[0][i], stefi_L); + output[0][i] = L_add(output[0][i], L_shr(stefi_L, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); - output[1][i] = L_add(output[1][i], stefi_R); + output[1][i] = L_add(output[1][i], L_shr(stefi_R, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); } FOR ( i = dftOvlLen; i < output_frame; i++ ) @@ -941,9 +1040,9 @@ static void ivas_sba_dirac_stereo_apply_td_stefi( stefi_L = L_shr(Mpy_32_32(g_L , hStereoDft->hb_stefi_sig_fx[i]), 1); stefi_R = L_shr(Mpy_32_32(g_R , hStereoDft->hb_stefi_sig_fx[i]), 1); - output[0][i] = L_add(output[0][i], stefi_L); + output[0][i] = L_add(output[0][i], L_shr(stefi_L, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); - output[1][i] = L_add(output[1][i], stefi_R); + output[1][i] = L_add(output[1][i], L_shr(stefi_R, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); } hStereoDft->g_L_prev_fx = g_L; @@ -962,17 +1061,17 @@ static void ivas_sba_dirac_stereo_apply_td_stefi( win_out = sub(MAX_16 , win_in); tmp = L_shr(Mpy_32_32(Madd_32_16(Mpy_32_16_1(hStereoDft->td_gain_fx[0], win_in) , hStereoDft->td_gain_fx[1] , win_out) , hStereoDft->hb_stefi_sig_fx[i]), 1); - output[0][i] = L_add(output[0][i], tmp); + output[0][i] = L_add(output[0][i], L_shr(tmp, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); - output[1][i] = L_sub(output[1][i], tmp); + output[1][i] = L_sub(output[1][i], L_shr(tmp, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); } FOR ( i = dftOvlLen; i < output_frame; i++ ) { - tmp = L_shr(hStereoDft->td_gain_fx[0] * hStereoDft->hb_stefi_sig_fx[i], 1); - output[0][i] = L_add(output[0][i], tmp); + tmp = L_shr(Mpy_32_32(hStereoDft->hb_stefi_sig_fx[i], hStereoDft->td_gain_fx[0]), 1); + output[0][i] = L_add(output[0][i], L_shr(tmp, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); - output[1][i] = L_sub(output[1][i], tmp); + output[1][i] = L_sub(output[1][i], L_shr(tmp, sub(hStereoDft->q_hb_stefi_sig_fx, hStereoDft->q_dft))); move32(); } } @@ -1190,7 +1289,7 @@ void ivas_sba_dirac_stereo_dec_fx( ELSE { /* nrg calculation for TD Stereo Filling, as done in ICBWE which is not used in this case */ - ivas_sba_dirac_stereo_compute_td_stefi_nrgs( hStereoDft, hSCE->save_hb_synth_fx, hSCE->hCoreCoder[0]->core, output_frame, fd_cng_flag ); + ivas_sba_dirac_stereo_compute_td_stefi_nrgs( hStereoDft, hSCE->save_hb_synth_fx, hSCE->hCoreCoder[0]->core, output_frame, fd_cng_flag, hSCE->q_save_synth_fx ); /* do DFT Stereo core switching (including DFT analysis) here as CPE element was not available in SCE decoder */ Copy32( hSCE->save_synth_fx, tmp_synth, hSCE->hCoreCoder[0]->L_frame ); @@ -1203,7 +1302,7 @@ void ivas_sba_dirac_stereo_dec_fx( /* mapping of DirAC parameters (azimuth, elevation, diffuseness) to DFT Stereo parameters (side gain, prediction gain) */ map_params_dirac_to_stereo( hStereoDft, st_ivas->hQMetaData, tmp_synth, DFT[0], st_ivas->ivas_format == MC_FORMAT, ( ( st_ivas->ivas_format != SBA_FORMAT && st_ivas->ivas_format != SBA_ISM_FORMAT ) || mcmasa ) ? hSCE->hCoreCoder[0]->L_frame : output_frame, - ( ( st_ivas->ivas_format != SBA_FORMAT && st_ivas->ivas_format != SBA_ISM_FORMAT ) || mcmasa )); + ( ( st_ivas->ivas_format != SBA_FORMAT && st_ivas->ivas_format != SBA_ISM_FORMAT ) || mcmasa ), hSCE != NULL ? hSCE->q_save_synth_fx:0); IF ( (EQ_32( st_ivas->ivas_format , SBA_FORMAT) || EQ_32(st_ivas->ivas_format , SBA_ISM_FORMAT) ) && !mcmasa ) { @@ -1236,7 +1335,7 @@ void ivas_sba_dirac_stereo_dec_fx( Copy32( hSCE->save_hb_synth_fx + output_frame - memOffset, tmp_buf, memOffset ); Copy32( hSCE->save_hb_synth_fx, hSCE->save_hb_synth_fx + memOffset, output_frame - memOffset ); Copy32( hSCE->prev_hb_synth_fx, hSCE->save_hb_synth_fx, memOffset ); - Copy32( tmp_buf, hSCE->prev_hb_synth_fx, memOffset ); + v_shr( tmp_buf, sub(hSCE->q_prev_hb_synth_fx, hSCE->q_save_hb_synth_fx) ,hSCE->prev_hb_synth_fx, memOffset ); } IF ( (EQ_16( hCPE->hCoreCoder[0]->core, ACELP_CORE) || EQ_16(hCPE->hCoreCoder[0]->last_core, ACELP_CORE)) && EQ_16(fd_cng_flag, 0) && EQ_16(st_ivas->nchan_transport, 1) ) diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index d11b7aa0e..ce2aebb99 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -71,6 +71,7 @@ typedef struct #ifdef IVAS_FLOAT_FIXED Word32 gains_fx[3]; Word32 buffer_fx[3][STEREO_DFT_ALLPASS_BUFFERLEN]; + Word16 q_buffer_fx; #endif @@ -223,9 +224,9 @@ typedef struct stereo_dft_dec_data_struct #ifdef IVAS_FLOAT_FIXED Word32 res_cod_mem_fx[STEREO_DFT_OVL_8k]; Word32 buff_LBTCX_mem_fx[NS2SA( 16000, STEREO_DFT32MS_OVL_NS )]; + Word16 q_res_cod_mem_fx; #endif - float stab_fac_smooth_res; /* low-pass filtered stability factor */ BPF_DEC_HANDLE hBpf; TCX_LTP_DEC_HANDLE hTcxLtpDec; @@ -253,6 +254,7 @@ typedef struct stereo_dft_dec_data_struct Word16 q_lt_pred_gain; Word32 ap_delay_mem_fx[NS2SA( 16000, DELAY_BWE_TOTAL_NS )]; Word32 ap_fade_mem_fx[STEREO_DFT_ALLPASS_FADELEN_16k]; + Word32 q_ap_fade_mem_fx; #endif int16_t ap_wasTransient; @@ -278,6 +280,7 @@ typedef struct stereo_dft_dec_data_struct Word16 Q_nrg_subr; Word16 prev_Q_stefi_sig; Word32 q_td_gain[STEREO_DFT_CORE_HIST_MAX]; + Word16 q_hb_stefi_sig_fx; #endif /* stereo DTX */ @@ -939,6 +942,9 @@ typedef struct sce_dec_data_structure Word32 *save_synth_fx; Word32 *save_hb_synth_fx; + Word16 q_prev_hb_synth_fx; + Word16 q_save_synth_fx; + Word16 q_save_hb_synth_fx; #endif // IVAS_FLOAT_FIXED } SCE_DEC_DATA, *SCE_DEC_HANDLE; diff --git a/lib_dec/ivas_stereo_dft_dec.c b/lib_dec/ivas_stereo_dft_dec.c index f79052c2e..93cabea26 100644 --- a/lib_dec/ivas_stereo_dft_dec.c +++ b/lib_dec/ivas_stereo_dft_dec.c @@ -466,6 +466,9 @@ void stereo_dft_dec_open( } hStereoDft->win_8k = dft_win_8k; +#ifdef IVAS_FLOAT_FIXED + hStereoDft->win_8k_fx = dft_win_8k_fx; +#endif /*Bands: find the number of bands, Nyquist freq. is not taken into account*/ set_s( hStereoDft->band_res, hStereoDft->hConfig->band_res, STEREO_DFT_DEC_DFT_NB ); @@ -491,6 +494,8 @@ void stereo_dft_dec_open( hStereoDft->min_smooth_gains = min_smooth_gains1; hStereoDft->max_smooth_gains = max_smooth_gains1; } + hStereoDft->q_hb_stefi_sig_fx = Q31; + hStereoDft->q_ap_fade_mem_fx = Q31; /* reset DFT stereo memories */ stereo_dft_dec_reset( hStereoDft ); @@ -601,6 +606,9 @@ void stereo_dft_dec_open( } hStereoDft->win_8k = dft_win_8k; +#ifdef IVAS_FLOAT_FIXED + hStereoDft->win_8k_fx = dft_win_8k_fx; +#endif /*Bands: find the number of bands, Nyquist freq. is not taken into account*/ set_s( hStereoDft->band_res, hStereoDft->hConfig->band_res, STEREO_DFT_DEC_DFT_NB ); @@ -2096,6 +2104,7 @@ void stereo_dft_dec_synthesize( } +#ifndef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * stereo_dft_dec() * @@ -2672,6 +2681,7 @@ void stereo_dft_dec( return; } +#endif /*------------------------------------------------------------------------- diff --git a/lib_dec/ivas_stereo_dft_dec_fx.c b/lib_dec/ivas_stereo_dft_dec_fx.c index 34d210a4d..49f7300b8 100644 --- a/lib_dec/ivas_stereo_dft_dec_fx.c +++ b/lib_dec/ivas_stereo_dft_dec_fx.c @@ -322,6 +322,8 @@ static void stereo_dft_dec_open_fx( hStereoDft->min_smooth_gains_fx = min_smooth_gains1_fx; hStereoDft->max_smooth_gains_fx = max_smooth_gains1_fx; } + hStereoDft->q_hb_stefi_sig_fx = Q31; + hStereoDft->q_ap_fade_mem_fx = Q31; /* reset DFT stereo memories */ stereo_dft_dec_reset_fx( hStereoDft ); @@ -698,11 +700,11 @@ void stereo_dft_dec_synthesize_fx( } /*IFFT*/ - //scale_dft = getScaleFactor32(p_DFT, NFFT); - //scale_dft = find_guarded_bits_fx(NFFT) - scale_dft; - //v_shr(p_DFT, scale_dft, p_DFT, NFFT); + scale_dft = getScaleFactor32(p_DFT, NFFT); + scale_dft = find_guarded_bits_fx(NFFT) - scale_dft; + v_shr(p_DFT, scale_dft, p_DFT, NFFT); rfft_fx( p_DFT, trigo_dec, NFFT, +1 ); - //v_shr(p_DFT, negate(scale_dft), p_DFT, NFFT); + v_shr(p_DFT, negate(scale_dft), p_DFT, NFFT); IF ( EQ_16(k , 0) ) { @@ -1171,6 +1173,113 @@ void stereo_dft_dec_smooth_parameters_fx( return; } +/*------------------------------------------------------------------------- + * stereo_dft_dec_res_fx() + * + * Decode the residual signal + *-------------------------------------------------------------------------*/ + +void stereo_dft_dec_res_fx( + CPE_DEC_HANDLE hCPE, /* i/o: decoder CPE handle */ + Word32 res_buf[STEREO_DFT_N_8k], /* i : residual buffer */ + Word16 q_res, /* i : q fact of residural buffer */ + Word16 q_output, /* i : q factor of output buffer */ + Word32 *output /* o : output */ +) +{ + Word16 i; + Word16 win[L_FRAME8k + STEREO_DFT_OVL_8k]; + Word16 out_16[L_FRAME8k + STEREO_DFT_OVL_8k]; + Word32 bpf_error_signal_8k[L_FRAME8k]; + Word16 prev_bfi; + Word16 fac, step; + Word16 res_bpf_flag; + + prev_bfi = hCPE->hCoreCoder[0]->prev_old_bfi; /* The core decoding is already completed here and the prev_bfi has been updated for the next frame. + The prev_old_bfi still holds the prev_bfi for the current frame. */ + move16(); + + /* flush memories when switching residual coding on */ + IF ( EQ_16(hCPE->hStereoDft->res_cod_mode[STEREO_DFT_OFFSET - 1], STEREO_DFT_RES_COD_OFF) ) + { + set_val_Word32( hCPE->hStereoDft->res_cod_mem_fx, 0, STEREO_DFT_OVL_8k ); + set_val_Word32( hCPE->input_mem_fx[1], 0, NS2SA( 8000, STEREO_DFT32MS_OVL_NS ) ); + set_val_Word16( hCPE->hStereoDft->hBpf->pst_old_syn_fx, 0, STEREO_DFT_NBPSF_PIT_MAX_8k ); + hCPE->hStereoDft->hBpf->pst_mem_deemp_err_fx = 0; + move16(); + } + + /*Inverse MDCT*/ + TCX_MDCT_Inverse( res_buf, Q15, win, STEREO_DFT_OVL_8k, L_FRAME8k - STEREO_DFT_OVL_8k, STEREO_DFT_OVL_8k, IVAS_CPE_DFT ); + + IF ( !prev_bfi ) + { + /*OLA*/ + /*overlapping parts*/ + Word16 q_shift = sub(hCPE->hStereoDft->q_res_cod_mem_fx, sub(Q15, q_res)); + FOR ( i = 0; i < STEREO_DFT_OVL_8k; i++ ) + { + win[i] = extract_h(L_add(hCPE->hStereoDft->res_cod_mem_fx[i], L_shl(L_mult(win[i], hCPE->hStereoDft->win_8k_fx[i]), q_shift))); + hCPE->hStereoDft->res_cod_mem_fx[i] = L_mult(win[L_FRAME8k + i], hCPE->hStereoDft->win_8k_fx[STEREO_DFT_OVL_8k - 1 - i]); + } + hCPE->hStereoDft->q_res_cod_mem_fx = sub(Q15, q_res); + } + ELSE + { + Word16 q_div; + /* For first good frame, ola memory contains extended ECU buffer -- need to crossfade instead of OLA */ + step = BASOP_Util_Divide3232_Scale( 1, STEREO_DFT_OVL_8k, &q_div); + IF (NE_16(q_div, 0)) + { + step = shl(step, q_div); + } + fac = 0; + FOR ( i = 0; i < STEREO_DFT_OVL_8k; i++ ) + { + win[i] = extract_h(Madd_32_16(Mpy_32_16_1(hCPE->hStereoDft->res_cod_mem_fx[i], sub(MAX_16, mult(fac, fac))), + L_mult(hCPE->hStereoDft->win_8k_fx[i], win[i]), + sub(MAX_16, mult(sub(MAX_16, fac), sub(MAX_16 , fac))))); + hCPE->hStereoDft->res_cod_mem_fx[i] = L_mult(win[L_FRAME8k + i], hCPE->hStereoDft->win_8k_fx[STEREO_DFT_OVL_8k - 1 - i]); + fac = add(fac, step); + } + } + + Copy( win, out_16, L_FRAME8k ); + + IF ( hCPE->hCoreCoder[0]->core == ACELP_CORE ) + { + /* bass post-filter */ + bass_psfilter_fx( hCPE->hStereoDft->hBpf, hCPE->hCoreCoder[0]->Opt_AMR_WB, out_16, L_FRAME8k, hCPE->hCoreCoder[0]->old_pitch_buf_16_fx + ( L_FRAME8k / STEREO_DFT_L_SUBFR_8k ), hCPE->hCoreCoder[0]->bpf_off, + hCPE->hCoreCoder[0]->stab_fac_fx, &hCPE->hStereoDft->stab_fac_smooth_res_fx, hCPE->hCoreCoder[0]->last_coder_type, sub(q_output, Q16), bpf_error_signal_8k ); + + res_bpf_flag = res_bpf_adapt_fx( hCPE->hStereoDft, bpf_error_signal_8k, res_buf ); + + IF ( prev_bfi ) + { + /* Ramp up BPF contribution for the first good frame */ + step = (Word16)(0x00CD) ; // ( 1.0f / L_FRAME8k ); + fac = 0; + FOR ( i = 0; i < L_FRAME8k; i++ ) + { + bpf_error_signal_8k[i] = Mpy_32_16_1(bpf_error_signal_8k[i], fac); + fac = add(fac, step); + } + } + Copy_Scale_sig_16_32(out_16, output, L_FRAME8k, 16); + IF ( res_bpf_flag ) + { + v_sub_32( output, bpf_error_signal_8k, output, L_FRAME8k ); + } + } + ELSE IF ( EQ_16(hCPE->hCoreCoder[0]->last_core, ACELP_CORE) ) + { + set_val_Word16( hCPE->hStereoDft->hBpf->pst_old_syn_fx, 0, STEREO_DFT_NBPSF_PIT_MAX_8k ); + hCPE->hStereoDft->hBpf->pst_mem_deemp_err_fx = 0; + } + + return; +} + /*------------------------------------------------------------------------- * stereo_dft_dec_fx() @@ -2143,7 +2252,7 @@ static void stereo_dft_compute_td_stefi_params_fx( g2, STEREO_DFT_STEFFI_GAIN_REST_AMT_FX )); } - hStereoDft->td_gain_fx[0] = g2; + hStereoDft->td_gain_fx[0] = L_deposit_h((Word16)g2); move32(); if (q_pred_gain_avg != 0) hStereoDft->q_td_gain[0] = q_pred_gain_avg; @@ -2520,7 +2629,7 @@ void stereo_dft_generate_res_pred_fx( dmx_nrg = L_add(dmx_nrg, Madd_32_32(Mpy_32_32(pDFT_DMX[2 * i], pDFT_DMX[2 * i]), pDFT_DMX[2 * i + 1], pDFT_DMX[2 * i + 1])); } - hStereoDft->hb_nrg_fx[0] = Mpy_32_32(dmx_nrg , L_shr(hStereoDft->NFFT, 1)); + hStereoDft->hb_nrg_fx[0] = dmx_nrg , L_shr(hStereoDft->NFFT, 1); *stop = bin0; move16(); } diff --git a/lib_dec/ivas_stereo_esf_dec.c b/lib_dec/ivas_stereo_esf_dec.c index fee9f26f4..5fda7188e 100644 --- a/lib_dec/ivas_stereo_esf_dec.c +++ b/lib_dec/ivas_stereo_esf_dec.c @@ -69,6 +69,9 @@ void init_basic_allpass( ap->buffer_fx[i][j] = 0; #endif } +#ifdef IVAS_FLOAT_FIXED + ap->q_buffer_fx = 0; +#endif } ap->pos = 0; @@ -165,14 +168,15 @@ void filter_with_allpass_fx( D2_fx = ap->buffer_fx[1]; D3_fx = ap->buffer_fx[2]; - IF (NE_16(q_shift, 0)) + IF (NE_16(q_shift, ap->q_buffer_fx)) { FOR (k = 0; k < sizeof(ap->buffer_fx[0]) / sizeof(ap->buffer_fx[0][0]); k++) { - D1_fx[k] = L_shr(D1_fx[k], q_shift); - D2_fx[k] = L_shr(D2_fx[k], q_shift); - D3_fx[k] = L_shr(D3_fx[k], q_shift); + D1_fx[k] = L_shr(D1_fx[k], sub(ap->q_buffer_fx, q_shift)); + D2_fx[k] = L_shr(D2_fx[k], sub(ap->q_buffer_fx, q_shift)); + D3_fx[k] = L_shr(D3_fx[k], sub(ap->q_buffer_fx, q_shift)); } + ap->q_buffer_fx = q_shift; } Word32 D1_upd = pos + d1, D2_upd = pos + d2, D3_upd = pos + d3; diff --git a/lib_dec/ivas_stereo_switching_dec.c b/lib_dec/ivas_stereo_switching_dec.c index cdb9e7e75..9c4b1a734 100644 --- a/lib_dec/ivas_stereo_switching_dec.c +++ b/lib_dec/ivas_stereo_switching_dec.c @@ -3476,7 +3476,10 @@ void synchro_synthesis_fixed_clean( delay_signal_fx( output_fx[n], output_frame, sts[n]->prev_synth_buffer32_fx, delay_comp_DFT ); } } - hCPE->q_prev_synth_fx = hCPE->hStereoDft->q_dft; + IF( sba_dirac_stereo_flag ) + { + hCPE->q_prev_synth_fx = hCPE->hStereoDft->q_dft; + } IF( use_cldfb_for_last_dft ) { Copy32( hCPE->hCoreCoder[0]->hTcxDec->FBTCXdelayBuf_32, sts[0]->prev_synth_buffer32_fx + delay_comp_DFT, delay_diff ); diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index 5043c28e2..f0480b9d9 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -814,6 +814,7 @@ typedef struct bass_postfilt_structure { float pst_old_syn[NBPSF_PIT_MAX]; /* Bass post-filter - old synthesis buffer 1 */ Word16 pst_old_syn_fx[NBPSF_PIT_MAX]; /* Bass post-filter - old synthesis buffer 1 Q_syn2-1*/ + Word16 q_pst_old_syn; float pst_mem_deemp_err; /* Bass post-filter - filter memory of noise LP filter */ Word16 pst_mem_deemp_err_fx; /* Bass post-filter - filter memory of noise LP filter Q_syn2-1*/ @@ -1141,6 +1142,7 @@ typedef struct hq_dec_structure Word16 Q_old_outLB; #ifdef IVAS_FLOAT_FIXED Word32 old_outLB_fx[L_FRAME32k]; + Word16 q_old_outLB_fx; #endif Word16 Q_old_wtda_LB; @@ -1861,14 +1863,6 @@ typedef struct Decoder_State //note_ : produces failures if added below their float parts Word16 old_exc_fx[L_EXC_MEM_DEC]; /* old excitation Q_exc*/ Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame Q2.56*/ -#ifdef IVAS_FLOAT_FIXED - Word32 lsf_old32[M]; /* old LSF vector at the end of the frame Q2.56*/ - Word32 lsfoldbfi132[M]; - Word32 lsfoldbfi032[M]; - Word32 lsf_adaptive_mean32[M]; - Word32 mem_AR32[M]; - Word32 mem_MA32[M]; -#endif // IVAS_FLOAT_FIXED Word16 lsp_old_fx[M]; /* old LSP vector at the end of the frame Q15*/ /*----------------------------------------------------------------------------------* @@ -2022,6 +2016,7 @@ typedef struct Decoder_State //Word16 bfi_pitch_frame_fx; /*FEC - frame length when pitch for FEC is saved Q0*/ float old_pitch_buf[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values */ + Word16 old_pitch_buf_16_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values 15Q16 */ Word32 old_pitch_buf_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values 15Q16 */ int16_t upd_cnt; /* FEC - counter of frames since last update */ @@ -2550,6 +2545,7 @@ typedef struct Decoder_State #ifdef IVAS_FLOAT_FIXED Word16 prev_lpcQuantization; /*temporary check if for last frame lpcQuantization was set or not, to be removed */ float scale; /*temporary for lpc_unquantize fixed point implementation, to be removed */ + float scale_lsfbfi; /*temporary for lpc_unquantize fixed point implementation, to be removed */ #endif // IVAS_FLOAT_FIXED int16_t numlpc; diff --git a/lib_dec/updt_dec_fx.c b/lib_dec/updt_dec_fx.c index 5839ee214..a386b83d6 100644 --- a/lib_dec/updt_dec_fx.c +++ b/lib_dec/updt_dec_fx.c @@ -793,6 +793,17 @@ static void ivas_updt_bw_switching_fx( return; } +static Word32 sum_32_32_fx(Word32 *x, Word16 length) +{ + Word64 sum = 0; + Word16 i; + FOR (i = 0; i < length; i++) + { + sum = W_add(sum, W_mult_32_32(x[i], x[i])); + } + return W_round64_L(sum); +} + void ivas_updt_dec_common_fx( Decoder_State *st_fx, /* i/o: decoder state structure */ Word16 hq_core_type_fx, /* i : HQ core type */ @@ -940,6 +951,31 @@ void ivas_updt_dec_common_fx( } st->stab_fac_smooth_lt = ENV_SMOOTH_FAC * st->stab_fac + (1.0f - ENV_SMOOTH_FAC) * st->stab_fac_smooth_lt; } +#else + if (st_fx->element_mode != EVS_MONO) + { + Word16 q_div = sub(Q31, shl(Qpostd, 1)); + Word16 output_frame = NS2SA(st_fx->output_Fs, FRAME_SIZE_NS); + Word32 sum_val = sum_32_32_fx(synth, output_frame); + Word32 div_val = BASOP_Util_Divide3232_Scale(sum_val, output_frame, &q_div); + Word32 log_energy = L_add(L_shl(L_deposit_l(add(q_div, sub(Q31, shl(Qpostd, 1)))), Q15) , + L_shr(BASOP_Util_Log2(L_shl(L_add(div_val, EPSILON_FX), Q16)), Q10)); + Word32 log_energy_diff = L_abs(L_sub(st_fx->log_energy_old_fx , log_energy)); + st_fx->log_energy_old_fx = log_energy; + st_fx->log_energy_diff_lt_fx = Madd_32_16(Mpy_32_16_1(log_energy_diff, ENV_SMOOTH_FAC_FX ), st_fx->log_energy_diff_lt_fx, sub(MAX_16 , ENV_SMOOTH_FAC_FX)); + //To be deleted. + st_fx->log_energy_diff_lt = fixedToFloat(st_fx->log_energy_diff_lt_fx, Q15); + if (st_fx->core == HQ_CORE) + { + st_fx->stab_fac_fx = extract_l(L_min(MAX_16, L_shr(L_add(STAB_FAC_EST1_FX, Madd_32_16(Mpy_32_16_1(STAB_FAC_EST2_FX , st_fx->hHQ_core->mem_env_delta_fx), STAB_FAC_EST3_FX, st_fx->log_energy_diff_lt_fx)), Q15))); + st_fx->stab_fac_fx = s_max(0, st_fx->stab_fac_fx); + } + st_fx->stab_fac_smooth_lt_fx = L_add(L_mult(ENV_SMOOTH_FAC_FX , st_fx->stab_fac_fx), + L_mult(sub(MAX_16, ENV_SMOOTH_FAC_FX) , st_fx->stab_fac_smooth_lt_fx)); + + //To be deleted + st_fx->stab_fac_smooth_lt = fixedToFloat(st_fx->stab_fac_smooth_lt_fx, Q31); + } #endif IF( ((LE_32(st_fx->core_brate,SID_2k40))&&EQ_16(st_fx->cng_type,FD_CNG)) || (st_fx->tcxonly && EQ_16(st_fx->codec_mode,MODE2)) diff --git a/lib_enc/ivas_init_enc.c b/lib_enc/ivas_init_enc.c index 0b9aa64c7..c6ebfe917 100644 --- a/lib_enc/ivas_init_enc.c +++ b/lib_enc/ivas_init_enc.c @@ -39,6 +39,9 @@ #include "ivas_stat_enc.h" #include "ivas_rom_com.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif /*-------------------------------------------------------------------* diff --git a/lib_enc/ivas_masa_enc.c b/lib_enc/ivas_masa_enc.c index ec035d865..fd1c8f33b 100644 --- a/lib_enc/ivas_masa_enc.c +++ b/lib_enc/ivas_masa_enc.c @@ -39,6 +39,9 @@ #include "ivas_stat_enc.h" #include "wmc_auto.h" #include "prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif /*-----------------------------------------------------------------------* diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index c7ec693a8..50b7d7ab8 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -39,6 +39,9 @@ #include "prot.h" #include "ivas_prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif /*-----------------------------------------------------------------------* diff --git a/lib_enc/ivas_qmetadata_enc.c b/lib_enc/ivas_qmetadata_enc.c index 69d19b5db..5e1c4597e 100644 --- a/lib_enc/ivas_qmetadata_enc.c +++ b/lib_enc/ivas_qmetadata_enc.c @@ -1265,7 +1265,11 @@ static void ivas_qmetadata_quantize_diffuseness_nrg_ratios( * fact that with 2dir data, it is harder to achieve separate high direct-to-total ratio values * which are assumed by the direction quantization system. In practice, this improves direction * accuracy when it is perceptual meaningful. */ +#ifdef IVAS_FLOAT_FIXED + masa_compensate_two_dir_energy_ratio_index_fx( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); +#else masa_compensate_two_dir_energy_ratio_index( index_dirRatio1Inv, index_dirRatio2Inv, &index_dirRatio1Inv_mod, &index_dirRatio2Inv_mod, hodirac_flag ); +#endif for ( k = 0; k < hQMetaData->q_direction[0].cfg.nblocks; k++ ) { diff --git a/lib_enc/ivas_qspherical_enc.c b/lib_enc/ivas_qspherical_enc.c index 8c99b4e5a..2c5294e31 100644 --- a/lib_enc/ivas_qspherical_enc.c +++ b/lib_enc/ivas_qspherical_enc.c @@ -40,6 +40,9 @@ #include "ivas_stat_enc.h" #include "wmc_auto.h" #include "prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif /*-----------------------------------------------------------------------* diff --git a/lib_rend/ivas_dirac_ana.c b/lib_rend/ivas_dirac_ana.c index 40470f0a5..631fd5f55 100644 --- a/lib_rend/ivas_dirac_ana.c +++ b/lib_rend/ivas_dirac_ana.c @@ -41,6 +41,9 @@ #include "wmc_auto.h" #include "prot_fx2.h" #include "prot_fx1.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif /*------------------------------------------------------------------------- * Local function prototypes @@ -344,7 +347,7 @@ static void ivas_dirac_param_est_ana( Word16 ts, i, d, j; Word16 num_freq_bands, index; Word32 dir_v[DIRAC_NUM_DIMS]; - Word32 dir_q; + Word16 dir_q; Word16 l_ts; Word32 Foa_RealBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; Word32 Foa_ImagBuffer_fx[FOA_CHANNELS][CLDFB_NO_CHANNELS_MAX]; -- GitLab