From 05756b72db58b40aaed9b7b776cc416e390b9214 Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Fri, 7 Jun 2024 16:11:15 +0200 Subject: [PATCH 01/10] fix compilation with DEBUGGING active --- apps/decoder.c | 2 +- apps/encoder.c | 2 +- apps/renderer.c | 2 +- lib_com/options.h | 1 - lib_rend/ivas_crend.c | 8 ++++---- lib_rend/ivas_rotation.c | 2 +- lib_rend/lib_rend.c | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index abe1788de..33c15e514 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -54,7 +54,7 @@ * Local constants *------------------------------------------------------------------------------------------*/ -#if !defined( WMOPS_FLT ) +#if !defined( DEBUGGING ) && !defined( WMOPS ) static #endif int32_t frame = 0; /* Counter of frames */ diff --git a/apps/encoder.c b/apps/encoder.c index c8e6f32d6..283f1626a 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -48,7 +48,7 @@ * Local constants, enums *------------------------------------------------------------------------------------------*/ -#if !defined( WMOPS ) +#if !defined( DEBUGGING ) && !defined( WMOPS ) static #endif int32_t frame = 0; /* Counter of frames */ diff --git a/apps/renderer.c b/apps/renderer.c index 5f39dc4e6..06437f331 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -67,7 +67,7 @@ #define IVAS_MIN16B_FLT ( -32768.0f ) #define IVAS_MAX16B_FX 32767 #define IVAS_MIN16B_FX ( -32768 ) -#if !defined( WMOPS ) +#if !defined(DEBUGGING) && !defined( WMOPS ) static #endif int32_t frame = 0; diff --git a/lib_com/options.h b/lib_com/options.h index cbd62853c..1f43107a9 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -109,7 +109,6 @@ #define FIX_TMP_714 #define BASOP_NOGLOB_TMP_715 #define EVS_FUNC_MODIFIED -//#define DEBUGGING //#define DBG_WAV_WRITER #define EVS_FLOAT_ENC //#define DUMPS_ENABLED diff --git a/lib_rend/ivas_crend.c b/lib_rend/ivas_crend.c index b678a90f8..08a65bb33 100644 --- a/lib_rend/ivas_crend.c +++ b/lib_rend/ivas_crend.c @@ -3161,7 +3161,7 @@ static ivas_error ivas_rend_crendConvolver( ivas_mdft_fx( pIn, pFreq_buf_re, pFreq_buf_im, subframe_length, subframe_length ); -#ifdef DEBUGGING +#ifdef DBG_WAV_WRITER dbgwrite_txt( pFreq_buf_re, subframe_length, "Fixed_pFreq_buf_re_mdft.txt", NULL ); dbgwrite_txt( pFreq_buf_im, subframe_length, "Fixed_pFreq_buf_im_mdft.txt", NULL ); #endif @@ -3223,7 +3223,7 @@ static ivas_error ivas_rend_crendConvolver( ivas_imdft_fx( tmp_out_re, tmp_out_im, pOut, subframe_length ); -#ifdef DEBUGGING +#ifdef DBG_WAV_WRITER dbgwrite_txt( pOut, subframe_length << 1, "Fixed_imdft_out.txt", NULL ); #endif pFreq_buf_re = &pcm_out[j][i_ts * subframe_length]; @@ -3334,7 +3334,7 @@ static ivas_error ivas_rend_crendConvolver( pFreq_buf_im = &hCrend->freq_buffer_im[i][offset]; ivas_mdft( pIn, pFreq_buf_re, pFreq_buf_im, subframe_length, subframe_length ); -#ifdef DEBUGGING +#ifdef DBG_WAV_WRITER dbgwrite_txt( pFreq_buf_re, subframe_length, "Float_pFreq_buf_re_mdft.txt", NULL ); dbgwrite_txt( pFreq_buf_im, subframe_length, "Float_pFreq_buf_im_mdft.txt", NULL ); #endif @@ -3394,7 +3394,7 @@ static ivas_error ivas_rend_crendConvolver( } ivas_imdft( tmp_out_re, tmp_out_im, pOut, subframe_length ); -#ifdef DEBUGGING +#ifdef DBG_WAV_WRITER dbgwrite_txt( pOut, subframe_length << 1, "Float_imdft_out.txt", NULL ); #endif pFreq_buf_re = &pcm_out[j][i_ts * subframe_length]; diff --git a/lib_rend/ivas_rotation.c b/lib_rend/ivas_rotation.c index be96d186f..3e13c977e 100644 --- a/lib_rend/ivas_rotation.c +++ b/lib_rend/ivas_rotation.c @@ -1385,7 +1385,7 @@ void rotateFrame_shd_cldfb( /* calculate Ambisonics rotation matrix from the quaternion */ SHrotmatgen_fx( SHrotmat, Rmat, shd_rot_max_order ); -#ifdef DEBUGGING +#ifdef DBG_WAV_WRITER dbgwrite_txt( SHrotmat, HEADROT_SHMAT_DIM * HEADROT_SHMAT_DIM, "Fixed_SHrotmat.txt", NULL ); #endif /* rotation by mtx multiplication */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 925265558..470ef7f23 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -8780,7 +8780,7 @@ static ivas_error rotateFrameSba_fx( /* calculate ambisonics rotation matrices for the previous and current frames */ SHrotmatgen_fx( gains, Rmat, shd_rot_max_order ); -#ifdef DEBUGGING +#ifdef DBG_WAV_WRITER dbgwrite_txt( gains, HEADROT_SHMAT_DIM * HEADROT_SHMAT_DIM, "Fixed_code_gains.txt", NULL ); dbgwrite_txt( Rmat, 3 * 3, "Fixed_code_Rmat.txt", NULL ); #endif -- GitLab From ac11b94e60d578e616bea4fc7412deb6635282da Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Fri, 7 Jun 2024 16:11:51 +0200 Subject: [PATCH 02/10] add logging of brate --- lib_enc/ivas_enc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index 23dee7bc6..2340afe8d 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -581,8 +581,11 @@ ivas_error ivas_enc( *----------------------------------------------------------------*/ hEncoderConfig->last_ivas_total_brate = ivas_total_brate; - - + +#ifdef DEBUGGING + dbgwrite(&st_ivas->hEncoderConfig->ivas_total_brate, sizeof(Word32), 1, 1, "ENC_VER-ivas_total_brate"); +#endif + pop_wmops(); return error; } -- GitLab From 79b32de9b5ec942b6f3c0f0862e27fad02d75c52 Mon Sep 17 00:00:00 2001 From: malenov Date: Mon, 24 Jun 2024 14:32:11 +0200 Subject: [PATCH 03/10] add dbg output to encoder --- apps/encoder.c | 19 +++++++++++++++- lib_com/bits_alloc_fx.c | 21 +++++++++--------- lib_com/ivas_prot.h | 4 ++++ lib_com/options.h | 5 ++++- lib_enc/amr_wb_enc_fx.c | 17 ++++++++++++-- lib_enc/evs_enc_fx.c | 20 +++++++++++++++-- lib_enc/ivas_core_enc.c | 37 ++++++++++++++++++++++++++++++- lib_enc/ivas_cpe_enc.c | 9 ++++++++ lib_enc/ivas_enc.c | 11 +++++++-- lib_enc/ivas_ism_enc.c | 33 +++++++++++++++++++++++++++ lib_enc/ivas_omasa_enc.c | 29 ++++++++++++++++++++++++ lib_enc/ivas_sce_enc.c | 12 ++++++++++ lib_enc/ivas_stereo_ica_enc.c | 3 +++ lib_enc/ivas_stereo_td_enc.c | 10 +++++++++ lib_enc/speech_music_classif_fx.c | 4 ---- 15 files changed, 210 insertions(+), 24 deletions(-) diff --git a/apps/encoder.c b/apps/encoder.c index 283f1626a..7d39027a0 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -936,7 +936,19 @@ static bool parseCmdlIVAS_enc( return false; } } - +#ifdef DEBUG_MODE_INFO +#ifdef DEBUG_MODE_INFO_TWEAK + /*-----------------------------------------------------------------* + * Define additional subfolder for debug info output in ./res + *-----------------------------------------------------------------*/ + else if ( strcmp( argv_to_upper, "-INFO" ) == 0 ) + { + extern char infoFolder[FILENAME_MAX]; + strncpy( infoFolder, argv[i + 1], sizeof( infoFolder ) ); + i += 2; + } +#endif /* #ifdef DEBUG_MODE_INFO_TWEAK */ +#endif /* #ifdef DEBUG_MODE_INFO */ /*-----------------------------------------------------------------* * deactivate delay compensation @@ -1636,6 +1648,11 @@ static void usage_enc( void ) fprintf( stdout, "-pca : activate PCA in SBA format FOA at 256 kbps \n" ); fprintf( stdout, "-level level : Complexity level, level = (1, 2, 3), will be defined after characterisation. \n" ); fprintf( stdout, " Currently, all values default to level 3 (full functionality).\n" ); +#ifdef DEBUG_MODE_INFO +#ifdef DEBUG_MODE_INFO_TWEAK + fprintf( stdout, "-info : specify subfolder name for debug output\n" ); +#endif +#endif fprintf( stdout, "-q : Quiet mode, no frame counters\n" ); fprintf( stdout, " default is deactivated\n" ); fprintf( stdout, "\n" ); diff --git a/lib_com/bits_alloc_fx.c b/lib_com/bits_alloc_fx.c index 514a9f894..968cc6090 100644 --- a/lib_com/bits_alloc_fx.c +++ b/lib_com/bits_alloc_fx.c @@ -493,7 +493,7 @@ static ivas_error acelp_FCB_allocator( } cdbk--; -#if defined DEBUGGING +#ifdef DEBUGGING if ( cdbk < 0 && coder_type != TRANSITION ) { return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Too low bit-budget for fixed innovation codebook (frame = %d). Exiting! \n" ); @@ -612,7 +612,6 @@ ivas_error config_acelp1( Word16 flag_hardcoded, coder_type_sw, fix_first; Word32 core_brate; #ifdef DEBUGGING - Word32 core_brate_inpI = core_brate_inp; #ifdef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING (void) active_cnt; #endif @@ -642,15 +641,15 @@ ivas_error config_acelp1( { nb_subfr = NB_SUBFR; -#if defined DEBUGGING +#ifdef DEBUGGING if ( ( ( core_brate_inp < 5900 && coder_type > UNVOICED ) && !( core_brate_inp < MIN_TC_BRATE && coder_type == TRANSITION ) ) && !( idchan > 0 && element_mode == IVAS_CPE_TD ) && !( element_mode == IVAS_SCE && tdm_low_rate_mode ) ) { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Too low bitrate (%d bps) for ACELP@12k8 in frame %d. Exiting!\n", core_brate_inpI ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Too low bitrate (%d bps) for ACELP@12k8 in frame %d. Exiting!\n", core_brate_inp ); } if ( core_brate_inp > ACELP_12k8_HIGH_LIMIT && core == ACELP_CORE ) { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Too high bitrate (%d bps) for ACELP@12k8 in frame %d. Exiting!\n", core_brate_inpI ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Too high bitrate (%d bps) for ACELP@12k8 in frame %d. Exiting!\n", core_brate_inp ); } #endif } @@ -658,10 +657,10 @@ ivas_error config_acelp1( { nb_subfr = NB_SUBFR16k; -#if defined DEBUGGING +#ifdef DEBUGGING if ( core_brate_inp < ACELP_16k_LOW_LIMIT && core == ACELP_CORE ) { - return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Too low bitrate (%d bps) for ACELP@16k in frame %d. Exiting!\n", core_brate_inpI ); + return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Error: Too low bitrate (%d bps) for ACELP@16k in frame %d. Exiting!\n", core_brate_inp ); } #endif } @@ -1220,7 +1219,7 @@ ivas_error config_acelp1( } else /* No FCB */ { -#if defined DEBUGGING +#ifdef DEBUGGING IVAS_ERROR( IVAS_ERR_INTERNAL, "WARNING!!!, No bit allocated to FCB, check frame %d\n" ); #endif acelp_cfg->fixed_cdk_index[0] = -1; @@ -1376,7 +1375,7 @@ ivas_error config_acelp1( } else if ( flag_hardcoded && core == ACELP_CORE && bits != 0 ) { -#if defined DEBUGGING +#ifdef DEBUGGING IVAS_ERROR( IVAS_ERR_INTERNAL, "ERROR: bit-budget incorrect (%d bits) in frame %d.\n", (Word32) bits ); #endif } @@ -1440,7 +1439,7 @@ ivas_error config_acelp1( bits -= allocate_unused( core_brate, coder_type, bits, 1, 0, LSFPRM, &acelp_cfg->lsf_bits ); } #endif -#if defined DEBUGGING +#ifdef DEBUGGING if ( idchan > 0 && bits > 0 && ( coder_type > UNVOICED || tdm_low_rate_mode == 0 ) ) { IVAS_ERROR( IVAS_ERR_INTERNAL, "WARNING !! Unused bits in secondary channel at frame %d\n" ); @@ -1470,7 +1469,7 @@ ivas_error config_acelp1( } else if ( bits < 0 && !( coder_type == UNVOICED && tdm_low_rate_mode == 1 && element_mode == IVAS_CPE_TD ) ) { -#if defined DEBUGGING +#ifdef DEBUGGING IVAS_ERROR( IVAS_ERR_INTERNAL, "ERROR: bit-budget incorrect (%d bits) in frame %d.\n", (Word32) bits ); #endif } diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index c388377c1..83488eb74 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -7298,6 +7298,10 @@ void ivas_omasa_enc( void ivas_set_surplus_brate_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +#ifdef DEBUG_MODE_INFO + , + const int16_t *nb_bits_metadata /* i : number of metadata bits */ +#endif ); void ivas_set_surplus_brate_dec( diff --git a/lib_com/options.h b/lib_com/options.h index 1f43107a9..59da5e6c7 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -36,13 +36,16 @@ #ifndef OPTIONS_H #define OPTIONS_H -//#define DEBUGGING /*allows message printed out during run time */ +#define DEBUGGING /*allows message printed out during run time */ #ifdef DEBUGGING +#define DEBUG_MODE_INFO /* define to output most important parameters to the subdirectory "res/" */ +#define DEBUG_MODE_INFO_TWEAK /* enable command line switch to specify subdirectory for debug info output inside "./res/" */ #include "debug.h" #endif #include "stl.h" + /* clang-format off */ /* ################### Start compiler switches ######################## */ diff --git a/lib_enc/amr_wb_enc_fx.c b/lib_enc/amr_wb_enc_fx.c index 3f5ddbb4b..535123e45 100644 --- a/lib_enc/amr_wb_enc_fx.c +++ b/lib_enc/amr_wb_enc_fx.c @@ -591,9 +591,22 @@ void amr_wb_enc_fx( /* update main codec parameters */ updt_enc_common_fx( st, Etot, Q_new ); -#ifdef MY_DEBUG - dbgwrite_indices( st ); + +#ifdef DEBUG_MODE_INFO + dbgwrite( &st->codec_mode, sizeof( short ), 1, input_frame, "res/codec" ); + dbgwrite( &st->core, sizeof( short ), 1, input_frame, "res/core" ); + dbgwrite( &st->extl, sizeof( short ), 1, input_frame, "res/extl" ); + dbgwrite( &st->bwidth, sizeof( short ), 1, input_frame, "res/bwidth" ); + float ener_flt = st->total_brate / 1000.0f; + dbgwrite( &ener_flt, sizeof( float ), 1, input_frame, "res/total_brate" ); + ener_flt = st->core_brate / 1000.0f; + dbgwrite( &ener_flt, sizeof( float ), 1, input_frame, "res/core_brate" ); + dbgwrite( &st->coder_type, sizeof( short ), 1, input_frame, "res/coder_type" ); + dbgwrite( &st->cng_type, sizeof( short ), 1, input_frame, "res/cng_type" ); + dbgwrite( &st->L_frame, sizeof( short ), 1, input_frame, "res/L_frame" ); + dbgwrite( &st->vad_flag, sizeof( short ), 1, input_frame, "res/vad_flag" ); #endif + return; } /*---------------------------------------------------------------------* diff --git a/lib_enc/evs_enc_fx.c b/lib_enc/evs_enc_fx.c index 53b52d3dc..0032784cd 100644 --- a/lib_enc/evs_enc_fx.c +++ b/lib_enc/evs_enc_fx.c @@ -589,9 +589,25 @@ ivas_error evs_enc_fx( st->L_frame = L_FRAME; st->rf_mode = 1; } -#ifdef MY_DEBUG - dbgwrite_indices( st ); + +#ifdef DEBUG_MODE_INFO + dbgwrite( &st->codec_mode, sizeof( short ), 1, input_frame, "res/codec" ); + dbgwrite( &st->core, sizeof( short ), 1, input_frame, "res/core" ); + dbgwrite( &st->extl, sizeof( short ), 1, input_frame, "res/extl" ); + dbgwrite( &st->bwidth, sizeof( short ), 1, input_frame, "res/bwidth" ); + float ener_flt = st->total_brate / 1000.0f; + dbgwrite( &ener_flt, sizeof( float ), 1, input_frame, "res/total_brate" ); + ener_flt = st->core_brate / 1000.0f; + dbgwrite( &ener_flt, sizeof( float ), 1, input_frame, "res/core_brate" ); + ener_flt = st->extl_brate / 1000.0f; + dbgwrite( &ener_flt, sizeof( float ), 1, input_frame, "res/extl_brate" ); + dbgwrite( &st->coder_type, sizeof( short ), 1, input_frame, "res/coder_type" ); + dbgwrite( &st->clas, sizeof( short ), 1, input_frame, "res/clas" ); + dbgwrite( &st->cng_type, sizeof( short ), 1, input_frame, "res/cng_type" ); + dbgwrite( &st->L_frame, sizeof( short ), 1, input_frame, "res/L_frame" ); + dbgwrite( &st->vad_flag, sizeof( short ), 1, input_frame, "res/vad_flag" ); #endif + return error; } diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index db7f5d9d1..995182f8e 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -436,7 +436,42 @@ ivas_error ivas_core_enc( } } - +#ifdef DEBUG_MODE_INFO + for ( n = 0; n < n_CoreChannels; n++ ) + { + float tmpF; + short tmpS, id; + + st = sts[n]; + id = st->id_element; + + dbgwrite( &st->core, sizeof( short ), 1, input_frame, fname( debug_dir, "core", n, id, ENC ) ); + dbgwrite( &st->extl, sizeof( short ), 1, input_frame, fname( debug_dir, "extl", n, id, ENC ) ); + dbgwrite( &st->bwidth, sizeof( short ), 1, input_frame, fname( debug_dir, "bwidth", n, id, ENC ) ); + tmpF = st->total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "total_brate", n, id, ENC ) ); + tmpS = st->bits_frame_nominal; + dbgwrite( &tmpS, sizeof( short ), 1, input_frame, fname( debug_dir, "bits_nominal", n, id, ENC ) ); + tmpF = st->core_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "core_brate", n, id, ENC ) ); + tmpF = st->extl_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "extl_brate", n, id, ENC ) ); + + dbgwrite( &st->coder_type, sizeof( short ), 1, input_frame, fname( debug_dir, "coder_type", n, id, ENC ) ); + dbgwrite( &st->clas, sizeof( short ), 1, input_frame, fname( debug_dir, "clas", n, id, ENC ) ); + dbgwrite( &st->cng_type, sizeof( short ), 1, input_frame, fname( debug_dir, "cng_type", n, id, ENC ) ); + dbgwrite( &st->L_frame, sizeof( short ), 1, input_frame, fname( debug_dir, "L_frame", n, id, ENC ) ); + dbgwrite( &st->vad_flag, sizeof( short ), 1, input_frame, fname( debug_dir, "vad_flag", n, id, ENC ) ); + dbgwrite( &st->localVAD, sizeof( short ), 1, input_frame, fname( debug_dir, "localVAD", n, id, ENC ) ); + + dbgwrite( &st->count_WB, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "count_WB", n, id, ENC ) ); + dbgwrite( &st->count_SWB, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "count_SWB", n, id, ENC ) ); + + dbgwrite( &st->sp_aud_decision0, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "sp_aud_decision0", n, id, ENC ) ); + dbgwrite( &st->sp_aud_decision1, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "sp_aud_decision1", n, id, ENC ) ); + dbgwrite( &st->sp_aud_decision2, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "sp_aud_decision2", n, id, ENC ) ); + } +#endif pop_wmops(); return error; diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index 5e9f49ba7..6ecbd64ea 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -438,6 +438,9 @@ ivas_error ivas_cpe_enc( set_zero( sts[1]->input, input_frame ); } +#ifdef DEBUG_MODE_INFO + dbgwrite( &hCPE->element_mode, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "element_mode", 0, sts[0]->id_element, ENC ) ); +#endif /*----------------------------------------------------------------* * Front Pre-processing @@ -711,6 +714,12 @@ ivas_error ivas_cpe_enc( sts[n]->hTranDet->transientDetector.prev_bIsAttackPresent = sts[n]->hTranDet->transientDetector.bIsAttackPresent; } +#ifdef DEBUG_MODE_INFO + { + float tmpF = ivas_total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "element_brate", 0, cpe_id, ENC ) ); + } +#endif pop_wmops(); return error; diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index 2340afe8d..a3d3b0c30 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -335,7 +335,11 @@ ivas_error ivas_enc( } /* Configuration of combined-format bit-budget distribution */ +#ifdef DEBUG_MODE_INFO + ivas_set_surplus_brate_enc( st_ivas, nb_bits_metadata ); +#else ivas_set_surplus_brate_enc( st_ivas ); +#endif /* Encode MASA transport channels */ if ( ( ivas_cpe_enc( st_ivas, 0, data_f[n], data_f[n + 1], input_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) @@ -582,8 +586,11 @@ ivas_error ivas_enc( hEncoderConfig->last_ivas_total_brate = ivas_total_brate; -#ifdef DEBUGGING - dbgwrite(&st_ivas->hEncoderConfig->ivas_total_brate, sizeof(Word32), 1, 1, "ENC_VER-ivas_total_brate"); +#ifdef DEBUG_MODE_INFO + { + float tmpF = ivas_total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, "res/ivas_total_brate" ); + } #endif pop_wmops(); diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index 296323cf9..974ceb9d3 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -370,6 +370,39 @@ ivas_error ivas_ism_enc( } } +#ifdef DEBUG_MODE_INFO + if ( dtx_flag ) + { + float tmpF; + int16_t id, n; + + n = 0; + for ( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) + { + if ( sce_id != st_ivas->hISMDTX->sce_id_dtx ) + { + st = st_ivas->hSCE[sce_id]->hCoreCoder[0]; + id = st->id_element; + + dbgwrite( &st->core, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "core", n, id, ENC ) ); + dbgwrite( &st->extl, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "extl", n, id, ENC ) ); + dbgwrite( &st->bwidth, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "bwidth", n, id, ENC ) ); + tmpF = st->total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "total_brate", n, id, ENC ) ); + tmpF = st->core_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "core_brate", n, id, ENC ) ); + tmpF = st->extl_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "extl_brate", n, id, ENC ) ); + + dbgwrite( &st->coder_type, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type", n, id, ENC ) ); + dbgwrite( &st->coder_type_raw, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "coder_type_raw", n, id, ENC ) ); + dbgwrite( &st->vad_flag, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "vad_flag", n, id, ENC ) ); + dbgwrite( &st->localVAD, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "localVAD", n, id, ENC ) ); + } + } + } +#endif + pop_wmops(); return error; diff --git a/lib_enc/ivas_omasa_enc.c b/lib_enc/ivas_omasa_enc.c index 102a8307b..8c6052933 100644 --- a/lib_enc/ivas_omasa_enc.c +++ b/lib_enc/ivas_omasa_enc.c @@ -666,6 +666,10 @@ void ivas_set_ism_importance_interformat( void ivas_set_surplus_brate_enc( Encoder_Struct *st_ivas /* i/o: IVAS encoder structure */ +#ifdef DEBUG_MODE_INFO + , + const int16_t *nb_bits_metadata /* i : number of metadata bits */ +#endif ) { if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) @@ -682,6 +686,31 @@ void ivas_set_surplus_brate_enc( st_ivas->hCPE[0]->brate_surplus = 0; } +#ifdef DEBUG_MODE_INFO + if ( st_ivas->hSCE[0] != NULL ) + { + int16_t input_frame = ( int16_t )( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC ); + float tmpF = 0; + + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + { + tmpF += st_ivas->hSCE[0]->hCoreCoder[0]->total_brate + (float) ( nb_bits_metadata[1] * 50 ); + } + else + { + for ( int16_t i = 0; i < st_ivas->hEncoderConfig->nchan_ism; i++ ) + { + tmpF += st_ivas->hSCE[i]->hCoreCoder[0]->total_brate + (float) ( nb_bits_metadata[i + 1] * 50 ); + } + } + tmpF /= 1000.f; + dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_ISM" ); /* == ism_total_brate incl. ISM MD */ + tmpF = st_ivas->hEncoderConfig->ivas_total_brate / 1000.0f - tmpF; + dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_MASA" ); /* == masa_total_brate incl. MASA MD */ + tmpF = nb_bits_metadata[0] * FRAMES_PER_SEC / 1000.0f; + dbgwrite( &tmpF, 4, 1, input_frame, "res/brate_MASA_MD" ); /* == MASA MD bitrate */ + } +#endif return; } diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index ba36a7a2b..c447a1935 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -171,6 +171,11 @@ ivas_error ivas_sce_enc( flag_16k_smc = 1; } +#ifdef DEBUG_MODE_INFO + dbgwrite( st->input - NS2SA( st->input_Fs, ACELP_LOOK_NS ), sizeof( float ), input_frame, 1, "res/input_DMX" ); + dbgwrite( &st->element_mode, sizeof( int16_t ), 1, input_frame, fname( debug_dir, "element_mode", 0, st->id_element, ENC ) ); +#endif + /*----------------------------------------------------------------* * Front Pre-processing @@ -275,6 +280,13 @@ ivas_error ivas_sce_enc( /* Store previous attack detection flag */ st->hTranDet->transientDetector.prev_bIsAttackPresent = st->hTranDet->transientDetector.bIsAttackPresent; +#ifdef DEBUG_MODE_INFO + { + float tmpF = hSCE->element_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, input_frame, fname( debug_dir, "element_brate", 0, sce_id, ENC ) ); + } +#endif + pop_wmops(); diff --git a/lib_enc/ivas_stereo_ica_enc.c b/lib_enc/ivas_stereo_ica_enc.c index 428489882..086b247a4 100644 --- a/lib_enc/ivas_stereo_ica_enc.c +++ b/lib_enc/ivas_stereo_ica_enc.c @@ -928,6 +928,9 @@ void stereo_tca_enc( hStereoTCA->corrStatsSmoothFac = 0.7f; estDownmixGain( hStereoTCA, ptrChanL, ptrChanR, 0, input_frame, hCPE->element_mode, NULL, 0 ); hStereoTCA->prevTargetGain = hStereoTCA->targetGain; +#ifdef DEBUG_MODE_INFO + hStereoTCA->indx_ica_NCShift = 0; +#endif /* back up the L/R missing target */ mvr2r( bufChanL + input_frame, hStereoTCA->memChanL, lMemRecalc + lMemRecalc_SCh ); diff --git a/lib_enc/ivas_stereo_td_enc.c b/lib_enc/ivas_stereo_td_enc.c index 8a388ca92..cc02e1fb5 100644 --- a/lib_enc/ivas_stereo_td_enc.c +++ b/lib_enc/ivas_stereo_td_enc.c @@ -254,6 +254,10 @@ ivas_error stereo_set_tdm( hCPE->hStereoTD->tdm_LRTD_flag = hCPE->hStereoTD->prev_fr_LRTD_TD_dec; } +#ifdef DEBUG_MODE_INFO + dbgwrite( &hCPE->hStereoTD->tdm_LRTD_flag, 2, 1, ( int16_t )( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); +#endif + /* normal TD / LRTD switching */ if ( hCPE->hStereoTD->tdm_LRTD_flag == 0 ) @@ -351,6 +355,12 @@ ivas_error stereo_set_tdm( } else { +#ifdef DEBUG_MODE_INFO + { + int16_t tmp = -2; + dbgwrite( &tmp, 2, 1, ( int16_t )( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); + } +#endif hCPE->hCoreCoder[0]->tdm_LRTD_flag = 0; hCPE->hCoreCoder[1]->tdm_LRTD_flag = 0; } diff --git a/lib_enc/speech_music_classif_fx.c b/lib_enc/speech_music_classif_fx.c index bba2c502a..40adab4f0 100644 --- a/lib_enc/speech_music_classif_fx.c +++ b/lib_enc/speech_music_classif_fx.c @@ -2136,10 +2136,6 @@ int16_t ivas_smc_gmm( mvs2s( &hSpMusClas->past_dec[0], &hSpMusClas->past_dec[1], HANG_LEN - 2 ); hSpMusClas->past_dec[0] = dec; -#ifdef DEBUG_MODE_INFO - dbgwrite( &st->hSpMusClas->wdlp_0_95_sp, sizeof( float ), 1, 1, "res/wdlp_0_95_sp.x" ); -#endif - return dec; } -- GitLab From 4be6ffdb7408dd309ea219dd2690e0fb91a6c2ec Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Tue, 25 Jun 2024 13:32:41 +0200 Subject: [PATCH 04/10] compare binary encoder files based on their histograms --- tests/cmp_bin_files.py | 89 +++ .../test_param_file.py | 726 ++++++++++++++++++ tests/constants.py | 33 + 3 files changed, 848 insertions(+) create mode 100644 tests/cmp_bin_files.py create mode 100644 tests/codec_be_on_mr_nonselection/test_param_file.py create mode 100644 tests/constants.py diff --git a/tests/cmp_bin_files.py b/tests/cmp_bin_files.py new file mode 100644 index 000000000..2c6fe59b2 --- /dev/null +++ b/tests/cmp_bin_files.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys +import pdb + +THIS_PATH = os.path.join(os.getcwd(), __file__) +sys.path.append(os.path.join(os.path.dirname(THIS_PATH), "../scripts")) + +import numpy as np +import pyaudio3dtools +import pyivastest +from collections import OrderedDict + + +def cmp_bin_files(ref_file, cut_file, dtype=np.int16, nsamples_per_frame=960, len_check=0, min_diff_thr=0.1) -> (int, str): + """ + Compare two int16 binary files based on their histograms + """ + print(f"Comparing {os.path.basename(ref_file)} between Ref and Dut ... ", end="") + + # read the files + with open(ref_file, "r") as f: + ref = np.fromfile(f, dtype=dtype) + + with open(cut_file, "r") as f: + cut = np.fromfile(f, dtype=dtype) + + # remove the duplicates of each value + if nsamples_per_frame > 1: + ref = ref[::nsamples_per_frame] + cut = cut[::nsamples_per_frame] + + # check the lengths + N = ref.shape[0] + cut.shape[0] + if len_check and ref.shape != cut.shape: + print( f"files have different length, ref: {ref.shape[0]}, cut: {cut.shape[0]}" ) + result = 1 + reason = f"files have different length!" + return result, reason + + # calculate histograms from data + unique_values = np.sort(np.unique(np.concatenate([ref, cut]))) + ref_hist,_ = np.histogram(ref, bins=np.append(unique_values, unique_values[-1] + 10)) + cut_hist,_ = np.histogram(cut, bins=np.append(unique_values, unique_values[-1] + 10)) + diff_hist = cut_hist - ref_hist + + # convert to dict and sort by absolute value of difference + diff = {unique_values[i]: diff_hist[i] for i in range(len(unique_values))} + diff = dict(sorted(diff.items(), key=lambda k: abs(k[1]), reverse=True)) + + # calcualte the total number of differences + total_num_diff = sum(np.abs(list(diff.values()))) + total_num_diff_ratio = total_num_diff / N + + if total_num_diff_ratio > min_diff_thr: + print( f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%), exceeding the threshold of {(min_diff_thr*100):.2f}%!" ) + result = 1 + reason = f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%), exceeding the threshold of {(min_diff_thr*100):.2f}%!" + elif total_num_diff_ratio > 0 and total_num_diff_ratio < min_diff_thr: + print( f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)." ) + result = 0 + reason = f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)." + else: + print( f"files are bit-exact." ) + result = 0 + reason = f"files are bit-exact." + + return result, reason + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("ref_file", type=str) + parser.add_argument("cut_file", type=str) + parser.add_argument("--data_type", type=str, default='int16', dest="dtype") + parser.add_argument("--nsamples_per_frame", type=str, default=960, dest="nsamples_per_frame") + parser.add_argument("--len_check", type=int, default=0, dest="len_check") + parser.add_argument("--min_diff_thr", type=float, default=0.0, dest="min_diff_thr") + args = parser.parse_args() + + # convert dtype from str + if isinstance(args.dtype, str): + args.dtype = np.dtype(getattr(np, args.dtype)) + + result, msg = cmp_bin_files(**vars(args)) + print(msg) + sys.exit(result) diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py new file mode 100644 index 000000000..770f89edb --- /dev/null +++ b/tests/codec_be_on_mr_nonselection/test_param_file.py @@ -0,0 +1,726 @@ +__copyright__ = """ +(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository. All Rights Reserved. + +This software is protected by copyright law and by international treaties. +The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, +Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., +Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, +Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other +contributors to this repository retain full ownership rights in their respective contributions in +the software. This notice grants no license of any kind, including but not limited to patent +license, nor is any license granted by implication, estoppel or otherwise. + +Contributors are required to enter into the IVAS codec Public Collaboration agreement before making +contributions. + +This software is provided "AS IS", without any express or implied warranties. The software is in the +development stage. It is intended exclusively for experts who have experience with such software and +solely for the purpose of inspection. All implied warranties of non-infringement, merchantability +and fitness for a particular purpose are hereby disclaimed and excluded. + +Any dispute, controversy or claim arising under or in relation to providing this software shall be +submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in +accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and +the United Nations Convention on Contracts on the International Sales of Goods. +""" + +__doc__ = """ +Execute tests specified via a parameter file. +""" + +import errno +import filecmp +import os +import re +import platform +from pathlib import Path +from subprocess import run +import pytest +import glob +import tempfile +import numpy as np +import shutil + +from tests.cmp_pcm import cmp_pcm +from tests.cmp_bin_files import cmp_bin_files +from tests.conftest import DecoderFrontend, EncoderFrontend +from tests.testconfig import PARAM_FILE +from ..constants import MLD_PATTERN, MAX_DIFF_PATTERN, ENC_AUX_FILES, MAX_ENC_DIFF_PATTERN + +import pdb + +VALID_DEC_OUTPUT_CONF = [ + "MONO", + "STEREO", + "5_1", + "7_1", + "5_1_2", + "5_1_4", + "7_1_4", + "FOA", + "HOA2", + "HOA3", + "BINAURAL", + "BINAURAL_ROOM_IR", + "BINAURAL_ROOM_REVERB", + "EXT", +] + +param_file_test_dict = {} +with open(PARAM_FILE, "r", encoding="UTF-8") as fp: + data = fp.read() + blocks = data.split("\n\n") + for block in blocks: + tag = "" + enc_opts = "" + dec_opts = "" + sim_opts = "" + eid_opts = "" + for line in block.split("\n"): + if line.startswith("// "): + tag = line[3:] + if line.startswith("../IVAS_cod "): + enc_opts = line[12:] + if line.startswith("../IVAS_dec "): + dec_opts = line[12:] + if line.startswith("networkSimulator_g192 "): + sim_opts = line[22:] + if line.startswith("eid-xor "): + eid_opts = line[8:] + if tag == "" or enc_opts == "" or dec_opts == "": + # no complete parameter set + continue + if tag in param_file_test_dict: + print("non-unique tag found - ignoring new entry") + continue + param_file_test_dict[tag] = (enc_opts, dec_opts, sim_opts, eid_opts) + + +def check_and_makedir(dir_path): + if not os.path.exists(dir_path): + try: + os.makedirs(dir_path) + except OSError as e: + if e.errno != errno.EEXIST: + raise # raises the error again + + +def convert_test_string_to_tag(test_string): + """ + Convert a test string (i.e. the test tag from the parameter file) to a tag string. + Example: + in: "DFT stereo at 13.2 kbps, 16kHz in, 16kHz out, DTX on, random FEC at 5%" + out: "DFT_stereo_at_13_2_kbps_16kHz_in_16kHz_out_DTX_on_random_FEC_at_5_" + """ + # replace certain characters by "_" or remove them + tag_str = "" + replace_chars = " %.-()" + remove_chars = "," + for char in test_string: + if char in replace_chars: + tag_str += "_" + elif char not in remove_chars: + tag_str += char + # replace double underscore by single one + tag_str = "_".join(tag_str.split("__")) + return tag_str + + +@pytest.mark.create_ref +@pytest.mark.parametrize("test_tag", list(param_file_test_dict.keys())) +def test_param_file_tests( + record_property, + decoder_only, + dut_encoder_frontend: EncoderFrontend, + dut_decoder_frontend: DecoderFrontend, + ref_encoder_frontend: EncoderFrontend, + ref_decoder_frontend: DecoderFrontend, + reference_path, + dut_base_path, + test_vector_path, + update_ref, + rootdir, + keep_files, + test_tag, + get_mld, + get_mld_lim, + abs_tol, +): + enc_opts, dec_opts, sim_opts, eid_opts = param_file_test_dict[test_tag] + + tag_str = convert_test_string_to_tag(test_tag) + + # evaluate encoder options + enc_split = enc_opts.split() + assert len(enc_split) >= 4 + + # replace "testv/" by test vector path + enc_split = [ + x.replace("testv", f"{test_vector_path}", 1) if x.startswith("testv/") else x + for x in enc_split + ] + + bitstream_file = enc_split.pop() + testv_file = enc_split.pop() + fs = enc_split.pop() + sampling_rate = int(fs) + bitrate = enc_split.pop() + + # bitrate can be a filename: remove leading "../" + if bitrate.startswith("../"): + bitrate = bitrate[3:] + + testv_base = testv_file.split("/")[-1] + if testv_base.endswith(".pcm"): + testv_base = testv_base[:-4] + + assert bitstream_file == "bit" + # in the parameter file, only "bit" is used as bitstream file name + # -> construct bitstream filename + bitstream_file = f"{testv_base}_{tag_str}.192" + + if not decoder_only: + if update_ref == 2: + # generate temp subdir for encoder output files + ref_enc_res_dir = os.path.join(os.path.split(ref_encoder_frontend._path)[0], 'res') + check_and_makedir(ref_enc_res_dir) + ref_enc_dbg_dir = tempfile.TemporaryDirectory(dir=ref_enc_res_dir) + + dut_enc_res_dir = os.path.join(os.path.split(dut_encoder_frontend._path)[0], 'res') + check_and_makedir(dut_enc_res_dir) + dut_enc_dbg_dir = tempfile.TemporaryDirectory(dir=dut_enc_res_dir) + + encode( + dut_encoder_frontend, + ref_encoder_frontend, + reference_path, + dut_base_path, + bitrate, + sampling_rate, + testv_file, + bitstream_file, + enc_split, + update_ref, + ref_enc_dbg_dir = ref_enc_dbg_dir.name, + dut_enc_dbg_dir = dut_enc_dbg_dir.name, + ) + + # compare binary files extracted from the encoder + if update_ref == 2: + msg = "" + max_diff = 0 + for f in ENC_AUX_FILES: + filename = f[0] + dtype = f[1] + fs = int(sampling_rate) * 1000 + if isinstance(f[2], str): + nsamples_per_frame = np.int16(eval(f[2])) + else: + nsamples_per_frame = np.int16(f[2]) + + ref_aux_files = glob.glob(os.path.join(ref_enc_dbg_dir.name, filename + '*')) + ref_aux_files = [os.path.basename(f) for f in ref_aux_files] + dut_aux_files = glob.glob(os.path.join(ref_enc_dbg_dir.name, filename + '*')) + dut_aux_files = [os.path.basename(f) for f in dut_aux_files] + common_aux_files = [f for f in ref_aux_files if f in dut_aux_files] + + for aux_file in common_aux_files: + # compare the contents of each binary file extracted from the encoder based on histogram + output_differs, reason = cmp_bin_files( + os.path.join(ref_enc_dbg_dir.name, aux_file), + os.path.join(dut_enc_dbg_dir.name, aux_file), + dtype=dtype, + nsamples_per_frame=nsamples_per_frame, + len_check=1, + min_diff_thr=0.1, + ) + + # check if the maximum difference has been exceeded + if output_differs: + msg += reason + search_result = re.search(MAX_ENC_DIFF_PATTERN, reason) + + if search_result: + diff = search_result.groups(1)[0] + diff = np.float(diff) + if diff > max_diff: + max_diff = diff + else: + msg = "Error " + MAX_ENC_DIFF_PATTERN + " not found" + print(msg) + pytest.fail(msg) + + if max_diff > 0: + record_property("MAXIMUM ENC DIFF", max_diff) + + if msg: + pytest.fail(reason) + + # remove encoder output files to save disk space + if ref_enc_dbg_dir: + shutil.rmtree(ref_enc_dbg_dir.name) + + if dut_enc_dbg_dir: + shutil.rmtree(dut_enc_dbg_dir.name) + + # check for networkSimulator_g192 command line + if sim_opts != "": + sim_split = sim_opts.split() + assert len(sim_split) == 6, "networkSimulator_g192 expects 6 parameters" + # [sim_profile, sim_input, sim_output, sim_trace, sim_nFPP, sim_offset] = sim_split + if sim_split[0].startswith(("../")): + # remove leading "../" + sim_split[0] = sim_split[0][3:] + assert sim_split[1] == "bit" + # in the parameter file, only "bit" is used as bitstream file name + # -> re-use bitstream filename from encoder call + sim_split[1] = bitstream_file + assert sim_split[2] == "netsimoutput" + # in the parameter file, only "netsimoutput" is used as netsim output file name + # -> construct netsim output file name + netsim_outfile = f"{testv_base}_{tag_str}.netsimout" + sim_split[2] = netsim_outfile + assert sim_split[3] == "tracefile_sim" + # in the parameter file, only "tracefile_sim" is used as trace output file name + # -> construct trace output file name + netsim_trace_outfile = f"{testv_base}_{tag_str}.netsimtrace" + sim_split[3] = netsim_trace_outfile + simulate( + reference_path, + dut_base_path, + sim_split, + update_ref, + rootdir, + decoder_only, + ) + + # check for eid-xor command line + if eid_opts != "": + eid_split = eid_opts.split() + assert len(eid_split) >= 3, "eid-xor expects at least 3 parameters" + # [..., in_bs, err_pat_bs, out_bs] = eid_split + if eid_split[-2].startswith(("../")): + # remove leading "../" + eid_split[-2] = eid_split[-2][3:] + assert eid_split[-3] == "bit" + # in the parameter file, only "bit" is used as the input bitstream file name + # -> re-use bitstream filename from encoder call + eid_split[-3] = bitstream_file + assert eid_split[-1] == "bit_error" + # in the parameter file, only "bit_error" is used as the output bitstream file name + # -> construct netsim output file name + eid_xor_outfile = f"{testv_base}_{tag_str}.fer.192" + eid_split[-1] = eid_xor_outfile + error_insertion( + reference_path, + dut_base_path, + eid_split, + update_ref, + rootdir, + decoder_only, + ) + + # evaluate decoder options + dec_split = dec_opts.split() + assert len(dec_split) >= 3 + + # replace "testv/" by test vector path + dec_split = [ + x.replace("testv", f"{test_vector_path}", 1) if x.startswith("testv/") else x + for x in dec_split + ] + # remove leading "../" + dec_split = [x[3:] if x.startswith("../") else x for x in dec_split] + + output_file = dec_split.pop() + bitstream_file_dec = dec_split.pop() + sampling_rate = int(dec_split.pop()) + if len(dec_split) > 0: + output_config = dec_split.pop() + if output_config.upper() not in VALID_DEC_OUTPUT_CONF: + if not output_config.endswith(".txt"): + # must be EVS tests with additional parameters - put param back + dec_split.append(output_config) + output_config = "" + else: + output_config = "" + + output_config_name = output_config + if "/" in output_config: + # the output config is a file + output_config_name = os.path.splitext(os.path.basename(output_config))[0] + + tracefile_dec = "" + if sim_opts != "": + assert bitstream_file_dec == "netsimoutput" + # in the parameter file, only "netsimoutput" is used as bitstream file name + # -> re-use netsim_outfile + bitstream_file = netsim_outfile + tracefile_dec = f"{testv_base}_{tag_str}.dectrace" + elif eid_opts != "": + assert bitstream_file_dec == "bit_error" + # in the parameter file, only "bit_error" is used as bitstream input file name + # -> re-use eid_xor_outfile + bitstream_file = eid_xor_outfile + else: + assert bitstream_file_dec == "bit" + # in the parameter file, only "bit" is used as bitstream file name + # -> re-use bitstream filename from encoder call + + # the output file is not the real output filename + # -> construct output filename + output_file = f"{testv_base}_{tag_str}.dec.wav" + + stdout = decode( + dut_decoder_frontend, + ref_decoder_frontend, + reference_path, + dut_base_path, + output_config, + sampling_rate, + bitstream_file, + output_file, + dec_split, + update_ref, + tracefile_dec, + decoder_only, + ) + + if update_ref in [0, 2]: + dut_output_file = f"{dut_base_path}/param_file/dec/{output_file}" + ref_output_file = f"{reference_path}/param_file/dec/{output_file}" + fs = int(sampling_rate) * 1000 + output_differs, reason = cmp_pcm( + dut_output_file, + ref_output_file, + output_config, + fs, + get_mld=get_mld, + mld_lim=get_mld_lim, + abs_tol=abs_tol, + ) + md_out_files = get_expected_md_files(ref_output_file, enc_split, output_config) + + if get_mld: + mld = re.search(MLD_PATTERN, reason).groups(1)[0] + record_property("MLD", mld) + + max_diff =0 + if output_differs: + search_result = re.search(MAX_DIFF_PATTERN, reason) + if search_result: + max_diff = search_result.groups(1)[0] + else: + msg = "Error " + MAX_DIFF_PATTERN + " not found" + print(msg) + pytest.fail(msg) + record_property("MAXIMUM ABS DIFF", max_diff) + + metadata_differs = False + for md_file in md_out_files: + dut_metadata_file = Path(f"{dut_base_path}/param_file/dec/{md_file}") + ref_metadata_file = Path(f"{reference_path}/param_file/dec/{md_file}") + try: + if not filecmp.cmp(dut_metadata_file, ref_metadata_file): + print("Output metadata differs for file: " + md_file) + metadata_differs = True + except FileNotFoundError: + if not dut_metadata_file.exists(): + print("DUT output metadata missing for expected file: " + md_file) + if not ref_metadata_file.exists(): + print("REF output metadata missing for expected file: " + md_file) + metadata_differs = True + + if get_mld and get_mld_lim > 0: + if output_differs: + pytest.fail(reason) + else: + if output_differs or metadata_differs: + msg = "Difference between ref and dut in " + if output_differs and metadata_differs: + msg += f"output ({reason}) and metadata" + elif output_differs: + msg += f"output only ({reason})" + elif metadata_differs: + msg += "metadata only" + pytest.fail(msg) + + # remove DUT output files when test result is OK (to save disk space) + if not keep_files: + os.remove(f"{dut_base_path}/param_file/dec/{output_file}") + if not decoder_only: + os.remove(f"{dut_base_path}/param_file/enc/{bitstream_file}") + if sim_opts != "": + os.remove( + f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192" + ) + os.remove(f"{dut_base_path}/param_file/enc/{netsim_trace_outfile}") + os.remove(f"{dut_base_path}/param_file/dec/{tracefile_dec}") + elif eid_opts != "": + os.remove( + f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192" + ) + + +def encode( + dut_encoder_frontend, + ref_encoder_frontend, + reference_path, + dut_base_path, + bitrate, + sampling_rate, + testv_file, + bitstream_file, + enc_opts_list, + update_ref, + ref_enc_dbg_dir, + dut_enc_dbg_dir, +): + """ + Call REF and/or DUT encoder. + """ + # directories + dut_out_dir = f"{dut_base_path}/param_file/enc" + ref_out_dir = f"{reference_path}/param_file/enc" + + ref_out_file = f"{ref_out_dir}/{bitstream_file}" + dut_out_file = f"{dut_out_dir}/{bitstream_file}" + + if update_ref == 1 or update_ref == 2 and ( not os.path.exists(ref_out_file) or ref_enc_dbg_dir ): + check_and_makedir(ref_out_dir) + # call REF encoder + ref_encoder_frontend.run( + bitrate, + sampling_rate, + testv_file, + ref_out_file, + add_option_list=enc_opts_list, + enc_dbg_dir=ref_enc_dbg_dir + ) + + if update_ref in [0, 2]: + check_and_makedir(dut_out_dir) + # call DUT encoder + dut_encoder_frontend.run( + bitrate, + sampling_rate, + testv_file, + dut_out_file, + add_option_list=enc_opts_list, + enc_dbg_dir=dut_enc_dbg_dir + ) + + +def simulate( + reference_path, + dut_base_path, + sim_opts_list, + update_ref, + rootdir, + decoder_only, +): + """ + Call network simulator on REF and/or DUT encoder output. + """ + # directories + dut_out_dir = f"{dut_base_path}/param_file/enc" + ref_out_dir = f"{reference_path}/param_file/enc" + + netsim_infile = sim_opts_list[1] + netsim_outfile = sim_opts_list[2] + netsim_tracefile = sim_opts_list[3] + ref_out_file = f"{ref_out_dir}/{netsim_outfile}" + + if platform.system() == "Windows": + netsim = [ + os.path.join( + rootdir, "scripts", "tools", "Win32", "networkSimulator_g192.exe" + ) + ] + elif platform.system() in ["Linux", "Darwin"]: + netsim = [ + os.path.join( + rootdir, "scripts", "tools", platform.system(), "networkSimulator_g192" + ) + ] + else: + assert False, f"networkSimulator_g192 not available for {platform.system()}" + + cmd_opts = sim_opts_list + if ( + update_ref == 1 + or (update_ref == 2 and not os.path.exists(ref_out_file)) + or decoder_only + ): + # call network simulator on REF encoder output + cmd_opts[1] = f"{ref_out_dir}/{netsim_infile}" + cmd_opts[2] = f"{ref_out_dir}/{netsim_outfile}" # ref_out_file + elif update_ref in [0, 2]: + # call network simulator on DUT encoder output + cmd_opts[1] = f"{dut_out_dir}/{netsim_infile}" + cmd_opts[2] = f"{dut_out_dir}/{netsim_outfile}" # dut_out_file + + if update_ref == 1 or (update_ref == 2 and not os.path.exists(ref_out_file)): + cmd_opts[3] = f"{ref_out_dir}/{netsim_tracefile}" + cmd_opts[2] = f"{ref_out_dir}/{netsim_outfile}" # ref_out_file + elif update_ref in [0, 2]: + cmd_opts[3] = f"{dut_out_dir}/{netsim_tracefile}" + cmd_opts[2] = f"{dut_out_dir}/{netsim_outfile}" # dut_out_file + + run(netsim + cmd_opts, check=False) + + +def error_insertion( + reference_path, + dut_base_path, + eid_opts_list, + update_ref, + rootdir, + decoder_only, +): + """ + Call eid-xor to insert frame erasure on REF and/or DUT encoder output. + """ + + # directories + dut_out_dir = f"{dut_base_path}/param_file/enc" + ref_out_dir = f"{reference_path}/param_file/enc" + + eid_xor_infile = eid_opts_list[-3] + eid_xor_outfile = eid_opts_list[-1] + ref_out_file = f"{ref_out_dir}/{eid_xor_outfile}" + + if platform.system() == "Windows": + eid_xor = [os.path.join(rootdir, "scripts", "tools", "Win32", "eid-xor.exe")] + elif platform.system() in ["Linux", "Darwin"]: + eid_xor = [ + os.path.join(rootdir, "scripts", "tools", platform.system(), "eid-xor") + ] + else: + assert False, f"eid-xor not available for {platform.system()}" + + cmd_opts = eid_opts_list + + if ( + update_ref == 1 + or (update_ref == 2 and not os.path.exists(ref_out_file)) + or decoder_only + ): + # call eid-xor on REF encoder output + cmd_opts[-3] = f"{ref_out_dir}/{eid_xor_infile}" + elif update_ref in [0, 2]: + # call eid-xor on DUT encoder output + cmd_opts[-3] = f"{dut_out_dir}/{eid_xor_infile}" + + if update_ref == 1 or (update_ref == 2 and not os.path.exists(ref_out_file)): + cmd_opts[-1] = f"{ref_out_dir}/{eid_xor_outfile}" # ref_out_file + elif update_ref in [0, 2]: + cmd_opts[-1] = f"{dut_out_dir}/{eid_xor_outfile}" # ref_out_file + + run(eid_xor + cmd_opts, check=False) + + +def decode( + decoder_frontend, + ref_decoder_frontend, + reference_path, + dut_base_path, + output_config, + sampling_rate, + bitstream_file, + output_file, + dec_opts_list, + update_ref, + tracefile_dec, + decoder_only, +): + """ + Call REF and/or DUT decoder. + """ + # directories + dut_out_dir = f"{dut_base_path}/param_file/dec" + ref_out_dir = f"{reference_path}/param_file/dec" + + dut_in_file = f"{dut_base_path}/param_file/enc/{bitstream_file}" + ref_in_file = f"{reference_path}/param_file/enc/{bitstream_file}" + dut_out_file = f"{dut_out_dir}/{output_file}" + ref_out_file = f"{ref_out_dir}/{output_file}" + + if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): + check_and_makedir(ref_out_dir) + add_option_list = dec_opts_list + if tracefile_dec != "": + add_option_list = [ + x if x != "tracefile_dec" else f"{ref_out_dir}/{tracefile_dec}" + for x in dec_opts_list + ] + # call REF decoder + ref_decoder_frontend.run( + output_config, + sampling_rate, + ref_in_file, + ref_out_file, + add_option_list=add_option_list, + ) + + stdout = ref_decoder_frontend.stdout + + if update_ref in [0, 2]: + check_and_makedir(dut_out_dir) + add_option_list = dec_opts_list + if tracefile_dec != "": + add_option_list = [ + x if x != "tracefile_dec" else f"{dut_out_dir}/{tracefile_dec}" + for x in dec_opts_list + ] + + if decoder_only: + dut_in_file = ref_in_file + + # call DUT decoder + decoder_frontend.run( + output_config, + sampling_rate, + dut_in_file, + dut_out_file, + add_option_list=add_option_list, + ) + + stdout = decoder_frontend.stdout + + return stdout + + +def get_expected_md_files(ref_output_file, enc_opts, output_config): + """ + Based on input and output configs, get the filenames of MD files that are expected to being output by the decoder + """ + + if output_config.upper() != "EXT": + return list() + + md_files = list() + enc_opts_upper = [o.upper() for o in enc_opts] + md_filename = Path(ref_output_file).name + + if any([o in enc_opts_upper for o in ["-MASA", "-ISM_MASA"]]): + # always only one MD file, just add ending + md_files.append(md_filename + ".met") + + for ism_opt in ["-ISM", "-ISM_MASA", "-ISM_SBA"]: + # for ism MD, there are three modes that may output MD files + # try to find any of them in the encoder options + md_tmpl = md_filename + ".{}.csv" + try: + idx = enc_opts_upper.index(ism_opt) + ism_num = int(enc_opts[idx + 1]) + md_files.extend([md_tmpl.format(i) for i in range(ism_num)]) + break + except ValueError: + pass + + return md_files diff --git a/tests/constants.py b/tests/constants.py new file mode 100644 index 000000000..12e9a8157 --- /dev/null +++ b/tests/constants.py @@ -0,0 +1,33 @@ +import numpy as np + +# regex patterns for parsing the output from cmp_pcm -> mainly for BASOP ci +MLD_PATTERN = r"MLD: ([\d\.]*)" +MAX_DIFF_PATTERN = r"MAXIMUM ABS DIFF: (\d*)" +MAX_ENC_DIFF_PATTERN = r"The total number of differences is \d (\d+\.\d+)%" + +# list of encoder filename patterns with their data type and number of samples per frame +# note: instead of specifying the number of samples per frame, you can use a formula incl. 'fs', e.g. 'fs/50' +ENC_AUX_FILES = [ + ['bits_nominal', np.int16, 'fs/50'], + ['bwidth', np.int16, 'fs/50'], + ['clas', np.int16, 'fs/50'], + ['cng_type', np.int16, 'fs/50'], + ['coder_type', np.int16, 'fs/50'], + ['core', np.int16, 'fs/50'], + ['core_brate', np.float32, 640], + ['count_SWB', np.int16, 'fs/50'], + ['count_WB', np.int16, 'fs/50'], + ['element_brate', np.float32, 'fs/50'], + ['element_mode', np.int16, 'fs/50'], + ['extl', np.int16, 'fs/50'], + ['extl_brate', np.float32, 'fs/50'], + ['ivas_total_brate', np.float32, 'fs/50'], + ['L_frame', np.int16, 'fs/50'], + ['localVAD', np.int16, 'fs/50'], + ['sp_aud_decision0', np.int16, 'fs/50'], + ['sp_aud_decision1', np.int16, 'fs/50'], + ['sp_aud_decision2', np.int16, 'fs/50'], + ['tdm_LRTD_flag', np.int16, 'fs/50'], + ['total_brate', np.float32, 'fs/50'], + ['vad_flag', np.int16, 'fs/50'] +] -- GitLab From 8f9b5f8d7e32fefd36dc1a7ca1c8c6dbe8e97493 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 26 Jun 2024 10:36:45 +0200 Subject: [PATCH 05/10] fix wrong glob dir for Dut --- tests/codec_be_on_mr_nonselection/test_param_file.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py index 770f89edb..eb662d292 100644 --- a/tests/codec_be_on_mr_nonselection/test_param_file.py +++ b/tests/codec_be_on_mr_nonselection/test_param_file.py @@ -211,6 +211,9 @@ def test_param_file_tests( # compare binary files extracted from the encoder if update_ref == 2: + print ("Comparing encoder auxiliary files") + print ("=================================\n") + msg = "" max_diff = 0 for f in ENC_AUX_FILES: @@ -224,7 +227,7 @@ def test_param_file_tests( ref_aux_files = glob.glob(os.path.join(ref_enc_dbg_dir.name, filename + '*')) ref_aux_files = [os.path.basename(f) for f in ref_aux_files] - dut_aux_files = glob.glob(os.path.join(ref_enc_dbg_dir.name, filename + '*')) + dut_aux_files = glob.glob(os.path.join(dut_enc_dbg_dir.name, filename + '*')) dut_aux_files = [os.path.basename(f) for f in dut_aux_files] common_aux_files = [f for f in ref_aux_files if f in dut_aux_files] @@ -254,6 +257,8 @@ def test_param_file_tests( print(msg) pytest.fail(msg) + print ("") + if max_diff > 0: record_property("MAXIMUM ENC DIFF", max_diff) -- GitLab From 9db4588ae17f553b28e2e481ac6bf5fcc5a4d701 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Thu, 27 Jun 2024 11:05:27 +0200 Subject: [PATCH 06/10] improve printout messages --- tests/cmp_bin_files.py | 50 ++++++++++++------- .../test_param_file.py | 35 +++++++------ tests/constants.py | 3 +- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/tests/cmp_bin_files.py b/tests/cmp_bin_files.py index 2c6fe59b2..9ad7f74b1 100644 --- a/tests/cmp_bin_files.py +++ b/tests/cmp_bin_files.py @@ -27,18 +27,26 @@ def cmp_bin_files(ref_file, cut_file, dtype=np.int16, nsamples_per_frame=960, le with open(cut_file, "r") as f: cut = np.fromfile(f, dtype=dtype) - # remove the duplicates of each value + # remove the duplicates of each value per frame if nsamples_per_frame > 1: ref = ref[::nsamples_per_frame] cut = cut[::nsamples_per_frame] - # check the lengths - N = ref.shape[0] + cut.shape[0] + reason = f"File {os.path.basename(ref_file)}" + + # check file lengths + result_len_check = 0 if len_check and ref.shape != cut.shape: - print( f"files have different length, ref: {ref.shape[0]}, cut: {cut.shape[0]}" ) - result = 1 - reason = f"files have different length!" - return result, reason + print(f"files have different length: Ref {ref.shape[0]}, DuT {cut.shape[0]}, ", end="") + reason += f" has different length between Ref ({ref.shape[0]}) and DuT ({cut.shape[0]}), " + + # check if threshold has been exceeded + if abs(ref.shape[0] - cut.shape[0]) / max(ref.shape[0], cut.shape[0]) > min_diff_thr: + result_len_check = 1 + else: + result_len_check = 0 + else: + reason += ": " # calculate histograms from data unique_values = np.sort(np.unique(np.concatenate([ref, cut]))) @@ -50,22 +58,26 @@ def cmp_bin_files(ref_file, cut_file, dtype=np.int16, nsamples_per_frame=960, le diff = {unique_values[i]: diff_hist[i] for i in range(len(unique_values))} diff = dict(sorted(diff.items(), key=lambda k: abs(k[1]), reverse=True)) - # calcualte the total number of differences + # calculate the total number of differences total_num_diff = sum(np.abs(list(diff.values()))) - total_num_diff_ratio = total_num_diff / N + total_num_diff_ratio = total_num_diff / max(ref.shape[0], cut.shape[0]) if total_num_diff_ratio > min_diff_thr: - print( f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%), exceeding the threshold of {(min_diff_thr*100):.2f}%!" ) - result = 1 - reason = f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%), exceeding the threshold of {(min_diff_thr*100):.2f}%!" - elif total_num_diff_ratio > 0 and total_num_diff_ratio < min_diff_thr: - print( f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)." ) - result = 0 - reason = f"files are different, total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)." + msg = f"the total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%), exceeding the threshold of {(min_diff_thr*100):.2f}%!" + reason += msg + print(msg, end="") + result_diff_check = 1 else: - print( f"files are bit-exact." ) - result = 0 - reason = f"files are bit-exact." + msg = f"the total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)." + reason += msg + print( msg, end="" ) + result_diff_check = 0 + + print("") + + result = 0 + if result_len_check or result_diff_check: + result = 1 return result, reason diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py index eb662d292..a3059a791 100644 --- a/tests/codec_be_on_mr_nonselection/test_param_file.py +++ b/tests/codec_be_on_mr_nonselection/test_param_file.py @@ -215,7 +215,8 @@ def test_param_file_tests( print ("=================================\n") msg = "" - max_diff = 0 + max_enc_diff = 0 + enc_test_result = 0 for f in ENC_AUX_FILES: filename = f[0] dtype = f[1] @@ -242,29 +243,22 @@ def test_param_file_tests( min_diff_thr=0.1, ) - # check if the maximum difference has been exceeded if output_differs: + enc_test_result = 1 + if msg: + msg += ", " msg += reason - search_result = re.search(MAX_ENC_DIFF_PATTERN, reason) - if search_result: - diff = search_result.groups(1)[0] - diff = np.float(diff) - if diff > max_diff: - max_diff = diff - else: - msg = "Error " + MAX_ENC_DIFF_PATTERN + " not found" - print(msg) - pytest.fail(msg) + # check if the maximum difference has been exceeded + search_result = re.search(MAX_ENC_DIFF_PATTERN, reason) + if search_result: + diff = search_result.groups(1)[0] + diff = float(diff) + if diff > max_enc_diff: + max_enc_diff = diff print ("") - if max_diff > 0: - record_property("MAXIMUM ENC DIFF", max_diff) - - if msg: - pytest.fail(reason) - # remove encoder output files to save disk space if ref_enc_dbg_dir: shutil.rmtree(ref_enc_dbg_dir.name) @@ -272,6 +266,11 @@ def test_param_file_tests( if dut_enc_dbg_dir: shutil.rmtree(dut_enc_dbg_dir.name) + if enc_test_result: + record_property("MAXIMUM ENC DIFF", max_enc_diff) + pytest.fail(msg) + + # check for networkSimulator_g192 command line if sim_opts != "": sim_split = sim_opts.split() diff --git a/tests/constants.py b/tests/constants.py index 12e9a8157..23dbef0b8 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -3,7 +3,8 @@ import numpy as np # regex patterns for parsing the output from cmp_pcm -> mainly for BASOP ci MLD_PATTERN = r"MLD: ([\d\.]*)" MAX_DIFF_PATTERN = r"MAXIMUM ABS DIFF: (\d*)" -MAX_ENC_DIFF_PATTERN = r"The total number of differences is \d (\d+\.\d+)%" +MAX_ENC_DIFF_PATTERN = r"total number of differences is \d+ \((\d+\.\d+)%\)" + # list of encoder filename patterns with their data type and number of samples per frame # note: instead of specifying the number of samples per frame, you can use a formula incl. 'fs', e.g. 'fs/50' -- GitLab From 68f0a023f90ee49d6178ecdb54461a5e369607d6 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 3 Jul 2024 12:56:32 +0200 Subject: [PATCH 07/10] store statistics in .stats file --- .../test_param_file.py | 324 ++++++++++++++---- tests/constants.py | 4 +- 2 files changed, 260 insertions(+), 68 deletions(-) diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py index a3059a791..cb17ce668 100644 --- a/tests/codec_be_on_mr_nonselection/test_param_file.py +++ b/tests/codec_be_on_mr_nonselection/test_param_file.py @@ -44,12 +44,13 @@ import glob import tempfile import numpy as np import shutil +import json from tests.cmp_pcm import cmp_pcm from tests.cmp_bin_files import cmp_bin_files from tests.conftest import DecoderFrontend, EncoderFrontend from tests.testconfig import PARAM_FILE -from ..constants import MLD_PATTERN, MAX_DIFF_PATTERN, ENC_AUX_FILES, MAX_ENC_DIFF_PATTERN +from ..constants import MLD_PATTERN, MAX_DIFF_PATTERN, ENC_AUX_FILES, MAX_ENC_DIFF_PATTERN, MIN_ENC_AUX_FILE_DIFF_THR, MIN_ENC_AUX_FILE_LENGTH_DIFF import pdb @@ -129,11 +130,20 @@ def convert_test_string_to_tag(test_string): tag_str = "_".join(tag_str.split("__")) return tag_str +def num(s): + """ + Convert string either to integer or float + """ + try: + return int(s) + except ValueError: + return float(s) @pytest.mark.create_ref @pytest.mark.parametrize("test_tag", list(param_file_test_dict.keys())) def test_param_file_tests( record_property, + encoder_only, decoder_only, dut_encoder_frontend: EncoderFrontend, dut_decoder_frontend: DecoderFrontend, @@ -184,15 +194,6 @@ def test_param_file_tests( bitstream_file = f"{testv_base}_{tag_str}.192" if not decoder_only: - if update_ref == 2: - # generate temp subdir for encoder output files - ref_enc_res_dir = os.path.join(os.path.split(ref_encoder_frontend._path)[0], 'res') - check_and_makedir(ref_enc_res_dir) - ref_enc_dbg_dir = tempfile.TemporaryDirectory(dir=ref_enc_res_dir) - - dut_enc_res_dir = os.path.join(os.path.split(dut_encoder_frontend._path)[0], 'res') - check_and_makedir(dut_enc_res_dir) - dut_enc_dbg_dir = tempfile.TemporaryDirectory(dir=dut_enc_res_dir) encode( dut_encoder_frontend, @@ -205,71 +206,174 @@ def test_param_file_tests( bitstream_file, enc_split, update_ref, - ref_enc_dbg_dir = ref_enc_dbg_dir.name, - dut_enc_dbg_dir = dut_enc_dbg_dir.name, + encoder_only, ) # compare binary files extracted from the encoder - if update_ref == 2: + if encoder_only: print ("Comparing encoder auxiliary files") print ("=================================\n") - msg = "" - max_enc_diff = 0 + ref_out_dir = f"{reference_path}/param_file/enc" + + stats_file = bitstream_file.replace(".192", ".stats") + ref_stats_file = f"{reference_path}/param_file/enc/{stats_file}" + dut_stats_file = f"{dut_base_path}/param_file/enc/{stats_file}" + + # pdb.set_trace() + + # open and read the .stats file + with open(ref_stats_file, "r") as f_aux: + ref_stats = json.load(f_aux) + # create dictionary to map "name" to the corresponding dictionaries + ref_stats_names = {d["name"]: d for d in ref_stats} + + with open(dut_stats_file, "r") as f_aux: + dut_stats = json.load(f_aux) + # create dictionary to map "name" to the corresponding dictionaries + dut_stats_names = {d["name"]: d for d in dut_stats} + + # loop over all common aux files enc_test_result = 0 - for f in ENC_AUX_FILES: - filename = f[0] - dtype = f[1] - fs = int(sampling_rate) * 1000 - if isinstance(f[2], str): - nsamples_per_frame = np.int16(eval(f[2])) - else: - nsamples_per_frame = np.int16(f[2]) - - ref_aux_files = glob.glob(os.path.join(ref_enc_dbg_dir.name, filename + '*')) - ref_aux_files = [os.path.basename(f) for f in ref_aux_files] - dut_aux_files = glob.glob(os.path.join(dut_enc_dbg_dir.name, filename + '*')) - dut_aux_files = [os.path.basename(f) for f in dut_aux_files] - common_aux_files = [f for f in ref_aux_files if f in dut_aux_files] - - for aux_file in common_aux_files: - # compare the contents of each binary file extracted from the encoder based on histogram - output_differs, reason = cmp_bin_files( - os.path.join(ref_enc_dbg_dir.name, aux_file), - os.path.join(dut_enc_dbg_dir.name, aux_file), - dtype=dtype, - nsamples_per_frame=nsamples_per_frame, - len_check=1, - min_diff_thr=0.1, - ) + enc_test_result_msg = "" + max_enc_diff = 0 + for name in ref_stats_names: + if name in dut_stats_names: + # retrieve the dictionaries + ref_stats_dict = ref_stats_names[name] + dut_stats_dict = dut_stats_names[name] + # ref_stats_dict = ref_stats_names["core_brate"] + # dut_stats_dict = dut_stats_names["total_brate"] - if output_differs: - enc_test_result = 1 - if msg: - msg += ", " - msg += reason + msg = f"File {name}" + + # compare the file lengths + result_len_check = 0 + file_length = max(ref_stats_dict["length"], dut_stats_dict["length"]) + if ref_stats_dict["length"] != dut_stats_dict["length"]: + msg += f" has different length between Ref {ref_stats_dict['length']} and DuT {dut_stats_dict['length']}" + + # check if threshold has been exceeded + if abs(ref_stats_dict["length"] - dut_stats_dict["length"]) / file_length > MIN_ENC_AUX_FILE_LENGTH_DIFF: + result_len_check = 1 + + msg += f", " + + # remove the "name" and "length" keys for further processing + del ref_stats_dict["name"] + del dut_stats_dict["name"] + del ref_stats_dict["length"] + del dut_stats_dict["length"] + # convert keys and values from string to float + ref_hist = {num(i) : num(j) for i,j in ref_stats_dict.items()} + cut_hist = {num(i) : num(j) for i,j in dut_stats_dict.items()} + delta_ref = set(cut_hist) - set(ref_hist) + delta_cut = set(ref_hist) - set(cut_hist) + + # append missing keys + for item in delta_cut: + cut_hist[item] = 0 + + for item in delta_ref: + ref_hist[item] = 0 + + ref_hist = dict(sorted(ref_hist.items())) + cut_hist = dict(sorted(cut_hist.items())) + + # caculate difference of statistics + diff_hist = { k : cut_hist[k] - ref_hist[k] for k in ref_hist.keys()} + + # calculate the total number of differences + total_num_diff = sum(np.abs(list(diff_hist.values()))) + total_num_diff_ratio = total_num_diff / (sum(ref_hist.values()) + sum(cut_hist.values())) + + msg += f"the total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)" + if total_num_diff_ratio > MIN_ENC_AUX_FILE_DIFF_THR: + result_diff_check = 1 + msg += "! " + else: + result_diff_check = 0 + msg += ". " + # check if the maximum difference has been exceeded - search_result = re.search(MAX_ENC_DIFF_PATTERN, reason) - if search_result: - diff = search_result.groups(1)[0] - diff = float(diff) - if diff > max_enc_diff: - max_enc_diff = diff - + if total_num_diff_ratio > max_enc_diff: + max_enc_diff = total_num_diff_ratio + + # update test result + if result_len_check or result_diff_check: + enc_test_result = 1 + enc_test_result_msg += msg + + print(msg) + print ("") - - # remove encoder output files to save disk space - if ref_enc_dbg_dir: - shutil.rmtree(ref_enc_dbg_dir.name) - - if dut_enc_dbg_dir: - shutil.rmtree(dut_enc_dbg_dir.name) - + if enc_test_result: record_property("MAXIMUM ENC DIFF", max_enc_diff) - pytest.fail(msg) + pytest.fail(enc_test_result_msg) + + + + + # msg = "" + # max_enc_diff = 0 + # enc_test_result = 0 + # for f in ENC_AUX_FILES: + # filename = f[0] + # dtype = f[1] + # fs = int(sampling_rate) * 1000 + # if isinstance(f[2], str): + # nsamples_per_frame = np.int16(eval(f[2])) + # else: + # nsamples_per_frame = np.int16(f[2]) + # ref_aux_files = glob.glob(os.path.join(ref_enc_dbg_dir.name, filename + '*')) + # ref_aux_files = [os.path.basename(f) for f in ref_aux_files] + # dut_aux_files = glob.glob(os.path.join(dut_enc_dbg_dir.name, filename + '*')) + # dut_aux_files = [os.path.basename(f) for f in dut_aux_files] + # common_aux_files = [f for f in ref_aux_files if f in dut_aux_files] + + # for aux_file in common_aux_files: + # # compare the contents of each binary file extracted from the encoder based on histogram + # output_differs, reason = cmp_bin_files( + # os.path.join(ref_enc_dbg_dir.name, aux_file), + # os.path.join(dut_enc_dbg_dir.name, aux_file), + # dtype=dtype, + # nsamples_per_frame=nsamples_per_frame, + # len_check=1, + # min_diff_thr=0.1, + # ) + + # if output_differs: + # enc_test_result = 1 + # if msg: + # msg += ", " + # msg += reason + + # # check if the maximum difference has been exceeded + # search_result = re.search(MAX_ENC_DIFF_PATTERN, reason) + # if search_result: + # diff = search_result.groups(1)[0] + # diff = float(diff) + # if diff > max_enc_diff: + # max_enc_diff = diff + + # print ("") + + # # remove encoder output files to save disk space + # if ref_enc_dbg_dir: + # shutil.rmtree(ref_enc_dbg_dir.name) + + # if dut_enc_dbg_dir: + # shutil.rmtree(dut_enc_dbg_dir.name) + + # if enc_test_result: + # record_property("MAXIMUM ENC DIFF", max_enc_diff) + # pytest.fail(msg) + + if encoder_only: + return # check for networkSimulator_g192 command line if sim_opts != "": @@ -481,8 +585,7 @@ def encode( bitstream_file, enc_opts_list, update_ref, - ref_enc_dbg_dir, - dut_enc_dbg_dir, + encoder_only, ): """ Call REF and/or DUT encoder. @@ -493,32 +596,119 @@ def encode( ref_out_file = f"{ref_out_dir}/{bitstream_file}" dut_out_file = f"{dut_out_dir}/{bitstream_file}" + + if encoder_only: + stats_file = bitstream_file.replace(".192", ".stats") + ref_stats_file = f"{ref_out_dir}/{stats_file}" + dut_stats_file = f"{dut_out_dir}/{stats_file}" - if update_ref == 1 or update_ref == 2 and ( not os.path.exists(ref_out_file) or ref_enc_dbg_dir ): + if ( update_ref in [1, 2] and not os.path.exists(ref_out_file) ) or encoder_only: check_and_makedir(ref_out_dir) + + # generate dbg tweak subfolder under /res to store encoder output files + ref_dbg_tweak_folder = os.path.join(os.path.split(ref_encoder_frontend._path)[0], 'res') + check_and_makedir(ref_dbg_tweak_folder) + ref_dbg_tweak_folder = tempfile.TemporaryDirectory(dir=ref_dbg_tweak_folder) + # call REF encoder ref_encoder_frontend.run( bitrate, sampling_rate, testv_file, ref_out_file, + encoder_only=encoder_only, add_option_list=enc_opts_list, - enc_dbg_dir=ref_enc_dbg_dir + dbg_tweak_folder=Path(ref_dbg_tweak_folder.name), ) + + # generate ref encoder stats + if encoder_only: + extract_enc_stats(Path(ref_dbg_tweak_folder.name), ref_stats_file, sampling_rate) + + ref_dbg_tweak_folder.cleanup() - if update_ref in [0, 2]: + if update_ref in [0, 2] or encoder_only: check_and_makedir(dut_out_dir) + + # generate dbg tweak subfolder under /res to store encoder output files + dut_dbg_tweak_folder = os.path.join(os.path.split(dut_encoder_frontend._path)[0], 'res') + check_and_makedir(dut_dbg_tweak_folder) + dut_dbg_tweak_folder = tempfile.TemporaryDirectory(dir=dut_dbg_tweak_folder) + # call DUT encoder dut_encoder_frontend.run( bitrate, sampling_rate, testv_file, dut_out_file, + encoder_only=encoder_only, add_option_list=enc_opts_list, - enc_dbg_dir=dut_enc_dbg_dir + dbg_tweak_folder=Path(dut_dbg_tweak_folder.name), ) + # generate dut encoder stats + if encoder_only: + extract_enc_stats(Path(dut_dbg_tweak_folder.name), dut_stats_file, sampling_rate) + + dut_dbg_tweak_folder.cleanup() + +def extract_enc_stats ( + dbg_tweak_folder, + stats_file, + sampling_rate, +): + """ + Extract statistics from auxiliary encoder files generated by running the encoder with DEBUG_MODE_INFO. + Write the statistics to a text file + """ + + hist_dicts = [] + for f in ENC_AUX_FILES: + filename = f[0] + dtype = f[1] + fs = int(sampling_rate) * 1000 + if isinstance(f[2], str): + nsamples_per_frame = np.int16(eval(f[2])) + else: + nsamples_per_frame = np.int16(f[2]) + + # aux_files = glob.glob(os.path.join(dbg_tweak_folder, filename + '\.*')) + aux_files = [f for f in os.listdir(dbg_tweak_folder) if re.search(rf'^{filename}(\..*)?$', f)] + # aux_files = [os.path.basename(f) for f in aux_files] + + for aux_file in aux_files: + # extract statistics from the aux file based on histogram of values + print(f"Extracting statistics from {os.path.basename(aux_file)} ... ", end="") + + # read the aux file + with open(os.path.join(dbg_tweak_folder, aux_file), "r") as f_aux: + data = np.fromfile(f_aux, dtype=dtype) + + # get file length + data_len = data.shape[0] + + # remove the duplicates of each value per frame + if nsamples_per_frame > 1: + data = data[::nsamples_per_frame] + # calculate histogram from data + unique_values = np.sort(np.unique(data)) + hist, _ = np.histogram(data, bins=np.append(unique_values, unique_values[-1] + 10)) + + # convert to dict and sort by absolute value of difference + hist_dict = {"name" : os.path.basename(aux_file), "length" : data_len} + dict_values = {str(unique_values[i]): str(hist[i]) for i in range(len(unique_values))} + hist_dict.update(dict_values) + hist_dicts.append(hist_dict) + + print(f"DONE") + + print("") + + with open(stats_file, "w") as f_stats: + # append the statistics to the output file in text format + f_stats.write(json.dumps(hist_dicts, indent=2)) + def simulate( reference_path, dut_base_path, diff --git a/tests/constants.py b/tests/constants.py index 23dbef0b8..995d76ab4 100644 --- a/tests/constants.py +++ b/tests/constants.py @@ -5,6 +5,8 @@ MLD_PATTERN = r"MLD: ([\d\.]*)" MAX_DIFF_PATTERN = r"MAXIMUM ABS DIFF: (\d*)" MAX_ENC_DIFF_PATTERN = r"total number of differences is \d+ \((\d+\.\d+)%\)" +MIN_ENC_AUX_FILE_DIFF_THR = 0.1 # minimum ratio of total number of differences in encoder aux file +MIN_ENC_AUX_FILE_LENGTH_DIFF = 0.1 # minimum difference of encoder aux file length # list of encoder filename patterns with their data type and number of samples per frame # note: instead of specifying the number of samples per frame, you can use a formula incl. 'fs', e.g. 'fs/50' @@ -15,7 +17,7 @@ ENC_AUX_FILES = [ ['cng_type', np.int16, 'fs/50'], ['coder_type', np.int16, 'fs/50'], ['core', np.int16, 'fs/50'], - ['core_brate', np.float32, 640], + ['core_brate', np.float32, 'fs/50'], ['count_SWB', np.int16, 'fs/50'], ['count_WB', np.int16, 'fs/50'], ['element_brate', np.float32, 'fs/50'], -- GitLab From fab8bac771761a79da168793afa63ea4339d6967 Mon Sep 17 00:00:00 2001 From: Jan Kiene Date: Wed, 31 Jul 2024 09:04:18 +0200 Subject: [PATCH 08/10] delete test scripts -> they will be pulled in from flt repo --- tests/cmp_bin_files.py | 101 -- .../test_param_file.py | 920 ------------------ tests/constants.py | 36 - 3 files changed, 1057 deletions(-) delete mode 100644 tests/cmp_bin_files.py delete mode 100644 tests/codec_be_on_mr_nonselection/test_param_file.py delete mode 100644 tests/constants.py diff --git a/tests/cmp_bin_files.py b/tests/cmp_bin_files.py deleted file mode 100644 index 9ad7f74b1..000000000 --- a/tests/cmp_bin_files.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import sys -import pdb - -THIS_PATH = os.path.join(os.getcwd(), __file__) -sys.path.append(os.path.join(os.path.dirname(THIS_PATH), "../scripts")) - -import numpy as np -import pyaudio3dtools -import pyivastest -from collections import OrderedDict - - -def cmp_bin_files(ref_file, cut_file, dtype=np.int16, nsamples_per_frame=960, len_check=0, min_diff_thr=0.1) -> (int, str): - """ - Compare two int16 binary files based on their histograms - """ - print(f"Comparing {os.path.basename(ref_file)} between Ref and Dut ... ", end="") - - # read the files - with open(ref_file, "r") as f: - ref = np.fromfile(f, dtype=dtype) - - with open(cut_file, "r") as f: - cut = np.fromfile(f, dtype=dtype) - - # remove the duplicates of each value per frame - if nsamples_per_frame > 1: - ref = ref[::nsamples_per_frame] - cut = cut[::nsamples_per_frame] - - reason = f"File {os.path.basename(ref_file)}" - - # check file lengths - result_len_check = 0 - if len_check and ref.shape != cut.shape: - print(f"files have different length: Ref {ref.shape[0]}, DuT {cut.shape[0]}, ", end="") - reason += f" has different length between Ref ({ref.shape[0]}) and DuT ({cut.shape[0]}), " - - # check if threshold has been exceeded - if abs(ref.shape[0] - cut.shape[0]) / max(ref.shape[0], cut.shape[0]) > min_diff_thr: - result_len_check = 1 - else: - result_len_check = 0 - else: - reason += ": " - - # calculate histograms from data - unique_values = np.sort(np.unique(np.concatenate([ref, cut]))) - ref_hist,_ = np.histogram(ref, bins=np.append(unique_values, unique_values[-1] + 10)) - cut_hist,_ = np.histogram(cut, bins=np.append(unique_values, unique_values[-1] + 10)) - diff_hist = cut_hist - ref_hist - - # convert to dict and sort by absolute value of difference - diff = {unique_values[i]: diff_hist[i] for i in range(len(unique_values))} - diff = dict(sorted(diff.items(), key=lambda k: abs(k[1]), reverse=True)) - - # calculate the total number of differences - total_num_diff = sum(np.abs(list(diff.values()))) - total_num_diff_ratio = total_num_diff / max(ref.shape[0], cut.shape[0]) - - if total_num_diff_ratio > min_diff_thr: - msg = f"the total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%), exceeding the threshold of {(min_diff_thr*100):.2f}%!" - reason += msg - print(msg, end="") - result_diff_check = 1 - else: - msg = f"the total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)." - reason += msg - print( msg, end="" ) - result_diff_check = 0 - - print("") - - result = 0 - if result_len_check or result_diff_check: - result = 1 - - return result, reason - - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("ref_file", type=str) - parser.add_argument("cut_file", type=str) - parser.add_argument("--data_type", type=str, default='int16', dest="dtype") - parser.add_argument("--nsamples_per_frame", type=str, default=960, dest="nsamples_per_frame") - parser.add_argument("--len_check", type=int, default=0, dest="len_check") - parser.add_argument("--min_diff_thr", type=float, default=0.0, dest="min_diff_thr") - args = parser.parse_args() - - # convert dtype from str - if isinstance(args.dtype, str): - args.dtype = np.dtype(getattr(np, args.dtype)) - - result, msg = cmp_bin_files(**vars(args)) - print(msg) - sys.exit(result) diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py deleted file mode 100644 index cb17ce668..000000000 --- a/tests/codec_be_on_mr_nonselection/test_param_file.py +++ /dev/null @@ -1,920 +0,0 @@ -__copyright__ = """ -(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, -Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., -Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, -Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other -contributors to this repository. All Rights Reserved. - -This software is protected by copyright law and by international treaties. -The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, -Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., -Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, -Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other -contributors to this repository retain full ownership rights in their respective contributions in -the software. This notice grants no license of any kind, including but not limited to patent -license, nor is any license granted by implication, estoppel or otherwise. - -Contributors are required to enter into the IVAS codec Public Collaboration agreement before making -contributions. - -This software is provided "AS IS", without any express or implied warranties. The software is in the -development stage. It is intended exclusively for experts who have experience with such software and -solely for the purpose of inspection. All implied warranties of non-infringement, merchantability -and fitness for a particular purpose are hereby disclaimed and excluded. - -Any dispute, controversy or claim arising under or in relation to providing this software shall be -submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in -accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and -the United Nations Convention on Contracts on the International Sales of Goods. -""" - -__doc__ = """ -Execute tests specified via a parameter file. -""" - -import errno -import filecmp -import os -import re -import platform -from pathlib import Path -from subprocess import run -import pytest -import glob -import tempfile -import numpy as np -import shutil -import json - -from tests.cmp_pcm import cmp_pcm -from tests.cmp_bin_files import cmp_bin_files -from tests.conftest import DecoderFrontend, EncoderFrontend -from tests.testconfig import PARAM_FILE -from ..constants import MLD_PATTERN, MAX_DIFF_PATTERN, ENC_AUX_FILES, MAX_ENC_DIFF_PATTERN, MIN_ENC_AUX_FILE_DIFF_THR, MIN_ENC_AUX_FILE_LENGTH_DIFF - -import pdb - -VALID_DEC_OUTPUT_CONF = [ - "MONO", - "STEREO", - "5_1", - "7_1", - "5_1_2", - "5_1_4", - "7_1_4", - "FOA", - "HOA2", - "HOA3", - "BINAURAL", - "BINAURAL_ROOM_IR", - "BINAURAL_ROOM_REVERB", - "EXT", -] - -param_file_test_dict = {} -with open(PARAM_FILE, "r", encoding="UTF-8") as fp: - data = fp.read() - blocks = data.split("\n\n") - for block in blocks: - tag = "" - enc_opts = "" - dec_opts = "" - sim_opts = "" - eid_opts = "" - for line in block.split("\n"): - if line.startswith("// "): - tag = line[3:] - if line.startswith("../IVAS_cod "): - enc_opts = line[12:] - if line.startswith("../IVAS_dec "): - dec_opts = line[12:] - if line.startswith("networkSimulator_g192 "): - sim_opts = line[22:] - if line.startswith("eid-xor "): - eid_opts = line[8:] - if tag == "" or enc_opts == "" or dec_opts == "": - # no complete parameter set - continue - if tag in param_file_test_dict: - print("non-unique tag found - ignoring new entry") - continue - param_file_test_dict[tag] = (enc_opts, dec_opts, sim_opts, eid_opts) - - -def check_and_makedir(dir_path): - if not os.path.exists(dir_path): - try: - os.makedirs(dir_path) - except OSError as e: - if e.errno != errno.EEXIST: - raise # raises the error again - - -def convert_test_string_to_tag(test_string): - """ - Convert a test string (i.e. the test tag from the parameter file) to a tag string. - Example: - in: "DFT stereo at 13.2 kbps, 16kHz in, 16kHz out, DTX on, random FEC at 5%" - out: "DFT_stereo_at_13_2_kbps_16kHz_in_16kHz_out_DTX_on_random_FEC_at_5_" - """ - # replace certain characters by "_" or remove them - tag_str = "" - replace_chars = " %.-()" - remove_chars = "," - for char in test_string: - if char in replace_chars: - tag_str += "_" - elif char not in remove_chars: - tag_str += char - # replace double underscore by single one - tag_str = "_".join(tag_str.split("__")) - return tag_str - -def num(s): - """ - Convert string either to integer or float - """ - try: - return int(s) - except ValueError: - return float(s) - -@pytest.mark.create_ref -@pytest.mark.parametrize("test_tag", list(param_file_test_dict.keys())) -def test_param_file_tests( - record_property, - encoder_only, - decoder_only, - dut_encoder_frontend: EncoderFrontend, - dut_decoder_frontend: DecoderFrontend, - ref_encoder_frontend: EncoderFrontend, - ref_decoder_frontend: DecoderFrontend, - reference_path, - dut_base_path, - test_vector_path, - update_ref, - rootdir, - keep_files, - test_tag, - get_mld, - get_mld_lim, - abs_tol, -): - enc_opts, dec_opts, sim_opts, eid_opts = param_file_test_dict[test_tag] - - tag_str = convert_test_string_to_tag(test_tag) - - # evaluate encoder options - enc_split = enc_opts.split() - assert len(enc_split) >= 4 - - # replace "testv/" by test vector path - enc_split = [ - x.replace("testv", f"{test_vector_path}", 1) if x.startswith("testv/") else x - for x in enc_split - ] - - bitstream_file = enc_split.pop() - testv_file = enc_split.pop() - fs = enc_split.pop() - sampling_rate = int(fs) - bitrate = enc_split.pop() - - # bitrate can be a filename: remove leading "../" - if bitrate.startswith("../"): - bitrate = bitrate[3:] - - testv_base = testv_file.split("/")[-1] - if testv_base.endswith(".pcm"): - testv_base = testv_base[:-4] - - assert bitstream_file == "bit" - # in the parameter file, only "bit" is used as bitstream file name - # -> construct bitstream filename - bitstream_file = f"{testv_base}_{tag_str}.192" - - if not decoder_only: - - encode( - dut_encoder_frontend, - ref_encoder_frontend, - reference_path, - dut_base_path, - bitrate, - sampling_rate, - testv_file, - bitstream_file, - enc_split, - update_ref, - encoder_only, - ) - - # compare binary files extracted from the encoder - if encoder_only: - print ("Comparing encoder auxiliary files") - print ("=================================\n") - - ref_out_dir = f"{reference_path}/param_file/enc" - - stats_file = bitstream_file.replace(".192", ".stats") - ref_stats_file = f"{reference_path}/param_file/enc/{stats_file}" - dut_stats_file = f"{dut_base_path}/param_file/enc/{stats_file}" - - # pdb.set_trace() - - # open and read the .stats file - with open(ref_stats_file, "r") as f_aux: - ref_stats = json.load(f_aux) - # create dictionary to map "name" to the corresponding dictionaries - ref_stats_names = {d["name"]: d for d in ref_stats} - - with open(dut_stats_file, "r") as f_aux: - dut_stats = json.load(f_aux) - # create dictionary to map "name" to the corresponding dictionaries - dut_stats_names = {d["name"]: d for d in dut_stats} - - # loop over all common aux files - enc_test_result = 0 - enc_test_result_msg = "" - max_enc_diff = 0 - for name in ref_stats_names: - if name in dut_stats_names: - # retrieve the dictionaries - ref_stats_dict = ref_stats_names[name] - dut_stats_dict = dut_stats_names[name] - # ref_stats_dict = ref_stats_names["core_brate"] - # dut_stats_dict = dut_stats_names["total_brate"] - - msg = f"File {name}" - - # compare the file lengths - result_len_check = 0 - file_length = max(ref_stats_dict["length"], dut_stats_dict["length"]) - if ref_stats_dict["length"] != dut_stats_dict["length"]: - msg += f" has different length between Ref {ref_stats_dict['length']} and DuT {dut_stats_dict['length']}" - - # check if threshold has been exceeded - if abs(ref_stats_dict["length"] - dut_stats_dict["length"]) / file_length > MIN_ENC_AUX_FILE_LENGTH_DIFF: - result_len_check = 1 - - msg += f", " - - # remove the "name" and "length" keys for further processing - del ref_stats_dict["name"] - del dut_stats_dict["name"] - del ref_stats_dict["length"] - del dut_stats_dict["length"] - - # convert keys and values from string to float - ref_hist = {num(i) : num(j) for i,j in ref_stats_dict.items()} - cut_hist = {num(i) : num(j) for i,j in dut_stats_dict.items()} - delta_ref = set(cut_hist) - set(ref_hist) - delta_cut = set(ref_hist) - set(cut_hist) - - # append missing keys - for item in delta_cut: - cut_hist[item] = 0 - - for item in delta_ref: - ref_hist[item] = 0 - - ref_hist = dict(sorted(ref_hist.items())) - cut_hist = dict(sorted(cut_hist.items())) - - # caculate difference of statistics - diff_hist = { k : cut_hist[k] - ref_hist[k] for k in ref_hist.keys()} - - # calculate the total number of differences - total_num_diff = sum(np.abs(list(diff_hist.values()))) - total_num_diff_ratio = total_num_diff / (sum(ref_hist.values()) + sum(cut_hist.values())) - - msg += f"the total number of differences is {total_num_diff} ({(total_num_diff_ratio*100):.2f}%)" - if total_num_diff_ratio > MIN_ENC_AUX_FILE_DIFF_THR: - result_diff_check = 1 - msg += "! " - else: - result_diff_check = 0 - msg += ". " - - # check if the maximum difference has been exceeded - if total_num_diff_ratio > max_enc_diff: - max_enc_diff = total_num_diff_ratio - - # update test result - if result_len_check or result_diff_check: - enc_test_result = 1 - enc_test_result_msg += msg - - print(msg) - - print ("") - - if enc_test_result: - record_property("MAXIMUM ENC DIFF", max_enc_diff) - pytest.fail(enc_test_result_msg) - - - - - # msg = "" - # max_enc_diff = 0 - # enc_test_result = 0 - # for f in ENC_AUX_FILES: - # filename = f[0] - # dtype = f[1] - # fs = int(sampling_rate) * 1000 - # if isinstance(f[2], str): - # nsamples_per_frame = np.int16(eval(f[2])) - # else: - # nsamples_per_frame = np.int16(f[2]) - - # ref_aux_files = glob.glob(os.path.join(ref_enc_dbg_dir.name, filename + '*')) - # ref_aux_files = [os.path.basename(f) for f in ref_aux_files] - # dut_aux_files = glob.glob(os.path.join(dut_enc_dbg_dir.name, filename + '*')) - # dut_aux_files = [os.path.basename(f) for f in dut_aux_files] - # common_aux_files = [f for f in ref_aux_files if f in dut_aux_files] - - # for aux_file in common_aux_files: - # # compare the contents of each binary file extracted from the encoder based on histogram - # output_differs, reason = cmp_bin_files( - # os.path.join(ref_enc_dbg_dir.name, aux_file), - # os.path.join(dut_enc_dbg_dir.name, aux_file), - # dtype=dtype, - # nsamples_per_frame=nsamples_per_frame, - # len_check=1, - # min_diff_thr=0.1, - # ) - - # if output_differs: - # enc_test_result = 1 - # if msg: - # msg += ", " - # msg += reason - - # # check if the maximum difference has been exceeded - # search_result = re.search(MAX_ENC_DIFF_PATTERN, reason) - # if search_result: - # diff = search_result.groups(1)[0] - # diff = float(diff) - # if diff > max_enc_diff: - # max_enc_diff = diff - - # print ("") - - # # remove encoder output files to save disk space - # if ref_enc_dbg_dir: - # shutil.rmtree(ref_enc_dbg_dir.name) - - # if dut_enc_dbg_dir: - # shutil.rmtree(dut_enc_dbg_dir.name) - - # if enc_test_result: - # record_property("MAXIMUM ENC DIFF", max_enc_diff) - # pytest.fail(msg) - - if encoder_only: - return - - # check for networkSimulator_g192 command line - if sim_opts != "": - sim_split = sim_opts.split() - assert len(sim_split) == 6, "networkSimulator_g192 expects 6 parameters" - # [sim_profile, sim_input, sim_output, sim_trace, sim_nFPP, sim_offset] = sim_split - if sim_split[0].startswith(("../")): - # remove leading "../" - sim_split[0] = sim_split[0][3:] - assert sim_split[1] == "bit" - # in the parameter file, only "bit" is used as bitstream file name - # -> re-use bitstream filename from encoder call - sim_split[1] = bitstream_file - assert sim_split[2] == "netsimoutput" - # in the parameter file, only "netsimoutput" is used as netsim output file name - # -> construct netsim output file name - netsim_outfile = f"{testv_base}_{tag_str}.netsimout" - sim_split[2] = netsim_outfile - assert sim_split[3] == "tracefile_sim" - # in the parameter file, only "tracefile_sim" is used as trace output file name - # -> construct trace output file name - netsim_trace_outfile = f"{testv_base}_{tag_str}.netsimtrace" - sim_split[3] = netsim_trace_outfile - simulate( - reference_path, - dut_base_path, - sim_split, - update_ref, - rootdir, - decoder_only, - ) - - # check for eid-xor command line - if eid_opts != "": - eid_split = eid_opts.split() - assert len(eid_split) >= 3, "eid-xor expects at least 3 parameters" - # [..., in_bs, err_pat_bs, out_bs] = eid_split - if eid_split[-2].startswith(("../")): - # remove leading "../" - eid_split[-2] = eid_split[-2][3:] - assert eid_split[-3] == "bit" - # in the parameter file, only "bit" is used as the input bitstream file name - # -> re-use bitstream filename from encoder call - eid_split[-3] = bitstream_file - assert eid_split[-1] == "bit_error" - # in the parameter file, only "bit_error" is used as the output bitstream file name - # -> construct netsim output file name - eid_xor_outfile = f"{testv_base}_{tag_str}.fer.192" - eid_split[-1] = eid_xor_outfile - error_insertion( - reference_path, - dut_base_path, - eid_split, - update_ref, - rootdir, - decoder_only, - ) - - # evaluate decoder options - dec_split = dec_opts.split() - assert len(dec_split) >= 3 - - # replace "testv/" by test vector path - dec_split = [ - x.replace("testv", f"{test_vector_path}", 1) if x.startswith("testv/") else x - for x in dec_split - ] - # remove leading "../" - dec_split = [x[3:] if x.startswith("../") else x for x in dec_split] - - output_file = dec_split.pop() - bitstream_file_dec = dec_split.pop() - sampling_rate = int(dec_split.pop()) - if len(dec_split) > 0: - output_config = dec_split.pop() - if output_config.upper() not in VALID_DEC_OUTPUT_CONF: - if not output_config.endswith(".txt"): - # must be EVS tests with additional parameters - put param back - dec_split.append(output_config) - output_config = "" - else: - output_config = "" - - output_config_name = output_config - if "/" in output_config: - # the output config is a file - output_config_name = os.path.splitext(os.path.basename(output_config))[0] - - tracefile_dec = "" - if sim_opts != "": - assert bitstream_file_dec == "netsimoutput" - # in the parameter file, only "netsimoutput" is used as bitstream file name - # -> re-use netsim_outfile - bitstream_file = netsim_outfile - tracefile_dec = f"{testv_base}_{tag_str}.dectrace" - elif eid_opts != "": - assert bitstream_file_dec == "bit_error" - # in the parameter file, only "bit_error" is used as bitstream input file name - # -> re-use eid_xor_outfile - bitstream_file = eid_xor_outfile - else: - assert bitstream_file_dec == "bit" - # in the parameter file, only "bit" is used as bitstream file name - # -> re-use bitstream filename from encoder call - - # the output file is not the real output filename - # -> construct output filename - output_file = f"{testv_base}_{tag_str}.dec.wav" - - stdout = decode( - dut_decoder_frontend, - ref_decoder_frontend, - reference_path, - dut_base_path, - output_config, - sampling_rate, - bitstream_file, - output_file, - dec_split, - update_ref, - tracefile_dec, - decoder_only, - ) - - if update_ref in [0, 2]: - dut_output_file = f"{dut_base_path}/param_file/dec/{output_file}" - ref_output_file = f"{reference_path}/param_file/dec/{output_file}" - fs = int(sampling_rate) * 1000 - output_differs, reason = cmp_pcm( - dut_output_file, - ref_output_file, - output_config, - fs, - get_mld=get_mld, - mld_lim=get_mld_lim, - abs_tol=abs_tol, - ) - md_out_files = get_expected_md_files(ref_output_file, enc_split, output_config) - - if get_mld: - mld = re.search(MLD_PATTERN, reason).groups(1)[0] - record_property("MLD", mld) - - max_diff =0 - if output_differs: - search_result = re.search(MAX_DIFF_PATTERN, reason) - if search_result: - max_diff = search_result.groups(1)[0] - else: - msg = "Error " + MAX_DIFF_PATTERN + " not found" - print(msg) - pytest.fail(msg) - record_property("MAXIMUM ABS DIFF", max_diff) - - metadata_differs = False - for md_file in md_out_files: - dut_metadata_file = Path(f"{dut_base_path}/param_file/dec/{md_file}") - ref_metadata_file = Path(f"{reference_path}/param_file/dec/{md_file}") - try: - if not filecmp.cmp(dut_metadata_file, ref_metadata_file): - print("Output metadata differs for file: " + md_file) - metadata_differs = True - except FileNotFoundError: - if not dut_metadata_file.exists(): - print("DUT output metadata missing for expected file: " + md_file) - if not ref_metadata_file.exists(): - print("REF output metadata missing for expected file: " + md_file) - metadata_differs = True - - if get_mld and get_mld_lim > 0: - if output_differs: - pytest.fail(reason) - else: - if output_differs or metadata_differs: - msg = "Difference between ref and dut in " - if output_differs and metadata_differs: - msg += f"output ({reason}) and metadata" - elif output_differs: - msg += f"output only ({reason})" - elif metadata_differs: - msg += "metadata only" - pytest.fail(msg) - - # remove DUT output files when test result is OK (to save disk space) - if not keep_files: - os.remove(f"{dut_base_path}/param_file/dec/{output_file}") - if not decoder_only: - os.remove(f"{dut_base_path}/param_file/enc/{bitstream_file}") - if sim_opts != "": - os.remove( - f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192" - ) - os.remove(f"{dut_base_path}/param_file/enc/{netsim_trace_outfile}") - os.remove(f"{dut_base_path}/param_file/dec/{tracefile_dec}") - elif eid_opts != "": - os.remove( - f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192" - ) - - -def encode( - dut_encoder_frontend, - ref_encoder_frontend, - reference_path, - dut_base_path, - bitrate, - sampling_rate, - testv_file, - bitstream_file, - enc_opts_list, - update_ref, - encoder_only, -): - """ - Call REF and/or DUT encoder. - """ - # directories - dut_out_dir = f"{dut_base_path}/param_file/enc" - ref_out_dir = f"{reference_path}/param_file/enc" - - ref_out_file = f"{ref_out_dir}/{bitstream_file}" - dut_out_file = f"{dut_out_dir}/{bitstream_file}" - - if encoder_only: - stats_file = bitstream_file.replace(".192", ".stats") - ref_stats_file = f"{ref_out_dir}/{stats_file}" - dut_stats_file = f"{dut_out_dir}/{stats_file}" - - if ( update_ref in [1, 2] and not os.path.exists(ref_out_file) ) or encoder_only: - check_and_makedir(ref_out_dir) - - # generate dbg tweak subfolder under /res to store encoder output files - ref_dbg_tweak_folder = os.path.join(os.path.split(ref_encoder_frontend._path)[0], 'res') - check_and_makedir(ref_dbg_tweak_folder) - ref_dbg_tweak_folder = tempfile.TemporaryDirectory(dir=ref_dbg_tweak_folder) - - # call REF encoder - ref_encoder_frontend.run( - bitrate, - sampling_rate, - testv_file, - ref_out_file, - encoder_only=encoder_only, - add_option_list=enc_opts_list, - dbg_tweak_folder=Path(ref_dbg_tweak_folder.name), - ) - - # generate ref encoder stats - if encoder_only: - extract_enc_stats(Path(ref_dbg_tweak_folder.name), ref_stats_file, sampling_rate) - - ref_dbg_tweak_folder.cleanup() - - if update_ref in [0, 2] or encoder_only: - check_and_makedir(dut_out_dir) - - # generate dbg tweak subfolder under /res to store encoder output files - dut_dbg_tweak_folder = os.path.join(os.path.split(dut_encoder_frontend._path)[0], 'res') - check_and_makedir(dut_dbg_tweak_folder) - dut_dbg_tweak_folder = tempfile.TemporaryDirectory(dir=dut_dbg_tweak_folder) - - # call DUT encoder - dut_encoder_frontend.run( - bitrate, - sampling_rate, - testv_file, - dut_out_file, - encoder_only=encoder_only, - add_option_list=enc_opts_list, - dbg_tweak_folder=Path(dut_dbg_tweak_folder.name), - ) - - # generate dut encoder stats - if encoder_only: - extract_enc_stats(Path(dut_dbg_tweak_folder.name), dut_stats_file, sampling_rate) - - dut_dbg_tweak_folder.cleanup() - -def extract_enc_stats ( - dbg_tweak_folder, - stats_file, - sampling_rate, -): - """ - Extract statistics from auxiliary encoder files generated by running the encoder with DEBUG_MODE_INFO. - Write the statistics to a text file - """ - - hist_dicts = [] - for f in ENC_AUX_FILES: - filename = f[0] - dtype = f[1] - fs = int(sampling_rate) * 1000 - if isinstance(f[2], str): - nsamples_per_frame = np.int16(eval(f[2])) - else: - nsamples_per_frame = np.int16(f[2]) - - # aux_files = glob.glob(os.path.join(dbg_tweak_folder, filename + '\.*')) - aux_files = [f for f in os.listdir(dbg_tweak_folder) if re.search(rf'^{filename}(\..*)?$', f)] - # aux_files = [os.path.basename(f) for f in aux_files] - - for aux_file in aux_files: - # extract statistics from the aux file based on histogram of values - print(f"Extracting statistics from {os.path.basename(aux_file)} ... ", end="") - - # read the aux file - with open(os.path.join(dbg_tweak_folder, aux_file), "r") as f_aux: - data = np.fromfile(f_aux, dtype=dtype) - - # get file length - data_len = data.shape[0] - - # remove the duplicates of each value per frame - if nsamples_per_frame > 1: - data = data[::nsamples_per_frame] - - # calculate histogram from data - unique_values = np.sort(np.unique(data)) - hist, _ = np.histogram(data, bins=np.append(unique_values, unique_values[-1] + 10)) - - # convert to dict and sort by absolute value of difference - hist_dict = {"name" : os.path.basename(aux_file), "length" : data_len} - dict_values = {str(unique_values[i]): str(hist[i]) for i in range(len(unique_values))} - hist_dict.update(dict_values) - hist_dicts.append(hist_dict) - - print(f"DONE") - - print("") - - with open(stats_file, "w") as f_stats: - # append the statistics to the output file in text format - f_stats.write(json.dumps(hist_dicts, indent=2)) - -def simulate( - reference_path, - dut_base_path, - sim_opts_list, - update_ref, - rootdir, - decoder_only, -): - """ - Call network simulator on REF and/or DUT encoder output. - """ - # directories - dut_out_dir = f"{dut_base_path}/param_file/enc" - ref_out_dir = f"{reference_path}/param_file/enc" - - netsim_infile = sim_opts_list[1] - netsim_outfile = sim_opts_list[2] - netsim_tracefile = sim_opts_list[3] - ref_out_file = f"{ref_out_dir}/{netsim_outfile}" - - if platform.system() == "Windows": - netsim = [ - os.path.join( - rootdir, "scripts", "tools", "Win32", "networkSimulator_g192.exe" - ) - ] - elif platform.system() in ["Linux", "Darwin"]: - netsim = [ - os.path.join( - rootdir, "scripts", "tools", platform.system(), "networkSimulator_g192" - ) - ] - else: - assert False, f"networkSimulator_g192 not available for {platform.system()}" - - cmd_opts = sim_opts_list - if ( - update_ref == 1 - or (update_ref == 2 and not os.path.exists(ref_out_file)) - or decoder_only - ): - # call network simulator on REF encoder output - cmd_opts[1] = f"{ref_out_dir}/{netsim_infile}" - cmd_opts[2] = f"{ref_out_dir}/{netsim_outfile}" # ref_out_file - elif update_ref in [0, 2]: - # call network simulator on DUT encoder output - cmd_opts[1] = f"{dut_out_dir}/{netsim_infile}" - cmd_opts[2] = f"{dut_out_dir}/{netsim_outfile}" # dut_out_file - - if update_ref == 1 or (update_ref == 2 and not os.path.exists(ref_out_file)): - cmd_opts[3] = f"{ref_out_dir}/{netsim_tracefile}" - cmd_opts[2] = f"{ref_out_dir}/{netsim_outfile}" # ref_out_file - elif update_ref in [0, 2]: - cmd_opts[3] = f"{dut_out_dir}/{netsim_tracefile}" - cmd_opts[2] = f"{dut_out_dir}/{netsim_outfile}" # dut_out_file - - run(netsim + cmd_opts, check=False) - - -def error_insertion( - reference_path, - dut_base_path, - eid_opts_list, - update_ref, - rootdir, - decoder_only, -): - """ - Call eid-xor to insert frame erasure on REF and/or DUT encoder output. - """ - - # directories - dut_out_dir = f"{dut_base_path}/param_file/enc" - ref_out_dir = f"{reference_path}/param_file/enc" - - eid_xor_infile = eid_opts_list[-3] - eid_xor_outfile = eid_opts_list[-1] - ref_out_file = f"{ref_out_dir}/{eid_xor_outfile}" - - if platform.system() == "Windows": - eid_xor = [os.path.join(rootdir, "scripts", "tools", "Win32", "eid-xor.exe")] - elif platform.system() in ["Linux", "Darwin"]: - eid_xor = [ - os.path.join(rootdir, "scripts", "tools", platform.system(), "eid-xor") - ] - else: - assert False, f"eid-xor not available for {platform.system()}" - - cmd_opts = eid_opts_list - - if ( - update_ref == 1 - or (update_ref == 2 and not os.path.exists(ref_out_file)) - or decoder_only - ): - # call eid-xor on REF encoder output - cmd_opts[-3] = f"{ref_out_dir}/{eid_xor_infile}" - elif update_ref in [0, 2]: - # call eid-xor on DUT encoder output - cmd_opts[-3] = f"{dut_out_dir}/{eid_xor_infile}" - - if update_ref == 1 or (update_ref == 2 and not os.path.exists(ref_out_file)): - cmd_opts[-1] = f"{ref_out_dir}/{eid_xor_outfile}" # ref_out_file - elif update_ref in [0, 2]: - cmd_opts[-1] = f"{dut_out_dir}/{eid_xor_outfile}" # ref_out_file - - run(eid_xor + cmd_opts, check=False) - - -def decode( - decoder_frontend, - ref_decoder_frontend, - reference_path, - dut_base_path, - output_config, - sampling_rate, - bitstream_file, - output_file, - dec_opts_list, - update_ref, - tracefile_dec, - decoder_only, -): - """ - Call REF and/or DUT decoder. - """ - # directories - dut_out_dir = f"{dut_base_path}/param_file/dec" - ref_out_dir = f"{reference_path}/param_file/dec" - - dut_in_file = f"{dut_base_path}/param_file/enc/{bitstream_file}" - ref_in_file = f"{reference_path}/param_file/enc/{bitstream_file}" - dut_out_file = f"{dut_out_dir}/{output_file}" - ref_out_file = f"{ref_out_dir}/{output_file}" - - if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): - check_and_makedir(ref_out_dir) - add_option_list = dec_opts_list - if tracefile_dec != "": - add_option_list = [ - x if x != "tracefile_dec" else f"{ref_out_dir}/{tracefile_dec}" - for x in dec_opts_list - ] - # call REF decoder - ref_decoder_frontend.run( - output_config, - sampling_rate, - ref_in_file, - ref_out_file, - add_option_list=add_option_list, - ) - - stdout = ref_decoder_frontend.stdout - - if update_ref in [0, 2]: - check_and_makedir(dut_out_dir) - add_option_list = dec_opts_list - if tracefile_dec != "": - add_option_list = [ - x if x != "tracefile_dec" else f"{dut_out_dir}/{tracefile_dec}" - for x in dec_opts_list - ] - - if decoder_only: - dut_in_file = ref_in_file - - # call DUT decoder - decoder_frontend.run( - output_config, - sampling_rate, - dut_in_file, - dut_out_file, - add_option_list=add_option_list, - ) - - stdout = decoder_frontend.stdout - - return stdout - - -def get_expected_md_files(ref_output_file, enc_opts, output_config): - """ - Based on input and output configs, get the filenames of MD files that are expected to being output by the decoder - """ - - if output_config.upper() != "EXT": - return list() - - md_files = list() - enc_opts_upper = [o.upper() for o in enc_opts] - md_filename = Path(ref_output_file).name - - if any([o in enc_opts_upper for o in ["-MASA", "-ISM_MASA"]]): - # always only one MD file, just add ending - md_files.append(md_filename + ".met") - - for ism_opt in ["-ISM", "-ISM_MASA", "-ISM_SBA"]: - # for ism MD, there are three modes that may output MD files - # try to find any of them in the encoder options - md_tmpl = md_filename + ".{}.csv" - try: - idx = enc_opts_upper.index(ism_opt) - ism_num = int(enc_opts[idx + 1]) - md_files.extend([md_tmpl.format(i) for i in range(ism_num)]) - break - except ValueError: - pass - - return md_files diff --git a/tests/constants.py b/tests/constants.py deleted file mode 100644 index 995d76ab4..000000000 --- a/tests/constants.py +++ /dev/null @@ -1,36 +0,0 @@ -import numpy as np - -# regex patterns for parsing the output from cmp_pcm -> mainly for BASOP ci -MLD_PATTERN = r"MLD: ([\d\.]*)" -MAX_DIFF_PATTERN = r"MAXIMUM ABS DIFF: (\d*)" -MAX_ENC_DIFF_PATTERN = r"total number of differences is \d+ \((\d+\.\d+)%\)" - -MIN_ENC_AUX_FILE_DIFF_THR = 0.1 # minimum ratio of total number of differences in encoder aux file -MIN_ENC_AUX_FILE_LENGTH_DIFF = 0.1 # minimum difference of encoder aux file length - -# list of encoder filename patterns with their data type and number of samples per frame -# note: instead of specifying the number of samples per frame, you can use a formula incl. 'fs', e.g. 'fs/50' -ENC_AUX_FILES = [ - ['bits_nominal', np.int16, 'fs/50'], - ['bwidth', np.int16, 'fs/50'], - ['clas', np.int16, 'fs/50'], - ['cng_type', np.int16, 'fs/50'], - ['coder_type', np.int16, 'fs/50'], - ['core', np.int16, 'fs/50'], - ['core_brate', np.float32, 'fs/50'], - ['count_SWB', np.int16, 'fs/50'], - ['count_WB', np.int16, 'fs/50'], - ['element_brate', np.float32, 'fs/50'], - ['element_mode', np.int16, 'fs/50'], - ['extl', np.int16, 'fs/50'], - ['extl_brate', np.float32, 'fs/50'], - ['ivas_total_brate', np.float32, 'fs/50'], - ['L_frame', np.int16, 'fs/50'], - ['localVAD', np.int16, 'fs/50'], - ['sp_aud_decision0', np.int16, 'fs/50'], - ['sp_aud_decision1', np.int16, 'fs/50'], - ['sp_aud_decision2', np.int16, 'fs/50'], - ['tdm_LRTD_flag', np.int16, 'fs/50'], - ['total_brate', np.float32, 'fs/50'], - ['vad_flag', np.int16, 'fs/50'] -] -- GitLab From 2208a390c12eadd6fe3b4f982b9add5bc81adc50 Mon Sep 17 00:00:00 2001 From: malenov Date: Wed, 31 Jul 2024 10:26:30 +0200 Subject: [PATCH 09/10] sync with main --- lib_com/options.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 60ada8b87..5c43f6297 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -158,13 +158,10 @@ #define FIX_798_LSF_SECONDARY_CH_MISSING_CODE /* Adding the missing code to properly render the secondary channel of TD stereo*/ #define FIX_798_WRONG_CPY_OF_PITCH /* The copy of the pitch from primary to secondary channel was wrong AND safety check was really wrong */ #define FIX_800_PROPOSAL_HB_LPC_COEFFICIENT /* Proposal to fix wrong shape of TDBWE, #800 */ -<<<<<<< HEAD -======= #define FIX_802__NON_BE_DECODING /* Fix possible difference float and fixed point when computing the GSC bit allocation */ #define FIX_802_1137_1137_GSC_IVAS_FXFLT_DECODING /* VA: ISSUES 802 and 1137 Made sure that float and fixed point GCS bit allocation is the same during IVAS modes */ #define FIX_810_PREVENT_UNECESSARY_SAT_IN_TC /* VA : Prevent an unnecessary saturation that can happen in TC, have a minimal impact on most cases. Significant improvement for the last segment of LTV when TC is triggered */ ->>>>>>> main /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ -- GitLab From 9a7d480d7270c664250091521c1170de1991e01e Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 31 Jul 2024 12:11:24 +0200 Subject: [PATCH 10/10] clang format --- apps/renderer.c | 2 +- lib_enc/ivas_core_enc.c | 2 +- lib_enc/ivas_enc.c | 4 ++-- lib_enc/ivas_omasa_enc.c | 2 +- lib_enc/ivas_stereo_td_enc.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 0798a7f74..fcc1a04b7 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -67,7 +67,7 @@ #define IVAS_MIN16B_FLT ( -32768.0f ) #define IVAS_MAX16B_FX 32767 #define IVAS_MIN16B_FX ( -32768 ) -#if !defined(DEBUGGING) && !defined( WMOPS ) +#if !defined( DEBUGGING ) && !defined( WMOPS ) static #endif int32_t frame = 0; diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index 5c7009674..1be1a8b55 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -863,7 +863,7 @@ ivas_error ivas_core_enc( float tmpF; short tmpS, id; - st = sts[n]; + st = sts[n]; id = st->id_element; dbgwrite( &st->core, sizeof( short ), 1, input_frame, fname( debug_dir, "core", n, id, ENC ) ); diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index fbe87dfb4..d73ec1ea5 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -1167,14 +1167,14 @@ ivas_error ivas_enc( *----------------------------------------------------------------*/ hEncoderConfig->last_ivas_total_brate = ivas_total_brate; - + #ifdef DEBUG_MODE_INFO { float tmpF = ivas_total_brate / 1000.0f; dbgwrite( &tmpF, sizeof( float ), 1, input_frame, "res/ivas_total_brate" ); } #endif - + pop_wmops(); return error; } diff --git a/lib_enc/ivas_omasa_enc.c b/lib_enc/ivas_omasa_enc.c index c5706d019..09fb8777c 100644 --- a/lib_enc/ivas_omasa_enc.c +++ b/lib_enc/ivas_omasa_enc.c @@ -780,7 +780,7 @@ void ivas_set_surplus_brate_enc( #ifdef DEBUG_MODE_INFO if ( st_ivas->hSCE[0] != NULL ) { - int16_t input_frame = ( int16_t )( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC ); + int16_t input_frame = (int16_t) ( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC ); float tmpF = 0; if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) diff --git a/lib_enc/ivas_stereo_td_enc.c b/lib_enc/ivas_stereo_td_enc.c index 12e5ae603..96e6fe797 100644 --- a/lib_enc/ivas_stereo_td_enc.c +++ b/lib_enc/ivas_stereo_td_enc.c @@ -257,7 +257,7 @@ ivas_error stereo_set_tdm( } #ifdef DEBUG_MODE_INFO - dbgwrite( &hCPE->hStereoTD->tdm_LRTD_flag, 2, 1, ( int16_t )( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); + dbgwrite( &hCPE->hStereoTD->tdm_LRTD_flag, 2, 1, (int16_t) ( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); #endif @@ -367,7 +367,7 @@ ivas_error stereo_set_tdm( #ifdef DEBUG_MODE_INFO { int16_t tmp = -2; - dbgwrite( &tmp, 2, 1, ( int16_t )( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); + dbgwrite( &tmp, 2, 1, (int16_t) ( hCPE->hCoreCoder[0]->input_Fs / FRAMES_PER_SEC ), "res/tdm_LRTD_flag" ); } #endif hCPE->hCoreCoder[0]->tdm_LRTD_flag = 0; -- GitLab