diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b0efa75256f97734e8d4eaff07c0d1e02a7aeab1..e7d544e78313c37b02575602c0edfa006fffcf69 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,14 +4,15 @@ variables: BUILD_OUTPUT: "build_output.txt" EVS_BE_TEST_DIR: "/usr/local/be_2_evs_test" EVS_BE_WIN_TEST_DIR: "C:/Users/gitlab-runner/testvec" - SANITIZER_TESTS: "CLANG1 CLANG2 CLANG3" - OUT_FORMATS_CHANNEL_BASED: "stereo mono 5_1 5_1_2 5_1_4 7_1 7_1_4" - OUT_FORMATS_SCENE_BASED: "FOA HOA2 HOA3" - OUT_FORMATS_BINAURAL: "BINAURAL BINAURAL_ROOM_IR BINAURAL_ROOM_REVERB" EXIT_CODE_NON_BE: 123 EXIT_CODE_FAIL: 1 PROCESSING_SCRIPTS_BIN_DIR: "/test-bin" TESTS_DIR_CODEC_BE_ON_MR: "tests/codec_be_on_mr_nonselection" + SANITIZER_TESTS: "CLANG1 CLANG2 CLANG3" + OUT_FORMATS_CHANNEL_BASED: "stereo mono 5_1 5_1_2 5_1_4 7_1 7_1_4" + OUT_FORMATS_SCENE_BASED: "FOA HOA2 HOA3" + OUT_FORMATS_BINAURAL: "BINAURAL BINAURAL_ROOM_IR BINAURAL_ROOM_REVERB" + OUT_FORMATS_ALL: "$OUT_FORMATS_ALL" IVAS_PIPELINE_NAME: '' MANUAL_PIPELINE_TYPE: description: "Type for the manual pipeline run. Use 'test-be-release' to run BE test against release codec." @@ -226,12 +227,12 @@ stages: - if [ $CLANG_NUM -eq 1 ]; then sanitizer_type="MemorySanitizer"; elif [ $CLANG_NUM -eq 2 ]; then sanitizer_type="AddressSanitizer"; elif [ $CLANG_NUM -eq 3 ]; then sanitizer_type="UndefinedBehaviorSanitizer"; else echo "Wrong CLANG_NUM $CLANG_NUM given!"; exit 1; fi # run encoder and decoder with 20ms renderer framesize first, use reference creation mode - - python3 -m pytest $SELF_TEST_PRM_FILE -v --update_ref 1 -m create_ref --html=report-20ms.html --self-contained-html --junit-xml=report-junit-20ms.xml --testcase_timeout=$testcase_timeout --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec || exit_code20=$? + - python3 -m pytest tests/codec_be_on_mr_nonselection/test_param_file.py --param_file $SELF_TEST_PRM_FILE -v --update_ref 1 -m create_ref --html=report-20ms.html --self-contained-html --junit-xml=report-junit-20ms.xml --testcase_timeout=$testcase_timeout --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec || exit_code20=$? # for 10ms and 5ms renderer framesize, we only need to run the decoder part as renderer framesize is a decoder-only option # set tolerance very high do ignore any BE differences due to the different renderer framesizes, those can appear due to the limiter being active # we are only interested in runtime errors from the sanitizers and ignore the diffs - - python3 -m pytest $SELF_TEST_PRM_FILE -v --html=report-5ms.html --self-contained-html --junit-xml=report-junit-5ms.xml --dut_fr 5 --decoder_only --abs_tol 100000 || exit_code5=$? - - python3 -m pytest $SELF_TEST_PRM_FILE -v --html=report-10ms.html --self-contained-html --junit-xml=report-junit-10ms.xml --dut_fr 10 --decoder_only --abs_tol 100000 || exit_code10=$? + - python3 -m pytest tests/codec_be_on_mr_nonselection/test_param_file.py --param_file $SELF_TEST_PRM_FILE -v --html=report-5ms.html --self-contained-html --junit-xml=report-junit-5ms.xml --dut_fr 5 --decoder_only --abs_tol 100000 || exit_code5=$? + - python3 -m pytest tests/codec_be_on_mr_nonselection/test_param_file.py --param_file $SELF_TEST_PRM_FILE -v --html=report-10ms.html --self-contained-html --junit-xml=report-junit-10ms.xml --dut_fr 10 --decoder_only --abs_tol 100000 || exit_code10=$? - if [ $exit_code20 -ne 0 ] || [ $exit_code10 -ne 0 ] || [ $exit_code5 -ne 0 ]; then exit 1; fi @@ -535,11 +536,10 @@ codec-smoke-test: - *update-ltv-repo - bash ci/smoke_test.sh ### analyze for failures - - if ! [ -s smoke_test_output.txt ] || ! [ -s smoke_test_output_plc.txt ] || ! [ -s smoke_test_output_jbm_noEXT.txt ] || ! [ -s smoke_test_output_hrtf.txt ]; then echo "Error in smoke test"; exit 1; fi + - if ! [ -s smoke_test_output.txt ] || ! [ -s smoke_test_output_jbm.txt ] || ! [ -s smoke_test_output_hrtf.txt ]; then echo "Error in smoke test"; exit 1; fi - ret_val=0 - - if cat smoke_test_output.txt | grep -c "failed"; then echo "Smoke test without PLC failed"; ret_val=1; fi - - if cat smoke_test_output_plc.txt | grep -c "failed"; then echo "Smoke test with PLC failed"; ret_val=1; fi - - if cat smoke_test_output_jbm_noEXT.txt | grep -c "failed"; then echo "Smoke test JBM part failed"; ret_val=1; fi + - if cat smoke_test_output.txt | grep -c "failed"; then echo "Smoke test without JBM failed"; ret_val=1; fi + - if cat smoke_test_output_jbm.txt | grep -c "failed"; then echo "Smoke test JBM part failed"; ret_val=1; fi - if cat smoke_test_output_hrtf.txt | grep -c "failed"; then echo "Smoke test with external hrtf files failed"; ret_val=1; fi - exit $ret_val artifacts: @@ -548,8 +548,7 @@ codec-smoke-test: when: always paths: - smoke_test_output.txt - - smoke_test_output_plc.txt - - smoke_test_output_jbm_noEXT.txt + - smoke_test_output_jbm.txt - smoke_test_output_hrtf.txt expose_as: "Smoke test results" @@ -562,7 +561,7 @@ codec-msan: before_script: - CLANG_NUM=1 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS - - SELF_TEST_PRM_FILE="tests/codec_be_on_mr_nonselection/test_param_file.py" + - SELF_TEST_PRM_FILE="scripts/config/self_test.prm" <<: *sanitizer-selftest-anchor # code selftest testvectors with address-sanitizer binaries @@ -572,7 +571,7 @@ codec-asan: before_script: - CLANG_NUM=2 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS - - SELF_TEST_PRM_FILE="tests/codec_be_on_mr_nonselection/test_param_file.py" + - SELF_TEST_PRM_FILE="scripts/config/self_test.prm" <<: *sanitizer-selftest-anchor # code selftest testvectors with undefined-behaviour-sanitizer binaries @@ -584,7 +583,7 @@ codec-usan: before_script: - CLANG_NUM=3 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS - - SELF_TEST_PRM_FILE="tests/codec_be_on_mr_nonselection/test_param_file.py" + - SELF_TEST_PRM_FILE="scripts/config/self_test.prm" <<: *sanitizer-selftest-anchor # compare bit-exactness between 5ms and 20 on the branch @@ -1662,13 +1661,13 @@ ltv-msan: - .sanitizer-selftest-ltv rules: - if: $SANITIZER_SCHEDULE_E - timeout: 3 hour + timeout: 4 hour tags: - ivas-linux-fast before_script: - CLANG_NUM=1 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS - - SELF_TEST_PRM_FILE="tests/test_param_file_ltv.py" + - SELF_TEST_PRM_FILE="scripts/config/self_test_ltv.prm" <<: *sanitizer-selftest-anchor # code selftest long testvectors with address-sanitizer binaries @@ -1678,14 +1677,14 @@ ltv-asan: rules: - if: $SANITIZER_SCHEDULE_E when: delayed - start_in: 3 hours + start_in: 4 hours tags: - ivas-linux-fast timeout: 3 hour before_script: - CLANG_NUM=2 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS - - SELF_TEST_PRM_FILE="tests/test_param_file_ltv.py" + - SELF_TEST_PRM_FILE="scripts/config/self_test_ltv.prm" <<: *sanitizer-selftest-anchor # code selftest long testvectors with undefined-behaviour-sanitizer binaries @@ -1695,14 +1694,14 @@ ltv-usan: rules: - if: $SANITIZER_SCHEDULE_E when: delayed - start_in: 6 hours + start_in: 7 hours tags: - ivas-linux-fast timeout: 3 hour before_script: - CLANG_NUM=3 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS - - SELF_TEST_PRM_FILE="tests/test_param_file_ltv.py" + - SELF_TEST_PRM_FILE="scripts/config/self_test_ltv.prm" <<: *sanitizer-selftest-anchor .sanitizer-test-template: @@ -1748,7 +1747,7 @@ sanitizer-test-stereo: timeout: 2.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py stereo $OUT_FORMATS_CHANNEL_BASED --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py stereo $OUT_FORMATS_CHANNEL_BASED EXT --tests $SANITIZER_TESTS sanitizer-test-stereodmxevs: extends: .sanitizer-test-schedule-A @@ -1770,7 +1769,7 @@ sanitizer-test-mc-5_1: timeout: 2.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py 5_1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py 5_1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-5_1_2: extends: .sanitizer-test-schedule-A @@ -1781,7 +1780,7 @@ sanitizer-test-mc-5_1_2: timeout: 2.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py 5_1_2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py 5_1_2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-5_1_4: extends: .sanitizer-test-schedule-A @@ -1792,7 +1791,7 @@ sanitizer-test-mc-5_1_4: timeout: 3.75 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py 5_1_4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py 5_1_4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-7_1: extends: .sanitizer-test-schedule-A @@ -1803,7 +1802,7 @@ sanitizer-test-mc-7_1: timeout: 2.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py 7_1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py 7_1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-7_1_4: extends: .sanitizer-test-schedule-A @@ -1814,7 +1813,7 @@ sanitizer-test-mc-7_1_4: timeout: 5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py 7_1_4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py 7_1_4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+1: extends: .sanitizer-test-schedule-A @@ -1825,7 +1824,7 @@ sanitizer-test-ism+1: timeout: 1.25 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+2: extends: .sanitizer-test-schedule-A @@ -1836,7 +1835,7 @@ sanitizer-test-ism+2: timeout: 2.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+3: extends: .sanitizer-test-schedule-A @@ -1847,7 +1846,7 @@ sanitizer-test-ism+3: timeout: 3.75 hour script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+4: extends: .sanitizer-test-schedule-A @@ -1858,7 +1857,7 @@ sanitizer-test-ism+4: timeout: 5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-masa: extends: .sanitizer-test-schedule-A @@ -1869,7 +1868,7 @@ sanitizer-test-masa: timeout: 10 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py MASA $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py MASA $OUT_FORMATS_ALL --tests $SANITIZER_TESTS ### --- sanitizer schedule B --- @@ -1884,7 +1883,7 @@ sanitizer-test-foa: - if: $SANITIZER_SCHEDULE_B script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py FOA $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py FOA $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-hoa2: extends: .sanitizer-test-schedule-B @@ -1894,7 +1893,7 @@ sanitizer-test-hoa2: start_in: 7.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-hoa3: extends: .sanitizer-test-schedule-B @@ -1904,7 +1903,7 @@ sanitizer-test-hoa3: start_in: 15 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism1: extends: .sanitizer-test-schedule-B @@ -1914,7 +1913,7 @@ sanitizer-test-osba-foa-ism1: start_in: 22.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism2: extends: .sanitizer-test-schedule-B @@ -1924,7 +1923,7 @@ sanitizer-test-osba-foa-ism2: start_in: 30 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism3: extends: .sanitizer-test-schedule-B @@ -1934,7 +1933,7 @@ sanitizer-test-osba-foa-ism3: start_in: 37.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism4: extends: .sanitizer-test-schedule-B @@ -1944,7 +1943,7 @@ sanitizer-test-osba-foa-ism4: start_in: 45 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism1: extends: .sanitizer-test-schedule-B @@ -1954,7 +1953,7 @@ sanitizer-test-osba-hoa2-ism1: start_in: 52.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism2: extends: .sanitizer-test-schedule-B @@ -1964,7 +1963,7 @@ sanitizer-test-osba-hoa2-ism2: start_in: 60 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism3: extends: .sanitizer-test-schedule-B @@ -1974,7 +1973,7 @@ sanitizer-test-osba-hoa2-ism3: start_in: 67.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism4: extends: .sanitizer-test-schedule-B @@ -1984,7 +1983,7 @@ sanitizer-test-osba-hoa2-ism4: start_in: 75 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism1: extends: .sanitizer-test-schedule-B @@ -1994,7 +1993,7 @@ sanitizer-test-osba-hoa3-ism1: start_in: 82.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism2: extends: .sanitizer-test-schedule-B @@ -2004,7 +2003,7 @@ sanitizer-test-osba-hoa3-ism2: start_in: 90 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-omasa-ism4: extends: .sanitizer-test-schedule-B @@ -2015,7 +2014,7 @@ sanitizer-test-omasa-ism4: timeout: 10 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS ### --- sanitizer schedule C --- @@ -2031,7 +2030,7 @@ sanitizer-test-omasa-ism1: - if: $SANITIZER_SCHEDULE_C script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-omasa-ism2: extends: .sanitizer-test-schedule-C @@ -2041,7 +2040,7 @@ sanitizer-test-omasa-ism2: start_in: 10 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-omasa-ism3: extends: .sanitizer-test-schedule-C @@ -2051,7 +2050,7 @@ sanitizer-test-omasa-ism3: start_in: 20 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism3: extends: .sanitizer-test-schedule-C @@ -2062,7 +2061,7 @@ sanitizer-test-osba-hoa3-ism3: timeout: 7.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism4: extends: .sanitizer-test-schedule-C @@ -2073,7 +2072,7 @@ sanitizer-test-osba-hoa3-ism4: timeout: 7.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS ### --- sanitizer schedule D --- @@ -2088,7 +2087,7 @@ sanitizer-test-planar-foa: - if: $SANITIZER_SCHEDULE_D script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-planar-hoa2: extends: .sanitizer-test-schedule-D @@ -2098,7 +2097,7 @@ sanitizer-test-planar-hoa2: start_in: 7.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-planar-hoa3: extends: .sanitizer-test-schedule-D @@ -2108,7 +2107,7 @@ sanitizer-test-planar-hoa3: start_in: 15 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism1: extends: .sanitizer-test-schedule-D @@ -2118,7 +2117,7 @@ sanitizer-test-osba-planar-foa-ism1: start_in: 22.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism2: extends: .sanitizer-test-schedule-D @@ -2128,7 +2127,7 @@ sanitizer-test-osba-planar-foa-ism2: start_in: 30 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism3: extends: .sanitizer-test-schedule-D @@ -2138,7 +2137,7 @@ sanitizer-test-osba-planar-foa-ism3: start_in: 37.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism4: extends: .sanitizer-test-schedule-D @@ -2148,7 +2147,7 @@ sanitizer-test-osba-planar-foa-ism4: start_in: 45 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism1: extends: .sanitizer-test-schedule-D @@ -2158,7 +2157,7 @@ sanitizer-test-osba-planar-hoa2-ism1: start_in: 52.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism2: extends: .sanitizer-test-schedule-D @@ -2168,7 +2167,7 @@ sanitizer-test-osba-planar-hoa2-ism2: start_in: 60 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism3: extends: .sanitizer-test-schedule-D @@ -2178,7 +2177,7 @@ sanitizer-test-osba-planar-hoa2-ism3: start_in: 67.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism4: extends: .sanitizer-test-schedule-D @@ -2188,7 +2187,7 @@ sanitizer-test-osba-planar-hoa2-ism4: start_in: 75 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism1: extends: .sanitizer-test-schedule-D @@ -2198,7 +2197,7 @@ sanitizer-test-osba-planar-hoa3-ism1: start_in: 82.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM1 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism2: extends: .sanitizer-test-schedule-D @@ -2208,7 +2207,7 @@ sanitizer-test-osba-planar-hoa3-ism2: start_in: 90 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM2 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism3: extends: .sanitizer-test-schedule-D @@ -2218,7 +2217,7 @@ sanitizer-test-osba-planar-hoa3-ism3: start_in: 97.5 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM3 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism4: extends: .sanitizer-test-schedule-D @@ -2228,7 +2227,8 @@ sanitizer-test-osba-planar-hoa3-ism4: start_in: 105 hours script: - *update-ltv-repo - - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM4 $OUT_FORMATS_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL --tests $SANITIZER_TESTS + - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS + # GCOV/LCOV coverage analysis of self_test suite @@ -2289,7 +2289,7 @@ coverage-test-on-main-scheduled: &complexity-measurements-setup # create necessary environment - mkdir -p wmops/logs - - job_id=$(python3 ci/get_id_of_last_job_occurence.py $CI_COMMIT_REF_NAME $CI_JOB_NAME) + - job_id=$(python3 ci/get_id_of_last_job_occurence.py $CI_COMMIT_REF_NAME $CI_JOB_NAME $CI_PROJECT_ID --success_only) - echo $job_id - curl --request GET "https://forge.3gpp.org/rep/api/v4/projects/$CI_PROJECT_ID/jobs/$job_id/artifacts" --output artifacts.zip - unzip artifacts.zip || true # this may fail on first run, when there are no artifacts there and the zip file is actually just "404"-html diff --git a/Workspace_msvc/lib_util.vcxproj b/Workspace_msvc/lib_util.vcxproj index c887ffaa96ec38106a0b0669d27b9c274c42e003..79e5545f3fee266b8433f1b74a1926d40b570aa5 100644 --- a/Workspace_msvc/lib_util.vcxproj +++ b/Workspace_msvc/lib_util.vcxproj @@ -100,6 +100,7 @@ + @@ -126,6 +127,7 @@ + diff --git a/apps/decoder.c b/apps/decoder.c index 9d38acb1da54002fbe27e144bd60d4eba4b0f140..736e6130ffd953212dfa44acf2fbd555653767af 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -43,6 +43,9 @@ #include "masa_file_writer.h" #include "render_config_reader.h" #include "rotation_file_reader.h" +#ifdef FIX_1053_REVERB_RECONFIGURATION +#include "aeid_file_reader.h" +#endif #ifdef SPLIT_REND_WITH_HEAD_ROT #include "split_render_file_read_write.h" #endif @@ -1543,65 +1546,25 @@ static bool parseCmdlIVAS_dec( if ( !is_digits_only( argv[i] ) ) { #ifdef FIX_1053_REVERB_RECONFIGURATION - uint16_t k; - char *s = argv[i]; - char *token = argv[i]; + aeidFileReader *aeidReader = NULL; - for ( k = 0; s[k]; ) + if ( aeidFileReader_open( argv[i], &aeidReader ) != IVAS_ERR_OK ) { - s[k] == ',' ? k++ : *s++; - } - k++; - - if ( k == 0 ) - { - fprintf( stdout, "Error: Invalid acoustic environment sequence specified: %s\n\n", argv[i] ); + fprintf( stderr, "\nError: Can't open aeid file %s \n", argv[i] ); usage_dec(); return false; } - if ( NULL == ( arg->aeSequence.pID = malloc( sizeof( uint16_t ) * k ) ) || - NULL == ( arg->aeSequence.pValidity = malloc( sizeof( uint16_t ) * k ) ) ) + if ( aeidFileReading( aeidReader, &arg->aeSequence.count, &arg->aeSequence.pID, &arg->aeSequence.pValidity ) != IVAS_ERR_OK ) { - fprintf( stdout, "Error: Unable to allocate memory for acoustic environment sequence: %s\n\n", argv[i] ); + fprintf( stderr, "\nError while reading aeid from %s\n", argv[i] ); usage_dec(); return false; } - arg->aeSequence.count = k; - - k = 0; - token = strtok( argv[i++], ":" ); - - while ( token != NULL ) - { - if ( !is_number( token ) ) - { - fprintf( stdout, "Error: Invalid token %s found in acoustic environment sequence: %s\n\n", token, argv[i] ); - usage_dec(); - return false; - } - arg->aeSequence.pID[k] = (uint16_t) atoi( token ); + aeidFileReader_close( &aeidReader ); - token = strtok( NULL, "," ); - if ( !is_number( token ) ) - { - fprintf( stdout, "Error: Invalid token %s found in acoustic environment sequence: %s\n\n", token, argv[i] ); - usage_dec(); - return false; - } - arg->aeSequence.pValidity[k] = (uint16_t) atoi( token ); - - token = strtok( NULL, ":" ); - k++; - } - - if ( k != arg->aeSequence.count ) - { - fprintf( stdout, "Error while parsing acoustic environment sequence: %s\n\n", argv[i] ); - usage_dec(); - return false; - } + i++; #else fprintf( stdout, "Error: Invalid acoustic environment ID specified: %s\n\n", argv[i] ); usage_dec(); @@ -1872,10 +1835,8 @@ static void usage_dec( void ) fprintf( stdout, " ISMs 1,2,3 and 4 respectively. This options needs to be accompanied by a render_config file,\n" ); fprintf( stdout, " otherwise a default directivity pattern is used.\n" ); #ifdef FIX_1053_REVERB_RECONFIGURATION - fprintf( stdout, "-aeid ID : Acoustic environment ID (number > 0) or\n" ); - fprintf( stdout, " a sequence thereof in the format [ID1:duration1,ID2:duration2...]\n" ); - fprintf( stdout, " without braces and spaces, with ':' character separating ID from duration and ',' separating\n" ); - fprintf( stdout, " ID and duration pairs, where duration is specified in frames\n" ); + fprintf( stdout, "-aeid ID | File : Acoustic environment ID (number > 0)\n" ); + fprintf( stdout, " alternatively, it can be a text file where each line contains \"ID duration\"\n" ); fprintf( stdout, " for BINAURAL_ROOM_REVERB output configuration.\n" ); #else fprintf( stdout, "-aeid ID : Acoustic environment ID (number >= 0) for BINAURAL_ROOM_REVERB output configuration\n" ); diff --git a/apps/renderer.c b/apps/renderer.c index f8c53320d1ca65ed22823cf907f90b58445c0642..6a9f1048f31b6172043654890b20b5255f35c4bd 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -45,6 +45,9 @@ #include "masa_file_writer.h" #include "render_config_reader.h" #include "rotation_file_reader.h" +#ifdef FIX_1053_REVERB_RECONFIGURATION +#include "aeid_file_reader.h" +#endif #ifdef SPLIT_REND_WITH_HEAD_ROT #include "split_render_file_read_write.h" #include "split_rend_bfi_file_reader.h" @@ -400,7 +403,7 @@ static const CmdLnParser_Option cliOptions[] = { .match = "acoustic_environment_id", .matchShort = "aeid", #ifdef FIX_1053_REVERB_RECONFIGURATION - .description = "Acoustic environment ID( number > 0 ) or a sequence thereof in the format [ID1:duration1,ID2:duration2...] without braces and spaces, with ':' character separating ID from duration and ',' separating ID and duration pairs, where duration is specified in frames for BINAURAL_ROOM_REVERB output configuration.", + .description = "Acoustic environment ID (number > 0) alternatively, it can be a text file where each line contains \"ID duration\" for BINAURAL_ROOM_REVERB output configuration.", #else .description = "Acoustic environment ID (number >= 0) for BINAURAL_ROOM_REVERB output configuration", #endif @@ -737,6 +740,7 @@ int main( int32_t delayTimeScale = 0; int16_t i, numChannels; #ifdef FIX_1053_REVERB_RECONFIGURATION + IVAS_RENDER_CONFIG_DATA renderConfig; uint16_t aeID; #endif ivas_error error = IVAS_ERR_OK; @@ -1051,7 +1055,9 @@ int main( if ( args.renderConfigFilePath[0] != '\0' ) { +#ifndef FIX_1053_REVERB_RECONFIGURATION IVAS_RENDER_CONFIG_DATA renderConfig; +#endif /* sanity check */ #ifdef SPLIT_REND_WITH_HEAD_ROT @@ -1563,8 +1569,10 @@ int main( { if ( ++args.aeSequence.frameCounter >= args.aeSequence.pValidity[args.aeSequence.selected] ) { +#ifndef FIX_1053_REVERB_RECONFIGURATION IVAS_RENDER_CONFIG_DATA renderConfig; +#endif if ( ++args.aeSequence.selected >= args.aeSequence.count ) { args.aeSequence.selected = 0; @@ -1574,7 +1582,7 @@ int main( { if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) { - fprintf( stderr, "Invalid acoustic environment configuratoin parameters\n\n" ); + fprintf( stderr, "Invalid acoustic environment configuration parameters\n\n" ); goto cleanup; } } @@ -2569,69 +2577,27 @@ static bool parseAcousticEnvironmentIds( const char *value, AcousticEnvironmentSequence *aeSequence ) { - uint16_t k; char config_string[RENDERER_MAX_METADATA_LINE_LENGTH]; - char *s; - char *token; strncpy( config_string, value, RENDERER_MAX_METADATA_LINE_LENGTH ); - s = config_string; - token = config_string; if ( !is_digits_only( config_string ) ) { + aeidFileReader *aeidReader = NULL; - for ( k = 0; s[k]; ) - { - s[k] == ',' ? k++ : *s++; - } - k++; - - if ( k == 0 ) + if ( aeidFileReader_open( config_string, &aeidReader ) != IVAS_ERR_OK ) { - fprintf( stdout, "Error: Invalid acoustic environment sequence specified: %s\n\n", config_string ); + fprintf( stderr, "\nError: Can't open aeid file %s \n", config_string ); return false; } - if ( NULL == ( aeSequence->pID = malloc( sizeof( uint16_t ) * k ) ) || - NULL == ( aeSequence->pValidity = malloc( sizeof( uint16_t ) * k ) ) ) + if ( aeidFileReading( aeidReader, &aeSequence->count, &aeSequence->pID, &aeSequence->pValidity ) != IVAS_ERR_OK ) { - fprintf( stdout, "Error: Unable to allocate memory for acoustic environment sequence: %s\n\n", config_string ); + fprintf( stderr, "\nError while reading aeid from %s\n", config_string ); return false; } - aeSequence->count = k; - - k = 0; - - token = strtok( config_string, ":" ); - - while ( token != NULL ) - { - if ( !is_number( token ) ) - { - fprintf( stdout, "Error: Invalid token %s found in acoustic environment sequence: %s\n\n", token, config_string ); - return false; - } - aeSequence->pID[k] = (uint16_t) atoi( token ); - - token = strtok( NULL, "," ); - if ( !is_number( token ) ) - { - fprintf( stdout, "Error: Invalid token %s found in acoustic environment sequence: %s\n\n", token, config_string ); - return false; - } - aeSequence->pValidity[k] = (uint16_t) atoi( token ); - - token = strtok( NULL, ":" ); - k++; - } - - if ( k != aeSequence->count ) - { - fprintf( stdout, "Error while parsing acoustic environment sequence: %s\n\n", config_string ); - return false; - } + aeidFileReader_close( &aeidReader ); } else { diff --git a/ci/basop-pages/basop_index.html b/ci/basop-pages/basop_index.html new file mode 100644 index 0000000000000000000000000000000000000000..4c5202ad352c5821de0e106eee7100ac95d8fcd5 --- /dev/null +++ b/ci/basop-pages/basop_index.html @@ -0,0 +1,22 @@ + + + + + +

