diff --git a/lib_com/ivas_ism_com.c b/lib_com/ivas_ism_com.c index 82aec26acccc850f75bc0cc0e193ccd884a3cb5f..b6f2e5bc3bbf2c807b3cce018a8f2f253b86bc20 100644 --- a/lib_com/ivas_ism_com.c +++ b/lib_com/ivas_ism_com.c @@ -212,6 +212,7 @@ ivas_error ivas_ism_config( } } + n_higher = sum_s( flag_higher, n_ISms ); if ( diff > 0 && n_higher > 0 ) @@ -252,6 +253,17 @@ ivas_error ivas_ism_config( limit = ( ACELP_16k_LOW_LIMIT + SWB_TBE_1k6 ) / FRAMES_PER_SEC; } +#ifdef DEBUGGING +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING_DEBUG + /* for dbg testing of HQ decoder, high rate HQ coding requires 16.4kbps to 48kbps */ + if ( limit < 16400 / 50 ) + { + limit = 16400 / 50; + } +#endif +#endif + + if ( ism_imp[ch] == ISM_NO_META ) { tmp = BITS_ISM_INACTIVE; @@ -305,6 +317,17 @@ ivas_error ivas_ism_config( limit_high = ACELP_12k8_HIGH_LIMIT / FRAMES_PER_SEC; } +#ifdef DEBUGGING +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING_DEBUG + /* for dbg testing of HQ decoder, high rate HQ coding requires 16.4kbps to 48kbps */ + if ( limit_high > 48000 / 50 ) + { + limit_high = 48000 / 50; + } +#endif +#endif + + tmp = (int16_t) min( bits_CoreCoder[ch], limit_high ); diff += bits_CoreCoder[ch] - tmp; diff --git a/lib_com/options.h b/lib_com/options.h index 8b22dc430b84cf629e28cebd799f8d538207ae4a..85ec991fb6c1d78f37b963b1a6f14ea8a7f8a229 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -48,7 +48,8 @@ /* ################### Start DEBUGGING switches ########################### */ #ifndef RELEASE -/*#define DEBUGGING*/ /* Activate debugging part of the code */ +/* #define DEBUGGING */ /* Activate debugging part of the code */ + #endif /*#define WMOPS*/ /* Activate complexity and memory counters */ /*#define WMOPS_PER_FRAME*/ /* Output per-frame complexity (writes one float value per frame to the file "wmops_analysis") */ @@ -175,6 +176,11 @@ #define NONBE_1246_INF_COHERENCE_IN_HIGH_LEVEL_DTX /* Ericsson: Issue 1246: High level input which triggers DTX can lead to numerical overflow in coherence calculation */ #define NONBE_1211_DTX_BR_SWITCHING /* VA: issue 1211: fix crash in MASA DTX bitrate switching */ #define NONBE_1217_INIT_OBJ_EDIT /* VA: issue 1217: do object editing only when objects metadata is available */ +#define NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING /* Ericsson: issue 1180, corrected long term mute loop attnuation after 200ms in PhECU-PLC */ + +# ifdef DEBUGGING +# define NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING_DEBUG /* Ericsson FORCE HQ in music mode at 32 kbps for PLC simulations, -force HQ is not working at 32 kbps */ +# endif /* ##################### End NON-BE switches ########################### */ diff --git a/lib_dec/FEC_HQ_phase_ecu.c b/lib_dec/FEC_HQ_phase_ecu.c index 425ff21fe97a693c36a11f224bfd4b6366fc0ab3..2c5a9512b94829ad22167022a2f848e745599a45 100644 --- a/lib_dec/FEC_HQ_phase_ecu.c +++ b/lib_dec/FEC_HQ_phase_ecu.c @@ -263,10 +263,13 @@ static void trans_ana( const int16_t time_offs, /* i : Time offset */ const float est_mus_content, /* i : 0.0=speech_like ... 1.0=Music (==st->env_stab ) */ const int16_t last_fec, /* i : signal that previous frame was concealed with fec_alg*/ - float *alpha, /* o : Magnitude modification factors for fade to average */ - float *beta, /* o : Magnitude modification factors for fade to average */ - float *beta_mute, /* o : Factor for long-term mute */ - float Xavg[LGW_MAX] /* o : Frequency group average gain to fade to */ +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING + const int16_t element_mode, /* i : element_mode req to handle EVS_MONO specific BE path */ +#endif + float *alpha, /* o : Magnitude modification factors for fade to average */ + float *beta, /* o : Magnitude modification factors for fade to average */ + float *beta_mute, /* o : Factor for long-term mute */ + float Xavg[LGW_MAX] /* o : Frequency group average gain to fade to */ ) { const float *w_hamm; @@ -416,10 +419,27 @@ static void trans_ana( { mag_chg[k] = 0; } +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING + if ( element_mode != EVS_MONO ) + { + if ( k == 0 && burst_len > BETA_MUTE_THR ) /* beta_mute final long term attenuation adjusted only once per frame in the first sub-band, Ref Eq(184) in 26.447 */ + { + *beta_mute *= BETA_MUTE_FAC; + } + } + else + { + if ( burst_len > BETA_MUTE_THR ) /* legacy incorrect(too fast) EVS_MONO operation, still kept for BE. To be updated after EVS CR, ref Eq (184) in 26.447 */ + { + *beta_mute *= BETA_MUTE_FAC; + } + } +#else if ( burst_len > BETA_MUTE_THR ) { *beta_mute *= BETA_MUTE_FAC; } +#endif alpha[k] = mag_chg[k]; beta[k] = (float) ( sqrt( 1.0f - SQR( alpha[k] ) ) * *beta_mute ); if ( k >= LGW32k - 1 ) @@ -2098,7 +2118,11 @@ static void hq_phase_ecu( *time_offs = 0; } - trans_ana( prevsynth + 2 * output_frame - Lprot - *time_offs + ph_ecu_lookahead, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab, *last_fec, alpha, beta, beta_mute, Xavg ); + trans_ana( prevsynth + 2 * output_frame - Lprot - *time_offs + ph_ecu_lookahead, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab, *last_fec, +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING + element_mode, +#endif + alpha, beta, beta_mute, Xavg ); spec_ana( prevsynth + 2 * output_frame - Lprot - *time_offs + ph_ecu_lookahead, plocs, plocsi, num_p, X_sav, output_frame, bwidth, element_mode, &noise_fac, pcorr ); if ( prev_bfi && *last_fec ) @@ -2115,7 +2139,11 @@ static void hq_phase_ecu( *time_offs = MAX16B; /* continued muting will ensure that the now fixed seeds are not creating tones */ } - trans_ana( prevsynth + 2 * output_frame - Lprot, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab, 0, alpha, beta, beta_mute, Xavg ); /* 1.0 stable-music, 0.0 speech-like */ + trans_ana( prevsynth + 2 * output_frame - Lprot, mag_chg, &ph_dith, mag_chg_1st, output_frame, *time_offs, env_stab, 0, +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING + element_mode, +#endif + alpha, beta, beta_mute, Xavg ); /* 1.0 stable-music, 0.0 speech-like */ } mvr2r( X_sav, X, Lprot ); @@ -2201,7 +2229,10 @@ void hq_ecu( ( st->total_brate < 48000 && ( ( ph_ecu_HqVoicing || corr > 0.85 ) && !prev_bfi && ( !old_is_transient[0] || old_is_transient[1] ) ) ); ivas_mode_selection = ( N < PH_ECU_N_LIMIT ) || ( corr < PH_ECU_CORR_LIMIT ); - +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING_DEBUG + evs_mode_selection = 0; + ivas_mode_selection = 0; +#endif if ( ( ( st->element_mode == EVS_MONO ) && evs_mode_selection ) || ( ( st->element_mode != EVS_MONO ) && evs_mode_selection && ivas_mode_selection ) ) diff --git a/lib_enc/ivas_ism_metadata_enc.c b/lib_enc/ivas_ism_metadata_enc.c index c7b991e2f67912cc3472d0e489917bf779f53d8f..9f6984f6763f6bfc5c00b85f5f7712a468e2eddf 100644 --- a/lib_enc/ivas_ism_metadata_enc.c +++ b/lib_enc/ivas_ism_metadata_enc.c @@ -141,6 +141,14 @@ static void rate_ism_importance( if ( ( hIsmMeta[ch]->ism_metadata_flag == 0 || lowrate_metadata_flag[ch] == 1 ) && hSCE[ch]->hCoreCoder[0]->localVAD == 0 ) { ism_imp[ch] = ISM_NO_META; +#ifdef DEBUGGING +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING_DEBUG + if ( nchan_transport > 1 ) + { + ism_imp[ch] = ISM_LOW_IMP; /*use of ISM_NO_META may cause too low rate sum when forcing to HQ encoding modes */ + } +#endif +#endif } else if ( ctype == INACTIVE || ctype == UNVOICED ) { diff --git a/lib_enc/mdct_classifier.c b/lib_enc/mdct_classifier.c index a01482b47fcaf64b08f6865fa7b6149faa6c3835..c0ad724da748e021d341408ab77ef9507d222e2d 100644 --- a/lib_enc/mdct_classifier.c +++ b/lib_enc/mdct_classifier.c @@ -336,6 +336,13 @@ int16_t mdct_classifier( /* Restrict usage of HQ_core to supported operating range */ /* EVS: brate == st->total_brate */ /* IVAS: brate is the nominal bitrate while st->total_brate may fluctuate. This sets a hard limit for HQ at HQ_16k40 */ +#ifdef DEBUGGING +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING_DEBUG + clas_final = HQ_CORE; + /* note for ISM the bitrate can adaptively drop below 16.4 kbps , or be higher than 8kbps, thus activating TCX20 */ +#endif +#endif + if ( st->total_brate <= HQ_16k40 || brate < HQ_16k40 || st->bwidth == NB || brate > IVAS_48k ) { clas_final = TCX_20_CORE; @@ -347,6 +354,7 @@ int16_t mdct_classifier( hTcxEnc->last_gain1 = gain1; hTcxEnc->last_gain2 = gain2; + return clas_final; } diff --git a/lib_enc/mdct_selector.c b/lib_enc/mdct_selector.c index 0c2bd3a0a5775f8248b2885c62fd5ccca5e82436..e5f35a0e00effccbe3448ec4bb2a3e4cc322117d 100644 --- a/lib_enc/mdct_selector.c +++ b/lib_enc/mdct_selector.c @@ -255,6 +255,12 @@ void MDCT_selector( st->core = TCX_20_CORE; } +#ifdef DEBUGGING +#ifdef NONBE_FIX_1180_HQMDCT_PHECU_LT_MUTING_DEBUG + st->core = HQ_CORE; +#endif +#endif + /* Update memories */ if ( hi_sparse <= 0 ) diff --git a/lib_enc/speech_music_classif.c b/lib_enc/speech_music_classif.c index 3d17233c40991de6bfb44c555e86d9a532f541f3..4f917aae5d5fcb84d50af469b08480007472df62 100644 --- a/lib_enc/speech_music_classif.c +++ b/lib_enc/speech_music_classif.c @@ -352,8 +352,13 @@ void speech_music_classif( st->sp_aud_decision0 = st->sp_aud_decision1; } +#ifdef FORCE_AUDIO_DECISION + st->sp_aud_decision1 = 1; + sp_aud_decision +#endif - return; + + return; } diff --git a/scripts/sim_bursts.sh b/scripts/sim_bursts.sh new file mode 100644 index 0000000000000000000000000000000000000000..bfb24b71f40715534404f4893abdd9333ac23554 --- /dev/null +++ b/scripts/sim_bursts.sh @@ -0,0 +1,150 @@ +#!/bin/bash -xv + +# +# (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. +# + +set -euo pipefail # find when variables are not set but used anyway +IFS=$'\n\t' # space is not a separator in bash vectors definitions, for simple matrix row creation +#IFS=$' ' # space is a separation, for matrix row adressing + +NARG="$#" +echo NARG=$NARG + +help=0 +deconly=0 +#opt_cnt=0 + +if [ $NARG -gte 1 ] ; then +if [ "$1" == "-h" ] || [ "$1" == "-help" ]; then + help=1; + if [ $help -ne 0 ]; then + echo "Usage: $0 [-d] " + echo " -d: deconly (do not rerun encoder)" + exit + fi +fi + +if [ "$1" == "-d" ] || [ "$1" == "-deconly" ]; then + deconly=1; +fi + +fi + + + +echo POSTARGS +#MONOFILE="./testv/stv_muting_tones_and_noise3p2s_L48n" +#STEREOFILE="./testv/stv_muting_tones_and_noise3p2s_ST48n" + +#MONOFILE="./testv/stv_mut3x20s_L48n" +#STEREOFILE="./testv/stv_mut3x20s_ST48n" + +#MONOFILE="./testv/stv1MASA1TC48n" +#STEREOFILE="./testv/stv1MASA2TC48n" + +MONOFILE="./testv/stv_mut_pink20s_L48n" +STEREOFILE="./testv/stv_mut3x20s_ST48n" + + +#FECFILE="./testv/FEC_burstlens_10to34in40.g192" + +#FECFILE="./testv/FEC_bl10to34in40.g192" +#FERTAG="bl10to34" + +FECFILE="./testv/FEC_bl10to69in70.g192" +FERTAG="bl10to69" + + +#FECFILE="./testv/FEC_bl35to65in70.g192" +#FERTAG="bl35to65" + +IO="48" + +BR_ISM1="32000" +BR_ISM2="64000" + +#COND="HQLOCK" +#COND="DEFAULT" + +declare -a cond_arr=(HQONLY DEFAULT) + +## now loop through the condition array +for cond in "${cond_arr[@]}" +do + ENCOPT=(-FORCE MUSIC) # as array, working expand as ${ENCOPT[@]} + # ENCOPT="-FORCE MUSIC" # as string not ! working + + IVASCOD="../IVAS_cod_$cond.exe" + IVASDEC="../IVAS_dec_$cond.exe" + + if [ "$cond" == "DEFAULT" ] ; then + ENCOPT=() + + IVASCOD="../IVAS_cod.exe" + IVASDEC="../IVAS_dec.exe" + fi + + + echo ISM1 + #ISM1 + if [ $deconly -ne 1 ] ; then + rm -f $MONOFILE.ism1.$cond.ana + $IVASCOD ${ENCOPT[@]} -ISM 1 NULL $BR_ISM1 $IO $MONOFILE.wav $MONOFILE.ism1.$cond.ana + fi + $IVASDEC MONO $IO $MONOFILE.ism1.$cond.ana $MONOFILE.ism1.$cond.dec.no.fer.wav + rm -f tmp.ana + ~/bin/eid-xor -fer $MONOFILE.ism1.$cond.ana $FECFILE tmp.ana + #$IVASDEC -FEC $FECFILE MONO $IO $MONOFILE.ism1.$cond.ana $MONOFILE.ism1.$cond.dec.$FERTAG.fer.wav + $IVASDEC MONO $IO tmp.ana $MONOFILE.ism1.$cond.dec.$FERTAG.fer.wav + + #ISM2 + if [ $deconly -ne 1 ] ; then + \rm -f $STEREOFILE.ism2.$cond.ana + $IVASCOD ${ENCOPT[@]} -ISM 2 NULL NULL $BR_ISM2 $IO $STEREOFILE.wav $STEREOFILE.ism2.$cond.ana + fi + $IVASDEC STEREO $IO $STEREOFILE.ism2.$cond.ana $STEREOFILE.ism2.$cond.dec.no.fer.wav + rm -f tmp.ana + ~/bin/eid-xor -fer $STEREOFILE.ism2.$cond.ana $FECFILE tmp.ana + $IVASDEC STEREO $IO tmp.ana $MONOFILE.ism2.$cond.dec.$FERTAG.fer.wav + + #stereo + if [ $deconly -ne 1 ] ; then + \rm -f $STEREOFILE.stereo.$cond.ana + $IVASCOD ${ENCOPT[@]} -stereo $BR_ISM2 $IO $STEREOFILE.wav $STEREOFILE.stereo.$cond.ana + fi + $IVASDEC STEREO $IO $STEREOFILE.stereo.$cond.ana $STEREOFILE.stereo.$cond.dec.no.fer.wav + rm -f tmp.ana + ~/bin/eid-xor -fer $STEREOFILE.stereo.$cond.ana $FECFILE tmp.ana + $IVASDEC STEREO $IO tmp.ana $STEREOFILE.stereo.$cond.dec.$FERTAG.fer.wav + + #EVS (TBD) + echo $0 done with cond $cond + +done diff --git a/scripts/testv/FEC_bl10to69in70.g192 b/scripts/testv/FEC_bl10to69in70.g192 new file mode 100644 index 0000000000000000000000000000000000000000..c79e472fdbf4920202c70d7821ec306a8e6cfa51 --- /dev/null +++ b/scripts/testv/FEC_bl10to69in70.g192 @@ -0,0 +1 @@ +!k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k!k!k!k!k!k!k \ No newline at end of file diff --git a/scripts/testv/FEC_burstl_1_to_20.bin b/scripts/testv/FEC_burstl_1_to_20.bin new file mode 100644 index 0000000000000000000000000000000000000000..da46bd553171705945a2676e694aaaae0d547fb4 --- /dev/null +++ b/scripts/testv/FEC_burstl_1_to_20.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce4900a50bf68e4c8c856d8e88aa233d10e5c1897957d0ef315487134baf3614 +size 1100 diff --git a/scripts/testv/PL_perc30_itut_bfer.g192 b/scripts/testv/PL_perc30_itut_bfer.g192 new file mode 100644 index 0000000000000000000000000000000000000000..f287a231cbaf1118abcb76b4a237a546deb6cffc --- /dev/null +++ b/scripts/testv/PL_perc30_itut_bfer.g192 @@ -0,0 +1 @@ +!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k k k k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k k k k k k k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k k!k!k!k!k!k k k k!k!k k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k k k!k k k k!k!k!k k k k k!k!k!k!k!k k k!k k k k k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k k k k!k k k k k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k k k k!k!k!k k k k k k k k k k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k k k k k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k k k k k k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k k k k!k!k!k k k k k!k!k!k!k k k k k k!k!k!k!k!k!k!k k k!k k k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k k k k k k k k k!k k k k k k k k k k k!k k k k k k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k k k!k!k!k!k!k!k!k k k k k k k k k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k k!k!k!k k k k k k k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k k k k!k!k k k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k k k k k k k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k k k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k k!k!k!k!k!k!k!k!k!k k k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k!k!k!k!k!k!k k k k k k!k!k k k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k k k!k k k k k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k k k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k k k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k k k!k!k!k!k!k k k k k k k!k!k!k!k k!k!k!k k k k k k!k!k!k!k!k k k!k!k!k!k k k k k!k k k!k k!k!k!k!k!k k!k k k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k k k k k k k k k!k!k k k k!k!k k k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k k k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k k k k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k k k k!k k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k k k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k k k k k k k!k!k k k k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k k k k k k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k k k k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k k k k!k k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k k k k k k!k!k!k!k k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k k k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k k!k!k k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k k k k!k!k!k k k k k k k k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k k!k!k k k k k k k!k!k!k!k!k!k!k!k!k!k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k k k k k k!k!k!k k k k k k!k!k k k k k k k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k!k!k k k k k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k k k k k k k k!k k k k k k k k k!k!k!k!k!k k k k!k!k!k!k!k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k!k!k k k k k k k!k!k!k!k!k!k!k k k k k k k!k k k k k k!k k k k!k!k!k k k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k k k k k k k k k k!k!k k k k k k k k k!k!k k k k k k!k!k!k!k!k!k!k!k!k k k k k k k k!k!k!k k k k!k!k!k!k!k k k k!k!k!k!k k k k k k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k!k!k!k!k!k!k!k!k k k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k!k!k!k!k k k!k!k k k k k k!k!k!k!k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k!k!k!k!k!k k k k!k!k!k!k!k k k k k k k k k!k!k!k!k!k!k k k k k k k k k!k!k!k!k k!k!k!k k k k k k k!k!k!k!k!k!k!k!k!k k k k k!k!k!k!k!k!k!k!k k k k k k k k k k k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k!k k k k \ No newline at end of file diff --git a/scripts/testv/ep_stats_bin_files.m b/scripts/testv/ep_stats_bin_files.m new file mode 100644 index 0000000000000000000000000000000000000000..9aec93950519ba7918ace2434007466687c7098f --- /dev/null +++ b/scripts/testv/ep_stats_bin_files.m @@ -0,0 +1,38 @@ +function bl=ep_stats_bin_files(name) +%function bl=eps_stats_bin_files(name) +% +% Check burst length and total fer of .bin files +% format PC/Linux signed 16 bit words, int16_t value 1=BAD, value 0 = GOOD +% +% Copyright Ericsson AB(2024-2025) + +if nargin <1 + % name='FEC_burstl_1_to_20' + name='FEC_burstl_1_to_30' + % name='FEC_burstl_1_to_65' + % name='./FEC_burstl_1_to_65flip' + name= [ name, '.bin']; + % evaluate + % or find first file in folder +end + +name2 = strrep(name,'_','\_'); +[fid, msg] = fopen(name,'r','n') ; +e=fread(fid,inf,'int16'); +fclose(fid); + +a=find(diff(e)==1); +b=find(diff(e)==-1); +bl=b-a; + +fer_pct = 100*sum(e==1)/length(e); + +h=histogram(bl,0.5:max(bl+.5),'normalization','probability'); +title(sprintf("%s, Total FER=%.2f %%, frames=%d, Av. burstlen=%.2f",name2, fer_pct, length(e),mean(bl) )) +set(gca,'xtick',1:max(bl)) +ylabel('probablility'); +xlabel('burst length') +grid + + +return diff --git a/scripts/testv/gen_ep_long_bursts.m b/scripts/testv/gen_ep_long_bursts.m new file mode 100644 index 0000000000000000000000000000000000000000..32980d943c7ec820ff4079f0238730b0fd0987ba --- /dev/null +++ b/scripts/testv/gen_ep_long_bursts.m @@ -0,0 +1,228 @@ +function pat_ser = gen_ep_long_bursts(l_min, l_max, period_frames, n_periods, file_name_no_ext, seed_in ) +%function gen_ep_long_bursts(l_min, l_max, period_frames, file_name, seed_in, ) +% +% examples: +% gen_ep_long_bursts(10, 35, 40, 25,'FEC_burstlens_10to35in40') +% gen_ep_long_bursts(38, 39, 40, 2,'FEC_burstlens_38to39in40') +% +% generate long burst sequences for regression testing of PLC algorithms +% if n_periods is less than n_burstlens = l_max-lmin+1 , then +% a random selection of burst lengths between l_min and l_max takes place +% but l_min and l_max is always a part of the generated set +% +% first frame in any period of period_frames is always a good frame ! +% +% generates a .bin file and a .g192 FER file +% l_min smallest burst length +% l_max largest burst length : l_max > l_min, l_max < periodframes +% period frames period : period_frames > l_max, period_frames >=2 +% n_periods number of periods, default one period per possible burst length +% filename_no_ext filename , default filename FEC_burstlens_XtoYinZ{.bin,.g192} +% seed_in seed , seed for burst positions in a period and period scrambling +% outputs +% pat_ser 0= good, 1 == bad +% bin file in format PC/Linux signed 16 bit words, int16_t value 1=BAD, value 0 = GOOD +% g192 file in format PC/Linux GOOD synchword = "0x6b21", bad synchword "0x6b20", +% wav file at 48kHz 20ms frames , showing the BFi flag as 16384(bad) or 0(good) +% Copyright Ericsson AB(2024-2025) + + +local_dbg = 1; + + +% wav plot to see the error pattern in synch with wav synthesis file +fs=48000; +fps=50; % 50 Hz +samplesPerFrame = floor(fs/fps); + + +if nargin < 3 + help gen_ep_long_bursts + disp('exiting') + return +end + +if nargin < 4 + n_periods = l_max-l_min+1; + % generates all possible burst lengths +end + +if nargin < 5 + base_name = sprintf("FEC_bl%dto%din%d",l_min,l_max,period_frames) +else + base_name=file_name_no_ext; +end + +if nargin < 6 + rng('default') +else + rng(seed_in) +end + +assert(l_min>0 , "gen_ep_long_bursts:l_min"," invalid l_min"); +assert(l_max>l_min , "gen_ep_long_bursts:l_max"," invalid l_max"); +assert(period_frames>l_max , "gen_ep_long_bursts:period_frames"," invalid period_frames"); +assert(n_periods>=2 , "gen_ep_long_bursts:n_periods"," invalid n_periods"); + +namebin= sprintf('%s.bin',base_name); +nameg192= sprintf('%s.g192',base_name); +namewav= sprintf('%s.frsize.%d.fs.%d.wav',base_name, samplesPerFrame, fs); + + +n_burstlens= l_max-l_min+1; + + +%generate the patterns matrix +% (will be flattened in the end) + +pat = zeros(n_periods,period_frames); +taken=zeros(1,n_periods); + +if ( n_periods==2 ) + % min length + startp = randi( [ 2 period_frames-l_min+1 ]) + pat(1,startp:(startp+l_min-1))=1; + assert( sum(pat(1,:))==l_min); + taken(1)=1; + + % max length + startp = randi( [ 2 period_frames-l_max+1 ]); + pat(2, startp:(startp+l_max-1))=1; + assert( sum(pat(2,:))==l_max); + taken(2)=1; +else + % pseudo random assignment + % always include min and max lengths first + + % min length + p=randi([1 n_periods]); + startp = randi( [ 2 period_frames-l_min+1 ]); + pat(p,startp:(startp+l_min-1))=1; + assert( sum(pat(p,:))==l_min); + taken(p)=1; + + % max length + p = randi([1 n_periods]); + while taken(p)==1, + p = randi([1 n_periods]); + end + assert(taken(p)==0); + startp = randi( [ 2 period_frames-l_max+1 ]); + pat(p, startp:(startp+l_max-1))=1; + assert( sum(pat(p,:))==l_max); + taken(p)=1; + +end + + disp pat + + % now inject all remaining possible burstlengths as far as possible + n_rem = n_burstlens - 2; % = l_max-l_min+1 -2 ; + unique_blens = l_min + randperm ( n_rem, n_rem); + n_left = min(numel(unique_blens), n_periods-2 ) + + for bidx=1:n_left, + p = find( taken==0,1,'first'); + assert(taken(p)==0); + blen =unique_blens(bidx); + startp = randi( [ 2 period_frames-blen+1 ]); + pat(p, startp:(startp+blen-1))=1; + assert( sum(pat(p,:))==blen); + taken(p)=1; + end + + % if any remaining periods + % simply randomize the burst length + % random fil of the rest + while sum(taken) < n_periods, + p = find( taken==0, 1,'first'); + assert(taken(p)==0); + blen =randi( [l_min l_max]); + startp = randi( [ 2 period_frames-blen+1 ]); + pat(p, startp:(startp+blen-1))=1; + assert( sum(pat(p,:))==blen); + taken(p)=1; + end + + disp pat + + + % serialize + pat_ser=transpose(pat); + pat_ser=pat_ser(:); + + % write FER files + [fid, msg] = fopen(namebin,'w','n') ; + cnt=fwrite(fid,pat_ser,'int16'); + fclose(fid); + + disp(sprintf ("Wrote FER file %s (0's or 1's) ", namebin)); + + assert(cnt== numel(pat_ser) ) + + [fid, msg] = fopen(nameg192,'w','n') ; + % Linux GOOD synchword = "0x6b21", bad synchword "0x6b20", + for i=1:numel(pat_ser) + sym = 0x6b21 ; % 27425 good synch , bfi==0 + if( pat_ser(i) == 1) + sym= 0x6b20 ; % 27424 bad synch , BFI==1 + end + cnt=fwrite(fid,sym,'uint16'); + assert(cnt==1); + end + fclose(fid); + disp(sprintf ("Wrote FER file %s (0x6b21's or 0x6b20's) ", nameg192)); + + + % write wav file + + % create matrix + n_frames = numel(pat_ser); + y=repmat(int16(16384*(1-pat_ser)),1, samplesPerFrame ) ;% 16384=good, 0 = bad + y=transpose(y); + y=y(:); + + audiowrite(namewav,y,fs) + + disp(sprintf ("Wrote fer pattern wave file %s (0's for bad or 16384 for good) ", namewav)); + + + if local_dbg + figure(1) + clf; + + name2 = strrep(base_name,'_','\_'); + %[fid, msg] = fopen(name,'r','n') ; + %e=fread(fid,inf,'int16'); + %fclose(fid); + + e = pat_ser; + if e(end)==1, + e(end+1)=0; % terminate last burst + end + a=find(diff(e)==1); + b=find(diff(e)==-1); + assert(numel(a)== numel(b)); + + bl=b-a; + + fer_pct = 100*sum(e==1)/length(e); + + h=histogram(bl,0.5:max(bl+.5),'normalization','probability'); + title(sprintf("%s, Total FER=%.2f %%, frames=%d, Av. burstlen=%.2f",name2, fer_pct, length(e),mean(bl) )) + set(gca,'xtick',1:max(bl)) + ylabel('probablility'); + xlabel('burst length') + grid + + figure(2) + clf; + clear yy + [yy, Fs_y] = audioread(namewav, 'native'); + plot(yy); + name2wav = strrep(namewav,'_','\_'); + title( sprintf('%s, frSize=%d, Fs=%d, length: %.2fs (%d frames)', name2wav,samplesPerFrame, Fs_y, numel(yy)/Fs_y, int16(floor(numel(yy)/samplesPerFrame)))); + legend("16384=good, 0=bad"); + end + +return