diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 275b91bfbb4ff8d5994d938242e5f017bdc292e2..79bac14eb7f62f83dfcdea333fce1be51b20d232 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -170,10 +170,10 @@ stages: - current_commit_sha=$(git rev-parse HEAD) ### build reference binaries - git checkout $FLOAT_REF_BRANCH - - git pull origin $FLOAT_REF_BRANCH + - git pull - *activate-debug-mode-info-if-set - make clean - - make -j >> /dev/null + - make -j - mv ./IVAS_cod ./$REF_ENCODER_PATH_FOR_BUILD_DO_NOT_MODIFY - mv ./IVAS_dec ./$REF_DECODER_PATH_FOR_BUILD_DO_NOT_MODIFY - mv ./IVAS_rend ./IVAS_rend_ref @@ -186,10 +186,10 @@ stages: - current_commit_sha=$(git rev-parse HEAD) ### build merge target binaries - git checkout $CI_MERGE_REQUEST_TARGET_BRANCH_NAME - - git pull origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME + - git pull - *activate-debug-mode-info-if-set - make clean - - make -j >> /dev/null + - make -j - mv ./IVAS_cod ./$MERGE_TARGET_ENCODER_PATH_FOR_BUILD_DO_NOT_MODIFY - mv ./IVAS_dec ./$MERGE_TARGET_DECODER_PATH_FOR_BUILD_DO_NOT_MODIFY - mv ./IVAS_rend ./IVAS_rend_merge_target @@ -204,7 +204,7 @@ stages: ### build dut binaries - *activate-debug-mode-info-if-set - make clean - - make -j >> /dev/null + - make -j .build-and-create-float-ref-outputs: &build-and-create-float-ref-outputs - *build-float-ref-and-dut-binaries @@ -234,7 +234,7 @@ stages: - git fetch - git restore . # Just as a precaution - git checkout $BASOP_CI_BRANCH_PC_REPO - - git pull origin $BASOP_CI_BRANCH_PC_REPO + - git pull - cd - - cp -r $SCRIPTS_DIR/ci . - cp -r $SCRIPTS_DIR/scripts . @@ -402,8 +402,6 @@ stages: - INV_LEVEL_SCALING=$(awk "BEGIN {print 1.0 / $LEVEL_SCALING}") - comp_args="--mld --ssnr --odg --scalefac $INV_LEVEL_SCALING" - - summary_args="MLD DIFF SSNR ODG" - - REPORT_ARG="" - if [ "$ENCODER_TEST" = "true" ]; then comp_args="${comp_args} --enc_stats"; fi - if [ "$DELTA_ODG" = "true" ]; then comp_args="${comp_args} --odg_bin"; MEASURES_FOR_REPORT="$MEASURES_FOR_REPORT DELTA_ODG"; fi - if [ "$SPLIT_COMPARISON" = "true" ]; then comp_args="${comp_args} --split-comparison"; fi @@ -529,7 +527,7 @@ stages: - *build-float-ref-binaries - *build-merge-target-binaries - make clean - - make -j >> /dev/null + - make -j - *check-up-to-date-in-comparison-jobs - exit_code_target=0 @@ -537,7 +535,7 @@ stages: - exit_code=0 - rm -rf .pytest_cache || true - - python3 -m pytest --tb=no -q $TEST_SUITE -v --keep_files --create_cut --html=$HTML_REPORT --self-contained-html --junit-xml=$XML_REPORT --ref_encoder_path $MERGE_TARGET_ENCODER_PATH --ref_decoder_path $MERGE_TARGET_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH -n auto --testcase_timeout $testcase_timeout > pytest_log.txt || exit_code=$? + - python3 -m pytest --tb=no -q $TEST_SUITE -v --keep_files --create_cut --html=$HTML_REPORT --self-contained-html --junit-xml=$XML_REPORT --mld --ssnr --odg --ref_encoder_path $MERGE_TARGET_ENCODER_PATH --ref_decoder_path $MERGE_TARGET_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH -n auto --testcase_timeout $testcase_timeout > pytest_log.txt || exit_code=$? - if [ $exit_code -ne 0 ]; then - exit_code=$EXIT_CODE_NON_BE @@ -656,16 +654,13 @@ stages: - echo $CI_MERGE_REQUEST_TITLE > tmp.txt - allow_regressions_flag=$(grep -c --ignore-case "\[allow[ -]*regression\]" tmp.txt) || true - - INV_LEVEL_SCALING=$(awk "BEGIN {print 1.0 / $LEVEL_SCALING}") - - comp_args="--mld --ssnr --odg --scalefac $INV_LEVEL_SCALING" - ### run branch first # this per default builds the branch and the reference and creates the reference outputs - *build-and-create-float-ref-outputs - *check-up-to-date-in-comparison-jobs # need to restore cache again - *overwrite-pytest-cache-with-artifact - - python3 -m pytest --tb=no -q $TEST_SUITE -v --keep_files --create_cut --html=$HTML_REPORT_BRANCH --self-contained-html --junit-xml=$XML_REPORT_BRANCH $comp_args --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH -n auto --testcase_timeout $testcase_timeout || true + - python3 -m pytest --tb=no -q $TEST_SUITE -v --keep_files --create_cut --html=$HTML_REPORT_BRANCH --self-contained-html --junit-xml=$XML_REPORT_BRANCH --mld --ssnr --odg --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH -n auto --testcase_timeout $testcase_timeout || true - zero_errors_branch=$(cat $XML_REPORT_BRANCH | grep -c 'errors="0"') || true - python3 scripts/parse_xml_report.py $XML_REPORT_BRANCH $CSV_BRANCH @@ -678,12 +673,12 @@ stages: ### run main now - git checkout $CI_MERGE_REQUEST_TARGET_BRANCH_NAME - - git pull origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME + - git pull - make clean - - make -j >> /dev/null + - make -j # need to restore cache again - *overwrite-pytest-cache-with-artifact - - python3 -m pytest --tb=no -q $TEST_SUITE -v --keep_files --create_cut --html=$HTML_REPORT_MAIN --self-contained-html --junit-xml=$XML_REPORT_MAIN $comp_args --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH -n auto --testcase_timeout $testcase_timeout || true + - python3 -m pytest --tb=no -q $TEST_SUITE -v --keep_files --create_cut --html=$HTML_REPORT_MAIN --self-contained-html --junit-xml=$XML_REPORT_MAIN --mld --ssnr --odg --ref_encoder_path $REF_ENCODER_PATH --ref_decoder_path $REF_DECODER_PATH --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH -n auto --testcase_timeout $testcase_timeout || true - python3 scripts/parse_xml_report.py $XML_REPORT_MAIN $CSV_MAIN ### compare the two csv files for regressions @@ -779,7 +774,7 @@ stages: - make_args="$make_args IGNORELIST=1" - fi - make clean - - make -j $make_args >> /dev/null + - make -j $make_args - testcase_timeout_arg="--testcase_timeout $TESTCASE_TIMEOUT_LTV_SANITIZERS" # disable per-testcase timeout for msan to evaluate what is going on that it takes so long - if [[ $CLANG_NUM = 1 ]]; then @@ -821,13 +816,10 @@ stages: - fi - *build-float-ref-and-dut-binaries - - INV_LEVEL_SCALING=$(awk "BEGIN {print 1.0 / $LEVEL_SCALING}") - - comp_args="--mld --ssnr --odg --scalefac $INV_LEVEL_SCALING" - ### run pytest - exit_code=0 - - python3 -m pytest --tb=no $TEST_SUITE -v --create_cut --html=report-ref.html --self-contained-html --junit-xml=report-junit-ref.xml $comp_args -n auto --testcase_timeout $testcase_timeout --dut_encoder_path $REF_ENCODER_PATH --dut_decoder_path $REF_DECODER_PATH --compare_to_input || exit_code=$? - - python3 -m pytest --tb=no $TEST_SUITE -v --create_cut --html=report-dut.html --self-contained-html --junit-xml=report-junit-dut.xml $comp_args -n auto --testcase_timeout $testcase_timeout --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH --compare_to_input || exit_code=$? + - python3 -m pytest --tb=no $TEST_SUITE -v --create_cut --html=report-ref.html --self-contained-html --junit-xml=report-junit-ref.xml --mld --ssnr --odg -n auto --testcase_timeout $testcase_timeout --dut_encoder_path $REF_ENCODER_PATH --dut_decoder_path $REF_DECODER_PATH --compare_to_input || exit_code=$? + - python3 -m pytest --tb=no $TEST_SUITE -v --create_cut --html=report-dut.html --self-contained-html --junit-xml=report-junit-dut.xml --mld --ssnr --odg -n auto --testcase_timeout $testcase_timeout --dut_encoder_path $DUT_ENCODER_PATH --dut_decoder_path $DUT_DECODER_PATH --compare_to_input || exit_code=$? - zero_errors_ref=$(cat report-junit-ref.xml | grep -c 'errors="0"') || true - zero_errors_dut=$(cat report-junit-dut.xml | grep -c 'errors="0"') || true - python3 scripts/parse_xml_report.py report-junit-ref.xml report-ref.csv @@ -1562,7 +1554,7 @@ coverage-test-on-main-scheduled: - *copy-ltv-files-to-testv-dir - *build-float-ref-binaries # Build DuT binaries with GCOV - - make clean >> /dev/null + - make clean - make GCOV=1 -j - cp IVAS_rend IVAS_rend_ref # Copy to ensure instrumented renderer is run in the first pytest call @@ -1620,7 +1612,7 @@ be-2-evs-26444: - *print-common-info - *update-scripts-repo - sed -i".bak" "s/\(#define EVS_FLOAT\)/\/\/\1/" lib_com/options.h - - make -j >> /dev/null + - make -j # copy over to never change the testvector dir - cp -r $EVS_BE_TEST_DIR_BASOP ./evs_be_test @@ -1684,7 +1676,7 @@ voip-be-on-merge-request: script: - *print-common-info - make clean - - make -j >> /dev/null + - make -j - python3 -m pytest tests/test_be_for_jbm_neutral_dly_profile.py @@ -1773,19 +1765,13 @@ voip-be-on-merge-request: - *update-ltv-repo - *build-float-ref-and-dut-binaries - *complexity-measurements-setup - # delete previous jobs logfiles if present (-f flag ensures return calue of 0 even in first run where this folder is not present) - - rm -rf COMPLEXITY/logs - which coan - allow_failure: - exit_codes: - - 123 artifacts: name: "$CI_JOB_NAME--$CI_COMMIT_REF_NAME--sha-$CI_COMMIT_SHA" when: always expire_in: 2 week paths: - $CI_JOB_NAME-public - - COMPLEXITY/logs complexity-stereo-in-stereo-out: extends: diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 17566e3cb20bf02778690228d2fe096a13fdbbb6..3612e6730dd6e1e92e3a41adca793d238246157f 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -2665,7 +2665,13 @@ void ms_inv_mask_processing_fx( const Word32 x_1_fx[], /* i : spectrum 2 */ Word32 x_inv_0_fx[], /* o : inverse spectrum 1 */ Word32 x_inv_1_fx[], /* o : inverse spectrum 2 */ - Word16 maxSfb /* i : number of stereo frequency bands */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 *x_0_e, + Word16 *x_1_e, + Word16 *x_inv_0_e, + Word16 *x_inv_1_e, +#endif + Word16 maxSfb /* i : number of stereo frequency bands */ ); void ms_processing_fx( @@ -2675,13 +2681,21 @@ void ms_processing_fx( const Word16 iSubframe, /* i : subframe number */ Word32 x_0_fx[], /* i/o: spectrum 1 */ Word32 x_1_fx[], /* i/o: spectrum 1 */ - Word16 maxSfb /* i : number of stereo frequency bands*/ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 *x_0_e, + Word16 *x_1_e, +#endif + Word16 maxSfb /* i : number of stereo frequency bands*/ ); void convertToMS_fx( const Word16 L_frame, /* i : frame length */ Word32 x0[], /* i/o: mid/left channel coefficients */ Word32 x1[], /* i/o: side/right channel coefficients */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 *x0_e, + Word16 *x1_e, +#endif const Word32 norm_fac /* i : normalization factor */ ); @@ -2695,7 +2709,12 @@ void IGFEncStereoEncoder_fx( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : IGF handle */ const Word32 *mdctSpectrumL_fx, /* i : left spectrum */ const Word32 *mdctSpectrumR_fx, /* i : right spectrum */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + const Word16 mdctSpectrumL_e, + const Word16 mdctSpectrumR_e, +#else Word16 q_mdctSpectrum, +#endif Word16 *msMask, /* i/o: MS mask */ Word16 *igfStereoMode, /* o : IGF stereo mode */ const Word16 mdct_stereo_mode, /* i : MDCT stereo mode */ @@ -2711,8 +2730,14 @@ void stereo_coder_tcx_fx( Word32 *inv_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ Word32 *inv_mdst_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ const Word16 mct_on, /* i : flag mct block (1) or stereo (0) */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 mdst_spectrum_e[CPE_CHANNELS][NB_DIV], + Word16 inv_spectrum_e[CPE_CHANNELS][NB_DIV], + Word16 inv_mdst_spectrum_e[CPE_CHANNELS][NB_DIV] ); +#else Word16 exp_spec, Word16 exp_mdst_spec ); +#endif // bw_detect_fx.c Word16 set_bw_mct_fx( @@ -2741,7 +2766,12 @@ void apply_MCT_enc_fx( Word32 *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum */ Word32 *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum */ Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ - const Word16 nchan /* i : number of channels */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 mdst_spectrum_e[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum exponent Q0*/ + Word16 inv_spectrum_e[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inv spectrum exponent Q0*/ + Word16 inv_mdst_spectrum_e[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum exponent Q0*/ +#endif + const Word16 nchan /* i : number of channels */ ); void ivas_spar_config_fx( @@ -3343,7 +3373,10 @@ void mctStereoIGF_enc_fx( Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as powerSpec_fx but for inverse spect.*/ Word16 q_powerSpecMsInv[MCT_MAX_CHANNELS], /* i : Q for powSpecMsInv_fx */ Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ - const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 q_inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : Q for inv_spectrum_fx */ +#endif + const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ ); void ivas_mct_core_enc_fx( diff --git a/lib_com/options.h b/lib_com/options.h index 2f1e82de892287fe20a9e242f4d06a7f967f5a7a..a1c8897302db9b44e5c9335b68b6a5fca8ab51ba 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -73,6 +73,9 @@ #define FIX_1379_MASA_ANGLE_ROUND +#define FIX_1464_SQ_GAIN_PRECISION +#define FIX_1464_NO_SINGLE_SPEC_Q + /* Note: each compile switch (FIX_1101_...) is independent from the other ones */ //#define OPT_STEREO_32KBPS_V1 /* Optimization made in stereo decoding path for 32kbps decoding */ #define OPT_AVOID_STATE_BUF_RESCALE /* Optimization made to avoid rescale of synth state buffer */ diff --git a/lib_enc/fd_cng_enc_fx.c b/lib_enc/fd_cng_enc_fx.c index a7339e65334a0964eaeecdfd2a4fa1c3c9a35a9a..8a8c77a348a93d00e07bec03fc3827940923eaa6 100644 --- a/lib_enc/fd_cng_enc_fx.c +++ b/lib_enc/fd_cng_enc_fx.c @@ -2864,7 +2864,11 @@ void FdCngEncodeMDCTStereoSID_fx( /* M/S transform on log envelopes */ IF( is_inp_ms == 0 ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], &ms_ptr_e, &ms_ptr_e, ONE_IN_Q30 ); // ms_ptr_e = Q23; +#else convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q30 ); // ms_ptr_e = Q23; +#endif } gb = find_guarded_bits_fx( N ); @@ -2967,7 +2971,11 @@ void FdCngEncodeMDCTStereoSID_fx( /* undo M/S */ IF( is_inp_ms == 0 ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], &ms_ptr_e, &ms_ptr_e, ONE_IN_Q31 ); +#else convertToMS_fx( N, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q31 ); +#endif } /* Compute gain against original left and right channels */ @@ -3151,7 +3159,11 @@ void FdCngEncodeDiracMDCTStereoSID_fx( move16(); /* M/S transform on log envelopes */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + convertToMS_fx( N[0], ms_ptr_fx[0], ms_ptr_fx[1], &ms_ptr_e, &ms_ptr_e, ONE_IN_Q30 ); +#else convertToMS_fx( N[0], ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q30 ); +#endif E_fx[0] = 0; move32(); FOR( p = 0; p < N[0]; p++ ) @@ -3234,7 +3246,11 @@ void FdCngEncodeDiracMDCTStereoSID_fx( move32(); /* undo M/S */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + convertToMS_fx( NPART, ms_ptr_fx[0], ms_ptr_fx[1], &ms_ptr_e, &ms_ptr_e, ONE_IN_Q31 ); +#else convertToMS_fx( NPART, ms_ptr_fx[0], ms_ptr_fx[1], ONE_IN_Q31 ); +#endif /* restore channel noise envelopes */ FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 9769d83b6c8ba64acd1546156bbaaaba3153f65d..e1c2172447672e140c770022fc93dae24f6c181b 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -1171,13 +1171,21 @@ static void IGF_CalculateStereoEnvelope_fx( move16(); // tmp_tb = IGF_getSFM_ivas(pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1]) / IGF_getCrest_ivas(pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1]); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + sfm = IGF_getSFM( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, swb_offset[sfb], swb_offset[sfb + 1] ); +#else sfm = IGF_getSFM_ivas_fx( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, swb_offset[sfb], swb_offset[sfb + 1] ); +#endif crest = IGF_getCrest( &crest_exp, pPowerSpectrum_fx, pPowerSpectrum_e, swb_offset[sfb], swb_offset[sfb + 1] ); tmp_tb_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); tmp_tb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); /*stores the resultant exponent for tmp_tb_fx*/ // tmp_sb = IGF_getSFM_ivas(tileSrcSpec, 0, strt_cpy - tmp) / IGF_getCrest_ivas(tileSrcSpec, 0, strt_cpy - tmp); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + sfm = IGF_getSFM( &sfm_exp, tileSrcSpec_fx, &tileSrcSpec_e, 0, sub( strt_cpy, tmp ) ); +#else sfm = IGF_getSFM_ivas_fx( &sfm_exp, tileSrcSpec_fx, &tileSrcSpec_e, 0, sub( strt_cpy, tmp ) ); +#endif crest = IGF_getCrest( &crest_exp, tileSrcSpec_fx, tileSrcSpec_e, 0, sub( strt_cpy, tmp ) ); tmp_sb_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); tmp_sb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); /*stores the resultant exponent for tmp_sb_fx*/ @@ -1322,7 +1330,11 @@ static void IGF_CalculateStereoEnvelope_fx( { Word16 shift = shr( width, 1 ); // shiftedSFM = IGF_getSFM_ivas( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ) / IGF_getCrest_ivas( pPowerSpectrum, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift ); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + sfm = IGF_getSFM( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, sub( swb_offset[sfb], shift ), sub( swb_offset[sfb + 1], shift ) ); +#else sfm = IGF_getSFM_ivas_fx( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, sub( swb_offset[sfb], shift ), sub( swb_offset[sfb + 1], shift ) ); +#endif crest = IGF_getCrest( &crest_exp, pPowerSpectrum_fx, pPowerSpectrum_e, sub( swb_offset[sfb], shift ), sub( swb_offset[sfb + 1], shift ) ); shiftedSFM_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); } @@ -1331,7 +1343,11 @@ static void IGF_CalculateStereoEnvelope_fx( Word16 shift; shift = shr( width, 1 ); // shiftedSFM = IGF_getSFM_ivas( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ) / IGF_getCrest_ivas( pPowerSpectrum, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift ); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + sfm = IGF_getSFM( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, add( swb_offset[sfb], shift ), add( swb_offset[sfb + 1], shift ) ); +#else sfm = IGF_getSFM_ivas_fx( &sfm_exp, pPowerSpectrum_fx, &pPowerSpectrum_e, add( swb_offset[sfb], shift ), add( swb_offset[sfb + 1], shift ) ); +#endif crest = IGF_getCrest( &crest_exp, pPowerSpectrum_fx, pPowerSpectrum_e, add( swb_offset[sfb], shift ), add( swb_offset[sfb + 1], shift ) ); shiftedSFM_fx = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); } @@ -2515,15 +2531,24 @@ void IGFEncResetTCX10BitCounter_ivas_fx( * * apply the IGF encoder, main encoder interface *-------------------------------------------------------------------*/ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q +/* temporary change */ +static Word16 e_ps[1200 * 2]; +#endif void IGFEncApplyMono_ivas_fx( - Encoder_State *st, /* i : Encoder state */ - Word16 powerSpectrum_len, /* i: length of pPowerSpectrum_fx buffer */ - const Word16 igfGridIdx, /* i : IGF grid index */ - Word32 *pMDCTSpectrum_fx, /* i/o: MDCT spectrum */ - Word16 e_mdct, /* i : exponent of pMDCTspectrum */ - Word32 *pPowerSpectrum_fx, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ - Word16 *e_ps, /* i : exponent of pPowerSpectrum */ + Encoder_State *st, /* i : Encoder state */ + Word16 powerSpectrum_len, /* i: length of pPowerSpectrum_fx buffer */ + const Word16 igfGridIdx, /* i : IGF grid index */ + Word32 *pMDCTSpectrum_fx, /* i/o: MDCT spectrum */ + Word16 e_mdct, /* i : exponent of pMDCTspectrum */ + Word32 *pPowerSpectrum_fx, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + /* temporary change */ + Word16 *_e_ps, /* i : exponent of pPowerSpectrum */ +#else + Word16 *e_ps, /* i : exponent of pPowerSpectrum */ +#endif const Word16 isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ const Word8 isTNSActive, /* i : flag indicating if the TNS is active */ const Word16 sp_aud_decision0, /* i : first stage switching decision */ @@ -2553,6 +2578,11 @@ void IGFEncApplyMono_ivas_fx( move16(); } +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + /* temporary change */ + set16_fx( e_ps, *_e_ps, 1200 * 2 ); +#endif + test(); IF( !isTNSActive && isTCX20 ) { diff --git a/lib_enc/ivas_mct_core_enc_fx.c b/lib_enc/ivas_mct_core_enc_fx.c index 0ab232dd9552d462eb7cc75fc22638baeea4f871..6cb02418b6eee45695758c235ba4770321efd767 100644 --- a/lib_enc/ivas_mct_core_enc_fx.c +++ b/lib_enc/ivas_mct_core_enc_fx.c @@ -241,6 +241,11 @@ void ivas_mct_core_enc_fx( Word32 *inv_mdst_spectrum_fx[MCT_MAX_CHANNELS][2]; Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][2]; Word32 *mdst_spectrum_fx[MCT_MAX_CHANNELS][2] = { { NULL } }; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 inv_mdst_spectrum_e[MCT_MAX_CHANNELS][2]; + Word16 inv_spectrum_e[MCT_MAX_CHANNELS][2]; + Word16 mdst_spectrum_e[MCT_MAX_CHANNELS][2]; +#endif Word32 inv_spectrum_long_fx[MCT_MAX_CHANNELS][L_FRAME48k]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ Word16 total_side_bits; Word16 chBitRatios[MCT_MAX_CHANNELS]; @@ -398,8 +403,12 @@ void ivas_mct_core_enc_fx( /*--------------------------------------------------------------* * MCT algorithm *---------------------------------------------------------------*/ - +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + apply_MCT_enc_fx( hMCT, sts, mdst_spectrum_fx, inv_spectrum_fx, inv_mdst_spectrum_fx, + mdst_spectrum_e, inv_spectrum_e, inv_mdst_spectrum_e, nChannels ); +#else apply_MCT_enc_fx( hMCT, sts, mdst_spectrum_fx, inv_spectrum_fx, inv_mdst_spectrum_fx, nChannels ); +#endif /*--------------------------------------------------------------* * Power spectrum calculation for Noise Estimation @@ -609,7 +618,11 @@ void ivas_mct_core_enc_fx( { IF( hMCT->currBlockDataCnt > 0 ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + mctStereoIGF_enc_fx( hMCT, sts, orig_spectrum_fx, q_origSpec, powerSpec_fx, q_powSpec, powerSpecMsInv_fx, q_powerSpecMsInv, inv_spectrum_fx, inv_spectrum_e, sp_aud_decision0 ); +#else mctStereoIGF_enc_fx( hMCT, sts, orig_spectrum_fx, q_origSpec, powerSpec_fx, q_powSpec, powerSpecMsInv_fx, q_powerSpecMsInv, inv_spectrum_fx, sp_aud_decision0 ); +#endif } ELSE { diff --git a/lib_enc/ivas_mct_enc_mct_fx.c b/lib_enc/ivas_mct_enc_mct_fx.c index 94015abb7e0ddc68de2dcb04cb1c9da8740bad42..f683984363d6e0f8cb52cd4356cabcf7d4aad345 100644 --- a/lib_enc/ivas_mct_enc_mct_fx.c +++ b/lib_enc/ivas_mct_enc_mct_fx.c @@ -359,7 +359,13 @@ static void getBlockValues_fx( Word32 *mdst_spectrum[MCT_MAX_CHANNELS][2], /* i/o: MDST spectrum, Q = q_spec */ Word32 *inv_spectrum[MCT_MAX_CHANNELS][2], /* i/o: inverse spectrum, Q = q_spec */ Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][2], /* i/o: invers MDST spectrum, Q = q_spec */ - Word16 q_spec /* i : common Q factor of the above spectrum buffers */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 mdst_spectrum_e[MCT_MAX_CHANNELS][2], + Word16 inv_spectrum_e[MCT_MAX_CHANNELS][2], + Word16 inv_mdst_spectrum_e[MCT_MAX_CHANNELS][2] +#else + Word16 q_spec /* i : common Q factor of the above spectrum buffers */ +#endif ) { Word16 n; @@ -385,7 +391,11 @@ static void getBlockValues_fx( p_st[0] = sts[ch1]; p_st[1] = sts[ch2]; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + stereo_coder_tcx_fx( hBlock->hStereoMdct, p_st, hBlock->mask, p_mdst_spectrum, p_inv_spectrum, p_inv_mdst_spectrum, 1, mdst_spectrum_e, inv_spectrum_e, inv_mdst_spectrum_e ); +#else stereo_coder_tcx_fx( hBlock->hStereoMdct, p_st, hBlock->mask, p_mdst_spectrum, p_inv_spectrum, p_inv_mdst_spectrum, 1, sub( 31, q_spec ), sub( 31, q_spec ) ); +#endif test(); test(); @@ -629,7 +639,12 @@ void apply_MCT_enc_fx( Word32 *mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum Qx*/ Word32 *inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse spectrum Qx*/ Word32 *inv_mdst_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum Qx*/ - const Word16 nchan /* i : number of channels */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 mdst_spectrum_e[MCT_MAX_CHANNELS][NB_DIV], /* i/o: MDST spectrum exponent Q0*/ + Word16 inv_spectrum_e[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inv spectrum exponent Q0*/ + Word16 inv_mdst_spectrum_e[MCT_MAX_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum exponent Q0*/ +#endif + const Word16 nchan /* i : number of channels */ ) { Word16 ch, k, ch1, ch2, nSubframes, L_subframeTCX; @@ -803,8 +818,11 @@ void apply_MCT_enc_fx( /* calculate all related values: */ assert( sts[ch1]->mct_chan_mode != MCT_CHAN_MODE_IGNORE && sts[ch2]->mct_chan_mode != MCT_CHAN_MODE_IGNORE ); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + getBlockValues_fx( sts, ch1, ch2, hMCT->hBlockData[currBlockDataCnt], mdst_spectrum, inv_spectrum, inv_mdst_spectrum, mdst_spectrum_e, inv_spectrum_e, inv_mdst_spectrum_e ); +#else getBlockValues_fx( sts, ch1, ch2, hMCT->hBlockData[currBlockDataCnt], mdst_spectrum, inv_spectrum, inv_mdst_spectrum, sub( 31, sts[0]->hTcxEnc->spectrum_e[0] ) ); - +#endif IF( hMCT->hBlockData[currBlockDataCnt]->isActive == 0 ) { inactiveBlockDetected = add( inactiveBlockDetected, 1 ); @@ -988,7 +1006,10 @@ void mctStereoIGF_enc_fx( Word32 *powerSpecMsInv_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : same as powerSpec_fx but for inverse spect.*/ Word16 q_powerSpecMsInv[MCT_MAX_CHANNELS], /* i : Q for powSpecMsInv_fx */ Word32 *inv_spectrum_fx[MCT_MAX_CHANNELS][NB_DIV], /* i : inverse spectrum */ - const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 q_inv_spectrum[MCT_MAX_CHANNELS][NB_DIV], /* i : Q for inv_spectrum_fx */ +#endif + const Word16 sp_aud_decision0[MCT_MAX_CHANNELS] /* i : speech audio decision */ ) { Word32 *p_powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV]; @@ -1072,6 +1093,19 @@ void mctStereoIGF_enc_fx( IF( NE_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], hMCT->hBlockData[b]->hStereoMdct->IGFStereoMode[n] ) || EQ_16( hMCT->hBlockData[b]->hStereoMdct->mdct_stereo_mode[n], SMDCT_BW_MS ) ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 exp_SI_ch[CPE_CHANNELS], exp_pS_ch[CPE_CHANNELS], exp_pSI_ch[CPE_CHANNELS]; + exp_SI_ch[0] = sub( 31, q_inv_spectrum[ch1][n] ); + exp_SI_ch[1] = sub( 31, q_inv_spectrum[ch2][n] ); + exp_pSI_ch[0] = sub( 31, q_pSI_ch[0] ); + exp_pSI_ch[1] = sub( 31, q_pSI_ch[1] ); + exp_pS_ch[0] = sub( 31, q_pS_ch[0] ); + exp_pS_ch[1] = sub( 31, q_pS_ch[1] ); + + ProcessStereoIGF_fx( hMCT->hBlockData[b]->hStereoMdct, p_st, hMCT->hBlockData[b]->mask, + p_orig_spectrum_fx, q_origSpec, q_origSpec, + p_powerSpec_fx, exp_pS_ch, p_powerSpecMsInv_fx, exp_pSI_ch, p_inv_spectrum_fx, exp_SI_ch, n, sp_aud_decision0[ch1], p_st[0]->total_brate, 1 ); +#else Word16 exp_powerSpec_fx[CPE_CHANNELS], exp_powerSpecMsInv_fx[CPE_CHANNELS], exp_inv_spectrum_fx[CPE_CHANNELS]; FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) @@ -1086,6 +1120,7 @@ void mctStereoIGF_enc_fx( ProcessStereoIGF_fx( hMCT->hBlockData[b]->hStereoMdct, p_st, hMCT->hBlockData[b]->mask, p_orig_spectrum_fx, q_origSpec, q_origSpec, p_powerSpec_fx, exp_powerSpec_fx, p_powerSpecMsInv_fx, exp_powerSpecMsInv_fx, p_inv_spectrum_fx, exp_inv_spectrum_fx, n, sp_aud_decision0[ch1], p_st[0]->total_brate, 1 ); +#endif } ELSE { diff --git a/lib_enc/ivas_mdct_core_enc_fx.c b/lib_enc/ivas_mdct_core_enc_fx.c index 4d8bc7b9979f5a8e60a9b8cbb79cc9c8e942020f..4dc73e611ebef0a8a3a524fd8a60b48f458e4659 100644 --- a/lib_enc/ivas_mdct_core_enc_fx.c +++ b/lib_enc/ivas_mdct_core_enc_fx.c @@ -1279,11 +1279,42 @@ void ivas_mdct_core_whitening_enc_fx( Q_new = 0; move16(); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 lshift, l_frame; + l_frame = extract_l( Mpy_32_32( st->input_Fs, 42949673 /* 0.2f in Q31 */ ) ); + if ( EQ_16( st->core, TCX_10_CORE ) ) + { + l_frame = shr( l_frame, 1 ); + } + nSubframes = NB_DIV; + move16(); + if ( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + FOR( n = 0; n < nSubframes; n++ ) + { + lshift = sub( L_norm_arr( st->hTcxEnc->spectrum_fx[n], l_frame ), 2 ); + Scale_sig32( st->hTcxEnc->spectrum_fx[n], l_frame, lshift ); + st->hTcxEnc->spectrum_e[n] = sub( st->hTcxEnc->spectrum_e[n], lshift ); + } +#endif core_signal_analysis_high_bitrate_ivas_fx( new_samples_fx[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal_fx[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0, mdst_spectrum_fx[ch], mdst_spectrum_e[ch], &Q_new, &q_windowedSignal[ch] ); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + FOR( n = 0; n < nSubframes; n++ ) + { + lshift = sub( L_norm_arr( mdst_spectrum_fx[ch][n], l_frame ), 2 ); + Scale_sig32( mdst_spectrum_fx[ch][n], l_frame, lshift ); + mdst_spectrum_e[ch][n] = sub( mdst_spectrum_e[ch][n], lshift ); + } +#endif + /* BWD in MDCT domain */ IF( NE_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) { +#ifndef FIX_1464_NO_SINGLE_SPEC_Q nSubframes = NB_DIV; move16(); if ( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) @@ -1291,10 +1322,16 @@ void ivas_mdct_core_whitening_enc_fx( nSubframes = 1; move16(); } +#endif FOR( n = 0; n < nSubframes; n++ ) { Word16 spect_fx[L_FRAME48k]; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 q_spectrum; + Copy_Scale_sig32_16( st->hTcxEnc->spectrum_fx[n], spect_fx, l_frame, 0 ); + q_spectrum = sub( sub( Q31, st->hTcxEnc->spectrum_e[n] ), 16 ); +#else Word16 q_spectrum, lshift, l_frame; /*l_frame = (int16_t)(st->input_Fs / FRAMES_PER_SEC); 1 / FRAMES_PER_SEC = 0.2f */ l_frame = extract_l( Mpy_32_32( st->input_Fs, 42949673 /* 0.2f in Q31 */ ) ); @@ -1305,6 +1342,7 @@ void ivas_mdct_core_whitening_enc_fx( lshift = L_norm_arr( st->hTcxEnc->spectrum_fx[n], l_frame ); Copy_Scale_sig32_16( st->hTcxEnc->spectrum_fx[n], spect_fx, l_frame, lshift ); q_spectrum = sub( add( sub( Q31, st->hTcxEnc->spectrum_e[n] ), lshift ), 16 ); +#endif bw_detect_fx( st, NULL, spect_fx, NULL, NULL, MC_FORMAT /*just cannot be ISM_FORMAT*/, mct_on, q_spectrum ); test(); diff --git a/lib_enc/ivas_sns_enc_fx.c b/lib_enc/ivas_sns_enc_fx.c index b7de878a12a6e567f1b868deb3d55472a407d51f..8dab38cecb9eb8e2b617eb20ad743714b94f165d 100644 --- a/lib_enc/ivas_sns_enc_fx.c +++ b/lib_enc/ivas_sns_enc_fx.c @@ -706,7 +706,12 @@ Word16 quantize_sns_fx( IF( EQ_16( sns_stereo_mode[k], SNS_STEREO_MODE_MS ) ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 ms_e = 0; + convertToMS_fx( M, snsQ_out_fx[0][k], snsQ_out_fx[1][k], &ms_e, &ms_e, ONE_IN_Q30 ); +#else convertToMS_fx( M, snsQ_out_fx[0][k], snsQ_out_fx[1][k], ONE_IN_Q30 ); +#endif } } } @@ -840,7 +845,12 @@ Word16 quantize_sns_fx( { IF( EQ_16( sns_stereo_mode[k], SNS_STEREO_MODE_MS ) ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 ms_e = 0; + convertToMS_fx( M, snsQ_out_fx[0][k], snsQ_out_fx[1][k], &ms_e, &ms_e, ONE_IN_Q31 ); +#else convertToMS_fx( M, snsQ_out_fx[0][k], snsQ_out_fx[1][k], ONE_IN_Q31 ); +#endif } } } diff --git a/lib_enc/ivas_stereo_mdct_core_enc_fx.c b/lib_enc/ivas_stereo_mdct_core_enc_fx.c index c38494669c8ae4179c34fa7c61a8c7ea49e8a630..f2bd88408292234a71ed6fcae575f0a486f3f634 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc_fx.c +++ b/lib_enc/ivas_stereo_mdct_core_enc_fx.c @@ -135,15 +135,21 @@ void stereo_mdct_core_enc_fx( { Word32 orig_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* MDCT output (L/R). */ Word32 *orig_spectrum_fx[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; + Word32 powerSpec_fx_tmp[CPE_CHANNELS][N_MAX]; /* This 32 bit buffer is created to preserve the precision for original separate Q calculation of powerSpec_fx buffer ( Related to 3gpp issue #1192 ) */ + Word32 *p_powerSpec_fx[CPE_CHANNELS]; +#else Word64 powerSpec64[CPE_CHANNELS][N_MAX]; Word16 exp_powerSpec64[CPE_CHANNELS][NB_DIV]; +#endif Word32 powerSpecMsInv_long_fx[CPE_CHANNELS][N_MAX]; /* MS inv power spectrum, also inverse MDST spectrum */ Word32 *powerSpecMsInv_fx[CPE_CHANNELS][NB_DIV]; Word32 quantized_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ Word32 *quantized_spectrum_fx[CPE_CHANNELS][NB_DIV]; Word32 *inv_mdst_spectrum_fx[CPE_CHANNELS][NB_DIV]; + Word16 inv_mdst_spectrum_e[CPE_CHANNELS][NB_DIV]; Word32 *inv_spectrum_fx[CPE_CHANNELS][NB_DIV]; - Word16 exp_inv_spectrum[CPE_CHANNELS]; Word16 i, ch, nSubframes, L_subframeTCX; Word16 n, nAvailBits; Word16 tnsSize[CPE_CHANNELS][NB_DIV]; /* number of tns parameters put into prm */ @@ -152,9 +158,16 @@ void stereo_mdct_core_enc_fx( Word32 *p_mdst_spectrum_long_fx[CPE_CHANNELS]; Word32 mdst_spectrum_long_fx[CPE_CHANNELS][N_MAX]; Word32 *mdst_spectrum_fx[CPE_CHANNELS][NB_DIV]; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + /* ToDo: exchange dimensions of 3 arrays below for more efficiency */ + Word16 pwrMdstMdct_e[CPE_CHANNELS][NB_DIV]; + Word16 pwrMdstMdctInv_e[CPE_CHANNELS][NB_DIV]; + Word16 inv_spectrum_e[CPE_CHANNELS][NB_DIV]; +#else Word16 exp_powSpecMsInv[MCT_MAX_CHANNELS]; Word16 tmp_q_powSpecInv[N_MAX], *exp_powSpecInv[2]; Word64 W_tmp; +#endif Encoder_State *st, **sts; STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct; BSTR_ENC_HANDLE hBstr; @@ -183,13 +196,17 @@ void stereo_mdct_core_enc_fx( p_orig_spectrum_long_fx[ch] = orig_spectrum_long_fx[ch]; orig_spectrum_fx[ch][0] = orig_spectrum_long_fx[ch]; orig_spectrum_fx[ch][1] = orig_spectrum_long_fx[ch] + N_TCX10_MAX; +#ifndef FIX_1464_NO_SINGLE_SPEC_Q set16_fx( exp_powerSpec64[ch], 0, NB_DIV ); +#endif } +#ifndef FIX_1464_NO_SINGLE_SPEC_Q set16_fx( tmp_q_powSpecInv, 63, N_MAX ); exp_powSpecInv[0] = tmp_q_powSpecInv; exp_powSpecInv[1] = &tmp_q_powSpecInv[N_TCX10_MAX]; +#endif sts = hCPE->hCoreCoder; hStereoMdct = hCPE->hStereoMdct; @@ -260,7 +277,13 @@ void stereo_mdct_core_enc_fx( inv_spectrum_fx[ch][1] = quantized_spectrum_fx[ch][1]; mdst_spectrum_fx[ch][0] = mdst_spectrum_long_fx[ch]; mdst_spectrum_fx[ch][1] = mdst_spectrum_long_fx[ch] + N_TCX10_MAX; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + inv_spectrum_e[ch][0] = 0; + inv_spectrum_e[ch][1] = 0; + set32_fx( powerSpec_fx[ch], 0, N_MAX ); +#else set64_fx( powerSpec64[ch], 0, N_MAX ); +#endif set32_fx( powerSpecMsInv_long_fx[ch], 0, N_MAX ); set32_fx( quantized_spectrum_long_fx[ch], 0, N_MAX ); set32_fx( mdst_spectrum_long_fx[ch], 0, N_MAX ); @@ -270,8 +293,8 @@ void stereo_mdct_core_enc_fx( sts[ch]->hTcxEnc->tns_ms_flag[1] = 0; move16(); - scale_sig( sts[ch]->input_fx, add( extract_l( Mpy_32_32( sts[ch]->input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ), NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ), sub( q_com, sts[ch]->q_inp ) ); /* q_com */ - scale_sig( sts[ch]->old_input_signal_fx, extract_l( Mpy_32_32( sts[ch]->input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ), sub( q_com, sts[ch]->q_old_inp ) ); /* q_com */ + Scale_sig( sts[ch]->input_fx, add( extract_l( Mpy_32_32( sts[ch]->input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ), NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ), sub( q_com, sts[ch]->q_inp ) ); /* Q0 */ + Scale_sig( sts[ch]->old_input_signal_fx, extract_l( Mpy_32_32( sts[ch]->input_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ), sub( q_com, sts[ch]->q_old_inp ) ); /* Q0 */ sts[ch]->q_old_inp = q_com; move16(); sts[ch]->q_inp = q_com; @@ -342,6 +365,7 @@ void stereo_mdct_core_enc_fx( test(); IF( !hStereoMdct->isSBAStereoMode ) { +#ifndef FIX_1464_NO_SINGLE_SPEC_Q /* Common q for mdst_spectrum and spectrum */ Word16 exp1, exp2; Word16 length; @@ -398,13 +422,18 @@ void stereo_mdct_core_enc_fx( exp_inv_spectrum[0] = exp_inv_spectrum[1] = sts[0]->hTcxEnc->spectrum_e[0]; move16(); move16(); +#else + stereo_coder_tcx_fx( hStereoMdct, sts, ms_mask, mdst_spectrum_fx, inv_spectrum_fx, inv_mdst_spectrum_fx, 0, mdst_spectrum_e, inv_spectrum_e, inv_mdst_spectrum_e ); +#endif } /*--------------------------------------------------------------* * Power spectrum calculation *---------------------------------------------------------------*/ +#ifndef FIX_1464_NO_SINGLE_SPEC_Q Word16 length, exp, shift1, shift2, norm; Word32 mdct, mdst, imdct, imdst; +#endif FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { @@ -425,6 +454,87 @@ void stereo_mdct_core_enc_fx( L_subframeTCX = add( L_subframeTCX, shr( L_subframeTCX, 2 ) ); /* Q0 */ } +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + FOR( n = 0; n < nSubframes; n++ ) + { + Word16 shift0, shift1, shift0i, shift1i; + + IF( sts[ch]->hTcxEnc->tns_ms_flag[n] ) + { +#if 0 + pwrMdstMdct_e[ch][n] = add( shl( s_max( mdst_spectrum_e[ch][n], sts[ch]->hTcxEnc->spectrum_e[n] ), 1 ), 1 ); + shift0 = add( shl( s_max( 0, sub( sts[ch]->hTcxEnc->spectrum_e[n], mdst_spectrum_e[ch][n] ) ), 1 ), 1 ); + shift1 = add( shl( s_max( 0, sub( mdst_spectrum_e[ch][n], sts[ch]->hTcxEnc->spectrum_e[n] ) ), 1 ), 1 ); + pwrMdstMdctInv_e[ch][n] = add( shl( s_max( inv_mdst_spectrum_e[ch][n], inv_spectrum_e[ch][n] ), 1 ), 1 ); + shift0i = add( shl( s_max( 0, sub( inv_spectrum_e[ch][n], inv_mdst_spectrum_e[ch][n] ) ), 1 ), 1 ); + shift1i = add( shl( s_max( 0, sub( inv_mdst_spectrum_e[ch][n], inv_spectrum_e[ch][n] ) ), 1 ), 1 ); +#else + pwrMdstMdct_e[ch][n] = shl( s_max( mdst_spectrum_e[ch][n], sts[ch]->hTcxEnc->spectrum_e[n] ), 1 ); + shift0 = shl( s_max( 0, sub( sts[ch]->hTcxEnc->spectrum_e[n], mdst_spectrum_e[ch][n] ) ), 1 ); + shift1 = shl( s_max( 0, sub( mdst_spectrum_e[ch][n], sts[ch]->hTcxEnc->spectrum_e[n] ) ), 1 ); + pwrMdstMdctInv_e[ch][n] = shl( s_max( inv_mdst_spectrum_e[ch][n], inv_spectrum_e[ch][n] ), 1 ); + shift0i = shl( s_max( 0, sub( inv_spectrum_e[ch][n], inv_mdst_spectrum_e[ch][n] ) ), 1 ); + shift1i = shl( s_max( 0, sub( inv_mdst_spectrum_e[ch][n], inv_spectrum_e[ch][n] ) ), 1 ); +#endif + /* power spectrum: MDCT^2 + MDST^2 */ + FOR( i = 0; i < L_subframeTCX; i++ ) + { + Word32 L_tmp; + L_tmp = L_add( L_shr( Mpy_32_32( mdst_spectrum_fx[ch][n][i], mdst_spectrum_fx[ch][n][i] ), shift0 ), L_shr( Mpy_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ), shift1 ) ); + powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = L_tmp; /* 2 * max( mdst_spectrum_e[ch][n], sts[ch]->hTcxEnc->spectrum_e[n] ) */ + move32(); + + L_tmp = L_add( L_shr( Mpy_32_32( inv_mdst_spectrum_fx[ch][n][i], inv_mdst_spectrum_fx[ch][n][i] ), shift0i ), L_shr( Mpy_32_32( inv_spectrum_fx[ch][n][i], inv_spectrum_fx[ch][n][i] ), shift1i ) ); + powerSpecMsInv_fx[ch][n][i] = L_tmp; /* 2 * max( inv_mdst_spectrum_e[ch][n], inv_spectrum_e[ch][n] ) */ + move32(); + } + } + ELSE + { + pwrMdstMdct_e[ch][n] = shl( sts[ch]->hTcxEnc->spectrum_e[n], 1 ); + pwrMdstMdctInv_e[ch][n] = shl( inv_spectrum_e[ch][n], 1 ); + IF( NE_16( hStereoMdct->mdct_stereo_mode[n], SMDCT_DUAL_MONO ) ) + { + /* power spectrum: MDCT^2 + MDST^2 */ + Word32 L_tmp; + L_tmp = Mpy_32_32( inv_spectrum_fx[ch][n][0], inv_spectrum_fx[ch][n][0] ); + powerSpecMsInv_fx[ch][n][0] = L_tmp; + move32(); + + FOR( i = 1; i < L_subframeTCX - 1; i++ ) + { + Word32 mdst_fx = L_sub( inv_spectrum_fx[ch][n][i + 1], inv_spectrum_fx[ch][n][i - 1] ); /* An MDST estimate q_spec*/ + + L_tmp = L_add( Mpy_32_32( mdst_fx, mdst_fx ), Mpy_32_32( inv_spectrum_fx[ch][n][i], inv_spectrum_fx[ch][n][i] ) ); + powerSpecMsInv_fx[ch][n][i] = L_tmp; + move32(); + } + + L_tmp = Mpy_32_32( inv_spectrum_fx[ch][n][L_subframeTCX - 1], inv_spectrum_fx[ch][n][L_subframeTCX - 1] ); + powerSpecMsInv_fx[ch][n][L_subframeTCX - 1] = L_tmp; + move32(); + } + + /* power spectrum: MDCT^2 + MDST^2 */ + L_tmp = Mpy_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][0], sts[ch]->hTcxEnc->spectrum_fx[n][0] ); + powerSpec_fx[ch][n * L_subframeTCX] = L_tmp; + move32(); + + FOR( i = 1; i < L_subframeTCX - 1; i++ ) + { + Word32 mdst_fx = L_sub( sts[ch]->hTcxEnc->spectrum_fx[n][i + 1], sts[ch]->hTcxEnc->spectrum_fx[n][i - 1] ); /* An MDST estimate q_spec*/ + + L_tmp = L_add( Mpy_32_32( mdst_fx, mdst_fx ), Mpy_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][i], sts[ch]->hTcxEnc->spectrum_fx[n][i] ) ); + powerSpec_fx[ch][( i + ( n * L_subframeTCX ) )] = L_tmp; + move32(); + } + + L_tmp = Mpy_32_32( sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1], sts[ch]->hTcxEnc->spectrum_fx[n][L_subframeTCX - 1] ); + powerSpec_fx[ch][( ( L_subframeTCX - 1 ) + ( n * L_subframeTCX ) )] = L_tmp; + move32(); + } + } +#else FOR( n = 0; n < nSubframes; n++ ) { IF( sts[ch]->hTcxEnc->tns_ms_flag[n] ) @@ -533,6 +643,7 @@ void stereo_mdct_core_enc_fx( } exp_powSpecMsInv[ch] = exp; move16(); +#endif } FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) @@ -564,9 +675,15 @@ void stereo_mdct_core_enc_fx( * and quantization (0: tonal, 1: noise-like). * * Detect low pass if present. * *-----------------------------------------------------------*/ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + ComputeSpectrumNoiseMeasure_fx( powerSpec_fx_tmp[ch], L_subframeTCX, i_mult( st->hTcxEnc->nmStartLine, idiv1616( L_subframeTCX, st->hTcxEnc->L_frameTCX ) ), + NE_32( imult3216( st->last_sr_core, st->L_frame ), imult3216( st->sr_core, st->L_frame_past ) ) || NE_16( st->last_core, TCX_20_CORE ), st->hTcxEnc->memQuantZeros, L_subframeTCX ); + +#else ComputeSpectrumNoiseMeasure_ivas_fx( powerSpec64[ch], L_subframeTCX, i_mult( st->hTcxEnc->nmStartLine, idiv1616( L_subframeTCX, st->hTcxEnc->L_frameTCX ) ), NE_32( imult3216( st->last_sr_core, st->L_frame ), imult3216( st->sr_core, st->L_frame_past ) ) || NE_16( st->last_core, TCX_20_CORE ), st->hTcxEnc->memQuantZeros, L_subframeTCX ); +#endif } st->hTcxEnc->measuredBwRatio = ONE_IN_Q14; /* No bandwidth limit for the noise filling Q14*/ @@ -599,10 +716,36 @@ void stereo_mdct_core_enc_fx( IF( ( NE_16( hStereoMdct->mdct_stereo_mode[n], hStereoMdct->IGFStereoMode[n] ) || EQ_16( hStereoMdct->mdct_stereo_mode[n], SMDCT_BW_MS ) ) && !hStereoMdct->isSBAStereoMode ) { IGF_ENC_INSTANCE_HANDLE hIGFEnc[CPE_CHANNELS]; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + p_powerSpec_fx[0] = powerSpec_fx[0]; + p_powerSpec_fx[1] = powerSpec_fx[1]; + Word16 exp_SI_ch[CPE_CHANNELS], exp_pS_ch[CPE_CHANNELS], exp_pSI_ch[CPE_CHANNELS]; + exp_SI_ch[0] = inv_spectrum_e[0][n]; + exp_SI_ch[1] = inv_spectrum_e[1][n]; + move16(); + move16(); + exp_pS_ch[0] = pwrMdstMdct_e[0][n]; + exp_pS_ch[1] = pwrMdstMdct_e[1][n]; + move16(); + move16(); + exp_pSI_ch[0] = pwrMdstMdctInv_e[0][n]; + exp_pSI_ch[1] = pwrMdstMdctInv_e[1][n]; + move16(); + move16(); + hIGFEnc[0] = sts[0]->hIGFEnc; + hIGFEnc[1] = sts[1]->hIGFEnc; + hIGFEnc[0]->spec_be_igf_e = p_orig_spectrum_e[0]; + move16(); + hIGFEnc[1]->spec_be_igf_e = p_orig_spectrum_e[1]; + move16(); + ProcessStereoIGF_fx( hStereoMdct, sts, ms_mask, + orig_spectrum_fx, sub( Q31, p_orig_spectrum_e[0] ), sub( Q31, p_orig_spectrum_e[1] ), + p_powerSpec_fx, exp_pS_ch, powerSpecMsInv_fx, exp_pSI_ch, inv_spectrum_fx, exp_SI_ch, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); +#else Word32 powerSpec_fx[CPE_CHANNELS][N_MAX], *p_powerSpec_fx[CPE_CHANNELS]; - Word16 exp_powSpec[CPE_CHANNELS]; p_powerSpec_fx[0] = powerSpec_fx[0]; p_powerSpec_fx[1] = powerSpec_fx[1]; + Word16 exp_powSpec[CPE_CHANNELS]; { /* Copy powerSpec values from 64 bit buffer to 32 bit buffer */ FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) @@ -652,9 +795,25 @@ void stereo_mdct_core_enc_fx( ProcessStereoIGF_fx( hStereoMdct, sts, ms_mask, orig_spectrum_fx, sub( Q31, p_orig_spectrum_e[0] ), sub( Q31, p_orig_spectrum_e[1] ), p_powerSpec_fx, exp_powSpec, powerSpecMsInv_fx, exp_powSpecMsInv, inv_spectrum_fx, exp_inv_spectrum, n, hCPE->hCoreCoder[0]->sp_aud_decision0, hCPE->hCoreCoder[0]->element_brate, 0 ); +#endif } ELSE { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + /* update the pointer to the buffer of indices of the second channel */ + if ( EQ_16( ch, 1 ) ) + { + st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + L_subframeTCX = idiv1616( st->hTcxEnc->L_frameTCX, nSubframes ); /* Q0 */ + + // ProcessIGF_fx( st, N_MAX, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &st->hIGFEnc->spec_be_igf_e, &powerSpec_fx[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); + ProcessIGF_ivas_fx( st, N_MAX, st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum_e, orig_spectrum_fx[ch][n], st->hIGFEnc->spec_be_igf_e, &powerSpec_fx[ch][n * L_subframeTCX], pwrMdstMdct_e[ch], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); + } +#else Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; // each value has a different exponent Word16 exp_powerSpec[CPE_CHANNELS][N_MAX + L_MDCT_OVLP_MAX]; { @@ -712,11 +871,43 @@ void stereo_mdct_core_enc_fx( Scale_sig32( orig_spectrum_fx[ch][n], st->hIGFEnc->infoStopLine, sub( q_spectrum, sub( Q31, p_orig_spectrum_e[ch] ) ) ); /* q_spectrum */ ProcessIGF_ivas_fx( st, N_MAX, st->hTcxEnc->spectrum_fx[n], &q_spectrum, orig_spectrum_fx[ch][n], q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &exp_powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); } +#endif } } } ELSE { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + /* update the pointer to the buffer of indices of the second channel */ + if ( EQ_16( ch, 1 ) ) + { + st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; + } + + nSubframes = NB_DIV; + move16(); + + if ( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + move16(); + } + IF( st->igf ) + { + FOR( n = 0; n < nSubframes; n++ ) + { + L_subframeTCX = idiv1616( st->hTcxEnc->L_frameTCX, nSubframes ); /* Q0 */ + + ProcessIGF_ivas_fx( st, N_MAX, st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum_e, orig_spectrum_fx[ch][n], st->hIGFEnc->spec_be_igf_e, &powerSpec_fx[ch][n * L_subframeTCX], &pwrMdstMdct_e[ch][n], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); + } + } + } + +#else Word32 powerSpec_fx[CPE_CHANNELS][N_MAX]; // each value has a different exponent Word16 exp_powerSpec[CPE_CHANNELS][N_MAX + L_MDCT_OVLP_MAX]; { @@ -791,6 +982,7 @@ void stereo_mdct_core_enc_fx( } } } +#endif } /*write IGF data to bitstream*/ diff --git a/lib_enc/ivas_stereo_mdct_igf_enc_fx.c b/lib_enc/ivas_stereo_mdct_igf_enc_fx.c index 6c3588cabc6d7a93997e0937dfd86940f859dee8..f1bcf04975f1d965cb3ddcb4181a9702e5306054 100644 --- a/lib_enc/ivas_stereo_mdct_igf_enc_fx.c +++ b/lib_enc/ivas_stereo_mdct_igf_enc_fx.c @@ -61,7 +61,12 @@ static Word16 calcCoh_fx( // Q15 const Word32 *sig1_fx, // Q( q_sig ) const Word32 *sig2_fx, // Q( q_sig ) +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + const Word16 sig1_e, + const Word16 sig2_e, +#else const Word16 q_sig, +#endif const Word16 nSamples, /* Q0 */ Word32 *corr, /* Q31-corr_e */ Word16 *corr_e, @@ -75,8 +80,13 @@ static Word16 calcCoh_fx( // Q15 coh_fx = 0; move16(); Word16 gB = find_guarded_bits_fx( nSamples ); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + q_ener1 = shl( sub( 31, sig1_e ), 1 ); + q_ener2 = shl( sub( 31, sig2_e ), 1 ); +#else q_ener1 = shl( q_sig, 1 ); q_ener2 = q_ener1; +#endif move16(); q_cc = q_ener1; move16(); @@ -131,7 +141,12 @@ static void IGF_MsStereoDecision_fx( H_IGF_GRID hGrid, const Word32 *specL_fx, /* q_spec */ const Word32 *specR_fx, /* q_spec */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + const Word16 specL_e, + const Word16 specR_e, +#else Word16 q_spec, +#endif Word16 *igfStereoMode, /* output Q0*/ Word16 *msMask, /* output Q0*/ const Word16 mdct_stereo_mode /* Q0 */ ) @@ -171,8 +186,13 @@ static void IGF_MsStereoDecision_fx( move16(); move16(); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 coh_src = calcCoh_fx( &specL_fx[strt_cpy], &specR_fx[strt_cpy], specL_e, specR_e, width, &cc_src_fx, &cc_src_e, &pc_src_fx, &pc_src_e ); + Word16 coh_target = calcCoh_fx( &specL_fx[hGrid->swb_offset[sfb]], &specR_fx[hGrid->swb_offset[sfb]], specL_e, specR_e, width, &cc_target_fx, &cc_target_e, &pc_target_fx, &pc_target_e ); +#else Word16 coh_src = calcCoh_fx( &specL_fx[strt_cpy], &specR_fx[strt_cpy], q_spec, width, &cc_src_fx, &cc_src_e, &pc_src_fx, &pc_src_e ); Word16 coh_target = calcCoh_fx( &specL_fx[hGrid->swb_offset[sfb]], &specR_fx[hGrid->swb_offset[sfb]], q_spec, width, &cc_target_fx, &cc_target_e, &pc_target_fx, &pc_target_e ); +#endif tmp1_e = BASOP_Util_Add_MantExp( pc_target_fx, pc_target_e, negate( pc_src_fx ), pc_src_e, &tmp1 ); /* Q15-tmp1_e */ tmp2_e = BASOP_Util_Add_MantExp( pc_target_fx, pc_target_e, -16384, 1, &tmp2 ); /* Q15-tmp2_e */ @@ -300,7 +320,12 @@ void IGFEncStereoEncoder_fx( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : IGF handle */ const Word32 *mdctSpectrumL_fx, /* i : left spectrum q_mdctSpectrum*/ const Word32 *mdctSpectrumR_fx, /* i : right spectrum q_mdctSpectrum*/ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + const Word16 mdctSpectrumL_e, + const Word16 mdctSpectrumR_e, +#else Word16 q_mdctSpectrum, +#endif Word16 *msMask, /* i/o: MS mask Q0*/ Word16 *igfStereoMode, /* o : IGF stereo mode Q0*/ const Word16 mdct_stereo_mode, /* i : MDCT stereo mode Q0*/ @@ -329,7 +354,11 @@ void IGFEncStereoEncoder_fx( } hGrid = &hIGFEnc->igfData.igfInfo.grid[igfGridIdx]; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + IGF_MsStereoDecision_fx( sfbParam, hGrid, mdctSpectrumL_fx, mdctSpectrumR_fx, mdctSpectrumL_e, mdctSpectrumR_e, igfStereoMode, msMask + sfbParam->nBandsStereoCore, mdct_stereo_mode ); +#else IGF_MsStereoDecision_fx( sfbParam, hGrid, mdctSpectrumL_fx, mdctSpectrumR_fx, q_mdctSpectrum, igfStereoMode, msMask + sfbParam->nBandsStereoCore, mdct_stereo_mode ); +#endif return; } diff --git a/lib_enc/ivas_stereo_mdct_stereo_enc_fx.c b/lib_enc/ivas_stereo_mdct_stereo_enc_fx.c index 2f1b7d6c8d6a37248247971dece778020c06e8e5..b4982a76e3d6fb916aa4e898d0b2eeb0c375f260 100644 --- a/lib_enc/ivas_stereo_mdct_stereo_enc_fx.c +++ b/lib_enc/ivas_stereo_mdct_stereo_enc_fx.c @@ -59,12 +59,19 @@ static void convertToBwMS_fx( const Word16 startLine, const Word16 stopLine, Word32 x0[], Word32 x1[], const Word32 norm_fac ); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q +void convertToMS_fx( const Word16 L_frame, Word32 x0_fx[], Word32 x1_fx[], Word16 *x0_e, Word16 *x1_e, const Word32 norm_fac ); +#else void convertToMS_fx( const Word16 L_frame, Word32 x0_fx[], Word32 x1_fx[], const Word32 norm_fac ); +#endif static Word16 GetChannelEnergyRatio_fx( Encoder_State **st, const Word16 iFirstSubframe, const Word16 iLastSubframe, const UWord8 ratioInRmsDomain ); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q +static void MsStereoDecision_fx( STEREO_MDCT_BAND_PARAMETERS *sfbParam, Word32 *specL_fx, Word32 *specR_fx, Word32 *specM_fx, Word32 *specS_fx, Word16 specL_e, Word16 specR_e, Word16 *specM_e, Word16 *specS_e, Word16 *mdct_stereo_mode, Word16 *msMask, const Word16 nBitsAvailable ); +#else static void MsStereoDecision_fx( STEREO_MDCT_BAND_PARAMETERS *sfbParam, Word32 *specL_fx, Word32 *specR_fx, Word32 *specM_fx, Word32 *specS_fx, Word16 q_spec, Word16 *mdct_stereo_mode, Word16 *msMask, const Word16 nBitsAvailable ); - +#endif /*-------------------------------------------------------------------* * dft_ana_init() @@ -190,8 +197,14 @@ void stereo_coder_tcx_fx( Word32 *inv_mdst_spectrum_fx[CPE_CHANNELS][NB_DIV], /* i/o: inverse MDST spectrum */ // Q( q_spec ) (same as spectrum buffer in hTcxEnc) const Word16 mct_on, /* i : flag mct block (1) or stereo (0) Q0*/ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 mdst_spectrum_e[CPE_CHANNELS][NB_DIV], + Word16 inv_spectrum_e[CPE_CHANNELS][NB_DIV], + Word16 inv_mdst_spectrum_e[CPE_CHANNELS][NB_DIV] ) +#else Word16 exp_spec, Word16 exp_mdct_spec ) +#endif { STEREO_MDCT_BAND_PARAMETERS *sfbConf = NULL; Word32 nrgRatio_fx[CPE_CHANNELS]; @@ -264,9 +277,18 @@ void stereo_coder_tcx_fx( L_frameTCX = add( sts[0]->hTcxEnc->L_frameTCX, EQ_16( sts[0]->last_core, 0 ) ? shr( sts[0]->hTcxEnc->L_frameTCX, 2 ) : 0 ); /* Q0 */ L_frameTCX = idiv1616( L_frameTCX, ( sts[0]->core == TCX_20_CORE ) ? 1 : NB_DIV ); /* Q0 */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + v_multc_fixed_16( sts[0]->hTcxEnc->spectrum_fx[k], round_fx( nrgRatio_fx[k] ), sts[0]->hTcxEnc->spectrum_fx[k], L_frameTCX ); /* Q31-spectrum_e[k] */ + v_multc_fixed_16( mdst_spectrum_fx[0][k], round_fx( nrgRatio_fx[k] ), mdst_spectrum_fx[0][k], L_frameTCX ); /* q_spec */ + sts[0]->hTcxEnc->spectrum_e[k] = add( sts[0]->hTcxEnc->spectrum_e[k], nrgRatio_e[k] ); + move16(); + mdst_spectrum_e[0][k] = add( mdst_spectrum_e[0][k], nrgRatio_e[k] ); + move16(); +#else /* This operation is resulting in some high MLDs in fixed point. */ v_multc_fixed_16( sts[0]->hTcxEnc->spectrum_fx[k], extract_l( L_shr( nrgRatio_fx[k], 16 - nrgRatio_e[k] ) ), sts[0]->hTcxEnc->spectrum_fx[k], L_frameTCX ); /* exp: exp_spec */ v_multc_fixed_16( mdst_spectrum_fx[0][k], extract_l( L_shr( nrgRatio_fx[k], 16 - nrgRatio_e[k] ) ), mdst_spectrum_fx[0][k], L_frameTCX ); /* exp: exp_mdct_spec */ +#endif } } } @@ -310,7 +332,11 @@ void stereo_coder_tcx_fx( } for ( k = 0; k < nSubframes; k++ ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + convertToMS_fx( L_frameTCX, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], &sts[1]->hTcxEnc->spectrum_e[k], sts[1]->hTcxEnc->spectrum_e[k], SQRT2_OVER_2_FIXED ); +#else convertToMS_fx( L_frameTCX, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], SQRT2_OVER_2_FIXED ); +#endif /* Make sure that the MDST is processed in the correct way also */ set_s( &ms_mask[k][0], 1, MAX_SFB ); @@ -349,6 +375,20 @@ void stereo_coder_tcx_fx( sfb = add( sfb, 1 ); /* find start offset */ } +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + /* The factor applied below to the spectrum can be up to 1.414, so aplly one bit headroom to entire spectrum */ + /* Below first stereo core SFB */ + scale_sig32( sts[0]->hTcxEnc->spectrum_fx[k], sfbConf->sfbOffset[sfb - 1], -Q1 ); + scale_sig32( mdst_spectrum_fx[0][k], sfbConf->sfbOffset[sfb - 1], -Q1 ); + scale_sig32( sts[1]->hTcxEnc->spectrum_fx[k], sfbConf->sfbOffset[sfb - 1], -Q1 ); + scale_sig32( mdst_spectrum_fx[1][k], sfbConf->sfbOffset[sfb - 1], -Q1 ); + /* Above last stereo core SFB */ + scale_sig32( sts[0]->hTcxEnc->spectrum_fx[k] + sfbConf->sfbOffset[sfbConf->nBandsStereoCore], sfbConf->sfbOffset[sfbConf->sfbCnt] - sfbConf->sfbOffset[sfbConf->nBandsStereoCore], -Q1 ); + scale_sig32( mdst_spectrum_fx[0][k] + sfbConf->sfbOffset[sfbConf->nBandsStereoCore], sfbConf->sfbOffset[sfbConf->sfbCnt] - sfbConf->sfbOffset[sfbConf->nBandsStereoCore], -Q1 ); + scale_sig32( sts[1]->hTcxEnc->spectrum_fx[k] + sfbConf->sfbOffset[sfbConf->nBandsStereoCore], sfbConf->sfbOffset[sfbConf->sfbCnt] - sfbConf->sfbOffset[sfbConf->nBandsStereoCore], -Q1 ); + scale_sig32( mdst_spectrum_fx[1][k] + sfbConf->sfbOffset[sfbConf->nBandsStereoCore], sfbConf->sfbOffset[sfbConf->sfbCnt] - sfbConf->sfbOffset[sfbConf->nBandsStereoCore], -Q1 ); +#endif + FOR( sfb--; sfb < sfbConf->nBandsStereoCore; sfb++ ) /* start one SFB early for the fade-in */ { const Word16 startLine = sfbConf->sfbOffset[sfb]; /* Q0 */ @@ -356,8 +396,12 @@ void stereo_coder_tcx_fx( const Word16 endLine = sfbConf->sfbOffset[sfb + 1]; /* Q0 */ move16(); const Word16 sfbWidth = sub( endLine, startLine ); - +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + nrgRatio_e[0] = sts[0]->hTcxEnc->spectrum_e[k]; + nrgRatio_e[1] = sts[1]->hTcxEnc->spectrum_e[k]; +#else nrgRatio_e[0] = nrgRatio_e[1] = exp_spec; +#endif move16(); move16(); @@ -371,11 +415,19 @@ void stereo_coder_tcx_fx( { Word32 tmp_fx; Word16 tmp_e; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + tmp_e = mdst_spectrum_e[0][k]; +#else tmp_e = exp_mdct_spec; +#endif move16(); tmp_fx = sum2_32_fx( &mdst_spectrum_fx[0][k][startLine], sfbWidth, &tmp_e ); /* Q31-tmp_e */ nrgRatio_fx[0] = BASOP_Util_Add_Mant32Exp( nrgRatio_fx[0], nrgRatio_e[0], tmp_fx, tmp_e, &nrgRatio_e[0] ); /* Q31-nrgRatio_e[0] */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + tmp_e = mdst_spectrum_e[1][k]; +#else tmp_e = exp_mdct_spec; +#endif move16(); tmp_fx = sum2_32_fx( &mdst_spectrum_fx[1][k][startLine], sfbWidth, &tmp_e ); /* Q31-tmp_e */ nrgRatio_fx[1] = BASOP_Util_Add_Mant32Exp( nrgRatio_fx[1], nrgRatio_e[1], tmp_fx, tmp_e, &nrgRatio_e[1] ); /* Q31-nrgRatio_e[1] */ @@ -431,15 +483,37 @@ void stereo_coder_tcx_fx( v_multc_fixed( &sts[0]->hTcxEnc->spectrum_fx[k][startLine], nrgRatio_fx[0], &sts[0]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth ); /* exp: exp_spec+1 */ v_multc_fixed( &mdst_spectrum_fx[0][k][startLine], nrgRatio_fx[0], &mdst_spectrum_fx[0][k][startLine], sfbWidth ); /* exp: exp_mdct_spec+1 */ - scale_sig32( &sts[0]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth, Q1 ); // exp: exp_spec - scale_sig32( &mdst_spectrum_fx[0][k][startLine], sfbWidth, Q1 ); // exp: exp_mdct_spec +#ifndef FIX_1464_NO_SINGLE_SPEC_Q + scale_sig32( &sts[0]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth, Q1 ); // exp: exp_spec + scale_sig32( &mdst_spectrum_fx[0][k][startLine], sfbWidth, Q1 ); // exp: exp_mdct_spec +#endif v_multc_fixed( &sts[1]->hTcxEnc->spectrum_fx[k][startLine], nrgRatio_fx[1], &sts[1]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth ); /* exp: exp_spec+1 */ v_multc_fixed( &mdst_spectrum_fx[1][k][startLine], nrgRatio_fx[1], &mdst_spectrum_fx[1][k][startLine], sfbWidth ); /* exp: exp_mdct_spec+1 */ - scale_sig32( &sts[1]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth, Q1 ); // exp: exp_spec - scale_sig32( &mdst_spectrum_fx[1][k][startLine], sfbWidth, Q1 ); // exp: exp_mdct_spec +#ifndef FIX_1464_NO_SINGLE_SPEC_Q + scale_sig32( &sts[1]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth, Q1 ); // exp: exp_spec + scale_sig32( &mdst_spectrum_fx[1][k][startLine], sfbWidth, Q1 ); // exp: exp_mdct_spec +#endif + } +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + ELSE + { + /* Apply same scale as for all other cases. */ + scale_sig32( &sts[0]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth, -Q1 ); + scale_sig32( &mdst_spectrum_fx[0][k][startLine], sfbWidth, -Q1 ); + scale_sig32( &sts[1]->hTcxEnc->spectrum_fx[k][startLine], sfbWidth, -Q1 ); + scale_sig32( &mdst_spectrum_fx[1][k][startLine], sfbWidth, -Q1 ); } +#endif } + +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + /* Follow right shift in SFB processing above. */ + sts[0]->hTcxEnc->spectrum_e[k] = add( sts[0]->hTcxEnc->spectrum_e[k], Q1 ); + mdst_spectrum_e[0][k] = add( mdst_spectrum_e[0][k], Q1 ); + sts[1]->hTcxEnc->spectrum_e[k] = add( sts[1]->hTcxEnc->spectrum_e[k], Q1 ); + mdst_spectrum_e[1][k] = add( mdst_spectrum_e[1][k], Q1 ); +#endif } /* set mask to zero */ @@ -471,13 +545,21 @@ void stereo_coder_tcx_fx( nAvailBitsMS[k] = idiv1616( nAvailBitsMS[k], nSubframes ); /* Q0 */ move16(); - +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + MsStereoDecision_fx( sfbConf, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], inv_spectrum_fx[0][k], inv_spectrum_fx[1][k], + sts[0]->hTcxEnc->spectrum_e[k], sts[1]->hTcxEnc->spectrum_e[k], &inv_spectrum_e[0][k], &inv_spectrum_e[1][k], &hStereoMdct->mdct_stereo_mode[k], &ms_mask[k][0], nAvailBitsMS[k] ); +#else MsStereoDecision_fx( sfbConf, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], inv_spectrum_fx[0][k], inv_spectrum_fx[1][k], sub( Q31, exp_spec ), &hStereoMdct->mdct_stereo_mode[k], &ms_mask[k][0], nAvailBitsMS[k] ); - +#endif IF( sts[0]->igf ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + IGFEncStereoEncoder_fx( sfbConf, sts[0]->hIGFEnc, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], sts[0]->hTcxEnc->spectrum_e[k], sts[1]->hTcxEnc->spectrum_e[k], &ms_mask[k][0], + &hStereoMdct->IGFStereoMode[k], hStereoMdct->mdct_stereo_mode[k], (Word16) EQ_16( sts[0]->core, TCX_20_CORE ), (Word16) EQ_16( sts[0]->last_core, ACELP_CORE ) ); +#else IGFEncStereoEncoder_fx( sfbConf, sts[0]->hIGFEnc, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], sub( Q31, exp_spec ), &ms_mask[k][0], &hStereoMdct->IGFStereoMode[k], hStereoMdct->mdct_stereo_mode[k], (Word16) EQ_16( sts[0]->core, TCX_20_CORE ), (Word16) EQ_16( sts[0]->last_core, ACELP_CORE ) ); +#endif } ELSE { @@ -488,10 +570,23 @@ void stereo_coder_tcx_fx( IF( NE_16( hStereoMdct->mdct_stereo_mode[k], SMDCT_DUAL_MONO ) || NE_16( hStereoMdct->IGFStereoMode[k], SMDCT_DUAL_MONO ) ) { - +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + ms_inv_mask_processing_fx( hStereoMdct, sts, ms_mask, k, + sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], + inv_spectrum_fx[0][k], inv_spectrum_fx[1][k], + &sts[0]->hTcxEnc->spectrum_e[k], &sts[1]->hTcxEnc->spectrum_e[k], + &inv_spectrum_e[0][k], &inv_spectrum_e[1][k], + sfbConf->sfbCnt ); + + ms_processing_fx( hStereoMdct, sts, ms_mask, k, + sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], + &sts[0]->hTcxEnc->spectrum_e[k], &sts[1]->hTcxEnc->spectrum_e[k], + sfbConf->sfbCnt ); +#else ms_inv_mask_processing_fx( hStereoMdct, sts, ms_mask, k, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], inv_spectrum_fx[0][k], inv_spectrum_fx[1][k], sfbConf->sfbCnt ); ms_processing_fx( hStereoMdct, sts, ms_mask, k, sts[0]->hTcxEnc->spectrum_fx[k], sts[1]->hTcxEnc->spectrum_fx[k], sfbConf->sfbCnt ); +#endif IF( !sts[0]->hTcxEnc->fUseTns[k] && !sts[1]->hTcxEnc->fUseTns[k] ) { @@ -499,9 +594,23 @@ void stereo_coder_tcx_fx( move16(); sts[1]->hTcxEnc->tns_ms_flag[k] = 1; move16(); +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + ms_inv_mask_processing_fx( hStereoMdct, sts, ms_mask, k, + mdst_spectrum_fx[0][k], mdst_spectrum_fx[1][k], + inv_mdst_spectrum_fx[0][k], inv_mdst_spectrum_fx[1][k], + &mdst_spectrum_e[0][k], &mdst_spectrum_e[1][k], + &inv_mdst_spectrum_e[0][k], &inv_mdst_spectrum_e[1][k], + -1 ); + + ms_processing_fx( hStereoMdct, sts, ms_mask, k, + mdst_spectrum_fx[0][k], mdst_spectrum_fx[1][k], + &mdst_spectrum_e[0][k], &mdst_spectrum_e[1][k], + sfbConf->sfbCnt ); +#else ms_inv_mask_processing_fx( hStereoMdct, sts, ms_mask, k, mdst_spectrum_fx[0][k], mdst_spectrum_fx[1][k], inv_mdst_spectrum_fx[0][k], inv_mdst_spectrum_fx[1][k], -1 ); ms_processing_fx( hStereoMdct, sts, ms_mask, k, mdst_spectrum_fx[0][k], mdst_spectrum_fx[1][k], sfbConf->sfbCnt ); +#endif } } } /* for k */ @@ -549,8 +658,12 @@ void ms_processing_fx( Word32 x_0_fx[], /* i/o: spectrum 1 */ // Q( q_x ) Word32 x_1_fx[], - /* i/o: spectrum 1 */ // Q( q_x ) - Word16 maxSfb /* i : number of stereo frequency bands Q0*/ +/* i/o: spectrum 1 */ // Q( q_x ) +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 *x_0_e, + Word16 *x_1_e, +#endif + Word16 maxSfb /* i : number of stereo frequency bands Q0*/ ) { Word16 sfb; @@ -570,6 +683,18 @@ void ms_processing_fx( move16(); } +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 newE = add( s_max( *x_0_e, *x_1_e ), 1 ); + scale_sig32( x_0_fx, sfbConf->sfbOffset[maxSfb], sub( *x_0_e, newE ) ); + scale_sig32( x_1_fx, sfbConf->sfbOffset[maxSfb], sub( *x_1_e, newE ) ); + *x_0_e = newE; + move16(); + *x_1_e = newE; + move16(); + + assert( *x_0_e == *x_1_e ); +#endif + FOR( sfb = 0; sfb < maxSfb; sfb++ ) { IF( NE_16( ms_mask[iSubframe][sfb], 0 ) ) @@ -578,6 +703,15 @@ void ms_processing_fx( } } +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + newE = sub( L_norm_arr( x_0_fx, sfbConf->sfbOffset[maxSfb] ), 1 ); + scale_sig32( x_0_fx, sfbConf->sfbOffset[maxSfb], newE ); + *x_0_e = sub( *x_0_e, newE ); + newE = sub( L_norm_arr( x_1_fx, sfbConf->sfbOffset[maxSfb] ), 1 ); + scale_sig32( x_1_fx, sfbConf->sfbOffset[maxSfb], newE ); + *x_1_e = sub( *x_1_e, newE ); +#endif + return; } @@ -599,8 +733,14 @@ void ms_inv_mask_processing_fx( Word32 x_inv_0_fx[], /* o : inverse spectrum 1 */ // Q( q_x ) Word32 x_inv_1_fx[], - /* o : inverse spectrum 2 */ // Q( q_x ) - Word16 maxSfb /* i : number of stereo frequency bands Q0*/ +/* o : inverse spectrum 2 */ // Q( q_x ) +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 *x_0_e, + Word16 *x_1_e, + Word16 *x_inv_0_e, + Word16 *x_inv_1_e, +#endif + Word16 maxSfb /* i : number of stereo frequency bands Q0*/ ) { Word16 sfb; @@ -623,11 +763,24 @@ void ms_inv_mask_processing_fx( move16(); } +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + /* convertToBwMS_fx requires 1 bit headroom and same exponent of both inputs */ + *x_inv_0_e = add( s_max( *x_0_e, *x_1_e ), 1 ); + move16(); + *x_inv_1_e = *x_inv_0_e; + move16(); + Copy_Scale_sig32( x_0_fx, x_inv_0_fx, sfbConf->sfbOffset[maxSfb], sub( *x_0_e, *x_inv_0_e ) ); + Copy_Scale_sig32( x_1_fx, x_inv_1_fx, sfbConf->sfbOffset[maxSfb], sub( *x_1_e, *x_inv_1_e ) ); + + assert( *x_inv_0_e == *x_inv_1_e ); +#endif + FOR( sfb = 0; sfb < maxSfb; sfb++ ) { +#ifndef FIX_1464_NO_SINGLE_SPEC_Q Copy32( &x_0_fx[sfbConf->sfbOffset[sfb]], &x_inv_0_fx[sfbConf->sfbOffset[sfb]], sfbConf->sfbOffset[sfb + 1] - sfbConf->sfbOffset[sfb] ); /* q_x */ Copy32( &x_1_fx[sfbConf->sfbOffset[sfb]], &x_inv_1_fx[sfbConf->sfbOffset[sfb]], sfbConf->sfbOffset[sfb + 1] - sfbConf->sfbOffset[sfb] ); /* q_x */ - +#endif IF( EQ_16( ms_mask[iSubframe][sfb], 0 ) ) { convertToBwMS_fx( sfbConf->sfbOffset[sfb], sfbConf->sfbOffset[sfb + 1], x_inv_0_fx, x_inv_1_fx, SQRT2_OVER_2_FIXED ); @@ -823,9 +976,17 @@ void convertToMS_fx( const Word16 L_frame, /* i : frame length Q0*/ Word32 x0[], /* i/o: mid/left channel coefficients Q(q_x)*/ Word32 x1[], /* i/o: side/right channel coefficients Q(q_x)*/ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 *x0_e, + Word16 *x1_e, +#endif const Word32 norm_fac /* i : normalization factor Q31*/ ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + assert( *x0_e == *x1_e ); +#endif + convertToBwMS_fx( 0, L_frame, x0, x1, norm_fac ); return; @@ -847,26 +1008,122 @@ static Word32 SQ_gain_estimate_stereo_fx( // e_res const Word16 lg, /* i : vector size (2048 max) Q0*/ Word16 *e_res ) { +#ifdef FIX_1464_SQ_GAIN_PRECISION + Word16 i, q, iter, e_ener; + Word32 ener_fx, tmp_32, target_fx, fac_fx, offset_fx; + Word32 en_fx[N_MAX / 2]; // Q25 + Word16 lg2, lg_4, lg2_4; + Word64 W_tmp; +#else Word16 i, q, iter, e_ener, e_xL_2, e_xR_2, s; Word32 ener_fx, tmp_32, target_fx, fac_fx, offset_fx; Word32 en_fx[N_MAX / 2]; // Q25 Word16 lg2, lg_4, lg2_4; Word64 W_tmp, _0_01; +#endif lg_4 = shr( lg, 2 ); /* Q0 */ lg2_4 = shl( lg_4, 1 ); /* Q0 */ lg2 = shl( lg2_4, 2 ); /* Q0 */ i = 0; move16(); +#ifndef FIX_1464_SQ_GAIN_PRECISION e_xL_2 = shl( e_xL, 1 ); e_xR_2 = shl( e_xR, 1 ); _0_01 = W_shr( 21474836 /* 0.01 in Q31 */, sub( e_xL_2, 32 ) ); // 0.01 in 2*(Q of specL/R) + 1 set32_fx( en_fx, 335544 /* 0.01 in Q25 */, ( N_MAX / 2 ) ); +#endif /* energy of quadruples with 9dB offset */ /* ignore that we may take no all lines into account, max. 3 lines at the upper end of the spectrum can be missed (if lg is not a multiple of 4, happens also in SQGain()*/ +#ifdef FIX_1464_SQ_GAIN_PRECISION +#if 1 + FOR( q = 0; q < lg_4; q++ ) + { + Word16 e_tmp; + e_tmp = s_min( add( e_xL, 3 ), sub( L_norm_arr( xL_fx + i, 4 ), 2 ) ); + e_ener = shl( sub( e_xL, e_tmp ), 1 ); + ener_fx = L_shr( 21474836 /* 0.01 */, e_ener ); + tmp_32 = L_shl( xL_fx[i + 0], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xL_fx[i + 1], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xL_fx[i + 2], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xL_fx[i + 3], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + en_fx[q] = BASOP_Util_Log2( ener_fx ); /* saves a MAC */ + move32(); + en_fx[q] = Mpy_32_16_1( L_add( e_ener * ONE_IN_Q25, en_fx[q] ), 9864 /* log10(2) in Q15 */ ); // Q(25) + move32(); + i = add( i, 4 ); + } + i = 0; + FOR( ; q < lg2_4; q++ ) + { + Word16 e_tmp; + e_tmp = s_min( add( e_xR, 3 ), sub( L_norm_arr( xR_fx + i, 4 ), 2 ) ); + e_ener = shl( sub( e_xR, e_tmp ), 1 ); + ener_fx = L_shr( 21474836 /* 0.01 */, e_ener ); + tmp_32 = L_shl( xR_fx[i + 0], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xR_fx[i + 1], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xR_fx[i + 2], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xR_fx[i + 3], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + en_fx[q] = BASOP_Util_Log2( ener_fx ); /* saves a MAC */ + move32(); + en_fx[q] = Mpy_32_16_1( L_add( e_ener * ONE_IN_Q25, en_fx[q] ), 9864 /* log10(2) in Q15 */ ); // Q(25) + move32(); + i = add( i, 4 ); + } + +#else + e_tmp = s_min( add( e_xL, 3 ), sub( L_norm_arr( xL_fx, lg ), 2 ) ); + e_xL = sub( e_xL, e_tmp ); + FOR( q = 0; q < lg_4; q++ ) + { + ener_fx = L_shr( 21474836 /* 0.01 */, shl( e_xL, 1 ) ); + tmp_32 = L_shl( xL_fx[i + 0], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xL_fx[i + 1], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xL_fx[i + 2], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xL_fx[i + 3], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + en_fx[q] = BASOP_Util_Log2( ener_fx ); /* saves a MAC */ + move32(); + en_fx[q] = Mpy_32_16_1( L_add( 2 * e_xL * ONE_IN_Q25, en_fx[q] ), 9864 /* log10(2) in Q15 */ ); // Q(25) + move32(); + i = add( i, 4 ); + } + e_tmp = s_min( add( e_xR, 3 ), sub( L_norm_arr( xR_fx, lg ), 2 ) ); + e_xR = sub( e_xR, e_tmp ); + i = 0; + FOR( ; q < lg2_4; q++ ) + { + ener_fx = L_shr( 21474836 /* 0.01 */, shl( e_xR, 1 ) ); + tmp_32 = L_shl( xR_fx[i + 0], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xR_fx[i + 1], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xR_fx[i + 2], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + tmp_32 = L_shl( xR_fx[i + 3], e_tmp ); + ener_fx = L_add( ener_fx, Mpy_32_32( tmp_32, tmp_32 ) ); + en_fx[q] = BASOP_Util_Log2( ener_fx ); /* saves a MAC */ + move32(); + en_fx[q] = Mpy_32_16_1( L_add( 2 * e_xR * ONE_IN_Q25, en_fx[q] ), 9864 /* log10(2) in Q15 */ ); // Q(25) + move32(); + i = add( i, 4 ); + } +#endif +#else FOR( q = 0; q < lg_4; q++ ) { W_tmp = W_mac_32_32( _0_01, xL_fx[i], xL_fx[i] ); // 2 * e_xL @@ -903,6 +1160,7 @@ static Word32 SQ_gain_estimate_stereo_fx( // e_res move32(); i = add( i, 4 ); } +#endif /* SQ scale: 4 bits / 6 dB per quadruple */ target_fx = L_mult( 19660 /* 0.15 in Q17 */, sub( nbitsSQ, shr( lg2, 4 ) ) ); // Q(18) @@ -1132,8 +1390,15 @@ static void MsStereoDecision_fx( Word32 *specM_fx, /* scratch buffer for M, use buffer for inverse MS mask spectrum */ /* Q( q_spec ) */ Word32 *specS_fx, - /* scratch buffer for M, use buffer for inverse MS mask spectrum */ /* Q( q_spec ) */ +/* scratch buffer for M, use buffer for inverse MS mask spectrum */ /* Q( q_spec ) */ +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 specL_e, + Word16 specR_e, + Word16 *p_specM_e, + Word16 *p_specS_e, +#else Word16 q_spec, +#endif Word16 *mdct_stereo_mode, /* output Q0*/ Word16 *msMask, /* output Q0*/ const Word16 nBitsAvailable /*Q0*/ ) @@ -1162,23 +1427,49 @@ static void MsStereoDecision_fx( ctxR = &ctxMem[1]; ctxM = &ctxMem[2]; ctxS = &ctxMem[3]; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word16 specM_e, specS_e, G_fx, G_e, shiftL, shiftR; +#else Word16 specL_e, specR_e, specM_e, specS_e, G_fx, G_e; +#endif Word16 e_GLR; Word32 GLR_fx; +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + shiftL = s_max( 0, sub( specR_e, specL_e ) ); + shiftR = s_max( 0, sub( specL_e, specR_e ) ); + specM_e = s_max( specL_e, specR_e ); + specS_e = specM_e; + move16(); + *p_specM_e = specM_e; + move16(); + *p_specS_e = specS_e; + move16(); +#else specL_e = sub( Q31, q_spec ); specR_e = sub( Q31, q_spec ); specM_e = sub( Q31, q_spec ); specS_e = sub( Q31, q_spec ); +#endif GLR_fx = SQ_gain_estimate_stereo_fx( specL_fx, specL_e, specR_fx, specR_e, nBitsAvailable, length, &e_GLR ); /* Q31-e_GLR */ FOR( i = 0; i < length; i++ ) { +#ifdef FIX_1464_NO_SINGLE_SPEC_Q + Word32 tempL, tempR; + tempL = L_shr( specL_fx[i], shiftL ); + tempR = L_shr( specR_fx[i], shiftR ); + specM_fx[i] = Mpy_32_32( L_add( tempL, tempR ), SQRT2_OVER_2_FIXED ); // Q( q_spec ) + move32(); + specS_fx[i] = Mpy_32_32( L_sub( tempL, tempR ), SQRT2_OVER_2_FIXED ); // Q( q_spec ) + move32(); +#else specM_fx[i] = Mpy_32_32( L_add( specL_fx[i], specR_fx[i] ), SQRT2_OVER_2_FIXED ); // Q( q_spec ) move32(); specS_fx[i] = Mpy_32_32( L_sub( specL_fx[i], specR_fx[i] ), SQRT2_OVER_2_FIXED ); // Q( q_spec ) move32(); +#endif } G_fx = extract_h( GLR_fx ); /* seems to be favourable to underestimate a bit Q15-e_GLR*/ diff --git a/lib_enc/lib_enc.h b/lib_enc/lib_enc.h index 8cf6be1cd0e6ca1385d5c7ec3588583ea115ac20..ab6c39c23c4da9b2ca62da54e672eaf5dbc61607 100644 --- a/lib_enc/lib_enc.h +++ b/lib_enc/lib_enc.h @@ -169,8 +169,8 @@ ivas_error IVAS_ENC_Open_fx( /*! r: error code */ ivas_error IVAS_ENC_ConfigureForMono( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the output bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the output bitstream */ const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ @@ -182,8 +182,8 @@ ivas_error IVAS_ENC_ConfigureForMono( /*! r: error code */ ivas_error IVAS_ENC_ConfigureForStereo( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the output bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the output bitstream */ const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ @@ -197,8 +197,8 @@ ivas_error IVAS_ENC_ConfigureForStereo( /*! r: error code */ ivas_error IVAS_ENC_ConfigureForObjects( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the output bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the output bitstream */ const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ @@ -209,8 +209,8 @@ ivas_error IVAS_ENC_ConfigureForObjects( /*! r: encoder error code */ ivas_error IVAS_ENC_ConfigureForMASAObjects( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the ouput bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the ouput bitstream */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ const UWord16 numObjects, /* i : number of objects to be encoded */ @@ -220,8 +220,8 @@ ivas_error IVAS_ENC_ConfigureForMASAObjects( /*! r: encoder error code */ ivas_error IVAS_ENC_ConfigureForSBAObjects( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the ouput bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the ouput bitstream */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ const UWord16 numObjects, /* i : number of objects to be encoded */ @@ -233,8 +233,8 @@ ivas_error IVAS_ENC_ConfigureForSBAObjects( /*! r: error code */ ivas_error IVAS_ENC_ConfigureForAmbisonics( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the output bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the output bitstream */ const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ @@ -245,8 +245,8 @@ ivas_error IVAS_ENC_ConfigureForAmbisonics( ivas_error IVAS_ENC_ConfigureForAmbisonics_fx( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the output bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the output bitstream */ const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ @@ -257,8 +257,8 @@ ivas_error IVAS_ENC_ConfigureForAmbisonics_fx( /*! r: error code */ ivas_error IVAS_ENC_ConfigureForMasa( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the output bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the output bitstream */ const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ @@ -268,8 +268,8 @@ ivas_error IVAS_ENC_ConfigureForMasa( /*! r: encoder error code */ ivas_error IVAS_ENC_ConfigureForMultichannel( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 inputFs, /* i : input sampling frequency */ - const Word32 bitrate, /* i : requested bitrate of the output bitstream */ + const Word32 inputFs, /* i : input sampling frequency */ + const Word32 bitrate, /* i : requested bitrate of the output bitstream */ const bool max_bwidth_user, /* i : shows if bandwidth limitation was set by the user (true) or if default bandwidth was used (false) */ const IVAS_ENC_BANDWIDTH maxBandwidth, /* i : bandwidth limitation */ const IVAS_ENC_DTX_CONFIG dtxConfig, /* i : configuration of DTX, can by set to default by using IVAS_ENC_GetDefaultDtxConfig() */ @@ -285,7 +285,7 @@ void IVAS_ENC_Close( /*! r: error code */ ivas_error IVAS_ENC_FeedObjectMetadata( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const UWord16 ismIndex, /* i : object index */ + const UWord16 ismIndex, /* i : object index */ const IVAS_ISM_METADATA metadata /* i : object metadata handle for current frame */ ); @@ -307,8 +307,8 @@ ivas_error IVAS_ENC_EncodeFrameToSerial( /*! r: error code */ ivas_error IVAS_ENC_EncodeFrameToCompact( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - Word16 *inputBuffer, /* i : PCM input */ - const Word16 inputBufferSize, /* i : total number of samples in the input buffer. Related function: IVAS_ENC_GetInputBufferSize() */ + Word16 *inputBuffer, /* i : PCM input */ + const Word16 inputBufferSize, /* i : total number of samples in the input buffer. Related function: IVAS_ENC_GetInputBufferSize() */ UWord8 *outputBitStream, /* o : pointer to compact output bitstream. The array must already be allocated. */ UWord16 *numOutBits /* o : number of bits written to output bitstream */ ); @@ -324,7 +324,7 @@ ivas_error IVAS_ENC_SetBandwidth( /*! r: error code */ ivas_error IVAS_ENC_SetBitrate( IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - const Word32 totalBitrate /* i : requested bitrate of the output bitstream */ + const Word32 totalBitrate /* i : requested bitrate of the output bitstream */ ); /*! r: error code */ @@ -355,13 +355,13 @@ ivas_error IVAS_ENC_GetDelay( /*! r: encoder error code */ ivas_error IVAS_ENC_GetNumInChannels( const IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - Word16 *numInChannels /* o : total number of samples expected in the input buffer for current encoder configuration */ + Word16 *numInChannels /* o : total number of samples expected in the input buffer for current encoder configuration */ ); /*! r: encoder error code */ ivas_error IVAS_ENC_GetInputBufferSize( const IVAS_ENC_HANDLE hIvasEnc, /* i/o: IVAS encoder handle */ - Word16 *inputBufferSize /* o : total number of samples expected in the input buffer for current encoder configuration */ + Word16 *inputBufferSize /* o : total number of samples expected in the input buffer for current encoder configuration */ ); /* Utility functions */ diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index 120dd42b517093453d30f84287b99123ded2615c..ef39833e44f6d42ac689fcaf82591fbc200ce7a5 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -145,9 +145,9 @@ void bw_detect_fx( Encoder_State *st, /* i/o: Encoder State */ const Word16 signal_in[], /* i : input signal */ Word16 *spectrum, /* i : MDCT spectrum Q_spec */ - const Word32 *enerBuffer, /* i : CLDFB Energy Q31 */ - const Word16 *cldfbBuf_Ener_Exp, /* i : CLDFB Energy Exponent */ - const IVAS_FORMAT ivas_format, /* i : IVAS format */ + const Word32 *enerBuffer, /* i : CLDFB Energy Q31 */ + const Word16 *cldfbBuf_Ener_Exp, /* i : CLDFB Energy Exponent */ + const IVAS_FORMAT ivas_format, /* i : IVAS format */ const Word16 mct_on, /* i : flag MCT mode */ const Word16 Q_spec );