Ivas BASOP code Development

+ +

Daily long testvector tests

+ + + +

Test Coverage

+ +
+ tbd... +
+ + diff --git a/ci/basop-pages/create_report_pages.py b/ci/basop-pages/create_report_pages.py new file mode 100644 index 0000000000000000000000000000000000000000..d8c3373b5432dfdfd371e30d42452d4e438ffa15 --- /dev/null +++ b/ci/basop-pages/create_report_pages.py @@ -0,0 +1,226 @@ +import csv +import pathlib +import argparse + + +CSV_DELIM = ";" +SUBPAGE_TMPL_CSS = """ + +""" + +SUBPAGE_TMPL_HTML = """ + +

Report for job {job_name}

+
  • Current run - id: {id_current}
  • +
  • Previous run - id: {id_previous}
  • +
  • Merged csv data
  • + + +
    +Table is sorted by Difference in MLD with ERRORs or missing values ("None", "") being on top additionally. +
    + + + + {table_header_a} + + + {table_header_b} + + +{table_body} + +
    +""" +TD_TMPL_NORMAL = "{}" +TD_TMPL_INCREASE = "{}" +TD_TMPL_REDUCE = "{}" +TR_TMPL = "{}" +TH_TMPL_GLOBAL = '{}' +TH_TMPL_DIFFERENTIAL = '{}' +TH_TMPL_SECOND_ROW = '{}' + +# expected columns. actual columns are filtered from the incoming data later, this +# is mainly for controlling the order in the output table +COLUMNS = ["testcase", "Result", "MLD", "MAXIMUM ABS DIFF"] +COLUMNS_GLOBAL = COLUMNS[:1] +COLUMNS_DIFFERENTIAL = COLUMNS[1:] + + +def create_subpage( + html_out, + csv_out, + csv_current: str, + csv_previous: str, + id_current: int, + id_previous: int, + job_name: str, +): + merged_reports = merge_and_cleanup_mld_reports( + csv_current, csv_previous, id_current, id_previous + ) + write_out_csv(merged_reports, merged_reports[0].keys(), csv_out) + + table_header_a = "".join([TH_TMPL_GLOBAL.format(c) for c in COLUMNS_GLOBAL] + [TH_TMPL_DIFFERENTIAL.format(c) for c in COLUMNS_DIFFERENTIAL]) + table_header_b = list() + for c in COLUMNS_DIFFERENTIAL: + table_header_b.append(TH_TMPL_SECOND_ROW.format(id_previous)) + table_header_b.append(TH_TMPL_SECOND_ROW.format(id_current)) + table_header_b = "".join(table_header_b) + table_body = "\n".join( + tr_from_row(row, id_current, id_previous) for row in merged_reports + ) + new_subpage = SUBPAGE_TMPL_CSS + SUBPAGE_TMPL_HTML.format( + id_current=id_current, + id_previous=id_previous, + table_body=table_body, + job_name=job_name, + table_header_a=table_header_a, + table_header_b=table_header_b, + ) + with open(html_out, "w") as f: + f.write(new_subpage) + + +def write_out_csv(data, col_names, outfile): + with open(outfile, "w") as f: + writer = csv.DictWriter(f, col_names, delimiter=";") + writer.writeheader() + for row in data: + writer.writerow(row) + + +def tr_from_row(row, id_current, id_previous): + tr = list() + + # pre-filter columns to handle case where new columns are added + # only include columns that are there in both data + columns_global = [c for c in COLUMNS_GLOBAL if c in row] + diff_col_tmpl = "{}-{}" + incoming_cols = row.keys() + columns_differential = [ + c + for c in COLUMNS_DIFFERENTIAL + if diff_col_tmpl.format(c, id_current) in incoming_cols + and diff_col_tmpl.format(c, id_previous) in incoming_cols + ] + + for c in columns_global: + # this is currently for the "testcase" column - here we don't compare, just one value is used + tr.append(TD_TMPL_NORMAL.format(row[c])) + for c in columns_differential: + # this is for all columns where we compare between current and previous run + prev = row[f"{c}-{id_previous}"] + curr = row[f"{c}-{id_current}"] + + # use red background if increase, green if decrease, white if same + td_tmpl = TD_TMPL_NORMAL + try: + if float(curr) > float(prev): + td_tmpl = TD_TMPL_INCREASE + if float(curr) < float(prev): + td_tmpl = TD_TMPL_REDUCE + except ValueError: + # if we land here, one of the cells is not a number, this indicates a crash + # or some error in the scripts, so mark with red as well + td_tmpl = TD_TMPL_INCREASE + + tr.append(td_tmpl.format(row[f"{c}-{id_previous}"])) + tr.append(td_tmpl.format(row[f"{c}-{id_current}"])) + + return TR_TMPL.format("\n".join(tr)) + + +def merge_and_cleanup_mld_reports( + csv_current: str, csv_previous: str, id_current: int, id_previous: int +): + with open(csv_current) as f: + current_reader = csv.DictReader(f, delimiter=CSV_DELIM) + current = list(current_reader) + with open(csv_previous) as f: + previous = list(csv.DictReader(f, delimiter=CSV_DELIM)) + + # TODO: handle newly added testcases - for now assume that both have the same columns + merge_key = "testcase" + other_keys = [k for k in current_reader.fieldnames if k != merge_key] + merged = merge_tables( + current, previous, id_current, id_previous, merge_key, other_keys + ) + + # TODO: sort on result as well + mld_col_curr = f"MLD-{id_current}" + mld_col_prev = f"MLD-{id_previous}" + + # sort based on difference in MLD between current and previous run + # put cases with "None" at the top of the list + def sort_func(x): + vals_missing = ["None", ""] + + if x[mld_col_curr] in vals_missing or x[mld_col_prev] in vals_missing: + return float("inf") + + return float(x[mld_col_curr]) - float(x[mld_col_prev]) + + merged = sorted(merged, key=sort_func, reverse=True) + + # remove the unecessary whole path from the testcase names + for row in merged: + row["testcase"] = pathlib.Path(row["testcase"]).name + + return merged + + +def merge_tables(tbl1, tbl2, suffix1, suffix2, merge_key, other_keys): + merged = list() + + for row1 in tbl1: + new_row = dict() + for key in other_keys: + new_row[f"{key}-{suffix1}"] = row1[key] + + for row2 in tbl2: + if row1[merge_key] == row2[merge_key]: + new_row[merge_key] = row1[merge_key] + for key in other_keys: + new_row[f"{key}-{suffix2}"] = row2[key] + break + + merged.append(new_row) + + return merged + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("html_out") + parser.add_argument("csv_out") + parser.add_argument("csv_current") + parser.add_argument("csv_previous") + parser.add_argument("id_current", type=int) + parser.add_argument("id_previous", type=int) + parser.add_argument("job_name") + args = parser.parse_args() + + create_subpage( + args.html_out, + args.csv_out, + args.csv_current, + args.csv_previous, + args.id_current, + args.id_previous, + args.job_name, + ) diff --git a/ci/get_id_of_last_job_occurence.py b/ci/get_id_of_last_job_occurence.py index 449902f50a12919897ef0c0aaac41c197cd59f05..50beac5bb7c96d9b657604fb562e870bade65d68 100755 --- a/ci/get_id_of_last_job_occurence.py +++ b/ci/get_id_of_last_job_occurence.py @@ -1,49 +1,50 @@ #!/usr/bin/env python3 """ - (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. +(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. """ import argparse import requests + PER_PAGE_SUFFIX = "?per_page=50" PAGE_SUFFIX = "&page={}" -API_BASE_URL = "https://forge.3gpp.org/rep/api/v4/projects/49" +API_URL_TMPL = "https://forge.3gpp.org/rep/api/v4/projects/{}/pipelines" -def get_job_id(branch_name, job_name): +def get_job_id(branch_name, job_name, project_id, success_only): job_id = -1 # check last 500 pipelines max for page in range(100): - url_pls = API_BASE_URL + "/pipelines" + url_pls = API_URL_TMPL.format(project_id) # need both suffixes here to descend through the pages and get also older pipelines suffix = PER_PAGE_SUFFIX + PAGE_SUFFIX.format(page) @@ -61,7 +62,8 @@ def get_job_id(branch_name, job_name): # find actual job by name for job in resp_jobs.json(): - if job["name"] == job_name and job["status"] == "success": + include_job = not success_only or job["status"] == "success" + if include_job and job["name"] == job_name: job_id = job["id"] break if job_id >= 0: @@ -75,10 +77,12 @@ def get_job_id(branch_name, job_name): if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument("branch_name") - parser.add_argument("job_name") + parser.add_argument("branch_name", help="Name of the branch to search on") + parser.add_argument("job_name", help="Name of the job to get the id of") + parser.add_argument("project_id", help="ID of project to search in", type=int) + parser.add_argument("--success_only", help="Only include jobs with status 'success'", action="store_true") args = parser.parse_args() - job_id = get_job_id(args.branch_name, args.job_name) + job_id = get_job_id(args.branch_name, args.job_name, args.project_id, args.success_only) print(job_id) diff --git a/ci/setup_pages.py b/ci/setup_pages.py index 10a2e9e84ecf2f5ad1a351ca2cb040e0f5a1b569..4754d09f5c8d834e9f664aa63a73377b60473668 100755 --- a/ci/setup_pages.py +++ b/ci/setup_pages.py @@ -3,10 +3,16 @@ import os import pathlib import subprocess import sys +import shutil +from tempfile import TemporaryDirectory from get_id_of_last_job_occurence import get_job_id -JOBS = [ +PROJECT_ID_FLOAT_REPO = 49 +PROJECT_ID_BASOP_REPO = 77 + + +JOBS_FLOAT_REPO = [ "complexity-stereo-in-stereo-out", "complexity-ism-in-binaural-out", "complexity-sba-hoa3-in-hoa3-out", @@ -15,44 +21,81 @@ JOBS = [ "complexity-StereoDmxEVS-stereo-in-mono-out", "coverage-test-on-main-scheduled", ] +JOBS_BASOP_REPO = [ + "ivas-pytest-mld-long-dec", +] + +JOBS_FOR_PROJECT_ID = { + PROJECT_ID_FLOAT_REPO: JOBS_FLOAT_REPO, + PROJECT_ID_BASOP_REPO: JOBS_BASOP_REPO, +} + ARTIFACTS = "artifacts.zip" API_URL_BASE = "https://forge.3gpp.org/rep/api/v4/projects/{}/jobs" -PUBLIC = "./public" +PUBLIC_FOLDER = pathlib.Path("./public").absolute() def main(): + PUBLIC_FOLDER.mkdir() - public_folder = pathlib.Path(PUBLIC) - public_folder.mkdir() + project_id = int(os.environ["CI_PROJECT_ID"]) + jobs = JOBS_FOR_PROJECT_ID[project_id] + success_only = project_id == PROJECT_ID_FLOAT_REPO + failed_count = get_artifacts_for_jobs_and_return_num_failed( + jobs, project_id, success_only + ) + if failed_count == len(jobs): + print("Artifact collection failed for all jobs to check.") + sys.exit(1) + + index_html = PUBLIC_FOLDER.joinpath("index.html") + if project_id == PROJECT_ID_FLOAT_REPO: + src = pathlib.Path("ci/index-pages.html").absolute() + shutil.move(src, index_html) + elif project_id == PROJECT_ID_BASOP_REPO: + src = pathlib.Path("ci/basop-pages/basop_index.html").absolute() + shutil.move(src, index_html) + + sys.exit(0) + + +def get_artifacts_for_jobs_and_return_num_failed( + jobs: list, project_id: int, success_only: bool +) -> int: + """ + Get specified artifact folders for all jobs given and put them into the public folder. + + jobs: dictionary with the job names in the keys and a list of the + public folders to copy from the artifacts in the values + if "-public" is in the list, the actual folder name to copy is the key with "-public" appended + """ failed_count = 0 - for job in JOBS: - job_id = get_job_id(os.environ["CI_COMMIT_REF_NAME"], job) + + for job in jobs: + job_id = get_job_id( os.environ["CI_DEFAULT_BRANCH"], job, project_id, success_only) + print(f"{job_id} - {job}") try: - curl_for_artifacts(job_id) + with TemporaryDirectory() as tmp_dir: + curl_for_artifacts(job_id, tmp_dir) - job_public = job + "-public" - if job == "coverage-test-on-main-scheduled": - job_public = "coverage" - pathlib.Path("coverage_stv").rename( - public_folder.joinpath("coverage_stv") - ) + tmp_dir = pathlib.Path(tmp_dir) - pathlib.Path(job_public).rename(public_folder.joinpath(job_public)) + for artifact in tmp_dir.iterdir(): + src = tmp_dir.joinpath(artifact).absolute() + dst = PUBLIC_FOLDER.joinpath(artifact.name) + print(f"{src} -> {dst}") + shutil.move(src, dst) except subprocess.CalledProcessError: print(f"Could not get artifacts for {job}") failed_count += 1 - if failed_count == len(JOBS): - sys.exit(1) - - pathlib.Path("ci/index-pages.html").rename(public_folder.joinpath("index.html")) - sys.exit(0) + return failed_count -def curl_for_artifacts(job_id): +def curl_for_artifacts(job_id: int, exdir: str): cmd = [ "curl", "--request", @@ -61,6 +104,7 @@ def curl_for_artifacts(job_id): "--output", ARTIFACTS, ] + print(cmd) subprocess.run(cmd, check=True) # check for valid archive (if not, it is likely a 404 page, then display that) @@ -73,7 +117,7 @@ def curl_for_artifacts(job_id): raise subprocess.CalledProcessError(-1, "Unzip check failed") # do the actual unzipping - cmd = ["unzip", ARTIFACTS] + cmd = ["unzip", ARTIFACTS, "-d", exdir] subprocess.run(cmd, check=True) diff --git a/ci/smoke_test.sh b/ci/smoke_test.sh index 57e3e1b154d7a9d57cacda8956ed84af04e05a3b..071b9a0be620c8ebf8aef7c00f50914459088047 100755 --- a/ci/smoke_test.sh +++ b/ci/smoke_test.sh @@ -52,12 +52,11 @@ fi cfg=./scripts/config/ci_linux.json -dly_profile=./scripts/dly_error_profiles/dly_error_profile_10.dat +dly_profile=./scripts/dly_error_profiles/dly_error_profile_10_smoke_test.dat ism_md_cmd="--ism_metadata_files /usr/local/ltv/ltvISM1.csv /usr/local/ltv/ltvISM2.csv /usr/local/ltv/ltvISM3.csv /usr/local/ltv/ltvISM4.csv" duration_arg="-U 1:2" verbosity_cmd="-z console" timeout_cmd="--timeout 20" -ep_file="ci/complexity_measurements/ep_10pct_fer.g192" if [ $BUILD -eq 1 ];then # Enable memory macros to find unbalanced memory allocations/deallocations @@ -88,33 +87,26 @@ echo "\n======================= 1. non-ism modes no FEC =======================\ ./scripts/runIvasCodec.py $verbosity_cmd -m $non_ism_modes -p $cfg $duration_arg $timeout_cmd | tee smoke_test_output.txt echo "\n======================= 2. ism modes no FEC =======================\n\n" ./scripts/runIvasCodec.py $verbosity_cmd -m $ism_modes -p $cfg $duration_arg $ism_md_cmd $timeout_cmd | tee smoke_test_output.txt -# run the decoding again, but with 15% frame loss -echo "\n======================= 3. all modes with FEC =======================\n\n" -./scripts/runIvasCodec.py $verbosity_cmd -p $cfg $duration_arg -f="$ep_file" --decoder_only $timeout_cmd | tee smoke_test_output_plc.txt - -# run JBM modes - EXT is excluded as not supported yet -formats_with_no_ext_out=$(./scripts/runIvasCodec.py -L | grep -v MASA | grep -v ISM | grep -v OSBA) -formats_with_ext_out=$(./scripts/runIvasCodec.py -L | grep 'MASA\|ISM\|OSBA') -echo "\n======================= 4. JBM, modes with no EXT =======================\n\n" -./scripts/runIvasCodec.py $verbosity_cmd -C $formats_with_no_ext_out -p $cfg $duration_arg --decoder_only --jbm_file $dly_profile $timeout_cmd | tee smoke_test_output_jbm_noEXT.txt -echo "\n======================= 5. JBM, modes with EXT =======================\n\n" -./scripts/runIvasCodec.py $verbosity_cmd -C $formats_with_ext_out -p $cfg $duration_arg --decoder_only --jbm_file $dly_profile --oc BINAURAL BINAURAL_ROOM_IR mono stereo FOA HOA3 5_1 7_1_4 $timeout_cmd | tee -a smoke_test_output_jbm_noEXT.txt + +# all modes with simulated network delay - this includes JBM TSM and lost frames +echo "\n======================= 3. JBM =======================\n\n" +./scripts/runIvasCodec.py $verbosity_cmd -p $cfg $duration_arg --decoder_only --jbm_file $dly_profile $timeout_cmd | tee smoke_test_output_jbm.txt # run all modes with binaural output using external files formats_with_bin_out=$(./scripts/runIvasCodec.py -L | grep -v "mono\|tereo") -bin_out_modes="BINAURAL BINAURAL_ROOM_IR" +bin_out_modes="BINAURAL BINAURAL_ROOM_IR BINAURAL_ROOM_REVERB" -echo "\n======================= 6. binaural out with HRTF files - WB =======================\n\n" +echo "\n======================= 4. binaural out with HRTF files - WB =======================\n\n" wb_modes=$(./scripts/runIvasCodec.py -l -C $formats_with_bin_out | grep _wb_) hrtf_wb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_16kHz.bin" ./scripts/runIvasCodec.py $verbosity_cmd -p $cfg -m $wb_modes $duration_arg -D="-hrtf ${hrtf_wb}" --decoder_only --oc $bin_out_modes $timeout_cmd | tee -a smoke_test_output_hrtf.txt -echo "\n======================= 7. binaural out with HRTF files - SWB =======================\n\n" +echo "\n======================= 5. binaural out with HRTF files - SWB =======================\n\n" swb_modes=$(./scripts/runIvasCodec.py -l -C $formats_with_bin_out | grep _swb_) hrtf_swb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_32kHz.bin" ./scripts/runIvasCodec.py $verbosity_cmd -p $cfg -m $swb_modes $duration_arg -D="-hrtf ${hrtf_swb}" --decoder_only --oc $bin_out_modes $timeout_cmd | tee -a smoke_test_output_hrtf.txt -echo "\n======================= 8. binaural out with HRTF files - FB =======================\n\n" +echo "\n======================= 6. binaural out with HRTF files - FB =======================\n\n" fb_modes=$(./scripts/runIvasCodec.py -l -C $formats_with_bin_out | grep _fb_) hrtf_fb="../scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/ivas_binaural_48kHz.bin" ./scripts/runIvasCodec.py $verbosity_cmd -p $cfg -m $fb_modes $duration_arg -D="-hrtf ${hrtf_fb}" --decoder_only --oc $bin_out_modes $timeout_cmd | tee -a smoke_test_output_hrtf.txt diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 9d842f9b37eba0ba9ac5e8dd640e0bccd524bbf2..b803c9860a4b925dff01c59baa9489b08ce52ee9 100755 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -1458,12 +1458,17 @@ typedef enum /*----------------------------------------------------------------------------------* * Amplitude Panning (EFAP, VBAP) constants *----------------------------------------------------------------------------------*/ - +#ifndef FIX_1050_EFAP_ALLOC #define PANNING_AZI_RESOLUTION 2 #define PANNING_ELE_RESOLUTION 5 +#endif #define EFAP_MAX_CHAN_NUM 5 /* Maximum number of channels that constitute a polygon, 4 or 5 */ +#ifdef FIX_1050_EFAP_ALLOC +#define EFAP_MAX_POLY_SET 54 /* Upper bound on number of polygons; found to be 54 in the worst case for a speaker setup of 16.0 */ +#else #define EFAP_MAX_POLY_SET 50 /* Upper bound on number of polygons; with a Speaker setup of 16.0, we obtain 44 polygons/triangles in the matlab implementation. */ +#endif #define EFAP_MODE_EFAP 0 /* EFAP Panning */ #define EFAP_MODE_EFIP 1 /* EFIP Panning */ diff --git a/lib_com/options.h b/lib_com/options.h index 6c4363df1775edf2e1fcac6b2c6b395dd8ed9ad1..c0a4dfe8fc3000e79bb716e1d03fc417de1175e0 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -175,6 +175,7 @@ #define FIX_989_TD_REND_ROM /* Eri: Clean-up for TD renderer and completion of ROM generation tool */ #define FIX_1068_ASAN_IN_MC_2_BINAURAL_ROOM_IR /* issue 1068 : Memory leak in MC to BINAURAL_ROOM decoding with bitrate switching*/ +#define FIX_1050_EFAP_ALLOC /* FhG: issue 1050: reduction of memory allocated to EFAP handle */ /* #################### End BE switches ################################## */ @@ -190,6 +191,7 @@ #define NONBE_FIX_1087_OOB_SBA_DTX_RS /* VA: issue 1087: Extend the length of the buffer for MCT decoding to avoid out-of-bound writing in SBA SID bitrate switching decoding */ #define NONBE_FIX_1091_PMC_LOW_SIGNAL_BURSTS /* FhG: fix for #1091, fix limit calculation for the regularized inverse of Kx to avoid bursts in very low signals */ #define NONBE_FIX_1074_NOBJ_SIGNAL_OMASA_LBR /* Nok: issue 1074 fixing number of objects signaling in OMASA low rate */ +#define NONBE_FIX_1096_NAN_VALUES_IN_DIRAC_TO_STEREO /* FhG: avoid sidegain DFT-Stereo param to be larger than 1 when converting from Dirac parameters */ /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index b890dd98e5c64f778d5a9a2e0b3f7b146210b313..743a99275c1ca97ead6d075dac7f00e4f15a47c5 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -66,7 +66,14 @@ ivas_error ivas_ism_renderer_open( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for ISM renderer\n" ) ); } +#ifdef FIX_1050_EFAP_ALLOC + if ( st_ivas->hIntSetup.is_loudspeaker_setup && + st_ivas->hDecoderConfig->output_config != IVAS_AUDIO_CONFIG_STEREO && + st_ivas->hIntSetup.ls_azimuth != NULL && st_ivas->hIntSetup.ls_elevation != NULL && + st_ivas->hEFAPdata == NULL ) +#else if ( st_ivas->hIntSetup.is_loudspeaker_setup && st_ivas->hIntSetup.ls_azimuth != NULL && st_ivas->hIntSetup.ls_elevation != NULL && st_ivas->hEFAPdata == NULL ) +#endif { if ( ( error = efap_init_data( &( st_ivas->hEFAPdata ), st_ivas->hIntSetup.ls_azimuth, st_ivas->hIntSetup.ls_elevation, st_ivas->hIntSetup.nchan_out_woLFE, EFAP_MODE_EFAP ) ) != IVAS_ERR_OK ) { diff --git a/lib_dec/ivas_sba_dirac_stereo_dec.c b/lib_dec/ivas_sba_dirac_stereo_dec.c index 123e51da4bdb24f1018c75fc1015c18922d2de24..b277df73520b56d6b519533ff811d67c31ba538f 100644 --- a/lib_dec/ivas_sba_dirac_stereo_dec.c +++ b/lib_dec/ivas_sba_dirac_stereo_dec.c @@ -395,10 +395,23 @@ static void map_params_dirac_to_stereo( } } +#ifdef NONBE_FIX_1096_NAN_VALUES_IN_DIRAC_TO_STEREO + /* Clamp values here. [-1, 1] is the allowed range, but due to precision issues they can be slightly off which can cause problems later. */ side_gain[b] *= sqrtf( 1.f - diffuseness[b] ); + side_gain[b] = max( min( side_gain[b], 1 ), -1 ); side_gain[b + STEREO_DFT_BAND_MAX] *= sqrtf( 1.f - diffuseness[b] ); + side_gain[b + STEREO_DFT_BAND_MAX] = max( min( side_gain[b + STEREO_DFT_BAND_MAX], 1 ), -1 ); + /* for residual prediction gain, allowed range is [0, 1]*/ res_pred_gain[b] = diffuseness[b] * ( 1.0f - surrCoh[b] ); + res_pred_gain[b] = max( min( res_pred_gain[b], 1 ), 0 ); res_pred_gain[b + STEREO_DFT_BAND_MAX] = diffuseness[b] * ( 1.0f - surrCoh[b] ); + res_pred_gain[b + STEREO_DFT_BAND_MAX] = max( min( res_pred_gain[b + STEREO_DFT_BAND_MAX], 1 ), 0 ); +#else + side_gain[b] *= sqrtf( 1.f - diffuseness[b] ); + side_gain[b + STEREO_DFT_BAND_MAX] *= sqrtf( 1.f - diffuseness[b] ); + res_pred_gain[b] = diffuseness[b] * ( 1.0f - surrCoh[b] ); + res_pred_gain[b + STEREO_DFT_BAND_MAX] = diffuseness[b] * ( 1.0f - surrCoh[b] ); +#endif } } diff --git a/lib_rend/ivas_efap.c b/lib_rend/ivas_efap.c index 3caf13783fceb33c2dcd00f8a586084a275788f2..5be932d60f8fa13bf1d8890f7d0dd5ee07dcd299 100644 --- a/lib_rend/ivas_efap.c +++ b/lib_rend/ivas_efap.c @@ -38,6 +38,9 @@ #include "prot.h" #include "ivas_prot.h" #include "ivas_prot_rend.h" +#ifdef FIX_1050_EFAP_ALLOC +#include "ivas_rom_rend.h" +#endif #include "ivas_stat_dec.h" #ifdef DEBUGGING #include "debug.h" @@ -51,6 +54,12 @@ #define EFAP_MAX_SIZE_TMP_BUFF 30 #define EFAP_MAX_GHOST_LS 5 /* Maximum number of ghost Loudspeakers, for memory allocation purpose */ #define POLY_THRESH 1e-4f +#ifdef FIX_1050_EFAP_ALLOC +#ifdef DEBUG_EFAP_POLY_TOFILE +#define PANNING_AZI_RESOLUTION 2 +#define PANNING_ELE_RESOLUTION 5 +#endif +#endif /*-----------------------------------------------------------------------* @@ -147,6 +156,9 @@ ivas_error efap_init_data( ) { /* Handle instance declaration */ +#ifdef FIX_1050_EFAP_ALLOC + int8_t polyset_size; +#endif EFAP *efap; ivas_error error; @@ -163,13 +175,13 @@ ivas_error efap_init_data( * Allocate memory *-----------------------------------------------------------------*/ - /* Memory Allocations for efap */ + /* Memory allocation for main EFAP structure */ if ( ( efap = (EFAP *) malloc( sizeof( EFAP ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP handle\n" ) ); } - /* Memory Allocation and update for aziSpk & eleSpk arrays*/ + /* Memory allocation and update for aziSpk & eleSpk arrays*/ if ( ( efap->aziSpk = (float *) malloc( num_speaker_nodes * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker azimuths\n" ) ); @@ -179,7 +191,7 @@ ivas_error efap_init_data( return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP speaker elevations\n" ) ); } - /* Memory Allocation for vertexArray */ + /* Memory allocation for vertexArray */ if ( ( efap->vtxData.vertexArray = (EFAP_VERTEX *) malloc( ( num_speaker_nodes + EFAP_MAX_GHOST_LS ) * sizeof( EFAP_VERTEX ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP Vertex Array\n" ) ); @@ -190,6 +202,22 @@ ivas_error efap_init_data( { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferS\n" ) ); } +#ifdef FIX_1050_EFAP_ALLOC + /* get upper bound of number of polygons required */ + polyset_size = efap_poly_limit[num_speaker_nodes - 1]; + + /* Memory allocation for the polyset array */ + if ( ( efap->polyData.polysetArray = (EFAP_POLYSET *) malloc( polyset_size * sizeof( EFAP_POLYSET ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferS\n" ) ); + } + + /* Memory allocation for the triangle array */ + if ( ( efap->polyData.triArray = (EFAP_LS_TRIANGLE *) malloc( polyset_size * sizeof( EFAP_LS_TRIANGLE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for EFAP bufferS\n" ) ); + } +#endif /*-----------------------------------------------------------------* * Initialize values @@ -333,6 +361,14 @@ void efap_free_data( free( ( *hEFAPdata )->vtxData.vtxOrder ); ( *hEFAPdata )->vtxData.vtxOrder = NULL; +#ifdef FIX_1050_EFAP_ALLOC + + free( ( *hEFAPdata )->polyData.polysetArray ); + ( *hEFAPdata )->vtxData.vtxOrder = NULL; + + free( ( *hEFAPdata )->polyData.triArray ); + ( *hEFAPdata )->vtxData.vtxOrder = NULL; +#endif free( ( *hEFAPdata )->bufferLong ); ( *hEFAPdata )->bufferLong = NULL; @@ -401,7 +437,11 @@ static ivas_error poly_init( if ( efap->vtxData.vertexArray[n].ele > 90.0 - 1e-6 || efap->vtxData.vertexArray[n].ele < 1e-6 - 90.0 ) { +#ifdef FIX_1050_EFAP_ALLOC + efap->vtxData.vertexArray[n].isNaN = true; +#else efap->vtxData.vertexArray[n].isNaN = 1; +#endif } } @@ -1493,8 +1533,12 @@ static void add_vertex( /* Final Idx */ vtxArray[pos].idx = (int16_t) idxAziTmp + 181 * (int16_t) idxEleTmp; - /* Setting the nan flag to 0 */ +/* Setting the nan flag to 0 */ +#ifdef FIX_1050_EFAP_ALLOC + vtxArray[pos].isNaN = false; +#else vtxArray[pos].isNaN = 0; +#endif /* Set the default downmix type */ vtxArray[pos].dmxType = dmxType; diff --git a/lib_rend/ivas_objectRenderer_mix.c b/lib_rend/ivas_objectRenderer_mix.c index b2492324c91dea187c096c9e0a1f64185e7973d1..cd8b59cf253d440e7f21ac8d1bb5a4a6aea21b5d 100644 --- a/lib_rend/ivas_objectRenderer_mix.c +++ b/lib_rend/ivas_objectRenderer_mix.c @@ -539,7 +539,7 @@ static ivas_error DefaultBSplineModel( model->EL = (const float *) defaultHRIR_rom_EL16; model->ER = (const float *) defaultHRIR_rom_ER16; #ifdef FIX_989_TD_REND_ROM - model->K = (int16_t) ceil( RESAMPLE_FACTOR_16_48 * defaultHRIR_rom_model_configuration[5] ); + model->K = (int16_t) ceilf( RESAMPLE_FACTOR_16_48 * defaultHRIR_rom_model_configuration[5] ); #else model->K = 43; #endif diff --git a/lib_rend/ivas_rom_rend.c b/lib_rend/ivas_rom_rend.c index 90a2feb86a4f0345bd215507bf8b7c2a47980684..61871f2e3391a149a0d0738ebe561fce18725d2b 100644 --- a/lib_rend/ivas_rom_rend.c +++ b/lib_rend/ivas_rom_rend.c @@ -388,8 +388,15 @@ const float ivas_reverb_default_DSR[IVAS_REVERB_DEFAULT_N_BANDS] = const float ls_azimuth_CICP1[1] = { 0.0f }; const float ls_elevation_CICP1[1] = { 0.0f }; +#ifdef FIX_1050_EFAP_ALLOC +/*----------------------------------------------------------------------------------* + * EFAP ROM tables + *----------------------------------------------------------------------------------*/ +const int8_t efap_poly_limit[MAX_OUTPUT_CHANNELS] = {22, 22, 22, 26, 30, 34, 36, 42, 42, 44, 47, 51, 52, 54, 54, 54}; + +#endif /*----------------------------------------------------------------------------------* * LS Renderer ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_rom_rend.h b/lib_rend/ivas_rom_rend.h index 9988962dbe62b3e3b8f10d54b735357bcc328701..2041585dbea6c5c5fa809fa90a91ed06366c9034 100644 --- a/lib_rend/ivas_rom_rend.h +++ b/lib_rend/ivas_rom_rend.h @@ -125,6 +125,15 @@ extern const float ls_azimuth_CICP1[1]; extern const float ls_elevation_CICP1[1]; +#ifdef FIX_1050_EFAP_ALLOC +/*----------------------------------------------------------------------------------* + * EFAP ROM tables + *----------------------------------------------------------------------------------*/ + +extern const int8_t efap_poly_limit[MAX_OUTPUT_CHANNELS]; + + +#endif /*----------------------------------------------------------------------------------* * LS Configuration Converter ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index d1f0fe4bca2b805fb03721aae9767df554c983ee..db5c99ab7052e03e4c3d9cc1a82a78e9b614b631 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -580,11 +580,15 @@ typedef struct ivas_binaural_rendering_conv_module_struct typedef struct EFAP_VERTEX { - float azi; /* azimuth of the loudspeaker */ - float ele; /* elevation of the loudspeaker */ - float pos[3]; /* [x y z] cartesian coordinate vector */ - int16_t idx; /* integer, that corresponds to the first index for the LS in the 1D output */ - int16_t isNaN; /* used to indicate if the vertex is a virtual speaker */ + float azi; /* azimuth of the loudspeaker */ + float ele; /* elevation of the loudspeaker */ + float pos[3]; /* [x y z] cartesian coordinate vector */ + int16_t idx; /* integer, that corresponds to the first index for the LS in the 1D output */ +#ifdef FIX_1050_EFAP_ALLOC + bool isNaN; /* used to indicate if the vertex is a virtual speaker */ +#else + int16_t isNaN; /* used to indicate if the vertex is a virtual speaker */ +#endif EFAP_VTX_DMX_TYPE dmxType; /* virtual speaker downmix type */ } EFAP_VERTEX; @@ -599,8 +603,12 @@ typedef struct EFAP_VERTEX_DATA typedef struct EFAP_POLYSET { - int16_t chan[EFAP_MAX_CHAN_NUM]; /* An array indicating the loudspeaker index of the polygon vertices */ - int16_t isNaN[EFAP_MAX_CHAN_NUM]; /* Indicates if one of the vertices isNaN */ + int16_t chan[EFAP_MAX_CHAN_NUM]; /* An array indicating the loudspeaker index of the polygon vertices */ +#ifdef FIX_1050_EFAP_ALLOC + bool isNaN[EFAP_MAX_CHAN_NUM]; /* Indicates if one of the vertices isNaN */ +#else + int16_t isNaN[EFAP_MAX_CHAN_NUM]; /* Indicates if one of the vertices isNaN */ +#endif int16_t numChan; /* An integer between 0 and EFAP_MAX_CHAN_NUM corresponding to the number of vertices of the polygon */ float polyAzi[EFAP_MAX_CHAN_NUM]; /* An array (same length as "chan"), with the azimuth of the channels */ float polyEle[EFAP_MAX_CHAN_NUM]; /* An array (same length as "chan"), with the elevation of the channels */ @@ -615,10 +623,18 @@ typedef struct EFAP_LS_TRIANGLE typedef struct EFAP_POLYSET_DATA { +#ifdef FIX_1050_EFAP_ALLOC + EFAP_POLYSET *polysetArray; /* Array of polygons */ +#else EFAP_POLYSET polysetArray[EFAP_MAX_POLY_SET]; /* Array of polygons */ - int16_t numPoly; /* Number of polygons */ +#endif + int16_t numPoly; /* Number of polygons */ +#ifdef FIX_1050_EFAP_ALLOC + EFAP_LS_TRIANGLE *triArray; /* Array of triangles */ +#else EFAP_LS_TRIANGLE triArray[EFAP_MAX_POLY_SET]; /* Array of triangles */ - int16_t numTri; /* Number of triangles */ +#endif + int16_t numTri; /* Number of triangles */ } EFAP_POLYSET_DATA; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index b99bf9a93ad001bcbf97920ddb4c0a904b762ce6..087c86118eb79a42c641ef313e3447fefa27dfcc 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -4393,6 +4393,10 @@ int16_t IVAS_REND_GetRenderConfig( hRCout->roomAcoustics.use_er = hRCin->roomAcoustics.use_er; hRCout->roomAcoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity; +#ifdef FIX_1053_REVERB_RECONFIGURATION + mvr2r( hRCin->distAtt, hRCout->distAtt, 3 ); +#endif + return IVAS_ERR_OK; } @@ -4439,6 +4443,9 @@ int16_t IVAS_REND_FeedRenderConfig( mvr2r( renderConfig.roomAcoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.roomAcoustics.pAcoustic_dsr, hRenderConfig->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX ); mvr2r( renderConfig.directivity, hRenderConfig->directivity, 3 * MAX_NUM_OBJECTS ); +#ifdef FIX_1053_REVERB_RECONFIGURATION + mvr2r( renderConfig.distAtt, hRenderConfig->distAtt, 3 ); +#endif hRenderConfig->roomAcoustics.use_er = 0; if ( renderConfig.roomAcoustics.use_er == 1 ) @@ -4468,16 +4475,13 @@ int16_t IVAS_REND_FeedRenderConfig( return error; } } - #ifdef SPLIT_REND_WITH_HEAD_ROT if ( pIsmInput->crendWrapper != NULL && pIsmInput->crendWrapper->hCrend[0] != NULL ) -#else - if ( pIsmInput->crendWrapper != NULL && pIsmInput->crendWrapper->hCrend != NULL ) -#endif { -#ifdef SPLIT_REND_WITH_HEAD_ROT if ( ( error = ivas_reverb_open( &pIsmInput->crendWrapper->hCrend[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pIsmInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) #else + if ( pIsmInput->crendWrapper != NULL && pIsmInput->crendWrapper->hCrend != NULL ) + { if ( ( error = ivas_reverb_open( &pIsmInput->crendWrapper->hCrend->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pIsmInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) #endif { diff --git a/lib_util/aeid_file_reader.c b/lib_util/aeid_file_reader.c new file mode 100644 index 0000000000000000000000000000000000000000..737c71f0c8934c3cc27d62f98818ce6465855d6d --- /dev/null +++ b/lib_util/aeid_file_reader.c @@ -0,0 +1,187 @@ +/****************************************************************************************************** + + (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. + +*******************************************************************************************************/ + +#include "aeid_file_reader.h" +#ifdef FIX_1053_REVERB_RECONFIGURATION +#include "ivas_error_utils.h" +#include +#include + +struct aeidFileReader +{ + FILE *aeidFile; + char *file_path; +}; + + +/*-----------------------------------------------------------------------* + * aeidFileReader_open() + * + * Allocate and initialize rotation handle + *-----------------------------------------------------------------------*/ + +ivas_error aeidFileReader_open( + char *aeidFilePath, /* i : aeid file name */ + aeidFileReader **aeidReader /* o : aeidFileReader handle */ +) +{ + aeidFileReader *self; + FILE *aeidFile; + + /* Open trajectory file */ + if ( strlen( aeidFilePath ) < 1 ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + aeidFile = fopen( aeidFilePath, "r" ); + + if ( !aeidFile ) + { + return IVAS_ERR_FAILED_FILE_OPEN; + } + + self = calloc( sizeof( aeidFileReader ), 1 ); + self->aeidFile = aeidFile; + self->file_path = calloc( sizeof( char ), strlen( aeidFilePath ) + 1 ); + strcpy( self->file_path, aeidFilePath ); + + *aeidReader = self; + + return IVAS_ERR_OK; +} + + +/*-----------------------------------------------------------------------* + * aeidFileReading() + * + * Read values from the aeid file + *-----------------------------------------------------------------------*/ + +ivas_error aeidFileReading( + aeidFileReader *aeidReader, /* i : aeidFileReader handle */ + uint16_t *count, /* o : number of sequences */ + uint16_t **pID, /* o : acoustic environment ID data */ + uint16_t **pValidity /* o : duration data */ +) +{ + int32_t id; + int32_t duration; + uint16_t k = 0; + + while ( !feof( aeidReader->aeidFile ) ) + { + if ( fscanf( aeidReader->aeidFile, "%d %d", &id, &duration ) == 2 ) + { + k++; + } + else + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_PARSE, "Error while parsing acoustic environment sequence" ); + } + } + + if ( k == 0 ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_PARSE, "No acoustic environment" ); + } + + if ( NULL == ( *pID = malloc( sizeof( uint16_t ) * k ) ) || + NULL == ( *pValidity = malloc( sizeof( uint16_t ) * k ) ) ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Unable to allocate memory for acoustic environment sequence" ); + } + + *count = k; + + k = 0; + + fseek( aeidReader->aeidFile, 0, SEEK_SET ); + + while ( !feof( aeidReader->aeidFile ) ) + { + if ( fscanf( aeidReader->aeidFile, "%d %d", &id, &duration ) == 2 ) + { + ( *pID )[k] = (uint16_t) id; + ( *pValidity )[k] = (uint16_t) duration; + k++; + } + else + { + return IVAS_ERROR( IVAS_ERR_FAILED_FILE_PARSE, "Error while parsing acoustic environment sequence" ); + } + } + + return IVAS_ERR_OK; +} + +/*-----------------------------------------------------------------------* + * aeidFileReader_close() + * + * Deallocates memory for the aeid handle + *-----------------------------------------------------------------------*/ + +void aeidFileReader_close( + aeidFileReader **aeidReader /* i/o: aeidFileReader handle */ +) +{ + if ( aeidReader == NULL || *aeidReader == NULL ) + { + return; + } + + fclose( ( *aeidReader )->aeidFile ); + free( ( *aeidReader )->file_path ); + free( *aeidReader ); + *aeidReader = NULL; + + return; +} + +/*-----------------------------------------------------------------------* + * aeidFileReader_getFilePath() + * + * + *-----------------------------------------------------------------------*/ + +const char *aeidFileReader_getFilePath( + aeidFileReader *aeidReader /* i : aeidFileReader handle */ +) +{ + if ( aeidReader == NULL ) + { + return NULL; + } + + return aeidReader->file_path; +} +#endif diff --git a/lib_util/aeid_file_reader.h b/lib_util/aeid_file_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..2e7c3209447f85bc13ae7db77f335c9efd6eebc0 --- /dev/null +++ b/lib_util/aeid_file_reader.h @@ -0,0 +1,89 @@ +/****************************************************************************************************** + + (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. + +*******************************************************************************************************/ + +#ifndef IVAS_AEID_FILE_READER_H +#define IVAS_AEID_FILE_READER_H + +#include "common_api_types.h" + +#ifdef FIX_1053_REVERB_RECONFIGURATION + +struct aeidFileReader; +typedef struct aeidFileReader aeidFileReader; + +/*-----------------------------------------------------------------------* + * aeidFileReader_open() + * + * Allocate and initialize rotation handle + *-----------------------------------------------------------------------*/ + +ivas_error aeidFileReader_open( + char *aeidFilePath, /* i : aeid file name */ + struct aeidFileReader **aeidReader /* o : aeidFileReader handle */ +); + +/*-----------------------------------------------------------------------* + * aeidFileReading() + * + * Read values from the aeid file + *-----------------------------------------------------------------------*/ + +ivas_error aeidFileReading( + aeidFileReader *aeidReader, /* i : aeidFileReader handle */ + uint16_t *count, /* o : number of sequences */ + uint16_t **pID, /* o : acoustic environment ID data */ + uint16_t **pValidity /* o : duration data */ +); + +/*-----------------------------------------------------------------------* + * aeidFileReader_close() + * + * Deallocates memory for the aeid handle + *-----------------------------------------------------------------------*/ + +void aeidFileReader_close( + aeidFileReader **aeidReader /* i/o: aeidFileReader handle */ +); + +/*-----------------------------------------------------------------------* + * aeidFileReader_getFilePath() + * + * + *-----------------------------------------------------------------------*/ + +const char *aeidFileReader_getFilePath( + aeidFileReader *aeidReader /* i : aeidFileReader handle */ +); + +#endif + +#endif /* IVAS_AEID_FILE_READER_H */ diff --git a/readme.txt b/readme.txt index e7e5d432f5b79d58fa6f15574326f3b3f03d95fc..cd5a01d4bed7837f7f29b9856d32858aba6d152b 100644 --- a/readme.txt +++ b/readme.txt @@ -286,7 +286,9 @@ Options: -exof File : External orientation trajectory File for simulation of external orientations -dpid ID : Directivity pattern ID(s) (space-separated list of up to 4 numbers can be specified) for binaural output configuration --aeid ID : Acoustic environment ID (number >= 0) for BINAURAL_ROOM_REVERB output config. +-aeid ID | File : Acoustic environment ID (number > 0) or + alternatively, it can be a text file where each line contains "ID duration" + for BINAURAL_ROOM_REVERB output configuration. -level level : Complexity level, level = (1, 2, 3), will be defined after characterisation. -om File : Coded metadata File for BINAURAL_SPLIT_PCM OutputConf Currently, all values default to level 3 (full functionality). @@ -319,11 +321,9 @@ Options: -exof File : External orientation trajectory File for simulation of external orientations -dpid ID : Directivity pattern ID(s) (space-separated list of up to 4 numbers can be specified) for binaural output configuration --aeid ID : Acoustic environment ID (number > 0) or - a sequence thereof in the format [ID1:duration1,ID2:duration2...] - without braces and spaces, with ':' character separating ID from duration and ',' separating - ID and duration pairs, where duration is specified in frames - for BINAURAL_ROOM_REVERB output configuration. +-aeid ID | File : Acoustic environment ID (number > 0) + alternatively, it can be a text file where each line contains "ID duration" + for BINAURAL_ROOM_REVERB output configuration. -lp Position : Output LFE position. Comma-delimited triplet of [gain, azimuth, elevation] where gain is linear (like --gain, -g) and azimuth, elevation are in degrees. If specified, overrides the default behavior which attempts to map input to output LFE channel(s) diff --git a/scripts/config/ivas_modes.json b/scripts/config/ivas_modes.json index 42b4d2b6a4afa7a244e42ff385987ca0302f00d3..1ba398353649aaac74b63db50106a242fb7c3385 100644 --- a/scripts/config/ivas_modes.json +++ b/scripts/config/ivas_modes.json @@ -622,7 +622,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "FOA", "table_name": "FOA@{table_bitrate} kbps {bandwidth}", @@ -702,7 +703,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "FOA", "table_name": "FOA@{table_bitrate} kbps DTX {bandwidth}", @@ -760,7 +762,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "FOA", "table_name": "FOA@{table_bitrate} kbps RS {bandwidth}", @@ -805,7 +808,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA2", "table_name": "HOA2@{table_bitrate} kbps {bandwidth}", @@ -885,7 +889,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA2", "table_name": "HOA2@{table_bitrate} kbps DTX {bandwidth}", @@ -943,7 +948,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA2", "table_name": "HOA2@{table_bitrate} kbps RS {bandwidth}", @@ -988,7 +994,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA3", "table_name": "HOA3@{table_bitrate} kbps {bandwidth}", @@ -1068,7 +1075,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA3", "table_name": "HOA3@{table_bitrate} kbps DTX {bandwidth}", @@ -1126,7 +1134,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA3", "table_name": "HOA3@{table_bitrate} kbps RS {bandwidth}", @@ -1171,7 +1180,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "FOA", "table_name": "Planar FOA@{table_bitrate} kbps {bandwidth}", @@ -1251,7 +1261,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "FOA", "table_name": "Planar FOA@{table_bitrate} kbps DTX {bandwidth}", @@ -1309,7 +1320,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "FOA", "table_name": "Planar FOA@{table_bitrate} kbps RS {bandwidth}", @@ -1354,7 +1366,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA2", "table_name": "Planar HOA2@{table_bitrate} kbps {bandwidth}", @@ -1434,7 +1447,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA2", "table_name": "Planar HOA2@{table_bitrate} kbps DTX {bandwidth}", @@ -1492,7 +1506,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA2", "table_name": "Planar HOA2@{table_bitrate} kbps RS {bandwidth}", @@ -1537,7 +1552,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA3", "table_name": "Planar HOA3@{table_bitrate} kbps {bandwidth}", @@ -1617,7 +1633,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA3", "table_name": "Planar HOA3@{table_bitrate} kbps DTX {bandwidth}", @@ -1675,7 +1692,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "HOA3", "table_name": "Planar HOA3@{table_bitrate} kbps RS {bandwidth}", @@ -2135,7 +2153,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "5_1", "table_name": "MC 5_1@{table_bitrate} kbps {bandwidth}", @@ -2214,7 +2233,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "7_1", "table_name": "MC 7_1@{table_bitrate} kbps {bandwidth}", @@ -2293,7 +2313,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "5_1_2", "table_name": "MC 5_1_2@{table_bitrate} kbps {bandwidth}", @@ -2372,7 +2393,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "5_1_4", "table_name": "MC 5_1_4@{table_bitrate} kbps {bandwidth}", @@ -2451,7 +2473,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "7_1_4", "table_name": "MC 7_1_4@{table_bitrate} kbps {bandwidth}", @@ -2530,7 +2553,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "5_1", "table_name": "MC 5_1@{table_bitrate} kbps RS {bandwidth}", @@ -2573,7 +2597,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "7_1", "table_name": "MC 7_1@{table_bitrate} kbps RS {bandwidth}", @@ -2616,7 +2641,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "5_1_2", "table_name": "MC 5_1_2@{table_bitrate} kbps RS {bandwidth}", @@ -2659,7 +2685,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "5_1_4", "table_name": "MC 5_1_4@{table_bitrate} kbps RS {bandwidth}", @@ -2702,7 +2729,8 @@ "HOA2": [], "FOA": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "7_1_4", "table_name": "MC 7_1_4@{table_bitrate} kbps RS {bandwidth}", @@ -4124,7 +4152,8 @@ "5_1_2": [], "5_1": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "STEREO", "table_name": "Stereo@{table_bitrate} kbps {bandwidth}", @@ -4191,7 +4220,8 @@ "5_1_2": [], "5_1": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "STEREO", "table_name": "Stereo@{table_bitrate} kbps DTX {bandwidth}", @@ -4257,7 +4287,8 @@ "5_1_2": [], "5_1": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "STEREO", "table_name": "stereo@{table_bitrate} kbps RS {bandwidth}", @@ -4299,7 +4330,8 @@ "5_1_2": [], "5_1": [], "mono": [], - "stereo": [] + "stereo": [], + "EXT": [] }, "in_config": "STEREO", "table_name": "stereo@{table_bitrate} kbps RS DTX {bandwidth}", diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm index caede15c01cab82739000bc773292a60154fa4c8..301a80dfe3552ad54c91785737b5b3fa436f5fca 100644 --- a/scripts/config/self_test.prm +++ b/scripts/config/self_test.prm @@ -1308,18 +1308,6 @@ eid-xor -fer -vbr -bs g192 -ep g192 bit ../scripts/dly_error_profiles/ep_5pct.g1 ../IVAS_cod -mc 5_1 512000 48 testv/stv51MC48c.wav bit ../IVAS_dec -render_config testv/rend_config_renderer.cfg BINAURAL_ROOM_REVERB 16 bit testv/stv51MC48c.wav_MC51_512000_48-16_MC_Config_renderer.tst -// Multi-channel 5_1 at 512 kbps, 48kHz in 48kHz out, BINAURAL_ROOM_REVERB out custom acoustic environment with a sequence (CREND) -//../IVAS_cod -mc 5_1 512000 48 testv/stv51MC48c.wav bit -//../IVAS_dec -render_config testv/rend_config_combined.cfg -aeid 1:200,0:100,2:500 BINAURAL_ROOM_REVERB 48 bit testv/stv51MC48c.wav_MC51_512000_48-48_MC_reverb_sequence.tst - -// Multi-channel 5_1 at 64 kbps, 48kHz in 48kHz out, BINAURAL_ROOM_REVERB out custom acoustic environment with a sequence (FastConv) -//../IVAS_cod -mc 5_1 64000 48 testv/stv51MC48c.wav bit -//../IVAS_dec -render_config testv/rend_config_combined.cfg -aeid 1:500,2:100,0:300 BINAURAL_ROOM_REVERB 48 bit testv/stv51MC48c.wav_MC51_64000_48-48_MC_reverb_sequence.tst - -// Multi-channel 5_1 at 32 kbps, 48kHz in 48kHz out, BINAURAL_ROOM_REVERB out custom acoustic environment with a sequence (ParamBin) -//../IVAS_cod -mc 5_1 32000 48 testv/stv51MC48c.wav bit -//../IVAS_dec -render_config testv/rend_config_combined.cfg -aeid 0:100,2:500,1:200 BINAURAL_ROOM_REVERB 48 bit testv/stv51MC48c.wav_MC51_32000_48-48_MC_reverb_sequence.tst - // Multi-channel 5_1 at 32 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM_REVERB out Config hospital_patientroom ../IVAS_cod -mc 5_1 32000 48 testv/stv51MC48c.wav bit ../IVAS_dec -render_config testv/rend_config_hospital_patientroom.cfg BINAURAL_ROOM_REVERB 48 bit testv/stv51MC48c.wav_MC51_32000_48-48_MC_Config_hospital_patientroom.tst diff --git a/scripts/config/self_test_ltv.prm b/scripts/config/self_test_ltv.prm index f8888c56c11edc3af003b2072e38b2929c408f49..2a66699563e2f906fbe186b5b19d8bd95d9d1b03 100644 --- a/scripts/config/self_test_ltv.prm +++ b/scripts/config/self_test_ltv.prm @@ -1307,18 +1307,6 @@ eid-xor -fer -vbr -bs g192 -ep g192 bit ../scripts/dly_error_profiles/ep_5pct.g1 ../IVAS_cod -mc 5_1 512000 48 testv/ltv48_MC51.wav bit ../IVAS_dec -render_config testv/rend_config_renderer.cfg BINAURAL_ROOM_REVERB 16 bit testv/ltv48_MC51.wav_MC51_512000_48-16_MC_Config_renderer.tst -// Multi-channel 5_1 at 512 kbps, 48kHz in 48kHz out, BINAURAL_ROOM_REVERB out custom acoustic environment with a sequence (CREND) -//../IVAS_cod -mc 5_1 512000 48 testv/ltv51MC48c.wav bit -//../IVAS_dec -render_config testv/rend_config_combined.cfg -aeid 1:500,0:1000,2:500 BINAURAL_ROOM_REVERB 48 bit testv/ltv51MC48c.wav_MC51_512000_48-48_MC_reverb_sequence.tst - -// Multi-channel 5_1 at 64 kbps, 48kHz in 48kHz out, BINAURAL_ROOM_REVERB out custom acoustic environment with a sequence (FastConv) -//../IVAS_cod -mc 5_1 64000 48 testv/ltv51MC48c.wav bit -//../IVAS_dec -render_config testv/rend_config_combined.cfg -aeid 1:500,2:500,0:500 BINAURAL_ROOM_REVERB 48 bit testv/ltv51MC48c.wav_MC51_64000_48-48_MC_reverb_sequence.tst - -// Multi-channel 5_1 at 32 kbps, 48kHz in 48kHz out, BINAURAL_ROOM_REVERB out custom acoustic environment with a sequence (ParamBin) -//../IVAS_cod -mc 5_1 32000 48 testv/ltv51MC48c.wav bit -//../IVAS_dec -render_config testv/rend_config_combined.cfg -aeid 0:1000,2:500,1:500 BINAURAL_ROOM_REVERB 48 bit testv/ltv51MC48c.wav_MC51_32000_48-48_MC_reverb_sequence.tst - // Multi-channel 5_1 at 32 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM_REVERB out Config hospital_patientroom ../IVAS_cod -mc 5_1 32000 48 testv/ltv48_MC51.wav bit ../IVAS_dec -render_config testv/rend_config_hospital_patientroom.cfg BINAURAL_ROOM_REVERB 48 bit testv/ltv48_MC51.wav_MC51_80000_48-48_MC_Config_hospital_patientroom.tst diff --git a/scripts/dly_error_profiles/dly_error_profile_10_smoke_test.dat b/scripts/dly_error_profiles/dly_error_profile_10_smoke_test.dat new file mode 100644 index 0000000000000000000000000000000000000000..fec3e67fbd515f337eb3b5e8f5019e2724e085e7 --- /dev/null +++ b/scripts/dly_error_profiles/dly_error_profile_10_smoke_test.dat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe29117bce3afc93b2c9ffdc38f930a2914dc9376f0386a9fcab95f0d0ee479c +size 188 diff --git a/tests/codec_be_on_mr_nonselection/test_param_file.py b/tests/codec_be_on_mr_nonselection/test_param_file.py index 34e92b715a3a42ca9ee66264d3aba68af588201a..5b0f7f696a278ec51462e4d9a7bfec191e413914 100644 --- a/tests/codec_be_on_mr_nonselection/test_param_file.py +++ b/tests/codec_be_on_mr_nonselection/test_param_file.py @@ -63,6 +63,8 @@ VALID_DEC_OUTPUT_CONF = [ "EXT", ] +PARAM_FILE_ID = "stv" if PARAM_FILE.stem == "self_test" else PARAM_FILE.stem.replace("self_test_", "") + param_file_test_dict = {} with open(PARAM_FILE, "r", encoding="UTF-8") as fp: data = fp.read() @@ -125,6 +127,8 @@ def convert_test_string_to_tag(test_string): @pytest.mark.create_ref @pytest.mark.parametrize("test_tag", list(param_file_test_dict.keys())) +# hack to have stv/ltv/evs in the test name +@pytest.mark.parametrize("param_file_id", [PARAM_FILE_ID]) def test_param_file_tests( record_property, decoder_only, @@ -139,6 +143,7 @@ def test_param_file_tests( rootdir, keep_files, test_tag, + param_file_id, get_mld, get_mld_lim, abs_tol, diff --git a/tests/conftest.py b/tests/conftest.py index 6d9398524300be18eb97379aa5e936d783af28ac..cec06c2061b767601e6de4f85e13e9f377a330e5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -128,6 +128,7 @@ def pytest_addoption(parser): parser.addoption( "--param_file", action="store", + type=Path, help="If specified, use given param file in test_param_file.", ) diff --git a/tests/renderer/test_renderer.py b/tests/renderer/test_renderer.py index ca71224aea36a0f266b91d4226e1eed3be302fdb..0c1ce804b81fd9b2f54bdbed27400df4f30b5520 100644 --- a/tests/renderer/test_renderer.py +++ b/tests/renderer/test_renderer.py @@ -127,6 +127,32 @@ def test_ambisonics_binaural_headrotation( ) +@pytest.mark.skip(reason="Not supported for BASOP code currently") +@pytest.mark.create_ref +@pytest.mark.parametrize("out_fmt", OUTPUT_FORMATS_BINAURAL[2:]) +@pytest.mark.parametrize("in_fmt", INPUT_FORMATS_AMBI) +@pytest.mark.parametrize("frame_size", FRAMING_TO_TEST) +@pytest.mark.parametrize("aeid", ["1", "0"]) +def test_dynamic_acoustic_environment( + record_property, test_info, in_fmt, out_fmt, frame_size, get_mld, get_mld_lim, aeid +): + rend_config_path = TEST_VECTOR_DIR.joinpath(f"rend_config_combined.cfg") + rend_config_path.with_stem(f"rend_config") + + run_renderer( + record_property, + test_info, + in_fmt, + out_fmt, + binary_suffix=EXE_SUFFIX, + frame_size=frame_size, + get_mld=get_mld, + mld_lim=get_mld_lim, + config_file=rend_config_path, + aeid=aeid, + ) + + """ Multichannel """ diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index 9717af0b81fb83eed279793470977f6a3b10c7ec..9bd2b8f4b77f04a89ef89ca8416de2c840815c5d 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -164,6 +164,7 @@ def run_renderer( get_mld=False, mld_lim=0, get_mld_lim=0, + aeid: Optional[str] = None, ) -> str: # prepare arguments and filepaths if trj_file is not None: @@ -196,6 +197,11 @@ def run_renderer( else: framing_name = "" + if aeid is not None: + aeid_name = f"_{aeid}" + else: + aeid_name = "" + if not isinstance(out_fmt, str): out_name = f"{out_fmt.stem}" else: @@ -227,7 +233,7 @@ def run_renderer( in_file = FORMAT_TO_FILE[in_fmt] in_name = in_fmt - out_file_stem = f"{in_name}_to_{out_name}{trj_name}{non_diegetic_pan}{refrot_name}{refvec_name}{refveclev_name}{config_name}{framing_name}{hrtf_file_name}{name_extension}.wav" + out_file_stem = f"{in_name}_to_{out_name}{trj_name}{non_diegetic_pan}{refrot_name}{refvec_name}{refveclev_name}{config_name}{framing_name}{hrtf_file_name}{name_extension}{aeid_name}.wav" out_file = str(output_path_base.joinpath(out_file_stem)) @@ -270,6 +276,9 @@ def run_renderer( if frame_size: cmd.extend(["-fr", str(frame_size.replace("ms", ""))]) + if aeid is not None: + cmd.extend(["-aeid", str(aeid)]) + # Set env variables for UBSAN env = os.environ.copy() if test_info.node.name and "UBSAN_OPTIONS" in env.keys(): diff --git a/tests/test_param_file_ltv.py b/tests/test_param_file_ltv.py deleted file mode 100644 index 4216318d375ad86f148a0d0141e93c1da7d9957c..0000000000000000000000000000000000000000 --- a/tests/test_param_file_ltv.py +++ /dev/null @@ -1,610 +0,0 @@ -__copyright__ = """ -(C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, -Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., -Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, -Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other -contributors to this repository. All Rights Reserved. - -This software is protected by copyright law and by international treaties. -The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, -Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., -Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, -Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other -contributors to this repository retain full ownership rights in their respective contributions in -the software. This notice grants no license of any kind, including but not limited to patent -license, nor is any license granted by implication, estoppel or otherwise. - -Contributors are required to enter into the IVAS codec Public Collaboration agreement before making -contributions. - -This software is provided "AS IS", without any express or implied warranties. The software is in the -development stage. It is intended exclusively for experts who have experience with such software and -solely for the purpose of inspection. All implied warranties of non-infringement, merchantability -and fitness for a particular purpose are hereby disclaimed and excluded. - -Any dispute, controversy or claim arising under or in relation to providing this software shall be -submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in -accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and -the United Nations Convention on Contracts on the International Sales of Goods. -""" - -__doc__ = """ -Execute tests specified via a parameter file. -""" - -import errno -import filecmp -import os -import re -import platform -from pathlib import Path -from subprocess import run - -import pytest - -from tests.cmp_pcm import cmp_pcm -from tests.conftest import DecoderFrontend, EncoderFrontend -from .constants import MLD_PATTERN, MAX_DIFF_PATTERN - -# from tests.testconfig import PARAM_FILE - - -VALID_DEC_OUTPUT_CONF = [ - "MONO", - "STEREO", - "5_1", - "7_1", - "5_1_2", - "5_1_4", - "7_1_4", - "FOA", - "HOA2", - "HOA3", - "BINAURAL", - "BINAURAL_ROOM_IR", - "BINAURAL_ROOM_REVERB", - "EXT", -] - -param_file_test_dict = {} -PARAM_FILE = "scripts/config/self_test_ltv.prm" -with open(PARAM_FILE, "r", encoding="UTF-8") as fp: - data = fp.read() - blocks = data.split("\n\n") - for block in blocks: - tag = "" - enc_opts = "" - dec_opts = "" - sim_opts = "" - eid_opts = "" - for line in block.split("\n"): - if line.startswith("// "): - tag = line[3:] - if line.startswith("../IVAS_cod "): - enc_opts = line[12:] - if line.startswith("../IVAS_dec "): - dec_opts = line[12:] - if line.startswith("networkSimulator_g192 "): - sim_opts = line[22:] - if line.startswith("eid-xor "): - eid_opts = line[8:] - if tag == "" or enc_opts == "" or dec_opts == "": - # no complete parameter set - continue - if tag in param_file_test_dict: - print("non-unique tag found - ignoring new entry") - continue - param_file_test_dict[tag] = (enc_opts, dec_opts, sim_opts, eid_opts) - - -def check_and_makedir(dir_path): - if not os.path.exists(dir_path): - try: - os.makedirs(dir_path) - except OSError as e: - if e.errno != errno.EEXIST: - raise # raises the error again - - -def convert_test_string_to_tag(test_string): - """ - Convert a test string (i.e. the test tag from the parameter file) to a tag string. - Example: - in: "DFT stereo at 13.2 kbps, 16kHz in, 16kHz out, DTX on, random FEC at 5%" - out: "DFT_stereo_at_13_2_kbps_16kHz_in_16kHz_out_DTX_on_random_FEC_at_5_" - """ - # replace certain characters by "_" or remove them - tag_str = "" - replace_chars = " %.-()" - remove_chars = "," - for char in test_string: - if char in replace_chars: - tag_str += "_" - elif char not in remove_chars: - tag_str += char - # replace double underscore by single one - tag_str = "_".join(tag_str.split("__")) - return tag_str - - -@pytest.mark.create_ref -@pytest.mark.parametrize("test_tag", list(param_file_test_dict.keys())) -def test_param_file_tests( - record_property, - dut_encoder_frontend: EncoderFrontend, - dut_decoder_frontend: DecoderFrontend, - ref_encoder_frontend: EncoderFrontend, - ref_decoder_frontend: DecoderFrontend, - reference_path, - dut_base_path, - test_vector_path, - update_ref, - rootdir, - keep_files, - test_tag, - get_mld, - get_mld_lim, - abs_tol, -): - enc_opts, dec_opts, sim_opts, eid_opts = param_file_test_dict[test_tag] - - tag_str = convert_test_string_to_tag(test_tag) - - # evaluate encoder options - enc_split = enc_opts.split() - assert len(enc_split) >= 4 - - # replace "testv/" by test vector path - enc_split = [ - x.replace("testv", f"{test_vector_path}", 1) if x.startswith("testv/") else x - for x in enc_split - ] - - bitstream_file = enc_split.pop() - testv_file = enc_split.pop() - fs = enc_split.pop() - sampling_rate = int(fs) - bitrate = enc_split.pop() - - # bitrate can be a filename: remove leading "../" - if bitrate.startswith("../"): - bitrate = bitrate[3:] - - testv_base = testv_file.split("/")[-1] - if testv_base.endswith(".pcm"): - testv_base = testv_base[:-4] - - assert bitstream_file == "bit" - # in the parameter file, only "bit" is used as bitstream file name - # -> construct bitstream filename - bitstream_file = f"{testv_base}_{tag_str}.192" - - encode( - dut_encoder_frontend, - ref_encoder_frontend, - reference_path, - dut_base_path, - bitrate, - sampling_rate, - testv_file, - bitstream_file, - enc_split, - update_ref, - ) - - # check for networkSimulator_g192 command line - if sim_opts != "": - sim_split = sim_opts.split() - assert len(sim_split) == 6, "networkSimulator_g192 expects 6 parameters" - # [sim_profile, sim_input, sim_output, sim_trace, sim_nFPP, sim_offset] = sim_split - if sim_split[0].startswith(("../")): - # remove leading "../" - sim_split[0] = sim_split[0][3:] - assert sim_split[1] == "bit" - # in the parameter file, only "bit" is used as bitstream file name - # -> re-use bitstream filename from encoder call - sim_split[1] = bitstream_file - assert sim_split[2] == "netsimoutput" - # in the parameter file, only "netsimoutput" is used as netsim output file name - # -> construct netsim output file name - netsim_outfile = f"{testv_base}_{tag_str}.netsimout" - sim_split[2] = netsim_outfile - assert sim_split[3] == "tracefile_sim" - # in the parameter file, only "tracefile_sim" is used as trace output file name - # -> construct trace output file name - netsim_trace_outfile = f"{testv_base}_{tag_str}.netsimtrace" - sim_split[3] = netsim_trace_outfile - simulate( - reference_path, - dut_base_path, - sim_split, - update_ref, - rootdir, - ) - - # check for eid-xor command line - if eid_opts != "": - eid_split = eid_opts.split() - assert len(eid_split) >= 3, "eid-xor expects at least 3 parameters" - # [..., in_bs, err_pat_bs, out_bs] = eid_split - if eid_split[-2].startswith(("../")): - # remove leading "../" - eid_split[-2] = eid_split[-2][3:] - assert eid_split[-3] == "bit" - # in the parameter file, only "bit" is used as the input bitstream file name - # -> re-use bitstream filename from encoder call - eid_split[-3] = bitstream_file - assert eid_split[-1] == "bit_error" - # in the parameter file, only "bit_error" is used as the output bitstream file name - # -> construct netsim output file name - eid_xor_outfile = f"{testv_base}_{tag_str}.fer.192" - eid_split[-1] = eid_xor_outfile - error_insertion( - reference_path, - dut_base_path, - eid_split, - update_ref, - rootdir, - ) - - # evaluate decoder options - dec_split = dec_opts.split() - assert len(dec_split) >= 3 - - # replace "testv/" by test vector path - dec_split = [ - x.replace("testv", f"{test_vector_path}", 1) if x.startswith("testv/") else x - for x in dec_split - ] - # remove leading "../" - dec_split = [x[3:] if x.startswith("../") else x for x in dec_split] - - output_file = dec_split.pop() - bitstream_file_dec = dec_split.pop() - sampling_rate = int(dec_split.pop()) - if len(dec_split) > 0: - output_config = dec_split.pop() - if output_config.upper() not in VALID_DEC_OUTPUT_CONF: - if not output_config.endswith(".txt"): - # must be EVS tests with additional parameters - put param back - dec_split.append(output_config) - output_config = "" - else: - output_config = "" - - output_config_name = output_config - if "/" in output_config: - # the output config is a file - output_config_name = os.path.splitext(os.path.basename(output_config))[0] - - tracefile_dec = "" - if sim_opts != "": - assert bitstream_file_dec == "netsimoutput" - # in the parameter file, only "netsimoutput" is used as bitstream file name - # -> re-use netsim_outfile - bitstream_file = netsim_outfile - tracefile_dec = f"{testv_base}_{tag_str}.dectrace" - elif eid_opts != "": - assert bitstream_file_dec == "bit_error" - # in the parameter file, only "bit_error" is used as bitstream input file name - # -> re-use eid_xor_outfile - bitstream_file = eid_xor_outfile - else: - assert bitstream_file_dec == "bit" - # in the parameter file, only "bit" is used as bitstream file name - # -> re-use bitstream filename from encoder call - - # the output file is not the real output filename - # -> construct output filename - output_file = f"{testv_base}_{tag_str}.dec.wav" - - stdout = decode( - dut_decoder_frontend, - ref_decoder_frontend, - reference_path, - dut_base_path, - output_config, - sampling_rate, - bitstream_file, - output_file, - dec_split, - update_ref, - tracefile_dec, - ) - - if update_ref in [0, 2]: - dut_output_file = f"{dut_base_path}/param_file/dec/{output_file}" - ref_output_file = f"{reference_path}/param_file/dec/{output_file}" - fs = int(sampling_rate) * 1000 - output_differs, reason = cmp_pcm( - dut_output_file, - ref_output_file, - output_config, - fs, - get_mld=get_mld, - mld_lim=get_mld_lim, - abs_tol=abs_tol, - ) - md_out_files = get_expected_md_files(ref_output_file, enc_split, output_config) - - if get_mld: - mld = re.search(MLD_PATTERN, reason).groups(1)[0] - record_property("MLD", mld) - - max_diff = 0 - if output_differs: - search_result = re.search(MAX_DIFF_PATTERN, reason) - max_diff = search_result.groups(1)[0] - record_property("MAXIMUM ABS DIFF", max_diff) - - metadata_differs = False - for md_file in md_out_files: - dut_metadata_file = Path(f"{dut_base_path}/param_file/dec/{md_file}") - ref_metadata_file = Path(f"{reference_path}/param_file/dec/{md_file}") - try: - if not filecmp.cmp(dut_metadata_file, ref_metadata_file): - print("Output metadata differs for file: " + md_file) - metadata_differs = True - except FileNotFoundError: - if not dut_metadata_file.exists(): - print("DUT output metadata missing for expected file: " + md_file) - if not ref_metadata_file.exists(): - print("REF output metadata missing for expected file: " + md_file) - metadata_differs = True - - if output_differs or metadata_differs: - msg = "Difference between ref and dut in " - if output_differs and metadata_differs: - msg += f"output ({reason}) and metadata" - elif output_differs: - msg += f"output only ({reason})" - elif metadata_differs: - msg += "metadata only" - pytest.fail(msg) - - # remove DUT output files when test result is OK (to save disk space) - if not keep_files: - os.remove(f"{dut_base_path}/param_file/enc/{bitstream_file}") - os.remove(f"{dut_base_path}/param_file/dec/{output_file}") - if sim_opts != "": - os.remove(f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192") - os.remove(f"{dut_base_path}/param_file/enc/{netsim_trace_outfile}") - os.remove(f"{dut_base_path}/param_file/dec/{tracefile_dec}") - elif eid_opts != "": - os.remove(f"{dut_base_path}/param_file/enc/{testv_base}_{tag_str}.192") - - -def encode( - dut_encoder_frontend, - ref_encoder_frontend, - reference_path, - dut_base_path, - bitrate, - sampling_rate, - testv_file, - bitstream_file, - enc_opts_list, - update_ref, -): - """ - Call REF and/or DUT encoder. - """ - # directories - dut_out_dir = f"{dut_base_path}/param_file/enc" - ref_out_dir = f"{reference_path}/param_file/enc" - - ref_out_file = f"{ref_out_dir}/{bitstream_file}" - dut_out_file = f"{dut_out_dir}/{bitstream_file}" - - if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): - check_and_makedir(ref_out_dir) - # call REF encoder - ref_encoder_frontend.run( - bitrate, - sampling_rate, - testv_file, - ref_out_file, - add_option_list=enc_opts_list, - ) - - if update_ref in [0, 2]: - check_and_makedir(dut_out_dir) - # call DUT encoder - dut_encoder_frontend.run( - bitrate, - sampling_rate, - testv_file, - dut_out_file, - add_option_list=enc_opts_list, - ) - - -def simulate( - reference_path, - dut_base_path, - sim_opts_list, - update_ref, - rootdir, -): - """ - Call network simulator on REF and/or DUT encoder output. - """ - # directories - dut_out_dir = f"{dut_base_path}/param_file/enc" - ref_out_dir = f"{reference_path}/param_file/enc" - - netsim_infile = sim_opts_list[1] - netsim_outfile = sim_opts_list[2] - netsim_tracefile = sim_opts_list[3] - ref_out_file = f"{ref_out_dir}/{netsim_outfile}" - - if platform.system() == "Windows": - netsim = [ - os.path.join( - rootdir, "scripts", "tools", "Win32", "networkSimulator_g192.exe" - ) - ] - elif platform.system() in ["Linux", "Darwin"]: - netsim = [ - os.path.join( - rootdir, "scripts", "tools", platform.system(), "networkSimulator_g192" - ) - ] - else: - assert False, f"networkSimulator_g192 not available for {platform.system()}" - - if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): - # call network simulator on REF encoder output - cmd_opts = sim_opts_list - cmd_opts[1] = f"{ref_out_dir}/{netsim_infile}" - cmd_opts[2] = f"{ref_out_dir}/{netsim_outfile}" # ref_out_file - cmd_opts[3] = f"{ref_out_dir}/{netsim_tracefile}" - run(netsim + cmd_opts, check=False) - - if update_ref in [0, 2]: - # call network simulator on DUT encoder output - cmd_opts = sim_opts_list - cmd_opts[1] = f"{dut_out_dir}/{netsim_infile}" - cmd_opts[2] = f"{dut_out_dir}/{netsim_outfile}" # dut_out_file - cmd_opts[3] = f"{dut_out_dir}/{netsim_tracefile}" - run(netsim + cmd_opts, check=False) - - -def error_insertion( - reference_path, - dut_base_path, - eid_opts_list, - update_ref, - rootdir, -): - """ - Call eid-xor to insert frame erasure on REF and/or DUT encoder output. - """ - - # directories - dut_out_dir = f"{dut_base_path}/param_file/enc" - ref_out_dir = f"{reference_path}/param_file/enc" - - eid_xor_infile = eid_opts_list[-3] - eid_xor_outfile = eid_opts_list[-1] - ref_out_file = f"{ref_out_dir}/{eid_xor_outfile}" - - if platform.system() == "Windows": - eid_xor = [os.path.join(rootdir, "scripts", "tools", "Win32", "eid-xor.exe")] - elif platform.system() in ["Linux", "Darwin"]: - eid_xor = [ - os.path.join(rootdir, "scripts", "tools", platform.system(), "eid-xor") - ] - else: - assert False, f"eid-xor not available for {platform.system()}" - - if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): - # call eid-xor on REF encoder output - cmd_opts = eid_opts_list - cmd_opts[-3] = f"{ref_out_dir}/{eid_xor_infile}" - cmd_opts[-1] = f"{ref_out_dir}/{eid_xor_outfile}" # ref_out_file - run(eid_xor + cmd_opts, check=False) - - if update_ref in [0, 2]: - # call eid-xor on DUT encoder output - cmd_opts = eid_opts_list - cmd_opts[-3] = f"{dut_out_dir}/{eid_xor_infile}" - cmd_opts[-1] = f"{dut_out_dir}/{eid_xor_outfile}" # ref_out_file - run(eid_xor + cmd_opts, check=False) - - -def decode( - decoder_frontend, - ref_decoder_frontend, - reference_path, - dut_base_path, - output_config, - sampling_rate, - bitstream_file, - output_file, - dec_opts_list, - update_ref, - tracefile_dec, -): - """ - Call REF and/or DUT decoder. - """ - # directories - dut_out_dir = f"{dut_base_path}/param_file/dec" - ref_out_dir = f"{reference_path}/param_file/dec" - - dut_in_file = f"{dut_base_path}/param_file/enc/{bitstream_file}" - ref_in_file = f"{reference_path}/param_file/enc/{bitstream_file}" - dut_out_file = f"{dut_out_dir}/{output_file}" - ref_out_file = f"{ref_out_dir}/{output_file}" - - if update_ref == 1 or update_ref == 2 and not os.path.exists(ref_out_file): - check_and_makedir(ref_out_dir) - add_option_list = dec_opts_list - if tracefile_dec != "": - add_option_list = [ - x if x != "tracefile_dec" else f"{ref_out_dir}/{tracefile_dec}" - for x in dec_opts_list - ] - # call REF decoder - ref_decoder_frontend.run( - output_config, - sampling_rate, - ref_in_file, - ref_out_file, - add_option_list=add_option_list, - ) - - stdout = ref_decoder_frontend.stdout - - if update_ref in [0, 2]: - check_and_makedir(dut_out_dir) - add_option_list = dec_opts_list - if tracefile_dec != "": - add_option_list = [ - x if x != "tracefile_dec" else f"{dut_out_dir}/{tracefile_dec}" - for x in dec_opts_list - ] - # call DUT decoder - decoder_frontend.run( - output_config, - sampling_rate, - dut_in_file, - dut_out_file, - add_option_list=add_option_list, - ) - - stdout = decoder_frontend.stdout - - return stdout - - -def get_expected_md_files(ref_output_file, enc_opts, output_config): - """ - Based on input and output configs, get the filenames of MD files that are expected to being output by the decoder - """ - - if output_config.upper() != "EXT": - return list() - - md_files = list() - enc_opts_upper = [o.upper() for o in enc_opts] - md_filename = Path(ref_output_file).name - - if any([o in enc_opts_upper for o in ["-MASA", "-ISM_MASA"]]): - # always only one MD file, just add ending - md_files.append(md_filename + ".met") - - for ism_opt in ["-ISM", "-ISM_MASA", "-ISM_SBA"]: - # for ism MD, there are three modes that may output MD files - # try to find any of them in the encoder options - md_tmpl = md_filename + ".{}.csv" - try: - idx = enc_opts_upper.index(ism_opt) - ism_num = int(enc_opts[idx + 1]) - md_files.extend([md_tmpl.format(i) for i in range(ism_num)]) - break - except ValueError: - pass - - return md_files diff --git a/tests/testconfig.py b/tests/testconfig.py index 6a60c9de049d4f9444e14afe3cde8eae5bdb571f..77e0f9f59d02b58d43feea3e90436bed4de95bb2 100644 --- a/tests/testconfig.py +++ b/tests/testconfig.py @@ -32,6 +32,8 @@ __doc__ = """ To configure test modules. """ -PARAM_FILE = "scripts/config/self_test.prm" +from pathlib import Path + +PARAM_FILE = Path("scripts/config/self_test.prm") MD5_REF_DICT = dict()