diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0b7192009190e2845d177fb876a41cc406ac080f..1a4448046e775c2f2a9c69ae43cf5760599e6997 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,40 +1,13 @@ variables: - TESTV_DIR: "/usr/local/testv" - LTV_DIR: "/usr/local/ltv" - 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" - 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_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT" - IVAS_PIPELINE_NAME: '' - MANUAL_PIPELINE_TYPE: - description: "Type for the manual pipeline run. Use 'test-be-release' to run BE test against release codec." - value: 'default' - options: - - 'default' - - 'test-be-release' - - 'test-long-self-test' - - 'ivas-conformance' - - 'ivas-conformance-linux' - - 'check-clipping' - - 'test-branch-vs-input-passthrough' - - GIT_CLEAN_FLAGS: -ffdxq - TESTCASE_TIMEOUT_STV_SANITIZERS: 180 - TESTCASE_TIMEOUT_LTV_SANITIZERS: 2400 - BASOP_REFERENCE_BRANCH: "ivas-float-update" - SCALE_FACTOR: "3.162" - - -default: - interruptible: true # Make all jobs by default interruptible + # note: GitLab cannot reference variables defined by users in the include ref:, we need to use a YAML anchor for this + # see https://docs.gitlab.com/ci/yaml/includes/#use-variables-with-include for more information + IVAS_CODEC_CI_REF: &IVAS_CODEC_CI_REF main + +include: + - local: .gitlab-ci/variables.yml + - project: ivas-codec-pc/ivas-codec-ci + ref: *IVAS_CODEC_CI_REF + file: main.yml # This sets when pipelines are created. Jobs have more specific rules to restrict them. workflow: @@ -76,30 +49,12 @@ workflow: variables: IVAS_PIPELINE_NAME: 'Pass-through comparison vs input: $CI_COMMIT_BRANCH' -stages: - - .pre - - maintenance - - prevalidate - - build - - test - - compare - - postvalidate - - deploy - # --------------------------------------------------------------- # Generic script anchors # --------------------------------------------------------------- # These can be used later on to do common tasks -# Prints useful information for every job and should be used at the beginning of each job -.print-common-info: &print-common-info - - | - echo "Printing common information for build job." - echo "Current job is run on commit $CI_COMMIT_SHA" - echo "Commit time was $CI_COMMIT_TIMESTAMP" - date | xargs echo "System time is" - .print-common-info-windows: &print-common-info-windows - | echo "Printing common information for build job." @@ -107,34 +62,18 @@ stages: echo "Commit time was $CI_COMMIT_TIMESTAMP" ("echo 'System time is'", "Get-Date -Format 'dddd dd/MM/yyyy HH:mm K'") | Invoke-Expression -.get-previous-merge-commit-sha: &get-previous-merge-commit-sha - - previous_merge_commit=$(git --no-pager log --merges HEAD~1 -n 1 --pretty=format:%H) - -.mr-fetch-target-branch: &mr-fetch-target-branch - # first delete local target branch to avoid conflicts when branch is cached and there are merge conflicts during fetching - # depending on chaching, the branch may not be there, so prevent failure of this command -> should maybe be done smarter later - - git branch -D $CI_MERGE_REQUEST_TARGET_BRANCH_NAME || true - # needed when depth is lower than the number of commits in the branch - - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME - -.mr-get-target-commit: &mr-get-target-commit # compare to last target branch commit before pipeline was created - - target_commit=$(git log $CI_MERGE_REQUEST_TARGET_BRANCH_NAME -1 --oneline --before=${CI_PIPELINE_CREATED_AT} --format=%H) - -.check-for-testvectors: &check-for-testvectors # check if the testvector files specified in scripts/config/ci_linux*.json are present - - python3 -m pytest ci/test_vectors_available.py - -.disable-debugging-macro: &disable-debugging-macro -# automatically disable #DEBUGGING macro in options.h using /**/-comment - - sed -i.bak -e "s/^[[:space:]]*\(#define[[:space:]]*DEBUGGING\)/\/\*\1\*\//g" lib_com/options.h - -.enable-debugging-macro: &enable-debugging-macro -# automatically enable #DEBUGGING macro in options.h using either /**/-comment or //-comment - - sed -i.bak -e "s/\/\*\ *\(#define\ *DEBUGGING\ *\)\*\//\1/g" lib_com/options.h - - sed -i.bak -e "s/\/\/\ *\(#define\ *DEBUGGING\ *\)/\1/g" lib_com/options.h +.get-basop-float-reference: &get-basop-float-reference + - git clone -b $BASOP_REFERENCE_BRANCH https://forge.3gpp.org/rep/sa4/audio/ivas-basop.git --single-branch --depth 1 ivas-basop + - cd ivas-basop + - git status + - make -j + - cd - + - cp ivas-basop/IVAS_cod ./ + - cp ivas-basop/IVAS_dec ./ .merge-request-comparison-setup-codec: &merge-request-comparison-setup-codec ### build test binaries, initial clean for paranoia reasons - - *disable-debugging-macro + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/disable-debugging-macro.sh - make clean - mkdir build - cd build @@ -151,13 +90,13 @@ stages: - source_branch_commit_sha=$(git rev-parse HEAD) ### checkout version to compare against - - *mr-fetch-target-branch - - *mr-get-target-commit + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/mr-fetch-target-branch.sh + - target_commit="$("${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/mr-get-target-commit.sh)" - git checkout $target_commit - echo "Building reference codec at commit $target_commit" ### build reference binaries - - *disable-debugging-macro + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/disable-debugging-macro.sh - cd build - cmake .. - make -j @@ -179,53 +118,27 @@ stages: - if [ $exit_code -ne 0 ] && [ $non_be_flag != 0 ]; then echo "Non-bitexact cases with non-BE tag encountered"; exit $EXIT_CODE_NON_BE; fi - exit 0 -.update-ltv-repo: &update-ltv-repo - - cd $LTV_DIR - - git pull - - cd - - .update-ltv-repo-win: &update-ltv-repo-win - Push-Location - cd $LTV_DIR_WIN - git pull - Pop-Location -.disable-limiter: &disable-limiter -# automatically enable #define DISABLE_LIMITER in options.h, handling both /**/-comment and //-comment - - sed -i.bak -e "s/\/\*[[:space:]]*\(#define[[:space:]]*DISABLE_LIMITER\)[[:space:]]*\*\//\1/g" ./lib_com/options.h - -.get-commits-behind-count: &get-commits-behind-count - - echo $CI_COMMIT_SHA - - echo $CI_MERGE_REQUEST_TARGET_BRANCH_NAME - - commits_behind_count=$(git rev-list --count $CI_COMMIT_SHA..origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME) - -.check-commits-behind-count-in-compare-jobs: &check-commits-behind-count-in-compare-jobs - - if [ $commits_behind_count -ne 0 ]; then echo "Your branch is not up-to-date with main -> Compare tests will not run as they can contain false negatives this way.\nMain might have changed during your pipeline run. Run 'git merge origin/main' to update."; exit 1; fi - -.copy-ltv-files-to-testv-dir: ©-ltv-files-to-testv-dir - - cp "$LTV_DIR"/*.wav scripts/testv/ - - cp "$LTV_DIR"/*.met scripts/testv/ - - cp "$LTV_DIR"/*.csv scripts/testv/ - .copy-ltv-files-to-testv-dir-win: ©-ltv-files-to-testv-dir-win - cp $LTV_DIR_WIN\*.wav scripts\testv - cp $LTV_DIR_WIN\*.met scripts\testv - cp $LTV_DIR_WIN\*.csv scripts\testv -.activate-Werror-linux: &activate-Werror-linux - - sed -i.bak "s/^# \(CFLAGS += -Werror\)/\1/" Makefile - - sed -i.bak "s/# \(set(CMAKE_C_FLAGS \"\${CMAKE_C_FLAGS} -Werror\")\)/\1/" CMakeLists.txt - .activate-WX-windows: &activate-WX-windows - (Get-Content -Path "CMakeLists.txt") -replace '# \(add_compile_options\("\/WX"\)\)', '$1' | Set-Content -Path "CMakeLists.txt" - Get-ChildItem -Path "Workspace_msvc" -Filter "*.vcxproj" | ForEach-Object { (Get-Content -Path $_.FullName) -replace 'false', 'true' | Set-Content -Path $_.FullName } # to be reused in MR and LTV-scheduled sanitizer test jobs # set CLANG_NUM, SELFTEST_SANITY_TIMEOUT and SELF_TEST_PRM_FILE in before_script section -.sanitizer-selftest-anchor: &sanitizer-selftest-anchor +.sanitizer-selftest-anchor: script: - - *print-common-info - - *copy-ltv-files-to-testv-dir + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/copy-ltv-files-to-testv-dir.sh - make clean - make -j CLANG=$CLANG_NUM - testcase_timeout=$SELFTEST_SANITY_TIMEOUT @@ -248,126 +161,6 @@ stages: - if [ $exit_code20 -ne 0 ] || [ $exit_code10 -ne 0 ] || [ $exit_code5 -ne 0 ]; then exit 1; fi -# --------------------------------------------------------------- -# Job templates -# --------------------------------------------------------------- - -# When designing templates, try not to use too much inheritance and -# if multiple templates and extended on, remember that on conflict, -# latest overwrites the parameter. - -# templates for rules -.rules-basis: - rules: - - if: $MIRROR_ACCESS_TOKEN # Don't run in the mirror update pipeline (only then MIRROR_ACCESS_TOKEN is defined) - when: never - - if: $CI_PIPELINE_SOURCE == 'schedule' # Don't run in any scheduled pipelines by default (use schedule templates below to enable again for certain conditions) - when: never - - if: $CI_PIPELINE_SOURCE == 'trigger' # Don't run triggered pipeline by default - when: never - - if: $MANUAL_PIPELINE_TYPE == 'test-be-release' # Skip all the normal jobs when testing manually against release codec - when: never - - if: $MANUAL_PIPELINE_TYPE == 'test-long-self-test' # Skip all the normal jobs when testing manually against release codec - when: never - - if: $MANUAL_PIPELINE_TYPE == 'ivas-conformance' - when: never - - if: $MANUAL_PIPELINE_TYPE == 'ivas-conformance-linux' - when: never - - if: $MANUAL_PIPELINE_TYPE == 'check-clipping' - when: never - - if: $MANUAL_PIPELINE_TYPE == 'test-branch-vs-input-passthrough' - when: never - - when: on_success - -.rules-merge-request: - extends: .rules-basis - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" # only have MR pipelines for MRs to main - - if: $CI_PIPELINE_SOURCE == 'push' - when: never - -.rules-main-push: - extends: .rules-basis - rules: - - if: $CI_PIPELINE_SOURCE == 'push' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - -.rules-main-scheduled: - extends: .rules-basis - rules: - - if: $CI_PIPELINE_SOURCE == 'schedule' && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - -# templates to define stages and platforms -.test-job-linux: - tags: - - ivas-linux - -.build-job-linux: - stage: build - timeout: "4 minutes" - needs: [] - tags: - - ivas-linux - -.build-job-windows: - stage: build - needs: [] - timeout: "4 minutes" - tags: - - ivas-windows - -# template for test jobs on linux that need the TESTV_DIR -.test-job-linux-needs-testv-dir: - extends: .test-job-linux - before_script: - - if [ ! -d "$TESTV_DIR" ]; then mkdir -p $TESTV_DIR; fi - - python3 scripts/prepare_combined_format_inputs.py - - cp -r scripts/testv/* $TESTV_DIR/ - -.sanitizer-selftest-on-mr: - stage: test - extends: - - .test-job-linux-needs-testv-dir - - .rules-merge-request - artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" - expire_in: 1 week - when: always - paths: - - report-junit-20ms.xml - - report-junit-10ms.xml - - report-junit-5ms.xml - - report-20ms.html - - report-10ms.html - - report-5ms.html - expose_as: "Sanitizer selftest results" - reports: - junit: - - report-junit-20ms.xml - - report-junit-10ms.xml - - report-junit-5ms.xml - -.sanitizer-selftest-ltv: - stage: test - extends: - - .test-job-linux-needs-testv-dir - artifacts: - name: "$CI_JOB_NAME--sha-$CI_COMMIT_SHORT_SHA--results" - expire_in: 2 week - when: always - paths: - - report-junit-20ms.xml - - report-junit-10ms.xml - - report-junit-5ms.xml - - report-20ms.html - - report-10ms.html - - report-5ms.html - expose_as: "Sanitizer selftest results" - reports: - junit: - - report-junit-20ms.xml - - report-junit-10ms.xml - - report-junit-5ms.xml - # --------------------------------------------------------------- # .pre jobs for setting up things # --------------------------------------------------------------- @@ -396,70 +189,69 @@ uninterruptible: branch-is-up-to-date-with-main-pre: extends: - - .rules-merge-request + - .rules-merge-request-to-main + - .job-linux stage: prevalidate needs: [] - tags: - - ivas-linux script: - - *get-commits-behind-count - - echo $commits_behind_count - - if [ $commits_behind_count -eq 0 ]; then exit 0; else echo "Your branch is behind main, run 'git merge origin/main' to update."; exit 1; fi; + - | + commits_behind_count="$(bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/get-commits-behind-count.sh)" + echo "Commits behind: $commits_behind_count" + if [ "$commits_behind_count" -ne 0 ]; then + echo "Your branch is behind main, run 'git merge origin/main' to update." + exit 1 + fi check-self-test-names-pre: extends: - - .rules-merge-request + - .rules-merge-request-to-main + - .job-linux stage: prevalidate needs: [] - tags: - - ivas-linux script: - python3 ci/check_self_test_names.py scripts/config/self_test.prm 135 check-no-duplicates-in-self-tests: extends: - - .rules-merge-request + - .rules-merge-request-to-main + - .job-linux stage: prevalidate needs: [] - tags: - - ivas-linux script: - python3 ci/find_duplicates_in_prm_files.py branch-is-up-to-date-with-main-post: extends: - - .rules-merge-request + - .rules-merge-request-to-main + - .job-linux stage: postvalidate - tags: - - ivas-linux script: - - *get-commits-behind-count - - echo $commits_behind_count - - if [ $commits_behind_count -eq 0 ]; then exit 0; else echo "Your branch is behind main, possibly main changed during your pipeline run, run 'git merge origin/main' to update." exit 1; fi; + - | + commits_behind_count="$(bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/get-commits-behind-count.sh)" + echo "Commits behind: $commits_behind_count" + if [ "$commits_behind_count" -ne 0 ]; then + echo "Your branch is behind main, possibly main changed during your pipeline run, run 'git merge origin/main' to update." + exit 1 + fi .basop-ci-branch-compat-template: extends: - .test-job-linux - rules: - - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "basop-ci-branch" - changes: - - tests/**/* - - scripts/**/* - - if: $CI_PIPELINE_SOURCE == 'push' - when: never + - .rules-merge-request-to-basop-ci-branch tags: - - ivas-linux-fast + - ivas-linux before_script: - - git clone -b $BASOP_REFERENCE_BRANCH https://forge.3gpp.org/rep/sa4/audio/ivas-basop.git --single-branch - - make -j -C ivas-basop - - python3 ci/remove_unsupported_testcases.py $PARAM_FILE + - !reference [.job-linux, before_script] + - python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm - python3 tests/create_short_testvectors.py - - *update-ltv-repo - - *copy-ltv-files-to-testv-dir + - python3 scripts/prepare_combined_format_inputs.py - - python3 -m pytest tests/codec_be_on_mr_nonselection --param_file $PARAM_FILE --update_ref 1 --ref_encoder_path ivas-basop/IVAS_cod --ref_decoder_path ivas-basop/IVAS_dec --html=report.html --self-contained-html --junit-xml=report-junit.xml || true - - zero_errors=$(cat report-junit.xml | grep -c 'errors="0"') || true - - if [ $zero_errors != 1 ]; then echo "Run errors encountered with $PARAM_FILE !"; exit $EXIT_CODE_FAIL; fi + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/copy-ltv-files-to-testv-dir.sh + + - *get-basop-float-reference + + - python3 -m pytest $TEST_SUITE $PYTEST_ARGS --update_ref 1 --ref_encoder_path IVAS_cod --ref_decoder_path IVAS_dec --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout=$TESTCASE_TIMEOUT artifacts: name: "$CI_JOB_NAME--sha-$CI_COMMIT_SHORT_SHA--results" @@ -474,35 +266,54 @@ branch-is-up-to-date-with-main-post: junit: - report-junit.xml -check-compatibility-with-basop-reference-branch-stv: +basop-ref-compat-stv: + extends: + - .basop-ci-branch-compat-template + variables: + TEST_SUITE: "$SHORT_TEST_SUITE tests/renderer" + TESTCASE_TIMEOUT: $TESTCASE_TIMEOUT_STV_SANITIZERS + script: + - exit 0 + +basop-ref-compat-ltv: extends: - .basop-ci-branch-compat-template + tags: + - ivas-linux-fast variables: - PARAM_FILE: scripts/config/self_test.prm + TEST_SUITE: $LONG_TEST_SUITE + TESTCASE_TIMEOUT: $TESTCASE_TIMEOUT_LTV_SANITIZERS script: - exit 0 -check-compatibility-with-basop-reference-branch-ltv: +basop-ref-compat-encoder-stv: extends: - .basop-ci-branch-compat-template variables: - PARAM_FILE: scripts/config/self_test_ltv.prm + TEST_SUITE: $SHORT_TEST_SUITE_ENCODER + TESTCASE_TIMEOUT: $TESTCASE_TIMEOUT_STV_SANITIZERS script: - exit 0 -check-compatibility-with-basop-reference-branch-encoder-stv: +basop-ref-compat-encoder-ltv: extends: - .basop-ci-branch-compat-template + tags: + - ivas-linux-fast variables: - PARAM_FILE: scripts/config/self_test_basop_encoder.prm + TEST_SUITE: $LONG_TEST_SUITE_ENCODER + TESTCASE_TIMEOUT: $TESTCASE_TIMEOUT_LTV_SANITIZERS script: - exit 0 -check-compatibility-with-basop-reference-branch-encoder-ltv: +basop-ref-compat-encoder-dmx-comp: extends: - .basop-ci-branch-compat-template variables: - PARAM_FILE: scripts/config/self_test_ltv_basop_encoder.prm + TEST_SUITE: $SHORT_TEST_SUITE_ENCODER + # USING PYTEST_ADDOPTS env var did not work for some reason when testing locally - maybe because this is a custom option + PYTEST_ARGS: "--compare_enc_dmx" + TESTCASE_TIMEOUT: $TESTCASE_TIMEOUT_STV_SANITIZERS script: - exit 0 @@ -515,8 +326,8 @@ build-codec-linux-make: - .build-job-linux - .rules-basis script: - - *print-common-info - - *activate-Werror-linux + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/activate-Werror-linux.sh - make -j build-codec-linux-cmake: @@ -524,8 +335,8 @@ build-codec-linux-cmake: - .build-job-linux - .rules-basis script: - - *print-common-info - - *activate-Werror-linux + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/activate-Werror-linux.sh - mkdir build - cd build - cmake .. @@ -538,9 +349,16 @@ build-codec-instrumented-linux: - .rules-basis timeout: "10 minutes" script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - ./scripts/prepare_instrumentation.sh - make -j -C scripts/c-code_instrument + artifacts: + when: always + access: all + expire_in: "30 days" + paths: + - wmc_tool_output.txt + # make sure that the codec builds with msan, asan and usan build-codec-sanitizers-linux: @@ -548,8 +366,8 @@ build-codec-sanitizers-linux: - .build-job-linux - .rules-basis script: - - *print-common-info - - *activate-Werror-linux + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/activate-Werror-linux.sh - bash ci/build_codec_sanitizers_linux.sh build-codec-windows-cmake: @@ -579,17 +397,27 @@ build-codec-windows-msbuild: codec-smoke-test: extends: - .test-job-linux-needs-testv-dir - - .rules-merge-request + - .rules-merge-request-to-basop-ci-branch-or-main timeout: "20 minutes" tags: - ivas-linux-fast stage: test needs: ["build-codec-linux-cmake", "build-codec-linux-make", "build-codec-instrumented-linux", "build-codec-sanitizers-linux"] script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh # LTV update needed as ltv ISM metadata files are used - - *update-ltv-repo - - bash ci/smoke_test.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh + + # for MRs to basop-ci-branch, we want to test with the BASOP float reference build + # per default, the smoke test builds the current repo again with WMOPS activated to catch unbalanced instrumentation macros + - if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" = "basop-ci-branch" ]; then + - python3 scripts/smoketest-basop-filter.py scripts/config/ivas_modes.json --inline + - *get-basop-float-reference + - bash ci/smoke_test.sh coverage + - else + - bash ci/smoke_test.sh + - fi + ### analyze for failures - 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 @@ -598,7 +426,7 @@ codec-smoke-test: - 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: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always paths: @@ -611,49 +439,52 @@ codec-smoke-test: codec-msan: extends: - .sanitizer-selftest-on-mr + - .sanitizer-selftest-anchor tags: - ivas-linux-fast before_script: + - !reference [.job-linux, before_script] - CLANG_NUM=1 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS - SELF_TEST_PRM_FILE="scripts/config/self_test.prm" - USE_LTV="" - <<: *sanitizer-selftest-anchor # code selftest testvectors with address-sanitizer binaries codec-asan: extends: - .sanitizer-selftest-on-mr + - .sanitizer-selftest-anchor before_script: + - !reference [.job-linux, before_script] - CLANG_NUM=2 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS - SELF_TEST_PRM_FILE="scripts/config/self_test.prm" - USE_LTV="" - <<: *sanitizer-selftest-anchor # code selftest testvectors with undefined-behaviour-sanitizer binaries codec-usan: extends: - .sanitizer-selftest-on-mr + - .sanitizer-selftest-anchor tags: - ivas-linux-fast before_script: + - !reference [.job-linux, before_script] - CLANG_NUM=3 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_STV_SANITIZERS - SELF_TEST_PRM_FILE="scripts/config/self_test.prm" - USE_LTV="" - <<: *sanitizer-selftest-anchor # compare bit-exactness between 5ms and 20 on the branch pytest-compare-20ms-and-5ms-rendering: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main stage: test needs: ["build-codec-linux-cmake", "build-codec-linux-make", "build-codec-instrumented-linux", "build-codec-sanitizers-linux"] script: - - *print-common-info - - *disable-limiter + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/disable-limiter.sh - make clean - make -j ### prepare pytest @@ -677,7 +508,7 @@ pytest-compare-20ms-and-5ms-rendering: - if [ $exit_code10 -ne 0 ]; then echo "Non-bitexact cases encountered with 10ms rendering!"; exit_code=1; fi - if [ $exit_code -ne 0 ]; then exit $EXIT_CODE_FAIL; fi artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always expose_as: "pytest 5ms and 10ms vs 20ms results" @@ -695,7 +526,7 @@ pytest-compare-20ms-and-5ms-rendering: renderer-smoke-test: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main needs: ["build-codec-linux-make"] stage: test script: @@ -713,95 +544,82 @@ renderer-smoke-test: junit: - report-junit.xml -# test renderer executable with cmake + asan -renderer-asan: +.renderer-sanitizer-job: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main needs: ["build-codec-linux-cmake"] stage: test - script: - - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=asan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - - cmake --build cmake-build -- -j - - testcase_timeout=180 - - python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py --testcase_timeout=$testcase_timeout - + timeout: "1 hour" artifacts: name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always paths: - report-junit.xml - expose_as: "renderer asan pytest results" + - report.html reports: junit: - report-junit.xml + before_script: + - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=$SANITIZER_BUILD_STRING -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true + - cmake --build cmake-build -- -j + # rename files to fit naming convention + # en- and decoder needed because of split rendering testcases + - mv IVAS_cod IVAS_cod_ref + - mv IVAS_dec IVAS_dec_ref + - mv IVAS_rend IVAS_rend_ref + - mv ISAR_post_rend ISAR_post_rend_ref + - testcase_timeout=180 + +# test renderer executable with cmake + asan +renderer-asan: + extends: + - .renderer-sanitizer-job + variables: + SANITIZER_BUILD_STRING: "asan" + script: + - python3 -m pytest -q --tb=no -n auto --html=report.html --self-contained-html --junit-xml=report-junit.xml tests/renderer/test_renderer.py tests/split_rendering/test_split_rendering.py --create_ref --testcase_timeout=$testcase_timeout + artifacts: + expose_as: "renderer asan result" + # test renderer executable with cmake + msan renderer-msan: extends: - - .test-job-linux - - .rules-merge-request - needs: ["build-codec-linux-cmake"] - stage: test + - .renderer-sanitizer-job + variables: + SANITIZER_BUILD_STRING: "msan" script: - - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=msan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - - cmake --build cmake-build -- -j - - testcase_timeout=180 - - python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py --testcase_timeout=$testcase_timeout - + - python3 -m pytest -q --tb=no -n auto --html=report.html --self-contained-html --junit-xml=report-junit.xml tests/renderer/test_renderer.py tests/split_rendering/test_split_rendering.py --create_ref --testcase_timeout=$testcase_timeout artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" - expire_in: 1 week - when: always - paths: - - report-junit.xml - expose_as: "renderer msan pytest results" - reports: - junit: - - report-junit.xml + expose_as: "renderer msan result" + # test renderer executable with cmake + usan renderer-usan: extends: - - .test-job-linux - - .rules-merge-request - needs: ["build-codec-linux-cmake"] - stage: test + - .renderer-sanitizer-job + variables: + SANITIZER_BUILD_STRING: "usan" script: - - cmake -B cmake-build -G "Unix Makefiles" -DCLANG=usan -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - - cmake --build cmake-build -- -j - - testcase_timeout=180 - - UBSAN_OPTIONS=suppressions=scripts/ubsan.supp,report_error_type=1,log_path=usan_log_catchall python3 -m pytest -q -n auto -rA --junit-xml=report-junit.xml tests/renderer/test_renderer.py --testcase_timeout=$testcase_timeout - - grep_exit_code=0 - - touch usan_log_empty # Creates an empty file, this is to avoid "grep: usan_log_*: No such file or directory" in case no USAN failures are reported from pytest - - grep UndefinedBehaviorSanitizer usan_log_* || grep_exit_code=$? - - if [ $grep_exit_code != 1 ] ; then echo "Run errors in test_renderer.py with Clang undefined-behavior-sanitizer"; exit 1; fi - + - UBSAN_OPTIONS=suppressions=scripts/ubsan.supp,report_error_type=1 python3 -m pytest -q --tb=no -n auto --html=report.html --self-contained-html --junit-xml=report-junit.xml tests/renderer/test_renderer.py tests/split_rendering/test_split_rendering.py --create_ref --testcase_timeout=$testcase_timeout artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" - expire_in: 1 week - when: always - paths: - - report-junit.xml - expose_as: "renderer usan pytest results" - reports: - junit: - - report-junit.xml + expose_as: "renderer usan result" + # compare renderer bitexactness between target and source branch renderer-pytest-on-merge-request: extends: - .test-job-linux-needs-testv-dir - - .rules-merge-request + - .rules-merge-request-to-main needs: ["build-codec-linux-make"] # TODO: set reasonable timeout, will most likely take less timeout: "20 minutes" stage: compare script: - - *print-common-info - - *get-commits-behind-count - - *check-commits-behind-count-in-compare-jobs + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/float/check-commits-behind-count-in-compare-jobs.sh - *merge-request-comparison-setup-codec # some helper variables - "|| true" to prevent failures from grep not finding anything @@ -845,7 +663,7 @@ renderer-pytest-on-merge-request: split-rendering-smoke-test: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main needs: ["build-codec-linux-make"] stage: test script: @@ -866,27 +684,27 @@ split-rendering-smoke-test: lc3-wrapper-unit-test: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main needs: ["build-codec-linux-cmake"] stage: test script: - cmake -B cmake-build -G "Unix Makefiles" -DCOPY_EXECUTABLES_FROM_BUILD_DIR=true - cmake --build cmake-build -- -j - - scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test + - scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test # compare split-rendering bitexactness between target and source branch split-rendering-pytest-on-merge-request: extends: - .test-job-linux-needs-testv-dir - - .rules-merge-request + - .rules-merge-request-to-main needs: ["build-codec-linux-make"] # TODO: set reasonable timeout, will most likely take less timeout: "30 minutes" stage: compare script: - - *print-common-info - - *get-commits-behind-count - - *check-commits-behind-count-in-compare-jobs + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - commits_behind_count="$(bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/get-commits-behind-count.sh)" + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/float/check-commits-behind-count-in-compare-jobs.sh # some helper variables - "|| true" to prevent failures from grep not finding anything # write to temporary file as workaround for failures observed with piping echo @@ -897,8 +715,8 @@ split-rendering-pytest-on-merge-request: # store the current commit hash - source_branch_commit_sha=$(git rev-parse HEAD) - - *mr-fetch-target-branch - - *mr-get-target-commit + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/mr-fetch-target-branch.sh + - target_commit="$("${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/mr-get-target-commit.sh)" - git checkout $target_commit - echo "Building reference codec at commit $target_commit" @@ -907,6 +725,7 @@ split-rendering-pytest-on-merge-request: - mv IVAS_cod IVAS_cod_ref - mv IVAS_dec IVAS_dec_ref - mv IVAS_rend IVAS_rend_ref + - mv ISAR_post_rend ISAR_post_rend_ref ### If ref_using_main is not set, checkout the source branch to use scripts and input from there - if [ $ref_using_main == 0 ]; then git restore lib_com/options.h; fi # Revert changes back before checking out another branch to avoid conflicts @@ -950,14 +769,20 @@ split-rendering-pytest-on-merge-request: ivas-pytest-on-merge-request: extends: - .test-job-linux-needs-testv-dir - - .rules-merge-request + - .rules-merge-request-to-main stage: compare needs: ["build-codec-linux-cmake", "codec-smoke-test"] timeout: "14 minutes" - script: - - *print-common-info - - *get-commits-behind-count - - *check-commits-behind-count-in-compare-jobs + parallel: + matrix: + # note: keep in sync with list in $TESTS_DIR_CODEC_BE_ON_MR + - PYTEST_SCRIPT: + - test_param_file.py + - test_sba.py + script: + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - commits_behind_count="$(bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/get-commits-behind-count.sh)" + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/float/check-commits-behind-count-in-compare-jobs.sh - *merge-request-comparison-setup-codec # some helper variables - "|| true" to prevent failures from grep not finding anything @@ -971,7 +796,7 @@ ivas-pytest-on-merge-request: ### prepare pytest # create references - - python3 -m pytest $TESTS_DIR_CODEC_BE_ON_MR -v --update_ref 1 + - python3 -m pytest "$TESTS_DIR_CODEC_BE_ON_MR"/"$PYTEST_SCRIPT" -v --update_ref 1 ### Run test using branch scripts and input - if [ $ref_using_main == 1 ]; then git checkout $source_branch_commit_sha; fi @@ -979,7 +804,7 @@ ivas-pytest-on-merge-request: ### run pytest - exit_code=0 - testcase_timeout=60 - - python3 -m pytest $TESTS_DIR_CODEC_BE_ON_MR -v --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout=$testcase_timeout || exit_code=$? + - python3 -m pytest "$TESTS_DIR_CODEC_BE_ON_MR"/"$PYTEST_SCRIPT" -v --html=report.html --self-contained-html --junit-xml=report-junit.xml --testcase_timeout=$testcase_timeout || exit_code=$? - zero_errors=$(cat report-junit.xml | grep -c 'errors="0"') || true - *merge-request-comparison-check @@ -988,7 +813,7 @@ ivas-pytest-on-merge-request: exit_codes: - 123 artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always paths: @@ -1004,14 +829,14 @@ ivas-pytest-on-merge-request: ivas-interop-on-merge-request: extends: - .test-job-linux-needs-testv-dir - - .rules-merge-request + - .rules-merge-request-to-main stage: test needs: ["build-codec-linux-cmake"] timeout: "10 minutes" script: - - *print-common-info - - *get-commits-behind-count - - *check-commits-behind-count-in-compare-jobs + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - commits_behind_count="$(bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/get-commits-behind-count.sh)" + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/float/check-commits-behind-count-in-compare-jobs.sh - *merge-request-comparison-setup-codec # the next line is dependent on ref-using-main flag in the other tests, but here the flag does not make sense - git checkout $source_branch_commit_sha @@ -1039,7 +864,7 @@ ivas-interop-on-merge-request: exit_codes: - 123 artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always paths: @@ -1053,14 +878,14 @@ ivas-interop-on-merge-request: evs-pytest-on-merge-request: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main stage: compare needs: ["build-codec-linux-cmake", "codec-smoke-test"] timeout: "10 minutes" script: - - *print-common-info - - *get-commits-behind-count - - *check-commits-behind-count-in-compare-jobs + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - commits_behind_count="$(bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/get-commits-behind-count.sh)" + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/float/check-commits-behind-count-in-compare-jobs.sh - *merge-request-comparison-setup-codec # some helper variables - "|| true" to prevent failures from grep not finding anything @@ -1091,7 +916,7 @@ evs-pytest-on-merge-request: exit_codes: - 123 artifacts: - name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + name: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always paths: @@ -1105,12 +930,12 @@ evs-pytest-on-merge-request: voip-be-on-merge-request: extends: - .test-job-linux-needs-testv-dir - - .rules-merge-request + - .rules-merge-request-to-main stage: test needs: ["build-codec-linux-make"] timeout: "10 minutes" script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - make clean - make -j - python3 -m pytest tests/test_be_for_jbm_neutral_dly_profile.py @@ -1118,7 +943,7 @@ voip-be-on-merge-request: clang-format-check: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main variables: ARTIFACT_BASE_NAME: "mr-$CI_MERGE_REQUEST_IID--sha-$CI_COMMIT_SHORT_SHA--formatting-fix" stage: prevalidate @@ -1165,17 +990,15 @@ clang-format-check: check-first-frame-is-sid: extends: - .test-job-linux-needs-testv-dir - - .rules-merge-request - tags: - - ivas-linux + - .rules-merge-request-to-main stage: test needs: ["build-codec-linux-cmake"] script: - - *print-common-info - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh # this rm makes check-for-testvectors only check for the signals we actually need in this test - rm scripts/config/ci_linux_ltv.json scripts/config/ci_linux.json - - *check-for-testvectors + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/check-for-testvectors.sh - bash ci/run-first-frame-is-sid-test.sh artifacts: @@ -1189,10 +1012,10 @@ check-first-frame-is-sid: expose_as: "logs-sidstart" expire_in: "5 days" -.lc3plus-ensure-no-code-changes: +lc3plus-ensure-no-code-changes: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main stage: postvalidate needs: [] timeout: "5 minutes" @@ -1201,18 +1024,18 @@ check-first-frame-is-sid: - ./scripts/lc3plus_lib_setup/get_lc3plus.sh # Ensure git reports no changes - - modified_files=$(git status -s) + - modified_files=$(git status -su lib_lc3plus) - if [[ $modified_files ]]; then printf 'LC3plus codebase was modified!\n\n'"$modified_files"'\n\n'; exit $EXIT_CODE_FAIL; fi check-bitexactness-hrtf-rom-and-file: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main stage: test needs: ["build-codec-linux-cmake"] timeout: "5 minutes" script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - cmake . - make -j - python3 tests/create_short_testvectors.py --cut_len 1.0 @@ -1229,12 +1052,12 @@ check-bitexactness-hrtf-rom-and-file: check-bitexactness-ext-and-transport-format: extends: - .test-job-linux - - .rules-merge-request + - .rules-merge-request-to-main stage: test needs: ["build-codec-linux-cmake"] timeout: "5 minutes" script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - cmake . - make -j - python3 tests/create_short_testvectors.py --cut_len 1.0 @@ -1256,7 +1079,7 @@ check-bitexactness-ext-and-transport-format: # check bitexactness to EVS windows binaries be-2-evs-windows: extends: - - .rules-merge-request + - .rules-merge-request-to-main tags: - ivas-windows stage: test @@ -1288,7 +1111,7 @@ be-2-evs-linux: needs: ["build-codec-linux-cmake"] timeout: "20 minutes" # To be revisited script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - mkdir build - cd build @@ -1312,9 +1135,9 @@ codec-comparison-on-main-push: needs: ["build-codec-linux-cmake"] timeout: "30 minutes" # To be revisited script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - latest_commit=$(git rev-parse HEAD) # Latest commit - - *get-previous-merge-commit-sha # Stored in previous_merge_commit shell variable now + - previous_merge_commit=$(git --no-pager log --merges HEAD~1 -n 1 --pretty=format:%H) - echo "Comparing changes from $previous_merge_commit to $latest_commit" - git --no-pager diff --stat $previous_merge_commit..$latest_commit @@ -1375,7 +1198,7 @@ codec-comparison-on-main-push: exit_codes: - 123 artifacts: - name: "main-push--sha-$CI_COMMIT_SHORT_SHA--stage-$CI_JOB_STAGE--results" + name: "main-push--sha-$CI_COMMIT_SHORT_SHA--job-$CI_JOB_NAME--results" expire_in: 1 week when: always paths: @@ -1434,6 +1257,7 @@ ivas-conformance: - cp -force IVAS_cod.exe IVAS_cod_ref.exe - cp -force IVAS_dec.exe IVAS_dec_ref.exe - cp -force IVAS_rend.exe IVAS_rend_ref.exe + - cp -force ISAR_post_rend.exe ISAR_post_rend_ref.exe # Reference creation - python scripts/prepare_combined_format_inputs.py @@ -1499,6 +1323,7 @@ ivas-conformance: expire_in: 1 week when: always paths: + - report_cmd.html - report-junit.xml - report.html - Readme_IVAS_dec.txt @@ -1512,8 +1337,8 @@ ivas-conformance: junit: report-junit.xml ivas-conformance-linux: - tags: - - ivas-linux + extends: + - .job-linux stage: test timeout: "90 minutes" rules: @@ -1522,11 +1347,12 @@ ivas-conformance-linux: exit_codes: - 123 script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - make -j - cp IVAS_cod IVAS_cod_ref - cp IVAS_dec IVAS_dec_ref - cp IVAS_rend IVAS_rend_ref + - cp ISAR_post_rend ISAR_post_rend_ref # Reference creation - python3 scripts/prepare_combined_format_inputs.py @@ -1619,8 +1445,8 @@ ivas-conformance-linux: test-long-self-test: - tags: - - ivas-linux-fast + extends: + - .job-linux stage: compare resource_group: ivas-long-self-test-resource timeout: "50 minutes" @@ -1630,8 +1456,8 @@ test-long-self-test: exit_codes: - 123 script: - - *print-common-info - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh ### build branch binaries - cmake . -Bbuild-test @@ -1659,7 +1485,7 @@ test-long-self-test: ### prepare pytest # Copy test vectors from LTV to TESTV - - *copy-ltv-files-to-testv-dir + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/copy-ltv-files-to-testv-dir.sh # create references - exit_code_ref=0 @@ -1689,8 +1515,8 @@ test-long-self-test: - report-junit-ltv.xml check-clipping: - tags: - - ivas-linux + extends: + - .job-linux stage: test timeout: "30 minutes" rules: @@ -1699,8 +1525,8 @@ check-clipping: exit_codes: - 123 script: - - *print-common-info - - *enable-debugging-macro + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/enable-debugging-macro.sh - make -j - tests/scale_pcm.py ./scripts/testv/ $SCALE_FACTOR # Default: 3.162 (+10 dB). Can be set in manual trigger. - python3 -m pytest $TESTS_DIR_CODEC_BE_ON_MR -v --update_ref 1 --html=report.html --self-contained-html --junit-xml=report-junit.xml --ref_encoder_path ./IVAS_cod --ref_decoder_path ./IVAS_dec @@ -1719,8 +1545,8 @@ check-clipping: - report-junit.xml test-branch-vs-input-passthrough: - tags: - - ivas-linux + extends: + - .job-linux stage: compare timeout: "30 minutes" # TBD rules: @@ -1729,7 +1555,7 @@ test-branch-vs-input-passthrough: exit_codes: - 123 script: - - *print-common-info + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh - make -j - exit_code=0 @@ -1761,53 +1587,56 @@ test-branch-vs-input-passthrough: ltv-msan: extends: - .sanitizer-selftest-ltv + - .sanitizer-selftest-anchor rules: - if: $SANITIZER_SCHEDULE_E - timeout: 4 hour + timeout: 5 hours tags: - ivas-linux-fast before_script: + - !reference [.job-linux, before_script] - CLANG_NUM=1 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS - SELF_TEST_PRM_FILE="scripts/config/self_test_ltv.prm" - USE_LTV="--use_ltv" - <<: *sanitizer-selftest-anchor # code selftest long testvectors with address-sanitizer binaries ltv-asan: extends: - .sanitizer-selftest-ltv + - .sanitizer-selftest-anchor rules: - if: $SANITIZER_SCHEDULE_E when: delayed - start_in: 4 hours + start_in: 5 hours tags: - ivas-linux-fast - timeout: 3 hour + timeout: 5 hours before_script: + - !reference [.job-linux, before_script] - CLANG_NUM=2 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS - SELF_TEST_PRM_FILE="scripts/config/self_test_ltv.prm" - USE_LTV="--use_ltv" - <<: *sanitizer-selftest-anchor # code selftest long testvectors with undefined-behaviour-sanitizer binaries ltv-usan: extends: - .sanitizer-selftest-ltv + - .sanitizer-selftest-anchor rules: - if: $SANITIZER_SCHEDULE_E when: delayed - start_in: 7 hours + start_in: 8 hours tags: - ivas-linux-fast - timeout: 3 hour + timeout: 5 hours before_script: + - !reference [.job-linux, before_script] - CLANG_NUM=3 - SELFTEST_SANITY_TIMEOUT=$TESTCASE_TIMEOUT_LTV_SANITIZERS - SELF_TEST_PRM_FILE="scripts/config/self_test_ltv.prm" - USE_LTV="--use_ltv" - <<: *sanitizer-selftest-anchor .sanitizer-test-template: extends: @@ -1818,7 +1647,7 @@ ltv-usan: - ivas-linux-fast artifacts: name: "$CI_JOB_NAME--main--sha-$CI_COMMIT_SHORT_SHA" - expire_in: 4 weeks + expire_in: 7 weeks when: always paths: - ep_015.g192 @@ -1840,7 +1669,7 @@ sanitizer-test-mono: - if: $SANITIZER_SCHEDULE_A timeout: 1.25 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py mono mono --tests $SANITIZER_TESTS sanitizer-test-stereo: @@ -1851,7 +1680,7 @@ sanitizer-test-stereo: start_in: 1.25 hours timeout: 2.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py stereo $OUT_FORMATS_CHANNEL_BASED EXT --tests $SANITIZER_TESTS sanitizer-test-stereodmxevs: @@ -1862,7 +1691,7 @@ sanitizer-test-stereodmxevs: start_in: 3.75 hours timeout: 1.25 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py StereoDmxEVS mono --tests $SANITIZER_TESTS sanitizer-test-mc-5_1: @@ -1873,7 +1702,7 @@ sanitizer-test-mc-5_1: start_in: 5 hours timeout: 2.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py 5_1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-5_1_2: @@ -1884,7 +1713,7 @@ sanitizer-test-mc-5_1_2: start_in: 7.5 hours timeout: 2.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py 5_1_2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-5_1_4: @@ -1895,7 +1724,7 @@ sanitizer-test-mc-5_1_4: start_in: 10 hours timeout: 3.75 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py 5_1_4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-7_1: @@ -1906,7 +1735,7 @@ sanitizer-test-mc-7_1: start_in: 13.75 hours timeout: 2.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py 7_1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-mc-7_1_4: @@ -1917,7 +1746,7 @@ sanitizer-test-mc-7_1_4: start_in: 16.25 hours timeout: 5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py 7_1_4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+1: @@ -1928,7 +1757,7 @@ sanitizer-test-ism+1: start_in: 21.25 hours timeout: 1.25 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+2: @@ -1939,7 +1768,7 @@ sanitizer-test-ism+2: start_in: 22.5 hours timeout: 2.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+3: @@ -1950,7 +1779,7 @@ sanitizer-test-ism+3: start_in: 25 hours timeout: 3.75 hour script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-ism+4: @@ -1961,7 +1790,7 @@ sanitizer-test-ism+4: start_in: 28.75 hours timeout: 5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-masa: @@ -1972,7 +1801,7 @@ sanitizer-test-masa: start_in: 33.75 hours timeout: 10 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py MASA $OUT_FORMATS_ALL --tests $SANITIZER_TESTS ### --- sanitizer schedule B --- @@ -1987,7 +1816,7 @@ sanitizer-test-foa: rules: - if: $SANITIZER_SCHEDULE_B script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py FOA $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-hoa2: @@ -1997,7 +1826,7 @@ sanitizer-test-hoa2: when: delayed start_in: 7.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-hoa3: @@ -2007,7 +1836,7 @@ sanitizer-test-hoa3: when: delayed start_in: 15 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism1: @@ -2017,7 +1846,7 @@ sanitizer-test-osba-foa-ism1: when: delayed start_in: 22.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism2: @@ -2027,7 +1856,7 @@ sanitizer-test-osba-foa-ism2: when: delayed start_in: 30 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism3: @@ -2037,7 +1866,7 @@ sanitizer-test-osba-foa-ism3: when: delayed start_in: 37.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-foa-ism4: @@ -2047,7 +1876,7 @@ sanitizer-test-osba-foa-ism4: when: delayed start_in: 45 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py FOA-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism1: @@ -2057,7 +1886,7 @@ sanitizer-test-osba-hoa2-ism1: when: delayed start_in: 52.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism2: @@ -2067,7 +1896,7 @@ sanitizer-test-osba-hoa2-ism2: when: delayed start_in: 60 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism3: @@ -2077,7 +1906,7 @@ sanitizer-test-osba-hoa2-ism3: when: delayed start_in: 67.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa2-ism4: @@ -2087,7 +1916,7 @@ sanitizer-test-osba-hoa2-ism4: when: delayed start_in: 75 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA2-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism1: @@ -2097,7 +1926,7 @@ sanitizer-test-osba-hoa3-ism1: when: delayed start_in: 82.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism2: @@ -2107,7 +1936,7 @@ sanitizer-test-osba-hoa3-ism2: when: delayed start_in: 90 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-omasa-ism4: @@ -2118,7 +1947,7 @@ sanitizer-test-omasa-ism4: start_in: 97.5 hours timeout: 10 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS @@ -2134,7 +1963,7 @@ sanitizer-test-omasa-ism1: rules: - if: $SANITIZER_SCHEDULE_C script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-omasa-ism2: @@ -2144,7 +1973,7 @@ sanitizer-test-omasa-ism2: when: delayed start_in: 10 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-omasa-ism3: @@ -2154,7 +1983,7 @@ sanitizer-test-omasa-ism3: when: delayed start_in: 20 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py MASA-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism3: @@ -2165,7 +1994,7 @@ sanitizer-test-osba-hoa3-ism3: start_in: 30 hours timeout: 7.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-hoa3-ism4: @@ -2176,7 +2005,7 @@ sanitizer-test-osba-hoa3-ism4: start_in: 37.5 hours timeout: 7.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py HOA3-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS ### --- sanitizer schedule D --- @@ -2191,7 +2020,7 @@ sanitizer-test-planar-foa: rules: - if: $SANITIZER_SCHEDULE_D script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-planar-hoa2: @@ -2201,7 +2030,7 @@ sanitizer-test-planar-hoa2: when: delayed start_in: 7.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-planar-hoa3: @@ -2211,7 +2040,7 @@ sanitizer-test-planar-hoa3: when: delayed start_in: 15 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism1: @@ -2221,7 +2050,7 @@ sanitizer-test-osba-planar-foa-ism1: when: delayed start_in: 22.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism2: @@ -2231,7 +2060,7 @@ sanitizer-test-osba-planar-foa-ism2: when: delayed start_in: 30 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism3: @@ -2241,7 +2070,7 @@ sanitizer-test-osba-planar-foa-ism3: when: delayed start_in: 37.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-foa-ism4: @@ -2251,7 +2080,7 @@ sanitizer-test-osba-planar-foa-ism4: when: delayed start_in: 45 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarFOA-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism1: @@ -2261,7 +2090,7 @@ sanitizer-test-osba-planar-hoa2-ism1: when: delayed start_in: 52.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism2: @@ -2271,7 +2100,7 @@ sanitizer-test-osba-planar-hoa2-ism2: when: delayed start_in: 60 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism3: @@ -2281,7 +2110,7 @@ sanitizer-test-osba-planar-hoa2-ism3: when: delayed start_in: 67.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa2-ism4: @@ -2291,7 +2120,7 @@ sanitizer-test-osba-planar-hoa2-ism4: when: delayed start_in: 75 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA2-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism1: @@ -2301,7 +2130,7 @@ sanitizer-test-osba-planar-hoa3-ism1: when: delayed start_in: 82.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM1 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism2: @@ -2311,7 +2140,7 @@ sanitizer-test-osba-planar-hoa3-ism2: when: delayed start_in: 90 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM2 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism3: @@ -2321,7 +2150,7 @@ sanitizer-test-osba-planar-hoa3-ism3: when: delayed start_in: 97.5 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM3 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS sanitizer-test-osba-planar-hoa3-ism4: @@ -2331,7 +2160,7 @@ sanitizer-test-osba-planar-hoa3-ism4: when: delayed start_in: 105 hours script: - - *update-ltv-repo + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - python3 ci/run_scheduled_sanitizer_test.py PlanarHOA3-ISM4 $OUT_FORMATS_ALL --tests $SANITIZER_TESTS @@ -2349,9 +2178,9 @@ coverage-test-on-main-scheduled: - if: $COVERAGE_TEST timeout: 3 hours script: - - *print-common-info - - *update-ltv-repo - - *copy-ltv-files-to-testv-dir + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/copy-ltv-files-to-testv-dir.sh - make GCOV=1 -j - cp IVAS_rend IVAS_rend_ref # Copy exec to be able to run renderer script @@ -2403,13 +2232,30 @@ coverage-test-on-main-scheduled: - job_id=$(python3 ci/get_id_of_last_job_occurence.py $CI_COMMIT_REF_NAME $CI_JOB_NAME $CI_PROJECT_ID) - 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 - - ls + - curl --silent --show-error --request GET "https://forge.3gpp.org/rep/api/v4/projects/$CI_PROJECT_ID/jobs/$job_id/artifacts" --output artifacts.zip + - unzip -qq artifacts.zip || true # this may fail on first run, when there are no artifacts there and the zip file is actually just "404"-html - public_dir="$CI_JOB_NAME-public" + # if is needed to catch case when no artifact is there (first run), similarly as above - - if [[ -d $public_dir ]]; then mv $public_dir/* wmops/; fi - - ls wmops + # 1. check for public_dir being there as this might not be the case when artifact download failed + # 2. check for public dir not being empty - handle job failures in prev job that happen after the dir is created. In that case, the empty dir is in the artifacts + - if [ -d $public_dir ] && [ ! -z "$( ls -A $public_dir )" ]; then + - mv $public_dir/* wmops/ + # check here if we have the split-by-levels files present - if not, fake them up with the existing global one + # this is needed for the first run with split graphs on a branch where the global version did run previously + # NOTE: checking only for level_1 file here as this should already be sufficient + # NOTE2: also not chechking for RAM for same reason + - wmops_all_global="wmops/log_wmops_all.txt" + - ram_all_global="wmops/log_ram_all.txt" + - if [ -f "${wmops_all_global}" ] && [ ! -f "wmops/log_wmops_all_level_1.txt" ]; then + - declare -a suffixes=("level_1" "level_2" "level_3" "rate_sw") + - for suffix in "${suffixes[@]}"; do + - cp ${wmops_all_global} wmops/log_wmops_all_${suffix}.txt + - cp ${ram_all_global} wmops/log_ram_all_${suffix}.txt + - done + - fi + - fi + - rm artifacts.zip - rm -rf $public_dir @@ -2417,13 +2263,11 @@ coverage-test-on-main-scheduled: &complexity-measurements-prepare-artifacts # prepare artifacts -> move to public directory - public_dir="$CI_JOB_NAME-public" - mkdir $public_dir - - mv -f wmops/log_*_all.txt ./*.js ${public_dir}/ + - mv -f wmops/log_*_all*.txt ./*.js ${public_dir}/ # move logfiles for links - mkdir $public_dir/logs # first move logs - log_files=$(cat $public_dir/graphs*.js | grep logFile | sed "s/.*\(wmops_newsletter_.*\.csv\).*/\1/g") - - echo $log_files - - ls wmops/logs - for f in $log_files; do [ -f wmops/logs/$f ] && mv wmops/logs/$f $public_dir/logs/$f; done # copy index page blueprint - cp ci/complexity_measurements/index_complexity.html ${public_dir}/index.html @@ -2431,7 +2275,6 @@ coverage-test-on-main-scheduled: - sed -i "s/IVAS FORMAT/IVAS $in_format to $out_format/g" ${public_dir}/index.html # do separately here to avoid overwrite complaints by mv - mv -f ci/complexity_measurements/style.css ${public_dir}/ - - ls $public_dir .complexity-template: extends: @@ -2442,9 +2285,13 @@ coverage-test-on-main-scheduled: timeout: 3 hours 30 minutes stage: test before_script: - - *print-common-info - - *update-ltv-repo + - !reference [.job-linux, before_script] + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/print-common-info.sh + - bash "${CI_PROJECT_DIR}"/ivas-codec-ci/snippets/update-ltv-repo.sh - *complexity-measurements-setup + allow_failure: + exit_codes: + - 123 artifacts: name: "$CI_JOB_NAME--$CI_COMMIT_REF_NAME--sha-$CI_COMMIT_SHA" when: always @@ -2757,8 +2604,8 @@ complexity-osba-in-binaural_room_ir-out: # job that sets up gitlab pages website pages: stage: deploy - tags: - - ivas-linux + extends: + - .job-linux rules: - if: $UPDATE_PAGES script: diff --git a/.gitlab-ci/variables.yml b/.gitlab-ci/variables.yml new file mode 100644 index 0000000000000000000000000000000000000000..9e60194a6c7cbe29dba20cbbcc6de430961cb571 --- /dev/null +++ b/.gitlab-ci/variables.yml @@ -0,0 +1,30 @@ +variables: + EVS_BE_TEST_DIR: "/usr/local/be_2_evs_test" + EVS_BE_WIN_TEST_DIR: "C:/Users/gitlab-runner/testvec" + PROCESSING_SCRIPTS_BIN_DIR: "/test-bin" + 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_CHANNEL_BASED $OUT_FORMATS_SCENE_BASED $OUT_FORMATS_BINAURAL EXT" + MANUAL_PIPELINE_TYPE: + description: "Type for the manual pipeline run. Use 'test-be-release' to run BE test against release codec." + value: 'default' + options: + - 'default' + - 'test-be-release' + - 'test-long-self-test' + - 'ivas-conformance' + - 'ivas-conformance-linux' + - 'check-clipping' + - 'test-branch-vs-input-passthrough' + + PYTEST_ARGS: "" + LONG_TEST_SUITE: "tests/codec_be_on_mr_nonselection tests/renderer --param_file scripts/config/self_test_ltv.prm --use_ltv" + LONG_TEST_SUITE_NO_RENDERER: "tests/codec_be_on_mr_nonselection --param_file scripts/config/self_test_ltv.prm --use_ltv" + SHORT_TEST_SUITE: "tests/codec_be_on_mr_nonselection" + SHORT_TEST_SUITE_ENCODER: "tests/codec_be_on_mr_nonselection/test_param_file.py --param_file scripts/config/self_test_basop_encoder.prm" + LONG_TEST_SUITE_ENCODER: "tests/codec_be_on_mr_nonselection/test_param_file.py --param_file scripts/config/self_test_ltv_basop_encoder.prm" + TEST_SUITE: "" + # note: currently overwrites default value from ci repo + TESTCASE_TIMEOUT_STV_SANITIZERS: 240 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c5beb9a0d546fe2649575fe8110037314df6621..de4727bec85854deffa025173bcd7407202df2cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ # cmake --build . --config Release -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.10) set(CMAKE_C_STANDARD 99) @@ -121,7 +121,7 @@ if(WMOPS) add_definitions("-DWMOPS=1") endif() -project(stereo-evs) +project(stereo-evs LANGUAGES C) set_property(GLOBAL PROPERTY USE_FOLDERS ON) # make Visual Studio projects look nicer include(CTest) @@ -174,7 +174,7 @@ target_include_directories(lib_util PUBLIC lib_util PRIVATE lib_com lib_enc lib_ target_include_directories(lib_util PRIVATE lib_lc3plus lib_isar) if(NOT WMOPS) - add_executable(ivas_lc3plus_unit_test scripts/split_rendering/lc3plus/ivas_lc3plus_unit_test.c) + add_executable(ivas_lc3plus_unit_test scripts/split_rendering/lc3plus_float/ivas_lc3plus_unit_test.c) target_link_libraries(ivas_lc3plus_unit_test lib_rend lib_dec lib_util lib_com lib_debug lib_isar) endif() @@ -213,7 +213,7 @@ if(COPY_EXECUTABLES_FROM_BUILD_DIR) add_custom_command(TARGET IVAS_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") add_custom_command(TARGET ISAR_post_rend POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/") if (NOT WMOPS) - add_custom_command(TARGET ivas_lc3plus_unit_test POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/split_rendering/lc3plus") + add_custom_command(TARGET ivas_lc3plus_unit_test POST_BUILD VERBATIM COMMAND "${CMAKE_COMMAND}" -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/scripts/split_rendering/lc3plus_float") endif() endif() diff --git a/IvasBrirIntExtRenderers.py b/IvasBrirIntExtRenderers.py deleted file mode 100644 index a74869d7777b80834c1e815e80bf11a157459f0d..0000000000000000000000000000000000000000 --- a/IvasBrirIntExtRenderers.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 - -import os -import subprocess - -# Set/unset the flags below to activate/deactivate build/encode/decode phases -build = False -encode = True -decode = True - -# Variables -fs = 48 -ivasPath = './' -ivasEnc = 'IVAS_cod' -ivasDec = 'IVAS_dec' -ivasRend = 'IVAS_rend' -inPath = './in/' -bitPath = './bit/' -outPath = './out/' -hrtfPath = f'{ivasPath}scripts/binauralRenderer_interface/binaural_renderers_hrtf_data/' -# hrtfName = f'HRIR_128_Meth5_IRC_53_Q10_symL_Itrp1_{fs}000' -# brirKern = 'BRIR_Auditorium_S1_R1' -# brirName = f'{brirKern}_Combined_BRIR_{fs}kHz' -# brirFile = f'{hrtfPath}{hrtfName}+{brirName}.bin' -# brirFile = f'{hrtfPath}fastconv_{hrtfName}_{brirKern}.bin' -# brirFile = f'{hrtfPath}ivas_binaural_custom_48kHz.bin' -brirFiles = ['',f'ivas_binaural_{fs}kHz',f'ivas_binaural_custom_{fs}kHz', f'ivas_binaural_custom_no_optim_{fs}kHz', f'ivas_binaural_custom_fabian_hrir_{fs}kHz'] -brirPaths = [f'{hrtfPath}{brirFiles[0]}.bin', f'{hrtfPath}{brirFiles[1]}.bin'] -bitrates = [32, 80, 256] -# inFormats = ['mc 5_1', 'mc 7_1_4', 'sba 1', 'sba 2', 'sba 3'] -# files = {'mc 5_1' : f'5ch_ident_{fs}', 'mc 7_1_4' : f'dirac_714_{fs}k', 'sba 1' : f'dirac_HOA1S_{fs}k' , 'sba 2' : f'dirac_HOA2S_{fs}k' , 'sba 3' : f'dirac_HOA3S_{fs}k' } -# outFormats = {'mc 5_1' : '5_1', 'mc 7_1_4' : '7_1_4', 'sba 1' : 'FOA' , 'sba 2' : 'HOA2' , 'sba 3' : 'HOA3' } -inFormats = ['mc 5_1', 'mc 7_1_4', 'sba 3'] -files = {'mc 5_1' : f'5ch_ident_{fs}', 'mc 7_1_4' : f'dirac_714_{fs}k' , 'sba 3' : f'dirac_HOA3S_{fs}k' } -outFormats = {'mc 5_1' : '5_1', 'mc 7_1_4' : '7_1_4', 'sba 1' : 'FOA' , 'sba 3' : 'HOA3' } - -testDir = os.getcwd() - -# Build phase -if build: - os.chdir(ivasPath) - subprocess.run('cmake -D CMAKE_BUILD_TYPE=Release -D TARGET_PLATFORM=x86_64 -D COPY_EXECUTABLES_FROM_BUILD_DIR=true -B build -G "Visual Studio 15 2017 Win64"') - subprocess.run('cmake --build build --config release --clean-first') - #subprocess.run('cmake --build build --config release') - os.chdir(testDir) - -#Encode -if encode: - for b in bitrates: - for f in inFormats: - cmd = f'{ivasPath}{ivasEnc} -{f} {b * 1000} {fs} {inPath}{files[f]}.wav {bitPath}{files[f]}-{b}kbps.ivas' - subprocess.run(cmd,shell=True) - -#Decode & Render -# for b in bitrates: -# for f in inFormats: -# for brir in brirFiles: -# ivasFile = f'{bitPath}{files[f]}-{b}kbps.ivas' -# outFileBase = f'{outPath}{files[f]}-{b}kbps' -# # Decode and render binaural -# cmd = f'{ivasPath}{ivasDec} -hrtf {hrtfPath}{brir}.bin BINAURAL {fs} {ivasFile} {outFileBase}-dec-bin-{brir}.wav' -# subprocess.run(cmd,shell=True) - -# # Decode and render binaural IR -# cmd = f'{ivasPath}{ivasDec} -hrtf {hrtfPath}{brir}.bin BINAURAL_ROOM_IR {fs} {ivasFile} {outFileBase}-dec-brir-{brir}.wav' -# subprocess.run(cmd,shell=True) - -# # Decode and render binaural reverb -# cmd = f'{ivasPath}{ivasDec} -hrtf {hrtfPath}{brir}.bin BINAURAL_ROOM_REVERB {fs} {ivasFile} {outFileBase}-dec-rev-{brir}.wav' -# subprocess.run(cmd,shell=True) - -# # Decode pass-through -# cmd = f'{ivasPath}{ivasDec} {outFormats[f]} {fs} {ivasFile} {outFileBase}-dec-ext.wav' -# subprocess.run(cmd,shell=True) - -# # Render binaural -# cmd = f'{ivasPath}{ivasRend} -i {outFileBase}-dec-ext.wav -if {outFormats[f]} -o {outFileBase}-ext-bin-{brir}.wav -of BINAURAL -fs {fs} -hrtf {hrtfPath}{brir}.bin' -# subprocess.run(cmd,shell=True) - -# # Render binaural IR -# cmd = f'{ivasPath}{ivasRend} -i {outFileBase}-dec-ext.wav -if {outFormats[f]} -o {outFileBase}-ext-brir-{brir}.wav -of BINAURAL_ROOM_IR -fs {fs} -hrtf {hrtfPath}{brir}.bin' -# subprocess.run(cmd,shell=True) - -# # Render binaural reverb -# cmd = f'{ivasPath}{ivasRend} -i {outFileBase}-dec-ext.wav -if {outFormats[f]} -o {outFileBase}-ext-rev-{brir}.wav -of BINAURAL_ROOM_REVERB -fs {fs}' -# subprocess.run(cmd,shell=True) - -for f in inFormats: - outFileBase = f'{outPath}{files[f]}' - for brir in brirFiles: - - # Render binaural - cmd = f'{ivasPath}{ivasRend} -i {inPath}{files[f]}.wav -if {outFormats[f]} -o {outFileBase}-rend-bin-{brir}.wav -of BINAURAL -fs {fs} -hrtf {hrtfPath}{brir}.bin' - subprocess.run(cmd,shell=True) - - # Render binaural IR - cmd = f'{ivasPath}{ivasRend} -i {inPath}{files[f]}.wav -if {outFormats[f]} -o {outFileBase}-rend-brir-{brir}.wav -of BINAURAL_ROOM_IR -fs {fs} -hrtf {hrtfPath}{brir}.bin -g 8' - subprocess.run(cmd,shell=True) - - # Render binaural reverb - cmd = f'{ivasPath}{ivasRend} -i {inPath}{files[f]}.wav -if {outFormats[f]} -o {outFileBase}-rend-rev-{brir}.wav -of BINAURAL_ROOM_REVERB -fs {fs} -hrtf {hrtfPath}{brir}.bin' - subprocess.run(cmd,shell=True) diff --git a/LICENSE.md b/LICENSE.md index 1c60a85b1afa1ba77ced378f75bed35f3ab214e6..ca74eaf483b6772614a49c5025aa865a357e063e 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2025 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 diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj index 223f837a2e1685afeedb952a5137dab7b902b3a6..c28b36a1454bdb9bd3245a0ce9050d258602a13a 100644 --- a/Workspace_msvc/lib_com.vcxproj +++ b/Workspace_msvc/lib_com.vcxproj @@ -223,7 +223,7 @@ - + diff --git a/Workspace_msvc/lib_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj index 55a291fa9c768769f213dac4423688e2db81f8e3..3f1527357ad6c96d8629a85f7ab3937e82fb3bb0 100644 --- a/Workspace_msvc/lib_lc3plus.vcxproj +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -106,7 +106,6 @@ - @@ -116,13 +115,13 @@ - - + + - + @@ -133,35 +132,36 @@ + - - - + + + + - - - + + + - @@ -169,14 +169,12 @@ - - - - + + + + - - diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 27d4a19a693cf86f60b3ce654912c65b4a7cbaa6..854c99a979e4ae274d9c002b2ca6686a96e75870 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -175,6 +175,7 @@ + diff --git a/Workspace_msvc/lib_rend.vcxproj.filters b/Workspace_msvc/lib_rend.vcxproj.filters index 942c63712f66e57821488868f81981d3042c56b0..2d1d7d46c0b86e517f6f5a9a35d3c5a985a4caac 100644 --- a/Workspace_msvc/lib_rend.vcxproj.filters +++ b/Workspace_msvc/lib_rend.vcxproj.filters @@ -32,30 +32,12 @@ rend_c - - rend_c - - - rend_c - - - rend_c - - - rend_c - rend_c rend_c - - rend_c - - - rend_c - rend_c @@ -83,15 +65,6 @@ rend_c - - rend_c - - - rend_c - - - rend_c - rend_c @@ -113,9 +86,6 @@ rend_c - - rend_c - rend_c @@ -134,24 +104,6 @@ rend_c - - rend_c - - - rend_c - - - rend_c - - - rend_c - - - rend_c - - - rend_c - rend_c @@ -161,30 +113,15 @@ rend_c - - rend_c - - - rend_c - - + rend_c - + rend_c - - rend_h - - - rend_h - - - rend_h - rend_h @@ -203,12 +140,6 @@ rend_h - - rend_h - - - rend_h - diff --git a/apps/decoder.c b/apps/decoder.c index ccc9e77c6b059fdb06773d283e7ba3df3a9bd7a3..4a28b4470b7c26a1673b05209a6c3d834a0882df 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2025 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 @@ -69,22 +69,10 @@ static #endif int32_t frame = 0; /* Counter of frames */ -#define MIN_NUM_BITS_ACTIVE_FRAME 56 -#define NUM_BITS_SID_IVAS_5K2 104 -#define MAX_OUTPUT_PCM_BUFFER_SIZE ( ( IVAS_MAX_OUTPUT_CHANNELS + IVAS_MAX_NUM_OBJECTS ) * IVAS_MAX_FRAME_SIZE ) - -#define ORIENT_TRK_NONE ( 0 ) -#define ORIENT_TRK_REF ( 1 ) -#define ORIENT_TRK_AVG ( 2 ) -#define ORIENT_TRK_REF_VEC ( 3 ) -#define ORIENT_TRK_REF_VEC_LEV ( 4 ) - -#ifdef VARIABLE_SPEED_DECODING -#define VARIABLE_SPEED_FETCH_FRAMESIZE_MS 20 +#ifdef DEBUGGING +#define MIN_NUM_BITS_ACTIVE_FRAME 56 +#define NUM_BITS_SID_IVAS_5K2 104 #endif -#define JBM_FRONTEND_FETCH_FRAMESIZE_MS 20 -#define HEADROTATION_FETCH_FRAMESIZE_MS 5 -#define DEFAULT_FETCH_FRAMESIZE_MS 20 /*------------------------------------------------------------------------------------------* @@ -129,7 +117,7 @@ typedef struct IVAS_DEC_INPUT_FORMAT inputFormat; bool customLsOutputEnabled; char *customLsSetupFilename; - int16_t orientation_tracking; + IVAS_HEAD_ORIENT_TRK_T orientation_tracking; bool non_diegetic_pan_enabled; float non_diegetic_pan_gain; bool renderConfigEnabled; @@ -183,7 +171,7 @@ typedef struct static bool parseCmdlIVAS_dec( int16_t argc, char **argv, DecArguments *arg ); static void usage_dec( void ); static ivas_error decodeG192( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, ISAR_SPLIT_REND_BITS_DATA *splitRendBits, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); -static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, IVAS_DEC_HANDLE hIvasDec ); +static ivas_error decodeVoIP( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtf, RotFileReader *headRotReader, RotFileReader *externalOrientationFileReader, RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, IVAS_DEC_HANDLE hIvasDec, int16_t *pcmBuf ); static ivas_error load_hrtf_from_file( IVAS_DEC_HRTF_BINARY_WRAPPER *hHrtfBinary, IVAS_DEC_HANDLE hIvasDec, const IVAS_AUDIO_CONFIG OutputConfig, const int32_t output_Fs ); #ifdef DEBUGGING static ivas_error printBitstreamInfoVoip( DecArguments arg, BS_READER_HANDLE hBsReader, IVAS_DEC_HANDLE hIvasDec ); @@ -310,7 +298,7 @@ int main( if ( arg.hrtfReaderEnabled ) { /* sanity check */ - if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) + if ( arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && arg.outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { arg.hrtfReaderEnabled = false; fprintf( stderr, "\nError: HRTF binary file cannot be used in this output configuration.\n\n" ); @@ -359,7 +347,7 @@ int main( } /* sanity check */ - if ( arg.orientation_tracking != ORIENT_TRK_REF ) + if ( arg.orientation_tracking != IVAS_HEAD_ORIENT_TRK_REF ) { fprintf( stderr, "\nError: Reference rotation file can be used in '-otr ref' mode only.\n\n" ); goto cleanup; @@ -386,7 +374,7 @@ int main( } /* sanity check */ - if ( arg.orientation_tracking != ORIENT_TRK_REF_VEC && arg.orientation_tracking != ORIENT_TRK_REF_VEC_LEV ) + if ( arg.orientation_tracking != IVAS_HEAD_ORIENT_TRK_REF_VEC && arg.orientation_tracking != IVAS_HEAD_ORIENT_TRK_REF_VEC_LEV ) { fprintf( stderr, "\nError: Reference trajectory file can be used in '-otr ref_vec' or '-otr ref_vec_lev' mode only.\n\n" ); goto cleanup; @@ -445,12 +433,14 @@ int main( asked_frame_size = arg.renderFramesize; uint16_t aeID = arg.aeSequence.count > 0 ? arg.aeSequence.pID[0] : 65535; - if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputConfig, arg.tsmEnabled, arg.renderFramesize, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, arg.enableHeadRotation, arg.enableExternalOrientation, arg.orientation_tracking, arg.renderConfigEnabled, arg.non_diegetic_pan_enabled, arg.non_diegetic_pan_gain, - arg.dpidEnabled, aeID, arg.objEditEnabled, arg.delayCompensationEnabled ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_Configure( hIvasDec, arg.output_Fs, arg.outputConfig, arg.renderFramesize, arg.customLsOutputEnabled, arg.hrtfReaderEnabled, + arg.enableHeadRotation, arg.enableExternalOrientation, arg.orientation_tracking, arg.renderConfigEnabled, arg.non_diegetic_pan_enabled, + arg.non_diegetic_pan_gain, arg.dpidEnabled, aeID, arg.objEditEnabled, arg.delayCompensationEnabled ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } + if ( ( error = IVAS_DEC_GetRenderFramesize( hIvasDec, &arg.renderFramesize ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nConfigure failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); @@ -665,7 +655,8 @@ int main( if ( ( error = IVAS_DEC_SetRenderFramesize( hIvasDec, arg.renderFramesize ) ) != IVAS_ERR_OK ) { - return error; + fprintf( stderr, "\nIVAS_DEC_PrintConfig failed: %s\n\n", IVAS_DEC_GetErrorMessage( error ) ); + goto cleanup; } if ( arg.renderFramesize != asked_frame_size ) @@ -749,6 +740,11 @@ int main( } pcmBuf = malloc( pcmBufSize * sizeof( int16_t ) ); + if ( pcmBuf == NULL ) + { + fprintf( stdout, "Error: Unable to allocate memory for output buffer.\n" ); + goto cleanup; + } /*-----------------------------------------------------------------* * Decoding @@ -756,7 +752,7 @@ int main( if ( arg.voipMode ) { - error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, hIvasDec ); + error = decodeVoIP( arg, hBsReader, &hHrtfBinary, headRotReader, externalOrientationFileReader, refRotReader, referenceVectorReader, objectEditFileReader, hIvasDec, pcmBuf ); } else { @@ -954,6 +950,10 @@ static bool parseCmdlIVAS_dec( int16_t i; char argv_to_upper[FILENAME_MAX]; + /*-----------------------------------------------------------------* + * Set default values + *-----------------------------------------------------------------*/ + #ifdef DEBUGGING float ftmp; @@ -962,7 +962,7 @@ static bool parseCmdlIVAS_dec( arg->agcBitstream = NULL; #endif #endif - arg->output_Fs = 48000; + arg->output_Fs = IVAS_MAX_SAMPLING_RATE; arg->outputConfig = IVAS_AUDIO_CONFIG_MONO; arg->decMode = IVAS_DEC_MODE_IVAS; arg->quietModeEnabled = false; @@ -972,7 +972,7 @@ static bool parseCmdlIVAS_dec( arg->enableHeadRotation = false; arg->headrotTrajFileName = NULL; - arg->orientation_tracking = ORIENT_TRK_NONE; + arg->orientation_tracking = IVAS_HEAD_ORIENT_TRK_NONE; arg->enableReferenceRotation = false; arg->headrotTrajFileName = NULL; arg->enableReferenceVectorTracking = false; @@ -1050,18 +1050,18 @@ static bool parseCmdlIVAS_dec( if ( strcmp( argv_to_upper, "-VOIP" ) == 0 ) { - arg->voipMode = 1; + arg->voipMode = true; i++; } else if ( strcmp( argv_to_upper, "-VOIP_HF_ONLY=0" ) == 0 ) { - arg->voipMode = 1; + arg->voipMode = true; arg->inputFormat = IVAS_DEC_INPUT_FORMAT_RTPDUMP; i++; } else if ( strcmp( argv_to_upper, "-VOIP_HF_ONLY=1" ) == 0 ) { - arg->voipMode = 1; + arg->voipMode = true; arg->inputFormat = IVAS_DEC_INPUT_FORMAT_RTPDUMP_HF; i++; } @@ -1172,9 +1172,9 @@ static bool parseCmdlIVAS_dec( } arg->tsmScale = (uint16_t) tmp; - if ( arg->tsmScale < 50 || arg->tsmScale > 150 ) + if ( arg->tsmScale < IVAS_TIME_SCALE_MIN || arg->tsmScale > IVAS_TIME_SCALE_MAX ) { - fprintf( stderr, "Error: Scaling factor value must be 50 <= fac <= 150!\n\n" ); + fprintf( stderr, "Error: Scaling factor value must be IVAS_TIME_SCALE_MIN <= fac <= IVAS_TIME_SCALE_MAX!\n\n" ); usage_dec(); return false; } @@ -1211,6 +1211,8 @@ static bool parseCmdlIVAS_dec( { if ( !is_digits_only( argv[i] ) ) { + fprintf( stderr, "Error: Render frame size is invalid or not specified!\n\n" ); + usage_dec(); return false; } @@ -1245,23 +1247,23 @@ static bool parseCmdlIVAS_dec( if ( strcmp( argv_to_upper, "NONE" ) == 0 ) { - arg->orientation_tracking = ORIENT_TRK_NONE; + arg->orientation_tracking = IVAS_HEAD_ORIENT_TRK_NONE; } else if ( strcmp( argv_to_upper, "REF" ) == 0 ) { - arg->orientation_tracking = ORIENT_TRK_REF; + arg->orientation_tracking = IVAS_HEAD_ORIENT_TRK_REF; } else if ( strcmp( argv_to_upper, "AVG" ) == 0 ) { - arg->orientation_tracking = ORIENT_TRK_AVG; + arg->orientation_tracking = IVAS_HEAD_ORIENT_TRK_AVG; } else if ( strcmp( argv_to_upper, "REF_VEC" ) == 0 ) { - arg->orientation_tracking = ORIENT_TRK_REF_VEC; + arg->orientation_tracking = IVAS_HEAD_ORIENT_TRK_REF_VEC; } else if ( strcmp( argv_to_upper, "REF_VEC_LEV" ) == 0 ) { - arg->orientation_tracking = ORIENT_TRK_REF_VEC_LEV; + arg->orientation_tracking = IVAS_HEAD_ORIENT_TRK_REF_VEC_LEV; } else { @@ -1615,6 +1617,18 @@ static bool parseCmdlIVAS_dec( return false; } +#ifdef SUPPORT_JBM_TRACEFILE + /* Validate options that depend on other options */ + if ( arg->jbmTraceFilename != NULL && arg->delayCompensationEnabled + /* This decMode check should be removed once timestamp sync issues between JBM trace and audio are fixed in EVS */ + && arg->decMode != IVAS_DEC_MODE_EVS ) + { + fprintf( stderr, "Error: Writing to a JBM trace file requires delay compensation to be disabled with -no_delay_cmp\n\n" ); + usage_dec(); + return false; + } +#endif + return true; } @@ -1651,12 +1665,13 @@ static void usage_dec( void ) fprintf( stdout, " EVS RTP Payload Format. The SDP parameter hf_only is required.\n" ); fprintf( stdout, " Reading RFC4867 AMR/AMR-WB RTP payload format is not supported.\n" ); #ifdef SUPPORT_JBM_TRACEFILE - fprintf( stdout, "-Tracefile TF : VoIP mode: Generate trace file named TF\n" ); + fprintf( stdout, "-Tracefile TF : VoIP mode: Generate trace file named TF. Requires -no_delay_cmp to\n" ); + fprintf( stdout, " be enabled so that trace contents remain in sync with audio output.\n" ); #endif #ifdef DEBUGGING #ifdef VARIABLE_SPEED_DECODING fprintf( stdout, "-VS fac : Variable Speed mode: change speed of playout fac as integer in percent.\n" ); - fprintf( stdout, " 50 <= fac <= 150; fac<100 faster, fac>100 slower\n" ); + fprintf( stdout, " IVAS_TIME_SCALE_MIN <= fac <= IVAS_TIME_SCALE_MAX; fac<100 faster, fac>100 slower\n" ); #endif #endif fprintf( stdout, "-fr L : render frame size in ms L=(5,10,20), default is 20)\n" ); @@ -1792,14 +1807,6 @@ static ivas_error initOnFirstGoodFrame( return error; } - int32_t pcmFrameSize; - - if ( ( error = IVAS_DEC_GetPcmFrameSize( hIvasDec, &pcmFrameSize ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_DEC_GetPcmFrameSize, error code: %d\n", error ); - return error; - } - if ( isSplitRend ) { /* Open split rendering metadata writer */ @@ -1857,8 +1864,20 @@ static ivas_error initOnFirstGoodFrame( } } - int16_t *zeroBuf = malloc( pcmFrameSize * sizeof( int16_t ) ); - memset( zeroBuf, 0, pcmFrameSize * sizeof( int16_t ) ); + int16_t pcmFrameSize; + if ( ( error = IVAS_DEC_GetOutputBufferSize( hIvasDec, &pcmFrameSize ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_GetOutputBufferSize, error code: %d\n", error ); + return error; + } + + /* Write zeros to the output audio buffer */ + int16_t *zeroBuf = calloc( pcmFrameSize, sizeof( int16_t ) ); + if ( zeroBuf == NULL ) + { + fprintf( stdout, "Error: Unable to allocate memory for output buffer.\n" ); + return IVAS_ERR_FAILED_ALLOC; + } for ( int16_t i = 0; i < numInitialBadFrames; ++i ) { @@ -1882,7 +1901,6 @@ static ivas_error initOnFirstGoodFrame( } else { - if ( *pRemainingDelayNumSamples < *numOutSamples ) { if ( ( error = AudioFileWriter_write( *ppAfWriter, zeroBuf, *numOutSamples * *pNumOutChannels - ( *pRemainingDelayNumSamples * *pNumOutChannels ) ) ) != IVAS_ERR_OK ) @@ -2071,6 +2089,17 @@ static ivas_error decodeG192( SplitFileReadWrite *splitRendWriter = NULL; int16_t isSplitRend, isSplitCoded; +#ifdef VARIABLE_SPEED_DECODING + if ( arg.tsmEnabled ) + { + if ( ( error = IVAS_DEC_EnableTsm( hIvasDec ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nError in IVAS_DEC_EnableTsm, code: %d\n", error ); + return error; + } + } + +#endif if ( ( error = IVAS_DEC_is_split_rendering_enabled( hIvasDec, &isSplitRend ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_is_split_rendering_enabled, code: %d\n", error ); @@ -2963,14 +2992,15 @@ static ivas_error decodeVoIP( RotFileReader *refRotReader, Vector3PairFileReader *referenceVectorReader, ObjectEditFileReader *objectEditFileReader, - IVAS_DEC_HANDLE hIvasDec ) + IVAS_DEC_HANDLE hIvasDec, + int16_t *pcmBuf ) { bool decodingFailed = true; /* Assume failure until cleanup is reached without errors */ ivas_error error = IVAS_ERR_OK; uint32_t nextPacketRcvTime_ms = 0; uint32_t systemTime_ms = 0; - uint32_t systemTimeInc_ms = (uint32_t) JBM_FRONTEND_FETCH_FRAMESIZE_MS; + uint32_t systemTimeInc_ms = (uint32_t) ( 1000 / IVAS_NUM_FRAMES_PER_SEC ); int32_t nFramesFed = 0; uint8_t au[( IVAS_MAX_BITS_PER_FRAME + 7 ) >> 3]; @@ -2984,7 +3014,6 @@ static ivas_error decodeVoIP( MasaFileWriter *masaWriter = NULL; uint16_t numObj = 0; - int16_t pcmBuf[MAX_OUTPUT_PCM_BUFFER_SIZE]; AudioFileWriter *afWriter = NULL; #ifdef SUPPORT_JBM_TRACEFILE JbmTraceFileWriter *jbmTraceWriter = NULL; @@ -3385,7 +3414,7 @@ static ivas_error decodeVoIP( { if ( ( error = IVAS_DEC_HasDecodedFirstGoodFrame( hIvasDec, &decodedGoodFrame ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_DEC_HasDecodedFirstGoodFrame, code: %d\n", error ); + fprintf( stderr, "Error in IVAS_DEC_HasDecodedFirstGoodFrame(): %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } @@ -3397,6 +3426,7 @@ static ivas_error decodeVoIP( if ( ( error = initOnFirstGoodFrame( hIvasDec, arg, numInitialBadFrames, &nOutSamples, NULL, delayNumSamples_orig, &delayNumSamples, &delayTimeScale, &bsFormat, &afWriter, &masaWriter, ismWriters, &nOutChannels, &numObj, &splitRendWriter ) ) != IVAS_ERR_OK ) { + fprintf( stderr, "Error in initOnFirstGoodFrame(): %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } } diff --git a/apps/encoder.c b/apps/encoder.c index 4caa60803d8cad63471931608cc2cb2e719d65b9..61bb8ebb3f0d24c4835755b0b69ced48636add72 100644 --- a/apps/encoder.c +++ b/apps/encoder.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2025 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 @@ -15,6 +15,7 @@ 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 Contributors are required to enter into the IVAS codec Public Collaboration agreement before making contributions. @@ -154,7 +155,6 @@ typedef struct * Local functions prototypes *------------------------------------------------------------------------------------------*/ -static void initArgStruct( EncArguments *arg ); static bool parseCmdlIVAS_enc( int16_t argc, char *argv[], EncArguments *arg ); static void usage_enc( void ); static bool readBandwidth( FILE *file, IVAS_ENC_BANDWIDTH *bandwidth, int32_t *bandwidthFrameCounter ); @@ -207,8 +207,6 @@ int main( reset_mem( USE_BYTES ); #endif - initArgStruct( &arg ); - /*------------------------------------------------------------------------------------------* * Parse command-line arguments *------------------------------------------------------------------------------------------*/ @@ -878,14 +876,29 @@ cleanup: * Local functions *-------------------------------------------------------------------*/ -#define IVAS_DEFAULT_AGC ( 0 ) +/*---------------------------------------------------------------------* + * parseCmdlIVAS_enc() + * + * Encoder command-line parsing + *---------------------------------------------------------------------*/ -static void initArgStruct( EncArguments *arg ) +static bool parseCmdlIVAS_enc( + int16_t argc, + char *argv[], + EncArguments *arg ) { - /* Set default values here */ + int16_t i, j; + char argv_to_upper[FILENAME_MAX]; + char stmp[FILENAME_MAX]; + int32_t tmp; + + /*-----------------------------------------------------------------* + * Set default values + *-----------------------------------------------------------------*/ + arg->inputWavFilename = NULL; arg->outputBitstreamFilename = NULL; - arg->inputFs = 0; + arg->inputFs = IVAS_MAX_SAMPLING_RATE; arg->inputFormat = IVAS_ENC_INPUT_MONO; arg->is_binaural = false; arg->inputFormatConfig.stereoToMonoDownmix = false; @@ -919,25 +932,9 @@ static void initArgStruct( EncArguments *arg ) #endif arg->pca = false; - return; -} - - -/*---------------------------------------------------------------------* - * parseCmdlIVAS_enc() - * - * Encoder command-line parsing - *---------------------------------------------------------------------*/ - -static bool parseCmdlIVAS_enc( - int16_t argc, - char *argv[], - EncArguments *arg ) -{ - int16_t i, j; - char argv_to_upper[FILENAME_MAX]; - char stmp[FILENAME_MAX]; - int32_t tmp; + /*-----------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ if ( argc < 5 ) { diff --git a/apps/isar_post_rend.c b/apps/isar_post_rend.c index 752618406c7ebe5aafadd330e264ddb30b498863..2744c3bbe5855eb06393bc3ac5a418cfef302c3e 100644 --- a/apps/isar_post_rend.c +++ b/apps/isar_post_rend.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2025 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 @@ -681,19 +681,20 @@ int main( int argc, char **argv ) { - ISAR_POST_REND_HANDLE hIsarPostRend; + bool mainFailed = true; /* Assume main failed until cleanup is reached without errors */ + ISAR_POST_REND_HANDLE hIsarPostRend = NULL; RotFileReader *headRotReader = NULL; RotFileReader *externalOrientationFileReader = NULL; SplitRendBFIFileReader *splitRendBFIReader = NULL; AudioFileReader *audioReader = NULL; - AudioFileWriter *audioWriter; + AudioFileWriter *audioWriter = NULL; int32_t inBufferSize; int32_t outBufferSize; int32_t bitsBufferSize; - int16_t *inpInt16Buffer; - float *inFloatBuffer; - int16_t *outInt16Buffer; - float *outFloatBuffer; + int16_t *inpInt16Buffer = NULL; + float *inFloatBuffer = NULL; + int16_t *outInt16Buffer = NULL; + float *outFloatBuffer = NULL; uint8_t *bitsBufferData = NULL; IVAS_REND_AudioBuffer inBuffer; IVAS_REND_AudioBuffer outBuffer; @@ -744,8 +745,8 @@ int main( { if ( RotationFileReader_open( args.headRotationFilePath, &headRotReader ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", args.headRotationFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", args.headRotationFilePath ); + goto cleanup; } } @@ -778,14 +779,14 @@ int main( &bitsBuffer.config.lc3plusHighRes ); if ( error != IVAS_ERR_OK ) { - fprintf( stderr, "Could not open split rend metadata file %s\n", args.inMetadataFilePaths[0] ); - exit( -1 ); + fprintf( stderr, "\nCould not open split rend metadata file %s\n", args.inMetadataFilePaths[0] ); + goto cleanup; } if ( AudioFileReader_open( &audioReader, audioFilePath ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", audioFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", audioFilePath ); + goto cleanup; } } @@ -802,8 +803,8 @@ int main( &bitsBuffer.config.lc3plusHighRes ); if ( error != IVAS_ERR_OK ) { - fprintf( stderr, "Could not open split rend metadata file %s\n", args.inputFilePath ); - exit( -1 ); + fprintf( stderr, "\nCould not open split rend metadata file %s\n", args.inputFilePath ); + goto cleanup; } audioReader = NULL; } @@ -828,20 +829,20 @@ int main( /* else if sampling rate given on command line, compare with wav file */ else if ( inFileSampleRate != args.sampleRate ) { - fprintf( stderr, "Sampling rate mismatch: %d Hz requested, but %d Hz found in file %s\n", args.sampleRate, inFileSampleRate, args.inputFilePath ); - exit( -1 ); + fprintf( stderr, "\nSampling rate mismatch: %d Hz requested, but %d Hz found in file %s\n", args.sampleRate, inFileSampleRate, args.inputFilePath ); + goto cleanup; } break; case IVAS_ERR_SAMPLING_RATE_UNKNOWN: /* Returned when input is raw PCM */ if ( args.sampleRate == 0 ) { - fprintf( stderr, "Sampling rate must be specified on command line when using raw PCM input\n" ); - exit( -1 ); + fprintf( stderr, "\nSampling rate must be specified on command line when using raw PCM input\n" ); + goto cleanup; } break; default: - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } int16_t inFileNumChannels = 0; @@ -850,8 +851,8 @@ int main( error = AudioFileReader_getNumChannels( audioReader, &inFileNumChannels ); if ( error != IVAS_ERR_OK && error != IVAS_ERR_NUM_CHANNELS_UNKNOWN ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nAudioFileReader_getNumChannels failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -863,8 +864,8 @@ int main( args.outConfig.audioConfig = IVAS_AUDIO_CONFIG_BINAURAL; if ( ( error = ISAR_POST_REND_open( &hIsarPostRend, args.sampleRate, args.outConfig.audioConfig, true, 0, 0.0, (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening renderer handle: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError opening renderer handle: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } /*------------------------------------------------------------------------------------------* @@ -873,8 +874,8 @@ int main( if ( ( error = ISAR_POST_REND_InitConfig( hIsarPostRend, args.outConfig.audioConfig ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in Renderer Config Init: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in Renderer Config Init: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( args.inConfig.numBinBuses > 0 ) @@ -886,8 +887,8 @@ int main( bitsBuffer.config.isar_frame_size_ms, bitsBuffer.config.lc3plusHighRes ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in getting split renderer bitstream header: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in getting split renderer bitstream header: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -901,23 +902,23 @@ int main( { if ( ( error = ISAR_POST_REND_AddInput( hIsarPostRend, args.inConfig.binBuses[i].audioConfig, &splitBinIds[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nISAR_POST_REND_AddInput failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } const int16_t totalNumInChannels = getTotalNumInChannels( hIsarPostRend, splitBinIds ); if ( inFileNumChannels != 0 /* inFileNumChannels is 0 with raw PCM input */ && totalNumInChannels != inFileNumChannels ) { - fprintf( stderr, "Number of channels in input file does not match selected configuration\n" ); - exit( -1 ); + fprintf( stderr, "\nNumber of channels in input file does not match selected configuration\n" ); + goto cleanup; } int16_t numOutChannels = 2; if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) { - fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); - exit( -1 ); + fprintf( stderr, "\nFailed to open file: %s\n", args.outputFilePath ); + goto cleanup; } /*------------------------------------------------------------------------------------------* @@ -945,7 +946,7 @@ int main( memset( outBuffer.data, 0, outBuffer.config.numSamplesPerChannel * outBuffer.config.numChannels * sizeof( float ) ); - bitsBufferSize = SPLIT_REND_BITS_BUFF_SIZE; + bitsBufferSize = ISAR_SPLIT_REND_BITS_BUFF_SIZE; if ( bitsBufferSize > 0 ) { @@ -985,6 +986,7 @@ int main( while ( 1 ) { + int16_t bfi = 0; int16_t num_in_channels; num_in_channels = inBuffer.config.numChannels; @@ -992,8 +994,10 @@ int main( if ( ( hSplitRendFileReadWrite != NULL ) && splitBinNeedsNewFrame ) { ivas_error error_tmp; + numSamplesRead = (int16_t) inBufferSize; - error_tmp = split_rend_read_bits_from_file( hSplitRendFileReadWrite, bitsBuffer.bits, &bitsBuffer.config.bitsRead, &bitsBuffer.config.bitsWritten ); + + error_tmp = split_rend_read_bits_from_file( hSplitRendFileReadWrite, bitsBuffer.bits, &bitsBuffer.config.bitsRead, &bitsBuffer.config.bitsWritten, &bfi ); if ( error_tmp != IVAS_ERR_OK ) { if ( error_tmp == IVAS_ERR_END_OF_FILE ) @@ -1003,7 +1007,7 @@ int main( else { fprintf( stderr, "\nUnable to read from bitstream file!\n" ); - exit( -1 ); + goto cleanup; } } } @@ -1014,7 +1018,7 @@ int main( if ( ( error = AudioFileReader_read( audioReader, inpInt16Buffer, (int16_t) inBufferSize, &numSamplesRead ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError reading from file %s\n", audioFilePath ); - exit( -1 ); + goto cleanup; } } @@ -1040,37 +1044,39 @@ int main( if ( ( error = HeadRotationFileReading( headRotReader, &headRot, &Pos ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = ISAR_POST_REND_SetHeadRotation( hIsarPostRend, headRot, Pos, DEFAULT_AXIS, sf_idx ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error setting Head Rotation: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError setting Head Rotation: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } else { - fprintf( stderr, "Head Rotation should be enabled in post renderer\n" ); - exit( -1 ); + fprintf( stderr, "\nHead Rotation should be enabled in post renderer\n" ); + goto cleanup; } /* Read from split renderer bfi file if specified */ if ( splitRendBFIReader != NULL && splitBinNeedsNewFrame ) { - int16_t bfi; if ( ( error = SplitRendBFIFileReading( splitRendBFIReader, &bfi ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in SplitRendBFIFileReading(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in SplitRendBFIFileReading(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } + } + if ( splitBinNeedsNewFrame ) + { if ( ( error = ISAR_POST_REND_SetSplitRendBFI( hIsarPostRend, bfi ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in ISAR_POST_REND_SetSplitRendBFI(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in ISAR_POST_REND_SetSplitRendBFI(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1080,31 +1086,31 @@ int main( { if ( ( error = ISAR_POST_REND_GetInputNumChannels( hIsarPostRend, splitBinIds[i], &numChannels ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nISAR_POST_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } ISAR_POST_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.binBuses[i].inputChannelIndex, numChannels ); if ( ( error = ISAR_POST_REND_FeedInputAudio( hIsarPostRend, splitBinIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nISAR_POST_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } if ( splitBinNeedsNewFrame ) { if ( ( error = ISAR_POST_REND_FeedSplitBinauralBitstream( hIsarPostRend, splitBinIds[i], &bitsBuffer ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nISAR_POST_REND_FeedSplitBinauralBitstream failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } if ( ( error = ISAR_POST_REND_GetSplitBinauralSamples( hIsarPostRend, outBuffer, &splitBinNeedsNewFrame ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nISAR_POST_REND_GetSplitBinauralSamples failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } int16_t num_out_channels; @@ -1121,7 +1127,7 @@ int main( if ( ISAR_POST_REND_GetDelay( hIsarPostRend, &delayNumSamples, &delayTimeScale ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to get delay of renderer!\n" ); - exit( -1 ); + goto cleanup; } if ( hSplitRendFileReadWrite != NULL ) @@ -1146,8 +1152,8 @@ int main( { if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error writing audio file %s\n", args.outputFilePath ); - exit( -1 ); + fprintf( stderr, "\nError writing audio file %s\n", args.outputFilePath ); + goto cleanup; } delayNumSamples = 0; } @@ -1181,7 +1187,7 @@ int main( if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); - exit( -1 ); + goto cleanup; } } @@ -1189,7 +1195,7 @@ int main( if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); - exit( -1 ); + goto cleanup; } zeroPadToWrite = 0; } @@ -1217,6 +1223,10 @@ int main( * Close files and deallocate resources *------------------------------------------------------------------------------------------*/ + mainFailed = false; /* This will stay set to true if cleanup is reached via a goto due to an error */ + +cleanup: + free( inpInt16Buffer ); free( inFloatBuffer ); free( outInt16Buffer ); @@ -1245,7 +1255,7 @@ int main( print_mem( NULL ); #endif - return 0; + return mainFailed ? -1 : 0; } diff --git a/apps/renderer.c b/apps/renderer.c index 4704f4433e233d661ffb660585a31c9ea582e551..26c4b349d2b8e436a01db2d5d3dda8a9f86f0d31 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1,6 +1,6 @@ /****************************************************************************************************** - (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + (C) 2022-2025 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 @@ -68,6 +68,8 @@ #define IVAS_MAX16B_FLT 32767.0f #define IVAS_MIN16B_FLT ( -32768.0f ) +#define OMASA_TDREND_MATCHING_GAIN_DB ( -2.0f ) + #if !defined( DEBUGGING ) && !defined( WMOPS ) static #endif @@ -168,7 +170,7 @@ typedef struct char externalOrientationFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; char customHrtfFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; char renderConfigFilePath[RENDERER_MAX_CLI_ARG_LENGTH]; - int8_t orientation_tracking; + IVAS_HEAD_ORIENT_TRK_T orientation_tracking; int16_t Opt_Headrotation; int16_t Opt_ExternalOrientation; int16_t nonDiegeticPan; @@ -232,13 +234,13 @@ static const CmdLnParser_Option cliOptions[] = { .id = CmdLnOptionId_inputFormat, .match = "input_format", .matchShort = "if", - .description = "Audio format of input file (e.g. 5_1 or HOA3 or META, use -l for a list)", + .description = "Audio format of input file (e.g. 5_1 or HOA3 or META,\nuse -l for a list)", }, { .id = CmdLnOptionId_inputMetadata, .match = "input_metadata", .matchShort = "im", - .description = "Space-separated list of path to metadata files for ISM or MASA inputs or BINAURAL_SPLIT_PCM input mode. For OMASA, ISM files must be specified first.", + .description = "Space-separated list of path to metadata files for ISM/MASA/OMASA/\nOSBA/BINAURAL_SPLIT_PCM inputs. \nFor OMASA, ISM files must be specified first.", }, { .id = CmdLnOptionId_outputFile, @@ -256,13 +258,13 @@ static const CmdLnParser_Option cliOptions[] = { .id = CmdLnOptionId_sampleRate, .match = "sample_rate", .matchShort = "fs", - .description = "Input sampling rate in kHz (16, 32, 48) - required only with raw PCM inputs", + .description = "Input sampling rate in kHz (16, 32, 48) - required only with raw\nPCM inputs", }, { .id = CmdLnOptionId_trajFile, .match = "trajectory_file", .matchShort = "T", - .description = "Head rotation trajectory file for simulation of head tracking (only for binaural outputs)", + .description = "Head rotation trajectory file for simulation of head tracking\n(only for binaural outputs)", }, { .id = CmdLnOptionId_outputMetadata, @@ -280,43 +282,43 @@ static const CmdLnParser_Option cliOptions[] = { .id = CmdLnOptionId_refRotFile, .match = "reference_rotation_file", .matchShort = "rf", - .description = "Reference rotation trajectory file for simulation of head tracking (only for binaural outputs)", + .description = "Reference rotation trajectory file for simulation of head tracking\n(only for binaural outputs)", }, { .id = CmdLnOptionId_customHrtfFile, .match = "custom_hrtf", .matchShort = "hrtf", - .description = "Custom HRTF file for binaural rendering (only for binaural outputs)", + .description = "Custom HRTF file for binaural rendering\n(only for binaural outputs)", }, { .id = CmdLnOptionId_renderConfigFile, .match = "render_config_parameters", .matchShort = "render_config", - .description = "Binaural renderer configuration parameters in file (only for binaural outputs)", + .description = "Binaural renderer configuration parameters in file\n(only for binaural outputs)", }, { .id = CmdLnOptionId_nonDiegeticPan, .match = "non_diegetic_panning", .matchShort = "non_diegetic_pan", - .description = "Panning mono non diegetic sound to stereo -90<= pan <= 90\nleft or l or 90->left, right or r or -90->right, center or c or 0 ->middle\n", + .description = "Panning mono non diegetic sound to stereo -90<= pan <= 90\nleft or l or 90->left, right or r or -90->right,\ncenter or c or 0 ->middle", }, { .id = CmdLnOptionId_orientationTracking, .match = "tracking_type", .matchShort = "otr", - .description = "Head orientation tracking type: 'none', 'ref', 'avg' or `ref_vec` or `ref_vec_lev` (only for binaural outputs)", + .description = "Head orientation tracking type: 'none', 'ref', 'avg' or `ref_vec`\nor `ref_vec_lev` (only for binaural outputs)", }, { .id = CmdlnOptionId_lfePosition, .match = "lfe_position", .matchShort = "lp", - .description = "Output LFE position. Comma-delimited triplet of [gain, azimuth, elevation] where gain is linear (like --gain, -g) and azimuth, elevation are in degrees.\nIf specified, overrides the default behavior which attempts to map input to output LFE channel(s)", + .description = "Output LFE position. Comma-delimited triplet of [gain, azimuth,\nelevation] where gain is linear (like --gain, -g) and azimuth,\nelevation are in degrees. If specified, overrides the default\nbehavior which attempts to map input to output LFE channel(s)", }, { .id = CmdlnOptionId_lfeMatrix, .match = "lfe_matrix", .matchShort = "lm", - .description = "LFE panning matrix. File (CSV table) containing a matrix of dimensions [ num_input_lfe x num_output_channels ] with elements specifying linear routing gain (like --gain, -g). \nIf specified, overrides the output LFE position option and the default behavior which attempts to map input to output LFE channel(s)", + .description = "LFE panning matrix. File (CSV table) containing a matrix of\ndimensions [ num_input_lfe x num_output_channels ] with elements\nspecifying linear routing gain (like --gain, -g). If specified,\noverrides the output LFE position option and the default\nbehavior which attempts to map input to output LFE channel(s)", }, { .id = CmdLnOptionId_noDelayCmp, @@ -328,7 +330,7 @@ static const CmdLnParser_Option cliOptions[] = { .id = CmdLnOptionId_complexityLevel, .match = "complexity_level", .matchShort = "level", - .description = "Complexity level, level = (1, 2, 3), will be defined after characterisation.", + .description = "Complexity level, level = (1, 2, 3), will be defined after\ncharacterisation.", }, { .id = CmdLnOptionId_quietModeEnabled, @@ -352,13 +354,13 @@ static const CmdLnParser_Option cliOptions[] = { .id = CmdLnOptionId_referenceVectorFile, .match = "reference_vector_file", .matchShort = "rvf", - .description = "Reference vector trajectory file for simulation of head tracking (only for binaural outputs)", + .description = "Reference vector trajectory file for simulation of head tracking\n(only for binaural outputs)", }, { .id = CmdLnOptionId_exteriorOrientationFile, .match = "exterior_orientation_file", .matchShort = "exof", - .description = "External orientation trajectory file for simulation of external orientations", + .description = "External orientation trajectory file for simulation of external\norientations", }, { .id = CmdLnOptionId_framing, @@ -370,19 +372,19 @@ static const CmdLnParser_Option cliOptions[] = { .id = CmdLnOptionId_syncMdDelay, .match = "sync_md_delay", .matchShort = "smd", - .description = "Metadata Synchronization Delay in ms, Default is 0. Quantized by 5ms subframes for TDRenderer (13ms -> 10ms -> 2subframes)", + .description = "Metadata Synchronization Delay in ms, Default is 0. Quantized by\n5ms subframes for TDRenderer (13ms -> 10ms -> 2subframes)", }, { .id = CmdLnOptionId_directivityPatternId, .match = "ism_directivity_pattern_id", .matchShort = "dpid", - .description = "Directivity pattern ID(s) = [ID1, ID2, ID3, ID4]. Space-separated list of up to 4 numbers (unsigned integers) can be specified for BINAURAL and BINAURAL_ROOM_REVERB output configuration.\nID1, ID2, ID3, ID4 specify the directivity pattern IDs used for ISMs 1,2,3 and 4 respectively.\nThis options needs to be accompanied by a render_config file, otherwise a default directivity pattern is used.", + .description = "Directivity pattern ID(s) = [ID1, ID2, ID3, ID4]. Space-separated\nlist of up to 4 numbers (unsigned integers) can be specified for\nBINAURAL and BINAURAL_ROOM_REVERB output.\nID1, ID2, ID3, ID4 specify the directivity pattern IDs used for\nISMs 1,2,3 and 4 respectively. \nThis option needs to be accompanied by a render_config file,\notherwise a default directivity pattern is used.", }, { .id = CmdLnOptionId_acousticEnvironmentId, .match = "acoustic_environment_id", .matchShort = "aeid", - .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.", + .description = "Acoustic environment ID (number > 0) alternatively, it can be\na text file where each line contains \"ID duration\" for\nBINAURAL_ROOM_REVERB output.", }, }; @@ -562,12 +564,19 @@ static void setupWithSingleFormatInput( positionProvider->numObjects = args.inConfig.numAudioObjects; for ( int16_t i = 0; i < positionProvider->numObjects; ++i ) { - /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string is empty or contains "NULL" */ + /* Check if path to metadata file was given */ + if ( isEmptyString( args.inMetadataFilePaths[i] ) ) + { + fprintf( stderr, "No metadata file was given for ISM input %d\n", i ); + exit( -1 ); + } + + /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string contains "NULL" */ char charBuf[FILENAME_MAX]; strncpy( charBuf, args.inMetadataFilePaths[i], min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1 ); charBuf[min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1] = '\0'; to_upper( charBuf ); - if ( isEmptyString( args.inMetadataFilePaths[i] ) || strncmp( charBuf, "NULL", 4 ) == 0 ) + if ( strncmp( charBuf, "NULL", 4 ) == 0 ) { continue; } @@ -659,12 +668,13 @@ int main( int argc, char **argv ) { - IVAS_REND_HANDLE hIvasRend; + bool mainFailed = true; /* Assume main failed until cleanup is reached without errors */ + IVAS_REND_HANDLE hIvasRend = NULL; RotFileReader *headRotReader = NULL; RotFileReader *externalOrientationFileReader = NULL; RotFileReader *referenceRotReader = NULL; - IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS]; - IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_INPUT_CHANNELS]; + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[RENDERER_MAX_INPUT_CHANNELS]; + IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[RENDERER_MAX_INPUT_CHANNELS]; int16_t cldfb_in_flag, CLDFBframeSize_smpls; SplitRendBFIFileReader *splitRendBFIReader = NULL; Vector3PairFileReader *referenceVectorReader = NULL; @@ -674,7 +684,7 @@ int main( IVAS_DEC_HRTF_PARAMBIN_HANDLE *hHrtfParambin = NULL; IVAS_DEC_HRTF_HANDLE *hHrtfTD = NULL; IVAS_DEC_HRTF_STATISTICS_HANDLE *hHrtfStatistics = NULL; - IsmPositionProvider *positionProvider; + IsmPositionProvider *positionProvider = NULL; LfeRoutingConfig *lfeRoutingConfigs[RENDERER_MAX_MC_INPUTS]; RenderConfigReader *renderConfigReader = NULL; MasaFileReader *masaReaders[RENDERER_MAX_MASA_INPUTS]; @@ -682,14 +692,14 @@ int main( IVAS_MASA_METADATA_HANDLE hMasaMetadata[RENDERER_MAX_MASA_INPUTS]; char audioFilePath[FILENAME_MAX]; AudioFileReader *audioReader = NULL; - AudioFileWriter *audioWriter; + AudioFileWriter *audioWriter = NULL; int32_t inBufferSize; int32_t outBufferSize; int32_t bitsBufferSize; - int16_t *inpInt16Buffer; - float *inFloatBuffer; - int16_t *outInt16Buffer; - float *outFloatBuffer; + int16_t *inpInt16Buffer = NULL; + float *inFloatBuffer = NULL; + int16_t *outInt16Buffer = NULL; + float *outFloatBuffer = NULL; uint8_t *bitsBufferData = NULL; IVAS_REND_AudioBuffer inBuffer; IVAS_REND_AudioBuffer outBuffer; @@ -697,6 +707,7 @@ int main( SplitFileReadWrite *hSplitRendFileReadWrite; int16_t delayNumSamples_temp; int32_t delayTimeScale_temp; + bool flushRendererLastFrame = false; int16_t numSamplesRead; int16_t delayNumSamples = -1; int16_t delayNumSamples_orig = 0; @@ -741,17 +752,20 @@ int main( CmdlnArgs args = parseCmdlnArgs( argc, argv ); - if ( args.nonDiegeticPan && !( ( args.inConfig.numAudioObjects == 0 && args.inConfig.multiChannelBuses[0].audioConfig == IVAS_AUDIO_CONFIG_MONO ) || - ( args.inConfig.numAudioObjects > 0 && args.inConfig.audioObjects[0].audioConfig == IVAS_AUDIO_CONFIG_OBA && args.inConfig.numAudioObjects == 1 ) ) ) + if ( args.nonDiegeticPan && + !( ( args.inConfig.numAudioObjects == 0 && + args.inConfig.multiChannelBuses[0].audioConfig == IVAS_AUDIO_CONFIG_MONO ) || + ( args.inConfig.numAudioObjects > 0 && + args.inConfig.audioObjects[0].audioConfig == IVAS_AUDIO_CONFIG_OBA && args.inConfig.numAudioObjects == 1 ) ) ) { fprintf( stderr, "\ninvalid configuration - non-diegetic panning requires mono or ISM1 input\n" ); - exit( -1 ); + goto cleanup; } if ( args.nonDiegeticPan && args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_STEREO ) { fprintf( stderr, "\ninvalid configuration - non-diegetic panning requires stereo output\n" ); - exit( -1 ); + goto cleanup; } positionProvider = IsmPositionProvider_open(); @@ -768,8 +782,8 @@ int main( { if ( RotationFileReader_open( args.headRotationFilePath, &headRotReader ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", args.headRotationFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", args.headRotationFilePath ); + goto cleanup; } } @@ -777,16 +791,16 @@ int main( { if ( RotationFileReader_open( args.referenceRotationFilePath, &referenceRotReader ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", args.referenceRotationFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", args.referenceRotationFilePath ); + goto cleanup; } } if ( !isEmptyString( args.referenceVectorFilePath ) ) { if ( Vector3PairFileReader_open( args.referenceVectorFilePath, &referenceVectorReader ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", args.referenceVectorFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", args.referenceVectorFilePath ); + goto cleanup; } } @@ -800,8 +814,8 @@ int main( { if ( RotationFileReader_open( args.externalOrientationFilePath, &externalOrientationFileReader ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", args.externalOrientationFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", args.externalOrientationFilePath ); + goto cleanup; } } @@ -810,8 +824,8 @@ int main( { if ( RenderConfigReader_open( args.renderConfigFilePath, &renderConfigReader ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", args.renderConfigFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", args.renderConfigFilePath ); + goto cleanup; } } @@ -834,21 +848,21 @@ int main( { fprintf( stderr, "\nInvalid configuration - Merging to MASA output requires MASA input and at least one another input to be present\n" ); fprintf( stderr, "\nMASA input is missing\n" ); - exit( -1 ); + goto cleanup; } if ( args.inConfig.numAudioObjects == 0 && args.inConfig.numMultiChannelBuses == 0 && args.inConfig.numAmbisonicsBuses == 0 ) { fprintf( stderr, "\nInvalid configuration - Merging to MASA output requires MASA input and at least one another input to be present\n" ); fprintf( stderr, "\nNo object, multi-channel, or Ambisonic input present.\n" ); - exit( -1 ); + goto cleanup; } } if ( AudioFileReader_open( &audioReader, audioFilePath ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", audioFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", audioFilePath ); + goto cleanup; } int32_t inFileSampleRate = 0; @@ -864,36 +878,36 @@ int main( /* else if sampling rate given on command line, compare with wav file */ else if ( inFileSampleRate != args.sampleRate ) { - fprintf( stderr, "Sampling rate mismatch: %d Hz requested, but %d Hz found in file %s\n", args.sampleRate, inFileSampleRate, args.inputFilePath ); - exit( -1 ); + fprintf( stderr, "\nSampling rate mismatch: %d Hz requested, but %d Hz found in file %s\n", args.sampleRate, inFileSampleRate, args.inputFilePath ); + goto cleanup; } break; case IVAS_ERR_SAMPLING_RATE_UNKNOWN: /* Returned when input is raw PCM */ if ( args.sampleRate == 0 ) { - fprintf( stderr, "Sampling rate must be specified on command line when using raw PCM input\n" ); - exit( -1 ); + fprintf( stderr, "\nSampling rate must be specified on command line when using raw PCM input\n" ); + goto cleanup; } break; default: - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nAudioFileReader_getSamplingRate failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } int16_t inFileNumChannels = 0; error = AudioFileReader_getNumChannels( audioReader, &inFileNumChannels ); if ( error != IVAS_ERR_OK && error != IVAS_ERR_NUM_CHANNELS_UNKNOWN ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nAudioFileReader_getNumChannels failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } const int16_t frameSize_smpls = (int16_t) ( ( args.render_framesize ) * args.sampleRate * 5 / ( 1000 ) ); if ( ( error = IVAS_REND_Open( &hIvasRend, args.sampleRate, args.outConfig.audioConfig, !isEmptyString( args.customHrtfFilePath ), args.nonDiegeticPan, args.nonDiegeticPanGain, args.Opt_Headrotation, args.Opt_ExternalOrientation, (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening renderer handle: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError opening renderer handle: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } fprintf( stdout, "Input audio file: %s\n", args.inputFilePath ); @@ -941,8 +955,8 @@ int main( { if ( hrtfFileReader_open( args.customHrtfFilePath, &hrtfFileReader ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error opening file: %s\n", args.customHrtfFilePath ); - exit( -1 ); + fprintf( stderr, "\nError opening file: %s\n", args.customHrtfFilePath ); + goto cleanup; } if ( hrtfFileReader != NULL ) @@ -1055,30 +1069,45 @@ int main( /* === Configure === */ if ( ( error = IVAS_REND_InitConfig( hIvasRend, args.outConfig.audioConfig ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in Renderer Config Init: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in Renderer Config Init: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( args.renderConfigFilePath[0] != '\0' ) { /* sanity check */ - if ( ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && !is_split_pre_rend_mode( &args ) ) + if ( ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL ) && + ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && + ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && + !is_split_pre_rend_mode( &args ) ) { fprintf( stderr, "\nExternal Renderer Config is supported only when binaural output configurations is used as output OR when Split pre-rendering mode is enabled. Exiting. \n" ); - exit( -1 ); + goto cleanup; } if ( ( error = IVAS_REND_GetRenderConfig( hIvasRend, &renderConfig ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + goto cleanup; } if ( RenderConfigReader_read( renderConfigReader, args.renderConfigFilePath, &renderConfig ) != IVAS_ERR_OK ) { - fprintf( stderr, "Failed to read renderer configuration from file %s\n", args.renderConfigFilePath ); - exit( -1 ); + fprintf( stderr, "\nFailed to read renderer configuration from file %s\n", args.renderConfigFilePath ); + goto cleanup; + } + + if ( ( error = RenderConfigReader_getDirectivity( renderConfigReader, args.directivityPatternId, renderConfig.directivity ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to get directivity patterns for one or more of IDs: %d %d %d %d\n\n", args.directivityPatternId[0], args.directivityPatternId[1], args.directivityPatternId[2], args.directivityPatternId[3] ); + goto cleanup; + } + + if ( ( error = RenderConfigReader_getDistanceAttenuation( renderConfigReader, renderConfig.distAtt ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "Failed to get Distance Attenuation \n\n" ); + goto cleanup; } if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) @@ -1088,14 +1117,14 @@ int main( { if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) { - fprintf( stderr, "Invalid room acoustics configuration parameters\n\n" ); - exit( -1 ); + fprintf( stderr, "\nInvalid room acoustics configuration parameters\n\n" ); + goto cleanup; } } else { - fprintf( stderr, "Failed to get acoustic environment with ID: %d\n\n", aeID ); - exit( -1 ); + fprintf( stderr, "\nFailed to get acoustic environment with ID: %d\n\n", aeID ); + goto cleanup; } } @@ -1106,7 +1135,7 @@ int main( if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_FeedRenderConfig failed: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + goto cleanup; } CLDFBframeSize_smpls = frameSize_smpls * 2; @@ -1115,8 +1144,8 @@ int main( if ( ( error = IVAS_REND_SetOrientationTrackingMode( hIvasRend, args.orientation_tracking ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_SetOrientationTrackingMode(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_SetOrientationTrackingMode(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } /* Set up output custom layout configuration */ @@ -1124,8 +1153,8 @@ int main( { if ( ( error = IVAS_REND_ConfigureCustomOutputLoudspeakerLayout( hIvasRend, args.outConfig.outSetupCustom ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_ConfigureCustomOutputLoudspeakerLayout(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_ConfigureCustomOutputLoudspeakerLayout(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1135,24 +1164,34 @@ int main( MasaFileWriter_open( args.outputFilePath, true, &masaWriter ); /* No delay for audio in renderer, so calling metadata writer in delayCompensated mode, i.e., no delay applied to meta */ if ( masaWriter == NULL ) { - fprintf( stderr, "Could not open MASA metadata file %s\n", args.outputFilePath ); - exit( -1 ); + fprintf( stderr, "\nCould not open MASA metadata file %s\n", args.outputFilePath ); + goto cleanup; } } - /* Set the total number of objects */ if ( args.inConfig.numAudioObjects > 0 ) { + /* Set the total number of objects */ if ( ( error = IVAS_REND_SetTotalNumberOfObjects( hIvasRend, args.inConfig.numAudioObjects ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_SetTotalNumberOfObjects(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_SetTotalNumberOfObjects(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } + /* Set the metadata delay for objects */ if ( ( error = IVAS_REND_SetIsmMetadataDelay( hIvasRend, args.syncMdDelay ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_SetIsmMetadataDelay(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_SetIsmMetadataDelay(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; + } + + /* For OMASA input and BINAURAL output, apply a gain to objects to match the loudness with MASA part */ + if ( args.inConfig.numMasaBuses > 0 && args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL ) + { + for ( i = 0; i < args.inConfig.numAudioObjects; ++i ) + { + args.inConfig.audioObjects[i].gain_dB += OMASA_TDREND_MATCHING_GAIN_DB; + } } } @@ -1163,8 +1202,8 @@ int main( { if ( ( error = parseLfePanMtxFile( args.inLfePanningMatrixFile, &lfePanMatrix ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1194,22 +1233,22 @@ int main( { if ( ( error = IVAS_REND_AddInput( hIvasRend, args.inConfig.multiChannelBuses[i].audioConfig, &mcIds[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_AddInput failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetInputGain( hIvasRend, mcIds[i], args.inputGainGlobal * dBToLin( args.inConfig.multiChannelBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( args.inConfig.multiChannelBuses[i].audioConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) { if ( ( error = IVAS_REND_ConfigureCustomInputLoudspeakerLayout( hIvasRend, mcIds[i], args.inConfig.inSetupCustom ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_ConfigureCustomInputLoudspeakerLayout(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_ConfigureCustomInputLoudspeakerLayout(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1218,14 +1257,14 @@ int main( { if ( args.lfePanningEnabled ) { - fprintf( stderr, "Warning: LFE position specified as well as panning matrix! Ignoring position and using gains from panning matrix\n" ); + fprintf( stderr, "\nWarning: LFE position specified as well as panning matrix! Ignoring position and using gains from panning matrix\n" ); args.lfePanningEnabled = false; } if ( ( error = IVAS_REND_SetInputLfeMtx( hIvasRend, mcIds[i], (const IVAS_REND_LfePanMtx *) &lfePanMatrix ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputLfeMtx failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } /* set panning gains for input LFE */ @@ -1233,8 +1272,8 @@ int main( { if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], args.lfeConfigGain, args.lfeConfigAzimuth, args.lfeConfigElevation ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputLfePos failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } else @@ -1247,14 +1286,14 @@ int main( { if ( ( error = parseLfePanMtxFile( lfeRoutingConfigs[i]->lfe_routing_mtx, &lfePanMatrix ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nparseLfePanMtxFile failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetInputLfeMtx( hIvasRend, mcIds[i], (const IVAS_REND_LfePanMtx *) &lfePanMatrix ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputLfeMtx failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } /* set position based gains */ @@ -1262,8 +1301,8 @@ int main( { if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], lfeRoutingConfigs[i]->lfe_gain_dB, lfeRoutingConfigs[i]->lfe_azi, lfeRoutingConfigs[i]->lfe_ele ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputLfePos failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } @@ -1274,14 +1313,14 @@ int main( { if ( ( error = IVAS_REND_AddInput( hIvasRend, IVAS_AUDIO_CONFIG_OBA, &ismIds[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_AddInput: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetInputGain( hIvasRend, ismIds[i], args.inputGainGlobal * dBToLin( args.inConfig.audioObjects[i].gain_dB ) ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } /* With MASA output, all objects are handled at once, so add only one input having all objects in it */ @@ -1295,14 +1334,14 @@ int main( { if ( ( error = IVAS_REND_AddInput( hIvasRend, args.inConfig.ambisonicsBuses[i].audioConfig, &sbaIds[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_AddInput failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetInputGain( hIvasRend, sbaIds[i], args.inputGainGlobal * dBToLin( args.inConfig.ambisonicsBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1310,14 +1349,14 @@ int main( { if ( ( error = IVAS_REND_AddInput( hIvasRend, args.inConfig.masaBuses[i].audioConfig, &masaIds[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_AddInput failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetInputGain( hIvasRend, masaIds[i], args.inputGainGlobal * dBToLin( args.inConfig.masaBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1325,8 +1364,8 @@ int main( if ( inFileNumChannels != 0 /* inFileNumChannels is 0 with raw PCM input */ && totalNumInChannels != inFileNumChannels ) { - fprintf( stderr, "Number of channels in input file does not match selected configuration\n" ); - exit( -1 ); + fprintf( stderr, "\nNumber of channels in input file does not match selected configuration\n" ); + goto cleanup; } for ( i = 0; i < args.inConfig.numMasaBuses; ++i ) @@ -1338,69 +1377,56 @@ int main( } int16_t numOutChannels; - if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_GetNumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_NumOutChannels(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_NumOutChannels(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( cldfb_in_flag ) { if ( ( error = IVAS_REND_openCldfb( cldfbAna, cldfbSyn, totalNumInChannels, numOutChannels, args.sampleRate ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_openCldfb(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_openCldfb(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } - if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { + char *outFile = args.outMetadataFilePath; + + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + outFile = args.outputFilePath; + audioWriter = NULL; + } + if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms, &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_GetSplitRendBitstreamHeader()!\n" ); - exit( -1 ); + goto cleanup; } if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to get delay of renderer!\n" ); - exit( -1 ); + goto cleanup; } - if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outputFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) + if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, outFile, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Could not open split rend metadata file %s\n", args.outputFilePath ); - exit( -1 ); + fprintf( stderr, "\nCould not open split rend metadata file %s\n", outFile ); + goto cleanup; } - audioWriter = NULL; } - else - { - if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms, &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_REND_GetSplitRendBitstreamHeader()!\n" ); - exit( -1 ); - } - - if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nUnable to get delay of renderer!\n" ); - exit( -1 ); - } - - if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outMetadataFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "Could not open split rend metadata file %s\n", args.outMetadataFilePath ); - exit( -1 ); - } - } + if ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) { - fprintf( stderr, "Failed to open file: %s\n", args.outputFilePath ); - exit( -1 ); + fprintf( stderr, "\nFailed to open file: %s\n", args.outputFilePath ); + goto cleanup; } } @@ -1436,7 +1462,7 @@ int main( if ( is_split_pre_rend_mode( &args ) ) { - bitsBufferSize = SPLIT_REND_BITS_BUFF_SIZE; + bitsBufferSize = ISAR_SPLIT_REND_BITS_BUFF_SIZE; } else { @@ -1494,13 +1520,13 @@ int main( { if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) { - fprintf( stderr, "Invalid acoustic environment configuration parameters\n\n" ); + fprintf( stderr, "\nInvalid acoustic environment configuration parameters\n\n" ); goto cleanup; } } else { - fprintf( stderr, "Failed to get acoustic environment with ID %d\n\n", args.aeSequence.pID[args.aeSequence.selected] ); + fprintf( stderr, "\nFailed to get acoustic environment with ID %d\n\n", args.aeSequence.pID[args.aeSequence.selected] ); goto cleanup; } if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK ) @@ -1516,22 +1542,29 @@ int main( if ( ( error = AudioFileReader_read( audioReader, inpInt16Buffer, (int16_t) inBufferSize, &numSamplesRead ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError reading from file %s\n", audioFilePath ); - exit( -1 ); + goto cleanup; } if ( numSamplesRead == 0 ) { /* end of input data */ - break; + flushRendererLastFrame = true; } /* Convert from int to float and from interleaved to packed */ - convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer, inBuffer.config.is_cldfb, cldfbAna ); + if ( !flushRendererLastFrame ) + { + convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer, inBuffer.config.is_cldfb, cldfbAna ); + } + else + { + memset( inBuffer.data, 0, inBuffer.config.numChannels * inBuffer.config.numSamplesPerChannel * sizeof( float ) ); + } int16_t num_subframes, sf_idx; num_subframes = (int16_t) args.render_framesize; - if ( isCurrentFrameMultipleOf20ms ) + if ( isCurrentFrameMultipleOf20ms && !flushRendererLastFrame ) { IsmPositionProvider_getNextFrame( positionProvider, &mtdBuffer ); @@ -1540,13 +1573,13 @@ int main( IVAS_VECTOR3 listenerPos, refPos; if ( ( error = Vector3PairFileReader_read( referenceVectorReader, &listenerPos, &refPos ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nVector3PairFileReader_read failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetReferenceVector( hIvasRend, listenerPos, refPos ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_SetReferenceVector failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } /* Read from reference rotation trajectory file if specified */ @@ -1557,14 +1590,14 @@ int main( IVAS_QUATERNION quaternions[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; if ( ( error = HeadRotationFileReading( referenceRotReader, &quaternions[sf_idx], NULL ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetReferenceRotation( hIvasRend, quaternions[sf_idx] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error setting Reference Rotation: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError setting Reference Rotation: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } @@ -1580,14 +1613,14 @@ int main( if ( ( error = HeadRotationFileReading( headRotReader, &headRot, &Pos ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in Head Rotation File Reading: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_SetHeadRotation( hIvasRend, headRot, Pos, DEFAULT_AXIS, sf_idx ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error setting Head Rotation: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError setting Head Rotation: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } @@ -1595,8 +1628,8 @@ int main( { if ( ( error = IVAS_REND_DisableHeadRotation( hIvasRend ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error disabling head rotation: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError disabling head rotation: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1612,16 +1645,16 @@ int main( { if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, &quatBuffer[sf_idx], &enableHeadRotation[sf_idx], &enableExternalOrientation[sf_idx], &enableRotationInterpolation[sf_idx], &numFramesToTargetOrientation[sf_idx] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in External Orientation File Reading: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in External Orientation File Reading: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { if ( ( error = IVAS_REND_SetExternalOrientation( hIvasRend, &quatBuffer[sf_idx], enableHeadRotation[sf_idx], enableExternalOrientation[sf_idx], enableRotationInterpolation[sf_idx], numFramesToTargetOrientation[sf_idx], sf_idx ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error setting External Orientation: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError setting External Orientation: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } @@ -1630,23 +1663,23 @@ int main( if ( ( error = IVAS_REND_CombineHeadAndExternalOrientation( hIvasRend ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error combining external and head orientations: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError combining external and head orientations: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } for ( i = 0; i < args.inConfig.numMultiChannelBuses; ++i ) { if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, mcIds[i], &numChannels ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.multiChannelBuses[i].inputChannelIndex, numChannels ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, mcIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, mcIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1658,33 +1691,33 @@ int main( { IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, args.inConfig.numAudioObjects ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } if ( ( error = IVAS_REND_FeedInputObjectMetadataToOMasa( hIvasRend, i, mtdBuffer.positions[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_FeedInputObjectMetadataToOMasa failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } else { IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, 1 ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_FeedInputObjectMetadata( hIvasRend, ismIds[i], mtdBuffer.positions[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_FeedInputObjectMetadata failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } @@ -1693,15 +1726,15 @@ int main( { if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, sbaIds[i], &numChannels ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.ambisonicsBuses[i].inputChannelIndex, numChannels ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, sbaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, sbaIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1709,32 +1742,32 @@ int main( { if ( ( error = IVAS_REND_GetInputNumChannels( hIvasRend, masaIds[i], &numChannels ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "IVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.masaBuses[i].inputChannelIndex, numChannels ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, masaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, masaIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "IVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } - if ( isCurrentFrameMultipleOf20ms ) + if ( isCurrentFrameMultipleOf20ms && !flushRendererLastFrame ) { if ( masaReaders[i] != NULL ) { /* This will update data in hMasaMetadata[i] */ if ( ( error = MasaFileReader_readNextFrame( masaReaders[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in MASA Metadata File Reading: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in MASA Metadata File Reading: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } if ( ( error = IVAS_REND_FeedInputMasaMetadata( hIvasRend, masaIds[i], hMasaMetadata[i] ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error: %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nIVAS_REND_FeedInputMasaMetadata failed: %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } @@ -1744,16 +1777,16 @@ int main( { if ( ( error = IVAS_REND_GetSplitBinauralBitstream( hIvasRend, outBuffer, &bitsBuffer ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_GetSplitBinauralBitstream(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_GetSplitBinauralBitstream(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } else { if ( ( error = IVAS_REND_GetSamples( hIvasRend, outBuffer ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_GetSamples()%s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_GetSamples()%s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1771,7 +1804,7 @@ int main( if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples, &delayTimeScale ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to get delay of renderer!\n" ); - exit( -1 ); + goto cleanup; } delayNumSamples_orig = delayNumSamples; @@ -1783,24 +1816,24 @@ int main( zeroPad = delayNumSamples; } - if ( is_split_pre_rend_mode( &args ) ) + if ( is_split_pre_rend_mode( &args ) && !flushRendererLastFrame ) { if ( split_rend_write_bitstream_to_file( hSplitRendFileReadWrite, bitsBuffer.bits, &bitsBuffer.config.bitsRead, &bitsBuffer.config.bitsWritten ) != IVAS_ERR_OK ) { fprintf( stderr, "\nUnable to write to bitstream file!\n" ); - exit( -1 ); + goto cleanup; } } - if ( audioWriter != NULL ) + if ( audioWriter != NULL && !flushRendererLastFrame ) { if ( delayNumSamples * num_out_channels < outBufferSize ) { if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error writing audio file %s\n", args.outputFilePath ); - exit( -1 ); + fprintf( stderr, "\nError writing audio file %s\n", args.outputFilePath ); + goto cleanup; } delayNumSamples = 0; } @@ -1814,7 +1847,7 @@ int main( bitsBuffer.config.bitsWritten = 0; /* Write MASA metadata for MASA outputs */ - if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA1 || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) + if ( !flushRendererLastFrame && ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA1 || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) ) { IVAS_REND_AudioConfigType inputType1; IVAS_REND_AudioConfigType inputType2; @@ -1860,8 +1893,8 @@ int main( { if ( ( error = IVAS_REND_GetMasaMetadata( hIvasRend, &hMetaOutput, inputType1 ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_GetMasaMetadata(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_GetMasaMetadata(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } else @@ -1871,8 +1904,8 @@ int main( inputType2 = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED; if ( ( error = IVAS_REND_MergeMasaMetadata( hIvasRend, &hMetaOutput, inputType1, inputType2 ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_MergeMasaMetadata(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_MergeMasaMetadata(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } @@ -1881,18 +1914,19 @@ int main( inputType2 = IVAS_REND_AUDIO_CONFIG_TYPE_MASA; if ( ( error = IVAS_REND_MergeMasaMetadata( hIvasRend, &hMetaOutput, inputType1, inputType2 ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_MergeMasaMetadata(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_MergeMasaMetadata(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } - if ( ( args.inConfig.numAmbisonicsBuses > 0 || args.inConfig.numMultiChannelBuses > 0 || args.inConfig.numMasaBuses > 0 ) && args.inConfig.numAudioObjects > 0 ) + if ( ( args.inConfig.numAmbisonicsBuses > 0 || args.inConfig.numMultiChannelBuses > 0 || args.inConfig.numMasaBuses > 0 ) && + args.inConfig.numAudioObjects > 0 ) { inputType2 = IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED; if ( ( error = IVAS_REND_MergeMasaMetadata( hIvasRend, &hMetaOutput, inputType1, inputType2 ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "Error in IVAS_REND_MergeMasaMetadata(): %s\n", ivas_error_to_string( error ) ); - exit( -1 ); + fprintf( stderr, "\nError in IVAS_REND_MergeMasaMetadata(): %s\n", ivas_error_to_string( error ) ); + goto cleanup; } } } @@ -1903,6 +1937,13 @@ int main( } } + /* no new input was actually read, only delay buffers were flushed + * therefore this is not a real frame */ + if ( flushRendererLastFrame ) + { + break; + } + frame++; if ( !args.quietModeEnabled ) { @@ -1915,31 +1956,32 @@ int main( #endif } - /* add zeros at the end to have equal length of synthesized signals */ + /* add zeros at the end to have equal length of synthesized signals + * the output buffer will contain either leftover input samples from delay aligned inputs + * or zeros for padding */ if ( audioWriter != NULL ) { for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) { - memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); - exit( -1 ); + goto cleanup; } } - memset( outInt16Buffer, 0, zeroPadToWrite * outBuffer.config.numChannels * sizeof( int16_t ) ); if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); - exit( -1 ); + goto cleanup; } zeroPadToWrite = 0; } - if ( args.inConfig.numAudioObjects != 0 && ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + if ( args.inConfig.numAudioObjects != 0 && + ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) { - fprintf( stdout, "\n\nMetadata delayed %d subframes\n\n", (int16_t) round( args.syncMdDelay / ( 1000 / IVAS_NUM_FRAMES_PER_SEC / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); + fprintf( stdout, "\n\nMetadata delayed %d subframes\n\n", (int16_t) round( args.syncMdDelay / ( 1000.f / IVAS_NUM_FRAMES_PER_SEC / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); } if ( !args.quietModeEnabled && args.delayCompensationEnabled ) @@ -1961,14 +2003,19 @@ int main( } #endif - /* === Close === */ + /*------------------------------------------------------------------------------------------* + * Close files and deallocate resources + *------------------------------------------------------------------------------------------*/ + + mainFailed = false; /* This will stay set to true if cleanup is reached via a goto due to an error */ + +cleanup: + free( inpInt16Buffer ); free( inFloatBuffer ); free( outInt16Buffer ); free( outFloatBuffer ); -cleanup: - if ( bitsBufferData != NULL ) { free( bitsBufferData ); @@ -2018,7 +2065,7 @@ cleanup: print_mem( NULL ); #endif - return 0; + return mainFailed ? -1 : 0; } @@ -2265,7 +2312,7 @@ static bool parseRenderFramesize( static bool parseOrientationTracking( char *value, - int8_t *orientation_tracking ) + IVAS_HEAD_ORIENT_TRK_T *orientation_tracking ) { to_upper( value ); @@ -2537,6 +2584,7 @@ static CmdlnArgs defaultArgs( const char *executableName ) { CmdlnArgs args; + int16_t i; strncpy( args.executableName, executableName, RENDERER_MAX_CLI_ARG_LENGTH ); clearString( args.inputFilePath ); @@ -2555,7 +2603,7 @@ static CmdlnArgs defaultArgs( args.outConfig.outSetupCustom.num_lfe = 0; args.inConfig.ambisonicsBuses->audioConfig = IVAS_AUDIO_CONFIG_INVALID; - for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS + RENDERER_MAX_MASA_INPUTS; ++i ) { clearString( args.inMetadataFilePaths[i] ); } @@ -2592,7 +2640,7 @@ static CmdlnArgs defaultArgs( args.render_framesize = IVAS_RENDER_FRAMESIZE_20MS; args.syncMdDelay = 0; - for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) { args.directivityPatternId[i] = 65535; } @@ -3264,7 +3312,8 @@ static void parseObjectPosition( *positionDuration = (uint16_t) strtol( line, &endptr, 10 ); readNextMetadataChunk( line, "\n" ); - read_values = (int16_t) sscanf( line, "%f,%f,%f,%f,%f,%f,%f,%f", &meta_prm[0], &meta_prm[1], &meta_prm[2], &meta_prm[3], &meta_prm[4], &meta_prm[5], &meta_prm[6], &meta_prm[7] ); + read_values = (int16_t) sscanf( line, "%f,%f,%f,%f,%f,%f,%f,%f", + &meta_prm[0], &meta_prm[1], &meta_prm[2], &meta_prm[3], &meta_prm[4], &meta_prm[5], &meta_prm[6], &meta_prm[7] ); if ( read_values < 2 ) { @@ -3473,14 +3522,8 @@ static void parseCombinedFormatInput( inConfig->numAmbisonicsBuses = 1; inConfig->ambisonicsBuses[0].audioConfig = audioConfig; inConfig->ambisonicsBuses[0].inputChannelIndex = inConfig->numAudioObjects; - inConfig->ambisonicsBuses[0].gain_dB = -6.f; + inConfig->ambisonicsBuses[0].gain_dB = 0.f; *configString += 4; - - /* Modify input gain for objects too */ - for ( int16_t i = 0; i < inConfig->numAudioObjects; ++i ) - { - inConfig->audioObjects[i].gain_dB = -6.f; - } } else if ( audioConfig == IVAS_AUDIO_CONFIG_MASA1 || audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) { @@ -3719,6 +3762,7 @@ static void printSupportedAudioConfigs( void ) "BINAURAL_SPLIT_CODED", "BINAURAL_ROOM_IR (output only)", "BINAURAL_ROOM_REVERB (output only)", + "META (Scene description, input only)", }; fprintf( stdout, "Supported audio formats:\n" ); @@ -3726,6 +3770,7 @@ static void printSupportedAudioConfigs( void ) { fprintf( stdout, "%s\n", supportedFormats[i] ); } + fprintf( stdout, "\n" ); return; } @@ -3736,7 +3781,7 @@ static ivas_error parseLfePanMtxFile( { int16_t i, lfe_in, ch_out; const char *tok; - char line[200]; /* > (10 chars * IVAS_MAX_OUTPUT_CHANNELS) i.e. "-999, " */ + char line[200]; /* > (10 chars * RENDERER_MAX_OUTPUT_CHANNELS) i.e. "-999, " */ FILE *mtxFile; if ( strlen( lfeRoutingMatrixFilePath ) < 1 ) @@ -3755,7 +3800,7 @@ static ivas_error parseLfePanMtxFile( any subsequent issue in file reading will gracefully exit the function */ for ( lfe_in = 0; lfe_in < RENDERER_MAX_INPUT_LFE_CHANNELS; lfe_in++ ) { - for ( i = 0; i < IVAS_MAX_OUTPUT_CHANNELS; i++ ) + for ( i = 0; i < RENDERER_MAX_OUTPUT_CHANNELS; i++ ) { ( *lfePanMtx )[lfe_in][i] = 0.0f; } @@ -3783,7 +3828,7 @@ static ivas_error parseLfePanMtxFile( { continue; } - if ( ch_out > IVAS_MAX_OUTPUT_CHANNELS ) + if ( ch_out > RENDERER_MAX_OUTPUT_CHANNELS ) { break; } @@ -3824,13 +3869,13 @@ static void convertInputBuffer( if ( cldfb_in_flag ) { int16_t slotIdx, numCldfbBands, numFloatPcmSamples; - float fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; + float fIn[RENDERER_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; numFloatPcmSamples = numFloatSamplesPerChannel >> 1; numCldfbBands = numFloatPcmSamples / IVAS_CLDFB_NO_COL_MAX; /* CLDFB Analysis*/ - assert( numIntSamplesPerChannel <= IVAS_MAX_OUTPUT_CHANNELS * IVAS_MAX_FRAME_SIZE ); + assert( numIntSamplesPerChannel <= RENDERER_MAX_OUTPUT_CHANNELS * IVAS_MAX_FRAME_SIZE ); for ( smpl = 0; smpl < numFloatPcmSamples; ++smpl ) { for ( chnl = 0; chnl < numChannels; ++chnl ) @@ -3905,9 +3950,9 @@ static void convertOutputBuffer( if ( cldfb_in_flag ) { int16_t slotIdx, numCldfbBands, numPcmSamples, b; - float fIn[IVAS_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; - float re[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; - float im[IVAS_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; + float fIn[RENDERER_MAX_OUTPUT_CHANNELS][IVAS_MAX_FRAME_SIZE]; + float re[RENDERER_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; + float im[RENDERER_MAX_OUTPUT_CHANNELS][IVAS_CLDFB_NO_COL_MAX][IVAS_CLDFB_NO_CHANNELS_MAX]; numPcmSamples = numSamplesPerChannel >> 1; numCldfbBands = numPcmSamples / IVAS_CLDFB_NO_COL_MAX; diff --git a/ci/basop-pages/basop_index.html b/ci/basop-pages/basop_index.html index a31f3673a531c53d97092d177d00d24c0ebdf922..c7203a9259ca65e7b0079ad8a2a0bbda99684107 100644 --- a/ci/basop-pages/basop_index.html +++ b/ci/basop-pages/basop_index.html @@ -5,6 +5,10 @@

Ivas BASOP code Development

+

Regression tracking

+ +
  • Long term regression
  • +

    Daily long testvector tests

      diff --git a/ci/basop-pages/create_report_pages.py b/ci/basop-pages/create_report_pages.py index 2f01db7bdec36df2a5748b76b88035792254a091..6cb6602de72af3d04d7bf9382dc9fc78ff9fe890 100644 --- a/ci/basop-pages/create_report_pages.py +++ b/ci/basop-pages/create_report_pages.py @@ -5,7 +5,7 @@ from functools import partial FORMATS = ["Stereo", "ISM", "Multichannel", "MASA", "SBA", "OSBA", "OMASA", "Renderer"] -CSV_DELIM = ";" +CSV_DELIM = "," SUBPAGE_TMPL_CSS = """